Compare commits

...
Author SHA1 Message Date
Jonathan Fung 719bfd845e Revert "Bump abacus to enable ROC (#275)"
This reverts commit 2fc55bbe9f.
2024-02-05 16:16:46 -08:00
moo-onthelawn 2fc55bbe9f Bump abacus to enable ROC (#275)
* bump

* fixed
2024-02-05 16:39:33 -07:00
aleka 97452d7785 Add historical trading rewards gated by feature flag (#260)
* add historical trading rewards gated by feature flag
2024-02-05 12:24:12 -05:00
moo-onthelawn 2704baf378 Update PoweredBy string key to use all caps version (#272)
* bump package + update stringkey

* styling
2024-02-05 10:22:00 -05:00
Jared Vu 453d7c545e Convert opensource CSVs to JSON (#273)
* 🧱 use json instead of csv

* Fixed code size in MessageDetailsDialog
2024-02-02 22:01:18 -08:00
aleka f79c062808 use updated isaccountconnected check (#268)
* use updated isaccountconnected check

* address feedback
2024-02-02 15:12:52 -05:00
moo-onthelawn 7d30c80320 fix (#269) 2024-02-02 09:56:57 -05:00
moo-onthelawn 1c1d602bf3 TRCL-3491 Add "System" setting to themeing options, and match cmd+k dialog to new display preferences (#265)
* clean up

* clean up UI

* add functionality, without user exposure yet

* fix commit history

* remove unnecessary change

* lint

* implemented functionality

* clean up, add into cmd+k

* fix imports

* TRCL-3537 DisplaySettings + Themeing Polish (#267)

* wip

* make system panel reflect user prefs

* clean up PnlChart

* testing changes removal

* clean up logo styling

* fix export of dark dots background

* remove comment

* fix system panel color background
2024-02-01 20:03:10 -05:00
moo-onthelawn 23a96c1c20 TRCL-3533 Add green/red preference functionality to themeing (#256)
* add functionality, without user exposure yet

* TRCL-3535 Add green/red preference to display modal (#261)

* add functionality, without user exposure yet

* fix commit history

* remove unnecessary change

* lint

* update css

* audit of pos/neg colors

* fix flipping of disconnect/export keys colors

* review comments

* clean up naming of icon

* fix icon sizing

* small edit to story example
2024-02-01 19:29:11 -05:00
moo-onthelawn d81e6b3a2c TRCL-3520 Add entry point + modal for themeing (#255)
* wip

* clean up

* clean up UI
2024-02-01 19:01:53 -05:00
Jared Vu 732114a8de Use BigInt toString() for initialDepositAmount param (#266) 2024-02-01 11:52:04 -08:00
Jared Vu 2c220233e3 Update potential-market csv (#264)
* Update potential-market csv to match opensource guidance

* missing quantom-conversion-exponent

* fix filter

* alphabetize
2024-01-31 10:07:21 -08:00
aleka 8187e3615b add back clickable label to checkbox (#263)
* add back clickable label to checkbox

* make disabled optional
2024-01-30 16:42:05 -05:00
Bill c5888c2d5c Fix if conditioned before hooks (#262) 2024-01-30 13:18:10 -08:00
Jared VuandTaehoon Lee 793b522487 New Market Widget (#234)
* 🚧 New Market Form

* use dev-5 as default

* Additional UI work

* Add mock data

* 💄 More UI items

* 💄 add preview step

* 💄 Disable proposal button if not enough native tokens

* ✏️ Add disclaimer

* ✏️ fix combobox search

* 🚧 clean up components

* Add filters, modify, button

*  feat: Add details to New Market Dialog

* add assetName

* add helper method - spagetti code

* Update NewMarketMessageDetailsDialog, attempt to hook up client call

* 🚨 fix mobile safari overflow

* update init deposit to 10_001 whole token

* reduce delay block to 5

* Update mock data

* 🚧 SO FRIGGIN CLOSE

* 💄 style/ux nits

* add gov to registry

* PLS

* IT FUCKING WORKS

* Add assets

* FIX TICKER

* ADD NEW ASSETICON

* button width

* change default env to dev

* Remove mention of Impersonation dialog

* Market Search entry point

* uncomment feature

* Clean up NewMarketStep components

* Restore env.json

* Add space T.T

* useGlobalCommands fix types

* 🚧 feat: useNextClobPairId hook WIP

* Add potentialMarkets hook to parse CSV and hide new market entrypoints

* Use updated stringKeys

* Update localization, import nits

* bump v4-client

* add gov vars

* new useGovernanceVariables

* Add validator client calls: proposal fetch/submission

* Update token usage, utilize gov vars

* remove console log

* import nits

* NewMarketMessageDetailsDialog: Fix initial_deposit_amount

* NewMarketAgreement Dialog

* confirm flow

* Remove initialDepositAmount from mainnet env

* NewMarket: Add stringParams to step3

* Update csv

* update env.json add localization changes

* cleanup initialDepositAmountBN and decimals

* ^

* use undefined in place of 0 for DiffOutput

* remove hardcoded string

* Remove potentialMarket from csv

* Ensure user is out of liquidity tier modification

* bump localization, add additional details to receipts

* feedback addressed

* Add margin instead of space

* margin/padding nits, shorten filter method, remove ?. chaining

* additional feedback

---------

Co-authored-by: Taehoon Lee <19664986+ttl33@users.noreply.github.com>
2024-01-30 11:59:16 -08:00
John Huang 13d6610492 Added a TestFlight deployment so help native app testers (#257) 2024-01-30 11:38:39 -08:00
Bill 9cbb9fc2c6 remove cexdeposit testflag (#259) 2024-01-30 11:38:22 -08:00
Bill 91f5b89eb6 Coinbase Deposit (#251)
* Coinbase Deposit

* bump packages

* fix lock

* add testflag

* Address feedback

* fix chain select
2024-01-29 15:12:06 -08:00
aleka 41cc531700 downgrade follow-redirects since new version breaks safari (#254)
* downgrade follow-redirects

* explicit override
2024-01-29 11:53:38 -05:00
Brendan Chou 5aeb01f968 allow viewer to use the address test-flag to have a view-only experience of a wallet (#250)
* allow viewer to use  test-flag to specify a view-only experience of a wallet

* respond to CR

* lint
2024-01-26 17:08:51 -05:00
moo-onthelawn c9596de9c3 TRCL-3322 Implement reduce-only checkbox on frontend (#246)
* implemented

* eol lint again

* update with correct abacus version

* update localization to latest

* fix localization v
2024-01-26 17:03:32 -05:00
Bill cc8c724f09 bump v4-client (#252) 2024-01-26 15:38:47 -05:00
aleka ac07abea07 make sure view more is hidden when not num rows not specified (#249) 2024-01-25 15:10:16 -05:00
Rui 54e81cca80 Change iOS app scheme to dydx-t-v4 (#248) 2024-01-25 09:19:49 -08:00
Jared Vu 0ed1f33808 Canvas Orderbook (#227)
* 🚧 Canvas Orderbook

* 🚧 Add orderbookMap to aid in Canvas redraws

* enable mine column

* Merge main into canvas-orderbook-2

* 🧱 fix: Add orderbook constants file, remove console log, nits

* 💄 style: orderbook canvas text 13.5px -> 12px

* Updated constants and typings

* loadingSpace logic was slowing down ref mount
2024-01-24 23:16:33 -08:00
Bill 48e67f5681 Upgrade v4 clients and @cosmjs packages (#243)
* Upgrade v4-client and @cosmjs packages

* add comments
2024-01-24 15:29:43 -08:00
mike-dydx da1ac0d087 Update ios app scheme in env.json (#247) 2024-01-24 15:28:11 -08:00
moo-onthelawn 17fce5417a TRCL-3476 Create colorTokens file + new theme color types (#239)
* introduce tokens file + theme type

* fix lint error

* TRCL-3497 Use color tokens in app + tradingView widget (#240)

* update to use tokens, small fixes

* fix eol lint

* move usage style helper to lib/styles

* move files, fix text colors

* fix logo in light mode

* remove colors.css file

* small lint things

* add transparency to button + destructive borders
2024-01-24 17:03:44 -05:00
aleka b86a346be3 move governance staking panels out of trading rewards to profile on mobile (#242)
* add collapsible table

* update to add a TR inside table instead

* move governance staking panels to mobile profile
2024-01-24 15:33:01 -05:00
aleka 5cecc40a1c fix http->https in validator v4dev4 url (#245)
* fix http->https in validator v4dev4 url

* add faucet url
2024-01-24 15:32:40 -05:00
moo-onthelawn 7134fa541d add icons and update stories (#244) 2024-01-24 15:07:32 -05:00
aleka cd30c9c7d9 add collapsible table (#231)
* add collapsible table

* update to add a TR inside table instead
2024-01-24 12:26:32 -05:00
aleka 414e38afec Delay wagmi connection if remember me is enabled (#210)
* connect wagmi on deposit if remember me

* use alert message instead of button message

* clear input state when closing transfers forms to renable trade place order button
2024-01-23 13:45:14 -05:00
Bill e93850484b CCTP deposit/withdraw to throw error if nobleClient is not initialized (#215)
* CCTP deposit/withdraw to throw error if nobleClient is not initialized

* update error str
2024-01-22 09:55:26 -08:00
aleka 521b6d6135 test flag for sign in option (#236) 2024-01-17 16:22:17 -08:00
aleka 94772bf4dc bump abacus to remove base position notional (#235) 2024-01-17 15:52:02 -08:00
Adam Fraser 149f21e7e0 Add trailing blocks to NetworkStatus analytics event (#230) 2024-01-17 10:34:04 -05:00
aleka 0a3ef3a7ab bump abacus (#233) 2024-01-17 10:33:29 -05:00
Bill fef9935883 Support notification for trading rewards (#224)
* Support notification for trading rewards

* bump abacus

* Stack notifications based on notification type

* address comments
2024-01-16 10:19:48 -08:00
Bill c7a5b706e1 Fix toAmount/toAmountMin on withdraw (#232) 2024-01-15 10:31:23 -08:00
moo-onthelawn f304bb069a TRCL-1979 Show open positions / orders in portfolio sidebar (#228)
* add tags for open orders + positions

* clean up, use new num selector function

* update logic for open orders
2024-01-12 14:44:09 -05:00
Bill ad6aa1af49 Bump abacus, fix onboarding toAmount (#229) 2024-01-11 11:52:02 -08:00
Jared Vu 55b2c3fb4a Update Funding Chart Tooltip (#225)
* 🚧 depth chart

*  Fixed types and shortened FundingRateTooltip

* 💄 update depth chart color scale to use css var

* 💄 use layer-6 instead of text-1

* 🌐 Add localization, fix nits
2024-01-11 10:31:53 -08:00
moo-onthelawn 83bcde00eb TRCL-1623 Update Positions icon in nav sidebar (#226)
* update icon

* remove unused cube icon
2024-01-11 11:02:23 -05:00
Jared Vu e8024b9337 Add Sepolia (#222) 2024-01-09 16:35:19 -08:00
Jared Vu 8280e512bc Remove BasePositionNotional DetailItem (#223) 2024-01-09 14:01:38 -08:00
aleka b2234cb969 reorganize rewards vs. profile, update panel and accordion styling (#221)
* reorganize rewards vs. profile, update panel and accordion styling

* feedback
2024-01-09 16:57:02 -05:00
Bill 4bcb1f64ac Add Kava support for onboarding, and add token symbol to token select (#220)
* Add Kava support for onboarding, and add token symbol to token select

* bump abacus
2024-01-09 11:51:31 -08:00
BillandAleka Cheung 4a64d59546 Update launch incentives to season 2 (#218)
* Update launch incentives to season 2

* update api url

---------

Co-authored-by: Aleka Cheung <aforaleka@gmail.com>
2024-01-04 19:14:23 -08:00
Jared Vu 3fc43e8a12 Remove base from baseInitialMarginFraction (#209) 2024-01-04 15:35:05 -08:00
Jared Vu c24a9229a6 Imperator testnet indexer to be scaled down (#219) 2024-01-04 15:34:18 -08:00
aleka 90329d44d0 update lock file (#217) 2024-01-03 13:57:21 -08:00
Bill 9a02bd3f1c remove testnet cctp chains (#216) 2024-01-03 12:55:58 -08:00
aleka adba11b462 add accordion component and rewards help panel (#214) 2024-01-03 14:20:30 -05:00
Jared Vu 29526b927f Update deposit and withdrawal receipts (#212)
* Update receipts

* Remove duplicate const

* Restore env

* format

* Try using raw

* Use 3 spaces T.T

* copy from main

* Update abacus, display proper toAmount and toAmountMin

* nits
2024-01-03 09:56:01 -08:00
189 changed files with 54136 additions and 1957 deletions
+44 -31
View File
@@ -5,34 +5,32 @@ import styled from 'styled-components';
import { store } from '@/state/_store';
import { GlobalStyle } from '@/styles/globalStyle';
import { SelectMenu, SelectItem } from '@/components/SelectMenu';
import { AppThemeAndColorModeProvider } from '@/hooks/useAppThemeAndColorMode';
import {
AppTheme,
AppThemeSystemSetting,
AppColorMode,
setAppThemeSetting,
setAppColorMode,
} from '@/state/configs';
import { setLocaleLoaded } from '@/state/localization';
import '@/index.css';
import './ladle.css';
export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [theme, setTheme] = useState('Default theme');
const [theme, setTheme] = useState(AppTheme.Classic);
const [colorMode, setColorMode] = useState(AppColorMode.GreenUp);
useEffect(() => {
switch (theme) {
case 'Dark theme': {
document?.documentElement?.classList.remove('theme-light');
document?.documentElement?.classList.add('theme-dark');
break;
}
case 'Light theme': {
document?.documentElement?.classList.remove('theme-dark');
document?.documentElement?.classList.add('theme-light');
break;
}
default: {
document?.documentElement?.classList.remove('theme-dark', 'theme-light');
break;
}
}
}, [theme]);
store.dispatch(setAppThemeSetting(theme));
store.dispatch(setAppColorMode(colorMode));
}, [theme, colorMode]);
useEffect(() => {
store.dispatch(setLocaleLoaded(true));
@@ -42,34 +40,49 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
<Provider store={store}>
<StoryHeader>
<h4>Active Theme:</h4>
<SelectMenu
value={theme}
onValueChange={setTheme}
>
<SelectMenu value={theme} onValueChange={setTheme}>
{[
{
value: 'Default theme',
value: AppTheme.Classic,
label: 'Default theme',
},
{
value: 'Dark theme',
value: AppThemeSystemSetting.System,
label: 'System theme',
},
{
value: AppTheme.Dark,
label: 'Dark theme',
},
{
value: 'Light theme',
value: AppTheme.Light,
label: 'Light theme',
},
].map(({ value, label }) => (
<SelectItem
key={value}
value={value}
label={label}
/>
<SelectItem key={value} value={value} label={label} />
))}
</SelectMenu>
<h4>Active Color Mode:</h4>
<SelectMenu value={colorMode} onValueChange={setColorMode}>
{[
{
value: AppColorMode.GreenUp,
label: 'Green up',
},
{
value: AppColorMode.RedUp,
label: 'Red up',
},
].map(({ value, label }) => (
<SelectItem key={value} value={value} label={label} />
))}
</SelectMenu>
</StoryHeader>
<hr />
<StoryContent>{children}</StoryContent>
<AppThemeAndColorModeProvider>
<GlobalStyle />
<StoryContent>{children}</StoryContent>
</AppThemeAndColorModeProvider>
</Provider>
);
};
+17 -10
View File
@@ -33,17 +33,18 @@
"packageManager": "pnpm@8.6.6",
"dependencies": {
"@0xsquid/sdk": "^1.10.0",
"@cosmjs/amino": "^0.31.0",
"@cosmjs/crypto": "^0.31.0",
"@cosmjs/encoding": "^0.31.0",
"@cosmjs/proto-signing": "^0.31.0",
"@cosmjs/stargate": "^0.31.0",
"@cosmjs/tendermint-rpc": "^0.31.0",
"@dydxprotocol/v4-abacus": "^1.1.31",
"@dydxprotocol/v4-client-js": "^1.0.11",
"@dydxprotocol/v4-localization": "^1.1.5",
"@cosmjs/amino": "^0.32.1",
"@cosmjs/crypto": "^0.32.1",
"@cosmjs/encoding": "^0.32.1",
"@cosmjs/proto-signing": "^0.32.1",
"@cosmjs/stargate": "^0.32.1",
"@cosmjs/tendermint-rpc": "^0.32.1",
"@dydxprotocol/v4-abacus": "^1.4.0",
"@dydxprotocol/v4-client-js": "^1.0.20",
"@dydxprotocol/v4-localization": "^1.1.22",
"@ethersproject/providers": "^5.7.2",
"@js-joda/core": "^5.5.3",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-collapsible": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.4",
@@ -91,6 +92,7 @@
"buffer": "^6.0.3",
"cmdk": "^0.2.0",
"color": "^4.2.3",
"cosmjs-types": "^0.9.0",
"crypto-js": "^4.1.1",
"ethers": "^6.6.1",
"graz": "^0.0.43",
@@ -110,7 +112,7 @@
"reselect": "^4.1.8",
"styled-components": "^5.3.11",
"use-latest": "^1.2.1",
"viem": "^1.12.2",
"viem": "^1.20.0",
"wagmi": "^1.4.12"
},
"devDependencies": {
@@ -154,5 +156,10 @@
"vitest": "^0.32.2",
"w3name": "^1.0.8",
"web3.storage": "^4.5.4"
},
"pnpm": {
"overrides": {
"follow-redirects": "1.15.3"
}
}
}
+346 -152
View File
@@ -1,46 +1,48 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
overrides:
follow-redirects: 1.15.3
dependencies:
'@0xsquid/sdk':
specifier: ^1.10.0
version: 1.10.0
'@cosmjs/amino':
specifier: ^0.31.0
version: 0.31.0
specifier: ^0.32.1
version: 0.32.2
'@cosmjs/crypto':
specifier: ^0.31.0
version: 0.31.0
specifier: ^0.32.1
version: 0.32.2
'@cosmjs/encoding':
specifier: ^0.31.0
version: 0.31.0
specifier: ^0.32.1
version: 0.32.2
'@cosmjs/proto-signing':
specifier: ^0.31.0
version: 0.31.0
specifier: ^0.32.1
version: 0.32.2
'@cosmjs/stargate':
specifier: ^0.31.0
version: 0.31.0
specifier: ^0.32.1
version: 0.32.2
'@cosmjs/tendermint-rpc':
specifier: ^0.31.0
version: 0.31.0
specifier: ^0.32.1
version: 0.32.2
'@dydxprotocol/v4-abacus':
specifier: ^1.1.31
version: 1.1.31
specifier: ^1.4.0
version: 1.4.0
'@dydxprotocol/v4-client-js':
specifier: ^1.0.11
version: 1.0.11
specifier: ^1.0.20
version: 1.0.20
'@dydxprotocol/v4-localization':
specifier: ^1.1.5
version: 1.1.5
specifier: ^1.1.22
version: 1.1.22
'@ethersproject/providers':
specifier: ^5.7.2
version: 5.7.2
'@js-joda/core':
specifier: ^5.5.3
version: 5.5.3
'@radix-ui/react-accordion':
specifier: ^1.1.2
version: 1.1.2(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-checkbox':
specifier: ^1.0.4
version: 1.0.4(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)
@@ -182,6 +184,9 @@ dependencies:
color:
specifier: ^4.2.3
version: 4.2.3
cosmjs-types:
specifier: ^0.9.0
version: 0.9.0
crypto-js:
specifier: ^4.1.1
version: 4.1.1
@@ -240,11 +245,11 @@ dependencies:
specifier: ^1.2.1
version: 1.2.1(@types/react@18.2.14)(react@18.2.0)
viem:
specifier: ^1.12.2
version: 1.12.2(typescript@5.1.3)
specifier: ^1.20.0
version: 1.20.0(typescript@5.1.3)
wagmi:
specifier: ^1.4.12
version: 1.4.12(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(viem@1.12.2)
version: 1.4.13(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(viem@1.20.0)
devDependencies:
'@babel/core':
@@ -389,12 +394,12 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/@adraffy/ens-normalize@1.9.2:
resolution: {integrity: sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg==}
/@adraffy/ens-normalize@1.10.0:
resolution: {integrity: sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==}
dev: false
/@adraffy/ens-normalize@1.9.4:
resolution: {integrity: sha512-UK0bHA7hh9cR39V+4gl2/NnBBjoXIxkuWAPCaY4X7fbH4L/azIi7ilWOCjMUYfpJgraLUAqkRi2BqrjME8Rynw==}
/@adraffy/ens-normalize@1.9.2:
resolution: {integrity: sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg==}
dev: false
/@ampproject/remapping@2.2.1:
@@ -685,6 +690,15 @@ packages:
'@cosmjs/utils': 0.31.0
dev: false
/@cosmjs/amino@0.32.2:
resolution: {integrity: sha512-lcK5RCVm4OfdAooxKcF2+NwaDVVpghOq6o/A40c2mHXDUzUoRZ33VAHjVJ9Me6vOFxshrw/XEFn1f4KObntjYA==}
dependencies:
'@cosmjs/crypto': 0.32.2
'@cosmjs/encoding': 0.32.2
'@cosmjs/math': 0.32.2
'@cosmjs/utils': 0.32.2
dev: false
/@cosmjs/cosmwasm-stargate@0.30.1:
resolution: {integrity: sha512-W/6SLUCJAJGBN+sJLXouLZikVgmqDd9LCdlMzQaxczcCHTWeJAmRvOiZGSZaSy3shw/JN1qc6g6PKpvTVgj10A==}
dependencies:
@@ -738,7 +752,19 @@ packages:
'@cosmjs/encoding': 0.31.0
'@cosmjs/math': 0.31.0
'@cosmjs/utils': 0.31.0
'@noble/hashes': 1.3.1
'@noble/hashes': 1.3.3
bn.js: 5.2.1
elliptic: 6.5.4
libsodium-wrappers-sumo: 0.7.11
dev: false
/@cosmjs/crypto@0.32.2:
resolution: {integrity: sha512-RuxrYKzhrPF9g6NmU7VEq++Hn1vZJjqqJpZ9Tmw9lOYOV8BUsv+j/0BE86kmWi7xVJ7EwxiuxYsKuM8IR18CIA==}
dependencies:
'@cosmjs/encoding': 0.32.2
'@cosmjs/math': 0.32.2
'@cosmjs/utils': 0.32.2
'@noble/hashes': 1.3.3
bn.js: 5.2.1
elliptic: 6.5.4
libsodium-wrappers-sumo: 0.7.11
@@ -768,8 +794,8 @@ packages:
readonly-date: 1.0.0
dev: false
/@cosmjs/encoding@0.31.1:
resolution: {integrity: sha512-IuxP6ewwX6vg9sUJ8ocJD92pkerI4lyG8J5ynAM3NaX3q+n+uMoPRSQXNeL9bnlrv01FF1kIm8if/f5F7ZPtkA==}
/@cosmjs/encoding@0.32.2:
resolution: {integrity: sha512-WX7m1wLpA9V/zH0zRcz4EmgZdAv1F44g4dbXOgNj1eXZw1PIGR12p58OEkLN51Ha3S4DKRtCv5CkhK1KHEvQtg==}
dependencies:
base64-js: 1.5.1
bech32: 1.1.4
@@ -790,6 +816,13 @@ packages:
xstream: 11.14.0
dev: false
/@cosmjs/json-rpc@0.32.2:
resolution: {integrity: sha512-lan2lOgmz4yVE/HR8eCOSiII/1OudIulk8836koyIDCsPEpt6eKBuctnAD168vABGArKccLAo7Mr2gy9nrKrOQ==}
dependencies:
'@cosmjs/stream': 0.32.2
xstream: 11.14.0
dev: false
/@cosmjs/launchpad@0.27.1:
resolution: {integrity: sha512-DcFwGD/z5PK8CzO2sojDxa+Be9EIEtRZb2YawgVnw2Ht/p5FlNv+OVo8qlishpBdalXEN7FvQ1dVeDFEe9TuJw==}
dependencies:
@@ -822,8 +855,8 @@ packages:
bn.js: 5.2.1
dev: false
/@cosmjs/math@0.31.1:
resolution: {integrity: sha512-kiuHV6m6DSB8/4UV1qpFhlc4ul8SgLXTGRlYkYiIIP4l0YNeJ+OpPYaOlEgx4Unk2mW3/O2FWYj7Jc93+BWXng==}
/@cosmjs/math@0.32.2:
resolution: {integrity: sha512-b8+ruAAY8aKtVKWSft2IvtCVCUH1LigIlf9ALIiY8n9jtM4kMASiaRbQ/27etnSAInV88IaezKK9rQZrtxTjcw==}
dependencies:
bn.js: 5.2.1
dev: false
@@ -852,6 +885,17 @@ packages:
long: 4.0.0
dev: false
/@cosmjs/proto-signing@0.32.2:
resolution: {integrity: sha512-UV4WwkE3W3G3s7wwU9rizNcUEz2g0W8jQZS5J6/3fiN0mRPwtPKQ6EinPN9ASqcAJ7/VQH4/9EPOw7d6XQGnqw==}
dependencies:
'@cosmjs/amino': 0.32.2
'@cosmjs/crypto': 0.32.2
'@cosmjs/encoding': 0.32.2
'@cosmjs/math': 0.32.2
'@cosmjs/utils': 0.32.2
cosmjs-types: 0.9.0
dev: false
/@cosmjs/socket@0.30.1:
resolution: {integrity: sha512-r6MpDL+9N+qOS/D5VaxnPaMJ3flwQ36G+vPvYJsXArj93BjgyFB7BwWwXCQDzZ+23cfChPUfhbINOenr8N2Kow==}
dependencies:
@@ -876,6 +920,18 @@ packages:
- utf-8-validate
dev: false
/@cosmjs/socket@0.32.2:
resolution: {integrity: sha512-Qc8jaw4uSBJm09UwPgkqe3g9TBFx4ZR9HkXpwT6Z9I+6kbLerXPR0Gy3NSJFSUgxIfTpO8O1yqoWAyf0Ay17Mw==}
dependencies:
'@cosmjs/stream': 0.32.2
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/stargate@0.30.1:
resolution: {integrity: sha512-RdbYKZCGOH8gWebO7r6WvNnQMxHrNXInY/gPHPzMjbQF6UatA6fNM2G2tdgS5j5u7FTqlCI10stNXrknaNdzog==}
dependencies:
@@ -918,6 +974,25 @@ packages:
- utf-8-validate
dev: false
/@cosmjs/stargate@0.32.2:
resolution: {integrity: sha512-AsJa29fT7Jd4xt9Ai+HMqhyj7UQu7fyYKdXj/8+/9PD74xe6lZSYhQPcitUmMLJ1ckKPgXSk5Dd2LbsQT0IhZg==}
dependencies:
'@confio/ics23': 0.6.8
'@cosmjs/amino': 0.32.2
'@cosmjs/encoding': 0.32.2
'@cosmjs/math': 0.32.2
'@cosmjs/proto-signing': 0.32.2
'@cosmjs/stream': 0.32.2
'@cosmjs/tendermint-rpc': 0.32.2
'@cosmjs/utils': 0.32.2
cosmjs-types: 0.9.0
xstream: 11.14.0
transitivePeerDependencies:
- bufferutil
- debug
- utf-8-validate
dev: false
/@cosmjs/stream@0.30.1:
resolution: {integrity: sha512-Fg0pWz1zXQdoxQZpdHRMGvUH5RqS6tPv+j9Eh7Q953UjMlrwZVo0YFLC8OTf/HKVf10E4i0u6aM8D69Q6cNkgQ==}
dependencies:
@@ -930,6 +1005,12 @@ packages:
xstream: 11.14.0
dev: false
/@cosmjs/stream@0.32.2:
resolution: {integrity: sha512-gpCufLfHAD8Zp1ZKge7AHbDf4RA0TZp66wZY6JaQR5bSiEF2Drjtp4mwXZPGejtaUMnaAgff3LrUzPJfKYdQwg==}
dependencies:
xstream: 11.14.0
dev: false
/@cosmjs/tendermint-rpc@0.30.1:
resolution: {integrity: sha512-Z3nCwhXSbPZJ++v85zHObeUggrEHVfm1u18ZRwXxFE9ZMl5mXTybnwYhczuYOl7KRskgwlB+rID0WYACxj4wdQ==}
dependencies:
@@ -968,6 +1049,25 @@ packages:
- utf-8-validate
dev: false
/@cosmjs/tendermint-rpc@0.32.2:
resolution: {integrity: sha512-DXyJHDmcAfCix4H/7/dKR0UMdshP01KxJOXHdHxBCbLIpck94BsWD3B2ZTXwfA6sv98so9wOzhp7qGQa5malxg==}
dependencies:
'@cosmjs/crypto': 0.32.2
'@cosmjs/encoding': 0.32.2
'@cosmjs/json-rpc': 0.32.2
'@cosmjs/math': 0.32.2
'@cosmjs/socket': 0.32.2
'@cosmjs/stream': 0.32.2
'@cosmjs/utils': 0.32.2
axios: 1.6.5
readonly-date: 1.0.0
xstream: 11.14.0
transitivePeerDependencies:
- bufferutil
- debug
- utf-8-validate
dev: false
/@cosmjs/utils@0.27.1:
resolution: {integrity: sha512-VG7QPDiMUzVPxRdJahDV8PXxVdnuAHiIuG56hldV4yPnOz/si/DLNd7VAUUA5923b6jS1Hhev0Hr6AhEkcxBMg==}
dev: false
@@ -980,52 +1080,53 @@ packages:
resolution: {integrity: sha512-nNcycZWUYLNJlrIXgpcgVRqdl6BXjF4YlXdxobQWpW9Tikk61bEGeAFhDYtC0PwHlokCNw0KxWiHGJL4nL7Q5A==}
dev: false
/@cosmjs/utils@0.31.1:
resolution: {integrity: sha512-n4Se1wu4GnKwztQHNFfJvUeWcpvx3o8cWhSbNs9JQShEuB3nv3R5lqFBtDCgHZF/emFQAP+ZjF8bTfCs9UBGhA==}
/@cosmjs/utils@0.32.2:
resolution: {integrity: sha512-Gg5t+eR7vPJMAmhkFt6CZrzPd0EKpAslWwk5rFVYZpJsM8JG5KT9XQ99hgNM3Ov6ScNoIWbXkpX27F6A9cXR4Q==}
dev: false
/@cush/relative@1.0.0:
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
dev: true
/@dydxprotocol/v4-abacus@1.1.31:
resolution: {integrity: sha512-CBfK78u/y2/9KR/w2f7IGhU6tKt/seoKHlsal0vk2WlJsjXnlTKoOQ3HpCSGoMmI5ZLQeqbFClvNH4RZLhEwzg==}
/@dydxprotocol/v4-abacus@1.4.0:
resolution: {integrity: sha512-mkdkXQXTVF1K6UmZwIwLC9gjsXg+Nt3h5/iW+WriVv1cUMPmHfPyRWL31eDDvkVO5UeECf05kiYXPk1y+7dPuA==}
dev: false
/@dydxprotocol/v4-client-js@1.0.11:
resolution: {integrity: sha512-rJNFGTO+HU1GQppXeRLKXNk4HWx/h+DjU2sUCieEv5mnRIMQpLw8dH/L+Uyhxx2oovccY1MaKB4Fr9IngdrF0A==}
/@dydxprotocol/v4-client-js@1.0.20:
resolution: {integrity: sha512-dXKW2NC1XlVVIRKvHWVDofLZSCPTJAaRY5eXzxH5CcXpnl2kdXorr7ykqWZxW0jHFPWWvRSJtUDqZN1qFrEe/w==}
dependencies:
'@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
'@cosmjs/utils': 0.31.1
'@dydxprotocol/v4-proto': 0.4.1
'@cosmjs/amino': 0.32.2
'@cosmjs/encoding': 0.32.2
'@cosmjs/math': 0.32.2
'@cosmjs/proto-signing': 0.32.2
'@cosmjs/stargate': 0.32.2
'@cosmjs/tendermint-rpc': 0.32.2
'@cosmjs/utils': 0.32.2
'@dydxprotocol/v4-proto': 4.0.0-dev.0
'@osmonauts/lcd': 0.6.0
'@scure/bip32': 1.3.2
'@scure/bip39': 1.2.1
axios: 1.1.3
bech32: 1.1.4
bignumber.js: 9.1.1
cosmjs-types: 0.9.0
ethereum-cryptography: 2.1.2
ethers: 6.6.1
long: 4.0.0
protobufjs: 6.11.4
ws: 8.15.0
ws: 8.15.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)
transitivePeerDependencies:
- bufferutil
- debug
- utf-8-validate
dev: false
/@dydxprotocol/v4-localization@1.1.5:
resolution: {integrity: sha512-Y25yuCLFaK3v/81B60lc3qthaWwJn1fNJuYQdOtgnmOhLNqI4YRryUncLkbjdB5xd4QODq5KZikP34pLKX9sgA==}
/@dydxprotocol/v4-localization@1.1.22:
resolution: {integrity: sha512-DURyvBx0qjXmtebSRMW4ZdTsX5xI8Mb6c7LQ8WUPU0O3Jr7n7iUT/phzZszTpwNOMFFMukMFtn7fHCgijw1TOg==}
dev: false
/@dydxprotocol/v4-proto@0.4.1:
resolution: {integrity: sha512-2pBkokufWcxfIpiXE6QuQOBXUe154OTp6ojCIdOPW9TFLxzchoygxXnb5dL6rAQVNj9Qbg+hhXBllutt4m99dw==}
/@dydxprotocol/v4-proto@4.0.0-dev.0:
resolution: {integrity: sha512-PC/xq5YJIisAd3jjIULJGrnujbrYkr5h4ehepnLc6U34nJT720iumKVMiPaezwRC+kHKTI1culpKNnlMnbeYBA==}
dependencies:
protobufjs: 6.11.4
dev: false
@@ -2320,6 +2421,35 @@ packages:
'@babel/runtime': 7.22.10
dev: false
/@radix-ui/react-accordion@1.1.2(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
dependencies:
'@babel/runtime': 7.22.10
'@radix-ui/primitive': 1.0.1
'@radix-ui/react-collapsible': 1.0.3(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.14)(react@18.2.0)
'@radix-ui/react-context': 1.0.1(@types/react@18.2.14)(react@18.2.0)
'@radix-ui/react-direction': 1.0.1(@types/react@18.2.14)(react@18.2.0)
'@radix-ui/react-id': 1.0.1(@types/react@18.2.14)(react@18.2.0)
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.14)(react@18.2.0)
'@types/react': 18.2.14
'@types/react-dom': 18.2.6
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==}
peerDependencies:
@@ -4858,7 +4988,7 @@ packages:
resolution: {integrity: sha512-XJbEPuaVc7b9n23MqlF6c+ToYIS3f7P2Sel8f3cSBQ9WORE4xrSuvhMpK9fDSFqJ7by/brc+rmJR/5HViRr0/w==}
dependencies:
'@safe-global/safe-gateway-typescript-sdk': 3.9.0
viem: 1.12.2(typescript@5.1.3)
viem: 1.20.0(typescript@5.1.3)
transitivePeerDependencies:
- bufferutil
- encoding
@@ -5362,31 +5492,13 @@ packages:
use-sync-external-store: 1.2.0(react@18.2.0)
dev: false
/@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.36.1):
resolution: {integrity: sha512-EmNnYpvFYpxS4j5WFeNmfVVBxqq4RDnEFDBZwNKRfb4pzukcx/hcWtwqFk7Qj0EI4Dk8QGl239MEYwJbAc83tQ==}
peerDependencies:
'@tanstack/react-query': ^4.32.6
dependencies:
'@tanstack/query-persist-client-core': 4.32.6
'@tanstack/react-query': 4.32.6(react-dom@18.2.0)(react@18.2.0)
dev: false
/@tanstack/react-query@4.32.6(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-AITu/IKJJJXsHHeXNBy5bclu12t08usMCY0vFC2dh9SP/w6JAk5U9GwfjOIPj3p+ATADZvxQPe8UiCtMLNeQbg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
react-native: '*'
peerDependenciesMeta:
react-dom:
optional: true
react-native:
optional: true
dependencies:
'@tanstack/query-core': 4.32.6
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
use-sync-external-store: 1.2.0(react@18.2.0)
'@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react@18.2.0)
dev: false
/@tanstack/react-query@4.36.1(react-dom@18.2.0)(react@18.2.0):
@@ -5592,6 +5704,7 @@ packages:
/@types/node@20.3.1:
resolution: {integrity: sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==}
dev: true
/@types/normalize-package-data@2.4.1:
resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
@@ -5653,12 +5766,6 @@ packages:
'@types/node': 20.10.5
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):
resolution: {integrity: sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -6155,8 +6262,8 @@ packages:
pretty-format: 27.5.1
dev: true
/@wagmi/connectors@3.1.10(@types/react@18.2.14)(react@18.2.0)(typescript@5.1.3)(viem@1.12.2):
resolution: {integrity: sha512-ZLJC1QaeiZarkF07Cr9mOlVjPO1Lf5TBx+JKBms2y5fUIXlKrxCfQgO/gDCureboI+Us2X3IRI659+XacSGpbA==}
/@wagmi/connectors@3.1.11(@types/react@18.2.14)(react@18.2.0)(typescript@5.1.3)(viem@1.20.0):
resolution: {integrity: sha512-wzxp9f9PtSUFjDUP/QDjc1t7HON4D8wrVKsw35ejdO8hToDpx1gU9lwH/47Zo/1zExGezQc392sjoHSszYd7OA==}
peerDependencies:
typescript: '>=5.0.4'
viem: '>=0.3.35'
@@ -6167,14 +6274,14 @@ packages:
'@coinbase/wallet-sdk': 3.7.1
'@safe-global/safe-apps-provider': 0.18.1(typescript@5.1.3)
'@safe-global/safe-apps-sdk': 8.1.0(typescript@5.1.3)
'@walletconnect/ethereum-provider': 2.10.6(@types/react@18.2.14)(react@18.2.0)
'@walletconnect/ethereum-provider': 2.11.0(@types/react@18.2.14)(react@18.2.0)
'@walletconnect/legacy-provider': 2.0.0
'@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0)
'@walletconnect/utils': 2.10.2
'@walletconnect/utils': 2.11.0
abitype: 0.8.7(typescript@5.1.3)
eventemitter3: 4.0.7
typescript: 5.1.3
viem: 1.12.2(typescript@5.1.3)
viem: 1.20.0(typescript@5.1.3)
transitivePeerDependencies:
- '@azure/app-configuration'
- '@azure/cosmos'
@@ -6197,8 +6304,8 @@ packages:
- zod
dev: false
/@wagmi/core@1.4.12(@types/react@18.2.14)(react@18.2.0)(typescript@5.1.3)(viem@1.12.2):
resolution: {integrity: sha512-bLcYmmGgjtl3jAGo8X3Sm6oUwsdjbVxFMu9SWnwHdE4S9JdYeWM57dEhQgq8SYul2yQ7yY2/gimBf1Or0Ky3dQ==}
/@wagmi/core@1.4.13(@types/react@18.2.14)(react@18.2.0)(typescript@5.1.3)(viem@1.20.0):
resolution: {integrity: sha512-ytMCvXbBOgfDu9Qw67279wq/jNEe7EZLjLyekX7ROnvHRADqFr3lwZI6ih41UmtRZAmXAx8Ghyuqy154EjB5mQ==}
peerDependencies:
typescript: '>=5.0.4'
viem: '>=0.3.35'
@@ -6206,11 +6313,11 @@ packages:
typescript:
optional: true
dependencies:
'@wagmi/connectors': 3.1.10(@types/react@18.2.14)(react@18.2.0)(typescript@5.1.3)(viem@1.12.2)
'@wagmi/connectors': 3.1.11(@types/react@18.2.14)(react@18.2.0)(typescript@5.1.3)(viem@1.20.0)
abitype: 0.8.7(typescript@5.1.3)
eventemitter3: 4.0.7
typescript: 5.1.3
viem: 1.12.2(typescript@5.1.3)
viem: 1.20.0(typescript@5.1.3)
zustand: 4.4.7(@types/react@18.2.14)(react@18.2.0)
transitivePeerDependencies:
- '@azure/app-configuration'
@@ -6272,6 +6379,45 @@ packages:
- utf-8-validate
dev: false
/@walletconnect/core@2.11.0:
resolution: {integrity: sha512-2Tjp5BCevI7dbmqo/OrCjX4tqgMqwJNQLlQAlphqPfvwlF9+tIu6pGcVbSN3U9zyXzWIZCeleqEaWUeSeET4Ew==}
dependencies:
'@walletconnect/heartbeat': 1.2.1
'@walletconnect/jsonrpc-provider': 1.0.13
'@walletconnect/jsonrpc-types': 1.0.3
'@walletconnect/jsonrpc-utils': 1.0.8
'@walletconnect/jsonrpc-ws-connection': 1.0.14
'@walletconnect/keyvaluestorage': 1.1.1
'@walletconnect/logger': 2.0.1
'@walletconnect/relay-api': 1.0.9
'@walletconnect/relay-auth': 1.0.4
'@walletconnect/safe-json': 1.0.2
'@walletconnect/time': 1.0.2
'@walletconnect/types': 2.11.0
'@walletconnect/utils': 2.11.0
events: 3.3.0
isomorphic-unfetch: 3.1.0
lodash.isequal: 4.5.0
uint8arrays: 3.1.1
transitivePeerDependencies:
- '@azure/app-configuration'
- '@azure/cosmos'
- '@azure/data-tables'
- '@azure/identity'
- '@azure/keyvault-secrets'
- '@azure/storage-blob'
- '@capacitor/preferences'
- '@netlify/blobs'
- '@planetscale/database'
- '@react-native-async-storage/async-storage'
- '@upstash/redis'
- '@vercel/kv'
- bufferutil
- encoding
- supports-color
- utf-8-validate
dev: false
/@walletconnect/crypto@1.0.3:
resolution: {integrity: sha512-+2jdORD7XQs76I2Odgr3wwrtyuLUXD/kprNVsjWRhhhdO9Mt6WqVzOPu0/t7OHSmgal8k7SoBQzUc5hu/8zL/g==}
dependencies:
@@ -6297,18 +6443,18 @@ packages:
tslib: 1.14.1
dev: false
/@walletconnect/ethereum-provider@2.10.6(@types/react@18.2.14)(react@18.2.0):
resolution: {integrity: sha512-bBQ+yUfxLv8VxNttgNKY7nED35gSVayO/BnLHbNKvyV1gpvSCla5mWB9MsXuQs70MK0g+/qtgRVSrOtdSubaNQ==}
/@walletconnect/ethereum-provider@2.11.0(@types/react@18.2.14)(react@18.2.0):
resolution: {integrity: sha512-YrTeHVjuSuhlUw7SQ6xBJXDuJ6iAC+RwINm9nVhoKYJSHAy3EVSJZOofMKrnecL0iRMtD29nj57mxAInIBRuZA==}
dependencies:
'@walletconnect/jsonrpc-http-connection': 1.0.7
'@walletconnect/jsonrpc-provider': 1.0.13
'@walletconnect/jsonrpc-types': 1.0.3
'@walletconnect/jsonrpc-utils': 1.0.8
'@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0)
'@walletconnect/sign-client': 2.10.6
'@walletconnect/types': 2.10.6
'@walletconnect/universal-provider': 2.10.6
'@walletconnect/utils': 2.10.6
'@walletconnect/sign-client': 2.11.0
'@walletconnect/types': 2.11.0
'@walletconnect/universal-provider': 2.11.0
'@walletconnect/utils': 2.11.0
events: 3.3.0
transitivePeerDependencies:
- '@azure/app-configuration'
@@ -6576,20 +6722,17 @@ packages:
- utf-8-validate
dev: false
/@walletconnect/time@1.0.2:
resolution: {integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==}
dependencies:
tslib: 1.14.1
dev: false
/@walletconnect/types@2.10.2:
resolution: {integrity: sha512-luNV+07Wdla4STi9AejseCQY31tzWKQ5a7C3zZZaRK/di+rFaAAb7YW04OP4klE7tw/mJRGPTlekZElmHxO8kQ==}
/@walletconnect/sign-client@2.11.0:
resolution: {integrity: sha512-H2ukscibBS+6WrzQWh+WyVBqO5z4F5et12JcwobdwgHnJSlqIoZxqnUYYWNCI5rUR5UKsKWaUyto4AE9N5dw4Q==}
dependencies:
'@walletconnect/core': 2.11.0
'@walletconnect/events': 1.0.1
'@walletconnect/heartbeat': 1.2.1
'@walletconnect/jsonrpc-types': 1.0.3
'@walletconnect/keyvaluestorage': 1.1.1
'@walletconnect/jsonrpc-utils': 1.0.8
'@walletconnect/logger': 2.0.1
'@walletconnect/time': 1.0.2
'@walletconnect/types': 2.11.0
'@walletconnect/utils': 2.11.0
events: 3.3.0
transitivePeerDependencies:
- '@azure/app-configuration'
@@ -6604,7 +6747,16 @@ packages:
- '@react-native-async-storage/async-storage'
- '@upstash/redis'
- '@vercel/kv'
- bufferutil
- encoding
- supports-color
- utf-8-validate
dev: false
/@walletconnect/time@1.0.2:
resolution: {integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==}
dependencies:
tslib: 1.14.1
dev: false
/@walletconnect/types@2.10.6:
@@ -6632,17 +6784,42 @@ packages:
- supports-color
dev: false
/@walletconnect/universal-provider@2.10.6:
resolution: {integrity: sha512-CEivusqqoD31BhCTKp08DnrccfGjwD9MFjZs5BNRorDteRFE8zVm9LmP6DSiNJCw82ZajGlZThggLQ/BAATfwA==}
/@walletconnect/types@2.11.0:
resolution: {integrity: sha512-AB5b1lrEbCGHxqS2vqfCkIoODieH+ZAUp9rA1O2ftrhnqDJiJK983Df87JhYhECsQUBHHfALphA8ydER0q+9sw==}
dependencies:
'@walletconnect/events': 1.0.1
'@walletconnect/heartbeat': 1.2.1
'@walletconnect/jsonrpc-types': 1.0.3
'@walletconnect/keyvaluestorage': 1.1.1
'@walletconnect/logger': 2.0.1
events: 3.3.0
transitivePeerDependencies:
- '@azure/app-configuration'
- '@azure/cosmos'
- '@azure/data-tables'
- '@azure/identity'
- '@azure/keyvault-secrets'
- '@azure/storage-blob'
- '@capacitor/preferences'
- '@netlify/blobs'
- '@planetscale/database'
- '@react-native-async-storage/async-storage'
- '@upstash/redis'
- '@vercel/kv'
- supports-color
dev: false
/@walletconnect/universal-provider@2.11.0:
resolution: {integrity: sha512-zgJv8jDvIMP4Qse/D9oIRXGdfoNqonsrjPZanQ/CHNe7oXGOBiQND2IIeX+tS0H7uNA0TPvctljCLiIN9nw4eA==}
dependencies:
'@walletconnect/jsonrpc-http-connection': 1.0.7
'@walletconnect/jsonrpc-provider': 1.0.13
'@walletconnect/jsonrpc-types': 1.0.3
'@walletconnect/jsonrpc-utils': 1.0.8
'@walletconnect/logger': 2.0.1
'@walletconnect/sign-client': 2.10.6
'@walletconnect/types': 2.10.6
'@walletconnect/utils': 2.10.6
'@walletconnect/sign-client': 2.11.0
'@walletconnect/types': 2.11.0
'@walletconnect/utils': 2.11.0
events: 3.3.0
transitivePeerDependencies:
- '@azure/app-configuration'
@@ -6663,8 +6840,8 @@ packages:
- utf-8-validate
dev: false
/@walletconnect/utils@2.10.2:
resolution: {integrity: sha512-syxXRpc2yhSknMu3IfiBGobxOY7fLfLTJuw+ppKaeO6WUdZpIit3wfuGOcc0Ms3ZPFCrGfyGOoZsCvgdXtptRg==}
/@walletconnect/utils@2.10.6:
resolution: {integrity: sha512-oRsWWhN2+hi3aiDXrQEOfysz6FHQJGXLsNQPVt+WIBJplO6Szmdau9dbleD88u1iiT4GKPqE0R9FOYvvPm1H/w==}
dependencies:
'@stablelib/chacha20poly1305': 1.0.1
'@stablelib/hkdf': 1.0.1
@@ -6674,7 +6851,7 @@ packages:
'@walletconnect/relay-api': 1.0.9
'@walletconnect/safe-json': 1.0.2
'@walletconnect/time': 1.0.2
'@walletconnect/types': 2.10.2
'@walletconnect/types': 2.10.6
'@walletconnect/window-getters': 1.0.1
'@walletconnect/window-metadata': 1.0.1
detect-browser: 5.3.0
@@ -6696,8 +6873,8 @@ packages:
- supports-color
dev: false
/@walletconnect/utils@2.10.6:
resolution: {integrity: sha512-oRsWWhN2+hi3aiDXrQEOfysz6FHQJGXLsNQPVt+WIBJplO6Szmdau9dbleD88u1iiT4GKPqE0R9FOYvvPm1H/w==}
/@walletconnect/utils@2.11.0:
resolution: {integrity: sha512-hxkHPlTlDQILHfIKXlmzgNJau/YcSBC3XHUSuZuKZbNEw3duFT6h6pm3HT/1+j1a22IG05WDsNBuTCRkwss+BQ==}
dependencies:
'@stablelib/chacha20poly1305': 1.0.1
'@stablelib/hkdf': 1.0.1
@@ -6707,7 +6884,7 @@ packages:
'@walletconnect/relay-api': 1.0.9
'@walletconnect/safe-json': 1.0.2
'@walletconnect/time': 1.0.2
'@walletconnect/types': 2.10.6
'@walletconnect/types': 2.11.0
'@walletconnect/window-getters': 1.0.1
'@walletconnect/window-metadata': 1.0.1
detect-browser: 5.3.0
@@ -7301,7 +7478,7 @@ packages:
/axios@0.21.4:
resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==}
dependencies:
follow-redirects: 1.15.2
follow-redirects: 1.15.3
transitivePeerDependencies:
- debug
dev: false
@@ -7309,7 +7486,7 @@ packages:
/axios@0.27.2:
resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==}
dependencies:
follow-redirects: 1.15.2
follow-redirects: 1.15.3
form-data: 4.0.0
transitivePeerDependencies:
- debug
@@ -7318,7 +7495,17 @@ packages:
/axios@1.1.3:
resolution: {integrity: sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==}
dependencies:
follow-redirects: 1.15.2
follow-redirects: 1.15.3
form-data: 4.0.0
proxy-from-env: 1.1.0
transitivePeerDependencies:
- debug
dev: false
/axios@1.6.5:
resolution: {integrity: sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==}
dependencies:
follow-redirects: 1.15.3
form-data: 4.0.0
proxy-from-env: 1.1.0
transitivePeerDependencies:
@@ -7982,11 +8169,15 @@ packages:
protobufjs: 6.11.4
dev: false
/cosmjs-types@0.9.0:
resolution: {integrity: sha512-MN/yUe6mkJwHnCFfsNPeCfXVhyxHYW6c/xDUzrSbBycYzw++XvWDMJArXp2pLdgD6FQ8DW79vkPjeNKVrXaHeQ==}
dev: false
/cosmos-directory-client@0.0.6:
resolution: {integrity: sha512-WIdaQ8uW1vIbYvNnAVunkC6yxTrneJC7VQ5UUQ0kuw8b0C0A39KTIpoQHCfc8tV7o9vF4niwRhdXEdfAgQEsQQ==}
dependencies:
cosmos-directory-types: 0.0.6
node-fetch-native: 1.4.1
node-fetch-native: 1.6.1
dev: false
/cosmos-directory-types@0.0.6:
@@ -9337,8 +9528,8 @@ packages:
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
dev: true
/follow-redirects@1.15.2:
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
/follow-redirects@1.15.3:
resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
@@ -10406,6 +10597,15 @@ packages:
engines: {node: '>=12'}
dev: true
/isomorphic-unfetch@3.1.0:
resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==}
dependencies:
node-fetch: 2.6.12
unfetch: 4.2.0
transitivePeerDependencies:
- encoding
dev: false
/isomorphic-ws@4.0.1(ws@7.5.9):
resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==}
peerDependencies:
@@ -10414,8 +10614,8 @@ packages:
ws: 7.5.9
dev: false
/isomorphic-ws@5.0.0(ws@8.13.0):
resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==}
/isows@1.0.3(ws@8.13.0):
resolution: {integrity: sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==}
peerDependencies:
ws: '*'
dependencies:
@@ -11748,8 +11948,8 @@ packages:
engines: {node: '>=10.5.0'}
dev: true
/node-fetch-native@1.4.1:
resolution: {integrity: sha512-NsXBU0UgBxo2rQLOeWNZqS3fvflWePMECr8CoSWoSTqCqGbVVsvl9vZu1HfQicYN0g5piV9Gh8RTEvo/uP752w==}
/node-fetch-native@1.6.1:
resolution: {integrity: sha512-bW9T/uJDPAJB2YNYEpWzE54U5O3MQidXsOyTfnbKYtTtFexRvGzb1waphBN4ZwP6EcIvYYEOwW0b72BpAqydTw==}
dev: false
/node-fetch@2.6.12:
@@ -11895,7 +12095,7 @@ packages:
resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==}
dependencies:
destr: 2.0.2
node-fetch-native: 1.4.1
node-fetch-native: 1.6.1
ufo: 1.3.2
dev: false
@@ -13783,10 +13983,14 @@ packages:
consola: 3.2.3
defu: 6.1.3
mime: 3.0.0
node-fetch-native: 1.4.1
node-fetch-native: 1.6.1
pathe: 1.1.1
dev: false
/unfetch@4.2.0:
resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==}
dev: false
/unified@10.1.2:
resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==}
dependencies:
@@ -13906,7 +14110,7 @@ packages:
listhen: 1.5.5
lru-cache: 10.1.0
mri: 1.2.0
node-fetch-native: 1.4.1
node-fetch-native: 1.6.1
ofetch: 1.3.3
ufo: 1.3.2
transitivePeerDependencies:
@@ -14140,22 +14344,21 @@ packages:
vfile-message: 3.1.4
dev: true
/viem@1.12.2(typescript@5.1.3):
resolution: {integrity: sha512-aCaUCyg72ES+jK4s6tVYOMnOt4if71RwzgiUAUpAuaCgvHFfh9DCnwuEfwkxEZLE2vafOsirgJ3fcn7nsDVQoQ==}
/viem@1.20.0(typescript@5.1.3):
resolution: {integrity: sha512-yPjV9pJr10xi28C/9LEvs5zdZNEMiru3Kz7nufghVYABJAfeSkoZQXb6b23n7MscS7c55JO5nmUI3xKkd9g6Yg==}
peerDependencies:
typescript: '>=5.0.4'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@adraffy/ens-normalize': 1.9.4
'@adraffy/ens-normalize': 1.10.0
'@noble/curves': 1.2.0
'@noble/hashes': 1.3.2
'@scure/bip32': 1.3.2
'@scure/bip39': 1.2.1
'@types/ws': 8.5.6
abitype: 0.9.8(typescript@5.1.3)
isomorphic-ws: 5.0.0(ws@8.13.0)
isows: 1.0.3(ws@8.13.0)
typescript: 5.1.3
ws: 8.13.0
transitivePeerDependencies:
@@ -14325,8 +14528,8 @@ packages:
- supports-color
dev: true
/wagmi@1.4.12(@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-QRxpjhdMlZmbYTfn9VQkQMKq+l3kwA1O7tF10vaykPrjbGX+IIlyn72ib9oqW9BfQO7n/Sf/mnVz1zbxRhGPWA==}
/wagmi@1.4.13(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(viem@1.20.0):
resolution: {integrity: sha512-AScVYFjqNt1wMgL99Bob7MLdhoTZ3XKiOZL5HVBdy4W1sh7QodA3gQ8IsmTuUrQ7oQaTxjiXEhwg7sWNrPBvJA==}
peerDependencies:
react: '>=17.0.0'
typescript: '>=5.0.4'
@@ -14336,14 +14539,14 @@ packages:
optional: true
dependencies:
'@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-persist-client': 4.32.6(@tanstack/react-query@4.32.6)
'@wagmi/core': 1.4.12(@types/react@18.2.14)(react@18.2.0)(typescript@5.1.3)(viem@1.12.2)
'@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react@18.2.0)
'@tanstack/react-query-persist-client': 4.32.6(@tanstack/react-query@4.36.1)
'@wagmi/core': 1.4.13(@types/react@18.2.14)(react@18.2.0)(typescript@5.1.3)(viem@1.20.0)
abitype: 0.8.7(typescript@5.1.3)
react: 18.2.0
typescript: 5.1.3
use-sync-external-store: 1.2.0(react@18.2.0)
viem: 1.12.2(typescript@5.1.3)
viem: 1.20.0(typescript@5.1.3)
transitivePeerDependencies:
- '@azure/app-configuration'
- '@azure/cosmos'
@@ -14590,19 +14793,6 @@ packages:
optional: true
dev: false
/ws@8.15.0:
resolution: {integrity: sha512-H/Z3H55mrcrgjFwI+5jKavgXvwQLtfPCUEp6pi35VhoB0pfcHnSoyuTzkBEZpzq49g1193CUEwIvmsjcotenYw==}
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.15.1(bufferutil@4.0.8)(utf-8-validate@5.0.10):
resolution: {integrity: sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ==}
engines: {node: '>=10.0.0'}
@@ -14722,3 +14912,7 @@ packages:
/zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
dev: true
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

+19
View File
@@ -0,0 +1,19 @@
<svg width="120" height="97" viewBox="0 0 120 97" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="8" width="120" height="1" fill="currentColor"/>
<rect y="18" width="120" height="1" fill="currentColor"/>
<rect y="28" width="120" height="1" fill="currentColor"/>
<rect y="38" width="120" height="1" fill="currentColor"/>
<rect y="48" width="120" height="1" fill="currentColor"/>
<rect y="58" width="120" height="1" fill="currentColor"/>
<rect y="68" width="120" height="1" fill="currentColor"/>
<rect y="78" width="120" height="1" fill="currentColor"/>
<rect y="88" width="120" height="1" fill="currentColor"/>
<rect x="18" width="1" height="97" fill="currentColor"/>
<rect x="32" width="1" height="97" fill="currentColor"/>
<rect x="46" width="1" height="97" fill="currentColor"/>
<rect x="60" width="1" height="97" fill="currentColor"/>
<rect x="74" width="1" height="97" fill="currentColor"/>
<rect x="88" width="1" height="97" fill="currentColor"/>
<rect x="102" width="1" height="97" fill="currentColor"/>
<path d="M0 0H120V97H0V0Z" fill="url(#paint0_radial_314_37586)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+20
View File
@@ -0,0 +1,20 @@
<svg width="90" height="39" viewBox="0 0 90 39" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="31.2344" width="2.57142" height="7.71427" fill="#3ED9A4"/>
<rect x="5.14258" y="28.6648" width="2.57142" height="5.14284" fill="#E45555"/>
<rect x="25.7139" y="26.0923" width="2.57142" height="10.2857" fill="#E45555"/>
<rect x="51.4283" y="28.6648" width="2.57142" height="5.14284" fill="#E45555"/>
<rect x="56.5712" y="31.2344" width="2.57142" height="5.14284" fill="#E45555"/>
<rect x="77.1426" y="18.3767" width="2.57142" height="5.14284" fill="#E45555"/>
<rect x="41.1427" y="23.5198" width="2.57142" height="5.14284" fill="#E45555"/>
<rect x="10.2856" y="28.6648" width="2.57142" height="10.2857" fill="#3ED9A4"/>
<rect x="61.7143" y="23.5198" width="2.57142" height="10.2857" fill="#3ED9A4"/>
<rect x="66.8569" y="20.9492" width="2.57142" height="5.14284" fill="#3ED9A4"/>
<rect x="71.9997" y="13.2346" width="2.57142" height="7.71427" fill="#3ED9A4"/>
<rect x="82.2856" y="10.6631" width="2.57142" height="10.2857" fill="#3ED9A4"/>
<rect x="87.4287" y="0.37793" width="2.57142" height="15.4285" fill="#3ED9A4"/>
<rect x="15.4284" y="26.0923" width="2.57142" height="5.14284" fill="#3ED9A4"/>
<rect x="20.5714" y="23.5198" width="2.57142" height="5.14284" fill="#3ED9A4"/>
<rect x="30.857" y="31.2344" width="2.57142" height="5.14284" fill="#3ED9A4"/>
<rect x="35.9999" y="26.0923" width="2.57142" height="5.14284" fill="#3ED9A4"/>
<rect x="46.2853" y="26.0923" width="2.57142" height="2.57142" fill="#3ED9A4"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 2.2 MiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 2.1 MiB

-29
View File
@@ -4,38 +4,9 @@
"tokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"name": "Ethereum"
},
{
"chainId": "421613",
"tokenAddress": "0xfd064a18f3bf249cf1f87fc203e90d8f650f2d63",
"name": "Arbitrum Goerli"
},
{
"chainId": "43113",
"tokenAddress": "0x5425890298aed601595a70AB815c96711a31Bc65",
"name": "Avalanche Fuji"
},
{
"chainId": "84531",
"tokenAddress": "0xf175520c52418dfe19c8098071a252da48cd1c19",
"name": "Base Goerli"
},
{
"chainId": "5",
"tokenAddress": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F",
"name": "Ethereum Goerli"
},
{
"chainId": "grand-1",
"tokenAddress": "uusdc",
"name": "Noble Testnet"
},
{
"chainId": "420",
"tokenAddress": "0xe05606174bac4a6364b31bd0eca4bf4dd368f8c6",
"name": "OP Goerli"
},
{
"chainId": "103",
"name": "Solana Devnet"
}
]
+143 -43
View File
@@ -1,7 +1,7 @@
{
"apps": {
"ios": {
"scheme": "dydxv4"
"scheme": "dydx-t-v4"
}
},
"deployments": {
@@ -11,6 +11,13 @@
],
"default": "dydxprotocol-mainnet"
},
"TESTFLIGHT": {
"environments": [
"dydxprotocol-mainnet",
"dydxprotocol-testnet"
],
"default": "dydxprotocol-mainnet"
},
"TESTNET": {
"environments": [
"dydxprotocol-testnet"
@@ -39,7 +46,7 @@
"environments": {
"dydxprotocol-dev": {
"name": "v4 Dev",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -81,7 +88,6 @@
"blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
@@ -109,11 +115,18 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-dev-2": {
"name": "v4 Dev 2",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -154,7 +167,6 @@
"blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
@@ -182,11 +194,18 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-dev-4": {
"name": "v4 Dev 4",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -215,10 +234,11 @@
}
],
"validators": [
"http://validator.v4dev4.dydx.exchange"
"https://validator.v4dev4.dydx.exchange"
],
"0xsquid": "https://testnet.api.0xsquid.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4dev4.dydx.exchange"
},
"links": {
"tos": "https://dydx.exchange/v4-terms",
@@ -227,7 +247,6 @@
"blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
@@ -255,11 +274,18 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-dev-5": {
"name": "v4 Dev 5",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -300,7 +326,6 @@
"blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
@@ -328,11 +353,18 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-staging": {
"name": "v4 Staging",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -377,7 +409,6 @@
"blogs": "https://www.dydx.foundation/blog",
"help": "https://help.dydx.exchange",
"foundation": "https://www.dydx.foundation",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
@@ -403,11 +434,18 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-staging-forced-update": {
"name": "v4 Staging Forced Update",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -473,14 +511,21 @@
"apps": {
"ios": {
"minimalVersion": "1.0",
"build":40000,
"build": 40000,
"url": "https://apps.apple.com/app/dydx/id1564787350"
}
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-staging-west": {
"name": "v4 Staging West",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -525,7 +570,6 @@
"blogs": "https://www.dydx.foundation/blog",
"help": "https://help.dydx.exchange",
"foundation": "https://www.dydx.foundation",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
@@ -551,11 +595,18 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-testnet": {
"name": "v4 Public Testnet",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -579,8 +630,8 @@
"endpoints": {
"indexers": [
{
"api": "https://dydx-testnet.imperator.co",
"socket": "wss://dydx-testnet.imperator.co"
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
@@ -604,7 +655,6 @@
"blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
@@ -630,11 +680,18 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-testnet-dydx": {
"name": "v4 Public Testnet/dYdX",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -680,7 +737,6 @@
"blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
@@ -706,11 +762,18 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-testnet-nodefleet": {
"name": "v4 Public Testnet/nodefleet",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -734,8 +797,8 @@
"endpoints": {
"indexers": [
{
"api": "https://dydx-testnet.imperator.co",
"socket": "wss://dydx-testnet.imperator.co"
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
@@ -756,7 +819,6 @@
"blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
@@ -782,11 +844,18 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-testnet-kingnodes": {
"name": "v4 Public Testnet/KingNodes",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -810,8 +879,8 @@
"endpoints": {
"indexers": [
{
"api": "https://dydx-testnet.imperator.co",
"socket": "wss://dydx-testnet.imperator.co"
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
@@ -832,7 +901,6 @@
"blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
@@ -858,11 +926,18 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-testnet-liquify": {
"name": "v4 Public Testnet/Liquify",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -886,8 +961,8 @@
"endpoints": {
"indexers": [
{
"api": "https://dydx-testnet.imperator.co",
"socket": "wss://dydx-testnet.imperator.co"
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
@@ -908,7 +983,6 @@
"blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
@@ -934,11 +1008,18 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-testnet-polkachu": {
"name": "v4 Public Testnet/Polkahcu",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -962,8 +1043,8 @@
"endpoints": {
"indexers": [
{
"api": "https://dydx-testnet.imperator.co",
"socket": "wss://dydx-testnet.imperator.co"
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
@@ -1001,11 +1082,18 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-testnet-bware": {
"name": "v4 Public Testnet/BWare",
"ethereumChainId": "5",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
@@ -1029,8 +1117,8 @@
"endpoints": {
"indexers": [
{
"api": "https://dydx-testnet.imperator.co",
"socket": "wss://dydx-testnet.imperator.co"
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
@@ -1051,7 +1139,6 @@
"blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnmore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnmore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnmore": "https://help.dydx.exchange",
@@ -1077,6 +1164,13 @@
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
}
},
"dydxprotocol-mainnet": {
@@ -1125,7 +1219,6 @@
"feedback": "[HTTP link to feedback form, can be null]",
"blogs": "[HTTP link to blogs, can be null]",
"foundation": "[HTTP link to foundation, can be null]",
"initialMarginFractionLearnMore": "[HTTP link to initial margin fraction learn more, can be null]",
"reduceOnlyLearnMore": "[HTTP link to reduce-only learn more, can be null]",
"documentation": "[HTTP link to documentation, can be null]",
"community": "[HTTP link to community, can be null]",
@@ -1153,6 +1246,13 @@
"images": "[Relative URL for wallet images]",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 0,
"delayBlocks": 0,
"newMarketsMethodology": "[URL to spreadsheet or document that explains methodology]"
}
}
}
}
+8
View File
@@ -0,0 +1,8 @@
[
{
"name": "coinbase",
"label": "Coinbase",
"icon": "/exchanges/coinbase.png",
"depositType": "noble"
}
]
+7
View File
@@ -69,6 +69,13 @@
"whitepaperLink": "https://bitcoincash.org/",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/bitcoin-cash/"
},
"BONK-USD": {
"name": "BONK COIN",
"tags": [],
"websiteLink": "https://bonkcoin.com/",
"whitepaperLink": "https://bonkcoin.com/",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/bonk1/"
},
"BLUR-USD": {
"name": "Blur",
"tags": [],
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

+230
View File
@@ -0,0 +1,230 @@
<svg width="254" height="77" viewBox="0 0 254 77" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 1258">
<g id="Ellipse 9" opacity="0.4" filter="url(#filter0_f_20300_14972)">
<ellipse cx="86.5425" cy="-3.91219" rx="116.542" ry="20.0878" fill="#7774FF"/>
</g>
<g id="Ellipse 10" opacity="0.3" filter="url(#filter1_f_20300_14972)">
<circle cx="74.5734" cy="4.63007" r="1.00507" fill="#9A9AFF"/>
</g>
<g id="Ellipse 12" opacity="0.3" filter="url(#filter2_f_20300_14972)">
<circle cx="82.1105" cy="7.64179" r="1.00507" fill="#9A9AFF"/>
</g>
<g id="Ellipse 22" opacity="0.3" filter="url(#filter3_f_20300_14972)">
<circle cx="116.785" cy="4.63007" r="1.00507" fill="#9A9AFF"/>
</g>
<g id="Ellipse 11" opacity="0.3" filter="url(#filter4_f_20300_14972)">
<circle cx="64.774" cy="8.90488" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 18" opacity="0.3" filter="url(#filter5_f_20300_14972)">
<circle cx="96.4322" cy="3.87363" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 20" opacity="0.3" filter="url(#filter6_f_20300_14972)">
<circle cx="76.0807" cy="14.9361" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 21" opacity="0.3" filter="url(#filter7_f_20300_14972)">
<circle cx="104.725" cy="4.87754" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 23" opacity="0.3" filter="url(#filter8_f_20300_14972)">
<circle cx="114.021" cy="7.13925" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 24" opacity="0.3" filter="url(#filter9_f_20300_14972)">
<circle cx="109.75" cy="15.4361" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 25" opacity="0.3" filter="url(#filter10_f_20300_14972)">
<circle cx="119.801" cy="12.6705" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 27" opacity="0.3" filter="url(#filter11_f_20300_14972)">
<circle cx="94.0885" cy="11.0182" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 30" opacity="0.3" filter="url(#filter12_f_20300_14972)">
<circle cx="154.475" cy="11.6666" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 29" opacity="0.3" filter="url(#filter13_f_20300_14972)">
<circle cx="146.435" cy="8.90488" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 15" opacity="0.3" filter="url(#filter14_f_20300_14972)">
<circle cx="24.0103" cy="4.44785" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 33" opacity="0.3" filter="url(#filter15_f_20300_14972)">
<circle cx="-1.05899" cy="13.6783" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 16" opacity="0.3" filter="url(#filter16_f_20300_14972)">
<circle cx="17.441" cy="16.4908" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 35" opacity="0.3" filter="url(#filter17_f_20300_14972)">
<circle cx="36.0553" cy="6.63535" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 32" opacity="0.3" filter="url(#filter18_f_20300_14972)">
<circle cx="10.8707" cy="14.2994" r="0.502536" fill="#9A9AFF"/>
</g>
<g id="Ellipse 13" opacity="0.3" filter="url(#filter19_f_20300_14972)">
<circle cx="55.7274" cy="9.65615" r="0.753803" fill="#9A9AFF"/>
</g>
<g id="Ellipse 19" opacity="0.3" filter="url(#filter20_f_20300_14972)">
<circle cx="87.3886" cy="20.7108" r="0.753803" fill="#9A9AFF"/>
</g>
<g id="Ellipse 26" opacity="0.3" filter="url(#filter21_f_20300_14972)">
<circle cx="123.82" cy="15.1874" r="0.753803" fill="#9A9AFF"/>
</g>
<g id="Ellipse 36" opacity="0.3" filter="url(#filter22_f_20300_14972)">
<circle cx="134.876" cy="14.4335" r="0.753803" fill="#9A9AFF"/>
</g>
<g id="Ellipse 28" opacity="0.3" filter="url(#filter23_f_20300_14972)">
<circle cx="129.6" cy="6.38662" r="0.753803" fill="#9A9AFF"/>
</g>
<g id="Ellipse 14" opacity="0.3" filter="url(#filter24_f_20300_14972)">
<circle cx="41.6571" cy="14.9335" r="0.753803" fill="#9A9AFF"/>
</g>
<g id="Ellipse 31" opacity="0.3" filter="url(#filter25_f_20300_14972)">
<circle cx="4.21767" cy="17.9491" r="0.753803" fill="#9A9AFF"/>
</g>
<g id="Ellipse 34" opacity="0.3" filter="url(#filter26_f_20300_14972)">
<circle cx="12.2177" cy="6.88662" r="0.753803" fill="#9A9AFF"/>
</g>
<g id="Ellipse 17" opacity="0.3" filter="url(#filter27_f_20300_14972)">
<circle cx="50.2001" cy="3.6249" r="0.753803" fill="#9A9AFF"/>
</g>
</g>
<defs>
<filter id="filter0_f_20300_14972" x="-94" y="-88" width="361.085" height="168.176" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="32" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter1_f_20300_14972" x="72.5633" y="2.61993" width="4.01991" height="4.02186" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter2_f_20300_14972" x="80.6029" y="6.13418" width="3.01484" height="3.01679" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter3_f_20300_14972" x="115.278" y="3.12246" width="3.01484" height="3.01679" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter4_f_20300_14972" x="63.2664" y="7.39727" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter5_f_20300_14972" x="94.9246" y="2.36602" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter6_f_20300_14972" x="74.5731" y="13.4285" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter7_f_20300_14972" x="103.218" y="3.36993" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter8_f_20300_14972" x="112.513" y="5.63165" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter9_f_20300_14972" x="108.242" y="13.9285" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter10_f_20300_14972" x="118.294" y="11.1629" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter11_f_20300_14972" x="92.5809" y="9.51055" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter12_f_20300_14972" x="153.47" y="10.6615" width="2.00995" height="2.00898" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter13_f_20300_14972" x="144.928" y="7.39727" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter14_f_20300_14972" x="22.5027" y="2.94024" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter15_f_20300_14972" x="-2.56659" y="12.1707" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter16_f_20300_14972" x="15.9334" y="14.9832" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter17_f_20300_14972" x="35.0502" y="5.63028" width="2.00995" height="2.00898" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter18_f_20300_14972" x="9.86563" y="13.2943" width="2.00995" height="2.00898" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter19_f_20300_14972" x="53.9686" y="7.89727" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter20_f_20300_14972" x="85.6297" y="18.952" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter21_f_20300_14972" x="122.061" y="13.4285" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter22_f_20300_14972" x="133.117" y="12.6746" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter23_f_20300_14972" x="127.842" y="4.62774" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter24_f_20300_14972" x="39.8982" y="13.1746" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter25_f_20300_14972" x="2.4588" y="16.1902" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter26_f_20300_14972" x="10.4588" y="5.12774" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
<filter id="filter27_f_20300_14972" x="48.4412" y="1.86602" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.6 KiB

+47 -35
View File
@@ -5,7 +5,7 @@ import { WagmiConfig } from 'wagmi';
import { QueryClient, QueryClientProvider } from 'react-query';
import { GrazProvider } from 'graz';
import { AppRoute, DEFAULT_TRADE_ROUTE } from '@/constants/routes';
import { AppRoute, DEFAULT_TRADE_ROUTE, MarketsRoute } from '@/constants/routes';
import {
useBreakpoints,
@@ -16,10 +16,12 @@ import {
} from '@/hooks';
import { DydxProvider } from '@/hooks/useDydxClient';
import { AccountsProvider } from '@/hooks/useAccounts';
import { AppThemeAndColorModeProvider } from '@/hooks/useAppThemeAndColorMode';
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
import { NotificationsProvider } from '@/hooks/useNotifications';
import { LocalNotificationsProvider } from '@/hooks/useLocalNotifications';
import { PotentialMarketsProvider } from '@/hooks/usePotentialMarkets';
import { RestrictionProvider } from '@/hooks/useRestrictions';
import { SubaccountProvider } from '@/hooks/useSubaccount';
@@ -35,6 +37,7 @@ import { GlobalCommandDialog } from '@/views/dialogs/GlobalCommandDialog';
import { config } from '@/lib/wagmi';
import { breakpoints } from '@/styles';
import { GlobalStyle } from '@/styles/globalStyle';
import { layoutMixins } from '@/styles/layoutMixins';
import { LoadingSpace } from './components/Loading/LoadingSpinner';
@@ -42,6 +45,7 @@ import '@/styles/constants.css';
import '@/styles/fonts.css';
import '@/styles/web3modal.css';
const NewMarket = lazy(() => import('@/pages/markets/NewMarket'));
const MarketsPage = lazy(() => import('@/pages/markets/Markets'));
const PortfolioPage = lazy(() => import('@/pages/portfolio/Portfolio'));
const AlertsPage = lazy(() => import('@/pages/AlertsPage'));
@@ -66,49 +70,55 @@ const Content = () => {
const { chainTokenLabel } = useTokenConfigs();
return (
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
{isNotTablet && <HeaderDesktop />}
<>
<GlobalStyle />
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
{isNotTablet && <HeaderDesktop />}
<Styled.Main>
<Suspense fallback={<LoadingSpace id="main" />}>
<Routes>
<Route path={AppRoute.Trade}>
<Route path=":market" element={<TradePage />} />
<Route path={AppRoute.Trade} element={<TradePage />} />
</Route>
<Styled.Main>
<Suspense fallback={<LoadingSpace id="main" />}>
<Routes>
<Route path={AppRoute.Trade}>
<Route path=":market" element={<TradePage />} />
<Route path={AppRoute.Trade} element={<TradePage />} />
</Route>
<Route path={AppRoute.Markets} element={<MarketsPage />} />
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
{isTablet && (
<>
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
<Route path={AppRoute.Profile} element={<ProfilePage />} />
<Route path={`${AppRoute.Settings}/*`} element={<SettingsPage />} />
</>
)}
<Route path={AppRoute.Markets}>
<Route path={MarketsRoute.New} element={<NewMarket />} />
<Route path={AppRoute.Markets} element={<MarketsPage />} />
</Route>
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
{isTablet && (
<>
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
<Route path={AppRoute.Profile} element={<ProfilePage />} />
<Route path={`${AppRoute.Settings}/*`} element={<SettingsPage />} />
</>
)}
<Route element={<GuardedMobileRoute />}>
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
</Route>
<Route element={<GuardedMobileRoute />}>
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
</Route>
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
</Routes>
</Suspense>
</Styled.Main>
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
</Routes>
</Suspense>
</Styled.Main>
{isTablet ? <FooterMobile /> : <FooterDesktop />}
{isTablet ? <FooterMobile /> : <FooterDesktop />}
<Styled.NotificationsToastArea />
<Styled.NotificationsToastArea />
<Styled.DialogArea ref={setDialogArea}>
<DialogManager />
</Styled.DialogArea>
<Styled.DialogArea ref={setDialogArea}>
<DialogManager />
</Styled.DialogArea>
<GlobalCommandDialog />
</Styled.Content>
<GlobalCommandDialog />
</Styled.Content>
</>
);
};
@@ -131,6 +141,8 @@ const providers = [
wrapProvider(LocalNotificationsProvider),
wrapProvider(NotificationsProvider),
wrapProvider(DialogAreaProvider),
wrapProvider(PotentialMarketsProvider),
wrapProvider(AppThemeAndColorModeProvider),
];
const App = () => {
+26
View File
@@ -0,0 +1,26 @@
import type { Story } from '@ladle/react';
import { Accordion as AccordionComponent, AccordionProps } from '@/components/Accordion';
import { StoryWrapper } from '.ladle/components';
export const Accordion: Story<AccordionProps> = (args) => {
return (
<StoryWrapper>
<AccordionComponent {...args} />
</StoryWrapper>
);
};
Accordion.args = {
items: [
{
header: 'Question 1?',
content: 'Answer 1.',
},
{
header: 'Question 2?',
content: 'Answer 2.',
},
],
};
+129
View File
@@ -0,0 +1,129 @@
import styled, { keyframes, type AnyStyledComponent } from 'styled-components';
import { Root, Item, Header, Trigger, Content } from '@radix-ui/react-accordion';
import { layoutMixins } from '@/styles/layoutMixins';
import { breakpoints } from '@/styles';
import { PlusIcon } from '@/icons';
export type AccordionItem = {
header: React.ReactNode;
content: React.ReactNode;
};
export type AccordionProps = {
items: AccordionItem[];
className?: string;
};
export const Accordion = ({ items, className }: AccordionProps) => (
<Styled.Root className={className} type="single" collapsible>
{items.map(({ header, content }, idx) => (
<Styled.Item key={idx} value={idx.toString()}>
<Header>
<Styled.Trigger>
{header}
<Styled.Icon>
<PlusIcon />
</Styled.Icon>
</Styled.Trigger>
</Header>
<Styled.Content>{content}</Styled.Content>
</Styled.Item>
))}
</Styled.Root>
);
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Root = styled(Root)`
--accordion-paddingY: 1rem;
--accordion-paddingX: 1rem;
@media ${breakpoints.notTablet} {
--accordion-paddingX: 1.5rem;
}
> *:not(:last-child) {
border-bottom: var(--border-width) solid var(--border-color);
}
`;
Styled.Item = styled(Item)``;
Styled.Icon = styled.div`
display: inline-flex;
justify-content: center;
align-items: center;
width: 2.25rem;
height: 2.25rem;
--color-border: var(--color-layer-6);
color: var(--color-text-1);
background-color: var(--color-layer-5);
border: solid var(--border-width) var(--color-border);
border-radius: 50%;
font: var(--font-small-book);
svg {
height: 1.125em;
width: 1.125em;
}
`;
Styled.Trigger = styled(Trigger)`
${layoutMixins.spacedRow}
width: 100%;
padding: var(--accordion-paddingY) var(--accordion-paddingX);
gap: 0.5rem;
color: var(--color-text-1);
text-align: start;
&:hover {
${Styled.Icon} {
color: var(--color-text-2);
filter: brightness(var(--hover-filter-base));
}
}
svg {
color: var(--color-text-0);
transition: transform 0.3s var(--ease-out-expo);
}
&[data-state='open'] svg {
transform: rotate(45deg);
}
`;
Styled.Content = styled(Content)`
overflow: hidden;
margin: 0 var(--accordion-paddingX) var(--accordion-paddingY);
color: var(--color-text-0);
&[data-state='open'] {
animation: ${keyframes`
from {
height: 0;
}
to {
height: var(--radix-accordion-content-height);
}
`} 0.3s var(--ease-out-expo);
}
&[data-state='closed'] {
animation: ${keyframes`
from {
height: var(--radix-accordion-content-height);
}
to {
height: 0;
}
`} 0.1s var(--ease-in-expo);
}
`;
+1
View File
@@ -16,6 +16,7 @@ const assetIcons = {
AVAX: '/currencies/avax.png',
BCH: '/currencies/bch.png',
BLUR: '/currencies/blur.png',
BONK: '/currencies/bonk.png',
BTC: '/currencies/btc.png',
CELO: '/currencies/celo.png',
COMP: '/currencies/comp.png',
+2 -2
View File
@@ -134,8 +134,8 @@ const ButtonStyle = css<StyleProps>`
--button-textColor: var(--color-text-0);
--button-backgroundColor: transparent;
--button-active-filter: brightness(0.9);
--button-hover-filter: brightness(1.1);
--button-active-filter: brightness(var(--active-filter));
--button-hover-filter: brightness(var(--hover-filter-base));
--button-hover-textColor: var(--button-textColor);
--button-radius: 0.5em;
+10 -6
View File
@@ -89,9 +89,10 @@ const buttonActionVariants = {
--button-border: solid var(--border-width) var(--color-border);
`,
[ButtonAction.Primary]: css`
--button-textColor: var(--color-text-2);
--button-textColor: var(--color-text-button);
--button-backgroundColor: var(--color-accent);
--button-border: solid var(--border-width) var(--color-border-white);
--button-hover-filter: brightness(var(--hover-filter-variant));
`,
[ButtonAction.Secondary]: css`
@@ -101,15 +102,17 @@ const buttonActionVariants = {
`,
[ButtonAction.Create]: css`
--button-textColor: var(--color-text-2);
--button-backgroundColor: var(--color-positive);
--button-textColor: var(--color-text-button);
--button-backgroundColor: var(--color-success);
--button-border: solid var(--border-width) var(--color-border-white);
--button-hover-filter: brightness(var(--hover-filter-variant));
`,
[ButtonAction.Destroy]: css`
--button-textColor: var(--color-text-2);
--button-backgroundColor: var(--color-negative);
--button-textColor: var(--color-text-button);
--button-backgroundColor: var(--color-error);
--button-border: solid var(--border-width) var(--color-border-white);
--button-hover-filter: brightness(var(--hover-filter-variant));
`,
[ButtonAction.Navigation]: css`
@@ -119,9 +122,10 @@ const buttonActionVariants = {
`,
[ButtonAction.Reset]: css`
--button-textColor: var(--color-negative);
--button-textColor: var(--color-error);
--button-backgroundColor: var(--color-layer-3);
--button-border: solid var(--border-width) var(--color-border-red);
--button-hover-filter: brightness(var(--hover-filter-variant));
`,
};
+13
View File
@@ -0,0 +1,13 @@
import { forwardRef } from 'react';
type CanvasProps = {
className?: string;
width: number | string;
height: number | string;
};
export const Canvas = forwardRef<HTMLCanvasElement, CanvasProps>(
({ className, width, height }, canvasRef) => (
<canvas ref={canvasRef} className={className} width={width} height={height} />
)
);
+10 -2
View File
@@ -5,7 +5,7 @@ import { Checkbox, CheckboxProps } from '@/components/Checkbox';
import { StoryWrapper } from '.ladle/components';
export const Checkboxes: Story<CheckboxProps> = (args) => {
export const CheckboxStory: Story<CheckboxProps> = (args) => {
const [isChecked, setIsChecked] = useState(false);
return (
@@ -21,4 +21,12 @@ export const Checkboxes: Story<CheckboxProps> = (args) => {
);
};
Checkboxes.args = {};
CheckboxStory.args = {};
CheckboxStory.argTypes = {
disabled: {
options: [true, false],
control: { type: 'select' },
defaultValue: false,
}
}
+34 -8
View File
@@ -1,4 +1,4 @@
import styled, { type AnyStyledComponent } from 'styled-components';
import styled, { css, type AnyStyledComponent } from 'styled-components';
import { Root, Indicator } from '@radix-ui/react-checkbox';
import { CheckIcon } from '@radix-ui/react-icons';
@@ -9,6 +9,7 @@ type ElementProps = {
onCheckedChange: (checked: boolean) => void;
id?: string;
label?: React.ReactNode;
disabled?: boolean;
};
type StyleProps = {
@@ -23,14 +24,25 @@ export const Checkbox: React.FC<CheckboxProps> = ({
onCheckedChange,
id,
label,
disabled,
}) => (
<Styled.Container>
<Styled.Root className={className} checked={checked} onCheckedChange={onCheckedChange} id={id}>
<Styled.Root
className={className}
checked={checked}
disabled={disabled}
onCheckedChange={onCheckedChange}
id={id}
>
<Styled.Indicator>
<CheckIcon />
</Styled.Indicator>
</Styled.Root>
{label && <label htmlFor={id}>{label}</label>}
{label && (
<Styled.Label disabled={disabled} htmlFor={id}>
{label}
</Styled.Label>
)}
</Styled.Container>
);
@@ -40,25 +52,27 @@ Styled.Container = styled.div`
${layoutMixins.row}
gap: 1ch;
font: var(--font-small-book);
label {
cursor: pointer;
}
`;
Styled.Root = styled(Root)`
--checkbox-backgroundColor: var(--color-layer-0);
--checkbox-borderColor: var(--color-border);
min-width: 1.25rem;
height: 1.25rem;
border-radius: 0.375rem;
border: var(--border-width) solid var(--color-border);
border: var(--border-width) solid var(--checkbox-borderColor);
background-color: var(--checkbox-backgroundColor);
&[data-state='checked'] {
--checkbox-backgroundColor: var(--color-accent);
}
&[data-disabled] {
cursor: not-allowed;
--checkbox-backgroundColor: var(--color-layer-1);
}
`;
Styled.Indicator = styled(Indicator)`
@@ -66,5 +80,17 @@ Styled.Indicator = styled(Indicator)`
align-items: center;
justify-content: center;
color: var(--color-text-button);
`;
Styled.Label = styled.label<{ disabled?: boolean }>`
cursor: pointer;
color: var(--color-text-2);
${({ disabled }) =>
disabled &&
css`
cursor: not-allowed;
color: var(--color-text-0);
`}
`;
+5 -4
View File
@@ -50,10 +50,11 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
label={title}
// value={highlightedCommand}
// onValueChange={setHighlightedCommand}
filter={(value: string, search: string) => {
if (value.replace(/ /g, '').includes(search.replace(/ /g, ''))) return 1;
return 0;
}}
filter={(value: string, search: string) =>
value.replace(/ /g, '').toLowerCase().includes(search.replace(/ /g, '').toLowerCase())
? 1
: 0
}
className={className}
$withStickyLayout={withStickyLayout}
>
-1
View File
@@ -11,6 +11,5 @@ export const DetachedScrollableSection = styled.section`
export const AttachedExpandingSection = styled.section`
${layoutMixins.contentSectionAttached}
${layoutMixins.expandingColumnWithHeader}
gap: var(--border-width);
`;
+3 -3
View File
@@ -77,7 +77,7 @@ Styled.InlineRow = styled.div<{ copied: boolean }>`
`
: css`
&:hover {
filter: brightness(1.1);
filter: brightness(var(--hover-filter-base));
text-decoration: underline;
}
`}
@@ -87,7 +87,7 @@ Styled.Icon = styled(Icon)<{ copied: boolean }>`
${({ copied }) =>
copied &&
css`
color: var(--color-positive);
color: var(--color-success);
`}
`;
@@ -96,7 +96,7 @@ Styled.IconButton = styled(IconButton)<{ copied: boolean }>`
copied &&
css`
svg {
color: var(--color-positive);
color: var(--color-success);
}
`}
`;
+1 -1
View File
@@ -14,7 +14,7 @@ export const DiffArrowStory: Story<DiffArrowProps> = (args) => (
DiffArrowStory.argTypes = {
direction: {
options: ['left', 'right'],
options: ['left', 'right', 'up', 'down'],
control: { type: 'select' },
defaultValue: 'right',
},
+7 -1
View File
@@ -10,7 +10,7 @@ type ElementProps = {
type StyleProps = {
className?: string;
direction?: 'right' | 'left';
direction?: 'right' | 'left' | 'up' | 'down';
};
export type DiffArrowProps = ElementProps & StyleProps;
@@ -57,5 +57,11 @@ Styled.DiffArrowContainer = styled.span<DiffArrowProps>`
left: css`
transform: scaleX(-1);
`,
up: css`
transform: rotate(-90deg);
`,
down: css`
transform: rotate(90deg);
`,
}[direction || 'right'])}
`;
+1 -1
View File
@@ -75,7 +75,7 @@ Styled.DiffValue = styled.div<{ hasInvalidNewValue?: boolean }>`
${({ hasInvalidNewValue }) =>
hasInvalidNewValue &&
css`
color: var(--color-negative);
color: var(--color-error);
`}
`;
+3 -3
View File
@@ -35,8 +35,8 @@ export const DropdownHeaderMenu = <MenuItemValue extends string>({
<Root>
<Styled.Trigger className={className} asChild>
<div>
{children}
<Styled.DropdownIconButton iconName={IconName.Caret} isToggle />
{children}
<Styled.DropdownIconButton iconName={IconName.Caret} isToggle />
</div>
</Styled.Trigger>
<Portal>
@@ -87,7 +87,7 @@ Styled.Trigger = styled(Trigger)`
outline: none;
:hover {
filter: brightness(1.1);
filter: brightness(var(--hover-filter-base));
}
`;
+12 -7
View File
@@ -6,29 +6,34 @@ import { StoryWrapper } from '.ladle/components';
export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>> = (args) => {
const exampleItems = [
{
value: '0',
label: 'Item 0',
onSelect: () => alert('Item 0 action'),
},
{
value: '1',
label: 'Item 1',
label: 'Item 1 (accent)',
onSelect: () => alert('Item 1 action'),
highlightColor: 'accent',
},
{
value: '2',
label: 'Item 2',
label: 'Item 2 (create)',
onSelect: () => alert('Item 2 action'),
highlightColor: 'create',
},
{
value: '3',
label: 'Item 3',
label: 'Item 3 (destroy)',
onSelect: () => alert('Item 3 action'),
highlightColor: 'destroy',
},
];
return (
<StoryWrapper>
<DropdownMenu
{...args}
items={exampleItems}
>
<DropdownMenu {...args} items={exampleItems}>
<span>Menu</span>
</DropdownMenu>
</StoryWrapper>
+6 -6
View File
@@ -13,7 +13,7 @@ export type DropdownMenuItem<T> = {
label: React.ReactNode;
onSelect?: () => void;
separator?: boolean;
highlightColor?: 'accent' | 'positive' | 'negative';
highlightColor?: 'accent' | 'create' | 'destroy';
};
type StyleProps = {
@@ -82,7 +82,7 @@ Styled.Separator = styled(Separator)`
margin: 0.25rem 1rem;
`;
Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'positive' | 'negative' }>`
Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'create' | 'destroy' }>`
${popoverMixins.item}
--item-font-size: var(--dropdownMenu-item-font-size);
${({ $highlightColor }) =>
@@ -90,11 +90,11 @@ Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'positive' | 'negative'
['accent']: `
--item-highlighted-textColor: var(--color-accent);
`,
['positive']: `
--item-highlighted-textColor: var(--color-positive);
['create']: `
--item-highlighted-textColor: var(--color-success);
`,
['negative']: `
--item-highlighted-textColor: var(--color-negative);
['destroy']: `
--item-highlighted-textColor: var(--color-error);
`,
}[$highlightColor])}
+3 -3
View File
@@ -32,7 +32,7 @@ export const FormInput = forwardRef<HTMLInputElement, FormInputProps>(
isValidationAttached={validationConfig?.attached}
>
<Styled.InputContainer hasSlotRight={!!slotRight}>
<Styled.WithLabel label={label} inputID={id}>
<Styled.WithLabel label={label} inputID={id} disabled={otherProps?.disabled}>
<Input ref={ref} id={id} {...otherProps} />
</Styled.WithLabel>
{slotRight}
@@ -85,11 +85,11 @@ Styled.InputContainer = styled.div<{ hasSlotRight?: boolean }>`
`}
`;
Styled.WithLabel = styled(WithLabel)`
Styled.WithLabel = styled(WithLabel)<{ disabled?: boolean }>`
${formMixins.inputLabel}
label {
cursor: text;
${({ disabled }) => !disabled && 'cursor: text;'}
padding: var(--form-input-paddingY) var(--form-input-paddingX) 0;
}
`;
+15 -3
View File
@@ -13,6 +13,7 @@ import {
CaretIcon,
CautionCircleStrokeIcon,
CautionCircleIcon,
ChaosLabsIcon,
ChatIcon,
CheckIcon,
CheckCircleIcon,
@@ -24,7 +25,6 @@ import {
CoinsIcon,
CommentIcon,
CopyIcon,
CubeIcon,
DepositIcon,
DepthChartIcon,
DiscordIcon,
@@ -45,6 +45,7 @@ import {
MenuIcon,
MigrateIcon,
MintscanIcon,
MoonIcon,
OrderbookIcon,
OrderCanceledIcon,
OrderFilledIcon,
@@ -55,16 +56,19 @@ import {
OverviewIcon,
PencilIcon,
PlayIcon,
PlusIcon,
PositionsIcon,
PriceChartIcon,
PrivacyIcon,
QrIcon,
RewardStarIcon,
SearchIcon,
SendIcon,
ShareIcon,
ShowIcon,
TogglesMenuIcon,
StarIcon,
SunIcon,
TerminalIcon,
TradeIcon,
TransferIcon,
@@ -87,6 +91,7 @@ export enum IconName {
Caret = 'Caret',
CautionCircle = 'CautionCircle',
CautionCircleStroked = 'CautionCircleStroked',
ChaosLabs = 'ChaosLabs',
Chat = 'Chat',
Check = 'Check',
CheckCircle = 'CheckCircle',
@@ -98,7 +103,6 @@ export enum IconName {
Coins = 'Coins',
Comment = 'Comment',
Copy = 'Copy',
Cube = 'Cube',
Deposit = 'Deposit',
DepthChart = 'DepthChart',
Discord = 'Discord',
@@ -119,6 +123,7 @@ export enum IconName {
Menu = 'Menu',
Migrate = 'Migrate',
Mintscan = 'Mintscan',
Moon = 'Moon',
Onboarding = 'Onboarding',
Orderbook = 'OrderbookIcon',
OrderCanceled = 'OrderCanceled',
@@ -130,15 +135,18 @@ export enum IconName {
Overview = 'Overview',
Pencil = 'Pencil',
Play = 'Play',
Plus = 'Plus',
Positions = 'Positions',
PriceChart = 'PriceChart',
Privacy = 'Privacy',
Qr = 'Qr',
RewardStar = 'RewardStar',
Search = 'Search',
Send = 'Send',
Share = 'Share',
Show = 'Show',
Star = 'Star',
Sun = 'Sun',
Terminal = 'Terminal',
TogglesMenu = 'TogglesMenu',
Trade = 'Trade',
@@ -162,6 +170,7 @@ const icons = {
[IconName.Caret]: CaretIcon,
[IconName.CautionCircle]: CautionCircleIcon,
[IconName.CautionCircleStroked]: CautionCircleStrokeIcon,
[IconName.ChaosLabs]: ChaosLabsIcon,
[IconName.Chat]: ChatIcon,
[IconName.Check]: CheckIcon,
[IconName.CheckCircle]: CheckCircleIcon,
@@ -173,7 +182,6 @@ const icons = {
[IconName.Coins]: CoinsIcon,
[IconName.Comment]: CommentIcon,
[IconName.Copy]: CopyIcon,
[IconName.Cube]: CubeIcon,
[IconName.Deposit]: DepositIcon,
[IconName.DepthChart]: DepthChartIcon,
[IconName.Discord]: DiscordIcon,
@@ -194,6 +202,7 @@ const icons = {
[IconName.Menu]: MenuIcon,
[IconName.Migrate]: MigrateIcon,
[IconName.Mintscan]: MintscanIcon,
[IconName.Moon]: MoonIcon,
[IconName.Orderbook]: OrderbookIcon,
[IconName.OrderCanceled]: OrderCanceledIcon,
[IconName.OrderFilled]: OrderFilledIcon,
@@ -204,15 +213,18 @@ const icons = {
[IconName.Overview]: OverviewIcon,
[IconName.Pencil]: PencilIcon,
[IconName.Play]: PlayIcon,
[IconName.Plus]: PlusIcon,
[IconName.Positions]: PositionsIcon,
[IconName.PriceChart]: PriceChartIcon,
[IconName.Privacy]: PrivacyIcon,
[IconName.Qr]: QrIcon,
[IconName.RewardStar]: RewardStarIcon,
[IconName.Search]: SearchIcon,
[IconName.Send]: SendIcon,
[IconName.Share]: ShareIcon,
[IconName.Show]: ShowIcon,
[IconName.Star]: StarIcon,
[IconName.Sun]: SunIcon,
[IconName.Terminal]: TerminalIcon,
[IconName.TogglesMenu]: TogglesMenuIcon,
[IconName.Trade]: TradeIcon,
@@ -11,6 +11,7 @@ export const LoadingSpinner: React.FC<{
return (
<Styled.Spinner className={className}>
<Styled.LoadingSpinnerSvg
id={id}
width="38"
height="38"
viewBox="0 0 38 38"
+1 -1
View File
@@ -1,11 +1,11 @@
import styled, { type AnyStyledComponent } from 'styled-components';
import { RiskLevels } from '@/constants/abacus';
import { UsageColorFromRiskLevel } from '@/styles/colors';
import { Ring } from '@/components/Ring';
import { abacusHelper } from '@/lib/abacus';
import { UsageColorFromRiskLevel } from '@/lib/styles';
type ElementProps = {
value: number;
+11 -1
View File
@@ -65,6 +65,9 @@ type ElementProps = {
resolution?: number;
stripRelativeWords?: boolean;
};
timeOptions?: {
useUTC?: boolean;
};
tag?: React.ReactNode;
withParentheses?: boolean;
locale?: string;
@@ -89,6 +92,7 @@ export const Output = ({
relativeTimeFormatOptions = {
format: 'singleCharacter',
},
timeOptions,
tag,
withParentheses,
locale = navigator.language || 'en-US',
@@ -116,6 +120,7 @@ export const Output = ({
{value?.toString() ?? null}
{tag && <Tag>{tag}</Tag>}
{slotRight}
</Styled.Text>
);
}
@@ -165,16 +170,21 @@ export const Output = ({
if ((typeof value !== 'string' && typeof value !== 'number') || !value) return null;
const date = new Date(value);
const dateString = {
[OutputType.Date]: date.toLocaleString(selectedLocale, { dateStyle: 'medium' }),
[OutputType.Date]: date.toLocaleString(selectedLocale, {
dateStyle: 'medium',
timeZone: timeOptions?.useUTC ? 'UTC' : undefined,
}),
[OutputType.DateTime]: date.toLocaleString(selectedLocale, {
dateStyle: 'short',
timeStyle: 'short',
timeZone: timeOptions?.useUTC ? 'UTC' : undefined,
}),
[OutputType.Time]: date.toLocaleString(selectedLocale, {
hour12: false,
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
timeZone: timeOptions?.useUTC ? 'UTC' : undefined,
}),
}[type];
+5 -3
View File
@@ -1,10 +1,10 @@
import type { Story } from '@ladle/react';
import { Panel } from '@/components/Panel';
import { Panel, PanelProps } from '@/components/Panel';
import { StoryWrapper } from '.ladle/components';
export const PanelStory: Story<{ slotHeader: React.ReactNode, children?: React.ReactNode }> = (args) => {
export const PanelStory: Story<PanelProps> = (args) => {
return (
<StoryWrapper>
<Panel {...args} />
@@ -13,6 +13,8 @@ export const PanelStory: Story<{ slotHeader: React.ReactNode, children?: React.R
};
PanelStory.args = {
slotHeader: 'Header',
slotHeaderContent: 'Header',
children: 'Content',
slotRight: '1️⃣',
hasSeparator: true,
};
+13 -4
View File
@@ -4,9 +4,10 @@ import { Link } from 'react-router-dom';
import { Icon, IconName } from '@/components/Icon';
import { layoutMixins } from '@/styles/layoutMixins';
import { breakpoints } from '@/styles';
type PanelProps = {
slotHeaderContent?: string;
type ElementProps = {
slotHeaderContent?: React.ReactNode;
slotHeader?: React.ReactNode;
slotRight?: React.ReactNode;
children?: React.ReactNode;
@@ -15,11 +16,13 @@ type PanelProps = {
onClick?: () => void;
};
type PanelStyleProps = {
type StyleProps = {
className?: string;
hasSeparator?: boolean;
};
export type PanelProps = ElementProps & StyleProps;
export const Panel = ({
slotHeaderContent,
slotHeader,
@@ -30,7 +33,7 @@ export const Panel = ({
onClick,
hasSeparator,
className,
}: PanelProps & PanelStyleProps) => (
}: PanelProps) => (
<Styled.Panel onClick={onClick} className={className}>
<Styled.Left>
{href ? (
@@ -67,6 +70,12 @@ Styled.Panel = styled.section<{ onClick?: () => void }>`
--panel-content-paddingY: var(--panel-paddingY);
--panel-content-paddingX: var(--panel-paddingX);
@media ${breakpoints.notTablet} {
--panel-paddingX: 1.5rem;
--panel-paddingY: 1.25rem;
--panel-content-paddingY: 1rem;
}
${layoutMixins.row}
background-color: var(--color-layer-3);
+3 -2
View File
@@ -11,6 +11,7 @@ type ElementProps = {
};
type StyleProps = {
className?: string;
hasLogo?: boolean;
size?: number;
};
@@ -18,7 +19,7 @@ type StyleProps = {
const DARK_LOGO_MARK_URL = '/logos/logo-mark-dark.svg';
const LIGHT_LOGO_MARK_URL = '/logos/logo-mark-light.svg';
export const QrCode = ({ value, hasLogo, size = 300 }: ElementProps & StyleProps) => {
export const QrCode = ({ className, value, hasLogo, size = 300 }: ElementProps & StyleProps) => {
const ref = useRef<HTMLDivElement>(null);
const appTheme: AppTheme = useSelector(getAppTheme);
@@ -74,7 +75,7 @@ export const QrCode = ({ value, hasLogo, size = 300 }: ElementProps & StyleProps
}
}, [appTheme, hasLogo]);
return <Styled.QrCode ref={ref} />;
return <Styled.QrCode className={className} ref={ref} />;
};
const Styled: Record<string, AnyStyledComponent> = {};
+1 -1
View File
@@ -47,7 +47,7 @@ Styled.Root = styled(Root)`
--switch-thumb-backgroundColor: var(--color-layer-6);
--switch-active-backgroundColor: var(--color-accent);
--switch-active-thumb-backgroundColor: var(--color-white);
--switch-active-thumb-backgroundColor: ${({ theme }) => theme.switchThumbActiveBackground};
position: relative;
width: var(--switch-width);
+77 -9
View File
@@ -33,17 +33,20 @@ import {
import { useAsyncList } from 'react-stately';
import { useBreakpoints } from '@/hooks';
import { useBreakpoints, useStringGetter } from '@/hooks';
import { MediaQueryKeys } from '@/hooks/useBreakpoints';
import { Checkbox } from '@/components/Checkbox';
import { breakpoints } from '@/styles';
import { layoutMixins } from '@/styles/layoutMixins';
import { CaretIcon } from '@/icons';
import { STRING_KEYS } from '@/constants/localization';
import { MustBigNumber } from '@/lib/numbers';
import { Icon, IconName } from './Icon';
import { Tag } from './Tag';
import { MustBigNumber } from '@/lib/numbers';
import { Button } from './Button';
export { TableCell } from './Table/TableCell';
export { TableColumnHeader } from './Table/TableColumnHeader';
@@ -80,7 +83,7 @@ export type ColumnDef<TableRowData extends object> = {
width?: ColumnSize;
};
type ElementProps<TableRowData extends object | CustomRowConfig, TableRowKey extends Key> = {
export type ElementProps<TableRowData extends object | CustomRowConfig, TableRowKey extends Key> = {
label?: string;
columns: ColumnDef<TableRowData>[];
data: TableRowData[];
@@ -92,6 +95,7 @@ type ElementProps<TableRowData extends object | CustomRowConfig, TableRowKey ext
selectionBehavior?: 'replace' | 'toggle';
onRowAction?: (key: TableRowKey, row: TableRowData) => void;
slotEmpty?: React.ReactNode;
initialNumRowsToShow?: number;
// collection: TableCollection<string>;
// children: React.ReactNode;
};
@@ -121,6 +125,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
selectionMode = 'single',
selectionBehavior = 'toggle',
slotEmpty,
initialNumRowsToShow,
// shouldRowRender,
// collection,
@@ -136,6 +141,8 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
style,
}: ElementProps<TableRowData, TableRowKey> & StyleProps) => {
const [selectedKeys, setSelectedKeys] = useState(new Set<TableRowKey>());
const [numRowsToShow, setNumRowsToShow] = useState(initialNumRowsToShow);
const enableViewMore = numRowsToShow !== undefined;
const currentBreakpoints = useBreakpoints();
const shownColumns = columns.filter(
@@ -209,6 +216,12 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
onRowAction &&
((key: TableRowKey) => onRowAction(key, data.find((row) => getRowKey(row) === key)!))
}
numColumns={shownColumns.length}
onViewMoreClick={
enableViewMore && numRowsToShow < data.length
? () => setNumRowsToShow(data.length)
: undefined
}
// shouldRowRender={shouldRowRender}
hideHeader={hideHeader}
withGradientCardRows={withGradientCardRows}
@@ -233,7 +246,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
)}
</TableHeader>
<TableBody items={list.items}>
<TableBody items={enableViewMore ? list.items.slice(0, numRowsToShow) : list.items}>
{(item) => (
<Row key={getRowKey(item)}>
{(columnKey) => (
@@ -267,6 +280,8 @@ const TableRoot = <TableRowData extends object | CustomRowConfig, TableRowKey ex
onRowAction?: (key: TableRowKey) => void;
// shouldRowRender?: (prevRowData: object, currentRowData: object) => boolean;
children: CollectionChildren<TableRowData>;
numColumns: number;
onViewMoreClick?: () => void;
hideHeader?: boolean;
withGradientCardRows?: boolean;
@@ -276,7 +291,7 @@ const TableRoot = <TableRowData extends object | CustomRowConfig, TableRowKey ex
withScrollSnapColumns?: boolean;
withScrollSnapRows?: boolean;
}) => {
const { selectionMode, selectionBehavior } = props;
const { selectionMode, selectionBehavior, numColumns, onViewMoreClick } = props;
const state = useTableState<TableRowData>({
...props,
@@ -337,6 +352,7 @@ const TableRoot = <TableRowData extends object | CustomRowConfig, TableRowKey ex
<TableBodyRowGroup
withGradientCardRows={props.withGradientCardRows}
withInnerBorders={props.withInnerBorders}
withOuterBorder={props.withOuterBorder}
>
{/* {Array.from(collection.getChildren!(collection.body.key), (row) => */}
{[...collection.body.childNodes].map((row) =>
@@ -382,6 +398,9 @@ const TableRoot = <TableRowData extends object | CustomRowConfig, TableRowKey ex
</TableRow>
)
)}
{onViewMoreClick ? (
<ViewMoreRow colSpan={numColumns} onClick={onViewMoreClick} />
) : undefined}
</TableBodyRowGroup>
</Styled.Table>
);
@@ -415,6 +434,7 @@ const TableBodyRowGroup = ({
children,
withGradientCardRows,
withInnerBorders,
withOuterBorder,
}: { children: React.ReactNode } & StyleProps) => {
const { rowGroupProps } = useTableRowGroup();
@@ -423,6 +443,7 @@ const TableBodyRowGroup = ({
{...rowGroupProps}
withGradientCardRows={withGradientCardRows}
withInnerBorders={withInnerBorders}
withOuterBorder={withOuterBorder}
>
{children}
</Styled.Tbody>
@@ -489,6 +510,23 @@ const TableColumnHeader = <TableRowData extends object>({
);
};
export const ViewMoreRow = ({ colSpan, onClick }: { colSpan: number; onClick: () => void }) => {
const stringGetter = useStringGetter();
return (
<Styled.ViewMoreTr key="viewmore">
<Styled.Td
colSpan={colSpan}
onMouseDown={(e: MouseEvent) => e.preventDefault()}
onPointerDown={(e: MouseEvent) => e.preventDefault()}
>
<Styled.ViewMoreButton slotRight={<CaretIcon />} onClick={onClick}>
{stringGetter({ key: STRING_KEYS.VIEW_MORE })}
</Styled.ViewMoreButton>
</Styled.Td>
</Styled.ViewMoreTr>
);
};
export const TableRow = <TableRowData extends object>({
item,
children,
@@ -635,6 +673,8 @@ Styled.TableWrapper = styled.div<{
--table-lastColumn-cell-align: end; // start | center | end | var(--table-cell-align)
--tableCell-padding: 0 1rem;
--tableViewMore-borderColor: inherit;
// Rules
flex: 1;
@@ -660,7 +700,7 @@ Styled.Empty = styled.div<{ withOuterBorder: boolean }>`
justify-items: center;
align-content: center;
padding: 2rem;
padding: 4rem;
gap: 0.75em;
color: var(--color-text-0);
@@ -744,7 +784,7 @@ Styled.Tr = styled.tr<{
&:focus-visible,
&:focus-within {
--tableRow-currentBackgroundColor: var(--tableRow-hover-backgroundColor);
filter: brightness(1.1);
filter: brightness(var(--hover-filter-base));
}
`};
@@ -868,6 +908,18 @@ Styled.Tbody = styled.tbody<StyleProps>`
--stickyArea2-paddingLeft: var(--border-width);
--stickyArea2-paddingRight: var(--border-width);
tr:first-of-type {
box-shadow: 0 calc(var(--border-width)) 0 0 var(--border-color);
}
`}
${({ withOuterBorder }) =>
withOuterBorder &&
css`
tr:last-of-type:not(:only-of-type) {
box-shadow: 0 calc(-1 * var(--border-width)) 0 0 var(--border-color);
}
tr:first-of-type {
box-shadow: none;
}
@@ -922,3 +974,19 @@ Styled.Row = styled.div`
${layoutMixins.inlineRow}
padding: var(--tableCell-padding);
`;
Styled.ViewMoreButton = styled(Button)`
--button-backgroundColor: var(--color-layer-2);
--button-textColor: var(--color-text-1);
width: 100%;
svg {
width: 0.675rem;
margin-left: 0.5ch;
}
`;
Styled.ViewMoreTr = styled(Styled.Tr)`
--border-color: var(--tableViewMore-borderColor);
`;
+4
View File
@@ -8,6 +8,7 @@ import { Button, type ButtonStateConfig, type ButtonProps } from '@/components/B
type ElementProps = {
timeoutInSeconds: number;
slotFinal?: ReactNode;
} & ButtonProps;
export type TimeoutButtonProps = ElementProps;
@@ -15,6 +16,7 @@ export type TimeoutButtonProps = ElementProps;
export const TimeoutButton = ({
children,
timeoutInSeconds,
slotFinal,
...otherProps
}: TimeoutButtonProps) => {
const [timeoutDeadline] = useState(Date.now() + timeoutInSeconds * 1000);
@@ -23,6 +25,8 @@ export const TimeoutButton = ({
const secondsLeft = Math.max(0, (timeoutDeadline - now) / 1000);
if (slotFinal && secondsLeft <= 0) return slotFinal;
return (
<Button
{...otherProps}
+1 -2
View File
@@ -27,9 +27,8 @@ export const ToastArea = ({ swipeDirection, children, className }: ToastAreaProp
const $ToastArea = styled.aside`
// Params
--toasts-gap: 0.5rem;
// Rules
${layoutMixins.scrollArea}
z-index: 1;
pointer-events: none;
+2 -2
View File
@@ -2,9 +2,9 @@ import styled, { type AnyStyledComponent } from 'styled-components';
import { type RiskLevels } from '@/constants/abacus';
import { UsageColorFromRiskLevel } from '@/styles/colors';
import { abacusHelper } from '@/lib/abacus';
import { UsageColorFromRiskLevel } from '@/lib/styles';
type ElementProps = {
value: number;
};
+2 -2
View File
@@ -117,7 +117,7 @@ Styled.ConfirmButton = styled(Styled.IconButton)`
--button-backgroundColor: hsla(203, 25%, 19%, 1);
svg {
color: var(--color-positive);
color: var(--color-success);
}
`;
@@ -125,7 +125,7 @@ Styled.CancelButton = styled(Styled.IconButton)`
--button-backgroundColor: hsla(296, 16%, 18%, 1);
svg {
color: var(--color-negative);
color: var(--color-error);
width: 0.8em;
height: 0.8em;
+1 -1
View File
@@ -40,5 +40,5 @@ Styled.Details = styled(Details)`
padding: 0.375rem 0.75rem 0.25rem;
font-size: 0.8125em;
font-size: var(--details-item-fontSize, 0.8125em);
`;
+1 -6
View File
@@ -110,12 +110,7 @@ Styled.Abbr = styled.abbr`
Styled.Content = styled(Content)`
--tooltip-backgroundColor: var(--color-layer-4);
--tooltip-backgroundColor: hsl(
var(--layer-base-hue),
var(--layer-base-saturation),
calc(var(--layer-base-lightness) + 4%),
0.66
);
--tooltip-backgroundColor: ${({ theme }) => theme.tooltipBackground};
${popoverMixins.popover}
--popover-backgroundColor: var(--tooltip-backgroundColor);
+1 -6
View File
@@ -27,12 +27,7 @@ Styled.TooltipContent = styled.aside<{ accentColor?: string }>`
${popoverMixins.popover}
--popover-radius: 0.5rem;
--popover-background-color: hsl(
var(--layer-base-hue),
var(--layer-base-saturation),
calc(var(--layer-base-lightness)),
0.9
);
--popover-background-color: ${({ theme }) => theme.popoverBackground};
--popover-backdrop-filter: saturate(120%) blur(12px);
display: grid;
@@ -1,26 +1,33 @@
import React, { useContext, useState } from 'react';
import React, { PropsWithChildren, useContext, useState } from 'react';
import { Point } from '@visx/point';
import { localPoint } from '@visx/event';
import { XYChart, DataContext } from '@visx/xychart';
import { XYChart, DataContext, type EventHandlerParams } from '@visx/xychart';
import { getScaleBandwidth } from '@/components/visx/getScaleBandwidth';
export const XYChartWithPointerEvents = ({
onPointerMove, onPointerUp, onPointerPressedChange, ...props
onPointerMove,
onPointerUp,
onPointerPressedChange,
...props
}: {
onPointerMove?: (point: Point) => void;
onPointerUp?: (point: Point) => void;
onPointerMove?: (point: Point | EventHandlerParams<object>) => void;
onPointerUp?: (point: Point | EventHandlerParams<object>) => void;
onPointerPressedChange?: (isPointerPressed: boolean) => void;
} & React.PropsWithChildren<Parameters<typeof XYChart>>) => {
} & PropsWithChildren<Parameters<typeof XYChart>[0]>) => {
const { xScale, yScale } = useContext(DataContext);
const [lastPointerMoveEvent, setLastPointerMoveEvent] = useState<React.PointerEvent>();
const pointerContainerPosition = lastPointerMoveEvent ? localPoint(lastPointerMoveEvent) : null;
const pointerChartPosition = xScale && yScale && pointerContainerPosition &&
const pointerChartPosition =
xScale &&
yScale &&
pointerContainerPosition &&
new Point({
// @ts-expect-error invert supposedly doesn't exist on AxisScale
x: xScale.invert(pointerContainerPosition?.x - getScaleBandwidth(xScale) / 2),
// @ts-expect-error invert supposedly doesn't exist on AxisScale
y: yScale.invert(pointerContainerPosition?.y - getScaleBandwidth(yScale) / 2),
});
@@ -29,15 +36,13 @@ export const XYChartWithPointerEvents = ({
{...props}
onPointerMove={({ event }) => {
setLastPointerMoveEvent(event as React.PointerEvent);
if (pointerChartPosition)
onPointerMove?.(pointerChartPosition);
if (pointerChartPosition) onPointerMove?.(pointerChartPosition);
}}
onPointerOut={() => setLastPointerMoveEvent(undefined)}
onPointerDown={() => onPointerPressedChange?.(true)}
onPointerUp={() => {
onPointerPressedChange?.(false);
if (pointerChartPosition)
onPointerUp?.(pointerChartPosition);
if (pointerChartPosition) onPointerUp?.(pointerChartPosition);
}}
>
{props.children}
+38 -4
View File
@@ -119,6 +119,13 @@ export const InputSelectionOption = Abacus.exchange.dydx.abacus.output.input.Sel
// ------ Wallet ------ //
export type Wallet = Abacus.exchange.dydx.abacus.output.Wallet;
export type AccountBalance = Abacus.exchange.dydx.abacus.output.AccountBalance;
export type TradingRewards = Abacus.exchange.dydx.abacus.output.TradingRewards;
export type HistoricalTradingReward = Abacus.exchange.dydx.abacus.output.HistoricalTradingReward;
export const HistoricalTradingRewardsPeriod =
Abacus.exchange.dydx.abacus.state.manager.HistoricalTradingRewardsPeriod;
const historicalTradingRewardsPeriod = [...HistoricalTradingRewardsPeriod.values()] as const;
export type HistoricalTradingRewardsPeriods = (typeof historicalTradingRewardsPeriod)[number];
export type Subaccount = Abacus.exchange.dydx.abacus.output.Subaccount;
export type SubaccountPosition = Abacus.exchange.dydx.abacus.output.SubaccountPosition;
export type SubaccountOrder = Abacus.exchange.dydx.abacus.output.SubaccountOrder;
@@ -142,7 +149,7 @@ const historicalPnlPeriod = [...HistoricalPnlPeriod.values()] as const;
export type HistoricalPnlPeriods = (typeof historicalPnlPeriod)[number];
// ------ Transfer Items ------ //
export const TransferInputField = Abacus.exchange.dydx.abacus.state.modal.TransferInputField;
export const TransferInputField = Abacus.exchange.dydx.abacus.state.model.TransferInputField;
const transferInputFields = [...TransferInputField.values()] as const;
export type TransferInputFields = (typeof transferInputFields)[number];
@@ -151,7 +158,7 @@ const transferTypes = [...TransferType.values()] as const;
export type TransferTypes = (typeof transferTypes)[number];
// ------ Trade Items ------ //
export const TradeInputField = Abacus.exchange.dydx.abacus.state.modal.TradeInputField;
export const TradeInputField = Abacus.exchange.dydx.abacus.state.model.TradeInputField;
const tradeInputFields = [...TradeInputField.values()] as const;
export type TradeInputFields = (typeof tradeInputFields)[number];
@@ -162,7 +169,7 @@ export type TradeState<T> = {
};
export const ClosePositionInputField =
Abacus.exchange.dydx.abacus.state.modal.ClosePositionInputField;
Abacus.exchange.dydx.abacus.state.model.ClosePositionInputField;
const closePositionInputFields = [...ClosePositionInputField.values()] as const;
export type ClosePositionInputFields = (typeof closePositionInputFields)[number];
@@ -202,6 +209,9 @@ export const RestrictionType = Abacus.exchange.dydx.abacus.output.Restriction;
const restrictionTypes = [...RestrictionType.values()] as const;
export type RestrictionTypes = (typeof restrictionTypes)[number];
// ------ Api data ------ //
export const ApiData = Abacus.exchange.dydx.abacus.state.manager.ApiData;
// ------ Enum Conversions ------ //
type IfEquals<X, Y, A, B> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2
? A
@@ -236,6 +246,15 @@ export const HISTORICAL_PNL_PERIODS: Record<
[HistoricalPnlPeriod.Period90d.name]: HistoricalPnlPeriod.Period90d,
};
export const HISTORICAL_TRADING_REWARDS_PERIODS: Record<
KotlinIrEnumValues<typeof HistoricalTradingRewardsPeriod>,
HistoricalTradingRewardsPeriods
> = {
[HistoricalTradingRewardsPeriod.MONTHLY.name]: HistoricalTradingRewardsPeriod.MONTHLY,
[HistoricalTradingRewardsPeriod.WEEKLY.name]: HistoricalTradingRewardsPeriod.WEEKLY,
[HistoricalTradingRewardsPeriod.DAILY.name]: HistoricalTradingRewardsPeriod.DAILY,
};
export const ORDER_STATUS_STRINGS: Record<KotlinIrEnumValues<typeof AbacusOrderStatus>, string> = {
[AbacusOrderStatus.open.name]: STRING_KEYS.OPEN_STATUS,
[AbacusOrderStatus.open.rawValue]: STRING_KEYS.OPEN_STATUS,
@@ -282,13 +301,22 @@ export const TRADE_TYPES: Record<
[AbacusOrderType.takeProfitMarket.rawValue]: TradeTypes.TAKE_PROFIT_MARKET,
[AbacusOrderType.liquidated.name]: null,
[AbacusOrderType.liquidation.name]: null,
[AbacusOrderType.liquidated.rawValue]: null,
[AbacusOrderType.liquidation.name]: null,
[AbacusOrderType.liquidation.rawValue]: null,
[AbacusOrderType.trailingStop.name]: null,
[AbacusOrderType.trailingStop.rawValue]: null,
[AbacusOrderType.offsetting.name]: null,
[AbacusOrderType.offsetting.rawValue]: null,
[AbacusOrderType.deleveraged.name]: null,
[AbacusOrderType.deleveraged.rawValue]: null,
[AbacusOrderType.finalSettlement.name]: null,
[AbacusOrderType.finalSettlement.rawValue]: null,
};
// Custom types involving Abacus
@@ -307,3 +335,9 @@ export type NetworkConfig = Partial<{
}>;
export type ConnectNetworkEvent = CustomEvent<Partial<NetworkConfig>>;
export type PerpetualMarketOrderbookLevel = OrderbookLine & {
side?: 'ask' | 'bid';
mine: number;
key: string;
};
+1
View File
@@ -96,6 +96,7 @@ export type AnalyticsEventData<T extends AnalyticsEvent> =
elapsedTime?: number;
blockHeight?: number;
indexerBlockHeight?: number;
trailingBlocks?: number;
}
: // Navigation
T extends AnalyticsEvent.NavigatePage
+40
View File
@@ -0,0 +1,40 @@
import { OrderSide } from '@dydxprotocol/v4-client-js';
import { FundingDirection } from './markets';
// ------ Depth Chart ------ //
export enum DepthChartSeries {
Asks = 'Asks',
Bids = 'Bids',
MidMarket = 'MidMarket',
}
export type DepthChartDatum = {
size: number;
price: number;
depth: number;
seriesKey: DepthChartSeries;
};
export type DepthChartPoint = {
side: OrderSide;
price: number;
size: number;
};
export const SERIES_KEY_FOR_ORDER_SIDE = {
[OrderSide.BUY]: DepthChartSeries.Bids,
[OrderSide.SELL]: DepthChartSeries.Asks,
};
// ------ Funding Chart ------ //
export enum FundingRateResolution {
OneHour = 'OneHour',
EightHour = 'EightHour',
Annualized = 'Annualized',
}
export type FundingChartDatum = {
time: number;
fundingRate: number;
direction: FundingDirection;
};
+3
View File
@@ -2,6 +2,7 @@ export enum DialogTypes {
ClosePosition = 'ClosePosition',
Deposit = 'Deposit',
DisconnectWallet = 'DisconnectWallet',
DisplaySettings = 'DisplaySettings',
ExchangeOffline = 'ExchangeOffline',
ExternalLink = 'ExternalLink',
FillDetails = 'FillDetails',
@@ -19,6 +20,8 @@ export enum DialogTypes {
Transfer = 'Transfer',
Withdraw = 'Withdraw',
ManageFunds = 'ManageFunds',
NewMarketMessageDetails = 'NewMarketMessageDetails',
NewMarketAgreement = 'NewMarketAgreement',
}
export enum TradeBoxDialogTypes {
+23
View File
@@ -0,0 +1,23 @@
/**
* Temporary Indexer types
* remove when Indexer type lib is available through @dydxprotocol/v4-client-js
*/
export type PerpetualMarketResponse = {
clobPairId: string;
ticker: string;
status: string;
oraclePrice: string;
priceChange24H: string;
volume24H: string;
trades24H: number;
nextFundingRate: string;
initialMarginFraction: string;
maintenanceMarginFraction: string;
openInterest: string;
atomicResolution: number;
quantumConversionExponent: number;
tickSize: string;
stepSize: string;
stepBaseQuantums: number;
subticksPerTick: number;
};
+1
View File
@@ -20,6 +20,7 @@ export enum LocalStorageKey {
SelectedLocale = 'dydx.SelectedLocale',
SelectedNetwork = 'dydx.SelectedNetwork',
SelectedTheme = 'dydx.SelectedTheme',
SelectedColorMode = 'dydx.SelectedColorMode',
SelectedTradeLayout = 'dydx.SelectedTradeLayout',
TradingViewChartConfig = 'dydx.TradingViewChartConfig',
HasSeenLaunchIncentives = 'dydx.HasSeenLaunchIncentives',
+1 -1
View File
@@ -95,7 +95,7 @@ export type TooltipStrings = {
stringParams?: any;
urlConfigs?: LinksConfigs;
}) => {
title: string;
title?: string;
body: string;
learnMoreLink?: string;
};
+1
View File
@@ -25,4 +25,5 @@ export const DEFAULT_MARKETID = 'ETH-USD';
export enum FundingDirection {
ToShort = 'ToShort',
ToLong = 'ToLong',
None = 'None',
}
+2
View File
@@ -87,6 +87,8 @@ export type NotificationDisplayData = {
slotTitleLeft?: React.ReactNode;
slotTitleRight?: React.ReactNode;
groupKey: string; // Grouping key toast notification stacking
// Overrides title/body for Notification in NotificationMenu
renderCustomBody?: ({
isToast,
+15
View File
@@ -0,0 +1,15 @@
/**
* @description Orderbook display constants
*/
export const ORDERBOOK_MAX_ROWS_PER_SIDE = 30;
export const ORDERBOOK_ANIMATION_DURATION = 400;
/**
* @description Orderbook pixel constants
* @note ORDERBOOK_ROW_HEIGHT should be a divisor of ORDERBOOK_HEIGHT so that we do not have a partial row at the bottom
* @note To change the Orderbook width, --orderbook-trades-width and ORDERBOOK_WIDTH must be changed to the same value
*/
export const ORDERBOOK_HEIGHT = 800;
export const ORDERBOOK_WIDTH = 300;
export const ORDERBOOK_ROW_HEIGHT = 24;
export const ORDERBOOK_ROW_PADDING_RIGHT = 8;
+85
View File
@@ -0,0 +1,85 @@
export type ExchangeConfigParsedCsv = Array<{
base_asset: string;
exchange: string;
pair: string;
adjust_by_market: string;
min_2_depth: string;
avg_30d_vol: string;
reference_price: string;
risk_assessment: string;
num_oracles: string;
liquidity_tier: string;
asset_name: string;
}>;
export type ExchangeConfigItem = {
exchangeName: string;
ticker: string;
adjustByMarket?: string;
};
export type PotentialMarketParsedCsv = Array<{
base_asset: string;
reference_price: string;
num_oracles: string;
liquidity_tier: string;
asset_name: string;
p: string;
atomic_resolution: string;
min_exchanges: string;
min_price_change_ppm: string;
price_exponent: string;
step_base_quantum: string;
ticksize_exponent: string;
subticks_per_tick: string;
min_order_size: string;
quantum_conversion_exponent: string;
}>;
export type PotentialMarketItem = {
baseAsset: string;
referencePrice: string;
numOracles: number;
liquidityTier: number;
assetName: string;
p: number;
atomicResolution: number;
minExchanges: number;
minPriceChangePpm: number;
priceExponent: number;
stepBaseQuantum: number;
ticksizeExponent: number;
subticksPerTick: number;
minOrderSize: number;
quantumConversionExponent: number;
};
export const NUM_ORACLES_TO_QUALIFY_AS_SAFE = 6;
export const LIQUIDITY_TIERS = {
0: {
label: 'Large-cap',
initialMarginFraction: 0.05,
maintenanceMarginFraction: 0.03,
impactNotional: 10_000,
},
1: {
label: 'Mid-cap',
initialMarginFraction: 0.1,
maintenanceMarginFraction: 0.05,
impactNotional: 5_000,
},
2: {
label: 'Long-tail',
initialMarginFraction: 0.2,
maintenanceMarginFraction: 0.1,
impactNotional: 2_500,
},
3: {
label: 'Safety',
initialMarginFraction: 1,
maintenanceMarginFraction: 0.2,
impactNotional: 2_500,
},
};
+4
View File
@@ -11,6 +11,10 @@ export enum AppRoute {
Privacy = '/privacy',
}
export enum MarketsRoute {
New = 'new',
}
export enum PortfolioRoute {
Fees = 'fees',
History = 'history',
+76
View File
@@ -0,0 +1,76 @@
export enum ColorToken {
Black = '#000000',
White = '#FFFFFF',
LightGray0 = '#FAFAFA',
LightGray1 = '#F7F8FA',
LightGray2 = '#FAFAFD',
LightGray3 = '#F5F5F5',
LightGray4 = '#EDF0F2',
LightGray5 = '#EDEDED',
LightGray6 = '#E9ECEE',
LightGray7 = '#E6E6E6',
LightGray8 = '#DBDBDB',
LightGray9 = '#D5DADF',
LightGray10 = '#D1D9E0',
MediumGray0 = '#CACACE',
MediumGray1 = '#C2CBD3',
DarkGray0 = '#888891',
DarkGray1 = '#737373',
DarkGray2 = '#56565C',
DarkGray3 = '#4B4B4B',
DarkGray4 = '#494950',
DarkGray5 = '#3B3B3F',
DarkGray6 = '#303033',
DarkGray7 = '#313135',
DarkGray8 = '#292929',
DarkGray9 = '#23232F',
DarkGray10 = '#212124',
DarkGray11 = '#18181B',
DarkGray12 = '#181818',
DarkGray13 = '#0C0C0D',
GrayBlue0 = '#464659',
GrayBlue1 = '#38384D',
GrayBlue2 = '#303045',
GrayBlue3 = '#29293D',
GrayBlue4 = '#212131',
GrayBlue5 = '#181825',
GrayBlue6 = '#101018',
GrayBlue7 = '#08080C',
GrayPurple0 = '#DFDADF',
GrayPurple1 = '#C8C7D8',
GrayPurple2 = '#807E98',
Purple0 = '#7774FF',
Purple1 = '#6966FF',
Green0 = '#1AFFB9',
Green1 = '#3ED9A4',
Green2 = '#2CCC98',
Green3 = '#3EB68A',
Yellow0 = '#FFCC48',
Yellow1 = '#FFB647',
Red0 = '#FF5C5C',
Red1 = '#E76565',
Red2 = '#E45555',
}
/** Maps opacity to corresponding hex value */
export enum OpacityToken {
Opacity16 = '29',
Opacity20 = '33',
Opacity66 = 'A8',
Opacity90 = 'E6',
}
export enum BrightnessFilterToken {
Darken10 = '0.9',
Darken5 = '0.95',
Lighten10 = '1.1',
}
+98
View File
@@ -0,0 +1,98 @@
import { AppColorMode } from '@/state/configs';
export type Theme = {
[AppColorMode.GreenUp]: ThemeColorBase;
[AppColorMode.RedUp]: ThemeColorBase;
};
export type ThemeColorBase = LayerColors &
BorderColors &
TextColors &
GradientColors &
AccentColors &
StatusColors &
DirectionalColors &
RiskColors &
IconColors &
ComponentColors &
Filters;
type LayerColors = {
layer0: string;
layer1: string;
layer2: string;
layer3: string;
layer4: string;
layer5: string;
layer6: string;
layer7: string;
};
type BorderColors = {
borderDefault: string;
borderDestructive: string;
borderButton: string;
};
type TextColors = {
textPrimary: string;
textSecondary: string;
textTertiary: string;
textButton: string;
};
type GradientColors = {
gradientBase0: string;
gradientBase1: string;
};
type AccentColors = {
accent: string;
accentFaded: string;
favorite: string;
};
type StatusColors = {
success: string;
warning: string;
error: string;
successFaded: string;
warningFaded: string;
errorFaded: string;
};
/** ##InvertDirectionalColors
* When adding colors here, make sure to update linked function to invert colors for AppColorMode. */
type DirectionalColors = {
positive: string;
negative: string;
positiveFaded: string;
negativeFaded: string;
};
type RiskColors = {
riskLow: string;
riskMedium: string;
riskHigh: string;
};
type IconColors = {
logoFill: string;
profileYellow: string;
profileRed: string;
};
type ComponentColors = {
inputBackground: string;
popoverBackground: string;
switchThumbActiveBackground: string;
toggleBackground: string;
tooltipBackground: string;
};
type Filters = {
hoverFilterBase: string;
hoverFilterVariant: string;
activeFilter: string;
};
+4
View File
@@ -1,6 +1,10 @@
import { type TooltipStrings, TOOLTIP_STRING_KEYS } from '@/constants/localization';
export const depositTooltips: TooltipStrings = {
'minimum-deposit-amount': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.MINIMUM_DEPOSIT_AMOUNT_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.MINIMUM_DEPOSIT_AMOUNT_BODY }),
}),
swap: ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.SWAP_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.SWAP_BODY }),
+20 -2
View File
@@ -57,10 +57,9 @@ export const tradeTooltips: TooltipStrings = {
title: stringGetter({ key: TOOLTIP_STRING_KEYS.INDEX_PRICE_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.INDEX_PRICE_BODY }),
}),
'initial-margin-fraction': ({ stringGetter, urlConfigs }) => ({
'initial-margin-fraction': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.INITIAL_MARGIN_FRACTION_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.INITIAL_MARGIN_FRACTION_BODY }),
learnMoreLink: urlConfigs?.initialMarginFractionLearnMore,
}),
'initial-stop': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.INITIAL_STOP_TITLE }),
@@ -138,6 +137,10 @@ export const tradeTooltips: TooltipStrings = {
title: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_BODY }),
}),
'post-only-timeinforce-gtt': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TIMEINFORCE_GTT_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TIMEINFORCE_GTT_BODY }),
}),
'price-impact': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.PRICE_IMPACT_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.PRICE_IMPACT_BODY }),
@@ -151,6 +154,18 @@ export const tradeTooltips: TooltipStrings = {
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_BODY }),
learnMoreLink: urlConfigs?.reduceOnlyLearnMore,
}),
'reduce-only-execution-ioc-fok': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_EXECUTION_IOC_FOK_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_EXECUTION_IOC_FOK_BODY }),
}),
'reduce-only-timeinforce-ioc-fok': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_TIMEINFORCE_IOC_FOK_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_TIMEINFORCE_IOC_FOK_BODY }),
}),
'reference-price': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.REFERENCE_PRICE_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REFERENCE_PRICE_BODY }),
}),
spread: () => ({
title: 'Spread',
body: 'The difference in price between the highest bid (the price a buyer is willing to buy for) and lowest ask (the price a seller is willing to sell for) an asset.',
@@ -183,4 +198,7 @@ export const tradeTooltips: TooltipStrings = {
title: stringGetter({ key: TOOLTIP_STRING_KEYS.UNREALIZED_PNL_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.UNREALIZED_PNL_BODY }),
}),
'reward-history': ({ stringGetter }) => ({
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REWARD_HISTORY_BODY }),
}),
} as const;
+4
View File
@@ -5,6 +5,10 @@ export const withdrawTooltips: TooltipStrings = {
title: stringGetter({ key: TOOLTIP_STRING_KEYS.FAST_WITHDRAW_FEE_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.FAST_WITHDRAW_FEE_BODY }),
}),
'minimum-amount-received': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.MINIMUM_AMOUNT_RECEIVED_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.MINIMUM_AMOUNT_RECEIVED_BODY }),
}),
'withdraw-types': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.WITHDRAW_TYPES_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.WITHDRAW_TYPES_BODY }),
+13 -1
View File
@@ -33,6 +33,7 @@ export enum WalletConnectionType {
CosmosSigner = 'CosmosSigner',
InjectedEip1193 = 'injectedEip1193',
WalletConnect2 = 'walletConnect2',
TestWallet = 'TestWallet',
}
export enum WalletErrorType {
@@ -68,6 +69,9 @@ export const walletConnectionTypes: Record<WalletConnectionType, WalletConnectio
[WalletConnectionType.CosmosSigner]: {
name: 'CosmosSigner',
},
[WalletConnectionType.TestWallet]: {
name: 'TestWallet',
},
};
// Wallets
@@ -88,7 +92,7 @@ export enum WalletType {
TokenPocket = 'TOKEN_POCKET',
TrustWallet = 'TRUST_WALLET',
WalletConnect2 = 'WALLETCONNECT_2',
// TestWallet = 'TEST_WALLET',
TestWallet = 'TEST_WALLET',
OtherWallet = 'OTHER_WALLET',
}
@@ -243,6 +247,12 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: KeplrIcon,
connectionTypes: [WalletConnectionType.CosmosSigner],
},
[WalletType.TestWallet]: {
type: WalletType.TestWallet,
stringKey: STRING_KEYS.TEST_WALLET,
icon: GenericWalletIcon,
connectionTypes: [WalletConnectionType.TestWallet],
},
};
// Injected EIP-1193 Providers
@@ -354,3 +364,5 @@ export enum DydxChainAsset {
USDC = 'usdc',
CHAINTOKEN = 'chain',
}
export const TEST_WALLET_EVM_ADDRESS: EvmAddress = '0x0000000000000000000000000000000000000000';
+4
View File
@@ -0,0 +1,4 @@
export * from './useCenterOrderbook';
export * from './useSpreadRowScrollListener';
export * from './useDrawOrderbook';
export * from './useOrderbookValues';
+22
View File
@@ -0,0 +1,22 @@
import { useEffect, type RefObject } from 'react';
type Props = {
marketId: string;
orderbookRef: RefObject<HTMLDivElement>;
};
/**
* @description Center Orderbook on load and market change
* Assumed that the two sides are the same height
*/
export const useCenterOrderbook = ({ marketId, orderbookRef }: Props) => {
const orderbookEl = orderbookRef.current;
const { clientHeight, scrollHeight } = orderbookEl ?? {};
const shouldScroll = scrollHeight && clientHeight && scrollHeight > clientHeight;
useEffect(() => {
if (orderbookEl && shouldScroll) {
orderbookEl.scrollTo({ top: (scrollHeight - clientHeight) / 2 });
}
}, [shouldScroll, marketId]);
};
+373
View File
@@ -0,0 +1,373 @@
import { useEffect, useMemo, useRef } from 'react';
import { shallowEqual, useSelector } from 'react-redux';
import type { PerpetualMarketOrderbookLevel } from '@/constants/abacus';
import { SMALL_USD_DECIMALS, TOKEN_DECIMALS } from '@/constants/numbers';
import {
ORDERBOOK_ANIMATION_DURATION,
ORDERBOOK_HEIGHT,
ORDERBOOK_ROW_HEIGHT,
ORDERBOOK_ROW_PADDING_RIGHT,
ORDERBOOK_WIDTH,
} from '@/constants/orderbook';
import { useAppThemeAndColorModeContext } from '@/hooks/useAppThemeAndColorMode';
import { getCurrentMarketConfig, getCurrentMarketOrderbookMap } from '@/state/perpetualsSelectors';
import { MustBigNumber } from '@/lib/numbers';
import {
getHistogramXValues,
getRektFromIdx,
getXByColumn,
getYForElements,
} from '@/lib/orderbookHelpers';
type ElementProps = {
data: Array<PerpetualMarketOrderbookLevel | undefined>;
histogramRange: number;
side: PerpetualMarketOrderbookLevel['side'];
};
type StyleProps = {
histogramSide: 'left' | 'right';
};
enum OrderbookRowAnimationType {
REMOVE,
NEW,
NONE,
}
export const useDrawOrderbook = ({
data,
histogramRange,
histogramSide,
side,
}: ElementProps & StyleProps) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
const canvas = canvasRef.current;
const currentOrderbookMap = useSelector(getCurrentMarketOrderbookMap, shallowEqual);
const { stepSizeDecimals = TOKEN_DECIMALS, tickSizeDecimals = SMALL_USD_DECIMALS } =
useSelector(getCurrentMarketConfig, shallowEqual) || {};
const prevData = useRef<typeof data>(data);
const theme = useAppThemeAndColorModeContext();
/**
* Scale canvas using device pixel ratio to unblur drawn text
* @url https://stackoverflow.com/questions/15661339/how-do-i-fix-blurry-text-in-my-html5-canvas/65124939#65124939
* @returns adjusted canvas width/height/rowHeight used in coordinates for drawing
**/
const { canvasWidth, canvasHeight, rowHeight } = useMemo(() => {
const ratio = window.devicePixelRatio || 1;
if (!canvas) {
return {
canvasWidth: ORDERBOOK_WIDTH / devicePixelRatio,
canvasHeight: ORDERBOOK_HEIGHT / devicePixelRatio,
rowHeight: ORDERBOOK_ROW_HEIGHT / devicePixelRatio,
};
}
const ctx = canvas.getContext('2d');
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
if (ctx) {
ctx.scale(ratio, ratio);
ctx.font = '12px Satoshi';
ctx.textAlign = 'right';
ctx.textBaseline = 'middle';
ctx.imageSmoothingQuality = 'high';
}
return {
canvasWidth: canvas.width / ratio,
canvasHeight: canvas.height / ratio,
rowHeight: ORDERBOOK_ROW_HEIGHT,
};
}, [canvas]);
const drawBars = ({
barType,
ctx,
depthOrSizeValue,
gradientMultiplier,
histogramAccentColor,
histogramSide,
idx,
}: {
barType: 'depth' | 'size';
ctx: CanvasRenderingContext2D;
depthOrSizeValue: number;
gradientMultiplier: number;
histogramAccentColor: string;
histogramSide: 'left' | 'right';
idx: number;
}) => {
const { x1, x2, y1, y2 } = getRektFromIdx({
idx,
rowHeight,
canvasWidth,
canvasHeight,
side,
});
// X values
const maxHistogramBarWidth = x2 - x1 - (barType === 'size' ? 8 : 2);
const barWidth = depthOrSizeValue
? Math.min((depthOrSizeValue / histogramRange) * maxHistogramBarWidth, maxHistogramBarWidth)
: 0;
const { gradient, bar } = getHistogramXValues({
barWidth,
canvasWidth,
gradientMultiplier,
histogramSide,
});
// Gradient
let linearGradient;
try {
linearGradient = ctx.createLinearGradient(gradient.x1, y1, gradient.x2, y2);
linearGradient.addColorStop(0, histogramAccentColor);
linearGradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
ctx.fillStyle = linearGradient;
} catch (err) {
ctx.fillStyle = 'rgba(0, 0, 0, 0)';
}
ctx.beginPath();
// Bar
const { bar: y } = getYForElements({ y: y1, rowHeight });
if (ctx.roundRect) {
ctx.roundRect(
bar.x1,
y,
bar.x2,
rowHeight - 2,
histogramSide === 'right' ? [2, 0, 0, 2] : [0, 2, 2, 0]
);
} else {
ctx.rect(bar.x1, y, bar.x2, rowHeight - 2);
}
ctx.fill();
};
const drawText = ({
animationType = OrderbookRowAnimationType.NONE,
ctx,
idx,
mine,
price,
size,
}: {
animationType?: OrderbookRowAnimationType;
ctx: CanvasRenderingContext2D;
idx: number;
mine?: number;
price?: number;
size?: number;
}) => {
const { y1 } = getRektFromIdx({
idx,
rowHeight,
canvasWidth,
canvasHeight,
side,
});
const { text: y } = getYForElements({ y: y1, rowHeight });
let textColor: string;
let updatedTextColor: string | undefined;
switch (animationType) {
case OrderbookRowAnimationType.REMOVE: {
textColor = theme.textSecondary;
break;
}
case OrderbookRowAnimationType.NEW: {
updatedTextColor = side === 'bid' ? theme.positive : theme.negative;
textColor = theme.textPrimary;
break;
}
default: {
textColor = theme.textPrimary;
break;
}
}
// Size text
if (size) {
ctx.fillStyle = updatedTextColor ?? textColor;
ctx.fillText(
MustBigNumber(size).toFixed(stepSizeDecimals ?? TOKEN_DECIMALS),
getXByColumn({ canvasWidth, colIdx: 0 }) - ORDERBOOK_ROW_PADDING_RIGHT,
y
);
}
// Price text
if (price) {
ctx.fillStyle = textColor;
ctx.fillText(
MustBigNumber(price).toFixed(tickSizeDecimals ?? SMALL_USD_DECIMALS),
getXByColumn({ canvasWidth, colIdx: 1 }) - ORDERBOOK_ROW_PADDING_RIGHT,
y
);
}
// Mine text
if (mine) {
ctx.fillStyle = textColor;
ctx.fillText(
MustBigNumber(mine).toFixed(stepSizeDecimals ?? TOKEN_DECIMALS),
getXByColumn({ canvasWidth, colIdx: 2 }) - ORDERBOOK_ROW_PADDING_RIGHT,
y
);
}
};
const drawOrderbookRow = ({
ctx,
idx,
rowToRender,
animationType = OrderbookRowAnimationType.NONE,
}: {
ctx: CanvasRenderingContext2D;
idx: number;
rowToRender?: PerpetualMarketOrderbookLevel;
animationType?: OrderbookRowAnimationType;
}) => {
if (!rowToRender) return;
const { depth, mine, price, size } = rowToRender;
const histogramAccentColor = side === 'bid' ? theme.positiveFaded : theme.negativeFaded;
// Depth Bar
if (depth) {
drawBars({
barType: 'depth',
ctx,
depthOrSizeValue: depth,
gradientMultiplier: 1.3,
histogramAccentColor,
histogramSide,
idx,
});
}
// Size Bar
drawBars({
barType: 'size',
ctx,
depthOrSizeValue: size,
gradientMultiplier: 5,
histogramAccentColor,
histogramSide,
idx,
});
// Size, Price, Mine
drawText({
animationType,
ctx,
idx,
mine,
price,
size,
});
};
// Update histograms and row contents on data change
useEffect(() => {
const ctx = canvas?.getContext('2d');
if (!canvas || !ctx) return;
// Clear canvas before redraw
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// Animate row removal and update
const mapOfOrderbookPriceLevels =
side && currentOrderbookMap?.[side === 'ask' ? 'asks' : 'bids'];
const empty: number[] = [];
const removed: number[] = [];
const updated: number[] = [];
prevData.current.forEach((row, idx) => {
if (!row) {
empty.push(idx);
return;
}
if (mapOfOrderbookPriceLevels?.[row.price] === 0) {
removed.push(idx);
drawOrderbookRow({
ctx,
idx,
rowToRender: row,
animationType: OrderbookRowAnimationType.REMOVE,
});
} else if (mapOfOrderbookPriceLevels?.[row.price] === row?.size) {
drawOrderbookRow({
ctx,
idx,
rowToRender: data[idx],
animationType: OrderbookRowAnimationType.NONE,
});
} else {
updated.push(idx);
drawOrderbookRow({
ctx,
idx,
rowToRender: row,
animationType: OrderbookRowAnimationType.NEW,
});
}
});
setTimeout(() => {
[...empty, ...removed, ...updated].forEach((idx) => {
const { x1, y1, x2, y2 } = getRektFromIdx({
idx,
rowHeight,
canvasWidth,
canvasHeight,
side,
});
ctx.clearRect(x1, y1, x2 - x1, y2 - y1);
drawOrderbookRow({
ctx,
idx,
rowToRender: data[idx],
});
});
}, ORDERBOOK_ANIMATION_DURATION);
prevData.current = data;
}, [
canvasHeight,
canvasWidth,
rowHeight,
data,
histogramRange,
stepSizeDecimals,
tickSizeDecimals,
histogramSide,
side,
theme,
currentOrderbookMap,
]);
return { canvasRef };
};
+126
View File
@@ -0,0 +1,126 @@
import { useMemo } from 'react';
import { shallowEqual, useSelector } from 'react-redux';
import { OrderSide } from '@dydxprotocol/v4-client-js';
import { type PerpetualMarketOrderbookLevel } from '@/constants/abacus';
import { DepthChartSeries, DepthChartDatum } from '@/constants/charts';
import { getCurrentMarketOrderbook } from '@/state/perpetualsSelectors';
import { getSubaccountOpenOrdersBySideAndPrice } from '@/state/accountSelectors';
import { MustBigNumber } from '@/lib/numbers';
export const useCalculateOrderbookData = ({ maxRowsPerSide }: { maxRowsPerSide: number }) => {
const orderbook = useSelector(getCurrentMarketOrderbook, shallowEqual);
const openOrdersBySideAndPrice =
useSelector(getSubaccountOpenOrdersBySideAndPrice, shallowEqual) || {};
return useMemo(() => {
const asks: Array<PerpetualMarketOrderbookLevel | undefined> = (
orderbook?.asks?.toArray() ?? []
)
.map(
(row, idx: number) =>
({
key: `ask-${idx}`,
side: 'ask',
mine: openOrdersBySideAndPrice[OrderSide.SELL]?.[row.price]?.size,
...row,
} as PerpetualMarketOrderbookLevel)
)
.slice(0, maxRowsPerSide);
const bids: Array<PerpetualMarketOrderbookLevel | undefined> = (
orderbook?.bids?.toArray() ?? []
)
.map(
(row, idx: number) =>
({
key: `bid-${idx}`,
side: 'bid',
mine: openOrdersBySideAndPrice[OrderSide.BUY]?.[row.price]?.size,
...row,
} as PerpetualMarketOrderbookLevel)
)
.slice(0, maxRowsPerSide);
// Prevent the bid/ask sides from crossing by using the offsets.
// While the books are crossing...
while (asks[0] && bids[0] && bids[0]!.price >= asks[0].price) {
// Drop the order on the side with the lower offset.
// The offset of the other side is higher and so supercedes.
if (bids[0]!.offset === asks[0].offset) {
// If offsets are the same, give precedence to the larger size. In this case,
// one of the sizes *should* be zero, but we simply check for the larger size.
if (bids[0]!.size > asks[0].size) {
asks.shift();
} else {
bids.pop();
}
} else {
// Offsets are not equal. Give precedence to the larger offset.
if (bids[0]!.offset > asks[0].offset) {
asks.shift();
} else {
bids.pop();
}
}
}
const spread =
asks[0]?.price && bids[0]?.price ? MustBigNumber(asks[0].price).minus(bids[0].price) : null;
const spreadPercent = orderbook?.spreadPercent;
const histogramRange = Math.max(
isNaN(Number(bids[bids.length - 1]?.depth)) ? 0 : Number(bids[bids.length - 1]?.depth),
isNaN(Number(asks[asks.length - 1]?.depth)) ? 0 : Number(asks[asks.length - 1]?.depth)
);
return {
asks,
bids,
spread,
spreadPercent,
histogramRange,
hasOrderbook: !!orderbook,
};
}, [orderbook, openOrdersBySideAndPrice]);
};
export const useOrderbookValuesForDepthChart = () => {
const orderbook = useSelector(getCurrentMarketOrderbook, shallowEqual);
return useMemo(() => {
const bids = (orderbook?.bids?.toArray() ?? [])
.filter(Boolean)
.map((datum) => ({ ...datum, seriesKey: DepthChartSeries.Bids } as DepthChartDatum));
const asks = (orderbook?.asks?.toArray() ?? [])
.filter(Boolean)
.map((datum) => ({ ...datum, seriesKey: DepthChartSeries.Asks } as DepthChartDatum));
const lowestBid = bids[bids.length - 1];
const highestBid = bids[0];
const lowestAsk = asks[0];
const highestAsk = asks[asks.length - 1];
const midMarketPrice = orderbook?.midPrice;
const spread = MustBigNumber(lowestAsk?.price ?? 0).minus(highestBid?.price ?? 0);
const spreadPercent = orderbook?.spreadPercent;
return {
bids,
asks,
lowestBid,
highestBid,
lowestAsk,
highestAsk,
midMarketPrice,
spread,
spreadPercent,
orderbook,
};
}, [orderbook]);
};
@@ -0,0 +1,39 @@
import { type RefObject, useEffect, useState } from 'react';
export const useSpreadRowScrollListener = ({
orderbookRef,
spreadRowRef,
}: {
orderbookRef: RefObject<HTMLDivElement>;
spreadRowRef: RefObject<HTMLDivElement>;
}) => {
const [displaySide, setDisplaySide] = useState<string>();
useEffect(() => {
const onScroll = () => {
if (spreadRowRef.current && orderbookRef.current) {
const { clientHeight } = orderbookRef.current;
const parent = orderbookRef.current.getBoundingClientRect();
const spread = spreadRowRef.current.getBoundingClientRect();
const spreadTop = spread.top - parent.top;
const spreadBottom = spread.bottom - parent.top;
if (spreadBottom > clientHeight) {
setDisplaySide('bottom');
} else if (spreadTop < 0) {
setDisplaySide('top');
} else {
setDisplaySide(undefined);
}
}
};
orderbookRef.current?.addEventListener('scroll', onScroll, false);
return () => {
orderbookRef.current?.removeEventListener('scroll', onScroll, false);
};
}, [orderbookRef.current, spreadRowRef.current]);
return displaySide;
};
+4
View File
@@ -7,6 +7,7 @@ import { useDebounce } from './useDebounce';
import { useInterval } from './useInterval';
import { useDocumentTitle } from './useDocumentTitle';
import { useDydxClient } from './useDydxClient';
import { useGovernanceVariables } from './useGovernanceVariables';
import { useAccountBalance } from './useAccountBalance';
import { useAccounts } from './useAccounts';
import { useAnalytics } from './useAnalytics';
@@ -14,6 +15,7 @@ import { useInitializePage } from './useInitializePage';
import { useIsFirstRender } from './useIsFirstRender';
import { useLocaleSeparators } from './useLocaleSeparators';
import { useLocalStorage } from './useLocalStorage';
import { useNextClobPairId } from './useNextClobPairId';
import { useNow } from './useNow';
import { useOnClickOutside } from './useOnClickOutside';
import { usePageTitlePriceUpdates } from './usePageTitlePriceUpdates';
@@ -34,6 +36,7 @@ export {
useDebounce,
useDocumentTitle,
useDydxClient,
useGovernanceVariables,
useAccountBalance,
useAccounts,
useAnalytics,
@@ -42,6 +45,7 @@ export {
useIsFirstRender,
useLocaleSeparators,
useLocalStorage,
useNextClobPairId,
useNow,
useOnClickOutside,
usePageTitlePriceUpdates,
+11 -3
View File
@@ -11,7 +11,7 @@ import { useDydxClient, useLocalStorage } from '@/hooks';
import { store } from '@/state/_store';
import { getSelectedNetwork } from '@/state/appSelectors';
import { getAppTheme } from '@/state/configsSelectors';
import { getAppTheme, getAppColorMode } from '@/state/configsSelectors';
import { getSelectedLocale } from '@/state/localizationSelectors';
import { getCurrentMarketId, getMarketIds } from '@/state/perpetualsSelectors';
@@ -30,6 +30,7 @@ export const useTradingView = ({
}) => {
const marketId = useSelector(getCurrentMarketId);
const appTheme = useSelector(getAppTheme);
const appColorMode = useSelector(getAppColorMode);
const marketIds = useSelector(getMarketIds, shallowEqual);
const selectedLocale = useSelector(getSelectedLocale);
const selectedNetwork = useSelector(getSelectedNetwork);
@@ -46,7 +47,7 @@ export const useTradingView = ({
useEffect(() => {
if (hasMarkets && isClientConnected && marketId) {
const widgetOptions = getWidgetOptions();
const widgetOverrides = getWidgetOverrides(appTheme);
const widgetOverrides = getWidgetOverrides({ appTheme, appColorMode });
const options = {
// debug: true,
...widgetOptions,
@@ -75,7 +76,14 @@ export const useTradingView = ({
tvWidgetRef.current = null;
setIsChartReady(false);
};
}, [getCandlesForDatafeed, isClientConnected, hasMarkets, selectedLocale, selectedNetwork, !!marketId]);
}, [
getCandlesForDatafeed,
isClientConnected,
hasMarkets,
selectedLocale,
selectedNetwork,
!!marketId,
]);
return { savedResolution };
};
+20 -6
View File
@@ -3,9 +3,8 @@ import { useSelector } from 'react-redux';
import type { IChartingLibraryWidget, ThemeName } from 'public/tradingview/charting_library';
import { AppTheme } from '@/state/configs';
import { getAppTheme } from '@/state/configsSelectors';
import { AppColorMode, AppTheme } from '@/state/configs';
import { getAppTheme, getAppColorMode } from '@/state/configsSelectors';
import { getWidgetOverrides } from '@/lib/tradingView/utils';
@@ -29,7 +28,8 @@ export const useTradingViewTheme = ({
tvWidget: (IChartingLibraryWidget & { _id?: string; _ready?: boolean }) | null;
isWidgetReady?: boolean;
}) => {
const appTheme = useSelector(getAppTheme);
const appTheme: AppTheme = useSelector(getAppTheme);
const appColorMode: AppColorMode = useSelector(getAppColorMode);
useEffect(() => {
if (tvWidget && isWidgetReady) {
@@ -56,10 +56,24 @@ export const useTradingViewTheme = ({
}
}
const { overrides, studies_overrides } = getWidgetOverrides(appTheme);
const { overrides, studies_overrides } = getWidgetOverrides({ appTheme, appColorMode });
tvWidget?.applyOverrides(overrides);
tvWidget?.applyStudiesOverrides(studies_overrides);
// Necessary to update existing indicators
const volumeStudyId = tvWidget
?.activeChart()
?.getAllStudies()
?.find((x) => x.name === 'Volume')?.id;
if (volumeStudyId) {
const volume = tvWidget?.activeChart()?.getStudyById(volumeStudyId);
volume.applyOverrides({
'volume.color.0': studies_overrides['volume.volume.color.0'],
'volume.color.1': studies_overrides['volume.volume.color.1'],
});
}
});
}
}, [appTheme]);
}, [appTheme, appColorMode]);
};
+37 -2
View File
@@ -6,14 +6,22 @@ import { NOBLE_BECH32_PREFIX, LocalWallet, type Subaccount } from '@dydxprotocol
import { OnboardingGuard, OnboardingState, type EvmDerivedAddresses } from '@/constants/account';
import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization';
import { LocalStorageKey, LOCAL_STORAGE_VERSIONS } from '@/constants/localStorage';
import { DydxAddress, EvmAddress, PrivateInformation } from '@/constants/wallets';
import {
DydxAddress,
EvmAddress,
PrivateInformation,
TEST_WALLET_EVM_ADDRESS,
WalletType,
} from '@/constants/wallets';
import { setOnboardingState, setOnboardingGuard } from '@/state/account';
import { forceOpenDialog } from '@/state/dialogs';
import abacusStateManager from '@/lib/abacus';
import { log } from '@/lib/telemetry';
import { testFlags } from '@/lib/testFlags';
import { useDydxClient } from './useDydxClient';
import { useLocalStorage } from './useLocalStorage';
@@ -153,6 +161,7 @@ const useAccountsContext = () => {
// dYdX wallet / onboarding state
const [localDydxWallet, setLocalDydxWallet] = useState<LocalWallet>();
const [localNobleWallet, setLocalNobleWallet] = useState<LocalWallet>();
const [hdKey, setHdKey] = useState<PrivateInformation>();
const dydxAccounts = useMemo(() => localDydxWallet?.accounts, [localDydxWallet]);
@@ -162,6 +171,11 @@ const useAccountsContext = () => {
[localDydxWallet]
);
const nobleAddress = useMemo(
() => localNobleWallet?.address,
[localNobleWallet]
);
const setWalletFromEvmSignature = async (signature: string) => {
const { wallet, mnemonic, privateKey, publicKey } = await getWalletFromEvmSignature({
signature,
@@ -178,7 +192,26 @@ const useAccountsContext = () => {
useEffect(() => {
(async () => {
if (connectedDydxAddress && signerGraz) {
if (walletType === WalletType.TestWallet) {
// Get override values. Use the testFlags value if it exists, otherwise use the previously
// saved value where possible. If neither exist, use a default garbage value.
const addressOverride: DydxAddress = testFlags.addressOverride as DydxAddress ||
evmDerivedAddresses?.[TEST_WALLET_EVM_ADDRESS]?.dydxAddress as DydxAddress ||
'dydx1';
dispatch(setOnboardingState(OnboardingState.WalletConnected));
// Set variables.
saveEvmDerivedAccount({
evmAddress: TEST_WALLET_EVM_ADDRESS,
dydxAddress: addressOverride,
});
const wallet = new LocalWallet();
wallet.address = addressOverride;
setLocalDydxWallet(wallet);
dispatch(setOnboardingState(OnboardingState.AccountConnected));
} else if (connectedDydxAddress && signerGraz) {
dispatch(setOnboardingState(OnboardingState.WalletConnected));
try {
setLocalDydxWallet(await LocalWallet.fromOfflineSigner(signerGraz));
@@ -224,6 +257,7 @@ const useAccountsContext = () => {
if (hdKey?.mnemonic) {
const nobleWallet = await LocalWallet.fromMnemonic(hdKey.mnemonic, NOBLE_BECH32_PREFIX);
abacusStateManager.setNobleWallet(nobleWallet);
setLocalNobleWallet(nobleWallet);
}
};
setNobleWallet();
@@ -322,6 +356,7 @@ const useAccountsContext = () => {
localDydxWallet,
dydxAccounts,
dydxAddress,
nobleAddress,
// Onboarding state
saveHasAcknowledgedTerms,
+2 -1
View File
@@ -97,7 +97,7 @@ export const useAnalytics = () => {
}, []);
// AnalyticsEvent.NetworkStatus
const { height, indexerHeight, status } = useApiState();
const { height, indexerHeight, status, trailingBlocks} = useApiState();
useEffect(() => {
if (status) {
@@ -114,6 +114,7 @@ export const useAnalytics = () => {
elapsedTime: lastSuccessfulIndexerRpcQuery && Date.now() - lastSuccessfulIndexerRpcQuery,
blockHeight: height ?? undefined,
indexerBlockHeight: indexerHeight ?? undefined,
trailingBlocks: trailingBlocks ?? undefined
});
}
}, [status]);
+1 -1
View File
@@ -71,7 +71,7 @@ export const getIndexerHeight = (apiState: Nullable<AbacusApiState>) => {
export const useApiState = () => {
const stringGetter = useStringGetter();
const apiState = useSelector(getApiState, shallowEqual);
const { haltedBlock, height, status, trailingBlocks } = apiState ?? {};
const { haltedBlock, height, status, trailingBlocks} = apiState ?? {};
const statusErrorMessage = getStatusErrorMessage({ apiState, stringGetter });
const indexerHeight = getIndexerHeight(apiState);
+48
View File
@@ -0,0 +1,48 @@
import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { ThemeProvider } from 'styled-components';
import { AppTheme, AppThemeSetting, AppColorMode, AppThemeSystemSetting } from '@/state/configs';
import { getAppThemeSetting, getAppColorMode } from '@/state/configsSelectors';
import { Themes } from '@/styles/themes';
export const AppThemeAndColorModeProvider = ({ ...props }) => {
return <ThemeProvider theme={useAppThemeAndColorModeContext()} {...props} />;
};
export const useAppThemeAndColorModeContext = () => {
const themeSetting: AppThemeSetting = useSelector(getAppThemeSetting);
const colorMode: AppColorMode = useSelector(getAppColorMode);
const darkModePref = globalThis.matchMedia('(prefers-color-scheme: dark)');
const [systemPreference, setSystemPreference] = useState(
darkModePref.matches ? AppTheme.Dark : AppTheme.Light
);
useEffect(() => {
const handler = (e) => {
if (e.matches) {
setSystemPreference(AppTheme.Dark);
} else {
setSystemPreference(AppTheme.Light);
}
};
darkModePref.addEventListener('change', handler);
return () => darkModePref.removeEventListener('change', handler);
}, []);
const getThemeFromSetting = (): AppTheme => {
switch (themeSetting) {
case AppThemeSystemSetting.System:
return systemPreference;
case AppTheme.Classic:
case AppTheme.Dark:
case AppTheme.Light:
return themeSetting;
}
};
return Themes[getThemeFromSetting()][colorMode];
};
+43 -5
View File
@@ -1,5 +1,6 @@
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import {
BECH32_PREFIX,
CompositeClient,
@@ -9,6 +10,7 @@ import {
onboarding,
Network,
ValidatorConfig,
type ProposalStatus,
} from '@dydxprotocol/v4-client-js';
import type { ResolutionString } from 'public/tradingview/charting_library';
@@ -68,17 +70,21 @@ const useDydxClientContext = () => {
new Network(
selectedNetwork,
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,
broadcastTimeoutMs: 60_000,
})
},
{
broadcastPollIntervalMs: 3_000,
broadcastTimeoutMs: 60_000,
}
)
)
);
setCompositeClient(initializedClient);
@@ -111,6 +117,36 @@ const useDydxClientContext = () => {
};
// ------ Public Methods ------ //
const requestAllPerpetualMarkets = useCallback(async () => {
try {
const { markets } =
(await compositeClient?.indexerClient.markets.getPerpetualMarkets()) || {};
return markets || [];
} catch (error) {
log('useDydxClient/getPerpetualMarkets', error);
return [];
}
}, [compositeClient]);
/**
* @param proposalStatus - Optional filter for proposal status. If not provided, all proposals in ProposalStatus.VotingPeriod will be returned.
*/
const requestAllGovernanceProposals = useCallback(
async (proposalStatus?: ProposalStatus) => {
try {
const allGovProposals = await compositeClient?.validatorClient.get.getAllGovProposals(
proposalStatus
);
return allGovProposals;
} catch (error) {
log('useDydxClient/getProposals', error);
return undefined;
}
},
[compositeClient]
);
const requestCandles = useCallback(
async ({
marketId,
@@ -225,6 +261,8 @@ const useDydxClientContext = () => {
getWalletFromEvmSignature,
// Public Methods
requestAllPerpetualMarkets,
requestAllGovernanceProposals,
getCandlesForDatafeed,
screenAddresses,
};
+16
View File
@@ -0,0 +1,16 @@
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { useSelectedNetwork } from '@/hooks';
export interface GovernanceVariables {
newMarketProposal: {
initialDepositAmount: number;
delayBlocks: number;
newMarketsMethodology: string;
};
}
export const useGovernanceVariables = (): GovernanceVariables => {
const { selectedNetwork } = useSelectedNetwork();
const governanceVars = ENVIRONMENT_CONFIG_MAP[selectedNetwork].governance as GovernanceVariables;
return governanceVars;
};
+118
View File
@@ -0,0 +1,118 @@
import { useMemo } from 'react';
import { useQuery } from 'react-query';
import {
MsgCreateClobPair,
MsgCreateOracleMarket,
MsgCreatePerpetual,
MsgDelayMessage,
MsgUpdateClobPair,
TYPE_URL_MSG_CREATE_CLOB_PAIR,
TYPE_URL_MSG_CREATE_ORACLE_MARKET,
TYPE_URL_MSG_CREATE_PERPETUAL,
TYPE_URL_MSG_DELAY_MESSAGE,
TYPE_URL_MSG_UPDATE_CLOB_PAIR,
} from '@dydxprotocol/v4-client-js';
import type { PerpetualMarketResponse } from '@/constants/indexer';
import { useDydxClient } from '@/hooks/useDydxClient';
export const useNextClobPairId = () => {
const { isConnected, requestAllPerpetualMarkets, requestAllGovernanceProposals } =
useDydxClient();
const { data: perpetualMarkets, status: perpetualMarketsStatus } = useQuery({
enabled: isConnected,
queryKey: 'requestAllPerpetualMarkets',
queryFn: requestAllPerpetualMarkets,
refetchInterval: 60_000,
staleTime: 60_000,
});
const { data: allGovProposals, status: allGovProposalsStatus } = useQuery({
enabled: isConnected,
queryKey: 'requestAllActiveGovernanceProposals',
queryFn: () => requestAllGovernanceProposals(),
refetchInterval: 10_000,
staleTime: 10_000,
});
/**
*
* @param message from proposal. Each message is wrapped in a type any (on purpose).
* @param callback method used to compile all clobPairIds, perpetualIds, marketIds, etc.
*/
const decodeMsgForClobPairId = (message: any, callback: (id?: number) => void): any => {
const { typeUrl, value } = message;
switch (typeUrl) {
case TYPE_URL_MSG_CREATE_ORACLE_MARKET: {
const decodedValue = MsgCreateOracleMarket.decode(value);
callback(decodedValue.params?.id);
break;
}
case TYPE_URL_MSG_CREATE_PERPETUAL: {
const decodedValue = MsgCreatePerpetual.decode(value);
callback(decodedValue.params?.id);
callback(decodedValue.params?.marketId);
break;
}
case TYPE_URL_MSG_CREATE_CLOB_PAIR: {
const decodedValue = MsgCreateClobPair.decode(value);
callback(decodedValue.clobPair?.id);
callback(decodedValue.clobPair?.perpetualClobMetadata?.perpetualId);
break;
}
case TYPE_URL_MSG_UPDATE_CLOB_PAIR: {
const decodedValue = MsgUpdateClobPair.decode(value);
callback(decodedValue.clobPair?.id);
callback(decodedValue.clobPair?.perpetualClobMetadata?.perpetualId);
break;
}
case TYPE_URL_MSG_DELAY_MESSAGE: {
const decodedValue = MsgDelayMessage.decode(value);
decodeMsgForClobPairId(decodedValue.msg, callback);
break;
}
default: {
break;
}
}
};
const nextAvailableClobPairId = useMemo(() => {
const idsFromProposals: number[] = [];
if (allGovProposals && Object.values(allGovProposals.proposals).length > 0) {
const proposals = allGovProposals.proposals;
proposals.forEach((proposal) => {
if (proposal.messages) {
proposal.messages.map((message) => {
decodeMsgForClobPairId(message, (id?: number) => {
if (id) {
idsFromProposals.push(id);
}
});
});
}
});
}
if (perpetualMarkets && Object.values(perpetualMarkets).length > 0) {
const clobPairIds = Object.values(perpetualMarkets)?.map((perpetualMarket) =>
Number((perpetualMarket as PerpetualMarketResponse).clobPairId)
);
const nextAvailableClobPairId = Math.max(...[...clobPairIds, ...idsFromProposals]) + 1;
return nextAvailableClobPairId;
}
return undefined;
}, [perpetualMarkets, allGovProposals]);
return {
allGovProposalsStatus,
perpetualMarketsStatus,
nextAvailableClobPairId,
};
};
+30 -2
View File
@@ -28,6 +28,7 @@ import { useLocalNotifications } from '@/hooks/useLocalNotifications';
import { AssetIcon } from '@/components/AssetIcon';
import { Icon, IconName } from '@/components/Icon';
import { BlockRewardNotification } from '@/views/notifications/BlockRewardNotification';
import { TradeNotification } from '@/views/notifications/TradeNotification';
import { TransferStatusNotification } from '@/views/notifications/TransferStatusNotification';
@@ -80,6 +81,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
toastSensitivity: 'foreground',
groupKey: abacusNotificationType,
renderCustomBody: ({ isToast, notification }) => (
<TradeNotification
isToast={isToast}
@@ -93,6 +95,29 @@ export const notificationTypes: NotificationTypeConfig[] = [
);
break;
}
case 'blockReward': {
trigger(
abacusNotif.id,
{
icon: abacusNotif.image && <$Icon src={abacusNotif.image} alt="" />,
title: stringGetter({ key: abacusNotif.title }),
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
toastSensitivity: 'foreground',
groupKey: abacusNotificationType,
renderCustomBody: ({ isToast, notification }) => (
<BlockRewardNotification
isToast={isToast}
data={parsedData}
notification={notification}
/>
),
},
[abacusNotif.updateTimeInMilliseconds, abacusNotif.data],
true
);
break;
}
default:
trigger(
abacusNotif.id,
@@ -102,6 +127,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
toastSensitivity: 'foreground',
groupKey: abacusNotificationType,
},
[abacusNotif.updateTimeInMilliseconds, abacusNotif.data]
);
@@ -157,8 +183,8 @@ export const notificationTypes: NotificationTypeConfig[] = [
const isFinished = Boolean(status) && status?.squidTransactionStatus !== 'ongoing';
const icon = <Icon iconName={isFinished ? IconName.Transfer : IconName.Clock} />;
const transferType = type ??
fromChainId === ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId
const transferType =
type ?? fromChainId === ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId
? TransferNotificationTypes.Withdrawal
: TransferNotificationTypes.Deposit;
@@ -197,6 +223,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
/>
),
toastSensitivity: 'foreground',
groupKey: NotificationType.SquidTransfer,
},
[isFinished]
);
@@ -242,6 +269,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
},
}),
toastSensitivity: 'foreground',
groupKey: NotificationType.ReleaseUpdates,
},
[]
);
+62
View File
@@ -0,0 +1,62 @@
import { createContext, useContext, useEffect, useState } from 'react';
import type {
ExchangeConfigItem,
ExchangeConfigParsedCsv,
PotentialMarketItem,
PotentialMarketParsedCsv,
} from '@/constants/potentialMarkets';
import { log } from '@/lib/telemetry';
const PotentialMarketsContext = createContext<ReturnType<typeof usePotentialMarketsContext>>({
potentialMarkets: undefined,
exchangeConfigs: undefined,
hasPotentialMarketsData: false,
});
PotentialMarketsContext.displayName = 'PotentialMarkets';
export const PotentialMarketsProvider = ({ ...props }) => (
<PotentialMarketsContext.Provider value={usePotentialMarketsContext()} {...props} />
);
export const usePotentialMarkets = () => useContext(PotentialMarketsContext);
const EXCHANGE_CONFIG_FILE_PATH = '/configs/potentialMarketExchangeConfig.json';
const POTENTIAL_MARKETS_FILE_PATH = '/configs/potentialMarketParameters.json';
export const usePotentialMarketsContext = () => {
const [potentialMarkets, setPotentialMarkets] = useState<PotentialMarketItem[]>();
const [exchangeConfigs, setExchangeConfigs] = useState<Record<string, ExchangeConfigItem[]>>();
useEffect(() => {
try {
fetch(POTENTIAL_MARKETS_FILE_PATH)
.then((response) => response.json())
.then((data) => {
setPotentialMarkets(data as PotentialMarketItem[]);
});
} catch (error) {
log('usePotentialMarkets/potentialMarkets', error);
setPotentialMarkets(undefined);
}
try {
fetch(EXCHANGE_CONFIG_FILE_PATH)
.then((response) => response.json())
.then((data) => {
setExchangeConfigs(data as Record<string, ExchangeConfigItem[]>);
});
} catch (error) {
log('usePotentialMarkets/exchangeConfigs', error);
setExchangeConfigs(undefined);
}
}, []);
return {
potentialMarkets,
exchangeConfigs,
hasPotentialMarketsData: Boolean(potentialMarkets && exchangeConfigs),
};
};
+48 -11
View File
@@ -2,11 +2,16 @@ import { createContext, useCallback, useContext, useEffect, useMemo, useState }
import { shallowEqual, useSelector, useDispatch } from 'react-redux';
import type { Nullable } from '@dydxprotocol/v4-abacus';
import Long from 'long';
import type { IndexedTx } from '@cosmjs/stargate';
import { type IndexedTx } from '@cosmjs/stargate';
import type { EncodeObject } from '@cosmjs/proto-signing';
import { Method } from '@cosmjs/tendermint-rpc';
import { type LocalWallet, SubaccountClient } from '@dydxprotocol/v4-client-js';
import {
type LocalWallet,
SubaccountClient,
type GovAddNewMarketParams,
utils,
} from '@dydxprotocol/v4-client-js';
import type {
AccountBalance,
@@ -16,7 +21,6 @@ import type {
} from '@/constants/abacus';
import { AMOUNT_RESERVED_FOR_GAS_USDC } from '@/constants/account';
import { AnalyticsEvent } from '@/constants/analytics';
import { QUANTUM_MULTIPLIER } from '@/constants/numbers';
import { DydxAddress } from '@/constants/wallets';
@@ -24,14 +28,13 @@ import { setSubaccount, setHistoricalPnl, removeUncommittedOrderClientId } from
import { getBalances } from '@/state/accountSelectors';
import abacusStateManager from '@/lib/abacus';
import { track } from '@/lib/analytics';
import { MustBigNumber } from '@/lib/numbers';
import { hashFromTx } from '@/lib/hashfromTx';
import { log } from '@/lib/telemetry';
import { useAccounts } from './useAccounts';
import { useTokenConfigs } from './useTokenConfigs';
import { useDydxClient } from './useDydxClient';
import { hashFromTx } from '@/lib/hashfromTx';
import { useGovernanceVariables } from './useGovernanceVariables';
type SubaccountContextType = ReturnType<typeof useSubaccountContext>;
const SubaccountContext = createContext<SubaccountContextType>({} as SubaccountContextType);
@@ -198,7 +201,13 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
);
const ibcMsg: EncodeObject = {
typeUrl: transaction.msgTypeUrl,
value: transaction.msg,
value: {
...transaction.msg,
timeoutTimestamp: transaction.msg.timeoutTimestamp
? // Squid returns timeoutTimestamp as Long, but the signer expects BigInt
BigInt(Long.fromValue(transaction.msg.timeoutTimestamp).toString())
: undefined,
},
};
return await compositeClient.send(
@@ -295,9 +304,8 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
const sendSquidWithdraw = useCallback(
async (amount: number, payload: string, isCctp?: boolean) => {
const cctpWithdraw = () => {
return new Promise<string>((resolve, reject) =>
return new Promise<string>((resolve, reject) =>
abacusStateManager.cctpWithdraw((success, error, data) => {
const parsedData = JSON.parse(data);
if (success && parsedData?.code == 0) {
@@ -306,8 +314,8 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
reject(error);
}
})
)
}
);
};
if (isCctp) {
return await cctpWithdraw();
}
@@ -407,6 +415,32 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
[subaccountClient]
);
const { newMarketProposal } = useGovernanceVariables();
// ------ Governance Methods ------ //
const submitNewMarketProposal = useCallback(
async (params: GovAddNewMarketParams) => {
if (!compositeClient) {
throw new Error('client not initialized');
} else if (!localDydxWallet) {
throw new Error('wallet not initialized');
} else if (!newMarketProposal) {
throw new Error('governance variables not initialized');
}
const response = await compositeClient.submitGovAddNewMarketProposal(
localDydxWallet,
params,
utils.getGovAddNewMarketTitle(params.ticker),
utils.getGovAddNewMarketSummary(params.ticker, newMarketProposal.delayBlocks),
BigInt(newMarketProposal.initialDepositAmount).toString()
);
return response;
},
[compositeClient, localDydxWallet]
);
return {
// Deposit/Withdraw/Faucet Methods
deposit,
@@ -421,5 +455,8 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
placeOrder,
closePosition,
cancelOrder,
// Governance Methods
submitNewMarketProposal,
};
};
+42 -4
View File
@@ -1,6 +1,8 @@
import { useCallback, useEffect, useState, useMemo } from 'react';
import { useSelector } from 'react-redux';
import { EvmDerivedAddresses } from '@/constants/account';
import { STRING_KEYS } from '@/constants/localization';
import { LocalStorageKey } from '@/constants/localStorage';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
@@ -37,6 +39,7 @@ import { getWalletConnection, parseWalletError } from '@/lib/wallet';
import { log } from '@/lib/telemetry';
import { useStringGetter } from './useStringGetter';
import { testFlags } from '@/lib/testFlags';
export const useWalletConnection = () => {
const stringGetter = useStringGetter();
@@ -104,11 +107,25 @@ export const useWalletConnection = () => {
[walletConnectConfig, walletType, walletConnectionType]
);
const { connectAsync: connectWagmi } = useConnectWagmi({ connector: wagmiConnector })
const { connectAsync: connectWagmi } = useConnectWagmi({ connector: wagmiConnector });
const { suggestAndConnect: connectGraz } = useConnectGraz();
const [evmDerivedAddresses] = useLocalStorage({
key: LocalStorageKey.EvmDerivedAddresses,
defaultValue: {} as EvmDerivedAddresses,
});
const connectWallet = useCallback(
async ({ walletType }: { walletType: WalletType }) => {
async ({
walletType,
forceConnect,
isAccountConnected,
}: {
walletType?: WalletType;
forceConnect?: boolean;
isAccountConnected?: boolean;
}) => {
if (!walletType) return { walletType, walletConnectionType };
const walletConnection = getWalletConnection({ walletType });
try {
@@ -131,8 +148,11 @@ export const useWalletConnection = () => {
walletType: cosmosWalletType,
});
}
} else if (walletConnection.type === WalletConnectionType.TestWallet) {
saveEvmAddress(STRING_KEYS.TEST_WALLET as EvmAddress);
} else {
if (!isConnectedWagmi) {
// if account connected (via remember me), do not show wagmi popup until forceConnect
if (!isConnectedWagmi && (forceConnect || !isAccountConnected)) {
await connectWagmi({
connector: resolveWagmiConnector({
walletType,
@@ -180,6 +200,9 @@ export const useWalletConnection = () => {
try {
const { walletType, walletConnectionType } = await connectWallet({
walletType: selectedWalletType,
isAccountConnected: Boolean(
evmAddress && evmDerivedAddresses[evmAddress]?.encryptedSignature
),
});
setWalletType(walletType);
@@ -202,7 +225,7 @@ export const useWalletConnection = () => {
await disconnectWallet();
}
})();
}, [selectedWalletType, signerWagmi, signerGraz]);
}, [selectedWalletType, signerWagmi, signerGraz, evmDerivedAddresses, evmAddress]);
const selectWalletType = async (walletType: WalletType | undefined) => {
if (selectedWalletType) {
@@ -213,6 +236,15 @@ export const useWalletConnection = () => {
setSelectedWalletType(walletType);
};
// On page load, if testFlag.address is set, connect to the test wallet.
useEffect(() => {
(async () => {
if (testFlags.addressOverride) {
setSelectedWalletType(WalletType.TestWallet);
}
})();
}, []);
return {
// Wallet connection
walletType,
@@ -228,6 +260,12 @@ export const useWalletConnection = () => {
evmAddressWagmi,
signerWagmi,
publicClientWagmi,
isConnectedWagmi,
connectWallet: () =>
connectWallet({
walletType: selectedWalletType,
forceConnect: true,
}),
// Wallet connection (Cosmos)
dydxAddress,
+1 -3
View File
@@ -1,3 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 6L7.83335 10.5L2 6" stroke="currentColor" stroke-width="2.25" stroke-linecap="round"/>
</svg>
<svg fill="none" height="10" viewBox="0 0 15 10" width="15" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="m.321829 1.09389c.200562-.192959.469529-.298401.747791-.29315.27827.00525.54307.120763.73621.32115l5.194 5.5132 5.19397-5.5132c.0944-.10408.2088-.188152.3363-.247234.1275-.059081.2655-.091968.406-.096713.1404-.004746.2804.018748.4116.069088s.2509.126504.3522.223979c.1012.09747.1818.21427.2371.34347.0552.12921.084.26819.0845.40871.0006.14052-.0271.27972-.0813.40936s-.1339.24707-.2344.34534l-5.94997 6.3c-.09795.10163-.21538.18245-.34527.23766-.1299.05521-.26959.08367-.41073.08367s-.28083-.02846-.41073-.08367c-.12989-.05521-.24732-.13603-.34527-.23766l-5.950001-6.3c-.192962-.20056-.29840394-.46953-.29315364-.74779.00525031-.27827.12076264-.54307.32115364-.73621z" fill="currentColor" fill-rule="evenodd"/></svg>

Before

Width:  |  Height:  |  Size: 205 B

After

Width:  |  Height:  |  Size: 840 B

+62
View File
@@ -0,0 +1,62 @@
import { useSelector } from 'react-redux';
import { AppTheme } from '@/state/configs';
import { getAppTheme } from '@/state/configsSelectors';
const ChaosLabsIcon: React.FC = () => {
const appTheme = useSelector(getAppTheme);
const fills = appTheme === AppTheme.Light ? ['#1482E5', '#000000'] : ['#1482E5', '#E5E9EB'];
return (
<svg width="91" height="17" viewBox="0 0 91 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M13.4384 13.2558C13.3846 13.2931 13.3295 13.3283 13.2724 13.3615L11.4238 14.4385L4.17188 10.2149V6.61884L11.4198 2.39746L13.2724 3.47652C13.3376 3.51449 13.4007 3.55521 13.4619 3.59848L8.28233 6.60962V6.60225L6.20661 7.81644V9.05132L8.28233 10.2629V9.0364L14.4967 5.41709C14.5028 5.48788 14.5055 5.55928 14.5055 5.63112V7.80972L10.3675 10.2318V11.4757L13.4384 13.2558Z"
fill={fills[0]}
/>
<path
d="M9.34397 1.18863L8.48587 0.688787C7.72318 0.244363 6.78308 0.244363 6.01972 0.688787L1.23307 3.47666C0.470044 3.92109 0 4.74241 0 5.63125V11.207C0 12.0958 0.470044 12.9172 1.23307 13.3616L6.01972 16.1495C6.78308 16.5939 7.72318 16.5939 8.48587 16.1495L9.348 15.6475L2.09628 11.4241V5.41158L2.09911 5.41323L2.09628 5.41L9.34397 1.18863Z"
fill={fills[0]}
/>
<path d="M62.777 12.3629V4.57764H64.1102V11.1154H67.7133V12.3629H62.777Z" fill={fills[1]} />
<path
d="M70.2932 10.5919L69.5029 12.3629H68.0797L71.5585 4.57764H72.9817L76.4605 12.3629H75.0373L74.2464 10.5919H70.2932ZM73.7041 9.37795L72.2701 6.17032L70.8355 9.37795H73.7041Z"
fill={fills[1]}
/>
<path
d="M81.0141 12.3629H77.5581V4.57764H80.6304C81.1646 4.57764 81.6242 4.64075 82.0079 4.76698C82.3997 4.8932 82.6893 5.06398 82.8781 5.27931C83.2396 5.68026 83.4197 6.1332 83.4197 6.6381C83.4197 7.24693 83.2242 7.69991 82.8324 7.99692C82.6893 8.10087 82.5918 8.16767 82.5388 8.19737C82.4863 8.21968 82.3923 8.26047 82.2565 8.31987C82.7464 8.42382 83.1341 8.64289 83.4197 8.97699C83.7134 9.3037 83.8605 9.71213 83.8605 10.2021C83.8605 10.7442 83.6724 11.2231 83.2961 11.6389C82.8512 12.1215 82.0912 12.3629 81.0141 12.3629ZM78.8906 7.80756H80.5847C81.5489 7.80756 82.0307 7.48454 82.0307 6.83858C82.0307 6.46732 81.9138 6.20002 81.6806 6.03667C81.4468 5.87331 81.086 5.79164 80.5961 5.79164H78.8906V7.80756ZM78.8906 11.1489H80.9805C81.4697 11.1489 81.8426 11.0746 82.0986 10.9261C82.362 10.7701 82.4937 10.4806 82.4937 10.0574C82.4937 9.3668 81.9326 9.02154 80.8111 9.02154H78.8906V11.1489Z"
fill={fills[1]}
/>
<path
d="M87.9162 5.60121C87.5325 5.60121 87.216 5.67917 86.9674 5.8351C86.7194 5.99103 86.5951 6.22863 86.5951 6.54791C86.5951 6.85977 86.7194 7.1011 86.9674 7.27185C87.216 7.4352 87.7435 7.61341 88.5492 7.80647C89.3623 7.99953 89.9724 8.27053 90.379 8.61949C90.7929 8.96851 90.9999 9.48452 90.9999 10.1676C90.9999 10.8433 90.7405 11.3928 90.2204 11.816C89.701 12.2393 89.0196 12.4509 88.1763 12.4509C86.9412 12.4509 85.8459 12.0314 84.8896 11.1923L85.7249 10.201C86.5232 10.8842 87.3518 11.2257 88.2099 11.2257C88.6393 11.2257 88.9779 11.1366 89.2266 10.9584C89.4826 10.7728 89.6109 10.5314 89.6109 10.2345C89.6109 9.93003 89.49 9.69619 89.2494 9.53283C89.0156 9.36202 88.609 9.20981 88.0291 9.07616C87.4499 8.93511 87.0091 8.80885 86.708 8.6975C86.407 8.5787 86.1395 8.42643 85.9057 8.24083C85.4393 7.89188 85.2055 7.35726 85.2055 6.63702C85.2055 5.91678 85.4689 5.36361 85.9964 4.9775C86.5306 4.58397 87.1898 4.38721 87.9727 4.38721C88.4773 4.38721 88.9779 4.46889 89.4752 4.63224C89.9724 4.79558 90.4012 5.02577 90.7627 5.32277L90.0511 6.31402C89.8179 6.10612 89.5014 5.93534 89.1022 5.80169C88.7031 5.66804 88.308 5.60121 87.9162 5.60121Z"
fill={fills[1]}
/>
<path
d="M24.047 4.38721C22.8629 4.38721 21.861 4.77008 21.0648 5.54419L21.0634 5.54519C20.2745 6.31948 19.8807 7.2916 19.8807 8.43967C19.8807 9.58585 20.2665 10.5517 21.0433 11.3136L21.0439 11.3146C21.8268 12.0745 22.8072 12.4509 23.9643 12.4509C25.1463 12.4509 26.1536 11.9892 26.9707 11.0839L27.1609 10.8729L25.9722 9.65318L25.7558 9.85645C25.442 10.1501 25.1524 10.3555 24.8869 10.4827C24.6336 10.5973 24.3191 10.6603 23.9334 10.6603C23.3434 10.6603 22.8361 10.4504 22.3966 10.0177C21.9686 9.58323 21.7542 9.05029 21.7542 8.39841C21.7542 7.73954 21.9719 7.22084 22.4006 6.81607L22.402 6.81454C22.8367 6.39839 23.371 6.18802 24.0261 6.18802C24.4071 6.18802 24.7216 6.24839 24.9776 6.35892L24.9797 6.35987C25.2437 6.47129 25.5394 6.67559 25.866 6.98947L26.0904 7.20438L27.2583 5.92696L27.0729 5.72256C26.2665 4.83489 25.2511 4.38721 24.047 4.38721Z"
fill={fills[1]}
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M47.6624 4.38721C46.5167 4.38721 45.5396 4.77222 44.7521 5.54468C43.9625 6.31199 43.5687 7.27749 43.5687 8.41904C43.5687 9.55454 43.9632 10.5194 44.7514 11.2929L44.7527 11.2939C45.5403 12.0594 46.5173 12.4406 47.6624 12.4406C48.8074 12.4406 49.7845 12.0594 50.572 11.2939L50.5734 11.2929C51.3616 10.5194 51.756 9.55454 51.756 8.41904C51.756 7.27749 51.3623 6.312 50.5727 5.54469C49.7851 4.77223 48.8081 4.38721 47.6624 4.38721ZM45.4207 8.41904C45.4207 7.76676 45.6364 7.22501 46.0671 6.77549C46.5039 6.32689 47.0294 6.10561 47.6624 6.10561C48.2954 6.10561 48.8168 6.32697 49.2462 6.77466L49.2476 6.77617C49.6857 7.22615 49.9034 7.7677 49.9034 8.41904C49.9034 9.06265 49.6864 9.60104 49.2476 10.0516L49.2462 10.0531C48.8168 10.5008 48.2954 10.7222 47.6624 10.7222C47.0294 10.7222 46.5039 10.5009 46.0671 10.0523C45.6357 9.60218 45.4207 9.06359 45.4207 8.41904Z"
fill={fills[1]}
/>
<path
d="M55.2113 4.38721C54.4439 4.38721 53.7767 4.58367 53.2277 4.99291C52.6605 5.41417 52.3843 6.02137 52.3843 6.77092C52.3843 7.50415 52.6222 8.09878 53.1396 8.49282C53.3768 8.68366 53.6463 8.83835 53.9446 8.95789L53.9514 8.96024C54.2423 9.06951 54.6576 9.18959 55.1898 9.32096L55.1938 9.32176C55.7153 9.4438 56.0345 9.57362 56.1944 9.69243L56.1991 9.69565L56.2038 9.69874C56.3355 9.78966 56.402 9.90967 56.402 10.098C56.402 10.2701 56.3362 10.4048 56.1756 10.523C56.0177 10.6376 55.7791 10.7119 55.4277 10.7119C54.7335 10.7119 54.0461 10.4338 53.36 9.83838L53.1262 9.63551L51.9791 11.0155L52.1975 11.2103C53.1228 12.0336 54.1933 12.4509 55.3968 12.4509C56.2179 12.4509 56.9134 12.2409 57.4537 11.7944C57.9987 11.3443 58.2748 10.7498 58.2748 10.0363C58.2748 9.34239 58.0652 8.77028 57.6029 8.37509C57.1809 8.00799 56.5721 7.74216 55.808 7.55804C55.4458 7.47001 55.1515 7.38669 54.923 7.3084C54.6926 7.22931 54.5461 7.16104 54.4648 7.10769C54.3257 7.00954 54.2571 6.88184 54.2571 6.68852C54.2571 6.48456 54.3277 6.36719 54.4574 6.28486C54.6227 6.17969 54.8498 6.11592 55.1596 6.11592C55.4814 6.11592 55.8087 6.17147 56.144 6.28523C56.4813 6.39984 56.73 6.54009 56.9033 6.69703L57.1567 6.92574L58.1646 5.50194L57.9496 5.32269C57.5874 5.02123 57.1621 4.79104 56.6769 4.62937C56.1937 4.46839 55.7052 4.38721 55.2113 4.38721Z"
fill={fills[1]}
/>
<path
d="M29.7507 4.56055H27.9297V12.3667H29.7507V9.42066H32.7195V12.3667H34.5406V4.56055H32.7195V7.68166H29.7507V4.56055Z"
fill={fills[1]}
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M40.3586 4.56055H38.6659L35.2261 12.3667H37.1862L37.9072 10.7289H41.1173L41.8383 12.3667H43.7984L40.3586 4.56055ZM38.6686 9.00014L39.5126 7.08737L40.3559 9.00014H38.6686Z"
fill={fills[1]}
/>
</svg>
);
};
export default ChaosLabsIcon;
-3
View File
@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.95513 1.00169C7.89506 1.00645 7.83628 1.02054 7.78124 1.04337L1.31971 3.71042C1.2243 3.74983 1.14329 3.81414 1.08653 3.89553C1.02977 3.97691 0.999705 4.07186 1 4.16883V11.8366C1.00078 11.9327 1.03135 12.0265 1.08805 12.1069C1.14474 12.1873 1.22517 12.2508 1.31971 12.2898L7.78124 14.9568C7.85011 14.9853 7.92463 15 8 15C8.07536 15 8.14989 14.9853 8.21876 14.9568L14.6803 12.2898C14.7748 12.2508 14.8552 12.1873 14.9119 12.1069C14.9686 12.0265 14.9992 11.9327 15 11.8366V4.16883C15.0003 4.07186 14.9702 3.97691 14.9134 3.89553C14.8567 3.81414 14.7756 3.74983 14.6803 3.71042L8.21876 1.04337C8.13605 1.00911 8.04538 0.994778 7.95513 1.00169ZM8 2.04351L13.1378 4.16883L8 6.28894L2.86219 4.16883L8 2.04351ZM2.07693 4.93457L7.46153 7.15886V13.7328L2.07693 11.5084V4.93457ZM13.923 4.93457V11.5084L8.53846 13.7328V7.15886L13.923 4.93457Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 969 B

+1 -1
View File
@@ -1,3 +1,3 @@
<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="M2.98083 12.9826C2.41272 13.2911 1.68993 13.0863 1.36776 12.5275L0.759291 11.4721C0.436526 10.9122 0.620013 10.1856 1.1752 9.84545L1.55868 9.61048C1.7994 9.46299 1.99441 9.11427 1.99426 8.83155L1.99336 7.16756C1.99321 6.88486 1.79835 6.53637 1.55722 6.38862L1.17373 6.15365C0.621247 5.81513 0.435901 5.08599 0.758416 4.52738L1.36754 3.47235C1.69065 2.91271 2.41137 2.70816 2.98358 3.01889L3.37882 3.23351C3.62692 3.36824 4.02656 3.36298 4.27147 3.22176L5.71299 2.39053C5.95788 2.24932 6.16238 1.90653 6.16977 1.62385L6.18152 1.17426C6.19844 0.526553 6.73722 0.00115865 7.38226 0.000757669L8.60051 2.31805e-07C9.24674 -0.000401478 9.78426 0.521358 9.80119 1.1694L9.81302 1.62228C9.8204 1.90461 10.0249 2.24808 10.2698 2.38946L11.7111 3.22163C11.956 3.363 12.3553 3.36858 12.6039 3.23358L13.002 3.01739C13.5701 2.70889 14.2929 2.91369 14.6151 3.47251L15.2235 4.52792C15.5463 5.08777 15.3628 5.81437 14.8076 6.15455L14.4241 6.38952C14.1834 6.53701 13.9884 6.88573 13.9886 7.16845L13.9895 8.83244C13.9896 9.11514 14.1845 9.46364 14.4256 9.61138L14.8091 9.84636C15.3616 10.1849 15.5469 10.914 15.2244 11.4726L14.6153 12.5277C14.2922 13.0873 13.5715 13.2918 12.9992 12.9811L12.604 12.7665C12.3559 12.6318 11.9563 12.637 11.7114 12.7782L10.2698 13.6095C10.0249 13.7507 9.82045 14.0935 9.81306 14.3762L9.80132 14.8257C9.78439 15.4734 9.24561 15.9988 8.60057 15.9992L7.38232 16C6.73609 16.0004 6.19858 15.4786 6.18164 14.8306L6.16981 14.3777C6.16243 14.0954 5.95796 13.7519 5.71307 13.6105L4.27172 12.7784C4.02685 12.637 3.62756 12.6314 3.37895 12.7664L2.98083 12.9826ZM6.23556 11.0412C7.91519 12.011 10.0629 11.4355 11.0326 9.75585C12.0024 8.07623 11.4269 5.92851 9.74727 4.95878C8.06765 3.98905 5.91992 4.56453 4.95019 6.24415C3.98046 7.92377 4.55594 10.0715 6.23556 11.0412Z" fill="currentColor"/>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

+7 -2
View File
@@ -1,3 +1,4 @@
import ChaosLabsIcon from './chaos-labs';
export { default as AddressConnectorIcon } from './address-connector.svg';
export { default as ArrowIcon } from './arrow.svg';
export { default as Bar3Icon } from './bar3.svg';
@@ -19,7 +20,6 @@ export { default as CoinMarketCapIcon } from './logos/coinmarketcap.svg';
export { default as CoinsIcon } from './coins.svg';
export { default as CommentIcon } from './comment.svg';
export { default as CopyIcon } from './copy.svg';
export { default as CubeIcon } from './cube.svg';
export { default as DepositIcon } from './deposit.svg';
export { default as DepthChartIcon } from './depth-chart.svg';
export { default as DiscordIcon } from './discord.svg';
@@ -35,26 +35,29 @@ export { default as HistoryIcon } from './history.svg';
export { default as LeaderboardIcon } from './leaderboard.svg';
export { default as LinkOutIcon } from './link-out.svg';
export { default as LockIcon } from './lock.svg';
export { default as LogoShortIcon } from './logo-short';
export { default as MarketsIcon } from './markets.svg';
export { default as MenuIcon } from './menu.svg';
export { default as MigrateIcon } from './migrate.svg';
export { default as MintscanIcon } from './logos/mintscan.svg';
export { default as MoonIcon } from './moon.svg';
export { default as OrderbookIcon } from './orderbook.svg';
export { default as OverviewIcon } from './overview.svg';
export { default as PencilIcon } from './pencil.svg';
export { default as PlayIcon } from './play.svg';
export { default as PlusIcon } from './plus.svg';
export { default as PortfolioIcon } from './portfolio.svg';
export { default as PositionsIcon } from './positions.svg';
export { default as PriceChartIcon } from './price-chart.svg';
export { default as PrivacyIcon } from './privacy.svg';
export { default as ProfileIcon } from './profile.svg';
export { default as QrIcon } from './qr.svg';
export { default as RewardStarIcon } from './reward-star.svg';
export { default as SearchIcon } from './search.svg';
export { default as SendIcon } from './send.svg';
export { default as ShareIcon } from './share.svg';
export { default as ShowIcon } from './show.svg';
export { default as StarIcon } from './star.svg';
export { default as SunIcon } from './sun.svg';
export { default as TerminalIcon } from './terminal.svg';
export { default as TogglesMenuIcon } from './toggles-menu.svg';
export { default as TradeIcon } from './trade.svg';
@@ -87,7 +90,9 @@ export { default as WebsiteIcon } from './website.svg';
export { default as WhitepaperIcon } from './whitepaper.svg';
// Logos
export { default as ChaosLabsIcon } from './chaos-labs';
export { default as EtherscanIcon } from './logos/etherscan.svg';
export { default as LogoShortIcon } from './logo-short';
// Trade
export { default as OrderCanceledIcon } from './trade/order-canceled.svg';
+50 -43
View File
@@ -1,45 +1,52 @@
const LogoShortIcon: React.FC<{ id?: string }> = ({ id }: { id?: string }) => (
<svg
width="135"
height="145"
viewBox="0 0 135 145"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M100.986 0L0 144.988H31.0048L132.514 0H100.986Z" fill="white" />
<path
d="M34.2346 0L63.9475 42.7232L48.4451 66.0268L2.58386 0H34.2346Z"
fill={`url(#${id ? `${id}_logo_gradient_0` : 'paint0_linear'})`}
/>
<path
d="M103.995 145L71.0526 97.7455L86.555 75.0893L135 145H103.995Z"
fill={`url(#${id ? `${id}_logo_gradient_1` : 'paint1_linear'})`}
/>
<defs>
<linearGradient
id={id ? `${id}_logo_gradient_0` : 'paint0_linear'}
x1="27.1293"
y1="9.0625"
x2="69.773"
y2="60.4324"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="white" />
<stop offset="1" stopColor="white" stopOpacity="0.55" />
</linearGradient>
<linearGradient
id={id ? `${id}_logo_gradient_1` : 'paint1_linear'}
x1="111.1"
y1="133.996"
x2="58.6959"
y2="63.4999"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#6966FF" />
<stop offset="1" stopColor="#6966FF" stopOpacity="0.36" />
</linearGradient>
</defs>
</svg>
);
import { useAppThemeAndColorModeContext } from '@/hooks/useAppThemeAndColorMode';
const LogoShortIcon: React.FC<{ id?: string }> = ({ id }: { id?: string }) => {
const theme = useAppThemeAndColorModeContext();
const fill = theme.logoFill;
return (
<svg
width="135"
height="145"
viewBox="0 0 135 145"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M100.986 0L0 144.988H31.0048L132.514 0H100.986Z" fill={fill} />
<path
d="M34.2346 0L63.9475 42.7232L48.4451 66.0268L2.58386 0H34.2346Z"
fill={`url(#${id ? `${id}_logo_gradient_0` : 'paint0_linear'})`}
/>
<path
d="M103.995 145L71.0526 97.7455L86.555 75.0893L135 145H103.995Z"
fill={`url(#${id ? `${id}_logo_gradient_1` : 'paint1_linear'})`}
/>
<defs>
<linearGradient
id={id ? `${id}_logo_gradient_0` : 'paint0_linear'}
x1="27.1293"
y1="9.0625"
x2="69.773"
y2="60.4324"
gradientUnits="userSpaceOnUse"
>
<stop stopColor={fill} />
<stop offset="1" stopColor={fill} stopOpacity="0.55" />
</linearGradient>
<linearGradient
id={id ? `${id}_logo_gradient_1` : 'paint1_linear'}
x1="111.1"
y1="133.996"
x2="58.6959"
y2="63.4999"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#6966FF" />
<stop offset="1" stopColor="#6966FF" stopOpacity="0.36" />
</linearGradient>
</defs>
</svg>
);
};
export default LogoShortIcon;
+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z" />
</svg>

After

Width:  |  Height:  |  Size: 364 B

+1
View File
@@ -0,0 +1 @@
<svg fill="none" height="12" viewBox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="m6.75.75c0-.198912-.07902-.389678-.21967-.53033-.14065-.1406525-.33142-.21967-.53033-.21967s-.38968.0790175-.53033.21967c-.14065.140652-.21967.331418-.21967.53033v4.5h-4.5c-.198912 0-.389678.07902-.53033.21967-.1406525.14065-.21967.33142-.21967.53033s.0790175.38968.21967.53033c.140652.14065.331418.21967.53033.21967h4.5v4.5c0 .1989.07902.3897.21967.5303.14065.1407.33142.2197.53033.2197s.38968-.079.53033-.2197c.14065-.1406.21967-.3314.21967-.5303v-4.5h4.5c.1989 0 .3897-.07902.5303-.21967.1407-.14065.2197-.33142.2197-.53033s-.079-.38968-.2197-.53033c-.1406-.14065-.3314-.21967-.5303-.21967h-4.5z" fill="currentColor"/></svg>

After

Width:  |  Height:  |  Size: 731 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 481 KiB

Some files were not shown because too many files have changed in this diff Show More