Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73eb7aff96 | ||
|
|
6a3c4ec7f6 | ||
|
|
47b6618299 | ||
|
|
def44ad66e | ||
|
|
a6eb90952a |
+1
-1
@@ -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",
|
||||||
|
|||||||
Generated
+4
-4
@@ -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 |
+19
-45
@@ -35,13 +35,11 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
@@ -96,13 +94,11 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
@@ -156,13 +152,11 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
@@ -216,13 +210,11 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
@@ -276,13 +268,11 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
@@ -340,13 +330,11 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
@@ -403,14 +391,12 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
@@ -469,14 +455,12 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
@@ -534,14 +518,12 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
@@ -599,14 +581,12 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
@@ -664,14 +644,12 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
@@ -729,14 +707,12 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
@@ -795,14 +771,12 @@
|
|||||||
"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",
|
||||||
"image": "/currencies/dydx.png"
|
"image": "/currencies/dydx.png"
|
||||||
},
|
},
|
||||||
"usdc": {
|
"usdc": {
|
||||||
|
|||||||
+449
-439
@@ -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 |
@@ -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),
|
||||||
|
|||||||
@@ -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)`
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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(() => {
|
||||||
|
|||||||
@@ -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);
|
|
||||||
@@ -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-3'
|
|
||||||
) {
|
|
||||||
dispatch(
|
|
||||||
openDialog({ type: DialogTypes.ExchangeOffline, dialogProps: { preventClose: true } })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, [selectedNetwork]);
|
|
||||||
|
|
||||||
const switchNetwork = useCallback(
|
const switchNetwork = useCallback(
|
||||||
(network: DydxNetwork) => {
|
(network: DydxNetwork) => {
|
||||||
disconnect();
|
disconnect();
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
|
||||||
|
|||||||
@@ -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} />,
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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);
|
|
||||||
+3
-2
@@ -92,10 +92,11 @@ 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: {
|
||||||
|
|||||||
@@ -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)} />}
|
||||||
|
|||||||
@@ -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
@@ -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,
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -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';
|
||||||
|
|||||||
@@ -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}>
|
||||||
|
|||||||
@@ -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-3';
|
|
||||||
|
|
||||||
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}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
`;
|
|
||||||
@@ -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}>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user