Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e76d550d62 | ||
|
|
f23b92c880 | ||
|
|
582bc34ad5 | ||
|
|
383d133803 | ||
|
|
69abb8d60a | ||
|
|
aaf750f99d | ||
|
|
40f11b42c8 | ||
|
|
b3d2b7b0f5 |
@@ -109,19 +109,10 @@ pipeline {
|
||||
stage('Upload') {
|
||||
steps { script {
|
||||
sshagent(credentials: ['nix-cache-ssh']) {
|
||||
nix.shell(
|
||||
"""
|
||||
nix.shell("""
|
||||
find /nix/store/ -mindepth 1 -maxdepth 1 -type d \
|
||||
-not -name "*.links" -and -not -name "*-status-mobile-*" \
|
||||
-and -not -name "tmp-*" \
|
||||
-print0 | xargs -0 nix-store -qR | sort -u > "${WORKSPACE_TMP}"/store-paths.txt
|
||||
""",
|
||||
pure: false
|
||||
)
|
||||
nix.shell(
|
||||
"""
|
||||
nix-store --export < "${WORKSPACE_TMP}"/store-paths.txt | \\
|
||||
ssh ${env.NIX_SSHOPTS} ${params.NIX_CACHE_USER}@${params.NIX_CACHE_HOST} ${env.NIX_STORE_CMD} --import
|
||||
-not -name '*.links' -and -not -name '*-status-mobile-*' \
|
||||
| xargs nix copy --to ${NIX_SSH_REMOTE}
|
||||
""",
|
||||
pure: false
|
||||
)
|
||||
|
||||
@@ -88,3 +88,10 @@
|
||||
|
||||
(def gradient-end
|
||||
(assoc gradient-common :right 0))
|
||||
|
||||
(defn button-loader
|
||||
[theme]
|
||||
{:width 100
|
||||
:height 22
|
||||
:border-radius 6
|
||||
:background-color (loader-color theme)})
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
[:on-input-focus {:optional true} [:maybe fn?]]
|
||||
[:on-token-press {:optional true} [:maybe fn?]]
|
||||
[:on-max-press {:optional true} [:maybe fn?]]
|
||||
[:max-loading? {:optional true} [:maybe :boolean]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:container-style {:optional true} [:maybe :map]]]]]
|
||||
:any])
|
||||
@@ -52,7 +53,7 @@
|
||||
[{:keys [type status token value fiat-value show-approval-label? error? network-tag-props
|
||||
approval-label-props default-value auto-focus? input-disabled? enable-swap?
|
||||
currency-symbol on-change-text show-keyboard? get-ref
|
||||
container-style on-swap-press on-token-press on-max-press on-input-focus]}]
|
||||
container-style on-swap-press on-token-press on-max-press max-loading? on-input-focus]}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
pay? (= type :pay)
|
||||
disabled? (= status :disabled)
|
||||
@@ -172,11 +173,13 @@
|
||||
(when-not loading?
|
||||
[:<>
|
||||
(when pay?
|
||||
[rn/pressable {:on-press on-max-press}
|
||||
[network-tag/view
|
||||
(assoc network-tag-props
|
||||
:status
|
||||
(if error? :error :default))]])
|
||||
(if max-loading?
|
||||
[rn/view {:style (style/button-loader theme)}]
|
||||
[rn/pressable {:on-press on-max-press}
|
||||
[network-tag/view
|
||||
(assoc network-tag-props
|
||||
:status
|
||||
(if error? :error :default))]]))
|
||||
(when fiat-value
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
|
||||
@@ -492,10 +492,16 @@
|
||||
|
||||
(def ^:const token-for-fees-symbol "ETH")
|
||||
|
||||
;; The 15% buffer accounts for Ethereum's EIP-1559 fee mechanism, where the base fee can increase
|
||||
;; by up to 12.5% per block in periods of high congestion. The extra 2.5% provides additional
|
||||
;; safety to prevent failed transactions due to rapid gas price fluctuations.
|
||||
(def ^:const eth-max-fee-buffer-percent 15)
|
||||
|
||||
(def ^:const transaction-status-success "Success")
|
||||
(def ^:const transaction-status-pending "Pending")
|
||||
(def ^:const transaction-status-failed "Failed")
|
||||
|
||||
(def ^:const eth-send-amount-decimal 4)
|
||||
(def ^:const min-token-decimals-to-display 6)
|
||||
(def ^:const swap-proposal-refresh-interval-ms 15000)
|
||||
|
||||
|
||||
@@ -275,8 +275,7 @@
|
||||
{:events [:chat/unmute-chat-community]}
|
||||
[{:keys [db]} chat-id]
|
||||
(let [{:keys [community-id]} (get-in db [:chats chat-id])]
|
||||
(when community-id
|
||||
{:db (assoc-in db [:communities community-id :muted] false)})))
|
||||
{:db (assoc-in db [:communities community-id :muted] false)}))
|
||||
|
||||
(rf/defn mute-chat-failed
|
||||
{:events [:chat/mute-failed]}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
(:require [quo.core :as quo]
|
||||
[status-im.contexts.wallet.send.utils :as send-utils]
|
||||
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
|
||||
[status-im.contexts.wallet.swap.utils :as swap-utils]
|
||||
[status-im.feature-flags :as ff]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]
|
||||
@@ -78,34 +79,34 @@
|
||||
|
||||
(defn token-value-drawer
|
||||
[token watch-only? entry-point]
|
||||
(let [token-symbol (:token token)
|
||||
token-data (rf/sub [:wallet/token-by-symbol-from-first-available-account-with-balance
|
||||
token-symbol])
|
||||
selected-account (rf/sub [:wallet/current-viewing-account-address])
|
||||
token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol])
|
||||
testnet-mode? (rf/sub [:profile/test-networks-enabled?])
|
||||
account-owns-token? (rf/sub [:wallet/current-account-owns-token token-symbol])
|
||||
network-details (rf/sub [:wallet/network-details])
|
||||
receive-token-symbol (if (= token-symbol "SNT") "ETH" "SNT")
|
||||
token-owned? (if selected-account account-owns-token? (seq token-owners))
|
||||
asset-to-receive (rf/sub [:wallet/token-by-symbol receive-token-symbol])
|
||||
unique-owner? (= (count token-owners) 1)
|
||||
params (cond-> {:start-flow? true
|
||||
:owners token-owners
|
||||
:testnet-mode? testnet-mode?}
|
||||
selected-account
|
||||
(assoc :token token-data
|
||||
:stack-id :screen/wallet.accounts
|
||||
:has-balance? (-> (get-in token [:values :fiat-unformatted-value])
|
||||
money/above-zero?))
|
||||
(and (not selected-account) unique-owner?)
|
||||
(assoc :token-symbol token-symbol
|
||||
:token token-data
|
||||
:stack-id :wallet-stack)
|
||||
(let [token-symbol (:token token)
|
||||
token-data (rf/sub [:wallet/token-by-symbol-from-first-available-account-with-balance
|
||||
token-symbol])
|
||||
selected-account (rf/sub [:wallet/current-viewing-account-address])
|
||||
token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol])
|
||||
testnet-mode? (rf/sub [:profile/test-networks-enabled?])
|
||||
account-owns-token? (rf/sub [:wallet/current-account-owns-token token-symbol])
|
||||
network-details (rf/sub [:wallet/network-details])
|
||||
token-owned? (if selected-account account-owns-token? (seq token-owners))
|
||||
asset-to-receive (rf/sub [:wallet/token-by-symbol-from-first-available-account-with-balance
|
||||
(swap-utils/default-asset-to-receive token-symbol)])
|
||||
unique-owner? (= (count token-owners) 1)
|
||||
params (cond-> {:start-flow? true
|
||||
:owners token-owners
|
||||
:testnet-mode? testnet-mode?}
|
||||
selected-account
|
||||
(assoc :token token-data
|
||||
:stack-id :screen/wallet.accounts
|
||||
:has-balance? (-> (get-in token [:values :fiat-unformatted-value])
|
||||
money/above-zero?))
|
||||
(and (not selected-account) unique-owner?)
|
||||
(assoc :token-symbol token-symbol
|
||||
:token token-data
|
||||
:stack-id :wallet-stack)
|
||||
|
||||
(and (not selected-account) (not unique-owner?))
|
||||
(assoc :token-symbol token-symbol
|
||||
:stack-id :wallet-stack))]
|
||||
(and (not selected-account) (not unique-owner?))
|
||||
(assoc :token-symbol token-symbol
|
||||
:stack-id :wallet-stack))]
|
||||
[quo/action-drawer
|
||||
[(cond->> [(when (ff/enabled? ::ff/wallet.assets-modal-manage-tokens)
|
||||
(action-manage-tokens watch-only?))
|
||||
|
||||
@@ -182,12 +182,22 @@
|
||||
[amount display-decimals]
|
||||
(let [number (or (money/bignumber amount)
|
||||
(money/bignumber 0))
|
||||
amount-fixed-decimals (number/to-fixed number display-decimals)]
|
||||
amount-fixed-decimals (-> number
|
||||
(number/format-decimal-fixed display-decimals)
|
||||
(number/remove-trailing-zeroes))]
|
||||
(if (and (= amount-fixed-decimals "0")
|
||||
(money/above-zero? amount))
|
||||
(number/small-number-threshold display-decimals)
|
||||
(str amount-fixed-decimals))))
|
||||
|
||||
(defn token-balance-for-network
|
||||
"Returns the token balance for a specific chain"
|
||||
[token chain-id]
|
||||
(let [token-decimals (:decimals token)]
|
||||
(-> (get-in token [:balances-per-chain chain-id :raw-balance] 0)
|
||||
(number/convert-to-whole-number token-decimals)
|
||||
money/bignumber)))
|
||||
|
||||
(defn token-balance-display-for-network
|
||||
"Formats a token balance for a specific chain and rounds it to a specified number of decimals.
|
||||
If the balance is less than the smallest representable value based on rounding decimals,
|
||||
@@ -480,3 +490,25 @@
|
||||
(filter (fn [{:keys [tokens]}]
|
||||
(some positive-balance-in-any-chain? tokens))
|
||||
operable-account))))
|
||||
|
||||
(defn calculate-max-safe-send-amount
|
||||
"Calculates the max ETH that can be sent while reserving enough for gas fees.
|
||||
|
||||
- Ensures a minimum of 0.0001 ETH and a max of 0.01 ETH for gas.
|
||||
- Uses 20% of the value as an estimated fee, clamped within this range.
|
||||
- In Desktop it's 10% but after some more test, we found 20% is better option.
|
||||
- Prevents sending the full balance to avoid transaction failures.
|
||||
|
||||
Aligned with the desktop logic for consistency.
|
||||
https://github.com/status-im/status-desktop/blob/f320abb5c498ac260a1a4a9db046485b88af81e7/ui/app/AppLayouts/Wallet/WalletUtils.qml#L44"
|
||||
[value]
|
||||
(if (or (nil? value) (zero? value))
|
||||
"0"
|
||||
(let [raw-fee (money/mul (money/bignumber value) 0.2)
|
||||
clamped-fee (money/maximum (money/bignumber 0.0001)
|
||||
(money/minimum (money/bignumber 0.01) raw-fee))
|
||||
result (money/sub (money/bignumber value) clamped-fee)]
|
||||
(-> result
|
||||
(money/maximum 0)
|
||||
(number/format-decimal-fixed constants/eth-send-amount-decimal)
|
||||
(number/remove-trailing-zeroes)))))
|
||||
|
||||
@@ -202,7 +202,7 @@
|
||||
(is (= (utils/sanitized-token-amount-to-display 0.0001 3) "<0.001"))
|
||||
(is (= (utils/sanitized-token-amount-to-display 0.00001 3) "<0.001"))
|
||||
(is (= (utils/sanitized-token-amount-to-display 0 2) "0"))
|
||||
(is (= (utils/sanitized-token-amount-to-display 123.456789 4) "123.4568"))
|
||||
(is (= (utils/sanitized-token-amount-to-display 123.456789 4) "123.4567"))
|
||||
(is (= (utils/sanitized-token-amount-to-display 0.00000123 6) "0.000001"))
|
||||
(is (= (utils/sanitized-token-amount-to-display nil 2) "0"))
|
||||
(is (= (utils/sanitized-token-amount-to-display "invalid" 2) "0"))))
|
||||
@@ -375,3 +375,14 @@
|
||||
{:symbol "DAI"}
|
||||
{:symbol "ETH"}]]
|
||||
(is (= (utils/sort-tokens-by-name tokens) expected)))))
|
||||
|
||||
(deftest calculate-max-safe-send-amount-test
|
||||
(testing "Calculates the max ETH sendable while reserving fees"
|
||||
(is (= "0" (utils/calculate-max-safe-send-amount nil)))
|
||||
(is (= "0" (utils/calculate-max-safe-send-amount 0)))
|
||||
(is (= "0" (utils/calculate-max-safe-send-amount 0.00009)))
|
||||
(is (= "0" (utils/calculate-max-safe-send-amount 0.0001)))
|
||||
(is (= "0.008" (utils/calculate-max-safe-send-amount 0.01)))
|
||||
(is (= "0.99" (utils/calculate-max-safe-send-amount 1.0)))
|
||||
(is (= "9.99" (utils/calculate-max-safe-send-amount 10.0)))
|
||||
(is (= "99.99" (utils/calculate-max-safe-send-amount 100.0)))))
|
||||
|
||||
@@ -313,3 +313,40 @@
|
||||
(-> collectible
|
||||
transforms/json->clj
|
||||
transform-collectible))
|
||||
|
||||
(defn- bridge-amount-greater-than-bonder-fees?
|
||||
[{{token-decimals :decimals} :from-token
|
||||
bonder-fees :tx-bonder-fees
|
||||
amount-in :amount-in}]
|
||||
(let [bonder-fees (utils.money/token->unit bonder-fees token-decimals)
|
||||
amount-to-bridge (utils.money/token->unit amount-in token-decimals)]
|
||||
(> amount-to-bridge bonder-fees)))
|
||||
|
||||
(defn- remove-multichain-routes
|
||||
[routes]
|
||||
(if (> (count routes) 1)
|
||||
[] ;; if route is multichain, we remove it
|
||||
routes))
|
||||
|
||||
(defn- remove-invalid-bonder-fees-routes
|
||||
[routes]
|
||||
(filter bridge-amount-greater-than-bonder-fees? routes))
|
||||
|
||||
(defn- ->old-route-paths
|
||||
[routes]
|
||||
(map new->old-route-path routes))
|
||||
|
||||
(def ^:private best-routes-fix
|
||||
(comp ->old-route-paths
|
||||
remove-invalid-bonder-fees-routes
|
||||
remove-multichain-routes))
|
||||
|
||||
(def ^:private candidates-fix
|
||||
(comp ->old-route-paths remove-invalid-bonder-fees-routes))
|
||||
|
||||
(defn fix-routes
|
||||
[data]
|
||||
(-> data
|
||||
(rpc->suggested-routes)
|
||||
(update :best best-routes-fix)
|
||||
(update :candidates candidates-fix)))
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as utils.money]
|
||||
[utils.number]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
@@ -623,43 +622,6 @@
|
||||
{:event :wallet/stop-get-suggested-routes
|
||||
:error error}))}]]]}))
|
||||
|
||||
(defn- bridge-amount-greater-than-bonder-fees?
|
||||
[{{token-decimals :decimals} :from-token
|
||||
bonder-fees :tx-bonder-fees
|
||||
amount-in :amount-in}]
|
||||
(let [bonder-fees (utils.money/token->unit bonder-fees token-decimals)
|
||||
amount-to-bridge (utils.money/token->unit amount-in token-decimals)]
|
||||
(> amount-to-bridge bonder-fees)))
|
||||
|
||||
(defn- remove-multichain-routes
|
||||
[routes]
|
||||
(if (> (count routes) 1)
|
||||
[] ;; if route is multichain, we remove it
|
||||
routes))
|
||||
|
||||
(defn- remove-invalid-bonder-fees-routes
|
||||
[routes]
|
||||
(filter bridge-amount-greater-than-bonder-fees? routes))
|
||||
|
||||
(defn- ->old-route-paths
|
||||
[routes]
|
||||
(map data-store/new->old-route-path routes))
|
||||
|
||||
(def ^:private best-routes-fix
|
||||
(comp ->old-route-paths
|
||||
remove-invalid-bonder-fees-routes
|
||||
remove-multichain-routes))
|
||||
|
||||
(def ^:private candidates-fix
|
||||
(comp ->old-route-paths remove-invalid-bonder-fees-routes))
|
||||
|
||||
(defn- fix-routes
|
||||
[data]
|
||||
(-> data
|
||||
(data-store/rpc->suggested-routes)
|
||||
(update :best best-routes-fix)
|
||||
(update :candidates candidates-fix)))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/handle-suggested-routes
|
||||
(fn [{:keys [db]} [data]]
|
||||
@@ -685,8 +647,8 @@
|
||||
(cond
|
||||
(and failure? swap?) [:wallet/swap-proposal-error error]
|
||||
failure? [:wallet/suggested-routes-error error-message]
|
||||
swap? [:wallet/swap-proposal-success (fix-routes data)]
|
||||
:else [:wallet/suggested-routes-success (fix-routes data)
|
||||
swap? [:wallet/swap-proposal-success (data-store/fix-routes data)]
|
||||
:else [:wallet/suggested-routes-success (data-store/fix-routes data)
|
||||
enough-assets?])]]}))))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
(:require [re-frame.core :as rf]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.data-store :as data-store]
|
||||
[status-im.contexts.wallet.send.utils :as send-utils]
|
||||
[status-im.contexts.wallet.sheets.network-selection.view :as network-selection]
|
||||
[status-im.contexts.wallet.swap.utils :as swap-utils]
|
||||
@@ -28,6 +29,15 @@
|
||||
:account account
|
||||
:test-networks-enabled? test-networks-enabled?
|
||||
:token-symbol (get-in data [:asset-to-pay :symbol])}))
|
||||
received-asset (if-not (nil? asset-to-receive)
|
||||
asset-to-receive
|
||||
(swap-utils/select-asset-to-pay-by-symbol
|
||||
{:wallet wallet
|
||||
:account account
|
||||
:test-networks-enabled? test-networks-enabled?
|
||||
:token-symbol (if (= (:symbol asset-to-pay) "SNT")
|
||||
"ETH"
|
||||
"SNT")}))
|
||||
multi-account-balance? (-> available-accounts
|
||||
(count)
|
||||
(> 1))
|
||||
@@ -36,7 +46,7 @@
|
||||
start-point (if open-new-screen? :action-menu :swap-button)]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :swap :asset-to-pay] asset-to-pay)
|
||||
(assoc-in [:wallet :ui :swap :asset-to-receive] asset-to-receive)
|
||||
(assoc-in [:wallet :ui :swap :asset-to-receive] received-asset)
|
||||
(assoc-in [:wallet :ui :swap :network] network')
|
||||
(assoc-in [:wallet :ui :swap :launch-screen] view-id)
|
||||
(assoc-in [:wallet :ui :swap :start-point] start-point))
|
||||
@@ -53,7 +63,7 @@
|
||||
[:centralized-metrics/track :metric/swap-start
|
||||
{:network (:chain-id network)
|
||||
:pay_token (:symbol asset-to-pay)
|
||||
:receive_token (:symbol asset-to-receive)
|
||||
:receive_token (:symbol received-asset)
|
||||
:start_point start-point
|
||||
:launch_screen view-id}]]
|
||||
[:dispatch [:wallet.swap/set-default-slippage]]]
|
||||
@@ -67,7 +77,7 @@
|
||||
(rf/dispatch
|
||||
[:wallet.swap/start
|
||||
{:asset-to-pay asset-to-pay
|
||||
:asset-to-receive asset-to-receive
|
||||
:asset-to-receive received-asset
|
||||
:network network
|
||||
:open-new-screen?
|
||||
open-new-screen?
|
||||
@@ -577,3 +587,82 @@
|
||||
[:dispatch
|
||||
[:navigate-to-within-stack
|
||||
[:screen/wallet.swap-select-asset-to-pay :screen/wallet.swap-select-account]]]])})))
|
||||
|
||||
(rf/reg-event-fx :wallet/get-swap-proposal-fee
|
||||
(fn [{:keys [db]} [{:keys [amount-in amount-out]}]]
|
||||
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
|
||||
{:keys [asset-to-pay asset-to-receive
|
||||
network]} (get-in db [:wallet :ui :swap])
|
||||
test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
|
||||
networks ((if test-networks-enabled? :test :prod)
|
||||
(get-in db [:wallet :networks]))
|
||||
network-chain-ids (map :chain-id networks)
|
||||
pay-token-decimal (:decimals asset-to-pay)
|
||||
pay-token-id (:symbol asset-to-pay)
|
||||
receive-token-id (:symbol asset-to-receive)
|
||||
receive-token-decimals (:decimals asset-to-receive)
|
||||
gas-rates constants/gas-rate-medium
|
||||
amount-in-hex (if amount-in
|
||||
(send-utils/amount-in-hex amount-in pay-token-decimal)
|
||||
0)
|
||||
amount-out-hex (when amount-out
|
||||
(send-utils/amount-in-hex amount-out receive-token-decimals))
|
||||
to-address wallet-address
|
||||
from-address wallet-address
|
||||
swap-chain-id (:chain-id network)
|
||||
disabled-to-chain-ids (filter #(not= % swap-chain-id) network-chain-ids)
|
||||
disabled-from-chain-ids (filter #(not= % swap-chain-id) network-chain-ids)
|
||||
from-locked-amount {}
|
||||
send-type constants/send-type-swap
|
||||
request-uuid (str (random-uuid))
|
||||
params [(cond->
|
||||
{:uuid request-uuid
|
||||
:sendType send-type
|
||||
:addrFrom from-address
|
||||
:addrTo to-address
|
||||
:tokenID pay-token-id
|
||||
:toTokenID receive-token-id
|
||||
:disabledFromChainIDs disabled-from-chain-ids
|
||||
:disabledToChainIDs disabled-to-chain-ids
|
||||
:gasFeeMode gas-rates
|
||||
:fromLockedAmount from-locked-amount
|
||||
:amountOut (or amount-out-hex "0x0")}
|
||||
amount-in (assoc :amountIn amount-in-hex))]]
|
||||
{:db (assoc-in db [:wallet :ui :swap :loading-swap-proposal-fee?] true)
|
||||
:json-rpc/call [{:method "wallet_getSuggestedRoutes"
|
||||
:params params
|
||||
:on-success (fn [data]
|
||||
(let [swap-proposal (data-store/fix-routes data)]
|
||||
(rf/dispatch [:wallet/swap-proposal-fee-success
|
||||
swap-proposal])))
|
||||
:on-error (fn [error]
|
||||
(rf/dispatch [:wallet/swap-proposal-fee-error])
|
||||
(log/error "failed to get suggested routes"
|
||||
{:event :wallet/get-swap-proposal-fee
|
||||
:error (:message error)
|
||||
:params params}))}]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/swap-proposal-fee-success
|
||||
(fn [{:keys [db]} [swap-proposal]]
|
||||
(let [best-routes (:best swap-proposal)
|
||||
selected-route (first best-routes)
|
||||
relevant-fee-fields [:gas-amount :gas-fees :token-fees :approval-required
|
||||
:approval-fee :approval-l-1-fee :bonder-fees]
|
||||
fee-data (select-keys selected-route relevant-fee-fields)]
|
||||
{:db (update-in db
|
||||
[:wallet :ui :swap]
|
||||
assoc
|
||||
:loading-swap-proposal-fee? false
|
||||
:swap-proposal
|
||||
(when-not (empty? best-routes)
|
||||
fee-data))})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/swap-proposal-fee-error
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db
|
||||
[:wallet :ui :swap]
|
||||
assoc
|
||||
:loading-swap-proposal-fee?
|
||||
false)}))
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
|
||||
[status-im.contexts.wallet.common.asset-list.view :as asset-list]
|
||||
[status-im.contexts.wallet.swap.select-asset-to-pay.style :as style]
|
||||
[status-im.contexts.wallet.swap.utils :as swap-utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@@ -20,11 +21,11 @@
|
||||
|
||||
(defn- assets-view
|
||||
[search-text on-change-text]
|
||||
(let [snt-token (rf/sub [:wallet/token-by-symbol "SNT"])
|
||||
eth-token (rf/sub [:wallet/token-by-symbol "ETH"])
|
||||
on-token-press (fn [token]
|
||||
(let [on-token-press (fn [token]
|
||||
(let [pay-token-symbol (:symbol token)
|
||||
asset-to-receive (if (= pay-token-symbol "SNT") eth-token snt-token)]
|
||||
asset-to-receive (rf/sub [:wallet/token-by-symbol
|
||||
(swap-utils/default-asset-to-receive
|
||||
pay-token-symbol)])]
|
||||
(rf/dispatch [:wallet.swap/start
|
||||
{:asset-to-pay {:symbol pay-token-symbol}
|
||||
:asset-to-receive asset-to-receive
|
||||
|
||||
@@ -115,6 +115,7 @@
|
||||
pay-token-symbol (rf/sub [:wallet/swap-asset-to-pay-symbol])
|
||||
pay-token-decimals (rf/sub [:wallet/swap-asset-to-pay-decimals])
|
||||
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
|
||||
loading-swap-proposal-fee? (rf/sub [:wallet/swap-loading-swap-proposal-fee?])
|
||||
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
|
||||
approval-required (rf/sub [:wallet/swap-proposal-approval-required])
|
||||
approval-amount-required (rf/sub [:wallet/swap-proposal-approval-amount-required])
|
||||
@@ -122,6 +123,7 @@
|
||||
approval-transaction-id (rf/sub [:wallet/swap-approval-transaction-id])
|
||||
approved-amount (rf/sub [:wallet/swap-approved-amount])
|
||||
error-response (rf/sub [:wallet/swap-error-response])
|
||||
eth-proposal? (= pay-token-symbol "ETH")
|
||||
overlay-shown? (boolean (:sheets (rf/sub [:bottom-sheet])))
|
||||
input-ref (rn/use-ref-atom nil)
|
||||
set-input-ref (rn/use-callback (fn [ref] (reset! input-ref ref)))
|
||||
@@ -131,12 +133,16 @@
|
||||
(:chain-id network)])
|
||||
pay-token-fiat-value (rf/sub [:wallet/swap-asset-to-pay-amount-in-fiat
|
||||
pay-input-num-value])
|
||||
available-crypto-limit (money/bignumber
|
||||
pay-token-balance-selected-chain)
|
||||
available-crypto-limit (rf/sub [:wallet/swap-available-crypto-limit])
|
||||
display-decimals (min pay-token-decimals
|
||||
constants/min-token-decimals-to-display)
|
||||
available-crypto-limit-display (rf/sub [:wallet/swap-asset-to-pay-balance-for-chain-ui
|
||||
(:chain-id network)])
|
||||
(if eth-proposal?
|
||||
constants/eth-send-amount-decimal
|
||||
constants/min-token-decimals-to-display))
|
||||
total-crypto-limit (money/bignumber
|
||||
pay-token-balance-selected-chain)
|
||||
total-crypto-limit-display (utils/sanitized-token-amount-to-display
|
||||
total-crypto-limit
|
||||
display-decimals)
|
||||
approval-amount-required-num (when approval-amount-required
|
||||
(number/to-fixed (number/hex->whole
|
||||
approval-amount-required
|
||||
@@ -157,14 +163,36 @@
|
||||
pay-input-amount))
|
||||
(> pay-input-amount 0)
|
||||
(not pay-input-error?))
|
||||
request-swap-proposal-fee (rn/use-callback
|
||||
(fn []
|
||||
(let [safe-send-amount (utils/calculate-max-safe-send-amount
|
||||
pay-token-balance-selected-chain)]
|
||||
(rf/dispatch [:wallet/get-swap-proposal-fee
|
||||
{:amount-in safe-send-amount}])))
|
||||
[pay-token-balance-selected-chain])
|
||||
request-fetch-swap-proposal (rn/use-callback
|
||||
(fn []
|
||||
(fetch-swap-proposal
|
||||
{:amount pay-input-amount
|
||||
:valid-input? valid-pay-input?
|
||||
:clean-approval-transaction? true}))
|
||||
[pay-input-amount])]
|
||||
[pay-input-amount])
|
||||
on-max-balance-press (rn/use-callback
|
||||
(fn []
|
||||
(let [max-value (if eth-proposal?
|
||||
(number/format-decimal-fixed
|
||||
available-crypto-limit
|
||||
constants/eth-send-amount-decimal)
|
||||
(money/to-string available-crypto-limit))]
|
||||
(when (money/greater-than max-value 0)
|
||||
(on-max-press max-value))))
|
||||
[available-crypto-limit eth-proposal?])]
|
||||
(rn/use-unmount #(rf/dispatch [:wallet/clean-swap]))
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(when eth-proposal?
|
||||
(request-swap-proposal-fee)))
|
||||
[eth-proposal?])
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(request-fetch-swap-proposal))
|
||||
@@ -196,12 +224,13 @@
|
||||
input-focused? :typing
|
||||
:else :disabled)
|
||||
:on-token-press on-token-press
|
||||
:on-max-press #(on-max-press (str pay-token-balance-selected-chain))
|
||||
:on-max-press on-max-balance-press
|
||||
:max-loading? loading-swap-proposal-fee?
|
||||
:on-input-focus on-input-focus
|
||||
:value pay-input-amount
|
||||
:fiat-value pay-token-fiat-value
|
||||
:network-tag-props {:title (i18n/label :t/max-token
|
||||
{:number available-crypto-limit-display
|
||||
{:number total-crypto-limit-display
|
||||
:token-symbol pay-token-symbol})
|
||||
:networks [{:source (:source network)}]}
|
||||
:approval-label-props {:status (case approval-transaction-status
|
||||
@@ -302,16 +331,16 @@
|
||||
|
||||
(defn- action-button
|
||||
[{:keys [on-press]}]
|
||||
(let [account-color (rf/sub [:wallet/current-viewing-account-color])
|
||||
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
|
||||
error-response (rf/sub [:wallet/swap-error-response])
|
||||
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
|
||||
approval-required? (rf/sub [:wallet/swap-proposal-approval-required])
|
||||
approval-transaction-status (rf/sub [:wallet/swap-approval-transaction-status])]
|
||||
(let [account-color (rf/sub [:wallet/current-viewing-account-color])
|
||||
swap-proposal-received-amount (rf/sub [:wallet/swap-proposal-amount-out])
|
||||
error-response (rf/sub [:wallet/swap-error-response])
|
||||
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
|
||||
approval-required? (rf/sub [:wallet/swap-proposal-approval-required])
|
||||
approval-transaction-status (rf/sub [:wallet/swap-approval-transaction-status])]
|
||||
[quo/bottom-actions
|
||||
{:actions :one-action
|
||||
:button-one-label (i18n/label :t/review-swap)
|
||||
:button-one-props {:disabled? (or (not swap-proposal)
|
||||
:button-one-props {:disabled? (or (not swap-proposal-received-amount)
|
||||
error-response
|
||||
(and approval-required?
|
||||
(not= approval-transaction-status :confirmed))
|
||||
|
||||
@@ -62,3 +62,9 @@
|
||||
[{:keys [networks]}]
|
||||
(when (= (count networks) 1)
|
||||
(first networks)))
|
||||
|
||||
(defn default-asset-to-receive
|
||||
[pay-token-symbol]
|
||||
(cond (= pay-token-symbol "SNT") "ETH"
|
||||
(= pay-token-symbol "ETH") "USDC"
|
||||
:else "SNT"))
|
||||
|
||||
@@ -142,6 +142,11 @@
|
||||
:<- [:wallet/swap]
|
||||
:-> :loading-swap-proposal?)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/swap-loading-swap-proposal-fee?
|
||||
:<- [:wallet/swap]
|
||||
:-> :loading-swap-proposal-fee?)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/swap-transaction-for-signing
|
||||
:<- [:wallet/swap]
|
||||
@@ -373,3 +378,28 @@
|
||||
:token asset-to-pay
|
||||
:prices-per-token prices-per-token})]
|
||||
(utils/fiat-formatted-for-ui currency-symbol fiat-value)))))
|
||||
|
||||
(rf/reg-sub :wallet/max-swap-fee
|
||||
:<- [:wallet/swap-proposal-approval-required]
|
||||
:<- [:wallet/swap-approval-fee]
|
||||
:<- [:wallet/swap-proposal]
|
||||
(fn [[approval-required swap-approval-fee swap-proposal]]
|
||||
(let [wallet-swap-proposal-fee (send-utils/full-route-gas-fee [swap-proposal])]
|
||||
(if approval-required
|
||||
(money/add swap-approval-fee wallet-swap-proposal-fee)
|
||||
wallet-swap-proposal-fee))))
|
||||
|
||||
(rf/reg-sub :wallet/swap-available-crypto-limit
|
||||
:<- [:wallet/swap-network]
|
||||
:<- [:wallet/swap-asset-to-pay-balance-for-chain-data]
|
||||
:<- [:wallet/max-swap-fee]
|
||||
:<- [:wallet/swap-asset-to-pay-symbol]
|
||||
(fn [[network asset-to-pay-with-current-account-balance max-swap-fee pay-token-symbol]]
|
||||
(let [pay-token-balance (utils/token-balance-for-network
|
||||
asset-to-pay-with-current-account-balance
|
||||
(:chain-id network))]
|
||||
(if (= pay-token-symbol constants/token-for-fees-symbol)
|
||||
(let [buffered-fee (money/mul max-swap-fee
|
||||
(inc (/ constants/eth-max-fee-buffer-percent 100)))]
|
||||
(money/sub pay-token-balance buffered-fee))
|
||||
pay-token-balance))))
|
||||
|
||||
@@ -246,3 +246,13 @@
|
||||
(schema/=> format-amount
|
||||
[:=> [:cat [:maybe :int]]
|
||||
[:maybe :string]])
|
||||
|
||||
(defn maximum
|
||||
[n1 n2]
|
||||
(when-let [[^js bn1 ^js bn2] (->bignumbers n1 n2)]
|
||||
(if (greater-than-or-equals bn1 bn2) bn1 bn2)))
|
||||
|
||||
(defn minimum
|
||||
[n1 n2]
|
||||
(when-let [[^js bn1 ^js bn2] (->bignumbers n1 n2)]
|
||||
(if (less-than bn1 bn2) bn1 bn2)))
|
||||
|
||||
@@ -97,3 +97,18 @@
|
||||
[num decimal-count]
|
||||
(let [decimal-part (second (string/split (str num) #"\."))]
|
||||
(or (nil? decimal-part) (<= (count decimal-part) decimal-count))))
|
||||
|
||||
(defn format-decimal-fixed
|
||||
"Formats a number `n` to `decimal-places` without rounding.
|
||||
- Ensures the exact number of decimal places (including trailing zeros).
|
||||
- Does not round up or down, just trims excess decimals."
|
||||
[n decimal-places]
|
||||
(let [bn (money/bignumber n)
|
||||
scale (money/bignumber (money/from-decimal decimal-places))
|
||||
truncated (if (money/less-than bn 0)
|
||||
(Math/ceil (money/mul bn scale))
|
||||
(Math/floor (money/mul bn scale)))]
|
||||
(-> truncated
|
||||
(money/bignumber)
|
||||
(money/div scale)
|
||||
(money/to-fixed decimal-places))))
|
||||
|
||||
@@ -88,3 +88,19 @@
|
||||
|
||||
(is (true? (utils.number/valid-decimal-count? 1234567890.12 2)))
|
||||
(is (false? (utils.number/valid-decimal-count? 1234567890.12345 3)))))
|
||||
|
||||
(deftest format-decimal-fixed-test
|
||||
(testing "Format decimal numbers correctly without rounding"
|
||||
(is (= "123.45" (utils.number/format-decimal-fixed "123.456" 2)))
|
||||
(is (= "123.456" (utils.number/format-decimal-fixed "123.456" 3)))
|
||||
|
||||
(is (= "123.45600" (utils.number/format-decimal-fixed "123.456" 5)))
|
||||
(is (= "123.000" (utils.number/format-decimal-fixed "123.000" 3)))
|
||||
|
||||
(is (= "123" (utils.number/format-decimal-fixed "123.999" 0)))
|
||||
|
||||
(is (= "-123.4" (utils.number/format-decimal-fixed "-123.456" 1)))
|
||||
(is (= "-123.45" (utils.number/format-decimal-fixed "-123.456" 2)))
|
||||
|
||||
(is (= "0.0006" (utils.number/format-decimal-fixed "0.000650462672354754" 4)))
|
||||
(is (= "999999999.999" (utils.number/format-decimal-fixed "999999999.999999" 3)))))
|
||||
|
||||
@@ -199,7 +199,7 @@ def create_shared_drivers(quantity: int, platform_version: int = 14, device_name
|
||||
test_suite_data.current_test.testruns[-1].jobs[drivers[i].session_id] = i + 1
|
||||
drivers[i].implicitly_wait(implicit_wait)
|
||||
drivers[i].update_settings({"enforceXPath1": True})
|
||||
drivers[i].set_network_connection(ConnectionType.ALL_NETWORK_ON)
|
||||
drivers[i].set_network_connection(ConnectionType.WIFI_ONLY)
|
||||
return drivers, loop
|
||||
except (MaxRetryError, AttributeError) as e:
|
||||
test_suite_data.current_test.testruns[-1].error = str(e)
|
||||
|
||||
@@ -710,9 +710,10 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
if not self.chat_1.chat_element_by_text(message_to_disappear).is_element_disappeared(30):
|
||||
self.errors.append(self.chat_1, "Messages from blocked user is not cleared in public chat ")
|
||||
self.chat_1.navigate_back_to_home_view()
|
||||
self.home_1.chats_tab.click()
|
||||
if not self.home_1.element_by_translation_id("no-messages").is_element_displayed():
|
||||
self.errors.append("1-1 chat from blocked user is not removed and messages home is not empty!")
|
||||
# ToDo: enable when https://github.com/status-im/status-mobile/issues/19334 is fixed
|
||||
# self.home_1.chats_tab.click()
|
||||
# if not self.home_1.element_by_translation_id("no-messages").is_element_displayed():
|
||||
# self.errors.append("1-1 chat from blocked user is not removed and messages home is not empty!")
|
||||
self.chat_1.driver.set_network_connection(ConnectionType.AIRPLANE_MODE)
|
||||
|
||||
self.home_2.just_fyi('Send message to public chat while device 1 is offline')
|
||||
@@ -1244,199 +1245,3 @@ class TestCommunityMultipleDeviceMergedTwo(MultipleSharedDeviceTestCase):
|
||||
self.errors.append(self.home_2, "%s is not listed inside Joined communities tab" % community_name)
|
||||
|
||||
self.errors.verify_no_errors()
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="new_three_2")
|
||||
@marks.nightly
|
||||
class TestCommunityMultipleDeviceMergedThree(MultipleSharedDeviceTestCase):
|
||||
|
||||
def prepare_devices(self):
|
||||
self.drivers, self.loop = create_shared_drivers(2)
|
||||
self.device_1, self.device_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
|
||||
self.loop.run_until_complete(run_in_parallel(((self.device_1.create_user,),
|
||||
(self.device_2.create_user,))))
|
||||
self.homes = self.home_1, self.home_2 = self.device_1.get_home_view(), self.device_2.get_home_view()
|
||||
self.username_1, self.username_2 = self.home_1.get_username(), self.home_2.get_username()
|
||||
self.public_key_2 = self.home_2.get_public_key()
|
||||
self.profile_1 = self.home_1.get_profile_view()
|
||||
[home.navigate_back_to_home_view() for home in self.homes]
|
||||
[home.chats_tab.click() for home in self.homes]
|
||||
self.home_1.add_contact(self.public_key_2)
|
||||
self.home_2.handle_contact_request(self.username_1)
|
||||
self.text_message = 'hello'
|
||||
|
||||
self.chat_1 = self.home_1.get_chat(self.username_2).click()
|
||||
self.chat_1.send_message('hey')
|
||||
self.chat_2 = self.home_2.get_chat(self.username_1).click()
|
||||
self.home_1.navigate_back_to_home_view()
|
||||
|
||||
self.home_1.just_fyi("Open community to message")
|
||||
self.home_1.communities_tab.click()
|
||||
self.community_name = "open community"
|
||||
self.channel_name = 'general'
|
||||
self.home_1.create_community(community_type="open")
|
||||
|
||||
self.community_1, self.community_2 = self.home_1.get_community_view(), self.home_2.get_community_view()
|
||||
self.community_1.invite_to_community(self.community_name, self.username_2)
|
||||
self.channel_1 = self.home_1.get_to_community_channel_from_home(self.community_name)
|
||||
|
||||
self.community_2.join_community()
|
||||
self.channel_2 = self.community_2.get_channel(self.channel_name).click()
|
||||
|
||||
@marks.testrail_id(741924)
|
||||
def test_community_mobile_data_and_wi_fi_only_fetching(self):
|
||||
self.device_2.just_fyi("Receiver turns wi-fi off")
|
||||
self.device_2.navigate_back_to_home_view()
|
||||
self.device_2.driver.set_network_connection(ConnectionType.DATA_ONLY)
|
||||
# ToDo: pop up is not shown on LT emulators, needs more investigation
|
||||
# self.device_2.turn_wi_fi_off()
|
||||
#
|
||||
# for translation in ['which-connection-to-use', 'mobile-and-wifi', 'wifi-only']:
|
||||
# if not self.device_2.element_by_translation_id(translation).is_element_displayed():
|
||||
# self.errors.append(self.device_2,
|
||||
# "Element with text '%s' is not shown when switching to mobile data" % translation)
|
||||
profile_2 = self.device_2.profile_button.click()
|
||||
profile_2.syncing_button.scroll_and_click()
|
||||
profile_2.sync_and_backup_button.click()
|
||||
profile_2.wi_fi_only_button.click()
|
||||
self.device_2.click_system_back_button(times=2)
|
||||
self.home_2.communities_tab.click()
|
||||
self.home_2.discover_communities_button.click()
|
||||
if self.home_2.community_card_item.is_element_displayed(10):
|
||||
self.errors.append(self.home_2,
|
||||
"Community can be fetched while using mobile data with wi-fi only syncing settings")
|
||||
|
||||
message_1 = 'message text 1'
|
||||
self.channel_1.just_fyi("Sender sends a message in the community channel when receiver is using mobile data")
|
||||
self.channel_1.send_message(message_1)
|
||||
self.home_2.click_system_back_button()
|
||||
self.home_2.get_to_community_channel_from_home(self.community_name)
|
||||
if not self.channel_2.chat_element_by_text(message_1).is_element_displayed(120):
|
||||
self.errors.append(self.device_2,
|
||||
"Can't receive the message '%s' in community when using mobile data" % message_1)
|
||||
|
||||
self.device_2.just_fyi("Receiver turns internet off")
|
||||
self.device_2.driver.set_network_connection(ConnectionType.NO_CONNECTION)
|
||||
message_2 = 'message text 2'
|
||||
self.channel_1.just_fyi("Sender sends messages in the community channel and 1-1 chat when receiver is offline")
|
||||
self.channel_1.send_message(message_2)
|
||||
self.device_1.navigate_back_to_home_view()
|
||||
self.device_1.chats_tab.click()
|
||||
self.home_1.get_chat(self.username_2).click()
|
||||
message_3 = 'message text 3'
|
||||
self.chat_1.send_message(message_3)
|
||||
|
||||
self.device_2.just_fyi("Receiver turns mobile data on")
|
||||
self.device_2.driver.set_network_connection(ConnectionType.DATA_ONLY)
|
||||
if self.channel_2.chat_element_by_text(message_2).is_element_displayed(120):
|
||||
self.errors.append(
|
||||
self.device_2,
|
||||
"Message '%s' in community, which is sent when receiver was offline, is received using mobile data" % message_2)
|
||||
self.device_2.navigate_back_to_home_view()
|
||||
self.device_2.chats_tab.click()
|
||||
self.home_2.get_chat(self.username_1).click()
|
||||
if not self.chat_2.chat_element_by_text(message_3).is_element_displayed(120):
|
||||
self.errors.append(
|
||||
self.device_2,
|
||||
"Message '%s' in 1-1 chat, which is sent when receiver was offline, is missed" % message_3)
|
||||
|
||||
self.device_2.just_fyi("Receiver turns wi-fi on")
|
||||
self.device_2.driver.set_network_connection(ConnectionType.WIFI_ONLY)
|
||||
self.home_2.navigate_back_to_home_view()
|
||||
self.home_2.communities_tab.click()
|
||||
self.home_2.get_to_community_channel_from_home(self.community_name)
|
||||
if not self.channel_2.chat_element_by_text(message_2).is_element_displayed(120):
|
||||
self.errors.append(
|
||||
self.device_2,
|
||||
"Message '%s' in community channel, which is sent when receiver was offline, is missed after turning wi-fi on" % message_2)
|
||||
self.errors.verify_no_errors()
|
||||
|
||||
@marks.testrail_id(741925)
|
||||
def test_community_send_message_from_offline(self):
|
||||
self.device_1.just_fyi("Device 1 goes offline and send a message in 1-1 chat")
|
||||
self.device_1.driver.set_network_connection(ConnectionType.NO_CONNECTION)
|
||||
|
||||
message_1_1 = 'message in 1-1 chat'
|
||||
|
||||
def _send_message_1_1():
|
||||
self.device_1.navigate_back_to_home_view()
|
||||
self.device_1.chats_tab.click()
|
||||
self.home_1.get_chat(self.username_2).click()
|
||||
self.chat_1.send_message(message_1_1)
|
||||
|
||||
self.device_2.just_fyi("Device 2 goes offline and send a message in community")
|
||||
self.device_2.driver.set_network_connection(ConnectionType.NO_CONNECTION)
|
||||
|
||||
message_community = 'message community'
|
||||
|
||||
def _send_message_community():
|
||||
self.device_2.navigate_back_to_home_view()
|
||||
self.device_2.communities_tab.click()
|
||||
self.home_2.get_to_community_channel_from_home(self.community_name)
|
||||
self.channel_2.send_message(message_community)
|
||||
|
||||
self.loop.run_until_complete(run_in_parallel(((_send_message_1_1,), (_send_message_community,))))
|
||||
|
||||
self.device_1.just_fyi("Device 1 goes back online and checks a message in community channel")
|
||||
self.device_1.driver.set_network_connection(ConnectionType.WIFI_ONLY)
|
||||
|
||||
def _check_message_community():
|
||||
self.device_1.navigate_back_to_home_view()
|
||||
self.device_1.communities_tab.click()
|
||||
self.home_1.get_to_community_channel_from_home(self.community_name)
|
||||
if not self.channel_1.chat_element_by_text(message_community).is_element_displayed(120):
|
||||
self.errors.append(
|
||||
self.device_1,
|
||||
"Can't receive the message '%s' in community if it's sent from offline" % message_community)
|
||||
|
||||
self.device_2.just_fyi("Device 2 goes back online and checks a message in 1-1 chat")
|
||||
self.device_2.driver.set_network_connection(ConnectionType.WIFI_ONLY)
|
||||
|
||||
def _check_message_1_1():
|
||||
self.device_2.navigate_back_to_home_view()
|
||||
self.device_2.chats_tab.click()
|
||||
self.home_2.get_chat(self.username_1).click()
|
||||
if not self.chat_2.chat_element_by_text(message_1_1).is_element_displayed(120):
|
||||
self.errors.append(
|
||||
self.device_1,
|
||||
"Can't receive the message '%s' in 1-1 chat if it's sent from offline" % message_1_1)
|
||||
|
||||
self.loop.run_until_complete(run_in_parallel(((_check_message_community,), (_check_message_1_1,))))
|
||||
|
||||
self.errors.verify_no_errors()
|
||||
|
||||
@marks.testrail_id(741926)
|
||||
def test_community_messaging_on_mobile_data(self):
|
||||
self.device_1.just_fyi("Device 1 turns mobile data on and send a message in community channel")
|
||||
self.device_1.driver.set_network_connection(ConnectionType.DATA_ONLY)
|
||||
self.device_2.just_fyi("Device 2 turns mobile data on and checks receiving a message in community channel")
|
||||
self.device_2.driver.set_network_connection(ConnectionType.DATA_ONLY)
|
||||
|
||||
self.device_1.navigate_back_to_home_view()
|
||||
self.device_1.communities_tab.click()
|
||||
self.home_1.get_to_community_channel_from_home(self.community_name)
|
||||
message_community = 'message community'
|
||||
self.channel_1.send_message(message_community)
|
||||
self.device_2.navigate_back_to_home_view()
|
||||
self.device_2.communities_tab.click()
|
||||
self.home_2.get_to_community_channel_from_home(self.community_name)
|
||||
if not self.channel_2.chat_element_by_text(message_community).is_element_displayed(60):
|
||||
self.errors.append(self.channel_2,
|
||||
"Message with text '%s' was not received in community" % message_community)
|
||||
|
||||
self.device_2.just_fyi("Device 2 sends a message in 1-1 chat")
|
||||
self.device_2.navigate_back_to_home_view()
|
||||
self.device_2.chats_tab.click()
|
||||
self.home_2.get_chat(self.username_1).click()
|
||||
message_1_1 = "message 1-1 chat"
|
||||
self.chat_2.send_message(message_1_1)
|
||||
|
||||
self.device_1.just_fyi("Device 1 checks a message receiving in 1-1 chat")
|
||||
self.device_1.navigate_back_to_home_view()
|
||||
self.device_1.chats_tab.click()
|
||||
self.home_1.get_chat(self.username_2).click()
|
||||
if not self.chat_1.chat_element_by_text(message_1_1).is_element_displayed(60):
|
||||
self.errors.append(self.chat_1,
|
||||
"Message with text '%s' was not received in 1-1 chat" % message_1_1)
|
||||
|
||||
self.errors.verify_no_errors()
|
||||
|
||||
@@ -43,7 +43,7 @@ class TestWalletCollectibles(MultipleSharedDeviceTestCase):
|
||||
self.wallet_view.collectibles_tab.click()
|
||||
self.wallet_view.set_network_in_wallet(self.network_name)
|
||||
collectibles = {
|
||||
"BVL": {"quantity": 1,
|
||||
"BVL": {"quantity": 2,
|
||||
"info": {"Account": "Account 1",
|
||||
"Network": "Base",
|
||||
"category": "Football Player",
|
||||
@@ -102,8 +102,8 @@ class TestWalletCollectibles(MultipleSharedDeviceTestCase):
|
||||
self.wallet_view.collectibles_tab_on_select_token_view.click()
|
||||
time.sleep(5)
|
||||
self.wallet_view.get_collectible_element('BVL').click()
|
||||
# self.wallet_view.amount_input_increase_button.click()
|
||||
# self.wallet_view.confirm_button.click()
|
||||
self.wallet_view.amount_input_increase_button.click()
|
||||
self.wallet_view.confirm_button.click()
|
||||
for text in [self.account_name, self.sender_short_address]:
|
||||
if not self.wallet_view.from_data_container.get_child_element_by_text(text).is_element_displayed():
|
||||
self.errors.append(self.wallet_view,
|
||||
@@ -118,7 +118,7 @@ class TestWalletCollectibles(MultipleSharedDeviceTestCase):
|
||||
data_to_check = {
|
||||
'Est. time': ' min',
|
||||
'Max fees': r"[$]\d+.\d+",
|
||||
'Recipient gets': '1 '
|
||||
'Recipient gets': '2 '
|
||||
}
|
||||
for key, expected_value in data_to_check.items():
|
||||
try:
|
||||
|
||||
@@ -381,10 +381,3 @@ class BaseView(object):
|
||||
Button(self.driver,
|
||||
xpath="//*[@resource-id='android:id/resolver_list']//*[@text='%s']" % text_to_click).click_if_shown()
|
||||
Button(self.driver, xpath="//*[@resource-id='android:id/button_once']").click()
|
||||
|
||||
def turn_wi_fi_off(self):
|
||||
self.driver.swipe(900, 0, 900, 1000)
|
||||
self.element_by_text('Internet').click()
|
||||
Button(self.driver, accessibility_id='Wi‑Fi').click()
|
||||
self.element_by_text('Done').click()
|
||||
self.click_system_back_button_until_presence_of_element(self.chats_tab)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 330 KiB After Width: | Height: | Size: 329 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
@@ -120,6 +120,7 @@ class ProfileView(BaseView):
|
||||
self.recovery_phrase_next_button = Button(self.driver, accessibility_id="Next, icon")
|
||||
self.recovery_phrase_word_input = EditBox(self.driver, xpath="//android.widget.EditText")
|
||||
|
||||
|
||||
# Notifications
|
||||
self.profile_notifications_button = Button(self.driver,
|
||||
accessibility_id="icon, Notifications, label-component, icon")
|
||||
@@ -141,8 +142,6 @@ class ProfileView(BaseView):
|
||||
self.sync_plus_button = Button(
|
||||
self.driver,
|
||||
xpath="//*[@text='Paired devices']/following-sibling::android.view.ViewGroup[@content-desc='icon']")
|
||||
self.sync_and_backup_button = Button(self.driver, xpath="//*[@text='Sync and backup']")
|
||||
self.wi_fi_only_button = Button(self.driver, accessibility_id='wifi-only-action')
|
||||
|
||||
# Advanced
|
||||
self.advanced_button = AdvancedButton(self.driver)
|
||||
|
||||
Reference in New Issue
Block a user