Compare commits

..
Author SHA1 Message Date
John Huang 68ae1788c8 PR 2024-02-20 15:33:26 -08:00
John Huang 54d5b9fc1d MOB-193 PR 2024-02-20 15:30:40 -08:00
John Huang 614f92def8 Merge branch 'main' into feature/MOB-193-install-app-dlg
# Conflicts:
#	package.json
#	pnpm-lock.yaml
2024-02-20 15:18:37 -08:00
yujin512 fdc262f59f Update otherMarketExchangeConfig.json (#315)
* Update otherMarketExchangeConfig.json

add strk

* Update otherMarketExchangeConfig.json

remove huobi, add kraken

* Update otherMarketParameters.json

add strk to parameters

* add strk icon and metadata
2024-02-20 16:08:11 -05:00
John Huang 14c155ce31 Rename URL variable 2024-02-15 10:11:51 -08:00
John Huang 8f92972c47 Comments 2024-02-15 10:03:19 -08:00
John Huang 2b53b6b8d7 Update localization 2024-02-15 09:57:05 -08:00
John Huang 0391cefebe Merge branch 'main' into feature/MOB-193-install-app-dlg 2024-02-15 09:42:24 -08:00
John Huang 5d7863348a Clean up 2024-02-15 09:42:04 -08:00
John Huang 027c1ef8ec getOS and get meta from header 2024-02-14 15:34:16 -08:00
24 changed files with 302 additions and 563 deletions
+1 -1
View File
@@ -42,7 +42,7 @@
"@cosmjs/tendermint-rpc": "^0.32.1",
"@dydxprotocol/v4-abacus": "^1.4.6",
"@dydxprotocol/v4-client-js": "^1.0.20",
"@dydxprotocol/v4-localization": "^1.1.31",
"@dydxprotocol/v4-localization": "^1.1.34",
"@ethersproject/providers": "^5.7.2",
"@js-joda/core": "^5.5.3",
"@radix-ui/react-accordion": "^1.1.2",
+8 -8
View File
@@ -1,5 +1,9 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
overrides:
follow-redirects: 1.15.3
@@ -32,8 +36,8 @@ dependencies:
specifier: ^1.0.20
version: 1.0.20
'@dydxprotocol/v4-localization':
specifier: ^1.1.31
version: 1.1.31
specifier: ^1.1.34
version: 1.1.34
'@ethersproject/providers':
specifier: ^5.7.2
version: 5.7.2
@@ -1319,8 +1323,8 @@ packages:
- utf-8-validate
dev: false
/@dydxprotocol/v4-localization@1.1.31:
resolution: {integrity: sha512-plJVIgFAKq9/hA/gk5GgKgCQFsH3pNtDWfG/yHLDXyiGX0M0mMEi1bTNVs4podFVoHJu1nSL9YPFlpJ00FteGw==}
/@dydxprotocol/v4-localization@1.1.34:
resolution: {integrity: sha512-I7zivjv8gS+6b9n7/wh7PY9QEUDIIyLx9ugZ5K6ybar0xT/06yupOVdVE6iLivQ/IAsVi/RFHkD8bQd0DWCetg==}
dev: false
/@dydxprotocol/v4-proto@4.0.0-dev.0:
@@ -16049,7 +16053,3 @@ packages:
/zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
dev: true
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
+31 -61
View File
@@ -98,8 +98,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"wallets": {
"walletconnect": {
@@ -127,8 +126,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-dev-2": {
@@ -184,8 +182,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"wallets": {
"walletconnect": {
@@ -213,8 +210,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-dev-4": {
@@ -271,8 +267,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"wallets": {
"walletconnect": {
@@ -300,8 +295,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-dev-5": {
@@ -357,8 +351,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"wallets": {
"walletconnect": {
@@ -386,8 +379,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-staging": {
@@ -445,8 +437,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"wallets": {
"walletconnect": {
@@ -474,8 +465,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-staging-forced-update": {
@@ -524,8 +514,7 @@
"community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals"
},
"wallets": {
"walletconnect": {
@@ -560,8 +549,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-staging-west": {
@@ -619,8 +607,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"wallets": {
"walletconnect": {
@@ -648,8 +635,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-testnet": {
@@ -711,8 +697,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"wallets": {
"walletconnect": {
@@ -740,8 +725,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-dydx": {
@@ -800,8 +784,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"wallets": {
"walletconnect": {
@@ -829,8 +812,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-nodefleet": {
@@ -889,8 +871,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"wallets": {
"walletconnect": {
@@ -918,8 +899,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-kingnodes": {
@@ -978,8 +958,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"wallets": {
"walletconnect": {
@@ -1007,8 +986,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-liquify": {
@@ -1067,8 +1045,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"wallets": {
"walletconnect": {
@@ -1096,8 +1073,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-polkachu": {
@@ -1147,8 +1123,7 @@
"community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals"
},
"wallets": {
"walletconnect": {
@@ -1176,8 +1151,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-bware": {
@@ -1236,8 +1210,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnmore": "https://help.dydx.exchange",
"walletLearnmore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnmore": "https://www.dydx.academy/video/defi-wallet"
},
"wallets": {
"walletconnect": {
@@ -1265,8 +1238,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-mainnet": {
@@ -1325,8 +1297,7 @@
"keplrDashboard": "[HTTP link to keplr dashboard, can be null]",
"strideZoneApp": "[HTTP link to stride zone app, can be null]",
"accountExportLearnMore": "[HTTP link to account export learn more, can be null]",
"walletLearnMore": "[HTTP link to wallet learn more, can be null]",
"withdrawalGateLearnMore": "[HTTP link to withdrawal gate learn more, can be null]"
"walletLearnMore": "[HTTP link to wallet learn more, can be null]"
},
"wallets": {
"walletconnect": {
@@ -1354,9 +1325,8 @@
}
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": false
"reduceOnlySupported": false
}
}
}
}
}
+7
View File
@@ -428,6 +428,13 @@
"whitepaperLink": "https://solana.com/solana-whitepaper.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/solana/"
},
"STRK-USD": {
"name": "Starknet",
"tags": ["Layer 2"],
"websiteLink": "https://www.starknet.io/en",
"whitepaperLink": "https://docs.starknet.io/documentation/",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/starknet-token/"
},
"STX-USD": {
"name": "Stacks",
"tags": ["Layer 2"],
@@ -513,6 +513,14 @@
{ "exchangeName": "Okx", "ticker": "SOL-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "SOL_USDT", "adjustByMarket": "USDT-USD" }
],
"STRK": [
{ "exchangeName": "Binance", "ticker": "STRKUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "STRKUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "STRKUSD" },
{ "exchangeName": "Kucoin", "ticker": "STRK-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "STRK-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "STRK_USDT", "adjustByMarket": "USDT-USD" }
],
"STX": [
{ "exchangeName": "Binance", "ticker": "STXUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "STXUSDT", "adjustByMarket": "USDT-USD" },
+17
View File
@@ -968,6 +968,23 @@
"minOrderSize": 1000000,
"quantumConversionExponent": -9
},
{
"baseAsset": "STRK",
"referencePrice": 2.05,
"numOracles": 6,
"liquidityTier": 2,
"assetName": "Starknet",
"p": 0.0,
"atomicResolution": -6.0,
"minExchanges": 3,
"minPriceChangePpm": 4000,
"priceExponent": -9.0,
"stepBaseQuantum": 1000000,
"ticksizeExponent": -3,
"subticksPerTick": 1000000,
"minOrderSize": 1000000,
"quantumConversionExponent": -9
},
{
"baseAsset": "STX",
"referencePrice": 1.5144048703611412,
+19 -37
View File
@@ -71,8 +71,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"dydx-testnet-4": {
"tos": "https://dydx.exchange/v4-terms",
@@ -93,8 +92,7 @@
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"withdrawalGateLearnMore": "https://help.dydx.exchange"
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
"[mainnet chain id]": {
"tos": "[HTTP link to TOS]",
@@ -115,8 +113,7 @@
"keplrDashboard": "[HTTP link to keplr dashboard, can be null]",
"strideZoneApp": "[HTTP link to stride zone app, can be null]",
"accountExportLearnMore": "[HTTP link to account export learn more, can be null]",
"walletLearnMore": "[HTTP link to wallet learn more, can be null]",
"withdrawalGateLearnMore": "[HTTP link to withdrawal gate learn more, can be null]"
"walletLearnMore": "[HTTP link to wallet learn more, can be null]"
}
},
"wallets": {
@@ -261,8 +258,7 @@
"faucet": "https://faucet.v4dev.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-dev-2": {
@@ -287,8 +283,7 @@
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-dev-4": {
@@ -314,8 +309,7 @@
"faucet": "https://faucet.v4dev4.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-dev-5": {
@@ -340,8 +334,7 @@
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-staging": {
@@ -367,8 +360,7 @@
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-staging-forced-update": {
@@ -401,8 +393,7 @@
}
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-staging-west": {
@@ -428,8 +419,7 @@
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
},
"featureFlags": {
"reduceOnlySupported": true,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": true
}
},
"dydxprotocol-testnet": {
@@ -459,8 +449,7 @@
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-dydx": {
@@ -486,8 +475,7 @@
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-nodefleet": {
@@ -513,8 +501,7 @@
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-kingnodes": {
@@ -540,8 +527,7 @@
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-liquify": {
@@ -567,8 +553,7 @@
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-polkachu": {
@@ -594,8 +579,7 @@
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-bware": {
@@ -621,8 +605,7 @@
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": true
"reduceOnlySupported": false
}
},
"dydxprotocol-mainnet": {
@@ -648,9 +631,8 @@
"nobleValidator": "[noble validator endpoint for mainnet]"
},
"featureFlags": {
"reduceOnlySupported": false,
"withdrawalSafetyEnabled": false
"reduceOnlySupported": false
}
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+1 -7
View File
@@ -7,12 +7,7 @@ type ElementProps = {
onClick?: () => void;
};
type StyleProps = {
className?: string;
};
export const BackButton = ({
className,
onClick = () => {
// @ts-ignore
const navigation = globalThis.navigation;
@@ -26,9 +21,8 @@ export const BackButton = ({
navigation.navigate('/', { replace: true });
}
},
}: ElementProps & StyleProps) => (
}: ElementProps) => (
<IconButton
className={className}
onClick={onClick}
iconName={IconName.ChevronLeft}
size={ButtonSize.Small}
+18 -78
View File
@@ -47,7 +47,6 @@ type StyleProps = {
hasHeaderBorder?: boolean;
children?: React.ReactNode;
className?: string;
stacked?: boolean;
withAnimation?: boolean;
};
@@ -82,7 +81,6 @@ export const Dialog = ({
slotTrigger,
slotHeaderInner,
slotFooter,
stacked,
withClose = true,
placement = DialogPlacement.Default,
portalContainer,
@@ -111,48 +109,27 @@ export const Dialog = ({
e.preventDefault();
}
}}
$stacked={stacked}
$withAnimation={withAnimation}
>
{stacked ? (
<Styled.StackedHeaderTopRow $withBorder={hasHeaderBorder}>
{onBack && <Styled.BackButton onClick={onBack} />}
<Styled.Header $withBorder={hasHeaderBorder}>
<Styled.HeaderTopRow>
{onBack && <BackButton onClick={onBack} />}
{slotIcon}
{!preventClose && withClose && (
<Styled.Close ref={closeButtonRef} $absolute={stacked}>
<Icon iconName={IconName.Close} />
</Styled.Close>
)}
{slotIcon && <Styled.Icon>{slotIcon}</Styled.Icon>}
{title && <Styled.Title>{title}</Styled.Title>}
{description && <Styled.Description>{description}</Styled.Description>}
{!preventClose && withClose && (
<Styled.Close ref={closeButtonRef}>
<Icon iconName={IconName.Close} />
</Styled.Close>
)}
</Styled.HeaderTopRow>
{slotHeaderInner}
</Styled.StackedHeaderTopRow>
) : (
<Styled.Header $withBorder={hasHeaderBorder}>
<Styled.HeaderTopRow>
{onBack && <BackButton onClick={onBack} />}
{description && <Styled.Description>{description}</Styled.Description>}
{slotIcon && <Styled.Icon>{slotIcon}</Styled.Icon>}
{title && <Styled.Title>{title}</Styled.Title>}
{!preventClose && withClose && (
<Styled.Close ref={closeButtonRef}>
<Icon iconName={IconName.Close} />
</Styled.Close>
)}
</Styled.HeaderTopRow>
{description && <Styled.Description>{description}</Styled.Description>}
{slotHeaderInner}
</Styled.Header>
)}
{slotHeaderInner}
</Styled.Header>
<Styled.Content>{children}</Styled.Content>
@@ -196,11 +173,7 @@ Styled.Overlay = styled(Overlay)`
}
`;
Styled.Container = styled(Content)<{
placement: DialogPlacement;
$stacked?: boolean;
$withAnimation?: boolean;
}>`
Styled.Container = styled(Content)<{ placement: DialogPlacement; $withAnimation?: boolean }>`
/* Params */
--dialog-inset: 1rem;
--dialog-width: 30rem;
@@ -380,13 +353,6 @@ Styled.Container = styled(Content)<{
bottom: 0;
`,
}[placement])}
${({ $stacked }) =>
$stacked &&
css`
justify-content: center;
text-align: center;
`}
`;
Styled.Header = styled.header<{ $withBorder: boolean }>`
@@ -413,21 +379,9 @@ Styled.HeaderTopRow = styled.div`
gap: var(--dialog-title-gap);
`;
Styled.StackedHeaderTopRow = styled.div<{ $withBorder: boolean }>`
${layoutMixins.flexColumn}
align-items: center;
justify-content: center;
padding: var(--dialog-header-paddingTop) var(--dialog-header-paddingLeft)
var(--dialog-header-paddingBottom) var(--dialog-header-paddingRight);
border-top-left-radius: inherit;
border-top-right-radius: inherit;
${({ $withBorder }) =>
$withBorder &&
css`
${layoutMixins.withOuterBorder};
background: var(--dialog-backgroundColor);
`};
Styled.HeaderTopRow = styled.div`
${layoutMixins.row}
gap: var(--dialog-title-gap);
`;
Styled.Content = styled.div`
@@ -458,7 +412,7 @@ Styled.Icon = styled.div`
line-height: 1;
`;
Styled.Close = styled(Close)<{ $absolute?: boolean }>`
Styled.Close = styled(Close)`
width: 0.7813rem;
height: 0.7813rem;
@@ -484,14 +438,6 @@ Styled.Close = styled(Close)<{ $absolute?: boolean }>`
color: var(--color-text-2);
}
${({ $absolute }) =>
$absolute &&
css`
position: absolute;
right: var(--dialog-header-paddingRight);
top: var(--dialog-header-paddingTop);
`}
@media ${breakpoints.tablet} {
width: 1rem;
height: 1rem;
@@ -499,12 +445,6 @@ Styled.Close = styled(Close)<{ $absolute?: boolean }>`
}
`;
Styled.BackButton = styled(BackButton)`
position: absolute;
left: var(--dialog-header-paddingLeft);
top: var(--dialog-header-paddingTop);
`;
Styled.Title = styled(Title)`
flex: 1;
+4 -4
View File
@@ -9,11 +9,9 @@ export enum DialogTypes {
FillDetails = 'FillDetails',
Help = 'Help',
ExternalNavKeplr = 'ExternalNavKeplr',
ManageFunds = 'ManageFunds',
MnemonicExport = 'MnemonicExport',
MobileSignIn = 'MobileSignIn',
NewMarketAgreement = 'NewMarketAgreement',
NewMarketMessageDetails = 'NewMarketMessageDetails',
MobileDownload = 'MobileDownload',
Onboarding = 'Onboarding',
OrderDetails = 'OrderDetails',
Preferences = 'Preferences',
@@ -23,7 +21,9 @@ export enum DialogTypes {
Trade = 'Trade',
Transfer = 'Transfer',
Withdraw = 'Withdraw',
WithdrawalGated = 'WithdrawalGated',
ManageFunds = 'ManageFunds',
NewMarketMessageDetails = 'NewMarketMessageDetails',
NewMarketAgreement = 'NewMarketAgreement',
}
export enum TradeBoxDialogTypes {
-4
View File
@@ -7,7 +7,6 @@ import { useDebounce } from './useDebounce';
import { useInterval } from './useInterval';
import { useDocumentTitle } from './useDocumentTitle';
import { useDydxClient } from './useDydxClient';
import { useEnvFeatures } from './useEnvFeatures';
import { useGovernanceVariables } from './useGovernanceVariables';
import { useAccountBalance } from './useAccountBalance';
import { useAccounts } from './useAccounts';
@@ -27,7 +26,6 @@ import { useStringGetter } from './useStringGetter';
import { useSubaccount } from './useSubaccount';
import { useTradeFormInputs } from './useTradeFormInputs';
import { useURLConfigs } from './useURLConfigs';
import { useWithdrawalInfo } from './useWithdrawalInfo';
export {
useApiState,
@@ -38,7 +36,6 @@ export {
useDebounce,
useDocumentTitle,
useDydxClient,
useEnvFeatures,
useGovernanceVariables,
useAccountBalance,
useAccounts,
@@ -59,5 +56,4 @@ export {
useSubaccount,
useTradeFormInputs,
useURLConfigs,
useWithdrawalInfo,
};
-13
View File
@@ -251,17 +251,6 @@ const useDydxClientContext = () => {
[compositeClient]
);
const getWithdrawalAndTransferGatingStatus = useCallback(async () => {
return await compositeClient?.validatorClient.get.GetWithdrawalAndTransferGatingStatus();
}, [compositeClient]);
const getWithdrawalCapacityByDenom = useCallback(
async ({ denom }: { denom: string }) => {
return await compositeClient?.validatorClient.get.getWithdrawalCapacityByDenom(denom);
},
[compositeClient]
);
return {
// Client initialization
connect: setNetworkConfig,
@@ -278,7 +267,5 @@ const useDydxClientContext = () => {
requestAllGovernanceProposals,
getCandlesForDatafeed,
screenAddresses,
getWithdrawalAndTransferGatingStatus,
getWithdrawalCapacityByDenom,
};
};
-15
View File
@@ -1,15 +0,0 @@
import { useSelector } from 'react-redux';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { getSelectedNetwork } from '@/state/appSelectors';
export interface EnvironmentFeatures {
reduceOnlySupported: boolean;
withdrawalSafetyEnabled: boolean;
}
export const useEnvFeatures = (): EnvironmentFeatures => {
const selectedNetwork = useSelector(getSelectedNetwork);
return ENVIRONMENT_CONFIG_MAP[selectedNetwork].featureFlags;
};
-2
View File
@@ -27,7 +27,6 @@ export interface LinksConfigs {
strideZoneApp?: string;
accountExportLearnMore?: string;
walletLearnMore?: string;
withdrawalGateLearnMore?: string;
}
export const useURLConfigs = (): LinksConfigs => {
@@ -55,6 +54,5 @@ export const useURLConfigs = (): LinksConfigs => {
strideZoneApp: linksConfigs.strideZoneApp || FALLBACK_URL,
accountExportLearnMore: linksConfigs.accountExportLearnMore || FALLBACK_URL,
walletLearnMore: linksConfigs.walletLearnMore || FALLBACK_URL,
withdrawalGateLearnMore: linksConfigs.withdrawalGateLearnMore || FALLBACK_URL,
};
};
-131
View File
@@ -1,131 +0,0 @@
import { useEffect, useMemo } from 'react';
import { useQuery } from 'react-query';
import BigNumber from 'bignumber.js';
import { encodeJson } from '@dydxprotocol/v4-client-js';
import { ByteArrayEncoding } from '@dydxprotocol/v4-client-js/build/src/lib/helpers';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { DialogTypes } from '@/constants/dialogs';
import { isMainnet } from '@/constants/networks';
import { useEnvFeatures } from './useEnvFeatures';
import { getApiState } from '@/state/appSelectors';
import { closeDialog, openDialog } from '@/state/dialogs';
import { getSelectedLocale } from '@/state/localizationSelectors';
import { formatRelativeTime } from '@/lib/dateTime';
import { BIG_NUMBERS, MustBigNumber } from '@/lib/numbers';
import { log } from '@/lib/telemetry';
import { useDydxClient } from './useDydxClient';
import { useTokenConfigs } from './useTokenConfigs';
const BLOCK_TIME = isMainnet ? 1_000 : 1_500;
export const useWithdrawalInfo = ({
transferType,
}: {
transferType: 'withdrawal' | 'transfer';
}) => {
const { getWithdrawalAndTransferGatingStatus, getWithdrawalCapacityByDenom } = useDydxClient();
const { usdcDenom, usdcDecimals } = useTokenConfigs();
const apiState = useSelector(getApiState, shallowEqual);
const { height } = apiState || {};
const selectedLocale = useSelector(getSelectedLocale);
const dispatch = useDispatch();
const { withdrawalSafetyEnabled } = useEnvFeatures();
const { data: usdcWithdrawalCapacity } = useQuery({
enabled: withdrawalSafetyEnabled,
queryKey: 'usdcWithdrawalCapacity',
queryFn: async () => {
try {
const response = await getWithdrawalCapacityByDenom({ denom: usdcDenom });
return JSON.parse(encodeJson(response, ByteArrayEncoding.BIGINT));
} catch (error) {
log('useWithdrawalInfo/getWithdrawalCapacityByDenom', error);
}
},
refetchInterval: 60_000,
staleTime: 60_000,
});
const { data: withdrawalAndTransferGatingStatus } = useQuery({
enabled: withdrawalSafetyEnabled,
queryKey: 'withdrawalTransferGateStatus',
queryFn: async () => {
try {
return await getWithdrawalAndTransferGatingStatus();
} catch (error) {
log('useWithdrawalInfo/getWithdrawalAndTransferGatingStatus', error);
}
},
refetchInterval: 60_000,
staleTime: 60_000,
});
const capacity = useMemo(() => {
const capacityList = usdcWithdrawalCapacity?.limiterCapacityList;
if (!capacityList || capacityList.length < 2) {
if (!withdrawalSafetyEnabled) {
return BigNumber(Infinity);
}
return BIG_NUMBERS.ZERO;
}
const [{ capacity: daily }, { capacity: weekly }] = capacityList;
const dailyBN = MustBigNumber(daily);
const weeklyBN = MustBigNumber(weekly);
return BigNumber.minimum(dailyBN, weeklyBN).div(10 ** usdcDecimals);
}, [usdcDecimals, usdcWithdrawalCapacity]);
const withdrawalAndTransferGatingStatusValue = useMemo(() => {
const { withdrawalsAndTransfersUnblockedAtBlock } = withdrawalAndTransferGatingStatus ?? {};
if (
height &&
withdrawalsAndTransfersUnblockedAtBlock &&
height < withdrawalsAndTransfersUnblockedAtBlock &&
withdrawalSafetyEnabled
) {
return {
estimatedUnblockTime: formatRelativeTime(
Date.now() + (withdrawalsAndTransfersUnblockedAtBlock - height) * BLOCK_TIME,
{
locale: selectedLocale,
largestUnit: 'day',
}
),
isGated: true,
};
}
return {
estimatedUnblockTime: null,
isGated: false,
};
}, [height, withdrawalAndTransferGatingStatus, withdrawalSafetyEnabled]);
useEffect(() => {
if (
withdrawalAndTransferGatingStatusValue.isGated &&
withdrawalAndTransferGatingStatusValue.estimatedUnblockTime &&
withdrawalSafetyEnabled
) {
dispatch(closeDialog());
dispatch(
openDialog({
type: DialogTypes.WithdrawalGated,
dialogProps: {
transferType,
estimatedUnblockTime: withdrawalAndTransferGatingStatusValue.estimatedUnblockTime,
},
})
);
}
}, [transferType, withdrawalAndTransferGatingStatusValue.isGated, withdrawalSafetyEnabled]);
return {
usdcWithdrawalCapacity: capacity,
withdrawalAndTransferGatingStatus,
};
};
+7 -7
View File
@@ -11,27 +11,27 @@ import { DepositDialog } from '@/views/dialogs/DepositDialog';
import { DisconnectDialog } from '@/views/dialogs/DisconnectDialog';
import { DisplaySettingsDialog } from '@/views/dialogs/DisplaySettingsDialog';
import { ExchangeOfflineDialog } from '@/views/dialogs/ExchangeOfflineDialog';
import { ExternalNavStrideDialog } from '@/views/dialogs/ExternalNavStrideDialog';
import { HelpDialog } from '@/views/dialogs/HelpDialog';
import { ExternalLinkDialog } from '@/views/dialogs/ExternalLinkDialog';
import { ExternalNavKeplrDialog } from '@/views/dialogs/ExternalNavKeplrDialog';
import { ManageFundsDialog } from '@/views/dialogs/ManageFundsDialog';
import { MnemonicExportDialog } from '@/views/dialogs/MnemonicExportDialog';
import { MobileSignInDialog } from '@/views/dialogs/MobileSignInDialog';
import { NewMarketAgreementDialog } from '@/views/dialogs/NewMarketAgreementDialog';
import { NewMarketMessageDetailsDialog } from '@/views/dialogs/NewMarketMessageDetailsDialog';
import { OnboardingDialog } from '@/views/dialogs/OnboardingDialog';
import { PreferencesDialog } from '@/views/dialogs/PreferencesDialog';
import { RateLimitDialog } from '@/views/dialogs/RateLimitDialog';
import { RestrictedGeoDialog } from '@/views/dialogs/RestrictedGeoDialog';
import { RestrictedWalletDialog } from '@/views/dialogs/RestrictedWalletDialog';
import { TradeDialog } from '@/views/dialogs/TradeDialog';
import { TransferDialog } from '@/views/dialogs/TransferDialog';
import { RestrictedWalletDialog } from '@/views/dialogs/RestrictedWalletDialog';
import { WithdrawDialog } from '@/views/dialogs/WithdrawDialog';
import { WithdrawalGateDialog } from '@/views/dialogs/WithdrawalGateDialog';
import { ManageFundsDialog } from '@/views/dialogs/ManageFundsDialog';
import { OrderDetailsDialog } from '@/views/dialogs/DetailsDialog/OrderDetailsDialog';
import { FillDetailsDialog } from '@/views/dialogs/DetailsDialog/FillDetailsDialog';
import { NewMarketMessageDetailsDialog } from '@/views/dialogs/NewMarketMessageDetailsDialog';
import { NewMarketAgreementDialog } from '@/views/dialogs/NewMarketAgreementDialog';
import { ExternalNavStrideDialog } from '@/views/dialogs/ExternalNavStrideDialog';
import { MobileDownloadDialog } from '@/views/dialogs/MobileDownloadDialog';
export const DialogManager = () => {
const dispatch = useDispatch();
@@ -64,6 +64,7 @@ export const DialogManager = () => {
[DialogTypes.ExternalNavStride]: <ExternalNavStrideDialog {...modalProps} />,
[DialogTypes.MnemonicExport]: <MnemonicExportDialog {...modalProps} />,
[DialogTypes.MobileSignIn]: <MobileSignInDialog {...modalProps} />,
[DialogTypes.MobileDownload]: <MobileDownloadDialog {...modalProps} />,
[DialogTypes.Onboarding]: <OnboardingDialog {...modalProps} />,
[DialogTypes.OrderDetails]: <OrderDetailsDialog {...modalProps} />,
[DialogTypes.Preferences]: <PreferencesDialog {...modalProps} />,
@@ -73,7 +74,6 @@ export const DialogManager = () => {
[DialogTypes.Trade]: <TradeDialog {...modalProps} />,
[DialogTypes.Transfer]: <TransferDialog {...modalProps} />,
[DialogTypes.Withdraw]: <WithdrawDialog {...modalProps} />,
[DialogTypes.WithdrawalGated]: <WithdrawalGateDialog {...modalProps} />,
[DialogTypes.ManageFunds]: <ManageFundsDialog {...modalProps} />,
[DialogTypes.NewMarketMessageDetails]: <NewMarketMessageDetailsDialog {...modalProps} />,
[DialogTypes.NewMarketAgreement]: <NewMarketAgreementDialog {...modalProps} />,
-5
View File
@@ -1,5 +0,0 @@
import { ThemeColorBase } from '@/constants/styles/colors';
declare module 'styled-components' {
export interface DefaultTheme extends ThemeColorBase {}
}
+140
View File
@@ -0,0 +1,140 @@
import styled, { AnyStyledComponent, css } from 'styled-components';
import { layoutMixins } from '@/styles/layoutMixins';
import { Dialog } from '@/components/Dialog';
import { QrCode } from '@/components/QrCode';
import { useStringGetter } from '@/hooks';
import { STRING_KEYS } from '@/constants/localization';
type ElementProps = {
setIsOpen: (open: boolean) => void;
};
/*
When/if deployer deploys the web app with smartbanner, "smartbanner:button-url-apple" and/or
"smartbanner:button-url-google" <meta> are set.
This implementation assumes "smartbanner:button-url-apple" and "smartbanner:button-url-google"
are set to the same value with onelink or other redirect URL.
Since there is no way for the desktop web app to know what mobile device the user is using,
we should give a onelink URL which redirects to either iOS or Android app store depending on
the mobile device used to scan the link.
*/
// for testing only
// export const mobileAppUrl = "http://example.com";
let mobileAppUrl: string | undefined | null = undefined;
export const getMobileAppUrl = () => {
if (!mobileAppUrl) {
mobileAppUrl =
// for testing to verify <meta> is retrieved by name, QR code should show "@dYdX" as value
// document.querySelector('meta[name="twitter:creator"]')?.getAttribute('content') ??
document.querySelector('meta[name="smartbanner:button-url-apple"]')?.getAttribute('content') ??
document.querySelector('meta[name="smartbanner:button-url-google"]')?.getAttribute('content');
}
return mobileAppUrl;
}
const MobileQrCode = ({
url,
}: {
url: string;
}) => {
return (
<Styled.QrCodeContainer isShowing={true}>
<QrCode hasLogo size={432} value={url} />
</Styled.QrCodeContainer>
);
};
/*
MobileDownloadDialog should only been shown on desktop when mobileAppUrl has value. That's controlled by AccountMenu.tsx.
*/
export const MobileDownloadDialog = ({ setIsOpen }: ElementProps) => {
const stringGetter = useStringGetter();
const content = (
<MobileQrCode url={mobileAppUrl!} />
);
return (
<Dialog isOpen setIsOpen={setIsOpen} title={
stringGetter({ key: STRING_KEYS.DOWNLOAD_MOBILE_APP })
}>
<Styled.Content>{content}</Styled.Content>
</Dialog>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Content = styled.div`
${layoutMixins.column}
gap: 1rem;
strong {
font-weight: 900;
color: var(--color-text-2);
}
footer {
${layoutMixins.row}
justify-content: space-between;
svg {
width: auto;
}
}
`;
Styled.WaitingSpan = styled.span`
strong {
color: var(--color-warning);
}
`;
Styled.QrCodeContainer = styled.figure<{ isShowing: boolean }>`
${layoutMixins.stack}
overflow: hidden;
border-radius: 0.75em;
cursor: pointer;
transition: 0.2s;
&:hover {
filter: brightness(var(--hover-filter-base));
}
> * {
position: relative;
transition: 0.16s;
}
> :first-child {
pointer-events: none;
${({ isShowing }) =>
!isShowing &&
css`
filter: blur(1rem) brightness(1.4);
will-change: filter;
`}
}
> span {
place-self: center;
font-size: 1.4em;
color: var(--color-text-2);
${({ isShowing }) =>
isShowing &&
css`
opacity: 0;
`}
}
`;
-101
View File
@@ -1,101 +0,0 @@
import styled, { AnyStyledComponent } from 'styled-components';
import { ButtonAction, ButtonType } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization';
import { useStringGetter, useURLConfigs } from '@/hooks';
import { LinkOutIcon } from '@/icons';
import { layoutMixins } from '@/styles/layoutMixins';
import { Button } from '@/components/Button';
import { Dialog } from '@/components/Dialog';
import { Icon, IconName } from '@/components/Icon';
type ElementProps = {
setIsOpen: (open: boolean) => void;
transferType: 'withdrawal' | 'transfer';
estimatedUnblockTime?: string | null;
};
export const WithdrawalGateDialog = ({
setIsOpen,
estimatedUnblockTime,
transferType,
}: ElementProps) => {
const stringGetter = useStringGetter();
const { withdrawalGateLearnMore } = useURLConfigs();
return (
<Dialog
isOpen
stacked
setIsOpen={setIsOpen}
title={
{
withdrawal: stringGetter({ key: STRING_KEYS.WITHDRAWALS_PAUSED }),
transfer: stringGetter({ key: STRING_KEYS.TRANSFERS_PAUSED }),
}[transferType]
}
slotIcon={
<Styled.IconContainer>
<Styled.Icon iconName={IconName.Warning} />
</Styled.IconContainer>
}
slotFooter={
<Styled.ButtonRow>
<Button
type={ButtonType.Link}
action={ButtonAction.Secondary}
href={withdrawalGateLearnMore}
>
{stringGetter({ key: STRING_KEYS.LEARN_MORE })}
<LinkOutIcon />
</Button>
<Button action={ButtonAction.Primary} onClick={() => setIsOpen(false)}>
{stringGetter({ key: STRING_KEYS.CLOSE })}
</Button>
</Styled.ButtonRow>
}
>
<Styled.Content>
{stringGetter({
key: STRING_KEYS.WITHDRAWALS_PAUSED_DESC,
params: {
ESTIMATED_DURATION: estimatedUnblockTime,
},
})}
</Styled.Content>
</Dialog>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.IconContainer = styled.div`
display: flex;
justify-content: center;
align-items: center;
width: 4.5rem;
height: 4.5rem;
border-radius: 50%;
min-width: 4.5rem;
min-height: 4.5rem;
background-color: var(--color-gradient-warning);
`;
Styled.Icon = styled(Icon)`
color: var(--color-warning);
font-size: 2.5rem;
margin-bottom: 0.125rem;
`;
Styled.Content = styled.div`
${layoutMixins.column}
gap: 1rem;
`;
Styled.ButtonRow = styled.div`
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
`;
@@ -17,7 +17,6 @@ import {
MAX_PRICE_IMPACT,
MIN_CCTP_TRANSFER_AMOUNT,
NumberSign,
TOKEN_DECIMALS,
} from '@/constants/numbers';
import {
@@ -28,8 +27,6 @@ import {
useSelectedNetwork,
useStringGetter,
useSubaccount,
useTokenConfigs,
useWithdrawalInfo,
} from '@/hooks';
import { useLocalNotifications } from '@/hooks/useLocalNotifications';
@@ -88,8 +85,6 @@ export const WithdrawForm = () => {
const [withdrawAmount, setWithdrawAmount] = useState('');
const [slippage, setSlippage] = useState(isCctp ? 0 : 0.01); // 0.1% slippage
const debouncedAmount = useDebounce<string>(withdrawAmount, 500);
const { usdcLabel } = useTokenConfigs();
const { usdcWithdrawalCapacity } = useWithdrawalInfo({ transferType: 'withdrawal' });
const isValidAddress = toAddress && isAddress(toAddress);
@@ -326,102 +321,61 @@ export const WithdrawForm = () => {
const { sanctionedAddresses } = useRestrictions();
const { alertType, errorMessage } = useMemo(() => {
const errorMessage = useMemo(() => {
if (error) {
return {
errorMessage: error,
};
return error;
}
if (routeErrors) {
return {
errorMessage: routeErrorMessage
? stringGetter({
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
params: { ERROR_MESSAGE: routeErrorMessage },
})
: stringGetter({ key: STRING_KEYS.SOMETHING_WENT_WRONG }),
};
return routeErrorMessage
? stringGetter({
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
params: { ERROR_MESSAGE: routeErrorMessage },
})
: stringGetter({ key: STRING_KEYS.SOMETHING_WENT_WRONG });
}
if (!toAddress) {
return {
alertType: AlertType.Warning,
errorMessage: stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_ADDRESS }),
};
}
if (!toAddress) return stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_ADDRESS });
if (sanctionedAddresses.has(toAddress))
return {
errorMessage: stringGetter({
key: STRING_KEYS.TRANSFER_INVALID_DYDX_ADDRESS,
}),
};
return stringGetter({
key: STRING_KEYS.TRANSFER_INVALID_DYDX_ADDRESS,
});
if (debouncedAmountBN) {
if (!chainIdStr && !exchange) {
return {
errorMessage: stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_CHAIN }),
};
return stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_CHAIN });
} else if (!toToken) {
return {
errorMessage: stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_ASSET }),
};
return stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_ASSET });
}
}
if (debouncedAmountBN.gt(MustBigNumber(freeCollateralBN))) {
return {
errorMessage: stringGetter({ key: STRING_KEYS.WITHDRAW_MORE_THAN_FREE }),
};
if (MustBigNumber(debouncedAmountBN).gt(MustBigNumber(freeCollateralBN))) {
return stringGetter({ key: STRING_KEYS.WITHDRAW_MORE_THAN_FREE });
}
if (isCctp) {
if (debouncedAmountBN.gte(MAX_CCTP_TRANSFER_AMOUNT)) {
return {
errorMessage: stringGetter({
key: STRING_KEYS.MAX_CCTP_TRANSFER_LIMIT_EXCEEDED,
params: {
MAX_CCTP_TRANSFER_AMOUNT: MAX_CCTP_TRANSFER_AMOUNT,
},
}),
};
if (MustBigNumber(debouncedAmountBN).gte(MAX_CCTP_TRANSFER_AMOUNT)) {
return stringGetter({
key: STRING_KEYS.MAX_CCTP_TRANSFER_LIMIT_EXCEEDED,
params: {
MAX_CCTP_TRANSFER_AMOUNT: MAX_CCTP_TRANSFER_AMOUNT,
},
});
}
if (
!debouncedAmountBN.isZero() &&
MustBigNumber(debouncedAmountBN).lte(MIN_CCTP_TRANSFER_AMOUNT)
) {
return {
errorMessage: 'Amount must be greater than 10 USDC',
};
return 'Amount must be greater than 10 USDC';
}
}
if (isMainnet && MustBigNumber(summary?.aggregatePriceImpact).gte(MAX_PRICE_IMPACT)) {
return { errorMessage: stringGetter({ key: STRING_KEYS.PRICE_IMPACT_TOO_HIGH }) };
return stringGetter({ key: STRING_KEYS.PRICE_IMPACT_TOO_HIGH });
}
// Withdrawal Safety
if (usdcWithdrawalCapacity.gt(0) && debouncedAmountBN.gt(usdcWithdrawalCapacity)) {
return {
alertType: AlertType.Warning,
errorMessage: stringGetter({
key: STRING_KEYS.WITHDRAWAL_LIMIT_OVER,
params: {
USDC_LIMIT: (
<span>
{usdcWithdrawalCapacity.toFormat(TOKEN_DECIMALS)}
<Styled.Tag>{usdcLabel}</Styled.Tag>
</span>
),
},
}),
};
}
return {
errorMessage: undefined,
};
return undefined;
}, [
error,
routeErrors,
@@ -434,7 +388,6 @@ export const WithdrawForm = () => {
sanctionedAddresses,
stringGetter,
summary,
usdcWithdrawalCapacity,
]);
const isInvalidNobleAddress = Boolean(
@@ -495,11 +448,7 @@ export const WithdrawForm = () => {
}
/>
</Styled.WithDetailsReceipt>
{errorMessage && (
<Styled.AlertMessage type={alertType ?? AlertType.Error}>
{errorMessage}
</Styled.AlertMessage>
)}
{errorMessage && <AlertMessage type={AlertType.Error}>{errorMessage}</AlertMessage>}
<Styled.Footer>
<WithdrawButtonAndReceipt
isDisabled={isDisabled}
@@ -516,10 +465,6 @@ export const WithdrawForm = () => {
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Tag = styled(Tag)`
margin-left: 0.5ch;
`;
Styled.DiffOutput = styled(DiffOutput)`
--diffOutput-valueWithDiff-fontSize: 1em;
`;
@@ -539,10 +484,6 @@ Styled.DestinationRow = styled.div`
gap: 1rem;
`;
Styled.AlertMessage = styled(AlertMessage)`
display: inline;
`;
Styled.WithDetailsReceipt = styled(WithDetailsReceipt)`
--withReceipt-backgroundColor: var(--color-layer-2);
`;
-2
View File
@@ -20,7 +20,6 @@ import {
useStringGetter,
useSubaccount,
useTokenConfigs,
useWithdrawalInfo,
} from '@/hooks';
import { formMixins } from '@/styles/formMixins';
@@ -65,7 +64,6 @@ export const TransferForm = ({
const { nativeTokenBalance, usdcBalance } = useAccountBalance();
const selectedDydxChainId = useSelector(getSelectedDydxChainId);
const { tokensConfigs, usdcLabel, chainTokenLabel } = useTokenConfigs();
useWithdrawalInfo({ transferType: 'transfer' });
const {
address: recipientAddress,
+13
View File
@@ -40,6 +40,7 @@ import { getAppTheme } from '@/state/configsSelectors';
import { isTruthy } from '@/lib/isTruthy';
import { truncateAddress } from '@/lib/wallet';
import { MustBigNumber } from '@/lib/numbers';
import { getMobileAppUrl } from '../dialogs/MobileDownloadDialog';
export const AccountMenu = () => {
const stringGetter = useStringGetter();
@@ -189,6 +190,18 @@ export const AccountMenu = () => {
label: stringGetter({ key: STRING_KEYS.DISPLAY_SETTINGS }),
onSelect: () => dispatch(openDialog({ type: DialogTypes.DisplaySettings })),
},
...(getMobileAppUrl()
? [
{
value: 'MobileDownload',
icon: <Icon iconName={IconName.Qr} />,
label: stringGetter({ key: STRING_KEYS.DOWNLOAD_MOBILE_APP }),
onSelect: () => {
dispatch(openDialog({ type: DialogTypes.MobileDownload }));
},
},
]
: []),
...(onboardingState === OnboardingState.AccountConnected && hdKey
? [
{
+1 -1
View File
@@ -22,6 +22,6 @@
"@/*": ["src/*"]
}
},
"include": ["src", "scripts", "styled.d.ts"],
"include": ["src", "scripts"],
"references": [{ "path": "./tsconfig.node.json" }]
}