Skip to content

Commit

Permalink
feat: approve token transactions on swap
Browse files Browse the repository at this point in the history
Signed-off-by: Brian Sztamfater <[email protected]>
  • Loading branch information
briansztamfater committed Sep 2, 2024
1 parent 46bec86 commit 4c7487f
Show file tree
Hide file tree
Showing 9 changed files with 518 additions and 319 deletions.
8 changes: 7 additions & 1 deletion src/status_im/constants.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -591,11 +591,17 @@
(def ^:const default-slippage 0.5)
(def ^:const max-recommended-slippage 5)
(def ^:const max-slippage-decimal-places 2)
(def ^:const swap-default-provider
(def ^:const swap-provider-paraswap
{:name :paraswap
:full-name "Paraswap"
:color :blue
:contract-address "0xdef171fe48cf0115b1d80b88dc8eab59176fee57"
:terms-and-conditions-url "https://files.paraswap.io/tos_v4.pdf"})
(def ^:const swap-providers
{:paraswap swap-provider-paraswap})

(def ^:const token-for-fees-symbol "ETH")

(def ^:const transaction-status-success "Success")
(def ^:const transaction-status-pending "Pending")
(def ^:const transaction-status-failed "Failed")
120 changes: 120 additions & 0 deletions src/status_im/contexts/wallet/common/utils.cljs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
(ns status-im.contexts.wallet.common.utils
(:require [clojure.string :as string]
[native-module.core :as native-module]
[quo.foundations.resources :as resources]
[status-im.common.qr-codes.view :as qr-codes]
[status-im.constants :as constants]
[utils.hex :as utils.hex]
[utils.money :as money]
[utils.number :as number]
[utils.string]))
Expand Down Expand Up @@ -360,3 +362,121 @@
[tokens]
(let [priority #(get constants/token-sort-priority (:symbol %) ##Inf)]
(sort-by (juxt (comp - :balance) priority) tokens)))

(defn- transaction-data
[{:keys [from-address to-address token-address route data eth-transfer?]}]
(let [{:keys [amount-in gas-amount gas-fees]} route
eip-1559-enabled? (:eip-1559-enabled gas-fees)
{:keys [gas-price max-fee-per-gas-medium
max-priority-fee-per-gas]} gas-fees]
(cond-> {:From from-address
:To (or token-address to-address)
:Gas (money/to-hex gas-amount)
:Value (when eth-transfer? amount-in)
:Nonce nil
:Input ""
:Data (or data "0x")}
eip-1559-enabled? (assoc
:TxType "0x02"
:MaxFeePerGas
(money/to-hex
(money/->wei
:gwei
max-fee-per-gas-medium))
:MaxPriorityFeePerGas
(money/to-hex
(money/->wei
:gwei
max-priority-fee-per-gas)))
(not eip-1559-enabled?) (assoc :TxType "0x00"
:GasPrice
(money/to-hex
(money/->wei
:gwei
gas-price))))))

(defn approval-path
[{:keys [route from-address to-address token-address]}]
(let [{:keys [from]} route
from-chain-id (:chain-id from)
approval-amount-required (:approval-amount-required route)
approval-amount-required-sanitized (-> approval-amount-required
(utils.hex/normalize-hex)
(native-module/hex-to-number))
approval-contract-address (:approval-contract-address route)
data (native-module/encode-function-call
constants/contract-function-signature-erc20-approve
[approval-contract-address
approval-amount-required-sanitized])
tx-data (transaction-data {:from-address from-address
:to-address to-address
:token-address token-address
:route route
:data data
:eth-transfer? false})]
{:BridgeName constants/bridge-name-transfer
:ChainID from-chain-id
:TransferTx tx-data}))

(defn transaction-path
[{:keys [from-address to-address token-id token-address route data eth-transfer?]}]
(let [{:keys [bridge-name amount-in bonder-fees from
to]} route
tx-data (transaction-data {:from-address from-address
:to-address to-address
:token-address token-address
:route route
:data data
:eth-transfer? eth-transfer?})
to-chain-id (:chain-id to)
from-chain-id (:chain-id from)]
(cond-> {:BridgeName bridge-name
:ChainID from-chain-id}

(= bridge-name constants/bridge-name-erc-721-transfer)
(assoc :ERC721TransferTx
(assoc tx-data
:Recipient to-address
:TokenID token-id
:ChainID to-chain-id))

(= bridge-name constants/bridge-name-erc-1155-transfer)
(assoc :ERC1155TransferTx
(assoc tx-data
:Recipient to-address
:TokenID token-id
:ChainID to-chain-id
:Amount amount-in))

(= bridge-name constants/bridge-name-transfer)
(assoc :TransferTx tx-data)

(= bridge-name constants/bridge-name-hop)
(assoc :HopTx
(assoc tx-data
:ChainID from-chain-id
:ChainIDTo to-chain-id
:Symbol token-id
:Recipient to-address
:Amount amount-in
:BonderFee bonder-fees))

(not (or (= bridge-name constants/bridge-name-erc-721-transfer)
(= bridge-name constants/bridge-name-transfer)
(= bridge-name constants/bridge-name-hop)))
(assoc :CbridgeTx
(assoc tx-data
:ChainID to-chain-id
:Symbol token-id
:Recipient to-address
:Amount amount-in)))))

(defn multi-transaction-command
[{:keys [from-address to-address from-asset to-asset amount-out multi-transaction-type]
:or {multi-transaction-type constants/multi-transaction-type-unknown}}]
{:fromAddress from-address
:toAddress to-address
:fromAsset from-asset
:toAsset to-asset
:fromAmount amount-out
:type multi-transaction-type})
131 changes: 6 additions & 125 deletions src/status_im/contexts/wallet/send/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
[status-im.contexts.wallet.send.utils :as send-utils]
[taoensso.timbre :as log]
[utils.address :as address]
[utils.hex :as utils.hex]
[utils.money :as money]
[utils.number]
[utils.re-frame :as rf]))
Expand Down Expand Up @@ -582,124 +581,6 @@
[{:ms 20
:dispatch [:wallet/clean-up-transaction-flow]}]]]})))

(defn- transaction-data
[{:keys [from-address to-address token-address route data eth-transfer?]}]
(let [{:keys [amount-in gas-amount gas-fees]} route
eip-1559-enabled? (:eip-1559-enabled gas-fees)
{:keys [gas-price max-fee-per-gas-medium
max-priority-fee-per-gas]} gas-fees]
(cond-> {:From from-address
:To (or token-address to-address)
:Gas (money/to-hex gas-amount)
:Value (when eth-transfer? amount-in)
:Nonce nil
:Input ""
:Data (or data "0x")}
eip-1559-enabled? (assoc
:TxType "0x02"
:MaxFeePerGas
(money/to-hex
(money/->wei
:gwei
max-fee-per-gas-medium))
:MaxPriorityFeePerGas
(money/to-hex
(money/->wei
:gwei
max-priority-fee-per-gas)))
(not eip-1559-enabled?) (assoc :TxType "0x00"
:GasPrice
(money/to-hex
(money/->wei
:gwei
gas-price))))))

(defn- approval-path
[{:keys [route from-address to-address token-address]}]
(let [{:keys [from]} route
from-chain-id (:chain-id from)
approval-amount-required (:approval-amount-required route)
approval-amount-required-sanitized (-> approval-amount-required
(utils.hex/normalize-hex)
(native-module/hex-to-number))
approval-contract-address (:approval-contract-address route)
data (native-module/encode-function-call
constants/contract-function-signature-erc20-approve
[approval-contract-address
approval-amount-required-sanitized])
tx-data (transaction-data {:from-address from-address
:to-address to-address
:token-address token-address
:route route
:data data
:eth-transfer? false})]
{:BridgeName constants/bridge-name-transfer
:ChainID from-chain-id
:TransferTx tx-data}))

(defn- transaction-path
[{:keys [from-address to-address token-id token-address route data eth-transfer?]}]
(let [{:keys [bridge-name amount-in bonder-fees from
to]} route
tx-data (transaction-data {:from-address from-address
:to-address to-address
:token-address token-address
:route route
:data data
:eth-transfer? eth-transfer?})
to-chain-id (:chain-id to)
from-chain-id (:chain-id from)]
(cond-> {:BridgeName bridge-name
:ChainID from-chain-id}

(= bridge-name constants/bridge-name-erc-721-transfer)
(assoc :ERC721TransferTx
(assoc tx-data
:Recipient to-address
:TokenID token-id
:ChainID to-chain-id))

(= bridge-name constants/bridge-name-erc-1155-transfer)
(assoc :ERC1155TransferTx
(assoc tx-data
:Recipient to-address
:TokenID token-id
:ChainID to-chain-id
:Amount amount-in))

(= bridge-name constants/bridge-name-transfer)
(assoc :TransferTx tx-data)

(= bridge-name constants/bridge-name-hop)
(assoc :HopTx
(assoc tx-data
:ChainID from-chain-id
:ChainIDTo to-chain-id
:Symbol token-id
:Recipient to-address
:Amount amount-in
:BonderFee bonder-fees))

(not (or (= bridge-name constants/bridge-name-erc-721-transfer)
(= bridge-name constants/bridge-name-transfer)
(= bridge-name constants/bridge-name-hop)))
(assoc :CbridgeTx
(assoc tx-data
:ChainID to-chain-id
:Symbol token-id
:Recipient to-address
:Amount amount-in)))))

(defn- multi-transaction-command
[{:keys [from-address to-address from-asset to-asset amount-out multi-transaction-type]
:or {multi-transaction-type constants/multi-transaction-type-unknown}}]
{:fromAddress from-address
:toAddress to-address
:fromAsset from-asset
:toAsset to-asset
:fromAmount amount-out
:type multi-transaction-type})

(rf/reg-event-fx :wallet/send-transaction
(fn [{:keys [db]} [sha3-pwd]]
(let [routes (get-in db [:wallet :ui :send :route])
Expand Down Expand Up @@ -731,7 +612,7 @@
(native-module/encode-transfer
(address/normalized-hex to-address)
(:amount-in route)))
base-path (transaction-path
base-path (utils/transaction-path
{:to-address to-address
:from-address from-address
:route route
Expand All @@ -743,15 +624,15 @@
:data data
:eth-transfer? eth-transfer?})]
(if approval-required?
[(approval-path {:route route
:token-address token-address
:from-address from-address
:to-address to-address})
[(utils/approval-path {:route route
:token-address token-address
:from-address from-address
:to-address to-address})
base-path]
[base-path]))))
routes)
request-params
[(multi-transaction-command
[(utils/multi-transaction-command
{:from-address from-address
:to-address to-address
:from-asset token-id
Expand Down
19 changes: 16 additions & 3 deletions src/status_im/contexts/wallet/signals.cljs
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
(ns status-im.contexts.wallet.signals
(:require
[oops.core :as oops]
[status-im.constants :as constants]
[taoensso.timbre :as log]
[utils.re-frame :as rf]
[utils.transforms :as transforms]))

(rf/reg-event-fx
:wallet/pending-transaction-status-changed-received
(fn [{:keys [db]} [{:keys [message]}]]
(let [details (transforms/json->clj message)
tx-hash (:hash details)]
{:db (update-in db [:wallet :transactions tx-hash] assoc :status :confirmed :blocks 1)})))
(let [details (transforms/json->clj message)
tx-hash (:hash details)
tx-status (:status details)
status (cond
(= tx-status constants/transaction-status-success)
:confirmed
(= tx-status constants/transaction-status-pending)
:pending
(= tx-status constants/transaction-status-failed)
:failed)
swap-approval-transaction-id (get-in db [:wallet :ui :swap :approval-transaction-id])
swap-approval-transaction? (= swap-approval-transaction-id tx-hash)]
(cond-> {:db (update-in db [:wallet :transactions tx-hash] assoc :status status)}
swap-approval-transaction?
(assoc :fx [[:dispatch [:wallet.swap/approve-transaction-update status]]])))))

(rf/reg-event-fx
:wallet/signal-received
Expand Down
Loading

0 comments on commit 4c7487f

Please sign in to comment.