feat: added transaction record
This commit is contained in:
parent
78ed7f5805
commit
f9f8d4c524
|
@ -82,17 +82,16 @@
|
|||
(rf/reg-event-fx
|
||||
:wallet-connect/prepare-transaction-success
|
||||
(fn [{:keys [db]} [prepared-tx]]
|
||||
(let [{:keys [tx-args tx-details]} prepared-tx
|
||||
tx (-> tx-args
|
||||
bean/->clj
|
||||
(transactions/Transaction. tx-details))]
|
||||
(let [{:keys [tx-args]} prepared-tx
|
||||
tx (-> tx-args
|
||||
bean/->clj)]
|
||||
{:db (update-in db
|
||||
[:wallet-connect/current-request]
|
||||
assoc
|
||||
:raw-data prepared-tx
|
||||
:address (.sender tx)
|
||||
:transaction-summary (.summary tx)
|
||||
:display-data (.beautify-params tx))})))
|
||||
:raw-data prepared-tx
|
||||
:transaction tx
|
||||
:address (transactions/get-sender tx)
|
||||
:display-data (transactions/beautify-transaction tx))})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/process-eth-send-transaction
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
:wallet-connect/respond-sign-typed-data
|
||||
(fn [{:keys [db]} [password typed-data-version]]
|
||||
(let [{:keys [address raw-data event]} (get db :wallet-connect/current-request)
|
||||
chain-id (get-in event [:params :chainId])]
|
||||
chain-id (data-store/get-chain-id event)]
|
||||
{:fx [[:effects.wallet-connect/sign-typed-data
|
||||
{:password password
|
||||
:address address
|
||||
|
@ -68,8 +68,9 @@
|
|||
(rf/reg-event-fx
|
||||
:wallet-connect/respond-send-transaction-data
|
||||
(fn [{:keys [db]} [password]]
|
||||
(let [{:keys [chain-id raw-data address]} (get db :wallet-connect/current-request)
|
||||
{:keys [tx-hash tx-args]} raw-data]
|
||||
(let [{:keys [raw-data address event]} (get db :wallet-connect/current-request)
|
||||
{:keys [tx-hash tx-args]} raw-data
|
||||
chain-id (data-store/get-chain-id event)]
|
||||
{:fx [[:effects.wallet-connect/send-transaction
|
||||
{:password password
|
||||
:address address
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[status-im.contexts.wallet.wallet-connect.modals.common.page-nav.view :as page-nav]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.style :as style]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.transactions :as transaction-utils]
|
||||
[status-im.setup.hot-reload :as hot-reload]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
|
@ -73,9 +74,9 @@
|
|||
(set! (.-current refetch-interval-ref)
|
||||
(js/setInterval refetch-transaction constants/wallet-connect-transaction-refresh-interval-ms))))
|
||||
|
||||
(rn/use-unmount (fn []
|
||||
(clear-interval)
|
||||
(rf/dispatch [:wallet-connect/on-request-modal-dismissed])))
|
||||
(hot-reload/use-safe-unmount (fn []
|
||||
(clear-interval)
|
||||
(rf/dispatch [:wallet-connect/on-request-modal-dismissed])))
|
||||
|
||||
[rn/view {:style (style/container bottom)}
|
||||
[quo/gradient-cover {:customization-color customization-color}]
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
(ns status-im.contexts.wallet.wallet-connect.utils.rpc
|
||||
(:require [cljs-bean.core :as bean]
|
||||
[oops.core :as oops]
|
||||
(:require [oops.core :as oops]
|
||||
[promesa.core :as promesa]
|
||||
[status-im.common.json-rpc.events :as rpc-events]
|
||||
[status-im.constants :as constants]
|
||||
|
@ -13,15 +12,6 @@
|
|||
{:message-to-sign (oops/oget res :messageToSign)
|
||||
:tx-args (oops/oget res :txArgs)}))
|
||||
|
||||
(defn wallet-build-raw-transaction
|
||||
[chain-id tx-args signature]
|
||||
(-> (rpc-events/call-async "wallet_buildRawTransaction"
|
||||
true
|
||||
chain-id
|
||||
(transforms/js-stringify tx-args 0)
|
||||
signature)
|
||||
(promesa/then #(oops/oget % "rawTx"))))
|
||||
|
||||
(defn wallet-send-transaction-with-signature
|
||||
[chain-id tx-args signature]
|
||||
(rpc-events/call-async "wallet_sendTransactionWithSignature"
|
||||
|
@ -80,9 +70,3 @@
|
|||
[chain-id max-fee-per-gas]
|
||||
(-> (rpc-events/call-async "wallet_getTransactionEstimatedTime" true chain-id max-fee-per-gas)
|
||||
(promesa/then transforms/js->clj)))
|
||||
|
||||
(defn wallet-get-transaction-details
|
||||
[transaction]
|
||||
(->> (transforms/js-stringify transaction 0)
|
||||
(rpc-events/call-async "wallet_getTransactionMetadata" true)
|
||||
(transforms/js->clj)))
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||
data-store]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.rpc :as rpc]
|
||||
[utils.address :as address]
|
||||
[utils.hex :as hex]
|
||||
[utils.money :as money]
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
|
@ -132,11 +134,9 @@
|
|||
(prepare-transaction-fees tx
|
||||
tx-priority)
|
||||
prepare-transaction-for-rpc
|
||||
(rpc/wallet-build-transaction chain-id))
|
||||
details (rpc/wallet-get-transaction-details tx-args)]
|
||||
(rpc/wallet-build-transaction chain-id))]
|
||||
{:tx-args tx-args
|
||||
:tx-hash message-to-sign
|
||||
:tx-details details
|
||||
:tx-estimations estimations}))
|
||||
|
||||
(defn send-transaction
|
||||
|
@ -153,82 +153,134 @@
|
|||
(= k :Symbol)))
|
||||
data))
|
||||
|
||||
(defrecord Transaction
|
||||
[version from to gas gasPrice value nonce maxFeePerGas
|
||||
maxPriorityFeePerGas input data multiTransactionID])
|
||||
|
||||
(def tx-args
|
||||
(defn create-transaction
|
||||
[tx]
|
||||
;; TODO add malli check schema
|
||||
(map->Transaction tx))
|
||||
|
||||
(defn- non-empty-hex
|
||||
[hex-string]
|
||||
(let [normalized (hex/normalize-hex hex-string)]
|
||||
(when-not (string/blank? normalized)
|
||||
hex-string)))
|
||||
|
||||
(defn get-data
|
||||
[^Transaction tx]
|
||||
(let [{:keys [input data]} tx]
|
||||
(or (non-empty-hex input)
|
||||
(non-empty-hex data))))
|
||||
|
||||
(def function-selector-to-type
|
||||
{constants/method-id-transfer :transaction/erc-20-transfer
|
||||
constants/method-id-approve :transaction/erc-20-approve})
|
||||
|
||||
(defn get-type
|
||||
[^Transaction tx]
|
||||
(let [tx-data (get-data tx)
|
||||
eth-transfer? (nil? tx-data)
|
||||
contract-type (when-not eth-transfer?
|
||||
(-> tx-data (subs 0 10) function-selector-to-type))]
|
||||
(cond
|
||||
eth-transfer? :transaction/eth-transfer
|
||||
(keyword? contract-type) contract-type
|
||||
:else :transaction/unknown)))
|
||||
|
||||
(defn get-sender
|
||||
[^Transaction tx]
|
||||
(-> tx :from string/lower-case))
|
||||
|
||||
(defn- subs-bytes
|
||||
[hex-data start-bytes end-bytes]
|
||||
(when (-> hex-data count (/ 2) (>= end-bytes))
|
||||
(-> hex-data
|
||||
hex/normalize-hex
|
||||
(subs (* start-bytes 2)
|
||||
(* end-bytes 2)))))
|
||||
|
||||
(defn- decode-erc-20-transfer
|
||||
"Decode ERC20 transfer data, which has the following function signature:
|
||||
`approve(spender, amount)`"
|
||||
[tx-data]
|
||||
(when (>= (count tx-data) 138)
|
||||
(let [selector (subs-bytes tx-data 0 4) ;; Function selector (first 4 bytes)
|
||||
recipient-hex (subs-bytes tx-data 16 36) ;; Recipient address (next 32 bytes)
|
||||
amount-hex (subs-bytes tx-data 36 68)] ;; Amount (next 32 bytes)
|
||||
{:selector selector
|
||||
:recipient (address/normalized-hex recipient-hex)
|
||||
:amount (money/from-hex amount-hex)})))
|
||||
|
||||
(defn- decode-erc-20-approve
|
||||
"Decode ERC20 transfer data, which has the following function signature:
|
||||
`approve(spender, amount)`"
|
||||
[tx-data]
|
||||
(when (>= (count tx-data) 138)
|
||||
(let [selector (subs-bytes tx-data 0 4) ;; Function selector (first 4 bytes)
|
||||
spender-hex (subs-bytes tx-data 16 36) ;; Spender address (next 32 bytes)
|
||||
amount-hex (subs-bytes tx-data 36 68)] ;; Amount (next 32 bytes)
|
||||
{:selector selector
|
||||
:spender (address/normalized-hex spender-hex)
|
||||
:amount (money/from-hex amount-hex)})))
|
||||
|
||||
(defn get-recipient
|
||||
"Get the transaction recipient, depending on the transaction type"
|
||||
[^Transaction tx]
|
||||
(let [default (:to tx)]
|
||||
(condp = (get-type tx)
|
||||
:transaction/eth-transfer default
|
||||
:transaction/erc-20-transfer (-> tx
|
||||
get-data
|
||||
decode-erc-20-transfer
|
||||
:recipient
|
||||
(or default))
|
||||
:transaction/erc-20-approve (-> tx
|
||||
get-data
|
||||
decode-erc-20-approve
|
||||
:spender
|
||||
(or default))
|
||||
default)))
|
||||
|
||||
(defn get-amount
|
||||
[^Transaction tx]
|
||||
(let [default (-> tx :value money/from-hex)]
|
||||
(condp = (get-type tx)
|
||||
:transaction/eth-transfer default
|
||||
:transaction/erc-20-transfer (-> tx get-data decode-erc-20-transfer :amount)
|
||||
:transaction/erc-20-approve (-> tx get-data decode-erc-20-approve :amount)
|
||||
default)))
|
||||
|
||||
(->
|
||||
(decode-erc-20-transfer
|
||||
"0xa9059cbb00000000000000000000000097654628dd47c2d88fc9b3d0cc38a92e46a32cd400000000000000000000000000000000000000000000000a0af513f7628a8000"))
|
||||
|
||||
(def tt
|
||||
{:version 0
|
||||
:from "0xb18ec1808bd8b84f244c6e34cbedee9b0cd7e1fb"
|
||||
:to "0x744d70fdbe2ba4cf95131626614a1763df805b9e"
|
||||
:gas "0x21563"
|
||||
:gasPrice "0xda9a06de5"
|
||||
:gas "0x21e76"
|
||||
:gasPrice "0x8b491f4cf"
|
||||
:value "0x0"
|
||||
:nonce "0x19"
|
||||
:maxFeePerGas "0xda9a06de5"
|
||||
:maxPriorityFeePerGas "0x5d56b25c"
|
||||
:nonce "0x1b"
|
||||
:maxFeePerGas "0x8b491f4cf"
|
||||
:maxPriorityFeePerGas "0x3b9aca00"
|
||||
:input "0x"
|
||||
:data
|
||||
"0xa9059cbb00000000000000000000000097654628dd47c2d88fc9b3d0cc38a92e46a32cd4000000000000000000000000000000000000000000000016ca63768fcf860000"
|
||||
"0xa9059cbb00000000000000000000000097654628dd47c2d88fc9b3d0cc38a92e46a32cd400000000000000000000000000000000000000000000000a0af513f7628a8000"
|
||||
:multiTransactionID 0})
|
||||
|
||||
(def tx-met
|
||||
{:FunctionSelector "0xa9059cbb"
|
||||
:FunctionName "transfer"
|
||||
:Recipient "0x97654628dd47c2d88fc9b3d0cc38a92e46a32cd4"
|
||||
:Amount "420412000000000000000"
|
||||
:TokenID "<nil>"})
|
||||
(get-amount tt)
|
||||
(-> tt
|
||||
decode-erc-20-transfer)
|
||||
|
||||
(defrecord Transaction [params metadata]
|
||||
Object
|
||||
(beautify-params [this]
|
||||
(-> this :params beautify-transaction))
|
||||
(get-type tt)
|
||||
|
||||
(type [this]
|
||||
(condp = (get-in this [:metadata :FunctionName])
|
||||
"" :transaction/eth-transfer
|
||||
"transfer" :transaction/erc-20-transfer
|
||||
"approve" :transaction/approve
|
||||
:else :transaction/unknown))
|
||||
|
||||
(amount [this]
|
||||
(let [metadata-amount (get-in this [:metadata :Amount])
|
||||
params-amount (get-in this [:params :value])]
|
||||
(-> (condp =
|
||||
(.type this)
|
||||
:transaction/erc-20-transfer
|
||||
metadata-amount
|
||||
:transaction/approve
|
||||
metadata-amount
|
||||
:else
|
||||
params-amount)
|
||||
money/bignumber)))
|
||||
|
||||
(sender [this]
|
||||
(-> this :params :from string/lower-case))
|
||||
|
||||
(recipient [this]
|
||||
(let [metadata-recipient (get-in this [:metadata :Recipient])
|
||||
params-recipient (get-in this [:params :to])]
|
||||
(-> (condp =
|
||||
(.type this)
|
||||
:transaction/erc-20-transfer
|
||||
metadata-recipient
|
||||
:transaction/approve
|
||||
metadata-recipient
|
||||
:else
|
||||
params-recipient)
|
||||
string/lower-case)))
|
||||
|
||||
(token-address [this]
|
||||
(when (->> this
|
||||
.type
|
||||
(contains? #{:transaction/erc-20-transfer
|
||||
:transaction/approve}))
|
||||
(-> this :params :to string/lower-case)))
|
||||
|
||||
(summary [this]
|
||||
{:type (.type this)
|
||||
:amount (.amount this)
|
||||
:recipient (.recipient this)
|
||||
:sender (.sender this)
|
||||
:token-address (.token-address this)}))
|
||||
|
||||
(def tx (->Transaction tx-args tx-met))
|
||||
(defn get-contract-address
|
||||
[^Transaction tx]
|
||||
(condp = (get-type tx)
|
||||
:transaction/erc-20-transfer (:to tx)
|
||||
:transaction/erc-20-approve (:to tx)
|
||||
nil))
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
(ns status-im.contexts.wallet.wallet-connect.utils.typed-data
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.rpc :as rpc]
|
||||
[utils.number :as number]))
|
||||
|
||||
|
@ -85,9 +84,8 @@
|
|||
data-chain-id)))
|
||||
|
||||
(defn sign
|
||||
[password address data chain-id-eip155 version]
|
||||
(let [legacy? (= version :v1)
|
||||
chain-id (networks/eip155->chain-id chain-id-eip155)]
|
||||
[password address data chain-id version]
|
||||
(let [legacy? (= version :v1)]
|
||||
(rpc/wallet-safe-sign-typed-data data
|
||||
address
|
||||
password
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
[utils.string]))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet-connect/transaction-args
|
||||
:wallet-connect/transaction
|
||||
:<- [:wallet-connect/current-request]
|
||||
(fn [{:keys [event transaction]}]
|
||||
(when (transactions/transaction-request? event)
|
||||
transaction)))
|
||||
(transactions/create-transaction transaction))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet-connect/transaction-suggested-fees
|
||||
|
@ -22,7 +22,7 @@
|
|||
|
||||
(rf/reg-sub
|
||||
:wallet-connect/transaction-max-fees-wei
|
||||
:<- [:wallet-connect/transaction-args]
|
||||
:<- [:wallet-connect/transaction]
|
||||
:<- [:wallet-connect/transaction-suggested-fees]
|
||||
(fn [[transaction suggested-fees]]
|
||||
(when transaction
|
||||
|
@ -49,7 +49,7 @@
|
|||
:wallet-connect/current-request-transaction-information
|
||||
:<- [:wallet-connect/chain-id]
|
||||
:<- [:wallet-connect/transaction-max-fees-wei]
|
||||
:<- [:wallet-connect/transaction-args]
|
||||
:<- [:wallet-connect/transaction]
|
||||
:<- [:wallet-connect/account-eth-token]
|
||||
:<- [:profile/currency]
|
||||
:<- [:profile/currency-symbol]
|
||||
|
@ -78,3 +78,48 @@
|
|||
(not (money/sufficient-funds? total-transaction-value
|
||||
balance))
|
||||
:not-enough-assets-to-pay-gas-fees)}))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet-connect/transaction-type
|
||||
:<- [:wallet-connect/transaction]
|
||||
transactions/get-type)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet-connect/transaction-recipient
|
||||
:<- [:wallet-connect/transaction]
|
||||
transactions/get-recipient)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet-connect/transaction-amount
|
||||
:<- [:wallet-connect/transaction]
|
||||
transactions/get-amount)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet-connect/transaction-contract
|
||||
:<- [:wallet-connect/transaction]
|
||||
:<- [:wallet-connect/transaction-type]
|
||||
:<- [:wallet/tokens]
|
||||
(fn [[transaction type tokens]]
|
||||
(->> tokens
|
||||
:by-address
|
||||
(some #(when (= (:address %) (transactions/get-contract-address transaction)) %)))
|
||||
|
||||
))
|
||||
|
||||
(comment
|
||||
(->> [#_[:wallet-connect/transaction]
|
||||
#_[:wallet-connect/transaction-type]
|
||||
#_[:wallet-connect/transaction-recipient]
|
||||
#_[:wallet-connect/transaction-amount]
|
||||
[:wallet-connect/transaction-contract]
|
||||
#_[:wallet/tokens]
|
||||
]
|
||||
(map (comp deref rf/subscribe)))
|
||||
|
||||
;; => ({:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e",
|
||||
;; :decimals 18, :key "1-0x744d70fdbe2ba4cf95131626614a1763df805b9e", :community-id nil,
|
||||
;; :symbol "SNT", :sources ["Uniswap Labs Default Token List" "Status Token List"], :name
|
||||
;; "Status Network Token", :type :erc20, :verified? true, :chain-id 1,
|
||||
;; :image nil})
|
||||
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue