Compare commits

..
Author SHA1 Message Date
Bill He 59a276e36b Set minimum for CCTP withdraws 2024-02-14 14:51:00 -08:00
74 changed files with 647 additions and 1039 deletions
-1
View File
@@ -1,2 +1 @@
node_modules/
public/
+2 -2
View File
@@ -40,9 +40,9 @@
"@cosmjs/proto-signing": "^0.32.1",
"@cosmjs/stargate": "^0.32.1",
"@cosmjs/tendermint-rpc": "^0.32.1",
"@dydxprotocol/v4-abacus": "^1.4.6",
"@dydxprotocol/v4-abacus": "^1.4.2",
"@dydxprotocol/v4-client-js": "^1.0.20",
"@dydxprotocol/v4-localization": "^1.1.31",
"@dydxprotocol/v4-localization": "^1.1.30",
"@ethersproject/providers": "^5.7.2",
"@js-joda/core": "^5.5.3",
"@radix-ui/react-accordion": "^1.1.2",
+12 -12
View File
@@ -1,5 +1,9 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
overrides:
follow-redirects: 1.15.3
@@ -26,14 +30,14 @@ dependencies:
specifier: ^0.32.1
version: 0.32.2
'@dydxprotocol/v4-abacus':
specifier: ^1.4.6
version: 1.4.6
specifier: ^1.4.2
version: 1.4.2
'@dydxprotocol/v4-client-js':
specifier: ^1.0.20
version: 1.0.20
'@dydxprotocol/v4-localization':
specifier: ^1.1.31
version: 1.1.31
specifier: ^1.1.30
version: 1.1.30
'@ethersproject/providers':
specifier: ^5.7.2
version: 5.7.2
@@ -1286,8 +1290,8 @@ packages:
resolution: {integrity: sha512-Gg5t+eR7vPJMAmhkFt6CZrzPd0EKpAslWwk5rFVYZpJsM8JG5KT9XQ99hgNM3Ov6ScNoIWbXkpX27F6A9cXR4Q==}
dev: false
/@dydxprotocol/v4-abacus@1.4.6:
resolution: {integrity: sha512-qYq+4TizcMMxYVXckn0LCucWBe5N9ZNtD1XnowCAuBUUifHSgMGvao5OeZIKMgNM/udSKOXLss4zLy6dH/G2SA==}
/@dydxprotocol/v4-abacus@1.4.2:
resolution: {integrity: sha512-+hugk0RulMwMthR2xCMYXohcC3sEYqVW/lmiq0RUuHZ9yrjmgy48xl0aZUmXGUYXyoiHXPS4AULhRKHQ4OOLwg==}
dev: false
/@dydxprotocol/v4-client-js@1.0.20:
@@ -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.30:
resolution: {integrity: sha512-TZfWWRSOxcjLHs972wlJVVHkE7+DVqAUnGZSs24HYHsPtUkPhZiNXMOA2Vk9YddQxumhM79xIRH0cmJSe5DDUg==}
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
+11 -21
View File
@@ -1,22 +1,12 @@
[
{
"chainId": "1",
"tokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"name": "Ethereum"
},
{
"chainId": "5",
"tokenAddress": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F",
"name": "Ethereum Goerli"
},
{
"chainId": "43114",
"tokenAddress": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
"name": "Avalanche"
},
{
"chainId": "10",
"tokenAddress": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
"name": "optimism"
}
]
{
"chainId": "1",
"tokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"name": "Ethereum"
},
{
"chainId": "5",
"tokenAddress": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F",
"name": "Ethereum Goerli"
}
]
+1 -1
View File
@@ -1329,4 +1329,4 @@
}
}
}
}
}
+1 -162
View File
@@ -20,13 +20,6 @@
"whitepaperLink": "https://why.cardano.org/en/introduction/motivation/",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/cardano/"
},
"AGIX-USD": {
"name": "SingularityNET",
"tags": ["AI"],
"websiteLink": "https://public.singularitynet.io/whitepaper.pdf",
"whitepaperLink": "https://public.singularitynet.io/whitepaper.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/singularitynet/"
},
"ALGO-USD": {
"name": "Algorand",
"tags": ["Layer 1"],
@@ -85,7 +78,7 @@
},
"BLUR-USD": {
"name": "Blur",
"tags": ["NFT"],
"tags": [],
"websiteLink": "https://blur.io/",
"whitepaperLink": "https://docs.blur.foundation/",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/blur-token/"
@@ -98,13 +91,6 @@
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/bnb/"
},
"CHZ-USD": {
"name": "Chiliz",
"tags": ["Layer 1"],
"websiteLink": "https://www.chiliz.com/",
"whitepaperLink": "https://www.chiliz.com/docs/litepaper-v1.1-20230703.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/chiliz/"
},
"CELO-USD": {
"name": "Celo",
"tags": [],
@@ -161,13 +147,6 @@
"whitepaperLink": "https://cdn.enjin.io/downloads/whitepapers/enjin-coin/en.pdf/",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/enjin-coin/"
},
"ENS-USD": {
"name": "Ethereum Name Service",
"tags": [],
"websiteLink": "https://coinmarketcap.com/currencies/ethereum-name-service/",
"whitepaperLink": "https://docs.ens.domains/",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/ethereum-name-service/"
},
"EOS-USD": {
"name": "EOS",
"tags": ["Layer 1"],
@@ -191,13 +170,6 @@
"displayStepSize": "0.001",
"displayTickSize": "0.1"
},
"FET-USD": {
"name": "Fetch.ai",
"tags": ["AI"],
"websiteLink": "https://fetch.ai/",
"whitepaperLink": "https://www.dropbox.com/s/gxptsecwdl3jjtn/David%20Minarsch%20-%202021-04-26%2010.34.17%20-%20paper_21_finalversion.pdf?e=1&dl=0",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/fetch/"
},
"FIL-USD": {
"name": "Filecoin",
"tags": ["Layer 1"],
@@ -205,34 +177,6 @@
"whitepaperLink": "https://filecoin.io/filecoin.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/filecoin/"
},
"FTM-USD": {
"name": "Fantom",
"tags": [],
"websiteLink": "https://fantom.foundation/",
"whitepaperLink": "https://fantom.foundation/_next/static/media/wp_fantom_v1.6.39329cdc5d0ee59684cbc6f228516383.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/fantom/"
},
"GALA-USD": {
"name": "Gala",
"tags": ["Gaming", "Layer 1"],
"websiteLink": "https://gala.com/",
"whitepaperLink": "https://galahackathon.com/v1.0.0/pdf/sdk-documentation.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/gala/"
},
"GMT-USD": {
"name": "GMT",
"tags": ["Gaming"],
"websiteLink": "https://stepn.com/",
"whitepaperLink/": "https://whitepaper.stepn.com/",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/green-metaverse-token/"
},
"GRT-USD": {
"name": "The Graph",
"tags": [],
"websiteLink": "https://thegraph.com/",
"whitepaperLink/": "https://github.com/graphprotocol/research/blob/master/papers/whitepaper/the-graph-whitepaper.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/the-graph/"
},
"HNT-USD": {
"name": "Helium",
"tags": ["Layer 1"],
@@ -240,13 +184,6 @@
"whitepaperLink": "http://whitepaper.helium.com",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/helium/"
},
"HBAR-USD": {
"name": "Hedera",
"tags": [],
"websiteLink": "https://hedera.com/",
"whitepaperLink/": "https://files.hedera.com/hh_whitepaper_v2.2-20230918.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/hedera/"
},
"ICP-USD": {
"name": "Internet Computer",
"tags": ["Layer 1"],
@@ -254,27 +191,6 @@
"whitepaperLink": "https://dfinity.org/whitepaper.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/internet-computer/"
},
"IMX-USD": {
"name": "Immutable X",
"tags": ["Gaming", "Layer 2", "NFT"],
"websiteLink": "https://www.immutable.com/",
"whitepaperLink": "https://assets.website-files.com/646557ee455c3e16e4a9bcb3/6499367de527dd82ab7475a3_Immutable%20Whitepaper%20Update%202023%20(3).pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/immutable-x/"
},
"INJ-USD": {
"name": "Injective",
"tags": ["Layer 1", "Defi"],
"websiteLink": "https://injective.com/",
"whitepaperLink": "https://docs.injective.network/intro/01_overview.html",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/injective/"
},
"JTO-USD": {
"name": "Jito",
"tags": ["Defi"],
"websiteLink": "https://www.jito.network/",
"whitepaperLink": "https://github.com/jito-foundation",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/jito/"
},
"JUP-USD": {
"name": "Jupiter",
"tags": ["Defi"],
@@ -282,13 +198,6 @@
"whitepaperLink": "https://station.jup.ag/blog/green-paper",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/jupiter-ag/"
},
"KAVA-USD": {
"name": "Kava",
"tags": ["Layer 1"],
"websiteLink": "https://www.kava.io/",
"whitepaperLink": "https://docsend.com/view/gwbwpc3",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/kava/"
},
"LDO-USD": {
"name": "Lido DAO",
"tags": ["Defi"],
@@ -310,20 +219,6 @@
"whitepaperLink": "https://litecoin.info/index.php/Main_Page",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/litecoin/"
},
"MANA-USD": {
"name": "Decentraland",
"tags": ["AR/VR"],
"websiteLink": "https://decentraland.org/",
"whitepaperLink": "https://decentraland.org/whitepaper.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/decentraland/"
},
"MASK-USD": {
"name": "Mask Network",
"tags": [],
"websiteLink": "https://mask.io/",
"whitepaperLink": "https://masknetwork.medium.com/introducing-mask-network-maskbook-the-future-of-the-internet-5a973d874edd",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/mask-network/"
},
"MATIC-USD": {
"name": "Polygon",
"tags": ["Layer 2"],
@@ -331,13 +226,6 @@
"whitepaperLink": "https://polygon.technology/lightpaper-polygon.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/polygon/"
},
"MINA-USD": {
"name": "Mina",
"tags": ["Layer 1"],
"websiteLink": "https://minaprotocol.com/",
"whitepaperLink": "https://docs.minaprotocol.com/assets/economicsWhitepaper.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/mina/"
},
"MKR-USD": {
"name": "Maker",
"tags": ["Governance"],
@@ -352,13 +240,6 @@
"whitepaperLink": "https://near.org/papers/the-official-near-white-paper/",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/near-protocol/"
},
"ORDI-USD": {
"name": "Ordinals",
"tags": ["NFT"],
"websiteLink": "https://ordinals.com/",
"whitepaperLink": "https://rodarmor.com/blog/",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/ordi/"
},
"OP-USD": {
"name": "Optimism",
"tags": [],
@@ -372,20 +253,6 @@
"websiteLink": "https://www.pepe.vip/",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/pepe/"
},
"PYTH-USD": {
"name": "Pyth Network",
"tags": [],
"websiteLink": "https://pyth.network/",
"whitepaperLink": "https://pyth.network/whitepaper_v2.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/pyth-network/"
},
"RNDR-USD": {
"name": "Render Token",
"tags": ["AI"],
"websiteLink": "https://rendernetwork.com/",
"whitepaperLink": "https://renderfoundation.com/whitepaper",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/render/"
},
"RUNE-USD": {
"name": "THORChain",
"tags": ["Layer 1"],
@@ -393,13 +260,6 @@
"whitepaperLink": "https://whitepaper.io/document/709/thorchain-whitepaper",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/thorchain/"
},
"SAND-USD": {
"name": "The Sandbox",
"tags": ["Gaming"],
"websiteLink": "https://www.sandbox.game/en/",
"whitepaperLink": "https://installers.sandbox.game/The_Sandbox_Whitepaper_2020.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/the-sandbox/"
},
"SEI-USD": {
"name": "Sei",
"tags": ["Layer 1", "Defi"],
@@ -428,20 +288,6 @@
"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"],
"websiteLink": "https://www.stacks.co/",
"whitepaperLink": "https://gaia.blockstack.org/hub/1AxyPunHHAHiEffXWESKfbvmBpGQv138Fp/stacks.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/stacks/"
},
"SUI-USD": {
"name": "Sui",
"tags": ["Layer 1"],
@@ -491,13 +337,6 @@
"whitepaperLink": "https://whitepaper.worldcoin.org/",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/worldcoin-org/"
},
"WOO-USD": {
"name": "WOO Network",
"tags": ["Defi"],
"websiteLink": "https://woo.org/",
"whitepaperLink": "https://woo.org/Litepaper.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/wootrade/"
},
"XLM-USD": {
"name": "Stellar",
"tags": ["Layer 1"],
@@ -513,14 +513,6 @@
{ "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" },
+12 -29
View File
@@ -274,7 +274,7 @@
{
"baseAsset": "CRV",
"referencePrice": 0.48346754113361784,
"numOracles": 6,
"numOracles": 5,
"liquidityTier": 2,
"assetName": "Curve DAO Token",
"p": -1.0,
@@ -325,7 +325,7 @@
{
"baseAsset": "DYM",
"referencePrice": 5.544949130771594,
"numOracles": 6,
"numOracles": 5,
"liquidityTier": 2,
"assetName": "Dymension",
"p": 0.0,
@@ -412,7 +412,7 @@
"referencePrice": 0.5560893147613742,
"numOracles": 6,
"liquidityTier": 2,
"assetName": "Fetch.ai",
"assetName": "Fetch AI",
"p": -1.0,
"atomicResolution": -5.0,
"minExchanges": 3,
@@ -480,7 +480,7 @@
"referencePrice": 0.20404992804891367,
"numOracles": 6,
"liquidityTier": 2,
"assetName": "GMT",
"assetName": "STEPN",
"p": -1.0,
"atomicResolution": -5.0,
"minExchanges": 3,
@@ -514,7 +514,7 @@
"referencePrice": 0.07686278766140874,
"numOracles": 6,
"liquidityTier": 2,
"assetName": "Hedera",
"assetName": "Hedera Hashgraph",
"p": -2.0,
"atomicResolution": -4.0,
"minExchanges": 3,
@@ -565,7 +565,7 @@
"referencePrice": 33.427379051845875,
"numOracles": 7,
"liquidityTier": 2,
"assetName": "Injective",
"assetName": "Injective Protocol",
"p": 1.0,
"atomicResolution": -7.0,
"minExchanges": 3,
@@ -597,7 +597,7 @@
{
"baseAsset": "JUP",
"referencePrice": 0.4339790660244292,
"numOracles": 6,
"numOracles": 5,
"liquidityTier": 2,
"assetName": "Jupiter",
"p": -1.0,
@@ -750,7 +750,7 @@
{
"baseAsset": "MKR",
"referencePrice": 1943.1865605831852,
"numOracles": 6,
"numOracles": 5,
"liquidityTier": 2,
"assetName": "Maker",
"p": 3.0,
@@ -869,7 +869,7 @@
{
"baseAsset": "RUNE",
"referencePrice": 3.7264809096406806,
"numOracles": 6,
"numOracles": 5,
"liquidityTier": 2,
"assetName": "Thorchain",
"p": 0.0,
@@ -888,7 +888,7 @@
"referencePrice": 0.37297439115035663,
"numOracles": 6,
"liquidityTier": 2,
"assetName": "The Sandbox",
"assetName": "SAND",
"p": -1.0,
"atomicResolution": -5.0,
"minExchanges": 3,
@@ -968,23 +968,6 @@
"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,
@@ -1090,9 +1073,9 @@
{
"baseAsset": "WOO",
"referencePrice": 0.2944897275608197,
"numOracles": 6,
"numOracles": 5,
"liquidityTier": 2,
"assetName": "WOO Network",
"assetName": "Wootrade Network",
"p": -1.0,
"atomicResolution": -5.0,
"minExchanges": 3,
+406 -409
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -14,7 +14,7 @@ if (AMPLITUDE_API_KEY) {
const html = await fs.readFile(htmlFilePath, 'utf-8');
const amplitudeCdnScript = `<script type="text/javascript">
!function(){"use strict";!function(e,t){var n=e.amplitude||{_q:[],_iq:{}};if(n.invoked)e.console&&console.error&&console.error("Amplitude snippet has been loaded.");else{var r=function(e,t){e.prototype[t]=function(){return this._q.push({name:t,args:Array.prototype.slice.call(arguments,0)}),this}},s=function(e,t,n){return function(r){e._q.push({name:t,args:Array.prototype.slice.call(n,0),resolve:r})}},o=function(e,t,n){e[t]=function(){if(n)return{promise:new Promise(s(e,t,Array.prototype.slice.call(arguments)))}}},i=function(e){for(var t=0;t<m.length;t++)o(e,m[t],!1);for(var n=0;n<g.length;n++)o(e,g[n],!0)};n.invoked=!0;var u=t.createElement("script");u.type="text/javascript",u.integrity="sha384-BVo5ZjsjH373rWbcjz9Qjb2L6BgLwLADcZtZZPu3nMl8+7LPDhi1NcUEf0Ate41Y",u.crossOrigin="anonymous",u.async=!0,u.src="/libs/amplitude-analytics-browser-2.0.0-min.js",u.onload=function(){e.amplitude.runQueuedFunctions||console.log("[Amplitude] Error: could not load SDK")};var a=t.getElementsByTagName("script")[0];a.parentNode.insertBefore(u,a);for(var c=function(){return this._q=[],this},p=["add","append","clearAll","prepend","set","setOnce","unset","preInsert","postInsert","remove","getUserProperties"],l=0;l<p.length;l++)r(c,p[l]);n.Identify=c;for(var d=function(){return this._q=[],this},f=["getEventProperties","setProductId","setQuantity","setPrice","setRevenue","setRevenueType","setEventProperties"],v=0;v<f.length;v++)r(d,f[v]);n.Revenue=d;var m=["getDeviceId","setDeviceId","getSessionId","setSessionId","getUserId","setUserId","setOptOut","setTransport","reset","extendSession"],g=["init","add","remove","track","logEvent","identify","groupIdentify","setGroup","revenue","flush"];i(n),n.createInstance=function(e){return n._iq[e]={_q:[]},i(n._iq[e]),n._iq[e]},e.amplitude=n}}(window,document)}();
!function(){"use strict";!function(e,t){var n=e.amplitude||{_q:[],_iq:{}};if(n.invoked)e.console&&console.error&&console.error("Amplitude snippet has been loaded.");else{var r=function(e,t){e.prototype[t]=function(){return this._q.push({name:t,args:Array.prototype.slice.call(arguments,0)}),this}},s=function(e,t,n){return function(r){e._q.push({name:t,args:Array.prototype.slice.call(n,0),resolve:r})}},o=function(e,t,n){e[t]=function(){if(n)return{promise:new Promise(s(e,t,Array.prototype.slice.call(arguments)))}}},i=function(e){for(var t=0;t<m.length;t++)o(e,m[t],!1);for(var n=0;n<g.length;n++)o(e,g[n],!0)};n.invoked=!0;var u=t.createElement("script");u.type="text/javascript",u.integrity="sha384-x0ik2D45ZDEEEpYpEuDpmj05fY91P7EOZkgdKmq4dKL/ZAVcufJ+nULFtGn0HIZE",u.crossOrigin="anonymous",u.async=!0,u.src="https://cdn.amplitude.com/libs/analytics-browser-2.0.0-min.js.gz",u.onload=function(){e.amplitude.runQueuedFunctions||console.log("[Amplitude] Error: could not load SDK")};var a=t.getElementsByTagName("script")[0];a.parentNode.insertBefore(u,a);for(var c=function(){return this._q=[],this},p=["add","append","clearAll","prepend","set","setOnce","unset","preInsert","postInsert","remove","getUserProperties"],l=0;l<p.length;l++)r(c,p[l]);n.Identify=c;for(var d=function(){return this._q=[],this},f=["getEventProperties","setProductId","setQuantity","setPrice","setRevenue","setRevenueType","setEventProperties"],v=0;v<f.length;v++)r(d,f[v]);n.Revenue=d;var m=["getDeviceId","setDeviceId","getSessionId","setSessionId","getUserId","setUserId","setOptOut","setTransport","reset","extendSession"],g=["init","add","remove","track","logEvent","identify","groupIdentify","setGroup","revenue","flush"];i(n),n.createInstance=function(e){return n._iq[e]={_q:[]},i(n._iq[e]),n._iq[e]},e.amplitude=n}}(window,document)}();
</script>
`;
-22
View File
@@ -8,7 +8,6 @@ const assetIcons = {
'1INCH': '/currencies/1inch.png',
AAVE: '/currencies/aave.png',
ADA: '/currencies/ada.png',
AGIX: '/currencies/agix.png',
ALGO: '/currencies/algo.png',
APE: '/currencies/ape.png',
APT: '/currencies/apt.png',
@@ -21,7 +20,6 @@ const assetIcons = {
BONK: '/currencies/bonk.png',
BTC: '/currencies/btc.png',
CELO: '/currencies/celo.png',
CHZ: '/currencies/chz.png',
COMP: '/currencies/comp.png',
CRV: '/currencies/crv.png',
DAI: '/currencies/dai.png',
@@ -30,44 +28,25 @@ const assetIcons = {
DYDX: '/currencies/dydx.png',
DYM: '/currencies/dym.png',
ENJ: '/currencies/enj.png',
ENS: '/currencies/ens.png',
EOS: '/currencies/eos.png',
ETC: '/currencies/etc.png',
ETH: '/currencies/eth.png',
FET: '/currencies/fet.png',
FIL: '/currencies/fil.png',
FTM: '/currencies/ftm.png',
GALA: "/currencies/gala.png",
GMT: "/currencies/gmt.png",
GRT: "/currencies/grt.png",
HBAR: "/currencies/hbar.png",
ICP: '/currencies/icp.png',
IMX: '/currencies/imx.png',
INJ: '/currencies/inj.png',
JTO: '/currencies/jto.png',
JUP: '/currencies/jup.png',
KAVA: '/currencies/kava.png',
LDO: '/currencies/ldo.png',
LINK: '/currencies/link.png',
LTC: '/currencies/ltc.png',
MANA: '/currencies/mana.png',
MATIC: '/currencies/matic.png',
MASK: '/currencies/mask.png',
MINA: '/currencies/mina.png',
MKR: '/currencies/mkr.png',
NEAR: '/currencies/near.png',
ORDI: "/currencies/ordi.png",
OP: '/currencies/op.png',
PEPE: '/currencies/pepe.png',
PYTH: '/currencies/pyth.png',
RNDR: '/currencies/rndr.png',
RUNE: '/currencies/rune.png',
SAND: '/currencies/sand.png',
SEI: '/currencies/sei.png',
SHIB: '/currencies/shib.png',
SNX: '/currencies/snx.png',
SOL: '/currencies/sol.png',
STX: '/currencies/stx.png',
SUI: '/currencies/sui.png',
SUSHI: '/currencies/sushi.png',
TIA: '/currencies/tia.png',
@@ -78,7 +57,6 @@ const assetIcons = {
USDT: '/currencies/usdt.png',
WBTC: '/currencies/wbtc.png',
WETH: '/currencies/weth.png',
WOO: '/currencies/woo.png',
WLD: '/currencies/wld.png',
XLM: '/currencies/xlm.png',
XMR: '/currencies/xmr.png',
+3 -5
View File
@@ -39,7 +39,7 @@ export const SearchSelectMenu = ({
disabled,
label,
items,
withSearch = true,
withSearch,
withReceiptItems,
}: SearchSelectMenuProps) => {
const [open, setOpen] = useState(false);
@@ -77,7 +77,6 @@ export const SearchSelectMenu = ({
withSearch={withSearch}
onItemSelected={() => setOpen(false)}
withStickyLayout
$withSearch={withSearch}
/>
</Styled.Popover>
</Styled.WithDetailsReceipt>
@@ -128,7 +127,7 @@ Styled.Popover = styled(Popover)`
box-shadow: none;
`;
Styled.ComboboxMenu = styled(ComboboxMenu)<{ $withSearch?: boolean }>`
Styled.ComboboxMenu = styled(ComboboxMenu)`
${layoutMixins.withInnerHorizontalBorders}
--comboboxMenu-backgroundColor: var(--color-layer-4);
@@ -141,8 +140,7 @@ Styled.ComboboxMenu = styled(ComboboxMenu)<{ $withSearch?: boolean }>`
--comboboxMenu-item-checked-textColor: var(--color-text-2);
--comboboxMenu-item-highlighted-textColor: var(--color-text-2);
--stickyArea1-topHeight: ${({ $withSearch }) =>
!$withSearch ? '0' : 'var(--form-input-height)'};
--stickyArea1-topHeight: var(--form-input-height);
input:focus-visible {
outline: none;
+1 -8
View File
@@ -1,4 +1,4 @@
import { type ReactNode, useState, useEffect } from 'react';
import { type ReactNode, useState } from 'react';
import { ButtonAction, ButtonState } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization';
@@ -8,7 +8,6 @@ import { Button, type ButtonStateConfig, type ButtonProps } from '@/components/B
type ElementProps = {
timeoutInSeconds: number;
onTimeOut?: () => void;
slotFinal?: ReactNode;
} & ButtonProps;
@@ -17,7 +16,6 @@ export type TimeoutButtonProps = ElementProps;
export const TimeoutButton = ({
children,
timeoutInSeconds,
onTimeOut,
slotFinal,
...otherProps
}: TimeoutButtonProps) => {
@@ -27,11 +25,6 @@ export const TimeoutButton = ({
const secondsLeft = Math.max(0, (timeoutDeadline - now) / 1000);
useEffect(() => {
if (secondsLeft > 0) return;
onTimeOut?.();
}, [secondsLeft]);
if (slotFinal && secondsLeft <= 0) return slotFinal;
return (
+2 -10
View File
@@ -144,17 +144,9 @@ export type AnalyticsEventData<T extends AnalyticsEvent> =
validatorUrl: string;
}
: T extends AnalyticsEvent.TransferDeposit
? {
chainId?: string;
tokenAddress?: string;
tokenSymbol?: string;
}
? {}
: T extends AnalyticsEvent.TransferWithdraw
? {
chainId?: string;
tokenAddress?: string;
tokenSymbol?: string;
}
? {}
: // Trading
T extends AnalyticsEvent.TradeOrderTypeSelected
? {
+1 -6
View File
@@ -1,4 +1,4 @@
import environments from '../../public/configs/v1/env.json';
import environments from '../../public/configs/env.json';
const CURRENT_MODE = ({
production: 'MAINNET',
@@ -14,10 +14,5 @@ export const isDev = CURRENT_MODE === 'DEV';
export const AVAILABLE_ENVIRONMENTS = environments.deployments[CURRENT_MODE];
export const CURRENT_ABACUS_DEPLOYMENT = CURRENT_MODE;
export const ENVIRONMENT_CONFIG_MAP = environments.environments;
export const TOKEN_CONFIG_MAP = environments.tokens;
export const LINKS_CONFIG_MAP = environments.links;
export const WALLETS_CONFIG_MAP = environments.wallets;
export const GOVERNANCE_CONFIG_MAP = environments.governance;
export type DydxNetwork = keyof typeof ENVIRONMENT_CONFIG_MAP;
export type DydxChainId = keyof typeof TOKEN_CONFIG_MAP;
export const DEFAULT_APP_ENVIRONMENT = AVAILABLE_ENVIRONMENTS.default as DydxNetwork;
-1
View File
@@ -140,7 +140,6 @@ export type TransferNotifcation = {
isCctp?: boolean;
errorCount?: number;
status?: StatusResponse;
isExchange?: boolean;
};
/**
+4 -4
View File
@@ -24,7 +24,7 @@ import {
import { isMetaMask } from '@/lib/wallet/providers';
import { DydxChainId, WALLETS_CONFIG_MAP } from './networks';
import { DydxNetwork, ENVIRONMENT_CONFIG_MAP } from './networks';
// Wallet connection types
@@ -291,17 +291,17 @@ export const COSMOS_DERIVATION_PATH = "m/44'/118'/0'/0/0";
/**
* @description typed data to sign for dYdX Chain onboarding
*/
export const getSignTypedData = (selectedDydxChainId: DydxChainId) =>
export const getSignTypedData = (selectedNetwork: DydxNetwork) =>
({
primaryType: 'dYdX',
domain: {
name: WALLETS_CONFIG_MAP[selectedDydxChainId].signTypedDataDomainName,
name: ENVIRONMENT_CONFIG_MAP[selectedNetwork].wallets.signTypedDataDomainName,
},
types: {
dYdX: [{ name: 'action', type: 'string' }],
},
message: {
action: WALLETS_CONFIG_MAP[selectedDydxChainId].signTypedDataAction,
action: ENVIRONMENT_CONFIG_MAP[selectedNetwork].wallets.signTypedDataAction,
},
} as const);
@@ -27,26 +27,19 @@ export const useChartMarketAndResolution = ({
const dispatch = useDispatch();
const currentMarketId: string = useSelector(getCurrentMarketId) || DEFAULT_MARKETID;
const selectedResolution: string =
useSelector(getSelectedResolutionForMarket(currentMarketId)) || DEFAULT_RESOLUTION;
const chart = isWidgetReady ? tvWidget?.chart() : undefined;
const chartResolution = chart?.resolution?.();
/**
* @description Hook to handle changing markets - intentionally should avoid triggering on change of resolutions.
*/
useEffect(() => {
if (currentMarketId && isWidgetReady) {
const resolution = savedResolution || selectedResolution;
tvWidget?.setSymbol(currentMarketId, resolution as ResolutionString, () => {});
}
}, [currentMarketId, isWidgetReady]);
}, [currentMarketId, isWidgetReady, savedResolution, selectedResolution]);
/**
* @description Hook to handle changing chart resolution
*/
useEffect(() => {
if (chartResolution) {
if (chartResolution !== selectedResolution) {
+8 -8
View File
@@ -18,13 +18,14 @@ import type { ResolutionString } from 'public/tradingview/charting_library';
import type { ConnectNetworkEvent, NetworkConfig } from '@/constants/abacus';
import { DEFAULT_TRANSACTION_MEMO } from '@/constants/analytics';
import { type Candle, RESOLUTION_MAP } from '@/constants/candles';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { DydxChainAsset } from '@/constants/wallets';
import { getSelectedNetwork } from '@/state/appSelectors';
import { log } from '@/lib/telemetry';
import { useRestrictions } from './useRestrictions';
import { useTokenConfigs } from './useTokenConfigs';
type DydxContextType = ReturnType<typeof useDydxClientContext>;
const DydxContext = createContext<DydxContextType>({} as DydxContextType);
@@ -40,8 +41,7 @@ const useDydxClientContext = () => {
// ------ Network ------ //
const selectedNetwork = useSelector(getSelectedNetwork);
const { usdcDenom, usdcDecimals, usdcGasDenom, chainTokenDenom, chainTokenDecimals } =
useTokenConfigs();
const tokensConfigs = ENVIRONMENT_CONFIG_MAP[selectedNetwork].tokens;
const [networkConfig, setNetworkConfig] = useState<NetworkConfig>();
@@ -75,11 +75,11 @@ const useDydxClientContext = () => {
networkConfig.validatorUrl,
networkConfig.chainId,
{
USDC_DENOM: usdcDenom,
USDC_DECIMALS: usdcDecimals,
USDC_GAS_DENOM: usdcGasDenom,
CHAINTOKEN_DENOM: chainTokenDenom,
CHAINTOKEN_DECIMALS: chainTokenDecimals,
USDC_DENOM: tokensConfigs[DydxChainAsset.USDC].denom,
USDC_DECIMALS: tokensConfigs[DydxChainAsset.USDC].decimals,
USDC_GAS_DENOM: tokensConfigs[DydxChainAsset.USDC].gasDenom,
CHAINTOKEN_DENOM: tokensConfigs[DydxChainAsset.CHAINTOKEN].denom,
CHAINTOKEN_DECIMALS: tokensConfigs[DydxChainAsset.CHAINTOKEN].decimals,
},
{
broadcastPollIntervalMs: 3_000,
+4 -7
View File
@@ -1,8 +1,5 @@
import { useSelector } from 'react-redux';
import { GOVERNANCE_CONFIG_MAP } from '@/constants/networks';
import { getSelectedDydxChainId } from '@/state/appSelectors';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { useSelectedNetwork } from '@/hooks';
export interface GovernanceVariables {
newMarketProposal: {
@@ -13,7 +10,7 @@ export interface GovernanceVariables {
}
export const useGovernanceVariables = (): GovernanceVariables => {
const selectedDydxChainId = useSelector(getSelectedDydxChainId);
const governanceVars = GOVERNANCE_CONFIG_MAP[selectedDydxChainId] as GovernanceVariables;
const { selectedNetwork } = useSelectedNetwork();
const governanceVars = ENVIRONMENT_CONFIG_MAP[selectedNetwork].governance as GovernanceVariables;
return governanceVars;
};
+9 -15
View File
@@ -82,30 +82,24 @@ const useLocalNotificationsContext = () => {
isCctp,
errorCount,
status: currentStatus,
isExchange,
} = transferNotification;
const hasErrors =
// @ts-ignore status.errors is not in the type definition but can be returned
// also error can some time come back as an empty object so we need to ignore for that
!!currentStatus?.errors ||
(currentStatus?.error && Object.keys(currentStatus.error).length !== 0);
// @ts-ignore status.errors is not in the type definition but can be returned
// also error can some time come back as an empty object so we need to ignore for that
const hasErrors = !!currentStatus?.errors ||
(currentStatus?.error && Object.keys(currentStatus.error).length !== 0);
if (
!isExchange &&
!hasErrors &&
(!currentStatus?.squidTransactionStatus ||
currentStatus?.squidTransactionStatus === 'ongoing')
) {
try {
const status = await fetchSquidStatus(
{
transactionId: txHash,
toChainId,
fromChainId,
},
isCctp
);
const status = await fetchSquidStatus({
transactionId: txHash,
toChainId,
fromChainId,
}, isCctp);
if (status) {
transferNotification.status = status;
+6 -7
View File
@@ -5,6 +5,7 @@ import { isEqual, groupBy } from 'lodash';
import { useNavigate } from 'react-router-dom';
import { DialogTypes } from '@/constants/dialogs';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { AppRoute } from '@/constants/routes';
import { DydxChainAsset } from '@/constants/wallets';
@@ -22,7 +23,7 @@ import {
TransferNotificationTypes,
} from '@/constants/notifications';
import { useStringGetter } from '@/hooks';
import { useSelectedNetwork, useStringGetter } from '@/hooks';
import { useLocalNotifications } from '@/hooks/useLocalNotifications';
import { AssetIcon } from '@/components/AssetIcon';
@@ -35,7 +36,6 @@ import { getSubaccountFills, getSubaccountOrders } from '@/state/accountSelector
import { openDialog } from '@/state/dialogs';
import { getAbacusNotifications } from '@/state/notificationsSelectors';
import { getMarketIds } from '@/state/perpetualsSelectors';
import { getSelectedDydxChainId } from '@/state/appSelectors';
import { formatSeconds } from '@/lib/timeUtils';
@@ -175,17 +175,16 @@ export const notificationTypes: NotificationTypeConfig[] = [
useTrigger: ({ trigger }) => {
const stringGetter = useStringGetter();
const { transferNotifications } = useLocalNotifications();
const selectedDydxChainId = useSelector(getSelectedDydxChainId);
const { selectedNetwork } = useSelectedNetwork();
useEffect(() => {
for (const transfer of transferNotifications) {
const { fromChainId, status, txHash, toAmount, type, isExchange } = transfer;
const isFinished =
(Boolean(status) && status?.squidTransactionStatus !== 'ongoing') || isExchange;
const { fromChainId, status, txHash, toAmount, type } = transfer;
const isFinished = Boolean(status) && status?.squidTransactionStatus !== 'ongoing';
const icon = <Icon iconName={isFinished ? IconName.Transfer : IconName.Clock} />;
const transferType =
type ?? fromChainId === selectedDydxChainId
type ?? fromChainId === ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId
? TransferNotificationTypes.Withdrawal
: TransferNotificationTypes.Deposit;
+1 -1
View File
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { LocalStorageKey } from '@/constants/localStorage';
import { DEFAULT_APP_ENVIRONMENT, DydxNetwork } from '@/constants/networks';
import { DEFAULT_APP_ENVIRONMENT, DydxNetwork, ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { useAccounts, useLocalStorage } from '@/hooks';
+1 -1
View File
@@ -28,7 +28,7 @@ import { setSubaccount, setHistoricalPnl, removeUncommittedOrderClientId } from
import { getBalances } from '@/state/accountSelectors';
import abacusStateManager from '@/lib/abacus';
import { hashFromTx } from '@/lib/txUtils';
import { hashFromTx } from '@/lib/hashfromTx';
import { log } from '@/lib/telemetry';
import { useAccounts } from './useAccounts';
+10 -14
View File
@@ -1,9 +1,7 @@
import { useSelector } from 'react-redux';
import { TOKEN_CONFIG_MAP } from '@/constants/networks';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { DydxChainAsset } from '@/constants/wallets';
import { getSelectedDydxChainId } from '@/state/appSelectors';
import { useSelectedNetwork } from '@/hooks';
export const useTokenConfigs = (): {
tokensConfigs: {
@@ -12,33 +10,31 @@ export const useTokenConfigs = (): {
name: string;
decimals: number;
gasDenom?: string;
};
},
[DydxChainAsset.CHAINTOKEN]: {
denom: string;
name: string;
decimals: number;
gasDenom?: string;
};
},
};
usdcDenom: string;
usdcDecimals: number;
usdcGasDenom: string;
usdcLabel: string;
chainTokenDenom: string;
chainTokenDecimals: number;
chainTokenLabel: string;
} => {
const selectedDydxChainId = useSelector(getSelectedDydxChainId);
const tokensConfigs = TOKEN_CONFIG_MAP[selectedDydxChainId];
const { selectedNetwork } = useSelectedNetwork();
const tokensConfigs = ENVIRONMENT_CONFIG_MAP[selectedNetwork].tokens;
return {
return {
tokensConfigs,
usdcDenom: tokensConfigs[DydxChainAsset.USDC].denom,
usdcDecimals: tokensConfigs[DydxChainAsset.USDC].decimals,
usdcGasDenom: tokensConfigs[DydxChainAsset.USDC].gasDenom,
usdcDenom: tokensConfigs[DydxChainAsset.USDC].denom,
usdcDecimals: tokensConfigs[DydxChainAsset.USDC].decimals,
usdcLabel: tokensConfigs[DydxChainAsset.USDC].name,
chainTokenDenom: tokensConfigs[DydxChainAsset.CHAINTOKEN].denom,
chainTokenDecimals: tokensConfigs[DydxChainAsset.CHAINTOKEN].decimals,
chainTokenDecimals: tokensConfigs[DydxChainAsset.CHAINTOKEN].decimals,
chainTokenLabel: tokensConfigs[DydxChainAsset.CHAINTOKEN].name,
};
};
+4 -8
View File
@@ -1,15 +1,12 @@
import { useSelector } from 'react-redux';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { LINKS_CONFIG_MAP } from '@/constants/networks';
import { getSelectedDydxChainId } from '@/state/appSelectors';
import { useSelectedNetwork } from '@/hooks';
const FALLBACK_URL = 'https://help.dydx.exchange/';
export interface LinksConfigs {
tos: string;
privacy: string;
statusPage: string;
mintscan: string;
mintscanBase: string;
feedback?: string;
@@ -30,13 +27,12 @@ export interface LinksConfigs {
}
export const useURLConfigs = (): LinksConfigs => {
const selectedDydxChainId = useSelector(getSelectedDydxChainId);
const linksConfigs = LINKS_CONFIG_MAP[selectedDydxChainId] as LinksConfigs;
const { selectedNetwork } = useSelectedNetwork();
const linksConfigs = ENVIRONMENT_CONFIG_MAP[selectedNetwork].links as LinksConfigs;
return {
tos: linksConfigs.tos,
privacy: linksConfigs.privacy,
statusPage: linksConfigs.statusPage,
mintscan: linksConfigs.mintscan,
mintscanBase: linksConfigs.mintscanBase,
feedback: linksConfigs.feedback || FALLBACK_URL,
+4 -4
View File
@@ -4,7 +4,7 @@ import { useSelector } from 'react-redux';
import { EvmDerivedAddresses } from '@/constants/account';
import { STRING_KEYS } from '@/constants/localization';
import { LocalStorageKey } from '@/constants/localStorage';
import { ENVIRONMENT_CONFIG_MAP, WALLETS_CONFIG_MAP } from '@/constants/networks';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import {
type DydxAddress,
@@ -32,7 +32,7 @@ import {
WalletType as CosmosWalletType,
} from 'graz';
import { getSelectedDydxChainId } from '@/state/appSelectors';
import { getSelectedNetwork } from '@/state/appSelectors';
import { resolveWagmiConnector } from '@/lib/wagmi';
import { getWalletConnection, parseWalletError } from '@/lib/wallet';
@@ -91,8 +91,8 @@ export const useWalletConnection = () => {
// Wallet connection
const selectedDydxChainId = useSelector(getSelectedDydxChainId);
const walletConnectConfig = WALLETS_CONFIG_MAP[selectedDydxChainId].walletconnect;
const selectedNetwork = useSelector(getSelectedNetwork);
const walletConnectConfig = ENVIRONMENT_CONFIG_MAP[selectedNetwork].wallets.walletconnect;
const wagmiConnector = useMemo(
() =>
walletType && walletConnectionType
+4 -3
View File
@@ -3,9 +3,9 @@ import styled, { type AnyStyledComponent, css } from 'styled-components';
import { AbacusApiStatus } from '@/constants/abacus';
import { ButtonSize, ButtonType } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization';
import { isDev } from '@/constants/networks';
import { ENVIRONMENT_CONFIG_MAP, isDev } from '@/constants/networks';
import { useApiState, useStringGetter, useURLConfigs } from '@/hooks';
import { useApiState, useSelectedNetwork, useStringGetter } from '@/hooks';
import { ChatIcon, LinkOutIcon } from '@/icons';
import { layoutMixins } from '@/styles/layoutMixins';
@@ -28,7 +28,8 @@ enum ExchangeStatus {
export const FooterDesktop = () => {
const stringGetter = useStringGetter();
const { height, indexerHeight, status, statusErrorMessage } = useApiState();
const { statusPage } = useURLConfigs();
const { selectedNetwork } = useSelectedNetwork();
const { statusPage } = ENVIRONMENT_CONFIG_MAP[selectedNetwork].links;
const { exchangeStatus, label } =
!status || status === AbacusApiStatus.NORMAL
+6 -7
View File
@@ -34,7 +34,7 @@ import {
import { DEFAULT_TRANSACTION_MEMO } from '@/constants/analytics';
import { DialogTypes } from '@/constants/dialogs';
import { UNCOMMITTED_ORDER_TIMEOUT_MS } from '@/constants/trade';
import { DydxChainId, isTestnet } from '@/constants/networks';
import { ENVIRONMENT_CONFIG_MAP, DydxNetwork, isTestnet } from '@/constants/networks';
import { RootStore } from '@/state/_store';
import { addUncommittedOrderClientId, removeUncommittedOrderClientId } from '@/state/account';
@@ -43,11 +43,7 @@ import { openDialog } from '@/state/dialogs';
import { StatefulOrderError } from '../errors';
import { bytesToBigInt } from '../numbers';
import { log } from '../telemetry';
import { hashFromTx, getMintscanTxLink } from '../txUtils';
(BigInt.prototype as any).toJSON = function () {
return this.toString();
};
import { hashFromTx } from '../hashfromTx';
class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
private compositeClient: CompositeClient | undefined;
@@ -242,7 +238,9 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
if (isTestnet) {
console.log(
getMintscanTxLink(this.compositeClient.network.getString() as DydxChainId, hash)
`${ENVIRONMENT_CONFIG_MAP[
this.compositeClient.network.getString() as DydxNetwork
]?.links?.mintscan?.replace('{tx_hash}', hash.toString())}`
);
} else console.log(`txHash: ${hash}`);
@@ -538,6 +536,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
const result = await this.cctpWithdraw(params);
callback(result);
break;
break;
}
default: {
break;
-19
View File
@@ -25,22 +25,3 @@ export function convertBech32Address({
}): string {
return toBech32(bech32Prefix, fromHex(toHex(fromBech32(address).data)));
}
/**
* Validates a Cosmos address with a specific prefix.
* @param {string} address The Cosmos address to validate.
* @param {string} prefix The expected prefix for the address.
* @returns {boolean} True if the address is valid and matches the prefix, false otherwise.
*/
export function validateCosmosAddress(address: string, prefix: string) {
try {
// Decode the address to verify its structure and prefix
const { prefix: decodedPrefix } = fromBech32(address);
// Check if the decoded address has the expected prefix
return decodedPrefix === prefix;
} catch (error) {
// If decoding fails, the address is not valid
return false;
}
}
+3
View File
@@ -0,0 +1,3 @@
export const hashFromTx = (
txHash: string | Uint8Array
): string => `0x${Buffer.from(txHash).toString('hex')}`;
+2 -2
View File
@@ -1,4 +1,4 @@
import { type DydxNetwork, ENVIRONMENT_CONFIG_MAP, type DydxChainId } from '@/constants/networks';
import { type DydxNetwork, ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
export const validateAgainstAvailableEnvironments = (value: DydxNetwork) =>
Object.keys(ENVIRONMENT_CONFIG_MAP).includes(value);
Object.keys(ENVIRONMENT_CONFIG_MAP).includes(value);
+3 -3
View File
@@ -31,13 +31,13 @@ export const fetchSquidStatus = async (
const response = await fetch(url, {
headers: {
'x-integrator-id': integratorId || 'dYdX-api',
"x-integrator-id": integratorId || 'dYdX-api'
},
});
if (!response.ok) {
const error = await response.json();
throw error;
throw new Error(error);
}
return response.json();
@@ -45,4 +45,4 @@ export const fetchSquidStatus = async (
export const getNobleChainId = () => {
return isMainnet ? 'noble-1' : 'grand-1';
};
}
+2 -2
View File
@@ -19,10 +19,10 @@ class TestFlags {
return !!this.queryParams.displayinitializingmarkets;
}
get addressOverride(): string {
get addressOverride():string {
return this.queryParams.address;
}
get showTradingRewards() {
return !!this.queryParams.tradingrewards;
}
-7
View File
@@ -1,7 +0,0 @@
import { DydxChainId, LINKS_CONFIG_MAP } from '@/constants/networks';
export const hashFromTx = (txHash: string | Uint8Array): string =>
`0x${Buffer.from(txHash).toString('hex')}`;
export const getMintscanTxLink = (dydxChainId: DydxChainId, txHash: string): string =>
`${LINKS_CONFIG_MAP[dydxChainId]?.mintscan?.replace('{tx_hash}', txHash.toString())}`;
@@ -26,6 +26,8 @@ import { openDialog } from '@/state/dialogs';
import { log } from '@/lib/telemetry';
const SEASON_NUMBER = 2;
export const LaunchIncentivesPanel = ({ className }: { className?: string }) => {
const { isNotTablet } = useBreakpoints();
const dispatch = useDispatch();
@@ -72,38 +74,14 @@ const EstimatedRewards = () => {
const stringGetter = useStringGetter();
const { dydxAddress } = useAccounts();
const { data: seasonNumber } = useQuery({
queryKey: 'chaos_labs_season_number',
queryFn: async () => {
const resp = await fetch('https://cloud.chaoslabs.co/query/ccar-perpetuals', {
method: 'POST',
headers: {
'apollographql-client-name': 'dydx-v4',
'content-type': 'application/json',
protocol: 'dydx-v4',
},
body: JSON.stringify({
operationName: 'TradingSeasons',
variables: {},
query: `query TradingSeasons {
tradingSeasons {
label
}
}`,
}),
});
const seasons = (await resp.json())?.data?.tradingSeasons;
return seasons && seasons.length > 0 ? seasons[seasons.length - 1].label : undefined;
},
onError: (error: Error) => log('LaunchIncentives/fetchSeasonNumber', error),
});
const { data, isLoading } = useQuery({
enabled: !!dydxAddress,
queryKey: `launch_incentives_rewards_${dydxAddress ?? ''}`,
queryKey: `launch_incentives_rewards_${dydxAddress ?? ''}_${SEASON_NUMBER}`,
queryFn: async () => {
if (!dydxAddress) return undefined;
const resp = await fetch(`https://cloud.chaoslabs.co/query/api/dydx/points/${dydxAddress}`);
const resp = await fetch(
`https://cloud.chaoslabs.co/query/api/dydx/points/${dydxAddress}?n=${SEASON_NUMBER}`
);
return (await resp.json())?.incentivePoints;
},
onError: (error: Error) => log('LaunchIncentives/fetchPoints', error),
@@ -114,14 +92,12 @@ const EstimatedRewards = () => {
<Styled.EstimatedRewardsCardContent>
<div>
<span>{stringGetter({ key: STRING_KEYS.ESTIMATED_REWARDS })}</span>
{seasonNumber !== undefined && (
<Styled.Season>
{stringGetter({
key: STRING_KEYS.LAUNCH_INCENTIVES_SEASON_NUM,
params: { SEASON_NUMBER: seasonNumber },
})}
</Styled.Season>
)}
<Styled.Season>
{stringGetter({
key: STRING_KEYS.LAUNCH_INCENTIVES_SEASON_NUM,
params: { SEASON_NUMBER },
})}
</Styled.Season>
</div>
<Styled.Points>
-4
View File
@@ -1,8 +1,4 @@
import { DydxChainId, ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import type { RootState } from './_store';
export const getApiState = (state: RootState) => state.app.apiState;
export const getSelectedNetwork = (state: RootState) => state.app.selectedNetwork;
export const getSelectedDydxChainId = (state: RootState) =>
ENVIRONMENT_CONFIG_MAP[state.app.selectedNetwork].dydxChainId as DydxChainId;
+3 -1
View File
@@ -13,6 +13,8 @@ export const DepositDialog = ({ setIsOpen }: ElementProps) => {
const stringGetter = useStringGetter();
const { isMobile } = useBreakpoints();
const closeDialog = () => setIsOpen?.(false);
return (
<Dialog
isOpen
@@ -20,7 +22,7 @@ export const DepositDialog = ({ setIsOpen }: ElementProps) => {
title={stringGetter({ key: STRING_KEYS.DEPOSIT })}
placement={isMobile ? DialogPlacement.FullScreen : DialogPlacement.Default}
>
<DepositDialogContent />
<DepositDialogContent onDeposit={closeDialog} />
</Dialog>
);
};
@@ -2,7 +2,6 @@ import { useEffect, useState } from 'react';
import styled, { type AnyStyledComponent } from 'styled-components';
import { TransferInputField, TransferType } from '@/constants/abacus';
import { AnalyticsEvent } from '@/constants/analytics';
import { isMainnet } from '@/constants/networks';
import { layoutMixins } from '@/styles/layoutMixins';
@@ -10,7 +9,6 @@ import { DepositForm } from '@/views/forms/AccountManagementForms/DepositForm';
import { TestnetDepositForm } from '@/views/forms/AccountManagementForms/TestnetDepositForm';
import abacusStateManager from '@/lib/abacus';
import { track } from '@/lib/analytics';
type ElementProps = {
onDeposit?: () => void;
@@ -36,19 +34,9 @@ export const DepositDialogContent = ({ onDeposit }: ElementProps) => {
return (
<Styled.Content>
{isMainnet || !showFaucet ? (
<DepositForm
onDeposit={(event) => {
track(AnalyticsEvent.TransferDeposit, event);
onDeposit?.();
}}
/>
<DepositForm onDeposit={onDeposit} />
) : (
<TestnetDepositForm
onDeposit={() => {
track(AnalyticsEvent.TransferFaucet);
onDeposit?.();
}}
/>
<TestnetDepositForm onDeposit={onDeposit} />
)}
{!isMainnet && (
<Styled.TextToggle onClick={() => setShowFaucet(!showFaucet)}>
+2 -2
View File
@@ -105,8 +105,8 @@ export const OnboardingDialog = ({ setIsOpen }: ElementProps) => {
<Styled.Content>
{isMainnet ? (
<DepositForm
onDeposit={(event) => {
track(AnalyticsEvent.TransferDeposit, event);
onDeposit={() => {
track(AnalyticsEvent.TransferDeposit);
}}
/>
) : (
@@ -25,7 +25,7 @@ import { Switch } from '@/components/Switch';
import { WithReceipt } from '@/components/WithReceipt';
import { WithTooltip } from '@/components/WithTooltip';
import { getSelectedNetwork, getSelectedDydxChainId } from '@/state/appSelectors';
import { getSelectedNetwork } from '@/state/appSelectors';
import { track } from '@/lib/analytics';
import { isTruthy } from '@/lib/isTruthy';
@@ -98,8 +98,7 @@ export const GenerateKeys = ({
EvmDerivedAccountStatus.Derived,
].includes(status);
const selectedDydxChainId = useSelector(getSelectedDydxChainId);
const signTypedData = getSignTypedData(selectedDydxChainId);
const signTypedData = getSignTypedData(selectedNetwork);
const { signTypedDataAsync } = useSignTypedData({
...signTypedData,
domain: {
@@ -7,11 +7,10 @@ import { Abi, parseUnits } from 'viem';
import erc20 from '@/abi/erc20.json';
import erc20_usdt from '@/abi/erc20_usdt.json';
import { TransferInputField, TransferInputTokenResource, TransferType } from '@/constants/abacus';
import { AnalyticsEvent, AnalyticsEventData } from '@/constants/analytics';
import { AlertType } from '@/constants/alerts';
import { ButtonSize } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization';
import { isMainnet } from '@/constants/networks';
import { ENVIRONMENT_CONFIG_MAP, isMainnet } from '@/constants/networks';
import { MAX_CCTP_TRANSFER_AMOUNT, MAX_PRICE_IMPACT, NumberSign } from '@/constants/numbers';
import type { EvmAddress } from '@/constants/wallets';
@@ -33,7 +32,6 @@ import { OutputType } from '@/components/Output';
import { Tag } from '@/components/Tag';
import { WithDetailsReceipt } from '@/components/WithDetailsReceipt';
import { getSelectedDydxChainId } from '@/state/appSelectors';
import { getTransferInputs } from '@/state/inputsSelectors';
import abacusStateManager from '@/lib/abacus';
@@ -49,7 +47,7 @@ import { DepositButtonAndReceipt } from './DepositForm/DepositButtonAndReceipt';
import { NobleDeposit } from '../NobleDeposit';
type DepositFormProps = {
onDeposit?: (event?: AnalyticsEventData<AnalyticsEvent.TransferDeposit>) => void;
onDeposit?: () => void;
onError?: () => void;
};
@@ -58,7 +56,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
const [error, setError] = useState<Error | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [requireUserActionInWallet, setRequireUserActionInWallet] = useState(false);
const selectedDydxChainId = useSelector(getSelectedDydxChainId);
const { selectedNetwork } = useSelectedNetwork();
const { evmAddress, signerWagmi, publicClientWagmi, nobleAddress } = useAccounts();
@@ -133,7 +131,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
if (error) onError?.();
}, [error]);
const onSelectNetwork = useCallback((name: string, type: 'chain' | 'exchange') => {
const onSelectChain = useCallback((name: string, type: 'chain' | 'exchange') => {
if (name) {
abacusStateManager.clearTransferInputValues();
setFromAmount('');
@@ -259,10 +257,14 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
};
const txHash = await signerWagmi.sendTransaction(tx);
onDeposit?.();
if (txHash) {
addTransferNotification({
txHash: txHash,
toChainId: !isCctp ? selectedDydxChainId : getNobleChainId(),
toChainId: !isCctp
? ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId
: getNobleChainId(),
fromChainId: chainIdStr || undefined,
toAmount: summary?.usdcSize || undefined,
triggeredAt: Date.now(),
@@ -270,12 +272,6 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
});
abacusStateManager.clearTransferInputValues();
setFromAmount('');
onDeposit?.({
chainId: chainIdStr || undefined,
tokenAddress: sourceToken?.address || undefined,
tokenSymbol: sourceToken?.symbol || undefined,
});
}
} catch (error) {
log('DepositForm/onSubmit', error);
@@ -284,7 +280,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
setIsLoading(false);
}
},
[requestPayload, signerWagmi, chainId, sourceToken, sourceChain]
[requestPayload, signerWagmi, chainId]
);
const amountInputReceipt = [
@@ -383,7 +379,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
<SourceSelectMenu
selectedChain={chainIdStr || undefined}
selectedExchange={exchange || undefined}
onSelect={onSelectNetwork}
onSelect={onSelectChain}
/>
{exchange && nobleAddress ? (
<NobleDeposit />
@@ -14,7 +14,6 @@ import { popoverMixins } from '@/styles/popoverMixins';
import { getTransferInputs } from '@/state/inputsSelectors';
import { isTruthy } from '@/lib/isTruthy';
import { testFlags } from '@/lib/testFlags';
type ElementProps = {
label?: string;
@@ -17,10 +17,9 @@ import { getTransferInputs } from '@/state/inputsSelectors';
type ElementProps = {
selectedToken?: TransferInputTokenResource;
onSelectToken: (token: TransferInputTokenResource) => void;
isExchange?: boolean;
};
export const TokenSelectMenu = ({ selectedToken, onSelectToken, isExchange }: ElementProps) => {
export const TokenSelectMenu = ({ selectedToken, onSelectToken }: ElementProps) => {
const stringGetter = useStringGetter();
const { type, depositOptions, withdrawalOptions, resources } =
useSelector(getTransferInputs, shallowEqual) || {};
@@ -48,24 +47,19 @@ export const TokenSelectMenu = ({ selectedToken, onSelectToken, isExchange }: El
},
]}
label={stringGetter({ key: STRING_KEYS.ASSET })}
withSearch={!isExchange}
withReceiptItems={
!isExchange
? [
{
key: 'swap',
label: stringGetter({ key: STRING_KEYS.SWAP }),
value: selectedToken && (
<>
<Tag>{type === TransferType.deposit ? selectedToken?.symbol : 'USDC'}</Tag>
<DiffArrow />
<Tag>{type === TransferType.deposit ? 'USDC' : selectedToken?.symbol}</Tag>
</>
),
},
]
: undefined
}
withReceiptItems={[
{
key: 'swap',
label: stringGetter({ key: STRING_KEYS.SWAP }),
value: selectedToken && (
<>
<Tag>{type === TransferType.deposit ? selectedToken?.symbol : 'USDC'}</Tag>
<DiffArrow />
<Tag>{type === TransferType.deposit ? 'USDC' : selectedToken?.symbol}</Tag>
</>
),
},
]}
>
<Styled.AssetRow>
{selectedToken ? (
@@ -7,10 +7,9 @@ import { isAddress } from 'viem';
import { TransferInputField, TransferInputTokenResource, TransferType } from '@/constants/abacus';
import { AlertType } from '@/constants/alerts';
import { AnalyticsEvent } from '@/constants/analytics';
import { ButtonSize } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization';
import { isMainnet } from '@/constants/networks';
import { ENVIRONMENT_CONFIG_MAP, isMainnet } from '@/constants/networks';
import { TransferNotificationTypes } from '@/constants/notifications';
import {
MAX_CCTP_TRANSFER_AMOUNT,
@@ -46,7 +45,6 @@ import { Icon, IconName } from '@/components/Icon';
import { SourceSelectMenu } from '@/views/forms/AccountManagementForms/SourceSelectMenu';
import { getSelectedDydxChainId } from '@/state/appSelectors';
import { getSubaccount } from '@/state/accountSelectors';
import { getTransferInputs } from '@/state/inputsSelectors';
@@ -56,14 +54,12 @@ import { getNobleChainId } from '@/lib/squid';
import { TokenSelectMenu } from './TokenSelectMenu';
import { WithdrawButtonAndReceipt } from './WithdrawForm/WithdrawButtonAndReceipt';
import { validateCosmosAddress } from '@/lib/addressUtils';
import { track } from '@/lib/analytics';
export const WithdrawForm = () => {
const stringGetter = useStringGetter();
const [error, setError] = useState<string>();
const [isLoading, setIsLoading] = useState(false);
const selectedDydxChainId = useSelector(getSelectedDydxChainId);
const { selectedNetwork } = useSelectedNetwork();
const { sendSquidWithdraw } = useSubaccount();
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
@@ -71,7 +67,6 @@ export const WithdrawForm = () => {
const {
requestPayload,
token,
exchange,
chain: chainIdStr,
address: toAddress,
resources,
@@ -183,27 +178,20 @@ export const WithdrawForm = () => {
requestPayload.data,
isCctp
);
const nobleChainId = getNobleChainId();
const toChainId = Boolean(exchange) ? nobleChainId : chainIdStr || undefined;
if (txHash && toChainId) {
if (txHash) {
addTransferNotification({
txHash: txHash,
type: TransferNotificationTypes.Withdrawal,
fromChainId: !isCctp ? selectedDydxChainId : nobleChainId,
toChainId,
fromChainId: !isCctp
? ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId
: getNobleChainId(),
toChainId: chainIdStr || undefined,
toAmount: debouncedAmountBN.toNumber(),
triggeredAt: Date.now(),
isCctp,
isExchange: Boolean(exchange),
});
abacusStateManager.clearTransferInputValues();
setWithdrawAmount('');
track(AnalyticsEvent.TransferWithdraw, {
chainId: toChainId,
tokenAddress: toToken?.address || undefined,
tokenSymbol: toToken?.symbol || undefined,
});
}
}
} catch (error) {
@@ -226,17 +214,7 @@ export const WithdrawForm = () => {
setIsLoading(false);
}
},
[
requestPayload,
debouncedAmountBN,
chainIdStr,
toAddress,
selectedDydxChainId,
exchange,
toToken,
screenAddresses,
stringGetter,
]
[requestPayload, debouncedAmountBN, chainIdStr, toAddress, screenAddresses, stringGetter]
);
const onChangeAddress = useCallback((e: ChangeEvent<HTMLInputElement>) => {
@@ -269,20 +247,13 @@ export const WithdrawForm = () => {
setWithdrawAmount(freeCollateralBN.toString());
}, [freeCollateralBN, setWithdrawAmount]);
const onSelectNetwork = useCallback((name: string, type: 'chain' | 'exchange') => {
if (name) {
const onSelectChain = useCallback((chain: string) => {
if (chain) {
abacusStateManager.setTransferValue({
field: TransferInputField.chain,
value: chain,
});
setWithdrawAmount('');
if (type === 'chain') {
abacusStateManager.setTransferValue({
field: TransferInputField.chain,
value: name,
});
} else {
abacusStateManager.setTransferValue({
field: TransferInputField.exchange,
value: name,
});
}
}
}, []);
@@ -343,7 +314,7 @@ export const WithdrawForm = () => {
});
if (debouncedAmountBN) {
if (!chainIdStr && !exchange) {
if (!chainIdStr) {
return stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_CHAIN });
} else if (!toToken) {
return stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_ASSET });
@@ -390,19 +361,14 @@ export const WithdrawForm = () => {
summary,
]);
const isInvalidNobleAddress = Boolean(
exchange && toAddress && !validateCosmosAddress(toAddress, 'noble')
);
const isDisabled =
!!errorMessage ||
!toToken ||
(!chainIdStr && !exchange) ||
!chainIdStr ||
!toAddress ||
debouncedAmountBN.isNaN() ||
debouncedAmountBN.isZero() ||
isLoading ||
isInvalidNobleAddress;
isLoading;
return (
<Styled.Form onSubmit={onSubmit}>
@@ -420,21 +386,12 @@ export const WithdrawForm = () => {
}
/>
<SourceSelectMenu
selectedExchange={exchange || undefined}
label={stringGetter({ key: STRING_KEYS.NETWORK })}
selectedChain={chainIdStr || undefined}
onSelect={onSelectNetwork}
onSelect={onSelectChain}
/>
</Styled.DestinationRow>
{isInvalidNobleAddress && (
<AlertMessage type={AlertType.Error}>
{stringGetter({ key: STRING_KEYS.NOBLE_ADDRESS_VALIDATION })}
</AlertMessage>
)}
<TokenSelectMenu
selectedToken={toToken || undefined}
onSelectToken={onSelectToken}
isExchange={Boolean(exchange)}
/>
<TokenSelectMenu selectedToken={toToken || undefined} onSelectToken={onSelectToken} />
<Styled.WithDetailsReceipt side="bottom" detailItems={amountInputReceipt}>
<FormInput
type={InputType.Number}
@@ -27,8 +27,6 @@ import { calculateCanAccountTrade } from '@/state/accountCalculators';
import { getSubaccount } from '@/state/accountSelectors';
import { getTransferInputs } from '@/state/inputsSelectors';
import { isTruthy } from '@/lib/isTruthy';
import { SlippageEditor } from '../SlippageEditor';
type ElementProps = {
@@ -57,7 +55,7 @@ export const WithdrawButtonAndReceipt = ({
const stringGetter = useStringGetter();
const { leverage } = useSelector(getSubaccount, shallowEqual) || {};
const { summary, requestPayload, exchange } = useSelector(getTransferInputs, shallowEqual) || {};
const { summary, requestPayload } = useSelector(getTransferInputs, shallowEqual) || {};
const canAccountTrade = useSelector(calculateCanAccountTrade, shallowEqual);
const { usdcLabel } = useTokenConfigs();
@@ -94,7 +92,7 @@ export const WithdrawButtonAndReceipt = ({
value: <Output type={OutputType.Fiat} value={totalFees} />,
subitems: feeSubitems,
},
!exchange && {
{
key: 'exchange-rate',
label: <span>{stringGetter({ key: STRING_KEYS.EXCHANGE_RATE })}</span>,
value: withdrawToken && typeof summary?.exchangeRate === 'number' && (
@@ -135,9 +133,7 @@ export const WithdrawButtonAndReceipt = ({
{withdrawToken && <Tag>{withdrawToken?.symbol}</Tag>}
</span>
),
value: (
<Output type={OutputType.Asset} value={summary?.toAmount} fractionDigits={TOKEN_DECIMALS} />
),
value: <Output type={OutputType.Asset} value={summary?.toAmount} fractionDigits={TOKEN_DECIMALS} />,
subitems: [
{
key: 'minimum-amount-received',
@@ -148,17 +144,13 @@ export const WithdrawButtonAndReceipt = ({
</span>
),
value: (
<Output
type={OutputType.Asset}
value={summary?.toAmountMin}
fractionDigits={TOKEN_DECIMALS}
/>
<Output type={OutputType.Asset} value={summary?.toAmountMin} fractionDigits={TOKEN_DECIMALS} />
),
tooltip: 'minimum-amount-received',
},
],
},
!exchange && {
{
key: 'slippage',
label: <span>{stringGetter({ key: STRING_KEYS.MAX_SLIPPAGE })}</span>,
value: (
@@ -183,7 +175,7 @@ export const WithdrawButtonAndReceipt = ({
/>
),
},
].filter(isTruthy);
];
const isFormValid = !isDisabled && !isEditingSlippage;
+31 -25
View File
@@ -1,5 +1,5 @@
import { useState } from 'react';
import styled, { type AnyStyledComponent, css } from 'styled-components';
import styled, { type AnyStyledComponent } from 'styled-components';
import { OpacityToken } from '@/constants/styles/base';
import { STRING_KEYS } from '@/constants/localization';
@@ -10,6 +10,7 @@ import { useAccounts, useStringGetter } from '@/hooks';
import { CopyButton } from '@/components/CopyButton';
import { QrCode } from '@/components/QrCode';
import { Checkbox } from '@/components/Checkbox';
import { Icon, IconName } from '@/components/Icon';
import { TimeoutButton } from '@/components/TimeoutButton';
import { WithDetailsReceipt } from '@/components/WithDetailsReceipt';
import { WithReceipt } from '@/components/WithReceipt';
@@ -18,7 +19,6 @@ import { generateFadedColorVariant } from '@/lib/styles';
export const NobleDeposit = () => {
const [hasAcknowledged, setHasAcknowledged] = useState(false);
const [hasTimedout, setHasTimedout] = useState(false);
const stringGetter = useStringGetter();
const { nobleAddress } = useAccounts();
@@ -30,21 +30,23 @@ export const NobleDeposit = () => {
{
key: 'nobleAddress',
label: stringGetter({ key: STRING_KEYS.NOBLE_ADDRESS }),
value:
hasAcknowledged && hasTimedout
? nobleAddress
: stringGetter({ key: STRING_KEYS.ACKNOWLEDGE_TO_REVEAL }),
value: nobleAddress,
},
]}
>
<Styled.QrCode
hasLogo
size={432}
value={nobleAddress || ''}
blurred={!hasAcknowledged || !hasTimedout}
/>
<Styled.QrCodeContainer>
<Styled.QrCode size={432} value={nobleAddress || ''} />
</Styled.QrCodeContainer>
</WithDetailsReceipt>
<Styled.WaitingSpan>
<Styled.CautionIconContainer>
<Icon iconName={IconName.CautionCircleStroked} />
</Styled.CautionIconContainer>
<p>{stringGetter({ key: STRING_KEYS.NOBLE_WARNING })}</p>
</Styled.WaitingSpan>
<Styled.WithReceipt
slotReceipt={
<Styled.CheckboxContainer>
@@ -61,12 +63,7 @@ export const NobleDeposit = () => {
>
<TimeoutButton
timeoutInSeconds={8}
onTimeOut={() => setHasTimedout(true)}
slotFinal={
<CopyButton state={{ isDisabled: !hasAcknowledged }} value={nobleAddress}>
{!hasAcknowledged ? stringGetter({ key: STRING_KEYS.ACKNOWLEDGE_RISKS }) : undefined}
</CopyButton>
}
slotFinal={<CopyButton state={{ isDisabled: !hasAcknowledged }} value={nobleAddress} />}
/>
</Styled.WithReceipt>
</>
@@ -85,14 +82,23 @@ Styled.WithReceipt = styled(WithReceipt)`
--withReceipt-backgroundColor: var(--color-layer-2);
`;
Styled.QrCode = styled(QrCode)<{ blurred: boolean }>`
border-radius: 0.5em;
Styled.QrCodeContainer = styled.div`
display: flex;
justify-content: center;
${({ blurred }) =>
blurred &&
css`
filter: blur(8px);
`}
padding: 0.5rem;
background-color: var(--color-layer-2);
border-radius: 0.5rem;
`;
Styled.QrCode = styled(QrCode)`
max-height: 20rem;
width: fit-content;
svg {
max-height: 20rem;
}
`;
Styled.CheckboxContainer = styled.div`
+5 -4
View File
@@ -9,6 +9,7 @@ import { TransferInputField, TransferType } from '@/constants/abacus';
import { AlertType } from '@/constants/alerts';
import { ButtonShape, ButtonSize } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { NumberSign } from '@/constants/numbers';
import { DydxChainAsset } from '@/constants/wallets';
@@ -17,6 +18,7 @@ import {
useAccounts,
useDydxClient,
useRestrictions,
useSelectedNetwork,
useStringGetter,
useSubaccount,
useTokenConfigs,
@@ -39,7 +41,6 @@ import { TransferButtonAndReceipt } from '@/views/forms/TransferForm/TransferBut
import { WithDetailsReceipt } from '@/components/WithDetailsReceipt';
import { getSubaccount } from '@/state/accountSelectors';
import { getSelectedDydxChainId } from '@/state/appSelectors';
import { getTransferInputs } from '@/state/inputsSelectors';
import abacusStateManager from '@/lib/abacus';
@@ -62,7 +63,7 @@ export const TransferForm = ({
const { dydxAddress } = useAccounts();
const { transfer } = useSubaccount();
const { nativeTokenBalance, usdcBalance } = useAccountBalance();
const selectedDydxChainId = useSelector(getSelectedDydxChainId);
const { selectedNetwork } = useSelectedNetwork();
const { tokensConfigs, usdcLabel, chainTokenLabel } = useTokenConfigs();
const {
@@ -238,7 +239,7 @@ export const TransferForm = ({
const networkOptions = [
{
chainId: selectedDydxChainId,
chainId: ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId,
label: (
<Styled.InlineRow>
<AssetIcon symbol="DYDX" /> {stringGetter({ key: STRING_KEYS.DYDX_CHAIN })}
@@ -321,7 +322,7 @@ export const TransferForm = ({
/>
<Styled.NetworkSelectMenu
label={stringGetter({ key: STRING_KEYS.NETWORK })}
value={selectedDydxChainId}
value={ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId}
slotTriggerAfter={null}
>
{networkOptions.map(({ chainId, label }) => (
@@ -1,21 +1,18 @@
import { useMemo } from 'react';
import { useSelector } from 'react-redux';
import styled, { css, type AnyStyledComponent } from 'styled-components';
import { StatusResponse } from '@0xsquid/sdk';
import { STRING_KEYS } from '@/constants/localization';
import { TransferNotificationTypes } from '@/constants/notifications';
import { useStringGetter, useURLConfigs } from '@/hooks';
import { layoutMixins } from '@/styles/layoutMixins';
import { useStringGetter, useSelectedNetwork, useURLConfigs } from '@/hooks';
import { Link } from '@/components/Link';
import { Icon, IconName } from '@/components/Icon';
import { LoadingDots } from '@/components/Loading/LoadingDots';
import { LoadingSpinner } from '@/components/Loading/LoadingSpinner';
import { getSelectedDydxChainId } from '@/state/appSelectors';
import { layoutMixins } from '@/styles/layoutMixins';
import { STRING_KEYS } from '@/constants/localization';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { TransferNotificationTypes } from '@/constants/notifications';
type ElementProps = {
status?: StatusResponse;
@@ -35,8 +32,9 @@ enum TransferStatusStep {
export const TransferStatusSteps = ({ className, status, type }: ElementProps & StyleProps) => {
const stringGetter = useStringGetter();
const selectedDydxChainId = useSelector(getSelectedDydxChainId);
const { selectedNetwork } = useSelectedNetwork();
const { mintscan: mintscanTxUrl } = useURLConfigs();
const dydxChainId = ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId;
const { currentStep, steps } = useMemo(() => {
const routeStatus = status?.routeStatus;
@@ -57,7 +55,7 @@ export const TransferStatusSteps = ({ className, status, type }: ElementProps &
link:
type === TransferNotificationTypes.Deposit
? status?.fromChain?.transactionUrl
: routeStatus?.[0]?.chainId === selectedDydxChainId && routeStatus[0].txHash
: routeStatus?.[0]?.chainId === dydxChainId && routeStatus[0].txHash
? `${mintscanTxUrl?.replace('{tx_hash}', routeStatus[0].txHash.replace('0x', ''))}`
: undefined,
},
@@ -83,7 +81,7 @@ export const TransferStatusSteps = ({ className, status, type }: ElementProps &
link:
type === TransferNotificationTypes.Withdrawal
? status?.toChain?.transactionUrl
: currentStatus?.chainId === selectedDydxChainId && currentStatus?.txHash
: currentStatus?.chainId === dydxChainId && currentStatus?.txHash
? `${mintscanTxUrl?.replace('{tx_hash}', currentStatus.txHash.replace('0x', ''))}`
: undefined,
},
@@ -40,7 +40,7 @@ export const TransferStatusNotification = ({
const stringGetter = useStringGetter();
const [open, setOpen] = useState<boolean>(false);
const [secondsLeft, setSecondsLeft] = useState<number>(0);
const { fromChainId, status, txHash, toAmount, isExchange } = transfer;
const { fromChainId, status, txHash, toAmount } = transfer;
// @ts-ignore status.errors is not in the type definition but can be returned
const error = status?.errors?.length ? status?.errors[0] : status?.error;
@@ -54,8 +54,6 @@ export const TransferStatusNotification = ({
useInterval({ callback: updateSecondsLeft });
const isComplete = status?.squidTransactionStatus === 'success' || isExchange;
const inProgressStatusString =
type === TransferNotificationTypes.Deposit
? secondsLeft > 0
@@ -67,10 +65,10 @@ export const TransferStatusNotification = ({
const statusString =
type === TransferNotificationTypes.Deposit
? isComplete
? status?.squidTransactionStatus === 'success'
? STRING_KEYS.DEPOSIT_COMPLETE
: inProgressStatusString
: isComplete
: status?.squidTransactionStatus === 'success'
? STRING_KEYS.WITHDRAW_COMPLETE
: inProgressStatusString;
@@ -110,12 +108,12 @@ export const TransferStatusNotification = ({
slotIcon={isToast && slotIcon}
slotTitle={slotTitle}
slotCustomContent={
!status && !isExchange ? (
!status ? (
<LoadingDots size={3} />
) : (
<Styled.BridgingStatus>
{content}
{!isToast && !isComplete && !hasError && (
{!isToast && status?.squidTransactionStatus !== 'success' && !hasError && (
<Styled.TransferStatusSteps status={status} type={type} />
)}
</Styled.BridgingStatus>