Compare commits

..
Author SHA1 Message Date
Bill He 73eb7aff96 remove wc1 2023-10-12 15:22:42 -07:00
Bill He 6a3c4ec7f6 remove .env 2023-10-12 15:17:56 -07:00
Bill He 47b6618299 gitignore .env 2023-10-12 15:16:11 -07:00
Bill He def44ad66e remove WC 1 2023-10-12 15:07:49 -07:00
Bill He a6eb90952a Hide wallet options 2023-10-12 09:33:35 -07:00
46 changed files with 786 additions and 1166 deletions
+1 -1
View File
@@ -40,7 +40,7 @@
"@cosmjs/tendermint-rpc": "^0.31.0", "@cosmjs/tendermint-rpc": "^0.31.0",
"@dydxprotocol/v4-abacus": "^0.6.4", "@dydxprotocol/v4-abacus": "^0.6.4",
"@dydxprotocol/v4-client-js": "^0.36.1", "@dydxprotocol/v4-client-js": "^0.36.1",
"@dydxprotocol/v4-localization": "^0.1.30", "@dydxprotocol/v4-localization": "^0.1.24",
"@ethersproject/providers": "^5.7.2", "@ethersproject/providers": "^5.7.2",
"@js-joda/core": "^5.5.3", "@js-joda/core": "^5.5.3",
"@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-collapsible": "^1.0.3",
+4 -4
View File
@@ -33,8 +33,8 @@ dependencies:
specifier: ^0.36.1 specifier: ^0.36.1
version: 0.36.1 version: 0.36.1
'@dydxprotocol/v4-localization': '@dydxprotocol/v4-localization':
specifier: ^0.1.30 specifier: ^0.1.24
version: 0.1.30 version: 0.1.24
'@ethersproject/providers': '@ethersproject/providers':
specifier: ^5.7.2 specifier: ^5.7.2
version: 5.7.2 version: 5.7.2
@@ -1010,8 +1010,8 @@ packages:
- utf-8-validate - utf-8-validate
dev: false dev: false
/@dydxprotocol/v4-localization@0.1.30: /@dydxprotocol/v4-localization@0.1.24:
resolution: {integrity: sha512-xTlQuQmPz7wfGkjd07giYMAxRrolDbJE3DryJSIMB6R1MBq1wLzAcwp/iR/nELRwilRX9c44Tap0gGt+oAajiQ==} resolution: {integrity: sha512-zSiu8+/6BWNWZXxe73zUp/UjuLG1Cp5UuhXKtbATqqkeZyVCs01QxbBCTs1MLfgsLh02IrfhXCPHvXnzZyReEw==}
dev: false dev: false
/@dydxprotocol/v4-proto@0.2.1: /@dydxprotocol/v4-proto@0.2.1:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 193 KiB

+65 -78
View File
@@ -35,21 +35,17 @@
"name": "v4 Dev", "name": "v4 Dev",
"ethereumChainId": "5", "ethereumChainId": "5",
"dydxChainId": "dydxprotocol-testnet", "dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -79,6 +75,9 @@
"description": "dYdX v4 App", "description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png" "iconUrl": "/logos/dydx-x.png"
}, },
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": { "v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e" "projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
} }
@@ -95,21 +94,17 @@
"name": "v4 Dev 2", "name": "v4 Dev 2",
"ethereumChainId": "5", "ethereumChainId": "5",
"dydxChainId": "dydxprotocol-testnet", "dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -138,6 +133,9 @@
"description": "dYdX v4 App", "description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png" "iconUrl": "/logos/dydx-x.png"
}, },
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": { "v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e" "projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
} }
@@ -154,21 +152,17 @@
"name": "v4 Dev 4", "name": "v4 Dev 4",
"ethereumChainId": "5", "ethereumChainId": "5",
"dydxChainId": "dydxprotocol-testnet", "dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -197,6 +191,9 @@
"description": "dYdX v4 App", "description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png" "iconUrl": "/logos/dydx-x.png"
}, },
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": { "v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e" "projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
} }
@@ -213,21 +210,17 @@
"name": "v4 Dev 5", "name": "v4 Dev 5",
"ethereumChainId": "5", "ethereumChainId": "5",
"dydxChainId": "dydxprotocol-testnet", "dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -256,6 +249,9 @@
"description": "dYdX v4 App", "description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png" "iconUrl": "/logos/dydx-x.png"
}, },
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": { "v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e" "projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
} }
@@ -272,21 +268,17 @@
"name": "v4 Staging", "name": "v4 Staging",
"ethereumChainId": "5", "ethereumChainId": "5",
"dydxChainId": "dydxprotocol-testnet", "dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -319,6 +311,9 @@
"description": "dYdX v4 App", "description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png" "iconUrl": "/logos/dydx-x.png"
}, },
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": { "v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e" "projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
} }
@@ -335,21 +330,17 @@
"name": "v4 Staging West", "name": "v4 Staging West",
"ethereumChainId": "5", "ethereumChainId": "5",
"dydxChainId": "dydxprotocol-testnet", "dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -382,6 +373,9 @@
"description": "dYdX v4 App", "description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png" "iconUrl": "/logos/dydx-x.png"
}, },
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": { "v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e" "projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
} }
@@ -397,22 +391,18 @@
"dydxprotocol-testnet": { "dydxprotocol-testnet": {
"name": "v4 Public Testnet", "name": "v4 Public Testnet",
"ethereumChainId": "5", "ethereumChainId": "5",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-3",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -447,6 +437,9 @@
"description": "dYdX v4 App", "description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png" "iconUrl": "/logos/dydx-x.png"
}, },
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": { "v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e" "projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
} }
@@ -455,29 +448,25 @@
"callbackUrl": "/walletsegue" "callbackUrl": "/walletsegue"
}, },
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX V4 Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
} }
}, },
"dydxprotocol-testnet-dydx": { "dydxprotocol-testnet-dydx": {
"name": "v4 Public Testnet/dYdX", "name": "v4 Public Testnet/dYdX",
"ethereumChainId": "5", "ethereumChainId": "5",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-3",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -511,6 +500,9 @@
"description": "dYdX v4 App", "description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png" "iconUrl": "/logos/dydx-x.png"
}, },
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": { "v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e" "projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
} }
@@ -519,29 +511,25 @@
"callbackUrl": "/walletsegue" "callbackUrl": "/walletsegue"
}, },
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX V4 Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
} }
}, },
"dydxprotocol-testnet-dsrv": { "dydxprotocol-testnet-dsrv": {
"name": "v4 Public Testnet/DSRV", "name": "v4 Public Testnet/DSRV",
"ethereumChainId": "5", "ethereumChainId": "5",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-3",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -575,6 +563,9 @@
"description": "dYdX v4 App", "description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png" "iconUrl": "/logos/dydx-x.png"
}, },
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": { "v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e" "projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
} }
@@ -583,29 +574,25 @@
"callbackUrl": "/walletsegue" "callbackUrl": "/walletsegue"
}, },
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX V4 Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
} }
}, },
"dydxprotocol-testnet-nodefleet": { "dydxprotocol-testnet-nodefleet": {
"name": "v4 Public Testnet/nodefleet", "name": "v4 Public Testnet/nodefleet",
"ethereumChainId": "5", "ethereumChainId": "5",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-3",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -639,6 +626,9 @@
"description": "dYdX v4 App", "description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png" "iconUrl": "/logos/dydx-x.png"
}, },
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": { "v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e" "projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
} }
@@ -647,29 +637,25 @@
"callbackUrl": "/walletsegue" "callbackUrl": "/walletsegue"
}, },
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX V4 Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
} }
}, },
"dydxprotocol-testnet-kingnodes": { "dydxprotocol-testnet-kingnodes": {
"name": "v4 Public Testnet/KingNodes", "name": "v4 Public Testnet/KingNodes",
"ethereumChainId": "5", "ethereumChainId": "5",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-3",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -703,6 +689,9 @@
"description": "dYdX v4 App", "description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png" "iconUrl": "/logos/dydx-x.png"
}, },
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": { "v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e" "projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
} }
@@ -711,29 +700,25 @@
"callbackUrl": "/walletsegue" "callbackUrl": "/walletsegue"
}, },
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX V4 Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
} }
}, },
"dydxprotocol-testnet-liquify": { "dydxprotocol-testnet-liquify": {
"name": "v4 Public Testnet/Liquify", "name": "v4 Public Testnet/Liquify",
"ethereumChainId": "5", "ethereumChainId": "5",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-3",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -767,6 +752,9 @@
"description": "dYdX v4 App", "description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png" "iconUrl": "/logos/dydx-x.png"
}, },
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": { "v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e" "projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
} }
@@ -775,30 +763,26 @@
"callbackUrl": "/walletsegue" "callbackUrl": "/walletsegue"
}, },
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX V4 Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
} }
}, },
"dydxprotocol-mainnet": { "dydxprotocol-mainet": {
"name": "v4", "name": "v4",
"ethereumChainId": "1", "ethereumChainId": "1",
"dydxChainId": "[mainnet chain id]", "dydxChainId": "[mainnet chain id]",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": true, "isMainNet": true,
"tokens": { "tokens": {
"comment": "Change according to mainnet release", "comment": "Change according to mainnet release",
"chain": { "chain": {
"name": "DYDX", "name": "DYDX",
"denom": "adv4tnt", "denom": "dv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png" "image": "/currencies/dydx.png"
}, },
"usdc": { "usdc": {
"name": "USDC", "name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5", "denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc", "gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png" "image": "/currencies/usdc.png"
} }
}, },
@@ -831,6 +815,9 @@
"description": "[Description of the app]", "description": "[Description of the app]",
"iconUrl": "[Relative URL of the icon URL]" "iconUrl": "[Relative URL of the icon URL]"
}, },
"v1": {
"bridgeUrl": "[Bridge URL]"
},
"v2": { "v2": {
"projectId": "[Project ID]" "projectId": "[Project ID]"
} }
+448 -438
View File
@@ -1,464 +1,474 @@
[ [
{ {
"id": "c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96", "id":"c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96",
"name": "MetaMask", "name":"MetaMask",
"description": "", "description":"",
"homepage": "https://metamask.io/", "homepage":"https://metamask.io/",
"chains": [ "chains":[
"eip155:1", "eip155:1",
"eip155:42161", "eip155:42161",
"eip155:43114" "eip155:43114"
], ],
"versions": [ "versions":[
"1" "1"
], ],
"app": { "app":{
"browser": "", "browser":"",
"ios": "https://apps.apple.com/us/app/metamask/id1438144202", "ios":"https://apps.apple.com/us/app/metamask/id1438144202",
"android": "https://play.google.com/store/apps/details?id=io.metamask", "android":"https://play.google.com/store/apps/details?id=io.metamask",
"mac": "", "mac":"",
"windows": "", "windows":"",
"linux": "" "linux":""
}, },
"mobile": { "mobile":{
"native": "metamask:", "native":"metamask:",
"universal": "https://metamask.app.link" "universal":"https://metamask.app.link"
}, },
"desktop": { "desktop":{
"native": "", "native":"",
"universal": "" "universal":""
}, },
"metadata": { "metadata":{
"shortName": "MetaMask", "shortName":"MetaMask",
"colors": { "colors":{
"primary": "rgb(255, 255, 255)", "primary":"rgb(255, 255, 255)",
"secondary": "" "secondary":""
}
},
"config": {
"comment": "MetaMask",
"iosMinVersion": "0",
"imageUrl": "",
"encoding": "=\"#%/<>?@\\^`{|}:&",
"connections": [
{
"type": "walletConnectV2",
"native": "metamask:",
"universal": "https://metamask.app.link"
} }
], },
"methods": [ "config":{
"eth_sendTransaction", "comment":"MetaMask",
"personal_sign", "iosMinVersion":"0",
"eth_signTypedData", "imageUrl":"https://v4.testnet.dydx.exchange/wallets/metamask.png",
"wallet_addEthereumChain" "image":"metamask.png",
] "encoding":"=\"#%/<>?@\\^`{|}:&",
}, "connections":[
"userFields": { {
"analyticEvent": "METAMASK", "type":"walletConnectV2",
"imageName": "metamask.png" "native":"metamask:",
} "universal":"https://metamask.app.link"
}
]
},
"userFields":{
"analyticEvent":"METAMASK"
}
}, },
{ {
"id": "coinbase-wallet", "id":"coinbase-wallet",
"name": "Coinbase Wallet", "name":"Coinbase Wallet",
"description": "", "description":"",
"homepage": "https://www.coinbase.com/wallet", "homepage":"https://www.coinbase.com/wallet",
"chains": [ "chains":[
"eip155:1" "eip155:1"
], ],
"versions": [ "versions":[
"1" "1"
], ],
"app": { "app":{
"browser": "", "browser":"",
"ios": "https://apps.apple.com/us/app/coinbase-wallet-nfts-crypto/id1278383455", "ios":"https://apps.apple.com/us/app/coinbase-wallet-nfts-crypto/id1278383455",
"android": "https://play.google.com/store/apps/details?id=org.toshi", "android":"https://play.google.com/store/apps/details?id=org.toshi",
"mac": "", "mac":"",
"windows": "", "windows":"",
"linux": "" "linux":""
}, },
"mobile": { "mobile":{
"native": "cbwallet:", "native":"cbwallet:",
"universal": "" "universal":""
}, },
"desktop": { "desktop":{
"native": "", "native":"",
"universal": "" "universal":""
}, },
"metadata": { "metadata":{
"shortName": "Coinbase", "shortName":"Coinbase",
"colors": { "colors":{
"primary": "rgb(255, 255, 255)", "primary":"rgb(255, 255, 255)",
"secondary": "" "secondary":""
}
},
"config": {
"comment": "Coinbase",
"iosMinVersion": "1.8.0",
"imageUrl": "",
"encoding": "=\"#%/<>?@\\^`{|}:&",
"connections": [
{
"type": "walletSegue",
"native": "cbwallet:",
"universal": ""
} }
], },
"methods": [ "config":{
"eth_sendTransaction", "comment":"Coinbase",
"personal_sign", "iosMinVersion":"1.8.0",
"eth_signTypedData", "imageUrl":"https://v4.testnet.dydx.exchange/wallets/coinbase-wallet.png",
"wallet_addEthereumChain" "image":"coinbase-wallet.png",
] "encoding":"=\"#%/<>?@\\^`{|}:&",
}, "connections":[
"userFields": { {
"analyticEvent": "COINBASE_WALLET", "type":"walletSegue",
"imageName": "coinbase-wallet.png" "native":"cbwallet:",
} "universal":""
}
]
},
"userFields":{
"analyticEvent":"COINBASE_WALLET"
}
}, },
{ {
"id": "9d373b43ad4d2cf190fb1a774ec964a1addf406d6fd24af94ab7596e58c291b2", "id":"9d373b43ad4d2cf190fb1a774ec964a1addf406d6fd24af94ab7596e58c291b2",
"name": "imToken", "name":"imToken",
"description": "", "description":"",
"homepage": "https://token.im/", "homepage":"https://token.im/",
"chains": [ "chains":[
"eip155:1" "eip155:1"
], ],
"versions": [ "versions":[
"1" "1"
], ],
"app": { "app":{
"browser": "", "browser":"",
"ios": "https://itunes.apple.com/us/app/imtoken2/id1384798940", "ios":"https://itunes.apple.com/us/app/imtoken2/id1384798940",
"android": "https://play.google.com/store/apps/details?id=im.token.app", "android":"https://play.google.com/store/apps/details?id=im.token.app",
"mac": "", "mac":"",
"windows": "", "windows":"",
"linux": "" "linux":""
}, },
"mobile": { "mobile":{
"native": "imtokenv2:", "native":"imtokenv2:",
"universal": "" "universal":""
}, },
"desktop": { "desktop":{
"native": "", "native":"",
"universal": "" "universal":""
}, },
"metadata": { "metadata":{
"shortName": "imToken", "shortName":"imToken",
"colors": { "colors":{
"primary": "rgb(255, 255, 255)", "primary":"rgb(255, 255, 255)",
"secondary": "" "secondary":""
}
},
"config": {
"comment": "imToken",
"iosMinVersion": "0",
"imageUrl": "",
"connections": [
{
"type": "walletConnectV2",
"native": "imtokenv2:",
"universal": ""
} }
], },
"methods": [ "config":{
"eth_sendTransaction", "comment":"imToken",
"personal_sign", "iosMinVersion":"0",
"eth_signTypedData" "imageUrl":"https://v4.testnet.dydx.exchange/wallets/imtoken.png",
] "image":"imtoken.png",
}, "connections":[
"userFields": { {
"analyticEvent": "IMTOKEN", "type":"walletConnect",
"imageName": "imtoken.png" "native":"imtokenv2:",
} "universal":""
}
]
},
"userFields":{
"analyticEvent":"IMTOKEN"
}
}, },
{ {
"id": "4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0", "id":"4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0",
"name": "Trust Wallet", "name":"Trust Wallet",
"description": "", "description":"",
"homepage": "https://trustwallet.com/", "homepage":"https://trustwallet.com/",
"chains": [ "chains":[
"eip155:1", "eip155:1",
"eip155:42161", "eip155:42161",
"eip155:43114" "eip155:43114"
], ],
"versions": [ "versions":[
"1" "1"
], ],
"app": { "app":{
"browser": "", "browser":"",
"ios": "https://apps.apple.com/app/apple-store/id1288339409", "ios":"https://apps.apple.com/app/apple-store/id1288339409",
"android": "https://play.google.com/store/apps/details?id=com.wallet.crypto.trustapp", "android":"https://play.google.com/store/apps/details?id=com.wallet.crypto.trustapp",
"mac": "", "mac":"",
"windows": "", "windows":"",
"linux": "" "linux":""
}, },
"mobile": { "mobile":{
"native": "trust:", "native":"trust:",
"universal": "https://link.trustwallet.com" "universal":"https://link.trustwallet.com"
}, },
"desktop": { "desktop":{
"native": "", "native":"",
"universal": "" "universal":""
}, },
"metadata": { "metadata":{
"shortName": "Trust", "shortName":"Trust",
"colors": { "colors":{
"primary": "rgb(51, 117, 187)", "primary":"rgb(51, 117, 187)",
"secondary": "" "secondary":""
}
},
"config": {
"comment": "Trust Wallet",
"iosMinVersion": "0",
"encoding": "=\"#%/<>?@\\^`{|}:&",
"imageUrl": "",
"connections": [
{
"type": "walletConnectV2",
"native": "trust:",
"universal": "https://link.trustwallet.com"
} }
], },
"methods": [ "config":{
"eth_sendTransaction", "comment":"Trust Wallet",
"personal_sign", "iosMinVersion":"0",
"eth_signTypedData" "encoding":"=\"#%/<>?@\\^`{|}:&",
] "imageUrl":"https://v4.testnet.dydx.exchange/wallets/trust-wallet.png",
}, "image":"trust-wallet.png",
"userFields": { "connections":[
"analyticEvent": "TRUST_WALLET", {
"imageName": "trust-wallet.png" "type":"walletConnectV2",
} "native":"trust:",
"universal":"https://link.trustwallet.com"
}
]
},
"userFields":{
"analyticEvent":"TRUST_WALLET"
}
}, },
{ {
"id": "Zerion", "id":"Zerion",
"name": "Zerion", "name":"Zerion",
"description": "", "description":"",
"homepage": "https://zerion.io/", "homepage":"https://zerion.io/",
"chains": [ "chains":[
"eip155:1" "eip155:1"
], ],
"versions": [ "versions":[
"1" "1"
], ],
"app": { "app":{
"browser": "", "browser":"",
"ios": "https://apps.apple.com/app/apple-store/id1456732565", "ios":"https://apps.apple.com/app/apple-store/id1456732565",
"android": "https://play.google.com/store/apps/details?id=io.zerion.android", "android":"https://play.google.com/store/apps/details?id=io.zerion.android",
"mac": "", "mac":"",
"windows": "", "windows":"",
"linux": "" "linux":""
}, },
"mobile": { "mobile":{
"native": "zerion:", "native":"zerion:",
"universal": "" "universal":""
}, },
"desktop": { "desktop":{
"native": "", "native":"",
"universal": "" "universal":""
}, },
"metadata": { "metadata":{
"shortName": "Zerion", "shortName":"Zerion",
"colors": { "colors":{
"primary": "rgb(51, 117, 187)", "primary":"rgb(51, 117, 187)",
"secondary": "" "secondary":""
}
},
"config": {
"comment": "Zerion Wallet",
"iosMinVersion": "0",
"encoding": "=\"#%/<>?@\\^`{|}:&",
"imageUrl": "",
"connections": [
{
"type": "walletConnectV2",
"native": "zerion:",
"universal": ""
} }
], },
"methods": [ "config":{
"eth_sendTransaction", "comment":"Zerion Wallet",
"personal_sign", "iosMinVersion":"0",
"eth_signTypedData" "encoding":"=\"#%/<>?@\\^`{|}:&",
] "imageUrl":"https://v4.testnet.dydx.exchange/wallets/zerion.png",
}, "image":"zerion.png",
"userFields": { "connections":[
"analyticEvent": "ZERION", {
"imageName": "zerion.png" "type":"walletConnectV2",
} "native":"zerion:",
"universal":""
}
]
},
"userFields":{
"analyticEvent":"ZERION"
}
}, },
{ {
"id": "20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66", "id":"20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66",
"name": "TokenPocket", "name":"TokenPocket",
"description": "", "description":"",
"homepage": "https://tokenpocket.pro/", "homepage":"https://tokenpocket.pro/",
"chains": [ "chains":[
"eip155:1" "eip155:1"
], ],
"versions": [ "versions":[
"1" "1"
], ],
"app": { "app":{
"browser": "", "browser":"",
"ios": "https://apps.apple.com/us/app/tokenpocket-trusted-wallet/id1436028697", "ios":"https://apps.apple.com/us/app/tokenpocket-trusted-wallet/id1436028697",
"android": "https://play.google.com/store/apps/details?id=vip.mytokenpocket", "android":"https://play.google.com/store/apps/details?id=vip.mytokenpocket",
"mac": "", "mac":"",
"windows": "", "windows":"",
"linux": "" "linux":""
}, },
"mobile": { "mobile":{
"native": "tpoutside:", "native":"tpoutside:",
"universal": "" "universal":""
}, },
"desktop": { "desktop":{
"native": "", "native":"",
"universal": "" "universal":""
}, },
"metadata": { "metadata":{
"shortName": "TokenPocket", "shortName":"TokenPocket",
"colors": { "colors":{
"primary": "rgb(41, 128, 254)", "primary":"rgb(41, 128, 254)",
"secondary": "" "secondary":""
}
},
"config": {
"comment": "TokenPocket",
"iosMinVersion": "0",
"imageUrl": "",
"connections": [
{
"type": "walletConnectV2",
"native": "tpoutside:",
"universal": ""
} }
], },
"methods": [ "config":{
"eth_sendTransaction", "comment":"TokenPocket",
"personal_sign", "iosMinVersion":"0",
"eth_signTypedData" "imageUrl":"https://v4.testnet.dydx.exchange/wallets/tokenpocket.png",
] "image":"tokenpocket.png",
}, "connections":[
"userFields": { {
"analyticEvent": "TOKEN_POCKET", "type":"walletConnect",
"imageName": "tokenpocket.png" "native":"tpoutside:",
} "universal":""
}
]
},
"userFields":{
"analyticEvent":"TOKEN_POCKET"
}
}, },
{ {
"id": "1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369", "id":"1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369",
"name": "Rainbow", "name":"Rainbow",
"description": "", "description":"",
"homepage": "https://rainbow.me/", "homepage":"https://rainbow.me/",
"chains": [ "chains":[
"eip155:1" "eip155:1"
], ],
"versions": [ "versions":[
"1" "1"
], ],
"app": { "app":{
"browser": "", "browser":"",
"ios": "https://apps.apple.com/us/app/rainbow-ethereum-wallet/id1457119021", "ios":"https://apps.apple.com/us/app/rainbow-ethereum-wallet/id1457119021",
"android": "", "android":"",
"mac": "", "mac":"",
"windows": "", "windows":"",
"linux": "" "linux":""
}, },
"mobile": { "mobile":{
"native": "rainbow:", "native":"rainbow:",
"universal": "https://rnbwapp.com" "universal":"https://rnbwapp.com"
}, },
"desktop": { "desktop":{
"native": "", "native":"",
"universal": "" "universal":""
}, },
"metadata": { "metadata":{
"shortName": "Rainbow", "shortName":"Rainbow",
"colors": { "colors":{
"primary": "rgb(0, 30, 89)", "primary":"rgb(0, 30, 89)",
"secondary": "" "secondary":""
}
},
"config": {
"comment": "Rainbow",
"iosMinVersion": "0",
"encoding": "=\"#%/<>?@\\^`{|}:&",
"backlinked": true,
"imageUrl": "",
"connections": [
{
"type": "walletConnectV2",
"native": "rainbow:",
"universal": "https://rnbwapp.com"
} }
], },
"methods": [ "config":{
"eth_sendTransaction", "comment":"Rainbow",
"personal_sign", "iosMinVersion":"0",
"eth_signTypedData" "encoding":"=\"#%/<>?@\\^`{|}:&",
] "backlinked":true,
}, "imageUrl":"https://v4.testnet.dydx.exchange/wallets/rainbow-wallet.png",
"userFields": { "image":"rainbow-wallet.png",
"analyticEvent": "RAINBOW_WALLET", "connections":[
"imageName": "rainbow-wallet.png" {
} "type":"walletConnectV2",
"native":"rainbow:",
"universal":"https://rnbwapp.com"
}
]
},
"userFields":{
"analyticEvent":"RAINBOW_WALLET"
}
}, },
{ {
"id": "09102e7bbbd3f92001eda104abe23803181629f695e8f1b95af96d88ff7d5890", "id":"09102e7bbbd3f92001eda104abe23803181629f695e8f1b95af96d88ff7d5890",
"name": "1inch Wallet", "name":"1inch Wallet",
"description": "", "description":"",
"homepage": "https://1inch.io/wallet/", "homepage":"https://1inch.io/wallet/",
"chains": [ "chains":[
"eip155:1", "eip155:1",
"eip155:56" "eip155:56"
], ],
"versions": [ "versions":[
"1" "1"
], ],
"app": { "app":{
"browser": "", "browser":"",
"ios": "https://apps.apple.com/us/app/1inch-defi-wallet/id1546049391", "ios":"https://apps.apple.com/us/app/1inch-defi-wallet/id1546049391",
"android": "", "android":"",
"mac": "", "mac":"",
"windows": "", "windows":"",
"linux": "" "linux":""
}, },
"mobile": { "mobile":{
"native": "oneinch:", "native":"oneinch:",
"universal": "https://wallet.1inch.io" "universal":"https://wallet.1inch.io"
}, },
"desktop": { "desktop":{
"native": "", "native":"",
"universal": "" "universal":""
}, },
"metadata": { "metadata":{
"shortName": "1inch", "shortName":"1inch",
"colors": { "colors":{
"primary": "rgb(31, 36, 46)", "primary":"rgb(31, 36, 46)",
"secondary": "" "secondary":""
}
},
"config": {
"comment": "1inch",
"iosMinVersion": "0",
"encoding": "=\"#%/<>?@\\^`{|}:&",
"imageUrl": "",
"connections": [
{
"type": "walletConnectV2",
"native": "oneinch:",
"universal": "https://wallet.1inch.io"
} }
], },
"methods": [ "config":{
"eth_sendTransaction", "comment":"1inch",
"personal_sign", "iosMinVersion":"0",
"eth_signTypedData" "encoding":"=\"#%/<>?@\\^`{|}:&",
] "imageUrl":"https://v4.testnet.dydx.exchange/wallets/1inch.png",
}, "image":"1inch.png",
"userFields": { "connections":[
"analyticEvent": "1INCH", {
"imageName": "1inch.png" "type":"walletConnect",
} "native":"oneinch:",
"universal":"https://wallet.1inch.io"
}
]
},
"userFields":{
"analyticEvent":"1INCH"
}
},
{
"id":"bae74827272509a6d63ea25514d9c68ad235c14e45e183518c7ded4572a1b0c4",
"name":"Huobi Wallet",
"description":"",
"homepage":"https://huobiwallet.com/",
"chains":[
"eip155:1"
],
"versions":[
"1"
],
"app":{
"browser":"",
"ios":"https://apps.apple.com/us/app/id1433883012",
"android":"https://play.google.com/store/apps/details?id=com.huobionchainwallet.gp",
"mac":"",
"windows":"",
"linux":""
},
"mobile":{
"native":"huobiwallet:",
"universal":""
},
"desktop":{
"native":"",
"universal":""
},
"metadata":{
"shortName":"Huobi",
"colors":{
"primary":"rgb(45,101,248)",
"secondary":""
}
},
"config":{
"comment":"Huobi",
"iosMinVersion":"0",
"encoding":"=\"#%/<>?@\\^`{|}:&",
"imageUrl":"https://v4.testnet.dydx.exchange/wallets/huobi-wallet.png",
"image":"huobi-wallet.png",
"connections":[
{
"type":"walletConnect",
"native":"huobiwallet:",
"universal":""
}
]
},
"userFields":{
"analyticEvent":"HUOBI_WALLET"
}
} }
] ]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

-4
View File
@@ -14,7 +14,6 @@ import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
import { LocaleProvider } from '@/hooks/useLocaleSeparators'; import { LocaleProvider } from '@/hooks/useLocaleSeparators';
import { NotificationsProvider } from '@/hooks/useNotifications'; import { NotificationsProvider } from '@/hooks/useNotifications';
import { LocalNotificationsProvider } from '@/hooks/useLocalNotifications'; import { LocalNotificationsProvider } from '@/hooks/useLocalNotifications';
import { RestrictionProvider } from '@/hooks/useRestrictions';
import { SubaccountProvider } from '@/hooks/useSubaccount'; import { SubaccountProvider } from '@/hooks/useSubaccount';
import { SquidProvider } from '@/hooks/useSquid'; import { SquidProvider } from '@/hooks/useSquid';
@@ -67,7 +66,6 @@ const Content = () => {
<Route path=":market" element={<TradePage />} /> <Route path=":market" element={<TradePage />} />
<Route path={AppRoute.Trade} element={<TradePage />} /> <Route path={AppRoute.Trade} element={<TradePage />} />
</Route> </Route>
<Route path={AppRoute.Markets} element={<MarketsPage />} /> <Route path={AppRoute.Markets} element={<MarketsPage />} />
<Route path={AppRoute.Rewards} element={<RewardsPage />} /> <Route path={AppRoute.Rewards} element={<RewardsPage />} />
{isTablet && ( {isTablet && (
@@ -81,7 +79,6 @@ const Content = () => {
<Route element={<GuardedMobileRoute />}> <Route element={<GuardedMobileRoute />}>
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} /> <Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
</Route> </Route>
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} /> <Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
</Routes> </Routes>
</Suspense> </Suspense>
@@ -112,7 +109,6 @@ const providers = [
wrapProvider(GrazProvider), wrapProvider(GrazProvider),
wrapProvider(WagmiConfig, { config }), wrapProvider(WagmiConfig, { config }),
wrapProvider(LocaleProvider), wrapProvider(LocaleProvider),
wrapProvider(RestrictionProvider),
wrapProvider(DydxProvider), wrapProvider(DydxProvider),
wrapProvider(AccountsProvider), wrapProvider(AccountsProvider),
wrapProvider(SubaccountProvider), wrapProvider(SubaccountProvider),
-10
View File
@@ -207,16 +207,6 @@ const InputStyle = css`
color: var(--color-text-0); color: var(--color-text-0);
opacity: 1; opacity: 1;
} }
// Input autofill Styles
&:-webkit-autofill,
&:-webkit-autofill:focus {
transition: background-color 600000s 0s, color 600000s 0s;
}
&[data-autocompleted] {
background-color: var(--input-backgroundColor) !important;
}
`; `;
Styled.NumericFormat = styled(NumericFormat)` Styled.NumericFormat = styled(NumericFormat)`
-11
View File
@@ -78,13 +78,8 @@ export const Changes = Abacus.exchange.dydx.abacus.state.changes.Changes;
export type PerpetualStateChanges = Abacus.exchange.dydx.abacus.state.changes.StateChanges; export type PerpetualStateChanges = Abacus.exchange.dydx.abacus.state.changes.StateChanges;
export const AsyncAbacusStateManager = export const AsyncAbacusStateManager =
Abacus.exchange.dydx.abacus.state.manager.AsyncAbacusStateManager; Abacus.exchange.dydx.abacus.state.manager.AsyncAbacusStateManager;
// ------ Parsing Errors ------ //
export type ParsingError = Abacus.exchange.dydx.abacus.responses.ParsingError; export type ParsingError = Abacus.exchange.dydx.abacus.responses.ParsingError;
export type ParsingErrors = kollections.List<ParsingError>; export type ParsingErrors = kollections.List<ParsingError>;
export const ParsingErrorType = Abacus.exchange.dydx.abacus.responses.ParsingErrorType;
const parsingErrorTypes = [...ParsingErrorType.values()] as const;
export type ParsingErrorTypes = (typeof parsingErrorTypes)[number];
// ------ Perpetuals/Markets ------ // // ------ Perpetuals/Markets ------ //
export type PerpetualState = Abacus.exchange.dydx.abacus.output.PerpetualState; export type PerpetualState = Abacus.exchange.dydx.abacus.output.PerpetualState;
@@ -204,12 +199,6 @@ export type RiskLevels = (typeof riskLevels)[number];
// ------ Notifications ------ // // ------ Notifications ------ //
export type AbacusNotification = Abacus.exchange.dydx.abacus.output.Notification; export type AbacusNotification = Abacus.exchange.dydx.abacus.output.Notification;
// ------ Restrictions ------ //
export type UsageRestriction = Abacus.exchange.dydx.abacus.output.UsageRestriction;
export const RestrictionType = Abacus.exchange.dydx.abacus.output.Restriction;
const restrictionTypes = [...RestrictionType.values()] as const;
export type RestrictionTypes = (typeof restrictionTypes)[number];
// ------ Enum Conversions ------ // // ------ Enum Conversions ------ //
type IfEquals<X, Y, A, B> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 type IfEquals<X, Y, A, B> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2
? A ? A
-3
View File
@@ -10,10 +10,7 @@ export enum DialogTypes {
MobileSignIn = 'MobileSignIn', MobileSignIn = 'MobileSignIn',
Onboarding = 'Onboarding', Onboarding = 'Onboarding',
OrderDetails = 'OrderDetails', OrderDetails = 'OrderDetails',
RateLimit = 'RateLimit',
Receive = 'Receive', Receive = 'Receive',
RestrictedGeo = 'RestrictedGeo',
RestrictedWallet = 'RestrictedWallet',
Trade = 'Trade', Trade = 'Trade',
Transfer = 'Transfer', Transfer = 'Transfer',
Withdraw = 'Withdraw', Withdraw = 'Withdraw',
+1 -1
View File
@@ -24,6 +24,6 @@ export enum LocalStorageKey {
} }
export const LOCAL_STORAGE_VERSIONS = { export const LOCAL_STORAGE_VERSIONS = {
[LocalStorageKey.EvmDerivedAddresses]: 'v2', [LocalStorageKey.EvmDerivedAddresses]: 'v1',
// TODO: version all localStorage keys // TODO: version all localStorage keys
}; };
+16 -36
View File
@@ -92,24 +92,6 @@ export enum WalletType {
OtherWallet = 'OTHER_WALLET', OtherWallet = 'OTHER_WALLET',
} }
const WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS = {
Metamask: 'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96',
imToken: 'ef333840daf915aafdc4a004525502d6d49d77bd9c65e0642dbaefb3c2893bef',
TokenPocket: '20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66',
Trust: '4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0',
Rainbow: '1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369',
Zerion: 'ecc4036f814562b41a5268adc86270fba1365471402006302e70169465b7ac18',
Ledger: '19177a98252e07ddfc9af2083ba8e07ef627cb6103467ffebb3f8f4205fd7927',
Fireblocks: '5864e2ced7c293ed18ac35e0db085c09ed567d67346ccb6f58a0327a75137489',
Uniswap: 'c03dfee351b6fcc421b4494ea33b9d4b92a984f87aa76d1663bb28705e95034a',
Robinhood: '8837dd9413b1d9b585ee937d27a816590248386d9dbf59f5cd3422dbbb65683e',
'1inch': 'c286eebc742a537cd1d6818363e9dc53b21759a1e8e5d9b263d0c03ec7703576',
};
export const WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS = Object.values(
WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS
);
type WalletConfig = { type WalletConfig = {
type: WalletType; type: WalletType;
stringKey: string; stringKey: string;
@@ -143,6 +125,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: BitkeepIcon, icon: BitkeepIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2], connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isBitKeep, // isBitKeepChrome, isBitEthereum matchesInjectedEip1193: (provider) => provider.isBitKeep, // isBitKeepChrome, isBitEthereum
walletconnect2Id: '38f5d18bd8522c244bdd70cb4a68e0e718865155811c043f052fb9f1c51de662',
}, },
[WalletType.BitPie]: { [WalletType.BitPie]: {
type: WalletType.BitPie, type: WalletType.BitPie,
@@ -175,6 +158,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: Coin98Icon, icon: Coin98Icon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2], connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isCoin98, matchesInjectedEip1193: (provider) => provider.isCoin98,
walletconnect2Id: '2a3c89040ac3b723a1972a33a125b1db11e258a6975d3a61252cd64e6ea5ea01',
}, },
[WalletType.HuobiWallet]: { [WalletType.HuobiWallet]: {
type: WalletType.HuobiWallet, type: WalletType.HuobiWallet,
@@ -182,6 +166,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: HuobiIcon, icon: HuobiIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2], connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isHbWallet, matchesInjectedEip1193: (provider) => provider.isHbWallet,
walletconnect2Id: '797c615e2c556b610c048eb35535f212c0dd58de5d03e763120e90a7d1350a77',
}, },
[WalletType.ImToken]: { [WalletType.ImToken]: {
type: WalletType.ImToken, type: WalletType.ImToken,
@@ -189,7 +174,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: ImTokenIcon, icon: ImTokenIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2], connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isImToken, matchesInjectedEip1193: (provider) => provider.isImToken,
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.imToken, walletconnect2Id: 'ef333840daf915aafdc4a004525502d6d49d77bd9c65e0642dbaefb3c2893bef',
}, },
[WalletType.MathWallet]: { [WalletType.MathWallet]: {
type: WalletType.MathWallet, type: WalletType.MathWallet,
@@ -205,7 +190,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: MetaMaskIcon, icon: MetaMaskIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2], connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: isMetaMask, matchesInjectedEip1193: isMetaMask,
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.Metamask, walletconnect2Id: 'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96',
}, },
[WalletType.Rainbow]: { [WalletType.Rainbow]: {
type: WalletType.Rainbow, type: WalletType.Rainbow,
@@ -213,7 +198,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: RainbowIcon, icon: RainbowIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2], connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isRainbowWallet, matchesInjectedEip1193: (provider) => provider.isRainbowWallet,
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.Rainbow, walletconnect2Id: '1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369',
}, },
[WalletType.TokenPocket]: { [WalletType.TokenPocket]: {
type: WalletType.TokenPocket, type: WalletType.TokenPocket,
@@ -221,7 +206,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: TokenPocketIcon, icon: TokenPocketIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2], connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isTokenPocket, matchesInjectedEip1193: (provider) => provider.isTokenPocket,
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.TokenPocket, walletconnect2Id: '20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66',
}, },
[WalletType.TrustWallet]: { [WalletType.TrustWallet]: {
type: WalletType.TrustWallet, type: WalletType.TrustWallet,
@@ -229,7 +214,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: TrustWalletIcon, icon: TrustWalletIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2], connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isTrust, matchesInjectedEip1193: (provider) => provider.isTrust,
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.Trust, walletconnect2Id: '4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0',
}, },
[WalletType.WalletConnect2]: { [WalletType.WalletConnect2]: {
type: WalletType.WalletConnect2, type: WalletType.WalletConnect2,
@@ -302,10 +287,10 @@ export type DydxAddress = `dydx${string}`;
export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = { export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = {
rpc: 'https://dydx-testnet-archive.allthatnode.com:26657', rpc: 'https://dydx-testnet-archive.allthatnode.com:26657',
rest: 'https://dydx-testnet-archive.allthatnode.com:1317', rest: 'https://dydx-testnet-archive.allthatnode.com:1317',
chainId: 'dydx-testnet-4', chainId: 'dydx-testnet-3',
chainName: 'dYdX Public Testnet', chainName: 'dYdX Public Testnet',
chainSymbolImageUrl: chainSymbolImageUrl:
'https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/dydx-testnet-4/chain.png', 'https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/dydx-testnet-3/chain.png',
bech32Config: { bech32Config: {
bech32PrefixAccPub: 'dydxpub', bech32PrefixAccPub: 'dydxpub',
bech32PrefixValPub: 'dydxvaloperpub', bech32PrefixValPub: 'dydxvaloperpub',
@@ -319,31 +304,26 @@ export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = {
}, },
stakeCurrency: { stakeCurrency: {
coinDenom: 'DV4TNT', coinDenom: 'DV4TNT',
coinDecimals: 18, coinDecimals: 6,
coinMinimalDenom: 'adv4tnt', coinMinimalDenom: 'dv4tnt',
}, },
currencies: [ currencies: [
{ {
coinDenom: 'DV4TNT', coinDenom: 'DV4TNT',
coinDecimals: 18, coinDecimals: 6,
coinMinimalDenom: 'adv4tnt', coinMinimalDenom: 'dv4tnt',
}, },
{ {
coinDenom: 'USDC', coinDenom: 'USDC',
coinDecimals: 6,
coinMinimalDenom: 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5', coinMinimalDenom: 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5',
coinDecimals: 6,
}, },
], ],
feeCurrencies: [ feeCurrencies: [
{ {
coinDenom: 'DV4TNT', coinDenom: 'DV4TNT',
coinDecimals: 18,
coinMinimalDenom: 'adv4tnt',
},
{
coinDenom: 'USDC',
coinDecimals: 6, coinDecimals: 6,
coinMinimalDenom: 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5', coinMinimalDenom: 'dv4tnt',
}, },
], ],
features: [], features: [],
-2
View File
@@ -16,7 +16,6 @@ import { useLocalStorage } from './useLocalStorage';
import { useNow } from './useNow'; import { useNow } from './useNow';
import { useOnClickOutside } from './useOnClickOutside'; import { useOnClickOutside } from './useOnClickOutside';
import { usePageTitlePriceUpdates } from './usePageTitlePriceUpdates'; import { usePageTitlePriceUpdates } from './usePageTitlePriceUpdates';
import { useRestrictions } from './useRestrictions';
import { useShouldShowFooter } from './useShouldShowFooter'; import { useShouldShowFooter } from './useShouldShowFooter';
import { useSelectedNetwork } from './useSelectedNetwork'; import { useSelectedNetwork } from './useSelectedNetwork';
import { useStringGetter } from './useStringGetter'; import { useStringGetter } from './useStringGetter';
@@ -41,7 +40,6 @@ export {
useNow, useNow,
useOnClickOutside, useOnClickOutside,
usePageTitlePriceUpdates, usePageTitlePriceUpdates,
useRestrictions,
useShouldShowFooter, useShouldShowFooter,
useSelectedNetwork, useSelectedNetwork,
useStringGetter, useStringGetter,
+4 -22
View File
@@ -5,20 +5,18 @@ import { AES, enc } from 'crypto-js';
import { LocalWallet, USDC_DENOM, type Subaccount } from '@dydxprotocol/v4-client-js'; import { LocalWallet, USDC_DENOM, type Subaccount } from '@dydxprotocol/v4-client-js';
import { OnboardingGuard, OnboardingState, type EvmDerivedAddresses } from '@/constants/account'; import { OnboardingGuard, OnboardingState, type EvmDerivedAddresses } from '@/constants/account';
import { DialogTypes } from '@/constants/dialogs';
import { LocalStorageKey, LOCAL_STORAGE_VERSIONS } from '@/constants/localStorage'; import { LocalStorageKey, LOCAL_STORAGE_VERSIONS } from '@/constants/localStorage';
import { DydxAddress, EvmAddress, PrivateInformation } from '@/constants/wallets'; import { DydxAddress, EvmAddress, PrivateInformation } from '@/constants/wallets';
import { setOnboardingState, setOnboardingGuard } from '@/state/account'; import { setOnboardingState, setOnboardingGuard } from '@/state/account';
import { forceOpenDialog } from '@/state/dialogs';
import abacusStateManager from '@/lib/abacus'; import abacusStateManager from '@/lib/abacus';
import { log } from '@/lib/telemetry'; import { log } from '@/lib/telemetry';
import { useDydxClient } from './useDydxClient';
import { useLocalStorage } from './useLocalStorage'; import { useLocalStorage } from './useLocalStorage';
import { useRestrictions } from './useRestrictions';
import { useWalletConnection } from './useWalletConnection'; import { useWalletConnection } from './useWalletConnection';
import { useDydxClient } from './useDydxClient';
const AccountsContext = createContext<ReturnType<typeof useAccountsContext> | undefined>(undefined); const AccountsContext = createContext<ReturnType<typeof useAccountsContext> | undefined>(undefined);
@@ -59,9 +57,7 @@ const useAccountsContext = () => {
forgetEvmSignature(previousEvmAddress); forgetEvmSignature(previousEvmAddress);
} }
if (evmAddress) { if (evmAddress) abacusStateManager.setTransfersSourceAddress(evmAddress);
abacusStateManager.setTransfersSourceAddress(evmAddress);
}
setPreviousEvmAddress(evmAddress); setPreviousEvmAddress(evmAddress);
}, [evmAddress]); }, [evmAddress]);
@@ -221,6 +217,7 @@ const useAccountsContext = () => {
}, [evmAddress, evmDerivedAddresses, signerWagmi, connectedDydxAddress, signerGraz]); }, [evmAddress, evmDerivedAddresses, signerWagmi, connectedDydxAddress, signerGraz]);
// abacus // abacus
// TODO: useAbacus({ dydxAddress })
useEffect(() => { useEffect(() => {
if (dydxAddress) abacusStateManager.setAccount(localDydxWallet); if (dydxAddress) abacusStateManager.setAccount(localDydxWallet);
else abacusStateManager.attemptDisconnectAccount(); else abacusStateManager.attemptDisconnectAccount();
@@ -261,21 +258,6 @@ const useAccountsContext = () => {
); );
}, [dydxSubaccounts]); }, [dydxSubaccounts]);
// Restrictions
const { isBadActor, sanctionedAddresses } = useRestrictions();
useEffect(() => {
if (
dydxAddress &&
(isBadActor ||
sanctionedAddresses.has(dydxAddress) ||
(evmAddress && sanctionedAddresses.has(evmAddress)))
) {
dispatch(forceOpenDialog({ type: DialogTypes.RestrictedWallet }));
disconnect();
}
}, [isBadActor, evmAddress, dydxAddress, sanctionedAddresses]);
// Disconnect wallet / accounts // Disconnect wallet / accounts
const disconnectLocalDydxWallet = () => { const disconnectLocalDydxWallet = () => {
setLocalDydxWallet(undefined); setLocalDydxWallet(undefined);
+1 -25
View File
@@ -17,11 +17,8 @@ import type { NetworkConfig, ConnectNetworkEvent } from '@/constants/abacus';
import { type Candle, RESOLUTION_MAP } from '@/constants/candles'; import { type Candle, RESOLUTION_MAP } from '@/constants/candles';
import { getSelectedNetwork } from '@/state/appSelectors'; import { getSelectedNetwork } from '@/state/appSelectors';
import { log } from '@/lib/telemetry'; import { log } from '@/lib/telemetry';
import { useRestrictions } from './useRestrictions';
type DydxContextType = ReturnType<typeof useDydxClientContext>; type DydxContextType = ReturnType<typeof useDydxClientContext>;
const DydxContext = createContext<DydxContextType>({} as DydxContextType); const DydxContext = createContext<DydxContextType>({} as DydxContextType);
DydxContext.displayName = 'dYdXClient'; DydxContext.displayName = 'dYdXClient';
@@ -181,27 +178,7 @@ const useDydxClientContext = () => {
[requestCandles] [requestCandles]
); );
const { updateSanctionedAddresses } = useRestrictions(); // ------ Subacount Methods ------ //
const screenAddresses = useCallback(
async ({ addresses }: { addresses: string[] }) => {
if (compositeClient) {
const promises = addresses.map((address) =>
compositeClient.indexerClient.utility.screen(address)
);
const results = await Promise.all(promises);
const screenedAddresses = Object.fromEntries(
addresses.map((address, index) => [address, results[index]?.restricted])
);
updateSanctionedAddresses(screenedAddresses);
return screenedAddresses;
}
},
[compositeClient]
);
return { return {
// Client initialization // Client initialization
@@ -215,6 +192,5 @@ const useDydxClientContext = () => {
// Public Methods // Public Methods
getCandlesForDatafeed, getCandlesForDatafeed,
screenAddresses,
}; };
}; };
-2
View File
@@ -10,7 +10,6 @@ import { useLocalStorage } from '@/hooks';
import { initializeLocalization } from '@/state/app'; import { initializeLocalization } from '@/state/app';
import abacusStateManager from '@/lib/abacus'; import abacusStateManager from '@/lib/abacus';
import { validateAgainstAvailableEnvironments } from '@/lib/network';
export const useInitializePage = () => { export const useInitializePage = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@@ -19,7 +18,6 @@ export const useInitializePage = () => {
const [localStorageNetwork] = useLocalStorage<DydxNetwork>({ const [localStorageNetwork] = useLocalStorage<DydxNetwork>({
key: LocalStorageKey.SelectedNetwork, key: LocalStorageKey.SelectedNetwork,
defaultValue: DEFAULT_APP_ENVIRONMENT, defaultValue: DEFAULT_APP_ENVIRONMENT,
validateFn: validateAgainstAvailableEnvironments,
}); });
useEffect(() => { useEffect(() => {
+5 -6
View File
@@ -110,18 +110,18 @@ export const notificationTypes = [
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const { transferNotifications } = useLocalNotifications(); const { transferNotifications } = useLocalNotifications();
const getTitleStringKey = useCallback((type: 'deposit' | 'withdrawal', finished: boolean) => { const getTitleStringKey = useCallback((type: 'deposit' | 'withdraw', finished: boolean) => {
if (type === 'deposit' && !finished) return STRING_KEYS.DEPOSIT_IN_PROGRESS; if (type === 'deposit' && !finished) return STRING_KEYS.DEPOSIT_IN_PROGRESS;
if (type === 'deposit' && finished) return STRING_KEYS.DEPOSIT; if (type === 'deposit' && finished) return STRING_KEYS.DEPOSIT;
if (type === 'withdrawal' && !finished) return STRING_KEYS.WITHDRAW_IN_PROGRESS; if (type === 'withdraw' && !finished) return STRING_KEYS.WITHDRAW_IN_PROGRESS;
return STRING_KEYS.WITHDRAW; return STRING_KEYS.WITHDRAW;
}, []); }, []);
useEffect(() => { useEffect(() => {
for (const transfer of transferNotifications) { for (const transfer of transferNotifications) {
const { fromChainId, status, txHash, toAmount } = transfer; const { toChainId, status, txHash, toAmount } = transfer;
const finished = Boolean(status) && status?.squidTransactionStatus !== 'ongoing'; const finished = Boolean(status) && status?.squidTransactionStatus !== 'ongoing';
const type = fromChainId === TESTNET_CHAIN_ID ? 'withdrawal' : 'deposit'; const type = toChainId === TESTNET_CHAIN_ID ? 'deposit' : 'withdraw';
// @ts-ignore status.errors is not in the type definition but can be returned // @ts-ignore status.errors is not in the type definition but can be returned
const error = status?.errors?.length ? status?.errors[0] : status?.error; const error = status?.errors?.length ? status?.errors[0] : status?.error;
@@ -154,7 +154,6 @@ export const notificationTypes = [
description: description, description: description,
customContent: ( customContent: (
<TransferStatusToast <TransferStatusToast
type={type}
toAmount={transfer.toAmount} toAmount={transfer.toAmount}
triggeredAt={transfer.triggeredAt} triggeredAt={transfer.triggeredAt}
status={transfer.status} status={transfer.status}
@@ -163,7 +162,7 @@ export const notificationTypes = [
customMenuContent: !finished && ( customMenuContent: !finished && (
<div> <div>
{description} {description}
<TransferStatusSteps status={transfer.status} type={type} /> <TransferStatusSteps status={transfer.status} />
</div> </div>
), ),
toastSensitivity: 'foreground', toastSensitivity: 'foreground',
-53
View File
@@ -1,53 +0,0 @@
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { RestrictionType } from '@/constants/abacus';
import { DialogTypes } from '@/constants/dialogs';
import { getRestrictionType } from '@/state/accountSelectors';
import { forceOpenDialog } from '@/state/dialogs';
import { isTruthy } from '@/lib/isTruthy';
const useRestrictionContext = () => {
const dispatch = useDispatch();
const restrictionType = useSelector(getRestrictionType, shallowEqual);
const [sanctionedAddresses, setSanctionedAddresses] = useState<string[]>([]);
useEffect(() => {
if (restrictionType === RestrictionType.GEO_RESTRICTED) {
dispatch(
forceOpenDialog({ type: DialogTypes.RestrictedGeo, dialogProps: { preventClose: true } })
);
}
}, [restrictionType, dispatch]);
const updateSanctionedAddresses = useCallback(
(screenedAddresses: { [address: string]: boolean }) => {
const toAdd = Object.entries(screenedAddresses)
.filter(([, isSanctioned]) => isSanctioned)
.map(([address]) => address);
if (toAdd.length) {
setSanctionedAddresses([...sanctionedAddresses, ...toAdd]);
}
},
[sanctionedAddresses]
);
return {
isBadActor: restrictionType === RestrictionType.USER_RESTRICTED,
isGeoRestricted: restrictionType === RestrictionType.GEO_RESTRICTED,
updateSanctionedAddresses,
sanctionedAddresses: useMemo(() => new Set(sanctionedAddresses), [sanctionedAddresses]),
};
};
type RestrictionContextType = ReturnType<typeof useRestrictionContext>;
const RestrictionContext = createContext<RestrictionContextType>({} as RestrictionContextType);
RestrictionContext.displayName = 'Restriction';
export const RestrictionProvider = ({ ...props }) => (
<RestrictionContext.Provider value={useRestrictionContext()} {...props} />
);
export const useRestrictions = () => useContext(RestrictionContext);
+2 -18
View File
@@ -1,17 +1,13 @@
import { useCallback, useEffect } from 'react'; import { useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { DialogTypes } from '@/constants/dialogs';
import { LocalStorageKey } from '@/constants/localStorage'; import { LocalStorageKey } from '@/constants/localStorage';
import { DEFAULT_APP_ENVIRONMENT, DydxNetwork, ENVIRONMENT_CONFIG_MAP } from '@/constants/networks'; import { DEFAULT_APP_ENVIRONMENT, DydxNetwork } from '@/constants/networks';
import { useAccounts, useLocalStorage } from '@/hooks'; import { useAccounts, useLocalStorage } from '@/hooks';
import { setSelectedNetwork } from '@/state/app'; import { setSelectedNetwork } from '@/state/app';
import { getSelectedNetwork } from '@/state/appSelectors'; import { getSelectedNetwork } from '@/state/appSelectors';
import { openDialog } from '@/state/dialogs';
import { validateAgainstAvailableEnvironments } from '@/lib/network';
export const useSelectedNetwork = (): { export const useSelectedNetwork = (): {
switchNetwork: (network: DydxNetwork) => void; switchNetwork: (network: DydxNetwork) => void;
@@ -24,20 +20,8 @@ export const useSelectedNetwork = (): {
const [, setLocalStorageNetwork] = useLocalStorage<DydxNetwork>({ const [, setLocalStorageNetwork] = useLocalStorage<DydxNetwork>({
key: LocalStorageKey.SelectedNetwork, key: LocalStorageKey.SelectedNetwork,
defaultValue: DEFAULT_APP_ENVIRONMENT, defaultValue: DEFAULT_APP_ENVIRONMENT,
validateFn: validateAgainstAvailableEnvironments,
}); });
useEffect(() => {
if (
import.meta.env.MODE === 'production' &&
ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId === 'dydx-testnet-4'
) {
dispatch(
openDialog({ type: DialogTypes.ExchangeOffline, dialogProps: { preventClose: true } })
);
}
}, [selectedNetwork]);
const switchNetwork = useCallback( const switchNetwork = useCallback(
(network: DydxNetwork) => { (network: DydxNetwork) => {
disconnect(); disconnect();
+1 -1
View File
@@ -36,6 +36,7 @@ import { log } from '@/lib/telemetry';
import { useAccounts } from './useAccounts'; import { useAccounts } from './useAccounts';
import { useDydxClient } from './useDydxClient'; import { useDydxClient } from './useDydxClient';
type SubaccountContextType = ReturnType<typeof useSubaccountContext>; type SubaccountContextType = ReturnType<typeof useSubaccountContext>;
const SubaccountContext = createContext<SubaccountContextType>({} as SubaccountContextType); const SubaccountContext = createContext<SubaccountContextType>({} as SubaccountContextType);
SubaccountContext.displayName = 'Subaccount'; SubaccountContext.displayName = 'Subaccount';
@@ -274,7 +275,6 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
await getFaucetFunds({ dydxAddress, subaccountNumber }); await getFaucetFunds({ dydxAddress, subaccountNumber });
} catch (error) { } catch (error) {
log('useSubaccount/getFaucetFunds', error); log('useSubaccount/getFaucetFunds', error);
throw error;
} }
}, [dydxAddress, getFaucetFunds, subaccountNumber]); }, [dydxAddress, getFaucetFunds, subaccountNumber]);
-6
View File
@@ -15,12 +15,9 @@ import { ExternalNavKeplrDialog } from '@/views/dialogs/ExternalNavKeplrDialog';
import { MnemonicExportDialog } from '@/views/dialogs/MnemonicExportDialog'; import { MnemonicExportDialog } from '@/views/dialogs/MnemonicExportDialog';
import { MobileSignInDialog } from '@/views/dialogs/MobileSignInDialog'; import { MobileSignInDialog } from '@/views/dialogs/MobileSignInDialog';
import { OnboardingDialog } from '@/views/dialogs/OnboardingDialog'; import { OnboardingDialog } from '@/views/dialogs/OnboardingDialog';
import { RateLimitDialog } from '@/views/dialogs/RateLimitDialog';
import { ReceiveDialog } from '@/views/dialogs/ReceiveDialog'; import { ReceiveDialog } from '@/views/dialogs/ReceiveDialog';
import { RestrictedGeoDialog } from '@/views/dialogs/RestrictedGeoDialog';
import { TradeDialog } from '@/views/dialogs/TradeDialog'; import { TradeDialog } from '@/views/dialogs/TradeDialog';
import { TransferDialog } from '@/views/dialogs/TransferDialog'; import { TransferDialog } from '@/views/dialogs/TransferDialog';
import { RestrictedWalletDialog } from '@/views/dialogs/RestrictedWalletDialog';
import { WithdrawDialog } from '@/views/dialogs/WithdrawDialog'; import { WithdrawDialog } from '@/views/dialogs/WithdrawDialog';
import { OrderDetailsDialog } from '@/views/dialogs/DetailsDialog/OrderDetailsDialog'; import { OrderDetailsDialog } from '@/views/dialogs/DetailsDialog/OrderDetailsDialog';
@@ -56,10 +53,7 @@ export const DialogManager = () => {
[DialogTypes.MobileSignIn]: <MobileSignInDialog {...modalProps} />, [DialogTypes.MobileSignIn]: <MobileSignInDialog {...modalProps} />,
[DialogTypes.Onboarding]: <OnboardingDialog {...modalProps} />, [DialogTypes.Onboarding]: <OnboardingDialog {...modalProps} />,
[DialogTypes.OrderDetails]: <OrderDetailsDialog {...modalProps} />, [DialogTypes.OrderDetails]: <OrderDetailsDialog {...modalProps} />,
[DialogTypes.RateLimit]: <RateLimitDialog {...modalProps} />,
[DialogTypes.Receive]: <ReceiveDialog {...modalProps} />, [DialogTypes.Receive]: <ReceiveDialog {...modalProps} />,
[DialogTypes.RestrictedGeo]: <RestrictedGeoDialog {...modalProps} />,
[DialogTypes.RestrictedWallet]: <RestrictedWalletDialog {...modalProps} />,
[DialogTypes.Trade]: <TradeDialog {...modalProps} />, [DialogTypes.Trade]: <TradeDialog {...modalProps} />,
[DialogTypes.Transfer]: <TransferDialog {...modalProps} />, [DialogTypes.Transfer]: <TransferDialog {...modalProps} />,
[DialogTypes.Withdraw]: <WithdrawDialog {...modalProps} />, [DialogTypes.Withdraw]: <WithdrawDialog {...modalProps} />,
-5
View File
@@ -47,11 +47,6 @@ class AbacusRest implements AbacusRestProtocol {
body, body,
}; };
if (!url) {
callback(null, 0);
return;
}
fetch(url, options) fetch(url, options)
.then(async (response) => { .then(async (response) => {
const data = await response.text(); const data = await response.text();
-5
View File
@@ -25,7 +25,6 @@ import {
setFundingPayments, setFundingPayments,
setHistoricalPnl, setHistoricalPnl,
setLatestOrder, setLatestOrder,
setRestrictionType,
setSubaccount, setSubaccount,
setTransfers, setTransfers,
setWallet, setWallet,
@@ -122,10 +121,6 @@ class AbacusStateNotifier implements AbacusStateNotificationProtocol {
); );
} }
if (changes.has(Changes.restriction)) {
dispatch(setRestrictionType(updatedState.restriction));
}
subaccountNumbers?.forEach((subaccountId: number) => { subaccountNumbers?.forEach((subaccountId: number) => {
if (subaccountId !== null) { if (subaccountId !== null) {
if (changes.has(Changes.subaccount)) { if (changes.has(Changes.subaccount)) {
-4
View File
@@ -1,4 +0,0 @@
import { type DydxNetwork, ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
export const validateAgainstAvailableEnvironments = (value: DydxNetwork) =>
Object.keys(ENVIRONMENT_CONFIG_MAP).includes(value);
+26 -14
View File
@@ -36,15 +36,7 @@ import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet';
import { InjectedConnector } from 'wagmi/connectors/injected'; import { InjectedConnector } from 'wagmi/connectors/injected';
import { MetaMaskConnector } from 'wagmi/connectors/metaMask'; import { MetaMaskConnector } from 'wagmi/connectors/metaMask';
import { WalletConnectConnector } from 'wagmi/connectors/walletConnect'; import { WalletConnectConnector } from 'wagmi/connectors/walletConnect';
import { WalletConnectLegacyConnector } from 'wagmi/connectors/walletConnectLegacy';
import {
type WalletConnection,
WalletConnectionType,
type WalletType,
walletConnectionTypes,
wallets,
WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS,
} from '@/constants/wallets';
// Config // Config
@@ -100,19 +92,30 @@ const walletconnect2ConnectorOptions: ConstructorParameters<typeof WalletConnect
options: { options: {
projectId: import.meta.env.VITE_WALLETCONNECT2_PROJECT_ID, projectId: import.meta.env.VITE_WALLETCONNECT2_PROJECT_ID,
metadata: { metadata: {
// TODO: update to local URLs/images
name: 'dYdX', name: 'dYdX',
description: '', description: '',
url: import.meta.env.VITE_BASE_URL, url: 'https://trade.dydx.exchange',
icons: [`${import.meta.env.VITE_BASE_URL}/cbw-image.png}`], icons: ['https://trade.dydx.exchange/cbw-image.png'],
}, },
showQrModal: true, showQrModal: true,
qrModalOptions: { qrModalOptions: {
themeMode: 'dark' as const, themeMode: 'dark' as const,
themeVariables: { themeVariables: {
'--wcm-accent-color': '#5973fe', '--w3m-accent-color': '#5973fe',
'--wcm-font-family': 'var(--fontFamily-base)', '--w3m-background-color': '#5973fe',
'--w3m-color-bg-1': 'var(--color-layer-3)',
'--w3m-color-bg-2': 'var(--color-layer-4)',
'--w3m-color-bg-3': 'var(--color-layer-5)',
'--w3m-font-family': 'var(--fontFamily-base)',
'--w3m-font-feature-settings': 'none',
'--w3m-overlay-backdrop-filter': 'blur(6px)',
// '--w3m-logo-image-url': 'https://trade.dydx.exchange/cbw-image.png',
}, },
explorerRecommendedWalletIds: WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS, enableExplorer: true,
explorerAllowList: [],
explorerDenyList: [],
chainImages: {},
}, },
}, },
}; };
@@ -122,6 +125,7 @@ const connectors = [
chains, chains,
options: { options: {
shimDisconnect: true, shimDisconnect: true,
shimChainChangedDisconnect: false,
}, },
}), }),
new CoinbaseWalletConnector({ new CoinbaseWalletConnector({
@@ -162,11 +166,19 @@ const createWalletConnect2ConnectorWithId = (walletconnect2Id: string) =>
...walletconnect2ConnectorOptions.options.qrModalOptions, ...walletconnect2ConnectorOptions.options.qrModalOptions,
explorerRecommendedWalletIds: [walletconnect2Id], explorerRecommendedWalletIds: [walletconnect2Id],
explorerExcludedWalletIds: 'ALL', explorerExcludedWalletIds: 'ALL',
chainImages: {},
}, },
}, },
}); });
// Custom connector from wallet selection // Custom connector from wallet selection
import {
type WalletConnection,
WalletConnectionType,
type WalletType,
walletConnectionTypes,
wallets,
} from '@/constants/wallets';
export const resolveWagmiConnector = ({ export const resolveWagmiConnector = ({
walletType, walletType,
@@ -2,7 +2,6 @@ import { useMemo, useState } from 'react';
import styled, { AnyStyledComponent, css } from 'styled-components'; import styled, { AnyStyledComponent, css } from 'styled-components';
import { shallowEqual, useSelector } from 'react-redux'; import { shallowEqual, useSelector } from 'react-redux';
import { TooltipContextType } from '@visx/xychart'; import { TooltipContextType } from '@visx/xychart';
import BigNumber from 'bignumber.js';
import type { Nullable } from '@/constants/abacus'; import type { Nullable } from '@/constants/abacus';
import { OnboardingState } from '@/constants/account'; import { OnboardingState } from '@/constants/account';
@@ -26,6 +25,7 @@ import { OnboardingTriggerButton } from '@/views/dialogs/OnboardingTriggerButton
import { isTruthy } from '@/lib/isTruthy'; import { isTruthy } from '@/lib/isTruthy';
import { MustBigNumber } from '@/lib/numbers'; import { MustBigNumber } from '@/lib/numbers';
export const usePortfolioValues = ({ export const usePortfolioValues = ({
equity, equity,
visibleData, visibleData,
@@ -140,12 +140,7 @@ export const AccountDetailsAndHistory = () => {
<Styled.AccountValue> <Styled.AccountValue>
<Styled.WithLabel label={accountValueLabel}> <Styled.WithLabel label={accountValueLabel}>
<Styled.AccountEquity> <Styled.AccountEquity>
<Output <Output type={OutputType.Fiat} value={accountEquity} withBaseFont />
type={OutputType.Fiat}
value={accountEquity}
roundingMode={BigNumber.ROUND_FLOOR}
withBaseFont
/>
</Styled.AccountEquity> </Styled.AccountEquity>
<Styled.PnlDiff isPositive={MustBigNumber(pnlDiff).gte(0)}> <Styled.PnlDiff isPositive={MustBigNumber(pnlDiff).gte(0)}>
{pnlDiff && <TriangleIndicator value={MustBigNumber(pnlDiff)} />} {pnlDiff && <TriangleIndicator value={MustBigNumber(pnlDiff)} />}
+4
View File
@@ -3,6 +3,7 @@ import { configureStore } from '@reduxjs/toolkit';
import abacusStateManager from '@/lib/abacus'; import abacusStateManager from '@/lib/abacus';
import appMiddleware from './appMiddleware'; import appMiddleware from './appMiddleware';
import localizationMiddleware from './localizationMiddleware'; import localizationMiddleware from './localizationMiddleware';
import routerMiddleware from './routerMiddleware';
import { accountSlice } from './account'; import { accountSlice } from './account';
import { appSlice } from './app'; import { appSlice } from './app';
@@ -12,6 +13,7 @@ import { dialogsSlice } from './dialogs';
import { inputsSlice } from './inputs'; import { inputsSlice } from './inputs';
import { layoutSlice } from './layout'; import { layoutSlice } from './layout';
import { localizationSlice } from './localization'; import { localizationSlice } from './localization';
import { navigationSlice } from './navigation';
import { perpetualsSlice } from './perpetuals'; import { perpetualsSlice } from './perpetuals';
export const commandMenuSlices = [layoutSlice, localizationSlice]; export const commandMenuSlices = [layoutSlice, localizationSlice];
@@ -26,6 +28,7 @@ export const store = configureStore({
inputs: inputsSlice.reducer, inputs: inputsSlice.reducer,
layout: layoutSlice.reducer, layout: layoutSlice.reducer,
localization: localizationSlice.reducer, localization: localizationSlice.reducer,
navigation: navigationSlice.reducer,
perpetuals: perpetualsSlice.reducer, perpetuals: perpetualsSlice.reducer,
}, },
@@ -35,6 +38,7 @@ export const store = configureStore({
}), }),
appMiddleware, appMiddleware,
localizationMiddleware, localizationMiddleware,
routerMiddleware,
], ],
devTools: process.env.NODE_ENV !== 'production', devTools: process.env.NODE_ENV !== 'production',
+18 -40
View File
@@ -12,7 +12,6 @@ import type {
SubaccountTransfers, SubaccountTransfers,
HistoricalPnlPeriods, HistoricalPnlPeriods,
SubAccountHistoricalPNLs, SubAccountHistoricalPNLs,
UsageRestriction,
} from '@/constants/abacus'; } from '@/constants/abacus';
import { OnboardingGuard, OnboardingState } from '@/constants/account'; import { OnboardingGuard, OnboardingState } from '@/constants/account';
@@ -22,46 +21,34 @@ import { WalletType } from '@/constants/wallets';
import { getLocalStorage } from '@/lib/localStorage'; import { getLocalStorage } from '@/lib/localStorage';
export type AccountState = { export type AccountState = {
balances?: Record<string, AccountBalance>;
stakingBalances?: Record<string, AccountBalance>;
wallet?: Nullable<Wallet>;
walletType?: WalletType;
subaccount?: Nullable<Subaccount>;
fills?: SubaccountFills; fills?: SubaccountFills;
fundingPayments?: SubaccountFundingPayments; fundingPayments?: SubaccountFundingPayments;
transfers?: SubaccountTransfers; transfers?: SubaccountTransfers;
historicalPnl?: SubAccountHistoricalPNLs;
onboardingGuards: Record<OnboardingGuard, boolean | undefined>;
onboardingState: OnboardingState;
clearedOrderIds?: string[]; clearedOrderIds?: string[];
hasUnseenFillUpdates: boolean; hasUnseenFillUpdates: boolean;
hasUnseenOrderUpdates: boolean; hasUnseenOrderUpdates: boolean;
historicalPnl?: SubAccountHistoricalPNLs;
latestOrder?: Nullable<SubaccountOrder>; latestOrder?: Nullable<SubaccountOrder>;
historicalPnlPeriod?: HistoricalPnlPeriods; onboardingGuards: Record<OnboardingGuard, boolean | undefined>;
onboardingState: OnboardingState;
subaccount?: Nullable<Subaccount>;
uncommittedOrderClientIds: number[]; uncommittedOrderClientIds: number[];
wallet?: Nullable<Wallet>;
restriction?: Nullable<UsageRestriction>; walletType?: WalletType;
historicalPnlPeriod?: HistoricalPnlPeriods;
balances?: Record<string, AccountBalance>;
stakingBalances?: Record<string, AccountBalance>;
}; };
const initialState: AccountState = { const initialState: AccountState = {
// Wallet
balances: undefined,
wallet: undefined,
walletType: getLocalStorage<WalletType>({
key: LocalStorageKey.OnboardingSelectedWalletType,
}),
// Subaccount
subaccount: undefined,
fills: undefined, fills: undefined,
fundingPayments: undefined, fundingPayments: undefined,
transfers: undefined, transfers: undefined,
clearedOrderIds: undefined,
hasUnseenFillUpdates: false,
hasUnseenOrderUpdates: false,
historicalPnl: undefined, historicalPnl: undefined,
latestOrder: undefined,
// Onboarding
onboardingGuards: { onboardingGuards: {
[OnboardingGuard.hasAcknowledgedTerms]: Boolean( [OnboardingGuard.hasAcknowledgedTerms]: Boolean(
getLocalStorage<boolean>({ getLocalStorage<boolean>({
@@ -72,17 +59,12 @@ const initialState: AccountState = {
[OnboardingGuard.hasPreviousTransactions]: undefined, [OnboardingGuard.hasPreviousTransactions]: undefined,
}, },
onboardingState: OnboardingState.Disconnected, onboardingState: OnboardingState.Disconnected,
subaccount: undefined,
// UI
clearedOrderIds: undefined,
hasUnseenFillUpdates: false,
hasUnseenOrderUpdates: false,
latestOrder: undefined,
uncommittedOrderClientIds: [], uncommittedOrderClientIds: [],
historicalPnlPeriod: undefined, wallet: undefined,
walletType: getLocalStorage<WalletType>({
// Restriction key: LocalStorageKey.OnboardingSelectedWalletType,
restriction: undefined, }),
}; };
export const accountSlice = createSlice({ export const accountSlice = createSlice({
@@ -142,9 +124,6 @@ export const accountSlice = createSlice({
state.historicalPnl = action.payload; state.historicalPnl = action.payload;
} }
}, },
setRestrictionType: (state, action: PayloadAction<Nullable<UsageRestriction>>) => {
state.restriction = action.payload;
},
setSubaccount: (state, action: PayloadAction<Nullable<Subaccount>>) => { setSubaccount: (state, action: PayloadAction<Nullable<Subaccount>>) => {
const existingOrderIds = state.subaccount?.orders const existingOrderIds = state.subaccount?.orders
? state.subaccount.orders.toArray().map((order) => order.id) ? state.subaccount.orders.toArray().map((order) => order.id)
@@ -199,7 +178,6 @@ export const {
setOnboardingGuard, setOnboardingGuard,
setOnboardingState, setOnboardingState,
setHistoricalPnl, setHistoricalPnl,
setRestrictionType,
setSubaccount, setSubaccount,
setWallet, setWallet,
viewedFills, viewedFills,
-10
View File
@@ -342,13 +342,3 @@ export const getBalances = (state: RootState) => state.account?.balances;
* @returns user wallet staking balances * @returns user wallet staking balances
* */ * */
export const getStakingBalances = (state: RootState) => state.account?.stakingBalances; export const getStakingBalances = (state: RootState) => state.account?.stakingBalances;
/**
* @returns UsageRestriction of the current session
*/
export const getUsageRestriction = (state: RootState) => state.account.restriction;
/**
* @returns RestrictionType from the current session
*/
export const getRestrictionType = (state: RootState) => state.account.restriction?.restriction;
+1 -2
View File
@@ -2,10 +2,10 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { AbacusApiState } from '@/constants/abacus'; import { AbacusApiState } from '@/constants/abacus';
import { LocalStorageKey } from '@/constants/localStorage'; import { LocalStorageKey } from '@/constants/localStorage';
import { DEFAULT_APP_ENVIRONMENT, type DydxNetwork } from '@/constants/networks'; import { DEFAULT_APP_ENVIRONMENT, type DydxNetwork } from '@/constants/networks';
import { getLocalStorage } from '@/lib/localStorage'; import { getLocalStorage } from '@/lib/localStorage';
import { validateAgainstAvailableEnvironments } from '@/lib/network';
export interface AppState { export interface AppState {
apiState: AbacusApiState | undefined; apiState: AbacusApiState | undefined;
@@ -19,7 +19,6 @@ const initialState: AppState = {
selectedNetwork: getLocalStorage({ selectedNetwork: getLocalStorage({
key: LocalStorageKey.SelectedNetwork, key: LocalStorageKey.SelectedNetwork,
defaultValue: DEFAULT_APP_ENVIRONMENT, defaultValue: DEFAULT_APP_ENVIRONMENT,
validateFn: validateAgainstAvailableEnvironments,
}), }),
}; };
+25 -22
View File
@@ -23,36 +23,39 @@ export const dialogsSlice = createSlice({
name: 'Dialogs', name: 'Dialogs',
initialState, initialState,
reducers: { reducers: {
openDialog: (state: DialogsState, action: PayloadAction<DialogInfo<DialogTypes>>) => { addDialogToQueue: (state: DialogsState, action: PayloadAction<DialogInfo<DialogTypes>>) => {
if (state.activeDialog) { const dialogQueue = state.dialogQueue;
state.dialogQueue.push(action.payload); dialogQueue.push(action.payload);
} else {
state.activeDialog = action.payload; return {
} ...state,
}, dialogQueue,
closeDialog: (state: DialogsState) => { };
state.activeDialog = state.dialogQueue.shift();
},
forceOpenDialog: (state: DialogsState, action: PayloadAction<DialogInfo<DialogTypes>>) => {
if (state.activeDialog) {
state.dialogQueue.unshift(state.activeDialog);
}
state.activeDialog = action.payload;
},
closeDialogInTradeBox: (state: DialogsState) => {
state.activeTradeBoxDialog = undefined;
}, },
closeDialog: (state: DialogsState) => ({
...state,
activeDialog: state.dialogQueue.shift(),
}),
openDialog: (state: DialogsState, action: PayloadAction<DialogInfo<DialogTypes>>) => ({
...state,
activeDialog: action.payload,
}),
closeDialogInTradeBox: (state: DialogsState) => ({
...state,
activeTradeBoxDialog: undefined,
}),
openDialogInTradeBox: ( openDialogInTradeBox: (
state: DialogsState, state: DialogsState,
action: PayloadAction<DialogInfo<TradeBoxDialogTypes>> action: PayloadAction<DialogInfo<TradeBoxDialogTypes>>
) => { ) => ({
state.activeTradeBoxDialog = action.payload; ...state,
}, activeTradeBoxDialog: action.payload,
}),
}, },
}); });
export const { export const {
forceOpenDialog, addDialogToQueue,
closeDialog, closeDialog,
closeDialogInTradeBox, closeDialogInTradeBox,
openDialog, openDialog,
+42
View File
@@ -0,0 +1,42 @@
import { createSlice } from '@reduxjs/toolkit';
export interface NavigationState {
tradeLocation: {
hash: string;
key: string;
pathname: string;
search: string;
state: any;
};
}
export const CLEAR_TRADE_LOCATION = {
hash: '',
key: '',
pathname: '',
search: '',
state: null,
};
const initialState: NavigationState = {
tradeLocation: {
hash: '',
key: '',
pathname: '',
search: '',
state: null,
},
};
export const navigationSlice = createSlice({
name: 'Navigation',
initialState,
reducers: {
setTradeLocation: (state, { payload }) => ({
...state,
tradeLocation: payload,
}),
},
});
export const { setTradeLocation } = navigationSlice.actions;
+33
View File
@@ -0,0 +1,33 @@
import type { PayloadAction } from '@reduxjs/toolkit';
import { LocalStorageKey } from '@/constants/localStorage';
import { closeDialogInTradeBox } from '@/state/dialogs';
import { setTradeLocation } from '@/state/navigation';
import abacusStateManager from '@/lib/abacus';
import { setLocalStorage } from '@/lib/localStorage';
import { getMarketIdFromLocation } from '@/lib/tradeData';
export default (store: any) => (next: any) => async (action: PayloadAction<any>) => {
next(action);
const { type, payload } = action;
switch (type) {
case setTradeLocation.type: {
const marketId = getMarketIdFromLocation(payload);
if (marketId) {
abacusStateManager.setMarket(marketId);
store.dispatch(closeDialogInTradeBox());
setLocalStorage({ key: LocalStorageKey.LastViewedMarket, value: marketId });
}
break;
}
default: {
break;
}
}
};
+7 -3
View File
@@ -1,5 +1,6 @@
import { useCallback, useState, useMemo } from 'react'; import { useCallback, useState, useMemo } from 'react';
import styled, { type AnyStyledComponent } from 'styled-components'; import styled, { type AnyStyledComponent } from 'styled-components';
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
import { Root, Trigger, Content } from '@radix-ui/react-collapsible'; import { Root, Trigger, Content } from '@radix-ui/react-collapsible';
import { StatusResponse } from '@0xsquid/sdk'; import { StatusResponse } from '@0xsquid/sdk';
@@ -20,14 +21,12 @@ import { LoadingDots } from '@/components/Loading/LoadingDots';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
type ElementProps = { type ElementProps = {
type: 'withdrawal' | 'deposit';
toAmount?: number; toAmount?: number;
triggeredAt?: number; triggeredAt?: number;
status?: StatusResponse; status?: StatusResponse;
}; };
export const TransferStatusToast = ({ export const TransferStatusToast = ({
type,
toAmount, toAmount,
triggeredAt = Date.now(), triggeredAt = Date.now(),
status, status,
@@ -39,6 +38,11 @@ export const TransferStatusToast = ({
// @ts-ignore status.errors is not in the type definition but can be returned // @ts-ignore status.errors is not in the type definition but can be returned
const error = status?.errors?.length ? status?.errors[0] : status?.error; const error = status?.errors?.length ? status?.errors[0] : status?.error;
const type = useMemo(
() => (status?.toChain?.chainData?.chainId === TESTNET_CHAIN_ID ? 'deposit' : 'withdrawal'),
[status]
);
const updateSecondsLeft = useCallback(() => { const updateSecondsLeft = useCallback(() => {
const fromChainEta = (status?.fromChain?.chainData?.estimatedRouteDuration || 0) * 1000; const fromChainEta = (status?.fromChain?.chainData?.estimatedRouteDuration || 0) * 1000;
const toChainEta = (status?.toChain?.chainData?.estimatedRouteDuration || 0) * 1000; const toChainEta = (status?.toChain?.chainData?.estimatedRouteDuration || 0) * 1000;
@@ -65,7 +69,7 @@ export const TransferStatusToast = ({
side="bottom" side="bottom"
slotReceipt={ slotReceipt={
<Styled.Receipt> <Styled.Receipt>
<TransferStatusSteps status={status} type={type} /> <TransferStatusSteps status={status} />
</Styled.Receipt> </Styled.Receipt>
} }
> >
+4 -7
View File
@@ -1,6 +1,7 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import styled, { css, keyframes, type AnyStyledComponent } from 'styled-components'; import styled, { css, keyframes, type AnyStyledComponent } from 'styled-components';
import { StatusResponse } from '@0xsquid/sdk'; import { StatusResponse } from '@0xsquid/sdk';
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
import { useStringGetter } from '@/hooks'; import { useStringGetter } from '@/hooks';
@@ -14,7 +15,6 @@ import { STRING_KEYS } from '@/constants/localization';
type ElementProps = { type ElementProps = {
status?: StatusResponse; status?: StatusResponse;
type: 'withdrawal' | 'deposit';
}; };
enum TransferStatusStep { enum TransferStatusStep {
@@ -24,13 +24,14 @@ enum TransferStatusStep {
Complete, Complete,
} }
export const TransferStatusSteps = ({ status, type }: ElementProps) => { export const TransferStatusSteps = ({ status }: ElementProps) => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const { currentStep, steps } = useMemo(() => { const { currentStep, steps, type } = useMemo(() => {
const routeStatus = status?.routeStatus; const routeStatus = status?.routeStatus;
const fromChain = status?.fromChain?.chainData?.chainId; const fromChain = status?.fromChain?.chainData?.chainId;
const toChain = status?.toChain?.chainData?.chainId; const toChain = status?.toChain?.chainData?.chainId;
const type = toChain === TESTNET_CHAIN_ID ? 'deposit' : 'withdrawal';
const steps = [ const steps = [
{ {
@@ -73,10 +74,6 @@ export const TransferStatusSteps = ({ status, type }: ElementProps) => {
currentStep = TransferStatusStep.FromChain; currentStep = TransferStatusStep.FromChain;
} }
if (status?.squidTransactionStatus === 'success') {
currentStep = TransferStatusStep.Complete;
}
return { return {
currentStep, currentStep,
steps, steps,
+1 -5
View File
@@ -25,11 +25,7 @@ import { TimeSeriesChart } from '@/components/visx/TimeSeriesChart';
import { AxisLabelOutput } from '@/components/visx/AxisLabelOutput'; import { AxisLabelOutput } from '@/components/visx/AxisLabelOutput';
// import { TooltipContent } from '@/components/visx/TooltipContent'; // import { TooltipContent } from '@/components/visx/TooltipContent';
import { import { getSubaccount, getSubaccountHistoricalPnl, getSubaccountId } from '@/state/accountSelectors';
getSubaccount,
getSubaccountHistoricalPnl,
getSubaccountId,
} from '@/state/accountSelectors';
import abacusStateManager from '@/lib/abacus'; import abacusStateManager from '@/lib/abacus';
import { formatRelativeTime } from '@/lib/dateTime'; import { formatRelativeTime } from '@/lib/dateTime';
+2 -2
View File
@@ -27,9 +27,9 @@ export const DisconnectDialog = ({ setIsOpen }: ElementProps) => {
}; };
return ( return (
<Dialog isOpen setIsOpen={setIsOpen} title={stringGetter({ key: STRING_KEYS.DISCONNECT })}> <Dialog isOpen setIsOpen={setIsOpen} title="Disconnect">
<Styled.Content> <Styled.Content>
<p>{stringGetter({ key: STRING_KEYS.DISCONNECT_CONFIRMATION })}</p> <p>Are you sure you want to disconnect your account?</p>
<Styled.ButtonRow> <Styled.ButtonRow>
<Close asChild> <Close asChild>
<Button action={ButtonAction.Destroy} onClick={disconnect}> <Button action={ButtonAction.Destroy} onClick={disconnect}>
+2 -22
View File
@@ -5,9 +5,6 @@ import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { AbacusApiStatus } from '@/constants/abacus'; import { AbacusApiStatus } from '@/constants/abacus';
import { DialogTypes } from '@/constants/dialogs'; import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization'; import { STRING_KEYS } from '@/constants/localization';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { UNICODE } from '@/constants/unicode';
import { useApiState, useStringGetter } from '@/hooks'; import { useApiState, useStringGetter } from '@/hooks';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
@@ -32,16 +29,8 @@ export const ExchangeOfflineDialog = ({ preventClose, setIsOpen }: ElementProps)
const selectedNetwork = useSelector(getSelectedNetwork); const selectedNetwork = useSelector(getSelectedNetwork);
const activeDialog = useSelector(getActiveDialog, shallowEqual); const activeDialog = useSelector(getActiveDialog, shallowEqual);
const showOfflineMessage =
import.meta.env.MODE === 'production' &&
ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId === 'dydx-testnet-4';
useEffect(() => { useEffect(() => {
if ( if (activeDialog?.type === DialogTypes.ExchangeOffline && status === AbacusApiStatus.NORMAL) {
activeDialog?.type === DialogTypes.ExchangeOffline &&
status === AbacusApiStatus.NORMAL &&
!showOfflineMessage
) {
dispatch(closeDialog()); dispatch(closeDialog());
} }
}, [status, selectedNetwork]); }, [status, selectedNetwork]);
@@ -54,16 +43,7 @@ export const ExchangeOfflineDialog = ({ preventClose, setIsOpen }: ElementProps)
title={stringGetter({ key: STRING_KEYS.UNAVAILABLE })} title={stringGetter({ key: STRING_KEYS.UNAVAILABLE })}
> >
<Styled.Content> <Styled.Content>
{showOfflineMessage ? ( <p>{statusErrorMessage}</p>
<>
<p>Testnet is currently offline. Please check back!</p>
<Styled.Link href="https://v4-teacher.vercel.app/testnets/schedule">
{stringGetter({ key: STRING_KEYS.LEARN_MORE })} {UNICODE.ARROW_RIGHT}
</Styled.Link>
</>
) : (
<p>{statusErrorMessage}</p>
)}
{import.meta.env.MODE !== 'production' && <NetworkSelectMenu />} {import.meta.env.MODE !== 'production' && <NetworkSelectMenu />}
</Styled.Content> </Styled.Content>
</Dialog> </Dialog>
@@ -19,7 +19,7 @@ import { useDisplayedWallets } from '@/hooks/useDisplayedWallets';
import { breakpoints } from '@/styles'; import { breakpoints } from '@/styles';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
const aboutWalletsLink = `https://www.dydx.academy/video/defi-wallet`; const aboutWalletsLink = `https://www.dydxacademy.info/educational-video-series/onboarding-to-defi-with-dydx`;
export const ChooseWallet = () => { export const ChooseWallet = () => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
@@ -34,14 +34,7 @@ export const ChooseWallet = () => {
<Styled.AlertMessage type={AlertType.Error}> <Styled.AlertMessage type={AlertType.Error}>
{ {
<h4> <h4>
{stringGetter({ Couldn't connect to {stringGetter({ key: wallets[selectedWalletType].stringKey })}.
key: STRING_KEYS.COULD_NOT_CONNECT,
params: {
WALLET: stringGetter({
key: wallets[selectedWalletType].stringKey,
}),
},
})}
</h4> </h4>
} }
{selectedWalletError} {selectedWalletError}
-42
View File
@@ -1,42 +0,0 @@
import styled, { AnyStyledComponent } from 'styled-components';
import { STRING_KEYS } from '@/constants/localization';
import { useStringGetter } from '@/hooks';
import { layoutMixins } from '@/styles/layoutMixins';
import { Dialog } from '@/components/Dialog';
import { Icon, IconName } from '@/components/Icon';
type ElementProps = {
preventClose?: boolean;
setIsOpen?: (open: boolean) => void;
};
export const RateLimitDialog = ({ preventClose, setIsOpen }: ElementProps) => {
const stringGetter = useStringGetter();
return (
<Dialog
isOpen
preventClose={preventClose}
setIsOpen={setIsOpen}
title={stringGetter({ key: STRING_KEYS.RATE_LIMIT_REACHED_ERROR_TITLE })}
slotIcon={<Styled.Icon iconName={IconName.Warning} />}
>
<Styled.Content>
{stringGetter({ key: STRING_KEYS.RATE_LIMIT_REACHED_ERROR_MESSAGE })}
</Styled.Content>
</Dialog>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Icon = styled(Icon)`
color: var(--color-warning);
`;
Styled.Content = styled.div`
${layoutMixins.column}
gap: 1rem;
`;
-42
View File
@@ -1,42 +0,0 @@
import styled, { AnyStyledComponent } from 'styled-components';
import { STRING_KEYS } from '@/constants/localization';
import { useStringGetter } from '@/hooks';
import { layoutMixins } from '@/styles/layoutMixins';
import { Dialog } from '@/components/Dialog';
import { Icon, IconName } from '@/components/Icon';
type ElementProps = {
preventClose?: boolean;
setIsOpen?: (open: boolean) => void;
};
export const RestrictedGeoDialog = ({ preventClose, setIsOpen }: ElementProps) => {
const stringGetter = useStringGetter();
return (
<Dialog
isOpen
preventClose={preventClose}
setIsOpen={setIsOpen}
title={stringGetter({ key: STRING_KEYS.REGION_NOT_PERMITTED_TITLE })}
slotIcon={<Styled.Icon iconName={IconName.Warning} />}
>
<Styled.Content>
{stringGetter({ key: STRING_KEYS.REGION_NOT_PERMITTED_SUBTITLE })}
</Styled.Content>
</Dialog>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Icon = styled(Icon)`
color: var(--color-warning);
`;
Styled.Content = styled.div`
${layoutMixins.column}
gap: 1rem;
`;
@@ -1,42 +0,0 @@
import styled, { AnyStyledComponent } from 'styled-components';
import { STRING_KEYS } from '@/constants/localization';
import { useStringGetter } from '@/hooks';
import { layoutMixins } from '@/styles/layoutMixins';
import { Dialog } from '@/components/Dialog';
import { Icon, IconName } from '@/components/Icon';
type ElementProps = {
preventClose?: boolean;
setIsOpen?: (open: boolean) => void;
};
export const RestrictedWalletDialog = ({ preventClose, setIsOpen }: ElementProps) => {
const stringGetter = useStringGetter();
return (
<Dialog
isOpen
preventClose={preventClose}
setIsOpen={setIsOpen}
title={stringGetter({ key: STRING_KEYS.WALLET_RESTRICTED_ERROR_TITLE })}
slotIcon={<Styled.Icon iconName={IconName.Warning} />}
>
<Styled.Content>
{stringGetter({ key: STRING_KEYS.REGION_NOT_PERMITTED_SUBTITLE })}
</Styled.Content>
</Dialog>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Icon = styled(Icon)`
color: var(--color-warning);
`;
Styled.Content = styled.div`
${layoutMixins.column}
gap: 1rem;
`;
@@ -10,16 +10,9 @@ import { TransferInputField, TransferInputTokenResource, TransferType } from '@/
import { AlertType } from '@/constants/alerts'; import { AlertType } from '@/constants/alerts';
import { ButtonSize } from '@/constants/buttons'; import { ButtonSize } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization'; import { STRING_KEYS } from '@/constants/localization';
import { NumberSign } from '@/constants/numbers'; import { NumberSign, QUANTUM_MULTIPLIER } from '@/constants/numbers';
import { import { useDebounce, useStringGetter, useSubaccount } from '@/hooks';
useAccounts,
useDebounce,
useDydxClient,
useRestrictions,
useStringGetter,
useSubaccount,
} from '@/hooks';
import { useLocalNotifications } from '@/hooks/useLocalNotifications'; import { useLocalNotifications } from '@/hooks/useLocalNotifications';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
@@ -46,11 +39,10 @@ import { MustBigNumber } from '@/lib/numbers';
import { TokenSelectMenu } from './TokenSelectMenu'; import { TokenSelectMenu } from './TokenSelectMenu';
import { WithdrawButtonAndReceipt } from './WithdrawForm/WithdrawButtonAndReceipt'; import { WithdrawButtonAndReceipt } from './WithdrawForm/WithdrawButtonAndReceipt';
import { join } from 'path';
export const WithdrawForm = () => { export const WithdrawForm = () => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const [error, setError] = useState<string>(); const [error, setError] = useState<Error | null>(null);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const { sendSquidWithdraw } = useSubaccount(); const { sendSquidWithdraw } = useSubaccount();
@@ -79,11 +71,9 @@ export const WithdrawForm = () => {
const { addTransferNotification } = useLocalNotifications(); const { addTransferNotification } = useLocalNotifications();
// Async Data // Async Data
const debouncedAmountBN = useMemo(() => MustBigNumber(debouncedAmount), [debouncedAmount]); const debouncedAmountBN = MustBigNumber(debouncedAmount);
const freeCollateralBN = useMemo( const withdrawAmountBN = MustBigNumber(withdrawAmount);
() => MustBigNumber(freeCollateral?.current), const freeCollateralBN = MustBigNumber(freeCollateral?.current);
[freeCollateral?.current]
);
useEffect(() => { useEffect(() => {
abacusStateManager.setTransferValue({ abacusStateManager.setTransferValue({
@@ -115,85 +105,50 @@ export const WithdrawForm = () => {
value: debouncedAmount, value: debouncedAmount,
field: TransferInputField.usdcSize, field: TransferInputField.usdcSize,
}); });
setError(undefined); setError(null);
} }
} catch (error) { } catch (error) {
setError(error.message); setError(error);
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }
}; };
setTransferValue(); setTransferValue();
}, [debouncedAmountBN]); }, [debouncedAmountBN.toNumber()]);
const { screenAddresses } = useDydxClient();
const { dydxAddress } = useAccounts();
const onSubmit = useCallback( const onSubmit = useCallback(
async (e: FormEvent) => { async (e: FormEvent) => {
try { try {
e.preventDefault(); e.preventDefault();
if (!requestPayload?.data || !debouncedAmountBN.toNumber() || !toAddress || !dydxAddress) { if (!requestPayload?.data || !debouncedAmountBN.toNumber()) {
throw new Error('Invalid request payload'); throw new Error('Invalid request payload');
} }
setIsLoading(true); setIsLoading(true);
setError(undefined); const txHash = await sendSquidWithdraw(debouncedAmountBN.toNumber(), requestPayload?.data);
const screenResults = await screenAddresses({ if (txHash?.hash) {
addresses: [toAddress, dydxAddress], const hash = `0x${Buffer.from(txHash.hash).toString('hex')}`;
});
if (screenResults?.[dydxAddress]) { addTransferNotification({
setError( txHash: hash,
stringGetter({ fromChainId: TESTNET_CHAIN_ID,
key: STRING_KEYS.WALLET_RESTRICTED_WITHDRAWAL_TRANSFER_ORIGINATION_ERROR_MESSAGE, toChainId: chainIdStr || undefined,
}) toAmount: debouncedAmountBN.toNumber(),
); triggeredAt: Date.now(),
} else if (screenResults?.[toAddress]) { });
setError( abacusStateManager.clearTransferInputValues();
stringGetter({ setWithdrawAmount('');
key: STRING_KEYS.WALLET_RESTRICTED_WITHDRAWAL_TRANSFER_DESTINATION_ERROR_MESSAGE,
})
);
} else {
const txHash = await sendSquidWithdraw(debouncedAmountBN.toNumber(), requestPayload.data);
if (txHash?.hash) {
const hash = `0x${Buffer.from(txHash.hash).toString('hex')}`;
addTransferNotification({
txHash: hash,
fromChainId: TESTNET_CHAIN_ID,
toChainId: chainIdStr || undefined,
toAmount: debouncedAmountBN.toNumber(),
triggeredAt: Date.now(),
});
abacusStateManager.clearTransferInputValues();
setWithdrawAmount('');
}
} }
} catch (error) { } catch (error) {
if (error?.code === 429) { setError(error);
setError(stringGetter({ key: STRING_KEYS.RATE_LIMIT_REACHED_ERROR_MESSAGE }));
} else {
setError(
error.message
? stringGetter({
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
params: {
ERROR_MESSAGE:
error.message || stringGetter({ key: STRING_KEYS.UNKNOWN_ERROR }),
},
})
: stringGetter({ key: STRING_KEYS.SOMETHING_WENT_WRONG })
);
}
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }
}, },
[requestPayload, debouncedAmountBN, chainIdStr, toAddress, screenAddresses, stringGetter] [requestPayload, debouncedAmountBN, chainIdStr]
); );
const onChangeAddress = useCallback((e: ChangeEvent<HTMLInputElement>) => { const onChangeAddress = useCallback((e: ChangeEvent<HTMLInputElement>) => {
@@ -224,7 +179,7 @@ export const WithdrawForm = () => {
const onClickMax = useCallback(() => { const onClickMax = useCallback(() => {
setWithdrawAmount(freeCollateralBN.toString()); setWithdrawAmount(freeCollateralBN.toString());
}, [freeCollateralBN, setWithdrawAmount]); }, [freeCollateral?.current, setWithdrawAmount]);
const onSelectChain = useCallback((chain: string) => { const onSelectChain = useCallback((chain: string) => {
if (chain) { if (chain) {
@@ -260,7 +215,7 @@ export const WithdrawForm = () => {
value={freeCollateral?.current} value={freeCollateral?.current}
newValue={freeCollateral?.postOrder} newValue={freeCollateral?.postOrder}
sign={NumberSign.Negative} sign={NumberSign.Negative}
hasInvalidNewValue={MustBigNumber(withdrawAmount).minus(freeCollateralBN).isNegative()} hasInvalidNewValue={withdrawAmountBN.minus(freeCollateralBN).isNegative()}
withDiff={ withDiff={
Boolean(withdrawAmount) && !debouncedAmountBN.isNaN() && !debouncedAmountBN.isZero() Boolean(withdrawAmount) && !debouncedAmountBN.isNaN() && !debouncedAmountBN.isZero()
} }
@@ -269,23 +224,18 @@ export const WithdrawForm = () => {
}, },
]; ];
const { sanctionedAddresses } = useRestrictions();
const errorMessage = useMemo(() => { const errorMessage = useMemo(() => {
if (error) { if (error) {
return stringGetter({ return error?.message
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE, ? stringGetter({
params: { ERROR_MESSAGE: error }, key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
}); params: { ERROR_MESSAGE: error.message },
})
: stringGetter({ key: STRING_KEYS.SOMETHING_WENT_WRONG });
} }
if (!toAddress) return stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_ADDRESS }); if (!toAddress) return stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_ADDRESS });
if (sanctionedAddresses.has(toAddress))
return stringGetter({
key: STRING_KEYS.TRANSFER_INVALID_DYDX_ADDRESS,
});
if (debouncedAmountBN) { if (debouncedAmountBN) {
if (!chainIdStr) { if (!chainIdStr) {
return stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_CHAIN }); return stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_CHAIN });
@@ -299,15 +249,7 @@ export const WithdrawForm = () => {
} }
return undefined; return undefined;
}, [ }, [error, freeCollateralBN, chainIdStr, debouncedAmountBN, toToken]);
error,
freeCollateralBN,
chainIdStr,
debouncedAmountBN,
toToken,
toAddress,
sanctionedAddresses,
]);
const isDisabled = const isDisabled =
!!errorMessage || !!errorMessage ||
@@ -315,8 +257,7 @@ export const WithdrawForm = () => {
!chainIdStr || !chainIdStr ||
!toAddress || !toAddress ||
debouncedAmountBN.isNaN() || debouncedAmountBN.isNaN() ||
debouncedAmountBN.isZero() || debouncedAmountBN.isZero();
isLoading;
return ( return (
<Styled.Form onSubmit={onSubmit}> <Styled.Form onSubmit={onSubmit}>
+34 -68
View File
@@ -3,6 +3,8 @@ import styled, { type AnyStyledComponent } from 'styled-components';
import { type NumberFormatValues } from 'react-number-format'; import { type NumberFormatValues } from 'react-number-format';
import { shallowEqual, useSelector } from 'react-redux'; import { shallowEqual, useSelector } from 'react-redux';
import type { SyntheticInputEvent } from 'react-number-format/types/types'; import type { SyntheticInputEvent } from 'react-number-format/types/types';
import { debounce } from 'lodash';
import { StdFee } from '@cosmjs/stargate';
import { validation } from '@dydxprotocol/v4-client-js'; import { validation } from '@dydxprotocol/v4-client-js';
import { TransferInputField, TransferType } from '@/constants/abacus'; import { TransferInputField, TransferType } from '@/constants/abacus';
@@ -10,7 +12,7 @@ import { AlertType } from '@/constants/alerts';
import { ButtonShape, ButtonSize } from '@/constants/buttons'; import { ButtonShape, ButtonSize } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization'; import { STRING_KEYS } from '@/constants/localization';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks'; import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { NumberSign } from '@/constants/numbers'; import { NumberSign, QUANTUM_MULTIPLIER } from '@/constants/numbers';
import { import {
DYDX_CHAIN_ASSET_COIN_DENOM, DYDX_CHAIN_ASSET_COIN_DENOM,
DYDX_CHAIN_ASSET_TAGS, DYDX_CHAIN_ASSET_TAGS,
@@ -20,8 +22,6 @@ import {
import { import {
useAccountBalance, useAccountBalance,
useAccounts, useAccounts,
useDydxClient,
useRestrictions,
useSelectedNetwork, useSelectedNetwork,
useStringGetter, useStringGetter,
useSubaccount, useSubaccount,
@@ -77,7 +77,7 @@ export const TransferForm = ({
const [asset, setAsset] = useState<DydxChainAsset>(selectedAsset); const [asset, setAsset] = useState<DydxChainAsset>(selectedAsset);
// Form states // Form states
const [error, setError] = useState<string>(); const [error, setError] = useState<Error | undefined>();
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const balance = asset === DydxChainAsset.USDC ? freeCollateral?.current : nativeTokenBalance; const balance = asset === DydxChainAsset.USDC ? freeCollateral?.current : nativeTokenBalance;
@@ -96,6 +96,16 @@ export const TransferForm = ({
const balanceBN = MustBigNumber(balance); const balanceBN = MustBigNumber(balance);
const newBalanceBN = MustBigNumber(newBalance); const newBalanceBN = MustBigNumber(newBalance);
const isAddressValid = useMemo(
() =>
recipientAddress &&
dydxAddress !== recipientAddress &&
validation.isValidAddress(recipientAddress),
[recipientAddress]
);
const isAmountValid = balance && amount && amountBN.gt(0) && newBalanceBN.gte(0);
useEffect(() => { useEffect(() => {
abacusStateManager.setTransferValue({ abacusStateManager.setTransferValue({
value: TransferType.transferOut.rawValue, value: TransferType.transferOut.rawValue,
@@ -115,21 +125,6 @@ export const TransferForm = ({
}); });
}, [asset]); }, [asset]);
const { sanctionedAddresses } = useRestrictions();
const isAddressValid = useMemo(
() =>
recipientAddress &&
dydxAddress !== recipientAddress &&
validation.isValidAddress(recipientAddress) &&
!sanctionedAddresses.has(recipientAddress),
[recipientAddress, sanctionedAddresses, dydxAddress]
);
const isAmountValid = balance && amount && amountBN.gt(0) && newBalanceBN.gte(0);
const { screenAddresses } = useDydxClient();
const onTransfer = async () => { const onTransfer = async () => {
if (!isAmountValid || !isAddressValid || !fee) return; if (!isAmountValid || !isAddressValid || !fee) return;
setIsLoading(true); setIsLoading(true);
@@ -141,51 +136,20 @@ export const TransferForm = ({
asset === DydxChainAsset.DYDX ? amountBN.minus(fee) : amountBN asset === DydxChainAsset.DYDX ? amountBN.minus(fee) : amountBN
).toNumber(); ).toNumber();
const screenResults = await screenAddresses({ const txResponse = await transfer(
addresses: [recipientAddress!, dydxAddress!], amountToTransfer,
}); recipientAddress as string,
DYDX_CHAIN_ASSET_COIN_DENOM[asset]
);
if (screenResults?.[dydxAddress!]) { if (txResponse?.code === 0) {
setError( console.log('TransferForm > txReceipt > ', txResponse?.hash);
stringGetter({ onDone?.();
key: STRING_KEYS.WALLET_RESTRICTED_WITHDRAWAL_TRANSFER_ORIGINATION_ERROR_MESSAGE,
})
);
} else if (screenResults?.[recipientAddress!]) {
setError(
stringGetter({
key: STRING_KEYS.WALLET_RESTRICTED_WITHDRAWAL_TRANSFER_DESTINATION_ERROR_MESSAGE,
})
);
} else { } else {
const txResponse = await transfer( throw new Error(txResponse?.rawLog ?? 'Transaction did not commit.');
amountToTransfer,
recipientAddress as string,
DYDX_CHAIN_ASSET_COIN_DENOM[asset]
);
if (txResponse?.code === 0) {
console.log('TransferForm > txReceipt > ', txResponse?.hash);
onDone?.();
} else {
throw new Error(txResponse?.rawLog ?? 'Transaction did not commit.');
}
} }
} catch (error) { } catch (error) {
if (error?.code === 429) { setError(error);
setError(stringGetter({ key: STRING_KEYS.RATE_LIMIT_REACHED_ERROR_MESSAGE }));
} else {
setError(
error.message
? stringGetter({
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
params: {
ERROR_MESSAGE: error.message || stringGetter({ key: STRING_KEYS.UNKNOWN_ERROR }),
},
})
: stringGetter({ key: STRING_KEYS.SOMETHING_WENT_WRONG })
);
}
log('TransferForm/onTransfer', error); log('TransferForm/onTransfer', error);
} finally { } finally {
setIsLoading(false); setIsLoading(false);
@@ -267,6 +231,13 @@ export const TransferForm = ({
}, },
]; ];
const addressValidationErrorMessage = stringGetter({
key:
dydxAddress === recipientAddress
? STRING_KEYS.TRANSFER_TO_YOURSELF
: STRING_KEYS.TRANSFER_INVALID_DYDX_ADDRESS,
});
const renderFormInputButton = ({ const renderFormInputButton = ({
label, label,
isInputEmpty, isInputEmpty,
@@ -331,12 +302,7 @@ export const TransferForm = ({
{recipientAddress && !isAddressValid && ( {recipientAddress && !isAddressValid && (
<Styled.AddressValidationAlertMessage type={AlertType.Error}> <Styled.AddressValidationAlertMessage type={AlertType.Error}>
{stringGetter({ {addressValidationErrorMessage}
key:
dydxAddress === recipientAddress
? STRING_KEYS.TRANSFER_TO_YOURSELF
: STRING_KEYS.TRANSFER_INVALID_DYDX_ADDRESS,
})}
</Styled.AddressValidationAlertMessage> </Styled.AddressValidationAlertMessage>
)} )}
@@ -376,13 +342,13 @@ export const TransferForm = ({
</AlertMessage> </AlertMessage>
)} )}
{error && <AlertMessage type={AlertType.Error}>{error}</AlertMessage>} {error && <AlertMessage type={AlertType.Error}>{error.message}</AlertMessage>}
<Styled.Footer> <Styled.Footer>
<TransferButtonAndReceipt <TransferButtonAndReceipt
selectedAsset={asset} selectedAsset={asset}
fees={fee || undefined} fees={fee || undefined}
isDisabled={!isAmountValid || !isAddressValid || !fee || isLoading} isDisabled={!isAmountValid || !isAddressValid || !fee}
isLoading={isLoading || Boolean(isAmountValid && isAddressValid && !fee)} isLoading={isLoading || Boolean(isAmountValid && isAddressValid && !fee)}
/> />
</Styled.Footer> </Styled.Footer>