Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b220203c91 | ||
|
|
5ca923984d | ||
|
|
d97626f543 | ||
|
|
835f82dbcc | ||
|
|
051bdda73a | ||
|
|
27b79957d4 | ||
|
|
4bacc901dc | ||
|
|
82d32a91a9 | ||
|
|
2a794f9459 | ||
|
|
5c26a0c270 | ||
|
|
e4991cc31d | ||
|
|
da908c826a | ||
|
|
af46278539 | ||
|
|
ea58b55152 | ||
|
|
54d65bb81c | ||
|
|
e047a49bbc | ||
|
|
14316163e4 | ||
|
|
ac619a9da1 | ||
|
|
cb7f542a99 | ||
|
|
bc5569c4c9 | ||
|
|
dd087ae786 | ||
|
|
eb023ff0ff | ||
|
|
348e82293e | ||
|
|
48a48b4d70 | ||
|
|
944cea0d3d | ||
|
|
4ea2bdf53d | ||
|
|
c40f5eb549 | ||
|
|
d53e8f693e | ||
|
|
f9e301b3f0 | ||
|
|
67ecbd75b4 | ||
|
|
a05d88136d | ||
|
|
f1ca86326d | ||
|
|
5d1d734c59 | ||
|
|
9ba6b3d6ba | ||
|
|
62eeab06f5 | ||
|
|
fa621a085b | ||
|
|
0730e71109 | ||
|
|
fdd3fbd774 | ||
|
|
15bf8a1b34 | ||
|
|
6508a8b857 | ||
|
|
e10e7c10e0 | ||
|
|
175a6fe523 | ||
|
|
54181a1f52 | ||
|
|
e6750589db |
@@ -1,6 +0,0 @@
|
|||||||
VITE_BASE_URL=https://v4.testnet.dydx.exchange
|
|
||||||
|
|
||||||
VITE_ALCHEMY_API_KEY=FP275q327Yh7qswtZWenbPXdZZdnAFmC
|
|
||||||
|
|
||||||
VITE_WALLETCONNECT1_BRIDGE=wss://api.dydx.exchange/wc/
|
|
||||||
VITE_WALLETCONNECT2_PROJECT_ID=fbe94eaa691fa8d929561f8567062b32
|
|
||||||
@@ -4,5 +4,6 @@ VITE_ALCHEMY_API_KEY=
|
|||||||
|
|
||||||
VITE_PK_ENCRYPTION_KEY=
|
VITE_PK_ENCRYPTION_KEY=
|
||||||
|
|
||||||
VITE_WALLETCONNECT1_BRIDGE=
|
|
||||||
VITE_WALLETCONNECT2_PROJECT_ID=
|
VITE_WALLETCONNECT2_PROJECT_ID=
|
||||||
|
|
||||||
|
VITE_V3_TOKEN_ADDRESS=
|
||||||
@@ -33,11 +33,13 @@ jobs:
|
|||||||
AMPLITUDE_API_KEY: ${{ secrets.AMPLITUDE_API_KEY }}
|
AMPLITUDE_API_KEY: ${{ secrets.AMPLITUDE_API_KEY }}
|
||||||
BUGSNAG_API_KEY: ${{ secrets.BUGSNAG_API_KEY }}
|
BUGSNAG_API_KEY: ${{ secrets.BUGSNAG_API_KEY }}
|
||||||
STATUS_PAGE_SCRIPT_URI: ${{ secrets.STATUS_PAGE_SCRIPT_URI }}
|
STATUS_PAGE_SCRIPT_URI: ${{ secrets.STATUS_PAGE_SCRIPT_URI }}
|
||||||
|
IOS_APP_ID: ${{ secrets.IOS_APP_ID }}
|
||||||
run: |
|
run: |
|
||||||
pnpm run build
|
pnpm run build
|
||||||
pnpm run build:inject-amplitude
|
pnpm run build:inject-amplitude
|
||||||
pnpm run build:inject-bugsnag
|
pnpm run build:inject-bugsnag
|
||||||
pnpm run build:inject-statuspage
|
pnpm run build:inject-statuspage
|
||||||
|
sh scripts/inject-app-deeplinks.sh
|
||||||
|
|
||||||
- name: Upload to IPFS via web3.storage
|
- name: Upload to IPFS via web3.storage
|
||||||
uses: dydxprotocol/add-to-web3@v1
|
uses: dydxprotocol/add-to-web3@v1
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ dist
|
|||||||
dist-ssr
|
dist-ssr
|
||||||
*.local
|
*.local
|
||||||
*.key
|
*.key
|
||||||
|
.env
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Node.js version 18 and `pnpm` installed on your system
|
- 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.
|
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`.
|
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
|
### 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).
|
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
|
### web3.storage: deploy to IPFS via web3.storage using the provided script
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,10 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
"build:inject-app-deeplinks": "sh scripts/inject-app-deeplinks.sh",
|
||||||
"build:inject-amplitude": "node scripts/inject-amplitude.js",
|
"build:inject-amplitude": "node scripts/inject-amplitude.js",
|
||||||
"build:inject-bugsnag": "node scripts/inject-bugsnag.js",
|
"build:inject-bugsnag": "node scripts/inject-bugsnag.js",
|
||||||
|
"build:inject-intercom": "node scripts/inject-intercom.js",
|
||||||
"build:inject-statuspage": "node scripts/inject-statuspage.js",
|
"build:inject-statuspage": "node scripts/inject-statuspage.js",
|
||||||
"deploy:ipfs": "node scripts/upload-ipfs.js --verbose",
|
"deploy:ipfs": "node scripts/upload-ipfs.js --verbose",
|
||||||
"deploy:update-ipns": "node scripts/update-ipns.js",
|
"deploy:update-ipns": "node scripts/update-ipns.js",
|
||||||
@@ -37,9 +39,9 @@
|
|||||||
"@cosmjs/proto-signing": "^0.31.0",
|
"@cosmjs/proto-signing": "^0.31.0",
|
||||||
"@cosmjs/stargate": "^0.31.0",
|
"@cosmjs/stargate": "^0.31.0",
|
||||||
"@cosmjs/tendermint-rpc": "^0.31.0",
|
"@cosmjs/tendermint-rpc": "^0.31.0",
|
||||||
"@dydxprotocol/v4-abacus": "^0.5.12",
|
"@dydxprotocol/v4-abacus": "^0.7.6",
|
||||||
"@dydxprotocol/v4-client-js": "^0.36.1",
|
"@dydxprotocol/v4-client-js": "^0.40.3",
|
||||||
"@dydxprotocol/v4-localization": "^0.1.12",
|
"@dydxprotocol/v4-localization": "^0.1.32",
|
||||||
"@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",
|
||||||
@@ -105,7 +107,7 @@
|
|||||||
"reselect": "^4.1.8",
|
"reselect": "^4.1.8",
|
||||||
"styled-components": "^5.3.11",
|
"styled-components": "^5.3.11",
|
||||||
"use-latest": "^1.2.1",
|
"use-latest": "^1.2.1",
|
||||||
"viem": "^1.1.6",
|
"viem": "^1.12.2",
|
||||||
"wagmi": "^1.3.7"
|
"wagmi": "^1.3.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -27,14 +27,14 @@ dependencies:
|
|||||||
specifier: ^0.31.0
|
specifier: ^0.31.0
|
||||||
version: 0.31.0
|
version: 0.31.0
|
||||||
'@dydxprotocol/v4-abacus':
|
'@dydxprotocol/v4-abacus':
|
||||||
specifier: ^0.5.12
|
specifier: ^0.7.6
|
||||||
version: 0.5.12
|
version: 0.7.6
|
||||||
'@dydxprotocol/v4-client-js':
|
'@dydxprotocol/v4-client-js':
|
||||||
specifier: ^0.36.1
|
specifier: ^0.40.3
|
||||||
version: 0.36.1
|
version: 0.40.3
|
||||||
'@dydxprotocol/v4-localization':
|
'@dydxprotocol/v4-localization':
|
||||||
specifier: ^0.1.12
|
specifier: ^0.1.32
|
||||||
version: 0.1.12
|
version: 0.1.32
|
||||||
'@ethersproject/providers':
|
'@ethersproject/providers':
|
||||||
specifier: ^5.7.2
|
specifier: ^5.7.2
|
||||||
version: 5.7.2
|
version: 5.7.2
|
||||||
@@ -231,11 +231,11 @@ dependencies:
|
|||||||
specifier: ^1.2.1
|
specifier: ^1.2.1
|
||||||
version: 1.2.1(@types/react@18.2.14)(react@18.2.0)
|
version: 1.2.1(@types/react@18.2.14)(react@18.2.0)
|
||||||
viem:
|
viem:
|
||||||
specifier: ^1.1.6
|
specifier: ^1.12.2
|
||||||
version: 1.1.6(typescript@5.1.3)
|
version: 1.12.2(typescript@5.1.3)
|
||||||
wagmi:
|
wagmi:
|
||||||
specifier: ^1.3.7
|
specifier: ^1.3.7
|
||||||
version: 1.3.7(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(viem@1.1.6)
|
version: 1.3.7(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(viem@1.12.2)
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@babel/core':
|
'@babel/core':
|
||||||
@@ -380,14 +380,14 @@ packages:
|
|||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@adraffy/ens-normalize@1.9.0:
|
|
||||||
resolution: {integrity: sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@adraffy/ens-normalize@1.9.2:
|
/@adraffy/ens-normalize@1.9.2:
|
||||||
resolution: {integrity: sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg==}
|
resolution: {integrity: sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@adraffy/ens-normalize@1.9.4:
|
||||||
|
resolution: {integrity: sha512-UK0bHA7hh9cR39V+4gl2/NnBBjoXIxkuWAPCaY4X7fbH4L/azIi7ilWOCjMUYfpJgraLUAqkRi2BqrjME8Rynw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@ampproject/remapping@2.2.1:
|
/@ampproject/remapping@2.2.1:
|
||||||
resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
|
resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
@@ -645,7 +645,7 @@ packages:
|
|||||||
/@confio/ics23@0.6.8:
|
/@confio/ics23@0.6.8:
|
||||||
resolution: {integrity: sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==}
|
resolution: {integrity: sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@noble/hashes': 1.3.1
|
'@noble/hashes': 1.3.2
|
||||||
protobufjs: 6.11.4
|
protobufjs: 6.11.4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@@ -717,7 +717,7 @@ packages:
|
|||||||
'@cosmjs/encoding': 0.30.1
|
'@cosmjs/encoding': 0.30.1
|
||||||
'@cosmjs/math': 0.30.1
|
'@cosmjs/math': 0.30.1
|
||||||
'@cosmjs/utils': 0.30.1
|
'@cosmjs/utils': 0.30.1
|
||||||
'@noble/hashes': 1.3.1
|
'@noble/hashes': 1.3.2
|
||||||
bn.js: 5.2.1
|
bn.js: 5.2.1
|
||||||
elliptic: 6.5.4
|
elliptic: 6.5.4
|
||||||
libsodium-wrappers: 0.7.11
|
libsodium-wrappers: 0.7.11
|
||||||
@@ -979,12 +979,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@dydxprotocol/v4-abacus@0.5.12:
|
/@dydxprotocol/v4-abacus@0.7.6:
|
||||||
resolution: {integrity: sha512-OigoIjGtp0az1elkP84nc9qKYBVg5Fg4QEJFDn7J7oiUqVvwNggYNfnDsX77D8+K4DJ/rtbi2yZYsDE8OZMSoQ==}
|
resolution: {integrity: sha512-FdDXRaFMfxhyrJJs0dNrb1KG6X95lPHelua1yCn/SVgzwGaAqlJczrzmdh98INntuRAgIxOu69R5mCGyekumyg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@dydxprotocol/v4-client-js@0.36.1:
|
/@dydxprotocol/v4-client-js@0.40.3:
|
||||||
resolution: {integrity: sha512-KJ3MtWI61wmm+xZtXQd7/hYKIoVFG32TRdyyVaXXO8vpW9Oqd0JD8QSM/wuegkciAh5YmP/BrDzYuu77zHO6yg==}
|
resolution: {integrity: sha512-nMQd6tYisKDKIbfx0BGJSYEOSt+I+t5SsaBSmlgTdso+w2rCRO9vyxS+u6MF9h4w5FsVRfhHo3e6uTWX48WpGQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@cosmjs/amino': 0.30.1
|
'@cosmjs/amino': 0.30.1
|
||||||
'@cosmjs/encoding': 0.31.1
|
'@cosmjs/encoding': 0.31.1
|
||||||
@@ -993,14 +993,15 @@ packages:
|
|||||||
'@cosmjs/stargate': 0.30.1
|
'@cosmjs/stargate': 0.30.1
|
||||||
'@cosmjs/tendermint-rpc': 0.30.1
|
'@cosmjs/tendermint-rpc': 0.30.1
|
||||||
'@cosmjs/utils': 0.31.1
|
'@cosmjs/utils': 0.31.1
|
||||||
'@dydxprotocol/v4-proto': 0.2.1
|
'@dydxprotocol/v4-proto': 0.4.1
|
||||||
'@osmonauts/lcd': 0.6.0
|
'@osmonauts/lcd': 0.6.0
|
||||||
'@scure/bip32': 1.3.1
|
'@scure/bip32': 1.3.2
|
||||||
'@scure/bip39': 1.2.1
|
'@scure/bip39': 1.2.1
|
||||||
axios: 1.1.3
|
axios: 1.1.3
|
||||||
bech32: 1.1.4
|
bech32: 1.1.4
|
||||||
bignumber.js: 9.1.1
|
bignumber.js: 9.1.1
|
||||||
ethereum-cryptography: 2.1.2
|
ethereum-cryptography: 2.1.2
|
||||||
|
ethers: 6.6.1
|
||||||
long: 4.0.0
|
long: 4.0.0
|
||||||
protobufjs: 6.11.4
|
protobufjs: 6.11.4
|
||||||
ws: 8.13.0(bufferutil@4.0.7)(utf-8-validate@5.0.10)
|
ws: 8.13.0(bufferutil@4.0.7)(utf-8-validate@5.0.10)
|
||||||
@@ -1010,12 +1011,12 @@ packages:
|
|||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@dydxprotocol/v4-localization@0.1.12:
|
/@dydxprotocol/v4-localization@0.1.32:
|
||||||
resolution: {integrity: sha512-EiP/8+6Nk9QBa6YSWsyzsZaXoVbz5o/KgUlMp1Cew6VWkXL6DkQY0oMIEEy21pv0zuu/woxhlbyXygpUIcpdMg==}
|
resolution: {integrity: sha512-ZtXScxgFLjUt0Ag52RyFnQe9aEl1Aky5fp+vMGOBduVkFiCEMRMkSsSgg6grMdyw/x0AbnxOTRkhYoX2MsK9Ow==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@dydxprotocol/v4-proto@0.2.1:
|
/@dydxprotocol/v4-proto@0.4.1:
|
||||||
resolution: {integrity: sha512-Q5b/g331DoyMjBpO2/jtrxUX3WF5UaIKZp/unK332xuefHNFnkMYtZ05p0V71iSdO35tBdz8yt0VYP2WtUsp+w==}
|
resolution: {integrity: sha512-2pBkokufWcxfIpiXE6QuQOBXUe154OTp6ojCIdOPW9TFLxzchoygxXnb5dL6rAQVNj9Qbg+hhXBllutt4m99dw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
protobufjs: 6.11.4
|
protobufjs: 6.11.4
|
||||||
dev: false
|
dev: false
|
||||||
@@ -2032,6 +2033,12 @@ packages:
|
|||||||
'@noble/hashes': 1.3.1
|
'@noble/hashes': 1.3.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@noble/curves@1.2.0:
|
||||||
|
resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==}
|
||||||
|
dependencies:
|
||||||
|
'@noble/hashes': 1.3.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@noble/ed25519@1.7.3:
|
/@noble/ed25519@1.7.3:
|
||||||
resolution: {integrity: sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==}
|
resolution: {integrity: sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -2049,6 +2056,11 @@ packages:
|
|||||||
engines: {node: '>= 16'}
|
engines: {node: '>= 16'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@noble/hashes@1.3.2:
|
||||||
|
resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==}
|
||||||
|
engines: {node: '>= 16'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@noble/secp256k1@1.7.1:
|
/@noble/secp256k1@1.7.1:
|
||||||
resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==}
|
resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==}
|
||||||
|
|
||||||
@@ -4647,7 +4659,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-gYw0ki/EAuV1oSyMxpqandHjnthZjYYy+YWpTAzf8BqfXM3ItcZLpjxfg+3+mXW8HIO+3jw6T9iiqEXsqHaMMw==}
|
resolution: {integrity: sha512-gYw0ki/EAuV1oSyMxpqandHjnthZjYYy+YWpTAzf8BqfXM3ItcZLpjxfg+3+mXW8HIO+3jw6T9iiqEXsqHaMMw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@safe-global/safe-gateway-typescript-sdk': 3.9.0
|
'@safe-global/safe-gateway-typescript-sdk': 3.9.0
|
||||||
viem: 1.1.6(typescript@5.1.3)
|
viem: 1.12.2(typescript@5.1.3)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bufferutil
|
- bufferutil
|
||||||
- encoding
|
- encoding
|
||||||
@@ -4660,7 +4672,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-XJbEPuaVc7b9n23MqlF6c+ToYIS3f7P2Sel8f3cSBQ9WORE4xrSuvhMpK9fDSFqJ7by/brc+rmJR/5HViRr0/w==}
|
resolution: {integrity: sha512-XJbEPuaVc7b9n23MqlF6c+ToYIS3f7P2Sel8f3cSBQ9WORE4xrSuvhMpK9fDSFqJ7by/brc+rmJR/5HViRr0/w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@safe-global/safe-gateway-typescript-sdk': 3.9.0
|
'@safe-global/safe-gateway-typescript-sdk': 3.9.0
|
||||||
viem: 1.1.6(typescript@5.1.3)
|
viem: 1.12.2(typescript@5.1.3)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bufferutil
|
- bufferutil
|
||||||
- encoding
|
- encoding
|
||||||
@@ -4681,6 +4693,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==}
|
resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@scure/base@1.1.3:
|
||||||
|
resolution: {integrity: sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@scure/bip32@1.3.0:
|
/@scure/bip32@1.3.0:
|
||||||
resolution: {integrity: sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==}
|
resolution: {integrity: sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4693,8 +4709,16 @@ packages:
|
|||||||
resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==}
|
resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@noble/curves': 1.1.0
|
'@noble/curves': 1.1.0
|
||||||
'@noble/hashes': 1.3.1
|
'@noble/hashes': 1.3.2
|
||||||
'@scure/base': 1.1.1
|
'@scure/base': 1.1.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@scure/bip32@1.3.2:
|
||||||
|
resolution: {integrity: sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==}
|
||||||
|
dependencies:
|
||||||
|
'@noble/curves': 1.2.0
|
||||||
|
'@noble/hashes': 1.3.2
|
||||||
|
'@scure/base': 1.1.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@scure/bip39@1.2.0:
|
/@scure/bip39@1.2.0:
|
||||||
@@ -4707,8 +4731,8 @@ packages:
|
|||||||
/@scure/bip39@1.2.1:
|
/@scure/bip39@1.2.1:
|
||||||
resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==}
|
resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@noble/hashes': 1.3.1
|
'@noble/hashes': 1.3.2
|
||||||
'@scure/base': 1.1.1
|
'@scure/base': 1.1.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@solana/buffer-layout@4.0.1:
|
/@solana/buffer-layout@4.0.1:
|
||||||
@@ -4722,8 +4746,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-up5VG1dK+GPhykmuMIozJZBbVqpm77vbOG6/r5dS7NBGZonwHfTLdBbsYc3rjmaQ4DpCXUa3tUc4RZHRORvZrw==}
|
resolution: {integrity: sha512-up5VG1dK+GPhykmuMIozJZBbVqpm77vbOG6/r5dS7NBGZonwHfTLdBbsYc3rjmaQ4DpCXUa3tUc4RZHRORvZrw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.22.10
|
'@babel/runtime': 7.22.10
|
||||||
'@noble/curves': 1.1.0
|
'@noble/curves': 1.2.0
|
||||||
'@noble/hashes': 1.3.1
|
'@noble/hashes': 1.3.2
|
||||||
'@solana/buffer-layout': 4.0.1
|
'@solana/buffer-layout': 4.0.1
|
||||||
agentkeepalive: 4.5.0
|
agentkeepalive: 4.5.0
|
||||||
bigint-buffer: 1.1.5
|
bigint-buffer: 1.1.5
|
||||||
@@ -5408,6 +5432,12 @@ packages:
|
|||||||
'@types/node': 20.3.1
|
'@types/node': 20.3.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@types/ws@8.5.6:
|
||||||
|
resolution: {integrity: sha512-8B5EO9jLVCy+B58PLHvLDuOD8DRVMgQzq8d55SjLCOn9kqGyqOvy27exVaTio1q1nX5zLu8/6N0n2ThSxOM6tg==}
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 20.3.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@typescript-eslint/eslint-plugin@5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.1.3):
|
/@typescript-eslint/eslint-plugin@5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.1.3):
|
||||||
resolution: {integrity: sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==}
|
resolution: {integrity: sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
@@ -5904,17 +5934,6 @@ packages:
|
|||||||
pretty-format: 27.5.1
|
pretty-format: 27.5.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@wagmi/chains@1.2.0(typescript@5.1.3):
|
|
||||||
resolution: {integrity: sha512-dmDRipsE54JfyudOBkuhEexqQWcrZqxn/qiujG8SBzMh/az/AH5xlJSA+j1CPWTx9+QofSMF3B7A4gb6XRmSaQ==}
|
|
||||||
peerDependencies:
|
|
||||||
typescript: '>=5.0.4'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
typescript:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
typescript: 5.1.3
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@wagmi/chains@1.4.0(typescript@5.1.3):
|
/@wagmi/chains@1.4.0(typescript@5.1.3):
|
||||||
resolution: {integrity: sha512-9HwJrhcZ1TxyrCbE10y7s1eSiSiyfGam7AHIOLYExaOX+vpOZ+MNTt4orFEDbEpz1fxwJDPPI38lanAUix1OSA==}
|
resolution: {integrity: sha512-9HwJrhcZ1TxyrCbE10y7s1eSiSiyfGam7AHIOLYExaOX+vpOZ+MNTt4orFEDbEpz1fxwJDPPI38lanAUix1OSA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -5926,7 +5945,7 @@ packages:
|
|||||||
typescript: 5.1.3
|
typescript: 5.1.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@wagmi/connectors@2.6.5(@wagmi/chains@1.4.0)(react@18.2.0)(typescript@5.1.3)(viem@1.1.6):
|
/@wagmi/connectors@2.6.5(@wagmi/chains@1.4.0)(react@18.2.0)(typescript@5.1.3)(viem@1.12.2):
|
||||||
resolution: {integrity: sha512-klF31togMDd0qQqEcLl5cCGxjMbL0RRXQ8I1vxmEa3KdGzw6Z3ICVzX7/bDfnNEZcOW7BKyAnZDq7rCt5jTOiw==}
|
resolution: {integrity: sha512-klF31togMDd0qQqEcLl5cCGxjMbL0RRXQ8I1vxmEa3KdGzw6Z3ICVzX7/bDfnNEZcOW7BKyAnZDq7rCt5jTOiw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@wagmi/chains': '>=1.3.0'
|
'@wagmi/chains': '>=1.3.0'
|
||||||
@@ -5950,7 +5969,7 @@ packages:
|
|||||||
abitype: 0.8.7(typescript@5.1.3)
|
abitype: 0.8.7(typescript@5.1.3)
|
||||||
eventemitter3: 4.0.7
|
eventemitter3: 4.0.7
|
||||||
typescript: 5.1.3
|
typescript: 5.1.3
|
||||||
viem: 1.1.6(typescript@5.1.3)
|
viem: 1.12.2(typescript@5.1.3)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@react-native-async-storage/async-storage'
|
- '@react-native-async-storage/async-storage'
|
||||||
- bufferutil
|
- bufferutil
|
||||||
@@ -5962,7 +5981,7 @@ packages:
|
|||||||
- zod
|
- zod
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@wagmi/core@1.3.6(@types/react@18.2.14)(react@18.2.0)(typescript@5.1.3)(viem@1.1.6):
|
/@wagmi/core@1.3.6(@types/react@18.2.14)(react@18.2.0)(typescript@5.1.3)(viem@1.12.2):
|
||||||
resolution: {integrity: sha512-TXv9ZlRR5aySfERFuWMuo+lKXC/CoqtxVJZVHPqhK1jY+nldMx3AvrWzzF4CccRaMYcVdvPFepvmxzq2A2VvWg==}
|
resolution: {integrity: sha512-TXv9ZlRR5aySfERFuWMuo+lKXC/CoqtxVJZVHPqhK1jY+nldMx3AvrWzzF4CccRaMYcVdvPFepvmxzq2A2VvWg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=5.0.4'
|
typescript: '>=5.0.4'
|
||||||
@@ -5972,11 +5991,11 @@ packages:
|
|||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@wagmi/chains': 1.4.0(typescript@5.1.3)
|
'@wagmi/chains': 1.4.0(typescript@5.1.3)
|
||||||
'@wagmi/connectors': 2.6.5(@wagmi/chains@1.4.0)(react@18.2.0)(typescript@5.1.3)(viem@1.1.6)
|
'@wagmi/connectors': 2.6.5(@wagmi/chains@1.4.0)(react@18.2.0)(typescript@5.1.3)(viem@1.12.2)
|
||||||
abitype: 0.8.7(typescript@5.1.3)
|
abitype: 0.8.7(typescript@5.1.3)
|
||||||
eventemitter3: 4.0.7
|
eventemitter3: 4.0.7
|
||||||
typescript: 5.1.3
|
typescript: 5.1.3
|
||||||
viem: 1.1.6(typescript@5.1.3)
|
viem: 1.12.2(typescript@5.1.3)
|
||||||
zustand: 4.4.1(@types/react@18.2.14)(react@18.2.0)
|
zustand: 4.4.1(@types/react@18.2.14)(react@18.2.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@react-native-async-storage/async-storage'
|
- '@react-native-async-storage/async-storage'
|
||||||
@@ -6677,6 +6696,20 @@ packages:
|
|||||||
typescript: 5.1.3
|
typescript: 5.1.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/abitype@0.9.8(typescript@5.1.3):
|
||||||
|
resolution: {integrity: sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ==}
|
||||||
|
peerDependencies:
|
||||||
|
typescript: '>=5.0.4'
|
||||||
|
zod: ^3 >=3.19.1
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
zod:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
typescript: 5.1.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/abort-controller@3.0.0:
|
/abort-controller@3.0.0:
|
||||||
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
|
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
|
||||||
engines: {node: '>=6.5'}
|
engines: {node: '>=6.5'}
|
||||||
@@ -7112,7 +7145,7 @@ packages:
|
|||||||
/bip39@3.1.0:
|
/bip39@3.1.0:
|
||||||
resolution: {integrity: sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==}
|
resolution: {integrity: sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@noble/hashes': 1.3.1
|
'@noble/hashes': 1.3.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/bl@5.1.0:
|
/bl@5.1.0:
|
||||||
@@ -9986,12 +10019,12 @@ packages:
|
|||||||
ws: 7.5.9
|
ws: 7.5.9
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/isomorphic-ws@5.0.0(ws@8.12.0):
|
/isomorphic-ws@5.0.0(ws@8.13.0):
|
||||||
resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==}
|
resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
ws: '*'
|
ws: '*'
|
||||||
dependencies:
|
dependencies:
|
||||||
ws: 8.12.0
|
ws: 8.13.0(bufferutil@4.0.7)(utf-8-validate@5.0.10)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/it-all@1.0.6:
|
/it-all@1.0.6:
|
||||||
@@ -13520,21 +13553,24 @@ packages:
|
|||||||
vfile-message: 3.1.4
|
vfile-message: 3.1.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/viem@1.1.6(typescript@5.1.3):
|
/viem@1.12.2(typescript@5.1.3):
|
||||||
resolution: {integrity: sha512-7nK3HMucLr1Yz0QnDXiD6viigKS6QeYD/YhRHpi3Bby/g0hCyZqK8+YJNtp3/Ri64tpl4kaTIeCScJWV2jqXHQ==}
|
resolution: {integrity: sha512-aCaUCyg72ES+jK4s6tVYOMnOt4if71RwzgiUAUpAuaCgvHFfh9DCnwuEfwkxEZLE2vafOsirgJ3fcn7nsDVQoQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=5.0.4'
|
typescript: '>=5.0.4'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@adraffy/ens-normalize': 1.9.0
|
'@adraffy/ens-normalize': 1.9.4
|
||||||
'@noble/curves': 1.0.0
|
'@noble/curves': 1.2.0
|
||||||
'@noble/hashes': 1.3.0
|
'@noble/hashes': 1.3.2
|
||||||
'@scure/bip32': 1.3.0
|
'@scure/bip32': 1.3.2
|
||||||
'@scure/bip39': 1.2.0
|
'@scure/bip39': 1.2.1
|
||||||
'@wagmi/chains': 1.2.0(typescript@5.1.3)
|
'@types/ws': 8.5.6
|
||||||
abitype: 0.8.7(typescript@5.1.3)
|
abitype: 0.9.8(typescript@5.1.3)
|
||||||
isomorphic-ws: 5.0.0(ws@8.12.0)
|
isomorphic-ws: 5.0.0(ws@8.13.0)
|
||||||
typescript: 5.1.3
|
typescript: 5.1.3
|
||||||
ws: 8.12.0
|
ws: 8.13.0(bufferutil@4.0.7)(utf-8-validate@5.0.10)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bufferutil
|
- bufferutil
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
@@ -13702,7 +13738,7 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/wagmi@1.3.7(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(viem@1.1.6):
|
/wagmi@1.3.7(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(viem@1.12.2):
|
||||||
resolution: {integrity: sha512-n4Qwby0QB8/JSGjc0gGn4MWZ0BT229agEg6saPGS6VswmPjJLdkLq9qxKn1JptXxPREmb/ZvwHxU++3Z+gQJVA==}
|
resolution: {integrity: sha512-n4Qwby0QB8/JSGjc0gGn4MWZ0BT229agEg6saPGS6VswmPjJLdkLq9qxKn1JptXxPREmb/ZvwHxU++3Z+gQJVA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: '>=17.0.0'
|
react: '>=17.0.0'
|
||||||
@@ -13715,12 +13751,12 @@ packages:
|
|||||||
'@tanstack/query-sync-storage-persister': 4.32.6
|
'@tanstack/query-sync-storage-persister': 4.32.6
|
||||||
'@tanstack/react-query': 4.32.6(react-dom@18.2.0)(react@18.2.0)
|
'@tanstack/react-query': 4.32.6(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@tanstack/react-query-persist-client': 4.32.6(@tanstack/react-query@4.32.6)
|
'@tanstack/react-query-persist-client': 4.32.6(@tanstack/react-query@4.32.6)
|
||||||
'@wagmi/core': 1.3.6(@types/react@18.2.14)(react@18.2.0)(typescript@5.1.3)(viem@1.1.6)
|
'@wagmi/core': 1.3.6(@types/react@18.2.14)(react@18.2.0)(typescript@5.1.3)(viem@1.12.2)
|
||||||
abitype: 0.8.7(typescript@5.1.3)
|
abitype: 0.8.7(typescript@5.1.3)
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
typescript: 5.1.3
|
typescript: 5.1.3
|
||||||
use-sync-external-store: 1.2.0(react@18.2.0)
|
use-sync-external-store: 1.2.0(react@18.2.0)
|
||||||
viem: 1.1.6(typescript@5.1.3)
|
viem: 1.12.2(typescript@5.1.3)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@react-native-async-storage/async-storage'
|
- '@react-native-async-storage/async-storage'
|
||||||
- '@types/react'
|
- '@types/react'
|
||||||
@@ -13945,19 +13981,6 @@ packages:
|
|||||||
optional: true
|
optional: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/ws@8.12.0:
|
|
||||||
resolution: {integrity: sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==}
|
|
||||||
engines: {node: '>=10.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
bufferutil: ^4.0.1
|
|
||||||
utf-8-validate: '>=5.0.2'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
bufferutil:
|
|
||||||
optional: true
|
|
||||||
utf-8-validate:
|
|
||||||
optional: true
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/ws@8.13.0(bufferutil@4.0.7)(utf-8-validate@5.0.10):
|
/ws@8.13.0(bufferutil@4.0.7)(utf-8-validate@5.0.10):
|
||||||
resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==}
|
resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"details": [
|
"details": [
|
||||||
{
|
{
|
||||||
"appIDs": [
|
"appIDs": [
|
||||||
"75C6UARB5H.exchangeV4.dydx.trading"
|
"{PLACE_YOUR_APP_ID_HERE}"
|
||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 193 KiB After Width: | Height: | Size: 122 KiB |
@@ -1,179 +0,0 @@
|
|||||||
{
|
|
||||||
"deployments":{
|
|
||||||
"MAINNET":null,
|
|
||||||
"TESTNET":{
|
|
||||||
"environments":[
|
|
||||||
"dydxprotocol-testnet"
|
|
||||||
],
|
|
||||||
"default":"dydxprotocol-testnet"
|
|
||||||
},
|
|
||||||
"DEV":{
|
|
||||||
"environments":[
|
|
||||||
"dydxprotocol-dev",
|
|
||||||
"dydxprotocol-dev-2",
|
|
||||||
"dydxprotocol-dev-4",
|
|
||||||
"dydxprotocol-dev-5",
|
|
||||||
"dydxprotocol-staging",
|
|
||||||
"dydxprotocol-testnet"
|
|
||||||
],
|
|
||||||
"default":"dydxprotocol-testnet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"environments":[
|
|
||||||
{
|
|
||||||
"id":"dydxprotocol-dev",
|
|
||||||
"name":"v4 Dev",
|
|
||||||
"ethereumChainId":"5",
|
|
||||||
"dydxChainId":"dydxprotocol-testnet",
|
|
||||||
"isMainNet":false,
|
|
||||||
"endpoints":{
|
|
||||||
"indexers":[
|
|
||||||
{
|
|
||||||
"api":"http://indexer.v4dev.dydx.exchange",
|
|
||||||
"socket":"wss://indexer.v4dev.dydx.exchange"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"validators":[
|
|
||||||
"http://validator.v4dev.dydx.exchange"
|
|
||||||
],
|
|
||||||
"0xsquid":"https://testnet.api.0xsquid.com",
|
|
||||||
"faucet":"http://faucet.v4dev.dydx.exchange"
|
|
||||||
},
|
|
||||||
"links":{
|
|
||||||
"tos":"https://dydx.exchange/v4-terms",
|
|
||||||
"privacy":"https://dydx.exchange/privacy",
|
|
||||||
"mintscan":"https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"dydxprotocol-dev-2",
|
|
||||||
"name":"v4 Dev 2",
|
|
||||||
"ethereumChainId":"5",
|
|
||||||
"dydxChainId":"dydxprotocol-testnet",
|
|
||||||
"isMainNet":false,
|
|
||||||
"endpoints":{
|
|
||||||
"indexers":[
|
|
||||||
{
|
|
||||||
"api":"http://dev2-indexer-apne1-lb-public-2076363889.ap-northeast-1.elb.amazonaws.com",
|
|
||||||
"socket":"ws://dev2-indexer-apne1-lb-public-2076363889.ap-northeast-1.elb.amazonaws.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"validators":[
|
|
||||||
"http://35.75.227.118"
|
|
||||||
],
|
|
||||||
"0xsquid":"https://testnet.api.0xsquid.com"
|
|
||||||
},
|
|
||||||
"links":{
|
|
||||||
"tos":"https://dydx.exchange/v4-terms",
|
|
||||||
"privacy":"https://dydx.exchange/privacy",
|
|
||||||
"mintscan":"https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"dydxprotocol-dev-4",
|
|
||||||
"name":"v4 Dev 4",
|
|
||||||
"ethereumChainId":"5",
|
|
||||||
"dydxChainId":"dydxprotocol-testnet",
|
|
||||||
"isMainNet":false,
|
|
||||||
"endpoints":{
|
|
||||||
"indexers":[
|
|
||||||
{
|
|
||||||
"api":"http://indexer.v4dev4.dydx.exchange",
|
|
||||||
"socket":"ws://indexer.v4dev4.dydx.exchange"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"validators":[
|
|
||||||
"http://validator.v4dev4.dydx.exchange"
|
|
||||||
],
|
|
||||||
"0xsquid":"https://testnet.api.0xsquid.com"
|
|
||||||
},
|
|
||||||
"links":{
|
|
||||||
"tos":"https://dydx.exchange/v4-terms",
|
|
||||||
"privacy":"https://dydx.exchange/privacy",
|
|
||||||
"mintscan":"https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"dydxprotocol-dev-5",
|
|
||||||
"name":"v4 Dev 5",
|
|
||||||
"ethereumChainId":"5",
|
|
||||||
"dydxChainId":"dydxprotocol-testnet",
|
|
||||||
"isMainNet":false,
|
|
||||||
"endpoints":{
|
|
||||||
"indexers":[
|
|
||||||
{
|
|
||||||
"api":"http://dev5-indexer-apne1-lb-public-1721328151.ap-northeast-1.elb.amazonaws.com",
|
|
||||||
"socket":"ws://dev5-indexer-apne1-lb-public-1721328151.ap-northeast-1.elb.amazonaws.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"validators":[
|
|
||||||
"http://18.223.78.50"
|
|
||||||
],
|
|
||||||
"0xsquid":"https://testnet.api.0xsquid.com"
|
|
||||||
},
|
|
||||||
"links":{
|
|
||||||
"tos":"https://dydx.exchange/v4-terms",
|
|
||||||
"privacy":"https://dydx.exchange/privacy",
|
|
||||||
"mintscan":"https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"dydxprotocol-staging",
|
|
||||||
"name":"v4 Staging",
|
|
||||||
"ethereumChainId":"5",
|
|
||||||
"dydxChainId":"dydxprotocol-testnet",
|
|
||||||
"isMainNet":false,
|
|
||||||
"endpoints":{
|
|
||||||
"indexers":[
|
|
||||||
{
|
|
||||||
"api":"https://indexer.v4staging.dydx.exchange",
|
|
||||||
"socket":"wss://indexer.v4staging.dydx.exchange"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"faucet":"https://faucet.v4staging.dydx.exchange",
|
|
||||||
"validators":[
|
|
||||||
"https://validator.v4staging.dydx.exchange"
|
|
||||||
],
|
|
||||||
"0xsquid":"https://squid-api-git-main-cosmos-testnet-0xsquid.vercel.app"
|
|
||||||
},
|
|
||||||
"links":{
|
|
||||||
"tos":"https://dydx.exchange/v4-terms",
|
|
||||||
"privacy":"https://dydx.exchange/privacy",
|
|
||||||
"mintscan":"https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
|
||||||
"documentation":"https://v4-teacher.vercel.app/",
|
|
||||||
"community":"https://discord.com/invite/dydx",
|
|
||||||
"feedback":"https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"dydxprotocol-testnet",
|
|
||||||
"name":"v4 Public Testnet",
|
|
||||||
"ethereumChainId":"5",
|
|
||||||
"dydxChainId":"dydx-testnet-3",
|
|
||||||
"isMainNet":false,
|
|
||||||
"endpoints":{
|
|
||||||
"indexers":[
|
|
||||||
{
|
|
||||||
"api":"https://dydx-testnet.imperator.co",
|
|
||||||
"socket":"wss://dydx-testnet.imperator.co"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"validators":[
|
|
||||||
"https://dydx-testnet.nodefleet.org",
|
|
||||||
"https://dydx-testnet-archive.allthatnode.com:26657/XZvMM41hESf8PJrEQiTzbCOMVyFca79R",
|
|
||||||
"https://test-dydx.kingnodes.com/"
|
|
||||||
],
|
|
||||||
"0xsquid":"https://squid-api-git-main-cosmos-testnet-0xsquid.vercel.app",
|
|
||||||
"faucet":"https://faucet.v4testnet.dydx.exchange"
|
|
||||||
},
|
|
||||||
"links":{
|
|
||||||
"tos":"https://dydx.exchange/v4-terms",
|
|
||||||
"privacy":"https://dydx.exchange/privacy",
|
|
||||||
"mintscan":"https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
|
||||||
"documentation":"https://v4-teacher.vercel.app/",
|
|
||||||
"community":"https://discord.com/invite/dydx",
|
|
||||||
"feedback":"https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,847 @@
|
|||||||
|
{
|
||||||
|
"deployments": {
|
||||||
|
"MAINNET": {
|
||||||
|
"environments": [
|
||||||
|
"dydxprotocol-mainnet"
|
||||||
|
],
|
||||||
|
"default": "dydxprotocol-mainnet"
|
||||||
|
},
|
||||||
|
"TESTNET": {
|
||||||
|
"environments": [
|
||||||
|
"dydxprotocol-testnet"
|
||||||
|
],
|
||||||
|
"default": "dydxprotocol-testnet"
|
||||||
|
},
|
||||||
|
"DEV": {
|
||||||
|
"environments": [
|
||||||
|
"dydxprotocol-dev",
|
||||||
|
"dydxprotocol-dev-2",
|
||||||
|
"dydxprotocol-dev-4",
|
||||||
|
"dydxprotocol-dev-5",
|
||||||
|
"dydxprotocol-staging",
|
||||||
|
"dydxprotocol-staging-west",
|
||||||
|
"dydxprotocol-testnet",
|
||||||
|
"dydxprotocol-testnet-dydx",
|
||||||
|
"dydxprotocol-testnet-dsrv",
|
||||||
|
"dydxprotocol-testnet-nodefleet",
|
||||||
|
"dydxprotocol-testnet-kingnodes",
|
||||||
|
"dydxprotocol-testnet-liquify"
|
||||||
|
],
|
||||||
|
"default": "dydxprotocol-testnet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"environments": {
|
||||||
|
"dydxprotocol-dev": {
|
||||||
|
"name": "v4 Dev",
|
||||||
|
"ethereumChainId": "5",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": false,
|
||||||
|
"tokens": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4dev.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4dev.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://validator.v4dev.dydx.exchange"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.0xsquid.com",
|
||||||
|
"faucet": "https://faucet.v4dev.dydx.exchange"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX Chain"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-dev-2": {
|
||||||
|
"name": "v4 Dev 2",
|
||||||
|
"ethereumChainId": "5",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": false,
|
||||||
|
"tokens": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "http://dev2-indexer-apne1-lb-public-2076363889.ap-northeast-1.elb.amazonaws.com",
|
||||||
|
"socket": "ws://dev2-indexer-apne1-lb-public-2076363889.ap-northeast-1.elb.amazonaws.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"http://54.92.118.111"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.0xsquid.com"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX Chain"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-dev-4": {
|
||||||
|
"name": "v4 Dev 4",
|
||||||
|
"ethereumChainId": "5",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": false,
|
||||||
|
"tokens": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "http://indexer.v4dev4.dydx.exchange",
|
||||||
|
"socket": "ws://indexer.v4dev4.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"http://validator.v4dev4.dydx.exchange"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.0xsquid.com"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX Chain"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-dev-5": {
|
||||||
|
"name": "v4 Dev 5",
|
||||||
|
"ethereumChainId": "5",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": false,
|
||||||
|
"tokens": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "http://dev5-indexer-apne1-lb-public-1721328151.ap-northeast-1.elb.amazonaws.com",
|
||||||
|
"socket": "ws://dev5-indexer-apne1-lb-public-1721328151.ap-northeast-1.elb.amazonaws.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"http://18.223.78.50"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.0xsquid.com"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX Chain"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-staging": {
|
||||||
|
"name": "v4 Staging",
|
||||||
|
"ethereumChainId": "5",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": false,
|
||||||
|
"tokens": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4staging.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4staging.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"faucet": "https://faucet.v4staging.dydx.exchange",
|
||||||
|
"validators": [
|
||||||
|
"https://validator.v4staging.dydx.exchange"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"documentation": "https://v4-teacher.vercel.app/",
|
||||||
|
"community": "https://discord.com/invite/dydx",
|
||||||
|
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX Chain"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-staging-west": {
|
||||||
|
"name": "v4 Staging West",
|
||||||
|
"ethereumChainId": "5",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": false,
|
||||||
|
"tokens": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4staging.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4staging.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"faucet": "https://faucet.v4staging.dydx.exchange",
|
||||||
|
"validators": [
|
||||||
|
"https://validator-uswest1.v4staging.dydx.exchange"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"documentation": "https://v4-teacher.vercel.app/",
|
||||||
|
"community": "https://discord.com/invite/dydx",
|
||||||
|
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX Chain"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet": {
|
||||||
|
"name": "v4 Public Testnet",
|
||||||
|
"ethereumChainId": "5",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": false,
|
||||||
|
"tokens": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://dydx-testnet.imperator.co",
|
||||||
|
"socket": "wss://dydx-testnet.imperator.co"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://dydx-testnet.nodefleet.org",
|
||||||
|
"https://test-dydx.kingnodes.com",
|
||||||
|
"https://dydx-rpc.liquify.com/api=8878132/dydx"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"documentation": "https://v4-teacher.vercel.app/",
|
||||||
|
"community": "https://discord.com/invite/dydx",
|
||||||
|
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX V4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet-dydx": {
|
||||||
|
"name": "v4 Public Testnet/dYdX",
|
||||||
|
"ethereumChainId": "5",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": false,
|
||||||
|
"tokens": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://validator.v4testnet.dydx.exchange"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"statusPage": "https://status.v4testnet.dydx.exchange/",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"documentation": "https://v4-teacher.vercel.app/",
|
||||||
|
"community": "https://discord.com/invite/dydx",
|
||||||
|
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX V4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet-dsrv": {
|
||||||
|
"name": "v4 Public Testnet/DSRV",
|
||||||
|
"ethereumChainId": "5",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": false,
|
||||||
|
"tokens": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://dydx-testnet.imperator.co",
|
||||||
|
"socket": "wss://dydx-testnet.imperator.co"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://dydx-testnet-archive.allthatnode.com:26657/XZvMM41hESf8PJrEQiTzbCOMVyFca79R"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"statusPage": "https://status.v4testnet.dydx.exchange/",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"documentation": "https://v4-teacher.vercel.app/",
|
||||||
|
"community": "https://discord.com/invite/dydx",
|
||||||
|
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX V4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet-nodefleet": {
|
||||||
|
"name": "v4 Public Testnet/nodefleet",
|
||||||
|
"ethereumChainId": "5",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": false,
|
||||||
|
"tokens": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://dydx-testnet.imperator.co",
|
||||||
|
"socket": "wss://dydx-testnet.imperator.co"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://dydx-testnet.nodefleet.org"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"statusPage": "https://status.v4testnet.dydx.exchange/",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"documentation": "https://v4-teacher.vercel.app/",
|
||||||
|
"community": "https://discord.com/invite/dydx",
|
||||||
|
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX V4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet-kingnodes": {
|
||||||
|
"name": "v4 Public Testnet/KingNodes",
|
||||||
|
"ethereumChainId": "5",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": false,
|
||||||
|
"tokens": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://dydx-testnet.imperator.co",
|
||||||
|
"socket": "wss://dydx-testnet.imperator.co"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://test-dydx.kingnodes.com"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"statusPage": "https://status.v4testnet.dydx.exchange/",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"documentation": "https://v4-teacher.vercel.app/",
|
||||||
|
"community": "https://discord.com/invite/dydx",
|
||||||
|
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX V4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet-liquify": {
|
||||||
|
"name": "v4 Public Testnet/Liquify",
|
||||||
|
"ethereumChainId": "5",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": false,
|
||||||
|
"tokens": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://dydx-testnet.imperator.co",
|
||||||
|
"socket": "wss://dydx-testnet.imperator.co"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://dydx-rpc.liquify.com/api=8878132/dydx"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"statusPage": "https://status.v4testnet.dydx.exchange/",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"documentation": "https://v4-teacher.vercel.app/",
|
||||||
|
"community": "https://discord.com/invite/dydx",
|
||||||
|
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX V4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-mainnet": {
|
||||||
|
"name": "v4",
|
||||||
|
"ethereumChainId": "1",
|
||||||
|
"dydxChainId": "[mainnet chain id]",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "dydx-chain.png",
|
||||||
|
"isMainNet": true,
|
||||||
|
"tokens": {
|
||||||
|
"comment": "Change according to mainnet release",
|
||||||
|
"chain": {
|
||||||
|
"name": "TokenName",
|
||||||
|
"denom": "tokenDenom",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "[REST endpoint]",
|
||||||
|
"socket": "[Websocket endpoint]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"[Validator endpoint 1",
|
||||||
|
"[Validator endpoint n]"
|
||||||
|
],
|
||||||
|
"0xsquid": "[0xSquid endpoint for mainnet]"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"tos": "[HTTP link to TOS]",
|
||||||
|
"privacy": "[HTTP link to Privacy Policy]",
|
||||||
|
"mintscan": "[HTTP link to Mintscan, with {tx_hash} placeholder]",
|
||||||
|
"documentation": "[HTTP link to documentation, can be null]",
|
||||||
|
"community": "[HTTP link to community, can be null]",
|
||||||
|
"feedback": "[HTTP link to feedback form, can be null]",
|
||||||
|
"blogs": "[HTTP link to blogs, can be null]"
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "[Name of the app]",
|
||||||
|
"description": "[Description of the app]",
|
||||||
|
"iconUrl": "[Relative URL of the icon URL]"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "[Project ID]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "[Relative callback URL for WalletSegue, should match apple-app-site-association]"
|
||||||
|
},
|
||||||
|
"images": "[Relative URL for wallet images]",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX Chain"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,454 @@
|
|||||||
|
{
|
||||||
|
"1INCH-USD":{
|
||||||
|
"name":"1inch",
|
||||||
|
"tags":[
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://1inch.io/",
|
||||||
|
"whitepaperLink":"https://github.com/1inch",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/1inch/"
|
||||||
|
},
|
||||||
|
"AAVE-USD":{
|
||||||
|
"name":"Aave",
|
||||||
|
"tags":[
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://aave.com/",
|
||||||
|
"whitepaperLink":"https://github.com/aave/protocol-v2/blob/master/aave-v2-whitepaper.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/aave/"
|
||||||
|
},
|
||||||
|
"ADA-USD":{
|
||||||
|
"name":"Cardano",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://cardano.org/",
|
||||||
|
"whitepaperLink":"https://why.cardano.org/en/introduction/motivation/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/cardano/"
|
||||||
|
},
|
||||||
|
"ALGO-USD":{
|
||||||
|
"name":"Algorand",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://algorand.com/",
|
||||||
|
"whitepaperLink":"https://algorand.com/technology/white-papers",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/algorand/"
|
||||||
|
},
|
||||||
|
"APE-USD":{
|
||||||
|
"name":"ApeCoin",
|
||||||
|
"tags":[
|
||||||
|
|
||||||
|
],
|
||||||
|
"websiteLink":"https://apecoin.com/",
|
||||||
|
"whitepaperLink":"https://apecoin.com/about",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/apecoin-ape/"
|
||||||
|
},
|
||||||
|
"APT-USD":{
|
||||||
|
"name":"Aptos",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://aptoslabs.com/",
|
||||||
|
"whitepaperLink":"https://aptos.dev/aptos-white-paper/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/aptos/"
|
||||||
|
},
|
||||||
|
"ARB-USD":{
|
||||||
|
"name":"Arbitrum",
|
||||||
|
"tags":[
|
||||||
|
|
||||||
|
],
|
||||||
|
"websiteLink":"https://arbitrum.io/",
|
||||||
|
"whitepaperLink":"https://github.com/OffchainLabs/nitro",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/arbitrum/"
|
||||||
|
},
|
||||||
|
"ATOM-USD":{
|
||||||
|
"name":"Cosmos",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://cosmos.network/",
|
||||||
|
"whitepaperLink":"https://v1.cosmos.network/resources/whitepaper",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/cosmos/"
|
||||||
|
},
|
||||||
|
"AVAX-USD":{
|
||||||
|
"name":"Avalanche",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://www.avalabs.org/",
|
||||||
|
"whitepaperLink":"https://assets.website-files.com/5d80307810123f5ffbb34d6e/6008d7bbf8b10d1eb01e7e16_Avalanche%20Platform%20Whitepaper.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/avalanche/"
|
||||||
|
},
|
||||||
|
"BCH-USD":{
|
||||||
|
"name":"Bitcoin Cash",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://bitcoincash.org/",
|
||||||
|
"whitepaperLink":"https://bitcoincash.org/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/bitcoin-cash/"
|
||||||
|
},
|
||||||
|
"BLUR-USD":{
|
||||||
|
"name":"Blur",
|
||||||
|
"tags":[
|
||||||
|
|
||||||
|
],
|
||||||
|
"websiteLink":"https://blur.io/",
|
||||||
|
"whitepaperLink":"https://docs.blur.foundation/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/blur-token/"
|
||||||
|
},
|
||||||
|
"CELO-USD":{
|
||||||
|
"name":"Celo",
|
||||||
|
"tags":[
|
||||||
|
|
||||||
|
],
|
||||||
|
"websiteLink":"https://celo.org",
|
||||||
|
"whitepaperLink":"https://docs.celo.org",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/celo/"
|
||||||
|
},
|
||||||
|
"BTC-USD":{
|
||||||
|
"name":"Bitcoin",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://bitcoin.org/",
|
||||||
|
"whitepaperLink":"https://bitcoin.org/bitcoin.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/bitcoin/"
|
||||||
|
},
|
||||||
|
"COMP-USD":{
|
||||||
|
"name":"Compound",
|
||||||
|
"tags":[
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://compound.finance/",
|
||||||
|
"whitepaperLink":"https://compound.finance/documents/Compound.Whitepaper.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/compound/"
|
||||||
|
},
|
||||||
|
"CRV-USD":{
|
||||||
|
"name":"Curve",
|
||||||
|
"tags":[
|
||||||
|
"Governance"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://curve.fi/",
|
||||||
|
"whitepaperLink":"https://curve.fi/whitepaper",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/curve-dao-token/"
|
||||||
|
},
|
||||||
|
"DOGE-USD":{
|
||||||
|
"name":"Dogecoin",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://dogecoin.com/",
|
||||||
|
"whitepaperLink":"https://github.com/dogecoin/dogecoin",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/dogecoin/"
|
||||||
|
},
|
||||||
|
"DOT-USD":{
|
||||||
|
"name":"Polkadot",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://polkadot.network/",
|
||||||
|
"whitepaperLink":"https://polkadot.network/PolkaDotPaper.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/polkadot-new/"
|
||||||
|
},
|
||||||
|
"ENJ-USD":{
|
||||||
|
"name":"Enjin",
|
||||||
|
"tags":[
|
||||||
|
|
||||||
|
],
|
||||||
|
"websiteLink":"https://enjin.io/",
|
||||||
|
"whitepaperLink":"https://cdn.enjin.io/downloads/whitepapers/enjin-coin/en.pdf/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/enjin-coin/"
|
||||||
|
},
|
||||||
|
"EOS-USD":{
|
||||||
|
"name":"EOS",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://eos.io/",
|
||||||
|
"whitepaperLink":"https://github.com/EOSIO/Documentation/blob/master/TechnicalWhitePaper.md",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/eos/"
|
||||||
|
},
|
||||||
|
"ETC-USD":{
|
||||||
|
"name":"Ethereum Classic",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://ethereumclassic.org/",
|
||||||
|
"whitepaperLink":"https://ethereumclassic.org/why-classic",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/ethereum-classic/"
|
||||||
|
},
|
||||||
|
"ETH-USD":{
|
||||||
|
"name":"Ethereum",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://ethereum.org/",
|
||||||
|
"whitepaperLink":"https://ethereum.org/whitepaper/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/ethereum/",
|
||||||
|
"displayStepSize":"0.001",
|
||||||
|
"displayTickSize":"0.1"
|
||||||
|
},
|
||||||
|
"FIL-USD":{
|
||||||
|
"name":"Filecoin",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://filecoin.io/",
|
||||||
|
"whitepaperLink":"https://filecoin.io/filecoin.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/filecoin/"
|
||||||
|
},
|
||||||
|
"HNT-USD":{
|
||||||
|
"name":"Helium",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://www.helium.com",
|
||||||
|
"whitepaperLink":"http://whitepaper.helium.com",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/helium/"
|
||||||
|
},
|
||||||
|
"ICP-USD":{
|
||||||
|
"name":"Internet Computer",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://dfinity.org",
|
||||||
|
"whitepaperLink":"https://dfinity.org/whitepaper.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/internet-computer/"
|
||||||
|
},
|
||||||
|
"LDO-USD":{
|
||||||
|
"name":"Lido DAO",
|
||||||
|
"tags":[
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://lido.fi/",
|
||||||
|
"whitepaperLink":"https://lido.fi/static/Lido:Ethereum-Liquid-Staking.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/lido-dao/"
|
||||||
|
},
|
||||||
|
"LINK-USD":{
|
||||||
|
"name":"Chainlink",
|
||||||
|
"tags":[
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://chain.link/",
|
||||||
|
"whitepaperLink":"https://link.smartcontract.com/whitepaper",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/chainlink/"
|
||||||
|
},
|
||||||
|
"LTC-USD":{
|
||||||
|
"name":"Litecoin",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://litecoin.org/",
|
||||||
|
"whitepaperLink":"https://litecoin.info/index.php/Main_Page",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/litecoin/"
|
||||||
|
},
|
||||||
|
"MATIC-USD":{
|
||||||
|
"name":"Polygon",
|
||||||
|
"tags":[
|
||||||
|
"Layer 2"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://polygon.technology/",
|
||||||
|
"whitepaperLink":"https://polygon.technology/lightpaper-polygon.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/polygon/"
|
||||||
|
},
|
||||||
|
"MKR-USD":{
|
||||||
|
"name":"Maker",
|
||||||
|
"tags":[
|
||||||
|
"Governance"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://makerdao.com",
|
||||||
|
"whitepaperLink":"https://makerdao.com/whitepaper",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/maker/"
|
||||||
|
},
|
||||||
|
"NEAR-USD":{
|
||||||
|
"name":"NEAR Protocol",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://near.org",
|
||||||
|
"whitepaperLink":"https://near.org/papers/the-official-near-white-paper/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/near-protocol/"
|
||||||
|
},
|
||||||
|
"OP-USD":{
|
||||||
|
"name":"Optimism",
|
||||||
|
"tags":[
|
||||||
|
|
||||||
|
],
|
||||||
|
"websiteLink":"https://www.optimism.io/",
|
||||||
|
"whitepaperLink":"https://github.com/ethereum-optimism",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/optimism-ethereum/"
|
||||||
|
},
|
||||||
|
"PEPE-USD":{
|
||||||
|
"name":"Pepe",
|
||||||
|
"tags":[
|
||||||
|
|
||||||
|
],
|
||||||
|
"websiteLink":"https://www.pepe.vip/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/pepe/"
|
||||||
|
},
|
||||||
|
"RUNE-USD":{
|
||||||
|
"name":"THORChain",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://thorchain.org",
|
||||||
|
"whitepaperLink":"https://whitepaper.io/document/709/thorchain-whitepaper",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/thorchain/"
|
||||||
|
},
|
||||||
|
"SEI-USD":{
|
||||||
|
"name":"Sei",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1",
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://www.sei.io/",
|
||||||
|
"whitepaperLink":"https://github.com/sei-protocol/sei-chain/blob/3c9576fee3494ce039df684624f918dd8066ba3f/whitepaper/Sei_Whitepaper.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/sei/"
|
||||||
|
},
|
||||||
|
"SHIB-USD":{
|
||||||
|
"name":"Shiba Inu",
|
||||||
|
"tags":[
|
||||||
|
|
||||||
|
],
|
||||||
|
"websiteLink":"https://shibatoken.com/",
|
||||||
|
"whitepaperLink":"https://docs.shibatoken.com/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/shiba-inu/"
|
||||||
|
},
|
||||||
|
"SNX-USD":{
|
||||||
|
"name":"Synthetix",
|
||||||
|
"tags":[
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://synthetix.io/",
|
||||||
|
"whitepaperLink":"https://docs.synthetix.io/litepaper",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/synthetix-network-token/"
|
||||||
|
},
|
||||||
|
"SOL-USD":{
|
||||||
|
"name":"Solana",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://solana.com/",
|
||||||
|
"whitepaperLink":"https://solana.com/solana-whitepaper.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/solana/"
|
||||||
|
},
|
||||||
|
"SUI-USD":{
|
||||||
|
"name":"Sui",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://sui.io/",
|
||||||
|
"whitepaperLink":"https://github.com/MystenLabs",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/sui/"
|
||||||
|
},
|
||||||
|
"SUSHI-USD":{
|
||||||
|
"name":"Sushi",
|
||||||
|
"tags":[
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://sushi.com/",
|
||||||
|
"whitepaperLink":"https://docs.sushi.com/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/sushiswap/"
|
||||||
|
},
|
||||||
|
"TRX-USD":{
|
||||||
|
"name":"TRON",
|
||||||
|
"tags":[
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://tron.network/",
|
||||||
|
"whitepaperLink":"https://tron.network/static/doc/white_paper_v_2_0.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/tron/"
|
||||||
|
},
|
||||||
|
"UMA-USD":{
|
||||||
|
"name":"UMA",
|
||||||
|
"tags":[
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://umaproject.org/",
|
||||||
|
"whitepaperLink":"https://github.com/UMAprotocol/whitepaper",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/uma/"
|
||||||
|
},
|
||||||
|
"UNI-USD":{
|
||||||
|
"name":"Uniswap",
|
||||||
|
"tags":[
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://uniswap.org/",
|
||||||
|
"whitepaperLink":"https://uniswap.org/whitepaper-v3.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/uniswap/"
|
||||||
|
},
|
||||||
|
"WLD-USD":{
|
||||||
|
"name":"Worldcoin",
|
||||||
|
"tags":[
|
||||||
|
|
||||||
|
],
|
||||||
|
"websiteLink":"https://worldcoin.org/",
|
||||||
|
"whitepaperLink":"https://whitepaper.worldcoin.org/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/worldcoin-org/"
|
||||||
|
},
|
||||||
|
"XLM-USD":{
|
||||||
|
"name":"Stellar",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://www.stellar.org/",
|
||||||
|
"whitepaperLink":"https://www.stellar.org/papers/stellar-consensus-protocol",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/stellar/"
|
||||||
|
},
|
||||||
|
"XMR-USD":{
|
||||||
|
"name":"Monero",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://www.getmonero.org/",
|
||||||
|
"whitepaperLink":"https://www.getmonero.org/resources/research-lab/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/monero/"
|
||||||
|
},
|
||||||
|
"XRP-USD":{
|
||||||
|
"name":"Ripple",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://ripple.com/currency/",
|
||||||
|
"whitepaperLink":"https://github.com/ripple",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/xrp/"
|
||||||
|
},
|
||||||
|
"XTZ-USD":{
|
||||||
|
"name":"Tezos",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://tezos.com",
|
||||||
|
"whitepaperLink":"https://tezos.com/whitepaper.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/tezos/"
|
||||||
|
},
|
||||||
|
"YFI-USD":{
|
||||||
|
"name":"Yearn",
|
||||||
|
"tags":[
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://yearn.finance/",
|
||||||
|
"whitepaperLink":"https://docs.yearn.finance/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/yearn-finance/"
|
||||||
|
},
|
||||||
|
"ZEC-USD":{
|
||||||
|
"name":"Zcash",
|
||||||
|
"tags":[
|
||||||
|
"Layer 1"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://z.cash/",
|
||||||
|
"whitepaperLink":"https://z.cash/technology/",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/zcash/"
|
||||||
|
},
|
||||||
|
"ZRX-USD":{
|
||||||
|
"name":"0x",
|
||||||
|
"tags":[
|
||||||
|
"Defi"
|
||||||
|
],
|
||||||
|
"websiteLink":"https://0x.org/",
|
||||||
|
"whitepaperLink":"https://0x.org/pdfs/0x_white_paper.pdf",
|
||||||
|
"coinMarketCapsLink":"https://coinmarketcap.com/currencies/0x/"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,464 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96",
|
||||||
|
"name": "MetaMask",
|
||||||
|
"description": "",
|
||||||
|
"homepage": "https://metamask.io/",
|
||||||
|
"chains": [
|
||||||
|
"eip155:1",
|
||||||
|
"eip155:42161",
|
||||||
|
"eip155:43114"
|
||||||
|
],
|
||||||
|
"versions": [
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"app": {
|
||||||
|
"browser": "",
|
||||||
|
"ios": "https://apps.apple.com/us/app/metamask/id1438144202",
|
||||||
|
"android": "https://play.google.com/store/apps/details?id=io.metamask",
|
||||||
|
"mac": "",
|
||||||
|
"windows": "",
|
||||||
|
"linux": ""
|
||||||
|
},
|
||||||
|
"mobile": {
|
||||||
|
"native": "metamask:",
|
||||||
|
"universal": "https://metamask.app.link"
|
||||||
|
},
|
||||||
|
"desktop": {
|
||||||
|
"native": "",
|
||||||
|
"universal": ""
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"shortName": "MetaMask",
|
||||||
|
"colors": {
|
||||||
|
"primary": "rgb(255, 255, 255)",
|
||||||
|
"secondary": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"comment": "MetaMask",
|
||||||
|
"iosMinVersion": "0",
|
||||||
|
"imageUrl": "",
|
||||||
|
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"type": "walletConnectV2",
|
||||||
|
"native": "metamask:",
|
||||||
|
"universal": "https://metamask.app.link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"methods": [
|
||||||
|
"eth_sendTransaction",
|
||||||
|
"personal_sign",
|
||||||
|
"eth_signTypedData",
|
||||||
|
"wallet_addEthereumChain"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userFields": {
|
||||||
|
"analyticEvent": "METAMASK",
|
||||||
|
"imageName": "metamask.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "coinbase-wallet",
|
||||||
|
"name": "Coinbase Wallet",
|
||||||
|
"description": "",
|
||||||
|
"homepage": "https://www.coinbase.com/wallet",
|
||||||
|
"chains": [
|
||||||
|
"eip155:1"
|
||||||
|
],
|
||||||
|
"versions": [
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"app": {
|
||||||
|
"browser": "",
|
||||||
|
"ios": "https://apps.apple.com/us/app/coinbase-wallet-nfts-crypto/id1278383455",
|
||||||
|
"android": "https://play.google.com/store/apps/details?id=org.toshi",
|
||||||
|
"mac": "",
|
||||||
|
"windows": "",
|
||||||
|
"linux": ""
|
||||||
|
},
|
||||||
|
"mobile": {
|
||||||
|
"native": "cbwallet:",
|
||||||
|
"universal": ""
|
||||||
|
},
|
||||||
|
"desktop": {
|
||||||
|
"native": "",
|
||||||
|
"universal": ""
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"shortName": "Coinbase",
|
||||||
|
"colors": {
|
||||||
|
"primary": "rgb(255, 255, 255)",
|
||||||
|
"secondary": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"comment": "Coinbase",
|
||||||
|
"iosMinVersion": "1.8.0",
|
||||||
|
"imageUrl": "",
|
||||||
|
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"type": "walletSegue",
|
||||||
|
"native": "cbwallet:",
|
||||||
|
"universal": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"methods": [
|
||||||
|
"eth_sendTransaction",
|
||||||
|
"personal_sign",
|
||||||
|
"eth_signTypedData",
|
||||||
|
"wallet_addEthereumChain"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userFields": {
|
||||||
|
"analyticEvent": "COINBASE_WALLET",
|
||||||
|
"imageName": "coinbase-wallet.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9d373b43ad4d2cf190fb1a774ec964a1addf406d6fd24af94ab7596e58c291b2",
|
||||||
|
"name": "imToken",
|
||||||
|
"description": "",
|
||||||
|
"homepage": "https://token.im/",
|
||||||
|
"chains": [
|
||||||
|
"eip155:1"
|
||||||
|
],
|
||||||
|
"versions": [
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"app": {
|
||||||
|
"browser": "",
|
||||||
|
"ios": "https://itunes.apple.com/us/app/imtoken2/id1384798940",
|
||||||
|
"android": "https://play.google.com/store/apps/details?id=im.token.app",
|
||||||
|
"mac": "",
|
||||||
|
"windows": "",
|
||||||
|
"linux": ""
|
||||||
|
},
|
||||||
|
"mobile": {
|
||||||
|
"native": "imtokenv2:",
|
||||||
|
"universal": ""
|
||||||
|
},
|
||||||
|
"desktop": {
|
||||||
|
"native": "",
|
||||||
|
"universal": ""
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"shortName": "imToken",
|
||||||
|
"colors": {
|
||||||
|
"primary": "rgb(255, 255, 255)",
|
||||||
|
"secondary": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"comment": "imToken",
|
||||||
|
"iosMinVersion": "0",
|
||||||
|
"imageUrl": "",
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"type": "walletConnectV2",
|
||||||
|
"native": "imtokenv2:",
|
||||||
|
"universal": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"methods": [
|
||||||
|
"eth_sendTransaction",
|
||||||
|
"personal_sign",
|
||||||
|
"eth_signTypedData"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userFields": {
|
||||||
|
"analyticEvent": "IMTOKEN",
|
||||||
|
"imageName": "imtoken.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0",
|
||||||
|
"name": "Trust Wallet",
|
||||||
|
"description": "",
|
||||||
|
"homepage": "https://trustwallet.com/",
|
||||||
|
"chains": [
|
||||||
|
"eip155:1",
|
||||||
|
"eip155:42161",
|
||||||
|
"eip155:43114"
|
||||||
|
],
|
||||||
|
"versions": [
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"app": {
|
||||||
|
"browser": "",
|
||||||
|
"ios": "https://apps.apple.com/app/apple-store/id1288339409",
|
||||||
|
"android": "https://play.google.com/store/apps/details?id=com.wallet.crypto.trustapp",
|
||||||
|
"mac": "",
|
||||||
|
"windows": "",
|
||||||
|
"linux": ""
|
||||||
|
},
|
||||||
|
"mobile": {
|
||||||
|
"native": "trust:",
|
||||||
|
"universal": "https://link.trustwallet.com"
|
||||||
|
},
|
||||||
|
"desktop": {
|
||||||
|
"native": "",
|
||||||
|
"universal": ""
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"shortName": "Trust",
|
||||||
|
"colors": {
|
||||||
|
"primary": "rgb(51, 117, 187)",
|
||||||
|
"secondary": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"comment": "Trust Wallet",
|
||||||
|
"iosMinVersion": "0",
|
||||||
|
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
||||||
|
"imageUrl": "",
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"type": "walletConnectV2",
|
||||||
|
"native": "trust:",
|
||||||
|
"universal": "https://link.trustwallet.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"methods": [
|
||||||
|
"eth_sendTransaction",
|
||||||
|
"personal_sign",
|
||||||
|
"eth_signTypedData"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userFields": {
|
||||||
|
"analyticEvent": "TRUST_WALLET",
|
||||||
|
"imageName": "trust-wallet.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Zerion",
|
||||||
|
"name": "Zerion",
|
||||||
|
"description": "",
|
||||||
|
"homepage": "https://zerion.io/",
|
||||||
|
"chains": [
|
||||||
|
"eip155:1"
|
||||||
|
],
|
||||||
|
"versions": [
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"app": {
|
||||||
|
"browser": "",
|
||||||
|
"ios": "https://apps.apple.com/app/apple-store/id1456732565",
|
||||||
|
"android": "https://play.google.com/store/apps/details?id=io.zerion.android",
|
||||||
|
"mac": "",
|
||||||
|
"windows": "",
|
||||||
|
"linux": ""
|
||||||
|
},
|
||||||
|
"mobile": {
|
||||||
|
"native": "zerion:",
|
||||||
|
"universal": ""
|
||||||
|
},
|
||||||
|
"desktop": {
|
||||||
|
"native": "",
|
||||||
|
"universal": ""
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"shortName": "Zerion",
|
||||||
|
"colors": {
|
||||||
|
"primary": "rgb(51, 117, 187)",
|
||||||
|
"secondary": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"comment": "Zerion Wallet",
|
||||||
|
"iosMinVersion": "0",
|
||||||
|
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
||||||
|
"imageUrl": "",
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"type": "walletConnectV2",
|
||||||
|
"native": "zerion:",
|
||||||
|
"universal": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"methods": [
|
||||||
|
"eth_sendTransaction",
|
||||||
|
"personal_sign",
|
||||||
|
"eth_signTypedData"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userFields": {
|
||||||
|
"analyticEvent": "ZERION",
|
||||||
|
"imageName": "zerion.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66",
|
||||||
|
"name": "TokenPocket",
|
||||||
|
"description": "",
|
||||||
|
"homepage": "https://tokenpocket.pro/",
|
||||||
|
"chains": [
|
||||||
|
"eip155:1"
|
||||||
|
],
|
||||||
|
"versions": [
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"app": {
|
||||||
|
"browser": "",
|
||||||
|
"ios": "https://apps.apple.com/us/app/tokenpocket-trusted-wallet/id1436028697",
|
||||||
|
"android": "https://play.google.com/store/apps/details?id=vip.mytokenpocket",
|
||||||
|
"mac": "",
|
||||||
|
"windows": "",
|
||||||
|
"linux": ""
|
||||||
|
},
|
||||||
|
"mobile": {
|
||||||
|
"native": "tpoutside:",
|
||||||
|
"universal": ""
|
||||||
|
},
|
||||||
|
"desktop": {
|
||||||
|
"native": "",
|
||||||
|
"universal": ""
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"shortName": "TokenPocket",
|
||||||
|
"colors": {
|
||||||
|
"primary": "rgb(41, 128, 254)",
|
||||||
|
"secondary": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"comment": "TokenPocket",
|
||||||
|
"iosMinVersion": "0",
|
||||||
|
"imageUrl": "",
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"type": "walletConnectV2",
|
||||||
|
"native": "tpoutside:",
|
||||||
|
"universal": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"methods": [
|
||||||
|
"eth_sendTransaction",
|
||||||
|
"personal_sign",
|
||||||
|
"eth_signTypedData"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userFields": {
|
||||||
|
"analyticEvent": "TOKEN_POCKET",
|
||||||
|
"imageName": "tokenpocket.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369",
|
||||||
|
"name": "Rainbow",
|
||||||
|
"description": "",
|
||||||
|
"homepage": "https://rainbow.me/",
|
||||||
|
"chains": [
|
||||||
|
"eip155:1"
|
||||||
|
],
|
||||||
|
"versions": [
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"app": {
|
||||||
|
"browser": "",
|
||||||
|
"ios": "https://apps.apple.com/us/app/rainbow-ethereum-wallet/id1457119021",
|
||||||
|
"android": "",
|
||||||
|
"mac": "",
|
||||||
|
"windows": "",
|
||||||
|
"linux": ""
|
||||||
|
},
|
||||||
|
"mobile": {
|
||||||
|
"native": "rainbow:",
|
||||||
|
"universal": "https://rnbwapp.com"
|
||||||
|
},
|
||||||
|
"desktop": {
|
||||||
|
"native": "",
|
||||||
|
"universal": ""
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"shortName": "Rainbow",
|
||||||
|
"colors": {
|
||||||
|
"primary": "rgb(0, 30, 89)",
|
||||||
|
"secondary": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"comment": "Rainbow",
|
||||||
|
"iosMinVersion": "0",
|
||||||
|
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
||||||
|
"backlinked": true,
|
||||||
|
"imageUrl": "",
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"type": "walletConnectV2",
|
||||||
|
"native": "rainbow:",
|
||||||
|
"universal": "https://rnbwapp.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"methods": [
|
||||||
|
"eth_sendTransaction",
|
||||||
|
"personal_sign",
|
||||||
|
"eth_signTypedData"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userFields": {
|
||||||
|
"analyticEvent": "RAINBOW_WALLET",
|
||||||
|
"imageName": "rainbow-wallet.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "09102e7bbbd3f92001eda104abe23803181629f695e8f1b95af96d88ff7d5890",
|
||||||
|
"name": "1inch Wallet",
|
||||||
|
"description": "",
|
||||||
|
"homepage": "https://1inch.io/wallet/",
|
||||||
|
"chains": [
|
||||||
|
"eip155:1",
|
||||||
|
"eip155:56"
|
||||||
|
],
|
||||||
|
"versions": [
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"app": {
|
||||||
|
"browser": "",
|
||||||
|
"ios": "https://apps.apple.com/us/app/1inch-defi-wallet/id1546049391",
|
||||||
|
"android": "",
|
||||||
|
"mac": "",
|
||||||
|
"windows": "",
|
||||||
|
"linux": ""
|
||||||
|
},
|
||||||
|
"mobile": {
|
||||||
|
"native": "oneinch:",
|
||||||
|
"universal": "https://wallet.1inch.io"
|
||||||
|
},
|
||||||
|
"desktop": {
|
||||||
|
"native": "",
|
||||||
|
"universal": ""
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"shortName": "1inch",
|
||||||
|
"colors": {
|
||||||
|
"primary": "rgb(31, 36, 46)",
|
||||||
|
"secondary": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"comment": "1inch",
|
||||||
|
"iosMinVersion": "0",
|
||||||
|
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
||||||
|
"imageUrl": "",
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"type": "walletConnectV2",
|
||||||
|
"native": "oneinch:",
|
||||||
|
"universal": "https://wallet.1inch.io"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"methods": [
|
||||||
|
"eth_sendTransaction",
|
||||||
|
"personal_sign",
|
||||||
|
"eth_signTypedData"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userFields": {
|
||||||
|
"analyticEvent": "1INCH",
|
||||||
|
"imageName": "1inch.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 4.8 KiB |
@@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
source="dist/.well-known/apple-app-site-association"
|
||||||
|
if [ ! -f "$source" ]; then
|
||||||
|
echo "Error: $source file not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
app_id=$IOS_APP_ID
|
||||||
|
if [ -z "$app_id" ]; then
|
||||||
|
echo "Error: IOS_APP_ID is empty"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
sed -i '' "s/{PLACE_YOUR_APP_ID_HERE}/$app_id/g" $source
|
||||||
|
else
|
||||||
|
sed -i "s/{PLACE_YOUR_APP_ID_HERE}/$app_id/g" $source
|
||||||
|
fi
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
import path from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
const INTERCOM_APP_ID = process.env.INTERCOM_APP_ID;
|
||||||
|
|
||||||
|
const currentPath = fileURLToPath(import.meta.url);
|
||||||
|
const projectRoot = path.dirname(currentPath);
|
||||||
|
const htmlFilePath = path.resolve(projectRoot, '../dist/index.html');
|
||||||
|
|
||||||
|
if (INTERCOM_APP_ID) {
|
||||||
|
try {
|
||||||
|
const html = await fs.readFile(htmlFilePath, 'utf-8');
|
||||||
|
|
||||||
|
const intercomScripts = `
|
||||||
|
<!-- Intercom -->
|
||||||
|
<script>
|
||||||
|
window.intercomSettings = {
|
||||||
|
api_base: 'https://api-iam.intercom.io',
|
||||||
|
app_id: '${INTERCOM_APP_ID}',
|
||||||
|
custom_launcher_selector: '.custom_intercom',
|
||||||
|
hide_default_launcher: true,
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// We pre-filled your app ID in the widget URL: 'https://widget.intercom.io/widget/${INTERCOM_APP_ID}'
|
||||||
|
(function () {
|
||||||
|
var w = window;
|
||||||
|
var ic = w.Intercom;
|
||||||
|
if (typeof ic === 'function') {
|
||||||
|
ic('reattach_activator');
|
||||||
|
ic('update', w.intercomSettings);
|
||||||
|
} else {
|
||||||
|
var d = document;
|
||||||
|
var i = function () {
|
||||||
|
i.c(arguments);
|
||||||
|
};
|
||||||
|
i.q = [];
|
||||||
|
i.c = function (args) {
|
||||||
|
i.q.push(args);
|
||||||
|
};
|
||||||
|
w.Intercom = i;
|
||||||
|
var l = function () {
|
||||||
|
var s = d.createElement('script');
|
||||||
|
s.type = 'text/javascript';
|
||||||
|
s.async = true;
|
||||||
|
s.src = 'https://widget.intercom.io/widget/${INTERCOM_APP_ID}';
|
||||||
|
var x = d.getElementsByTagName('script')[0];
|
||||||
|
x.parentNode.insertBefore(s, x);
|
||||||
|
};
|
||||||
|
if (document.readyState === 'complete') {
|
||||||
|
l();
|
||||||
|
} else if (w.attachEvent) {
|
||||||
|
w.attachEvent('onload', l);
|
||||||
|
} else {
|
||||||
|
w.addEventListener('load', l, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const injectedHtml = html.replace(
|
||||||
|
'<div id="root"></div>',
|
||||||
|
`<div id="root"></div>\n${intercomScripts}\n`
|
||||||
|
);
|
||||||
|
|
||||||
|
await fs.writeFile(htmlFilePath, injectedHtml, 'utf-8');
|
||||||
|
|
||||||
|
console.log('Intercom scripts successfully injected.');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error injecting Intercom scripts:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,13 +7,20 @@ import { GrazProvider } from 'graz';
|
|||||||
|
|
||||||
import { AppRoute, DEFAULT_TRADE_ROUTE } from '@/constants/routes';
|
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 { DydxProvider } from '@/hooks/useDydxClient';
|
||||||
import { AccountsProvider } from '@/hooks/useAccounts';
|
import { AccountsProvider } from '@/hooks/useAccounts';
|
||||||
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
|
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';
|
||||||
|
|
||||||
@@ -26,6 +33,8 @@ import ProfilePage from '@/pages/Profile';
|
|||||||
import { SettingsPage } from '@/pages/settings/Settings';
|
import { SettingsPage } from '@/pages/settings/Settings';
|
||||||
import TradePage from '@/pages/trade/Trade';
|
import TradePage from '@/pages/trade/Trade';
|
||||||
import { RewardsPage } from '@/pages/rewards/RewardsPage';
|
import { RewardsPage } from '@/pages/rewards/RewardsPage';
|
||||||
|
import { TermsOfUsePage } from '@/pages/TermsOfUsePage';
|
||||||
|
import { PrivacyPolicyPage } from '@/pages/PrivacyPolicyPage';
|
||||||
|
|
||||||
import { HeaderDesktop } from '@/layout/Header/HeaderDesktop';
|
import { HeaderDesktop } from '@/layout/Header/HeaderDesktop';
|
||||||
import { FooterDesktop } from '@/layout/Footer/FooterDesktop';
|
import { FooterDesktop } from '@/layout/Footer/FooterDesktop';
|
||||||
@@ -54,6 +63,7 @@ const Content = () => {
|
|||||||
const { isTablet, isNotTablet } = useBreakpoints();
|
const { isTablet, isNotTablet } = useBreakpoints();
|
||||||
const isShowingHeader = isNotTablet;
|
const isShowingHeader = isNotTablet;
|
||||||
const isShowingFooter = useShouldShowFooter();
|
const isShowingFooter = useShouldShowFooter();
|
||||||
|
const { chainTokenLabel } = useTokenConfigs();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
|
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
|
||||||
@@ -66,10 +76,9 @@ 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 />} />
|
||||||
{import.meta.env.MODE !== 'production' && (
|
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
|
||||||
<Route path={AppRoute.Rewards} element={<RewardsPage />} />
|
|
||||||
)}
|
|
||||||
{isTablet && (
|
{isTablet && (
|
||||||
<>
|
<>
|
||||||
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
||||||
@@ -81,6 +90,10 @@ const Content = () => {
|
|||||||
<Route element={<GuardedMobileRoute />}>
|
<Route element={<GuardedMobileRoute />}>
|
||||||
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
|
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
|
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
|
||||||
|
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
|
||||||
|
|
||||||
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
|
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
@@ -111,6 +124,7 @@ 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),
|
||||||
@@ -197,7 +211,7 @@ Styled.NotificationsToastArea = styled(NotificationsToastArea)`
|
|||||||
|
|
||||||
Styled.DialogArea = styled.aside`
|
Styled.DialogArea = styled.aside`
|
||||||
position: fixed;
|
position: fixed;
|
||||||
height: 100vh;
|
height: 100%;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
overflow: clip;
|
overflow: clip;
|
||||||
|
|||||||
@@ -3,31 +3,43 @@ import styled, { AnyStyledComponent } from 'styled-components';
|
|||||||
|
|
||||||
import { type MenuConfig } from '@/constants/menus';
|
import { type MenuConfig } from '@/constants/menus';
|
||||||
|
|
||||||
import { Dialog, DialogPlacement } from '@/components/Dialog';
|
import { Dialog, DialogPlacement, type DialogProps } from '@/components/Dialog';
|
||||||
import { ComboboxMenu } from '@/components/ComboboxMenu';
|
import { ComboboxMenu, type ComboboxMenuProps } from '@/components/ComboboxMenu';
|
||||||
|
|
||||||
type ElementProps<MenuItemValue extends string | number, MenuGroupValue extends string | number> = {
|
type ElementProps<MenuItemValue extends string | number, MenuGroupValue extends string | number> = {
|
||||||
isOpen?: boolean;
|
|
||||||
setIsOpen?: (open: boolean) => void;
|
|
||||||
title?: React.ReactNode;
|
title?: React.ReactNode;
|
||||||
description?: React.ReactNode;
|
description?: React.ReactNode;
|
||||||
slotTrigger?: React.ReactNode;
|
|
||||||
slotHeaderInner?: React.ReactNode;
|
|
||||||
slotFooter?: React.ReactNode;
|
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
|
|
||||||
items: MenuConfig<MenuItemValue, MenuGroupValue>;
|
items: MenuConfig<MenuItemValue, MenuGroupValue>;
|
||||||
onItemSelected?: () => void;
|
|
||||||
inputPlaceholder?: string;
|
|
||||||
slotEmpty?: React.ReactNode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type StyleProps = {
|
type StyleProps = {
|
||||||
placement: DialogPlacement,
|
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ComboboxDialogMenu = <MenuItemValue extends string | number, MenuGroupValue extends string | number>({
|
type PickComboxMenuProps<
|
||||||
|
MenuItemValue extends string | number,
|
||||||
|
MenuGroupValue extends string | number
|
||||||
|
> = Pick<
|
||||||
|
ComboboxMenuProps<MenuItemValue, MenuGroupValue>,
|
||||||
|
'inputPlaceholder' | 'onItemSelected' | 'slotEmpty' | 'withSearch' | 'withStickyLayout'
|
||||||
|
>;
|
||||||
|
|
||||||
|
type PickDialogProps = Pick<
|
||||||
|
DialogProps,
|
||||||
|
| 'description'
|
||||||
|
| 'isOpen'
|
||||||
|
| 'placement'
|
||||||
|
| 'setIsOpen'
|
||||||
|
| 'slotHeaderInner'
|
||||||
|
| 'slotTrigger'
|
||||||
|
| 'slotFooter'
|
||||||
|
>;
|
||||||
|
|
||||||
|
export const ComboboxDialogMenu = <
|
||||||
|
MenuItemValue extends string | number,
|
||||||
|
MenuGroupValue extends string | number
|
||||||
|
>({
|
||||||
isOpen = false,
|
isOpen = false,
|
||||||
setIsOpen,
|
setIsOpen,
|
||||||
title,
|
title,
|
||||||
@@ -40,11 +52,16 @@ export const ComboboxDialogMenu = <MenuItemValue extends string | number, MenuGr
|
|||||||
onItemSelected,
|
onItemSelected,
|
||||||
inputPlaceholder,
|
inputPlaceholder,
|
||||||
slotEmpty,
|
slotEmpty,
|
||||||
|
withSearch,
|
||||||
|
withStickyLayout = true,
|
||||||
children,
|
children,
|
||||||
|
|
||||||
placement = DialogPlacement.Default,
|
placement = DialogPlacement.Default,
|
||||||
className,
|
className,
|
||||||
}: ElementProps<MenuItemValue, MenuGroupValue> & StyleProps) => (
|
}: ElementProps<MenuItemValue, MenuGroupValue> &
|
||||||
|
PickComboxMenuProps<MenuItemValue, MenuGroupValue> &
|
||||||
|
PickDialogProps &
|
||||||
|
StyleProps) => (
|
||||||
// TODO: sub-menu state management
|
// TODO: sub-menu state management
|
||||||
<Styled.Dialog
|
<Styled.Dialog
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
@@ -54,7 +71,6 @@ export const ComboboxDialogMenu = <MenuItemValue extends string | number, MenuGr
|
|||||||
slotHeaderInner={slotHeaderInner}
|
slotHeaderInner={slotHeaderInner}
|
||||||
slotTrigger={slotTrigger}
|
slotTrigger={slotTrigger}
|
||||||
slotFooter={slotFooter}
|
slotFooter={slotFooter}
|
||||||
|
|
||||||
placement={placement}
|
placement={placement}
|
||||||
className={className}
|
className={className}
|
||||||
>
|
>
|
||||||
@@ -64,7 +80,8 @@ export const ComboboxDialogMenu = <MenuItemValue extends string | number, MenuGr
|
|||||||
title={title}
|
title={title}
|
||||||
inputPlaceholder={inputPlaceholder}
|
inputPlaceholder={inputPlaceholder}
|
||||||
slotEmpty={slotEmpty}
|
slotEmpty={slotEmpty}
|
||||||
withStickyLayout
|
withSearch={withSearch}
|
||||||
|
withStickyLayout={withStickyLayout}
|
||||||
/>
|
/>
|
||||||
{children}
|
{children}
|
||||||
</Styled.Dialog>
|
</Styled.Dialog>
|
||||||
@@ -98,4 +115,5 @@ Styled.Dialog = styled(Dialog)`
|
|||||||
|
|
||||||
Styled.ComboboxMenu = styled(ComboboxMenu)`
|
Styled.ComboboxMenu = styled(ComboboxMenu)`
|
||||||
--comboboxMenu-backgroundColor: var(--comboboxDialogMenu-backgroundColor);
|
--comboboxMenu-backgroundColor: var(--comboboxDialogMenu-backgroundColor);
|
||||||
|
--comboboxMenu-item-gap: var(--comboxDialogMenu-item-gap, 0.5rem);
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { layoutMixins } from '@/styles/layoutMixins';
|
|||||||
|
|
||||||
import { Tag } from '@/components/Tag';
|
import { Tag } from '@/components/Tag';
|
||||||
|
|
||||||
type ElementProps<MenuItemValue extends string, MenuGroupValue extends string> = {
|
type ElementProps<MenuItemValue extends string | number, MenuGroupValue extends string | number> = {
|
||||||
items: MenuConfig<MenuItemValue, MenuGroupValue>;
|
items: MenuConfig<MenuItemValue, MenuGroupValue>;
|
||||||
onItemSelected?: () => void;
|
onItemSelected?: () => void;
|
||||||
|
|
||||||
@@ -23,6 +23,11 @@ type StyleProps = {
|
|||||||
withStickyLayout?: boolean;
|
withStickyLayout?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ComboboxMenuProps<
|
||||||
|
MenuItemValue extends string | number,
|
||||||
|
MenuGroupValue extends string | number
|
||||||
|
> = ElementProps<MenuItemValue, MenuGroupValue> & StyleProps;
|
||||||
|
|
||||||
export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extends string>({
|
export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extends string>({
|
||||||
items,
|
items,
|
||||||
onItemSelected,
|
onItemSelected,
|
||||||
@@ -34,7 +39,7 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
|
|||||||
|
|
||||||
className,
|
className,
|
||||||
withStickyLayout,
|
withStickyLayout,
|
||||||
}: ElementProps<MenuItemValue, MenuGroupValue> & StyleProps) => {
|
}: ComboboxMenuProps<MenuItemValue, MenuGroupValue>) => {
|
||||||
const [highlightedCommand, setHighlightedCommand] = useState<MenuItemValue>();
|
const [highlightedCommand, setHighlightedCommand] = useState<MenuItemValue>();
|
||||||
const [searchValue, setSearchValue] = useState('');
|
const [searchValue, setSearchValue] = useState('');
|
||||||
// const inputRef = useRef<HTMLInputElement | null>(null);
|
// const inputRef = useRef<HTMLInputElement | null>(null);
|
||||||
@@ -171,6 +176,7 @@ Styled.Command = styled(Command)<{ $withStickyLayout?: boolean }>`
|
|||||||
--comboboxMenu-item-highlighted-backgroundColor: var(--color-layer-3);
|
--comboboxMenu-item-highlighted-backgroundColor: var(--color-layer-3);
|
||||||
--comboboxMenu-item-highlighted-textColor: var(--color-text-1);
|
--comboboxMenu-item-highlighted-textColor: var(--color-text-1);
|
||||||
--comboboxMenu-item-backgroundColor: ;
|
--comboboxMenu-item-backgroundColor: ;
|
||||||
|
--comboboxMenu-item-gap: 0.5rem;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
align-content: start;
|
align-content: start;
|
||||||
@@ -269,18 +275,17 @@ Styled.List = styled(Command.List)<{ $withStickyLayout?: boolean }>`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Item = styled(Command.Item)`
|
Styled.Item = styled(Command.Item)`
|
||||||
|
${layoutMixins.scrollSnapItem}
|
||||||
${popoverMixins.item}
|
${popoverMixins.item}
|
||||||
--item-checked-backgroundColor: var(--comboboxMenu-item-checked-backgroundColor);
|
--item-checked-backgroundColor: var(--comboboxMenu-item-checked-backgroundColor);
|
||||||
--item-checked-textColor: var(--comboboxMenu-item-checked-textColor);
|
--item-checked-textColor: var(--comboboxMenu-item-checked-textColor);
|
||||||
--item-highlighted-textColor: var(--comboboxMenu-item-highlighted-textColor);
|
--item-highlighted-textColor: var(--comboboxMenu-item-highlighted-textColor);
|
||||||
|
--item-gap: var(--comboboxMenu-item-gap);
|
||||||
${layoutMixins.scrollSnapItem}
|
|
||||||
|
|
||||||
background-color: var(--comboboxMenu-backgroundColor, inherit);
|
background-color: var(--comboboxMenu-backgroundColor, inherit);
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
|
||||||
|
|
||||||
&[aria-disabled='true'] {
|
&[aria-disabled='true'] {
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ type StyleProps = {
|
|||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DialogProps = ElementProps & StyleProps;
|
||||||
|
|
||||||
const DialogPortal = ({
|
const DialogPortal = ({
|
||||||
withPortal,
|
withPortal,
|
||||||
container,
|
container,
|
||||||
@@ -82,7 +84,7 @@ export const Dialog = ({
|
|||||||
hasHeaderBorder = false,
|
hasHeaderBorder = false,
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
}: ElementProps & StyleProps) => {
|
}: DialogProps) => {
|
||||||
const closeButtonRef = useRef<HTMLButtonElement>();
|
const closeButtonRef = useRef<HTMLButtonElement>();
|
||||||
|
|
||||||
const showOverlay = ![DialogPlacement.Inline, DialogPlacement.FullScreen].includes(placement);
|
const showOverlay = ![DialogPlacement.Inline, DialogPlacement.FullScreen].includes(placement);
|
||||||
|
|||||||
@@ -6,11 +6,14 @@ import {
|
|||||||
AddressConnectorIcon,
|
AddressConnectorIcon,
|
||||||
ArrowIcon,
|
ArrowIcon,
|
||||||
Bar3Icon,
|
Bar3Icon,
|
||||||
|
BellIcon,
|
||||||
|
BellStrokeIcon,
|
||||||
BoxCloseIcon,
|
BoxCloseIcon,
|
||||||
CalculatorIcon,
|
CalculatorIcon,
|
||||||
CaretIcon,
|
CaretIcon,
|
||||||
CautionCircleStrokeIcon,
|
CautionCircleStrokeIcon,
|
||||||
CautionCircleIcon,
|
CautionCircleIcon,
|
||||||
|
ChatIcon,
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
ChevronLeftIcon,
|
ChevronLeftIcon,
|
||||||
ChevronRightIcon,
|
ChevronRightIcon,
|
||||||
@@ -71,11 +74,14 @@ export enum IconName {
|
|||||||
AddressConnector = 'AddressConnector',
|
AddressConnector = 'AddressConnector',
|
||||||
Arrow = 'Arrow',
|
Arrow = 'Arrow',
|
||||||
Bar3 = 'Bar3',
|
Bar3 = 'Bar3',
|
||||||
|
Bell = 'Bell',
|
||||||
|
BellStroked = 'BellStroked',
|
||||||
BoxClose = 'BoxClose',
|
BoxClose = 'BoxClose',
|
||||||
Calculator = 'Calculator',
|
Calculator = 'Calculator',
|
||||||
Caret = 'Caret',
|
Caret = 'Caret',
|
||||||
CautionCircle = 'CautionCircle',
|
CautionCircle = 'CautionCircle',
|
||||||
CautionCircleStroked = 'CautionCircleStroked',
|
CautionCircleStroked = 'CautionCircleStroked',
|
||||||
|
Chat = 'Chat',
|
||||||
Check = 'Check',
|
Check = 'Check',
|
||||||
ChevronLeft = 'ChevronLeft',
|
ChevronLeft = 'ChevronLeft',
|
||||||
ChevronRight = 'ChevronRight',
|
ChevronRight = 'ChevronRight',
|
||||||
@@ -137,11 +143,14 @@ const icons = {
|
|||||||
[IconName.AddressConnector]: AddressConnectorIcon,
|
[IconName.AddressConnector]: AddressConnectorIcon,
|
||||||
[IconName.Arrow]: ArrowIcon,
|
[IconName.Arrow]: ArrowIcon,
|
||||||
[IconName.Bar3]: Bar3Icon,
|
[IconName.Bar3]: Bar3Icon,
|
||||||
|
[IconName.Bell]: BellIcon,
|
||||||
|
[IconName.BellStroked]: BellStrokeIcon,
|
||||||
[IconName.BoxClose]: BoxCloseIcon,
|
[IconName.BoxClose]: BoxCloseIcon,
|
||||||
[IconName.Calculator]: CalculatorIcon,
|
[IconName.Calculator]: CalculatorIcon,
|
||||||
[IconName.Caret]: CaretIcon,
|
[IconName.Caret]: CaretIcon,
|
||||||
[IconName.CautionCircle]: CautionCircleIcon,
|
[IconName.CautionCircle]: CautionCircleIcon,
|
||||||
[IconName.CautionCircleStroked]: CautionCircleStrokeIcon,
|
[IconName.CautionCircleStroked]: CautionCircleStrokeIcon,
|
||||||
|
[IconName.Chat]: ChatIcon,
|
||||||
[IconName.Check]: CheckIcon,
|
[IconName.Check]: CheckIcon,
|
||||||
[IconName.ChevronLeft]: ChevronLeftIcon,
|
[IconName.ChevronLeft]: ChevronLeftIcon,
|
||||||
[IconName.ChevronRight]: ChevronRightIcon,
|
[IconName.ChevronRight]: ChevronRightIcon,
|
||||||
@@ -213,7 +222,8 @@ export const Icon = styled(
|
|||||||
iconComponent: Component = iconName && icons[iconName],
|
iconComponent: Component = iconName && icons[iconName],
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: ElementProps & StyleProps) => (Component ? <Component className={className} {...props} /> : null)
|
}: ElementProps & StyleProps) =>
|
||||||
|
Component ? <Component className={className} {...props} /> : null
|
||||||
)`
|
)`
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
|
|||||||
@@ -207,6 +207,16 @@ 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)`
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ type ElementProps = {
|
|||||||
};
|
};
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
href?: string;
|
href?: string;
|
||||||
onClick?: () => void;
|
onClick?: (e: MouseEvent) => void;
|
||||||
withIcon?: boolean;
|
withIcon?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -37,12 +37,12 @@ export const Link = forwardRef<HTMLAnchorElement, ElementProps & StyleProps>(
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
className={className}
|
className={className}
|
||||||
href={href}
|
href={href}
|
||||||
onClick={() => {
|
onClick={(e: MouseEvent) => {
|
||||||
if (analyticsConfig) {
|
if (analyticsConfig) {
|
||||||
console.log(analyticsConfig);
|
console.log(analyticsConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick?.();
|
onClick?.(e);
|
||||||
}}
|
}}
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ type PanelProps = {
|
|||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
href?: string;
|
href?: string;
|
||||||
onHeaderClick?: () => void;
|
onHeaderClick?: () => void;
|
||||||
|
onClick?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type PanelStyleProps = {
|
type PanelStyleProps = {
|
||||||
@@ -24,10 +25,11 @@ export const Panel = ({
|
|||||||
children,
|
children,
|
||||||
href,
|
href,
|
||||||
onHeaderClick,
|
onHeaderClick,
|
||||||
|
onClick,
|
||||||
hasSeparator,
|
hasSeparator,
|
||||||
className,
|
className,
|
||||||
}: PanelProps & PanelStyleProps) => (
|
}: PanelProps & PanelStyleProps) => (
|
||||||
<Styled.Panel>
|
<Styled.Panel onClick={onClick}>
|
||||||
{href ? (
|
{href ? (
|
||||||
<Link to={href}>
|
<Link to={href}>
|
||||||
{slotHeader ? (
|
{slotHeader ? (
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export const MarketTableCell = ({
|
|||||||
slotLeft={
|
slotLeft={
|
||||||
<>
|
<>
|
||||||
{showFavorite && <Icon iconName={IconName.Star} />}
|
{showFavorite && <Icon iconName={IconName.Star} />}
|
||||||
<Styled.AssetIcon symbol={asset?.symbol} />
|
<Styled.AssetIcon symbol={asset?.id} />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { STRING_KEYS } from './localization';
|
|||||||
export type Nullable<T> = T | null | undefined;
|
export type Nullable<T> = T | null | undefined;
|
||||||
|
|
||||||
// ------ V4 Protocols ------ //
|
// ------ V4 Protocols ------ //
|
||||||
|
export const AbacusAppConfig = Abacus.exchange.dydx.abacus.state.manager.AppConfigs;
|
||||||
export const IOImplementations = Abacus.exchange.dydx.abacus.utils.IOImplementations;
|
export const IOImplementations = Abacus.exchange.dydx.abacus.utils.IOImplementations;
|
||||||
export const UIImplementations = Abacus.exchange.dydx.abacus.utils.UIImplementations;
|
export const UIImplementations = Abacus.exchange.dydx.abacus.utils.UIImplementations;
|
||||||
export type AbacusDYDXChainTransactionsProtocol = Omit<
|
export type AbacusDYDXChainTransactionsProtocol = Omit<
|
||||||
@@ -58,16 +59,6 @@ export const TransactionType = Abacus.exchange.dydx.abacus.protocols.Transaction
|
|||||||
const transactionTypes = [...TransactionType.values()] as const;
|
const transactionTypes = [...TransactionType.values()] as const;
|
||||||
export type TransactionTypes = (typeof transactionTypes)[number];
|
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 ------
|
// ------ State ------
|
||||||
export type AbacusApiState = Abacus.exchange.dydx.abacus.state.manager.ApiState;
|
export type AbacusApiState = Abacus.exchange.dydx.abacus.state.manager.ApiState;
|
||||||
export const AbacusApiStatus = Abacus.exchange.dydx.abacus.state.manager.ApiStatus;
|
export const AbacusApiStatus = Abacus.exchange.dydx.abacus.state.manager.ApiStatus;
|
||||||
@@ -77,8 +68,13 @@ 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;
|
||||||
@@ -198,6 +194,12 @@ 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
|
||||||
@@ -255,3 +257,20 @@ export const TRADE_TYPES: Record<
|
|||||||
[AbacusOrderType.liquidation.name]: null,
|
[AbacusOrderType.liquidation.name]: null,
|
||||||
[AbacusOrderType.trailingStop.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>>;
|
||||||
|
|||||||
@@ -44,4 +44,4 @@ export type EvmDerivedAddresses = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AMOUNT_RESERVED_FOR_GAS_USDC = 100_000;
|
export const AMOUNT_RESERVED_FOR_GAS_USDC = 0.1;
|
||||||
|
|||||||
@@ -5,11 +5,15 @@ export enum DialogTypes {
|
|||||||
ExchangeOffline = 'ExchangeOffline',
|
ExchangeOffline = 'ExchangeOffline',
|
||||||
FillDetails = 'FillDetails',
|
FillDetails = 'FillDetails',
|
||||||
Help = 'Help',
|
Help = 'Help',
|
||||||
|
ExternalNavKeplr = 'ExternalNavKeplr',
|
||||||
MnemonicExport = 'MnemonicExport',
|
MnemonicExport = 'MnemonicExport',
|
||||||
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',
|
||||||
|
|||||||
@@ -24,6 +24,6 @@ export enum LocalStorageKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const LOCAL_STORAGE_VERSIONS = {
|
export const LOCAL_STORAGE_VERSIONS = {
|
||||||
[LocalStorageKey.EvmDerivedAddresses]: 'v1',
|
[LocalStorageKey.EvmDerivedAddresses]: 'v2',
|
||||||
// TODO: version all localStorage keys
|
// TODO: version all localStorage keys
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export type MenuItem<MenuItemValue, MenuItemTypes = string> = {
|
|||||||
value: MenuItemValue;
|
value: MenuItemValue;
|
||||||
|
|
||||||
slotBefore?: React.ReactNode;
|
slotBefore?: React.ReactNode;
|
||||||
label: string;
|
label: React.ReactNode;
|
||||||
labelRight?: React.ReactNode;
|
labelRight?: React.ReactNode;
|
||||||
tag?: React.ReactNode;
|
tag?: React.ReactNode;
|
||||||
slotAfter?: React.ReactNode;
|
slotAfter?: React.ReactNode;
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import environments from '../../public/configs/env.json';
|
||||||
|
|
||||||
|
// TODO: Update for Mainnet deployment
|
||||||
|
export const AVAILABLE_ENVIRONMENTS =
|
||||||
|
import.meta.env.MODE === 'production'
|
||||||
|
? environments.deployments.TESTNET
|
||||||
|
: environments.deployments.DEV;
|
||||||
|
|
||||||
|
export const CURRENT_ABACUS_DEPLOYMENT = import.meta.env.MODE === 'production' ? 'TESTNET' : 'DEV';
|
||||||
|
export const ENVIRONMENT_CONFIG_MAP = environments.environments;
|
||||||
|
export type DydxNetwork = keyof typeof ENVIRONMENT_CONFIG_MAP;
|
||||||
|
export const DEFAULT_APP_ENVIRONMENT = AVAILABLE_ENVIRONMENTS.default as DydxNetwork;
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import { ENDPOINTS, DEV_ENDPOINTS } from '@dydxprotocol/v4-localization';
|
|
||||||
|
|
||||||
export const NETWORK_ENDPOINTS = import.meta.env.MODE === 'production' ? ENDPOINTS : DEV_ENDPOINTS;
|
|
||||||
|
|
||||||
export const CLIENT_NETWORK_CONFIGS: Record<
|
|
||||||
string,
|
|
||||||
(typeof NETWORK_ENDPOINTS.environments)[number]
|
|
||||||
> = Object.fromEntries(
|
|
||||||
NETWORK_ENDPOINTS.environments.map((environment) => [environment.environment, environment])
|
|
||||||
);
|
|
||||||
|
|
||||||
export const DEFAULT_APP_ENVIRONMENT = NETWORK_ENDPOINTS.defaultEnvironment;
|
|
||||||
|
|
||||||
export enum DydxV4Network {
|
|
||||||
V4Mainnet = 'dydxprotocol-mainnet',
|
|
||||||
V4Staging = 'dydxprotocol-staging',
|
|
||||||
V4Testnet2 = 'dydxprotocol-testnet',
|
|
||||||
V4Local = 'dydxprotocol-dev',
|
|
||||||
}
|
|
||||||
|
|
||||||
export type DydxNetwork = keyof typeof CLIENT_NETWORK_CONFIGS;
|
|
||||||
|
|
||||||
export function isDydxV4Network(network: any): boolean {
|
|
||||||
return CLIENT_NETWORK_CONFIGS[network]?.version === 'v4';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isValidDydxNetwork(network: any): boolean {
|
|
||||||
return Object.keys(CLIENT_NETWORK_CONFIGS).includes(network);
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,8 @@ export enum AppRoute {
|
|||||||
Profile = '/profile',
|
Profile = '/profile',
|
||||||
Alerts = '/alerts',
|
Alerts = '/alerts',
|
||||||
Settings = '/settings',
|
Settings = '/settings',
|
||||||
Rewards = '/DV4TNT',
|
Terms = '/terms',
|
||||||
|
Privacy = '/privacy',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum PortfolioRoute {
|
export enum PortfolioRoute {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { ExternalProvider } from '@ethersproject/providers';
|
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 type { suggestChain } from 'graz';
|
||||||
|
|
||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
@@ -24,13 +24,14 @@ import {
|
|||||||
|
|
||||||
import { isMetaMask } from '@/lib/wallet/providers';
|
import { isMetaMask } from '@/lib/wallet/providers';
|
||||||
|
|
||||||
|
import { DydxNetwork, ENVIRONMENT_CONFIG_MAP } from './networks';
|
||||||
|
|
||||||
// Wallet connection types
|
// Wallet connection types
|
||||||
|
|
||||||
export enum WalletConnectionType {
|
export enum WalletConnectionType {
|
||||||
CoinbaseWalletSdk = 'coinbaseWalletSdk',
|
CoinbaseWalletSdk = 'coinbaseWalletSdk',
|
||||||
CosmosSigner = 'CosmosSigner',
|
CosmosSigner = 'CosmosSigner',
|
||||||
InjectedEip1193 = 'injectedEip1193',
|
InjectedEip1193 = 'injectedEip1193',
|
||||||
WalletConnect1 = 'walletConnect1',
|
|
||||||
WalletConnect2 = 'walletConnect2',
|
WalletConnect2 = 'walletConnect2',
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,10 +61,6 @@ export const walletConnectionTypes: Record<WalletConnectionType, WalletConnectio
|
|||||||
name: 'injected EIP-1193 provider',
|
name: 'injected EIP-1193 provider',
|
||||||
wagmiConnectorId: 'injected',
|
wagmiConnectorId: 'injected',
|
||||||
},
|
},
|
||||||
[WalletConnectionType.WalletConnect1]: {
|
|
||||||
name: 'WalletConnect 1.0',
|
|
||||||
wagmiConnectorId: 'walletConnectLegacy',
|
|
||||||
},
|
|
||||||
[WalletConnectionType.WalletConnect2]: {
|
[WalletConnectionType.WalletConnect2]: {
|
||||||
name: 'WalletConnect 2.0',
|
name: 'WalletConnect 2.0',
|
||||||
wagmiConnectorId: 'walletConnect',
|
wagmiConnectorId: 'walletConnect',
|
||||||
@@ -90,19 +87,35 @@ export enum WalletType {
|
|||||||
Rainbow = 'RAINBOW_WALLET',
|
Rainbow = 'RAINBOW_WALLET',
|
||||||
TokenPocket = 'TOKEN_POCKET',
|
TokenPocket = 'TOKEN_POCKET',
|
||||||
TrustWallet = 'TRUST_WALLET',
|
TrustWallet = 'TRUST_WALLET',
|
||||||
WalletConnect = 'WALLETCONNECT',
|
|
||||||
WalletConnect2 = 'WALLETCONNECT_2',
|
WalletConnect2 = 'WALLETCONNECT_2',
|
||||||
// TestWallet = 'TEST_WALLET',
|
// TestWallet = 'TEST_WALLET',
|
||||||
OtherWallet = 'OTHER_WALLET',
|
OtherWallet = 'OTHER_WALLET',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS = {
|
||||||
|
Metamask: 'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96',
|
||||||
|
imToken: 'ef333840daf915aafdc4a004525502d6d49d77bd9c65e0642dbaefb3c2893bef',
|
||||||
|
TokenPocket: '20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66',
|
||||||
|
Trust: '4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0',
|
||||||
|
Rainbow: '1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369',
|
||||||
|
Zerion: 'ecc4036f814562b41a5268adc86270fba1365471402006302e70169465b7ac18',
|
||||||
|
Ledger: '19177a98252e07ddfc9af2083ba8e07ef627cb6103467ffebb3f8f4205fd7927',
|
||||||
|
Fireblocks: '5864e2ced7c293ed18ac35e0db085c09ed567d67346ccb6f58a0327a75137489',
|
||||||
|
Uniswap: 'c03dfee351b6fcc421b4494ea33b9d4b92a984f87aa76d1663bb28705e95034a',
|
||||||
|
Robinhood: '8837dd9413b1d9b585ee937d27a816590248386d9dbf59f5cd3422dbbb65683e',
|
||||||
|
'1inch': 'c286eebc742a537cd1d6818363e9dc53b21759a1e8e5d9b263d0c03ec7703576',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS = Object.values(
|
||||||
|
WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS
|
||||||
|
);
|
||||||
|
|
||||||
type WalletConfig = {
|
type WalletConfig = {
|
||||||
type: WalletType;
|
type: WalletType;
|
||||||
stringKey: string;
|
stringKey: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
connectionTypes: WalletConnectionType[];
|
connectionTypes: WalletConnectionType[];
|
||||||
matchesInjectedEip1193?: (provider: ExternalProvider & any) => boolean;
|
matchesInjectedEip1193?: (provider: ExternalProvider & any) => boolean;
|
||||||
walletconnect1Name?: string;
|
|
||||||
walletconnect2Id?: string;
|
walletconnect2Id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,7 +128,6 @@ export const wallets: Record<WalletType, WalletConfig> = {
|
|||||||
WalletConnectionType.InjectedEip1193,
|
WalletConnectionType.InjectedEip1193,
|
||||||
// WalletConnectionType.CoinbaseWalletSdk,
|
// WalletConnectionType.CoinbaseWalletSdk,
|
||||||
WalletConnectionType.WalletConnect2,
|
WalletConnectionType.WalletConnect2,
|
||||||
WalletConnectionType.WalletConnect1,
|
|
||||||
],
|
],
|
||||||
matchesInjectedEip1193: (provider) =>
|
matchesInjectedEip1193: (provider) =>
|
||||||
Object.entries(wallets).every(
|
Object.entries(wallets).every(
|
||||||
@@ -129,30 +141,22 @@ export const wallets: Record<WalletType, WalletConfig> = {
|
|||||||
type: WalletType.BitKeep,
|
type: WalletType.BitKeep,
|
||||||
stringKey: STRING_KEYS.BITKEEP,
|
stringKey: STRING_KEYS.BITKEEP,
|
||||||
icon: BitkeepIcon,
|
icon: BitkeepIcon,
|
||||||
connectionTypes: [
|
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
|
||||||
WalletConnectionType.InjectedEip1193,
|
|
||||||
WalletConnectionType.WalletConnect2,
|
|
||||||
WalletConnectionType.WalletConnect1,
|
|
||||||
],
|
|
||||||
matchesInjectedEip1193: (provider) => provider.isBitKeep, // isBitKeepChrome, isBitEthereum
|
matchesInjectedEip1193: (provider) => provider.isBitKeep, // isBitKeepChrome, isBitEthereum
|
||||||
walletconnect1Name: 'bitkeep',
|
|
||||||
walletconnect2Id: '38f5d18bd8522c244bdd70cb4a68e0e718865155811c043f052fb9f1c51de662',
|
|
||||||
},
|
},
|
||||||
[WalletType.BitPie]: {
|
[WalletType.BitPie]: {
|
||||||
type: WalletType.BitPie,
|
type: WalletType.BitPie,
|
||||||
stringKey: STRING_KEYS.BITPIE,
|
stringKey: STRING_KEYS.BITPIE,
|
||||||
icon: BitpieIcon,
|
icon: BitpieIcon,
|
||||||
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect1],
|
connectionTypes: [WalletConnectionType.InjectedEip1193],
|
||||||
matchesInjectedEip1193: (provider) => provider.isBitpie,
|
matchesInjectedEip1193: (provider) => provider.isBitpie,
|
||||||
walletconnect1Name: 'bitpie',
|
|
||||||
},
|
},
|
||||||
[WalletType.CloverWallet]: {
|
[WalletType.CloverWallet]: {
|
||||||
type: WalletType.CloverWallet,
|
type: WalletType.CloverWallet,
|
||||||
stringKey: STRING_KEYS.CLOVER_WALLET,
|
stringKey: STRING_KEYS.CLOVER_WALLET,
|
||||||
icon: CloverWalletIcon,
|
icon: CloverWalletIcon,
|
||||||
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect1],
|
connectionTypes: [WalletConnectionType.InjectedEip1193],
|
||||||
matchesInjectedEip1193: (provider) => provider.isClover,
|
matchesInjectedEip1193: (provider) => provider.isClover,
|
||||||
// walletconnect1Name: 'clover',
|
|
||||||
},
|
},
|
||||||
[WalletType.CoinbaseWallet]: {
|
[WalletType.CoinbaseWallet]: {
|
||||||
type: WalletType.CoinbaseWallet,
|
type: WalletType.CoinbaseWallet,
|
||||||
@@ -161,122 +165,78 @@ export const wallets: Record<WalletType, WalletConfig> = {
|
|||||||
connectionTypes: [
|
connectionTypes: [
|
||||||
WalletConnectionType.CoinbaseWalletSdk,
|
WalletConnectionType.CoinbaseWalletSdk,
|
||||||
WalletConnectionType.InjectedEip1193,
|
WalletConnectionType.InjectedEip1193,
|
||||||
WalletConnectionType.WalletConnect1,
|
WalletConnectionType.WalletConnect2,
|
||||||
],
|
],
|
||||||
matchesInjectedEip1193: (provider) => provider.isCoinbaseWallet, // provider.selectedProvider?.isCoinbaseWallet,
|
matchesInjectedEip1193: (provider) => provider.isCoinbaseWallet, // provider.selectedProvider?.isCoinbaseWallet,
|
||||||
walletconnect1Name: 'coinbase',
|
|
||||||
},
|
},
|
||||||
[WalletType.Coin98]: {
|
[WalletType.Coin98]: {
|
||||||
type: WalletType.Coin98,
|
type: WalletType.Coin98,
|
||||||
stringKey: STRING_KEYS.COIN98,
|
stringKey: STRING_KEYS.COIN98,
|
||||||
icon: Coin98Icon,
|
icon: Coin98Icon,
|
||||||
connectionTypes: [
|
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
|
||||||
WalletConnectionType.InjectedEip1193,
|
|
||||||
WalletConnectionType.WalletConnect2,
|
|
||||||
WalletConnectionType.WalletConnect1,
|
|
||||||
],
|
|
||||||
matchesInjectedEip1193: (provider) => provider.isCoin98,
|
matchesInjectedEip1193: (provider) => provider.isCoin98,
|
||||||
walletconnect1Name: 'coin98',
|
|
||||||
walletconnect2Id: '2a3c89040ac3b723a1972a33a125b1db11e258a6975d3a61252cd64e6ea5ea01',
|
|
||||||
},
|
},
|
||||||
[WalletType.HuobiWallet]: {
|
[WalletType.HuobiWallet]: {
|
||||||
type: WalletType.HuobiWallet,
|
type: WalletType.HuobiWallet,
|
||||||
stringKey: STRING_KEYS.HUOBI_WALLET,
|
stringKey: STRING_KEYS.HUOBI_WALLET,
|
||||||
icon: HuobiIcon,
|
icon: HuobiIcon,
|
||||||
connectionTypes: [
|
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
|
||||||
WalletConnectionType.InjectedEip1193,
|
|
||||||
WalletConnectionType.WalletConnect2,
|
|
||||||
WalletConnectionType.WalletConnect1,
|
|
||||||
],
|
|
||||||
matchesInjectedEip1193: (provider) => provider.isHbWallet,
|
matchesInjectedEip1193: (provider) => provider.isHbWallet,
|
||||||
walletconnect2Id: '797c615e2c556b610c048eb35535f212c0dd58de5d03e763120e90a7d1350a77',
|
|
||||||
},
|
},
|
||||||
[WalletType.ImToken]: {
|
[WalletType.ImToken]: {
|
||||||
type: WalletType.ImToken,
|
type: WalletType.ImToken,
|
||||||
stringKey: STRING_KEYS.IMTOKEN,
|
stringKey: STRING_KEYS.IMTOKEN,
|
||||||
icon: ImTokenIcon,
|
icon: ImTokenIcon,
|
||||||
connectionTypes: [
|
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
|
||||||
WalletConnectionType.InjectedEip1193,
|
|
||||||
WalletConnectionType.WalletConnect2,
|
|
||||||
WalletConnectionType.WalletConnect1,
|
|
||||||
],
|
|
||||||
matchesInjectedEip1193: (provider) => provider.isImToken,
|
matchesInjectedEip1193: (provider) => provider.isImToken,
|
||||||
walletconnect1Name: 'imtoken',
|
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.imToken,
|
||||||
walletconnect2Id: 'ef333840daf915aafdc4a004525502d6d49d77bd9c65e0642dbaefb3c2893bef',
|
|
||||||
},
|
},
|
||||||
[WalletType.MathWallet]: {
|
[WalletType.MathWallet]: {
|
||||||
type: WalletType.MathWallet,
|
type: WalletType.MathWallet,
|
||||||
stringKey: STRING_KEYS.MATH_WALLET,
|
stringKey: STRING_KEYS.MATH_WALLET,
|
||||||
icon: MathWalletIcon,
|
icon: MathWalletIcon,
|
||||||
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect1],
|
connectionTypes: [WalletConnectionType.InjectedEip1193],
|
||||||
matchesInjectedEip1193: (provider) => provider.isMathWallet,
|
matchesInjectedEip1193: (provider) => provider.isMathWallet,
|
||||||
walletconnect1Name: 'math',
|
|
||||||
walletconnect2Id: '7674bb4e353bf52886768a3ddc2a4562ce2f4191c80831291218ebd90f5f5e26',
|
walletconnect2Id: '7674bb4e353bf52886768a3ddc2a4562ce2f4191c80831291218ebd90f5f5e26',
|
||||||
},
|
},
|
||||||
[WalletType.MetaMask]: {
|
[WalletType.MetaMask]: {
|
||||||
type: WalletType.MetaMask,
|
type: WalletType.MetaMask,
|
||||||
stringKey: STRING_KEYS.METAMASK,
|
stringKey: STRING_KEYS.METAMASK,
|
||||||
icon: MetaMaskIcon,
|
icon: MetaMaskIcon,
|
||||||
connectionTypes: [
|
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
|
||||||
WalletConnectionType.InjectedEip1193,
|
|
||||||
WalletConnectionType.WalletConnect2,
|
|
||||||
WalletConnectionType.WalletConnect1,
|
|
||||||
],
|
|
||||||
matchesInjectedEip1193: isMetaMask,
|
matchesInjectedEip1193: isMetaMask,
|
||||||
walletconnect1Name: 'metamask',
|
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.Metamask,
|
||||||
walletconnect2Id: 'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96',
|
|
||||||
},
|
},
|
||||||
[WalletType.Rainbow]: {
|
[WalletType.Rainbow]: {
|
||||||
type: WalletType.Rainbow,
|
type: WalletType.Rainbow,
|
||||||
stringKey: STRING_KEYS.RAINBOW_WALLET,
|
stringKey: STRING_KEYS.RAINBOW_WALLET,
|
||||||
icon: RainbowIcon,
|
icon: RainbowIcon,
|
||||||
connectionTypes: [
|
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
|
||||||
WalletConnectionType.InjectedEip1193,
|
|
||||||
WalletConnectionType.WalletConnect2,
|
|
||||||
WalletConnectionType.WalletConnect1,
|
|
||||||
],
|
|
||||||
matchesInjectedEip1193: (provider) => provider.isRainbowWallet,
|
matchesInjectedEip1193: (provider) => provider.isRainbowWallet,
|
||||||
walletconnect1Name: 'rainbow',
|
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.Rainbow,
|
||||||
walletconnect2Id: '1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369',
|
|
||||||
},
|
},
|
||||||
[WalletType.TokenPocket]: {
|
[WalletType.TokenPocket]: {
|
||||||
type: WalletType.TokenPocket,
|
type: WalletType.TokenPocket,
|
||||||
stringKey: STRING_KEYS.TOKEN_POCKET,
|
stringKey: STRING_KEYS.TOKEN_POCKET,
|
||||||
icon: TokenPocketIcon,
|
icon: TokenPocketIcon,
|
||||||
connectionTypes: [
|
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
|
||||||
WalletConnectionType.InjectedEip1193,
|
|
||||||
WalletConnectionType.WalletConnect2,
|
|
||||||
WalletConnectionType.WalletConnect1,
|
|
||||||
],
|
|
||||||
matchesInjectedEip1193: (provider) => provider.isTokenPocket,
|
matchesInjectedEip1193: (provider) => provider.isTokenPocket,
|
||||||
walletconnect1Name: 'tokenpocket',
|
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.TokenPocket,
|
||||||
walletconnect2Id: '20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66',
|
|
||||||
},
|
},
|
||||||
[WalletType.TrustWallet]: {
|
[WalletType.TrustWallet]: {
|
||||||
type: WalletType.TrustWallet,
|
type: WalletType.TrustWallet,
|
||||||
stringKey: STRING_KEYS.TRUST_WALLET,
|
stringKey: STRING_KEYS.TRUST_WALLET,
|
||||||
icon: TrustWalletIcon,
|
icon: TrustWalletIcon,
|
||||||
connectionTypes: [
|
connectionTypes: [WalletConnectionType.InjectedEip1193, WalletConnectionType.WalletConnect2],
|
||||||
WalletConnectionType.InjectedEip1193,
|
|
||||||
WalletConnectionType.WalletConnect2,
|
|
||||||
WalletConnectionType.WalletConnect1,
|
|
||||||
],
|
|
||||||
matchesInjectedEip1193: (provider) => provider.isTrust,
|
matchesInjectedEip1193: (provider) => provider.isTrust,
|
||||||
walletconnect1Name: 'trust',
|
walletconnect2Id: WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS.Trust,
|
||||||
walletconnect2Id: '4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0',
|
|
||||||
},
|
},
|
||||||
[WalletType.WalletConnect2]: {
|
[WalletType.WalletConnect2]: {
|
||||||
type: WalletType.WalletConnect,
|
type: WalletType.WalletConnect2,
|
||||||
stringKey: STRING_KEYS.WALLET_CONNECT_2,
|
stringKey: STRING_KEYS.WALLET_CONNECT_2,
|
||||||
icon: WalletConnectIcon,
|
icon: WalletConnectIcon,
|
||||||
connectionTypes: [WalletConnectionType.WalletConnect2],
|
connectionTypes: [WalletConnectionType.WalletConnect2],
|
||||||
},
|
},
|
||||||
[WalletType.WalletConnect]: {
|
|
||||||
type: WalletType.WalletConnect,
|
|
||||||
stringKey: STRING_KEYS.WALLET_CONNECT,
|
|
||||||
icon: WalletConnectIcon,
|
|
||||||
connectionTypes: [WalletConnectionType.WalletConnect1],
|
|
||||||
},
|
|
||||||
[WalletType.Keplr]: {
|
[WalletType.Keplr]: {
|
||||||
type: WalletType.Keplr,
|
type: WalletType.Keplr,
|
||||||
stringKey: STRING_KEYS.KEPLR,
|
stringKey: STRING_KEYS.KEPLR,
|
||||||
@@ -318,20 +278,21 @@ export type WalletConnection = {
|
|||||||
export const COSMOS_DERIVATION_PATH = "m/44'/118'/0'/0/0";
|
export const COSMOS_DERIVATION_PATH = "m/44'/118'/0'/0/0";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description typed data to sign for v4 onboarding
|
* @description typed data to sign for dYdX Chain onboarding
|
||||||
*/
|
*/
|
||||||
export const SIGN_TYPED_DATA = {
|
export const getSignTypedData = (selectedNetwork: DydxNetwork) =>
|
||||||
primaryType: 'dYdX',
|
({
|
||||||
domain: {
|
primaryType: 'dYdX',
|
||||||
name: 'dYdX V4',
|
domain: {
|
||||||
},
|
name: ENVIRONMENT_CONFIG_MAP[selectedNetwork].wallets.signTypedDataDomainName,
|
||||||
types: {
|
},
|
||||||
dYdX: [{ name: 'action', type: 'string' }],
|
types: {
|
||||||
},
|
dYdX: [{ name: 'action', type: 'string' }],
|
||||||
message: {
|
},
|
||||||
action: 'dYdX V4 Onboarding',
|
message: {
|
||||||
},
|
action: ENVIRONMENT_CONFIG_MAP[selectedNetwork].wallets.signTypedDataAction,
|
||||||
} as const;
|
},
|
||||||
|
} as const);
|
||||||
|
|
||||||
export type PrivateInformation = ReturnType<typeof onboarding.deriveHDKeyFromEthereumSignature>;
|
export type PrivateInformation = ReturnType<typeof onboarding.deriveHDKeyFromEthereumSignature>;
|
||||||
|
|
||||||
@@ -341,10 +302,10 @@ export type DydxAddress = `dydx${string}`;
|
|||||||
export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = {
|
export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = {
|
||||||
rpc: 'https://dydx-testnet-archive.allthatnode.com:26657',
|
rpc: 'https://dydx-testnet-archive.allthatnode.com:26657',
|
||||||
rest: 'https://dydx-testnet-archive.allthatnode.com:1317',
|
rest: 'https://dydx-testnet-archive.allthatnode.com:1317',
|
||||||
chainId: 'dydx-testnet-3',
|
chainId: 'dydx-testnet-4',
|
||||||
chainName: 'dYdX Public Testnet',
|
chainName: 'dYdX Public Testnet',
|
||||||
chainSymbolImageUrl:
|
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: {
|
bech32Config: {
|
||||||
bech32PrefixAccPub: 'dydxpub',
|
bech32PrefixAccPub: 'dydxpub',
|
||||||
bech32PrefixValPub: 'dydxvaloperpub',
|
bech32PrefixValPub: 'dydxvaloperpub',
|
||||||
@@ -358,26 +319,31 @@ export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = {
|
|||||||
},
|
},
|
||||||
stakeCurrency: {
|
stakeCurrency: {
|
||||||
coinDenom: 'DV4TNT',
|
coinDenom: 'DV4TNT',
|
||||||
coinDecimals: 6,
|
coinDecimals: 18,
|
||||||
coinMinimalDenom: 'dv4tnt',
|
coinMinimalDenom: 'adv4tnt',
|
||||||
},
|
},
|
||||||
currencies: [
|
currencies: [
|
||||||
{
|
{
|
||||||
coinDenom: 'DV4TNT',
|
coinDenom: 'DV4TNT',
|
||||||
coinDecimals: 6,
|
coinDecimals: 18,
|
||||||
coinMinimalDenom: 'dv4tnt',
|
coinMinimalDenom: 'adv4tnt',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
coinDenom: 'USDC',
|
coinDenom: 'USDC',
|
||||||
coinMinimalDenom: 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5',
|
|
||||||
coinDecimals: 6,
|
coinDecimals: 6,
|
||||||
|
coinMinimalDenom: 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
feeCurrencies: [
|
feeCurrencies: [
|
||||||
{
|
{
|
||||||
coinDenom: 'DV4TNT',
|
coinDenom: 'DV4TNT',
|
||||||
|
coinDecimals: 18,
|
||||||
|
coinMinimalDenom: 'adv4tnt',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
coinDenom: 'USDC',
|
||||||
coinDecimals: 6,
|
coinDecimals: 6,
|
||||||
coinMinimalDenom: 'dv4tnt',
|
coinMinimalDenom: 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
features: [],
|
features: [],
|
||||||
@@ -386,15 +352,5 @@ export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = {
|
|||||||
// TODO: export this type from abacus instead
|
// TODO: export this type from abacus instead
|
||||||
export enum DydxChainAsset {
|
export enum DydxChainAsset {
|
||||||
USDC = 'usdc',
|
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',
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useApiState } from './useApiState';
|
import { useApiState } from './useApiState';
|
||||||
import { useBreakpoints } from './useBreakpoints';
|
import { useBreakpoints } from './useBreakpoints';
|
||||||
|
import { useTokenConfigs } from './useTokenConfigs';
|
||||||
import { useCommandMenu } from './useCommandMenu';
|
import { useCommandMenu } from './useCommandMenu';
|
||||||
import { useCurrentMarketId } from './useCurrentMarketId';
|
import { useCurrentMarketId } from './useCurrentMarketId';
|
||||||
import { useDebounce } from './useDebounce';
|
import { useDebounce } from './useDebounce';
|
||||||
@@ -16,6 +17,7 @@ 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';
|
||||||
@@ -24,6 +26,7 @@ import { useSubaccount } from './useSubaccount';
|
|||||||
export {
|
export {
|
||||||
useApiState,
|
useApiState,
|
||||||
useBreakpoints,
|
useBreakpoints,
|
||||||
|
useTokenConfigs,
|
||||||
useCommandMenu,
|
useCommandMenu,
|
||||||
useCurrentMarketId,
|
useCurrentMarketId,
|
||||||
useDebounce,
|
useDebounce,
|
||||||
@@ -40,6 +43,7 @@ export {
|
|||||||
useNow,
|
useNow,
|
||||||
useOnClickOutside,
|
useOnClickOutside,
|
||||||
usePageTitlePriceUpdates,
|
usePageTitlePriceUpdates,
|
||||||
|
useRestrictions,
|
||||||
useShouldShowFooter,
|
useShouldShowFooter,
|
||||||
useSelectedNetwork,
|
useSelectedNetwork,
|
||||||
useStringGetter,
|
useStringGetter,
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const useTradingView = ({
|
|||||||
const marketIds = useSelector(getMarketIds, shallowEqual);
|
const marketIds = useSelector(getMarketIds, shallowEqual);
|
||||||
const selectedLocale = useSelector(getSelectedLocale);
|
const selectedLocale = useSelector(getSelectedLocale);
|
||||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||||
const { getCandlesForDatafeed } = useDydxClient();
|
const { getCandlesForDatafeed, isConnected: isClientConnected } = useDydxClient();
|
||||||
|
|
||||||
const [savedTvChartConfig, setTvChartConfig] = useLocalStorage<object | undefined>({
|
const [savedTvChartConfig, setTvChartConfig] = useLocalStorage<object | undefined>({
|
||||||
key: LocalStorageKey.TradingViewChartConfig,
|
key: LocalStorageKey.TradingViewChartConfig,
|
||||||
@@ -44,7 +44,7 @@ export const useTradingView = ({
|
|||||||
const hasMarkets = marketIds.length > 0;
|
const hasMarkets = marketIds.length > 0;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (hasMarkets) {
|
if (hasMarkets && isClientConnected) {
|
||||||
const widgetOptions = getWidgetOptions();
|
const widgetOptions = getWidgetOptions();
|
||||||
const widgetOverrides = getWidgetOverrides(appTheme);
|
const widgetOverrides = getWidgetOverrides(appTheme);
|
||||||
const options = {
|
const options = {
|
||||||
@@ -75,7 +75,7 @@ export const useTradingView = ({
|
|||||||
tvWidgetRef.current = null;
|
tvWidgetRef.current = null;
|
||||||
setIsChartReady(false);
|
setIsChartReady(false);
|
||||||
};
|
};
|
||||||
}, [getCandlesForDatafeed, hasMarkets, selectedLocale, selectedNetwork]);
|
}, [getCandlesForDatafeed, isClientConnected, hasMarkets, selectedLocale, selectedNetwork]);
|
||||||
|
|
||||||
return { savedResolution };
|
return { savedResolution };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,19 +5,18 @@ import { StargateClient } from '@cosmjs/stargate';
|
|||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import { formatUnits } from 'viem';
|
import { formatUnits } from 'viem';
|
||||||
|
|
||||||
import { USDC_DENOM, DYDX_DENOM } from '@dydxprotocol/v4-client-js';
|
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||||
|
|
||||||
import { CLIENT_NETWORK_CONFIGS } from '@/constants/networks';
|
|
||||||
import { QUANTUM_MULTIPLIER } from '@/constants/numbers';
|
import { QUANTUM_MULTIPLIER } from '@/constants/numbers';
|
||||||
import { EvmAddress } from '@/constants/wallets';
|
import { EvmAddress } from '@/constants/wallets';
|
||||||
|
|
||||||
import { convertBech32Address } from '@/lib/addressUtils';
|
import { convertBech32Address } from '@/lib/addressUtils';
|
||||||
import { MustBigNumber } from '@/lib/numbers';
|
import { MustBigNumber } from '@/lib/numbers';
|
||||||
|
|
||||||
import { getBalances } from '@/state/accountSelectors';
|
import { getBalances, getStakingBalances } from '@/state/accountSelectors';
|
||||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||||
|
|
||||||
import { useAccounts } from './useAccounts';
|
import { useAccounts } from './useAccounts';
|
||||||
|
import { useTokenConfigs } from './useTokenConfigs';
|
||||||
|
|
||||||
type UseAccountBalanceProps = {
|
type UseAccountBalanceProps = {
|
||||||
// Token Items
|
// Token Items
|
||||||
@@ -52,16 +51,16 @@ export const useAccountBalance = ({
|
|||||||
|
|
||||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||||
const balances = useSelector(getBalances, shallowEqual);
|
const balances = useSelector(getBalances, shallowEqual);
|
||||||
const evmChainId = Number(CLIENT_NETWORK_CONFIGS[selectedNetwork].ethereumChainId);
|
const { chainTokenDenom, usdcDenom } = useTokenConfigs();
|
||||||
|
const evmChainId = Number(ENVIRONMENT_CONFIG_MAP[selectedNetwork].ethereumChainId);
|
||||||
|
const stakingBalances = useSelector(getStakingBalances, shallowEqual);
|
||||||
|
|
||||||
const evmQuery = useBalance({
|
const evmQuery = useBalance({
|
||||||
enabled: Boolean(!isCosmosChain && addressOrDenom?.startsWith('0x')),
|
enabled: Boolean(!isCosmosChain && addressOrDenom?.startsWith('0x')),
|
||||||
address: evmAddress,
|
address: evmAddress,
|
||||||
chainId: typeof chainId === 'number' ? chainId : Number(evmChainId),
|
chainId: typeof chainId === 'number' ? chainId : Number(evmChainId),
|
||||||
token:
|
token:
|
||||||
addressOrDenom === CHAIN_DEFAULT_TOKEN_ADDRESS
|
addressOrDenom === CHAIN_DEFAULT_TOKEN_ADDRESS ? undefined : (addressOrDenom as EvmAddress),
|
||||||
? undefined
|
|
||||||
: (addressOrDenom as EvmAddress),
|
|
||||||
watch: true,
|
watch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -94,17 +93,19 @@ export const useAccountBalance = ({
|
|||||||
const { formatted: evmBalance } = evmQuery.data || {};
|
const { formatted: evmBalance } = evmQuery.data || {};
|
||||||
const balance = !assetSymbol ? '0' : isCosmosChain ? cosmosQuery.data : evmBalance;
|
const balance = !assetSymbol ? '0' : isCosmosChain ? cosmosQuery.data : evmBalance;
|
||||||
|
|
||||||
const nativeTokenCoinBalance = balances?.[DYDX_DENOM];
|
const nativeTokenCoinBalance = balances?.[chainTokenDenom];
|
||||||
const nativeTokenBalance = MustBigNumber(nativeTokenCoinBalance?.amount)
|
const nativeTokenBalance = MustBigNumber(nativeTokenCoinBalance?.amount);
|
||||||
.div(QUANTUM_MULTIPLIER)
|
|
||||||
.toNumber();
|
const usdcCoinBalance = balances?.[usdcDenom];
|
||||||
|
const usdcBalance = MustBigNumber(usdcCoinBalance?.amount).toNumber();
|
||||||
const usdcCoinBalance = balances?.[USDC_DENOM];
|
|
||||||
const usdcBalance = MustBigNumber(usdcCoinBalance?.amount).div(QUANTUM_MULTIPLIER).toNumber();
|
const nativeStakingCoinBalanace = stakingBalances?.[chainTokenDenom];
|
||||||
|
const nativeStakingBalance = MustBigNumber(nativeStakingCoinBalanace?.amount).toNumber();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
balance,
|
balance,
|
||||||
nativeTokenBalance,
|
nativeTokenBalance,
|
||||||
|
nativeStakingBalance,
|
||||||
usdcBalance,
|
usdcBalance,
|
||||||
queryStatus: isCosmosChain ? cosmosQuery.status : evmQuery.status,
|
queryStatus: isCosmosChain ? cosmosQuery.status : evmQuery.status,
|
||||||
isQueryFetching: isCosmosChain ? cosmosQuery.isFetching : evmQuery.fetchStatus === 'fetching',
|
isQueryFetching: isCosmosChain ? cosmosQuery.isFetching : evmQuery.fetchStatus === 'fetching',
|
||||||
|
|||||||
@@ -2,21 +2,23 @@ import { useCallback, useContext, createContext, useEffect, useState, useMemo }
|
|||||||
|
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { AES, enc } from 'crypto-js';
|
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 { 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 { useLocalStorage } from './useLocalStorage';
|
|
||||||
|
|
||||||
import { useWalletConnection } from './useWalletConnection';
|
|
||||||
import { useDydxClient } from './useDydxClient';
|
import { useDydxClient } from './useDydxClient';
|
||||||
|
import { useLocalStorage } from './useLocalStorage';
|
||||||
|
import { useRestrictions } from './useRestrictions';
|
||||||
|
import { useWalletConnection } from './useWalletConnection';
|
||||||
|
|
||||||
const AccountsContext = createContext<ReturnType<typeof useAccountsContext> | undefined>(undefined);
|
const AccountsContext = createContext<ReturnType<typeof useAccountsContext> | undefined>(undefined);
|
||||||
|
|
||||||
@@ -57,7 +59,9 @@ const useAccountsContext = () => {
|
|||||||
forgetEvmSignature(previousEvmAddress);
|
forgetEvmSignature(previousEvmAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evmAddress) abacusStateManager.setTransfersSourceAddress(evmAddress);
|
if (evmAddress) {
|
||||||
|
abacusStateManager.setTransfersSourceAddress(evmAddress);
|
||||||
|
}
|
||||||
|
|
||||||
setPreviousEvmAddress(evmAddress);
|
setPreviousEvmAddress(evmAddress);
|
||||||
}, [evmAddress]);
|
}, [evmAddress]);
|
||||||
@@ -126,16 +130,8 @@ const useAccountsContext = () => {
|
|||||||
// dYdX subaccounts
|
// dYdX subaccounts
|
||||||
const [dydxSubaccounts, setDydxSubaccounts] = useState<Subaccount[] | undefined>();
|
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 }) => {
|
getSubaccounts: async ({ dydxAddress }: { dydxAddress: DydxAddress }) => {
|
||||||
try {
|
try {
|
||||||
const response = await compositeClient?.indexerClient.account.getSubaccounts(dydxAddress);
|
const response = await compositeClient?.indexerClient.account.getSubaccounts(dydxAddress);
|
||||||
@@ -217,7 +213,6 @@ 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();
|
||||||
@@ -258,6 +253,21 @@ 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);
|
||||||
@@ -308,7 +318,6 @@ const useAccountsContext = () => {
|
|||||||
disconnect,
|
disconnect,
|
||||||
|
|
||||||
// dydxClient Account methods
|
// dydxClient Account methods
|
||||||
getAccountBalance,
|
|
||||||
getSubaccounts,
|
getSubaccounts,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ export const useCurrentMarketId = () => {
|
|||||||
}, [validId]);
|
}, [validId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
abacusStateManager.setMarket(marketId ?? DEFAULT_MARKETID);
|
// Check for marketIds otherwise Abacus will silently fail its isMarketValid check
|
||||||
}, [selectedNetwork, marketId]);
|
if (marketIds) {
|
||||||
|
abacusStateManager.setMarket(marketId ?? DEFAULT_MARKETID);
|
||||||
|
}
|
||||||
|
}, [selectedNetwork, marketIds, marketId]);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,29 +1,24 @@
|
|||||||
import { isDydxV4Network } from '@/constants/networks';
|
|
||||||
import { WalletType } from '@/constants/wallets';
|
import { WalletType } from '@/constants/wallets';
|
||||||
|
|
||||||
import { isTruthy } from '@/lib/isTruthy';
|
import { isTruthy } from '@/lib/isTruthy';
|
||||||
|
|
||||||
import { useSelectedNetwork } from './useSelectedNetwork';
|
|
||||||
|
|
||||||
export const useDisplayedWallets = () => {
|
export const useDisplayedWallets = () => {
|
||||||
const { selectedNetwork } = useSelectedNetwork();
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
WalletType.MetaMask,
|
WalletType.MetaMask,
|
||||||
|
|
||||||
import.meta.env.MODE !== 'production' && isDydxV4Network(selectedNetwork) && WalletType.Keplr,
|
import.meta.env.MODE !== 'production' && WalletType.Keplr,
|
||||||
|
|
||||||
WalletType.WalletConnect2,
|
WalletType.WalletConnect2,
|
||||||
WalletType.WalletConnect,
|
|
||||||
|
|
||||||
WalletType.CoinbaseWallet,
|
WalletType.CoinbaseWallet,
|
||||||
|
|
||||||
WalletType.ImToken,
|
// Hide these wallet options until they can be properly tested on mainnet
|
||||||
WalletType.Rainbow,
|
// WalletType.ImToken,
|
||||||
WalletType.TrustWallet,
|
// WalletType.Rainbow,
|
||||||
WalletType.HuobiWallet,
|
// WalletType.TrustWallet,
|
||||||
WalletType.BitKeep,
|
// WalletType.HuobiWallet,
|
||||||
WalletType.Coin98,
|
// WalletType.BitKeep,
|
||||||
|
// WalletType.Coin98,
|
||||||
|
|
||||||
WalletType.OtherWallet,
|
WalletType.OtherWallet,
|
||||||
].filter(isTruthy);
|
].filter(isTruthy);
|
||||||
|
|||||||
@@ -13,12 +13,17 @@ import {
|
|||||||
|
|
||||||
import type { ResolutionString } from 'public/tradingview/charting_library';
|
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 { type Candle, RESOLUTION_MAP } from '@/constants/candles';
|
||||||
|
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||||
|
import { DydxChainAsset } from '@/constants/wallets';
|
||||||
|
|
||||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
import { 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';
|
||||||
@@ -33,8 +38,9 @@ const useDydxClientContext = () => {
|
|||||||
// ------ Network ------ //
|
// ------ Network ------ //
|
||||||
|
|
||||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||||
|
const tokensConfigs = ENVIRONMENT_CONFIG_MAP[selectedNetwork].tokens;
|
||||||
|
|
||||||
const [networkConfig, setNetworkConfig] = useState<Partial<NetworkConfig>>();
|
const [networkConfig, setNetworkConfig] = useState<NetworkConfig>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onConnectNetwork = (event: ConnectNetworkEvent) => setNetworkConfig(event.detail);
|
const onConnectNetwork = (event: ConnectNetworkEvent) => setNetworkConfig(event.detail);
|
||||||
@@ -54,15 +60,22 @@ const useDydxClientContext = () => {
|
|||||||
if (
|
if (
|
||||||
networkConfig?.chainId &&
|
networkConfig?.chainId &&
|
||||||
networkConfig?.indexerUrl &&
|
networkConfig?.indexerUrl &&
|
||||||
networkConfig?.indexerSocketUrl &&
|
networkConfig?.websocketUrl &&
|
||||||
networkConfig?.validatorUrl
|
networkConfig?.validatorUrl
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const initializedClient = await CompositeClient.connect(
|
const initializedClient = await CompositeClient.connect(
|
||||||
new Network(
|
new Network(
|
||||||
selectedNetwork,
|
selectedNetwork,
|
||||||
new IndexerConfig(networkConfig.indexerUrl, networkConfig.indexerSocketUrl),
|
new IndexerConfig(networkConfig.indexerUrl, networkConfig.websocketUrl),
|
||||||
new ValidatorConfig(networkConfig.validatorUrl, networkConfig.chainId, {
|
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,
|
broadcastPollIntervalMs: 3_000,
|
||||||
broadcastTimeoutMs: 60_000,
|
broadcastTimeoutMs: 60_000,
|
||||||
})
|
})
|
||||||
@@ -178,7 +191,27 @@ const useDydxClientContext = () => {
|
|||||||
[requestCandles]
|
[requestCandles]
|
||||||
);
|
);
|
||||||
|
|
||||||
// ------ Subacount Methods ------ //
|
const { updateSanctionedAddresses } = useRestrictions();
|
||||||
|
|
||||||
|
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
|
||||||
@@ -186,11 +219,13 @@ const useDydxClientContext = () => {
|
|||||||
networkConfig,
|
networkConfig,
|
||||||
compositeClient,
|
compositeClient,
|
||||||
faucetClient,
|
faucetClient,
|
||||||
|
isConnected: !!compositeClient,
|
||||||
|
|
||||||
// Wallet Methods
|
// Wallet Methods
|
||||||
getWalletFromEvmSignature,
|
getWalletFromEvmSignature,
|
||||||
|
|
||||||
// Public Methods
|
// Public Methods
|
||||||
getCandlesForDatafeed,
|
getCandlesForDatafeed,
|
||||||
|
screenAddresses,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ import { useDispatch } from 'react-redux';
|
|||||||
|
|
||||||
import { LocalStorageKey } from '@/constants/localStorage';
|
import { LocalStorageKey } from '@/constants/localStorage';
|
||||||
|
|
||||||
import { DEFAULT_APP_ENVIRONMENT, DydxNetwork, isValidDydxNetwork } from '@/constants/networks';
|
import { DEFAULT_APP_ENVIRONMENT, type DydxNetwork } from '@/constants/networks';
|
||||||
|
|
||||||
import { useLocalStorage } from '@/hooks';
|
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();
|
||||||
@@ -18,7 +19,7 @@ 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: isValidDydxNetwork, // backwards compatibility
|
validateFn: validateAgainstAvailableEnvironments,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { LocalStorageKey } from '@/constants/localStorage';
|
|||||||
import { type TransferNotifcation } from '@/constants/notifications';
|
import { type TransferNotifcation } from '@/constants/notifications';
|
||||||
|
|
||||||
import { useAccounts } from '@/hooks/useAccounts';
|
import { useAccounts } from '@/hooks/useAccounts';
|
||||||
import { SQUID_ERROR_TYPES, useSquid } from '@/hooks/useSquid';
|
import { STATUS_ERROR_GRACE_PERIOD, useSquid } from '@/hooks/useSquid';
|
||||||
import { useLocalStorage } from './useLocalStorage';
|
import { useLocalStorage } from './useLocalStorage';
|
||||||
|
|
||||||
const LocalNotificationsContext = createContext<
|
const LocalNotificationsContext = createContext<
|
||||||
@@ -62,6 +62,7 @@ const useLocalNotificationsContext = () => {
|
|||||||
txHash,
|
txHash,
|
||||||
toChainId,
|
toChainId,
|
||||||
fromChainId,
|
fromChainId,
|
||||||
|
triggeredAt,
|
||||||
status: currentStatus,
|
status: currentStatus,
|
||||||
} of transferNotifications) {
|
} of transferNotifications) {
|
||||||
try {
|
try {
|
||||||
@@ -70,8 +71,8 @@ const useLocalNotificationsContext = () => {
|
|||||||
const status = await squid?.getStatus({ transactionId: txHash, toChainId, fromChainId });
|
const status = await squid?.getStatus({ transactionId: txHash, toChainId, fromChainId });
|
||||||
if (status) statuses[txHash] = status;
|
if (status) statuses[txHash] = status;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// ignore not found errors since the route might not be available yet
|
// ignore errors for the first 120s since the status might not be available yet
|
||||||
if (error?.errors?.length && error.errors[0].errorType !== SQUID_ERROR_TYPES.NotFoundError) {
|
if (!triggeredAt || Date.now() - triggeredAt > STATUS_ERROR_GRACE_PERIOD) {
|
||||||
statuses[txHash] = error;
|
statuses[txHash] = error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,15 +28,13 @@ export const useMarketsData = (
|
|||||||
const allAssets = useSelector(getAssets, shallowEqual) || {};
|
const allAssets = useSelector(getAssets, shallowEqual) || {};
|
||||||
|
|
||||||
const markets = useMemo(() => {
|
const markets = useMemo(() => {
|
||||||
return Object.values(allPerpetualMarkets)
|
return Object.values(allPerpetualMarkets).map((marketData) => ({
|
||||||
.filter((market) => allAssets[market?.assetId]) // Filter out markets with no asset information
|
asset: allAssets[marketData.assetId],
|
||||||
.map((marketData) => ({
|
tickSizeDecimals: marketData.configs?.tickSizeDecimals,
|
||||||
asset: allAssets[marketData.assetId],
|
...marketData,
|
||||||
tickSizeDecimals: marketData.configs?.tickSizeDecimals,
|
...marketData.perpetual,
|
||||||
...marketData,
|
...marketData.configs,
|
||||||
...marketData.perpetual,
|
})) as MarketData[];
|
||||||
...marketData.configs,
|
|
||||||
})) as MarketData[];
|
|
||||||
}, [allPerpetualMarkets, allAssets]);
|
}, [allPerpetualMarkets, allAssets]);
|
||||||
|
|
||||||
const filteredMarkets = useMemo(() => {
|
const filteredMarkets = useMemo(() => {
|
||||||
@@ -45,8 +43,8 @@ export const useMarketsData = (
|
|||||||
if (searchFilter) {
|
if (searchFilter) {
|
||||||
return filtered.filter(
|
return filtered.filter(
|
||||||
({ asset }) =>
|
({ asset }) =>
|
||||||
asset.name?.toLocaleLowerCase().includes(searchFilter.toLowerCase()) ||
|
asset?.name?.toLocaleLowerCase().includes(searchFilter.toLowerCase()) ||
|
||||||
asset.symbol?.toLocaleLowerCase().includes(searchFilter.toLowerCase())
|
asset?.id?.toLocaleLowerCase().includes(searchFilter.toLowerCase())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return filtered;
|
return filtered;
|
||||||
|
|||||||
@@ -4,15 +4,14 @@ import { useSelector, shallowEqual, useDispatch } from 'react-redux';
|
|||||||
import { groupBy } from 'lodash';
|
import { groupBy } from 'lodash';
|
||||||
|
|
||||||
import { AlertType } from '@/constants/alerts';
|
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 { 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 { 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 { useLocalNotifications } from '@/hooks/useLocalNotifications';
|
||||||
|
|
||||||
import { AlertMessage } from '@/components/AlertMessage';
|
|
||||||
import { Icon, IconName } from '@/components/Icon';
|
import { Icon, IconName } from '@/components/Icon';
|
||||||
import { Output, OutputType } from '@/components/Output';
|
import { Output, OutputType } from '@/components/Output';
|
||||||
import { TransferStatusToast } from '@/views/TransferStatus';
|
import { TransferStatusToast } from '@/views/TransferStatus';
|
||||||
@@ -69,11 +68,11 @@ export const notificationTypes = [
|
|||||||
<OrderStatusIcon status={order.status} totalFilled={order.totalFilled ?? 0} />
|
<OrderStatusIcon status={order.status} totalFilled={order.totalFilled ?? 0} />
|
||||||
),
|
),
|
||||||
title: `${stringGetter({
|
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
|
order.status === AbacusOrderStatus.open && (order?.totalFilled ?? 0) > 0
|
||||||
? stringGetter({ key: STRING_KEYS.PARTIALLY_FILLED })
|
? stringGetter({ key: STRING_KEYS.PARTIALLY_FILLED })
|
||||||
: stringGetter({ key: ORDER_STATUS_STRINGS[order.status.name] })
|
: stringGetter({ key: order.resources.statusStringKey as StringKey })
|
||||||
}`,
|
}`,
|
||||||
description: `${stringGetter({
|
description: `${stringGetter({
|
||||||
key: ORDER_SIDE_STRINGS[ORDER_SIDES[order.side.name]],
|
key: ORDER_SIDE_STRINGS[ORDER_SIDES[order.side.name]],
|
||||||
@@ -91,18 +90,34 @@ export const notificationTypes = [
|
|||||||
}, [orderIds]);
|
}, [orderIds]);
|
||||||
},
|
},
|
||||||
|
|
||||||
useNotificationAction: () => {
|
// useNotificationAction: () => {
|
||||||
const dispatch = useDispatch();
|
// const dispatch = useDispatch();
|
||||||
|
// const orders = useSelector(getSubaccountOrders, shallowEqual) || [];
|
||||||
|
// const ordersByOrderId = Object.fromEntries(orders.map((order) => [order.id, order]));
|
||||||
|
|
||||||
return (orderId) => {
|
// const fills = useSelector(getSubaccountFills, shallowEqual) || [];
|
||||||
dispatch(
|
// const fillsByOrderId = groupBy(fills, (fill) => fill.orderId);
|
||||||
openDialog({
|
|
||||||
type: DialogTypes.OrderDetails,
|
// return (id) => {
|
||||||
dialogProps: { orderId },
|
// 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]>,
|
} as NotificationTypeConfig<string, [string, number]>,
|
||||||
{
|
{
|
||||||
type: NotificationType.SquidTransfer,
|
type: NotificationType.SquidTransfer,
|
||||||
@@ -110,18 +125,18 @@ export const notificationTypes = [
|
|||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const { transferNotifications } = useLocalNotifications();
|
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_IN_PROGRESS;
|
||||||
if (type === 'deposit' && finished) return STRING_KEYS.DEPOSIT;
|
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;
|
return STRING_KEYS.WITHDRAW;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
for (const transfer of transferNotifications) {
|
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 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
|
// @ts-ignore status.errors is not in the type definition but can be returned
|
||||||
const error = status?.errors?.length ? status?.errors[0] : status?.error;
|
const error = status?.errors?.length ? status?.errors[0] : status?.error;
|
||||||
|
|
||||||
@@ -138,7 +153,8 @@ export const notificationTypes = [
|
|||||||
{stringGetter({
|
{stringGetter({
|
||||||
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
|
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
|
||||||
params: {
|
params: {
|
||||||
ERROR_MESSAGE: error.message || stringGetter({ key: STRING_KEYS.UNKNOWN_ERROR }),
|
ERROR_MESSAGE:
|
||||||
|
error.message || stringGetter({ key: STRING_KEYS.UNKNOWN_ERROR }),
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
</Styled.ErrorMessage>
|
</Styled.ErrorMessage>
|
||||||
@@ -154,6 +170,7 @@ export const notificationTypes = [
|
|||||||
description: description,
|
description: description,
|
||||||
customContent: (
|
customContent: (
|
||||||
<TransferStatusToast
|
<TransferStatusToast
|
||||||
|
type={type}
|
||||||
toAmount={transfer.toAmount}
|
toAmount={transfer.toAmount}
|
||||||
triggeredAt={transfer.triggeredAt}
|
triggeredAt={transfer.triggeredAt}
|
||||||
status={transfer.status}
|
status={transfer.status}
|
||||||
@@ -162,7 +179,7 @@ export const notificationTypes = [
|
|||||||
customMenuContent: !finished && (
|
customMenuContent: !finished && (
|
||||||
<div>
|
<div>
|
||||||
{description}
|
{description}
|
||||||
<TransferStatusSteps status={transfer.status} />
|
<TransferStatusSteps status={transfer.status} type={type} />
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
toastSensitivity: 'foreground',
|
toastSensitivity: 'foreground',
|
||||||
@@ -181,8 +198,8 @@ Styled.TransferText = styled.span`
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5ch;
|
gap: 0.5ch;
|
||||||
`
|
`;
|
||||||
|
|
||||||
Styled.ErrorMessage = styled.div`
|
Styled.ErrorMessage = styled.div`
|
||||||
max-width: 13rem;
|
max-width: 13rem;
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||||
|
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
|
import { RestrictionType } from '@/constants/abacus';
|
||||||
|
import { DialogTypes } from '@/constants/dialogs';
|
||||||
|
|
||||||
|
import { getRestrictionType } from '@/state/accountSelectors';
|
||||||
|
import { forceOpenDialog } from '@/state/dialogs';
|
||||||
|
import { isTruthy } from '@/lib/isTruthy';
|
||||||
|
|
||||||
|
const useRestrictionContext = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const restrictionType = useSelector(getRestrictionType, shallowEqual);
|
||||||
|
const [sanctionedAddresses, setSanctionedAddresses] = useState<string[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (restrictionType === RestrictionType.GEO_RESTRICTED) {
|
||||||
|
dispatch(
|
||||||
|
forceOpenDialog({ type: DialogTypes.RestrictedGeo, dialogProps: { preventClose: true } })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [restrictionType, dispatch]);
|
||||||
|
|
||||||
|
const updateSanctionedAddresses = useCallback(
|
||||||
|
(screenedAddresses: { [address: string]: boolean }) => {
|
||||||
|
const toAdd = Object.entries(screenedAddresses)
|
||||||
|
.filter(([, isSanctioned]) => isSanctioned)
|
||||||
|
.map(([address]) => address);
|
||||||
|
|
||||||
|
if (toAdd.length) {
|
||||||
|
setSanctionedAddresses([...sanctionedAddresses, ...toAdd]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[sanctionedAddresses]
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
isBadActor: restrictionType === RestrictionType.USER_RESTRICTED,
|
||||||
|
isGeoRestricted: restrictionType === RestrictionType.GEO_RESTRICTED,
|
||||||
|
updateSanctionedAddresses,
|
||||||
|
sanctionedAddresses: useMemo(() => new Set(sanctionedAddresses), [sanctionedAddresses]),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type RestrictionContextType = ReturnType<typeof useRestrictionContext>;
|
||||||
|
const RestrictionContext = createContext<RestrictionContextType>({} as RestrictionContextType);
|
||||||
|
RestrictionContext.displayName = 'Restriction';
|
||||||
|
|
||||||
|
export const RestrictionProvider = ({ ...props }) => (
|
||||||
|
<RestrictionContext.Provider value={useRestrictionContext()} {...props} />
|
||||||
|
);
|
||||||
|
|
||||||
|
export const useRestrictions = () => useContext(RestrictionContext);
|
||||||
@@ -2,13 +2,15 @@ import { useCallback } from 'react';
|
|||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
import { LocalStorageKey } from '@/constants/localStorage';
|
import { LocalStorageKey } from '@/constants/localStorage';
|
||||||
import { DEFAULT_APP_ENVIRONMENT, DydxNetwork } from '@/constants/networks';
|
import { DEFAULT_APP_ENVIRONMENT, DydxNetwork, ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||||
|
|
||||||
import { useAccounts, useLocalStorage } from '@/hooks';
|
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 { validateAgainstAvailableEnvironments } from '@/lib/network';
|
||||||
|
|
||||||
export const useSelectedNetwork = (): {
|
export const useSelectedNetwork = (): {
|
||||||
switchNetwork: (network: DydxNetwork) => void;
|
switchNetwork: (network: DydxNetwork) => void;
|
||||||
selectedNetwork: DydxNetwork;
|
selectedNetwork: DydxNetwork;
|
||||||
@@ -20,6 +22,7 @@ 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,
|
||||||
});
|
});
|
||||||
|
|
||||||
const switchNetwork = useCallback(
|
const switchNetwork = useCallback(
|
||||||
|
|||||||
@@ -2,15 +2,13 @@ import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
|||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { Squid } from '@0xsquid/sdk';
|
import { Squid } from '@0xsquid/sdk';
|
||||||
|
|
||||||
import { CLIENT_NETWORK_CONFIGS, isDydxV4Network } from '@/constants/networks';
|
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||||
|
|
||||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||||
|
|
||||||
export const NATIVE_TOKEN_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
export const NATIVE_TOKEN_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
|
||||||
|
|
||||||
export enum SQUID_ERROR_TYPES {
|
export const STATUS_ERROR_GRACE_PERIOD = 120_000;
|
||||||
NotFoundError = 'NotFoundError',
|
|
||||||
}
|
|
||||||
|
|
||||||
const useSquidContext = () => {
|
const useSquidContext = () => {
|
||||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||||
@@ -24,10 +22,7 @@ const useSquidContext = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const squid = useMemo(
|
const squid = useMemo(
|
||||||
() =>
|
() => new Squid({ baseUrl: ENVIRONMENT_CONFIG_MAP[selectedNetwork]?.endpoints['0xsquid'] }),
|
||||||
isDydxV4Network(selectedNetwork)
|
|
||||||
? new Squid({ baseUrl: CLIENT_NETWORK_CONFIGS[selectedNetwork]?.endpoints['0xsquid'] })
|
|
||||||
: undefined,
|
|
||||||
[selectedNetwork]
|
[selectedNetwork]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -41,7 +36,7 @@ const useSquidContext = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type SquidContextType = ReturnType<typeof useSquidContext>;
|
type SquidContextType = ReturnType<typeof useSquidContext>;
|
||||||
const SquidContext = createContext<SquidContextType>(undefined);
|
const SquidContext = createContext<SquidContextType | undefined>(undefined);
|
||||||
SquidContext.displayName = '0xSquid';
|
SquidContext.displayName = '0xSquid';
|
||||||
|
|
||||||
export const SquidProvider = ({ ...props }) => (
|
export const SquidProvider = ({ ...props }) => (
|
||||||
|
|||||||
@@ -3,15 +3,10 @@ import { shallowEqual, useSelector, useDispatch } from 'react-redux';
|
|||||||
import type { Nullable } from '@dydxprotocol/v4-abacus';
|
import type { Nullable } from '@dydxprotocol/v4-abacus';
|
||||||
import Long from 'long';
|
import Long from 'long';
|
||||||
import type { IndexedTx } from '@cosmjs/stargate';
|
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 { Method } from '@cosmjs/tendermint-rpc';
|
||||||
|
|
||||||
import {
|
import { type LocalWallet, SubaccountClient } from '@dydxprotocol/v4-client-js';
|
||||||
type LocalWallet,
|
|
||||||
SubaccountClient,
|
|
||||||
DYDX_DENOM,
|
|
||||||
USDC_DENOM,
|
|
||||||
} from '@dydxprotocol/v4-client-js';
|
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
AccountBalance,
|
AccountBalance,
|
||||||
@@ -34,9 +29,9 @@ import { MustBigNumber } from '@/lib/numbers';
|
|||||||
import { log } from '@/lib/telemetry';
|
import { log } from '@/lib/telemetry';
|
||||||
|
|
||||||
import { useAccounts } from './useAccounts';
|
import { useAccounts } from './useAccounts';
|
||||||
|
import { useTokenConfigs } from './useTokenConfigs';
|
||||||
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';
|
||||||
@@ -53,6 +48,7 @@ export const useSubaccount = () => useContext(SubaccountContext);
|
|||||||
|
|
||||||
export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: LocalWallet }) => {
|
export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: LocalWallet }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const { usdcDenom } = useTokenConfigs();
|
||||||
const { compositeClient, faucetClient } = useDydxClient();
|
const { compositeClient, faucetClient } = useDydxClient();
|
||||||
|
|
||||||
const { getFaucetFunds } = useMemo(
|
const { getFaucetFunds } = useMemo(
|
||||||
@@ -78,13 +74,12 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
() => ({
|
() => ({
|
||||||
depositToSubaccount: async ({
|
depositToSubaccount: async ({
|
||||||
subaccountClient,
|
subaccountClient,
|
||||||
assetId = 0,
|
|
||||||
amount,
|
amount,
|
||||||
}: {
|
}: {
|
||||||
subaccountClient: SubaccountClient;
|
subaccountClient: SubaccountClient;
|
||||||
assetId?: number;
|
assetId?: number;
|
||||||
amount: Long;
|
amount: number;
|
||||||
}) => await compositeClient?.validatorClient.post.deposit(subaccountClient, assetId, amount),
|
}) => await compositeClient?.depositToSubaccount(subaccountClient, amount.toString()),
|
||||||
|
|
||||||
withdrawFromSubaccount: async ({
|
withdrawFromSubaccount: async ({
|
||||||
subaccountClient,
|
subaccountClient,
|
||||||
@@ -92,7 +87,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
}: {
|
}: {
|
||||||
subaccountClient: SubaccountClient;
|
subaccountClient: SubaccountClient;
|
||||||
amount: number;
|
amount: number;
|
||||||
}) => await compositeClient?.withdrawFromSubaccount(subaccountClient, amount),
|
}) => await compositeClient?.withdrawFromSubaccount(subaccountClient, amount.toString()),
|
||||||
|
|
||||||
transferFromSubaccountToAddress: async ({
|
transferFromSubaccountToAddress: async ({
|
||||||
subaccountClient,
|
subaccountClient,
|
||||||
@@ -135,12 +130,21 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
amount: number;
|
amount: number;
|
||||||
recipient: string;
|
recipient: string;
|
||||||
}) =>
|
}) =>
|
||||||
await compositeClient?.validatorClient.post.sendToken(
|
await compositeClient?.validatorClient.post.send(
|
||||||
subaccountClient,
|
subaccountClient.wallet,
|
||||||
recipient,
|
() =>
|
||||||
DYDX_DENOM,
|
new Promise((resolve) => {
|
||||||
Long.fromNumber(amount * QUANTUM_MULTIPLIER),
|
const msg = compositeClient?.sendTokenMessage(
|
||||||
|
subaccountClient.wallet,
|
||||||
|
amount.toString(),
|
||||||
|
recipient,
|
||||||
|
);
|
||||||
|
|
||||||
|
resolve([msg]);
|
||||||
|
}),
|
||||||
false,
|
false,
|
||||||
|
compositeClient?.validatorClient?.post.defaultDydxGasPrice,
|
||||||
|
undefined,
|
||||||
Method.BroadcastTxCommit
|
Method.BroadcastTxCommit
|
||||||
),
|
),
|
||||||
|
|
||||||
@@ -157,7 +161,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
|
|
||||||
const transaction = JSON.parse(payload);
|
const transaction = JSON.parse(payload);
|
||||||
|
|
||||||
const msg = compositeClient.withdrawFromSubaccountMessage(subaccountClient, amount);
|
const msg = compositeClient.withdrawFromSubaccountMessage(subaccountClient, amount.toString());
|
||||||
const ibcMsg: EncodeObject = {
|
const ibcMsg: EncodeObject = {
|
||||||
typeUrl: transaction.msgTypeUrl,
|
typeUrl: transaction.msgTypeUrl,
|
||||||
value: transaction.msg,
|
value: transaction.msg,
|
||||||
@@ -196,13 +200,9 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
async (balance: AccountBalance) => {
|
async (balance: AccountBalance) => {
|
||||||
if (!localDydxWallet) return;
|
if (!localDydxWallet) return;
|
||||||
|
|
||||||
const amountAfterDust = MustBigNumber(balance.amount)
|
const amount = parseFloat(balance.amount) - AMOUNT_RESERVED_FOR_GAS_USDC;
|
||||||
.minus(AMOUNT_RESERVED_FOR_GAS_USDC) // keep 0.1 USDC in user's wallet for gas
|
|
||||||
.toString();
|
|
||||||
|
|
||||||
const amount = Long.fromString(amountAfterDust || '0');
|
if (amount > 0) {
|
||||||
|
|
||||||
if (amount.greaterThan(Long.ZERO)) {
|
|
||||||
const subaccountClient = new SubaccountClient(localDydxWallet, 0);
|
const subaccountClient = new SubaccountClient(localDydxWallet, 0);
|
||||||
await depositToSubaccount({ amount, subaccountClient });
|
await depositToSubaccount({ amount, subaccountClient });
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
);
|
);
|
||||||
|
|
||||||
const balances = useSelector(getBalances, shallowEqual);
|
const balances = useSelector(getBalances, shallowEqual);
|
||||||
const usdcCoinBalance = balances?.[USDC_DENOM];
|
const usdcCoinBalance = balances?.[usdcDenom];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (usdcCoinBalance) {
|
if (usdcCoinBalance) {
|
||||||
@@ -220,7 +220,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
}, [usdcCoinBalance]);
|
}, [usdcCoinBalance]);
|
||||||
|
|
||||||
const deposit = useCallback(
|
const deposit = useCallback(
|
||||||
async (amount: Long) => {
|
async (amount: number) => {
|
||||||
if (!subaccountClient) {
|
if (!subaccountClient) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -248,8 +248,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
if (!subaccountClient) {
|
if (!subaccountClient) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
return (await (coinDenom === usdcDenom
|
||||||
return (await (coinDenom === USDC_DENOM
|
|
||||||
? transferFromSubaccountToAddress
|
? transferFromSubaccountToAddress
|
||||||
: transferNativeToken)({ subaccountClient, amount, recipient })) as IndexedTx;
|
: transferNativeToken)({ subaccountClient, amount, recipient })) as IndexedTx;
|
||||||
},
|
},
|
||||||
@@ -275,6 +274,7 @@ 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]);
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
import { LocalStorageKey } from '@/constants/localStorage';
|
import { LocalStorageKey } from '@/constants/localStorage';
|
||||||
|
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type DydxAddress,
|
type DydxAddress,
|
||||||
@@ -28,6 +30,8 @@ import {
|
|||||||
WalletType as CosmosWalletType,
|
WalletType as CosmosWalletType,
|
||||||
} from 'graz';
|
} from 'graz';
|
||||||
|
|
||||||
|
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||||
|
|
||||||
import { resolveWagmiConnector } from '@/lib/wagmi';
|
import { resolveWagmiConnector } from '@/lib/wagmi';
|
||||||
import { getWalletConnection, parseWalletError } from '@/lib/wallet';
|
import { getWalletConnection, parseWalletError } from '@/lib/wallet';
|
||||||
import { log } from '@/lib/telemetry';
|
import { log } from '@/lib/telemetry';
|
||||||
@@ -84,6 +88,9 @@ export const useWalletConnection = () => {
|
|||||||
|
|
||||||
// Wallet connection
|
// Wallet connection
|
||||||
|
|
||||||
|
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||||
|
const walletConnectConfig = ENVIRONMENT_CONFIG_MAP[selectedNetwork].wallets.walletconnect;
|
||||||
|
|
||||||
const { connectAsync: connectWagmi } =
|
const { connectAsync: connectWagmi } =
|
||||||
walletType && walletConnectionType
|
walletType && walletConnectionType
|
||||||
? useConnectWagmi({
|
? useConnectWagmi({
|
||||||
@@ -92,6 +99,7 @@ export const useWalletConnection = () => {
|
|||||||
walletConnection: {
|
walletConnection: {
|
||||||
type: walletConnectionType,
|
type: walletConnectionType,
|
||||||
},
|
},
|
||||||
|
walletConnectConfig,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
: useConnectWagmi();
|
: useConnectWagmi();
|
||||||
@@ -127,6 +135,7 @@ export const useWalletConnection = () => {
|
|||||||
connector: resolveWagmiConnector({
|
connector: resolveWagmiConnector({
|
||||||
walletType,
|
walletType,
|
||||||
walletConnection,
|
walletConnection,
|
||||||
|
walletConnectConfig,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -217,7 +226,7 @@ export const useWalletConnection = () => {
|
|||||||
evmAddressWagmi,
|
evmAddressWagmi,
|
||||||
signerWagmi,
|
signerWagmi,
|
||||||
publicClientWagmi,
|
publicClientWagmi,
|
||||||
|
|
||||||
// Wallet connection (Cosmos)
|
// Wallet connection (Cosmos)
|
||||||
dydxAddress,
|
dydxAddress,
|
||||||
dydxAddressGraz,
|
dydxAddressGraz,
|
||||||
|
|||||||
@@ -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 @@
|
|||||||
<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 |
@@ -0,0 +1 @@
|
|||||||
|
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5.625 6.1875h6.75m-6.75 2.25H9M1.6875 9.57c0 1.2.84225 2.2455 2.03025 2.4203.84675.1245 1.7025.2197 2.56725.2842.2625.0195.5025.1575.64875.3758L9 15.75l2.0663-3.0997c.0724-.1078.1685-.1977.2809-.2628.1125-.0651.2382-.1038.3678-.113.8589-.0641 1.7152-.1589 2.5672-.2842 1.188-.1748 2.0303-1.2195 2.0303-2.42105v-4.5135c0-1.2015-.8423-2.24625-2.0303-2.421A36.294434 36.294434 0 0 0 9 2.25c-1.794 0-3.558.13125-5.28225.38475-1.188.17475-2.03025 1.22025-2.03025 2.421V9.57Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||||
|
After Width: | Height: | Size: 672 B |
@@ -1 +1 @@
|
|||||||
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15 8C15 9.53527 14.6867 10.8758 14.2269 11.7954C13.77 12.7092 13.3116 12.9664 13.0527 12.9968L12.6636 12.8953C12.4116 12.7511 12.092 12.4331 11.7731 11.7954C11.3133 10.8758 11 9.53527 11 8C11 6.46473 11.3133 5.12424 11.7731 4.20457C12.0924 3.56607 12.4124 3.24815 12.6645 3.10417L13.0519 3.00311C13.3107 3.0331 13.7696 3.28991 14.2269 4.20457C14.6867 5.12424 15 6.46473 15 8ZM12.2928 2.16768L1.41963 5.00415C0.628571 5.08768 0 6.39699 0 7.99992C0 9.60346 0.629045 10.9131 1.42053 10.9958L2.50023 11.2774V12.9998C2.50023 13.8283 3.17181 14.4998 4.00023 14.4998C4.82866 14.4998 5.50023 13.8283 5.50023 12.9998V12.0601L12.2914 13.8317C12.5186 13.9417 12.7559 14 13 14C14.6569 14 16 11.3137 16 8C16 4.68629 14.6569 2 13 2C12.7564 2 12.5196 2.05808 12.2928 2.16768ZM10.9931 3.5402L2.49607 5.75681C2.80523 6.30634 3 7.10764 3 7.99992C3 8.89214 2.80525 9.69339 2.49614 10.2429L10.9929 12.4595C10.3833 11.3612 10 9.77013 10 8C10 6.22968 10.3834 4.63843 10.9931 3.5402ZM2 7.99992C2 8.70677 1.85462 9.29725 1.66623 9.67403C1.59961 9.80728 1.54246 9.88955 1.5 9.93955C1.45754 9.88955 1.40039 9.80728 1.33377 9.67403C1.14538 9.29725 1 8.70677 1 7.99992C1 7.29308 1.14538 6.70259 1.33377 6.32582C1.40039 6.19256 1.45754 6.11029 1.5 6.06029C1.54246 6.11029 1.59961 6.19256 1.66623 6.32582C1.85462 6.70259 2 7.29308 2 7.99992ZM1.41964 10.0124C1.41962 10.0124 1.42071 10.0118 1.42296 10.0109C1.42079 10.0121 1.41966 10.0125 1.41964 10.0124ZM1.57704 10.0109C1.57929 10.0118 1.58038 10.0124 1.58036 10.0124C1.58033 10.0125 1.57921 10.0121 1.57704 10.0109ZM1.58036 5.9874C1.58038 5.98747 1.57929 5.98808 1.57704 5.98899C1.57921 5.98778 1.58034 5.98732 1.58036 5.9874ZM1.42296 5.98899C1.42071 5.98808 1.41962 5.98747 1.41964 5.9874C1.41966 5.98732 1.42079 5.98778 1.42296 5.98899ZM3.50023 12.9998V11.5383L4.50023 11.7992V12.9998C4.50023 13.276 4.27638 13.4998 4.00023 13.4998C3.72409 13.4998 3.50023 13.276 3.50023 12.9998Z" fill="currentColor"/></svg>
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15 8C15 9.53527 14.6867 10.8758 14.2269 11.7954C13.77 12.7092 13.3116 12.9664 13.0527 12.9968L12.6636 12.8953C12.4116 12.7511 12.092 12.4331 11.7731 11.7954C11.3133 10.8758 11 9.53527 11 8C11 6.46473 11.3133 5.12424 11.7731 4.20457C12.0924 3.56607 12.4124 3.24815 12.6645 3.10417L13.0519 3.00311C13.3107 3.0331 13.7696 3.28991 14.2269 4.20457C14.6867 5.12424 15 6.46473 15 8ZM12.2928 2.16768L1.41963 5.00415C0.628571 5.08768 0 6.39699 0 7.99992C0 9.60346 0.629045 10.9131 1.42053 10.9958L2.50023 11.2774V12.9998C2.50023 13.8283 3.17181 14.4998 4.00023 14.4998C4.82866 14.4998 5.50023 13.8283 5.50023 12.9998V12.0601L12.2914 13.8317C12.5186 13.9417 12.7559 14 13 14C14.6569 14 16 11.3137 16 8C16 4.68629 14.6569 2 13 2C12.7564 2 12.5196 2.05808 12.2928 2.16768ZM10.9931 3.5402L2.49607 5.75681C2.80523 6.30634 3 7.10764 3 7.99992C3 8.89214 2.80525 9.69339 2.49614 10.2429L10.9929 12.4595C10.3833 11.3612 10 9.77013 10 8C10 6.22968 10.3834 4.63843 10.9931 3.5402ZM2 7.99992C2 8.70677 1.85462 9.29725 1.66623 9.67403C1.59961 9.80728 1.54246 9.88955 1.5 9.93955C1.45754 9.88955 1.40039 9.80728 1.33377 9.67403C1.14538 9.29725 1 8.70677 1 7.99992C1 7.29308 1.14538 6.70259 1.33377 6.32582C1.40039 6.19256 1.45754 6.11029 1.5 6.06029C1.54246 6.11029 1.59961 6.19256 1.66623 6.32582C1.85462 6.70259 2 7.29308 2 7.99992ZM1.41964 10.0124C1.41962 10.0124 1.42071 10.0118 1.42296 10.0109C1.42079 10.0121 1.41966 10.0125 1.41964 10.0124ZM1.57704 10.0109C1.57929 10.0118 1.58038 10.0124 1.58036 10.0124C1.58033 10.0125 1.57921 10.0121 1.57704 10.0109ZM1.58036 5.9874C1.58038 5.98747 1.57929 5.98808 1.57704 5.98899C1.57921 5.98778 1.58034 5.98732 1.58036 5.9874ZM1.42296 5.98899C1.42071 5.98808 1.41962 5.98747 1.41964 5.9874C1.41966 5.98732 1.42079 5.98778 1.42296 5.98899ZM3.50023 12.9998V11.5383L4.50023 11.7992V12.9998C4.50023 13.276 4.27638 13.4998 4.00023 13.4998C3.72409 13.4998 3.50023 13.276 3.50023 12.9998Z" fill="currentColor"/></svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -2,11 +2,13 @@ export { default as AddressConnectorIcon } from './address-connector.svg';
|
|||||||
export { default as ArrowIcon } from './arrow.svg';
|
export { default as ArrowIcon } from './arrow.svg';
|
||||||
export { default as Bar3Icon } from './bar3.svg';
|
export { default as Bar3Icon } from './bar3.svg';
|
||||||
export { default as BellIcon } from './bell.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 BoxCloseIcon } from './box-close.svg';
|
||||||
export { default as CalculatorIcon } from './calculator.svg';
|
export { default as CalculatorIcon } from './calculator.svg';
|
||||||
export { default as CaretIcon } from './caret-down.svg';
|
export { default as CaretIcon } from './caret-down.svg';
|
||||||
export { default as CautionCircleIcon } from './caution-circle.svg';
|
export { default as CautionCircleIcon } from './caution-circle.svg';
|
||||||
export { default as CautionCircleStrokeIcon } from './caution-circle-stroke.svg';
|
export { default as CautionCircleStrokeIcon } from './caution-circle-stroke.svg';
|
||||||
|
export { default as ChatIcon } from './chat-bubble.svg';
|
||||||
export { default as CheckIcon } from './check.svg';
|
export { default as CheckIcon } from './check.svg';
|
||||||
export { default as ChevronLeftIcon } from './chevron-left.svg';
|
export { default as ChevronLeftIcon } from './chevron-left.svg';
|
||||||
export { default as ChevronRightIcon } from './chevron-right.svg';
|
export { default as ChevronRightIcon } from './chevron-right.svg';
|
||||||
|
|||||||
@@ -11,12 +11,16 @@ import { DepositDialog } from '@/views/dialogs/DepositDialog';
|
|||||||
import { DisconnectDialog } from '@/views/dialogs/DisconnectDialog';
|
import { DisconnectDialog } from '@/views/dialogs/DisconnectDialog';
|
||||||
import { ExchangeOfflineDialog } from '@/views/dialogs/ExchangeOfflineDialog';
|
import { ExchangeOfflineDialog } from '@/views/dialogs/ExchangeOfflineDialog';
|
||||||
import { HelpDialog } from '@/views/dialogs/HelpDialog';
|
import { HelpDialog } from '@/views/dialogs/HelpDialog';
|
||||||
|
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';
|
||||||
@@ -47,11 +51,15 @@ export const DialogManager = () => {
|
|||||||
[DialogTypes.ExchangeOffline]: <ExchangeOfflineDialog {...modalProps} />,
|
[DialogTypes.ExchangeOffline]: <ExchangeOfflineDialog {...modalProps} />,
|
||||||
[DialogTypes.FillDetails]: <FillDetailsDialog {...modalProps} />,
|
[DialogTypes.FillDetails]: <FillDetailsDialog {...modalProps} />,
|
||||||
[DialogTypes.Help]: <HelpDialog {...modalProps} />,
|
[DialogTypes.Help]: <HelpDialog {...modalProps} />,
|
||||||
|
[DialogTypes.ExternalNavKeplr]: <ExternalNavKeplrDialog {...modalProps} />,
|
||||||
[DialogTypes.MnemonicExport]: <MnemonicExportDialog {...modalProps} />,
|
[DialogTypes.MnemonicExport]: <MnemonicExportDialog {...modalProps} />,
|
||||||
[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} />,
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
import styled, { type AnyStyledComponent, css } from 'styled-components';
|
import styled, { type AnyStyledComponent, css } from 'styled-components';
|
||||||
|
|
||||||
import { AbacusApiStatus } from '@/constants/abacus';
|
import { AbacusApiStatus } from '@/constants/abacus';
|
||||||
|
import { ButtonSize } from '@/constants/buttons';
|
||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
|
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||||
|
|
||||||
import { useApiState, useStringGetter } from '@/hooks';
|
import { useApiState, useSelectedNetwork, useStringGetter } from '@/hooks';
|
||||||
|
import { ChatIcon, LinkOutIcon } from '@/icons';
|
||||||
|
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
|
import { Button } from '@/components/Button';
|
||||||
import { Details } from '@/components/Details';
|
import { Details } from '@/components/Details';
|
||||||
import { Output, OutputType } from '@/components/Output';
|
import { Output, OutputType } from '@/components/Output';
|
||||||
import { WithTooltip } from '@/components/WithTooltip';
|
import { WithTooltip } from '@/components/WithTooltip';
|
||||||
@@ -24,6 +28,8 @@ enum ExchangeStatus {
|
|||||||
export const FooterDesktop = () => {
|
export const FooterDesktop = () => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const { height, indexerHeight, status, statusErrorMessage } = useApiState();
|
const { height, indexerHeight, status, statusErrorMessage } = useApiState();
|
||||||
|
const { selectedNetwork } = useSelectedNetwork();
|
||||||
|
const { statusPage } = ENVIRONMENT_CONFIG_MAP[selectedNetwork].links;
|
||||||
|
|
||||||
const { exchangeStatus, label } =
|
const { exchangeStatus, label } =
|
||||||
!status || status === AbacusApiStatus.NORMAL
|
!status || status === AbacusApiStatus.NORMAL
|
||||||
@@ -38,20 +44,37 @@ export const FooterDesktop = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Styled.Footer>
|
<Styled.Footer>
|
||||||
<WithTooltip
|
<Styled.Row>
|
||||||
slotTooltip={
|
<WithTooltip
|
||||||
statusErrorMessage && (
|
slotTooltip={
|
||||||
<dl>
|
statusErrorMessage && (
|
||||||
<dd>{statusErrorMessage}</dd>
|
<dl>
|
||||||
</dl>
|
<dd>{statusErrorMessage}</dd>
|
||||||
)
|
</dl>
|
||||||
}
|
)
|
||||||
>
|
}
|
||||||
<Styled.Row>
|
>
|
||||||
<Styled.StatusDot exchangeStatus={exchangeStatus} />
|
<Styled.FooterButton
|
||||||
<span>{label}</span>
|
slotLeft={<Styled.StatusDot exchangeStatus={exchangeStatus} />}
|
||||||
</Styled.Row>
|
slotRight={statusPage && <LinkOutIcon />}
|
||||||
</WithTooltip>
|
size={ButtonSize.XSmall}
|
||||||
|
state={{ isDisabled: !statusPage }}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Styled.FooterButton>
|
||||||
|
</WithTooltip>
|
||||||
|
|
||||||
|
{globalThis?.Intercom && (
|
||||||
|
<Styled.FooterButton
|
||||||
|
slotLeft={<ChatIcon />}
|
||||||
|
size={ButtonSize.XSmall}
|
||||||
|
onClick={() => globalThis.Intercom('show')}
|
||||||
|
>
|
||||||
|
{stringGetter({ key: STRING_KEYS.HELP_AND_SUPPORT })}
|
||||||
|
</Styled.FooterButton>
|
||||||
|
)}
|
||||||
|
</Styled.Row>
|
||||||
|
|
||||||
{import.meta.env.MODE !== 'production' && (
|
{import.meta.env.MODE !== 'production' && (
|
||||||
<Styled.Details
|
<Styled.Details
|
||||||
withSeparators
|
withSeparators
|
||||||
@@ -82,20 +105,22 @@ Styled.Footer = styled.footer`
|
|||||||
${layoutMixins.stickyFooter}
|
${layoutMixins.stickyFooter}
|
||||||
${layoutMixins.spacedRow}
|
${layoutMixins.spacedRow}
|
||||||
grid-area: Footer;
|
grid-area: Footer;
|
||||||
|
|
||||||
font-size: 0.66em;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Row = styled.div`
|
Styled.Row = styled.div`
|
||||||
${layoutMixins.row}
|
${layoutMixins.row}
|
||||||
padding: 0 1rem;
|
${layoutMixins.spacedRow}
|
||||||
gap: 0.5rem;
|
width: var(--sidebar-width);
|
||||||
|
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
border-right: 1px solid var(--color-border);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.StatusDot = styled.div<{ exchangeStatus: ExchangeStatus }>`
|
Styled.StatusDot = styled.div<{ exchangeStatus: ExchangeStatus }>`
|
||||||
width: 1em;
|
width: 0.5rem;
|
||||||
height: 1em;
|
height: 0.5rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
|
||||||
background-color: ${({ exchangeStatus }) =>
|
background-color: ${({ exchangeStatus }) =>
|
||||||
({
|
({
|
||||||
@@ -104,12 +129,28 @@ Styled.StatusDot = styled.div<{ exchangeStatus: ExchangeStatus }>`
|
|||||||
}[exchangeStatus])};
|
}[exchangeStatus])};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
Styled.FooterButton = styled(Button)`
|
||||||
|
--button-height: 1.5rem;
|
||||||
|
--button-radius: 0.25rem;
|
||||||
|
--button-backgroundColor: var(--color-layer-2);
|
||||||
|
--button-border: none;
|
||||||
|
--button-textColor: var(--color-text-0);
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
--button-backgroundColor: var(--color-layer-3);
|
||||||
|
--button-textColor: var(--color-text-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
Styled.WarningOutput = styled(Output)`
|
Styled.WarningOutput = styled(Output)`
|
||||||
color: var(--color-warning);
|
color: var(--color-warning);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Details = styled(Details)`
|
Styled.Details = styled(Details)`
|
||||||
${layoutMixins.scrollArea}
|
${layoutMixins.scrollArea}
|
||||||
|
font: var(--font-tiny-book);
|
||||||
padding: 0 0.5em;
|
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ import { ButtonShape } from '@/constants/buttons';
|
|||||||
import { DialogTypes } from '@/constants/dialogs';
|
import { DialogTypes } from '@/constants/dialogs';
|
||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
import { AppRoute } from '@/constants/routes';
|
import { AppRoute } from '@/constants/routes';
|
||||||
import { useStringGetter } from '@/hooks';
|
import { LogoShortIcon, BellStrokeIcon } from '@/icons';
|
||||||
import { LogoShortIcon, BellIcon } from '@/icons';
|
|
||||||
|
import { useTokenConfigs, useStringGetter } from '@/hooks';
|
||||||
|
|
||||||
import { Icon, IconName } from '@/components/Icon';
|
import { Icon, IconName } from '@/components/Icon';
|
||||||
import { IconButton } from '@/components/IconButton';
|
import { IconButton } from '@/components/IconButton';
|
||||||
@@ -27,6 +28,7 @@ import { layoutMixins } from '@/styles/layoutMixins';
|
|||||||
export const HeaderDesktop = () => {
|
export const HeaderDesktop = () => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const { chainTokenLabel } = useTokenConfigs();
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{
|
{
|
||||||
@@ -42,6 +44,11 @@ export const HeaderDesktop = () => {
|
|||||||
label: stringGetter({ key: STRING_KEYS.TRADE }),
|
label: stringGetter({ key: STRING_KEYS.TRADE }),
|
||||||
href: AppRoute.Trade,
|
href: AppRoute.Trade,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: chainTokenLabel,
|
||||||
|
label: chainTokenLabel,
|
||||||
|
href: `/${chainTokenLabel}`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: 'PORTFOLIO',
|
value: 'PORTFOLIO',
|
||||||
label: stringGetter({ key: STRING_KEYS.PORTFOLIO }),
|
label: stringGetter({ key: STRING_KEYS.PORTFOLIO }),
|
||||||
@@ -73,13 +80,13 @@ export const HeaderDesktop = () => {
|
|||||||
value: 'TERMS_OF_USE',
|
value: 'TERMS_OF_USE',
|
||||||
slotBefore: <Icon iconName={IconName.File} />,
|
slotBefore: <Icon iconName={IconName.File} />,
|
||||||
label: stringGetter({ key: STRING_KEYS.TERMS_OF_USE }),
|
label: stringGetter({ key: STRING_KEYS.TERMS_OF_USE }),
|
||||||
href: 'https://dydx.exchange/terms',
|
href: AppRoute.Terms,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'PRIVACY_POLICY',
|
value: 'PRIVACY_POLICY',
|
||||||
slotBefore: <Icon iconName={IconName.Privacy} />,
|
slotBefore: <Icon iconName={IconName.Privacy} />,
|
||||||
label: stringGetter({ key: STRING_KEYS.PRIVACY_POLICY }),
|
label: stringGetter({ key: STRING_KEYS.PRIVACY_POLICY }),
|
||||||
href: 'https://dydx.exchange/privacy',
|
href: AppRoute.Privacy,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'HELP',
|
value: 'HELP',
|
||||||
@@ -126,7 +133,9 @@ export const HeaderDesktop = () => {
|
|||||||
<VerticalSeparator />
|
<VerticalSeparator />
|
||||||
|
|
||||||
<NotificationsMenu
|
<NotificationsMenu
|
||||||
slotTrigger={<Styled.IconButton shape={ButtonShape.Rectangle} iconComponent={BellIcon} />}
|
slotTrigger={
|
||||||
|
<Styled.IconButton shape={ButtonShape.Rectangle} iconComponent={BellStrokeIcon} />
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<VerticalSeparator />
|
<VerticalSeparator />
|
||||||
@@ -160,7 +169,7 @@ Styled.Header = styled.header`
|
|||||||
)
|
)
|
||||||
var(--border-width) 1fr var(--border-width) auto;
|
var(--border-width) 1fr var(--border-width) auto;
|
||||||
|
|
||||||
font-size: 0.9375em;
|
font-size: 0.9375rem;
|
||||||
|
|
||||||
:before {
|
:before {
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
@@ -209,7 +218,8 @@ Styled.NavAfter = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.IconButton = styled(IconButton)`
|
Styled.IconButton = styled(IconButton)<{ size?: string }>`
|
||||||
${headerMixins.button}
|
${headerMixins.button}
|
||||||
--button-border: none;
|
--button-border: none;
|
||||||
|
--button-icon-size: 1rem;
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ import {
|
|||||||
OrderSide,
|
OrderSide,
|
||||||
OrderTimeInForce,
|
OrderTimeInForce,
|
||||||
OrderExecution,
|
OrderExecution,
|
||||||
DYDX_DENOM,
|
|
||||||
GAS_PRICE_DYDX_DENOM,
|
|
||||||
} from '@dydxprotocol/v4-client-js';
|
} from '@dydxprotocol/v4-client-js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -61,22 +59,42 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async connectNetwork(
|
async connectNetwork(
|
||||||
indexerUrl: string,
|
paramsInJson: Nullable<string>,
|
||||||
indexerSocketUrl: string,
|
|
||||||
validatorUrl: string,
|
|
||||||
chainId: string,
|
|
||||||
faucetUrl: Nullable<string> | undefined,
|
|
||||||
callback: (p0: Nullable<string>) => void
|
callback: (p0: Nullable<string>) => void
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
try {
|
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(
|
const compositeClient = await CompositeClient.connect(
|
||||||
new Network(
|
new Network(
|
||||||
chainId,
|
chainId,
|
||||||
new IndexerConfig(indexerUrl, indexerSocketUrl),
|
new IndexerConfig(indexerUrl, websocketUrl),
|
||||||
new ValidatorConfig(validatorUrl, chainId, {
|
new ValidatorConfig(
|
||||||
broadcastPollIntervalMs: 3_000,
|
validatorUrl,
|
||||||
broadcastTimeoutMs: 60_000,
|
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
|
// Dispatch custom event to notify other parts of the app that the network has been connected
|
||||||
const customEvent = new CustomEvent('abacus:connectNetwork', {
|
const customEvent = new CustomEvent('abacus:connectNetwork', {
|
||||||
detail: {
|
detail: parsedParams,
|
||||||
indexerUrl,
|
|
||||||
indexerSocketUrl,
|
|
||||||
validatorUrl,
|
|
||||||
chainId,
|
|
||||||
faucetUrl,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
globalThis.dispatchEvent(customEvent);
|
globalThis.dispatchEvent(customEvent);
|
||||||
@@ -99,9 +111,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
|||||||
this.store?.dispatch(
|
this.store?.dispatch(
|
||||||
openDialog({ type: DialogTypes.ExchangeOffline, dialogProps: { preventClose: true } })
|
openDialog({ type: DialogTypes.ExchangeOffline, dialogProps: { preventClose: true } })
|
||||||
);
|
);
|
||||||
|
|
||||||
log('DydxChainTransactions/connectNetwork', error);
|
log('DydxChainTransactions/connectNetwork', error);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,13 +223,13 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
|||||||
params ?? {};
|
params ?? {};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const tx = await this.compositeClient?.cancelOrder(
|
const tx = await this.compositeClient?.cancelRawOrder(
|
||||||
new SubaccountClient(this.localWallet, subaccountNumber),
|
new SubaccountClient(this.localWallet, subaccountNumber),
|
||||||
clientId,
|
clientId,
|
||||||
orderFlags,
|
orderFlags,
|
||||||
clobPairId,
|
clobPairId,
|
||||||
goodTilBlock ?? undefined,
|
goodTilBlock || undefined,
|
||||||
goodTilBlockTime ?? undefined
|
goodTilBlockTime || undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
const parsedTx = this.parseToPrimitives(tx);
|
const parsedTx = this.parseToPrimitives(tx);
|
||||||
@@ -251,7 +261,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
|||||||
const msg = compositeClient.withdrawFromSubaccountMessage(subaccountClient, amount);
|
const msg = compositeClient.withdrawFromSubaccountMessage(subaccountClient, amount);
|
||||||
|
|
||||||
resolve([msg]);
|
resolve([msg]);
|
||||||
}),
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const parsedTx = this.parseToPrimitives(tx);
|
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) {
|
if (!this.compositeClient || !this.localWallet) {
|
||||||
throw new Error('Missing compositeClient or localWallet');
|
throw new Error('Missing compositeClient or localWallet');
|
||||||
}
|
}
|
||||||
@@ -280,16 +292,18 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
|||||||
this.localWallet,
|
this.localWallet,
|
||||||
() =>
|
() =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
const msg = compositeClient?.validatorClient.post.composer.composeMsgSendToken(
|
if (!this.localWallet) {
|
||||||
subaccountClient.address,
|
throw new Error('Missing compositeClient or localWallet');
|
||||||
|
}
|
||||||
|
const msg = compositeClient?.sendTokenMessage(
|
||||||
|
this.localWallet,
|
||||||
|
amount,
|
||||||
recipient,
|
recipient,
|
||||||
DYDX_DENOM,
|
|
||||||
Long.fromNumber(amount * QUANTUM_MULTIPLIER)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
resolve([msg]);
|
resolve([msg]);
|
||||||
}),
|
}),
|
||||||
GAS_PRICE_DYDX_DENOM,
|
this.compositeClient?.validatorClient?.post.defaultDydxGasPrice,
|
||||||
);
|
);
|
||||||
|
|
||||||
const parsedTx = this.parseToPrimitives(tx);
|
const parsedTx = this.parseToPrimitives(tx);
|
||||||
@@ -397,9 +411,10 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
|||||||
break;
|
break;
|
||||||
case QueryType.GetAccountBalances:
|
case QueryType.GetAccountBalances:
|
||||||
if (!this.localWallet?.address) throw new Error('Missing localWallet');
|
if (!this.localWallet?.address) throw new Error('Missing localWallet');
|
||||||
const accountBalances = await this.compositeClient?.validatorClient.get.getAccountBalances(
|
const accountBalances =
|
||||||
this.localWallet.address
|
await this.compositeClient?.validatorClient.get.getAccountBalances(
|
||||||
);
|
this.localWallet.address
|
||||||
|
);
|
||||||
const parsedAccountBalances = this.parseToPrimitives(accountBalances);
|
const parsedAccountBalances = this.parseToPrimitives(accountBalances);
|
||||||
callback(JSON.stringify(parsedAccountBalances));
|
callback(JSON.stringify(parsedAccountBalances));
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import type { AbacusFileSystemProtocol, FileLocation, Nullable } from '@/constants/abacus';
|
import type { AbacusFileSystemProtocol, FileLocation, Nullable } from '@/constants/abacus';
|
||||||
import { NETWORK_ENDPOINTS } from '@/constants/networks';
|
|
||||||
|
|
||||||
export const ENDPOINTS_PATH =
|
export const ENDPOINTS_PATH =
|
||||||
import.meta.env.MODE === 'production'
|
import.meta.env.MODE === 'production'
|
||||||
@@ -8,10 +7,6 @@ export const ENDPOINTS_PATH =
|
|||||||
|
|
||||||
class AbacusFileSystem implements AbacusFileSystemProtocol {
|
class AbacusFileSystem implements AbacusFileSystemProtocol {
|
||||||
readTextFile(location: FileLocation, path: string): Nullable<string> {
|
readTextFile(location: FileLocation, path: string): Nullable<string> {
|
||||||
if (path === ENDPOINTS_PATH) {
|
|
||||||
return JSON.stringify(NETWORK_ENDPOINTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,10 +22,11 @@ import {
|
|||||||
UIImplementations,
|
UIImplementations,
|
||||||
CoroutineTimer,
|
CoroutineTimer,
|
||||||
TransferType,
|
TransferType,
|
||||||
|
AbacusAppConfig,
|
||||||
} from '@/constants/abacus';
|
} from '@/constants/abacus';
|
||||||
|
|
||||||
import { DEFAULT_MARKETID } from '@/constants/markets';
|
import { DEFAULT_MARKETID } from '@/constants/markets';
|
||||||
import { type DydxNetwork } from '@/constants/networks';
|
import { CURRENT_ABACUS_DEPLOYMENT, type DydxNetwork } from '@/constants/networks';
|
||||||
|
|
||||||
import type { RootStore } from '@/state/_store';
|
import type { RootStore } from '@/state/_store';
|
||||||
|
|
||||||
@@ -80,8 +81,9 @@ class AbacusStateManager {
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.stateManager = new AsyncAbacusStateManager(
|
this.stateManager = new AsyncAbacusStateManager(
|
||||||
import.meta.env.SHARED_RESOURCES_URI,
|
'',
|
||||||
ENDPOINTS_PATH,
|
CURRENT_ABACUS_DEPLOYMENT,
|
||||||
|
AbacusAppConfig.Companion.forWeb,
|
||||||
ioImplementations,
|
ioImplementations,
|
||||||
uiImplementations,
|
uiImplementations,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|||||||
@@ -47,6 +47,11 @@ 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();
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ import type { RootStore } from '@/state/_store';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
setBalances,
|
setBalances,
|
||||||
|
setStakingBalances,
|
||||||
setFills,
|
setFills,
|
||||||
setFundingPayments,
|
setFundingPayments,
|
||||||
setHistoricalPnl,
|
setHistoricalPnl,
|
||||||
setLatestOrder,
|
setLatestOrder,
|
||||||
|
setRestrictionType,
|
||||||
setSubaccount,
|
setSubaccount,
|
||||||
setTransfers,
|
setTransfers,
|
||||||
setWallet,
|
setWallet,
|
||||||
@@ -34,6 +36,7 @@ import { setAssets } from '@/state/assets';
|
|||||||
import { setConfigs } from '@/state/configs';
|
import { setConfigs } from '@/state/configs';
|
||||||
import { setInputs } from '@/state/inputs';
|
import { setInputs } from '@/state/inputs';
|
||||||
import { setHistoricalFundings, setLiveTrades, setMarkets, setOrderbook } from '@/state/perpetuals';
|
import { setHistoricalFundings, setLiveTrades, setMarkets, setOrderbook } from '@/state/perpetuals';
|
||||||
|
import { isTruthy } from '../isTruthy';
|
||||||
|
|
||||||
class AbacusStateNotifier implements AbacusStateNotificationProtocol {
|
class AbacusStateNotifier implements AbacusStateNotificationProtocol {
|
||||||
private store: RootStore | undefined;
|
private store: RootStore | undefined;
|
||||||
@@ -76,12 +79,19 @@ class AbacusStateNotifier implements AbacusStateNotificationProtocol {
|
|||||||
|
|
||||||
if (changes.has(Changes.accountBalances)) {
|
if (changes.has(Changes.accountBalances)) {
|
||||||
if (updatedState.account?.balances) {
|
if (updatedState.account?.balances) {
|
||||||
const balances: Record<string, AccountBalance> = {}
|
const balances: Record<string, AccountBalance> = {};
|
||||||
for (const { k, v } of updatedState.account.balances.toArray()) {
|
for (const { k, v } of updatedState.account.balances.toArray()) {
|
||||||
balances[k] = v;
|
balances[k] = v;
|
||||||
}
|
}
|
||||||
dispatch(setBalances(balances));
|
dispatch(setBalances(balances));
|
||||||
}
|
}
|
||||||
|
if (updatedState.account?.stakingBalances) {
|
||||||
|
const stakingBalances: Record<string, AccountBalance> = {};
|
||||||
|
for (const { k, v } of updatedState.account.stakingBalances.toArray()) {
|
||||||
|
stakingBalances[k] = v;
|
||||||
|
}
|
||||||
|
dispatch(setStakingBalances(stakingBalances));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changes.has(Changes.configs)) {
|
if (changes.has(Changes.configs)) {
|
||||||
@@ -100,16 +110,22 @@ class AbacusStateNotifier implements AbacusStateNotificationProtocol {
|
|||||||
dispatch(
|
dispatch(
|
||||||
setMarkets({
|
setMarkets({
|
||||||
markets: Object.fromEntries(
|
markets: Object.fromEntries(
|
||||||
(marketIds || updatedState.marketIds()?.toArray() || []).map((marketId: string) => {
|
(marketIds || updatedState.marketIds()?.toArray() || [])
|
||||||
const marketData = updatedState.market(marketId);
|
.map((marketId: string) => {
|
||||||
return [marketId, marketData];
|
const marketData = updatedState.market(marketId);
|
||||||
})
|
return [marketId, marketData];
|
||||||
|
})
|
||||||
|
.filter(isTruthy)
|
||||||
) as Record<string, PerpetualMarket>,
|
) as Record<string, PerpetualMarket>,
|
||||||
update: !!marketIds,
|
update: !!marketIds,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { type DydxNetwork, ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||||
|
|
||||||
|
export const validateAgainstAvailableEnvironments = (value: DydxNetwork) =>
|
||||||
|
Object.keys(ENVIRONMENT_CONFIG_MAP).includes(value);
|
||||||
@@ -10,7 +10,23 @@ import {
|
|||||||
bscTestnet,
|
bscTestnet,
|
||||||
optimism,
|
optimism,
|
||||||
optimismGoerli,
|
optimismGoerli,
|
||||||
} from 'wagmi/chains';
|
base,
|
||||||
|
baseGoerli,
|
||||||
|
polygon,
|
||||||
|
polygonMumbai,
|
||||||
|
linea,
|
||||||
|
lineaTestnet,
|
||||||
|
mantle,
|
||||||
|
mantleTestnet,
|
||||||
|
moonbeam,
|
||||||
|
moonbaseAlpha,
|
||||||
|
filecoin,
|
||||||
|
filecoinHyperspace,
|
||||||
|
fantom,
|
||||||
|
fantomTestnet,
|
||||||
|
celo,
|
||||||
|
celoAlfajores,
|
||||||
|
} from 'viem/chains';
|
||||||
|
|
||||||
import { alchemyProvider } from 'wagmi/providers/alchemy';
|
import { alchemyProvider } from 'wagmi/providers/alchemy';
|
||||||
import { jsonRpcProvider } from 'wagmi/providers/jsonRpc';
|
import { jsonRpcProvider } from 'wagmi/providers/jsonRpc';
|
||||||
@@ -20,7 +36,15 @@ import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet';
|
|||||||
import { InjectedConnector } from 'wagmi/connectors/injected';
|
import { InjectedConnector } from 'wagmi/connectors/injected';
|
||||||
import { MetaMaskConnector } from 'wagmi/connectors/metaMask';
|
import { MetaMaskConnector } from 'wagmi/connectors/metaMask';
|
||||||
import { WalletConnectConnector } from 'wagmi/connectors/walletConnect';
|
import { WalletConnectConnector } from 'wagmi/connectors/walletConnect';
|
||||||
import { WalletConnectLegacyConnector } from 'wagmi/connectors/walletConnectLegacy';
|
|
||||||
|
import {
|
||||||
|
type WalletConnection,
|
||||||
|
WalletConnectionType,
|
||||||
|
type WalletType,
|
||||||
|
walletConnectionTypes,
|
||||||
|
wallets,
|
||||||
|
WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS,
|
||||||
|
} from '@/constants/wallets';
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
|
|
||||||
@@ -36,10 +60,26 @@ export const WAGMI_SUPPORTED_CHAINS: Chain[] = [
|
|||||||
bscTestnet,
|
bscTestnet,
|
||||||
optimism,
|
optimism,
|
||||||
optimismGoerli,
|
optimismGoerli,
|
||||||
|
base,
|
||||||
|
baseGoerli,
|
||||||
|
polygon,
|
||||||
|
polygonMumbai,
|
||||||
|
linea,
|
||||||
|
lineaTestnet,
|
||||||
|
mantle,
|
||||||
|
mantleTestnet,
|
||||||
|
moonbeam,
|
||||||
|
moonbaseAlpha,
|
||||||
|
filecoin,
|
||||||
|
filecoinHyperspace,
|
||||||
|
fantom,
|
||||||
|
fantomTestnet,
|
||||||
|
celo,
|
||||||
|
celoAlfajores,
|
||||||
];
|
];
|
||||||
|
|
||||||
const { chains, publicClient, webSocketPublicClient } = configureChains(WAGMI_SUPPORTED_CHAINS, [
|
const { chains, publicClient, webSocketPublicClient } = configureChains(WAGMI_SUPPORTED_CHAINS, [
|
||||||
alchemyProvider({ apiKey: import.meta.env.VITE_ALCHEMY_API_KEY }),
|
// alchemyProvider({ apiKey: import.meta.env.VITE_ALCHEMY_API_KEY }),
|
||||||
jsonRpcProvider({
|
jsonRpcProvider({
|
||||||
rpc: (chain) => ({ http: chain.rpcUrls.default.http[0] }),
|
rpc: (chain) => ({ http: chain.rpcUrls.default.http[0] }),
|
||||||
}),
|
}),
|
||||||
@@ -55,53 +95,46 @@ const injectedConnectorOptions = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const walletconnect1ConnectorOptions = {
|
type WalletConnectConfig = {
|
||||||
chains,
|
client: {
|
||||||
options: {
|
name: string;
|
||||||
bridge: import.meta.env.VITE_WALLETCONNECT1_BRIDGE,
|
description: string;
|
||||||
qrcode: true,
|
iconUrl: string;
|
||||||
},
|
};
|
||||||
|
v2: {
|
||||||
|
projectId: string;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const walletconnect2ConnectorOptions: ConstructorParameters<typeof WalletConnectConnector>[0] = {
|
const getWalletconnect2ConnectorOptions = (
|
||||||
|
config: WalletConnectConfig
|
||||||
|
): ConstructorParameters<typeof WalletConnectConnector>[0] => ({
|
||||||
chains,
|
chains,
|
||||||
options: {
|
options: {
|
||||||
projectId: import.meta.env.VITE_WALLETCONNECT2_PROJECT_ID,
|
projectId: config.v2.projectId,
|
||||||
metadata: {
|
metadata: {
|
||||||
// TODO: update to local URLs/images
|
name: config.client.name,
|
||||||
name: 'dYdX',
|
description: config.client.description,
|
||||||
description: '',
|
url: import.meta.env.VITE_BASE_URL,
|
||||||
url: 'https://trade.dydx.exchange',
|
icons: [config.client.iconUrl],
|
||||||
icons: ['https://trade.dydx.exchange/cbw-image.png'],
|
|
||||||
},
|
},
|
||||||
showQrModal: true,
|
showQrModal: true,
|
||||||
qrModalOptions: {
|
qrModalOptions: {
|
||||||
themeMode: 'dark' as const,
|
themeMode: 'dark' as const,
|
||||||
themeVariables: {
|
themeVariables: {
|
||||||
'--w3m-accent-color': '#5973fe',
|
'--wcm-accent-color': '#5973fe',
|
||||||
'--w3m-background-color': '#5973fe',
|
'--wcm-font-family': 'var(--fontFamily-base)',
|
||||||
'--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',
|
|
||||||
},
|
},
|
||||||
enableExplorer: true,
|
explorerRecommendedWalletIds: WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS,
|
||||||
explorerAllowList: [],
|
|
||||||
explorerDenyList: [],
|
|
||||||
chainImages: {},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
|
||||||
const connectors = [
|
const getConnectors = (walletConnectConfig: WalletConnectConfig) => [
|
||||||
new MetaMaskConnector({
|
new MetaMaskConnector({
|
||||||
chains,
|
chains,
|
||||||
options: {
|
options: {
|
||||||
shimDisconnect: true,
|
shimDisconnect: true,
|
||||||
shimChainChangedDisconnect: false,
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
new CoinbaseWalletConnector({
|
new CoinbaseWalletConnector({
|
||||||
@@ -111,8 +144,7 @@ const connectors = [
|
|||||||
reloadOnDisconnect: false,
|
reloadOnDisconnect: false,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
new WalletConnectLegacyConnector(walletconnect1ConnectorOptions),
|
new WalletConnectConnector(getWalletconnect2ConnectorOptions(walletConnectConfig)),
|
||||||
new WalletConnectConnector(walletconnect2ConnectorOptions),
|
|
||||||
new InjectedConnector(injectedConnectorOptions),
|
new InjectedConnector(injectedConnectorOptions),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -134,58 +166,41 @@ const createInjectedConnectorWithProvider = (provider: ExternalProvider) =>
|
|||||||
provider as unknown as Awaited<ReturnType<InjectedConnector['getProvider']>>;
|
provider as unknown as Awaited<ReturnType<InjectedConnector['getProvider']>>;
|
||||||
})(injectedConnectorOptions) as InjectedConnector;
|
})(injectedConnectorOptions) as InjectedConnector;
|
||||||
|
|
||||||
// Create a custom wagmi WalletConnectLegacyConnector with a modal showing only wallet links matching the given name
|
const createWalletConnect2ConnectorWithId = (
|
||||||
const createWalletConnect1ConnectorWithName = (walletconnect1Name: string) =>
|
walletconnectId: string,
|
||||||
new WalletConnectLegacyConnector({
|
walletConnectConfig: WalletConnectConfig
|
||||||
...walletconnect1ConnectorOptions,
|
) => {
|
||||||
options: {
|
const walletconnect2ConnectorOptions = getWalletconnect2ConnectorOptions(walletConnectConfig);
|
||||||
...walletconnect1ConnectorOptions.options,
|
return new WalletConnectConnector({
|
||||||
qrcodeModalOptions: {
|
|
||||||
desktopLinks: [walletconnect1Name],
|
|
||||||
mobileLinks: [walletconnect1Name],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const createWalletConnect2ConnectorWithId = (walletconnect2Id: string) =>
|
|
||||||
new WalletConnectConnector({
|
|
||||||
...walletconnect2ConnectorOptions,
|
...walletconnect2ConnectorOptions,
|
||||||
options: {
|
options: {
|
||||||
...walletconnect2ConnectorOptions.options,
|
...walletconnect2ConnectorOptions.options,
|
||||||
qrModalOptions: {
|
qrModalOptions: {
|
||||||
...walletconnect2ConnectorOptions.options.qrModalOptions,
|
...walletconnect2ConnectorOptions.options.qrModalOptions,
|
||||||
explorerRecommendedWalletIds: [walletconnect2Id],
|
explorerRecommendedWalletIds: [walletconnectId],
|
||||||
explorerExcludedWalletIds: 'ALL',
|
explorerExcludedWalletIds: 'ALL',
|
||||||
chainImages: {},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Custom connector from wallet selection
|
// Custom connector from wallet selection
|
||||||
import {
|
|
||||||
type WalletConnection,
|
|
||||||
WalletConnectionType,
|
|
||||||
type WalletType,
|
|
||||||
walletConnectionTypes,
|
|
||||||
wallets,
|
|
||||||
} from '@/constants/wallets';
|
|
||||||
|
|
||||||
export const resolveWagmiConnector = ({
|
export const resolveWagmiConnector = ({
|
||||||
walletType,
|
walletType,
|
||||||
walletConnection,
|
walletConnection,
|
||||||
|
walletConnectConfig,
|
||||||
}: {
|
}: {
|
||||||
walletType: WalletType;
|
walletType: WalletType;
|
||||||
walletConnection: WalletConnection;
|
walletConnection: WalletConnection;
|
||||||
|
walletConnectConfig: WalletConnectConfig;
|
||||||
}) => {
|
}) => {
|
||||||
const walletConfig = wallets[walletType];
|
const walletConfig = wallets[walletType];
|
||||||
const walletConnectionConfig = walletConnectionTypes[walletConnection.type];
|
const walletConnectionConfig = walletConnectionTypes[walletConnection.type];
|
||||||
|
|
||||||
return walletConnection.type === WalletConnectionType.InjectedEip1193 && walletConnection.provider
|
return walletConnection.type === WalletConnectionType.InjectedEip1193 && walletConnection.provider
|
||||||
? createInjectedConnectorWithProvider(walletConnection.provider)
|
? createInjectedConnectorWithProvider(walletConnection.provider)
|
||||||
: walletConnection.type === WalletConnectionType.WalletConnect1 &&
|
|
||||||
walletConfig.walletconnect1Name
|
|
||||||
? createWalletConnect1ConnectorWithName(walletConfig.walletconnect1Name)
|
|
||||||
: walletConnection.type === WalletConnectionType.WalletConnect2 && walletConfig.walletconnect2Id
|
: walletConnection.type === WalletConnectionType.WalletConnect2 && walletConfig.walletconnect2Id
|
||||||
? createWalletConnect2ConnectorWithId(walletConfig.walletconnect2Id)
|
? createWalletConnect2ConnectorWithId(walletConfig.walletconnect2Id, walletConnectConfig)
|
||||||
: connectors.find(({ id }: { id: string }) => id === walletConnectionConfig.wagmiConnectorId);
|
: getConnectors(walletConnectConfig).find(({ id }: { id: string }) => id === walletConnectionConfig.wagmiConnectorId);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -45,12 +45,6 @@ export const getWalletConnection = ({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WalletConnectionType.WalletConnect1: {
|
|
||||||
return {
|
|
||||||
type: WalletConnectionType.WalletConnect1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case WalletConnectionType.WalletConnect2: {
|
case WalletConnectionType.WalletConnect2: {
|
||||||
return {
|
return {
|
||||||
type: WalletConnectionType.WalletConnect2,
|
type: WalletConnectionType.WalletConnect2,
|
||||||
|
|||||||
@@ -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}
|
||||||
|
`;
|
||||||
@@ -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}
|
||||||
|
`;
|
||||||
@@ -2,6 +2,7 @@ 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';
|
||||||
@@ -25,7 +26,6 @@ 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,7 +140,12 @@ export const AccountDetailsAndHistory = () => {
|
|||||||
<Styled.AccountValue>
|
<Styled.AccountValue>
|
||||||
<Styled.WithLabel label={accountValueLabel}>
|
<Styled.WithLabel label={accountValueLabel}>
|
||||||
<Styled.AccountEquity>
|
<Styled.AccountEquity>
|
||||||
<Output type={OutputType.Fiat} value={accountEquity} withBaseFont />
|
<Output
|
||||||
|
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,7 +3,7 @@ import styled, { AnyStyledComponent } from 'styled-components';
|
|||||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
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 { ButtonAction, ButtonSize } from '@/constants/buttons';
|
||||||
import { DialogTypes } from '@/constants/dialogs';
|
import { DialogTypes } from '@/constants/dialogs';
|
||||||
@@ -29,15 +29,16 @@ export const DYDXBalancePanel = () => {
|
|||||||
|
|
||||||
const { walletType } = useAccounts();
|
const { walletType } = useAccounts();
|
||||||
const canAccountTrade = useSelector(calculateCanAccountTrade, shallowEqual);
|
const canAccountTrade = useSelector(calculateCanAccountTrade, shallowEqual);
|
||||||
const { nativeTokenBalance } = useAccountBalance();
|
const { nativeTokenBalance, nativeStakingBalance } = useAccountBalance();
|
||||||
|
const { chainTokenLabel } = useTokenConfigs();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Styled.TransfersCard
|
<Panel
|
||||||
slotHeader={
|
slotHeader={
|
||||||
<Styled.Header>
|
<Styled.Header>
|
||||||
<Styled.Title>
|
<Styled.Title>
|
||||||
{/* <AssetIcon symbol="DYDX" /> */}
|
{/* <AssetIcon symbol="DYDX" /> */}
|
||||||
Dv4TNT
|
{chainTokenLabel}
|
||||||
</Styled.Title>
|
</Styled.Title>
|
||||||
<Styled.ReceiveAndTransferButtons>
|
<Styled.ReceiveAndTransferButtons>
|
||||||
{!canAccountTrade ? (
|
{!canAccountTrade ? (
|
||||||
@@ -97,7 +98,7 @@ export const DYDXBalancePanel = () => {
|
|||||||
</Styled.Label>
|
</Styled.Label>
|
||||||
),
|
),
|
||||||
|
|
||||||
value: <Output type={OutputType.Asset} value={undefined} />,
|
value: <Output type={OutputType.Asset} value={nativeStakingBalance} />,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
@@ -106,21 +107,23 @@ export const DYDXBalancePanel = () => {
|
|||||||
{
|
{
|
||||||
key: 'totalBalance',
|
key: 'totalBalance',
|
||||||
label: 'Total balance',
|
label: 'Total balance',
|
||||||
value: <Output type={OutputType.Asset} value={nativeTokenBalance} tag="Dv4TNT" />,
|
value: (
|
||||||
|
<Output
|
||||||
|
type={OutputType.Asset}
|
||||||
|
value={nativeTokenBalance + nativeStakingBalance}
|
||||||
|
tag={chainTokenLabel}
|
||||||
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Styled.Content>
|
</Styled.Content>
|
||||||
</Styled.TransfersCard>
|
</Panel>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Styled: Record<string, AnyStyledComponent> = {};
|
const Styled: Record<string, AnyStyledComponent> = {};
|
||||||
|
|
||||||
Styled.TransfersCard = styled(Panel)`
|
|
||||||
width: 21.25rem;
|
|
||||||
`;
|
|
||||||
|
|
||||||
Styled.Header = styled.div`
|
Styled.Header = styled.div`
|
||||||
${layoutMixins.spacedRow}
|
${layoutMixins.spacedRow}
|
||||||
padding: 1.25rem 1.5rem 0.5rem;
|
padding: 1.25rem 1.5rem 0.5rem;
|
||||||
@@ -174,13 +177,14 @@ Styled.IconContainer = styled.div`
|
|||||||
|
|
||||||
Styled.WalletAndStakedBalance = styled(Details)`
|
Styled.WalletAndStakedBalance = styled(Details)`
|
||||||
--details-item-backgroundColor: var(--color-layer-6);
|
--details-item-backgroundColor: var(--color-layer-6);
|
||||||
|
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
width: 8.625rem;
|
|
||||||
|
|
||||||
border-radius: 0.75em;
|
border-radius: 0.75em;
|
||||||
background-color: var(--color-layer-5);
|
background-color: var(--color-layer-5);
|
||||||
|
|||||||
@@ -1,17 +1,333 @@
|
|||||||
import styled, { AnyStyledComponent } from 'styled-components';
|
import styled, { AnyStyledComponent } from 'styled-components';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
|
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||||
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
|
import { ButtonAction, ButtonSize, ButtonState, ButtonType } from '@/constants/buttons';
|
||||||
|
import { DialogTypes } from '@/constants/dialogs';
|
||||||
|
|
||||||
|
import { useAccountBalance, useBreakpoints, useStringGetter } from '@/hooks';
|
||||||
|
|
||||||
|
import { breakpoints } from '@/styles';
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
|
import { Details } from '@/components/Details';
|
||||||
|
import { Panel } from '@/components/Panel';
|
||||||
|
import { IconName } from '@/components/Icon';
|
||||||
|
import { Button } from '@/components/Button';
|
||||||
|
import { IconButton } from '@/components/IconButton';
|
||||||
|
import { Link } from '@/components/Link';
|
||||||
|
import { Output, OutputType } from '@/components/Output';
|
||||||
|
import { VerticalSeparator } from '@/components/Separator';
|
||||||
|
import { WithReceipt } from '@/components/WithReceipt';
|
||||||
|
|
||||||
|
import { openDialog } from '@/state/dialogs';
|
||||||
|
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||||
|
|
||||||
import { DYDXBalancePanel } from './DYDXBalancePanel';
|
import { DYDXBalancePanel } from './DYDXBalancePanel';
|
||||||
|
|
||||||
export const RewardsPage = () => (
|
// TODO: replace placeholder URL with real URLs when avaialble
|
||||||
<Styled.Page>
|
const GOVERNANCE_HELP_URL = 'https://help.dydx.exchange/';
|
||||||
<DYDXBalancePanel />
|
const STAKING_HELP_URL = 'https://help.dydx.exchange/';
|
||||||
</Styled.Page>
|
|
||||||
);
|
export const RewardsPage = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const stringGetter = useStringGetter();
|
||||||
|
const { isTablet, isNotTablet } = useBreakpoints();
|
||||||
|
|
||||||
|
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||||
|
|
||||||
|
// const chainId = Number(ENVIRONMENT_CONFIG_MAP[selectedNetwork].ethereumChainId);
|
||||||
|
|
||||||
|
// const { balance } = useAccountBalance({
|
||||||
|
// addressOrDenom: import.meta.env.VITE_V3_TOKEN_ADDRESS,
|
||||||
|
// assetSymbol: 'DYDX',
|
||||||
|
// chainId,
|
||||||
|
// isCosmosChain: false,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const tokenBalance = import.meta.env.VITE_V3_TOKEN_ADDRESS ? balance : 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Styled.Page>
|
||||||
|
{/* {isNotTablet ? (
|
||||||
|
<Styled.Migrate>
|
||||||
|
<Styled.TwoItemRow>
|
||||||
|
<div>
|
||||||
|
<Styled.MigrateTitle>
|
||||||
|
{stringGetter({ key: STRING_KEYS.MIGRATE })}
|
||||||
|
</Styled.MigrateTitle>
|
||||||
|
<Styled.Description>
|
||||||
|
{stringGetter({ key: STRING_KEYS.MIGRATE_DESCRIPTION })}
|
||||||
|
<Link href={MIGRATE_HELP_URL}>
|
||||||
|
{stringGetter({ key: STRING_KEYS.LEARN_MORE })} →
|
||||||
|
</Link>
|
||||||
|
</Styled.Description>
|
||||||
|
</div>
|
||||||
|
<Styled.MigrateAction>
|
||||||
|
<div>
|
||||||
|
<div>{stringGetter({ key: STRING_KEYS.AVAILABLE_TO_MIGRATE })}</div>
|
||||||
|
<div>
|
||||||
|
<Styled.Token type={OutputType.Asset} value={tokenBalance} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
action={tokenBalance ? ButtonAction.Primary : ButtonAction.Base}
|
||||||
|
// type={ButtonType.Link}
|
||||||
|
// href={BRIDGE_URL}
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
{tokenBalance
|
||||||
|
? `${stringGetter({ key: STRING_KEYS.MIGRATE_NOW })} →`
|
||||||
|
: stringGetter({ key: STRING_KEYS.NO_TOKENS_TO_MIGRATE })}
|
||||||
|
</Button>
|
||||||
|
</Styled.MigrateAction>
|
||||||
|
</Styled.TwoItemRow>
|
||||||
|
</Styled.Migrate>
|
||||||
|
) : (
|
||||||
|
<Styled.MobileMigrateCard
|
||||||
|
slotHeader={
|
||||||
|
<Styled.MobileMigrateHeader>
|
||||||
|
<h3>{stringGetter({ key: STRING_KEYS.MIGRATE })}</h3>
|
||||||
|
<VerticalSeparator />
|
||||||
|
<span>
|
||||||
|
{stringGetter({
|
||||||
|
key: STRING_KEYS.FROM_TO,
|
||||||
|
params: { FROM: <strong>Ethereum</strong>, TO: <strong>dYdX Chain</strong> },
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</Styled.MobileMigrateHeader>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Styled.WithReceipt
|
||||||
|
slotReceipt={
|
||||||
|
<Styled.Details
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
key: 'available-to-migrate',
|
||||||
|
label: stringGetter({ key: STRING_KEYS.AVAILABLE_TO_MIGRATE }),
|
||||||
|
value: <Output type={OutputType.Asset} value={tokenBalance} />,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
action={tokenBalance ? ButtonAction.Primary : ButtonAction.Base}
|
||||||
|
size={ButtonSize.Medium}
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
{tokenBalance
|
||||||
|
? `${stringGetter({ key: STRING_KEYS.MIGRATE_NOW })} →`
|
||||||
|
: stringGetter({ key: STRING_KEYS.NO_TOKENS_TO_MIGRATE })}
|
||||||
|
</Button>
|
||||||
|
</Styled.WithReceipt>
|
||||||
|
<Styled.LearnMore>
|
||||||
|
{stringGetter({ key: STRING_KEYS.WANT_TO_LEARN })}
|
||||||
|
<Link href={MIGRATE_HELP_URL}>{stringGetter({ key: STRING_KEYS.CLICK_HERE })}</Link>
|
||||||
|
</Styled.LearnMore>
|
||||||
|
</Styled.MobileMigrateCard>
|
||||||
|
)} */}
|
||||||
|
|
||||||
|
<Styled.PanelRow>
|
||||||
|
{isTablet && (
|
||||||
|
<Styled.BalancePanelContainer>
|
||||||
|
<DYDXBalancePanel />
|
||||||
|
</Styled.BalancePanelContainer>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Styled.Panel
|
||||||
|
slotHeader={<Styled.Title>{stringGetter({ key: STRING_KEYS.GOVERNANCE })}</Styled.Title>}
|
||||||
|
onClick={() => dispatch(openDialog({ type: DialogTypes.ExternalNavKeplr }))}
|
||||||
|
>
|
||||||
|
<Styled.Row>
|
||||||
|
<Styled.Description>
|
||||||
|
{stringGetter({ key: STRING_KEYS.GOVERNANCE_DESCRIPTION })}
|
||||||
|
<Link href={GOVERNANCE_HELP_URL} onClick={(e) => e.stopPropagation()}>
|
||||||
|
{stringGetter({ key: STRING_KEYS.LEARN_MORE })} →
|
||||||
|
</Link>
|
||||||
|
</Styled.Description>
|
||||||
|
{/* TODO: vertically center based on Panel height */}
|
||||||
|
<Styled.IconButton
|
||||||
|
action={ButtonAction.Base}
|
||||||
|
iconName={IconName.Arrow}
|
||||||
|
size={ButtonSize.Small}
|
||||||
|
/>
|
||||||
|
</Styled.Row>
|
||||||
|
</Styled.Panel>
|
||||||
|
|
||||||
|
<Styled.Panel
|
||||||
|
slotHeader={<Styled.Title>{stringGetter({ key: STRING_KEYS.STAKING })}</Styled.Title>}
|
||||||
|
onClick={() => dispatch(openDialog({ type: DialogTypes.ExternalNavKeplr }))}
|
||||||
|
>
|
||||||
|
<Styled.Row>
|
||||||
|
<Styled.Description>
|
||||||
|
{stringGetter({ key: STRING_KEYS.STAKING_DESCRIPTION })}
|
||||||
|
<Link href={STAKING_HELP_URL} onClick={(e) => e.stopPropagation()}>
|
||||||
|
{stringGetter({ key: STRING_KEYS.LEARN_MORE })} →
|
||||||
|
</Link>
|
||||||
|
</Styled.Description>
|
||||||
|
{/* TODO: vertically center based on Panel height */}
|
||||||
|
<Styled.IconButton
|
||||||
|
action={ButtonAction.Base}
|
||||||
|
iconName={IconName.Arrow}
|
||||||
|
size={ButtonSize.Small}
|
||||||
|
/>
|
||||||
|
</Styled.Row>
|
||||||
|
</Styled.Panel>
|
||||||
|
|
||||||
|
{isNotTablet && (
|
||||||
|
<Styled.BalancePanelContainer>
|
||||||
|
<DYDXBalancePanel />
|
||||||
|
</Styled.BalancePanelContainer>
|
||||||
|
)}
|
||||||
|
</Styled.PanelRow>
|
||||||
|
</Styled.Page>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const Styled: Record<string, AnyStyledComponent> = {};
|
const Styled: Record<string, AnyStyledComponent> = {};
|
||||||
|
|
||||||
Styled.Page = styled.div`
|
Styled.Page = styled.div`
|
||||||
${layoutMixins.centered}
|
${layoutMixins.contentContainerPage}
|
||||||
|
gap: 1.5rem;
|
||||||
|
|
||||||
|
@media ${breakpoints.tablet} {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Panel = styled(Panel)`
|
||||||
|
padding: 0 1.5rem 1rem;
|
||||||
|
|
||||||
|
@media ${breakpoints.tablet} {
|
||||||
|
max-width: calc(100vw - 2rem);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Row = styled.div`
|
||||||
|
${layoutMixins.spacedRow}
|
||||||
|
gap: 1rem;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Description = styled.div`
|
||||||
|
color: var(--color-text-0);
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Migrate = styled.section`
|
||||||
|
max-width: min(100vw, var(--content-max-width));
|
||||||
|
|
||||||
|
padding: 1.5rem;
|
||||||
|
|
||||||
|
background-color: var(--color-layer-3);
|
||||||
|
border-radius: 0.875rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.TwoItemRow = styled(Styled.Row)`
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.MigrateAction = styled(Styled.TwoItemRow)`
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
background-color: var(--color-layer-2);
|
||||||
|
border: solid var(--border-width) var(--color-border);
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Token = styled(Output)`
|
||||||
|
font: var(--font-large-book);
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.PanelRow = styled(Styled.Row)`
|
||||||
|
gap: 1.5rem;
|
||||||
|
max-width: min(100vw, var(--content-max-width));
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
> section {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media ${breakpoints.tablet} {
|
||||||
|
grid-auto-flow: row;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
max-width: auto;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.BalancePanelContainer = styled.div`
|
||||||
|
width: 21.25rem;
|
||||||
|
|
||||||
|
@media ${breakpoints.tablet} {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Title = styled.h3`
|
||||||
|
${layoutMixins.inlineRow}
|
||||||
|
padding: 1.25rem 1.5rem 0.5rem;
|
||||||
|
|
||||||
|
font: var(--font-medium-book);
|
||||||
|
color: var(--color-text-2);
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.MigrateTitle = styled(Styled.Title)`
|
||||||
|
padding: 0 0 0.5rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.MobileMigrateCard = styled(Styled.Panel)`
|
||||||
|
${layoutMixins.flexColumn}
|
||||||
|
gap: 1rem;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.MobileMigrateHeader = styled(Styled.Title)`
|
||||||
|
${layoutMixins.inlineRow}
|
||||||
|
gap: 1ch;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
|
||||||
|
font: var(--font-small-book);
|
||||||
|
color: var(--color-text-0);
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
${layoutMixins.inlineRow}
|
||||||
|
font: var(--font-large-book);
|
||||||
|
color: var(--color-text-2);
|
||||||
|
|
||||||
|
svg {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-top: 0.2rem;
|
||||||
|
b {
|
||||||
|
font-weight: var(--fontWeight-book);
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Details = styled(Details)`
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.WithReceipt = styled(WithReceipt)`
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.LearnMore = styled(Styled.Description)`
|
||||||
|
${layoutMixins.row}
|
||||||
|
gap: 1ch;
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.IconButton = styled(IconButton)`
|
||||||
|
color: var(--color-text-0);
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ import { getCurrentMarketAssetData } from '@/state/assetsSelectors';
|
|||||||
import { getCurrentMarketId } from '@/state/perpetualsSelectors';
|
import { getCurrentMarketId } from '@/state/perpetualsSelectors';
|
||||||
|
|
||||||
export const MarketSelectorAndStats = ({ className }: { className?: string }) => {
|
export const MarketSelectorAndStats = ({ className }: { className?: string }) => {
|
||||||
const { symbol = '' } = useSelector(getCurrentMarketAssetData, shallowEqual) ?? {};
|
const { id = '' } = useSelector(getCurrentMarketAssetData, shallowEqual) ?? {};
|
||||||
const currentMarketId = useSelector(getCurrentMarketId);
|
const currentMarketId = useSelector(getCurrentMarketId);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Styled.Container className={className}>
|
<Styled.Container className={className}>
|
||||||
<MarketsDropdown currentMarketId={currentMarketId} symbol={symbol} />
|
<MarketsDropdown currentMarketId={currentMarketId} symbol={id} />
|
||||||
|
|
||||||
<VerticalSeparator />
|
<VerticalSeparator />
|
||||||
|
|
||||||
|
|||||||
@@ -13,4 +13,6 @@ declare global {
|
|||||||
|
|
||||||
'abacus:connectNetwork': CustomEvent;
|
'abacus:connectNetwork': CustomEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var Intercom: any;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ 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';
|
||||||
@@ -13,7 +12,6 @@ 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];
|
||||||
@@ -28,7 +26,6 @@ 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,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -38,7 +35,6 @@ export const store = configureStore({
|
|||||||
}),
|
}),
|
||||||
appMiddleware,
|
appMiddleware,
|
||||||
localizationMiddleware,
|
localizationMiddleware,
|
||||||
routerMiddleware,
|
|
||||||
],
|
],
|
||||||
|
|
||||||
devTools: process.env.NODE_ENV !== 'production',
|
devTools: process.env.NODE_ENV !== 'production',
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ 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';
|
||||||
@@ -21,33 +22,46 @@ 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>;
|
||||||
onboardingGuards: Record<OnboardingGuard, boolean | undefined>;
|
|
||||||
onboardingState: OnboardingState;
|
|
||||||
subaccount?: Nullable<Subaccount>;
|
|
||||||
uncommittedOrderClientIds: number[];
|
|
||||||
wallet?: Nullable<Wallet>;
|
|
||||||
walletType?: WalletType;
|
|
||||||
historicalPnlPeriod?: HistoricalPnlPeriods;
|
historicalPnlPeriod?: HistoricalPnlPeriods;
|
||||||
balances?: Record<string, AccountBalance>;
|
uncommittedOrderClientIds: number[];
|
||||||
|
|
||||||
|
restriction?: Nullable<UsageRestriction>;
|
||||||
};
|
};
|
||||||
|
|
||||||
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>({
|
||||||
@@ -58,12 +72,17 @@ 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: [],
|
||||||
wallet: undefined,
|
historicalPnlPeriod: undefined,
|
||||||
walletType: getLocalStorage<WalletType>({
|
|
||||||
key: LocalStorageKey.OnboardingSelectedWalletType,
|
// Restriction
|
||||||
}),
|
restriction: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const accountSlice = createSlice({
|
export const accountSlice = createSlice({
|
||||||
@@ -123,6 +142,9 @@ 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)
|
||||||
@@ -154,6 +176,9 @@ export const accountSlice = createSlice({
|
|||||||
setBalances: (state, action: PayloadAction<Record<string, AccountBalance>>) => {
|
setBalances: (state, action: PayloadAction<Record<string, AccountBalance>>) => {
|
||||||
state.balances = action.payload;
|
state.balances = action.payload;
|
||||||
},
|
},
|
||||||
|
setStakingBalances: (state, action: PayloadAction<Record<string, AccountBalance>>) => {
|
||||||
|
state.stakingBalances = action.payload;
|
||||||
|
},
|
||||||
addUncommittedOrderClientId: (state, action: PayloadAction<number>) => {
|
addUncommittedOrderClientId: (state, action: PayloadAction<number>) => {
|
||||||
state.uncommittedOrderClientIds.push(action.payload);
|
state.uncommittedOrderClientIds.push(action.payload);
|
||||||
},
|
},
|
||||||
@@ -174,11 +199,13 @@ export const {
|
|||||||
setOnboardingGuard,
|
setOnboardingGuard,
|
||||||
setOnboardingState,
|
setOnboardingState,
|
||||||
setHistoricalPnl,
|
setHistoricalPnl,
|
||||||
|
setRestrictionType,
|
||||||
setSubaccount,
|
setSubaccount,
|
||||||
setWallet,
|
setWallet,
|
||||||
viewedFills,
|
viewedFills,
|
||||||
viewedOrders,
|
viewedOrders,
|
||||||
setBalances,
|
setBalances,
|
||||||
|
setStakingBalances,
|
||||||
addUncommittedOrderClientId,
|
addUncommittedOrderClientId,
|
||||||
removeUncommittedOrderClientId,
|
removeUncommittedOrderClientId,
|
||||||
} = accountSlice.actions;
|
} = accountSlice.actions;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { createSelector } from 'reselect';
|
|||||||
|
|
||||||
import { SubaccountPosition } from '@/constants/abacus';
|
import { SubaccountPosition } from '@/constants/abacus';
|
||||||
import { OnboardingState, OnboardingSteps } from '@/constants/account';
|
import { OnboardingState, OnboardingSteps } from '@/constants/account';
|
||||||
import { isDydxV4Network } from '@/constants/networks';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getExistingOpenPositions,
|
getExistingOpenPositions,
|
||||||
@@ -12,8 +11,6 @@ import {
|
|||||||
getUncommittedOrderClientIds,
|
getUncommittedOrderClientIds,
|
||||||
} from '@/state/accountSelectors';
|
} from '@/state/accountSelectors';
|
||||||
|
|
||||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
|
||||||
|
|
||||||
export const calculateOnboardingStep = createSelector(
|
export const calculateOnboardingStep = createSelector(
|
||||||
[getOnboardingState, getOnboardingGuards],
|
[getOnboardingState, getOnboardingGuards],
|
||||||
(onboardingState: OnboardingState, onboardingGuards: ReturnType<typeof getOnboardingGuards>) => {
|
(onboardingState: OnboardingState, onboardingGuards: ReturnType<typeof getOnboardingGuards>) => {
|
||||||
@@ -35,9 +32,9 @@ export const calculateOnboardingStep = createSelector(
|
|||||||
* @description calculate whether an account is in a state where they can trade
|
* @description calculate whether an account is in a state where they can trade
|
||||||
*/
|
*/
|
||||||
export const calculateCanAccountTrade = createSelector(
|
export const calculateCanAccountTrade = createSelector(
|
||||||
[getOnboardingState, getSelectedNetwork],
|
[getOnboardingState],
|
||||||
(onboardingState: OnboardingState, selectedNetwork: string) => {
|
(onboardingState: OnboardingState) => {
|
||||||
return onboardingState === OnboardingState.AccountConnected && isDydxV4Network(selectedNetwork);
|
return onboardingState === OnboardingState.AccountConnected;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -337,3 +337,18 @@ export const getUserStats = (state: RootState) => ({
|
|||||||
* @returns user wallet balances
|
* @returns user wallet balances
|
||||||
*/
|
*/
|
||||||
export const getBalances = (state: RootState) => state.account?.balances;
|
export const getBalances = (state: RootState) => state.account?.balances;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns user wallet staking balances
|
||||||
|
* */
|
||||||
|
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;
|
||||||
|
|||||||
@@ -2,14 +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,
|
|
||||||
isValidDydxNetwork,
|
|
||||||
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;
|
||||||
@@ -23,7 +19,7 @@ const initialState: AppState = {
|
|||||||
selectedNetwork: getLocalStorage({
|
selectedNetwork: getLocalStorage({
|
||||||
key: LocalStorageKey.SelectedNetwork,
|
key: LocalStorageKey.SelectedNetwork,
|
||||||
defaultValue: DEFAULT_APP_ENVIRONMENT,
|
defaultValue: DEFAULT_APP_ENVIRONMENT,
|
||||||
validateFn: isValidDydxNetwork,
|
validateFn: validateAgainstAvailableEnvironments,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -23,39 +23,38 @@ export const dialogsSlice = createSlice({
|
|||||||
name: 'Dialogs',
|
name: 'Dialogs',
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
addDialogToQueue: (state: DialogsState, action: PayloadAction<DialogInfo<DialogTypes>>) => {
|
openDialog: (state: DialogsState, action: PayloadAction<DialogInfo<DialogTypes>>) => {
|
||||||
const dialogQueue = state.dialogQueue;
|
if (state.activeDialog?.type === action.payload.type) return;
|
||||||
dialogQueue.push(action.payload);
|
|
||||||
|
|
||||||
return {
|
if (state.activeDialog) {
|
||||||
...state,
|
state.dialogQueue.push(action.payload);
|
||||||
dialogQueue,
|
} else {
|
||||||
};
|
state.activeDialog = action.payload;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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,
|
state.activeTradeBoxDialog = action.payload;
|
||||||
activeTradeBoxDialog: action.payload,
|
},
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
addDialogToQueue,
|
forceOpenDialog,
|
||||||
closeDialog,
|
closeDialog,
|
||||||
closeDialogInTradeBox,
|
closeDialogInTradeBox,
|
||||||
openDialog,
|
openDialog,
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
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;
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
||||||
@@ -36,11 +36,10 @@
|
|||||||
--single-unit-height: 9.375rem;
|
--single-unit-height: 9.375rem;
|
||||||
|
|
||||||
/* Modal constants */
|
/* Modal constants */
|
||||||
--sidebar-modal-width: 18.75rem;
|
--dialog-small-width: 18.75rem;
|
||||||
--modal-small-width: 18.75rem;
|
--dialog-medium-width: 20.5rem;
|
||||||
--modal-medium-width: 20.5rem;
|
--dialog-large-width: 26.25rem;
|
||||||
--modal-large-width: 26.25rem;
|
--dialog-header-height: 4rem;
|
||||||
--modal-header-height: 4rem;
|
|
||||||
|
|
||||||
/* Market Selector constants */
|
/* Market Selector constants */
|
||||||
--marketsDropdown-openWidth: 45rem;
|
--marketsDropdown-openWidth: 45rem;
|
||||||
|
|||||||
@@ -188,13 +188,14 @@ export const popoverMixins = {
|
|||||||
--item-highlighted-backgroundColor: var(--color-layer-2);
|
--item-highlighted-backgroundColor: var(--color-layer-2);
|
||||||
--item-highlighted-textColor: var(--color-text-2);
|
--item-highlighted-textColor: var(--color-text-2);
|
||||||
|
|
||||||
|
--item-gap: 0.5em;
|
||||||
--item-radius: 0px;
|
--item-radius: 0px;
|
||||||
--item-padding: 0.5em 1em;
|
--item-padding: 0.5em 1em;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5em;
|
gap: var(--item-gap);
|
||||||
|
|
||||||
padding: var(--item-padding);
|
padding: var(--item-padding);
|
||||||
border-radius: var(--item-radius);
|
border-radius: var(--item-radius);
|
||||||
|
|||||||
@@ -75,16 +75,14 @@ export const AccountInfoConnectedState = () => {
|
|||||||
<Styled.Header>
|
<Styled.Header>
|
||||||
<span>{stringGetter({ key: STRING_KEYS.ACCOUNT })}</span>
|
<span>{stringGetter({ key: STRING_KEYS.ACCOUNT })}</span>
|
||||||
<Styled.TransferButtons>
|
<Styled.TransferButtons>
|
||||||
{import.meta.env.MODE !== 'production' && (
|
<Styled.Button
|
||||||
<Styled.Button
|
state={{ isDisabled: !dydxAccounts }}
|
||||||
state={{ isDisabled: !dydxAccounts }}
|
onClick={() => dispatch(openDialog({ type: DialogTypes.Withdraw }))}
|
||||||
onClick={() => dispatch(openDialog({ type: DialogTypes.Withdraw }))}
|
shape={ButtonShape.Pill}
|
||||||
shape={ButtonShape.Pill}
|
size={ButtonSize.XSmall}
|
||||||
size={ButtonSize.XSmall}
|
>
|
||||||
>
|
{stringGetter({ key: STRING_KEYS.WITHDRAW })}
|
||||||
{stringGetter({ key: STRING_KEYS.WITHDRAW })}
|
</Styled.Button>
|
||||||
</Styled.Button>
|
|
||||||
)}
|
|
||||||
<Styled.Button
|
<Styled.Button
|
||||||
state={{ isDisabled: !dydxAccounts }}
|
state={{ isDisabled: !dydxAccounts }}
|
||||||
onClick={() => dispatch(openDialog({ type: DialogTypes.Deposit }))}
|
onClick={() => dispatch(openDialog({ type: DialogTypes.Deposit }))}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export const MarketDetails: React.FC = () => {
|
|||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const { isTablet } = useBreakpoints();
|
const { isTablet } = useBreakpoints();
|
||||||
const { configs, market } = useSelector(getCurrentMarketData, shallowEqual) || {};
|
const { configs, market } = useSelector(getCurrentMarketData, shallowEqual) || {};
|
||||||
const { symbol, name, resources } = useSelector(getCurrentMarketAssetData, shallowEqual) || {};
|
const { id, name, resources } = useSelector(getCurrentMarketAssetData, shallowEqual) || {};
|
||||||
|
|
||||||
if (!configs) return null;
|
if (!configs) return null;
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ export const MarketDetails: React.FC = () => {
|
|||||||
useGrouping
|
useGrouping
|
||||||
value={stepSize}
|
value={stepSize}
|
||||||
type={OutputType.Asset}
|
type={OutputType.Asset}
|
||||||
tag={symbol}
|
tag={id}
|
||||||
fractionDigits={stepSizeDecimals}
|
fractionDigits={stepSizeDecimals}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -88,7 +88,7 @@ export const MarketDetails: React.FC = () => {
|
|||||||
useGrouping
|
useGrouping
|
||||||
value={minOrderSize}
|
value={minOrderSize}
|
||||||
type={OutputType.Asset}
|
type={OutputType.Asset}
|
||||||
tag={symbol}
|
tag={id}
|
||||||
fractionDigits={stepSizeDecimals}
|
fractionDigits={stepSizeDecimals}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -132,18 +132,16 @@ export const MarketDetails: React.FC = () => {
|
|||||||
<Styled.Header>
|
<Styled.Header>
|
||||||
<Styled.WrapRow>
|
<Styled.WrapRow>
|
||||||
<Styled.MarketTitle>
|
<Styled.MarketTitle>
|
||||||
<AssetIcon symbol={symbol} />
|
<AssetIcon symbol={id} />
|
||||||
{name}
|
{name}
|
||||||
</Styled.MarketTitle>
|
</Styled.MarketTitle>
|
||||||
{isTablet && <Styled.MarketLinks />}
|
{isTablet && <Styled.MarketLinks />}
|
||||||
</Styled.WrapRow>
|
</Styled.WrapRow>
|
||||||
|
|
||||||
<Styled.MarketDescription>
|
<Styled.MarketDescription>
|
||||||
{primaryDescriptionKey && (
|
{primaryDescriptionKey && <p>{stringGetter({ key: `APP.${primaryDescriptionKey}` })}</p>}
|
||||||
<p>{stringGetter({ key: STRING_KEYS[primaryDescriptionKey as StringKey] })}</p>
|
|
||||||
)}
|
|
||||||
{secondaryDescriptionKey && (
|
{secondaryDescriptionKey && (
|
||||||
<p>{stringGetter({ key: STRING_KEYS[secondaryDescriptionKey as StringKey] })}</p>
|
<p>{stringGetter({ key: `APP.${secondaryDescriptionKey}` })}</p>
|
||||||
)}
|
)}
|
||||||
</Styled.MarketDescription>
|
</Styled.MarketDescription>
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const defaultMarketStatistics = Object.values(MarketStats);
|
|||||||
export const MarketStatsDetails = ({ showMidMarketPrice = true }: ElementProps) => {
|
export const MarketStatsDetails = ({ showMidMarketPrice = true }: ElementProps) => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const { isTablet } = useBreakpoints();
|
const { isTablet } = useBreakpoints();
|
||||||
const { symbol = '' } = useSelector(getCurrentMarketAssetData, shallowEqual) ?? {};
|
const { id = '' } = useSelector(getCurrentMarketAssetData, shallowEqual) ?? {};
|
||||||
const { tickSizeDecimals } = useSelector(getCurrentMarketConfig, shallowEqual) ?? {};
|
const { tickSizeDecimals } = useSelector(getCurrentMarketConfig, shallowEqual) ?? {};
|
||||||
const midMarketPrice = useSelector(getCurrentMarketMidMarketPrice);
|
const midMarketPrice = useSelector(getCurrentMarketMidMarketPrice);
|
||||||
const lastMidMarketPrice = useRef(midMarketPrice);
|
const lastMidMarketPrice = useRef(midMarketPrice);
|
||||||
@@ -116,7 +116,7 @@ export const MarketStatsDetails = ({ showMidMarketPrice = true }: ElementProps)
|
|||||||
<Styled.Output
|
<Styled.Output
|
||||||
type={OutputType.Number}
|
type={OutputType.Number}
|
||||||
value={value}
|
value={value}
|
||||||
tag={symbol}
|
tag={id}
|
||||||
fractionDigits={LARGE_TOKEN_DECIMALS}
|
fractionDigits={LARGE_TOKEN_DECIMALS}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -60,12 +60,12 @@ const MarketsDropdownContent = ({ onRowAction }: { onRowAction?: (market: string
|
|||||||
columnKey: 'market',
|
columnKey: 'market',
|
||||||
getCellValue: (row) => row.market,
|
getCellValue: (row) => row.market,
|
||||||
label: stringGetter({ key: STRING_KEYS.MARKET }),
|
label: stringGetter({ key: STRING_KEYS.MARKET }),
|
||||||
renderCell: ({ asset }) => (
|
renderCell: ({ assetId, id }) => (
|
||||||
<Styled.MarketName isFavorited={false}>
|
<Styled.MarketName isFavorited={false}>
|
||||||
{/* TRCL-1693 <Icon iconName={IconName.Star} /> */}
|
{/* TRCL-1693 <Icon iconName={IconName.Star} /> */}
|
||||||
<AssetIcon symbol={asset.symbol} />
|
<AssetIcon symbol={assetId} />
|
||||||
<h2>{asset.name}</h2>
|
<h2>{id}</h2>
|
||||||
<Tag>{asset.symbol}</Tag>
|
<Tag>{assetId}</Tag>
|
||||||
</Styled.MarketName>
|
</Styled.MarketName>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export const PositionInfo = ({ showNarrowVariation }: { showNarrowVariation?: bo
|
|||||||
const isLoading = useSelector(calculateIsAccountLoading);
|
const isLoading = useSelector(calculateIsAccountLoading);
|
||||||
|
|
||||||
const { stepSizeDecimals, tickSizeDecimals } = currentMarketConfigs || {};
|
const { stepSizeDecimals, tickSizeDecimals } = currentMarketConfigs || {};
|
||||||
const { symbol } = currentMarketAssetData || {};
|
const { id } = currentMarketAssetData || {};
|
||||||
const { type: dialogType } = activeDialog || {};
|
const { type: dialogType } = activeDialog || {};
|
||||||
const { type: tradeBoxDialogType } = activeTradeBoxDialog || {};
|
const { type: tradeBoxDialogType } = activeTradeBoxDialog || {};
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ export const PositionInfo = ({ showNarrowVariation }: { showNarrowVariation?: bo
|
|||||||
label: STRING_KEYS.LIQUIDATION_PRICE,
|
label: STRING_KEYS.LIQUIDATION_PRICE,
|
||||||
tooltip: 'liquidation-price',
|
tooltip: 'liquidation-price',
|
||||||
tooltipParams: {
|
tooltipParams: {
|
||||||
SYMBOL: symbol || '',
|
SYMBOL: id || '',
|
||||||
},
|
},
|
||||||
fractionDigits: tickSizeDecimals,
|
fractionDigits: tickSizeDecimals,
|
||||||
hasInvalidNewValue: Boolean(newLeverageIsInvalid),
|
hasInvalidNewValue: Boolean(newLeverageIsInvalid),
|
||||||
@@ -326,7 +326,7 @@ export const PositionInfo = ({ showNarrowVariation }: { showNarrowVariation?: bo
|
|||||||
notionalTotal={notionalTotal?.current}
|
notionalTotal={notionalTotal?.current}
|
||||||
postOrderSize={size?.postOrder}
|
postOrderSize={size?.postOrder}
|
||||||
stepSizeDecimals={stepSizeDecimals}
|
stepSizeDecimals={stepSizeDecimals}
|
||||||
symbol={symbol || undefined}
|
symbol={id || undefined}
|
||||||
tickSizeDecimals={tickSizeDecimals}
|
tickSizeDecimals={tickSizeDecimals}
|
||||||
showNarrowVariation={showNarrowVariation}
|
showNarrowVariation={showNarrowVariation}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
@@ -370,7 +370,7 @@ export const PositionInfo = ({ showNarrowVariation }: { showNarrowVariation?: bo
|
|||||||
notionalTotal={notionalTotal?.current}
|
notionalTotal={notionalTotal?.current}
|
||||||
postOrderSize={size?.postOrder}
|
postOrderSize={size?.postOrder}
|
||||||
stepSizeDecimals={stepSizeDecimals}
|
stepSizeDecimals={stepSizeDecimals}
|
||||||
symbol={symbol || undefined}
|
symbol={id || undefined}
|
||||||
tickSizeDecimals={tickSizeDecimals}
|
tickSizeDecimals={tickSizeDecimals}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { useCallback, useState, useMemo } from 'react';
|
import { useCallback, useState, useMemo } from 'react';
|
||||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||||
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
|
|
||||||
import { Root, Trigger, Content } from '@radix-ui/react-collapsible';
|
import { Root, Trigger, Content } from '@radix-ui/react-collapsible';
|
||||||
import { StatusResponse } from '@0xsquid/sdk';
|
import { StatusResponse } from '@0xsquid/sdk';
|
||||||
|
|
||||||
@@ -21,12 +20,14 @@ import { LoadingDots } from '@/components/Loading/LoadingDots';
|
|||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
type ElementProps = {
|
type ElementProps = {
|
||||||
|
type: 'withdrawal' | 'deposit';
|
||||||
toAmount?: number;
|
toAmount?: number;
|
||||||
triggeredAt?: number;
|
triggeredAt?: number;
|
||||||
status?: StatusResponse;
|
status?: StatusResponse;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TransferStatusToast = ({
|
export const TransferStatusToast = ({
|
||||||
|
type,
|
||||||
toAmount,
|
toAmount,
|
||||||
triggeredAt = Date.now(),
|
triggeredAt = Date.now(),
|
||||||
status,
|
status,
|
||||||
@@ -38,11 +39,6 @@ export const TransferStatusToast = ({
|
|||||||
// @ts-ignore status.errors is not in the type definition but can be returned
|
// @ts-ignore status.errors is not in the type definition but can be returned
|
||||||
const error = status?.errors?.length ? status?.errors[0] : status?.error;
|
const error = status?.errors?.length ? status?.errors[0] : status?.error;
|
||||||
|
|
||||||
const type = useMemo(
|
|
||||||
() => (status?.toChain?.chainData?.chainId === TESTNET_CHAIN_ID ? 'deposit' : 'withdrawal'),
|
|
||||||
[status]
|
|
||||||
);
|
|
||||||
|
|
||||||
const updateSecondsLeft = useCallback(() => {
|
const updateSecondsLeft = useCallback(() => {
|
||||||
const fromChainEta = (status?.fromChain?.chainData?.estimatedRouteDuration || 0) * 1000;
|
const fromChainEta = (status?.fromChain?.chainData?.estimatedRouteDuration || 0) * 1000;
|
||||||
const toChainEta = (status?.toChain?.chainData?.estimatedRouteDuration || 0) * 1000;
|
const toChainEta = (status?.toChain?.chainData?.estimatedRouteDuration || 0) * 1000;
|
||||||
@@ -53,6 +49,15 @@ export const TransferStatusToast = ({
|
|||||||
|
|
||||||
if (!status) return <LoadingDots size={3} />;
|
if (!status) return <LoadingDots size={3} />;
|
||||||
|
|
||||||
|
const statusString =
|
||||||
|
type === 'deposit'
|
||||||
|
? status?.squidTransactionStatus === 'success'
|
||||||
|
? STRING_KEYS.DEPOSIT_COMPLETE
|
||||||
|
: STRING_KEYS.DEPOSIT_STATUS
|
||||||
|
: status?.squidTransactionStatus === 'success'
|
||||||
|
? STRING_KEYS.WITHDRAW_COMPLETE
|
||||||
|
: STRING_KEYS.WITHDRAW_STATUS;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Styled.Root open={open} onOpenChange={setOpen}>
|
<Styled.Root open={open} onOpenChange={setOpen}>
|
||||||
<WithReceipt
|
<WithReceipt
|
||||||
@@ -60,14 +65,14 @@ export const TransferStatusToast = ({
|
|||||||
side="bottom"
|
side="bottom"
|
||||||
slotReceipt={
|
slotReceipt={
|
||||||
<Styled.Receipt>
|
<Styled.Receipt>
|
||||||
<TransferStatusSteps status={status} />
|
<TransferStatusSteps status={status} type={type} />
|
||||||
</Styled.Receipt>
|
</Styled.Receipt>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Styled.BridgingStatus>
|
<Styled.BridgingStatus>
|
||||||
<Styled.Status>
|
<Styled.Status>
|
||||||
{stringGetter({
|
{stringGetter({
|
||||||
key: type === 'deposit' ? STRING_KEYS.DEPOSIT_STATUS : STRING_KEYS.WITHDRAW_STATUS,
|
key: statusString,
|
||||||
params: {
|
params: {
|
||||||
AMOUNT_USD: <Styled.InlineOutput type={OutputType.Fiat} value={toAmount} />,
|
AMOUNT_USD: <Styled.InlineOutput type={OutputType.Fiat} value={toAmount} />,
|
||||||
ESTIMATED_DURATION: (
|
ESTIMATED_DURATION: (
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import styled, { css, keyframes, type AnyStyledComponent } from 'styled-components';
|
import styled, { css, keyframes, type AnyStyledComponent } from 'styled-components';
|
||||||
import { StatusResponse } from '@0xsquid/sdk';
|
import { StatusResponse } from '@0xsquid/sdk';
|
||||||
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
|
|
||||||
|
|
||||||
import { useStringGetter } from '@/hooks';
|
import { useStringGetter } from '@/hooks';
|
||||||
|
|
||||||
@@ -15,6 +14,7 @@ import { STRING_KEYS } from '@/constants/localization';
|
|||||||
|
|
||||||
type ElementProps = {
|
type ElementProps = {
|
||||||
status?: StatusResponse;
|
status?: StatusResponse;
|
||||||
|
type: 'withdrawal' | 'deposit';
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TransferStatusStep {
|
enum TransferStatusStep {
|
||||||
@@ -24,14 +24,13 @@ enum TransferStatusStep {
|
|||||||
Complete,
|
Complete,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TransferStatusSteps = ({ status }: ElementProps) => {
|
export const TransferStatusSteps = ({ status, type }: ElementProps) => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
|
|
||||||
const { currentStep, steps, type } = useMemo(() => {
|
const { currentStep, steps } = useMemo(() => {
|
||||||
const routeStatus = status?.routeStatus;
|
const routeStatus = status?.routeStatus;
|
||||||
const fromChain = status?.fromChain?.chainData?.chainId;
|
const fromChain = status?.fromChain?.chainData?.chainId;
|
||||||
const toChain = status?.toChain?.chainData?.chainId;
|
const toChain = status?.toChain?.chainData?.chainId;
|
||||||
const type = toChain === TESTNET_CHAIN_ID ? 'deposit' : 'withdrawal';
|
|
||||||
|
|
||||||
const steps = [
|
const steps = [
|
||||||
{
|
{
|
||||||
@@ -51,7 +50,7 @@ export const TransferStatusSteps = ({ status }: ElementProps) => {
|
|||||||
label: stringGetter({
|
label: stringGetter({
|
||||||
key: type === 'deposit' ? STRING_KEYS.DEPOSIT_TO_CHAIN : STRING_KEYS.WITHDRAW_TO_CHAIN,
|
key: type === 'deposit' ? STRING_KEYS.DEPOSIT_TO_CHAIN : STRING_KEYS.WITHDRAW_TO_CHAIN,
|
||||||
params: {
|
params: {
|
||||||
CHAIN: status?.toChain?.chainData?.chainName,
|
CHAIN: type === 'deposit' ? 'dYdX' : status?.toChain?.chainData?.chainName,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
step: TransferStatusStep.ToChain,
|
step: TransferStatusStep.ToChain,
|
||||||
@@ -74,6 +73,10 @@ export const TransferStatusSteps = ({ status }: ElementProps) => {
|
|||||||
currentStep = TransferStatusStep.FromChain;
|
currentStep = TransferStatusStep.FromChain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status?.squidTransactionStatus === 'success') {
|
||||||
|
currentStep = TransferStatusStep.Complete;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentStep,
|
currentStep,
|
||||||
steps,
|
steps,
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ export const DepthChart = ({
|
|||||||
// Chart data
|
// Chart data
|
||||||
|
|
||||||
const orderbook = useSelector(getCurrentMarketOrderbook, shallowEqual);
|
const orderbook = useSelector(getCurrentMarketOrderbook, shallowEqual);
|
||||||
const { symbol = '' } = useSelector(getCurrentMarketAssetData, shallowEqual) ?? {};
|
const { id = '' } = useSelector(getCurrentMarketAssetData, shallowEqual) ?? {};
|
||||||
const { stepSizeDecimals, tickSizeDecimals } =
|
const { stepSizeDecimals, tickSizeDecimals } =
|
||||||
useSelector(getCurrentMarketConfig, shallowEqual) ?? {};
|
useSelector(getCurrentMarketConfig, shallowEqual) ?? {};
|
||||||
|
|
||||||
@@ -393,7 +393,7 @@ export const DepthChart = ({
|
|||||||
? chartPointAtPointer.size
|
? chartPointAtPointer.size
|
||||||
: tooltipData!.nearestDatum?.datum.depth
|
: tooltipData!.nearestDatum?.datum.depth
|
||||||
}
|
}
|
||||||
tag={symbol}
|
tag={id}
|
||||||
accentColor={
|
accentColor={
|
||||||
{
|
{
|
||||||
[DepthChartSeries.Asks]: 'var(--color-negative)',
|
[DepthChartSeries.Asks]: 'var(--color-negative)',
|
||||||
@@ -476,7 +476,7 @@ export const DepthChart = ({
|
|||||||
type={OutputType.Asset}
|
type={OutputType.Asset}
|
||||||
value={chartPointAtPointer.size}
|
value={chartPointAtPointer.size}
|
||||||
fractionDigits={stepSizeDecimals}
|
fractionDigits={stepSizeDecimals}
|
||||||
tag={symbol}
|
tag={id}
|
||||||
useGrouping={false}
|
useGrouping={false}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -543,7 +543,7 @@ export const DepthChart = ({
|
|||||||
type={OutputType.Asset}
|
type={OutputType.Asset}
|
||||||
value={nearestDatum?.datum.depth}
|
value={nearestDatum?.datum.depth}
|
||||||
fractionDigits={stepSizeDecimals}
|
fractionDigits={stepSizeDecimals}
|
||||||
tag={symbol}
|
tag={id}
|
||||||
useGrouping={false}
|
useGrouping={false}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -25,7 +25,11 @@ 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 { getSubaccount, getSubaccountHistoricalPnl, getSubaccountId } from '@/state/accountSelectors';
|
import {
|
||||||
|
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';
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ type ElementProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const ClosePositionDialog = ({ setIsOpen }: ElementProps) => {
|
export const ClosePositionDialog = ({ setIsOpen }: ElementProps) => {
|
||||||
const { symbol } = useSelector(getCurrentMarketAssetData, shallowEqual) ?? {};
|
const { id } = useSelector(getCurrentMarketAssetData, shallowEqual) ?? {};
|
||||||
const { isTablet } = useBreakpoints();
|
const { isTablet } = useBreakpoints();
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ export const ClosePositionDialog = ({ setIsOpen }: ElementProps) => {
|
|||||||
} = {
|
} = {
|
||||||
[MobilePlaceOrderSteps.EditOrder]: {
|
[MobilePlaceOrderSteps.EditOrder]: {
|
||||||
title: <CloseOrderHeader />,
|
title: <CloseOrderHeader />,
|
||||||
slotIcon: <AssetIcon symbol={symbol} />,
|
slotIcon: <AssetIcon symbol={id} />,
|
||||||
},
|
},
|
||||||
[MobilePlaceOrderSteps.PreviewOrder]: {
|
[MobilePlaceOrderSteps.PreviewOrder]: {
|
||||||
title: (
|
title: (
|
||||||
|
|||||||
@@ -32,12 +32,9 @@ export const DepositDialog = ({ setIsOpen }: ElementProps) => {
|
|||||||
>
|
>
|
||||||
<Styled.Content>
|
<Styled.Content>
|
||||||
{showTestDeposit ? <TestnetDepositForm onDeposit={closeDialog} /> : <DepositForm />}
|
{showTestDeposit ? <TestnetDepositForm onDeposit={closeDialog} /> : <DepositForm />}
|
||||||
{/* TODO TRCL-1693 - uncomment when deposit form is ready */}
|
<Styled.TextToggle onClick={() => setShowTestDeposit(!showTestDeposit)}>
|
||||||
{import.meta.env.MODE !== 'production' && (
|
{showTestDeposit ? 'Show deposit form (Under Construction)' : 'Show test faucet'}
|
||||||
<Styled.TextToggle onClick={() => setShowTestDeposit(!showTestDeposit)}>
|
</Styled.TextToggle>
|
||||||
{showTestDeposit ? 'Show deposit form (Under Construction)' : 'Show test faucet'}
|
|
||||||
</Styled.TextToggle>
|
|
||||||
)}
|
|
||||||
</Styled.Content>
|
</Styled.Content>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { MustBigNumber } from '@/lib/numbers';
|
|||||||
|
|
||||||
type ElementProps = {
|
type ElementProps = {
|
||||||
fillId: string;
|
fillId: string;
|
||||||
setIsOpen?: (open: boolean) => void;
|
setIsOpen: (open: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FillDetailsDialog = ({ fillId, setIsOpen }: ElementProps) => {
|
export const FillDetailsDialog = ({ fillId, setIsOpen }: ElementProps) => {
|
||||||
@@ -94,7 +94,7 @@ export const FillDetailsDialog = ({ fillId, setIsOpen }: ElementProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DetailsDialog
|
<DetailsDialog
|
||||||
slotIcon={<Styled.AssetIcon symbol={asset.symbol} />}
|
slotIcon={<Styled.AssetIcon symbol={asset.id} />}
|
||||||
title={resources.typeStringKey && stringGetter({ key: resources.typeStringKey })}
|
title={resources.typeStringKey && stringGetter({ key: resources.typeStringKey })}
|
||||||
items={detailItems}
|
items={detailItems}
|
||||||
setIsOpen={setIsOpen}
|
setIsOpen={setIsOpen}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ export const OrderDetailsDialog = ({ orderId, setIsOpen }: ElementProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DetailsDialog
|
<DetailsDialog
|
||||||
slotIcon={<Styled.AssetIcon symbol={asset.symbol} />}
|
slotIcon={<Styled.AssetIcon symbol={asset.id} />}
|
||||||
title={!resources.typeStringKey ? '' : stringGetter({ key: resources.typeStringKey })}
|
title={!resources.typeStringKey ? '' : stringGetter({ key: resources.typeStringKey })}
|
||||||
slotFooter={
|
slotFooter={
|
||||||
isAccountViewOnly ? null : isOrderStatusClearable(status) ? (
|
isAccountViewOnly ? null : isOrderStatusClearable(status) ? (
|
||||||
|
|||||||