Skip to content

Commit

Permalink
Optimize state reading
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitayutanov committed Sep 2, 2024
1 parent 6e45a85 commit 741845a
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 124 deletions.
6 changes: 3 additions & 3 deletions frontend/src/features/swap/components/swap-form/swap-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function SwapForm({ networkIndex, disabled, useHandleSubmit, useBalance, renderS
const FromNetwork = isVaraNetwork ? Network.Vara : Network.Eth;
const ToNetwork = isVaraNetwork ? Network.Eth : Network.Vara;

const { address, options, symbol, pair, ...bridge } = useBridge(networkIndex);
const { address, options, symbol, pair, nativeSymbol, ...bridge } = useBridge(networkIndex);
const { fee, ...config } = useVaraConfig(isVaraNetwork);
const balance = useBalance(address);
const { onSubmit, isSubmitting } = useHandleSubmit(address, fee.value);
Expand All @@ -41,7 +41,7 @@ function SwapForm({ networkIndex, disabled, useHandleSubmit, useBalance, renderS
const renderFromBalance = () => (
<Balance
value={balance.formattedValue}
unit={symbol.value}
unit={symbol}
isLoading={balance.isLoading}
onMaxButtonClick={setMaxBalance}
/>
Expand Down Expand Up @@ -81,7 +81,7 @@ function SwapForm({ networkIndex, disabled, useHandleSubmit, useBalance, renderS
heading="Expected Fee"
value={fee.formattedValue}
isLoading={config.isLoading}
unit={symbol.native}
unit={nativeSymbol}
/>

<Button
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/features/swap/consts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ERC20_TREASURY_ABI, FUNGIBLE_TOKEN_ABI } from './abi';
import { FUNCTION_NAME, EVENT_NAME } from './eth';
import { FIELD_NAME, DEFAULT_VALUES, ADDRESS_SCHEMA, ERROR_MESSAGE } from './form';
import { BridgingPaymentProgram, VftGatewayProgram, VftProgram } from './sails';
import { SERVICE_NAME, QUERY_NAME } from './vara';

const BRIDGING_PAYMENT_CONTRACT_ADDRESS = import.meta.env.VITE_BRIDGING_PAYMENT_CONTRACT_ADDRESS as HexString;
const ERC20_TREASURY_CONTRACT_ADDRESS = import.meta.env.VITE_ERC20_TREASURY_CONTRACT_ADDRESS as HexString;
Expand All @@ -28,6 +29,8 @@ export {
ERROR_MESSAGE,
BALANCE_REFETCH_INTERVAL,
NETWORK_INDEX,
SERVICE_NAME,
QUERY_NAME,
BridgingPaymentProgram,
VftGatewayProgram,
VftProgram,
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/features/swap/consts/vara.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const SERVICE_NAME = {
BRIDGING_PAYMENT: 'bridgingPayment',
VFT_GATEWAY: 'vftGateway',
VFT: 'vft',
} as const;

const QUERY_NAME = {
VFT_GATEWAY_ADDRESS: 'vftGatewayAddress',
FT_ADDRESSES: 'varaToEthAddresses',
BALANCE: 'balanceOf',
DECIMALS: 'decimals',
GET_CONFIG: 'getConfig',
} as const;

export { SERVICE_NAME, QUERY_NAME };
120 changes: 14 additions & 106 deletions frontend/src/features/swap/hooks/use-bridge.ts
Original file line number Diff line number Diff line change
@@ -1,120 +1,28 @@
import { HexString } from '@gear-js/api';
import { useProgram, useProgramQuery, useApi } from '@gear-js/react-hooks';
import { useQuery } from '@tanstack/react-query';
import { useState } from 'react';
import { useConfig } from 'wagmi';
import { readContract } from 'wagmi/actions';
import { useMemo, useState } from 'react';

import {
BRIDGING_PAYMENT_CONTRACT_ADDRESS,
BridgingPaymentProgram,
FUNGIBLE_TOKEN_ABI,
NETWORK_INDEX,
VftGatewayProgram,
VftProgram,
} from '../consts';
import { NETWORK_INDEX } from '../consts';
import { getOptions } from '../utils';

function useTokens() {
const wagmiConfig = useConfig();

const { data: program } = useProgram({
library: BridgingPaymentProgram,
id: BRIDGING_PAYMENT_CONTRACT_ADDRESS,
});

const { data: vftGatewayAddress } = useProgramQuery({
program,
serviceName: 'bridgingPayment',
functionName: 'vftGatewayAddress',
args: [],
});

const { data: vftGatewayProgram } = useProgram({
library: VftGatewayProgram,
id: vftGatewayAddress?.toString() as HexString,
});

const { data: ftAdresses } = useProgramQuery({
program: vftGatewayProgram,
serviceName: 'vftGateway',
functionName: 'varaToEthAddresses',
args: [],
});

const { api, isApiReady } = useApi();

const { data, isPending } = useQuery({
queryKey: ['options', ftAdresses],

queryFn: () => {
if (!api || !ftAdresses) throw new Error('Api or ftAdresses is not ready');

const promises = ftAdresses.map(async (addressPair) => {
const varaAddress = addressPair[0].toString() as HexString;
const ethAddress = addressPair[1].toString() as HexString;

// TODO: read decimals only for selected?
const vftProgram = new VftProgram(api, varaAddress);
const varaSymbol = await vftProgram.vft.symbol();
const varaDecimals = await vftProgram.vft.decimals();

const ethSymbol = await readContract(wagmiConfig, {
address: ethAddress.toString() as HexString,
abi: FUNGIBLE_TOKEN_ABI,
functionName: 'symbol',
});

const ethDecimals = await readContract(wagmiConfig, {
address: ethAddress.toString() as HexString,
abi: FUNGIBLE_TOKEN_ABI,
functionName: 'decimals',
});

return [
{ address: varaAddress, symbol: varaSymbol, decimals: varaDecimals },
{ address: ethAddress, symbol: ethSymbol, decimals: ethDecimals },
];
});

return Promise.all(promises);
},

enabled: isApiReady && Boolean(ftAdresses),
});

const isLoading = isPending;

return { data, isLoading };
}

const getOptions = (data: ReturnType<typeof useTokens>['data']) => {
const varaOptions: { label: string; value: string }[] = [];
const ethOptions: { label: string; value: string }[] = [];

data?.forEach(([vara, eth], index) => {
varaOptions.push({ value: index.toString(), label: vara.symbol });
ethOptions.push({ value: index.toString(), label: eth.symbol });
});

return { varaOptions, ethOptions };
};
import { useFTSymbols } from './use-ft-symbols';
import { useFTAddresses } from './vara';

function useBridge(networkIndex: number) {
const isVaraNetwork = networkIndex === NETWORK_INDEX.VARA;
const nativeSymbol = isVaraNetwork ? 'VARA' : 'ETH';

const tokens = useTokens();
const [pair, setPair] = useState('0');
const { data: ftAddresses } = useFTAddresses();
const { data: ftSymbols, isPending } = useFTSymbols(ftAddresses);

const { varaOptions, ethOptions } = getOptions(tokens.data);
const { varaOptions, ethOptions } = useMemo(() => getOptions(ftSymbols), [ftSymbols]);
const options = { from: isVaraNetwork ? varaOptions : ethOptions, to: isVaraNetwork ? ethOptions : varaOptions };

const bridge = tokens.data?.[Number(pair)][networkIndex];
const { address } = bridge || {};

const nativeSymbol = isVaraNetwork ? 'VARA' : 'ETH';
const symbol = { value: bridge?.symbol, native: nativeSymbol };
const [pair, setPair] = useState('0');
const pairIndex = Number(pair);
const address = ftAddresses?.[pairIndex][networkIndex].toString() as HexString | undefined;
const symbol = ftSymbols?.[pairIndex][networkIndex];

return { address, options, symbol, pair: { value: pair, set: setPair }, isLoading: tokens.isLoading };
return { address, options, symbol, nativeSymbol, pair: { value: pair, set: setPair }, isLoading: isPending };
}

export { useBridge };
40 changes: 40 additions & 0 deletions frontend/src/features/swap/hooks/use-ft-symbols.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { HexString } from '@gear-js/api';
import { useApi } from '@gear-js/react-hooks';
import { useQuery } from '@tanstack/react-query';
import { ActorId, H160 } from 'sails-js';
import { useConfig } from 'wagmi';
import { readContract } from 'wagmi/actions';

import { VftProgram, FUNGIBLE_TOKEN_ABI } from '../consts';

function useFTSymbols(addresses: [ActorId, H160][] | undefined) {
const { api, isApiReady } = useApi();
const wagmiConfig = useConfig();

const readVaraSymbol = (address: HexString) => {
if (!api) throw new Error('Api is not initialized');

return new VftProgram(api, address).vft.symbol();
};

const readEthSymbol = (address: HexString) =>
readContract(wagmiConfig, { address, abi: FUNGIBLE_TOKEN_ABI, functionName: 'symbol' });

const readSymbols = () => {
if (!addresses) throw new Error('Fungible token addresses are not found');

return Promise.all(
addresses.map((pair) =>
Promise.all([readVaraSymbol(pair[0].toString() as HexString), readEthSymbol(pair[1].toString() as HexString)]),
),
);
};

return useQuery({
queryKey: ['ftSymbols', addresses],
queryFn: readSymbols,
enabled: isApiReady && Boolean(addresses),
});
}

export { useFTSymbols };
3 changes: 2 additions & 1 deletion frontend/src/features/swap/hooks/vara/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useFTAddresses } from './use-ft-addresses';
import { useFungibleTokenBalance } from './use-fungible-token-balance';
import { useHandleVaraSubmit } from './use-handle-vara-submit';
import { useVaraConfig } from './use-vara-config';

export { useVaraConfig, useFungibleTokenBalance, useHandleVaraSubmit };
export { useVaraConfig, useFungibleTokenBalance, useHandleVaraSubmit, useFTAddresses };
38 changes: 38 additions & 0 deletions frontend/src/features/swap/hooks/vara/use-ft-addresses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { HexString } from '@gear-js/api';
import { useProgram, useProgramQuery } from '@gear-js/react-hooks';

import {
BridgingPaymentProgram,
BRIDGING_PAYMENT_CONTRACT_ADDRESS,
VftGatewayProgram,
SERVICE_NAME,
QUERY_NAME,
} from '../../consts';

function useFTAddresses() {
const { data: program } = useProgram({
library: BridgingPaymentProgram,
id: BRIDGING_PAYMENT_CONTRACT_ADDRESS,
});

const { data: vftGatewayAddress } = useProgramQuery({
program,
serviceName: SERVICE_NAME.BRIDGING_PAYMENT,
functionName: QUERY_NAME.VFT_GATEWAY_ADDRESS,
args: [],
});

const { data: vftGatewayProgram } = useProgram({
library: VftGatewayProgram,
id: vftGatewayAddress?.toString() as HexString,
});

return useProgramQuery({
program: vftGatewayProgram,
serviceName: SERVICE_NAME.VFT_GATEWAY,
functionName: QUERY_NAME.FT_ADDRESSES,
args: [],
});
}

export { useFTAddresses };
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,7 @@ import { formatUnits } from 'viem';

import { isUndefined } from '@/utils';

import { BALANCE_REFETCH_INTERVAL, VftProgram } from '../../consts';

const SERVICE_NAME = 'vft';

const QUERY_NAME = {
BALANCE: 'balanceOf',
DECIMALS: 'decimals',
} as const;
import { BALANCE_REFETCH_INTERVAL, QUERY_NAME, SERVICE_NAME, VftProgram } from '../../consts';

function useFungibleTokenBalance(address: HexString | undefined) {
const { account } = useAccount();
Expand All @@ -23,15 +16,15 @@ function useFungibleTokenBalance(address: HexString | undefined) {

const { data: balance, isPending: isBalancePending } = useProgramQuery({
program,
serviceName: SERVICE_NAME,
serviceName: SERVICE_NAME.VFT,
functionName: QUERY_NAME.BALANCE,
args: [account?.decodedAddress || '0x00'],
query: { enabled: Boolean(account), refetchInterval: BALANCE_REFETCH_INTERVAL },
});

const { data: decimals, isPending: isDecimalsPending } = useProgramQuery({
program,
serviceName: SERVICE_NAME,
serviceName: SERVICE_NAME.VFT,
functionName: QUERY_NAME.DECIMALS,
args: [],
});
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/features/swap/hooks/vara/use-vara-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useBalanceFormat, useProgram, useProgramQuery } from '@gear-js/react-ho

import { isUndefined } from '@/utils';

import { BRIDGING_PAYMENT_CONTRACT_ADDRESS, BridgingPaymentProgram } from '../../consts';
import { BRIDGING_PAYMENT_CONTRACT_ADDRESS, BridgingPaymentProgram, QUERY_NAME, SERVICE_NAME } from '../../consts';

function useVaraConfig(enabled: boolean) {
const { getFormattedBalance } = useBalanceFormat();
Expand All @@ -15,8 +15,8 @@ function useVaraConfig(enabled: boolean) {

const { data: config, isPending } = useProgramQuery({
program,
serviceName: 'bridgingPayment',
functionName: 'getConfig',
serviceName: SERVICE_NAME.BRIDGING_PAYMENT,
functionName: QUERY_NAME.GET_CONFIG,
args: [],
query: { enabled },
});
Expand Down
18 changes: 17 additions & 1 deletion frontend/src/features/swap/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,20 @@ const getAmountSchema = (
.refine((value) => value + feeValue <= balanceValue, { message: ERROR_MESSAGE.NO_BALANCE });
};

export { getAmountSchema };
const getOptions = (symbols: [string, string][] | undefined) => {
const varaOptions: { label: string; value: string }[] = [];
const ethOptions: { label: string; value: string }[] = [];

if (!symbols) return { varaOptions, ethOptions };

symbols.forEach(([varaSymbol, ethSymbol], index) => {
const value = index.toString();

varaOptions.push({ label: varaSymbol, value });
ethOptions.push({ label: ethSymbol, value });
});

return { varaOptions, ethOptions };
};

export { getAmountSchema, getOptions };

0 comments on commit 741845a

Please sign in to comment.