Compare commits

..

197 Commits

Author SHA1 Message Date
Jared Vu
d24a02f7b9
Add BrowserRouter support (#258)
* Add BrowserRouter support

* Handle base route for hashrouter/browserrouter

* Add hashstring fallback

* parseHash -> parseLocationHash
2024-02-23 09:44:01 -08:00
mike-dydx
caaea7e475
remove trailing slash (#325) 2024-02-23 08:49:10 -08:00
Bill
9d3a124485
Add support for OKX wallet (#312)
* Add support for OKX wallet

* strings
2024-02-22 13:54:58 -08:00
aleka
038eb08e2e
pessimistic collat check in non-dev/staging envs (#323)
Signed-off-by: aforaleka <aforaleka@gmail.com>
2024-02-22 15:11:42 -05:00
moo-onthelawn
e1d2a5eda4
Update env config to enable reduce only in testnet (#321)
* update flag

* update new env.json
2024-02-22 13:07:06 -05:00
moo-onthelawn
56be9ba9cc
traced back to innerWindow error (#320) 2024-02-21 19:17:33 -05:00
Bill
859e7dde80
Add notification for season 3 incentives (#322)
* Add notification for season 3 incentives

* add type

* address comments
2024-02-21 16:04:56 -08:00
John Huang
d9daf9f583
Feature/mob 193 install app dlg (#308)
* getOS and get meta from header

* Clean up

* Update localization

* Comments

* Rename URL variable

* MOB-193 PR

* PR
2024-02-21 12:52:11 -08:00
John Huang
5be9d2b1b2
TRCL-3553 Having the launch incentive api in env.json (#317) 2024-02-21 12:51:36 -08:00
Bill
d2c5b7945b
Remove CEX withdraw testflag (#316) 2024-02-21 09:50:11 -08:00
aleka
fc5d8538fe
bump abacus for new env config path usage (#314)
* bump abacus for new env config path usage

* bump abacus + localization for good til date
2024-02-20 22:42:18 -05:00
yujin512
fdc262f59f
Update otherMarketExchangeConfig.json (#315)
* Update otherMarketExchangeConfig.json

add strk

* Update otherMarketExchangeConfig.json

remove huobi, add kraken

* Update otherMarketParameters.json

add strk to parameters

* add strk icon and metadata
2024-02-20 16:08:11 -05:00
Bill
7f947804bd
Enable CCTP onboarding for avalanche, optimism (#310)
* Enable CCTP for arbitrum avalanche optimism

* Enable CCTP onboarding for arbitrum, avalanche, optimism

* remove arb
2024-02-19 20:18:57 -08:00
aleka
6620a70a5d
fix parsing error and surface tx broadcast error (#313)
* fix parsing error and surface tx broadcast error

* fix network as chain id
2024-02-19 22:06:13 -05:00
Bill
bff779631b
Cex withdraw (#301)
* Coinbase withdrawal and deposit UI

* analytics

* packages bumps

* address comments

* address comments

* add test flag
2024-02-16 17:56:06 -08:00
yujin512
b115bf33a0
Update markets.json (#311)
update ORDI asset name
2024-02-16 10:54:13 -08:00
aleka
b544b8202b
fetch chaos labs latest season (#309)
* fetch chaos labs latest season

* safer access
2024-02-16 11:09:48 -05:00
yujin512
ad6f99ffdf
add icons and metadata (#305)
* add icons

* Update otherMarketParameters.json

update numOracles for markets with robust DEX oracles (not currently queryable)

* Update otherMarketParameters.json

update numOracles for markets with robust DEX oracles

* update asset name to match cmc

* Update otherMarketParameters.json

* add icons for other markets

* fix url and market name
2024-02-16 09:44:08 -05:00
Bill
a7bd6a3ee8
host amplitude script ourselves (#307)
* host amplitude script ourselves

* update sha
2024-02-15 15:45:44 -08:00
aleka
c92f218493
bump abacus + use new env config format (#298)
* bump abacus + use new env config format

* use new config path

* bump abacus to 1.4.5

* util function for getting mintscan link
2024-02-15 13:38:05 -05:00
moo-onthelawn
b09fe9ebb1
fix bug (#304) 2024-02-14 15:19:37 -08:00
Bill
1c28505ec0
Set minimum for CCTP withdraws (#306) 2024-02-14 14:59:04 -08:00
moo-onthelawn
5531e21c76
change text color (#302) 2024-02-14 14:29:38 -05:00
John Huang
4ebeb21841
MOB-231 Refactor env.json to env2.json (#303)
* MOB-231 Refactor env.json to env2.json

* Move to v1/env.json

* dydx-testnet-4
2024-02-14 13:37:51 -05:00
moo-onthelawn
b638ec1ad6
CT-463 Add Position (entry) line to TradingView (#292)
* wip

* fix deleted line issue

* compress tgz changes

* fix dependency hook

* simplify

* typo

* add trailing percent

* fix bug

* fix order

* merge order types

* wip

* rename variable

* review comments

* remove file

* rebase on new changes

* remove log

* clean up chart line type

* clean up typings a bit more

* fix var rename

* review comments

* clean up logic

* typing
2024-02-14 09:41:04 -05:00
Jared Vu
f7a1cfc67e
Updated Keplr language (#300) 2024-02-13 17:07:22 -08:00
aleka
d66a776ad2
show trading rewards in testnet (#299) 2024-02-13 16:02:10 -05:00
moo-onthelawn
e3e00f4f1e
CT-145 Add warning icon + tooltip to trade order button CTA (#297)
* update

* rename to config
2024-02-13 16:00:46 -05:00
aleka
9ea578b8e4
avoid logging expected switch chain error (#291)
* avoid logging expected switch chain error

* skip logging more expected errors

* update switch chain error requirements check
2024-02-13 13:51:47 -05:00
moo-onthelawn
f47fda45bf
CT-428 Update browser tab title to be mid market price (#294)
* calculation

* make new selectors
2024-02-13 13:49:24 -05:00
moo-onthelawn
a7addda930
CT-425 + TRCL-2154 Add orderlines to TradingView + fix colors (#287)
* wip

* fix deleted line issue

* compress tgz changes

* fix dependency hook

* simplify

* typo

* add trailing percent

* fix bug

* fix order

* merge order types
2024-02-12 10:31:15 -05:00
yujin512
b839cf695e
upload new jsons and update file names (#295)
* upload new jsons and update file names

* add disclaimer and format json

* change filename

* remove (ENS) from assetName

---------

Co-authored-by: jaredvu <jaredvu@gmail.com>
2024-02-09 21:03:00 -08:00
yujin512
c9b8f1d59b
Yujin/update assets (#293)
* add links for DYM, BNB, ZETA

* add icons

* update asseticon.tsc

* readd JUP

* bump v4-localization

* Added TODO

* Update public/configs/markets.json

Co-authored-by: Jared Vu <jaredvu@gmail.com>

* address comments

* higher resolution icons

---------

Co-authored-by: jaredvu <jaredvu@gmail.com>
2024-02-09 14:32:52 -08:00
moo-onthelawn
91c04956d6
adjust calculation (#290) 2024-02-08 16:12:42 -08:00
aleka
3a3f817501
wrap details item + fix cancel reason overflow/overlay (#284)
* wrap details item

* more details nits
2024-02-08 13:10:42 -05:00
Jared Vu
5fb2f278da
Liquid staking language and localization (#289)
* ✏️ Liquid staking language and localization

* import nits
2024-02-08 06:44:50 -08:00
Jared Vu
bd788f22e8
Restore env format (#288)
* restore formatting

* copy from prev commit
2024-02-07 14:22:12 -08:00
Jared Vu
1a41ccaf2a
Liquid Staking CTA (#281)
* 🚧 feat(token-page): Scaffold sidebar components for token page

* 🚧 feat(staking/governance): Scaffold adding Panels to Staking and Governance page

*  Update and add icons

* 🧱 Add strideZoneApp to shared config

* 🧱 Add dialogs, update ExternalLinkDialog

* 🚧 Add New Panels/Update paths

* Fix mobile Profile Panel

* 💄 fix desktop padding

*  Add New tag

* 💄 Highlight tag on StrideStakingPanel

* 💄 Single columns for panels on mobile breakpoint

* 💄 fix import nits and alignment nits on panels

* Add circular keplr icon
2024-02-07 11:17:54 -08:00
Jared Vu
26b426c9e9
fix(ladle): Fix ladle environment and parameter types in stories (#286) 2024-02-07 11:02:26 -08:00
John Huang
994ba832f6
Feature/mob 162 smartbanner (#274)
* Implemented according to instructions but not working

* Exclude touch screen windows (see in Issues on library repo)

* Make the banner generic

* Moved icon_url to generic section

* Hide in Safari

* Use injection script with ENV variables instead manual update

* debugging

* Use CDN for js and css

* PR
2024-02-07 10:10:22 -08:00
Jared Vu
597456a0d1
JUP Asset details (#285)
*  add JUP assets

* localize eg
2024-02-07 09:49:46 -08:00
Bill
3b75e60bd2
Add custom amplitude server URL (#282)
* Add custom amplitude server URL

* string

* add to readme
2024-02-06 21:43:05 -08:00
aleka
e453977299
bump localization (#283) 2024-02-06 17:23:00 -05:00
moo-onthelawn
dbc34599a6
TRCL-3543 Create red/green color tokens and audit (replace) usages of error/success color tokens (#271)
* audited

* fix double header
2024-02-06 13:38:13 -05:00
aleka
f762e9bfac
add featureFlags to env config for reduce only + remove mobile sign in flag (#278)
* add featureFlags to env config

* update abacus and remove mobilesignin test flag
2024-02-06 12:31:08 -05:00
Bill
ed3c336cc0
Add memo to transactions for onchain tracking (#279) 2024-02-06 09:27:10 -08:00
Rui
b4f9f03bdc
Add Digital Asset Links for android app (#280) 2024-02-06 09:09:02 -08:00
aleka
44ed52d5e2
add more controlled pagination to table (#276) 2024-02-06 11:48:49 -05:00
Jonathan Fung
42595a3667
Revert "Bump abacus to enable ROC (#275)" (#277)
This reverts commit 2fc55bbe9f.
2024-02-05 17:25:29 -07: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 Vu
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
Bill
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
Jared Vu
503e089efa
temp hide fees for cctp route (#213) 2023-12-23 01:17:41 -08:00
Jared Vu
c3495f462c
Additional Withdraw/Deposit validation (#211)
* Add cctp amount check and price impact check

* 2.5% -> 2%
2023-12-22 17:31:32 -08:00
Bill
6da6eeb2a4
Enable CCTP (#194)
* Enable CCTP

* Handle base64 encode

* Update localization package

---------

Co-authored-by: jaredvu <jaredvu@gmail.com>
2023-12-22 11:12:41 -08:00
mike-dydx
0cf3e81bd7
Create documentation.json (#205) 2023-12-21 15:08:08 -05:00
aleka
f8cf1d364b
update coinbase connect app name (#208) 2023-12-21 10:58:57 -08:00
Jared Vu
6f344c6b5d
Update comparison function in Table (#207) 2023-12-21 10:53:56 -08:00
Jared Vu
133856afca
Export secret phrase help article (#206)
* Update config with correct article link

* Remove auto-format of json
2023-12-21 10:49:52 -08:00
Jared Vu
33c543daaf
Update bridgeFee in Withdraw/Deposit forms (#202)
* Update Withdraw form receipt

* Bump abacus 1.1.27

* pnpm-lock

* bump v4-localization
2023-12-19 23:36:13 -08:00
Jared Vu
c77e727d2b
TRCL-3406: firefox mobile position table row has stretched icon (#204)
* Fix PositionsTable assetIcon

* Mobile width of HelpDialog
2023-12-19 23:33:36 -08:00
Jared Vu
b94538711d
Lazy load Pages (#203)
* Lazy import pages

* Fix import order
2023-12-19 23:30:51 -08:00
Jared Vu
b83479f45c
Handle New Markets added by Gov (#201)
* Add celestia assets

* Handle symbol not yet added
2023-12-19 23:25:14 -08:00
Jared Vu
001aad3abc
Navigate to the Markets page if the current marketId is not included in subscribed markets (#198)
* Navigate to markets if current url is invalid

* nits
2023-12-19 15:58:49 -08:00
Jared Vu
f8db5e1ba0
Update abacus to 1.1.25: Good til time fix (#199) 2023-12-19 09:49:51 -08:00
Jared Vu
f8bec0fb3d
Update Withdraw form receipt (#200) 2023-12-19 09:49:37 -08:00
Bill
8bf23b7e9c
bump abacus (#197) 2023-12-15 15:12:35 -08:00
Jared Vu
3f10e045f4
bump abacus & wagmi (#196) 2023-12-15 09:26:41 -08:00
Bill
71d1a0321b
Do not block website if NobleClient cannot init, and other onboarding fixes (#193) 2023-12-13 08:11:19 -08:00
Bill
0f16396c8d
Implement CCTP withdraw (#188)
* Implement CCTP withdraw

* bump packages

* address comments
2023-12-12 10:12:37 -08:00
Jared Vu
2709d79f59
Firefox issues (#190)
* remove row flicker on hover

* Fix border for AccountInfoConnectedState on mobile

* Remove sticky position to allow button click

* Fix: AccountInfo not displaying on mobile firefox

* Fix css var name

* Restore filter on Table row hover

* Remove PerspectiveArea. broken on firefox

* Symbol no longer exists on AbacusType

* HorizontalPanel: memoize tabConfig

* input: firefox cant click between chars
2023-12-12 08:37:50 -08:00
Bill
ab0eec5d4f
Update noble tesnet rpc (#192) 2023-12-12 11:35:21 -05:00
Jared Vu
4a044da38f
Size inputs (#191)
* use formattedValue to update redux state

* Separate updateLeverage and onLeverageInput

* Remove console.log
2023-12-12 07:11:51 -08:00
Jared Vu
fbbfbc6580
Bump v4-abacus and v4-localization (#189) 2023-12-08 15:41:07 -08:00
Rui
2714c2b084
Fix path to chainLogo (#187) 2023-12-07 13:03:44 -08:00
Jared Vu
9979bc8a16
Prevent Spread row from moving when orderbook updates (#186)
* Add dummy rows to ensure even row count

* Reverse bids for horizontal layout

* disable pointer-events for dummy rows
2023-12-06 10:26:47 -08:00
aleka
a958a59ea2
Display more markets 12/06 (#178)
* add more markets 12/06
2023-12-06 11:38:49 -05:00
Jared Vu
2bf9e66da5
Fix inputs for comma locales (#171)
* Fix for comma decimal separator locales

* Accept tickSizeDecimals 0

* Use FloatValue as value for Size Input

* Use formattedValue to handle prefix/suffix

* Use MustBigNumber.toString()
2023-12-05 16:22:41 -08:00
Bill
2980144e40
Enable CCTP via TestFlags (#185)
* Enable CCTP via Env Var

* Use test flags instead
2023-12-05 14:48:47 -08:00
aleka
5387fe8632
Display more markets 12/05 (#177)
* add more markets 12/05
2023-12-05 09:52:12 -05:00
Bill
1132ea3bbd
Do not init nobleClient if nobleValidatorUrl does not exist (#184) 2023-12-04 11:19:29 -08:00
aleka
9188e08a4f
prevent 1password fill (#183) 2023-12-04 11:06:49 -05:00
aleka
941ef7f9dd
Display more markets 12/04 (#176)
* add more markets 11/30

* add more markets 12/01

* add more markets 12/04
2023-12-04 10:53:25 -05:00
Bill
b1ffa2e219
Support CCTP and noble auto deposits on testnet (#180)
* Support CCTP and noble auto deposits on testnet

* slippage

* fix fees

* update isCctp, and comments

* bump packages

* cctp.json

* Bump abacus

* fix error

* fix loading button
2023-12-01 15:18:50 -08:00
aleka
91ea68dc53
Add chaos labs launch incentives panel (#182)
* add chaos lab incentives panel

* add seen state

* external link dialog

* better disconnected state
2023-12-01 15:27:19 -05:00
aleka
cf79528d05
Display more markets 12/01 (#175)
* add more markets 12/01
2023-12-01 09:59:04 -05:00
Bill
ef81f9da57
Add nobleValidator to config (#181) 2023-11-30 16:11:55 -08:00
aleka
60d59cd211
add more markets 11/30 (#174) 2023-11-30 10:06:25 -05:00
aleka
19d38378f3
display more markets (#173) 2023-11-29 10:33:02 -05:00
Bill
15a64232c0
Fix USDT approval (#170)
* Fix USDT approval

* address comment
2023-11-28 11:44:21 -08:00
aleka
28d3be0370
Release notification (#169)
* add release notif
2023-11-28 12:36:29 -05:00
Rui
90ff9ccc5a
Add token address to cctp.json (#167)
* Add token address to cctp.json

* Update field name to tokenAddress
2023-11-27 17:55:52 -08:00
Jared Vu
33516422e7
Filter markets and add test flag (#168) 2023-11-27 17:05:19 -08:00
Rui
eb31610a38
Add CCTP supported chains to cctp.json (#166) 2023-11-27 14:27:42 -08:00
Jared Vu
b0e1655018
Bump Abacus@1.0.30 (#165) 2023-11-27 13:01:25 -08:00
Jared Vu
b4cc5f87ec
Add href prop to button component (#164)
* Add href prop to button component

* Use ButtonType.Link
2023-11-27 12:39:57 -08:00
Bill
549ae558e7
Default Locale to EN if not supported (#163) 2023-11-27 08:57:57 -08:00
Jared Vu
5b06110e2d
Update Abacus@1.0.28 (#161) 2023-11-22 14:08:03 -08:00
aleka
e3da2ee4b1
update copy and other polish (#157)
* update copy and other polish

* fix mobile nav menu nested buttons

* feedback
2023-11-22 15:06:21 -05:00
Rui
6b38d68b09
Remove universal link for trust wallet since it's no longer valid. (#160) 2023-11-21 19:25:03 -08:00
Jared Vu
1dedc93a56
Mobile friendly Toast: Collapse/Close (#159) 2023-11-21 19:24:19 -08:00
Jared Vu
1427b55728
MarketsTable: Sort OpenInterest by notional, Display 24h volume as fiat value (#158)
* Fix Sort by notional, Display fiat for volume

* OpenInterest notional on top
2023-11-21 16:10:23 -08:00
Jared Vu
20521b5b3f
Add button to stack/unstack Toast notifications (#149)
* Add button to stack/unstack

* Button -> Toggle button, add offset for notifs
2023-11-20 15:12:38 -08:00
Jared Vu
532df49a06
Use new redux tradeFormInputs object for TradingForm input display values (#144)
* Redux slice for TradeFormInputs

* Move sideEffects from TradeForm to hook in Trade
2023-11-20 11:56:09 -08:00
aleka
fb65db633a
move buttons to footer in ack terms (#155) 2023-11-20 13:21:06 -05:00
aleka
279ef6b4f9
bump abacus (#153) 2023-11-13 10:57:40 -05:00
aleka
0def18db07
fix sorting 24h price change in markets table (#152) 2023-11-13 09:36:32 -05:00
Jared Vu
50bd860ced
Bump Abacus 1.0.25 (#151) 2023-11-13 09:36:16 -05:00
Jared Vu
818574cedb
Change dep in hook to fix input bug (#150) 2023-11-13 09:11:54 -05:00
aleka
3be0429a60
add back border to toggle buttons (#148) 2023-11-11 20:46:04 -08:00
aleka
b8e72246b9
add manage funds dialog and transfers form styling (#147)
* add manage funds dialog and transfers form styling

* add sticky footer backdrop

* add testnet deposit toggle
2023-11-10 20:56:27 -08:00
Jared Vu
99e708a984
Notifications Refresh (#135)
* Remove X button from tablet/mobile Notification menu

* Toast styling

* missed in merge

* .env.example

* Update abacus@1.0.9

* Add notif strings, and abaucs notif state

* Update Notification hooks, add Notification Preference controls

* Consolidate Notification into single component

* withLabel -> withTrigger prop

* nits

* OrderStatusChanged -> AbacusGenerated

* Notification OnClick

* Move Notification -> Components

* withAnimation -> $withAnimation

* Notification styling and click handle

* load state, onClick, localStorage

* add error count

* Rez localStorage Notifications

* Update TransferStatus UI

* Use Notification component for other abacusNotifs

* fix uselocalnotif query

* Default to Notification from NotificationMenu

---------

Co-authored-by: Bill He <bill@dydx.exchange>
2023-11-10 20:55:34 -08:00
aleka
876f620ada
Account menu and components improvements (#145)
* better copy button

* hide sign into mobile for production and use new copy icon button

* new checkbox
2023-11-10 22:07:29 -05:00
Bill
b9550890da
Add additional onboarding entry points (#146)
* Add additional onboarding entry points

* flex-wrap
2023-11-10 19:05:46 -08:00
aleka
3732b955f5
add sample terms of use (#138)
* add sample terms of use

* add back article mixin
2023-11-10 14:58:26 -05:00
aleka
253bfc0eff
update nav menu dropdown behavior to click instead of hover to open (#142) 2023-11-10 14:58:17 -05:00
Bill
d4bcfc0428
Fix status empty bug (#143) 2023-11-10 09:55:54 -08:00
aleka
7dec32df5e
fix 24h sort in market dropdown, table styling (#141) 2023-11-09 16:40:27 -05:00
aleka
e09d574d5b
show deposit form in mainnet onboarding (#140) 2023-11-09 15:33:16 -05:00
Bill
944fc6dc95
Handle squid rout errors (#139)
* Handle squid route errors

* bump abacus

* add dep

* address comments

* fix max

* disable slippage editor

* parse error message in abacus
2023-11-09 10:34:22 -08:00
aleka
91a97a1c68
add network select menu in restriction modals (dev) (#137) 2023-11-09 09:10:12 -05:00
aleka
c5f736d805
fix deposit dialog logic (#136) 2023-11-08 14:01:16 -05:00
aleka
3769f7078c
update readme re env mode (#133) 2023-11-07 20:28:56 -08:00
Jared Vu
edc9fadfee
Add TestFlags provider and class (#132)
* Add TestFlags provider and class

* import order nit

* markets is an object and not array

* Use null coalescing op
2023-11-07 20:28:42 -08:00
aleka
5e2d426cd1
Send native tokens inclusive fee (#118)
* send dv4tnt inclusive of fees
2023-11-07 22:42:41 -05:00
Bill
766209baf1
Onboarding fixes (#131)
* Onboarding fixes

* address comments

* rebase
2023-11-07 17:18:16 -08:00
aleka
906faa554d
Surface close position input errors (#130)
* show abacus close position validation errors

* bump abacus version
2023-11-07 19:11:08 -05:00
John Huang
c339eeccde
TRCL-3077 Added an environment for testing. Expected behavior - when "v4 Staging Forced Update" is selected in iOS app, it should switch to the forced update screen (#99) 2023-11-07 13:33:06 -08:00
aleka
bd03fb73ca
update mintscan tx link on transfer history table (#128)
* update mintscan tx link on transfer history table

* bump localization + fix icon button padding in header
2023-11-07 16:00:22 -05:00
Rui
31825a8a52
Change "iOS" to "ios" for consistency (#129) 2023-11-07 11:01:41 -08:00
John Huang
8d5bf1a721
TRCL-3128 TradePlaceOrder and TradeCancelOrder are now tracked by Abacus (#115) 2023-11-07 10:34:06 -08:00
aleka
7f3d57b46a
support multiple modes (#125) 2023-11-07 12:13:59 -05:00
Bill
c292c84c2c
Fix decimal overflow bug (#127)
* Fix decimal overflow bug

* use decimals:
2023-11-06 17:48:19 -08:00
Bill
2d37ff676b
do not use TESTNET_CHAIN_ID (#126) 2023-11-06 17:39:02 -08:00
Rui
68f3552569
Add app configuration to env.json (#121) 2023-11-06 13:02:38 -08:00
aleka
18b12591ca
Update LICENSE (#123) 2023-11-06 11:10:31 -08:00
Bill
3f963ffb07
Add Env var descriptions to readme (#124)
* Add Env var descriptions to readme

* update

* remove examples

* grammar
2023-11-06 10:50:45 -08:00
aleka
aac024fd5e
showing negative buying power as - (#119) 2023-11-06 13:31:41 -05:00
Christopher-Li
4913c690ec
Update all dev4 endpoints to use https and wss (#117)
* Update all dev endpoints to use https and wss

* dev4
2023-11-06 09:33:22 -08:00
Bill
b0db577b28
Configurable squid integrator id (#120)
* Configurable squid integrator id

* bump abacus
2023-11-03 14:18:15 -07:00
Bill
9815437a80
Account dropdown onboarding entrypoints (#113)
* Account dropdown onboarding entrypoints

* Update based on latest designs
2023-10-31 14:29:36 -07:00
aleka
890a4b2c0e
Padding fixes, markets data null fix, update .env.example (#112)
* update .env.example for token migration

* bump icon size in icon button

* add padding in rewards / fees page, panel changes

* fix markets data crashing

* fix market details overflow on tablet

* fix market filters

* prevent fees table overflow

* remove notifications close button on mobile

* fix nested button console warning

* update ToggleGroup value change logic

* panel hover impact button hover

* update dropdown icon in header
2023-10-31 17:11:46 -04:00
Bill
8d3cc76d14
Configurable URLs (#107)
* Configurable URLs

* add learnmore to tooltip

* Learnmore -> LearnMore
2023-10-31 11:02:45 -07:00
Adam Fraser
c7ad4b3028
Remove DSRV from Testnet node config options (#108)
* Remove DSRV from Testnet node config options

* Add Bware to testnet node config
2023-10-31 10:52:49 -07:00
Rui
c88d5dd411
Add Android config to wallets.json (#114) 2023-10-31 09:35:59 -07:00
Jared Vu
d6ab547055
Update README.md (#111)
* Add README in scripts directory

* Add Cloudflare instructions to README
2023-10-30 15:17:12 -07:00
392 changed files with 63917 additions and 6202 deletions

View File

@ -3,8 +3,20 @@ VITE_BASE_URL=
VITE_ALCHEMY_API_KEY= VITE_ALCHEMY_API_KEY=
VITE_PK_ENCRYPTION_KEY= VITE_PK_ENCRYPTION_KEY=
VITE_ROUTER_TYPE=
VITE_WALLETCONNECT2_PROJECT_ID=
VITE_V3_TOKEN_ADDRESS= VITE_V3_TOKEN_ADDRESS=
VITE_TOKEN_MIGRATION_URI= VITE_TOKEN_MIGRATION_URI=
AMPLITUDE_API_KEY=
AMPLITUDE_SERVER_URL=
BUGSNAG_API_KEY=
IOS_APP_ID=
INTERCOM_APP_ID=
STATUS_PAGE_SCRIPT_URI=
SMARTBANNER_APP_NAME=
SMARTBANNER_ORG_NAME=
SMARTBANNER_ICON_URL=
SMARTBANNER_APPSTORE_URL=
SMARTBANNER_GOOGLEPLAY_URL=

View File

@ -39,6 +39,7 @@ jobs:
pnpm run build:inject-amplitude pnpm run build:inject-amplitude
pnpm run build:inject-bugsnag pnpm run build:inject-bugsnag
pnpm run build:inject-statuspage pnpm run build:inject-statuspage
pnpm run build:inject-smartbanner
sh scripts/inject-app-deeplinks.sh sh scripts/inject-app-deeplinks.sh
- name: Upload to IPFS via web3.storage - name: Upload to IPFS via web3.storage

View File

@ -2,74 +2,132 @@ import '@/polyfills';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import styled from 'styled-components'; import styled from 'styled-components';
import { WagmiConfig } from 'wagmi';
import { GrazProvider } from 'graz';
import { QueryClient, QueryClientProvider } from 'react-query';
import { store } from '@/state/_store'; import { SupportedLocales } from '@/constants/localization';
import { AccountsProvider } from '@/hooks/useAccounts';
import { AppThemeAndColorModeProvider } from '@/hooks/useAppThemeAndColorMode';
import { DydxProvider } from '@/hooks/useDydxClient';
import { DialogAreaProvider } from '@/hooks/useDialogArea';
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
import { PotentialMarketsProvider } from '@/hooks/usePotentialMarkets';
import { RestrictionProvider } from '@/hooks/useRestrictions';
import { SubaccountProvider } from '@/hooks/useSubaccount';
import { GlobalStyle } from '@/styles/globalStyle';
import { SelectMenu, SelectItem } from '@/components/SelectMenu'; import { SelectMenu, SelectItem } from '@/components/SelectMenu';
import { setLocaleLoaded } from '@/state/localization'; import {
AppTheme,
AppThemeSystemSetting,
AppColorMode,
setAppThemeSetting,
setAppColorMode,
} from '@/state/configs';
import { setLocaleLoaded, setSelectedLocale } from '@/state/localization';
import { store } from '@/state/_store';
import { config } from '@/lib/wagmi';
import '@/index.css'; import '@/index.css';
import './ladle.css'; import './ladle.css';
const queryClient = new QueryClient();
const wrapProvider = (Component: React.ComponentType<any>, props?: any) => {
// eslint-disable-next-line react/display-name
return ({ children }: { children: React.ReactNode }) => (
<Component {...props}>{children}</Component>
);
};
const providers = [
wrapProvider(QueryClientProvider, { client: queryClient }),
wrapProvider(GrazProvider),
wrapProvider(WagmiConfig, { config }),
wrapProvider(LocaleProvider),
wrapProvider(RestrictionProvider),
wrapProvider(DydxProvider),
wrapProvider(AccountsProvider),
wrapProvider(SubaccountProvider),
wrapProvider(DialogAreaProvider),
wrapProvider(PotentialMarketsProvider),
wrapProvider(AppThemeAndColorModeProvider),
];
export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => { 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(() => { useEffect(() => {
switch (theme) { store.dispatch(setAppThemeSetting(theme));
case 'Dark theme': { store.dispatch(setAppColorMode(colorMode));
document?.documentElement?.classList.remove('theme-light'); }, [theme, colorMode]);
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]);
useEffect(() => { useEffect(() => {
store.dispatch(setSelectedLocale({ locale: SupportedLocales.EN }));
store.dispatch(setLocaleLoaded(true)); store.dispatch(setLocaleLoaded(true));
}, []); }, []);
const content = [...providers].reverse().reduce(
(children, Provider) => {
return <Provider>{children}</Provider>;
},
<StoryContent>
<GlobalStyle />
{children}
</StoryContent>
);
return ( return (
<Provider store={store}> <Provider store={store}>
<StoryHeader> <StoryHeader>
<h4>Active Theme:</h4> <h4>Active Theme:</h4>
<SelectMenu <SelectMenu value={theme} onValueChange={setTheme}>
value={theme}
onValueChange={setTheme}
>
{[ {[
{ {
value: 'Default theme', value: AppTheme.Classic,
label: 'Default theme', label: 'Default theme',
}, },
{ {
value: 'Dark theme', value: AppThemeSystemSetting.System,
label: 'System theme',
},
{
value: AppTheme.Dark,
label: 'Dark theme', label: 'Dark theme',
}, },
{ {
value: 'Light theme', value: AppTheme.Light,
label: 'Light theme', label: 'Light theme',
}, },
].map(({ value, label }) => ( ].map(({ value, label }) => (
<SelectItem <SelectItem key={value} value={value} label={label} />
key={value} ))}
value={value} </SelectMenu>
label={label} <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> </SelectMenu>
</StoryHeader> </StoryHeader>
<hr /> <hr />
<StoryContent>{children}</StoryContent> {content}
</Provider> </Provider>
); );
}; };

View File

@ -1 +1,2 @@
node_modules/ node_modules/
public/

View File

@ -1,6 +1,9 @@
Copyright (C) 2023 dYdX Trading Inc. Copyright (C) 2023 dYdX Trading Inc.
Subject to your compliance with applicable law, you are granted the right to use the Licensed Work (defined below) under the terms of the GNU Affero General Public License as set forth below; provided, however, that if you violate any such applicable law in your use of the Licensed Work, all of your rights and licenses to use (including any rights to reproduce, distribute, install or modify) the Licensed Work will automatically and immediately terminate. Subject to your compliance with applicable law and the v4 Terms of Use, available at dydx.exchange/legal, you are granted the right to use the Program or Licensed Work (defined below) under the terms of the GNU Affero General Public License as set forth below; provided, however, that if you violate any such applicable law in your use of the Program or Licensed Work, all of your rights and licenses to use (including any rights to reproduce, distribute, install or modify) the Program or Licensed Work will automatically and immediately terminate.
The “Program” or “Licensed Work” shall mean any of the following: dydxprotocol/cosmos-sdk, dydxprotocol/cometbft, dydxprotocol/v4-chain, dydxprotocol/v4-clients, dydxprotocol/v4-web, dydxprotocol/v4-abacus, dydxprotocol/v4-localization, dydxprotocol/v4-documentation, and any dYdX or dYdX Trading Inc. repository reflecting a copy of, or link to, this license.
The GNU Affero General Public License The GNU Affero General Public License

View File

@ -26,7 +26,7 @@ Alternatively, follow the [IPFS Kubo installation guide](https://docs.ipfs.tech
## Part 1: Setting up your local environment ## Part 1: Setting up your local environment
### Step 1: Clone the repo ### 1. Clone the repo
Clone the repository and navigate to its directory: Clone the repository and navigate to its directory:
@ -35,7 +35,7 @@ git clone https://github.com/dydxprotocol/v4-web.git
cd v4-web cd v4-web
``` ```
### Step 2: Install pnpm and dependencies ### 2. Install pnpm and dependencies
Install pnpm and the project dependencies: Install pnpm and the project dependencies:
@ -66,10 +66,30 @@ This will automatically open your default browser at `http://localhost:61000`.
Add or modify the relevant endpoints, links and options in `/public/configs/env.json`. Add or modify the relevant endpoints, links and options in `/public/configs/env.json`.
You'll need to provide a Wallet Connect project id to enable onboarding and wallet connection: You'll need to provide a Wallet Connect project id to enable onboarding and wallet connection:
- Create a project on https://cloud.walletconnect.com/app - Create a project on https://cloud.walletconnect.com/app
- Copy over the project ID into this [field](https://github.com/dydxprotocol/v4-web/blob/67ecbd75b43e0c264b7b4d2d9b3d969830b0621c/public/configs/env.json#L822C33-L822C46) - Copy over the project ID into this [field](https://github.com/dydxprotocol/v4-web/blob/67ecbd75b43e0c264b7b4d2d9b3d969830b0621c/public/configs/env.json#L822C33-L822C46)
## Part 4: Deploying with Vercel ## Part 4: Set Enviornment variables
Set environment variables via `.env`.
- `VITE_BASE_URL` (required): The base URL of the deployment (e.g., `https://www.example.com`).
- `VITE_ALCHEMY_API_KEY` (optional): Add an Alchemy API key for EVM interactions; the app will fall back to public RPCs if not provided.
- `VITE_PK_ENCRYPTION_KEY` (optional): AES encryption key used for signature obfuscation; necessary for enabling the "Remember Me" feature.
- `VITE_V3_TOKEN_ADDRESS` (optional): Address of the V3 $DYDX token.
- `VITE_TOKEN_MIGRATION_URI` (optional): The URL of the token migration website.
- `AMPLITUDE_API_KEY` (optional): Amplitude API key for enabling Amplitude; used with `pnpm run build:inject-amplitude`.
- `AMPLITUDE_SERVER_URL` (optional): Custom Amplitude server URL
- `BUGSNAG_API_KEY` (optional): API key for enabling Bugsnag; used with `pnpm run build:inject-bugsnag`.
- `IOS_APP_ID` (optional): iOS app ID used for enabling deep linking to the iOS app; used with `pnpm run build:inject-app-deeplinks`.
- `INTERCOM_APP_ID` (optional): Used for enabling Intercom; utilized with `pnpm run build:inject-intercom`.
- `STATUS_PAGE_SCRIPT_URI` (optional): Used for enabling the status page; used with `pnpm run build:inject-statuspage`.
- `SMARTBANNER_APP_NAME`, `SMARTBANNER_ORG_NAME`, `SMARTBANNER_ICON_URL`, `SMARTBANNER_APPSTORE_URL` (optional): Used for enabling the smart app banner; used with `pnpm run build:inject-smartbanner`.
# Deployments
## Deploying with Vercel
### Step 1: Connect your repository to Vercel ### Step 1: Connect your repository to Vercel
@ -78,15 +98,33 @@ Select "Import Git Repository" from your dashboard, and provide the URL of this
### Step 2: Configure your project ### Step 2: Configure your project
For the "Build & Development Settings", we recommend the following: For the "Build & Development Settings", we recommend the following:
- Framework Preset: `Vite` - Framework Preset: `Vite`
- Build Command (override): `pnpm run build` - Build Command (override): `pnpm run build`
By default, the dev server runs in development mode and the build command runs in production mode. To override the default mode, you can pass in the `--mode` option flag. For example, if you want to build your app for testnet:
```
pnpm run build --mode testnet
```
If you wish to incorporate analytics via Amplitude and Bugsnag, you can use our scripts: If you wish to incorporate analytics via Amplitude and Bugsnag, you can use our scripts:
`pnpm run build:inject-amplitude` and `pnpm run build:inject-bugsnag`. You will need to provide your own API keys for these services. In the Environment Variables section, name the variables as `AMPLITUDE_API_KEY` and `BUGSNAG_API_KEY` and provide the respective keys as their values. `pnpm run build:inject-amplitude` and `pnpm run build:inject-bugsnag`. You will need to provide your own API keys for these services. In the Environment Variables section, name the variables as `AMPLITUDE_API_KEY` and `BUGSNAG_API_KEY` and provide the respective keys as their values.
If you wish to incorporate smart banner for iOS and/or Android apps, you can use our scripts:
`pnpm run build:inject-smartbanner`. You will need to provide your own app configurations for these services. In the Environment Variables section, name the variables as `SMARTBANNER_APP_NAME`, `SMARTBANNER_ORG_NAME`, `SMARTBANNER_ICON_URL` and `SMARTBANNER_APPSTORE_URL` or `SMARTBANNER_GOOGLEPLAY_URL` and provide the respective values.
For more details, check out Vercel's [official documentation](https://vercel.com/docs). For more details, check out Vercel's [official documentation](https://vercel.com/docs).
## Part 5: Deploying to IPFS ## Deploying to IPFS
### Must Enable HashRouting
Add the following to `.env` file
```
VITE_ROUTER_TYPE=hash
```
### web3.storage: deploy to IPFS via web3.storage using the provided script ### web3.storage: deploy to IPFS via web3.storage using the provided script
@ -118,3 +156,20 @@ To access your content on IPFS:
2. **Public IPFS gateway:** Access your content via a public IPFS gateway, such as [https://dweb.link](https://dweb.link/) or [https://w3s.link/](https://w3s.link/). Use the gateway URL with your CID appended, like `https://dweb.link/ipfs/your_cid`. 2. **Public IPFS gateway:** Access your content via a public IPFS gateway, such as [https://dweb.link](https://dweb.link/) or [https://w3s.link/](https://w3s.link/). Use the gateway URL with your CID appended, like `https://dweb.link/ipfs/your_cid`.
Replace `your_cid` with the actual CID. Replace `your_cid` with the actual CID.
## Cloudflare Settings
We recommend that you add your website to Cloudflare for additional security settings.
To block OFAC Sanctioned countries:
1. Navigate Websites > Domain > Security > WAF
2. Create Rule with the following settings:
- If incoming requests match
`(ip.geoip.country eq "CU") or (ip.geoip.country eq "IR") or (ip.geoip.country eq "KP") or (ip.geoip.country eq "SY") or (ip.geoip.country eq "MM") or (ip.geoip.subdivision_1_iso_code eq "UA-09") or (ip.geoip.subdivision_1_iso_code eq "UA-14") or (ip.geoip.subdivision_1_iso_code eq "UA-43")`
- This rule will bring up a Cloudflare page when a restricted geography tries to access your site. You will have the option to display:
1. Custom Text
- (e.g. `Because you appear to be a resident of, or trading from, a jurisdiction that violates our terms of use, or have engaged in activity that violates our terms of use, you have been blocked. You may withdraw your funds from the protocol at any time.`)
2. Default Cloudflare WAF block page

View File

@ -15,6 +15,7 @@
"build:inject-bugsnag": "node scripts/inject-bugsnag.js", "build:inject-bugsnag": "node scripts/inject-bugsnag.js",
"build:inject-intercom": "node scripts/inject-intercom.js", "build:inject-intercom": "node scripts/inject-intercom.js",
"build:inject-statuspage": "node scripts/inject-statuspage.js", "build:inject-statuspage": "node scripts/inject-statuspage.js",
"build:inject-smartbanner": "node scripts/inject-smartbanner.js",
"deploy:ipfs": "node scripts/upload-ipfs.js --verbose", "deploy:ipfs": "node scripts/upload-ipfs.js --verbose",
"deploy:update-ipns": "node scripts/update-ipns.js", "deploy:update-ipns": "node scripts/update-ipns.js",
"deploy:update-dnslink": "node scripts/update-dnslink.js", "deploy:update-dnslink": "node scripts/update-dnslink.js",
@ -33,20 +34,23 @@
"packageManager": "pnpm@8.6.6", "packageManager": "pnpm@8.6.6",
"dependencies": { "dependencies": {
"@0xsquid/sdk": "^1.10.0", "@0xsquid/sdk": "^1.10.0",
"@cosmjs/amino": "^0.31.0", "@cosmjs/amino": "^0.32.1",
"@cosmjs/crypto": "^0.31.0", "@cosmjs/crypto": "^0.32.1",
"@cosmjs/encoding": "^0.31.0", "@cosmjs/encoding": "^0.32.1",
"@cosmjs/proto-signing": "^0.31.0", "@cosmjs/proto-signing": "^0.32.1",
"@cosmjs/stargate": "^0.31.0", "@cosmjs/stargate": "^0.32.1",
"@cosmjs/tendermint-rpc": "^0.31.0", "@cosmjs/tendermint-rpc": "^0.32.1",
"@dydxprotocol/v4-abacus": "^1.0.3", "@dydxprotocol/v4-abacus": "^1.4.12",
"@dydxprotocol/v4-client-js": "^1.0.0", "@dydxprotocol/v4-client-js": "^1.0.20",
"@dydxprotocol/v4-localization": "^1.0.0", "@dydxprotocol/v4-localization": "^1.1.35",
"@ethersproject/providers": "^5.7.2", "@ethersproject/providers": "^5.7.2",
"@js-joda/core": "^5.5.3", "@js-joda/core": "^5.5.3",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-collapsible": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.5", "@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-navigation-menu": "^1.1.3", "@radix-ui/react-navigation-menu": "^1.1.3",
"@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-popover": "^1.0.6",
"@radix-ui/react-radio-group": "^1.1.3", "@radix-ui/react-radio-group": "^1.1.3",
@ -89,6 +93,7 @@
"buffer": "^6.0.3", "buffer": "^6.0.3",
"cmdk": "^0.2.0", "cmdk": "^0.2.0",
"color": "^4.2.3", "color": "^4.2.3",
"cosmjs-types": "^0.9.0",
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"ethers": "^6.6.1", "ethers": "^6.6.1",
"graz": "^0.0.43", "graz": "^0.0.43",
@ -96,6 +101,7 @@
"long": "^5.2.3", "long": "^5.2.3",
"luxon": "^3.3.0", "luxon": "^3.3.0",
"qr-code-styling": "1.6.0-rc.1", "qr-code-styling": "1.6.0-rc.1",
"query-string": "^8.1.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-aria": "^3.25.0", "react-aria": "^3.25.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
@ -107,12 +113,12 @@
"reselect": "^4.1.8", "reselect": "^4.1.8",
"styled-components": "^5.3.11", "styled-components": "^5.3.11",
"use-latest": "^1.2.1", "use-latest": "^1.2.1",
"viem": "^1.12.2", "viem": "^1.20.0",
"wagmi": "^1.3.7" "wagmi": "^1.4.12"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.22.5", "@babel/core": "^7.22.5",
"@ladle/react": "^2.15.0", "@ladle/react": "^4.0.2",
"@types/color": "^3.0.3", "@types/color": "^3.0.3",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.1.1",
"@types/luxon": "^3.3.0", "@types/luxon": "^3.3.0",
@ -151,5 +157,10 @@
"vitest": "^0.32.2", "vitest": "^0.32.2",
"w3name": "^1.0.8", "w3name": "^1.0.8",
"web3.storage": "^4.5.4" "web3.storage": "^4.5.4"
},
"pnpm": {
"overrides": {
"follow-redirects": "1.15.3"
}
} }
} }

4241
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "exchange.dydx.trading.debug",
"sha256_cert_fingerprints": [
"8A:9C:CC:49:B0:35:9A:91:67:CB:98:B0:B5:87:92:5F:9E:B7:EF:CE:A0:47:57:85:A4:35:3E:0C:E1:56:9E:A2"
]
}
},
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "exchange.dydx.trading",
"sha256_cert_fingerprints": [
"B2:2D:CC:27:9D:52:05:98:63:C9:7B:34:36:70:A3:8E:00:31:28:08:2D:2E:70:76:C9:31:AE:F9:55:21:15:A5"
]
}
}
]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

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
public/chart-bars.svg Normal file
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

22
public/configs/cctp.json Normal file
View File

@ -0,0 +1,22 @@
[
{
"chainId": "1",
"tokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"name": "Ethereum"
},
{
"chainId": "5",
"tokenAddress": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F",
"name": "Ethereum Goerli"
},
{
"chainId": "43114",
"tokenAddress": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
"name": "Avalanche"
},
{
"chainId": "10",
"tokenAddress": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
"name": "optimism"
}
]

View File

@ -0,0 +1,16 @@
{
"tradingRewardsFAQs": [
{
"questionLocalizationKey": "APP.TRADING_REWARDS.FAQ_WHO_IS_ELIGIBLE_QUESTION",
"answerLocalizationKey": "APP.TRADING_REWARDS.FAQ_WHO_IS_ELIGIBLE_ANSWER"
},
{
"questionLocalizationKey": "APP.TRADING_REWARDS.FAQ_HOW_DO_TRADING_REWARDS_WORK_QUESTION",
"answerLocalizationKey": "APP.TRADING_REWARDS.FAQ_HOW_DO_TRADING_REWARDS_WORK_ANSWER"
},
{
"questionLocalizationKey": "APP.TRADING_REWARDS.FAQ_HOW_DO_I_CLAIM_MY_REWARDS_QUESTION",
"answerLocalizationKey": "APP.TRADING_REWARDS.FAQ_HOW_DO_I_CLAIM_MY_REWARDS_ANSWER"
}
]
}

View File

@ -1,4 +1,9 @@
{ {
"apps": {
"ios": {
"scheme": "dydx-t-v4"
}
},
"deployments": { "deployments": {
"MAINNET": { "MAINNET": {
"environments": [ "environments": [
@ -6,6 +11,13 @@
], ],
"default": "dydxprotocol-mainnet" "default": "dydxprotocol-mainnet"
}, },
"TESTFLIGHT": {
"environments": [
"dydxprotocol-mainnet",
"dydxprotocol-testnet"
],
"default": "dydxprotocol-mainnet"
},
"TESTNET": { "TESTNET": {
"environments": [ "environments": [
"dydxprotocol-testnet" "dydxprotocol-testnet"
@ -34,10 +46,11 @@
"environments": { "environments": {
"dydxprotocol-dev": { "dydxprotocol-dev": {
"name": "v4 Dev", "name": "v4 Dev",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet", "dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -65,13 +78,27 @@
"https://validator.v4dev.dydx.exchange" "https://validator.v4dev.dydx.exchange"
], ],
"0xsquid": "https://testnet.api.0xsquid.com", "0xsquid": "https://testnet.api.0xsquid.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4dev.dydx.exchange" "faucet": "https://faucet.v4dev.dydx.exchange"
}, },
"links": { "links": {
"tos": "https://dydx.exchange/v4-terms", "tos": "https://dydx.exchange/v4-terms",
"privacy": "https://dydx.exchange/privacy", "privacy": "https://dydx.exchange/privacy",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}", "mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -90,14 +117,25 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain" "signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-dev-2": { "dydxprotocol-dev-2": {
"name": "v4 Dev 2", "name": "v4 Dev 2",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet", "dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -124,13 +162,27 @@
"validators": [ "validators": [
"http://54.92.118.111" "http://54.92.118.111"
], ],
"0xsquid": "https://testnet.api.0xsquid.com" "0xsquid": "https://testnet.api.0xsquid.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
}, },
"links": { "links": {
"tos": "https://dydx.exchange/v4-terms", "tos": "https://dydx.exchange/v4-terms",
"privacy": "https://dydx.exchange/privacy", "privacy": "https://dydx.exchange/privacy",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}", "mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -149,14 +201,25 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain" "signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-dev-4": { "dydxprotocol-dev-4": {
"name": "v4 Dev 4", "name": "v4 Dev 4",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet", "dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -176,20 +239,35 @@
"endpoints": { "endpoints": {
"indexers": [ "indexers": [
{ {
"api": "http://indexer.v4dev4.dydx.exchange", "api": "https://indexer.v4dev4.dydx.exchange",
"socket": "ws://indexer.v4dev4.dydx.exchange" "socket": "wss://indexer.v4dev4.dydx.exchange"
} }
], ],
"validators": [ "validators": [
"http://validator.v4dev4.dydx.exchange" "https://validator.v4dev4.dydx.exchange"
], ],
"0xsquid": "https://testnet.api.0xsquid.com" "0xsquid": "https://testnet.api.0xsquid.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4dev4.dydx.exchange"
}, },
"links": { "links": {
"tos": "https://dydx.exchange/v4-terms", "tos": "https://dydx.exchange/v4-terms",
"privacy": "https://dydx.exchange/privacy", "privacy": "https://dydx.exchange/privacy",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}", "mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -208,14 +286,25 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain" "signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-dev-5": { "dydxprotocol-dev-5": {
"name": "v4 Dev 5", "name": "v4 Dev 5",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet", "dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -242,13 +331,27 @@
"validators": [ "validators": [
"http://18.223.78.50" "http://18.223.78.50"
], ],
"0xsquid": "https://testnet.api.0xsquid.com" "0xsquid": "https://testnet.api.0xsquid.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
}, },
"links": { "links": {
"tos": "https://dydx.exchange/v4-terms", "tos": "https://dydx.exchange/v4-terms",
"privacy": "https://dydx.exchange/privacy", "privacy": "https://dydx.exchange/privacy",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}", "mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -267,14 +370,25 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain" "signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-staging": { "dydxprotocol-staging": {
"name": "v4 Staging", "name": "v4 Staging",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet", "dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -302,7 +416,8 @@
"validators": [ "validators": [
"https://validator.v4staging.dydx.exchange" "https://validator.v4staging.dydx.exchange"
], ],
"0xsquid": "https://testnet.api.squidrouter.com" "0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
}, },
"links": { "links": {
"tos": "https://dydx.exchange/v4-terms", "tos": "https://dydx.exchange/v4-terms",
@ -312,7 +427,17 @@
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog", "blogs": "https://www.dydx.foundation/blog",
"help": "https://help.dydx.exchange" "help": "https://help.dydx.exchange",
"foundation": "https://www.dydx.foundation",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -331,14 +456,109 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain" "signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
}
},
"dydxprotocol-staging-forced-update": {
"name": "v4 Staging Forced Update",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"tokens": {
"chain": {
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4staging.dydx.exchange",
"socket": "wss://indexer.v4staging.dydx.exchange"
}
],
"faucet": "https://faucet.v4staging.dydx.exchange",
"validators": [
"https://validator.v4staging.dydx.exchange"
],
"0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
},
"links": {
"tos": "https://dydx.exchange/v4-terms",
"privacy": "https://dydx.exchange/privacy",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://v4-teacher.vercel.app/",
"community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals"
},
"wallets": {
"walletconnect": {
"client": {
"name": "dYdX v4",
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
},
"walletSegue": {
"callbackUrl": "/walletsegue"
},
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain"
},
"apps": {
"ios": {
"minimalVersion": "1.0",
"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"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-staging-west": { "dydxprotocol-staging-west": {
"name": "v4 Staging West", "name": "v4 Staging West",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet", "dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -366,7 +586,8 @@
"validators": [ "validators": [
"https://validator-uswest1.v4staging.dydx.exchange" "https://validator-uswest1.v4staging.dydx.exchange"
], ],
"0xsquid": "https://testnet.api.squidrouter.com" "0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
}, },
"links": { "links": {
"tos": "https://dydx.exchange/v4-terms", "tos": "https://dydx.exchange/v4-terms",
@ -376,7 +597,17 @@
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog", "blogs": "https://www.dydx.foundation/blog",
"help": "https://help.dydx.exchange" "help": "https://help.dydx.exchange",
"foundation": "https://www.dydx.foundation",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -395,14 +626,25 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain" "signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-testnet": { "dydxprotocol-testnet": {
"name": "v4 Public Testnet", "name": "v4 Public Testnet",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -422,8 +664,8 @@
"endpoints": { "endpoints": {
"indexers": [ "indexers": [
{ {
"api": "https://dydx-testnet.imperator.co", "api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://dydx-testnet.imperator.co" "socket": "wss://indexer.v4testnet.dydx.exchange"
} }
], ],
"validators": [ "validators": [
@ -434,6 +676,7 @@
"https://dydx-rpc.liquify.com/api=8878132/dydx" "https://dydx-rpc.liquify.com/api=8878132/dydx"
], ],
"0xsquid": "https://testnet.api.squidrouter.com", "0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange" "faucet": "https://faucet.v4testnet.dydx.exchange"
}, },
"links": { "links": {
@ -443,7 +686,18 @@
"documentation": "https://docs.dydx.exchange/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -462,14 +716,25 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-testnet-dydx": { "dydxprotocol-testnet-dydx": {
"name": "v4 Public Testnet/dYdX", "name": "v4 Public Testnet/dYdX",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -497,6 +762,7 @@
"https://validator.v4testnet.dydx.exchange" "https://validator.v4testnet.dydx.exchange"
], ],
"0xsquid": "https://testnet.api.squidrouter.com", "0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange" "faucet": "https://faucet.v4testnet.dydx.exchange"
}, },
"links": { "links": {
@ -507,7 +773,18 @@
"documentation": "https://docs.dydx.exchange/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -526,14 +803,25 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-testnet-nodefleet": { "dydxprotocol-testnet-nodefleet": {
"name": "v4 Public Testnet/nodefleet", "name": "v4 Public Testnet/nodefleet",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -553,14 +841,15 @@
"endpoints": { "endpoints": {
"indexers": [ "indexers": [
{ {
"api": "https://dydx-testnet.imperator.co", "api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://dydx-testnet.imperator.co" "socket": "wss://indexer.v4testnet.dydx.exchange"
} }
], ],
"validators": [ "validators": [
"https://dydx-testnet.nodefleet.org" "https://dydx-testnet.nodefleet.org"
], ],
"0xsquid": "https://testnet.api.squidrouter.com", "0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange" "faucet": "https://faucet.v4testnet.dydx.exchange"
}, },
"links": { "links": {
@ -571,7 +860,18 @@
"documentation": "https://docs.dydx.exchange/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -590,14 +890,25 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-testnet-kingnodes": { "dydxprotocol-testnet-kingnodes": {
"name": "v4 Public Testnet/KingNodes", "name": "v4 Public Testnet/KingNodes",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -617,14 +928,15 @@
"endpoints": { "endpoints": {
"indexers": [ "indexers": [
{ {
"api": "https://dydx-testnet.imperator.co", "api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://dydx-testnet.imperator.co" "socket": "wss://indexer.v4testnet.dydx.exchange"
} }
], ],
"validators": [ "validators": [
"https://test-dydx.kingnodes.com" "https://test-dydx.kingnodes.com"
], ],
"0xsquid": "https://testnet.api.squidrouter.com", "0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange" "faucet": "https://faucet.v4testnet.dydx.exchange"
}, },
"links": { "links": {
@ -635,7 +947,18 @@
"documentation": "https://docs.dydx.exchange/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -654,14 +977,25 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-testnet-liquify": { "dydxprotocol-testnet-liquify": {
"name": "v4 Public Testnet/Liquify", "name": "v4 Public Testnet/Liquify",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -681,14 +1015,15 @@
"endpoints": { "endpoints": {
"indexers": [ "indexers": [
{ {
"api": "https://dydx-testnet.imperator.co", "api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://dydx-testnet.imperator.co" "socket": "wss://indexer.v4testnet.dydx.exchange"
} }
], ],
"validators": [ "validators": [
"https://dydx-rpc.liquify.com/api=8878132/dydx" "https://dydx-rpc.liquify.com/api=8878132/dydx"
], ],
"0xsquid": "https://testnet.api.squidrouter.com", "0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange" "faucet": "https://faucet.v4testnet.dydx.exchange"
}, },
"links": { "links": {
@ -699,7 +1034,18 @@
"documentation": "https://docs.dydx.exchange/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -718,14 +1064,25 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-testnet-polkachu": { "dydxprotocol-testnet-polkachu": {
"name": "v4 Public Testnet/Polkahcu", "name": "v4 Public Testnet/Polkahcu",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -745,14 +1102,15 @@
"endpoints": { "endpoints": {
"indexers": [ "indexers": [
{ {
"api": "https://dydx-testnet.imperator.co", "api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://dydx-testnet.imperator.co" "socket": "wss://indexer.v4testnet.dydx.exchange"
} }
], ],
"validators": [ "validators": [
"https://dydx-testnet-rpc.polkachu.com/" "https://dydx-testnet-rpc.polkachu.com/"
], ],
"0xsquid": "https://testnet.api.squidrouter.com", "0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange" "faucet": "https://faucet.v4testnet.dydx.exchange"
}, },
"links": { "links": {
@ -760,10 +1118,12 @@
"privacy": "https://dydx.exchange/privacy", "privacy": "https://dydx.exchange/privacy",
"statusPage": "https://status.v4testnet.dydx.exchange/", "statusPage": "https://status.v4testnet.dydx.exchange/",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}", "mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -782,14 +1142,25 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-testnet-bware": { "dydxprotocol-testnet-bware": {
"name": "v4 Public Testnet/BWare", "name": "v4 Public Testnet/BWare",
"ethereumChainId": "5", "ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4", "dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false, "isMainNet": false,
"tokens": { "tokens": {
"chain": { "chain": {
@ -809,14 +1180,15 @@
"endpoints": { "endpoints": {
"indexers": [ "indexers": [
{ {
"api": "https://dydx-testnet.imperator.co", "api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://dydx-testnet.imperator.co" "socket": "wss://indexer.v4testnet.dydx.exchange"
} }
], ],
"validators": [ "validators": [
"https://dydx-testnet-full-rpc.public.blastapi.io/" "https://dydx-testnet-full-rpc.public.blastapi.io/"
], ],
"0xsquid": "https://testnet.api.squidrouter.com", "0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange" "faucet": "https://faucet.v4testnet.dydx.exchange"
}, },
"links": { "links": {
@ -824,10 +1196,21 @@
"privacy": "https://dydx.exchange/privacy", "privacy": "https://dydx.exchange/privacy",
"statusPage": "https://status.v4testnet.dydx.exchange/", "statusPage": "https://status.v4testnet.dydx.exchange/",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}", "mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"documentation": "https://v4-teacher.vercel.app/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"reduceOnlyLearnmore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnmore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnmore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnmore": "https://help.dydx.exchange",
"walletLearnmore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -846,6 +1229,16 @@
"images": "/wallets/", "images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX V4" "signTypedDataDomainName": "dYdX V4"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
} }
}, },
"dydxprotocol-mainnet": { "dydxprotocol-mainnet": {
@ -853,7 +1246,8 @@
"ethereumChainId": "1", "ethereumChainId": "1",
"dydxChainId": "[mainnet chain id]", "dydxChainId": "[mainnet chain id]",
"chainName": "dYdX Chain", "chainName": "dYdX Chain",
"chainLogo": "dydx-chain.png", "chainLogo": "/dydx-chain.png",
"squidIntegratorId": "[mainnet squid integrator id]",
"isMainNet": true, "isMainNet": true,
"tokens": { "tokens": {
"comment": "Change according to mainnet release", "comment": "Change according to mainnet release",
@ -882,17 +1276,28 @@
"[Validator endpoint 1", "[Validator endpoint 1",
"[Validator endpoint n]" "[Validator endpoint n]"
], ],
"0xsquid": "[0xSquid endpoint for mainnet]" "0xsquid": "[0xSquid endpoint for mainnet]",
"nobleValidator": "[noble validator endpoint for mainnet]"
}, },
"links": { "links": {
"tos": "[HTTP link to TOS]", "tos": "[HTTP link to TOS]",
"privacy": "[HTTP link to Privacy Policy]", "privacy": "[HTTP link to Privacy Policy]",
"mintscan": "[HTTP link to Mintscan, with {tx_hash} placeholder]", "mintscan": "[HTTP link to Mintscan, with {tx_hash} placeholder]",
"documentation": "[HTTP link to documentation, can be null]", "mintscanBase": "[HTTP link to TOS mintscan base url]",
"community": "[HTTP link to community, can be null]",
"feedback": "[HTTP link to feedback form, can be null]", "feedback": "[HTTP link to feedback form, can be null]",
"blogs": "[HTTP link to blogs, can be null]", "blogs": "[HTTP link to blogs, can be null]",
"help": "[HTTP link to help page, can be null]" "foundation": "[HTTP link to foundation, 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]",
"help": "[HTTP link to help page, can be null]",
"governanceLearnMore": "[HTTP link to governance learn more, can be null]",
"newMarketProposalLearnMore": "[HTTP link to new market proposal learn more, can be null]",
"stakingLearnMore": "[HTTP link to staking learn more, can be null]",
"keplrDashboard": "[HTTP link to keplr dashboard, can be null]",
"strideZoneApp": "[HTTP link to stride zone app, can be null]",
"accountExportLearnMore": "[HTTP link to account export learn more, can be null]",
"walletLearnMore": "[HTTP link to wallet learn more, can be null]"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -911,6 +1316,16 @@
"images": "[Relative URL for wallet images]", "images": "[Relative URL for wallet images]",
"signTypedDataAction": "dYdX Chain Onboarding", "signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain" "signTypedDataDomainName": "dYdX Chain"
},
"governance": {
"newMarketProposal": {
"initialDepositAmount": 0,
"delayBlocks": 0,
"newMarketsMethodology": "[URL to spreadsheet or document that explains methodology]"
}
},
"featureFlags": {
"reduceOnlySupported": false
} }
} }
} }

View File

@ -0,0 +1,8 @@
[
{
"name": "coinbase",
"label": "Coinbase",
"icon": "/exchanges/coinbase.png",
"depositType": "noble"
}
]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
This file identifies parameters for the optimal performance of various assets with the dYdX v4 open source software ("dYdX Chain"). For information on which assets are likely to be best compatible with dYdX Chain and how likely software compatibility and optimal parameters are assessed, please review the documentation [here](https://docs.dydx.trade/governance/proposing_a_new_market#example-proposal-json). Users considering using the permissionless markets function of the dYdX Chain are encouraged to consult qualified legal counsel to ensure compliance with the laws of their jurisdiction. The information herein does not constitute and should not be relied on as an endorsement or recommendation for any specific market, or investment, legal, or any other form of professional advice. Use of the v4 software is prohibited in the United States, Canada, and sanctioned jurisdictions as described in the [v4 Terms of Use](https://dydx.exchange/v4-terms).

View File

@ -0,0 +1,616 @@
{
"1INCH": [
{ "exchangeName": "Binance", "ticker": "1INCHUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "1INCH-USD" },
{ "exchangeName": "Gate", "ticker": "1INCH_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "1INCH-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "1INCH-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "1INCH_USDT", "adjustByMarket": "USDT-USD" }
],
"AAVE": [
{ "exchangeName": "Binance", "ticker": "AAVEUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "AAVE-USD" },
{ "exchangeName": "Huobi", "ticker": "aaveusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "AAVEUSD" },
{ "exchangeName": "Kucoin", "ticker": "AAVE-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "AAVE-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "AAVE_USDT", "adjustByMarket": "USDT-USD" }
],
"ADA": [
{ "exchangeName": "Binance", "ticker": "ADAUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bitstamp", "ticker": "ADA/USD" },
{ "exchangeName": "Bybit", "ticker": "ADAUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "ADA-USD" },
{ "exchangeName": "Huobi", "ticker": "adausdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "ADAUSD" },
{ "exchangeName": "Kucoin", "ticker": "ADA-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "ADA-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "ADA_USDT", "adjustByMarket": "USDT-USD" }
],
"AGIX": [
{ "exchangeName": "Binance", "ticker": "AGIXUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "AGIXUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "AGIX_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "AGIX-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "AGIX-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "AGIX_USDT", "adjustByMarket": "USDT-USD" }
],
"ALGO": [
{ "exchangeName": "Binance", "ticker": "ALGOUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "ALGO-USD" },
{ "exchangeName": "Kraken", "ticker": "ALGOUSD" },
{ "exchangeName": "Kucoin", "ticker": "ALGO-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "ALGO-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "ALGO_USDT", "adjustByMarket": "USDT-USD" }
],
"APE": [
{ "exchangeName": "Binance", "ticker": "APEUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "APE-USD" },
{ "exchangeName": "Gate", "ticker": "APE_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "APEUSD" },
{ "exchangeName": "Kucoin", "ticker": "APE-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "APE-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "APE_USDT", "adjustByMarket": "USDT-USD" }
],
"APT": [
{ "exchangeName": "Binance", "ticker": "APTUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "APTUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "APT-USD" },
{ "exchangeName": "Gate", "ticker": "APT_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Huobi", "ticker": "aptusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "APTUSD" },
{ "exchangeName": "Kucoin", "ticker": "APT-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "APT-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "APT_USDT", "adjustByMarket": "USDT-USD" }
],
"ARB": [
{ "exchangeName": "Binance", "ticker": "ARBUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "ARBUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "ARB-USD" },
{ "exchangeName": "Huobi", "ticker": "arbusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "ARBUSD" },
{ "exchangeName": "Kucoin", "ticker": "ARB-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "ARB-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "ARB_USDT", "adjustByMarket": "USDT-USD" }
],
"ATOM": [
{ "exchangeName": "Binance", "ticker": "ATOMUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "ATOMUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "ATOM-USD" },
{ "exchangeName": "Gate", "ticker": "ATOM_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "ATOMUSD" },
{ "exchangeName": "Kucoin", "ticker": "ATOM-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "ATOM-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "ATOM_USDT", "adjustByMarket": "USDT-USD" }
],
"AVAX": [
{ "exchangeName": "Binance", "ticker": "AVAXUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bitstamp", "ticker": "AVAX/USD" },
{ "exchangeName": "Bybit", "ticker": "AVAXUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "AVAX-USD" },
{ "exchangeName": "Huobi", "ticker": "avaxusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "AVAXUSD" },
{ "exchangeName": "Kucoin", "ticker": "AVAX-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "AVAX-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "AVAX_USDT", "adjustByMarket": "USDT-USD" }
],
"BCH": [
{ "exchangeName": "Binance", "ticker": "BCHUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bitstamp", "ticker": "BCH/USD" },
{ "exchangeName": "Bybit", "ticker": "BCHUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "BCH-USD" },
{ "exchangeName": "Huobi", "ticker": "bchusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "BCHUSD" },
{ "exchangeName": "Kucoin", "ticker": "BCH-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "BCH-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "BCH_USDT", "adjustByMarket": "USDT-USD" }
],
"BLUR": [
{ "exchangeName": "Binance", "ticker": "BLURUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "BLURUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "BLUR-USD" },
{ "exchangeName": "Kraken", "ticker": "BLURUSD" },
{ "exchangeName": "Kucoin", "ticker": "BLUR-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "BLUR-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "BLUR_USDT", "adjustByMarket": "USDT-USD" }
],
"BNB": [
{ "exchangeName": "Binance", "ticker": "BNBUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "BNBUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "BNB_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "BNB-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "BNB-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "BNB_USDT", "adjustByMarket": "USDT-USD" }
],
"BONK": [
{ "exchangeName": "Binance", "ticker": "BONKUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "BONKUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "BONK-USD" },
{ "exchangeName": "Kucoin", "ticker": "BONK-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "BONK-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "BONK_USDT", "adjustByMarket": "USDT-USD" }
],
"BTC": [
{ "exchangeName": "Binance", "ticker": "BTCUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bitstamp", "ticker": "BTC/USD" },
{ "exchangeName": "Bybit", "ticker": "BTCUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "BTC-USD" },
{ "exchangeName": "Huobi", "ticker": "btcusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "BTCUSD" },
{ "exchangeName": "Kucoin", "ticker": "BTC-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "BTC-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "BTC_USDT", "adjustByMarket": "USDT-USD" }
],
"CHZ": [
{ "exchangeName": "Binance", "ticker": "CHZUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "CHZ-USD" },
{ "exchangeName": "Kraken", "ticker": "CHZUSD" },
{ "exchangeName": "Kucoin", "ticker": "CHZ-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "CHZ-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "CHZ_USDT", "adjustByMarket": "USDT-USD" }
],
"CRV": [
{ "exchangeName": "Binance", "ticker": "CRVUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "CRV-USD" },
{ "exchangeName": "Kraken", "ticker": "CRVUSD" },
{ "exchangeName": "Kucoin", "ticker": "CRV-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "CRV-USDT", "adjustByMarket": "USDT-USD" }
],
"DOGE": [
{ "exchangeName": "Binance", "ticker": "DOGEUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "DOGEUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "DOGE-USD" },
{ "exchangeName": "Huobi", "ticker": "dogeusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "DOGEUSD" },
{ "exchangeName": "Kucoin", "ticker": "DOGE-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "DOGE-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "DOGE_USDT", "adjustByMarket": "USDT-USD" }
],
"DOT": [
{ "exchangeName": "Binance", "ticker": "DOTUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "DOTUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "DOT-USD" },
{ "exchangeName": "Huobi", "ticker": "dotusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "DOTUSD" },
{ "exchangeName": "Kucoin", "ticker": "DOT-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "DOT-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "DOT_USDT", "adjustByMarket": "USDT-USD" }
],
"DYM": [
{ "exchangeName": "Binance", "ticker": "DYMUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "DYMUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "DYM_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "DYM-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "DYM_USDT", "adjustByMarket": "USDT-USD" }
],
"ENS": [
{ "exchangeName": "Binance", "ticker": "ENSUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "ENS-USD" },
{ "exchangeName": "Gate", "ticker": "ENS_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "ENS-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "ENS-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "ENS_USDT", "adjustByMarket": "USDT-USD" }
],
"EOS": [
{ "exchangeName": "Binance", "ticker": "EOSUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "EOSUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "EOS-USD" },
{ "exchangeName": "Gate", "ticker": "EOS_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "EOSUSD" },
{ "exchangeName": "Kucoin", "ticker": "EOS-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "EOS-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "EOS_USDT", "adjustByMarket": "USDT-USD" }
],
"ETC": [
{ "exchangeName": "Binance", "ticker": "ETCUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "ETCUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "ETC-USD" },
{ "exchangeName": "Huobi", "ticker": "etcusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "ETCUSD" },
{ "exchangeName": "Kucoin", "ticker": "ETC-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "ETC-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "ETC_USDT", "adjustByMarket": "USDT-USD" }
],
"ETH": [
{ "exchangeName": "Binance", "ticker": "ETHUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bitstamp", "ticker": "ETH/USD" },
{ "exchangeName": "Bybit", "ticker": "ETHUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "ETH-USD" },
{ "exchangeName": "Huobi", "ticker": "ethusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "ETHUSD" },
{ "exchangeName": "Kucoin", "ticker": "ETH-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "ETH-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "ETH_USDT", "adjustByMarket": "USDT-USD" }
],
"FET": [
{ "exchangeName": "Binance", "ticker": "FETUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "FET-USD" },
{ "exchangeName": "Kraken", "ticker": "FETUSD" },
{ "exchangeName": "Kucoin", "ticker": "FET-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "FET-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "FET_USDT", "adjustByMarket": "USDT-USD" }
],
"FIL": [
{ "exchangeName": "Binance", "ticker": "FILUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "FILUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "FIL-USD" },
{ "exchangeName": "Huobi", "ticker": "filusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "FILUSD" },
{ "exchangeName": "Kucoin", "ticker": "FIL-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "FIL-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "FIL_USDT", "adjustByMarket": "USDT-USD" }
],
"FTM": [
{ "exchangeName": "Binance", "ticker": "FTMUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "FTMUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "FTMUSD" },
{ "exchangeName": "Kucoin", "ticker": "FTM-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "FTM-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "FTM_USDT", "adjustByMarket": "USDT-USD" }
],
"GALA": [
{ "exchangeName": "Binance", "ticker": "GALAUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "GALAUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "GALA_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "GALAUSD" },
{ "exchangeName": "Okx", "ticker": "GALA-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "GALA_USDT", "adjustByMarket": "USDT-USD" }
],
"GMT": [
{ "exchangeName": "Binance", "ticker": "GMTUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "GMTUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "GMT-USD" },
{ "exchangeName": "Gate", "ticker": "GMT_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "GMT-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "GMT-USDT", "adjustByMarket": "USDT-USD" }
],
"GRT": [
{ "exchangeName": "Binance", "ticker": "GRTUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "GRT-USD" },
{ "exchangeName": "Gate", "ticker": "GRT_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "GRTUSD" },
{ "exchangeName": "Kucoin", "ticker": "GRT-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "GRT-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "GRT_USDT", "adjustByMarket": "USDT-USD" }
],
"HBAR": [
{ "exchangeName": "Binance", "ticker": "HBARUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "HBARUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "HBAR-USD" },
{ "exchangeName": "Kucoin", "ticker": "HBAR-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "HBAR-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "HBAR_USDT", "adjustByMarket": "USDT-USD" }
],
"ICP": [
{ "exchangeName": "Binance", "ticker": "ICPUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "ICPUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "ICP-USD" },
{ "exchangeName": "Kraken", "ticker": "ICPUSD" },
{ "exchangeName": "Kucoin", "ticker": "ICP-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "ICP-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "ICP_USDT", "adjustByMarket": "USDT-USD" }
],
"IMX": [
{ "exchangeName": "Binance", "ticker": "IMXUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "IMX-USD" },
{ "exchangeName": "Kraken", "ticker": "IMXUSD" },
{ "exchangeName": "Kucoin", "ticker": "IMX-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "IMX-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "IMX_USDT", "adjustByMarket": "USDT-USD" }
],
"INJ": [
{ "exchangeName": "Binance", "ticker": "INJUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "INJUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "INJ-USD" },
{ "exchangeName": "Kraken", "ticker": "INJUSD" },
{ "exchangeName": "Kucoin", "ticker": "INJ-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "INJ-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "INJ_USDT", "adjustByMarket": "USDT-USD" }
],
"JTO": [
{ "exchangeName": "Binance", "ticker": "JTOUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "JTOUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "JTO-USD" },
{ "exchangeName": "Kucoin", "ticker": "JTO-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "JTO-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "JTO_USDT", "adjustByMarket": "USDT-USD" }
],
"JUP": [
{ "exchangeName": "Binance", "ticker": "JUPUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "JUPUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "JUP_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "JUP-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "JUP_USDT", "adjustByMarket": "USDT-USD" }
],
"KAVA": [
{ "exchangeName": "Binance", "ticker": "KAVAUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "KAVAUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "KAVA-USD" },
{ "exchangeName": "Gate", "ticker": "KAVA_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "KAVAUSD" },
{ "exchangeName": "Kucoin", "ticker": "KAVA-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "KAVA_USDT", "adjustByMarket": "USDT-USD" }
],
"LDO": [
{ "exchangeName": "Binance", "ticker": "LDOUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "LDOUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "LDO-USD" },
{ "exchangeName": "Kraken", "ticker": "LDOUSD" },
{ "exchangeName": "Kucoin", "ticker": "LDO-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "LDO-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "LDO_USDT", "adjustByMarket": "USDT-USD" }
],
"LINK": [
{ "exchangeName": "Binance", "ticker": "LINKUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bitstamp", "ticker": "LINK/USD" },
{ "exchangeName": "Bybit", "ticker": "LINKUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "LINK-USD" },
{ "exchangeName": "Kraken", "ticker": "LINKUSD" },
{ "exchangeName": "Kucoin", "ticker": "LINK-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "LINK-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "LINK_USDT", "adjustByMarket": "USDT-USD" }
],
"LTC": [
{ "exchangeName": "Binance", "ticker": "LTCUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bitstamp", "ticker": "LTC/USD" },
{ "exchangeName": "Bybit", "ticker": "LTCUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "LTC-USD" },
{ "exchangeName": "Huobi", "ticker": "ltcusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "LTCUSD" },
{ "exchangeName": "Kucoin", "ticker": "LTC-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "LTC-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "LTC_USDT", "adjustByMarket": "USDT-USD" }
],
"MANA": [
{ "exchangeName": "Binance", "ticker": "MANAUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "MANA-USD" },
{ "exchangeName": "Gate", "ticker": "MANA_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "MANAUSD" },
{ "exchangeName": "Kucoin", "ticker": "MANA-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "MANA-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "MANA_USDT", "adjustByMarket": "USDT-USD" }
],
"MASK": [
{ "exchangeName": "Binance", "ticker": "MASKUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "MASKUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "MASK-USD" },
{ "exchangeName": "Gate", "ticker": "MASK_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Huobi", "ticker": "maskusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "MASK-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "MASK-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "MASK_USDT", "adjustByMarket": "USDT-USD" }
],
"MATIC": [
{ "exchangeName": "Binance", "ticker": "MATICUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bitstamp", "ticker": "MATIC/USD" },
{ "exchangeName": "Bybit", "ticker": "MATICUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "MATIC-USD" },
{ "exchangeName": "Huobi", "ticker": "maticusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "MATICUSD" },
{ "exchangeName": "Kucoin", "ticker": "MATIC-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "MATIC-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "MATIC_USDT", "adjustByMarket": "USDT-USD" }
],
"MINA": [
{ "exchangeName": "Binance", "ticker": "MINAUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "MINA-USD" },
{ "exchangeName": "Gate", "ticker": "MINA_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "MINAUSD" },
{ "exchangeName": "Okx", "ticker": "MINA-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "MINA_USDT", "adjustByMarket": "USDT-USD" }
],
"MKR": [
{ "exchangeName": "Binance", "ticker": "MKRUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "MKR-USD" },
{ "exchangeName": "Kraken", "ticker": "MKRUSD" },
{ "exchangeName": "Kucoin", "ticker": "MKR-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "MKR-USDT", "adjustByMarket": "USDT-USD" }
],
"NEAR": [
{ "exchangeName": "Binance", "ticker": "NEARUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "NEARUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "NEAR-USD" },
{ "exchangeName": "Huobi", "ticker": "nearusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "NEARUSD" },
{ "exchangeName": "Kucoin", "ticker": "NEAR-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "NEAR-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "NEAR_USDT", "adjustByMarket": "USDT-USD" }
],
"OP": [
{ "exchangeName": "Binance", "ticker": "OPUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "OPUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "OP-USD" },
{ "exchangeName": "Gate", "ticker": "OP_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "OPUSD" },
{ "exchangeName": "Kucoin", "ticker": "OP-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "OP-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "OP_USDT", "adjustByMarket": "USDT-USD" }
],
"ORDI": [
{ "exchangeName": "Binance", "ticker": "ORDIUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "ORDIUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "ORDI_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Huobi", "ticker": "ordiusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "ORDI-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "ORDI-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "ORDI_USDT", "adjustByMarket": "USDT-USD" }
],
"PEPE": [
{ "exchangeName": "Binance", "ticker": "PEPEUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "PEPEUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "PEPEUSD" },
{ "exchangeName": "Kucoin", "ticker": "PEPE-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "PEPE-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "PEPE_USDT", "adjustByMarket": "USDT-USD" }
],
"PYTH": [
{ "exchangeName": "Binance", "ticker": "PYTHUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "PYTHUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "PYTH_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "PYTH-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "PYTH-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "PYTH_USDT", "adjustByMarket": "USDT-USD" }
],
"RNDR": [
{ "exchangeName": "Binance", "ticker": "RNDRUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "RNDR-USD" },
{ "exchangeName": "Kraken", "ticker": "RNDRUSD" },
{ "exchangeName": "Kucoin", "ticker": "RNDR-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "RNDR-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "RNDR_USDT", "adjustByMarket": "USDT-USD" }
],
"RUNE": [
{ "exchangeName": "Binance", "ticker": "RUNEUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "RUNE_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "RUNEUSD" },
{ "exchangeName": "Kucoin", "ticker": "RUNE-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "RUNE_USDT", "adjustByMarket": "USDT-USD" }
],
"SAND": [
{ "exchangeName": "Binance", "ticker": "SANDUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "SAND-USD" },
{ "exchangeName": "Gate", "ticker": "SAND_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "SAND-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "SAND-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "SAND_USDT", "adjustByMarket": "USDT-USD" }
],
"SEI": [
{ "exchangeName": "Binance", "ticker": "SEIUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "SEIUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "SEI-USD" },
{ "exchangeName": "Huobi", "ticker": "seiusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "SEIUSD" },
{ "exchangeName": "Kucoin", "ticker": "SEI-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "SEI_USDT", "adjustByMarket": "USDT-USD" }
],
"SHIB": [
{ "exchangeName": "Binance", "ticker": "SHIBUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "SHIBUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "SHIB-USD" },
{ "exchangeName": "Huobi", "ticker": "shibusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "SHIBUSD" },
{ "exchangeName": "Kucoin", "ticker": "SHIB-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "SHIB-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "SHIB_USDT", "adjustByMarket": "USDT-USD" }
],
"SNX": [
{ "exchangeName": "Binance", "ticker": "SNXUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "SNXUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "SNX-USD" },
{ "exchangeName": "Kraken", "ticker": "SNXUSD" },
{ "exchangeName": "Kucoin", "ticker": "SNX-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "SNX-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "SNX_USDT", "adjustByMarket": "USDT-USD" }
],
"SOL": [
{ "exchangeName": "Binance", "ticker": "SOLUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bitstamp", "ticker": "SOL/USD" },
{ "exchangeName": "Bybit", "ticker": "SOLUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "SOL-USD" },
{ "exchangeName": "Huobi", "ticker": "solusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "SOLUSD" },
{ "exchangeName": "Kucoin", "ticker": "SOL-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "SOL-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "SOL_USDT", "adjustByMarket": "USDT-USD" }
],
"STRK": [
{ "exchangeName": "Binance", "ticker": "STRKUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "STRKUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "STRKUSD" },
{ "exchangeName": "Kucoin", "ticker": "STRK-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "STRK-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "STRK_USDT", "adjustByMarket": "USDT-USD" }
],
"STX": [
{ "exchangeName": "Binance", "ticker": "STXUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "STXUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "STX-USD" },
{ "exchangeName": "Gate", "ticker": "STX_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "STXUSD" },
{ "exchangeName": "Kucoin", "ticker": "STX-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "STX-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "STX_USDT", "adjustByMarket": "USDT-USD" }
],
"SUI": [
{ "exchangeName": "Binance", "ticker": "SUIUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "SUIUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "SUI-USD" },
{ "exchangeName": "Huobi", "ticker": "suiusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "SUIUSD" },
{ "exchangeName": "Kucoin", "ticker": "SUI-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "SUI-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "SUI_USDT", "adjustByMarket": "USDT-USD" }
],
"TIA": [
{ "exchangeName": "Binance", "ticker": "TIAUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "TIAUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "TIA-USD" },
{ "exchangeName": "Kraken", "ticker": "TIAUSD" },
{ "exchangeName": "Kucoin", "ticker": "TIA-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "TIA-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "TIA_USDT", "adjustByMarket": "USDT-USD" }
],
"TRX": [
{ "exchangeName": "Binance", "ticker": "TRXUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "TRXUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "TRX_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Huobi", "ticker": "trxusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "TRXUSD" },
{ "exchangeName": "Kucoin", "ticker": "TRX-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "TRX-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "TRX_USDT", "adjustByMarket": "USDT-USD" }
],
"UNI": [
{ "exchangeName": "Binance", "ticker": "UNIUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "UNIUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "UNI-USD" },
{ "exchangeName": "Kraken", "ticker": "UNIUSD" },
{ "exchangeName": "Kucoin", "ticker": "UNI-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "UNI-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "UNI_USDT", "adjustByMarket": "USDT-USD" }
],
"WLD": [
{ "exchangeName": "Binance", "ticker": "WLDUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bybit", "ticker": "WLDUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "WLD_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "WLD-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "WLD-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "WLD_USDT", "adjustByMarket": "USDT-USD" }
],
"WOO": [
{ "exchangeName": "Binance", "ticker": "WOOUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Gate", "ticker": "WOO_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "WOO-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "WOO-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "WOO_USDT", "adjustByMarket": "USDT-USD" }
],
"XLM": [
{ "exchangeName": "Binance", "ticker": "XLMUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bitstamp", "ticker": "XLM/USD" },
{ "exchangeName": "Bybit", "ticker": "XLMUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "XLM-USD" },
{ "exchangeName": "Kraken", "ticker": "XLMUSD" },
{ "exchangeName": "Kucoin", "ticker": "XLM-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "XLM-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "XLM_USDT", "adjustByMarket": "USDT-USD" }
],
"XRP": [
{ "exchangeName": "Binance", "ticker": "XRPUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Bitstamp", "ticker": "XRP/USD" },
{ "exchangeName": "Bybit", "ticker": "XRPUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "XRP-USD" },
{ "exchangeName": "Huobi", "ticker": "xrpusdt", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kraken", "ticker": "XRPUSD" },
{ "exchangeName": "Kucoin", "ticker": "XRP-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "XRP-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "XRP_USDT", "adjustByMarket": "USDT-USD" }
],
"ZETA": [
{ "exchangeName": "Bybit", "ticker": "ZETAUSDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "CoinbasePro", "ticker": "ZETA-USD" },
{ "exchangeName": "Gate", "ticker": "ZETA_USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Kucoin", "ticker": "ZETA-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Okx", "ticker": "ZETA-USDT", "adjustByMarket": "USDT-USD" },
{ "exchangeName": "Mexc", "ticker": "ZETA_USDT", "adjustByMarket": "USDT-USD" }
]
}

File diff suppressed because it is too large Load Diff

656
public/configs/v1/env.json Normal file
View File

@ -0,0 +1,656 @@
{
"apps": {
"ios": {
"scheme": "dydx-t-v4"
}
},
"tokens": {
"dydxprotocol-testnet": {
"chain": {
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
"dydx-testnet-4": {
"chain": {
"name": "Dv4TNT",
"denom": "adv4tnt",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
},
"[mainnet chain id]": {
"comment": "Change according to mainnet release",
"chain": {
"name": "TokenName",
"denom": "tokenDenom",
"decimals": 18,
"image": "/currencies/dydx.png"
},
"usdc": {
"name": "USDC",
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
"gasDenom": "uusdc",
"decimals": 6,
"image": "/currencies/usdc.png"
}
}
},
"links": {
"dydxprotocol-testnet": {
"tos": "https://dydx.exchange/v4-terms",
"privacy": "https://dydx.exchange/privacy",
"statusPage": "https://status.v4testnet.dydx.exchange/",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"launchIncentive": "https://cloud.chaoslabs.co"
},
"dydx-testnet-4": {
"tos": "https://dydx.exchange/v4-terms",
"privacy": "https://dydx.exchange/privacy",
"statusPage": "https://status.v4testnet.dydx.exchange/",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
"launchIncentive": "https://cloud.chaoslabs.co"
},
"[mainnet chain id]": {
"tos": "[HTTP link to TOS]",
"privacy": "[HTTP link to Privacy Policy]",
"statusPage": "[HTTP link to status page]",
"mintscan": "[HTTP link to Mintscan, with {tx_hash} placeholder]",
"mintscanBase": "[HTTP link to TOS mintscan base url]",
"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]",
"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]",
"help": "[HTTP link to help page, can be null]",
"governanceLearnMore": "[HTTP link to governance learn more, can be null]",
"newMarketProposalLearnMore": "[HTTP link to new market proposal learn more, can be null]",
"stakingLearnMore": "[HTTP link to staking learn more, can be null]",
"keplrDashboard": "[HTTP link to keplr dashboard, can be null]",
"strideZoneApp": "[HTTP link to stride zone app, can be null]",
"accountExportLearnMore": "[HTTP link to account export learn more, can be null]",
"walletLearnMore": "[HTTP link to wallet learn more, can be null]",
"launchIncentive": "[HTTP link to launch incentive host, can be null]"
}
},
"wallets": {
"dydxprotocol-testnet": {
"walletconnect": {
"client": {
"name": "dYdX v4",
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
},
"walletSegue": {
"callbackUrl": "/walletsegue"
},
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain"
},
"dydx-testnet-4": {
"walletconnect": {
"client": {
"name": "dYdX v4",
"description": "dYdX v4 App",
"iconUrl": "/logos/dydx-x.png"
},
"v2": {
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
}
},
"walletSegue": {
"callbackUrl": "/walletsegue"
},
"images": "/wallets/",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain"
},
"[mainnet chain id]": {
"walletconnect": {
"client": {
"name": "[Name of the app]",
"description": "[Description of the app]",
"iconUrl": "[Relative URL of the icon URL]"
},
"v2": {
"projectId": "[Project ID]"
}
},
"walletSegue": {
"callbackUrl": "[Relative callback URL for WalletSegue, should match apple-app-site-association]"
},
"images": "[Relative URL for wallet images]",
"signTypedDataAction": "dYdX Chain Onboarding",
"signTypedDataDomainName": "dYdX Chain"
}
},
"governance": {
"dydxprotocol-testnet": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"dydx-testnet-4": {
"newMarketProposal": {
"initialDepositAmount": 10000000,
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"[mainnet chain id]": {
"newMarketProposal": {
"initialDepositAmount": 0,
"delayBlocks": 0,
"newMarketsMethodology": "[URL to spreadsheet or document that explains methodology]"
}
}
},
"deployments": {
"MAINNET": {
"environments": [
"dydxprotocol-mainnet"
],
"default": "dydxprotocol-mainnet"
},
"TESTFLIGHT": {
"environments": [
"dydxprotocol-mainnet",
"dydxprotocol-testnet"
],
"default": "dydxprotocol-mainnet"
},
"TESTNET": {
"environments": [
"dydxprotocol-testnet"
],
"default": "dydxprotocol-testnet"
},
"DEV": {
"environments": [
"dydxprotocol-dev",
"dydxprotocol-dev-2",
"dydxprotocol-dev-4",
"dydxprotocol-dev-5",
"dydxprotocol-staging",
"dydxprotocol-staging-west",
"dydxprotocol-testnet",
"dydxprotocol-testnet-dydx",
"dydxprotocol-testnet-nodefleet",
"dydxprotocol-testnet-kingnodes",
"dydxprotocol-testnet-liquify",
"dydxprotocol-testnet-polkachu",
"dydxprotocol-testnet-bware"
],
"default": "dydxprotocol-testnet"
}
},
"environments": {
"dydxprotocol-dev": {
"name": "v4 Dev",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4dev.dydx.exchange",
"socket": "wss://indexer.v4dev.dydx.exchange"
}
],
"validators": [
"https://validator.v4dev.dydx.exchange"
],
"0xsquid": "https://testnet.api.0xsquid.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4dev.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": false
}
},
"dydxprotocol-dev-2": {
"name": "v4 Dev 2",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "http://dev2-indexer-apne1-lb-public-2076363889.ap-northeast-1.elb.amazonaws.com",
"socket": "ws://dev2-indexer-apne1-lb-public-2076363889.ap-northeast-1.elb.amazonaws.com"
}
],
"validators": [
"http://54.92.118.111"
],
"0xsquid": "https://testnet.api.0xsquid.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": false
}
},
"dydxprotocol-dev-4": {
"name": "v4 Dev 4",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4dev4.dydx.exchange",
"socket": "wss://indexer.v4dev4.dydx.exchange"
}
],
"validators": [
"https://validator.v4dev4.dydx.exchange"
],
"0xsquid": "https://testnet.api.0xsquid.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4dev4.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": false
}
},
"dydxprotocol-dev-5": {
"name": "v4 Dev 5",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "http://dev5-indexer-apne1-lb-public-1721328151.ap-northeast-1.elb.amazonaws.com",
"socket": "ws://dev5-indexer-apne1-lb-public-1721328151.ap-northeast-1.elb.amazonaws.com"
}
],
"validators": [
"http://18.223.78.50"
],
"0xsquid": "https://testnet.api.0xsquid.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": false
}
},
"dydxprotocol-staging": {
"name": "v4 Staging",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4staging.dydx.exchange",
"socket": "wss://indexer.v4staging.dydx.exchange"
}
],
"faucet": "https://faucet.v4staging.dydx.exchange",
"validators": [
"https://validator.v4staging.dydx.exchange"
],
"0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": false
}
},
"dydxprotocol-staging-forced-update": {
"name": "v4 Staging Forced Update",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4staging.dydx.exchange",
"socket": "wss://indexer.v4staging.dydx.exchange"
}
],
"faucet": "https://faucet.v4staging.dydx.exchange",
"validators": [
"https://validator.v4staging.dydx.exchange"
],
"0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
},
"apps": {
"ios": {
"minimalVersion": "1.0",
"build": 40000,
"url": "https://apps.apple.com/app/dydx/id1564787350"
}
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": false
}
},
"dydxprotocol-staging-west": {
"name": "v4 Staging West",
"ethereumChainId": "11155111",
"dydxChainId": "dydxprotocol-testnet",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4staging.dydx.exchange",
"socket": "wss://indexer.v4staging.dydx.exchange"
}
],
"faucet": "https://faucet.v4staging.dydx.exchange",
"validators": [
"https://validator-uswest1.v4staging.dydx.exchange"
],
"0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": false
}
},
"dydxprotocol-testnet": {
"name": "v4 Public Testnet",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
"https://dydx-testnet-full-rpc.public.blastapi.io/",
"https://dydx-testnet-rpc.polkachu.com/",
"https://dydx-testnet.nodefleet.org",
"https://test-dydx.kingnodes.com",
"https://dydx-rpc.liquify.com/api=8878132/dydx"
],
"0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": true
}
},
"dydxprotocol-testnet-dydx": {
"name": "v4 Public Testnet/dYdX",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
"https://validator.v4testnet.dydx.exchange"
],
"0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": true
}
},
"dydxprotocol-testnet-nodefleet": {
"name": "v4 Public Testnet/nodefleet",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
"https://dydx-testnet.nodefleet.org"
],
"0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": true
}
},
"dydxprotocol-testnet-kingnodes": {
"name": "v4 Public Testnet/KingNodes",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
"https://test-dydx.kingnodes.com"
],
"0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": true
}
},
"dydxprotocol-testnet-liquify": {
"name": "v4 Public Testnet/Liquify",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
"https://dydx-rpc.liquify.com/api=8878132/dydx"
],
"0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": true
}
},
"dydxprotocol-testnet-polkachu": {
"name": "v4 Public Testnet/Polkahcu",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
"https://dydx-testnet-rpc.polkachu.com/"
],
"0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": true
}
},
"dydxprotocol-testnet-bware": {
"name": "v4 Public Testnet/BWare",
"ethereumChainId": "11155111",
"dydxChainId": "dydx-testnet-4",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "dYdX-api",
"isMainNet": false,
"endpoints": {
"indexers": [
{
"api": "https://indexer.v4testnet.dydx.exchange",
"socket": "wss://indexer.v4testnet.dydx.exchange"
}
],
"validators": [
"https://dydx-testnet-full-rpc.public.blastapi.io/"
],
"0xsquid": "https://testnet.api.squidrouter.com",
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
"faucet": "https://faucet.v4testnet.dydx.exchange"
},
"featureFlags": {
"reduceOnlySupported": true,
"usePessimisticCollateralCheck": true
}
},
"dydxprotocol-mainnet": {
"name": "v4",
"ethereumChainId": "1",
"dydxChainId": "[mainnet chain id]",
"chainName": "dYdX Chain",
"chainLogo": "/dydx-chain.png",
"squidIntegratorId": "[mainnet squid integrator id]",
"isMainNet": true,
"endpoints": {
"indexers": [
{
"api": "[REST endpoint]",
"socket": "[Websocket endpoint]"
}
],
"validators": [
"[Validator endpoint 1",
"[Validator endpoint n]"
],
"0xsquid": "[0xSquid endpoint for mainnet]",
"nobleValidator": "[noble validator endpoint for mainnet]"
},
"featureFlags": {
"reduceOnlySupported": false,
"usePessimisticCollateralCheck": true
}
}
}
}

View File

@ -40,6 +40,7 @@
"iosMinVersion": "0", "iosMinVersion": "0",
"imageUrl": "", "imageUrl": "",
"encoding": "=\"#%/<>?@\\^`{|}:&", "encoding": "=\"#%/<>?@\\^`{|}:&",
"androidPackage": "io.metamask",
"connections": [ "connections": [
{ {
"type": "walletConnectV2", "type": "walletConnectV2",
@ -98,6 +99,7 @@
"iosMinVersion": "1.8.0", "iosMinVersion": "1.8.0",
"imageUrl": "", "imageUrl": "",
"encoding": "=\"#%/<>?@\\^`{|}:&", "encoding": "=\"#%/<>?@\\^`{|}:&",
"androidPackage": "org.toshi",
"connections": [ "connections": [
{ {
"type": "walletSegue", "type": "walletSegue",
@ -155,6 +157,7 @@
"comment": "imToken", "comment": "imToken",
"iosMinVersion": "0", "iosMinVersion": "0",
"imageUrl": "", "imageUrl": "",
"androidPackage": "im.token.app",
"connections": [ "connections": [
{ {
"type": "walletConnectV2", "type": "walletConnectV2",
@ -196,7 +199,7 @@
}, },
"mobile": { "mobile": {
"native": "trust:", "native": "trust:",
"universal": "https://link.trustwallet.com" "universal": ""
}, },
"desktop": { "desktop": {
"native": "", "native": "",
@ -214,6 +217,7 @@
"iosMinVersion": "0", "iosMinVersion": "0",
"encoding": "=\"#%/<>?@\\^`{|}:&", "encoding": "=\"#%/<>?@\\^`{|}:&",
"imageUrl": "", "imageUrl": "",
"androidPackage": "com.wallet.crypto.trustapp",
"connections": [ "connections": [
{ {
"type": "walletConnectV2", "type": "walletConnectV2",
@ -271,6 +275,7 @@
"iosMinVersion": "0", "iosMinVersion": "0",
"encoding": "=\"#%/<>?@\\^`{|}:&", "encoding": "=\"#%/<>?@\\^`{|}:&",
"imageUrl": "", "imageUrl": "",
"androidPackage": "io.zerion.android",
"connections": [ "connections": [
{ {
"type": "walletConnectV2", "type": "walletConnectV2",
@ -327,6 +332,7 @@
"comment": "TokenPocket", "comment": "TokenPocket",
"iosMinVersion": "0", "iosMinVersion": "0",
"imageUrl": "", "imageUrl": "",
"androidPackage": "vip.mytokenpocket",
"connections": [ "connections": [
{ {
"type": "walletConnectV2", "type": "walletConnectV2",
@ -383,6 +389,7 @@
"comment": "Rainbow", "comment": "Rainbow",
"iosMinVersion": "0", "iosMinVersion": "0",
"encoding": "=\"#%/<>?@\\^`{|}:&", "encoding": "=\"#%/<>?@\\^`{|}:&",
"androidPackage": "me.rainbow",
"backlinked": true, "backlinked": true,
"imageUrl": "", "imageUrl": "",
"connections": [ "connections": [
@ -442,6 +449,7 @@
"comment": "1inch", "comment": "1inch",
"iosMinVersion": "0", "iosMinVersion": "0",
"encoding": "=\"#%/<>?@\\^`{|}:&", "encoding": "=\"#%/<>?@\\^`{|}:&",
"androidPackage": "io.oneinch.android",
"imageUrl": "", "imageUrl": "",
"connections": [ "connections": [
{ {

BIN
public/currencies/agix.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
public/currencies/bnb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
public/currencies/bonk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

BIN
public/currencies/chz.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
public/currencies/dym.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
public/currencies/ens.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
public/currencies/fet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

BIN
public/currencies/ftm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

BIN
public/currencies/gala.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
public/currencies/gmt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

BIN
public/currencies/grt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
public/currencies/hbar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
public/currencies/imx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
public/currencies/inj.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

BIN
public/currencies/jto.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
public/currencies/jup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
public/currencies/kava.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
public/currencies/mana.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
public/currencies/mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
public/currencies/mina.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
public/currencies/ordi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
public/currencies/pyth.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
public/currencies/rndr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

BIN
public/currencies/sand.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
public/currencies/strk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
public/currencies/stx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
public/currencies/tia.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
public/currencies/woo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
public/currencies/zeta.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

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

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 300 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

File diff suppressed because one or more lines are too long

1
public/rewards-stars.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 481 KiB

15
public/smartbanner.html Normal file
View File

@ -0,0 +1,15 @@
<!-- Smartbanner: Configure the mobile app -->
<meta name="smartbanner:title" content="SMARTBANNER_APP_NAME">
<meta name="smartbanner:author" content="SMARTBANNER_ORG_NAME">
<meta name="smartbanner:icon-apple" content="SMARTBANNER_ICON_URL">
<meta name="smartbanner:icon-google" content="SMARTBANNER_ICON_URL">
<!-- Smartbanner: The rest of the configurations can be kept as is -->
<meta name="smartbanner:price" content="FREE">
<meta name="smartbanner:price-suffix-apple" content=" - On the App Store">
<meta name="smartbanner:price-suffix-google" content=" - In Google Play">
<meta name="smartbanner:button" content="VIEW">
<meta name="smartbanner:close-label" content="Close">
<meta name="smartbanner:exclude-user-agent-regex" content="^.*(Windows NT|Intel Mac OS X).*$">
<script src="https://cdn.jsdelivr.net/npm/smartbanner.js@1.22.0/dist/smartbanner.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/smartbanner.js@1.22.0/dist/smartbanner.min.css" rel="stylesheet">
<!-- Smartbanner: End configuration -->

BIN
public/third-party/keplr.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
public/third-party/stride.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 817 B

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

52
scripts/README.md Normal file
View File

@ -0,0 +1,52 @@
## App Integrations
### Amplitude
Analytics service used to collect data to help the dYdX Product team make informed product decisions.
<b>To use with dydxprotocol/v4-web:</b>
1. Amplitude account with API key.
2. Add API key in Github > Secrets and Variables > Actions as `AMPLITUDE_API_KEY`
3. In your deploy scripts add `pnpm run build:inject-amplitude` after your pnpm build / vite build command.
### Bugsnag
Error handling service used to collect handled/unhandled errors within the app. The information collected is used to help debug and alert the engineering team of crashes/unhandled errors within the app to improve stability.
<b>To use with dydxprotocol/v4-web:</b>
1. Bugsnag account with API key.
2. Add API key in Github > Secrets and Variables > Actions as `BUGSNAG_API_KEY`
3. In your deploy scripts add `pnpm run build:inject-bugsnag` after your pnpm build / vite build command.
4. If you are using with the Amplitude deployment scripts, your build command may look like the following: `pnpm build && pnpm run build:inject-amplitude && pnpm run build:inject-bugsnag`
### StatusPage
Service used to inform users of any status updates to our platform. These status updates are manually set and updated by the On Call engineers.
<b>To use with dydxprotocol/v4-web:</b>
1. StatusPage account and script URI
2. Add API key in Github > Secrets and Variables > Actions as `STATUS_PAGE_SCRIPT_URI`
3. In your deploy scripts add `pnpm run build:inject-statuspage` after your pnpm build / vite build command.
4. If you are using with the Amplitude deployment scripts, your build command may look like the following: `pnpm build && pnpm run build:inject-amplitude && pnpm run build:inject-statuspage`
### Intercom
Service used for live customer support (chat/inbox) as well as home for Help Articles.
<b>To use with dydxprotocol/v4-web:</b>
1. Create Intercom account
2. In Intercom UI
Getting started > Set up Messenger > will give you your API Key on Step 2
Customize Intercom Messenger by adding logo and brand colors
3. Add API key in Github > Secrets and Variables > Actions as `INTERCOM_APP_ID`
4. In your deploy scripts add `pnpm run build:inject-intercom` after your pnpm build / vite build command.
5. If you are using with the Amplitude deployment scripts, your build command may look like the following: `pnpm build && pnpm run build:inject-amplitude && pnpm run build:inject-intercom`
### Smartbanner
Smartbanner to show download links to iOS and/or Android native apps on mobile devices.
<b>To use with dydxprotocol/v4-web:</b>
1. iOS app App Store link or Android app Google Play link.
2. Add configurations in Github > Secrets and Variables > Actions as
`SMARTBANNER_APP_NAME` for app name
`SMARTBANNER_ORG_NAME` for organization name
`SMARTBANNER_ICON_URL` for icon image
`SMARTBANNER_APPSTORE_URL` for iOS App Store link
`SMARTBANNER_GOOGLEPLAY_URL` for Android Google Play link
3. In your deploy scripts add `pnpm run build:inject-smartbanner` after your pnpm build / vite build command.
4. If you are using with the Amplitude deployment scripts, your build command may look like the following: `pnpm build && pnpm run build:inject-smartbanner`

View File

@ -3,23 +3,50 @@ import path from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
const AMPLITUDE_API_KEY = process.env.AMPLITUDE_API_KEY; const AMPLITUDE_API_KEY = process.env.AMPLITUDE_API_KEY;
const AMPLITUDE_SERVER_URL = process.env.AMPLITUDE_SERVER_URL;
const currentPath = fileURLToPath(import.meta.url); const currentPath = fileURLToPath(import.meta.url);
const projectRoot = path.dirname(currentPath); const projectRoot = path.dirname(currentPath);
const htmlFilePath = path.resolve(projectRoot, '../dist/index.html'); const htmlFilePath = path.resolve(projectRoot, '../dist/index.html');
if(AMPLITUDE_API_KEY){ if (AMPLITUDE_API_KEY) {
try { try {
const html = await fs.readFile(htmlFilePath, 'utf-8'); const html = await fs.readFile(htmlFilePath, 'utf-8');
const amplitudeCdnScript = `<script type="text/javascript"> const amplitudeCdnScript = `<script type="text/javascript">
!function(){"use strict";!function(e,t){var n=e.amplitude||{_q:[],_iq:{}};if(n.invoked)e.console&&console.error&&console.error("Amplitude snippet has been loaded.");else{var r=function(e,t){e.prototype[t]=function(){return this._q.push({name:t,args:Array.prototype.slice.call(arguments,0)}),this}},s=function(e,t,n){return function(r){e._q.push({name:t,args:Array.prototype.slice.call(n,0),resolve:r})}},o=function(e,t,n){e[t]=function(){if(n)return{promise:new Promise(s(e,t,Array.prototype.slice.call(arguments)))}}},i=function(e){for(var t=0;t<m.length;t++)o(e,m[t],!1);for(var n=0;n<g.length;n++)o(e,g[n],!0)};n.invoked=!0;var u=t.createElement("script");u.type="text/javascript",u.integrity="sha384-x0ik2D45ZDEEEpYpEuDpmj05fY91P7EOZkgdKmq4dKL/ZAVcufJ+nULFtGn0HIZE",u.crossOrigin="anonymous",u.async=!0,u.src="https://cdn.amplitude.com/libs/analytics-browser-2.0.0-min.js.gz",u.onload=function(){e.amplitude.runQueuedFunctions||console.log("[Amplitude] Error: could not load SDK")};var a=t.getElementsByTagName("script")[0];a.parentNode.insertBefore(u,a);for(var c=function(){return this._q=[],this},p=["add","append","clearAll","prepend","set","setOnce","unset","preInsert","postInsert","remove","getUserProperties"],l=0;l<p.length;l++)r(c,p[l]);n.Identify=c;for(var d=function(){return this._q=[],this},f=["getEventProperties","setProductId","setQuantity","setPrice","setRevenue","setRevenueType","setEventProperties"],v=0;v<f.length;v++)r(d,f[v]);n.Revenue=d;var m=["getDeviceId","setDeviceId","getSessionId","setSessionId","getUserId","setUserId","setOptOut","setTransport","reset","extendSession"],g=["init","add","remove","track","logEvent","identify","groupIdentify","setGroup","revenue","flush"];i(n),n.createInstance=function(e){return n._iq[e]={_q:[]},i(n._iq[e]),n._iq[e]},e.amplitude=n}}(window,document)}(); !function(){"use strict";!function(e,t){var n=e.amplitude||{_q:[],_iq:{}};if(n.invoked)e.console&&console.error&&console.error("Amplitude snippet has been loaded.");else{var r=function(e,t){e.prototype[t]=function(){return this._q.push({name:t,args:Array.prototype.slice.call(arguments,0)}),this}},s=function(e,t,n){return function(r){e._q.push({name:t,args:Array.prototype.slice.call(n,0),resolve:r})}},o=function(e,t,n){e[t]=function(){if(n)return{promise:new Promise(s(e,t,Array.prototype.slice.call(arguments)))}}},i=function(e){for(var t=0;t<m.length;t++)o(e,m[t],!1);for(var n=0;n<g.length;n++)o(e,g[n],!0)};n.invoked=!0;var u=t.createElement("script");u.type="text/javascript",u.integrity="sha384-BVo5ZjsjH373rWbcjz9Qjb2L6BgLwLADcZtZZPu3nMl8+7LPDhi1NcUEf0Ate41Y",u.crossOrigin="anonymous",u.async=!0,u.src="/libs/amplitude-analytics-browser-2.0.0-min.js",u.onload=function(){e.amplitude.runQueuedFunctions||console.log("[Amplitude] Error: could not load SDK")};var a=t.getElementsByTagName("script")[0];a.parentNode.insertBefore(u,a);for(var c=function(){return this._q=[],this},p=["add","append","clearAll","prepend","set","setOnce","unset","preInsert","postInsert","remove","getUserProperties"],l=0;l<p.length;l++)r(c,p[l]);n.Identify=c;for(var d=function(){return this._q=[],this},f=["getEventProperties","setProductId","setQuantity","setPrice","setRevenue","setRevenueType","setEventProperties"],v=0;v<f.length;v++)r(d,f[v]);n.Revenue=d;var m=["getDeviceId","setDeviceId","getSessionId","setSessionId","getUserId","setUserId","setOptOut","setTransport","reset","extendSession"],g=["init","add","remove","track","logEvent","identify","groupIdentify","setGroup","revenue","flush"];i(n),n.createInstance=function(e){return n._iq[e]={_q:[]},i(n._iq[e]),n._iq[e]},e.amplitude=n}}(window,document)}();
</script> </script>
`; `;
const amplitudeListenerScript = `<script type="module"> const amplitudeListenerScript = `<script type="module">
!function(){var e="${AMPLITUDE_API_KEY}";e&&(globalThis.amplitude.init(e),globalThis.amplitude.setOptOut(!1),globalThis.addEventListener("dydx:track",function(e){var t=e.detail.eventType,d=e.detail.eventData;globalThis.amplitude.track(t,d)}),globalThis.addEventListener("dydx:identify",function(e){var t=e.detail.property,d=e.detail.propertyValue;if("walletAddress"===t)globalThis.amplitude.setUserId(d);else{var i=new globalThis.amplitude.Identify;i.set(t,d),globalThis.amplitude.identify(i)}}),console.log("Amplitude enabled."))}(); !(function () {
</script>`; var e = "${AMPLITUDE_API_KEY}";
e &&
(globalThis.amplitude.init(e${
AMPLITUDE_SERVER_URL
? `, undefined, {
serverUrl: "${AMPLITUDE_SERVER_URL}"
}`
: ''
}),
globalThis.amplitude.setOptOut(!1),
globalThis.addEventListener("dydx:track", function (e) {
var t = e.detail.eventType,
d = e.detail.eventData;
globalThis.amplitude.track(t, d);
}),
globalThis.addEventListener("dydx:identify", function (e) {
var t = e.detail.property,
d = e.detail.propertyValue;
if ("walletAddress" === t) globalThis.amplitude.setUserId(d);
else {
var i = new globalThis.amplitude.Identify();
i.set(t, d), globalThis.amplitude.identify(i);
}
}),
console.log("Amplitude enabled."));
})();
</script>`;
const injectedHtml = html.replace( const injectedHtml = html.replace(
'<div id="root"></div>', '<div id="root"></div>',

View File

@ -0,0 +1,60 @@
/* eslint-disable no-console */
import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';
const SMARTBANNER_APP_NAME = process.env.SMARTBANNER_APP_NAME;
const SMARTBANNER_ORG_NAME = process.env.SMARTBANNER_ORG_NAME;
const SMARTBANNER_ICON_URL = process.env.SMARTBANNER_ICON_URL;
const SMARTBANNER_APPSTORE_URL = process.env.SMARTBANNER_APPSTORE_URL;
const SMARTBANNER_GOOGLEPLAY_URL = process.env.SMARTBANNER_GOOGLEPLAY_URL;
const currentPath = fileURLToPath(import.meta.url);
const projectRoot = path.dirname(currentPath);
const htmlFilePath = path.resolve(projectRoot, '../dist/index.html');
const smartbannerFilePath = path.resolve(projectRoot, '../dist/smartbanner.html');
if (
SMARTBANNER_APP_NAME &&
SMARTBANNER_ORG_NAME &&
SMARTBANNER_ICON_URL &&
(SMARTBANNER_APPSTORE_URL || SMARTBANNER_GOOGLEPLAY_URL)
) {
try {
const html = await fs.readFile(htmlFilePath, 'utf-8');
let smartbanner = await fs.readFile(smartbannerFilePath, 'utf-8');
smartbanner = smartbanner
.replace('SMARTBANNER_APP_NAME', SMARTBANNER_APP_NAME)
.replace('SMARTBANNER_ORG_NAME', SMARTBANNER_ORG_NAME)
.replace('SMARTBANNER_ICON_URL', SMARTBANNER_ICON_URL)
.replace('SMARTBANNER_ICON_URL', SMARTBANNER_ICON_URL);
/* hardcoded injection depending on whether the app is available on App Store and/or Google Play */
if (SMARTBANNER_APPSTORE_URL) {
smartbanner = `\t<meta name="smartbanner:button-url-apple" content="${SMARTBANNER_APPSTORE_URL}">\n` + smartbanner;
}
if (SMARTBANNER_GOOGLEPLAY_URL) {
smartbanner = `\t<meta name="smartbanner:button-url-google" content="${SMARTBANNER_GOOGLEPLAY_URL}">\n` + smartbanner;
}
if (SMARTBANNER_APPSTORE_URL) {
if (SMARTBANNER_GOOGLEPLAY_URL) {
smartbanner = `\t<meta name="smartbanner:enabled-platforms" content="android,ios">\n` + smartbanner;
} else {
smartbanner = `\t<meta name="smartbanner:enabled-platforms" content="ios">\n` + smartbanner;
}
} else {
if (SMARTBANNER_GOOGLEPLAY_URL) {
smartbanner = `\t<meta name="smartbanner:enabled-platforms" content="android">\n` + smartbanner;
}
}
const injectedHtml = html.replace('</head>', `${smartbanner}\n</head>`);
await fs.writeFile(htmlFilePath, injectedHtml, 'utf-8');
console.log('Smartbanner scripts successfully injected.');
} catch (err) {
console.error('Error injecting Smartbanner scripts:', err);
}
}

View File

@ -1,11 +1,11 @@
import { Suspense } from 'react'; import { lazy, Suspense, useMemo } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom'; import { Navigate, Route, Routes, useLocation } from 'react-router-dom';
import styled, { AnyStyledComponent, css } from 'styled-components'; import styled, { AnyStyledComponent, css } from 'styled-components';
import { WagmiConfig } from 'wagmi'; import { WagmiConfig } from 'wagmi';
import { QueryClient, QueryClientProvider } from 'react-query'; import { QueryClient, QueryClientProvider } from 'react-query';
import { GrazProvider } from 'graz'; import { GrazProvider } from 'graz';
import { AppRoute, DEFAULT_TRADE_ROUTE } from '@/constants/routes'; import { AppRoute, DEFAULT_TRADE_ROUTE, MarketsRoute } from '@/constants/routes';
import { import {
useBreakpoints, useBreakpoints,
@ -16,25 +16,17 @@ import {
} from '@/hooks'; } from '@/hooks';
import { DydxProvider } from '@/hooks/useDydxClient'; import { DydxProvider } from '@/hooks/useDydxClient';
import { AccountsProvider } from '@/hooks/useAccounts'; import { AccountsProvider } from '@/hooks/useAccounts';
import { AppThemeAndColorModeProvider } from '@/hooks/useAppThemeAndColorMode';
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea'; import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
import { LocaleProvider } from '@/hooks/useLocaleSeparators'; import { LocaleProvider } from '@/hooks/useLocaleSeparators';
import { NotificationsProvider } from '@/hooks/useNotifications'; import { NotificationsProvider } from '@/hooks/useNotifications';
import { LocalNotificationsProvider } from '@/hooks/useLocalNotifications'; import { LocalNotificationsProvider } from '@/hooks/useLocalNotifications';
import { PotentialMarketsProvider } from '@/hooks/usePotentialMarkets';
import { RestrictionProvider } from '@/hooks/useRestrictions'; import { RestrictionProvider } from '@/hooks/useRestrictions';
import { SubaccountProvider } from '@/hooks/useSubaccount'; import { SubaccountProvider } from '@/hooks/useSubaccount';
import { SquidProvider } from '@/hooks/useSquid';
import { GuardedMobileRoute } from '@/components/GuardedMobileRoute'; import { GuardedMobileRoute } from '@/components/GuardedMobileRoute';
import { LoadingSpace } from '@/components/Loading/LoadingSpinner';
import MarketsPage from '@/pages/markets/Markets';
import PortfolioPage from '@/pages/portfolio/Portfolio';
import { AlertsPage } from '@/pages/AlertsPage';
import ProfilePage from '@/pages/Profile';
import { SettingsPage } from '@/pages/settings/Settings';
import TradePage from '@/pages/trade/Trade';
import { RewardsPage } from '@/pages/rewards/RewardsPage';
import { TermsOfUsePage } from '@/pages/TermsOfUsePage';
import { PrivacyPolicyPage } from '@/pages/PrivacyPolicyPage';
import { HeaderDesktop } from '@/layout/Header/HeaderDesktop'; import { HeaderDesktop } from '@/layout/Header/HeaderDesktop';
import { FooterDesktop } from '@/layout/Footer/FooterDesktop'; import { FooterDesktop } from '@/layout/Footer/FooterDesktop';
@ -43,15 +35,28 @@ import { NotificationsToastArea } from '@/layout/NotificationsToastArea';
import { DialogManager } from '@/layout/DialogManager'; import { DialogManager } from '@/layout/DialogManager';
import { GlobalCommandDialog } from '@/views/dialogs/GlobalCommandDialog'; import { GlobalCommandDialog } from '@/views/dialogs/GlobalCommandDialog';
import { parseLocationHash } from '@/lib/urlUtils';
import { config } from '@/lib/wagmi'; import { config } from '@/lib/wagmi';
import { breakpoints } from '@/styles'; import { breakpoints } from '@/styles';
import { GlobalStyle } from '@/styles/globalStyle';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
import '@/styles/constants.css'; import '@/styles/constants.css';
import '@/styles/fonts.css'; import '@/styles/fonts.css';
import '@/styles/web3modal.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'));
const ProfilePage = lazy(() => import('@/pages/Profile'));
const SettingsPage = lazy(() => import('@/pages/settings/Settings'));
const TradePage = lazy(() => import('@/pages/trade/Trade'));
const TermsOfUsePage = lazy(() => import('@/pages/TermsOfUsePage'));
const PrivacyPolicyPage = lazy(() => import('@/pages/PrivacyPolicyPage'));
const TokenPage = lazy(() => import('@/pages/token/Token'));
const queryClient = new QueryClient(); const queryClient = new QueryClient();
const Content = () => { const Content = () => {
@ -64,51 +69,67 @@ const Content = () => {
const isShowingHeader = isNotTablet; const isShowingHeader = isNotTablet;
const isShowingFooter = useShouldShowFooter(); const isShowingFooter = useShouldShowFooter();
const { chainTokenLabel } = useTokenConfigs(); const { chainTokenLabel } = useTokenConfigs();
const location = useLocation();
const pathFromHash = useMemo(() => {
if (location.hash === '') {
return '';
}
return parseLocationHash(location.hash);
}, [location.hash]);
return ( return (
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}> <>
{isNotTablet && <HeaderDesktop />} <GlobalStyle />
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
{isNotTablet && <HeaderDesktop />}
<Styled.Main> <Styled.Main>
<Suspense fallback={null}> <Suspense fallback={<LoadingSpace id="main" />}>
<Routes> <Routes>
<Route path={AppRoute.Trade}> <Route path={AppRoute.Trade}>
<Route path=":market" element={<TradePage />} /> <Route path=":market" element={<TradePage />} />
<Route path={AppRoute.Trade} element={<TradePage />} /> <Route path={AppRoute.Trade} element={<TradePage />} />
</Route> </Route>
<Route path={AppRoute.Markets} element={<MarketsPage />} /> <Route path={AppRoute.Markets}>
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} /> <Route path={MarketsRoute.New} element={<NewMarket />} />
{isTablet && ( <Route path={AppRoute.Markets} element={<MarketsPage />} />
<> </Route>
<Route path={AppRoute.Alerts} element={<AlertsPage />} /> <Route path={`/${chainTokenLabel}/*`} element={<TokenPage />} />
<Route path={AppRoute.Profile} element={<ProfilePage />} /> {isTablet && (
<Route path={`${AppRoute.Settings}/*`} element={<SettingsPage />} /> <>
</> <Route path={AppRoute.Alerts} element={<AlertsPage />} />
)} <Route path={AppRoute.Profile} element={<ProfilePage />} />
<Route path={`${AppRoute.Settings}/*`} element={<SettingsPage />} />
</>
)}
<Route element={<GuardedMobileRoute />}> <Route element={<GuardedMobileRoute />}>
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} /> <Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
</Route> </Route>
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} /> <Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} /> <Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
<Route
path="*"
element={<Navigate to={pathFromHash || DEFAULT_TRADE_ROUTE} replace />}
/>
</Routes>
</Suspense>
</Styled.Main>
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} /> {isTablet ? <FooterMobile /> : <FooterDesktop />}
</Routes>
</Suspense>
</Styled.Main>
{isTablet ? <FooterMobile /> : <FooterDesktop />} <Styled.NotificationsToastArea />
<Styled.NotificationsToastArea /> <Styled.DialogArea ref={setDialogArea}>
<DialogManager />
</Styled.DialogArea>
<Styled.DialogArea ref={setDialogArea}> <GlobalCommandDialog />
<DialogManager /> </Styled.Content>
</Styled.DialogArea> </>
<GlobalCommandDialog />
</Styled.Content>
); );
}; };
@ -128,10 +149,11 @@ const providers = [
wrapProvider(DydxProvider), wrapProvider(DydxProvider),
wrapProvider(AccountsProvider), wrapProvider(AccountsProvider),
wrapProvider(SubaccountProvider), wrapProvider(SubaccountProvider),
wrapProvider(SquidProvider),
wrapProvider(LocalNotificationsProvider), wrapProvider(LocalNotificationsProvider),
wrapProvider(NotificationsProvider), wrapProvider(NotificationsProvider),
wrapProvider(DialogAreaProvider), wrapProvider(DialogAreaProvider),
wrapProvider(PotentialMarketsProvider),
wrapProvider(AppThemeAndColorModeProvider),
]; ];
const App = () => { const App = () => {
@ -196,6 +218,7 @@ Styled.Content = styled.div<{ isShowingHeader: boolean; isShowingFooter: boolean
Styled.Main = styled.main` Styled.Main = styled.main`
${layoutMixins.contentSectionAttached} ${layoutMixins.contentSectionAttached}
box-shadow: none;
grid-area: Main; grid-area: Main;

390
src/abi/erc20_usdt.json Normal file
View File

@ -0,0 +1,390 @@
[
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [{ "name": "", "type": "string" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "_upgradedAddress", "type": "address" }],
"name": "deprecate",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "name": "_spender", "type": "address" },
{ "name": "_value", "type": "uint256" }
],
"name": "approve",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "deprecated",
"outputs": [{ "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "_evilUser", "type": "address" }],
"name": "addBlackList",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "name": "_from", "type": "address" },
{ "name": "_to", "type": "address" },
{ "name": "_value", "type": "uint256" }
],
"name": "transferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "upgradedAddress",
"outputs": [{ "name": "", "type": "address" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [{ "name": "", "type": "address" }],
"name": "balances",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "maximumFee",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "_totalSupply",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "unpause",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [{ "name": "_maker", "type": "address" }],
"name": "getBlackListStatus",
"outputs": [{ "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{ "name": "", "type": "address" },
{ "name": "", "type": "address" }
],
"name": "allowed",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "paused",
"outputs": [{ "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [{ "name": "who", "type": "address" }],
"name": "balanceOf",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "pause",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getOwner",
"outputs": [{ "name": "", "type": "address" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [{ "name": "", "type": "address" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [{ "name": "", "type": "string" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "name": "_to", "type": "address" },
{ "name": "_value", "type": "uint256" }
],
"name": "transfer",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "name": "newBasisPoints", "type": "uint256" },
{ "name": "newMaxFee", "type": "uint256" }
],
"name": "setParams",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "amount", "type": "uint256" }],
"name": "issue",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "amount", "type": "uint256" }],
"name": "redeem",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{ "name": "_owner", "type": "address" },
{ "name": "_spender", "type": "address" }
],
"name": "allowance",
"outputs": [{ "name": "remaining", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "basisPointsRate",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [{ "name": "", "type": "address" }],
"name": "isBlackListed",
"outputs": [{ "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "_clearedUser", "type": "address" }],
"name": "removeBlackList",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "MAX_UINT",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "newOwner", "type": "address" }],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "_blackListedUser", "type": "address" }],
"name": "destroyBlackFunds",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{ "name": "_initialSupply", "type": "uint256" },
{ "name": "_name", "type": "string" },
{ "name": "_symbol", "type": "string" },
{ "name": "_decimals", "type": "uint256" }
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "name": "amount", "type": "uint256" }],
"name": "Issue",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "name": "amount", "type": "uint256" }],
"name": "Redeem",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "name": "newAddress", "type": "address" }],
"name": "Deprecate",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "name": "feeBasisPoints", "type": "uint256" },
{ "indexed": false, "name": "maxFee", "type": "uint256" }
],
"name": "Params",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "name": "_blackListedUser", "type": "address" },
{ "indexed": false, "name": "_balance", "type": "uint256" }
],
"name": "DestroyedBlackFunds",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "name": "_user", "type": "address" }],
"name": "AddedBlackList",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "name": "_user", "type": "address" }],
"name": "RemovedBlackList",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": true, "name": "owner", "type": "address" },
{ "indexed": true, "name": "spender", "type": "address" },
{ "indexed": false, "name": "value", "type": "uint256" }
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": true, "name": "from", "type": "address" },
{ "indexed": true, "name": "to", "type": "address" },
{ "indexed": false, "name": "value", "type": "uint256" }
],
"name": "Transfer",
"type": "event"
},
{ "anonymous": false, "inputs": [], "name": "Pause", "type": "event" },
{ "anonymous": false, "inputs": [], "name": "Unpause", "type": "event" }
]

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.',
},
],
};

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);
}
`;

View File

@ -40,9 +40,6 @@ const AlertContainer = styled.div<StyleProps>`
case AlertType.Info: { case AlertType.Info: {
return css` return css`
--alert-accent-color: var(--color-text-1); --alert-accent-color: var(--color-text-1);
--alert-default-background-opacity: 0.133; // Relative
// --alert-background: var(--color-layer-6); // Absolute
`; `;
} }
case AlertType.Success: { case AlertType.Success: {

View File

@ -8,6 +8,7 @@ const assetIcons = {
'1INCH': '/currencies/1inch.png', '1INCH': '/currencies/1inch.png',
AAVE: '/currencies/aave.png', AAVE: '/currencies/aave.png',
ADA: '/currencies/ada.png', ADA: '/currencies/ada.png',
AGIX: '/currencies/agix.png',
ALGO: '/currencies/algo.png', ALGO: '/currencies/algo.png',
APE: '/currencies/ape.png', APE: '/currencies/ape.png',
APT: '/currencies/apt.png', APT: '/currencies/apt.png',
@ -16,35 +17,60 @@ const assetIcons = {
AVAX: '/currencies/avax.png', AVAX: '/currencies/avax.png',
BCH: '/currencies/bch.png', BCH: '/currencies/bch.png',
BLUR: '/currencies/blur.png', BLUR: '/currencies/blur.png',
BNB: '/currencies/bnb.png',
BONK: '/currencies/bonk.png',
BTC: '/currencies/btc.png', BTC: '/currencies/btc.png',
CELO: '/currencies/celo.png', CELO: '/currencies/celo.png',
CHZ: '/currencies/chz.png',
COMP: '/currencies/comp.png', COMP: '/currencies/comp.png',
CRV: '/currencies/crv.png', CRV: '/currencies/crv.png',
DAI: '/currencies/dai.png', DAI: '/currencies/dai.png',
DOGE: '/currencies/doge.png', DOGE: '/currencies/doge.png',
DOT: '/currencies/dot.png', DOT: '/currencies/dot.png',
DYDX: '/currencies/dydx.png', DYDX: '/currencies/dydx.png',
DYM: '/currencies/dym.png',
ENJ: '/currencies/enj.png', ENJ: '/currencies/enj.png',
ENS: '/currencies/ens.png',
EOS: '/currencies/eos.png', EOS: '/currencies/eos.png',
ETC: '/currencies/etc.png', ETC: '/currencies/etc.png',
ETH: '/currencies/eth.png', ETH: '/currencies/eth.png',
FET: '/currencies/fet.png',
FIL: '/currencies/fil.png', FIL: '/currencies/fil.png',
FTM: '/currencies/ftm.png',
GALA: "/currencies/gala.png",
GMT: "/currencies/gmt.png",
GRT: "/currencies/grt.png",
HBAR: "/currencies/hbar.png",
ICP: '/currencies/icp.png', ICP: '/currencies/icp.png',
IMX: '/currencies/imx.png',
INJ: '/currencies/inj.png',
JTO: '/currencies/jto.png',
JUP: '/currencies/jup.png',
KAVA: '/currencies/kava.png',
LDO: '/currencies/ldo.png', LDO: '/currencies/ldo.png',
LINK: '/currencies/link.png', LINK: '/currencies/link.png',
LTC: '/currencies/ltc.png', LTC: '/currencies/ltc.png',
MANA: '/currencies/mana.png',
MATIC: '/currencies/matic.png', MATIC: '/currencies/matic.png',
MASK: '/currencies/mask.png',
MINA: '/currencies/mina.png',
MKR: '/currencies/mkr.png', MKR: '/currencies/mkr.png',
NEAR: '/currencies/near.png', NEAR: '/currencies/near.png',
ORDI: "/currencies/ordi.png",
OP: '/currencies/op.png', OP: '/currencies/op.png',
PEPE: '/currencies/pepe.png', PEPE: '/currencies/pepe.png',
PYTH: '/currencies/pyth.png',
RNDR: '/currencies/rndr.png',
RUNE: '/currencies/rune.png', RUNE: '/currencies/rune.png',
SAND: '/currencies/sand.png',
SEI: '/currencies/sei.png', SEI: '/currencies/sei.png',
SHIB: '/currencies/shib.png', SHIB: '/currencies/shib.png',
SNX: '/currencies/snx.png', SNX: '/currencies/snx.png',
SOL: '/currencies/sol.png', SOL: '/currencies/sol.png',
STX: '/currencies/stx.png',
SUI: '/currencies/sui.png', SUI: '/currencies/sui.png',
SUSHI: '/currencies/sushi.png', SUSHI: '/currencies/sushi.png',
TIA: '/currencies/tia.png',
TRX: '/currencies/trx.png', TRX: '/currencies/trx.png',
UMA: '/currencies/uma.png', UMA: '/currencies/uma.png',
UNI: '/currencies/uni.png', UNI: '/currencies/uni.png',
@ -52,6 +78,7 @@ const assetIcons = {
USDT: '/currencies/usdt.png', USDT: '/currencies/usdt.png',
WBTC: '/currencies/wbtc.png', WBTC: '/currencies/wbtc.png',
WETH: '/currencies/weth.png', WETH: '/currencies/weth.png',
WOO: '/currencies/woo.png',
WLD: '/currencies/wld.png', WLD: '/currencies/wld.png',
XLM: '/currencies/xlm.png', XLM: '/currencies/xlm.png',
XMR: '/currencies/xmr.png', XMR: '/currencies/xmr.png',
@ -59,6 +86,7 @@ const assetIcons = {
XTZ: '/currencies/xtz.png', XTZ: '/currencies/xtz.png',
YFI: '/currencies/yfi.png', YFI: '/currencies/yfi.png',
ZEC: '/currencies/zec.png', ZEC: '/currencies/zec.png',
ZETA: '/currencies/zeta.png',
ZRX: '/currencies/zrx.png', ZRX: '/currencies/zrx.png',
} as const; } as const;
@ -71,8 +99,13 @@ export const AssetIcon = ({
}: { }: {
symbol?: Nullable<string>; symbol?: Nullable<string>;
className?: string; className?: string;
}) => }) => (
isAssetSymbol(symbol) ? <Styled.Img src={assetIcons[symbol]} className={className} /> : null; <Styled.Img
src={isAssetSymbol(symbol) ? assetIcons[symbol] : '/currencies/unavailable.png'}
className={className}
alt={symbol}
/>
);
const Styled: Record<string, AnyStyledComponent> = {}; const Styled: Record<string, AnyStyledComponent> = {};

View File

@ -134,8 +134,8 @@ const ButtonStyle = css<StyleProps>`
--button-textColor: var(--color-text-0); --button-textColor: var(--color-text-0);
--button-backgroundColor: transparent; --button-backgroundColor: transparent;
--button-active-filter: brightness(0.9); --button-active-filter: brightness(var(--active-filter));
--button-hover-filter: brightness(1.1); --button-hover-filter: brightness(var(--hover-filter-base));
--button-hover-textColor: var(--button-textColor); --button-hover-textColor: var(--button-textColor);
--button-radius: 0.5em; --button-radius: 0.5em;

View File

@ -61,7 +61,7 @@ export const Button = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonPr
return ( return (
<StyledBaseButton <StyledBaseButton
disabled={state[ButtonState.Disabled]} disabled={state[ButtonState.Disabled] || state[ButtonState.Loading]}
{...{ ref, action, size, shape, state, ...otherProps }} {...{ ref, action, size, shape, state, ...otherProps }}
> >
{ {
@ -89,9 +89,10 @@ const buttonActionVariants = {
--button-border: solid var(--border-width) var(--color-border); --button-border: solid var(--border-width) var(--color-border);
`, `,
[ButtonAction.Primary]: css` [ButtonAction.Primary]: css`
--button-textColor: var(--color-text-2); --button-textColor: var(--color-text-button);
--button-backgroundColor: var(--color-accent); --button-backgroundColor: var(--color-accent);
--button-border: solid var(--border-width) var(--color-border-white); --button-border: solid var(--border-width) var(--color-border-white);
--button-hover-filter: brightness(var(--hover-filter-variant));
`, `,
[ButtonAction.Secondary]: css` [ButtonAction.Secondary]: css`
@ -101,15 +102,17 @@ const buttonActionVariants = {
`, `,
[ButtonAction.Create]: css` [ButtonAction.Create]: css`
--button-textColor: var(--color-text-2); --button-textColor: var(--color-text-button);
--button-backgroundColor: var(--color-positive); --button-backgroundColor: var(--color-green);
--button-border: solid var(--border-width) var(--color-border-white); --button-border: solid var(--border-width) var(--color-border-white);
--button-hover-filter: brightness(var(--hover-filter-variant));
`, `,
[ButtonAction.Destroy]: css` [ButtonAction.Destroy]: css`
--button-textColor: var(--color-text-2); --button-textColor: var(--color-text-button);
--button-backgroundColor: var(--color-negative); --button-backgroundColor: var(--color-red);
--button-border: solid var(--border-width) var(--color-border-white); --button-border: solid var(--border-width) var(--color-border-white);
--button-hover-filter: brightness(var(--hover-filter-variant));
`, `,
[ButtonAction.Navigation]: css` [ButtonAction.Navigation]: css`
@ -119,9 +122,10 @@ const buttonActionVariants = {
`, `,
[ButtonAction.Reset]: css` [ButtonAction.Reset]: css`
--button-textColor: var(--color-negative); --button-textColor: var(--color-red);
--button-backgroundColor: var(--color-layer-3); --button-backgroundColor: var(--color-layer-3);
--button-border: solid var(--border-width) var(--color-border-red); --button-border: solid var(--border-width) var(--color-border-red);
--button-hover-filter: brightness(var(--hover-filter-variant));
`, `,
}; };

13
src/components/Canvas.tsx Normal file
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} />
)
);

View File

@ -5,7 +5,7 @@ import { Checkbox, CheckboxProps } from '@/components/Checkbox';
import { StoryWrapper } from '.ladle/components'; import { StoryWrapper } from '.ladle/components';
export const Checkboxes: Story<CheckboxProps> = (args) => { export const CheckboxStory: Story<CheckboxProps> = (args) => {
const [isChecked, setIsChecked] = useState(false); const [isChecked, setIsChecked] = useState(false);
return ( return (
@ -13,10 +13,20 @@ export const Checkboxes: Story<CheckboxProps> = (args) => {
<Checkbox <Checkbox
{...args} {...args}
checked={isChecked} checked={isChecked}
onClick={(e: React.ChangeEvent) => setIsChecked((e.target as HTMLInputElement).checked)} onCheckedChange={setIsChecked}
id="story-checkbox"
label="example label"
/> />
</StoryWrapper> </StoryWrapper>
); );
}; };
Checkboxes.args = {}; CheckboxStory.args = {};
CheckboxStory.argTypes = {
disabled: {
options: [true, false],
control: { type: 'select' },
defaultValue: false,
}
}

View File

@ -1,10 +1,15 @@
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';
import { breakpoints } from '@/styles'; import { layoutMixins } from '@/styles/layoutMixins';
type ElementProps = { type ElementProps = {
checked: boolean; checked: boolean;
onClick: (e: React.ChangeEvent) => void; onCheckedChange: (checked: boolean) => void;
id?: string;
label?: React.ReactNode;
disabled?: boolean;
}; };
type StyleProps = { type StyleProps = {
@ -13,85 +18,79 @@ type StyleProps = {
export type CheckboxProps = ElementProps & StyleProps; export type CheckboxProps = ElementProps & StyleProps;
export const Checkbox: React.FC<CheckboxProps> = ({ checked, className, onClick }) => { export const Checkbox: React.FC<CheckboxProps> = ({
return ( checked,
<Styled.CheckboxWrapper className={className}> className,
<Styled.Checkbox onCheckedChange,
type="checkbox" id,
checked={checked} label,
onChange={onClick} disabled,
/> }) => (
<Styled.CustomCheckbox /> <Styled.Container>
</Styled.CheckboxWrapper> <Styled.Root
); className={className}
}; checked={checked}
disabled={disabled}
onCheckedChange={onCheckedChange}
id={id}
>
<Styled.Indicator>
<CheckIcon />
</Styled.Indicator>
</Styled.Root>
{label && (
<Styled.Label disabled={disabled} htmlFor={id}>
{label}
</Styled.Label>
)}
</Styled.Container>
);
const Styled: Record<string, AnyStyledComponent> = {}; const Styled: Record<string, AnyStyledComponent> = {};
Styled.CustomCheckbox = styled.span` Styled.Container = styled.div`
width: 1.25em; ${layoutMixins.row}
height: 1.25em; gap: 1ch;
font: var(--font-small-book);
`;
position: absolute; Styled.Root = styled(Root)`
left: 0; --checkbox-backgroundColor: var(--color-layer-0);
right: 0; --checkbox-borderColor: var(--color-border);
top: 0;
bottom: 0; min-width: 1.25rem;
height: 1.25rem;
border-radius: 0.375rem;
border: var(--border-width) solid var(--checkbox-borderColor);
background-color: var(--checkbox-backgroundColor); background-color: var(--checkbox-backgroundColor);
&::after { &[data-state='checked'] {
position: absolute; --checkbox-backgroundColor: var(--color-accent);
content: '';
top: 0.25em;
left: 0.4375em;
width: 0.3125em;
height: 0.5em;
border: solid var(--checkbox-checkColor);
border-width: 0 0.125em 0.125em 0;
border-radius: 0.0625em;
opacity: 0;
transform: rotate(0deg) scale(0);
transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out;
} }
@media ${breakpoints.tablet} { &[data-disabled] {
width: 1.5em; cursor: not-allowed;
height: 1.5em; --checkbox-backgroundColor: var(--color-layer-1);
&::after {
top: 0.25em;
left: 0.4375em;
width: 0.4375em;
height: 0.625em;
}
} }
`; `;
Styled.CheckboxWrapper = styled.div` Styled.Indicator = styled(Indicator)`
--checkbox-backgroundColor: var(--color-layer-1);
--checkbox-checkColor: var(--color-text-1);
display: flex; display: flex;
border-radius: 0.25em; align-items: center;
overflow: hidden; justify-content: center;
position: relative;
cursor: pointer;
> input:checked ~ ${Styled.CustomCheckbox}::after { color: var(--color-text-button);
opacity: 1;
transform: rotate(40deg) scale(1);
}
`; `;
Styled.Checkbox = styled.input` Styled.Label = styled.label<{ disabled?: boolean }>`
width: 1.25em;
height: 1.25em;
z-index: 1;
cursor: pointer; cursor: pointer;
opacity: 0; color: var(--color-text-2);
@media ${breakpoints.tablet} { ${({ disabled }) =>
width: 1.5em; disabled &&
height: 1.5em; css`
} cursor: not-allowed;
color: var(--color-text-0);
`}
`; `;

View File

@ -1,16 +1,13 @@
import type { Story } from '@ladle/react'; import type { Story } from '@ladle/react';
import { Collapsible } from '@/components/Collapsible'; import { Collapsible, type CollapsibleProps } from '@/components/Collapsible';
import { StoryWrapper } from '.ladle/components'; import { StoryWrapper } from '.ladle/components';
import { IconName } from './Icon'; import { IconName } from './Icon';
export const CollapsibleStory: Story<Parameters<typeof Collapsible>> = (args) => ( export const CollapsibleStory: Story<CollapsibleProps> = (args) => (
<StoryWrapper> <StoryWrapper>
<Collapsible <Collapsible {...args}>
label="Collapsible List of Items"
{...args}
>
<ul> <ul>
<li>Collapsible Item 1</li> <li>Collapsible Item 1</li>
<li>Collapsible Item 2</li> <li>Collapsible Item 2</li>
@ -23,6 +20,8 @@ export const CollapsibleStory: Story<Parameters<typeof Collapsible>> = (args) =>
CollapsibleStory.args = { CollapsibleStory.args = {
disabled: false, disabled: false,
withTrigger: true,
label: 'Collapsible List of Items',
}; };
CollapsibleStory.argTypes = { CollapsibleStory.argTypes = {

View File

@ -14,6 +14,7 @@ type ElementProps = {
label: React.ReactNode; label: React.ReactNode;
triggerIcon?: IconName; triggerIcon?: IconName;
children: React.ReactNode; children: React.ReactNode;
withTrigger?: boolean;
}; };
type StyleProps = { type StyleProps = {
@ -23,6 +24,8 @@ type StyleProps = {
fullWidth?: boolean; fullWidth?: boolean;
}; };
export type CollapsibleProps = ElementProps & StyleProps;
export const Collapsible = ({ export const Collapsible = ({
defaultOpen = false, defaultOpen = false,
disabled, disabled,
@ -35,26 +38,29 @@ export const Collapsible = ({
triggerIconSide = 'left', triggerIconSide = 'left',
fullWidth, fullWidth,
className, className,
}: ElementProps & StyleProps) => ( withTrigger = true,
}: CollapsibleProps) => (
<Styled.Root defaultOpen={defaultOpen} open={open} onOpenChange={onOpenChange}> <Styled.Root defaultOpen={defaultOpen} open={open} onOpenChange={onOpenChange}>
<Styled.Trigger className={className} disabled={disabled}> {withTrigger && (
{triggerIconSide === 'right' && ( <Styled.Trigger className={className} disabled={disabled}>
<> {triggerIconSide === 'right' && (
{label} <>
{fullWidth && <HorizontalSeparatorFiller />} {label}
</> {fullWidth && <HorizontalSeparatorFiller />}
)} </>
)}
<Styled.TriggerIcon> <Styled.TriggerIcon>
<Icon iconName={triggerIcon} /> <Icon iconName={triggerIcon} />
</Styled.TriggerIcon> </Styled.TriggerIcon>
{triggerIconSide === 'left' && ( {triggerIconSide === 'left' && (
<> <>
{fullWidth && <HorizontalSeparatorFiller />} {fullWidth && <HorizontalSeparatorFiller />}
{label} {label}
</> </>
)} )}
</Styled.Trigger> </Styled.Trigger>
)}
<Styled.Content $transitionDuration={transitionDuration}>{children}</Styled.Content> <Styled.Content $transitionDuration={transitionDuration}>{children}</Styled.Content>
</Styled.Root> </Styled.Root>
); );

View File

@ -31,10 +31,12 @@ type ElementProps<TabItemsValue> = {
}; };
type StyleProps = { type StyleProps = {
fullWidthTabs?: boolean;
className?: string; className?: string;
fullWidthTabs?: boolean;
}; };
export type CollapsibleTabsProps<TabItemsValue> = ElementProps<TabItemsValue> & StyleProps;
export const CollapsibleTabs = <TabItemsValue extends string>({ export const CollapsibleTabs = <TabItemsValue extends string>({
defaultValue, defaultValue,
items, items,
@ -43,8 +45,9 @@ export const CollapsibleTabs = <TabItemsValue extends string>({
onOpenChange, onOpenChange,
fullWidthTabs, fullWidthTabs,
className, className,
}: ElementProps<TabItemsValue> & StyleProps) => { }: CollapsibleTabsProps<TabItemsValue>) => {
const [value, setValue] = useState(defaultValue); const [value, setValue] = useState(defaultValue);
const currentItem = items.find((item) => item.value === value); const currentItem = items.find((item) => item.value === value);
@ -86,8 +89,8 @@ export const CollapsibleTabs = <TabItemsValue extends string>({
</Styled.Header> </Styled.Header>
<Styled.CollapsibleContent> <Styled.CollapsibleContent>
{items.map(({ value, content }) => ( {items.map(({ asChild, value, content }) => (
<Styled.TabsContent key={value} value={value}> <Styled.TabsContent key={value} asChild={asChild} value={value}>
{content} {content}
</Styled.TabsContent> </Styled.TabsContent>
))} ))}
@ -219,12 +222,12 @@ Styled.Header = styled.header`
Styled.CollapsibleContent = styled(CollapsibleContent)` Styled.CollapsibleContent = styled(CollapsibleContent)`
${layoutMixins.stack} ${layoutMixins.stack}
${layoutMixins.perspectiveArea}
box-shadow: none; box-shadow: none;
`; `;
Styled.IconButton = styled(IconButton)` Styled.IconButton = styled(IconButton)`
--button-icon-size: 1em;
${Styled.CollapsibleRoot}[data-state='closed'] & { ${Styled.CollapsibleRoot}[data-state='closed'] & {
rotate: -0.5turn; rotate: -0.5turn;
} }

View File

@ -22,7 +22,12 @@ type PickComboxMenuProps<
MenuGroupValue extends string | number MenuGroupValue extends string | number
> = Pick< > = Pick<
ComboboxMenuProps<MenuItemValue, MenuGroupValue>, ComboboxMenuProps<MenuItemValue, MenuGroupValue>,
'inputPlaceholder' | 'onItemSelected' | 'slotEmpty' | 'withSearch' | 'withStickyLayout' | 'inputPlaceholder'
| 'onItemSelected'
| 'slotEmpty'
| 'withItemBorders'
| 'withSearch'
| 'withStickyLayout'
>; >;
type PickDialogProps = Pick< type PickDialogProps = Pick<
@ -34,6 +39,7 @@ type PickDialogProps = Pick<
| 'slotHeaderInner' | 'slotHeaderInner'
| 'slotTrigger' | 'slotTrigger'
| 'slotFooter' | 'slotFooter'
| 'preventClose'
>; >;
export const ComboboxDialogMenu = < export const ComboboxDialogMenu = <
@ -52,11 +58,13 @@ export const ComboboxDialogMenu = <
onItemSelected, onItemSelected,
inputPlaceholder, inputPlaceholder,
slotEmpty, slotEmpty,
withItemBorders,
withSearch, withSearch,
withStickyLayout = true, withStickyLayout = true,
children, children,
placement = DialogPlacement.Default, placement = DialogPlacement.Default,
preventClose,
className, className,
}: ElementProps<MenuItemValue, MenuGroupValue> & }: ElementProps<MenuItemValue, MenuGroupValue> &
PickComboxMenuProps<MenuItemValue, MenuGroupValue> & PickComboxMenuProps<MenuItemValue, MenuGroupValue> &
@ -72,6 +80,7 @@ export const ComboboxDialogMenu = <
slotTrigger={slotTrigger} slotTrigger={slotTrigger}
slotFooter={slotFooter} slotFooter={slotFooter}
placement={placement} placement={placement}
preventClose={preventClose}
className={className} className={className}
> >
<Styled.ComboboxMenu <Styled.ComboboxMenu
@ -80,6 +89,7 @@ export const ComboboxDialogMenu = <
title={title} title={title}
inputPlaceholder={inputPlaceholder} inputPlaceholder={inputPlaceholder}
slotEmpty={slotEmpty} slotEmpty={slotEmpty}
withItemBorders={withItemBorders}
withSearch={withSearch} withSearch={withSearch}
withStickyLayout={withStickyLayout} withStickyLayout={withStickyLayout}
/> />
@ -92,6 +102,8 @@ const Styled: Record<string, AnyStyledComponent> = {};
Styled.Dialog = styled(Dialog)` Styled.Dialog = styled(Dialog)`
/* Params */ /* Params */
--comboboxDialogMenu-backgroundColor: var(--color-layer-2); --comboboxDialogMenu-backgroundColor: var(--color-layer-2);
--comboboxDialogMenu-item-gap: 0.5rem;
--comboboxDialogMenu-item-padding: 0.5rem 1rem;
/* Overrides */ /* Overrides */
& { & {
@ -110,10 +122,12 @@ Styled.Dialog = styled(Dialog)`
/* Net 0 sticky top inset (let stickyArea1 header stick to top) */ /* Net 0 sticky top inset (let stickyArea1 header stick to top) */
--stickyArea0-topGap: calc(-1 * var(--stickyArea0-topHeight)); --stickyArea0-topGap: calc(-1 * var(--stickyArea0-topHeight));
overflow-x: clip;
} }
`; `;
Styled.ComboboxMenu = styled(ComboboxMenu)` Styled.ComboboxMenu = styled(ComboboxMenu)`
--comboboxMenu-backgroundColor: var(--comboboxDialogMenu-backgroundColor); --comboboxMenu-backgroundColor: var(--comboboxDialogMenu-backgroundColor);
--comboboxMenu-item-gap: var(--comboxDialogMenu-item-gap, 0.5rem); --comboboxMenu-item-gap: var(--comboboxDialogMenu-item-gap);
--comboboxMenu-item-padding: var(--comboboxDialogMenu-item-padding);
`; `;

View File

@ -2,7 +2,7 @@ import { Fragment, type ReactNode, useState } from 'react';
import styled, { type AnyStyledComponent, css } from 'styled-components'; import styled, { type AnyStyledComponent, css } from 'styled-components';
import { Command } from 'cmdk'; import { Command } from 'cmdk';
import { type MenuConfig } from '@/constants/menus'; import { MenuItem, type MenuConfig } from '@/constants/menus';
import { popoverMixins } from '@/styles/popoverMixins'; import { popoverMixins } from '@/styles/popoverMixins';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
@ -20,6 +20,7 @@ type ElementProps<MenuItemValue extends string | number, MenuGroupValue extends
type StyleProps = { type StyleProps = {
className?: string; className?: string;
withItemBorders?: boolean;
withStickyLayout?: boolean; withStickyLayout?: boolean;
}; };
@ -38,38 +39,36 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
withSearch = true, withSearch = true,
className, className,
withItemBorders,
withStickyLayout, withStickyLayout,
}: ComboboxMenuProps<MenuItemValue, MenuGroupValue>) => { }: ComboboxMenuProps<MenuItemValue, MenuGroupValue>) => {
const [highlightedCommand, setHighlightedCommand] = useState<MenuItemValue>(); const [highlightedCommand, setHighlightedCommand] = useState<MenuItemValue>();
const [searchValue, setSearchValue] = useState(''); const [searchValue, setSearchValue] = useState('');
// const inputRef = useRef<HTMLInputElement | null>(null);
// console.log({ commandValue: highlightedCommand });
// useEffect(() => {
// inputRef?.current?.focus();
// }, []);
return ( return (
<Styled.Command <Styled.Command
label={title} label={title}
// value={highlightedCommand} // value={highlightedCommand}
// onValueChange={setHighlightedCommand} // onValueChange={setHighlightedCommand}
filter={(value: string, search: string) => { filter={(value: string, search: string) =>
if (value.replace(/ /g, '').includes(search.replace(/ /g, ''))) return 1; value.replace(/ /g, '').toLowerCase().includes(search.replace(/ /g, '').toLowerCase())
return 0; ? 1
}} : 0
}
className={className} className={className}
$withStickyLayout={withStickyLayout} $withStickyLayout={withStickyLayout}
> >
{withSearch && ( {withSearch && (
<Styled.Header $withStickyLayout={withStickyLayout}> <Styled.Header $withStickyLayout={withStickyLayout}>
<Styled.Input <Styled.Input
// ref={inputRef} /**
* Mobile Issue: Search Input will always trigger mobile keyboard drawer. There is no fix.
* https://github.com/pacocoursey/cmdk/issues/127
*/
autoFocus
type="search" type="search"
value={searchValue} value={searchValue}
onValueChange={setSearchValue} onValueChange={setSearchValue}
autoFocus
placeholder={inputPlaceholder} placeholder={inputPlaceholder}
/> />
</Styled.Header> </Styled.Header>
@ -80,6 +79,7 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
<Styled.Group <Styled.Group
key={group.group} key={group.group}
heading={group.groupLabel} heading={group.groupLabel}
$withItemBorders={withItemBorders}
$withStickyLayout={withStickyLayout} $withStickyLayout={withStickyLayout}
> >
{group.items.map((item) => ( {group.items.map((item) => (
@ -99,22 +99,31 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
} }
}} }}
disabled={item.disabled} disabled={item.disabled}
$withItemBorders={withItemBorders}
> >
{item.slotBefore} {
<Styled.ItemLabel> <>
<span> {item.slotBefore}
{`${item.label}${item.subitems?.length ? '…' : ''}`} {item.slotCustomContent ?? (
{item.tag && ( <Styled.ItemLabel>
<> <span>
{' '} {typeof item.label === 'string'
<Tag>{item.tag}</Tag> ? `${item.label}${item.subitems?.length ? '…' : ''}`
</> : item.label}
{item.tag && (
<>
{' '}
<Tag>{item.tag}</Tag>
</>
)}
</span>
{item.description && <span>{item.description}</span>}
</Styled.ItemLabel>
)} )}
</span> {item.slotAfter}
{item.description && <span>{item.description}</span>} {item.subitems && '→'}
</Styled.ItemLabel> </>
{item.slotAfter} }
{item.subitems && '→'}
</Styled.Item> </Styled.Item>
{searchValue && {searchValue &&
@ -137,6 +146,7 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
onItemSelected?.(); onItemSelected?.();
}} }}
disabled={subitem.disabled} disabled={subitem.disabled}
$withItemBorders={withItemBorders}
> >
{subitem.slotBefore} {subitem.slotBefore}
<Styled.ItemLabel> <Styled.ItemLabel>
@ -169,14 +179,17 @@ const Styled: Record<string, AnyStyledComponent> = {};
Styled.Command = styled(Command)<{ $withStickyLayout?: boolean }>` Styled.Command = styled(Command)<{ $withStickyLayout?: boolean }>`
--comboboxMenu-backgroundColor: var(--color-layer-2); --comboboxMenu-backgroundColor: var(--color-layer-2);
--comboboxMenu-input-backgroundColor: var(--color-layer-3); --comboboxMenu-input-backgroundColor: var(--color-layer-3);
--comboboxMenu-input-height: 2.5rem; --comboboxMenu-input-height: 2.5rem;
--comboboxMenu-item-checked-backgroundColor: ; --comboboxMenu-item-checked-backgroundColor: ;
--comboboxMenu-item-checked-textColor: ; --comboboxMenu-item-checked-textColor: ;
--comboboxMenu-item-highlighted-backgroundColor: var(--color-layer-3); --comboboxMenu-item-highlighted-backgroundColor: var(--color-layer-3);
--comboboxMenu-item-highlighted-textColor: var(--color-text-1); --comboboxMenu-item-highlighted-textColor: var(--color-text-1);
--comboboxMenu-item-backgroundColor: ; --comboboxMenu-item-backgroundColor: ;
--comboboxMenu-item-gap: 0.5rem; --comboboxMenu-item-gap: 0.5rem;
--comboboxMenu-item-padding: 0.5em 1em;
display: grid; display: grid;
align-content: start; align-content: start;
@ -225,7 +238,7 @@ Styled.Input = styled(Command.Input)`
gap: 0.5rem; gap: 0.5rem;
`; `;
Styled.Group = styled(Command.Group)<{ $withStickyLayout?: boolean }>` Styled.Group = styled(Command.Group)<{ $withItemBorders?: boolean; $withStickyLayout?: boolean }>`
color: var(--color-text-0); color: var(--color-text-0);
> [cmdk-group-heading] { > [cmdk-group-heading] {
@ -242,12 +255,21 @@ Styled.Group = styled(Command.Group)<{ $withStickyLayout?: boolean }>`
> [cmdk-group-heading] { > [cmdk-group-heading] {
${layoutMixins.stickyHeader} ${layoutMixins.stickyHeader}
z-index: 2;
} }
> [cmdk-group-items] { > [cmdk-group-items] {
${layoutMixins.stickyArea3} ${layoutMixins.stickyArea3}
} }
`} `}
${({ $withItemBorders }) =>
$withItemBorders &&
css`
> [cmdk-group-items] {
padding: var(--border-width) 0;
}
`}
`; `;
Styled.List = styled(Command.List)<{ $withStickyLayout?: boolean }>` Styled.List = styled(Command.List)<{ $withStickyLayout?: boolean }>`
@ -274,13 +296,14 @@ Styled.List = styled(Command.List)<{ $withStickyLayout?: boolean }>`
`} `}
`; `;
Styled.Item = styled(Command.Item)` Styled.Item = styled(Command.Item)<{ $withItemBorders?: boolean }>`
${layoutMixins.scrollSnapItem} ${layoutMixins.scrollSnapItem}
${popoverMixins.item} ${popoverMixins.item}
--item-checked-backgroundColor: var(--comboboxMenu-item-checked-backgroundColor); --item-checked-backgroundColor: var(--comboboxMenu-item-checked-backgroundColor);
--item-checked-textColor: var(--comboboxMenu-item-checked-textColor); --item-checked-textColor: var(--comboboxMenu-item-checked-textColor);
--item-highlighted-textColor: var(--comboboxMenu-item-highlighted-textColor); --item-highlighted-textColor: var(--comboboxMenu-item-highlighted-textColor);
--item-gap: var(--comboboxMenu-item-gap); --item-gap: var(--comboboxMenu-item-gap);
--item-padding: var(--comboboxMenu-item-padding);
background-color: var(--comboboxMenu-backgroundColor, inherit); background-color: var(--comboboxMenu-backgroundColor, inherit);
@ -291,6 +314,12 @@ Styled.Item = styled(Command.Item)`
opacity: 0.75; opacity: 0.75;
cursor: not-allowed; cursor: not-allowed;
} }
${({ $withItemBorders }) =>
$withItemBorders &&
css`
${layoutMixins.withOuterBorder}
`}
`; `;
Styled.ItemLabel = styled.div` Styled.ItemLabel = styled.div`
@ -309,6 +338,8 @@ Styled.ItemLabel = styled.div`
opacity: 0.8; opacity: 0.8;
} }
} }
min-width: 0;
`; `;
Styled.Empty = styled(Command.Empty)` Styled.Empty = styled(Command.Empty)`

View File

@ -11,6 +11,5 @@ export const DetachedScrollableSection = styled.section`
export const AttachedExpandingSection = styled.section` export const AttachedExpandingSection = styled.section`
${layoutMixins.contentSectionAttached} ${layoutMixins.contentSectionAttached}
${layoutMixins.expandingColumnWithHeader}
gap: var(--border-width); gap: var(--border-width);
`; `;

View File

@ -6,6 +6,7 @@ import { layoutMixins } from '@/styles/layoutMixins';
type ElementProps = { type ElementProps = {
title: string; title: string;
subtitle?: React.ReactNode; subtitle?: React.ReactNode;
slotLeft?: React.ReactNode;
slotRight?: React.ReactNode; slotRight?: React.ReactNode;
}; };
@ -16,14 +17,16 @@ type StyleProps = {
export const ContentSectionHeader = ({ export const ContentSectionHeader = ({
title, title,
subtitle, subtitle,
slotLeft,
slotRight, slotRight,
className, className,
}: ElementProps & StyleProps) => ( }: ElementProps & StyleProps) => (
<Styled.ContentSectionHeader className={className}> <Styled.ContentSectionHeader className={className}>
<div> {slotLeft}
<Styled.Header>
{title && <h3>{title}</h3>} {title && <h3>{title}</h3>}
{subtitle && <p>{subtitle}</p>} {subtitle && <p>{subtitle}</p>}
</div> </Styled.Header>
{slotRight} {slotRight}
</Styled.ContentSectionHeader> </Styled.ContentSectionHeader>
); );
@ -40,9 +43,15 @@ Styled.ContentSectionHeader = styled.header<StyleProps>`
padding: 1rem var(--header-horizontal-padding); padding: 1rem var(--header-horizontal-padding);
> div { @media ${breakpoints.tablet} {
${layoutMixins.column} flex-wrap: wrap;
--header-horizontal-padding: 1.25rem;
} }
`;
Styled.Header = styled.div`
${layoutMixins.column}
flex: 1;
h3 { h3 {
color: var(--color-text-2); color: var(--color-text-2);
@ -54,9 +63,4 @@ Styled.ContentSectionHeader = styled.header<StyleProps>`
font: var(--font-small-book); font: var(--font-small-book);
margin-top: 0.25rem; margin-top: 0.25rem;
} }
@media ${breakpoints.tablet} {
flex-wrap: wrap;
--header-horizontal-padding: 1.25rem;
}
`; `;

View File

@ -15,10 +15,10 @@ CopyButtonStory.args = {
}; };
CopyButtonStory.argTypes = { CopyButtonStory.argTypes = {
shownAsText: { buttonType: {
options: [true, false], options: ["text", "icon", "default"],
control: { type: 'select' }, control: { type: 'select' },
defaultValue: false, defaultValue: "default",
}, },
children: { children: {
options: ['some text to copy'], options: ['some text to copy'],

View File

@ -9,14 +9,21 @@ import { layoutMixins } from '@/styles/layoutMixins';
import { Button, ButtonProps } from './Button'; import { Button, ButtonProps } from './Button';
import { Icon, IconName } from './Icon'; import { Icon, IconName } from './Icon';
import { IconButton } from './IconButton';
import { WithTooltip } from './WithTooltip';
export type CopyButtonProps = { export type CopyButtonProps = {
value?: string; value?: string;
shownAsText?: boolean; buttonType?: 'text' | 'icon' | 'default';
children?: React.ReactNode; children?: React.ReactNode;
} & ButtonProps; } & ButtonProps;
export const CopyButton = ({ value, shownAsText, children, ...buttonProps }: CopyButtonProps) => { export const CopyButton = ({
value,
buttonType = 'default',
children,
...buttonProps
}: CopyButtonProps) => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const [copied, setCopied] = useState(false); const [copied, setCopied] = useState(false);
@ -28,11 +35,23 @@ export const CopyButton = ({ value, shownAsText, children, ...buttonProps }: Cop
setTimeout(() => setCopied(false), 500); setTimeout(() => setCopied(false), 500);
}; };
return shownAsText ? ( return buttonType === 'text' ? (
<Styled.InlineRow onClick={onCopy} copied={copied}> <Styled.InlineRow onClick={onCopy} copied={copied}>
{children} {children}
<Icon iconName={IconName.Copy} /> <Styled.Icon copied={copied} iconName={copied ? IconName.Check : IconName.Copy} />
</Styled.InlineRow> </Styled.InlineRow>
) : buttonType === 'icon' ? (
<WithTooltip
tooltipString={stringGetter({ key: copied ? STRING_KEYS.COPIED : STRING_KEYS.COPY })}
>
<Styled.IconButton
{...buttonProps}
copied={copied}
action={ButtonAction.Base}
iconName={copied ? IconName.Check : IconName.Copy}
onClick={onCopy}
/>
</WithTooltip>
) : ( ) : (
<Button <Button
{...buttonProps} {...buttonProps}
@ -58,8 +77,26 @@ Styled.InlineRow = styled.div<{ copied: boolean }>`
` `
: css` : css`
&:hover { &:hover {
filter: brightness(1.1); filter: brightness(var(--hover-filter-base));
text-decoration: underline; text-decoration: underline;
} }
`} `}
`; `;
Styled.Icon = styled(Icon)<{ copied: boolean }>`
${({ copied }) =>
copied &&
css`
color: var(--color-success);
`}
`;
Styled.IconButton = styled(IconButton)<{ copied: boolean }>`
${({ copied }) =>
copied &&
css`
svg {
color: var(--color-success);
}
`}
`;

View File

@ -7,35 +7,50 @@ import { StoryWrapper } from '.ladle/components';
import styled, { type AnyStyledComponent } from 'styled-components'; import styled, { type AnyStyledComponent } from 'styled-components';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
export const DetailsStory: Story<Parameters<typeof Details>> = () => ( export const DetailsStory: Story<Parameters<typeof Details>[0]> = (args) => (
<StoryWrapper> <StoryWrapper>
<Styled.Resizable> <Styled.Resizable>
<Details <Details {...args} />
items={[
{
key: 'item-1',
label: 'Item 1',
tooltip: 'leverage',
value: 'Value 1',
},
{
key: 'item-2',
label: 'Really really really long item name 2',
tooltip: 'liquidation-price',
value: 'Value 2',
},
{
key: 'item-3',
label: 'Item 3',
tooltip: 'realized-pnl',
value: 'Value 3',
},
]}
/>
</Styled.Resizable> </Styled.Resizable>
</StoryWrapper> </StoryWrapper>
); );
DetailsStory.args = {
items: [
{
key: 'item-1',
label: 'Item 1',
tooltip: 'leverage',
value: 'Value 1',
},
{
key: 'item-2',
label: 'Really really really long item name 2',
tooltip: 'liquidation-price',
value: 'Value 2',
},
{
key: 'item-3',
label: 'Item 3',
tooltip: 'realized-pnl',
value: 'Value 3',
},
],
showSubitems: false,
isLoading: false,
withOverflow: false,
withSeparators: false,
};
DetailsStory.argTypes = {
justifyItems: { options: ['start', 'end'], control: { type: 'select' }, defaultValue: 'start' },
layout: {
options: ['column', 'row', 'rowColumns', 'grid', 'stackColumn'],
control: { type: 'select' },
defaultValue: 'column',
},
};
const Styled: Record<string, AnyStyledComponent> = {}; const Styled: Record<string, AnyStyledComponent> = {};
Styled.Resizable = styled.section` Styled.Resizable = styled.section`

View File

@ -133,6 +133,7 @@ const detailsLayoutVariants = {
row: css` row: css`
${layoutMixins.row} ${layoutMixins.row}
align-self: stretch; align-self: stretch;
white-space: nowrap;
`, `,
rowColumns: css` rowColumns: css`
@ -159,12 +160,16 @@ const itemLayoutVariants: Record<string, FlattenInterpolation<ThemeProps<any>>>
${layoutMixins.spacedRow} ${layoutMixins.spacedRow}
gap: 0.5rem; gap: 0.5rem;
align-items: start;
padding: 0.5rem 0;
min-height: var(--details-item-height); min-height: var(--details-item-height);
> :last-child { > :first-child > abbr {
align-self: stretch; min-width: auto;
}
> :last-child {
${layoutMixins.row} ${layoutMixins.row}
${layoutMixins.stickyRight} ${layoutMixins.stickyRight}
@ -217,8 +222,6 @@ Styled.Details = styled.dl<{
--details-grid-numColumns: 2; --details-grid-numColumns: 2;
${({ layout }) => layout && detailsLayoutVariants[layout]} ${({ layout }) => layout && detailsLayoutVariants[layout]}
white-space: nowrap;
`; `;
Styled.Item = styled.div<{ Styled.Item = styled.div<{
@ -231,7 +234,7 @@ Styled.Item = styled.div<{
${({ justifyItems }) => ${({ justifyItems }) =>
justifyItems === 'end' && justifyItems === 'end' &&
css` css`
&:nth-child(even) { > :nth-child(even) {
justify-items: end; justify-items: end;
text-align: end; text-align: end;
} }
@ -243,6 +246,7 @@ Styled.Item = styled.div<{
{ {
column: css` column: css`
&:not(:hover) > :first-child { &:not(:hover) > :first-child {
white-space: nowrap;
overflow-x: hidden; overflow-x: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

View File

@ -26,7 +26,7 @@ export const DetailsDialog = ({ slotIcon, title, items, slotFooter, setIsOpen }:
placement={isTablet ? DialogPlacement.Default : DialogPlacement.Sidebar} placement={isTablet ? DialogPlacement.Default : DialogPlacement.Sidebar}
> >
<Styled.Content> <Styled.Content>
<Styled.Details withSeparators items={items} /> <Styled.Details withSeparators justifyItems="end" items={items} />
<Styled.Footer>{slotFooter}</Styled.Footer> <Styled.Footer>{slotFooter}</Styled.Footer>
</Styled.Content> </Styled.Content>

View File

@ -38,6 +38,7 @@ type ElementProps = {
slotTrigger?: React.ReactNode; slotTrigger?: React.ReactNode;
slotHeaderInner?: React.ReactNode; slotHeaderInner?: React.ReactNode;
slotFooter?: React.ReactNode; slotFooter?: React.ReactNode;
withClose?: boolean;
}; };
type StyleProps = { type StyleProps = {
@ -46,6 +47,7 @@ type StyleProps = {
hasHeaderBorder?: boolean; hasHeaderBorder?: boolean;
children?: React.ReactNode; children?: React.ReactNode;
className?: string; className?: string;
withAnimation?: boolean;
}; };
export type DialogProps = ElementProps & StyleProps; export type DialogProps = ElementProps & StyleProps;
@ -79,9 +81,11 @@ export const Dialog = ({
slotTrigger, slotTrigger,
slotHeaderInner, slotHeaderInner,
slotFooter, slotFooter,
withClose = true,
placement = DialogPlacement.Default, placement = DialogPlacement.Default,
portalContainer, portalContainer,
hasHeaderBorder = false, hasHeaderBorder = false,
withAnimation = false,
children, children,
className, className,
}: DialogProps) => { }: DialogProps) => {
@ -105,6 +109,7 @@ export const Dialog = ({
e.preventDefault(); e.preventDefault();
} }
}} }}
$withAnimation={withAnimation}
> >
<Styled.Header $withBorder={hasHeaderBorder}> <Styled.Header $withBorder={hasHeaderBorder}>
<Styled.HeaderTopRow> <Styled.HeaderTopRow>
@ -114,7 +119,7 @@ export const Dialog = ({
{title && <Styled.Title>{title}</Styled.Title>} {title && <Styled.Title>{title}</Styled.Title>}
{!preventClose && ( {!preventClose && withClose && (
<Styled.Close ref={closeButtonRef}> <Styled.Close ref={closeButtonRef}>
<Icon iconName={IconName.Close} /> <Icon iconName={IconName.Close} />
</Styled.Close> </Styled.Close>
@ -168,7 +173,7 @@ Styled.Overlay = styled(Overlay)`
} }
`; `;
Styled.Container = styled(Content)<{ placement: DialogPlacement }>` Styled.Container = styled(Content)<{ placement: DialogPlacement; $withAnimation?: boolean }>`
/* Params */ /* Params */
--dialog-inset: 1rem; --dialog-inset: 1rem;
--dialog-width: 30rem; --dialog-width: 30rem;
@ -224,7 +229,7 @@ Styled.Container = styled(Content)<{ placement: DialogPlacement }>`
outline: none; outline: none;
${({ placement }) => ${({ placement, $withAnimation }) =>
({ ({
[DialogPlacement.Default]: css` [DialogPlacement.Default]: css`
inset: var(--dialog-inset); inset: var(--dialog-inset);
@ -260,9 +265,11 @@ Styled.Container = styled(Content)<{ placement: DialogPlacement }>`
padding-bottom: var(--dialog-radius); */ padding-bottom: var(--dialog-radius); */
} }
@media (prefers-reduced-motion: no-preference) { ${$withAnimation &&
&[data-state='open'] { css`
animation: ${keyframes` @media (prefers-reduced-motion: no-preference) {
&[data-state='open'] {
animation: ${keyframes`
from { from {
opacity: 0; opacity: 0;
} }
@ -270,18 +277,19 @@ Styled.Container = styled(Content)<{ placement: DialogPlacement }>`
max-height: 0; max-height: 0;
} }
`} 0.15s var(--ease-out-expo); `} 0.15s var(--ease-out-expo);
} }
&[data-state='closed'] { &[data-state='closed'] {
animation: ${keyframes` animation: ${keyframes`
to { to {
opacity: 0; opacity: 0;
scale: 0.9; scale: 0.9;
max-height: 0; max-height: 0;
} }
`} 0.15s; `} 0.15s;
}
} }
} `}
`, `,
[DialogPlacement.Sidebar]: css` [DialogPlacement.Sidebar]: css`
--dialog-width: var(--sidebar-width); --dialog-width: var(--sidebar-width);
@ -291,50 +299,52 @@ Styled.Container = styled(Content)<{ placement: DialogPlacement }>`
margin-left: auto; margin-left: auto;
} }
@media (prefers-reduced-motion: no-preference) { ${$withAnimation &&
&[data-state='open'] { css`
animation: ${keyframes` @media (prefers-reduced-motion: no-preference) {
&[data-state='open'] {
animation: ${keyframes`
from { from {
translate: 100% 0; translate: 100% 0;
opacity: 0; opacity: 0;
} }
`} 0.15s var(--ease-out-expo); `} 0.15s var(--ease-out-expo);
} }
&[data-state='closed'] { &[data-state='closed'] {
animation: ${keyframes` animation: ${keyframes`
to { to {
translate: 100% 0; translate: 100% 0;
opacity: 0; opacity: 0;
} }
`} 0.15s var(--ease-out-expo); `} 0.15s var(--ease-out-expo);
}
} }
} `}
`, `,
[DialogPlacement.Inline]: css` [DialogPlacement.Inline]: css`
@media (prefers-reduced-motion: no-preference) { ${$withAnimation &&
&[data-state='open'] { css`
animation: ${keyframes` @media (prefers-reduced-motion: no-preference) {
&[data-state='open'] {
animation: ${keyframes`
from { from {
scale: 0.99; scale: 0.99;
opacity: 0; opacity: 0;
/* filter: blur(2px); */
/* backdrop-filter: none; */
} }
`} 0.15s var(--ease-out-expo); `} 0.15s var(--ease-out-expo);
} }
&[data-state='closed'] { &[data-state='closed'] {
animation: ${keyframes` animation: ${keyframes`
to { to {
scale: 0.99; scale: 0.99;
opacity: 0; opacity: 0;
/* filter: blur(2px); */
/* backdrop-filter: none; */
} }
`} 0.15s var(--ease-out-expo); `} 0.15s var(--ease-out-expo);
}
} }
} `}
`, `,
[DialogPlacement.FullScreen]: css` [DialogPlacement.FullScreen]: css`
--dialog-width: 100vw; --dialog-width: 100vw;

View File

@ -14,7 +14,7 @@ export const DiffArrowStory: Story<DiffArrowProps> = (args) => (
DiffArrowStory.argTypes = { DiffArrowStory.argTypes = {
direction: { direction: {
options: ['left', 'right'], options: ['left', 'right', 'up', 'down'],
control: { type: 'select' }, control: { type: 'select' },
defaultValue: 'right', defaultValue: 'right',
}, },

View File

@ -10,7 +10,7 @@ type ElementProps = {
type StyleProps = { type StyleProps = {
className?: string; className?: string;
direction?: 'right' | 'left'; direction?: 'right' | 'left' | 'up' | 'down';
}; };
export type DiffArrowProps = ElementProps & StyleProps; export type DiffArrowProps = ElementProps & StyleProps;
@ -57,5 +57,11 @@ Styled.DiffArrowContainer = styled.span<DiffArrowProps>`
left: css` left: css`
transform: scaleX(-1); transform: scaleX(-1);
`, `,
up: css`
transform: rotate(-90deg);
`,
down: css`
transform: rotate(90deg);
`,
}[direction || 'right'])} }[direction || 'right'])}
`; `;

View File

@ -75,7 +75,7 @@ Styled.DiffValue = styled.div<{ hasInvalidNewValue?: boolean }>`
${({ hasInvalidNewValue }) => ${({ hasInvalidNewValue }) =>
hasInvalidNewValue && hasInvalidNewValue &&
css` css`
color: var(--color-negative); color: var(--color-error);
`} `}
`; `;

View File

@ -33,9 +33,11 @@ export const DropdownHeaderMenu = <MenuItemValue extends string>({
return ( return (
<Root> <Root>
<Styled.Trigger className={className}> <Styled.Trigger className={className} asChild>
{children} <div>
<Styled.DropdownIconButton iconName={IconName.Caret} isToggle /> {children}
<Styled.DropdownIconButton iconName={IconName.Caret} isToggle />
</div>
</Styled.Trigger> </Styled.Trigger>
<Portal> <Portal>
<Styled.Content <Styled.Content
@ -85,7 +87,7 @@ Styled.Trigger = styled(Trigger)`
outline: none; outline: none;
:hover { :hover {
filter: brightness(1.1); filter: brightness(var(--hover-filter-base));
} }
`; `;

View File

@ -4,38 +4,43 @@ import { DropdownMenu } from '@/components/DropdownMenu';
import { StoryWrapper } from '.ladle/components'; import { StoryWrapper } from '.ladle/components';
export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>> = (args) => { export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>[0]> = (args) => {
const exampleItems = [
{
value: '1',
label: 'Item 1',
onSelect: () => alert('Item 1 action'),
},
{
value: '2',
label: 'Item 2',
onSelect: () => alert('Item 2 action'),
},
{
value: '3',
label: 'Item 3',
onSelect: () => alert('Item 3 action'),
},
];
return ( return (
<StoryWrapper> <StoryWrapper>
<DropdownMenu <DropdownMenu {...args}>
{...args}
items={exampleItems}
>
<span>Menu</span> <span>Menu</span>
</DropdownMenu> </DropdownMenu>
</StoryWrapper> </StoryWrapper>
); );
}; };
DropdownMenuStory.args = {}; DropdownMenuStory.args = {
items: [
{
value: '0',
label: 'Item 0',
onSelect: () => alert('Item 0 action'),
},
{
value: '1',
label: 'Item 1 (accent)',
onSelect: () => alert('Item 1 action'),
highlightColor: 'accent',
},
{
value: '2',
label: 'Item 2 (create)',
onSelect: () => alert('Item 2 action'),
highlightColor: 'create',
},
{
value: '3',
label: 'Item 3 (destroy)',
onSelect: () => alert('Item 3 action'),
highlightColor: 'destroy',
},
],
};
DropdownMenuStory.argTypes = { DropdownMenuStory.argTypes = {
align: { align: {

View File

@ -13,7 +13,7 @@ export type DropdownMenuItem<T> = {
label: React.ReactNode; label: React.ReactNode;
onSelect?: () => void; onSelect?: () => void;
separator?: boolean; separator?: boolean;
highlightColor?: 'accent' | 'positive' | 'negative'; highlightColor?: 'accent' | 'create' | 'destroy';
}; };
type StyleProps = { type StyleProps = {
@ -82,7 +82,7 @@ Styled.Separator = styled(Separator)`
margin: 0.25rem 1rem; margin: 0.25rem 1rem;
`; `;
Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'positive' | 'negative' }>` Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'create' | 'destroy' }>`
${popoverMixins.item} ${popoverMixins.item}
--item-font-size: var(--dropdownMenu-item-font-size); --item-font-size: var(--dropdownMenu-item-font-size);
${({ $highlightColor }) => ${({ $highlightColor }) =>
@ -90,11 +90,11 @@ Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'positive' | 'negative'
['accent']: ` ['accent']: `
--item-highlighted-textColor: var(--color-accent); --item-highlighted-textColor: var(--color-accent);
`, `,
['positive']: ` ['create']: `
--item-highlighted-textColor: var(--color-positive); --item-highlighted-textColor: var(--color-green);
`, `,
['negative']: ` ['destroy']: `
--item-highlighted-textColor: var(--color-negative); --item-highlighted-textColor: var(--color-red);
`, `,
}[$highlightColor])} }[$highlightColor])}

View File

@ -28,21 +28,22 @@ const exampleItems = [
}, },
]; ];
export const DropdownSelectMenuStory: Story<Parameters<typeof DropdownSelectMenu>> = (args) => { export const DropdownSelectMenuStory: Story<
Pick<Parameters<typeof DropdownSelectMenu>[0], 'items' | 'align' | 'sideOffset' | 'disabled'>
> = (args) => {
const [item, setItem] = useState(exampleItems[0].value); const [item, setItem] = useState(exampleItems[0].value);
return ( return (
<StoryWrapper> <StoryWrapper>
<DropdownSelectMenu <DropdownSelectMenu value={item} onValueChange={(value) => setItem(value)} {...args} />
items={exampleItems}
value={item}
onValueChange={(value) => setItem(value)}
{...args}
/>
</StoryWrapper> </StoryWrapper>
); );
}; };
DropdownSelectMenuStory.args = {}; DropdownSelectMenuStory.args = {
items: exampleItems,
sideOffset: 1,
disabled: false,
};
DropdownSelectMenuStory.argTypes = { DropdownSelectMenuStory.argTypes = {
align: { align: {

View File

@ -9,6 +9,7 @@ import {
RadioItem, RadioItem,
Portal, Portal,
} from '@radix-ui/react-dropdown-menu'; } from '@radix-ui/react-dropdown-menu';
import { CheckIcon } from '@radix-ui/react-icons';
import { type MenuItem } from '@/constants/menus'; import { type MenuItem } from '@/constants/menus';
@ -90,7 +91,9 @@ export const DropdownSelectMenu = <MenuItemValue extends string>({
{slotAfter} {slotAfter}
<Styled.ItemIndicator>{/* <CheckIcon /> */}</Styled.ItemIndicator> <Styled.ItemIndicator>
<CheckIcon />
</Styled.ItemIndicator>
</Styled.RadioItem> </Styled.RadioItem>
))} ))}
</RadioGroup> </RadioGroup>

View File

@ -32,7 +32,7 @@ export const FormInput = forwardRef<HTMLInputElement, FormInputProps>(
isValidationAttached={validationConfig?.attached} isValidationAttached={validationConfig?.attached}
> >
<Styled.InputContainer hasSlotRight={!!slotRight}> <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} /> <Input ref={ref} id={id} {...otherProps} />
</Styled.WithLabel> </Styled.WithLabel>
{slotRight} {slotRight}
@ -85,11 +85,11 @@ Styled.InputContainer = styled.div<{ hasSlotRight?: boolean }>`
`} `}
`; `;
Styled.WithLabel = styled(WithLabel)` Styled.WithLabel = styled(WithLabel)<{ disabled?: boolean }>`
${formMixins.inputLabel} ${formMixins.inputLabel}
label { label {
cursor: text; ${({ disabled }) => !disabled && 'cursor: text;'}
padding: var(--form-input-paddingY) var(--form-input-paddingX) 0; padding: var(--form-input-paddingY) var(--form-input-paddingX) 0;
} }
`; `;

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