feat(wallet)!: Activity - a more reliable update (#21596)
This commit: - Removes the usage of deprecated "wallet_filterActivityAsync RPC" and updates it to "wallet_startActivityFilterSessionV2" with other supporting activity filter session RPCs - Removes deprecated "wallet_checkRecentHistoryForChainIDs" RPC as we no longer support past transaction history - Added support for Bridge, Swap and Approval activities - Added context for the sender and receiver if the address is known (own accounts or saved addresses) - Added support for viewing, copying and sharing links to TX details on block explorer Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
This commit is contained in:
parent
f08ac94596
commit
f6dfc64567
|
@ -6,7 +6,8 @@
|
|||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:transaction {:optional true} [:maybe [:enum :receive :send :swap :bridge :buy :destroy :mint]]]
|
||||
[:transaction {:optional true}
|
||||
[:maybe [:enum :receive :send :swap :bridge :buy :destroy :mint :approval]]]
|
||||
[:status {:optional true} [:maybe [:enum :pending :confirmed :finalised :failed]]]
|
||||
[:counter {:optional true} [:maybe :int]]
|
||||
[:timestamp {:optional true} [:maybe :string]]
|
||||
|
|
|
@ -41,7 +41,8 @@
|
|||
colors/white-opa-10)})
|
||||
|
||||
(def timestamp-container
|
||||
{:margin-left 4})
|
||||
{:margin-left 4
|
||||
:flex 1})
|
||||
|
||||
(defn timestamp
|
||||
[theme blur?]
|
||||
|
|
|
@ -12,22 +12,24 @@
|
|||
[utils.i18n :as i18n]))
|
||||
|
||||
(def transaction-translation
|
||||
{:receive [i18n/label :t/receive]
|
||||
:send [i18n/label :t/send]
|
||||
:swap [i18n/label :t/swap]
|
||||
:bridge [i18n/label :t/bridge]
|
||||
:buy [i18n/label :t/buy]
|
||||
:destroy [i18n/label :t/destroy]
|
||||
:mint [i18n/label :t/mint]})
|
||||
{:receive [i18n/label :t/receive]
|
||||
:send [i18n/label :t/send]
|
||||
:swap [i18n/label :t/swap]
|
||||
:bridge [i18n/label :t/bridge]
|
||||
:buy [i18n/label :t/buy]
|
||||
:destroy [i18n/label :t/destroy]
|
||||
:mint [i18n/label :t/mint]
|
||||
:approval [i18n/label :t/set-spending-cap]})
|
||||
|
||||
(def transaction-icon
|
||||
{:receive :i/receive
|
||||
:send :i/send
|
||||
:swap :i/transaction
|
||||
:bridge :i/bridge
|
||||
:buy :i/buy
|
||||
:destroy :i/destroy
|
||||
:mint :i/mint})
|
||||
{:receive :i/receive
|
||||
:send :i/send
|
||||
:swap :i/transaction
|
||||
:bridge :i/bridge
|
||||
:buy :i/buy
|
||||
:destroy :i/destroy
|
||||
:mint :i/mint
|
||||
:approval :i/token-sales})
|
||||
|
||||
(def status-icon
|
||||
{:pending :i/pending-state
|
||||
|
@ -39,7 +41,8 @@
|
|||
[{:keys [transaction
|
||||
timestamp
|
||||
counter
|
||||
blur?]
|
||||
blur?
|
||||
on-press-options]
|
||||
:or {transaction :receive
|
||||
counter 1}}
|
||||
theme]
|
||||
|
@ -64,7 +67,13 @@
|
|||
:size :label
|
||||
:style (style/timestamp theme blur?)
|
||||
:accessibility-label :transaction-timestamp}
|
||||
timestamp]]])
|
||||
timestamp]]
|
||||
(when on-press-options
|
||||
[rn/pressable
|
||||
{:on-press on-press-options
|
||||
:hit-slop {:top 10 :bottom 10 :left 10 :right 10}}
|
||||
[icon/icon :i/options
|
||||
{:size 20}]])])
|
||||
|
||||
(defn transaction-icon-view
|
||||
[{:keys [blur? transaction status]
|
||||
|
@ -120,8 +129,8 @@
|
|||
:accessibility-label :wallet-activity
|
||||
:disabled (= state :disabled)
|
||||
:on-press on-press
|
||||
:on-press-in on-press-in
|
||||
:on-press-out on-press-out}
|
||||
:on-press-in (when on-press on-press-in)
|
||||
:on-press-out (when on-press on-press-out)}
|
||||
[rn/view {:style style/container}
|
||||
[transaction-icon-view props theme]
|
||||
[rn/view {:style {:flex 1}}
|
||||
|
|
|
@ -35,6 +35,12 @@
|
|||
(def sepolia-chain-explorer-link "https://sepolia.etherscan.io/address/")
|
||||
(def optimism-sepolia-chain-explorer-link "https://sepolia-optimistic.etherscan.io/address/")
|
||||
(def arbitrum-sepolia-chain-explorer-link "https://sepolia.arbiscan.io/address/")
|
||||
(def mainnet-tx-details-base-link "https://etherscan.io/tx")
|
||||
(def optimism-mainnet-tx-details-base-link "https://optimistic.etherscan.io/tx")
|
||||
(def arbitrum-mainnet-tx-details-base-link "https://arbiscan.io/tx")
|
||||
(def mainnet-sepolia-tx-details-base-link "https://sepolia.etherscan.io/tx")
|
||||
(def optimism-sepolia-tx-details-base-link "https://sepolia-optimistic.etherscan.io/tx")
|
||||
(def arbitrum-sepolia-tx-details-base-link "https://sepolia.arbiscan.io/tx")
|
||||
(def opensea-link "https://opensea.io")
|
||||
(def opensea-tesnet-link "https://testnets.opensea.io")
|
||||
|
||||
|
|
|
@ -152,7 +152,8 @@
|
|||
{:key :bridge}
|
||||
{:key :buy}
|
||||
{:key :destroy}
|
||||
{:key :mint}]}
|
||||
{:key :mint}
|
||||
{:key :approval}]}
|
||||
{:key :status
|
||||
:type :select
|
||||
:options [{:key :pending}
|
||||
|
@ -219,7 +220,8 @@
|
|||
:descriptor descriptor
|
||||
:blur? (:blur? @component-state)
|
||||
:show-blur-background? true}
|
||||
[rn/view {:style {:align-self :center}}
|
||||
[rn/view {:style {:flex 1}}
|
||||
[quo/wallet-activity
|
||||
(merge {:on-press #(js/alert "Dropdown pressed")}
|
||||
(merge {:on-press #(js/alert "Activity pressed")
|
||||
:on-press-options #(js/alert "Options pressed")}
|
||||
@component-state)]]])))
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
(def first-tab-id :assets)
|
||||
|
||||
;; NOTE: If the id of the tabs are changed, please check 'wallet/select-account-tab' event as
|
||||
;; a activity event depends on it
|
||||
(def tabs-data
|
||||
[{:id :assets :label (i18n/label :t/assets) :accessibility-label :assets-tab}
|
||||
{:id :collectibles :label (i18n/label :t/collectibles) :accessibility-label :collectibles-tab}
|
||||
|
@ -30,8 +32,6 @@
|
|||
(hot-reload/use-safe-unmount (fn []
|
||||
(rf/dispatch [:wallet/close-account-page])
|
||||
(rf/dispatch [:wallet/clean-current-viewing-account])))
|
||||
(rn/use-mount
|
||||
#(rf/dispatch [:wallet/fetch-activities-for-current-account]))
|
||||
[rn/view {:style {:flex 1}}
|
||||
[account-switcher/view
|
||||
{:type :wallet-networks
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
(ns status-im.contexts.wallet.common.activity-tab.activity-types.view
|
||||
(:require [quo.core :as quo]
|
||||
[status-im.contexts.wallet.common.activity-tab.options.view :as activity-options]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
;; Common helpers
|
||||
(defn- open-options
|
||||
[transactions]
|
||||
(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content #(activity-options/view (first transactions))}]))
|
||||
|
||||
(defn- common-activity-props
|
||||
[{:keys [tx-type relative-date status transactions]}]
|
||||
{:transaction tx-type
|
||||
:timestamp relative-date
|
||||
:status status
|
||||
:blur? false
|
||||
:on-press-options #(open-options transactions)})
|
||||
|
||||
(defn- network-tag
|
||||
[{:keys [network-name network-logo]}]
|
||||
{:type :network
|
||||
:network-name network-name
|
||||
:network-logo network-logo})
|
||||
|
||||
(defn- collectible-tag
|
||||
[{:keys [nft-url nft-name amount token-id]}]
|
||||
{:type :collectible
|
||||
:collectible nft-url
|
||||
:collectible-name (if (> amount 1)
|
||||
(str amount " " nft-name)
|
||||
nft-name)
|
||||
:collectible-number (when (not= token-id "0")
|
||||
token-id)})
|
||||
|
||||
(defn- token-tag
|
||||
[{:keys [token amount]}]
|
||||
{:type :token
|
||||
:token token
|
||||
:amount amount})
|
||||
|
||||
;; Activity type views
|
||||
(defn send-activity
|
||||
[{:keys [symbol-out amount-out token-id sender-tag recipient-tag network-name-out network-logo-out]
|
||||
:as activity-data}]
|
||||
(let [base-props (common-activity-props activity-data)
|
||||
first-tag (if token-id
|
||||
(collectible-tag activity-data)
|
||||
(token-tag {:token symbol-out :amount amount-out}))]
|
||||
[quo/wallet-activity
|
||||
(assoc base-props
|
||||
:first-tag first-tag
|
||||
:second-tag-prefix :t/from
|
||||
:second-tag sender-tag
|
||||
:third-tag-prefix :t/to
|
||||
:third-tag recipient-tag
|
||||
:fourth-tag-prefix :t/on
|
||||
:fourth-tag (network-tag {:network-name network-name-out
|
||||
:network-logo network-logo-out}))]))
|
||||
|
||||
(defn bridge-activity
|
||||
[{:keys [symbol-out amount-out network-name-out network-logo-out network-name-in network-logo-in
|
||||
sender-tag]
|
||||
:as activity-data}]
|
||||
[quo/wallet-activity
|
||||
(assoc (common-activity-props activity-data)
|
||||
:first-tag (token-tag {:token symbol-out :amount amount-out})
|
||||
:second-tag-prefix :t/from
|
||||
:second-tag (network-tag {:network-name network-name-out
|
||||
:network-logo network-logo-out})
|
||||
:third-tag-prefix :t/to
|
||||
:third-tag (network-tag {:network-name network-name-in
|
||||
:network-logo network-logo-in})
|
||||
:fourth-tag-prefix :t/in
|
||||
:fourth-tag sender-tag)])
|
||||
|
||||
(defn swap-activity
|
||||
[{:keys [symbol-out amount-out symbol-in amount-in sender-tag network-name-out network-logo-out]
|
||||
:as activity-data}]
|
||||
[quo/wallet-activity
|
||||
(assoc (common-activity-props activity-data)
|
||||
:first-tag (token-tag {:token symbol-out :amount amount-out})
|
||||
:second-tag-prefix :t/to
|
||||
:second-tag (token-tag {:token symbol-in :amount amount-in})
|
||||
:third-tag-prefix :t/in
|
||||
:third-tag sender-tag
|
||||
:fourth-tag-prefix :t/on
|
||||
:fourth-tag (network-tag {:network-name network-name-out
|
||||
:network-logo network-logo-out}))])
|
||||
|
||||
(defn approval-activity
|
||||
[{:keys [symbol-out amount-out sender-tag spender-tag network-name-out network-logo-out]
|
||||
:as activity-data}]
|
||||
[quo/wallet-activity
|
||||
(assoc (common-activity-props activity-data)
|
||||
:first-tag (token-tag {:token symbol-out :amount amount-out})
|
||||
:second-tag-prefix :t/in
|
||||
:second-tag sender-tag
|
||||
:third-tag-prefix :t/for
|
||||
:third-tag spender-tag
|
||||
:fourth-tag-prefix :t/on
|
||||
:fourth-tag (network-tag {:network-name network-name-out
|
||||
:network-logo network-logo-out}))])
|
|
@ -1,6 +1,5 @@
|
|||
(ns status-im.contexts.wallet.common.activity-tab.constants)
|
||||
|
||||
|
||||
(def ^:const wallet-activity-error-code-success 1)
|
||||
(def ^:const wallet-activity-error-code-task-canceled 2)
|
||||
(def ^:const wallet-activity-error-code-failed 3)
|
||||
|
@ -12,6 +11,7 @@
|
|||
(def ^:const wallet-activity-type-bridge 4)
|
||||
(def ^:const wallet-activity-type-contract-deployment 5)
|
||||
(def ^:const wallet-activity-type-mint 6)
|
||||
(def ^:const wallet-activity-type-approval 7)
|
||||
|
||||
(def ^:const wallet-activity-status-failed 0)
|
||||
(def ^:const wallet-activity-status-pending 1)
|
||||
|
@ -62,4 +62,3 @@
|
|||
wallet-activity-type-buy :t/via
|
||||
wallet-activity-type-swap :t/via
|
||||
wallet-activity-type-bridge :t/in})
|
||||
|
||||
|
|
|
@ -1,70 +1,126 @@
|
|||
(ns status-im.contexts.wallet.common.activity-tab.events
|
||||
(:require [camel-snake-kebab.extras :as cske]
|
||||
[utils.collection :as collection]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
(defonce ^:private request-id-atom (atom 0))
|
||||
(def ^:const limit-per-request 20)
|
||||
|
||||
(defn- get-unique-request-id
|
||||
(defn- nested-merge
|
||||
[& maps]
|
||||
(apply merge-with merge maps))
|
||||
|
||||
(defn- create-default-filters
|
||||
[]
|
||||
(swap! request-id-atom inc)
|
||||
@request-id-atom)
|
||||
{:period {:startTimestamp 0
|
||||
:endTimestamp 0}
|
||||
:types []
|
||||
:statuses []
|
||||
:counterpartyAddresses []
|
||||
:assets []
|
||||
:collectibles []
|
||||
:filterOutAssets false
|
||||
:filterOutCollectibles false})
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/store-session-id-for-activity-filter-session
|
||||
(fn [{:keys [db]} [request-id]]
|
||||
{:db (assoc-in db [:wallet :ui :activity-tab :request :request-id] request-id)}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/fetch-activities-for-current-account
|
||||
(fn [{:keys [db]}]
|
||||
(let [address (-> db :wallet :current-viewing-account-address)
|
||||
chain-ids (chain/chain-ids db)
|
||||
request-id (get-unique-request-id)
|
||||
filters {:period {:startTimestamp 0
|
||||
:endTimestamp 0}
|
||||
:types []
|
||||
:statuses []
|
||||
:counterpartyAddresses []
|
||||
:assets []
|
||||
:collectibles []
|
||||
:filterOutAssets false
|
||||
:filterOutCollectibles false}
|
||||
offset 0
|
||||
limit 50
|
||||
request-params [request-id [address] chain-ids filters offset limit]]
|
||||
{:db (assoc-in db [:wallet :ui :activity-tab :request request-id] address)
|
||||
(let [address (get-in db [:wallet :current-viewing-account-address])
|
||||
chain-ids (chain/chain-ids db)
|
||||
params [[address] chain-ids (create-default-filters) limit-per-request]]
|
||||
{:db (-> db
|
||||
(update-in [:wallet :activities] dissoc address)
|
||||
(update-in [:wallet :ui :activity-tab :request] dissoc :request-id)
|
||||
(update-in [:wallet :ui :activity-tab :request]
|
||||
assoc
|
||||
:address address
|
||||
:loading? true
|
||||
:initial-request? true))
|
||||
:fx [[:json-rpc/call
|
||||
[{;; This method is deprecated and will be replaced by
|
||||
;; "wallet_startActivityFilterSession"
|
||||
;; https://github.com/status-im/status-mobile/issues/19864
|
||||
:method "wallet_filterActivityAsync"
|
||||
:params request-params
|
||||
:on-error [:wallet/log-rpc-error
|
||||
{:event :wallet/fetch-activities-for-current-account
|
||||
:params request-params}]}]]]})))
|
||||
[{:method "wallet_startActivityFilterSessionV2"
|
||||
:params params
|
||||
:on-success [:wallet/store-session-id-for-activity-filter-session]
|
||||
:on-error [:wallet/log-rpc-error
|
||||
{:event :wallet/fetch-activities-for-current-account
|
||||
:params params}]}]]]})))
|
||||
|
||||
(def ^:private activity-transaction-id (comp hash :transaction))
|
||||
(rf/reg-event-fx
|
||||
:wallet/stop-activity-filter-session
|
||||
(fn [{:keys [db]}]
|
||||
(when-let [session-id (get-in db [:wallet :ui :activity-tab :request :request-id])]
|
||||
{:db (update-in db [:wallet :ui :activity-tab] dissoc :request)
|
||||
:fx [[:json-rpc/call
|
||||
[{:method "wallet_stopActivityFilterSession"
|
||||
:params [session-id]
|
||||
:on-error [:wallet/log-rpc-error
|
||||
{:event :wallet/stop-activity-filter-session
|
||||
:params [session-id]}]}]]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/get-more-for-activities-filter-session
|
||||
(fn [{:keys [db]}]
|
||||
(let [session-id (get-in db [:wallet :ui :activity-tab :request :request-id])
|
||||
has-more? (get-in db [:wallet :ui :activity-tab :request :has-more?])
|
||||
params [session-id limit-per-request]]
|
||||
(when (and session-id has-more?)
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_getMoreForActivityFilterSession"
|
||||
:params params
|
||||
:on-error [:wallet/log-rpc-error
|
||||
{:event :wallet/get-more-for-activities-filter-session
|
||||
:params params}]}]]]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/reset-activities-filter-session
|
||||
(fn [{:keys [db]}]
|
||||
(when-let [session-id (get-in db [:wallet :ui :activity-tab :request :request-id])]
|
||||
{:db (assoc-in db [:wallet :ui :activity-tab :request :initial-request?] true)
|
||||
:fx [[:json-rpc/call
|
||||
[{:method "wallet_resetActivityFilterSession"
|
||||
:params [session-id limit-per-request]
|
||||
:on-error [:wallet/log-rpc-error
|
||||
{:event :wallet/reset-activities-filter-session
|
||||
:params [session-id limit-per-request]}]}]]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/activity-filtering-for-current-account-done
|
||||
(fn [{:keys [db]} [{:keys [message requestId]}]]
|
||||
(let [address (get-in db [:wallet :ui :activity-tab :request requestId])
|
||||
activities (->> message
|
||||
(transforms/json->clj)
|
||||
(:activities)
|
||||
(cske/transform-keys transforms/->kebab-case-keyword))
|
||||
activities-indexed (zipmap (map activity-transaction-id activities)
|
||||
activities)]
|
||||
{:db (assoc-in db [:wallet :activities address] activities-indexed)})))
|
||||
|
||||
(def ^:private nested-merge (partial merge-with merge))
|
||||
(fn [{:keys [db]} [{:keys [message]}]]
|
||||
(let [{:keys [address initial-request?]} (get-in db [:wallet :ui :activity-tab :request])
|
||||
{:keys [activities offset hasMore]} (transforms/json->clj message)
|
||||
new-activities (->> activities
|
||||
(cske/transform-keys transforms/->kebab-case-keyword)
|
||||
(collection/index-by :key))
|
||||
existing-activities (get-in db [:wallet :activities address])
|
||||
updated-activities (if initial-request?
|
||||
new-activities
|
||||
(nested-merge existing-activities new-activities))]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :activities address] updated-activities)
|
||||
(assoc-in [:wallet :ui :activity-tab :request :offset] offset)
|
||||
(assoc-in [:wallet :ui :activity-tab :request :has-more?] hasMore)
|
||||
(assoc-in [:wallet :ui :activity-tab :request :loading?] false)
|
||||
(assoc-in [:wallet :ui :activity-tab :request :initial-request?] false))})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/activities-filtering-entries-updated
|
||||
(fn [{:keys [db]} [{:keys [message requestId]}]]
|
||||
(let [address (get-in db [:wallet :ui :activity-tab :request requestId])
|
||||
activities (->> message
|
||||
(transforms/json->clj)
|
||||
(cske/transform-keys transforms/->kebab-case-keyword))
|
||||
activities-indexed (zipmap (map activity-transaction-id activities)
|
||||
activities)]
|
||||
{:db (-> db
|
||||
(update-in [:wallet :ui :activity-tab :request] dissoc requestId)
|
||||
(update-in [:wallet :activities address] nested-merge activities-indexed))})))
|
||||
(when (= requestId (get-in db [:wallet :ui :activity-tab :request :request-id]))
|
||||
(let [address (get-in db [:wallet :ui :activity-tab :request :address])
|
||||
updated-activities (->> message
|
||||
transforms/json->clj
|
||||
(cske/transform-keys transforms/->kebab-case-keyword)
|
||||
(collection/index-by :key))]
|
||||
{:db (update-in db [:wallet :activities address] nested-merge updated-activities)}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/activities-session-updated
|
||||
(fn [_ [{:keys [message]}]]
|
||||
(let [{:keys [hasNewOnTop]} (transforms/json->clj message)]
|
||||
(when hasNewOnTop
|
||||
{:fx [[:dispatch [:wallet/reset-activities-filter-session]]]}))))
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
(ns status-im.contexts.wallet.common.activity-tab.options.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.clipboard :as clipboard]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.common.utils.external-links :as external-links]
|
||||
[status-im.contexts.wallet.common.utils.networks :as network-utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[{:keys [chain-id]
|
||||
tx-hash :hash}]
|
||||
(let [{:keys [view-on-block-explorer-label
|
||||
link-to-block-explorer-label]} (network-utils/get-network-details chain-id)
|
||||
tx-details-link-on-block-explorer (external-links/get-link-to-tx-details chain-id tx-hash)
|
||||
open-tx-on-block-explorer (rn/use-callback
|
||||
#(rf/dispatch [:browser.ui/open-url
|
||||
tx-details-link-on-block-explorer])
|
||||
[tx-details-link-on-block-explorer])
|
||||
copy-tx-hash-to-clipboard (rn/use-callback
|
||||
(fn []
|
||||
(clipboard/set-string tx-hash)
|
||||
(rf/dispatch
|
||||
[:toasts/upsert
|
||||
{:type :positive
|
||||
:text
|
||||
(i18n/label
|
||||
:t/transaction-hash-copied-to-clipboard)}]))
|
||||
[tx-hash])
|
||||
share-link-to-block-explorer (rn/use-callback
|
||||
#(rf/dispatch [:open-share
|
||||
{:options
|
||||
{:message
|
||||
tx-details-link-on-block-explorer}}])
|
||||
[tx-details-link-on-block-explorer])]
|
||||
[quo/action-drawer
|
||||
[[{:icon :i/link
|
||||
:accessibility-label :view-on-block-explorer
|
||||
:on-press open-tx-on-block-explorer
|
||||
:label (i18n/label view-on-block-explorer-label)
|
||||
:right-icon :i/external}]
|
||||
[{:icon :i/copy
|
||||
:accessibility-label :copy-transaction-hash
|
||||
:label (i18n/label :t/copy-transaction-hash)
|
||||
:on-press copy-tx-hash-to-clipboard}]
|
||||
[{:icon :i/share
|
||||
:accessibility-label :share-link-to-block-explorer
|
||||
:label (i18n/label link-to-block-explorer-label)
|
||||
:on-press share-link-to-block-explorer}]]]))
|
|
@ -1,157 +1,49 @@
|
|||
(ns status-im.contexts.wallet.common.activity-tab.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.resources :as resources]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.shell.constants :as shell.constants]
|
||||
[status-im.contexts.wallet.common.activity-tab.activity-types.view :as activity-type]
|
||||
[status-im.contexts.wallet.common.empty-tab.view :as empty-tab]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn send-and-receive-activity
|
||||
[{:keys [transaction relative-date status sender recipient token amount network-name
|
||||
network-logo token-id nft-url nft-name]}]
|
||||
(if token-id
|
||||
[quo/wallet-activity
|
||||
{:transaction transaction
|
||||
:timestamp relative-date
|
||||
:status status
|
||||
:counter 1
|
||||
:first-tag {:size 24
|
||||
:type :collectible
|
||||
:collectible nft-url
|
||||
:collectible-name (if (> amount 1)
|
||||
(str amount " " nft-name)
|
||||
nft-name)
|
||||
:collectible-number (when (not= token-id "0")
|
||||
token-id)}
|
||||
:second-tag-prefix :t/from
|
||||
:second-tag {:type :address :address sender}
|
||||
:third-tag-prefix :t/to
|
||||
:third-tag {:type :address :address recipient}
|
||||
:fourth-tag-prefix :t/via
|
||||
:fourth-tag {:size 24
|
||||
:type :network
|
||||
:network-name network-name
|
||||
:network-logo network-logo}
|
||||
:blur? false}]
|
||||
[quo/wallet-activity
|
||||
{:transaction transaction
|
||||
:timestamp relative-date
|
||||
:status status
|
||||
:counter 1
|
||||
:first-tag {:size 24
|
||||
:type :token
|
||||
:token token
|
||||
:amount amount}
|
||||
:second-tag-prefix :t/from
|
||||
:second-tag {:type :address :address sender}
|
||||
:third-tag-prefix :t/to
|
||||
:third-tag {:type :address :address recipient}
|
||||
:fourth-tag-prefix :t/via
|
||||
:fourth-tag {:size 24
|
||||
:type :network
|
||||
:network-name network-name
|
||||
:network-logo network-logo}
|
||||
:blur? false}]))
|
||||
|
||||
;; WIP to add the mint activity.
|
||||
;(defn mint-activity
|
||||
; [{:keys [transaction relative-date status recipient network-name
|
||||
; network-logo nft-name nft-url token-id]}]
|
||||
; [quo/wallet-activity
|
||||
; {:transaction transaction
|
||||
; :timestamp relative-date
|
||||
; :status status
|
||||
; :counter 1
|
||||
; :first-tag {:size 24
|
||||
; :type :collectible
|
||||
; :collectible nft-url
|
||||
; :collectible-name nft-name
|
||||
; :collectible-number token-id}
|
||||
; :second-tag-prefix :t/at
|
||||
; :second-tag {:type :address :address recipient}
|
||||
; :third-tag-prefix :t/to
|
||||
; :third-tag {:type :address :address recipient}
|
||||
; :fourth-tag-prefix :t/via
|
||||
; :fourth-tag {:size 24
|
||||
; :type :network
|
||||
; :network-name network-name
|
||||
; :network-logo network-logo}
|
||||
; :blur? false}])
|
||||
|
||||
(defn- section-header
|
||||
[{:keys [title]}]
|
||||
[quo/divider-date title])
|
||||
|
||||
(defn activity-item
|
||||
[{:keys [transaction] :as activity}]
|
||||
(case transaction
|
||||
(:send :receive) [send-and-receive-activity activity]
|
||||
;; WIP to add the mint activity.
|
||||
;; :mint [mint-activity activity]
|
||||
(defn- activity-item
|
||||
[{:keys [tx-type] :as activity}]
|
||||
(case tx-type
|
||||
:send [activity-type/send-activity activity]
|
||||
:bridge [activity-type/bridge-activity activity]
|
||||
:swap [activity-type/swap-activity activity]
|
||||
:approval [activity-type/approval-activity activity]
|
||||
nil))
|
||||
|
||||
(defn- pressable-text
|
||||
[{:keys [on-press text]}]
|
||||
[rn/text
|
||||
{:style {:text-decoration-line :underline}
|
||||
:on-press on-press}
|
||||
text])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
address (rf/sub [:wallet/current-viewing-account-address])
|
||||
activity-list (rf/sub [:wallet/activities-for-current-viewing-account])
|
||||
open-eth-chain-explorer (rn/use-callback
|
||||
#(rf/dispatch [:wallet/navigate-to-chain-explorer
|
||||
{:address address
|
||||
:network constants/mainnet-network-name}])
|
||||
[address])
|
||||
open-oeth-chain-explorer (rn/use-callback
|
||||
#(rf/dispatch [:wallet/navigate-to-chain-explorer
|
||||
{:address address
|
||||
:network constants/optimism-network-name}])
|
||||
[address])
|
||||
open-arb-chain-explorer (rn/use-callback
|
||||
#(rf/dispatch [:wallet/navigate-to-chain-explorer
|
||||
{:address address
|
||||
:network constants/arbitrum-network-name}])
|
||||
[address])]
|
||||
[:<>
|
||||
[quo/information-box
|
||||
{:type :informative
|
||||
:icon :i/info
|
||||
:closable? false
|
||||
:style {:margin-horizontal 20 :margin-vertical 8}}
|
||||
[:<>
|
||||
(str (i18n/label :t/wallet-activity-beta-message) " ")
|
||||
[pressable-text
|
||||
{:on-press open-eth-chain-explorer
|
||||
:text (i18n/label :t/etherscan)}]
|
||||
", "
|
||||
[pressable-text
|
||||
{:on-press open-oeth-chain-explorer
|
||||
:text (i18n/label :t/op-explorer)}]
|
||||
(str ", " (string/lower-case (i18n/label :t/or)) " ")
|
||||
[pressable-text
|
||||
{:on-press open-arb-chain-explorer
|
||||
:text (i18n/label :t/arbiscan)}]
|
||||
"."]]
|
||||
(if (empty? activity-list)
|
||||
[empty-tab/view
|
||||
{:title (i18n/label :t/no-activity)
|
||||
:description (i18n/label :t/empty-tab-description)
|
||||
:image (resources/get-themed-image :no-activity theme)}]
|
||||
[rn/section-list
|
||||
{:sections activity-list
|
||||
:sticky-section-headers-enabled false
|
||||
:style {:flex 1
|
||||
(let [theme (quo.theme/use-theme)
|
||||
loading? (rf/sub [:wallet/activity-tab-loading?])
|
||||
activity-list (rf/sub [:wallet/activities-for-current-viewing-account])
|
||||
on-end-reached (rn/use-callback
|
||||
#(rf/dispatch
|
||||
[:wallet/get-more-for-activities-filter-session]))]
|
||||
(if (and (and (some? loading?) (false? loading?)) (empty? activity-list))
|
||||
[empty-tab/view
|
||||
{:title (i18n/label :t/no-activity)
|
||||
:description (i18n/label :t/empty-tab-description)
|
||||
:image (resources/get-themed-image :no-activity theme)}]
|
||||
[rn/section-list
|
||||
{:sections activity-list
|
||||
:sticky-section-headers-enabled false
|
||||
:style {:flex 1
|
||||
:padding-horizontal 8}
|
||||
:content-container-style {:padding-bottom shell.constants/floating-shell-button-height}
|
||||
:render-fn activity-item
|
||||
:render-section-header-fn section-header}])]))
|
||||
:content-container-style {:padding-bottom shell.constants/floating-shell-button-height}
|
||||
:shows-vertical-scroll-indicator false
|
||||
:render-fn activity-item
|
||||
:render-section-header-fn section-header
|
||||
:on-end-reached on-end-reached
|
||||
:on-end-reached-threshold 2}])))
|
||||
|
|
|
@ -24,3 +24,30 @@
|
|||
config/optimism-sepolia-chain-explorer-link
|
||||
|
||||
:else config/mainnet-chain-explorer-link))
|
||||
|
||||
(defn get-base-url-for-tx-details-by-chain-id
|
||||
[chain-id]
|
||||
(condp = chain-id
|
||||
constants/ethereum-mainnet-chain-id
|
||||
config/mainnet-tx-details-base-link
|
||||
|
||||
constants/arbitrum-mainnet-chain-id
|
||||
config/arbitrum-mainnet-tx-details-base-link
|
||||
|
||||
constants/optimism-mainnet-chain-id
|
||||
config/optimism-mainnet-tx-details-base-link
|
||||
|
||||
constants/ethereum-sepolia-chain-id
|
||||
config/mainnet-sepolia-tx-details-base-link
|
||||
|
||||
constants/arbitrum-sepolia-chain-id
|
||||
config/arbitrum-sepolia-tx-details-base-link
|
||||
|
||||
constants/optimism-sepolia-chain-id
|
||||
config/optimism-sepolia-tx-details-base-link
|
||||
|
||||
config/mainnet-tx-details-base-link))
|
||||
|
||||
(defn get-link-to-tx-details
|
||||
[chain-id tx-hash]
|
||||
(str (get-base-url-for-tx-details-by-chain-id chain-id) "/" tx-hash))
|
||||
|
|
|
@ -139,25 +139,31 @@
|
|||
[(butlast $) (last $)]))
|
||||
|
||||
(def mainnet-network-details
|
||||
{:source (resources/get-network constants/mainnet-network-name)
|
||||
:short-name constants/mainnet-short-name
|
||||
:full-name constants/mainnet-full-name
|
||||
:network-name constants/mainnet-network-name
|
||||
:abbreviated-name constants/mainnet-abbreviated-name})
|
||||
{:source (resources/get-network constants/mainnet-network-name)
|
||||
:short-name constants/mainnet-short-name
|
||||
:full-name constants/mainnet-full-name
|
||||
:network-name constants/mainnet-network-name
|
||||
:abbreviated-name constants/mainnet-abbreviated-name
|
||||
:view-on-block-explorer-label :t/view-on-eth
|
||||
:link-to-block-explorer-label :t/share-link-to-eth})
|
||||
|
||||
(def arbitrum-network-details
|
||||
{:source (resources/get-network constants/arbitrum-network-name)
|
||||
:short-name constants/arbitrum-short-name
|
||||
:full-name constants/arbitrum-full-name
|
||||
:network-name constants/arbitrum-network-name
|
||||
:abbreviated-name constants/arbitrum-abbreviated-name})
|
||||
{:source (resources/get-network constants/arbitrum-network-name)
|
||||
:short-name constants/arbitrum-short-name
|
||||
:full-name constants/arbitrum-full-name
|
||||
:network-name constants/arbitrum-network-name
|
||||
:abbreviated-name constants/arbitrum-abbreviated-name
|
||||
:view-on-block-explorer-label :t/view-on-arb
|
||||
:link-to-block-explorer-label :t/share-link-to-arb})
|
||||
|
||||
(def optimism-network-details
|
||||
{:source (resources/get-network constants/optimism-network-name)
|
||||
:short-name constants/optimism-short-name
|
||||
:full-name constants/optimism-full-name
|
||||
:network-name constants/optimism-network-name
|
||||
:abbreviated-name constants/optimism-abbreviated-name})
|
||||
{:source (resources/get-network constants/optimism-network-name)
|
||||
:short-name constants/optimism-short-name
|
||||
:full-name constants/optimism-full-name
|
||||
:network-name constants/optimism-network-name
|
||||
:abbreviated-name constants/optimism-abbreviated-name
|
||||
:view-on-block-explorer-label :t/view-on-oeth
|
||||
:link-to-block-explorer-label :t/share-link-to-oeth})
|
||||
|
||||
(defn get-network-details
|
||||
[chain-id]
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
[status-im.feature-flags :as ff]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.collection]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.number]
|
||||
|
@ -40,14 +39,12 @@
|
|||
(rf/reg-event-fx :wallet/navigate-to-account
|
||||
(fn [{:keys [db]} [address]]
|
||||
{:db (assoc-in db [:wallet :current-viewing-account-address] address)
|
||||
:fx [[:dispatch [:navigate-to :screen/wallet.accounts address]]
|
||||
[:dispatch [:wallet/fetch-activities-for-current-account]]]}))
|
||||
:fx [[:dispatch [:navigate-to :screen/wallet.accounts address]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/navigate-to-account-within-stack
|
||||
(fn [{:keys [db]} [address]]
|
||||
{:db (assoc-in db [:wallet :current-viewing-account-address] address)
|
||||
:fx [[:dispatch [:navigate-to-within-stack [:screen/wallet.accounts :shell-stack] address]]
|
||||
[:dispatch [:wallet/fetch-activities-for-current-account]]]}))
|
||||
:fx [[:dispatch [:navigate-to-within-stack [:screen/wallet.accounts :shell-stack] address]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/navigate-to-new-account
|
||||
(fn [{:keys [db]} [address]]
|
||||
|
@ -58,7 +55,11 @@
|
|||
|
||||
(rf/reg-event-fx :wallet/select-account-tab
|
||||
(fn [{:keys [db]} [tab]]
|
||||
{:db (assoc-in db [:wallet :ui :account-page :active-tab] tab)}))
|
||||
(let [activity-tab-selected? (= tab :activity)]
|
||||
{:db (assoc-in db [:wallet :ui :account-page :active-tab] tab)
|
||||
:fx [(if activity-tab-selected?
|
||||
[:dispatch [:wallet/fetch-activities-for-current-account]]
|
||||
[:dispatch [:wallet/stop-activity-filter-session]])]})))
|
||||
|
||||
(rf/reg-event-fx :wallet/select-home-tab
|
||||
(fn [{:keys [db]} [tab]]
|
||||
|
@ -66,7 +67,8 @@
|
|||
|
||||
(rf/reg-event-fx :wallet/clear-account-tab
|
||||
(fn [{:keys [db]}]
|
||||
{:db (assoc-in db [:wallet :ui :account-page :active-tab] nil)}))
|
||||
{:db (assoc-in db [:wallet :ui :account-page :active-tab] nil)
|
||||
:fx [[:dispatch [:wallet/stop-activity-filter-session]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/switch-current-viewing-account
|
||||
(fn [{:keys [db]} [address]]
|
||||
|
@ -94,7 +96,8 @@
|
|||
(let [just-completed-transaction? (get-in db [:wallet :ui :send :just-completed-transaction?])]
|
||||
{:db (update db :wallet dissoc :current-viewing-account-address)
|
||||
:fx [(when-not just-completed-transaction?
|
||||
[:dispatch [:wallet/clear-account-tab]])]})))
|
||||
[:dispatch [:wallet/clear-account-tab]])
|
||||
[:dispatch [:wallet/stop-activity-filter-session]]]})))
|
||||
|
||||
(defn log-rpc-error
|
||||
[_ [{:keys [event params]} error]]
|
||||
|
@ -106,15 +109,13 @@
|
|||
|
||||
(def refresh-accounts-fx-dispatches
|
||||
[[:dispatch [:wallet/get-wallet-token-for-all-accounts]]
|
||||
[:dispatch [:wallet/request-collectibles-for-all-accounts {:new-request? true}]]
|
||||
[:dispatch [:wallet/check-recent-history-for-all-accounts]]])
|
||||
[:dispatch [:wallet/request-collectibles-for-all-accounts {:new-request? true}]]])
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/fetch-assets-for-address
|
||||
(fn [_ [address]]
|
||||
{:fx [[:dispatch [:wallet/get-wallet-token-for-account address]]
|
||||
[:dispatch [:wallet/request-collectibles-for-account address]]
|
||||
[:dispatch [:wallet/check-recent-history-for-account address]]]}))
|
||||
[:dispatch [:wallet/request-collectibles-for-account address]]]}))
|
||||
|
||||
(defn- reconcile-accounts
|
||||
[db-accounts-by-address new-accounts]
|
||||
|
@ -491,25 +492,6 @@
|
|||
[{:method "wallet_startWallet"
|
||||
:on-error [:wallet/log-rpc-error {:event :wallet/start-wallet}]}]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/check-recent-history-for-all-accounts
|
||||
(fn [{:keys [db]}]
|
||||
{:fx (->> (get-in db [:wallet :accounts])
|
||||
vals
|
||||
(mapv (fn [{:keys [address]}]
|
||||
[:dispatch [:wallet/check-recent-history-for-account address]])))}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/check-recent-history-for-account
|
||||
(fn [{:keys [db]} [address]]
|
||||
(let [chain-ids (chain/chain-ids db)
|
||||
params [chain-ids [address]]]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_checkRecentHistoryForChainIDs"
|
||||
:params params
|
||||
:on-error [:wallet/log-rpc-error
|
||||
{:event :wallet/check-recent-history-for-account
|
||||
:params params}]}]]]})))
|
||||
|
||||
(rf/reg-event-fx :wallet/initialize
|
||||
(fn []
|
||||
{:fx [[:dispatch [:wallet/start-wallet]]
|
||||
|
|
|
@ -131,18 +131,6 @@
|
|||
address]}]]]}]
|
||||
(is (match? expected-effects (dispatch [event-id address])))))
|
||||
|
||||
(h/deftest-event :wallet/check-recent-history-for-all-accounts
|
||||
[event-id dispatch]
|
||||
(testing "check recent history for all accounts"
|
||||
(let [address-1 "0x1"
|
||||
address-2 "0x2"
|
||||
expected-fx [[:dispatch [:wallet/check-recent-history-for-account address-1]]
|
||||
[:dispatch [:wallet/check-recent-history-for-account address-2]]]]
|
||||
(reset! rf-db/app-db
|
||||
{:wallet {:accounts {address-1 {:address address-1}
|
||||
address-2 {:address address-2}}}})
|
||||
(is (match? expected-fx (:fx (dispatch [event-id])))))))
|
||||
|
||||
(h/deftest-event :wallet/reconcile-keypairs
|
||||
[event-id dispatch]
|
||||
(let [keypair-key-uid (:key-uid raw-account)]
|
||||
|
|
|
@ -623,7 +623,6 @@
|
|||
(fn [{:keys [db]}]
|
||||
(let [address (get-in db [:wallet :current-viewing-account-address])]
|
||||
{:fx [[:dispatch [:wallet/navigate-to-account-within-stack address]]
|
||||
[:dispatch [:wallet/fetch-activities-for-current-account]]
|
||||
[:dispatch [:wallet/select-account-tab :activity]]
|
||||
[:dispatch-later
|
||||
[{:ms 20
|
||||
|
|
|
@ -107,4 +107,9 @@
|
|||
[:wallet/activities-filtering-entries-updated
|
||||
(transforms/js->clj event-js)]]]}
|
||||
|
||||
"wallet-activity-session-updated"
|
||||
{:fx [[:dispatch
|
||||
[:wallet/activities-session-updated
|
||||
(transforms/js->clj event-js)]]]}
|
||||
|
||||
(log/debug ::unknown-wallet-event :type event-type)))))
|
||||
|
|
|
@ -561,7 +561,6 @@
|
|||
(fn [{:keys [db]}]
|
||||
(let [address (get-in db [:wallet :current-viewing-account-address])]
|
||||
{:fx [[:dispatch [:wallet/navigate-to-account-within-stack address]]
|
||||
[:dispatch [:wallet/fetch-activities-for-current-account]]
|
||||
[:dispatch [:wallet/select-account-tab :activity]]
|
||||
[:dispatch-later
|
||||
[{:ms 20
|
||||
|
|
|
@ -1,119 +1,165 @@
|
|||
(ns status-im.subs.wallet.activities
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[quo.foundations.resources :as quo.resources]
|
||||
[quo.foundations.resources]
|
||||
[quo.foundations.resources :as resources]
|
||||
[re-frame.core :as rf]
|
||||
[status-im.contexts.wallet.common.activity-tab.constants :as constants]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.activity-tab.constants :as activity-constants]
|
||||
[utils.collection :as collection]
|
||||
[utils.datetime :as datetime]
|
||||
[utils.hex :as utils.hex]
|
||||
[utils.hex :as hex]
|
||||
[utils.money :as money]))
|
||||
|
||||
(def precision 6)
|
||||
(def ^:private precision 6)
|
||||
|
||||
(defn- hex->number
|
||||
[hex-str]
|
||||
(-> hex-str
|
||||
hex/normalize-hex
|
||||
money/from-hex
|
||||
str))
|
||||
|
||||
(defn- hex->amount
|
||||
[hex-str]
|
||||
(-> hex-str
|
||||
hex->number
|
||||
money/wei->ether
|
||||
(money/with-precision precision)
|
||||
str))
|
||||
|
||||
(defn- get-token-amount
|
||||
[{:keys [token-type]} amount]
|
||||
(if (#{activity-constants/wallet-activity-token-type-erc-721
|
||||
activity-constants/wallet-activity-token-type-erc-1155}
|
||||
token-type)
|
||||
(hex->number amount)
|
||||
(hex->amount amount)))
|
||||
|
||||
(defn- get-address-context-tag
|
||||
[accounts-and-saved-addresses address]
|
||||
(let [{:keys [context-type name emoji color customization-color]}
|
||||
(get accounts-and-saved-addresses address)]
|
||||
(case context-type
|
||||
:account
|
||||
{:type :account
|
||||
:account-name name
|
||||
:emoji emoji
|
||||
:customization-color color}
|
||||
|
||||
:saved-address
|
||||
{:type :default
|
||||
:full-name name
|
||||
:customization-color customization-color}
|
||||
|
||||
{:type :address :address address})))
|
||||
|
||||
(defn- get-spender-context-tag
|
||||
[address]
|
||||
(let [swap-providers (->> constants/swap-providers
|
||||
vals
|
||||
(collection/index-by :contract-address))
|
||||
{:keys [full-name name] :as spender} (get swap-providers address)]
|
||||
(if spender
|
||||
{:type :network
|
||||
:network-name full-name
|
||||
:network-logo (resources/get-network name)}
|
||||
{:type :address :address address})))
|
||||
|
||||
(defn- process-base-activity
|
||||
[{:keys [timestamp sender recipient token-in token-out chain-id-in chain-id-out activity-status]
|
||||
:as activity}
|
||||
{:keys [chain-id->network-details accounts-and-saved-addresses]}]
|
||||
(let [token-id (some-> (or token-in token-out)
|
||||
:token-id
|
||||
hex->number)
|
||||
network-in (chain-id->network-details chain-id-in)
|
||||
network-out (chain-id->network-details chain-id-out)]
|
||||
(assoc activity
|
||||
:relative-date (datetime/timestamp->relative (* timestamp 1000))
|
||||
:sender-tag (get-address-context-tag accounts-and-saved-addresses sender)
|
||||
:recipient-tag (get-address-context-tag accounts-and-saved-addresses recipient)
|
||||
:network-name-in (:full-name network-in)
|
||||
:network-logo-in (resources/get-network (:network-name network-in))
|
||||
:network-name-out (:full-name network-out)
|
||||
:network-logo-out (resources/get-network (:network-name network-out))
|
||||
:status (activity-constants/wallet-activity-status->name activity-status)
|
||||
:token-id token-id)))
|
||||
|
||||
(defn- process-activity
|
||||
[{:keys [activity-type token-out amount-out token-in amount-in approval-spender] :as activity} context]
|
||||
(let [base-activity (process-base-activity activity context)]
|
||||
(condp = activity-type
|
||||
activity-constants/wallet-activity-type-send
|
||||
(assoc base-activity
|
||||
:tx-type :send
|
||||
:amount-out (get-token-amount token-out amount-out))
|
||||
|
||||
activity-constants/wallet-activity-type-bridge
|
||||
(assoc base-activity
|
||||
:tx-type :bridge
|
||||
:amount-out (get-token-amount token-out amount-out))
|
||||
|
||||
activity-constants/wallet-activity-type-swap
|
||||
(assoc base-activity
|
||||
:tx-type :swap
|
||||
:amount-in (get-token-amount token-in amount-in)
|
||||
:amount-out (get-token-amount token-out amount-out))
|
||||
|
||||
activity-constants/wallet-activity-type-approval
|
||||
(assoc base-activity
|
||||
:tx-type :approval
|
||||
:amount-out (get-token-amount token-out amount-out)
|
||||
:spender-tag (get-spender-context-tag approval-spender))
|
||||
|
||||
nil)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/all-activities
|
||||
:<- [:wallet]
|
||||
:-> :activities)
|
||||
|
||||
(defn- hex-wei->amount
|
||||
[hex-str-amount]
|
||||
(-> hex-str-amount
|
||||
(utils.hex/normalize-hex)
|
||||
(native-module/hex-to-number)
|
||||
(money/wei->ether)
|
||||
(money/with-precision precision)
|
||||
(str)))
|
||||
(rf/reg-sub
|
||||
:wallet/activity-tab
|
||||
:<- [:wallet/ui]
|
||||
:-> :activity-tab)
|
||||
|
||||
(defn- hex-string->number
|
||||
[hex-str-amount]
|
||||
(-> hex-str-amount
|
||||
(utils.hex/normalize-hex)
|
||||
(native-module/hex-to-number)
|
||||
(str)))
|
||||
(rf/reg-sub
|
||||
:wallet/activity-tab-request
|
||||
:<- [:wallet/activity-tab]
|
||||
:-> :request)
|
||||
|
||||
(defn- get-token-amount
|
||||
[token amount]
|
||||
(let [token-type (:token-type token)]
|
||||
(if (#{constants/wallet-activity-token-type-erc-721
|
||||
constants/wallet-activity-token-type-erc-1155}
|
||||
token-type)
|
||||
(hex-string->number amount)
|
||||
(hex-wei->amount amount))))
|
||||
(rf/reg-sub
|
||||
:wallet/activity-tab-loading?
|
||||
:<- [:wallet/activity-tab-request]
|
||||
:-> :loading?)
|
||||
|
||||
(defn- process-send-activity
|
||||
[{:keys [symbol-out amount-out token-out]
|
||||
:as data}]
|
||||
(assoc data
|
||||
:transaction :send
|
||||
:token symbol-out
|
||||
:amount (get-token-amount token-out amount-out)))
|
||||
|
||||
(defn- process-receive-activity
|
||||
[{:keys [symbol-in amount-in token-in] :as data}]
|
||||
(assoc data
|
||||
:transaction :receive
|
||||
:token symbol-in
|
||||
:amount (get-token-amount token-in amount-in)))
|
||||
|
||||
;; WIP to add the mint activity.
|
||||
;(defn- process-mint-activity
|
||||
; [{:keys [token-in symbol-in amount-in chain-id-in nft-name] :as data}
|
||||
; chain-id->network-name]
|
||||
; (-> data
|
||||
; (merge activity)
|
||||
; (assoc :transaction :mint
|
||||
; ;:token symbol-in
|
||||
; ;:amount (activity-amount amount-in)
|
||||
; :nft-name (normalize-nft-name token-id nft-name))))
|
||||
|
||||
(defn- process-activity-by-type
|
||||
[chain-id->network-name
|
||||
{:keys [activity-type activity-status timestamp sender recipient token-in token-out
|
||||
chain-id-in chain-id-out]
|
||||
:as data}]
|
||||
(let [network-name (chain-id->network-name (or chain-id-in chain-id-out))
|
||||
token-id (some-> (or token-in token-out)
|
||||
:token-id
|
||||
hex-string->number)
|
||||
activity (assoc data
|
||||
:relative-date (datetime/timestamp->relative (* timestamp 1000))
|
||||
:sender sender
|
||||
:recipient recipient
|
||||
:timestamp timestamp
|
||||
:network-name network-name
|
||||
:token-id token-id
|
||||
:status (constants/wallet-activity-status->name activity-status)
|
||||
:network-logo (quo.resources/get-network network-name))]
|
||||
(condp = activity-type
|
||||
constants/wallet-activity-type-send
|
||||
(process-send-activity activity)
|
||||
|
||||
constants/wallet-activity-type-receive
|
||||
(process-receive-activity activity)
|
||||
|
||||
;; WIP to add the mint activity. Constants/wallet-activity-type-mint
|
||||
;; (process-mint-activity activity chain-id->network-name)
|
||||
|
||||
nil)))
|
||||
(rf/reg-sub
|
||||
:wallet/accounts-and-saved-addresses
|
||||
:<- [:wallet/accounts-without-assets]
|
||||
:<- [:wallet/saved-addresses-by-network-mode]
|
||||
(fn [[accounts saved-addresses]]
|
||||
(merge
|
||||
(collection/index-by :address (map #(assoc % :context-type :account) accounts))
|
||||
(collection/index-by :address
|
||||
(map #(assoc % :context-type :saved-address) (vals saved-addresses))))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/activities-for-current-viewing-account
|
||||
:<- [:wallet/all-activities]
|
||||
:<- [:wallet/current-viewing-account-address]
|
||||
:<- [:wallet/network-details]
|
||||
(fn [[activities current-viewing-account-address network-details]]
|
||||
(let [chain-id->network-name (update-vals (group-by :chain-id network-details)
|
||||
(comp :network-name first))
|
||||
address-activities (->> (get activities current-viewing-account-address)
|
||||
(vals)
|
||||
(sort-by :timestamp))]
|
||||
(->> address-activities
|
||||
(keep #(process-activity-by-type chain-id->network-name %))
|
||||
(group-by (fn [{:keys [timestamp]}]
|
||||
(datetime/timestamp->relative-short-date (* timestamp 1000))))
|
||||
:<- [:wallet/accounts-and-saved-addresses]
|
||||
(fn [[activities current-address network-details accounts-and-saved-addresses]]
|
||||
(let [context {:chain-id->network-details (collection/index-by :chain-id network-details)
|
||||
:accounts-and-saved-addresses accounts-and-saved-addresses}
|
||||
activities (->> (get activities current-address)
|
||||
vals
|
||||
(keep #(process-activity % context))
|
||||
(sort-by :timestamp >)
|
||||
(group-by #(datetime/timestamp->relative-short-date
|
||||
(* (:timestamp %) 1000))))]
|
||||
(->> activities
|
||||
(map (fn [[date activities]]
|
||||
{:title date
|
||||
:data (reverse activities)
|
||||
:data activities
|
||||
:timestamp (:timestamp (first activities))}))
|
||||
(sort-by (fn [{:keys [timestamp]}] (- timestamp)))))))
|
||||
(sort-by :timestamp >)))))
|
||||
|
|
|
@ -29,18 +29,14 @@
|
|||
:sender "acc1"
|
||||
:recipient "acc2"
|
||||
:timestamp 1588291200}
|
||||
2 {:activity-type constants/wallet-activity-type-receive
|
||||
:amount-in "0x1"
|
||||
:sender "acc2"
|
||||
:recipient "acc1"
|
||||
:timestamp 1588377600}
|
||||
3 {:activity-type constants/wallet-activity-type-send
|
||||
3 {:activity-type constants/wallet-activity-type-bridge
|
||||
:amount-out "0x1"
|
||||
:sender "acc1"
|
||||
:recipient "acc4"
|
||||
:timestamp 1588464000}
|
||||
4 {:activity-type constants/wallet-activity-type-send
|
||||
4 {:activity-type constants/wallet-activity-type-swap
|
||||
:amount-out "0x1"
|
||||
:amount-in "0x1"
|
||||
:sender "acc1"
|
||||
:recipient "acc4"
|
||||
:timestamp 1588464100}
|
||||
|
@ -58,59 +54,43 @@
|
|||
(is
|
||||
(match?
|
||||
[{:title "May 3, 2020"
|
||||
:timestamp 1588464000
|
||||
:data [{:relative-date "May 3, 2020"
|
||||
:amount "0"
|
||||
:network-logo nil
|
||||
:recipient "acc4"
|
||||
:transaction :send
|
||||
:token nil
|
||||
:network-name nil
|
||||
:status nil
|
||||
:sender "acc1"
|
||||
:timestamp 1588464100}
|
||||
{:relative-date "May 3, 2020"
|
||||
:amount "0"
|
||||
:network-logo nil
|
||||
:recipient "acc4"
|
||||
:transaction :send
|
||||
:token nil
|
||||
:network-name nil
|
||||
:status nil
|
||||
:sender "acc1"
|
||||
:timestamp 1588464050}
|
||||
{:relative-date "May 3, 2020"
|
||||
:amount "0"
|
||||
:network-logo nil
|
||||
:recipient "acc4"
|
||||
:transaction :send
|
||||
:token nil
|
||||
:network-name nil
|
||||
:status nil
|
||||
:sender "acc1"
|
||||
:timestamp 1588464000}]}
|
||||
{:title "May 2, 2020"
|
||||
:timestamp 1588377600
|
||||
:data [{:relative-date "May 2, 2020"
|
||||
:amount "0"
|
||||
:network-logo nil
|
||||
:recipient "acc1"
|
||||
:transaction :receive
|
||||
:token nil
|
||||
:network-name nil
|
||||
:status nil
|
||||
:sender "acc2"
|
||||
:timestamp 1588377600}]}
|
||||
:timestamp 1588464100
|
||||
:data [{:relative-date "May 3, 2020"
|
||||
:amount-out "0"
|
||||
:network-logo-out nil
|
||||
:recipient "acc4"
|
||||
:tx-type :swap
|
||||
:network-name-out nil
|
||||
:status nil
|
||||
:sender "acc1"
|
||||
:timestamp 1588464100}
|
||||
{:relative-date "May 3, 2020"
|
||||
:amount-out "0"
|
||||
:network-logo-out nil
|
||||
:recipient "acc4"
|
||||
:tx-type :send
|
||||
:network-name-out nil
|
||||
:status nil
|
||||
:sender "acc1"
|
||||
:timestamp 1588464050}
|
||||
{:relative-date "May 3, 2020"
|
||||
:amount-out "0"
|
||||
:network-logo-out nil
|
||||
:recipient "acc4"
|
||||
:tx-type :bridge
|
||||
:network-name-out nil
|
||||
:status nil
|
||||
:sender "acc1"
|
||||
:timestamp 1588464000}]}
|
||||
{:title "May 1, 2020"
|
||||
:timestamp 1588291200
|
||||
:data [{:relative-date "May 1, 2020"
|
||||
:amount "0"
|
||||
:network-logo nil
|
||||
:recipient "acc2"
|
||||
:transaction :send
|
||||
:token nil
|
||||
:network-name nil
|
||||
:status nil
|
||||
:sender "acc1"
|
||||
:timestamp 1588291200}]}]
|
||||
:data [{:relative-date "May 1, 2020"
|
||||
:amount-out "0"
|
||||
:network-logo-out nil
|
||||
:recipient "acc2"
|
||||
:tx-type :send
|
||||
:network-name-out nil
|
||||
:status nil
|
||||
:sender "acc1"
|
||||
:timestamp 1588291200}]}]
|
||||
(rf/sub [sub-name])))))
|
||||
|
|
|
@ -44,24 +44,30 @@
|
|||
(testing "returns data with prod"
|
||||
(swap! rf-db/app-db assoc-in [:wallet :networks] network-data)
|
||||
(is
|
||||
(= [{:network-name :mainnet
|
||||
:short-name "eth"
|
||||
:chain-id 1
|
||||
:abbreviated-name "Eth."
|
||||
:full-name "Mainnet"
|
||||
:layer 1}
|
||||
{:network-name :arbitrum
|
||||
:short-name "arb1"
|
||||
:abbreviated-name "Arb1."
|
||||
:full-name "Arbitrum"
|
||||
:chain-id 42161
|
||||
:layer 2}
|
||||
{:network-name :optimism
|
||||
:short-name "oeth"
|
||||
:abbreviated-name "Oeth."
|
||||
:full-name "Optimism"
|
||||
:chain-id 10
|
||||
:layer 2}]
|
||||
(= [{:network-name :mainnet
|
||||
:short-name "eth"
|
||||
:chain-id 1
|
||||
:abbreviated-name "Eth."
|
||||
:full-name "Mainnet"
|
||||
:layer 1
|
||||
:view-on-block-explorer-label :t/view-on-eth
|
||||
:link-to-block-explorer-label :t/share-link-to-eth}
|
||||
{:network-name :arbitrum
|
||||
:short-name "arb1"
|
||||
:abbreviated-name "Arb1."
|
||||
:full-name "Arbitrum"
|
||||
:chain-id 42161
|
||||
:layer 2
|
||||
:view-on-block-explorer-label :t/view-on-arb
|
||||
:link-to-block-explorer-label :t/share-link-to-arb}
|
||||
{:network-name :optimism
|
||||
:short-name "oeth"
|
||||
:abbreviated-name "Oeth."
|
||||
:full-name "Optimism"
|
||||
:chain-id 10
|
||||
:layer 2
|
||||
:view-on-block-explorer-label :t/view-on-oeth
|
||||
:link-to-block-explorer-label :t/share-link-to-oeth}]
|
||||
(map #(dissoc % :source :related-chain-id) (rf/sub [sub-name]))))))
|
||||
|
||||
(h/deftest-sub :wallet/network-details-by-network-name
|
||||
|
|
|
@ -373,6 +373,12 @@
|
|||
(map #(assoc-network-preferences-names network-details % test-networks-enabled?))
|
||||
(sort-by :position))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/accounts-without-assets
|
||||
:<- [:wallet/accounts]
|
||||
(fn [accounts]
|
||||
(map #(dissoc % :tokens :collectibles) accounts)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/watch-only-accounts
|
||||
:<- [:wallet/accounts]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v6.1.0",
|
||||
"commit-sha1": "c014fbfc1ec739aad2db951fdcff6182d4dbd919",
|
||||
"src-sha256": "16im0nc8zri5z1wvzbh83331g02iy305m2lca4ljjgdmlaq6l2zx"
|
||||
"version": "v6.2.0",
|
||||
"commit-sha1": "896eb635029e025cc446d73768038fb6c3afe2fb",
|
||||
"src-sha256": "08vpcxdhjh2szsarbnhqlgdnmn8i7zp11nk0j02gj3xjlzdn9yjy"
|
||||
}
|
||||
|
|
|
@ -531,7 +531,7 @@
|
|||
"copy-qr": "Copy code",
|
||||
"copy-text": "Copy text",
|
||||
"copy-to-clipboard": "Copy",
|
||||
"copy-transaction-hash": "Copy transaction ID",
|
||||
"copy-transaction-hash": "Copy transaction hash",
|
||||
"correct-private-key": "Correct private key",
|
||||
"cost-fee": "Cost/Fee",
|
||||
"counter-9-plus": "9+",
|
||||
|
@ -2326,6 +2326,7 @@
|
|||
"set-dapp-access-permissions": "Set DApp access permissions",
|
||||
"set-max": "Set max",
|
||||
"set-nickname-toast": "You have renamed {{primary-name}} as {{nickname}}",
|
||||
"set-spending-cap": "Set spending cap",
|
||||
"set-spending-cap-of": "Set spending cap of",
|
||||
"set-up-sync": "Set up sync",
|
||||
"settings": "Settings",
|
||||
|
@ -2347,6 +2348,9 @@
|
|||
"share-image": "Share image",
|
||||
"share-invite-link": "Share an invite link",
|
||||
"share-link": "Share link",
|
||||
"share-link-to-arb": "Share link to Arbiscan",
|
||||
"share-link-to-eth": "Share link to Etherscan",
|
||||
"share-link-to-oeth": "Share link to Optimism Explorer",
|
||||
"share-logs": "Share logs",
|
||||
"share-my-profile": "Share my profile",
|
||||
"share-opensea-link": "Share OpenSea link",
|
||||
|
@ -2594,6 +2598,7 @@
|
|||
"transaction-details": "Transaction details",
|
||||
"transaction-failed": "Transaction failed",
|
||||
"transaction-fee": "Transaction fee",
|
||||
"transaction-hash-copied-to-clipboard": "Transaction hash copied to clipboard",
|
||||
"transaction-history": "Transaction history",
|
||||
"transaction-request": "Transaction Request",
|
||||
"transaction-sent": "Transaction sent",
|
||||
|
|
Loading…
Reference in New Issue