diff --git a/src/status_im/ethereum/json_rpc.cljs b/src/status_im/ethereum/json_rpc.cljs index a8d5b05c73b..c5776540d75 100644 --- a/src/status_im/ethereum/json_rpc.cljs +++ b/src/status_im/ethereum/json_rpc.cljs @@ -148,6 +148,9 @@ "wallet_getTransfersByAddress" {} "wallet_watchTransaction" {} "wallet_checkRecentHistory" {} + "wallet_storePendingTransaction" {} + "wallet_deletePendingTransaction" {} + "wallet_getPendingTransactions" {} "wallet_getTokensBalances" {} "wallet_getCustomTokens" {} "wallet_addCustomToken" {} diff --git a/src/status_im/ethereum/transactions/core.cljs b/src/status_im/ethereum/transactions/core.cljs index 4df0fffbebf..d1efb32fc1c 100644 --- a/src/status_im/ethereum/transactions/core.cljs +++ b/src/status_im/ethereum/transactions/core.cljs @@ -215,6 +215,19 @@ :all :all-preloaded))})) +(fx/defn delete-pending-transactions + [{:keys [db]} address transactions] + (let [all-transactions + (get-in db [:wallet :accounts (eip55/address->checksum address) :transactions]) + pending-tx-hashes (keep (fn [{:keys [hash]}] + (let [{:keys [type] :as old-tx} + (get all-transactions hash)] + (when (and (get all-transactions hash) + (= type :pending)) + hash))) + transactions)] + {:wallet/delete-pending-transactions pending-tx-hashes})) + (fx/defn handle-new-transfer [{:keys [db] :as cofx} transfers {:keys [address limit]}] (log/debug "[transfers] new-transfers" @@ -228,7 +241,9 @@ (wallet/set-max-block-with-transfers checksum transfers)] (seq transfers) - (concat (mapv add-transfer transfers)) + (concat + [(delete-pending-transactions address transfers)] + (mapv add-transfer transfers)) (and max-known-block (some #(> (:block %) max-known-block) transfers)) diff --git a/src/status_im/multiaccounts/login/core.cljs b/src/status_im/multiaccounts/login/core.cljs index 0ddff6ab9cd..544779bedff 100644 --- a/src/status_im/multiaccounts/login/core.cljs +++ b/src/status_im/multiaccounts/login/core.cljs @@ -87,6 +87,7 @@ ::enable-local-notifications nil} (wallet/initialize-tokens custom-tokens) (wallet/initialize-favourites favourites) + (wallet/get-pending-transactions) (cond (and new-account? (not scan-all-tokens?)) (wallet/set-zero-balances (first accounts)) diff --git a/src/status_im/signing/core.cljs b/src/status_im/signing/core.cljs index 12eb13404c3..b18c877f450 100644 --- a/src/status_im/signing/core.cljs +++ b/src/status_im/signing/core.cljs @@ -109,28 +109,39 @@ (fx/defn prepare-unconfirmed-transaction [{:keys [db now]} new-tx-hash {:keys [value gasPrice gas data to from hash]} symbol amount] - (log/debug "[signing] prepare-unconfirmed-transaction") (let [token (tokens/symbol->token (:wallet/all-tokens db) symbol) from (eip55/address->checksum from) ;;if there is a hash in the tx object that means we resending transaction - old-tx-hash hash] + old-tx-hash hash + gas-price (money/to-fixed (money/bignumber gasPrice)) + gas-limit (money/to-fixed (money/bignumber gas)) + tx {:timestamp now + :to to + :from from + :type :pending + :hash new-tx-hash + :data data + :token token + :symbol symbol + :value (if token + (money/to-fixed (money/unit->token amount (:decimals token))) + (money/to-fixed (money/bignumber value))) + :gas-price gas-price + :gas-limit gas-limit}] + (log/info "[signing] prepare-unconfirmed-transaction" tx) {:db (-> db ;;remove old transaction, because we replace it with the new one (update-in [:wallet :accounts from :transactions] dissoc old-tx-hash) - (assoc-in [:wallet :accounts from :transactions new-tx-hash] - {:timestamp (str now) - :to to - :from from - :type :pending - :hash new-tx-hash - :data data - :token token - :symbol symbol - :value (if token - (money/unit->token amount (:decimals token)) - (money/to-fixed (money/bignumber value))) - :gas-price (money/to-fixed (money/bignumber gasPrice)) - :gas-limit (money/to-fixed (money/bignumber gas))}))})) + (assoc-in [:wallet :accounts from :transactions new-tx-hash] tx)) + ::json-rpc/call [{:method "wallet_storePendingTransaction" + :params [(-> tx + (dissoc :gas-price :gas-limit) + (assoc :gasPrice + (money/to-fixed (money/bignumber gasPrice)) + :gasLimit (money/to-fixed (money/bignumber gas))) + clj->js)] + :on-success #(log/info "pending transfer is saved") + :on-failure #(log/info "pending transfer was not saved" %)}]})) (defn get-method-type [data] (cond diff --git a/src/status_im/utils/money.cljs b/src/status_im/utils/money.cljs index 63d83b8c341..1f2af173308 100644 --- a/src/status_im/utils/money.cljs +++ b/src/status_im/utils/money.cljs @@ -70,6 +70,16 @@ (when bn (.toNumber bn))) +(defn to-string + ([^js bn] + (to-string bn 10)) + ([^js bn base] + (when bn + (.toString bn base)))) + +(defn to-hex [^js bn] + (str "0x" (to-string bn 16))) + (defn wei->str ([unit n display-unit] (str (to-fixed (wei-> unit n)) " " display-unit)) diff --git a/src/status_im/wallet/core.cljs b/src/status_im/wallet/core.cljs index e65d2fceaa8..dba615cbd81 100644 --- a/src/status_im/wallet/core.cljs +++ b/src/status_im/wallet/core.cljs @@ -686,18 +686,23 @@ (re-frame/reg-fx ::start-watching - (fn [hash] - (log/info "[wallet] watch transaction" hash) - (json-rpc/call - {:method "wallet_watchTransaction" - :params [hash] - :on-success #(re-frame.core/dispatch [::restart true]) - :on-error #(log/info "[wallet] watch transaction error" % "hash" hash)}))) + (fn [hashes] + (log/info "[wallet] watch transactions" hashes) + (doseq [hash hashes] + (json-rpc/call + {:method "wallet_watchTransaction" + :params [hash] + :on-success #(re-frame.core/dispatch [::restart true]) + :on-error #(log/info "[wallet] watch transaction error" % "hash" hash)})))) (fx/defn watch-tx {:events [:watch-tx]} [{:keys [db] :as cofx} tx-id] - {::start-watching tx-id}) + {::start-watching [tx-id]}) + +(fx/defn watch-transsactions + [_ hashes] + {::start-watching hashes}) (fx/defn clear-timeouts [{:keys [db]}] @@ -849,3 +854,56 @@ {:view :share-account :address address}) (keep-watching-history)))) + +(re-frame/reg-fx + ::get-pending-transactions + (fn [] + (json-rpc/call + {:method "wallet_getPendingTransactions" + :params [] + :on-success #(re-frame/dispatch [:wallet/on-retreiving-pending-transactions %])}))) + +(fx/defn get-pending-transactions + {:events [:wallet/get-pending-transactions]} + [_] + (log/info "[wallet] get pending transactions") + {::get-pending-transactions nil}) + +(defn normalize-transaction + [db {:keys [symbol gasPrice gasLimit value from to] :as transaction}] + (let [symbol (keyword symbol) + token (tokens/symbol->token (:wallet/all-tokens db) symbol)] + (-> transaction + (select-keys [:timestamp :hash :data]) + (assoc :from (eip55/address->checksum from) + :to (eip55/address->checksum to) + :type :pending + :symbol symbol + :token token + :value (money/bignumber value) + :gas-price (money/bignumber gasPrice) + :gas-limit (money/bignumber gasLimit))))) + +(fx/defn on-retriving-pending-transactions + {:events [:wallet/on-retreiving-pending-transactions]} + [{:keys [db]} raw-transactions] + (log/info "[wallet] pending transactions") + {:db + (reduce (fn [db {:keys [from hash] :as transaction}] + (let [path [:wallet :accounts from :transactions hash]] + (if-not (get-in db path) + (assoc-in db path transaction) + db))) + db + (map (partial normalize-transaction db) raw-transactions)) + ::start-watching (map :hash raw-transactions)}) + +(re-frame/reg-fx + :wallet/delete-pending-transactions + (fn [hashes] + (log/info "[wallet] delete pending transactions") + (doseq [hash hashes] + (json-rpc/call + {:method "wallet_deletePendingTransaction" + :params [hash] + :on-success #(log/info "[wallet] pending transaction deleted" hash)})))) diff --git a/status-go-version.json b/status-go-version.json index 3bd1231492a..71097da9c70 100644 --- a/status-go-version.json +++ b/status-go-version.json @@ -2,7 +2,7 @@ "_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh ' instead", "owner": "status-im", "repo": "status-go", - "version": "v0.76.6", - "commit-sha1": "fccee2230fcc8b7b7fca069765b8584dbe921d3f", - "src-sha256": "0gpimg5cwh6vawf3fsclbyimb3y9c8mpdhwd017p47g4fds697cj" + "version": "v0.77.0", + "commit-sha1": "6037570901233477cbef85d5494b257076a3acd9", + "src-sha256": "1f5pr4w5a8lby2sqginddbjff2fp1d906nnr1y7zbsgafpi82j83" }