Compare commits

...
Author SHA1 Message Date
Bill He e1e817ea92 update 2023-10-23 13:22:12 -07:00
Bill He 4b85ec7df0 update acknowledgement dialog with new copies 2023-10-23 11:17:55 -07:00
Bill 051bdda73a update v4-client init in useDydxClient (#91)
* update v4-client init in useDydxClient

* fix nit
2023-10-20 11:00:03 -07:00
Bill 27b79957d4 Bump v4 clients (#89)
* Have tokens be configurable, bump v4-client

* bump

* chain -> chaintoken

* use cancelRawOrder

* address comments

* add TODO
2023-10-19 11:01:12 -07:00
aleka 4bacc901dc use wallet connect config from envs (#88)
* use wallet connect config from envs

* update readme
2023-10-19 11:35:17 -04:00
aleka 82d32a91a9 fix dialog not showing up (#87) 2023-10-19 07:16:13 -07:00
aleka 2a794f9459 add empty terms + privacy pages (#80)
* add empty terms + privacy pages

* nit
2023-10-18 19:44:15 -04:00
lucas-dydx 5c26a0c270 Update dev2 validator IP address (#86) 2023-10-18 12:38:08 -07:00
Jared Vu e4991cc31d Update Abacus 0.7.0 & Misc. bug fixes (#84)
* Add Notification icon w/ stroke

* Update to abacus0.7.0

* Fix goodTilTime string

* Fix tradingView initial load

* Temp remove notif onClick

* remove isConnected state from dydxClient
2023-10-18 11:08:39 -07:00
aleka da908c826a Revert "Revert "remove offline message for testnet4 (#76)" (#78)" (#85)
This reverts commit 14316163e4.
2023-10-18 13:04:25 -04:00
John Huang af46278539 18 for adv4tnt, 6 for uusdc (#83)
* 18 for adv4tnt, 6 for uusdc

* Changed "exponents" to "decimals"
2023-10-17 15:42:00 -07:00
Jared Vu ea58b55152 Bump localStorage version to wipe EvmDerivedAddresses (#79) 2023-10-17 14:49:51 -07:00
aleka 54d65bb81c override walletconnect explorer recs (#81) 2023-10-17 17:42:41 -04:00
aleka e047a49bbc remove wc1 support and fix typo in env.json (#82) 2023-10-17 17:12:50 -04:00
aleka 14316163e4 Revert "remove offline message for testnet4 (#76)" (#78)
This reverts commit ac619a9da1.
2023-10-17 13:37:26 -04:00
aleka ac619a9da1 remove offline message for testnet4 (#76) 2023-10-17 13:03:50 -04:00
Bill cb7f542a99 Onboarding status do not rely on squidAPI to determine if deposit/withdraw (#73) 2023-10-16 17:35:07 -07:00
aleka bc5569c4c9 testnet4 followup, switch offline msg (#75) 2023-10-16 17:26:29 -04:00
John Huang dd087ae786 TRCL-3010 Change test net chain ID and token denom (#74) 2023-10-16 17:26:21 -04:00
aleka eb023ff0ff update signing message for testnet for reset (#72) 2023-10-16 16:44:29 -04:00
47 changed files with 678 additions and 423 deletions
+10 -2
View File
@@ -11,6 +11,7 @@
## Prerequisites
- Node.js version 18 and `pnpm` installed on your system
- Wallet Connect account
For deploying with Vercel, create an account with [Vercel](https://vercel.com/signup) if you don't have one already.
@@ -61,7 +62,14 @@ pnpm ladle
This will automatically open your default browser at `http://localhost:61000`.
## Part 3: Deploying with Vercel
## Part 3: Configuring environment
Add or modify the relevant endpoints, links and options in `/public/configs/env.json`.
You'll need to provide a Wallet Connect project id to enable onboarding and wallet connection:
- Create a project on https://cloud.walletconnect.com/app
- Copy over the project ID into this [field](https://github.com/dydxprotocol/v4-web/blob/67ecbd75b43e0c264b7b4d2d9b3d969830b0621c/public/configs/env.json#L822C33-L822C46)
## Part 4: Deploying with Vercel
### Step 1: Connect your repository to Vercel
@@ -78,7 +86,7 @@ If you wish to incorporate analytics via Amplitude and Bugsnag, you can use our
For more details, check out Vercel's [official documentation](https://vercel.com/docs).
## Part 4: Deploying to IPFS
## Part 5: Deploying to IPFS
### web3.storage: deploy to IPFS via web3.storage using the provided script
+3 -3
View File
@@ -38,9 +38,9 @@
"@cosmjs/proto-signing": "^0.31.0",
"@cosmjs/stargate": "^0.31.0",
"@cosmjs/tendermint-rpc": "^0.31.0",
"@dydxprotocol/v4-abacus": "^0.6.4",
"@dydxprotocol/v4-client-js": "^0.36.1",
"@dydxprotocol/v4-localization": "^0.1.30",
"@dydxprotocol/v4-abacus": "^0.7.2",
"@dydxprotocol/v4-client-js": "^0.40.3",
"@dydxprotocol/v4-localization": "^0.1.32",
"@ethersproject/providers": "^5.7.2",
"@js-joda/core": "^5.5.3",
"@radix-ui/react-collapsible": "^1.0.3",
+25 -24
View File
@@ -27,14 +27,14 @@ dependencies:
specifier: ^0.31.0
version: 0.31.0
'@dydxprotocol/v4-abacus':
specifier: ^0.6.4
version: 0.6.4
specifier: ^0.7.2
version: 0.7.2
'@dydxprotocol/v4-client-js':
specifier: ^0.36.1
version: 0.36.1
specifier: ^0.40.3
version: 0.40.3
'@dydxprotocol/v4-localization':
specifier: ^0.1.30
version: 0.1.30
specifier: ^0.1.32
version: 0.1.32
'@ethersproject/providers':
specifier: ^5.7.2
version: 5.7.2
@@ -645,7 +645,7 @@ packages:
/@confio/ics23@0.6.8:
resolution: {integrity: sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==}
dependencies:
'@noble/hashes': 1.3.1
'@noble/hashes': 1.3.2
protobufjs: 6.11.4
dev: false
@@ -717,7 +717,7 @@ packages:
'@cosmjs/encoding': 0.30.1
'@cosmjs/math': 0.30.1
'@cosmjs/utils': 0.30.1
'@noble/hashes': 1.3.1
'@noble/hashes': 1.3.2
bn.js: 5.2.1
elliptic: 6.5.4
libsodium-wrappers: 0.7.11
@@ -979,12 +979,12 @@ packages:
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
dev: true
/@dydxprotocol/v4-abacus@0.6.4:
resolution: {integrity: sha512-eH+/9Q/OnQtwzBwM1BJyXybFPdivGmFQWrxM71MFWGs6uIQGbZX775mpoa8deweSTyQ/QrRLRQ1mP2BPDgBQYg==}
/@dydxprotocol/v4-abacus@0.7.2:
resolution: {integrity: sha512-5foamomN82FH6ko3EuzwFlSoAEY6Sal8fDgvZo2RsB19Ks6SFgFDeeOcEDdfoa3DNwvl8yW0C9cfxeQ+BfU8uA==}
dev: false
/@dydxprotocol/v4-client-js@0.36.1:
resolution: {integrity: sha512-KJ3MtWI61wmm+xZtXQd7/hYKIoVFG32TRdyyVaXXO8vpW9Oqd0JD8QSM/wuegkciAh5YmP/BrDzYuu77zHO6yg==}
/@dydxprotocol/v4-client-js@0.40.3:
resolution: {integrity: sha512-nMQd6tYisKDKIbfx0BGJSYEOSt+I+t5SsaBSmlgTdso+w2rCRO9vyxS+u6MF9h4w5FsVRfhHo3e6uTWX48WpGQ==}
dependencies:
'@cosmjs/amino': 0.30.1
'@cosmjs/encoding': 0.31.1
@@ -993,14 +993,15 @@ packages:
'@cosmjs/stargate': 0.30.1
'@cosmjs/tendermint-rpc': 0.30.1
'@cosmjs/utils': 0.31.1
'@dydxprotocol/v4-proto': 0.2.1
'@dydxprotocol/v4-proto': 0.4.1
'@osmonauts/lcd': 0.6.0
'@scure/bip32': 1.3.1
'@scure/bip32': 1.3.2
'@scure/bip39': 1.2.1
axios: 1.1.3
bech32: 1.1.4
bignumber.js: 9.1.1
ethereum-cryptography: 2.1.2
ethers: 6.6.1
long: 4.0.0
protobufjs: 6.11.4
ws: 8.13.0(bufferutil@4.0.7)(utf-8-validate@5.0.10)
@@ -1010,12 +1011,12 @@ packages:
- utf-8-validate
dev: false
/@dydxprotocol/v4-localization@0.1.30:
resolution: {integrity: sha512-xTlQuQmPz7wfGkjd07giYMAxRrolDbJE3DryJSIMB6R1MBq1wLzAcwp/iR/nELRwilRX9c44Tap0gGt+oAajiQ==}
/@dydxprotocol/v4-localization@0.1.32:
resolution: {integrity: sha512-ZtXScxgFLjUt0Ag52RyFnQe9aEl1Aky5fp+vMGOBduVkFiCEMRMkSsSgg6grMdyw/x0AbnxOTRkhYoX2MsK9Ow==}
dev: false
/@dydxprotocol/v4-proto@0.2.1:
resolution: {integrity: sha512-Q5b/g331DoyMjBpO2/jtrxUX3WF5UaIKZp/unK332xuefHNFnkMYtZ05p0V71iSdO35tBdz8yt0VYP2WtUsp+w==}
/@dydxprotocol/v4-proto@0.4.1:
resolution: {integrity: sha512-2pBkokufWcxfIpiXE6QuQOBXUe154OTp6ojCIdOPW9TFLxzchoygxXnb5dL6rAQVNj9Qbg+hhXBllutt4m99dw==}
dependencies:
protobufjs: 6.11.4
dev: false
@@ -4708,8 +4709,8 @@ packages:
resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==}
dependencies:
'@noble/curves': 1.1.0
'@noble/hashes': 1.3.1
'@scure/base': 1.1.1
'@noble/hashes': 1.3.2
'@scure/base': 1.1.3
dev: false
/@scure/bip32@1.3.2:
@@ -4731,7 +4732,7 @@ packages:
resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==}
dependencies:
'@noble/hashes': 1.3.2
'@scure/base': 1.1.1
'@scure/base': 1.1.3
dev: false
/@solana/buffer-layout@4.0.1:
@@ -4745,8 +4746,8 @@ packages:
resolution: {integrity: sha512-up5VG1dK+GPhykmuMIozJZBbVqpm77vbOG6/r5dS7NBGZonwHfTLdBbsYc3rjmaQ4DpCXUa3tUc4RZHRORvZrw==}
dependencies:
'@babel/runtime': 7.22.10
'@noble/curves': 1.1.0
'@noble/hashes': 1.3.1
'@noble/curves': 1.2.0
'@noble/hashes': 1.3.2
'@solana/buffer-layout': 4.0.1
agentkeepalive: 4.5.0
bigint-buffer: 1.1.5
@@ -7144,7 +7145,7 @@ packages:
/bip39@3.1.0:
resolution: {integrity: sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==}
dependencies:
'@noble/hashes': 1.3.1
'@noble/hashes': 1.3.2
dev: false
/bl@5.1.0:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

+67 -80
View File
@@ -40,14 +40,16 @@
"isMainNet": false,
"tokens": {
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -77,9 +79,6 @@
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
@@ -101,14 +100,16 @@
"isMainNet": false,
"tokens": {
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -120,7 +121,7 @@
}
],
"validators": [
"http://35.75.227.118"
"http://54.92.118.111"
],
"0xsquid": "https://testnet.api.0xsquid.com"
},
@@ -137,9 +138,6 @@
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
@@ -161,14 +159,16 @@
"isMainNet": false,
"tokens": {
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -197,9 +197,6 @@
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
@@ -221,14 +218,16 @@
"isMainNet": false,
"tokens": {
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -257,9 +256,6 @@
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
@@ -281,14 +277,16 @@
"isMainNet": false,
"tokens": {
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -321,9 +319,6 @@
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
@@ -345,14 +340,16 @@
"isMainNet": false,
"tokens": {
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -385,9 +382,6 @@
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
@@ -403,20 +397,22 @@
"dydxprotocol-testnet": {
"name": "v4 Public Testnet",
"ethereumChainId": "5",
"dydxChainId": "dydx-testnet-3",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false,
"tokens": {
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -451,9 +447,6 @@
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
@@ -462,27 +455,29 @@
"callbackUrl": "/walletsegue"
},
"images": "/wallets/",
"signTypedDataAction": "dYdX V4 Onboarding",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
}
},
"dydxprotocol-testnet-dydx": {
"name": "v4 Public Testnet/dYdX",
"ethereumChainId": "5",
"dydxChainId": "dydx-testnet-3",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false,
"tokens": {
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -516,9 +511,6 @@
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
@@ -527,27 +519,29 @@
"callbackUrl": "/walletsegue"
},
"images": "/wallets/",
"signTypedDataAction": "dYdX V4 Onboarding",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
}
},
"dydxprotocol-testnet-dsrv": {
"name": "v4 Public Testnet/DSRV",
"ethereumChainId": "5",
"dydxChainId": "dydx-testnet-3",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false,
"tokens": {
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -581,9 +575,6 @@
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
@@ -592,27 +583,29 @@
"callbackUrl": "/walletsegue"
},
"images": "/wallets/",
"signTypedDataAction": "dYdX V4 Onboarding",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
}
},
"dydxprotocol-testnet-nodefleet": {
"name": "v4 Public Testnet/nodefleet",
"ethereumChainId": "5",
"dydxChainId": "dydx-testnet-3",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false,
"tokens": {
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -646,9 +639,6 @@
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
@@ -657,27 +647,29 @@
"callbackUrl": "/walletsegue"
},
"images": "/wallets/",
"signTypedDataAction": "dYdX V4 Onboarding",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
}
},
"dydxprotocol-testnet-kingnodes": {
"name": "v4 Public Testnet/KingNodes",
"ethereumChainId": "5",
"dydxChainId": "dydx-testnet-3",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false,
"tokens": {
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -711,9 +703,6 @@
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
@@ -722,27 +711,29 @@
"callbackUrl": "/walletsegue"
},
"images": "/wallets/",
"signTypedDataAction": "dYdX V4 Onboarding",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
}
},
"dydxprotocol-testnet-liquify": {
"name": "v4 Public Testnet/Liquify",
"ethereumChainId": "5",
"dydxChainId": "dydx-testnet-3",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png",
"isMainNet": false,
"tokens": {
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -776,9 +767,6 @@
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v1": {
"bridgeUrl": "wss://api.stage.dydx.exchange/wc/"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
@@ -787,11 +775,11 @@
"callbackUrl": "/walletsegue"
},
"images": "/wallets/",
"signTypedDataAction": "dYdX V4 Onboarding",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
}
},
"dydxprotocol-mainet": {
"dydxprotocol-mainnet": {
"name": "v4",
"ethereumChainId": "1",
"dydxChainId": "[mainnet chain id]",
@@ -801,14 +789,16 @@
"tokens": {
"comment": "Change according to mainnet release",
"chain": {
"name": "DYDX",
"denom": "dv4tnt",
"name": "TokenName",
"denom": "tokenDenom",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
@@ -841,9 +831,6 @@
"description": "[Description of the app]",
"iconUrl": "[Relative URL of the icon URL]"
},
"v1": {
"bridgeUrl": "[Bridge URL]"
},
"v2": {
"projectId": "[Project ID]"
}
@@ -857,4 +844,4 @@
}
}
}
}
}
+14 -2
View File
@@ -7,7 +7,13 @@ import { GrazProvider } from 'graz';
import { AppRoute, DEFAULT_TRADE_ROUTE } from '@/constants/routes';
import { useBreakpoints, useInitializePage, useShouldShowFooter, useAnalytics } from '@/hooks';
import {
useBreakpoints,
useTokenConfigs,
useInitializePage,
useShouldShowFooter,
useAnalytics,
} from '@/hooks';
import { DydxProvider } from '@/hooks/useDydxClient';
import { AccountsProvider } from '@/hooks/useAccounts';
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
@@ -27,6 +33,8 @@ import ProfilePage from '@/pages/Profile';
import { SettingsPage } from '@/pages/settings/Settings';
import TradePage from '@/pages/trade/Trade';
import { RewardsPage } from '@/pages/rewards/RewardsPage';
import { TermsOfUsePage } from '@/pages/TermsOfUsePage';
import { PrivacyPolicyPage } from '@/pages/PrivacyPolicyPage';
import { HeaderDesktop } from '@/layout/Header/HeaderDesktop';
import { FooterDesktop } from '@/layout/Footer/FooterDesktop';
@@ -55,6 +63,7 @@ const Content = () => {
const { isTablet, isNotTablet } = useBreakpoints();
const isShowingHeader = isNotTablet;
const isShowingFooter = useShouldShowFooter();
const { chainTokenLabel } = useTokenConfigs();
return (
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
@@ -69,7 +78,7 @@ const Content = () => {
</Route>
<Route path={AppRoute.Markets} element={<MarketsPage />} />
<Route path={AppRoute.Rewards} element={<RewardsPage />} />
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
{isTablet && (
<>
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
@@ -82,6 +91,9 @@ const Content = () => {
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
</Route>
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
</Routes>
</Suspense>
+8 -1
View File
@@ -6,6 +6,8 @@ import {
AddressConnectorIcon,
ArrowIcon,
Bar3Icon,
BellIcon,
BellStrokeIcon,
BoxCloseIcon,
CalculatorIcon,
CaretIcon,
@@ -71,6 +73,8 @@ export enum IconName {
AddressConnector = 'AddressConnector',
Arrow = 'Arrow',
Bar3 = 'Bar3',
Bell = 'Bell',
BellStroked = 'BellStroked',
BoxClose = 'BoxClose',
Calculator = 'Calculator',
Caret = 'Caret',
@@ -137,6 +141,8 @@ const icons = {
[IconName.AddressConnector]: AddressConnectorIcon,
[IconName.Arrow]: ArrowIcon,
[IconName.Bar3]: Bar3Icon,
[IconName.Bell]: BellIcon,
[IconName.BellStroked]: BellStrokeIcon,
[IconName.BoxClose]: BoxCloseIcon,
[IconName.Calculator]: CalculatorIcon,
[IconName.Caret]: CaretIcon,
@@ -213,7 +219,8 @@ export const Icon = styled(
iconComponent: Component = iconName && icons[iconName],
className,
...props
}: ElementProps & StyleProps) => (Component ? <Component className={className} {...props} /> : null)
}: ElementProps & StyleProps) =>
Component ? <Component className={className} {...props} /> : null
)`
width: 1em;
height: 1em;
+17 -10
View File
@@ -59,16 +59,6 @@ export const TransactionType = Abacus.exchange.dydx.abacus.protocols.Transaction
const transactionTypes = [...TransactionType.values()] as const;
export type TransactionTypes = (typeof transactionTypes)[number];
export type NetworkConfig = {
chainId: string;
indexerUrl: string;
indexerSocketUrl: string;
validatorUrl: string;
faucetUrl?: string | null;
};
export type ConnectNetworkEvent = CustomEvent<Partial<NetworkConfig>>;
// ------ State ------
export type AbacusApiState = Abacus.exchange.dydx.abacus.state.manager.ApiState;
export const AbacusApiStatus = Abacus.exchange.dydx.abacus.state.manager.ApiStatus;
@@ -267,3 +257,20 @@ export const TRADE_TYPES: Record<
[AbacusOrderType.liquidation.name]: null,
[AbacusOrderType.trailingStop.name]: null,
};
// Custom types involving Abacus
export type NetworkConfig = Partial<{
indexerUrl: Nullable<string>;
websocketUrl: Nullable<string>;
validatorUrl: Nullable<string>;
chainId: Nullable<string>;
faucetUrl: Nullable<string>;
USDC_DENOM: Nullable<string>;
USDC_DECIMALS: Nullable<number>;
USDC_GAS_DENOM: Nullable<string>;
CHAINTOKEN_DENOM: Nullable<string>;
CHAINTOKEN_DECIMALS: Nullable<number>;
}>;
export type ConnectNetworkEvent = CustomEvent<Partial<NetworkConfig>>;
+1 -1
View File
@@ -24,6 +24,6 @@ export enum LocalStorageKey {
}
export const LOCAL_STORAGE_VERSIONS = {
[LocalStorageKey.EvmDerivedAddresses]: 'v1',
[LocalStorageKey.EvmDerivedAddresses]: 'v2',
// TODO: version all localStorage keys
};
+2 -1
View File
@@ -7,7 +7,8 @@ export enum AppRoute {
Profile = '/profile',
Alerts = '/alerts',
Settings = '/settings',
Rewards = '/DV4TNT',
Terms = '/terms',
Privacy = '/privacy',
}
export enum PortfolioRoute {
+38 -28
View File
@@ -1,5 +1,5 @@
import type { ExternalProvider } from '@ethersproject/providers';
import { USDC_DENOM, type onboarding, DYDX_DENOM } from '@dydxprotocol/v4-client-js';
import { type onboarding } from '@dydxprotocol/v4-client-js';
import type { suggestChain } from 'graz';
import { STRING_KEYS } from '@/constants/localization';
@@ -92,6 +92,24 @@ export enum WalletType {
OtherWallet = 'OTHER_WALLET',
}
const WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS = {
Metamask: 'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96',
imToken: 'ef333840daf915aafdc4a004525502d6d49d77bd9c65e0642dbaefb3c2893bef',
TokenPocket: '20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66',
Trust: '4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0',
Rainbow: '1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369',
Zerion: 'ecc4036f814562b41a5268adc86270fba1365471402006302e70169465b7ac18',
Ledger: '19177a98252e07ddfc9af2083ba8e07ef627cb6103467ffebb3f8f4205fd7927',
Fireblocks: '5864e2ced7c293ed18ac35e0db085c09ed567d67346ccb6f58a0327a75137489',
Uniswap: 'c03dfee351b6fcc421b4494ea33b9d4b92a984f87aa76d1663bb28705e95034a',
Robinhood: '8837dd9413b1d9b585ee937d27a816590248386d9dbf59f5cd3422dbbb65683e',
'1inch': 'c286eebc742a537cd1d6818363e9dc53b21759a1e8e5d9b263d0c03ec7703576',
};
export const WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS = Object.values(
WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS
);
type WalletConfig = {
type: WalletType;
stringKey: string;
@@ -125,7 +143,6 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: BitkeepIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isBitKeep, // isBitKeepChrome, isBitEthereum
walletconnect2Id: '38f5d18bd8522c244bdd70cb4a68e0e718865155811c043f052fb9f1c51de662',
},
[WalletType.BitPie]: {
type: WalletType.BitPie,
@@ -158,7 +175,6 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: Coin98Icon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isCoin98,
walletconnect2Id: '2a3c89040ac3b723a1972a33a125b1db11e258a6975d3a61252cd64e6ea5ea01',
},
[WalletType.HuobiWallet]: {
type: WalletType.HuobiWallet,
@@ -166,7 +182,6 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: HuobiIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isHbWallet,
walletconnect2Id: '797c615e2c556b610c048eb35535f212c0dd58de5d03e763120e90a7d1350a77',
},
[WalletType.ImToken]: {
type: WalletType.ImToken,
@@ -174,7 +189,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: ImTokenIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isImToken,
walletconnect2Id: 'ef333840daf915aafdc4a004525502d6d49d77bd9c65e0642dbaefb3c2893bef',
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.imToken,
},
[WalletType.MathWallet]: {
type: WalletType.MathWallet,
@@ -190,7 +205,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: MetaMaskIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: isMetaMask,
walletconnect2Id: 'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96',
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.Metamask,
},
[WalletType.Rainbow]: {
type: WalletType.Rainbow,
@@ -198,7 +213,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: RainbowIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isRainbowWallet,
walletconnect2Id: '1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369',
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.Rainbow,
},
[WalletType.TokenPocket]: {
type: WalletType.TokenPocket,
@@ -206,7 +221,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: TokenPocketIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isTokenPocket,
walletconnect2Id: '20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66',
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.TokenPocket,
},
[WalletType.TrustWallet]: {
type: WalletType.TrustWallet,
@@ -214,7 +229,7 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: TrustWalletIcon,
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
matchesInjectedEip1193: (provider) => provider.isTrust,
walletconnect2Id: '4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0',
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.Trust,
},
[WalletType.WalletConnect2]: {
type: WalletType.WalletConnect2,
@@ -287,10 +302,10 @@ export type DydxAddress = `dydx${string}`;
export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = {
rpc: 'https://dydx-testnet-archive.allthatnode.com:26657',
rest: 'https://dydx-testnet-archive.allthatnode.com:1317',
chainId: 'dydx-testnet-3',
chainId: 'dydx-testnet-4',
chainName: 'dYdX Public Testnet',
chainSymbolImageUrl:
'https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/dydx-testnet-3/chain.png',
'https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/dydx-testnet-4/chain.png',
bech32Config: {
bech32PrefixAccPub: 'dydxpub',
bech32PrefixValPub: 'dydxvaloperpub',
@@ -304,26 +319,31 @@ export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = {
},
stakeCurrency: {
coinDenom: 'DV4TNT',
coinDecimals: 6,
coinMinimalDenom: 'dv4tnt',
coinDecimals: 18,
coinMinimalDenom: 'adv4tnt',
},
currencies: [
{
coinDenom: 'DV4TNT',
coinDecimals: 6,
coinMinimalDenom: 'dv4tnt',
coinDecimals: 18,
coinMinimalDenom: 'adv4tnt',
},
{
coinDenom: 'USDC',
coinMinimalDenom: 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5',
coinDecimals: 6,
coinMinimalDenom: 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5',
},
],
feeCurrencies: [
{
coinDenom: 'DV4TNT',
coinDecimals: 18,
coinMinimalDenom: 'adv4tnt',
},
{
coinDenom: 'USDC',
coinDecimals: 6,
coinMinimalDenom: 'dv4tnt',
coinMinimalDenom: 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5',
},
],
features: [],
@@ -332,15 +352,5 @@ export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = {
// TODO: export this type from abacus instead
export enum DydxChainAsset {
USDC = 'usdc',
DYDX = 'dydx',
CHAINTOKEN = 'chain',
}
export const DYDX_CHAIN_ASSET_COIN_DENOM: Record<DydxChainAsset, string> = {
[DydxChainAsset.USDC]: USDC_DENOM,
[DydxChainAsset.DYDX]: DYDX_DENOM,
};
export const DYDX_CHAIN_ASSET_TAGS: Record<DydxChainAsset, string> = {
[DydxChainAsset.USDC]: 'USDC',
[DydxChainAsset.DYDX]: 'Dv4TNT',
};
+2
View File
@@ -1,5 +1,6 @@
import { useApiState } from './useApiState';
import { useBreakpoints } from './useBreakpoints';
import { useTokenConfigs } from './useTokenConfigs';
import { useCommandMenu } from './useCommandMenu';
import { useCurrentMarketId } from './useCurrentMarketId';
import { useDebounce } from './useDebounce';
@@ -25,6 +26,7 @@ import { useSubaccount } from './useSubaccount';
export {
useApiState,
useBreakpoints,
useTokenConfigs,
useCommandMenu,
useCurrentMarketId,
useDebounce,
+3 -3
View File
@@ -33,7 +33,7 @@ export const useTradingView = ({
const marketIds = useSelector(getMarketIds, shallowEqual);
const selectedLocale = useSelector(getSelectedLocale);
const selectedNetwork = useSelector(getSelectedNetwork);
const { getCandlesForDatafeed } = useDydxClient();
const { getCandlesForDatafeed, isConnected: isClientConnected } = useDydxClient();
const [savedTvChartConfig, setTvChartConfig] = useLocalStorage<object | undefined>({
key: LocalStorageKey.TradingViewChartConfig,
@@ -44,7 +44,7 @@ export const useTradingView = ({
const hasMarkets = marketIds.length > 0;
useEffect(() => {
if (hasMarkets) {
if (hasMarkets && isClientConnected) {
const widgetOptions = getWidgetOptions();
const widgetOverrides = getWidgetOverrides(appTheme);
const options = {
@@ -75,7 +75,7 @@ export const useTradingView = ({
tvWidgetRef.current = null;
setIsChartReady(false);
};
}, [getCandlesForDatafeed, hasMarkets, selectedLocale, selectedNetwork]);
}, [getCandlesForDatafeed, isClientConnected, hasMarkets, selectedLocale, selectedNetwork]);
return { savedResolution };
};
+8 -12
View File
@@ -5,8 +5,6 @@ import { StargateClient } from '@cosmjs/stargate';
import { useQuery } from 'react-query';
import { formatUnits } from 'viem';
import { USDC_DENOM, DYDX_DENOM } from '@dydxprotocol/v4-client-js';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { QUANTUM_MULTIPLIER } from '@/constants/numbers';
import { EvmAddress } from '@/constants/wallets';
@@ -18,6 +16,7 @@ import { getBalances, getStakingBalances } from '@/state/accountSelectors';
import { getSelectedNetwork } from '@/state/appSelectors';
import { useAccounts } from './useAccounts';
import { useTokenConfigs } from './useTokenConfigs';
type UseAccountBalanceProps = {
// Token Items
@@ -52,6 +51,7 @@ export const useAccountBalance = ({
const selectedNetwork = useSelector(getSelectedNetwork);
const balances = useSelector(getBalances, shallowEqual);
const { chainTokenDenom, usdcDenom } = useTokenConfigs();
const evmChainId = Number(ENVIRONMENT_CONFIG_MAP[selectedNetwork].ethereumChainId);
const stakingBalances = useSelector(getStakingBalances, shallowEqual);
@@ -93,18 +93,14 @@ export const useAccountBalance = ({
const { formatted: evmBalance } = evmQuery.data || {};
const balance = !assetSymbol ? '0' : isCosmosChain ? cosmosQuery.data : evmBalance;
const nativeTokenCoinBalance = balances?.[DYDX_DENOM];
const nativeTokenBalance = MustBigNumber(nativeTokenCoinBalance?.amount)
.div(QUANTUM_MULTIPLIER)
.toNumber();
const nativeTokenCoinBalance = balances?.[chainTokenDenom];
const nativeTokenBalance = MustBigNumber(nativeTokenCoinBalance?.amount);
const usdcCoinBalance = balances?.[USDC_DENOM];
const usdcBalance = MustBigNumber(usdcCoinBalance?.amount).div(QUANTUM_MULTIPLIER).toNumber();
const usdcCoinBalance = balances?.[usdcDenom];
const usdcBalance = MustBigNumber(usdcCoinBalance?.amount).toNumber();
const nativeStakingCoinBalanace = stakingBalances?.[DYDX_DENOM];
const nativeStakingBalance = MustBigNumber(nativeStakingCoinBalanace?.amount)
.div(QUANTUM_MULTIPLIER)
.toNumber();
const nativeStakingCoinBalanace = stakingBalances?.[chainTokenDenom];
const nativeStakingBalance = MustBigNumber(nativeStakingCoinBalanace?.amount).toNumber();
return {
balance,
+2 -11
View File
@@ -2,7 +2,7 @@ import { useCallback, useContext, createContext, useEffect, useState, useMemo }
import { useDispatch } from 'react-redux';
import { AES, enc } from 'crypto-js';
import { LocalWallet, USDC_DENOM, type Subaccount } from '@dydxprotocol/v4-client-js';
import { LocalWallet, type Subaccount } from '@dydxprotocol/v4-client-js';
import { OnboardingGuard, OnboardingState, type EvmDerivedAddresses } from '@/constants/account';
import { DialogTypes } from '@/constants/dialogs';
@@ -130,16 +130,8 @@ const useAccountsContext = () => {
// dYdX subaccounts
const [dydxSubaccounts, setDydxSubaccounts] = useState<Subaccount[] | undefined>();
const { getAccountBalance, getSubaccounts } = useMemo(
const { getSubaccounts } = useMemo(
() => ({
getAccountBalance: async ({
dydxAddress,
denom = USDC_DENOM,
}: {
dydxAddress: DydxAddress;
denom?: string;
}) => await compositeClient?.validatorClient.get.getAccountBalance(dydxAddress, denom),
getSubaccounts: async ({ dydxAddress }: { dydxAddress: DydxAddress }) => {
try {
const response = await compositeClient?.indexerClient.account.getSubaccounts(dydxAddress);
@@ -326,7 +318,6 @@ const useAccountsContext = () => {
disconnect,
// dydxClient Account methods
getAccountBalance,
getSubaccounts,
};
};
+5 -2
View File
@@ -44,6 +44,9 @@ export const useCurrentMarketId = () => {
}, [validId]);
useEffect(() => {
abacusStateManager.setMarket(marketId ?? DEFAULT_MARKETID);
}, [selectedNetwork, marketId]);
// Check for marketIds otherwise Abacus will silently fail its isMarketValid check
if (marketIds) {
abacusStateManager.setMarket(marketId ?? DEFAULT_MARKETID);
}
}, [selectedNetwork, marketIds, marketId]);
};
+16 -5
View File
@@ -13,8 +13,10 @@ import {
import type { ResolutionString } from 'public/tradingview/charting_library';
import type { NetworkConfig, ConnectNetworkEvent } from '@/constants/abacus';
import type { ConnectNetworkEvent, NetworkConfig } from '@/constants/abacus';
import { type Candle, RESOLUTION_MAP } from '@/constants/candles';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { DydxChainAsset } from '@/constants/wallets';
import { getSelectedNetwork } from '@/state/appSelectors';
@@ -36,8 +38,9 @@ const useDydxClientContext = () => {
// ------ Network ------ //
const selectedNetwork = useSelector(getSelectedNetwork);
const tokensConfigs = ENVIRONMENT_CONFIG_MAP[selectedNetwork].tokens;
const [networkConfig, setNetworkConfig] = useState<Partial<NetworkConfig>>();
const [networkConfig, setNetworkConfig] = useState<NetworkConfig>();
useEffect(() => {
const onConnectNetwork = (event: ConnectNetworkEvent) => setNetworkConfig(event.detail);
@@ -57,15 +60,22 @@ const useDydxClientContext = () => {
if (
networkConfig?.chainId &&
networkConfig?.indexerUrl &&
networkConfig?.indexerSocketUrl &&
networkConfig?.websocketUrl &&
networkConfig?.validatorUrl
) {
try {
const initializedClient = await CompositeClient.connect(
new Network(
selectedNetwork,
new IndexerConfig(networkConfig.indexerUrl, networkConfig.indexerSocketUrl),
new ValidatorConfig(networkConfig.validatorUrl, networkConfig.chainId, {
new IndexerConfig(networkConfig.indexerUrl, networkConfig.websocketUrl),
new ValidatorConfig(networkConfig.validatorUrl, networkConfig.chainId,
{
USDC_DENOM: tokensConfigs[DydxChainAsset.USDC].denom,
USDC_DECIMALS: tokensConfigs[DydxChainAsset.USDC].decimals,
USDC_GAS_DENOM: tokensConfigs[DydxChainAsset.USDC].gasDenom,
CHAINTOKEN_DENOM: tokensConfigs[DydxChainAsset.CHAINTOKEN].denom,
CHAINTOKEN_DECIMALS: tokensConfigs[DydxChainAsset.CHAINTOKEN].decimals,
}, {
broadcastPollIntervalMs: 3_000,
broadcastTimeoutMs: 60_000,
})
@@ -209,6 +219,7 @@ const useDydxClientContext = () => {
networkConfig,
compositeClient,
faucetClient,
isConnected: !!compositeClient,
// Wallet Methods
getWalletFromEvmSignature,
+42 -25
View File
@@ -4,15 +4,14 @@ import { useSelector, shallowEqual, useDispatch } from 'react-redux';
import { groupBy } from 'lodash';
import { AlertType } from '@/constants/alerts';
import { AbacusOrderStatus, ORDER_SIDES, ORDER_STATUS_STRINGS } from '@/constants/abacus';
import { AbacusOrderStatus, ORDER_SIDES } from '@/constants/abacus';
import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization';
import { STRING_KEYS, StringKey } from '@/constants/localization';
import { type NotificationTypeConfig, NotificationType } from '@/constants/notifications';
import { ORDER_SIDE_STRINGS, TRADE_TYPE_STRINGS, TradeTypes } from '@/constants/trade';
import { ORDER_SIDE_STRINGS } from '@/constants/trade';
import { useLocalNotifications } from '@/hooks/useLocalNotifications';
import { AlertMessage } from '@/components/AlertMessage';
import { Icon, IconName } from '@/components/Icon';
import { Output, OutputType } from '@/components/Output';
import { TransferStatusToast } from '@/views/TransferStatus';
@@ -69,11 +68,11 @@ export const notificationTypes = [
<OrderStatusIcon status={order.status} totalFilled={order.totalFilled ?? 0} />
),
title: `${stringGetter({
key: TRADE_TYPE_STRINGS[order.type.rawValue as TradeTypes].tradeTypeKey,
key: order.resources.typeStringKey as StringKey,
})} ${
order.status === AbacusOrderStatus.open && (order?.totalFilled ?? 0) > 0
? stringGetter({ key: STRING_KEYS.PARTIALLY_FILLED })
: stringGetter({ key: ORDER_STATUS_STRINGS[order.status.name] })
: stringGetter({ key: order.resources.statusStringKey as StringKey })
}`,
description: `${stringGetter({
key: ORDER_SIDE_STRINGS[ORDER_SIDES[order.side.name]],
@@ -91,18 +90,34 @@ export const notificationTypes = [
}, [orderIds]);
},
useNotificationAction: () => {
const dispatch = useDispatch();
// useNotificationAction: () => {
// const dispatch = useDispatch();
// const orders = useSelector(getSubaccountOrders, shallowEqual) || [];
// const ordersByOrderId = Object.fromEntries(orders.map((order) => [order.id, order]));
return (orderId) => {
dispatch(
openDialog({
type: DialogTypes.OrderDetails,
dialogProps: { orderId },
})
);
};
},
// const fills = useSelector(getSubaccountFills, shallowEqual) || [];
// const fillsByOrderId = groupBy(fills, (fill) => fill.orderId);
// return (id) => {
// if (ordersByOrderId[id]) {
// dispatch(
// openDialog({
// type: DialogTypes.OrderDetails,
// dialogProps: { orderId: id },
// })
// );
// } else if (fillsByOrderId[id]) {
// const fillId = fillsByOrderId[id][0].id;
// dispatch(
// openDialog({
// type: DialogTypes.FillDetails,
// dialogProps: { fillId },
// })
// );
// }
// };
// },
} as NotificationTypeConfig<string, [string, number]>,
{
type: NotificationType.SquidTransfer,
@@ -110,18 +125,18 @@ export const notificationTypes = [
const stringGetter = useStringGetter();
const { transferNotifications } = useLocalNotifications();
const getTitleStringKey = useCallback((type: 'deposit' | 'withdraw', finished: boolean) => {
const getTitleStringKey = useCallback((type: 'deposit' | 'withdrawal', finished: boolean) => {
if (type === 'deposit' && !finished) return STRING_KEYS.DEPOSIT_IN_PROGRESS;
if (type === 'deposit' && finished) return STRING_KEYS.DEPOSIT;
if (type === 'withdraw' && !finished) return STRING_KEYS.WITHDRAW_IN_PROGRESS;
if (type === 'withdrawal' && !finished) return STRING_KEYS.WITHDRAW_IN_PROGRESS;
return STRING_KEYS.WITHDRAW;
}, []);
useEffect(() => {
for (const transfer of transferNotifications) {
const { toChainId, status, txHash, toAmount } = transfer;
const { fromChainId, status, txHash, toAmount } = transfer;
const finished = Boolean(status) && status?.squidTransactionStatus !== 'ongoing';
const type = toChainId === TESTNET_CHAIN_ID ? 'deposit' : 'withdraw';
const type = fromChainId === TESTNET_CHAIN_ID ? 'withdrawal' : 'deposit';
// @ts-ignore status.errors is not in the type definition but can be returned
const error = status?.errors?.length ? status?.errors[0] : status?.error;
@@ -138,7 +153,8 @@ export const notificationTypes = [
{stringGetter({
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
params: {
ERROR_MESSAGE: error.message || stringGetter({ key: STRING_KEYS.UNKNOWN_ERROR }),
ERROR_MESSAGE:
error.message || stringGetter({ key: STRING_KEYS.UNKNOWN_ERROR }),
},
})}
</Styled.ErrorMessage>
@@ -154,6 +170,7 @@ export const notificationTypes = [
description: description,
customContent: (
<TransferStatusToast
type={type}
toAmount={transfer.toAmount}
triggeredAt={transfer.triggeredAt}
status={transfer.status}
@@ -162,7 +179,7 @@ export const notificationTypes = [
customMenuContent: !finished && (
<div>
{description}
<TransferStatusSteps status={transfer.status} />
<TransferStatusSteps status={transfer.status} type={type} />
</div>
),
toastSensitivity: 'foreground',
@@ -181,8 +198,8 @@ Styled.TransferText = styled.span`
display: inline-flex;
align-items: center;
gap: 0.5ch;
`
`;
Styled.ErrorMessage = styled.div`
max-width: 13rem;
`;
`;
+1 -14
View File
@@ -1,7 +1,6 @@
import { useCallback, useEffect } from 'react';
import { useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { DialogTypes } from '@/constants/dialogs';
import { LocalStorageKey } from '@/constants/localStorage';
import { DEFAULT_APP_ENVIRONMENT, DydxNetwork, ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
@@ -9,7 +8,6 @@ import { useAccounts, useLocalStorage } from '@/hooks';
import { setSelectedNetwork } from '@/state/app';
import { getSelectedNetwork } from '@/state/appSelectors';
import { openDialog } from '@/state/dialogs';
import { validateAgainstAvailableEnvironments } from '@/lib/network';
@@ -27,17 +25,6 @@ export const useSelectedNetwork = (): {
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(
(network: DydxNetwork) => {
disconnect();
+22 -17
View File
@@ -3,15 +3,10 @@ import { shallowEqual, useSelector, useDispatch } from 'react-redux';
import type { Nullable } from '@dydxprotocol/v4-abacus';
import Long from 'long';
import type { IndexedTx } from '@cosmjs/stargate';
import type { EncodeObject, Coin } from '@cosmjs/proto-signing';
import type { EncodeObject } from '@cosmjs/proto-signing';
import { Method } from '@cosmjs/tendermint-rpc';
import {
type LocalWallet,
SubaccountClient,
DYDX_DENOM,
USDC_DENOM,
} from '@dydxprotocol/v4-client-js';
import { type LocalWallet, SubaccountClient } from '@dydxprotocol/v4-client-js';
import type {
AccountBalance,
@@ -34,6 +29,7 @@ import { MustBigNumber } from '@/lib/numbers';
import { log } from '@/lib/telemetry';
import { useAccounts } from './useAccounts';
import { useTokenConfigs } from './useTokenConfigs';
import { useDydxClient } from './useDydxClient';
type SubaccountContextType = ReturnType<typeof useSubaccountContext>;
@@ -52,6 +48,7 @@ export const useSubaccount = () => useContext(SubaccountContext);
export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: LocalWallet }) => {
const dispatch = useDispatch();
const { usdcDenom } = useTokenConfigs();
const { compositeClient, faucetClient } = useDydxClient();
const { getFaucetFunds } = useMemo(
@@ -91,7 +88,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
}: {
subaccountClient: SubaccountClient;
amount: number;
}) => await compositeClient?.withdrawFromSubaccount(subaccountClient, amount),
}) => await compositeClient?.withdrawFromSubaccount(subaccountClient, amount.toString()),
transferFromSubaccountToAddress: async ({
subaccountClient,
@@ -134,12 +131,21 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
amount: number;
recipient: string;
}) =>
await compositeClient?.validatorClient.post.sendToken(
subaccountClient,
recipient,
DYDX_DENOM,
Long.fromNumber(amount * QUANTUM_MULTIPLIER),
await compositeClient?.validatorClient.post.send(
subaccountClient.wallet,
() =>
new Promise((resolve) => {
const msg = compositeClient?.sendTokenMessage(
subaccountClient.wallet,
amount.toString(),
recipient,
);
resolve([msg]);
}),
false,
compositeClient?.validatorClient?.post.defaultDydxGasPrice,
undefined,
Method.BroadcastTxCommit
),
@@ -156,7 +162,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
const transaction = JSON.parse(payload);
const msg = compositeClient.withdrawFromSubaccountMessage(subaccountClient, amount);
const msg = compositeClient.withdrawFromSubaccountMessage(subaccountClient, amount.toString());
const ibcMsg: EncodeObject = {
typeUrl: transaction.msgTypeUrl,
value: transaction.msg,
@@ -210,7 +216,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
);
const balances = useSelector(getBalances, shallowEqual);
const usdcCoinBalance = balances?.[USDC_DENOM];
const usdcCoinBalance = balances?.[usdcDenom];
useEffect(() => {
if (usdcCoinBalance) {
@@ -247,8 +253,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
if (!subaccountClient) {
return;
}
return (await (coinDenom === USDC_DENOM
return (await (coinDenom === usdcDenom
? transferFromSubaccountToAddress
: transferNativeToken)({ subaccountClient, amount, recipient })) as IndexedTx;
},
+36
View File
@@ -0,0 +1,36 @@
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { DydxChainAsset } from '@/constants/wallets';
import { useSelectedNetwork } from '@/hooks';
export const useTokenConfigs = (): {
tokensConfigs: {
[DydxChainAsset.USDC]: {
denom: string;
name: string;
decimals: number;
gasDenom?: string;
},
[DydxChainAsset.CHAINTOKEN]: {
denom: string;
name: string;
decimals: number;
gasDenom?: string;
},
};
usdcDenom: string;
usdcLabel: string;
chainTokenDenom: string;
chainTokenLabel: string;
} => {
const { selectedNetwork } = useSelectedNetwork();
const tokensConfigs = ENVIRONMENT_CONFIG_MAP[selectedNetwork].tokens;
return {
tokensConfigs,
usdcDenom: tokensConfigs[DydxChainAsset.USDC].denom,
usdcLabel: tokensConfigs[DydxChainAsset.USDC].name,
chainTokenDenom: tokensConfigs[DydxChainAsset.CHAINTOKEN].denom,
chainTokenLabel: tokensConfigs[DydxChainAsset.CHAINTOKEN].name,
};
};
+10 -1
View File
@@ -1,6 +1,8 @@
import { useCallback, useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { LocalStorageKey } from '@/constants/localStorage';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import {
type DydxAddress,
@@ -28,6 +30,8 @@ import {
WalletType as CosmosWalletType,
} from 'graz';
import { getSelectedNetwork } from '@/state/appSelectors';
import { resolveWagmiConnector } from '@/lib/wagmi';
import { getWalletConnection, parseWalletError } from '@/lib/wallet';
import { log } from '@/lib/telemetry';
@@ -84,6 +88,9 @@ export const useWalletConnection = () => {
// Wallet connection
const selectedNetwork = useSelector(getSelectedNetwork);
const walletConnectConfig = ENVIRONMENT_CONFIG_MAP[selectedNetwork].wallets.walletconnect;
const { connectAsync: connectWagmi } =
walletType && walletConnectionType
? useConnectWagmi({
@@ -92,6 +99,7 @@ export const useWalletConnection = () => {
walletConnection: {
type: walletConnectionType,
},
walletConnectConfig,
}),
})
: useConnectWagmi();
@@ -127,6 +135,7 @@ export const useWalletConnection = () => {
connector: resolveWagmiConnector({
walletType,
walletConnection,
walletConnectConfig,
}),
});
}
@@ -217,7 +226,7 @@ export const useWalletConnection = () => {
evmAddressWagmi,
signerWagmi,
publicClientWagmi,
// Wallet connection (Cosmos)
dydxAddress,
dydxAddressGraz,
+3
View File
@@ -0,0 +1,3 @@
<svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.3811 13.235C11.9338 13.0512 13.4593 12.6847 14.9261 12.1433C13.6839 10.7673 12.9975 8.97875 13.0003 7.125V6.54167V6.5C13.0003 5.17392 12.4735 3.90215 11.5358 2.96447C10.5981 2.02678 9.32636 1.5 8.00028 1.5C6.67419 1.5 5.40242 2.02678 4.46474 2.96447C3.52706 3.90215 3.00028 5.17392 3.00028 6.5V7.125C3.00279 8.97886 2.3161 10.7675 1.07361 12.1433C2.51778 12.6767 4.04027 13.0475 5.61944 13.235M10.3811 13.235C8.79943 13.4226 7.20112 13.4226 5.61944 13.235M10.3811 13.235C10.5012 13.6099 10.5311 14.0078 10.4683 14.3964C10.4055 14.785 10.2518 15.1533 10.0198 15.4713C9.78772 15.7893 9.48386 16.048 9.13293 16.2263C8.78201 16.4047 8.39392 16.4976 8.00028 16.4976C7.60663 16.4976 7.21854 16.4047 6.86762 16.2263C6.51669 16.048 6.21283 15.7893 5.98079 15.4713C5.74875 15.1533 5.59508 14.785 5.53229 14.3964C5.46949 14.0078 5.49936 13.6099 5.61944 13.235" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

+1 -1
View File
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 24"><path fill="currentColor" d="M11 0C8.5 0 6.101.948 4.333 2.636 2.565 4.324 1.57 6.613 1.57 9v5.379l-1.11 1.06c-.22.21-.37.477-.43.768-.061.291-.03.593.089.867s.32.508.578.673c.259.165.562.253.873.253h18.86c.31 0 .614-.088.873-.253.258-.165.46-.399.578-.673.12-.274.15-.576.09-.867a1.48 1.48 0 0 0-.43-.768l-1.111-1.06V9c0-2.387-.993-4.676-2.762-6.364C15.9.948 13.501 0 11 0Zm0 24a4.83 4.83 0 0 1-3.334-1.318 4.399 4.399 0 0 1-1.38-3.182h9.428a4.399 4.399 0 0 1-1.38 3.182A4.83 4.83 0 0 1 11 24Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 24"><path fill="currentColor" d="M11 0C8.5 0 6.101.948 4.333 2.636 2.565 4.324 1.57 6.613 1.57 9v5.379l-1.11 1.06c-.22.21-.37.477-.43.768-.061.291-.03.593.089.867s.32.508.578.673c.259.165.562.253.873.253h18.86c.31 0 .614-.088.873-.253.258-.165.46-.399.578-.673.12-.274.15-.576.09-.867a1.48 1.48 0 0 0-.43-.768l-1.111-1.06V9c0-2.387-.993-4.676-2.762-6.364C15.9.948 13.501 0 11 0Zm0 24a4.83 4.83 0 0 1-3.334-1.318 4.399 4.399 0 0 1-1.38-3.182h9.428a4.399 4.399 0 0 1-1.38 3.182A4.83 4.83 0 0 1 11 24Z"/></svg>

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 564 B

+1
View File
@@ -2,6 +2,7 @@ export { default as AddressConnectorIcon } from './address-connector.svg';
export { default as ArrowIcon } from './arrow.svg';
export { default as Bar3Icon } from './bar3.svg';
export { default as BellIcon } from './bell.svg';
export { default as BellStrokeIcon } from './bell-stroke.svg';
export { default as BoxCloseIcon } from './box-close.svg';
export { default as CalculatorIcon } from './calculator.svg';
export { default as CaretIcon } from './caret-down.svg';
+15 -10
View File
@@ -6,8 +6,9 @@ import { ButtonShape } from '@/constants/buttons';
import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization';
import { AppRoute } from '@/constants/routes';
import { useStringGetter } from '@/hooks';
import { LogoShortIcon, BellIcon } from '@/icons';
import { LogoShortIcon, BellStrokeIcon } from '@/icons';
import { useTokenConfigs, useStringGetter } from '@/hooks';
import { Icon, IconName } from '@/components/Icon';
import { IconButton } from '@/components/IconButton';
@@ -27,6 +28,7 @@ import { layoutMixins } from '@/styles/layoutMixins';
export const HeaderDesktop = () => {
const stringGetter = useStringGetter();
const dispatch = useDispatch();
const { chainTokenLabel } = useTokenConfigs();
const navItems = [
{
@@ -43,9 +45,9 @@ export const HeaderDesktop = () => {
href: AppRoute.Trade,
},
{
value: 'Dv4TNT',
label: 'Dv4TNT',
href: AppRoute.Rewards,
value: chainTokenLabel,
label: chainTokenLabel,
href: `/${chainTokenLabel}`,
},
{
value: 'PORTFOLIO',
@@ -78,13 +80,13 @@ export const HeaderDesktop = () => {
value: 'TERMS_OF_USE',
slotBefore: <Icon iconName={IconName.File} />,
label: stringGetter({ key: STRING_KEYS.TERMS_OF_USE }),
href: 'https://dydx.exchange/terms',
href: AppRoute.Terms,
},
{
value: 'PRIVACY_POLICY',
slotBefore: <Icon iconName={IconName.Privacy} />,
label: stringGetter({ key: STRING_KEYS.PRIVACY_POLICY }),
href: 'https://dydx.exchange/privacy',
href: AppRoute.Privacy,
},
{
value: 'HELP',
@@ -131,7 +133,9 @@ export const HeaderDesktop = () => {
<VerticalSeparator />
<NotificationsMenu
slotTrigger={<Styled.IconButton shape={ButtonShape.Rectangle} iconComponent={BellIcon} />}
slotTrigger={
<Styled.IconButton shape={ButtonShape.Rectangle} iconComponent={BellStrokeIcon} />
}
/>
<VerticalSeparator />
@@ -165,7 +169,7 @@ Styled.Header = styled.header`
)
var(--border-width) 1fr var(--border-width) auto;
font-size: 0.9375em;
font-size: 0.9375rem;
:before {
backdrop-filter: blur(10px);
@@ -214,7 +218,8 @@ Styled.NavAfter = styled.div`
}
`;
Styled.IconButton = styled(IconButton)`
Styled.IconButton = styled(IconButton)<{ size?: string }>`
${headerMixins.button}
--button-border: none;
--button-icon-size: 1rem;
`;
+49 -34
View File
@@ -14,8 +14,6 @@ import {
OrderSide,
OrderTimeInForce,
OrderExecution,
DYDX_DENOM,
GAS_PRICE_DYDX_DENOM,
} from '@dydxprotocol/v4-client-js';
import {
@@ -61,22 +59,42 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
}
async connectNetwork(
indexerUrl: string,
indexerSocketUrl: string,
validatorUrl: string,
chainId: string,
faucetUrl: Nullable<string> | undefined,
paramsInJson: Nullable<string>,
callback: (p0: Nullable<string>) => void
): Promise<void> {
try {
const parsedParams = paramsInJson ? JSON.parse(paramsInJson) : {};
const {
indexerUrl,
websocketUrl,
validatorUrl,
chainId,
USDC_DENOM,
USDC_DECIMALS,
USDC_GAS_DENOM,
CHAINTOKEN_DENOM,
CHAINTOKEN_DECIMALS,
} = parsedParams;
const compositeClient = await CompositeClient.connect(
new Network(
chainId,
new IndexerConfig(indexerUrl, indexerSocketUrl),
new ValidatorConfig(validatorUrl, chainId, {
broadcastPollIntervalMs: 3_000,
broadcastTimeoutMs: 60_000,
})
new IndexerConfig(indexerUrl, websocketUrl),
new ValidatorConfig(
validatorUrl,
chainId,
{
USDC_DENOM,
USDC_DECIMALS,
USDC_GAS_DENOM,
CHAINTOKEN_DENOM,
CHAINTOKEN_DECIMALS,
},
{
broadcastPollIntervalMs: 3_000,
broadcastTimeoutMs: 60_000,
}
)
)
);
@@ -84,13 +102,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
// Dispatch custom event to notify other parts of the app that the network has been connected
const customEvent = new CustomEvent('abacus:connectNetwork', {
detail: {
indexerUrl,
indexerSocketUrl,
validatorUrl,
chainId,
faucetUrl,
},
detail: parsedParams,
});
globalThis.dispatchEvent(customEvent);
@@ -99,9 +111,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
this.store?.dispatch(
openDialog({ type: DialogTypes.ExchangeOffline, dialogProps: { preventClose: true } })
);
log('DydxChainTransactions/connectNetwork', error);
return;
}
}
@@ -213,13 +223,13 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
params ?? {};
try {
const tx = await this.compositeClient?.cancelOrder(
const tx = await this.compositeClient?.cancelRawOrder(
new SubaccountClient(this.localWallet, subaccountNumber),
clientId,
orderFlags,
clobPairId,
goodTilBlock ?? undefined,
goodTilBlockTime ?? undefined
goodTilBlock || undefined,
goodTilBlockTime || undefined,
);
const parsedTx = this.parseToPrimitives(tx);
@@ -251,7 +261,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
const msg = compositeClient.withdrawFromSubaccountMessage(subaccountClient, amount);
resolve([msg]);
}),
})
);
const parsedTx = this.parseToPrimitives(tx);
@@ -266,7 +276,9 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
}
}
async simulateTransferNativeTokenTransaction(params: HumanReadableTransferPayload): Promise<string> {
async simulateTransferNativeTokenTransaction(
params: HumanReadableTransferPayload
): Promise<string> {
if (!this.compositeClient || !this.localWallet) {
throw new Error('Missing compositeClient or localWallet');
}
@@ -280,16 +292,18 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
this.localWallet,
() =>
new Promise((resolve) => {
const msg = compositeClient?.validatorClient.post.composer.composeMsgSendToken(
subaccountClient.address,
if (!this.localWallet) {
throw new Error('Missing compositeClient or localWallet');
}
const msg = compositeClient?.sendTokenMessage(
this.localWallet,
amount,
recipient,
DYDX_DENOM,
Long.fromNumber(amount * QUANTUM_MULTIPLIER)
);
resolve([msg]);
}),
GAS_PRICE_DYDX_DENOM,
this.compositeClient?.validatorClient?.post.defaultDydxGasPrice,
);
const parsedTx = this.parseToPrimitives(tx);
@@ -397,9 +411,10 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
break;
case QueryType.GetAccountBalances:
if (!this.localWallet?.address) throw new Error('Missing localWallet');
const accountBalances = await this.compositeClient?.validatorClient.get.getAccountBalances(
this.localWallet.address
);
const accountBalances =
await this.compositeClient?.validatorClient.get.getAccountBalances(
this.localWallet.address
);
const parsedAccountBalances = this.parseToPrimitives(accountBalances);
callback(JSON.stringify(parsedAccountBalances));
break;
+45 -36
View File
@@ -36,7 +36,15 @@ import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet';
import { InjectedConnector } from 'wagmi/connectors/injected';
import { MetaMaskConnector } from 'wagmi/connectors/metaMask';
import { WalletConnectConnector } from 'wagmi/connectors/walletConnect';
import { WalletConnectLegacyConnector } from 'wagmi/connectors/walletConnectLegacy';
import {
type WalletConnection,
WalletConnectionType,
type WalletType,
walletConnectionTypes,
wallets,
WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS,
} from '@/constants/wallets';
// Config
@@ -87,44 +95,46 @@ const injectedConnectorOptions = {
},
};
const walletconnect2ConnectorOptions: ConstructorParameters<typeof WalletConnectConnector>[0] = {
type WalletConnectConfig = {
client: {
name: string;
description: string;
iconUrl: string;
};
v2: {
projectId: string;
};
};
const getWalletconnect2ConnectorOptions = (
config: WalletConnectConfig
): ConstructorParameters<typeof WalletConnectConnector>[0] => ({
chains,
options: {
projectId: import.meta.env.VITE_WALLETCONNECT2_PROJECT_ID,
projectId: config.v2.projectId,
metadata: {
name: 'dYdX',
description: '',
name: config.client.name,
description: config.client.description,
url: import.meta.env.VITE_BASE_URL,
icons: [`${import.meta.env.VITE_BASE_URL}/cbw-image.png}`],
icons: [config.client.iconUrl],
},
showQrModal: true,
qrModalOptions: {
themeMode: 'dark' as const,
themeVariables: {
'--w3m-accent-color': '#5973fe',
'--w3m-background-color': '#5973fe',
'--w3m-color-bg-1': 'var(--color-layer-3)',
'--w3m-color-bg-2': 'var(--color-layer-4)',
'--w3m-color-bg-3': 'var(--color-layer-5)',
'--w3m-font-family': 'var(--fontFamily-base)',
'--w3m-font-feature-settings': 'none',
'--w3m-overlay-backdrop-filter': 'blur(6px)',
// '--w3m-logo-image-url': 'https://trade.dydx.exchange/cbw-image.png',
'--wcm-accent-color': '#5973fe',
'--wcm-font-family': 'var(--fontFamily-base)',
},
enableExplorer: true,
explorerAllowList: [],
explorerDenyList: [],
chainImages: {},
explorerRecommendedWalletIds: WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS,
},
},
};
});
const connectors = [
const getConnectors = (walletConnectConfig: WalletConnectConfig) => [
new MetaMaskConnector({
chains,
options: {
shimDisconnect: true,
shimChainChangedDisconnect: false,
},
}),
new CoinbaseWalletConnector({
@@ -134,7 +144,7 @@ const connectors = [
reloadOnDisconnect: false,
},
}),
new WalletConnectConnector(walletconnect2ConnectorOptions),
new WalletConnectConnector(getWalletconnect2ConnectorOptions(walletConnectConfig)),
new InjectedConnector(injectedConnectorOptions),
];
@@ -156,35 +166,34 @@ const createInjectedConnectorWithProvider = (provider: ExternalProvider) =>
provider as unknown as Awaited<ReturnType<InjectedConnector['getProvider']>>;
})(injectedConnectorOptions) as InjectedConnector;
const createWalletConnect2ConnectorWithId = (walletconnect2Id: string) =>
new WalletConnectConnector({
const createWalletConnect2ConnectorWithId = (
walletconnectId: string,
walletConnectConfig: WalletConnectConfig
) => {
const walletconnect2ConnectorOptions = getWalletconnect2ConnectorOptions(walletConnectConfig);
return new WalletConnectConnector({
...walletconnect2ConnectorOptions,
options: {
...walletconnect2ConnectorOptions.options,
qrModalOptions: {
...walletconnect2ConnectorOptions.options.qrModalOptions,
explorerRecommendedWalletIds: [walletconnect2Id],
explorerRecommendedWalletIds: [walletconnectId],
explorerExcludedWalletIds: 'ALL',
chainImages: {},
},
},
});
};
// Custom connector from wallet selection
import {
type WalletConnection,
WalletConnectionType,
type WalletType,
walletConnectionTypes,
wallets,
} from '@/constants/wallets';
export const resolveWagmiConnector = ({
walletType,
walletConnection,
walletConnectConfig,
}: {
walletType: WalletType;
walletConnection: WalletConnection;
walletConnectConfig: WalletConnectConfig;
}) => {
const walletConfig = wallets[walletType];
const walletConnectionConfig = walletConnectionTypes[walletConnection.type];
@@ -192,6 +201,6 @@ export const resolveWagmiConnector = ({
return walletConnection.type === WalletConnectionType.InjectedEip1193 && walletConnection.provider
? createInjectedConnectorWithProvider(walletConnection.provider)
: walletConnection.type === WalletConnectionType.WalletConnect2 && walletConfig.walletconnect2Id
? createWalletConnect2ConnectorWithId(walletConfig.walletconnect2Id)
: connectors.find(({ id }: { id: string }) => id === walletConnectionConfig.wagmiConnectorId);
? createWalletConnect2ConnectorWithId(walletConfig.walletconnect2Id, walletConnectConfig)
: getConnectors(walletConnectConfig).find(({ id }: { id: string }) => id === walletConnectionConfig.wagmiConnectorId);
};
+17
View File
@@ -0,0 +1,17 @@
import styled, { AnyStyledComponent } from 'styled-components';
import { articleMixins } from '@/styles/articleMixins';
export const PrivacyPolicyPage = () => (
<Styled.Article>
<header>
<h1>Privacy Policy</h1>
</header>
</Styled.Article>
);
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Article = styled.article`
${articleMixins.article}
`;
+17
View File
@@ -0,0 +1,17 @@
import styled, { AnyStyledComponent } from 'styled-components';
import { articleMixins } from '@/styles/articleMixins';
export const TermsOfUsePage = () => (
<Styled.Article>
<header>
<h1>Terms of Use</h1>
</header>
</Styled.Article>
);
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Article = styled.article`
${articleMixins.article}
`;
+10 -4
View File
@@ -3,7 +3,7 @@ import styled, { AnyStyledComponent } from 'styled-components';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { layoutMixins } from '@/styles/layoutMixins';
import { useAccountBalance, useAccounts, useStringGetter } from '@/hooks';
import { useAccountBalance, useAccounts, useTokenConfigs, useStringGetter } from '@/hooks';
import { ButtonAction, ButtonSize } from '@/constants/buttons';
import { DialogTypes } from '@/constants/dialogs';
@@ -30,6 +30,7 @@ export const DYDXBalancePanel = () => {
const { walletType } = useAccounts();
const canAccountTrade = useSelector(calculateCanAccountTrade, shallowEqual);
const { nativeTokenBalance, nativeStakingBalance } = useAccountBalance();
const { chainTokenLabel } = useTokenConfigs();
return (
<Panel
@@ -37,7 +38,7 @@ export const DYDXBalancePanel = () => {
<Styled.Header>
<Styled.Title>
{/* <AssetIcon symbol="DYDX" /> */}
Dv4TNT
{chainTokenLabel}
</Styled.Title>
<Styled.ReceiveAndTransferButtons>
{!canAccountTrade ? (
@@ -106,7 +107,13 @@ export const DYDXBalancePanel = () => {
{
key: 'totalBalance',
label: 'Total balance',
value: <Output type={OutputType.Asset} value={nativeTokenBalance + nativeStakingBalance} tag="Dv4TNT" />,
value: (
<Output
type={OutputType.Asset}
value={nativeTokenBalance + nativeStakingBalance}
tag={chainTokenLabel}
/>
),
},
]}
/>
@@ -174,7 +181,6 @@ Styled.WalletAndStakedBalance = styled(Details)`
grid-template-columns: 1fr 1fr;
gap: 0.5rem;
> div {
gap: 1rem;
+2
View File
@@ -24,6 +24,8 @@ export const dialogsSlice = createSlice({
initialState,
reducers: {
openDialog: (state: DialogsState, action: PayloadAction<DialogInfo<DialogTypes>>) => {
if (state.activeDialog?.type === action.payload.type) return;
if (state.activeDialog) {
state.dialogQueue.push(action.payload);
} else {
+53
View File
@@ -0,0 +1,53 @@
import {
css,
type FlattenInterpolation,
type FlattenSimpleInterpolation,
type ThemeProps,
} from 'styled-components';
export const articleMixins: Record<
string,
FlattenSimpleInterpolation | FlattenInterpolation<ThemeProps<any>>
> = {
article: css`
padding: 2rem;
overflow-wrap: break-word;
user-select: text;
margin: 0 auto;
width: 60rem;
max-width: 100vw;
header {
color: var(--color-text-0);
margin-bottom: 2rem;
h1 {
font: var(--font-extra-book);
color: var(--color-text-2);
}
}
h2 {
font: var(--font-large-book);
color: var(--color-text-2);
padding: 0.5rem 0;
}
h3,
strong {
font-weight: 700;
}
strong {
color: var(--color-text-2);
}
p {
padding: 0.5rem 0;
}
ul {
padding: 0.5rem 1rem;
}
`,
};
@@ -75,16 +75,14 @@ export const AccountInfoConnectedState = () => {
<Styled.Header>
<span>{stringGetter({ key: STRING_KEYS.ACCOUNT })}</span>
<Styled.TransferButtons>
{import.meta.env.MODE !== 'production' && (
<Styled.Button
state={{ isDisabled: !dydxAccounts }}
onClick={() => dispatch(openDialog({ type: DialogTypes.Withdraw }))}
shape={ButtonShape.Pill}
size={ButtonSize.XSmall}
>
{stringGetter({ key: STRING_KEYS.WITHDRAW })}
</Styled.Button>
)}
<Styled.Button
state={{ isDisabled: !dydxAccounts }}
onClick={() => dispatch(openDialog({ type: DialogTypes.Withdraw }))}
shape={ButtonShape.Pill}
size={ButtonSize.XSmall}
>
{stringGetter({ key: STRING_KEYS.WITHDRAW })}
</Styled.Button>
<Styled.Button
state={{ isDisabled: !dydxAccounts }}
onClick={() => dispatch(openDialog({ type: DialogTypes.Deposit }))}
+3 -7
View File
@@ -1,6 +1,5 @@
import { useCallback, useState, useMemo } from 'react';
import styled, { type AnyStyledComponent } from 'styled-components';
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
import { Root, Trigger, Content } from '@radix-ui/react-collapsible';
import { StatusResponse } from '@0xsquid/sdk';
@@ -21,12 +20,14 @@ import { LoadingDots } from '@/components/Loading/LoadingDots';
import { layoutMixins } from '@/styles/layoutMixins';
type ElementProps = {
type: 'withdrawal' | 'deposit';
toAmount?: number;
triggeredAt?: number;
status?: StatusResponse;
};
export const TransferStatusToast = ({
type,
toAmount,
triggeredAt = Date.now(),
status,
@@ -38,11 +39,6 @@ export const TransferStatusToast = ({
// @ts-ignore status.errors is not in the type definition but can be returned
const error = status?.errors?.length ? status?.errors[0] : status?.error;
const type = useMemo(
() => (status?.toChain?.chainData?.chainId === TESTNET_CHAIN_ID ? 'deposit' : 'withdrawal'),
[status]
);
const updateSecondsLeft = useCallback(() => {
const fromChainEta = (status?.fromChain?.chainData?.estimatedRouteDuration || 0) * 1000;
const toChainEta = (status?.toChain?.chainData?.estimatedRouteDuration || 0) * 1000;
@@ -69,7 +65,7 @@ export const TransferStatusToast = ({
side="bottom"
slotReceipt={
<Styled.Receipt>
<TransferStatusSteps status={status} />
<TransferStatusSteps status={status} type={type} />
</Styled.Receipt>
}
>
+7 -4
View File
@@ -1,7 +1,6 @@
import { useMemo } from 'react';
import styled, { css, keyframes, type AnyStyledComponent } from 'styled-components';
import { StatusResponse } from '@0xsquid/sdk';
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
import { useStringGetter } from '@/hooks';
@@ -15,6 +14,7 @@ import { STRING_KEYS } from '@/constants/localization';
type ElementProps = {
status?: StatusResponse;
type: 'withdrawal' | 'deposit';
};
enum TransferStatusStep {
@@ -24,14 +24,13 @@ enum TransferStatusStep {
Complete,
}
export const TransferStatusSteps = ({ status }: ElementProps) => {
export const TransferStatusSteps = ({ status, type }: ElementProps) => {
const stringGetter = useStringGetter();
const { currentStep, steps, type } = useMemo(() => {
const { currentStep, steps } = useMemo(() => {
const routeStatus = status?.routeStatus;
const fromChain = status?.fromChain?.chainData?.chainId;
const toChain = status?.toChain?.chainData?.chainId;
const type = toChain === TESTNET_CHAIN_ID ? 'deposit' : 'withdrawal';
const steps = [
{
@@ -74,6 +73,10 @@ export const TransferStatusSteps = ({ status }: ElementProps) => {
currentStep = TransferStatusStep.FromChain;
}
if (status?.squidTransactionStatus === 'success') {
currentStep = TransferStatusStep.Complete;
}
return {
currentStep,
steps,
+3 -6
View File
@@ -32,12 +32,9 @@ export const DepositDialog = ({ setIsOpen }: ElementProps) => {
>
<Styled.Content>
{showTestDeposit ? <TestnetDepositForm onDeposit={closeDialog} /> : <DepositForm />}
{/* TODO TRCL-1693 - uncomment when deposit form is ready */}
{import.meta.env.MODE !== 'production' && (
<Styled.TextToggle onClick={() => setShowTestDeposit(!showTestDeposit)}>
{showTestDeposit ? 'Show deposit form (Under Construction)' : 'Show test faucet'}
</Styled.TextToggle>
)}
<Styled.TextToggle onClick={() => setShowTestDeposit(!showTestDeposit)}>
{showTestDeposit ? 'Show deposit form (Under Construction)' : 'Show test faucet'}
</Styled.TextToggle>
</Styled.Content>
</Dialog>
);
+2 -21
View File
@@ -5,8 +5,6 @@ import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { AbacusApiStatus } from '@/constants/abacus';
import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { UNICODE } from '@/constants/unicode';
import { useApiState, useStringGetter } from '@/hooks';
import { layoutMixins } from '@/styles/layoutMixins';
@@ -32,16 +30,8 @@ export const ExchangeOfflineDialog = ({ preventClose, setIsOpen }: ElementProps)
const selectedNetwork = useSelector(getSelectedNetwork);
const activeDialog = useSelector(getActiveDialog, shallowEqual);
const showOfflineMessage =
import.meta.env.MODE === 'production' &&
ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId === 'dydx-testnet-3';
useEffect(() => {
if (
activeDialog?.type === DialogTypes.ExchangeOffline &&
status === AbacusApiStatus.NORMAL &&
!showOfflineMessage
) {
if (activeDialog?.type === DialogTypes.ExchangeOffline && status === AbacusApiStatus.NORMAL) {
dispatch(closeDialog());
}
}, [status, selectedNetwork]);
@@ -54,16 +44,7 @@ export const ExchangeOfflineDialog = ({ preventClose, setIsOpen }: ElementProps)
title={stringGetter({ key: STRING_KEYS.UNAVAILABLE })}
>
<Styled.Content>
{showOfflineMessage ? (
<>
<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>
)}
<p>{statusErrorMessage}</p>
{import.meta.env.MODE !== 'production' && <NetworkSelectMenu />}
</Styled.Content>
</Dialog>
+11 -4
View File
@@ -37,7 +37,7 @@ export const OnboardingDialog = ({ setIsOpen }: ElementProps) => {
const stringGetter = useStringGetter();
const { isMobile } = useBreakpoints();
const { walletType } = useAccounts();
const { disconnect, walletType } = useAccounts();
const currentOnboardingStep = useSelector(calculateOnboardingStep);
@@ -45,10 +45,17 @@ export const OnboardingDialog = ({ setIsOpen }: ElementProps) => {
if (!currentOnboardingStep) setIsOpen?.(false);
}, [currentOnboardingStep]);
const setIsOpenFromDialog = (open: boolean) => {
if (!open && currentOnboardingStep === OnboardingSteps.AcknowledgeTerms) {
disconnect();
}
setIsOpen?.(open);
}
return (
<Styled.Dialog
isOpen={Boolean(currentOnboardingStep)}
setIsOpen={setIsOpen}
setIsOpen={setIsOpenFromDialog}
{...(currentOnboardingStep &&
{
[OnboardingSteps.ChooseWallet]: {
@@ -87,10 +94,10 @@ export const OnboardingDialog = ({ setIsOpen }: ElementProps) => {
title: stringGetter({ key: STRING_KEYS.ACKNOWLEDGE_TERMS }),
children: (
<Styled.Content>
<AcknowledgeTerms />
<AcknowledgeTerms onClose={() => setIsOpenFromDialog?.(false)} />
</Styled.Content>
),
width: '20rem',
width: '30rem',
},
[OnboardingSteps.DepositFunds]: {
title: stringGetter({ key: STRING_KEYS.DEPOSIT }),
@@ -2,17 +2,21 @@ import styled, { type AnyStyledComponent } from 'styled-components';
import { useAccounts, useStringGetter } from '@/hooks';
import { AppRoute } from '@/constants/routes';
import { STRING_KEYS } from '@/constants/localization';
import { ButtonAction } from '@/constants/buttons';
import { layoutMixins } from '@/styles/layoutMixins';
import { Button } from '@/components/Button';
import { Link } from '@/components/Link';
type ElementProps = {
onClose?: () => void;
onContinue?: () => void;
};
export const AcknowledgeTerms = ({ onContinue }: ElementProps) => {
export const AcknowledgeTerms = ({ onClose, onContinue }: ElementProps) => {
const stringGetter = useStringGetter();
const { saveHasAcknowledgedTerms } = useAccounts();
@@ -24,26 +28,40 @@ export const AcknowledgeTerms = ({ onContinue }: ElementProps) => {
return (
<>
<span>
<p>
{stringGetter({
key: STRING_KEYS.LEGAL_UPDATES_DESCRIPTION,
key: STRING_KEYS.TOS_TITLE,
params: {
TOU: (
<Styled.Link href="https://dydx.exchange/v4-terms">
TERMS_LINK: (
<Styled.Link href={`/#${AppRoute.Terms}`}>
{stringGetter({ key: STRING_KEYS.TERMS_OF_USE })}
</Styled.Link>
),
PRIVACY_POLICY: (
<Styled.Link href="https://dydx.exchange/privacy">
PRIVACY_POLICY_LINK: (
<Styled.Link href={`/#${AppRoute.Privacy}`}>
{stringGetter({ key: STRING_KEYS.PRIVACY_POLICY })}
</Styled.Link>
),
},
})}
</span>
<Button onClick={onAcknowledgement} action={ButtonAction.Primary}>
{stringGetter({ key: STRING_KEYS.I_AGREE })}
</Button>
</p>
<Styled.TOS>
<ul>
<li>{stringGetter({ key: STRING_KEYS.TOS_LINE1 })}</li>
<li>{stringGetter({ key: STRING_KEYS.TOS_LINE2 })}</li>
<li>{stringGetter({ key: STRING_KEYS.TOS_LINE3 })}</li>
<li>{stringGetter({ key: STRING_KEYS.TOS_LINE4 })}</li>
<li>{stringGetter({ key: STRING_KEYS.TOS_LINE5 })}</li>
</ul>
</Styled.TOS>
<Styled.Row>
<Styled.Button onClick={onClose} action={ButtonAction.Base}>
{stringGetter({ key: STRING_KEYS.CLOSE })}
</Styled.Button>
<Styled.Button onClick={onAcknowledgement} action={ButtonAction.Primary}>
{stringGetter({ key: STRING_KEYS.I_AGREE })}
</Styled.Button>
</Styled.Row>
</>
);
};
@@ -58,3 +76,23 @@ Styled.Link = styled(Link)`
color: var(--color-accent);
}
`;
Styled.TOS = styled.section`
background-color: var(--color-layer-4);
padding: 1rem 1rem 1rem 2rem;
border-radius: 0.875rem;
> ul {
${layoutMixins.column};
gap: 1rem;
}
`;
Styled.Row = styled.div`
${layoutMixins.row};
gap: 1rem;
`;
Styled.Button = styled(Button)`
flex-grow: 1;
`;
@@ -264,7 +264,6 @@ const Styled: Record<string, AnyStyledComponent> = {};
Styled.StatusCardsContainer = styled.div`
display: grid;
margin-top: 1rem;
gap: 1rem;
`;
+7 -5
View File
@@ -6,7 +6,7 @@ import { DydxChainAsset } from '@/constants/wallets';
import { formMixins } from '@/styles/formMixins';
import { layoutMixins } from '@/styles/layoutMixins';
import { useAccounts, useStringGetter } from '@/hooks';
import { useAccounts, useTokenConfigs, useStringGetter } from '@/hooks';
import { AssetIcon } from '@/components/AssetIcon';
import { CopyButton } from '@/components/CopyButton';
@@ -24,9 +24,10 @@ type ElementProps = {
setIsOpen: (open: boolean) => void;
};
export const ReceiveDialog = ({ selectedAsset = DydxChainAsset.DYDX, setIsOpen }: ElementProps) => {
export const ReceiveDialog = ({ selectedAsset = DydxChainAsset.CHAINTOKEN, setIsOpen }: ElementProps) => {
const stringGetter = useStringGetter();
const { dydxAddress } = useAccounts();
const { chainTokenLabel, usdcLabel } = useTokenConfigs();
const [asset, setAsset] = useState(selectedAsset);
@@ -35,16 +36,17 @@ export const ReceiveDialog = ({ selectedAsset = DydxChainAsset.DYDX, setIsOpen }
value: DydxChainAsset.USDC,
label: (
<Styled.InlineRow>
<AssetIcon symbol="USDC" /> USDC
<AssetIcon symbol="USDC" /> {usdcLabel}
</Styled.InlineRow>
),
},
{
value: DydxChainAsset.DYDX,
value: DydxChainAsset.CHAINTOKEN,
label: (
<Styled.InlineRow>
{/* TODO: conditionally display the native token assetIcon */}
{/* <AssetIcon symbol="DYDX" /> */}
Dv4TNT
{chainTokenLabel}
</Styled.InlineRow>
),
},
@@ -29,7 +29,7 @@ export const AdvancedTradeOptions = () => {
const currentTradeFormConfig = useSelector(getInputTradeOptions, shallowEqual);
const inputTradeData = useSelector(getInputTradeData, shallowEqual);
const { execution, goodTil, postOnly, reduceOnly, timeInForce } = inputTradeData || {};
const { execution, goodTil, postOnly, reduceOnly, timeInForce, type } = inputTradeData || {};
const { executionOptions, needsGoodUntil, needsPostOnly, needsReduceOnly, timeInForceOptions } =
currentTradeFormConfig || {};
@@ -37,6 +37,7 @@ export const AdvancedTradeOptions = () => {
const { duration, unit } = goodTil || {};
const needsExecution = executionOptions || needsPostOnly || needsReduceOnly;
const hasTimeInForce = timeInForceOptions?.toArray()?.length;
return (
<Styled.Collapsible
@@ -47,7 +48,7 @@ export const AdvancedTradeOptions = () => {
>
<Styled.AdvancedInputsContainer>
<Styled.AdvancedInputsRow needsGoodUntil={needsGoodUntil}>
{timeInForceOptions?.toArray() && (
{hasTimeInForce && (
<Styled.SelectMenu
value={timeInForce}
onValueChange={(selectedTimeInForceOption: string) =>
@@ -72,7 +73,9 @@ export const AdvancedTradeOptions = () => {
id="trade-good-til-time"
type={InputType.Number}
decimals={INTEGER_DECIMALS}
label={stringGetter({ key: STRING_KEYS.TIME })}
label={stringGetter({
key: hasTimeInForce ? STRING_KEYS.TIME : STRING_KEYS.GOOD_TIL_TIME,
})}
onChange={({ value }: NumberFormatValues) => {
abacusStateManager.setTradeValue({
value: Number(value),
+10 -12
View File
@@ -11,11 +11,7 @@ import { ButtonShape, ButtonSize } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { NumberSign } from '@/constants/numbers';
import {
DYDX_CHAIN_ASSET_COIN_DENOM,
DYDX_CHAIN_ASSET_TAGS,
DydxChainAsset,
} from '@/constants/wallets';
import { DydxChainAsset } from '@/constants/wallets';
import {
useAccountBalance,
@@ -25,6 +21,7 @@ import {
useSelectedNetwork,
useStringGetter,
useSubaccount,
useTokenConfigs,
} from '@/hooks';
import { formMixins } from '@/styles/formMixins';
@@ -57,7 +54,7 @@ type TransferFormProps = {
};
export const TransferForm = ({
selectedAsset = DydxChainAsset.DYDX,
selectedAsset = DydxChainAsset.CHAINTOKEN,
onDone,
className,
}: TransferFormProps) => {
@@ -72,6 +69,7 @@ export const TransferForm = ({
const { transfer } = useSubaccount();
const { nativeTokenBalance, usdcBalance } = useAccountBalance();
const { selectedNetwork } = useSelectedNetwork();
const { tokensConfigs, usdcLabel, chainTokenLabel } = useTokenConfigs();
// User Input
const [asset, setAsset] = useState<DydxChainAsset>(selectedAsset);
@@ -138,7 +136,7 @@ export const TransferForm = ({
try {
// Subtract fees from amount if sending native tokens
const amountToTransfer = (
asset === DydxChainAsset.DYDX ? amountBN.minus(fee) : amountBN
asset === DydxChainAsset.CHAINTOKEN ? amountBN.minus(fee) : amountBN
).toNumber();
const screenResults = await screenAddresses({
@@ -161,7 +159,7 @@ export const TransferForm = ({
const txResponse = await transfer(
amountToTransfer,
recipientAddress as string,
DYDX_CHAIN_ASSET_COIN_DENOM[asset]
tokensConfigs[asset].denom,
);
if (txResponse?.code === 0) {
@@ -220,16 +218,16 @@ export const TransferForm = ({
value: DydxChainAsset.USDC,
label: (
<Styled.InlineRow>
<AssetIcon symbol="USDC" /> {DYDX_CHAIN_ASSET_TAGS[DydxChainAsset.USDC]}
<AssetIcon symbol="USDC" /> {usdcLabel}
</Styled.InlineRow>
),
},
{
value: DydxChainAsset.DYDX,
value: DydxChainAsset.CHAINTOKEN,
label: (
<Styled.InlineRow>
{/* <AssetIcon symbol="DYDX" /> */}
{DYDX_CHAIN_ASSET_TAGS[DydxChainAsset.DYDX]}
{chainTokenLabel}
</Styled.InlineRow>
),
},
@@ -251,7 +249,7 @@ export const TransferForm = ({
key: 'amount',
label: (
<span>
{stringGetter({ key: STRING_KEYS.AVAILABLE })} <Tag>{DYDX_CHAIN_ASSET_TAGS[asset]}</Tag>
{stringGetter({ key: STRING_KEYS.AVAILABLE })} <Tag>{tokensConfigs[asset].name}</Tag>
</span>
),
value: (
@@ -3,9 +3,9 @@ import { shallowEqual, useSelector } from 'react-redux';
import { ButtonAction, ButtonSize, ButtonType } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization';
import { NumberSign } from '@/constants/numbers';
import { DYDX_CHAIN_ASSET_TAGS, DydxChainAsset } from '@/constants/wallets';
import { DydxChainAsset } from '@/constants/wallets';
import { useAccountBalance, useStringGetter } from '@/hooks';
import { useAccountBalance, useTokenConfigs, useStringGetter } from '@/hooks';
import { Button } from '@/components/Button';
import { DiffOutput } from '@/components/DiffOutput';
@@ -37,6 +37,7 @@ export const TransferButtonAndReceipt = ({
const stringGetter = useStringGetter();
const canAccountTrade = useSelector(calculateCanAccountTrade, shallowEqual);
const { size } = useSelector(getTransferInputs, shallowEqual) || {};
const { tokensConfigs } = useTokenConfigs();
const { equity: equityInfo, leverage: leverageInfo } =
useSelector(getSubaccount, shallowEqual) || {};
@@ -60,7 +61,7 @@ export const TransferButtonAndReceipt = ({
key: 'fees',
label: (
<span>
{stringGetter({ key: STRING_KEYS.FEES })} <Tag>{DYDX_CHAIN_ASSET_TAGS[selectedAsset]}</Tag>
{stringGetter({ key: STRING_KEYS.FEES })} <Tag>{tokensConfigs[selectedAsset].name}</Tag>
</span>
),
value: <Output type={OutputType.Asset} value={fees} />,
@@ -69,7 +70,7 @@ export const TransferButtonAndReceipt = ({
key: 'balance',
label: (
<span>
{stringGetter({ key: STRING_KEYS.BALANCE })} <Tag>{DYDX_CHAIN_ASSET_TAGS[selectedAsset]}</Tag>
{stringGetter({ key: STRING_KEYS.BALANCE })} <Tag>{tokensConfigs[selectedAsset].name}</Tag>
</span>
),
value: (
+17 -4
View File
@@ -9,7 +9,13 @@ import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS, TOOLTIP_STRING_KEYS } from '@/constants/localization';
import { DydxChainAsset, wallets } from '@/constants/wallets';
import { useAccounts, useBreakpoints, useStringGetter, useAccountBalance } from '@/hooks';
import {
useAccounts,
useBreakpoints,
useTokenConfigs,
useStringGetter,
useAccountBalance,
} from '@/hooks';
import { OnboardingTriggerButton } from '@/views/dialogs/OnboardingTriggerButton';
@@ -39,6 +45,7 @@ export const AccountMenu = () => {
const onboardingState = useSelector(getOnboardingState);
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
const { nativeTokenBalance } = useAccountBalance();
const { usdcLabel, chainTokenLabel } = useTokenConfigs();
const { evmAddress, walletType, dydxAddress, hdKey } = useAccounts();
@@ -107,17 +114,23 @@ export const AccountMenu = () => {
<div>
<div>
<Styled.label>
{stringGetter({ key: STRING_KEYS.ASSET_BALANCE, params: { ASSET: 'Dv4TNT' } })}
{stringGetter({
key: STRING_KEYS.ASSET_BALANCE,
params: { ASSET: chainTokenLabel },
})}
{/* <AssetIcon symbol="DYDX" /> */}
</Styled.label>
<Styled.BalanceOutput type={OutputType.Asset} value={nativeTokenBalance} />
</div>
<AssetActions asset={DydxChainAsset.DYDX} dispatch={dispatch} />
<AssetActions asset={DydxChainAsset.CHAINTOKEN} dispatch={dispatch} />
</div>
<div>
<div>
<Styled.label>
{stringGetter({ key: STRING_KEYS.ASSET_BALANCE, params: { ASSET: 'USDC' } })}
{stringGetter({
key: STRING_KEYS.ASSET_BALANCE,
params: { ASSET: usdcLabel },
})}
<AssetIcon symbol="USDC" />
</Styled.label>
<Styled.BalanceOutput
+5 -4
View File
@@ -178,10 +178,11 @@ export const NotificationsMenu = ({
};
const $UnreadIndicator = styled.div`
width: 0.5em;
height: 0.5em;
width: 0.5rem;
height: 0.5rem;
border-radius: 50%;
background-color: var(--color-accent);
border: 1px solid var(--color-layer-2);
`;
const $TriggerContainer = styled.div`
@@ -192,8 +193,8 @@ const $TriggerUnreadIndicator = styled($UnreadIndicator)`
place-self: center;
position: relative;
right: -0.425em;
top: -0.425em;
right: -0.2rem;
top: -0.325rem;
`;
const $Output = styled(Output)`