Compare commits
18
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1938feb66b | ||
|
|
2b105fb522 | ||
|
|
ea81d7a150 | ||
|
|
9a230401cd | ||
|
|
342bd2d334 | ||
|
|
cf68740725 | ||
|
|
1462e37c43 | ||
|
|
d99b0356e9 | ||
|
|
5cd9bb0fc5 | ||
|
|
986a134d07 | ||
|
|
ab454d5928 | ||
|
|
0f1491ac33 | ||
|
|
1f73f3a884 | ||
|
|
419d05a0e1 | ||
|
|
0c4b605666 | ||
|
|
710e5ac113 | ||
|
|
8fdac4dc09 | ||
|
|
4b86068d8f |
@@ -2,17 +2,5 @@ VITE_BASE_URL=https://v4.testnet.dydx.exchange
|
||||
|
||||
VITE_ALCHEMY_API_KEY=FP275q327Yh7qswtZWenbPXdZZdnAFmC
|
||||
|
||||
VITE_FAUCET_URL_DEV=https://faucet.v4dev.dydx.exchange/
|
||||
VITE_FAUCET_URL_STAGE=https://faucet.v4staging.dydx.exchange/
|
||||
VITE_FAUCET_URL_TESTNET2=https://faucet.v4testnet2.dydx.exchange/
|
||||
|
||||
VITE_VALIDATOR_URL_DEV=http://52.192.187.113:26657/
|
||||
VITE_VALIDATOR_URL_STAGE=https://validator.v4staging.dydx.exchange/
|
||||
VITE_VALIDATOR_URL_TESTNET2=https://validator.v4testnet2.dydx.exchange/
|
||||
|
||||
VITE_INDEXER_URL_DEV=http://dev-indexer-apne1-lb-public-890774175.ap-northeast-1.elb.amazonaws.com
|
||||
VITE_INDEXER_URL_STAGE=https://indexer.v4staging.dydx.exchange
|
||||
VITE_INDEXER_URL_TESTNET2=https://indexer.v4testnet2.dydx.exchange
|
||||
|
||||
VITE_WALLETCONNECT1_BRIDGE=wss://api.dydx.exchange/wc/
|
||||
VITE_WALLETCONNECT2_PROJECT_ID=fbe94eaa691fa8d929561f8567062b32
|
||||
|
||||
+3
-12
@@ -1,17 +1,8 @@
|
||||
VITE_BASE_URL=
|
||||
|
||||
VITE_ALCHEMY_API_KEY=
|
||||
|
||||
VITE_PK_ENCRYPTION_KEY=
|
||||
|
||||
VITE_WALLETCONNECT1_BRIDGE=
|
||||
VITE_WALLETCONNECT2_PROJECT_ID=
|
||||
|
||||
VITE_FAUCET_URL_DEV=
|
||||
VITE_FAUCET_URL_STAGE=
|
||||
VITE_FAUCET_URL_TESTNET2=
|
||||
|
||||
VITE_VALIDATOR_URL_DEV=
|
||||
VITE_VALIDATOR_URL_STAGE=
|
||||
VITE_VALIDATOR_URL_TESTNET2=
|
||||
|
||||
VITE_INDEXER_URL_DEV=
|
||||
VITE_INDEXER_URL_STAGE=
|
||||
VITE_INDEXER_URL_TESTNET2=
|
||||
|
||||
@@ -5,15 +5,10 @@ vite.config.ts
|
||||
|
||||
# Temporarily ignore, we will slowly remove each directory as we fix files to follow ESLint rules
|
||||
/src/components
|
||||
/src/dialogs
|
||||
/src/forms
|
||||
/src/hooks
|
||||
/src/history.ts
|
||||
/src/icons
|
||||
/src/lib
|
||||
/src/main.tsx
|
||||
/src/menus
|
||||
/src/pages
|
||||
/src/state
|
||||
/src/styles
|
||||
/src/views
|
||||
|
||||
+4
-6
@@ -33,14 +33,11 @@
|
||||
"jsx-a11y/anchor-is-valid": "off",
|
||||
"jsx-a11y/click-events-have-key-events": "off",
|
||||
"no-continue": "off",
|
||||
"no-console": [
|
||||
"error",
|
||||
{
|
||||
"devDependencies": ["./scripts/*.js"]
|
||||
}
|
||||
],
|
||||
"no-console": ["error"],
|
||||
"no-lonely-if": "off",
|
||||
"no-multi-assign": "off",
|
||||
"no-nested-ternary": "off",
|
||||
"no-param-reassign": ["error", { "props": false }],
|
||||
"no-return-assign": "off",
|
||||
"no-return-await": "off",
|
||||
"no-underscore-dangle": "off",
|
||||
@@ -65,6 +62,7 @@
|
||||
"react/sort-comp": "off",
|
||||
"@typescript-eslint/no-use-before-define": "off",
|
||||
"@typescript-eslint/comma-dangle": "off",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/member-delimiter-style": [
|
||||
"error",
|
||||
{
|
||||
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
# Contributing to Trader-Fe
|
||||
# Contributing to V4-web
|
||||
We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's:
|
||||
|
||||
- Reporting a bug
|
||||
@@ -18,10 +18,10 @@ Pull requests are the best way to propose changes to the codebase (we use [Githu
|
||||
4. Issue that pull request!
|
||||
|
||||
## Any contributions you make will be under the same License
|
||||
When you submit code changes, your submissions are understood to be under the same [License](https://github.com/dydxprotocol/trader-fe/blob/master/LICENSE) that covers the project.
|
||||
When you submit code changes, your submissions are understood to be under the same [License](https://github.com/dydxprotocol/v4-web/blob/master/LICENSE) that covers the project.
|
||||
|
||||
## Report bugs using Github's [issues](https://github.com/dydxprotocol/trader-fe/issues)
|
||||
Report a bug by [opening a new issue](https://github.com/dydxprotocol/trader-fe/issues/new).
|
||||
## Report bugs using Github's [issues](https://github.com/dydxprotocol/v4-web/issues)
|
||||
Report a bug by [opening a new issue](https://github.com/dydxprotocol/v4-web/issues/new).
|
||||
|
||||
**Great Bug Reports** tend to have:
|
||||
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
Business Source License 1.1
|
||||
License text copyright © 2023 MariaDB plc, All Rights Reserved. “Business Source License” is a trademark of MariaDB plc.
|
||||
Copyright (C) 2023 dYdX Trading Inc.
|
||||
Subject to your compliance with applicable law, you are granted the right to use the Licensed Work (defined below) under the terms of the below licenses; provided, however, that if you violate any such applicable law in your use of the Licensed Work, all of your rights and licenses to use (including any rights to reproduce, distribute, install or modify) the Licensed Work will automatically and immediately terminate.
|
||||
|
||||
Use of this software before the Change Date specified in the LICENSE file is governed by the Business Source License included in the LICENSE file and at https://spdx.org/licenses/BUSL-1.1.html.
|
||||
|
||||
On and after the Change Date specified in the LICENSE file, use of this software will be governed by the Change License (GNU Affero GPL v3) as specified in the LICENSE file.
|
||||
|
||||
|
||||
Business Source License 1.1
|
||||
Business Source License text copyright © 2023 MariaDB plc, All Rights Reserved. “Business Source License” is a trademark of MariaDB plc.
|
||||
Copyright (C) 2023 dYdX Trading Inc.
|
||||
|
||||
Parameters
|
||||
Licensor: dYdX Trading Inc.
|
||||
Licensed Work: dydxprotocol/cosmos-sdk, dydxprotocol/cometbft, dydxprotocol/v4-chain, dydxprotocol/v4-clients, dydxprotocol/v4-web, dydxprotocol/v4-abacus, dydxprotocol/v4-localization, dydxprotocol/v4-documentation, and any dYdX or dYdX Trading Inc. github repository reflecting a copy of this license, or link to this license.
|
||||
Additional Use Grant: None
|
||||
Change Date: On the later to occur of (i) the release of the Licensed Work labeled “dYdX Version 1.0 GPL”, and which includes a document uploaded to the relevant github repository stating “The software in this repository is Version 1.0, subject to GPL license”, and (ii) September 30, 2023 (approximate projected release of “Version 1.0” of this software).
|
||||
Change Date: On the later to occur of (i) the release of the Licensed Work labeled “dYdX Version 1.0 Affero GPL”, and which includes a document uploaded to the relevant github repository stating “The software in this repository is Version 1.0, subject to Affero GPL license”, and (ii) September 30, 2023 (approximate projected release of “Version 1.0” of this software).
|
||||
Change License: GNU Affero GPL License v3
|
||||
|
||||
License text copyright © 2023 MariaDB plc, All Rights Reserved. “Business Source License” is a trademark of MariaDB plc.
|
||||
@@ -39,7 +42,7 @@ OPEN SOURCE LICENSE BELOW - TO BE APPLIED AFTER THE CHANGE DATE.
|
||||
|
||||
Copyright (C) 2023 dYdX Trading Inc.
|
||||
|
||||
Use of this software is governed by the The GNU Affero General Public License as set forth below.
|
||||
Subject to your compliance with applicable law, you are granted the right to use the Licensed Work (defined below) under the terms of the GNU Affero General Public License as set forth below; provided, however, that if you violate any such applicable law in your use of the Licensed Work, all of your rights and licenses to use (including any rights to reproduce, distribute, install or modify) the Licensed Work will automatically and immediately terminate.
|
||||
|
||||
|
||||
The GNU Affero General Public License
|
||||
@@ -835,4 +838,4 @@ copy of the Program in return for a fee.
|
||||
|
||||
|
||||
For more information about this software, see https://dydx.exchange.
|
||||
Copyright (C) 2023 dYdX Trading Inc.
|
||||
Copyright (C) 2023 dYdX Trading Inc.
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
# v4 Web App
|
||||
<p align="center"><img src="https://dydx.exchange/icon.svg?" width="256" /></p>
|
||||
|
||||
<h1 align="center">v4 Web</h1>
|
||||
|
||||
<div align="center">
|
||||
<a href='https://github.com/dydxprotocol/v4-web/blob/main/LICENSE'>
|
||||
<img src='https://img.shields.io/badge/License-BSL_1.1-blue' alt='License' />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -22,8 +30,8 @@ Alternatively, follow the [IPFS Kubo installation guide](https://docs.ipfs.tech
|
||||
Clone the repository and navigate to its directory:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/dydxprotocol/trader-fe.git
|
||||
cd trader-fe
|
||||
git clone https://github.com/dydxprotocol/v4-web.git
|
||||
cd v4-web
|
||||
```
|
||||
|
||||
### Step 2: Install pnpm and dependencies
|
||||
|
||||
+3
-3
@@ -37,9 +37,9 @@
|
||||
"@cosmjs/proto-signing": "^0.31.0",
|
||||
"@cosmjs/stargate": "^0.31.0",
|
||||
"@cosmjs/tendermint-rpc": "^0.31.0",
|
||||
"@dydxprotocol/abacus": "^0.4.8",
|
||||
"@dydxprotocol/v4-client-js": "^0.32.0",
|
||||
"@dydxprotocol/v4-localization": "^0.0.25",
|
||||
"@dydxprotocol/v4-abacus": "^0.4.28",
|
||||
"@dydxprotocol/v4-client-js": "^0.36.1",
|
||||
"@dydxprotocol/v4-localization": "^0.1.8",
|
||||
"@ethersproject/providers": "^5.7.2",
|
||||
"@js-joda/core": "^5.5.3",
|
||||
"@radix-ui/react-collapsible": "^1.0.3",
|
||||
|
||||
Generated
+36
-242
@@ -26,15 +26,15 @@ dependencies:
|
||||
'@cosmjs/tendermint-rpc':
|
||||
specifier: ^0.31.0
|
||||
version: 0.31.0
|
||||
'@dydxprotocol/abacus':
|
||||
specifier: ^0.4.8
|
||||
version: 0.4.8
|
||||
'@dydxprotocol/v4-abacus':
|
||||
specifier: ^0.4.28
|
||||
version: 0.4.28
|
||||
'@dydxprotocol/v4-client-js':
|
||||
specifier: ^0.32.0
|
||||
version: 0.32.0
|
||||
specifier: ^0.36.1
|
||||
version: 0.36.1
|
||||
'@dydxprotocol/v4-localization':
|
||||
specifier: ^0.0.25
|
||||
version: 0.0.25
|
||||
specifier: ^0.1.8
|
||||
version: 0.1.8
|
||||
'@ethersproject/providers':
|
||||
specifier: ^5.7.2
|
||||
version: 5.7.2
|
||||
@@ -614,74 +614,6 @@ packages:
|
||||
'@babel/helper-validator-identifier': 7.22.5
|
||||
to-fast-properties: 2.0.0
|
||||
|
||||
/@bufbuild/buf-darwin-arm64@1.19.0-1:
|
||||
resolution: {integrity: sha512-HsWPii21wm3QSyuxrNq9+Yf8iAgpnC4rNCy4x3d6P1fd/LmgE1NPzQW0ghEZvl9dgAQKkL/4S5bKhlm7kbUdmQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@bufbuild/buf-darwin-x64@1.19.0-1:
|
||||
resolution: {integrity: sha512-2+Ig7ylYpVh4kms/OeJJVY+X0KX4awPA6hYr7L7aZOIcHwZEM8lWtSTO/se5pQc7dc8FXNiC4YUqHC8yfxxX6Q==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@bufbuild/buf-linux-aarch64@1.19.0-1:
|
||||
resolution: {integrity: sha512-g/Vxg3WiBr3nhsxsRr2Q81xXJD+0ktHIO3ZJggTG2Sbbl3dh8kyg1iKM6MjJiMP7su5RKCylLigzoEJzVTShyA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@bufbuild/buf-linux-x64@1.19.0-1:
|
||||
resolution: {integrity: sha512-anYuGx8k/2kp8GPX3eHNUf3IY/01Zpnyw0HaLPXK1Btqyy6XkapVywrDqg7YUzMd1ySFEp1wD9UqRNdEFNCQ4A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@bufbuild/buf-win32-arm64@1.19.0-1:
|
||||
resolution: {integrity: sha512-xXgF1qYnCfRKbGx1FqvPbpZ6ajh4ddxpXhSxI3VCeb3MsMBuIbiLqX4fQAL3ls/Zwz8tVIITuSwOhYmSEGcpBA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@bufbuild/buf-win32-x64@1.19.0-1:
|
||||
resolution: {integrity: sha512-futmqgpMQCR1lcAzZJEGjPr7ECw1gYTPIV8crm5SY+iCJ7sOeStOBNt7q5hV4LKmmeWmvm03XIMZPjhQzjH5NQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@bufbuild/buf@1.19.0-1:
|
||||
resolution: {integrity: sha512-TIsLTTQUntr/Xq/IMSULv3dlC3/ZsVwQtWgxmJ++IzSuOW79TFQfq59vFeTWrPa6+QXFMz5t6jkMyD4ghzO5nw==}
|
||||
engines: {node: '>=12'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
optionalDependencies:
|
||||
'@bufbuild/buf-darwin-arm64': 1.19.0-1
|
||||
'@bufbuild/buf-darwin-x64': 1.19.0-1
|
||||
'@bufbuild/buf-linux-aarch64': 1.19.0-1
|
||||
'@bufbuild/buf-linux-x64': 1.19.0-1
|
||||
'@bufbuild/buf-win32-arm64': 1.19.0-1
|
||||
'@bufbuild/buf-win32-x64': 1.19.0-1
|
||||
dev: false
|
||||
|
||||
/@coinbase/wallet-sdk@3.7.1:
|
||||
resolution: {integrity: sha512-LjyoDCB+7p0waQXfK+fUgcAs3Ezk6S6e+LYaoFjpJ6c9VTop3NyZF40Pi7df4z7QJohCwzuIDjz0Rhtig6Y7Pg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
@@ -726,15 +658,6 @@ packages:
|
||||
'@cosmjs/utils': 0.27.1
|
||||
dev: false
|
||||
|
||||
/@cosmjs/amino@0.29.3:
|
||||
resolution: {integrity: sha512-BFz1++ERerIggiFc7iGHhGe1CeV3rCv8BvkoBQTBN/ZwzHOaKvqQj8smDlRGlQxX3HWlTwgiLN2A+OB5yX4ZRw==}
|
||||
dependencies:
|
||||
'@cosmjs/crypto': 0.29.5
|
||||
'@cosmjs/encoding': 0.29.5
|
||||
'@cosmjs/math': 0.29.5
|
||||
'@cosmjs/utils': 0.29.5
|
||||
dev: false
|
||||
|
||||
/@cosmjs/amino@0.30.1:
|
||||
resolution: {integrity: sha512-yNHnzmvAlkETDYIpeCTdVqgvrdt1qgkOXwuRVi8s27UKI5hfqyE9fJ/fuunXE6ZZPnKkjIecDznmuUOMrMvw4w==}
|
||||
dependencies:
|
||||
@@ -788,18 +711,6 @@ packages:
|
||||
sha.js: 2.4.11
|
||||
dev: false
|
||||
|
||||
/@cosmjs/crypto@0.29.5:
|
||||
resolution: {integrity: sha512-2bKkaLGictaNL0UipQCL6C1afaisv6k8Wr/GCLx9FqiyFkh9ZgRHDyetD64ZsjnWV/N/D44s/esI+k6oPREaiQ==}
|
||||
dependencies:
|
||||
'@cosmjs/encoding': 0.29.5
|
||||
'@cosmjs/math': 0.29.5
|
||||
'@cosmjs/utils': 0.29.5
|
||||
'@noble/hashes': 1.3.1
|
||||
bn.js: 5.2.1
|
||||
elliptic: 6.5.4
|
||||
libsodium-wrappers: 0.7.11
|
||||
dev: false
|
||||
|
||||
/@cosmjs/crypto@0.30.1:
|
||||
resolution: {integrity: sha512-rAljUlake3MSXs9xAm87mu34GfBLN0h/1uPPV6jEwClWjNkAMotzjC0ab9MARy5FFAvYHL3lWb57bhkbt2GtzQ==}
|
||||
dependencies:
|
||||
@@ -832,14 +743,6 @@ packages:
|
||||
readonly-date: 1.0.0
|
||||
dev: false
|
||||
|
||||
/@cosmjs/encoding@0.29.5:
|
||||
resolution: {integrity: sha512-G4rGl/Jg4dMCw5u6PEZHZcoHnUBlukZODHbm/wcL4Uu91fkn5jVo5cXXZcvs4VCkArVGrEj/52eUgTZCmOBGWQ==}
|
||||
dependencies:
|
||||
base64-js: 1.5.1
|
||||
bech32: 1.1.4
|
||||
readonly-date: 1.0.0
|
||||
dev: false
|
||||
|
||||
/@cosmjs/encoding@0.30.1:
|
||||
resolution: {integrity: sha512-rXmrTbgqwihORwJ3xYhIgQFfMSrwLu1s43RIK9I8EBudPx3KmnmyAKzMOVsRDo9edLFNuZ9GIvysUCwQfq3WlQ==}
|
||||
dependencies:
|
||||
@@ -856,11 +759,12 @@ packages:
|
||||
readonly-date: 1.0.0
|
||||
dev: false
|
||||
|
||||
/@cosmjs/json-rpc@0.29.5:
|
||||
resolution: {integrity: sha512-C78+X06l+r9xwdM1yFWIpGl03LhB9NdM1xvZpQHwgCOl0Ir/WV8pw48y3Ez2awAoUBRfTeejPe4KvrE6NoIi/w==}
|
||||
/@cosmjs/encoding@0.31.1:
|
||||
resolution: {integrity: sha512-IuxP6ewwX6vg9sUJ8ocJD92pkerI4lyG8J5ynAM3NaX3q+n+uMoPRSQXNeL9bnlrv01FF1kIm8if/f5F7ZPtkA==}
|
||||
dependencies:
|
||||
'@cosmjs/stream': 0.29.5
|
||||
xstream: 11.14.0
|
||||
base64-js: 1.5.1
|
||||
bech32: 1.1.4
|
||||
readonly-date: 1.0.0
|
||||
dev: false
|
||||
|
||||
/@cosmjs/json-rpc@0.30.1:
|
||||
@@ -897,12 +801,6 @@ packages:
|
||||
bn.js: 5.2.1
|
||||
dev: false
|
||||
|
||||
/@cosmjs/math@0.29.5:
|
||||
resolution: {integrity: sha512-2GjKcv+A9f86MAWYLUkjhw1/WpRl2R1BTb3m9qPG7lzMA7ioYff9jY5SPCfafKdxM4TIQGxXQlYGewQL16O68Q==}
|
||||
dependencies:
|
||||
bn.js: 5.2.1
|
||||
dev: false
|
||||
|
||||
/@cosmjs/math@0.30.1:
|
||||
resolution: {integrity: sha512-yaoeI23pin9ZiPHIisa6qqLngfnBR/25tSaWpkTm8Cy10MX70UF5oN4+/t1heLaM6SSmRrhk3psRkV4+7mH51Q==}
|
||||
dependencies:
|
||||
@@ -915,16 +813,10 @@ packages:
|
||||
bn.js: 5.2.1
|
||||
dev: false
|
||||
|
||||
/@cosmjs/proto-signing@0.29.3:
|
||||
resolution: {integrity: sha512-Ai3l9THjMOrLJ4Ebn1Dgptwg6W5ZIRJqtnJjijHhGwTVC1WT0WdYU3aMZ7+PwubcA/cA1rH4ZTK7jrfYbra63g==}
|
||||
/@cosmjs/math@0.31.1:
|
||||
resolution: {integrity: sha512-kiuHV6m6DSB8/4UV1qpFhlc4ul8SgLXTGRlYkYiIIP4l0YNeJ+OpPYaOlEgx4Unk2mW3/O2FWYj7Jc93+BWXng==}
|
||||
dependencies:
|
||||
'@cosmjs/amino': 0.29.3
|
||||
'@cosmjs/crypto': 0.29.5
|
||||
'@cosmjs/encoding': 0.29.5
|
||||
'@cosmjs/math': 0.29.5
|
||||
'@cosmjs/utils': 0.29.5
|
||||
cosmjs-types: 0.5.2
|
||||
long: 4.0.0
|
||||
bn.js: 5.2.1
|
||||
dev: false
|
||||
|
||||
/@cosmjs/proto-signing@0.30.1:
|
||||
@@ -951,18 +843,6 @@ packages:
|
||||
long: 4.0.0
|
||||
dev: false
|
||||
|
||||
/@cosmjs/socket@0.29.5:
|
||||
resolution: {integrity: sha512-5VYDupIWbIXq3ftPV1LkS5Ya/T7Ol/AzWVhNxZ79hPe/mBfv1bGau/LqIYOm2zxGlgm9hBHOTmWGqNYDwr9LNQ==}
|
||||
dependencies:
|
||||
'@cosmjs/stream': 0.29.5
|
||||
isomorphic-ws: 4.0.1(ws@7.5.9)
|
||||
ws: 7.5.9
|
||||
xstream: 11.14.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/@cosmjs/socket@0.30.1:
|
||||
resolution: {integrity: sha512-r6MpDL+9N+qOS/D5VaxnPaMJ3flwQ36G+vPvYJsXArj93BjgyFB7BwWwXCQDzZ+23cfChPUfhbINOenr8N2Kow==}
|
||||
dependencies:
|
||||
@@ -987,27 +867,6 @@ packages:
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/@cosmjs/stargate@0.29.3:
|
||||
resolution: {integrity: sha512-455TgXStCi6E8KDjnhDAM8wt6aLSjobH4Dixvd7Up1DfCH6UB9NkC/G0fMJANNcNXMaM4wSX14niTXwD1d31BA==}
|
||||
dependencies:
|
||||
'@confio/ics23': 0.6.8
|
||||
'@cosmjs/amino': 0.29.3
|
||||
'@cosmjs/encoding': 0.29.5
|
||||
'@cosmjs/math': 0.29.5
|
||||
'@cosmjs/proto-signing': 0.29.3
|
||||
'@cosmjs/stream': 0.29.5
|
||||
'@cosmjs/tendermint-rpc': 0.29.5
|
||||
'@cosmjs/utils': 0.29.5
|
||||
cosmjs-types: 0.5.2
|
||||
long: 4.0.0
|
||||
protobufjs: 6.11.4
|
||||
xstream: 11.14.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- debug
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/@cosmjs/stargate@0.30.1:
|
||||
resolution: {integrity: sha512-RdbYKZCGOH8gWebO7r6WvNnQMxHrNXInY/gPHPzMjbQF6UatA6fNM2G2tdgS5j5u7FTqlCI10stNXrknaNdzog==}
|
||||
dependencies:
|
||||
@@ -1050,12 +909,6 @@ packages:
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/@cosmjs/stream@0.29.5:
|
||||
resolution: {integrity: sha512-TToTDWyH1p05GBtF0Y8jFw2C+4783ueDCmDyxOMM6EU82IqpmIbfwcdMOCAm0JhnyMh+ocdebbFvnX/sGKzRAA==}
|
||||
dependencies:
|
||||
xstream: 11.14.0
|
||||
dev: false
|
||||
|
||||
/@cosmjs/stream@0.30.1:
|
||||
resolution: {integrity: sha512-Fg0pWz1zXQdoxQZpdHRMGvUH5RqS6tPv+j9Eh7Q953UjMlrwZVo0YFLC8OTf/HKVf10E4i0u6aM8D69Q6cNkgQ==}
|
||||
dependencies:
|
||||
@@ -1068,25 +921,6 @@ packages:
|
||||
xstream: 11.14.0
|
||||
dev: false
|
||||
|
||||
/@cosmjs/tendermint-rpc@0.29.5:
|
||||
resolution: {integrity: sha512-ar80twieuAxsy0x2za/aO3kBr2DFPAXDmk2ikDbmkda+qqfXgl35l9CVAAjKRqd9d+cRvbQyb5M4wy6XQpEV6w==}
|
||||
dependencies:
|
||||
'@cosmjs/crypto': 0.29.5
|
||||
'@cosmjs/encoding': 0.29.5
|
||||
'@cosmjs/json-rpc': 0.29.5
|
||||
'@cosmjs/math': 0.29.5
|
||||
'@cosmjs/socket': 0.29.5
|
||||
'@cosmjs/stream': 0.29.5
|
||||
'@cosmjs/utils': 0.29.5
|
||||
axios: 0.21.4
|
||||
readonly-date: 1.0.0
|
||||
xstream: 11.14.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- debug
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/@cosmjs/tendermint-rpc@0.30.1:
|
||||
resolution: {integrity: sha512-Z3nCwhXSbPZJ++v85zHObeUggrEHVfm1u18ZRwXxFE9ZMl5mXTybnwYhczuYOl7KRskgwlB+rID0WYACxj4wdQ==}
|
||||
dependencies:
|
||||
@@ -1129,10 +963,6 @@ packages:
|
||||
resolution: {integrity: sha512-VG7QPDiMUzVPxRdJahDV8PXxVdnuAHiIuG56hldV4yPnOz/si/DLNd7VAUUA5923b6jS1Hhev0Hr6AhEkcxBMg==}
|
||||
dev: false
|
||||
|
||||
/@cosmjs/utils@0.29.5:
|
||||
resolution: {integrity: sha512-m7h+RXDUxOzEOGt4P+3OVPX7PuakZT3GBmaM/Y2u+abN3xZkziykD/NvedYFvvCCdQo714XcGl33bwifS9FZPQ==}
|
||||
dev: false
|
||||
|
||||
/@cosmjs/utils@0.30.1:
|
||||
resolution: {integrity: sha512-KvvX58MGMWh7xA+N+deCfunkA/ZNDvFLw4YbOmX3f/XBIkqrVY7qlotfy2aNb1kgp6h4B6Yc8YawJPDTfvWX7g==}
|
||||
dev: false
|
||||
@@ -1141,39 +971,29 @@ packages:
|
||||
resolution: {integrity: sha512-nNcycZWUYLNJlrIXgpcgVRqdl6BXjF4YlXdxobQWpW9Tikk61bEGeAFhDYtC0PwHlokCNw0KxWiHGJL4nL7Q5A==}
|
||||
dev: false
|
||||
|
||||
/@cosmjs/utils@0.31.1:
|
||||
resolution: {integrity: sha512-n4Se1wu4GnKwztQHNFfJvUeWcpvx3o8cWhSbNs9JQShEuB3nv3R5lqFBtDCgHZF/emFQAP+ZjF8bTfCs9UBGhA==}
|
||||
dev: false
|
||||
|
||||
/@cush/relative@1.0.0:
|
||||
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
||||
dev: true
|
||||
|
||||
/@dydxprotocol/abacus@0.4.8:
|
||||
resolution: {integrity: sha512-hX31m+a5Bwbs4dr5raPDtnflwUzEu/9BIt+LOlQgt1YOViuIse8dozgpgCHvqvA8MttqY3QGPalx5iRB8j8vtw==}
|
||||
/@dydxprotocol/v4-abacus@0.4.28:
|
||||
resolution: {integrity: sha512-RQGTXI7q4HAXDmlUpDhpJDLN8C0dFMgKHzFITK1Sz3KnLb3mkkpqEU1D8VIn/hB7ngt+equMsLFSkUwzXCzgdA==}
|
||||
dev: false
|
||||
|
||||
/@dydxprotocol/dydxjs@0.3.0:
|
||||
resolution: {integrity: sha512-ygNeBs0f3H7sJk1qLUjfNwaXgc5TmjD+qZf7BFDbi7+boHJI9xuOWrGpjfBo7OTUZxS6O5jZG323CgU5XqMSPw==}
|
||||
/@dydxprotocol/v4-client-js@0.36.1:
|
||||
resolution: {integrity: sha512-KJ3MtWI61wmm+xZtXQd7/hYKIoVFG32TRdyyVaXXO8vpW9Oqd0JD8QSM/wuegkciAh5YmP/BrDzYuu77zHO6yg==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.10
|
||||
'@bufbuild/buf': 1.19.0-1
|
||||
'@cosmjs/amino': 0.30.1
|
||||
'@cosmjs/encoding': 0.31.1
|
||||
'@cosmjs/math': 0.31.1
|
||||
'@cosmjs/proto-signing': 0.30.1
|
||||
'@cosmjs/stargate': 0.30.1
|
||||
'@cosmjs/tendermint-rpc': 0.30.1
|
||||
osmojs: 15.5.0
|
||||
protobufjs: 6.11.4
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- debug
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/@dydxprotocol/v4-client-js@0.32.0:
|
||||
resolution: {integrity: sha512-KvKActMgWLcsRQ7RQhpi/F8xeQ7MWUp3G5+4IPNZ4wyRwAxDSbcrfYbTetI/IesHyelRPSeYxam9eYq3wXwZ1A==}
|
||||
dependencies:
|
||||
'@cosmjs/amino': 0.30.1
|
||||
'@cosmjs/proto-signing': 0.30.1
|
||||
'@cosmjs/stargate': 0.30.1
|
||||
'@cosmjs/tendermint-rpc': 0.30.1
|
||||
'@dydxprotocol/dydxjs': 0.3.0
|
||||
'@cosmjs/utils': 0.31.1
|
||||
'@dydxprotocol/v4-proto': 0.2.1
|
||||
'@osmonauts/lcd': 0.6.0
|
||||
'@scure/bip32': 1.3.1
|
||||
'@scure/bip39': 1.2.1
|
||||
@@ -1182,6 +1002,7 @@ packages:
|
||||
bignumber.js: 9.1.1
|
||||
ethereum-cryptography: 2.1.2
|
||||
long: 4.0.0
|
||||
protobufjs: 6.11.4
|
||||
ws: 8.13.0(bufferutil@4.0.7)(utf-8-validate@5.0.10)
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
@@ -1189,8 +1010,14 @@ packages:
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/@dydxprotocol/v4-localization@0.0.25:
|
||||
resolution: {integrity: sha512-Rp6VHA8z+nwgvTjjB3fvL8gY7bd4DYDHV+NPoL0MFuRm39vhFxGlBVAGDkXPkQTh6YU5BlZV2yXLkDeSfFqEBQ==}
|
||||
/@dydxprotocol/v4-localization@0.1.8:
|
||||
resolution: {integrity: sha512-ZuM/V2tLVSWyi9pDZLOu8h6HScrzKlFftQ/1iBPNIOU4bBMx83vYgokm0X9hzueWzz0PJ2pzT+EoN81sPlN2bg==}
|
||||
dev: false
|
||||
|
||||
/@dydxprotocol/v4-proto@0.2.1:
|
||||
resolution: {integrity: sha512-Q5b/g331DoyMjBpO2/jtrxUX3WF5UaIKZp/unK332xuefHNFnkMYtZ05p0V71iSdO35tBdz8yt0VYP2WtUsp+w==}
|
||||
dependencies:
|
||||
protobufjs: 6.11.4
|
||||
dev: false
|
||||
|
||||
/@emotion/is-prop-valid@1.2.1:
|
||||
@@ -2246,15 +2073,6 @@ packages:
|
||||
fastq: 1.15.0
|
||||
dev: true
|
||||
|
||||
/@osmonauts/lcd@0.10.0:
|
||||
resolution: {integrity: sha512-PzmXk9x9MHyLn2fUztpAqWqvDmMiEJaQv/JcAoAOE8VdHrD9Hf/KWnE1RZtamuS2ngQRqvQPD0xotCGXW7eTxA==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.10
|
||||
axios: 0.27.2
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
dev: false
|
||||
|
||||
/@osmonauts/lcd@0.6.0:
|
||||
resolution: {integrity: sha512-vz9VavXrEfxZoXbSAfNfk90MLpn34XtBYPV3L9YilE+s56AhqYxUh83nne9J5somnTRfGnyR3oeV8C+lHkqiuA==}
|
||||
dependencies:
|
||||
@@ -7787,13 +7605,6 @@ packages:
|
||||
path-type: 4.0.0
|
||||
dev: true
|
||||
|
||||
/cosmjs-types@0.5.2:
|
||||
resolution: {integrity: sha512-zxCtIJj8v3Di7s39uN4LNcN3HIE1z0B9Z0SPE8ZNQR0oSzsuSe1ACgxoFkvhkS7WBasCAFcglS11G2hyfd5tPg==}
|
||||
dependencies:
|
||||
long: 4.0.0
|
||||
protobufjs: 6.11.4
|
||||
dev: false
|
||||
|
||||
/cosmjs-types@0.7.2:
|
||||
resolution: {integrity: sha512-vf2uLyktjr/XVAgEq0DjMxeAWh1yYREe7AMHDKd7EiHVqxBPCaBS+qEEQUkXbR9ndnckqr1sUG8BQhazh4X5lA==}
|
||||
dependencies:
|
||||
@@ -11641,23 +11452,6 @@ packages:
|
||||
type-check: 0.4.0
|
||||
dev: true
|
||||
|
||||
/osmojs@15.5.0:
|
||||
resolution: {integrity: sha512-7wy3QEYu+R+c8imfLEPS1PliYA8uw0qdFYjc2PToHteYG4hzYt4Noa7X0lM9O59s7nxo9ozT1N9z7uwB/1qHkA==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.10
|
||||
'@cosmjs/amino': 0.29.3
|
||||
'@cosmjs/proto-signing': 0.29.3
|
||||
'@cosmjs/stargate': 0.29.3
|
||||
'@cosmjs/tendermint-rpc': 0.29.5
|
||||
'@osmonauts/lcd': 0.10.0
|
||||
long: 5.2.3
|
||||
protobufjs: 6.11.4
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- debug
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/p-defer@3.0.0:
|
||||
resolution: {integrity: sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
+6
-5
@@ -10,11 +10,11 @@ import { AppRoute, DEFAULT_TRADE_ROUTE } from '@/constants/routes';
|
||||
import { useBreakpoints, useInitializePage, useShouldShowFooter, useAnalytics } from '@/hooks';
|
||||
import { DydxProvider } from '@/hooks/useDydxClient';
|
||||
import { AccountsProvider } from '@/hooks/useAccounts';
|
||||
import { DialogAreaProvider, useDialogArea } from './hooks/useDialogArea';
|
||||
import { LocaleProvider } from './hooks/useLocaleSeparators';
|
||||
import { NotificationsProvider } from './hooks/useNotifications';
|
||||
import { LocalNotificationsProvider } from './hooks/useLocalNotifications';
|
||||
import { SubaccountProvider } from './hooks/useSubaccount';
|
||||
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
|
||||
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
|
||||
import { NotificationsProvider } from '@/hooks/useNotifications';
|
||||
import { LocalNotificationsProvider } from '@/hooks/useLocalNotifications';
|
||||
import { SubaccountProvider } from '@/hooks/useSubaccount';
|
||||
import { SquidProvider } from '@/hooks/useSquid';
|
||||
|
||||
import { GuardedMobileRoute } from '@/components/GuardedMobileRoute';
|
||||
@@ -100,6 +100,7 @@ const Content = () => {
|
||||
};
|
||||
|
||||
const wrapProvider = (Component: React.ComponentType<any>, props?: any) => {
|
||||
// eslint-disable-next-line react/display-name
|
||||
return ({ children }: { children: React.ReactNode }) => (
|
||||
<Component {...props}>{children}</Component>
|
||||
);
|
||||
|
||||
@@ -80,6 +80,8 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
|
||||
{group.items.map((item) => (
|
||||
<Fragment key={item.value}>
|
||||
<Styled.Item
|
||||
// value={item.value} // search by both value and textContent
|
||||
// value={[group.groupLabel, item.label, item.tag].filter(Boolean).join('|')} // exclude item.value from searchable terms (not guaranteed to be unique)
|
||||
value={[group.groupLabel, item.value, item.description, item.label, item.tag]
|
||||
.filter(Boolean)
|
||||
.join('|')}
|
||||
@@ -114,6 +116,8 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
|
||||
item.subitems?.map((subitem) => (
|
||||
<Fragment key={subitem.value}>
|
||||
<Styled.Item
|
||||
// value={subitem.value} // search by both value and textContent
|
||||
// value={[group.groupLabel, item.label, subitem.label, subitem.tag].filter(Boolean).join('|')}
|
||||
value={[
|
||||
group.groupLabel,
|
||||
item.value,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Abacus, { kollections } from '@dydxprotocol/abacus';
|
||||
import Abacus, { kollections } from '@dydxprotocol/v4-abacus';
|
||||
import { OrderSide } from '@dydxprotocol/v4-client-js';
|
||||
import { PositionSide, TradeTypes } from './trade';
|
||||
import { STRING_KEYS } from './localization';
|
||||
@@ -40,10 +40,7 @@ export type AbacusFileSystemProtocol = Omit<
|
||||
Abacus.exchange.dydx.abacus.protocols.FileSystemProtocol,
|
||||
'__doNotUseOrImplementIt'
|
||||
>;
|
||||
export type AbacusTrackingProtocol = Omit<
|
||||
Abacus.exchange.dydx.abacus.protocols.TrackingProtocol,
|
||||
'__doNotUseOrImplementIt'
|
||||
>;
|
||||
|
||||
export type FileLocation = Abacus.exchange.dydx.abacus.protocols.FileLocation;
|
||||
export type ThreadingType = Abacus.exchange.dydx.abacus.protocols.ThreadingType;
|
||||
export const CoroutineTimer = Abacus.exchange.dydx.abacus.utils.CoroutineTimer;
|
||||
|
||||
@@ -1,18 +1,5 @@
|
||||
/**
|
||||
* OnboardingSteps
|
||||
* 1. Choose between 3 options
|
||||
* a. Ethereum EOA (current)
|
||||
* b. Keplr or Other Cosmos (future)
|
||||
* c. Social (future)
|
||||
* 2. Key derivation
|
||||
* a. If wallet has no dYdX Chain transactions and not on whitelist, sign twice (future)
|
||||
* i. Success
|
||||
* ii. Signatures don't match error (Wallet is non-deterministic)
|
||||
* b. Success
|
||||
* 3. Post Registration items (Only on first onboarding)
|
||||
* a. Acknowledge Terms
|
||||
* b. DepositFunds
|
||||
*/
|
||||
import type { DydxAddress, EvmAddress } from './wallets';
|
||||
|
||||
export enum OnboardingSteps {
|
||||
ChooseWallet = 'ChooseWallet',
|
||||
KeyDerivation = 'KeyDerivation',
|
||||
@@ -49,14 +36,12 @@ export enum EvmDerivedAccountStatus {
|
||||
Derived,
|
||||
}
|
||||
|
||||
import type { DydxAddress, EvmAddress } from './wallets';
|
||||
|
||||
export type EvmDerivedAddresses = {
|
||||
version?: string;
|
||||
[EvmAddress: EvmAddress]: {
|
||||
encryptedSignature?: string;
|
||||
dydxAddress?: DydxAddress;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export const AMOUNT_RESERVED_FOR_GAS_USDC = 100_000;
|
||||
export const AMOUNT_RESERVED_FOR_GAS_USDC = 100_000;
|
||||
|
||||
@@ -1,36 +1,6 @@
|
||||
import { Asset, PerpetualMarket } from '@/constants/abacus';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
|
||||
export interface Market {
|
||||
market: string;
|
||||
status: string;
|
||||
baseAsset: string;
|
||||
quoteAsset: string;
|
||||
stepSize: string;
|
||||
tickSize: string;
|
||||
oraclePrice: string;
|
||||
priceChange24H: string;
|
||||
nextFundingRate: string;
|
||||
nextFundingAt: string;
|
||||
minOrderSize: string;
|
||||
type: string;
|
||||
initialMarginFraction: string;
|
||||
maintenanceMarginFraction: string;
|
||||
volume24H: string;
|
||||
trades24H: string;
|
||||
openInterest: string;
|
||||
incrementalInitialMarginFraction: string;
|
||||
incrementalPositionSize: string;
|
||||
maxPositionSize: string;
|
||||
baselinePositionSize: string;
|
||||
assetResolution: string;
|
||||
syntheticAssetId: string;
|
||||
}
|
||||
|
||||
export type AllMarkets = {
|
||||
[market: string]: Market;
|
||||
};
|
||||
|
||||
export type MarketData = {
|
||||
asset: Asset;
|
||||
tickSizeDecimals: number;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import type { StatusResponse } from '@0xsquid/sdk';
|
||||
import { StatusResponse } from '@0xsquid/sdk';
|
||||
|
||||
/** implemented in useNotificationTypes */
|
||||
export enum NotificationType {
|
||||
@@ -12,44 +11,39 @@ export enum NotificationComponentType {}
|
||||
export type NotificationId = string | number;
|
||||
|
||||
export type NotificationTypeConfig<
|
||||
_NotificationId extends NotificationId = string,
|
||||
NotificationIdType extends NotificationId = string,
|
||||
NotificationUpdateKey = any
|
||||
> = {
|
||||
type: NotificationType;
|
||||
|
||||
/** React hook to trigger notifications based on app state */
|
||||
useTrigger: (_: {
|
||||
trigger: ({
|
||||
id,
|
||||
displayData,
|
||||
updateKey,
|
||||
isNew,
|
||||
}: {
|
||||
trigger: (
|
||||
/** Unique ID for the triggered notification */
|
||||
id: _NotificationId;
|
||||
id: NotificationIdType,
|
||||
|
||||
/** Display data for the triggered notification */
|
||||
displayData: NotificationDisplayData;
|
||||
displayData: NotificationDisplayData,
|
||||
|
||||
/**
|
||||
* JSON-serializable key.
|
||||
* Re-triggers the notification if passed a different value from the last trigger() call (even from a previous browser session).
|
||||
* Suggested usage: data dependency array
|
||||
*/
|
||||
updateKey?: NotificationUpdateKey;
|
||||
updateKey?: NotificationUpdateKey,
|
||||
|
||||
/**
|
||||
* @param true (default): Notification initialized with status NotificationStatus.Triggered
|
||||
* @param false: Notification initialized with status NotificationStatus.Cleared
|
||||
*/
|
||||
isNew?: boolean;
|
||||
}) => void;
|
||||
isNew?: boolean
|
||||
) => void;
|
||||
|
||||
lastUpdated: number;
|
||||
}) => void;
|
||||
|
||||
/** Callback for notification action (Toast action button click, NotificationsMenu item click, or native push notification interaction) */
|
||||
useNotificationAction?: () => (id: _NotificationId) => any;
|
||||
useNotificationAction?: () => (id: NotificationIdType) => any;
|
||||
};
|
||||
|
||||
export enum NotificationStatus {
|
||||
@@ -71,10 +65,10 @@ export enum NotificationStatus {
|
||||
|
||||
/** Notification state. Serialized and cached into localStorage. */
|
||||
export type Notification<
|
||||
_NotificationId extends NotificationId = string,
|
||||
NotificationIdType extends NotificationId = string,
|
||||
NotificationUpdateKey = any
|
||||
> = {
|
||||
id: _NotificationId;
|
||||
id: NotificationIdType;
|
||||
type: NotificationType;
|
||||
status: NotificationStatus;
|
||||
timestamps: Partial<Record<NotificationStatus, number>>;
|
||||
@@ -85,15 +79,15 @@ export type Notifications = Record<NotificationId, Notification<any>>;
|
||||
|
||||
/** Notification display data derived from app state at runtime. */
|
||||
export type NotificationDisplayData = {
|
||||
icon?: React.ReactElement<any, 'svg'>;
|
||||
icon?: React.ReactNode;
|
||||
|
||||
title?: string;
|
||||
|
||||
description?: ReactNode;
|
||||
description?: React.ReactNode;
|
||||
|
||||
customContent?: ReactNode;
|
||||
customContent?: React.ReactNode;
|
||||
|
||||
customMenuContent?: ReactNode;
|
||||
customMenuContent?: React.ReactNode;
|
||||
|
||||
actionDescription?: string;
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { getSeparator } from '@/lib/numbers';
|
||||
|
||||
export const USD_DECIMALS = 2;
|
||||
export const SMALL_USD_DECIMALS = 4;
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@ export const tradeTooltips: TooltipStrings = {
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.ACCOUNT_LEVERAGE_TITLE }),
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.ACCOUNT_LEVERAGE_BODY }),
|
||||
}),
|
||||
'base-position-notional': ({ stringGetter }) => ({
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.BASE_POSITION_NOTIONAL_TITLE }),
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.BASE_POSITION_NOTIONAL_BODY }),
|
||||
}),
|
||||
'bracket-sl': ({ stringGetter }) => ({
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.BRACKET_ORDER_SL_TITLE }),
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.BRACKET_ORDER_SL_BODY }),
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { ExternalProvider } from '@ethersproject/providers';
|
||||
import { USDC_DENOM, type onboarding, DYDX_DENOM } from '@dydxprotocol/v4-client-js';
|
||||
import type { suggestChain } from 'graz';
|
||||
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
|
||||
@@ -313,10 +315,6 @@ export type WalletConnection = {
|
||||
};
|
||||
|
||||
// dYdX Chain wallets
|
||||
|
||||
import { USDC_DENOM, type onboarding, DYDX_DENOM } from '@dydxprotocol/v4-client-js';
|
||||
import type { suggestChain } from 'graz';
|
||||
|
||||
export const COSMOS_DERIVATION_PATH = "m/44'/118'/0'/0/0";
|
||||
|
||||
/**
|
||||
@@ -341,12 +339,12 @@ export type EvmAddress = `0x${string}`;
|
||||
export type DydxAddress = `dydx${string}`;
|
||||
|
||||
export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = {
|
||||
rpc: '13.59.4.93:26657',
|
||||
rest: '13.59.4.93:1317',
|
||||
chainId: 'dydx-testnet-2',
|
||||
rpc: 'https://dydx-testnet-archive.allthatnode.com:26657',
|
||||
rest: 'https://dydx-testnet-archive.allthatnode.com:1317',
|
||||
chainId: 'dydx-testnet-3',
|
||||
chainName: 'dYdX Public Testnet',
|
||||
chainSymbolImageUrl:
|
||||
'https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/dydx-testnet-2/chain.png',
|
||||
'https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/dydx-testnet-3/chain.png',
|
||||
bech32Config: {
|
||||
bech32PrefixAccPub: 'dydxpub',
|
||||
bech32PrefixValPub: 'dydxvaloperpub',
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useMatch, useNavigate } from 'react-router-dom';
|
||||
|
||||
import { LocalStorageKey } from '@/constants/localStorage';
|
||||
import { DEFAULT_MARKETID } from '@/constants/markets';
|
||||
import { AppRoute, DEFAULT_TRADE_ROUTE } from '@/constants/routes';
|
||||
import { AppRoute } from '@/constants/routes';
|
||||
|
||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||
import { closeDialogInTradeBox } from '@/state/dialogs';
|
||||
|
||||
@@ -114,7 +114,7 @@ const useDydxClientContext = () => {
|
||||
}): Promise<Candle[]> => {
|
||||
try {
|
||||
const { candles } =
|
||||
(await compositeClient!.indexerClient.markets.getPerpetualMarketCandles(
|
||||
(await compositeClient?.indexerClient.markets.getPerpetualMarketCandles(
|
||||
marketId,
|
||||
RESOLUTION_MAP[resolution],
|
||||
fromIso,
|
||||
|
||||
@@ -6,7 +6,7 @@ import { LocalStorageKey } from '@/constants/localStorage';
|
||||
import { type TransferNotifcation } from '@/constants/notifications';
|
||||
|
||||
import { useAccounts } from '@/hooks/useAccounts';
|
||||
import { useSquid } from '@/hooks/useSquid';
|
||||
import { SQUID_ERROR_TYPES, useSquid } from '@/hooks/useSquid';
|
||||
import { useLocalStorage } from './useLocalStorage';
|
||||
|
||||
const LocalNotificationsContext = createContext<
|
||||
@@ -66,11 +66,14 @@ const useLocalNotificationsContext = () => {
|
||||
} of transferNotifications) {
|
||||
try {
|
||||
if (currentStatus && currentStatus?.squidTransactionStatus !== 'ongoing') continue;
|
||||
|
||||
|
||||
const status = await squid?.getStatus({ transactionId: txHash, toChainId, fromChainId });
|
||||
if (status) statuses[txHash] = status;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
// ignore not found errors since the route might not be available yet
|
||||
if (error?.errors?.length && error.errors[0].errorType !== SQUID_ERROR_TYPES.NotFoundError) {
|
||||
statuses[txHash] = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
return statuses;
|
||||
|
||||
@@ -1,27 +1,30 @@
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
import { useSelector, shallowEqual, useDispatch } from 'react-redux';
|
||||
import { groupBy } from 'lodash';
|
||||
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
|
||||
|
||||
import { AlertType } from '@/constants/alerts';
|
||||
import { AbacusOrderStatus, ORDER_SIDES, ORDER_STATUS_STRINGS } from '@/constants/abacus';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { type NotificationTypeConfig, NotificationType } from '@/constants/notifications';
|
||||
import { ORDER_SIDE_STRINGS } from '@/constants/trade';
|
||||
import { ORDER_SIDE_STRINGS, TRADE_TYPE_STRINGS, TradeTypes } from '@/constants/trade';
|
||||
|
||||
import { useLocalNotifications } from '@/hooks/useLocalNotifications';
|
||||
|
||||
import { AssetIcon } from '@/components/AssetIcon';
|
||||
import { AlertMessage } from '@/components/AlertMessage';
|
||||
import { Icon, IconName } from '@/components/Icon';
|
||||
import { Output, OutputType } from '@/components/Output';
|
||||
import { OrderStatusIcon } from '@/views/OrderStatusIcon';
|
||||
import { TransferStatusToast } from '@/views/TransferStatus';
|
||||
import { TransferStatusSteps } from '@/views/TransferStatusSteps';
|
||||
|
||||
import { getSubaccountFills, getSubaccountOrders } from '@/state/accountSelectors';
|
||||
import { openDialog } from '@/state/dialogs';
|
||||
|
||||
import { OrderStatusIcon } from '@/views/OrderStatusIcon';
|
||||
|
||||
import { useStringGetter } from './useStringGetter';
|
||||
import { TransferStatusSteps } from '@/views/TransferStatusSteps';
|
||||
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
|
||||
|
||||
export const notificationTypes = [
|
||||
{
|
||||
@@ -58,33 +61,34 @@ export const notificationTypes = [
|
||||
}
|
||||
: undefined);
|
||||
|
||||
if (order) console.log(order);
|
||||
trigger({
|
||||
id: order.id,
|
||||
displayData: {
|
||||
icon: <AssetIcon symbol={order.marketId.split('-')[0]} />, //<OrderStatusIcon status={order.status} totalFilled={order.totalFilled ?? 0} />,
|
||||
title: `${stringGetter({
|
||||
key: order.resources.typeStringKey ?? '',
|
||||
})} ${
|
||||
order.status === AbacusOrderStatus.open && (order?.totalFilled ?? 0) > 0
|
||||
? stringGetter({ key: STRING_KEYS.PARTIALLY_FILLED })
|
||||
: stringGetter({ key: ORDER_STATUS_STRINGS[order.status.name] })
|
||||
}`,
|
||||
|
||||
description: `${stringGetter({
|
||||
key: ORDER_SIDE_STRINGS[ORDER_SIDES[order.side.name]],
|
||||
})} ${order.size} ${order.marketId} @ $${order.price}`,
|
||||
actionDescription: 'View Order',
|
||||
actionAltText: 'View this order in the Orders tab or the Notifications menu.',
|
||||
toastSensitivity:
|
||||
order.status === AbacusOrderStatus.pending ? 'foreground' : 'background',
|
||||
toastDuration: Infinity,
|
||||
},
|
||||
updateKey: [order.status.name, order.size],
|
||||
isNew: !order.createdAtMilliseconds || order.createdAtMilliseconds > lastUpdated,
|
||||
});
|
||||
if (order)
|
||||
trigger(
|
||||
order.id,
|
||||
{
|
||||
icon: (
|
||||
<OrderStatusIcon status={order.status} totalFilled={order.totalFilled ?? 0} />
|
||||
),
|
||||
title: `${stringGetter({
|
||||
key: TRADE_TYPE_STRINGS[order.type.rawValue as TradeTypes].tradeTypeKey,
|
||||
})} ${
|
||||
order.status === AbacusOrderStatus.open && (order?.totalFilled ?? 0) > 0
|
||||
? stringGetter({ key: STRING_KEYS.PARTIALLY_FILLED })
|
||||
: stringGetter({ key: ORDER_STATUS_STRINGS[order.status.name] })
|
||||
}`,
|
||||
description: `${stringGetter({
|
||||
key: ORDER_SIDE_STRINGS[ORDER_SIDES[order.side.name]],
|
||||
})} ${order.size} ${order.marketId} @ $${order.price}`,
|
||||
actionDescription: 'View Order',
|
||||
actionAltText: 'View this order in the Orders tab or the Notifications menu.',
|
||||
toastSensitivity:
|
||||
order.status === AbacusOrderStatus.pending ? 'foreground' : 'background',
|
||||
toastDuration: 5000,
|
||||
},
|
||||
[order.status.name, order.size],
|
||||
!order.createdAtMilliseconds || order.createdAtMilliseconds > lastUpdated
|
||||
);
|
||||
}
|
||||
}, [orderIds, stringGetter]);
|
||||
}, [orderIds]);
|
||||
},
|
||||
|
||||
useNotificationAction: () => {
|
||||
@@ -118,19 +122,36 @@ export const notificationTypes = [
|
||||
const { toChainId, status, txHash, toAmount } = transfer;
|
||||
const finished = Boolean(status) && status?.squidTransactionStatus !== 'ongoing';
|
||||
const type = toChainId === TESTNET_CHAIN_ID ? 'deposit' : 'withdraw';
|
||||
// @ts-ignore status.errors is not in the type definition but can be returned
|
||||
const error = status?.errors?.length ? status?.errors[0] : status?.error;
|
||||
|
||||
trigger({
|
||||
id: txHash,
|
||||
displayData: {
|
||||
// TODO: confirm with design what the description should be
|
||||
const description = (
|
||||
<div>
|
||||
<Styled.TransferText>
|
||||
{type === 'deposit' ? 'Deposit of ' : 'Withdraw of '}
|
||||
<Output type={OutputType.Fiat} value={toAmount} />
|
||||
</Styled.TransferText>
|
||||
|
||||
{error && (
|
||||
<Styled.ErrorMessage type={AlertType.Error}>
|
||||
{stringGetter({
|
||||
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
|
||||
params: {
|
||||
ERROR_MESSAGE: error.message || stringGetter({ key: STRING_KEYS.UNKNOWN_ERROR }),
|
||||
},
|
||||
})}
|
||||
</Styled.ErrorMessage>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
trigger(
|
||||
txHash,
|
||||
{
|
||||
icon: <Icon iconName={finished ? IconName.Transfer : IconName.Clock} />,
|
||||
title: stringGetter({ key: getTitleStringKey(type, finished) }),
|
||||
// TODO: confirm with design what the description should be
|
||||
description: (
|
||||
<>
|
||||
<span>{type === 'deposit' ? 'Deposit of ' : 'Withdraw of'}</span>
|
||||
<Output type={OutputType.Fiat} value={toAmount} />
|
||||
</>
|
||||
),
|
||||
description: description,
|
||||
customContent: (
|
||||
<TransferStatusToast
|
||||
toAmount={transfer.toAmount}
|
||||
@@ -138,13 +159,30 @@ export const notificationTypes = [
|
||||
status={transfer.status}
|
||||
/>
|
||||
),
|
||||
customMenuContent: !finished && <TransferStatusSteps status={transfer.status} />,
|
||||
customMenuContent: !finished && (
|
||||
<div>
|
||||
{description}
|
||||
<TransferStatusSteps status={transfer.status} />
|
||||
</div>
|
||||
),
|
||||
toastSensitivity: 'foreground',
|
||||
},
|
||||
updateKey: [],
|
||||
});
|
||||
[]
|
||||
);
|
||||
}
|
||||
}, [transferNotifications, stringGetter]);
|
||||
}, [transferNotifications]);
|
||||
},
|
||||
} as NotificationTypeConfig<string, []>,
|
||||
},
|
||||
] satisfies NotificationTypeConfig[];
|
||||
|
||||
const Styled: Record<string, AnyStyledComponent> = {};
|
||||
|
||||
Styled.TransferText = styled.span`
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5ch;
|
||||
`
|
||||
|
||||
Styled.ErrorMessage = styled.div`
|
||||
max-width: 13rem;
|
||||
`;
|
||||
@@ -92,7 +92,7 @@ const useNotificationsContext = () => {
|
||||
for (const { type, useTrigger } of notificationTypes)
|
||||
useTrigger({
|
||||
trigger: useCallback(
|
||||
({ id, displayData, updateKey, isNew = true }) => {
|
||||
(id, displayData, updateKey, isNew = true) => {
|
||||
const key = getKey({ type, id });
|
||||
|
||||
const notification = notifications[key];
|
||||
@@ -182,23 +182,28 @@ const useNotificationsContext = () => {
|
||||
const iconUrl =
|
||||
displayData.icon && (await renderSvgToDataUrl(displayData.icon).catch(() => undefined));
|
||||
|
||||
if (displayData.title) {
|
||||
const pushNotification = new globalThis.Notification(displayData.title, {
|
||||
renotify: true,
|
||||
tag: getKey(notification),
|
||||
data: notification,
|
||||
body: displayData.description ?? '',
|
||||
icon: (iconUrl as string) ?? '/favicon.svg',
|
||||
badge: (iconUrl as string) ?? '/favicon.svg',
|
||||
image: (iconUrl as string) ?? '/favicon.svg',
|
||||
requireInteraction: displayData.toastDuration === Infinity,
|
||||
});
|
||||
const pushNotification = new globalThis.Notification(displayData.title, {
|
||||
renotify: true,
|
||||
tag: getKey(notification),
|
||||
data: notification,
|
||||
body: displayData.description,
|
||||
icon: iconUrl ?? '/favicon.svg',
|
||||
badge: iconUrl ?? '/favicon.svg',
|
||||
image: iconUrl ?? '/favicon.svg',
|
||||
vibrate: displayData.toastSensitivity === 'foreground',
|
||||
requireInteraction: displayData.toastDuration === Infinity,
|
||||
// actions: [
|
||||
// {
|
||||
// action: displayData.actionDescription,
|
||||
// title: displayData.actionDescription,
|
||||
// }
|
||||
// ].slice(0, globalThis.Notification.maxActions),
|
||||
});
|
||||
|
||||
pushNotification.addEventListener('click', () => {
|
||||
onNotificationAction(notification);
|
||||
markSeen(notification);
|
||||
});
|
||||
}
|
||||
pushNotification.addEventListener('click', () => {
|
||||
onNotificationAction(notification);
|
||||
markSeen(notification);
|
||||
});
|
||||
}
|
||||
|
||||
setPushNotificationsLastUpdated(Date.now());
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
|
||||
import { Squid } from '@0xsquid/sdk';
|
||||
|
||||
import { CLIENT_NETWORK_CONFIGS, DydxV4Network, isDydxV4Network } from '@/constants/networks';
|
||||
import { CLIENT_NETWORK_CONFIGS, isDydxV4Network } from '@/constants/networks';
|
||||
|
||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||
|
||||
export const NATIVE_TOKEN_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
||||
|
||||
export enum SQUID_ERROR_TYPES {
|
||||
NotFoundError = 'NotFoundError',
|
||||
}
|
||||
|
||||
const useSquidContext = () => {
|
||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||
const [_, setInitialized] = useState(false);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import type { Nullable } from '@dydxprotocol/abacus';
|
||||
import type { Nullable } from '@dydxprotocol/v4-abacus';
|
||||
import Long from 'long';
|
||||
import type { IndexedTx } from '@cosmjs/stargate';
|
||||
import type { EncodeObject, Coin } from '@cosmjs/proto-signing';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const LogoShortIcon: React.FC<{ id?: string }> = ({ id }) => (
|
||||
const LogoShortIcon: React.FC<{ id?: string }> = ({ id }: { id?: string }) => (
|
||||
<svg
|
||||
width="135"
|
||||
height="145"
|
||||
|
||||
@@ -7,10 +7,9 @@ import { DialogTypes } from '@/constants/dialogs';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { AppRoute } from '@/constants/routes';
|
||||
import { useStringGetter } from '@/hooks';
|
||||
import { LogoShortIcon } from '@/icons';
|
||||
import { LogoShortIcon, BellIcon } from '@/icons';
|
||||
|
||||
import { Icon, IconName } from '@/components/Icon';
|
||||
import { BellIcon } from '@/icons';
|
||||
import { IconButton } from '@/components/IconButton';
|
||||
import { NavigationMenu } from '@/components/NavigationMenu';
|
||||
import { VerticalSeparator } from '@/components/Separator';
|
||||
|
||||
@@ -15,12 +15,20 @@ type StyleProps = {
|
||||
};
|
||||
|
||||
export const NotificationsToastArea = ({ className }: StyleProps) => {
|
||||
const { notifications, getKey, getDisplayData, markUnseen, markSeen, isMenuOpen, onNotificationAction } = useNotifications();
|
||||
const {
|
||||
notifications,
|
||||
getKey,
|
||||
getDisplayData,
|
||||
markUnseen,
|
||||
markSeen,
|
||||
isMenuOpen,
|
||||
onNotificationAction,
|
||||
} = useNotifications();
|
||||
|
||||
const { isMobile } = useBreakpoints();
|
||||
|
||||
return (
|
||||
<$ToastArea swipeDirection={isMobile ? 'up' : 'right'} className={className}>
|
||||
<StyledToastArea swipeDirection={isMobile ? 'up' : 'right'} className={className}>
|
||||
{Object.values(notifications)
|
||||
// Sort by time of first trigger
|
||||
.sort(
|
||||
@@ -53,19 +61,20 @@ export const NotificationsToastArea = ({ className }: StyleProps) => {
|
||||
sensitivity={displayData.toastSensitivity}
|
||||
setIsOpen={(isOpen, isClosedFromTimeout) => {
|
||||
if (!isOpen)
|
||||
// Toast timer expired without user interaction
|
||||
if (isClosedFromTimeout) markUnseen(notification);
|
||||
if (isClosedFromTimeout)
|
||||
// Toast timer expired without user interaction
|
||||
markUnseen(notification);
|
||||
// Toast interacted with or dismissed
|
||||
else markSeen(notification);
|
||||
}}
|
||||
lastUpdated={notification.timestamps[notification.status]}
|
||||
/>
|
||||
))}
|
||||
</$ToastArea>
|
||||
</StyledToastArea>
|
||||
);
|
||||
};
|
||||
|
||||
const $ToastArea = styled(ToastArea)`
|
||||
const StyledToastArea = styled(ToastArea)`
|
||||
position: absolute;
|
||||
width: min(16rem, 100%);
|
||||
inset: 0 0 0 auto;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Abacus, { Nullable } from '@dydxprotocol/abacus';
|
||||
import Abacus, { Nullable } from '@dydxprotocol/v4-abacus';
|
||||
import Long from 'long';
|
||||
|
||||
import {
|
||||
@@ -15,14 +15,24 @@ import {
|
||||
type QueryTypes,
|
||||
type TransactionTypes,
|
||||
} from '@/constants/abacus';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
|
||||
import { RootStore } from '@/state/_store';
|
||||
import { openDialog } from '@/state/dialogs';
|
||||
|
||||
import { log } from '../telemetry';
|
||||
|
||||
class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
||||
private compositeClient: CompositeClient | undefined;
|
||||
private store: RootStore | undefined;
|
||||
|
||||
constructor() {
|
||||
this.compositeClient = undefined;
|
||||
this.store = undefined;
|
||||
}
|
||||
|
||||
setStore(store: RootStore): void {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
async connectNetwork(
|
||||
@@ -33,30 +43,41 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
||||
faucetUrl: Nullable<string> | undefined,
|
||||
callback: (p0: Nullable<string>) => void
|
||||
): Promise<void> {
|
||||
this.compositeClient = await CompositeClient.connect(
|
||||
new Network(
|
||||
chainId,
|
||||
new IndexerConfig(indexerUrl, indexerSocketUrl),
|
||||
new ValidatorConfig(validatorUrl, chainId, {
|
||||
broadcastPollIntervalMs: 3_000,
|
||||
broadcastTimeoutMs: 60_000,
|
||||
})
|
||||
)
|
||||
);
|
||||
try {
|
||||
const compositeClient = await CompositeClient.connect(
|
||||
new Network(
|
||||
chainId,
|
||||
new IndexerConfig(indexerUrl, indexerSocketUrl),
|
||||
new ValidatorConfig(validatorUrl, chainId, {
|
||||
broadcastPollIntervalMs: 3_000,
|
||||
broadcastTimeoutMs: 60_000,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
// Dispatch custom event to notify other parts of the app that the network has been connected
|
||||
const customEvent = new CustomEvent('abacus:connectNetwork', {
|
||||
detail: {
|
||||
indexerUrl,
|
||||
indexerSocketUrl,
|
||||
validatorUrl,
|
||||
chainId,
|
||||
faucetUrl,
|
||||
},
|
||||
});
|
||||
this.compositeClient = compositeClient;
|
||||
|
||||
globalThis.dispatchEvent(customEvent);
|
||||
callback(JSON.stringify({ success: true }));
|
||||
// Dispatch custom event to notify other parts of the app that the network has been connected
|
||||
const customEvent = new CustomEvent('abacus:connectNetwork', {
|
||||
detail: {
|
||||
indexerUrl,
|
||||
indexerSocketUrl,
|
||||
validatorUrl,
|
||||
chainId,
|
||||
faucetUrl,
|
||||
},
|
||||
});
|
||||
|
||||
globalThis.dispatchEvent(customEvent);
|
||||
callback(JSON.stringify({ success: true }));
|
||||
} catch (error) {
|
||||
this.store?.dispatch(
|
||||
openDialog({ type: DialogTypes.ExchangeOffline, dialogProps: { preventClose: true } })
|
||||
);
|
||||
|
||||
log('DydxChainTransactions/connectNetwork', error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
parseToPrimitives<T>(x: T): T {
|
||||
@@ -85,7 +106,6 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
||||
throw new Error(`Unsupported data type: ${typeof x}`);
|
||||
}
|
||||
|
||||
|
||||
async transaction(
|
||||
type: TransactionTypes,
|
||||
paramsInJson: Abacus.Nullable<string>,
|
||||
|
||||
@@ -36,7 +36,6 @@ import AbacusStateNotifier from './stateNotification';
|
||||
import AbacusLocalizer from './localizer';
|
||||
import AbacusFormatter from './formatter';
|
||||
import AbacusThreading from './threading';
|
||||
import AbacusTracking from './tracking';
|
||||
import AbacusFileSystem, { ENDPOINTS_PATH } from './filesystem';
|
||||
import { LocaleSeparators } from '../numbers';
|
||||
class AbacusStateManager {
|
||||
@@ -47,6 +46,7 @@ class AbacusStateManager {
|
||||
websocket: AbacusWebsocket;
|
||||
stateNotifier: AbacusStateNotifier;
|
||||
abacusFormatter: AbacusFormatter;
|
||||
chainTransactionClient: AbacusChainTransaction;
|
||||
|
||||
constructor() {
|
||||
this.store = undefined;
|
||||
@@ -54,13 +54,14 @@ class AbacusStateManager {
|
||||
this.stateNotifier = new AbacusStateNotifier();
|
||||
this.websocket = new AbacusWebsocket();
|
||||
this.abacusFormatter = new AbacusFormatter();
|
||||
this.chainTransactionClient = new AbacusChainTransaction();
|
||||
|
||||
const ioImplementations = new IOImplementations(
|
||||
// @ts-ignore
|
||||
new AbacusRest(),
|
||||
this.websocket,
|
||||
new AbacusChainTransaction(),
|
||||
new AbacusTracking(),
|
||||
this.chainTransactionClient,
|
||||
null,
|
||||
new AbacusThreading(),
|
||||
new CoroutineTimer(),
|
||||
new AbacusFileSystem()
|
||||
@@ -156,6 +157,7 @@ class AbacusStateManager {
|
||||
setStore = (store: RootStore) => {
|
||||
this.store = store;
|
||||
this.stateNotifier.setStore(store);
|
||||
this.chainTransactionClient.setStore(store);
|
||||
};
|
||||
|
||||
setAccount = (walletAddress: string) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Nullable, kollections } from '@dydxprotocol/abacus';
|
||||
import type { Nullable, kollections } from '@dydxprotocol/v4-abacus';
|
||||
|
||||
import type { AbacusRestProtocol } from '@/constants/abacus';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { kollections } from '@dydxprotocol/abacus';
|
||||
import { kollections } from '@dydxprotocol/v4-abacus';
|
||||
|
||||
import type {
|
||||
AbacusApiState,
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import type { AbacusTrackingProtocol, Nullable } from '@/constants/abacus';
|
||||
|
||||
class AbacusTracking implements AbacusTrackingProtocol {
|
||||
log(event: string, data: Nullable<string>) {
|
||||
console.log({ event, data });
|
||||
}
|
||||
}
|
||||
|
||||
export default AbacusTracking;
|
||||
+1
-1
@@ -48,7 +48,7 @@ export const isNumber = (value: any): value is number =>
|
||||
/**
|
||||
* @description Returns null if input is 0 or null, '99+' if input is greater than 99, otherwise original input number
|
||||
*/
|
||||
export const shorternNumberForDisplay = (num?: number) =>
|
||||
export const shortenNumberForDisplay = (num?: number) =>
|
||||
MustBigNumber(num).eq(0) ? null : MustBigNumber(num).gt(99) ? '99+' : num;
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,10 +21,8 @@ const applyComputedStyles = (html: string) => {
|
||||
const toDataUrl = (bytes: string, type = 'image/svg+xml') =>
|
||||
new Promise<string | ArrayBuffer | null>((resolve, reject) => {
|
||||
Object.assign(new FileReader(), {
|
||||
onload: (e: {
|
||||
target: { result: string | ArrayBuffer | PromiseLike<string | ArrayBuffer | null> | null };
|
||||
}) => resolve(e.target.result),
|
||||
onerror: (e: { target: { error: Error } }) => reject(e.target.error),
|
||||
onload: (e) => resolve(e.target.result),
|
||||
onerror: (e) => reject(e.target.error),
|
||||
}).readAsDataURL(new File([bytes], '', { type }));
|
||||
});
|
||||
|
||||
|
||||
+11
-3
@@ -1,5 +1,7 @@
|
||||
export const log = (location: string, error: Error, metadata?: any) => {
|
||||
// console.warn(error);
|
||||
if (import.meta.env.MODE !== 'production') {
|
||||
console.warn('telemetry/log:', { location, error, metadata });
|
||||
}
|
||||
|
||||
const customEvent = new CustomEvent('dydx:log', {
|
||||
detail: {
|
||||
@@ -16,7 +18,10 @@ export const log = (location: string, error: Error, metadata?: any) => {
|
||||
globalThis.addEventListener('unhandledrejection', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
log('window/onunhandledrejection', new Error(`Promise rejected and uncaught; reason: ${event.reason}`));
|
||||
log(
|
||||
'window/onunhandledrejection',
|
||||
new Error(`Promise rejected and uncaught; reason: ${event.reason}`)
|
||||
);
|
||||
});
|
||||
|
||||
// Log rejected Promises that are caught late (handler attached at a later time)
|
||||
@@ -25,7 +30,10 @@ globalThis.addEventListener(
|
||||
(event) => {
|
||||
event.preventDefault();
|
||||
|
||||
log('window/onrejectionhandled', new Error(`Promise rejected and caught late; reason: ${event.reason}`));
|
||||
log(
|
||||
'window/onrejectionhandled',
|
||||
new Error(`Promise rejected and caught late; reason: ${event.reason}`)
|
||||
);
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Nullable } from '@dydxprotocol/abacus';
|
||||
import { Nullable } from '@dydxprotocol/v4-abacus';
|
||||
import styled, { AnyStyledComponent } from 'styled-components';
|
||||
import { shallowEqual, useSelector } from 'react-redux';
|
||||
|
||||
@@ -270,11 +270,11 @@ Styled.FeeTable = styled(Table)`
|
||||
--table-cell-align: end;
|
||||
|
||||
font: var(--font-base-book);
|
||||
|
||||
|
||||
tbody tr {
|
||||
&[data-yours='true'] {
|
||||
background-color: var(--color-layer-3);
|
||||
|
||||
|
||||
td:first-child {
|
||||
border-left: 0.125rem solid var(--color-accent);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import {
|
||||
import { getCurrentMarketAssetId, getCurrentMarketId } from '@/state/perpetualsSelectors';
|
||||
|
||||
import { isTruthy } from '@/lib/isTruthy';
|
||||
import { shorternNumberForDisplay } from '@/lib/numbers';
|
||||
import { shortenNumberForDisplay } from '@/lib/numbers';
|
||||
|
||||
import { PositionInfo } from '@/views/PositionInfo';
|
||||
|
||||
@@ -73,9 +73,9 @@ export const HorizontalPanel = ({ isOpen = true, setIsOpen }: ElementProps) => {
|
||||
|
||||
const showCurrentMarket = isTablet || view === PanelView.CurrentMarket;
|
||||
|
||||
const fillsTagNumber = shorternNumberForDisplay(showCurrentMarket ? numFills : numTotalFills);
|
||||
const fillsTagNumber = shortenNumberForDisplay(showCurrentMarket ? numFills : numTotalFills);
|
||||
|
||||
const ordersTagNumber = shorternNumberForDisplay(
|
||||
const ordersTagNumber = shortenNumberForDisplay(
|
||||
showCurrentMarket ? numOpenOrders : numTotalOpenOrders
|
||||
);
|
||||
|
||||
@@ -86,7 +86,7 @@ export const HorizontalPanel = ({ isOpen = true, setIsOpen }: ElementProps) => {
|
||||
key: showCurrentMarket ? STRING_KEYS.POSITION : STRING_KEYS.POSITIONS,
|
||||
}),
|
||||
|
||||
tag: showCurrentMarket ? null : shorternNumberForDisplay(numTotalPositions),
|
||||
tag: showCurrentMarket ? null : shortenNumberForDisplay(numTotalPositions),
|
||||
|
||||
content: showCurrentMarket ? (
|
||||
<PositionInfo showNarrowVariation={isTablet} />
|
||||
@@ -190,7 +190,7 @@ export const HorizontalPanel = ({ isOpen = true, setIsOpen }: ElementProps) => {
|
||||
// value: InfoSection.Payments,
|
||||
// label: stringGetter({ key: STRING_KEYS.PAYMENTS }),
|
||||
|
||||
// tag: shorternNumberForDisplay(
|
||||
// tag: shortenNumberForDisplay(
|
||||
// showCurrentMarket ? numFundingPayments : numTotalFundingPayments
|
||||
// ),
|
||||
// content: (
|
||||
|
||||
+1
-2
@@ -1,5 +1,6 @@
|
||||
import { configureStore } from '@reduxjs/toolkit';
|
||||
|
||||
import abacusStateManager from '@/lib/abacus';
|
||||
import appMiddleware from './appMiddleware';
|
||||
import localizationMiddleware from './localizationMiddleware';
|
||||
import routerMiddleware from './routerMiddleware';
|
||||
@@ -16,8 +17,6 @@ import { localizationSlice } from './localization';
|
||||
import { navigationSlice } from './navigation';
|
||||
import { perpetualsSlice } from './perpetuals';
|
||||
|
||||
import abacusStateManager from '@/lib/abacus';
|
||||
|
||||
export const commandMenuSlices = [layoutSlice, localizationSlice];
|
||||
|
||||
export const store = configureStore({
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
|
||||
import _ from 'lodash';
|
||||
|
||||
import type {
|
||||
SubaccountFill,
|
||||
|
||||
@@ -12,9 +12,8 @@ import {
|
||||
|
||||
import { OnboardingState } from '@/constants/account';
|
||||
|
||||
import type { RootState } from './_store';
|
||||
|
||||
import { getHydratedTradingData } from '@/lib/orders';
|
||||
import type { RootState } from './_store';
|
||||
|
||||
import { getCurrentMarketId, getPerpetualMarkets } from './perpetualsSelectors';
|
||||
import { getAssets } from './assetsSelectors';
|
||||
@@ -106,11 +105,11 @@ export const getSubaccountOpenOrdersBySideAndPrice = createSelector(
|
||||
[getSubaccountOpenOrders],
|
||||
(openOrders = []) => {
|
||||
const ordersBySide: Partial<Record<OrderSide, Record<number, SubaccountOrder>>> = {};
|
||||
for (const order of openOrders) {
|
||||
openOrders.forEach((order) => {
|
||||
const side = ORDER_SIDES[order.side.name];
|
||||
const byPrice = (ordersBySide[side] ??= {});
|
||||
byPrice[order.price] = order;
|
||||
}
|
||||
});
|
||||
return ordersBySide;
|
||||
}
|
||||
);
|
||||
@@ -123,8 +122,10 @@ export const getOrderDetails = (orderId: string) =>
|
||||
createSelector(
|
||||
[getSubaccountOrders, getAssets, getPerpetualMarkets],
|
||||
(orders, assets, perpetualMarkets) => {
|
||||
const order = orders?.find((order) => order.id === orderId);
|
||||
return order ? getHydratedTradingData({ data: order, assets, perpetualMarkets }) : undefined;
|
||||
const matchingOrder = orders?.find((order) => order.id === orderId);
|
||||
return matchingOrder
|
||||
? getHydratedTradingData({ data: matchingOrder, assets, perpetualMarkets })
|
||||
: undefined;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -178,8 +179,10 @@ export const getFillDetails = (fillId: string) =>
|
||||
createSelector(
|
||||
[getSubaccountFills, getAssets, getPerpetualMarkets],
|
||||
(fills, assets, perpetualMarkets) => {
|
||||
const fill = fills?.find((fill) => fill.id === fillId);
|
||||
return fill ? getHydratedTradingData({ data: fill, assets, perpetualMarkets }) : undefined;
|
||||
const matchingFill = fills?.find((fill) => fill.id === fillId);
|
||||
return matchingFill
|
||||
? getHydratedTradingData({ data: matchingFill, assets, perpetualMarkets })
|
||||
: undefined;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
+2
-6
@@ -47,9 +47,5 @@ export const appSlice = createSlice({
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
initializeLocalization,
|
||||
initializeWebsocket,
|
||||
setApiState,
|
||||
setSelectedNetwork,
|
||||
} = appSlice.actions;
|
||||
export const { initializeLocalization, initializeWebsocket, setApiState, setSelectedNetwork } =
|
||||
appSlice.actions;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
|
||||
import type { kollections } from '@dydxprotocol/abacus';
|
||||
import type { kollections } from '@dydxprotocol/v4-abacus';
|
||||
|
||||
import type { Configs, FeeDiscount, FeeTier, NetworkConfigs, Nullable } from '@/constants/abacus';
|
||||
import { LocalStorageKey } from '@/constants/localStorage';
|
||||
|
||||
@@ -2,4 +2,4 @@ import { type RootState } from './_store';
|
||||
|
||||
export const getActiveDialog = (state: RootState) => state.dialogs.activeDialog;
|
||||
|
||||
export const getActiveTradeBoxDialog = (state: RootState) => state.dialogs.activeTradeBoxDialog;
|
||||
export const getActiveTradeBoxDialog = (state: RootState) => state.dialogs.activeTradeBoxDialog;
|
||||
|
||||
@@ -40,7 +40,7 @@ export const getStringGetterForLocaleData = (localeData: LocaleData) => {
|
||||
params?: { [key: string]: string | React.ReactNode };
|
||||
}): string | Array<string | React.ReactNode> => {
|
||||
// Fallback to english whenever a key doesn't exist for other languages
|
||||
let formattedString: string = _.get(localeData, key) || _.get(EN_LOCALE_DATA, key) || '';
|
||||
const formattedString: string = _.get(localeData, key) || _.get(EN_LOCALE_DATA, key) || '';
|
||||
|
||||
return formatString(formattedString, params);
|
||||
};
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { matchPath } from 'react-router-dom';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
import { Candle, TradingViewBar } from '@/constants/candles';
|
||||
import { TRADE_ROUTE } from '@/constants/routes';
|
||||
|
||||
import { mapCandle } from '@/lib/tradingView/utils';
|
||||
|
||||
import type { RootState } from './_store';
|
||||
import { mapCandle } from '@/lib/tradingView/utils';
|
||||
|
||||
/**
|
||||
* @param state
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import styled, { css, type FlattenSimpleInterpolation } from 'styled-components';
|
||||
import { css } from 'styled-components';
|
||||
|
||||
import breakpoints from './breakpoints';
|
||||
|
||||
|
||||
+36
-32
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -6,8 +6,6 @@ import {
|
||||
type ThemeProps,
|
||||
} from 'styled-components';
|
||||
|
||||
import breakpoints from './breakpoints';
|
||||
|
||||
export const layoutMixins: Record<
|
||||
string,
|
||||
FlattenSimpleInterpolation | FlattenInterpolation<ThemeProps<any>>
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
type ThemeProps,
|
||||
} from 'styled-components';
|
||||
|
||||
import breakpoints from './breakpoints';
|
||||
import { layoutMixins } from './layoutMixins';
|
||||
|
||||
export const tableMixins: Record<
|
||||
|
||||
+2
-8
@@ -1,22 +1,16 @@
|
||||
/* Constants */
|
||||
|
||||
:root {
|
||||
--fontFamily-base: "Circular", system-ui, -apple-system, Helvetica, Arial, sans-serif;
|
||||
--fontFamily-monospace: "CircularMono", Courier, monospace, var(--fontFamily-base);
|
||||
--fontFamily-base: "Satoshi", system-ui, -apple-system, Helvetica, Arial, sans-serif;
|
||||
--fontFamily-monospace: Courier, monospace, var(--fontFamily-base);
|
||||
|
||||
--fontWeight-base-0: 450;
|
||||
--fontWeight-base-1: 500;
|
||||
--fontWeight-base-2: 700;
|
||||
--fontWeight-monospace: 400;
|
||||
|
||||
--letter-spacing-base: -0.02em;
|
||||
|
||||
/* New Typography system */
|
||||
|
||||
/**
|
||||
* @size 10px/11px
|
||||
* @weight 400
|
||||
*/
|
||||
--fontSize-tiny: 0.625rem; /* 10px/11px */
|
||||
--fontSize-mini: 0.75rem; /* 12px/13px */
|
||||
--fontSize-small: 0.8438rem; /* 13.5px/14.5px */
|
||||
|
||||
+29
-39
@@ -2,7 +2,7 @@ import { shallowEqual, useSelector } from 'react-redux';
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
|
||||
import { ButtonShape, ButtonSize, ButtonType } from '@/constants/buttons';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { STRING_KEYS, type StringKey } from '@/constants/localization';
|
||||
import { useBreakpoints, useStringGetter } from '@/hooks';
|
||||
import { breakpoints } from '@/styles';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
@@ -29,15 +29,13 @@ export const MarketDetails: React.FC = () => {
|
||||
if (!configs) return null;
|
||||
|
||||
const {
|
||||
basePositionNotional,
|
||||
tickSize,
|
||||
stepSize,
|
||||
initialMarginFraction,
|
||||
maintenanceMarginFraction,
|
||||
minOrderSize,
|
||||
maxPositionSize,
|
||||
baselinePositionSize,
|
||||
incrementalInitialMarginFraction,
|
||||
incrementalPositionSize,
|
||||
stepSizeDecimals,
|
||||
tickSizeDecimals,
|
||||
} = configs;
|
||||
|
||||
@@ -72,12 +70,28 @@ export const MarketDetails: React.FC = () => {
|
||||
key: 'step-size',
|
||||
label: stringGetter({ key: STRING_KEYS.STEP_SIZE }),
|
||||
tooltip: 'step-size',
|
||||
value: <Output useGrouping value={stepSize} type={OutputType.Asset} tag={symbol} />,
|
||||
value: (
|
||||
<Output
|
||||
useGrouping
|
||||
value={stepSize}
|
||||
type={OutputType.Asset}
|
||||
tag={symbol}
|
||||
fractionDigits={stepSizeDecimals}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'min-order-size',
|
||||
label: stringGetter({ key: STRING_KEYS.MINIMUM_ORDER_SIZE }),
|
||||
value: <Output useGrouping value={minOrderSize} type={OutputType.Asset} tag={symbol} />,
|
||||
value: (
|
||||
<Output
|
||||
useGrouping
|
||||
value={minOrderSize}
|
||||
type={OutputType.Asset}
|
||||
tag={symbol}
|
||||
fractionDigits={stepSizeDecimals}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'max-leverage',
|
||||
@@ -100,40 +114,16 @@ export const MarketDetails: React.FC = () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'initial-margin-fraction',
|
||||
label: stringGetter({ key: STRING_KEYS.INITIAL_MARGIN_FRACTION }),
|
||||
key: 'base-initial-margin-fraction',
|
||||
label: stringGetter({ key: STRING_KEYS.BASE_INITIAL_MARGIN_FRACTION }),
|
||||
tooltip: 'initial-margin-fraction',
|
||||
value: <Output useGrouping value={initialMarginFraction} type={OutputType.SmallPercent} />,
|
||||
},
|
||||
{
|
||||
key: 'incremental-initial-margin-fraction',
|
||||
label: stringGetter({ key: STRING_KEYS.INCREMENTAL_INITIAL_MARGIN_FRACTION }),
|
||||
value: (
|
||||
<Output
|
||||
useGrouping
|
||||
value={incrementalInitialMarginFraction}
|
||||
type={OutputType.SmallPercent}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'incremental-position-size',
|
||||
label: stringGetter({ key: STRING_KEYS.INCREMENTAL_POSITION_SIZE }),
|
||||
value: (
|
||||
<Output useGrouping value={incrementalPositionSize} type={OutputType.Asset} tag={symbol} />
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'baseline-position-size',
|
||||
label: stringGetter({ key: STRING_KEYS.BASELINE_POSITION_SIZE }),
|
||||
value: (
|
||||
<Output useGrouping value={baselinePositionSize} type={OutputType.Asset} tag={symbol} />
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'max-position-size',
|
||||
label: stringGetter({ key: STRING_KEYS.MAXIMUM_POSITION_SIZE }),
|
||||
value: <Output useGrouping value={maxPositionSize} type={OutputType.Asset} tag={symbol} />,
|
||||
key: 'base-position-notional',
|
||||
label: stringGetter({ key: STRING_KEYS.BASE_POSITION_NOTIONAL }),
|
||||
tooltip: 'base-position-notional',
|
||||
value: <Output useGrouping value={basePositionNotional} type={OutputType.Number} />,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -150,10 +140,10 @@ export const MarketDetails: React.FC = () => {
|
||||
|
||||
<Styled.MarketDescription>
|
||||
{primaryDescriptionKey && (
|
||||
<p>{stringGetter({ key: STRING_KEYS[primaryDescriptionKey] })}</p>
|
||||
<p>{stringGetter({ key: STRING_KEYS[primaryDescriptionKey as StringKey] })}</p>
|
||||
)}
|
||||
{secondaryDescriptionKey && (
|
||||
<p>{stringGetter({ key: STRING_KEYS[secondaryDescriptionKey] })}</p>
|
||||
<p>{stringGetter({ key: STRING_KEYS[secondaryDescriptionKey as StringKey] })}</p>
|
||||
)}
|
||||
</Styled.MarketDescription>
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ const useTradeTypeOptions = () => {
|
||||
value && {
|
||||
value: value as TradeTypes,
|
||||
label,
|
||||
disabled: import.meta.env.MODE === 'production', // TODO: Remove this when stop orders are supported on testnet
|
||||
}
|
||||
)
|
||||
.filter(isTruthy),
|
||||
|
||||
@@ -7,9 +7,11 @@ import { StatusResponse } from '@0xsquid/sdk';
|
||||
import { useInterval, useStringGetter } from '@/hooks';
|
||||
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { AlertType } from '@/constants/alerts';
|
||||
|
||||
import { formatSeconds } from '@/lib/timeUtils';
|
||||
|
||||
import { AlertMessage } from '@/components/AlertMessage';
|
||||
import { Output, OutputType } from '@/components/Output';
|
||||
import { WithReceipt } from '@/components/WithReceipt';
|
||||
import { Icon, IconName } from '@/components/Icon';
|
||||
@@ -33,6 +35,9 @@ export const TransferStatusToast = ({
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const [secondsLeft, setSecondsLeft] = useState<number | undefined>();
|
||||
|
||||
// @ts-ignore status.errors is not in the type definition but can be returned
|
||||
const error = status?.errors?.length ? status?.errors[0] : status?.error;
|
||||
|
||||
const type = useMemo(
|
||||
() => (status?.toChain?.chainData?.chainId === TESTNET_CHAIN_ID ? 'deposit' : 'withdrawal'),
|
||||
[status]
|
||||
@@ -74,6 +79,16 @@ export const TransferStatusToast = ({
|
||||
},
|
||||
})}
|
||||
</Styled.Status>
|
||||
{error && (
|
||||
<AlertMessage type={AlertType.Error}>
|
||||
{stringGetter({
|
||||
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
|
||||
params: {
|
||||
ERROR_MESSAGE: error.message || stringGetter({ key: STRING_KEYS.UNKNOWN_ERROR }),
|
||||
},
|
||||
})}
|
||||
</AlertMessage>
|
||||
)}
|
||||
<Styled.Trigger>
|
||||
<Styled.TriggerIcon>
|
||||
<Icon iconName={IconName.Caret} />
|
||||
|
||||
@@ -59,7 +59,7 @@ export const TransferStatusSteps = ({ status }: ElementProps) => {
|
||||
},
|
||||
];
|
||||
|
||||
const currentStatus = routeStatus[routeStatus?.length - 1];
|
||||
const currentStatus = routeStatus?.[routeStatus?.length - 1];
|
||||
|
||||
let currentStep = TransferStatusStep.Bridge;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { layoutMixins } from '@/styles/layoutMixins';
|
||||
|
||||
import { AbacusOrderStatus, AbacusOrderTypes, type Nullable } from '@/constants/abacus';
|
||||
import { ButtonAction } from '@/constants/buttons';
|
||||
import { STRING_KEYS, StringKey } from '@/constants/localization';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
|
||||
import { AssetIcon } from '@/components/AssetIcon';
|
||||
import { Button } from '@/components/Button';
|
||||
@@ -38,9 +38,6 @@ type ElementProps = {
|
||||
setIsOpen: (open: boolean) => void;
|
||||
};
|
||||
|
||||
const isStringKey = (key: Nullable<string>): key is StringKey =>
|
||||
key != null && STRING_KEYS.hasOwnProperty(key);
|
||||
|
||||
export const OrderDetailsDialog = ({ orderId, setIsOpen }: ElementProps) => {
|
||||
const stringGetter = useStringGetter();
|
||||
const dispatch = useDispatch();
|
||||
@@ -50,7 +47,7 @@ export const OrderDetailsDialog = ({ orderId, setIsOpen }: ElementProps) => {
|
||||
const { cancelOrder } = useSubaccount();
|
||||
|
||||
const {
|
||||
asset,
|
||||
asset = {},
|
||||
cancelReason,
|
||||
createdAtMilliseconds,
|
||||
expiresAtMilliseconds,
|
||||
@@ -60,7 +57,7 @@ export const OrderDetailsDialog = ({ orderId, setIsOpen }: ElementProps) => {
|
||||
price,
|
||||
reduceOnly,
|
||||
totalFilled,
|
||||
resources,
|
||||
resources = {},
|
||||
size,
|
||||
status,
|
||||
stepSizeDecimals,
|
||||
@@ -112,9 +109,9 @@ export const OrderDetailsDialog = ({ orderId, setIsOpen }: ElementProps) => {
|
||||
<Styled.Row>
|
||||
<Styled.StatusIcon iconName={statusIcon} color={statusIconColor} />
|
||||
<Styled.Status>
|
||||
{isStringKey(statusStringKey)
|
||||
{statusStringKey
|
||||
? stringGetter({ key: statusStringKey })
|
||||
: isStringKey(resources.statusStringKey)
|
||||
: resources.statusStringKey
|
||||
? stringGetter({ key: resources.statusStringKey })
|
||||
: undefined}
|
||||
</Styled.Status>
|
||||
@@ -124,9 +121,7 @@ export const OrderDetailsDialog = ({ orderId, setIsOpen }: ElementProps) => {
|
||||
{
|
||||
key: 'cancel-reason',
|
||||
label: stringGetter({ key: STRING_KEYS.CANCEL_REASON }),
|
||||
value: isStringKey(cancelReason)
|
||||
? stringGetter({ key: STRING_KEYS[cancelReason] })
|
||||
: undefined,
|
||||
value: cancelReason ? stringGetter({ key: STRING_KEYS[cancelReason] }) : undefined,
|
||||
},
|
||||
{
|
||||
key: 'amount',
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { useEffect } from 'react';
|
||||
import styled, { AnyStyledComponent } from 'styled-components';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { AbacusApiStatus } from '@/constants/abacus';
|
||||
import { CLIENT_NETWORK_CONFIGS } from '@/constants/networks';
|
||||
import { UNICODE } from '@/constants/unicode';
|
||||
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { useApiState, useStringGetter } from '@/hooks';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
@@ -17,6 +15,7 @@ import { NetworkSelectMenu } from '@/views/menus/NetworkSelectMenu';
|
||||
import { closeDialog } from '@/state/dialogs';
|
||||
|
||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||
import { getActiveDialog } from '@/state/dialogsSelectors';
|
||||
|
||||
type ElementProps = {
|
||||
preventClose?: boolean;
|
||||
@@ -28,9 +27,10 @@ export const ExchangeOfflineDialog = ({ preventClose, setIsOpen }: ElementProps)
|
||||
const stringGetter = useStringGetter();
|
||||
const { status, statusErrorMessage } = useApiState();
|
||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||
const activeDialog = useSelector(getActiveDialog, shallowEqual);
|
||||
|
||||
useEffect(() => {
|
||||
if (status === AbacusApiStatus.NORMAL) {
|
||||
if (activeDialog?.type === DialogTypes.ExchangeOffline && status === AbacusApiStatus.NORMAL) {
|
||||
dispatch(closeDialog());
|
||||
}
|
||||
}, [status, selectedNetwork]);
|
||||
@@ -44,11 +44,6 @@ export const ExchangeOfflineDialog = ({ preventClose, setIsOpen }: ElementProps)
|
||||
>
|
||||
<Styled.Content>
|
||||
<p>{statusErrorMessage}</p>
|
||||
{CLIENT_NETWORK_CONFIGS[selectedNetwork].dydxChainId === 'dydx-testnet-2' && (
|
||||
<Styled.Link href="https://status.v4testnet.dydx.exchange">
|
||||
{stringGetter({ key: STRING_KEYS.LEARN_MORE })} {UNICODE.ARROW_RIGHT}
|
||||
</Styled.Link>
|
||||
)}
|
||||
{import.meta.env.MODE !== 'production' && <NetworkSelectMenu />}
|
||||
</Styled.Content>
|
||||
</Dialog>
|
||||
|
||||
@@ -38,6 +38,7 @@ import { getTransferInputs } from '@/state/inputsSelectors';
|
||||
import abacusStateManager from '@/lib/abacus';
|
||||
import { MustBigNumber } from '@/lib/numbers';
|
||||
import { log } from '@/lib/telemetry';
|
||||
import { parseWalletError } from '@/lib/wallet';
|
||||
|
||||
import { ChainSelectMenu } from './ChainSelectMenu';
|
||||
import { TokenSelectMenu } from './TokenSelectMenu';
|
||||
@@ -286,12 +287,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
|
||||
const errorMessage = useMemo(() => {
|
||||
if (error) {
|
||||
return error?.message
|
||||
? stringGetter({
|
||||
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
|
||||
params: { ERROR_MESSAGE: error.message },
|
||||
})
|
||||
: stringGetter({ key: STRING_KEYS.SOMETHING_WENT_WRONG });
|
||||
return parseWalletError({ error, stringGetter }).message;
|
||||
}
|
||||
|
||||
if (fromAmount) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ButtonShape, ButtonSize } from '@/constants/buttons';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { CLIENT_NETWORK_CONFIGS } from '@/constants/networks';
|
||||
import { NumberSign, QUANTUM_MULTIPLIER } from '@/constants/numbers';
|
||||
import { DYDX_CHAIN_ASSET_COIN_DENOM, DYDX_CHAIN_INFO, DydxChainAsset } from '@/constants/wallets';
|
||||
import { DYDX_CHAIN_ASSET_COIN_DENOM, DydxChainAsset } from '@/constants/wallets';
|
||||
|
||||
import {
|
||||
useAccountBalance,
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { groupBy } from 'lodash';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { groupBy } from 'lodash';
|
||||
|
||||
import { type Notification, NotificationStatus } from '@/constants/notifications';
|
||||
import { useStringGetter } from '@/hooks';
|
||||
|
||||
import { useNotifications } from '@/hooks/useNotifications';
|
||||
import { CloseIcon } from '@/icons';
|
||||
|
||||
import { Button } from '@/components/Button';
|
||||
import { ButtonAction, ButtonSize } from '@/constants/buttons';
|
||||
@@ -15,7 +13,9 @@ import { DialogPlacement } from '@/components/Dialog';
|
||||
import { Output, OutputType } from '@/components/Output';
|
||||
import { IconButton } from '@/components/IconButton';
|
||||
import { Toolbar } from '@/components/Toolbar';
|
||||
import { CloseIcon } from '@/icons';
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
|
||||
type ElementProps = {
|
||||
@@ -27,8 +27,6 @@ export const NotificationsMenu = ({
|
||||
slotTrigger,
|
||||
placement = DialogPlacement.Sidebar,
|
||||
}: ElementProps) => {
|
||||
const stringGetter = useStringGetter();
|
||||
|
||||
const {
|
||||
notifications,
|
||||
getDisplayData,
|
||||
@@ -71,7 +69,7 @@ export const NotificationsMenu = ({
|
||||
.map(([status, notifications]) => ({
|
||||
group: status,
|
||||
groupLabel: {
|
||||
[NotificationStatus.Triggered]: stringGetter({ key: STRING_KEYS.NEW }),
|
||||
[NotificationStatus.Triggered]: 'New',
|
||||
// [NotificationStatus.Updated]: 'Updates',
|
||||
[NotificationStatus.Seen]: 'Seen',
|
||||
[NotificationStatus.Cleared]: 'Archived',
|
||||
@@ -137,7 +135,7 @@ export const NotificationsMenu = ({
|
||||
isOpen={isMenuOpen || placement === DialogPlacement.Inline}
|
||||
setIsOpen={setIsMenuOpen}
|
||||
items={items}
|
||||
title={stringGetter({ key: STRING_KEYS.NOTIFICATIONS })}
|
||||
title="Notifications"
|
||||
slotTrigger={
|
||||
<$TriggerContainer>
|
||||
{slotTrigger}
|
||||
@@ -170,7 +168,7 @@ export const NotificationsMenu = ({
|
||||
),
|
||||
}}
|
||||
>
|
||||
{stringGetter({ key: STRING_KEYS.CLEAR })}
|
||||
Clear All
|
||||
</Button>
|
||||
</$FooterToolbar>
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ import styled, { type AnyStyledComponent, css } from 'styled-components';
|
||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||
import { OrderSide } from '@dydxprotocol/v4-client-js';
|
||||
import type { ColumnSize } from '@react-types/table';
|
||||
import { Nullable } from '@dydxprotocol/v4-abacus';
|
||||
|
||||
import { type Asset, type SubaccountFill } from '@/constants/abacus';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { STRING_KEYS, StringGetterFunction } from '@/constants/localization';
|
||||
|
||||
import { Nullable } from '@dydxprotocol/abacus';
|
||||
import { useBreakpoints, useStringGetter } from '@/hooks';
|
||||
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user