Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a91e56ac3 | ||
|
|
4a64d59546 | ||
|
|
3fc43e8a12 | ||
|
|
c24a9229a6 | ||
|
|
90329d44d0 | ||
|
|
9a02bd3f1c | ||
|
|
adba11b462 |
+6
-4
@@ -41,9 +41,10 @@
|
||||
"@cosmjs/tendermint-rpc": "^0.31.0",
|
||||
"@dydxprotocol/v4-abacus": "^1.1.32",
|
||||
"@dydxprotocol/v4-client-js": "^1.0.11",
|
||||
"@dydxprotocol/v4-localization": "^1.1.5",
|
||||
"@dydxprotocol/v4-localization": "^1.1.6",
|
||||
"@ethersproject/providers": "^5.7.2",
|
||||
"@js-joda/core": "^5.5.3",
|
||||
"@radix-ui/react-accordion": "^1.1.2",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-collapsible": "^1.0.3",
|
||||
"@radix-ui/react-dialog": "^1.0.4",
|
||||
@@ -71,6 +72,7 @@
|
||||
"@reduxjs/toolkit": "^1.9.5",
|
||||
"@scure/bip32": "^1.3.0",
|
||||
"@scure/bip39": "^1.2.0",
|
||||
"@tanstack/react-query": "^5.17.9",
|
||||
"@types/lodash": "^4.14.195",
|
||||
"@types/styled-components": "^5.1.26",
|
||||
"@visx/axis": "^3.1.0",
|
||||
@@ -103,15 +105,15 @@
|
||||
"react-aria": "^3.25.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-number-format": "^5.2.2",
|
||||
"react-query": "^3.39.3",
|
||||
"react-redux": "^8.1.1",
|
||||
"react-router-dom": "^6.14.0",
|
||||
"react-stately": "^3.23.0",
|
||||
"reselect": "^4.1.8",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"styled-components": "^5.3.11",
|
||||
"use-latest": "^1.2.1",
|
||||
"viem": "^1.12.2",
|
||||
"wagmi": "^1.4.12"
|
||||
"viem": "^2.0.0",
|
||||
"wagmi": "^2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.22.5",
|
||||
|
||||
Generated
+4330
-596
File diff suppressed because it is too large
Load Diff
+26
-26
@@ -39,7 +39,7 @@
|
||||
"environments": {
|
||||
"dydxprotocol-dev": {
|
||||
"name": "v4 Dev",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydxprotocol-testnet",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -113,7 +113,7 @@
|
||||
},
|
||||
"dydxprotocol-dev-2": {
|
||||
"name": "v4 Dev 2",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydxprotocol-testnet",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -186,7 +186,7 @@
|
||||
},
|
||||
"dydxprotocol-dev-4": {
|
||||
"name": "v4 Dev 4",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydxprotocol-testnet",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -259,7 +259,7 @@
|
||||
},
|
||||
"dydxprotocol-dev-5": {
|
||||
"name": "v4 Dev 5",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydxprotocol-testnet",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -332,7 +332,7 @@
|
||||
},
|
||||
"dydxprotocol-staging": {
|
||||
"name": "v4 Staging",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydxprotocol-testnet",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -407,7 +407,7 @@
|
||||
},
|
||||
"dydxprotocol-staging-forced-update": {
|
||||
"name": "v4 Staging Forced Update",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydxprotocol-testnet",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -480,7 +480,7 @@
|
||||
},
|
||||
"dydxprotocol-staging-west": {
|
||||
"name": "v4 Staging West",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydxprotocol-testnet",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -555,7 +555,7 @@
|
||||
},
|
||||
"dydxprotocol-testnet": {
|
||||
"name": "v4 Public Testnet",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydx-testnet-4",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -579,8 +579,8 @@
|
||||
"endpoints": {
|
||||
"indexers": [
|
||||
{
|
||||
"api": "https://dydx-testnet.imperator.co",
|
||||
"socket": "wss://dydx-testnet.imperator.co"
|
||||
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||
}
|
||||
],
|
||||
"validators": [
|
||||
@@ -634,7 +634,7 @@
|
||||
},
|
||||
"dydxprotocol-testnet-dydx": {
|
||||
"name": "v4 Public Testnet/dYdX",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydx-testnet-4",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -710,7 +710,7 @@
|
||||
},
|
||||
"dydxprotocol-testnet-nodefleet": {
|
||||
"name": "v4 Public Testnet/nodefleet",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydx-testnet-4",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -734,8 +734,8 @@
|
||||
"endpoints": {
|
||||
"indexers": [
|
||||
{
|
||||
"api": "https://dydx-testnet.imperator.co",
|
||||
"socket": "wss://dydx-testnet.imperator.co"
|
||||
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||
}
|
||||
],
|
||||
"validators": [
|
||||
@@ -786,7 +786,7 @@
|
||||
},
|
||||
"dydxprotocol-testnet-kingnodes": {
|
||||
"name": "v4 Public Testnet/KingNodes",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydx-testnet-4",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -810,8 +810,8 @@
|
||||
"endpoints": {
|
||||
"indexers": [
|
||||
{
|
||||
"api": "https://dydx-testnet.imperator.co",
|
||||
"socket": "wss://dydx-testnet.imperator.co"
|
||||
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||
}
|
||||
],
|
||||
"validators": [
|
||||
@@ -862,7 +862,7 @@
|
||||
},
|
||||
"dydxprotocol-testnet-liquify": {
|
||||
"name": "v4 Public Testnet/Liquify",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydx-testnet-4",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -886,8 +886,8 @@
|
||||
"endpoints": {
|
||||
"indexers": [
|
||||
{
|
||||
"api": "https://dydx-testnet.imperator.co",
|
||||
"socket": "wss://dydx-testnet.imperator.co"
|
||||
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||
}
|
||||
],
|
||||
"validators": [
|
||||
@@ -938,7 +938,7 @@
|
||||
},
|
||||
"dydxprotocol-testnet-polkachu": {
|
||||
"name": "v4 Public Testnet/Polkahcu",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydx-testnet-4",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -962,8 +962,8 @@
|
||||
"endpoints": {
|
||||
"indexers": [
|
||||
{
|
||||
"api": "https://dydx-testnet.imperator.co",
|
||||
"socket": "wss://dydx-testnet.imperator.co"
|
||||
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||
}
|
||||
],
|
||||
"validators": [
|
||||
@@ -1005,7 +1005,7 @@
|
||||
},
|
||||
"dydxprotocol-testnet-bware": {
|
||||
"name": "v4 Public Testnet/BWare",
|
||||
"ethereumChainId": "5",
|
||||
"ethereumChainId": "11155111",
|
||||
"dydxChainId": "dydx-testnet-4",
|
||||
"chainName": "dYdX Chain",
|
||||
"chainLogo": "/dydx-chain.png",
|
||||
@@ -1029,8 +1029,8 @@
|
||||
"endpoints": {
|
||||
"indexers": [
|
||||
{
|
||||
"api": "https://dydx-testnet.imperator.co",
|
||||
"socket": "wss://dydx-testnet.imperator.co"
|
||||
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||
}
|
||||
],
|
||||
"validators": [
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
import { lazy, Suspense } from 'react';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
import styled, { AnyStyledComponent, css } from 'styled-components';
|
||||
import { WagmiConfig } from 'wagmi';
|
||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
import { WagmiProvider } from 'wagmi';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { GrazProvider } from 'graz';
|
||||
|
||||
import { AppRoute, DEFAULT_TRADE_ROUTE } from '@/constants/routes';
|
||||
@@ -120,9 +120,9 @@ const wrapProvider = (Component: React.ComponentType<any>, props?: any) => {
|
||||
};
|
||||
|
||||
const providers = [
|
||||
wrapProvider(WagmiProvider, { config }),
|
||||
wrapProvider(QueryClientProvider, { client: queryClient }),
|
||||
wrapProvider(GrazProvider),
|
||||
wrapProvider(WagmiConfig, { config }),
|
||||
wrapProvider(LocaleProvider),
|
||||
wrapProvider(RestrictionProvider),
|
||||
wrapProvider(DydxProvider),
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
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 { PlusIcon } from '@/icons';
|
||||
|
||||
export type AccordionItem = {
|
||||
header: React.ReactNode;
|
||||
content: React.ReactNode;
|
||||
};
|
||||
|
||||
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)`
|
||||
> *: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: 1rem 0.75rem;
|
||||
|
||||
color: var(--color-text-1);
|
||||
text-align: start;
|
||||
|
||||
&:hover {
|
||||
${Styled.Icon} {
|
||||
color: var(--color-text-2);
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
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 0.75rem 1rem;
|
||||
|
||||
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);
|
||||
}
|
||||
`;
|
||||
@@ -55,6 +55,7 @@ import {
|
||||
OverviewIcon,
|
||||
PencilIcon,
|
||||
PlayIcon,
|
||||
PlusIcon,
|
||||
PositionsIcon,
|
||||
PriceChartIcon,
|
||||
PrivacyIcon,
|
||||
@@ -130,6 +131,7 @@ export enum IconName {
|
||||
Overview = 'Overview',
|
||||
Pencil = 'Pencil',
|
||||
Play = 'Play',
|
||||
Plus = 'Plus',
|
||||
Positions = 'Positions',
|
||||
PriceChart = 'PriceChart',
|
||||
Privacy = 'Privacy',
|
||||
@@ -204,6 +206,7 @@ const icons = {
|
||||
[IconName.Overview]: OverviewIcon,
|
||||
[IconName.Pencil]: PencilIcon,
|
||||
[IconName.Play]: PlayIcon,
|
||||
[IconName.Plus]: PlusIcon,
|
||||
[IconName.Positions]: PositionsIcon,
|
||||
[IconName.PriceChart]: PriceChartIcon,
|
||||
[IconName.Privacy]: PrivacyIcon,
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export enum QueryKeys {
|
||||
ACCOUNT_BALANCE = 'ACCOUNT_BALANCE',
|
||||
LAUNCH_INCENTIVES = 'LAUNCH_INCENTIVES',
|
||||
TRANSACTION_STATUS = 'TRANSACTION_STATUS',
|
||||
}
|
||||
@@ -52,7 +52,7 @@ type WalletConnectionTypeConfig = {
|
||||
wagmiConnectorId?: string;
|
||||
};
|
||||
|
||||
export const walletConnectionTypes: Record<WalletConnectionType, WalletConnectionTypeConfig> = {
|
||||
export const WALLET_CONNECTION_TYPES: Record<WalletConnectionType, WalletConnectionTypeConfig> = {
|
||||
[WalletConnectionType.CoinbaseWalletSdk]: {
|
||||
name: 'Coinbase Wallet SDK',
|
||||
wagmiConnectorId: 'coinbaseWallet',
|
||||
@@ -110,7 +110,7 @@ export const WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS = Object.values(
|
||||
WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS
|
||||
);
|
||||
|
||||
type WalletConfig = {
|
||||
export type WalletConfig = {
|
||||
type: WalletType;
|
||||
stringKey: string;
|
||||
icon: string;
|
||||
@@ -274,6 +274,17 @@ export type WalletConnection = {
|
||||
provider?: ExternalProvider;
|
||||
};
|
||||
|
||||
export type WalletConnectConfig = {
|
||||
client: {
|
||||
name: string;
|
||||
description: string;
|
||||
iconUrl: string;
|
||||
};
|
||||
v2: {
|
||||
projectId: string;
|
||||
};
|
||||
};
|
||||
|
||||
// dYdX Chain wallets
|
||||
export const COSMOS_DERIVATION_PATH = "m/44'/118'/0'/0/0";
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { shallowEqual, useSelector } from 'react-redux';
|
||||
import { useBalance } from 'wagmi';
|
||||
import { useBalance, useBlockNumber } from 'wagmi';
|
||||
import { StargateClient } from '@cosmjs/stargate';
|
||||
import { useQuery } from 'react-query';
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { formatUnits } from 'viem';
|
||||
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { QueryKeys } from '@/constants/queries';
|
||||
import { EvmAddress } from '@/constants/wallets';
|
||||
|
||||
import { convertBech32Address } from '@/lib/addressUtils';
|
||||
@@ -52,15 +53,27 @@ export const useAccountBalance = ({
|
||||
const evmChainId = Number(ENVIRONMENT_CONFIG_MAP[selectedNetwork].ethereumChainId);
|
||||
const stakingBalances = useSelector(getStakingBalances, shallowEqual);
|
||||
|
||||
const evmQuery = useBalance({
|
||||
enabled: Boolean(!isCosmosChain && addressOrDenom?.startsWith('0x')),
|
||||
const queryClient = useQueryClient();
|
||||
const { data: blockNumber } = useBlockNumber({ watch: true });
|
||||
const {
|
||||
data: evmQuery,
|
||||
status: evmBalanceStatus,
|
||||
fetchStatus: evmBalanceFetchStatus,
|
||||
queryKey,
|
||||
} = useBalance({
|
||||
query: {
|
||||
enabled: Boolean(!isCosmosChain && addressOrDenom?.startsWith('0x')),
|
||||
},
|
||||
address: evmAddress,
|
||||
chainId: typeof chainId === 'number' ? chainId : Number(evmChainId),
|
||||
token:
|
||||
addressOrDenom === CHAIN_DEFAULT_TOKEN_ADDRESS ? undefined : (addressOrDenom as EvmAddress),
|
||||
watch: true,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
queryClient.invalidateQueries({ queryKey });
|
||||
}, [blockNumber]);
|
||||
|
||||
const cosmosQueryFn = useCallback(async () => {
|
||||
if (dydxAddress && bech32AddrPrefix && rpc && addressOrDenom) {
|
||||
const address = convertBech32Address({
|
||||
@@ -78,7 +91,7 @@ export const useAccountBalance = ({
|
||||
|
||||
const cosmosQuery = useQuery({
|
||||
enabled: Boolean(isCosmosChain && dydxAddress && bech32AddrPrefix && rpc && addressOrDenom),
|
||||
queryKey: `accountBalances_${chainId}_${addressOrDenom}`,
|
||||
queryKey: [QueryKeys.ACCOUNT_BALANCE, chainId, addressOrDenom],
|
||||
queryFn: cosmosQueryFn,
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnMount: false,
|
||||
@@ -87,8 +100,11 @@ export const useAccountBalance = ({
|
||||
staleTime: 10_000,
|
||||
});
|
||||
|
||||
const { formatted: evmBalance } = evmQuery.data || {};
|
||||
const balance = isCosmosChain ? cosmosQuery.data : evmBalance;
|
||||
const balance = isCosmosChain
|
||||
? cosmosQuery.data
|
||||
: evmQuery
|
||||
? formatUnits(evmQuery?.value, evmQuery?.decimals)
|
||||
: undefined;
|
||||
|
||||
const nativeTokenCoinBalance = balances?.[chainTokenDenom];
|
||||
const nativeTokenBalance = MustBigNumber(nativeTokenCoinBalance?.amount);
|
||||
@@ -104,7 +120,7 @@ export const useAccountBalance = ({
|
||||
nativeTokenBalance,
|
||||
nativeStakingBalance,
|
||||
usdcBalance,
|
||||
queryStatus: isCosmosChain ? cosmosQuery.status : evmQuery.status,
|
||||
isQueryFetching: isCosmosChain ? cosmosQuery.isFetching : evmQuery.fetchStatus === 'fetching',
|
||||
queryStatus: isCosmosChain ? cosmosQuery.status : evmBalanceStatus,
|
||||
isQueryFetching: isCosmosChain ? cosmosQuery.isFetching : evmBalanceFetchStatus === 'fetching',
|
||||
};
|
||||
};
|
||||
|
||||
@@ -39,7 +39,6 @@ const useAccountsContext = () => {
|
||||
walletConnectionType,
|
||||
selectWalletType,
|
||||
selectedWalletType,
|
||||
selectedWalletError,
|
||||
evmAddress,
|
||||
signerWagmi,
|
||||
publicClientWagmi,
|
||||
@@ -300,9 +299,7 @@ const useAccountsContext = () => {
|
||||
walletConnectionType,
|
||||
|
||||
// Wallet selection
|
||||
selectWalletType,
|
||||
selectedWalletType,
|
||||
selectedWalletError,
|
||||
|
||||
// Wallet connection (EVM)
|
||||
evmAddress,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { createContext, useContext, useCallback, useEffect, useMemo } from 'react';
|
||||
import { useQuery } from 'react-query';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { LOCAL_STORAGE_VERSIONS, LocalStorageKey } from '@/constants/localStorage';
|
||||
import { type TransferNotifcation } from '@/constants/notifications';
|
||||
import { QueryKeys } from '@/constants/queries';
|
||||
import { useAccounts } from '@/hooks/useAccounts';
|
||||
|
||||
import { fetchSquidStatus, STATUS_ERROR_GRACE_PERIOD } from '@/lib/squid';
|
||||
@@ -68,8 +69,8 @@ const useLocalNotificationsContext = () => {
|
||||
[transferNotifications]
|
||||
);
|
||||
|
||||
useQuery({
|
||||
queryKey: 'getTransactionStatus',
|
||||
const { data: newTransferNotifications } = useQuery({
|
||||
queryKey: [QueryKeys.TRANSACTION_STATUS],
|
||||
queryFn: async () => {
|
||||
const processTransferNotifications = async (transferNotifications: TransferNotifcation[]) => {
|
||||
const newTransferNotifications = await Promise.all(
|
||||
@@ -84,10 +85,11 @@ const useLocalNotificationsContext = () => {
|
||||
status: currentStatus,
|
||||
} = transferNotification;
|
||||
|
||||
// @ts-ignore status.errors is not in the type definition but can be returned
|
||||
// also error can some time come back as an empty object so we need to ignore for that
|
||||
const hasErrors = !!currentStatus?.errors ||
|
||||
(currentStatus?.error && Object.keys(currentStatus.error).length !== 0);
|
||||
const hasErrors =
|
||||
// @ts-ignore status.errors is not in the type definition but can be returned
|
||||
// also error can some time come back as an empty object so we need to ignore for that
|
||||
!!currentStatus?.errors ||
|
||||
(currentStatus?.error && Object.keys(currentStatus.error).length !== 0);
|
||||
|
||||
if (
|
||||
!hasErrors &&
|
||||
@@ -95,11 +97,14 @@ const useLocalNotificationsContext = () => {
|
||||
currentStatus?.squidTransactionStatus === 'ongoing')
|
||||
) {
|
||||
try {
|
||||
const status = await fetchSquidStatus({
|
||||
transactionId: txHash,
|
||||
toChainId,
|
||||
fromChainId,
|
||||
}, isCctp);
|
||||
const status = await fetchSquidStatus(
|
||||
{
|
||||
transactionId: txHash,
|
||||
toChainId,
|
||||
fromChainId,
|
||||
},
|
||||
isCctp
|
||||
);
|
||||
|
||||
if (status) {
|
||||
transferNotification.status = status;
|
||||
@@ -121,12 +126,18 @@ const useLocalNotificationsContext = () => {
|
||||
|
||||
return newTransferNotifications;
|
||||
};
|
||||
|
||||
const newTransferNotifications = await processTransferNotifications(transferNotifications);
|
||||
setTransferNotifications(newTransferNotifications);
|
||||
return newTransferNotifications;
|
||||
},
|
||||
refetchInterval: TRANSFER_STATUS_FETCH_INTERVAL,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!newTransferNotifications) return;
|
||||
setTransferNotifications(newTransferNotifications);
|
||||
}, [newTransferNotifications]);
|
||||
|
||||
return {
|
||||
transferNotifications,
|
||||
addTransferNotification,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useNetwork, useSwitchNetwork } from 'wagmi';
|
||||
import { UseSwitchChainReturnType, useAccount, useSwitchChain } from 'wagmi';
|
||||
|
||||
export const useMatchingEvmNetwork = ({
|
||||
chainId,
|
||||
@@ -8,10 +8,10 @@ export const useMatchingEvmNetwork = ({
|
||||
}: {
|
||||
chainId?: string | number;
|
||||
switchAutomatically?: boolean;
|
||||
onError?: (error: Error) => void;
|
||||
onError?: Parameters<UseSwitchChainReturnType['switchChainAsync']>[1]['onError'];
|
||||
}) => {
|
||||
const { chain } = useNetwork();
|
||||
const { isLoading, switchNetworkAsync } = useSwitchNetwork({ onError });
|
||||
const { chain } = useAccount();
|
||||
const { switchChainAsync, isPending } = useSwitchChain();
|
||||
|
||||
// If chainId is not a number, we can assume it is a non EVM compatible chain
|
||||
const isMatchingNetwork = useMemo(
|
||||
@@ -21,7 +21,14 @@ export const useMatchingEvmNetwork = ({
|
||||
|
||||
const matchNetwork = useCallback(async () => {
|
||||
if (!isMatchingNetwork) {
|
||||
await switchNetworkAsync?.(Number(chainId));
|
||||
await switchChainAsync?.(
|
||||
{
|
||||
chainId: Number(chainId),
|
||||
},
|
||||
{
|
||||
onError,
|
||||
}
|
||||
);
|
||||
}
|
||||
}, [chainId, chain]);
|
||||
|
||||
@@ -34,6 +41,6 @@ export const useMatchingEvmNetwork = ({
|
||||
return {
|
||||
isMatchingNetwork,
|
||||
matchNetwork,
|
||||
isSwitchingNetwork: isLoading,
|
||||
isSwitchingNetwork: isPending,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -104,12 +104,13 @@ export const useWalletConnection = () => {
|
||||
[walletConnectConfig, walletType, walletConnectionType]
|
||||
);
|
||||
|
||||
const { connectAsync: connectWagmi } = useConnectWagmi({ connector: wagmiConnector })
|
||||
const { connectAsync: connectWagmi } = useConnectWagmi();
|
||||
const { suggestAndConnect: connectGraz } = useConnectGraz();
|
||||
|
||||
const connectWallet = useCallback(
|
||||
async ({ walletType }: { walletType: WalletType }) => {
|
||||
const walletConnection = getWalletConnection({ walletType });
|
||||
console.log({ walletConnection });
|
||||
|
||||
try {
|
||||
if (!walletConnection) {
|
||||
@@ -133,13 +134,17 @@ export const useWalletConnection = () => {
|
||||
}
|
||||
} else {
|
||||
if (!isConnectedWagmi) {
|
||||
await connectWagmi({
|
||||
connector: resolveWagmiConnector({
|
||||
walletType,
|
||||
walletConnection,
|
||||
walletConnectConfig,
|
||||
}),
|
||||
const connector = resolveWagmiConnector({
|
||||
walletType,
|
||||
walletConnection,
|
||||
walletConnectConfig,
|
||||
});
|
||||
|
||||
if (connector) {
|
||||
await connectWagmi({
|
||||
connector,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -156,7 +161,7 @@ export const useWalletConnection = () => {
|
||||
walletConnectionType: walletConnection.type,
|
||||
};
|
||||
},
|
||||
[isConnectedGraz, signerGraz, isConnectedWagmi, signerWagmi]
|
||||
[isConnectedGraz, signerGraz, isConnectedWagmi, signerWagmi, walletConnectConfig]
|
||||
);
|
||||
|
||||
const disconnectWallet = useCallback(async () => {
|
||||
@@ -204,10 +209,9 @@ export const useWalletConnection = () => {
|
||||
})();
|
||||
}, [selectedWalletType, signerWagmi, signerGraz]);
|
||||
|
||||
const selectWalletType = async (walletType: WalletType | undefined) => {
|
||||
const selectWalletType = (walletType: WalletType | undefined) => {
|
||||
if (selectedWalletType) {
|
||||
setSelectedWalletType(undefined);
|
||||
await new Promise(requestAnimationFrame);
|
||||
}
|
||||
|
||||
setSelectedWalletType(walletType);
|
||||
|
||||
@@ -44,6 +44,7 @@ export { default as OrderbookIcon } from './orderbook.svg';
|
||||
export { default as OverviewIcon } from './overview.svg';
|
||||
export { default as PencilIcon } from './pencil.svg';
|
||||
export { default as PlayIcon } from './play.svg';
|
||||
export { default as PlusIcon } from './plus.svg';
|
||||
export { default as PortfolioIcon } from './portfolio.svg';
|
||||
export { default as PositionsIcon } from './positions.svg';
|
||||
export { default as PriceChartIcon } from './price-chart.svg';
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg fill="none" height="12" viewBox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="m6.75.75c0-.198912-.07902-.389678-.21967-.53033-.14065-.1406525-.33142-.21967-.53033-.21967s-.38968.0790175-.53033.21967c-.14065.140652-.21967.331418-.21967.53033v4.5h-4.5c-.198912 0-.389678.07902-.53033.21967-.1406525.14065-.21967.33142-.21967.53033s.0790175.38968.21967.53033c.140652.14065.331418.21967.53033.21967h4.5v4.5c0 .1989.07902.3897.21967.5303.14065.1407.33142.2197.53033.2197s.38968-.079.53033-.2197c.14065-.1406.21967-.3314.21967-.5303v-4.5h4.5c.1989 0 .3897-.07902.5303-.21967.1407-.14065.2197-.33142.2197-.53033s-.079-.38968-.2197-.53033c-.1406-.14065-.3314-.21967-.5303-.21967h-4.5z" fill="currentColor"/></svg>
|
||||
|
After Width: | Height: | Size: 731 B |
+112
-118
@@ -1,7 +1,6 @@
|
||||
import { createConfig, configureChains, mainnet, Chain, Connector, usePublicClient } from 'wagmi';
|
||||
import { goerli } from 'wagmi/chains';
|
||||
|
||||
import { createConfig, createConnector, http, usePublicClient } from 'wagmi';
|
||||
import {
|
||||
type Chain,
|
||||
arbitrum,
|
||||
arbitrumGoerli,
|
||||
avalanche,
|
||||
@@ -26,34 +25,33 @@ import {
|
||||
fantomTestnet,
|
||||
celo,
|
||||
celoAlfajores,
|
||||
} from 'viem/chains';
|
||||
mainnet,
|
||||
goerli,
|
||||
sepolia,
|
||||
} from 'wagmi/chains';
|
||||
|
||||
import { alchemyProvider } from 'wagmi/providers/alchemy';
|
||||
import { jsonRpcProvider } from 'wagmi/providers/jsonRpc';
|
||||
import { publicProvider } from 'wagmi/providers/public';
|
||||
|
||||
import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet';
|
||||
import { InjectedConnector } from 'wagmi/connectors/injected';
|
||||
import { MetaMaskConnector } from 'wagmi/connectors/metaMask';
|
||||
import { WalletConnectConnector } from 'wagmi/connectors/walletConnect';
|
||||
import { coinbaseWallet, injected, metaMask, walletConnect } from 'wagmi/connectors';
|
||||
import type { ExternalProvider } from '@ethersproject/providers';
|
||||
|
||||
import {
|
||||
type WalletConnectConfig,
|
||||
type WalletConnection,
|
||||
WalletConnectionType,
|
||||
type WalletType,
|
||||
walletConnectionTypes,
|
||||
WalletType,
|
||||
WALLET_CONNECTION_TYPES,
|
||||
wallets,
|
||||
WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS,
|
||||
WalletConfig,
|
||||
} from '@/constants/wallets';
|
||||
|
||||
import { isTruthy } from './isTruthy';
|
||||
import { log } from './telemetry';
|
||||
|
||||
// Config
|
||||
|
||||
export const WAGMI_SUPPORTED_CHAINS: Chain[] = [
|
||||
const WAGMI_SUPPORTED_CHAINS: Parameters<typeof createConfig>[0]['chains'] = [
|
||||
mainnet,
|
||||
goerli,
|
||||
|
||||
sepolia,
|
||||
arbitrum,
|
||||
arbitrumGoerli,
|
||||
avalanche,
|
||||
@@ -80,118 +78,104 @@ export const WAGMI_SUPPORTED_CHAINS: Chain[] = [
|
||||
celoAlfajores,
|
||||
];
|
||||
|
||||
const { chains, publicClient, webSocketPublicClient } = configureChains(
|
||||
WAGMI_SUPPORTED_CHAINS,
|
||||
[
|
||||
import.meta.env.VITE_ALCHEMY_API_KEY &&
|
||||
alchemyProvider({ apiKey: import.meta.env.VITE_ALCHEMY_API_KEY }),
|
||||
jsonRpcProvider({
|
||||
rpc: (chain) => ({ http: chain.rpcUrls.default.http[0] }),
|
||||
}),
|
||||
publicProvider(),
|
||||
].filter(isTruthy)
|
||||
);
|
||||
export const config = createConfig({
|
||||
chains: WAGMI_SUPPORTED_CHAINS,
|
||||
transports: Object.fromEntries(
|
||||
Object.values(WAGMI_SUPPORTED_CHAINS).map(({ id }) => [id, http()])
|
||||
),
|
||||
});
|
||||
|
||||
const injectedConnectorOptions = {
|
||||
chains,
|
||||
options: {
|
||||
name: 'Injected',
|
||||
const createdInjectedConnectorWithProvider = ({ provider }: { provider: ExternalProvider }) => {
|
||||
console.log(provider);
|
||||
return injected({
|
||||
target() {
|
||||
return {
|
||||
id: 'windowProvider',
|
||||
name: 'Injected',
|
||||
provider,
|
||||
};
|
||||
},
|
||||
shimDisconnect: true,
|
||||
shimChainChangedDisconnect: false,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
type WalletConnectConfig = {
|
||||
client: {
|
||||
name: string;
|
||||
description: string;
|
||||
iconUrl: string;
|
||||
};
|
||||
v2: {
|
||||
projectId: string;
|
||||
};
|
||||
const getConnector = ({
|
||||
walletConnectionType,
|
||||
walletConnectConfig,
|
||||
}: {
|
||||
walletConnectionType: WalletConnectionType;
|
||||
walletConnectConfig: WalletConnectConfig;
|
||||
}) => {
|
||||
console.log(walletConnectionType);
|
||||
switch (walletConnectionType) {
|
||||
case WalletConnectionType.WalletConnect2:
|
||||
return [
|
||||
walletConnect(
|
||||
getConnectorInfoForWc2({
|
||||
walletConnectConfig,
|
||||
})
|
||||
),
|
||||
];
|
||||
case WalletConnectionType.CoinbaseWalletSdk:
|
||||
return [
|
||||
coinbaseWallet({
|
||||
appName: 'dYdX',
|
||||
appLogoUrl: walletConnectConfig.client.iconUrl,
|
||||
reloadOnDisconnect: false,
|
||||
darkMode: true,
|
||||
}),
|
||||
];
|
||||
case WalletConnectionType.InjectedEip1193:
|
||||
return injected({
|
||||
target() {
|
||||
return {
|
||||
id: 'windowProvider',
|
||||
name: 'Injected',
|
||||
provider: window.ethereum,
|
||||
};
|
||||
},
|
||||
shimDisconnect: true,
|
||||
});
|
||||
case WalletConnectionType.CosmosSigner:
|
||||
default: {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getWalletconnect2ConnectorOptions = (
|
||||
config: WalletConnectConfig
|
||||
): ConstructorParameters<typeof WalletConnectConnector>[0] => ({
|
||||
chains,
|
||||
options: {
|
||||
projectId: config.v2.projectId,
|
||||
const getConnectorInfoForWc2 = ({
|
||||
walletConnectId,
|
||||
walletConnectConfig,
|
||||
}: {
|
||||
walletConnectId?: string;
|
||||
walletConnectConfig: WalletConnectConfig;
|
||||
}) => {
|
||||
const explorerRecommendedWalletIds = walletConnectId
|
||||
? [walletConnectId]
|
||||
: WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS;
|
||||
|
||||
return {
|
||||
projectId: walletConnectConfig.v2.projectId,
|
||||
metadata: {
|
||||
name: config.client.name,
|
||||
description: config.client.description,
|
||||
name: walletConnectConfig.client.name,
|
||||
description: walletConnectConfig.client.description,
|
||||
url: import.meta.env.VITE_BASE_URL,
|
||||
icons: [config.client.iconUrl],
|
||||
icons: [walletConnectConfig.client.iconUrl],
|
||||
},
|
||||
showQrModal: true,
|
||||
qrModalOptions: {
|
||||
themeMode: 'dark' as const,
|
||||
themeVariables: {
|
||||
'--wcm-accent-color': '#5973fe',
|
||||
'--wcm-accent-color': 'var(--color-accent)',
|
||||
'--wcm-font-family': 'var(--fontFamily-base)',
|
||||
'--wcm-background-color': 'var(--color-accent)',
|
||||
},
|
||||
explorerRecommendedWalletIds: WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS,
|
||||
explorerRecommendedWalletIds,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const getConnectors = (walletConnectConfig: WalletConnectConfig) => [
|
||||
new MetaMaskConnector({
|
||||
chains,
|
||||
options: {
|
||||
shimDisconnect: true,
|
||||
},
|
||||
}),
|
||||
new CoinbaseWalletConnector({
|
||||
chains,
|
||||
options: {
|
||||
appName: 'dYdX',
|
||||
reloadOnDisconnect: false,
|
||||
},
|
||||
}),
|
||||
new WalletConnectConnector(getWalletconnect2ConnectorOptions(walletConnectConfig)),
|
||||
new InjectedConnector(injectedConnectorOptions),
|
||||
];
|
||||
|
||||
export const config = createConfig({
|
||||
autoConnect: true,
|
||||
// connectors,
|
||||
publicClient,
|
||||
webSocketPublicClient,
|
||||
});
|
||||
|
||||
// Custom connectors
|
||||
|
||||
import type { ExternalProvider } from '@ethersproject/providers';
|
||||
|
||||
// Create a custom wagmi InjectedConnector using a specific injected EIP-1193 provider (instead of wagmi's default detection logic)
|
||||
const createInjectedConnectorWithProvider = (provider: ExternalProvider) =>
|
||||
new (class extends InjectedConnector {
|
||||
getProvider = async () =>
|
||||
provider as unknown as Awaited<ReturnType<InjectedConnector['getProvider']>>;
|
||||
})(injectedConnectorOptions) as InjectedConnector;
|
||||
|
||||
const createWalletConnect2ConnectorWithId = (
|
||||
walletconnectId: string,
|
||||
walletConnectConfig: WalletConnectConfig
|
||||
) => {
|
||||
const walletconnect2ConnectorOptions = getWalletconnect2ConnectorOptions(walletConnectConfig);
|
||||
return new WalletConnectConnector({
|
||||
...walletconnect2ConnectorOptions,
|
||||
options: {
|
||||
...walletconnect2ConnectorOptions.options,
|
||||
qrModalOptions: {
|
||||
...walletconnect2ConnectorOptions.options.qrModalOptions,
|
||||
explorerRecommendedWalletIds: [walletconnectId],
|
||||
explorerExcludedWalletIds: 'ALL',
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
// Custom connector from wallet selection
|
||||
|
||||
export const resolveWagmiConnector = ({
|
||||
walletType,
|
||||
walletConnection,
|
||||
@@ -202,13 +186,23 @@ export const resolveWagmiConnector = ({
|
||||
walletConnectConfig: WalletConnectConfig;
|
||||
}) => {
|
||||
const walletConfig = wallets[walletType];
|
||||
const walletConnectionConfig = walletConnectionTypes[walletConnection.type];
|
||||
|
||||
return walletConnection.type === WalletConnectionType.InjectedEip1193 && walletConnection.provider
|
||||
? createInjectedConnectorWithProvider(walletConnection.provider)
|
||||
: walletConnection.type === WalletConnectionType.WalletConnect2 && walletConfig.walletconnect2Id
|
||||
? createWalletConnect2ConnectorWithId(walletConfig.walletconnect2Id, walletConnectConfig)
|
||||
: getConnectors(walletConnectConfig).find(
|
||||
({ id }: { id: string }) => id === walletConnectionConfig.wagmiConnectorId
|
||||
);
|
||||
if (walletConnection.type === WalletConnectionType.InjectedEip1193 && walletConnection.provider) {
|
||||
if (walletType === WalletType.MetaMask) {
|
||||
return metaMask();
|
||||
}
|
||||
return createdInjectedConnectorWithProvider({ provider: walletConnection.provider });
|
||||
} else if (
|
||||
walletConnection.type === WalletConnectionType.WalletConnect2 &&
|
||||
walletConfig.walletconnect2Id
|
||||
) {
|
||||
return walletConnect(
|
||||
getConnectorInfoForWc2({
|
||||
walletConnectId: walletConfig.walletconnect2Id,
|
||||
walletConnectConfig,
|
||||
})
|
||||
);
|
||||
} else {
|
||||
return getConnector({ walletConnectionType: walletConnection.type, walletConnectConfig });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useQuery } from 'react-query';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import styled, { AnyStyledComponent } from 'styled-components';
|
||||
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { ButtonAction } from '@/constants/buttons';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { QueryKeys } from '@/constants/queries';
|
||||
|
||||
import breakpoints from '@/styles/breakpoints';
|
||||
import { useAccounts, useBreakpoints, useStringGetter } from '@/hooks';
|
||||
@@ -24,6 +25,8 @@ import { openDialog } from '@/state/dialogs';
|
||||
|
||||
import { log } from '@/lib/telemetry';
|
||||
|
||||
const SEASON_NUMBER = 2;
|
||||
|
||||
export const LaunchIncentivesPanel = () => {
|
||||
const { isNotTablet } = useBreakpoints();
|
||||
const dispatch = useDispatch();
|
||||
@@ -66,17 +69,24 @@ const EstimatedRewards = () => {
|
||||
const stringGetter = useStringGetter();
|
||||
const { dydxAddress } = useAccounts();
|
||||
|
||||
const { data, isLoading } = useQuery({
|
||||
const { data, isLoading, status, error } = useQuery({
|
||||
enabled: !!dydxAddress,
|
||||
queryKey: `launch_incentives_rewards_${dydxAddress ?? ''}`,
|
||||
queryKey: [QueryKeys.LAUNCH_INCENTIVES, dydxAddress, SEASON_NUMBER],
|
||||
queryFn: async () => {
|
||||
if (!dydxAddress) return undefined;
|
||||
const resp = await fetch(`https://cloud.chaoslabs.co/query/api/dydx/points/${dydxAddress}`);
|
||||
const resp = await fetch(
|
||||
`https://cloud.chaoslabs.co/query/api/dydx/points/${dydxAddress}?n=${SEASON_NUMBER}`
|
||||
);
|
||||
return (await resp.json())?.incentivePoints;
|
||||
},
|
||||
onError: (error: Error) => log('LaunchIncentives/fetchPoints', error),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (status === 'error') {
|
||||
log('LaunchIncentives/fetchPoints', error);
|
||||
}
|
||||
}, [status]);
|
||||
|
||||
return (
|
||||
<Styled.EstimatedRewardsCard>
|
||||
<Styled.EstimatedRewardsCardContent>
|
||||
@@ -85,9 +95,7 @@ const EstimatedRewards = () => {
|
||||
<Styled.Season>
|
||||
{stringGetter({
|
||||
key: STRING_KEYS.LAUNCH_INCENTIVES_SEASON_NUM,
|
||||
params: {
|
||||
SEASON_NUMBER: 1,
|
||||
},
|
||||
params: { SEASON_NUMBER },
|
||||
})}
|
||||
</Styled.Season>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import styled, { AnyStyledComponent } from 'styled-components';
|
||||
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { useStringGetter } from '@/hooks';
|
||||
|
||||
import { Accordion } from '@/components/Accordion';
|
||||
import { Link } from '@/components/Link';
|
||||
import { Panel } from '@/components/Panel';
|
||||
|
||||
const REWARDS_LEARN_MORE_LINK = ''; // to be configured
|
||||
|
||||
export const RewardsHelpPanel = () => {
|
||||
const stringGetter = useStringGetter();
|
||||
|
||||
return (
|
||||
<Styled.HelpCard
|
||||
slotHeader={
|
||||
<Styled.Header>
|
||||
<h3>{stringGetter({ key: STRING_KEYS.HELP })}</h3>
|
||||
{REWARDS_LEARN_MORE_LINK && (
|
||||
<Link withIcon href={REWARDS_LEARN_MORE_LINK}>
|
||||
{stringGetter({ key: STRING_KEYS.LEARN_MORE })}
|
||||
</Link>
|
||||
)}
|
||||
</Styled.Header>
|
||||
}
|
||||
>
|
||||
<Accordion
|
||||
items={[
|
||||
{
|
||||
header: 'Who is eligible for trading rewards?',
|
||||
content: 'All traders are eligible for trading rewards.',
|
||||
},
|
||||
{
|
||||
header: 'How do trading rewards work?',
|
||||
content:
|
||||
'Immediately after each fill, trading rewards are sent directly to the trader’s dYdX Chain address, based on the amount of fees paid by the trader.',
|
||||
},
|
||||
{
|
||||
header: 'How do I claim my rewards?',
|
||||
content:
|
||||
'Each block, trading rewards are automatically sent directly to the trader’s dYdX Chain address.',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Styled.HelpCard>
|
||||
);
|
||||
};
|
||||
|
||||
const Styled: Record<string, AnyStyledComponent> = {};
|
||||
|
||||
Styled.HelpCard = styled(Panel)`
|
||||
--panel-content-paddingY: 0;
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
padding: 0;
|
||||
gap: 0;
|
||||
|
||||
text-align: start;
|
||||
`;
|
||||
|
||||
Styled.Header = styled.div`
|
||||
${layoutMixins.spacedRow}
|
||||
gap: 1ch;
|
||||
|
||||
padding: 1.25rem 1.5rem;
|
||||
border-bottom: var(--border-width) solid var(--border-color);
|
||||
|
||||
font: var(--font-small-book);
|
||||
|
||||
h3 {
|
||||
font: var(--font-medium-book);
|
||||
color: var(--color-text-2);
|
||||
}
|
||||
`;
|
||||
|
||||
Styled.Link = styled(Link)`
|
||||
display: inline-flex;
|
||||
`;
|
||||
@@ -114,8 +114,8 @@ export const MarketDetails: React.FC = () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'base-initial-margin-fraction',
|
||||
label: stringGetter({ key: STRING_KEYS.BASE_INITIAL_MARGIN_FRACTION }),
|
||||
key: 'initial-margin-fraction',
|
||||
label: stringGetter({ key: STRING_KEYS.INITIAL_MARGIN_FRACTION }),
|
||||
tooltip: 'initial-margin-fraction',
|
||||
value: <Output useGrouping value={initialMarginFraction} type={OutputType.SmallPercent} />,
|
||||
},
|
||||
|
||||
@@ -3,19 +3,18 @@ import styled, { AnyStyledComponent } from 'styled-components';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { AlertType } from '@/constants/alerts';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
|
||||
import { WalletType, wallets } from '@/constants/wallets';
|
||||
import { ButtonAction, ButtonSize } from '@/constants/buttons';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { WalletType, wallets } from '@/constants/wallets';
|
||||
import { useStringGetter, useURLConfigs } from '@/hooks';
|
||||
import { useDisplayedWallets } from '@/hooks/useDisplayedWallets';
|
||||
import { useWalletConnection } from '@/hooks/useWalletConnection';
|
||||
|
||||
import { AlertMessage } from '@/components/AlertMessage';
|
||||
import { Button } from '@/components/Button';
|
||||
import { Icon } from '@/components/Icon';
|
||||
import { Link } from '@/components/Link';
|
||||
|
||||
import { useAccounts, useStringGetter, useURLConfigs } from '@/hooks';
|
||||
import { useDisplayedWallets } from '@/hooks/useDisplayedWallets';
|
||||
|
||||
import { breakpoints } from '@/styles';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
|
||||
@@ -25,7 +24,7 @@ export const ChooseWallet = () => {
|
||||
|
||||
const displayedWallets = useDisplayedWallets();
|
||||
|
||||
const { selectWalletType, selectedWalletType, selectedWalletError } = useAccounts();
|
||||
const { selectWalletType, selectedWalletType, selectedWalletError } = useWalletConnection();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -86,13 +86,7 @@ export const GenerateKeys = ({
|
||||
].includes(status);
|
||||
|
||||
const signTypedData = getSignTypedData(selectedNetwork);
|
||||
const { signTypedDataAsync } = useSignTypedData({
|
||||
...signTypedData,
|
||||
domain: {
|
||||
...signTypedData.domain,
|
||||
chainId,
|
||||
},
|
||||
});
|
||||
const { signTypedDataAsync } = useSignTypedData();
|
||||
|
||||
const staticEncryptionKey = import.meta.env.VITE_PK_ENCRYPTION_KEY;
|
||||
|
||||
@@ -103,7 +97,13 @@ export const GenerateKeys = ({
|
||||
// 1. First signature
|
||||
setStatus(EvmDerivedAccountStatus.Deriving);
|
||||
|
||||
const signature = await signTypedDataAsync();
|
||||
const signature = await signTypedDataAsync({
|
||||
...signTypedData,
|
||||
domain: {
|
||||
...signTypedData.domain,
|
||||
chainId,
|
||||
},
|
||||
});
|
||||
const { wallet: dydxWallet } = await getWalletFromEvmSignature({ signature });
|
||||
|
||||
// 2. Ensure signature is deterministic
|
||||
@@ -121,7 +121,13 @@ export const GenerateKeys = ({
|
||||
setStatus(EvmDerivedAccountStatus.EnsuringDeterminism);
|
||||
|
||||
// Second signature
|
||||
const additionalSignature = await signTypedDataAsync();
|
||||
const additionalSignature = await signTypedDataAsync({
|
||||
...signTypedData,
|
||||
domain: {
|
||||
...signTypedData.domain,
|
||||
chainId,
|
||||
},
|
||||
});
|
||||
|
||||
if (signature !== additionalSignature) {
|
||||
throw new Error(
|
||||
|
||||
Reference in New Issue
Block a user