From 1cd589ce1c8f60b9f6fe057f42b54890e52baaa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20Stu=CC=88ber?= <15174476+TorstenStueber@users.noreply.github.com> Date: Fri, 14 Jun 2024 04:00:13 -0300 Subject: [PATCH 1/6] Execute Nabla after SEP-24 --- .eslintrc | 2 + src/components/InputKeys/AmountSelector.tsx | 8 +- src/components/InputKeys/From.tsx | 70 ++++----- src/components/InputKeys/SelectionModal.tsx | 2 +- src/components/InputKeys/To.tsx | 27 +--- src/components/InputKeys/index.tsx | 135 ++++++++---------- src/components/Nabla/BalanceState.tsx | 26 +--- src/components/Nabla/schema.tsx | 11 -- src/components/Nabla/useSwapForm.tsx | 82 ++++------- src/components/Sep24Component.tsx | 21 +-- src/components/Wallet/WalletConnect/index.tsx | 2 +- src/components/Wallet/index.tsx | 1 - src/config/index.ts | 18 +-- src/constants/tokenConfig.ts | 8 ++ src/helpers/contracts.ts | 13 +- src/helpers/transaction.ts | 14 -- src/hooks/nabla/useContractRead.ts | 4 +- src/hooks/nabla/useTokenAmountOut.ts | 114 +++++---------- src/pages/landing/index.tsx | 72 ++++++---- src/services/nabla.ts | 48 ++++--- 20 files changed, 258 insertions(+), 420 deletions(-) delete mode 100644 src/helpers/transaction.ts diff --git a/.eslintrc b/.eslintrc index f585df85..53939bb6 100644 --- a/.eslintrc +++ b/.eslintrc @@ -29,6 +29,8 @@ "react/react-in-jsx-scope": "off", "react-hooks/exhaustive-deps": "error", "react/prop-types": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "prefer-const": "warn", "@typescript-eslint/no-unused-vars": [ "warn", { diff --git a/src/components/InputKeys/AmountSelector.tsx b/src/components/InputKeys/AmountSelector.tsx index 9a8934a9..1c172da4 100644 --- a/src/components/InputKeys/AmountSelector.tsx +++ b/src/components/InputKeys/AmountSelector.tsx @@ -57,18 +57,12 @@ export function AmountSelector 20) return `The number you entered is too large`; - } }; const errorMessage = determineErrorMessage(); diff --git a/src/components/InputKeys/From.tsx b/src/components/InputKeys/From.tsx index d392e7d4..0970add8 100644 --- a/src/components/InputKeys/From.tsx +++ b/src/components/InputKeys/From.tsx @@ -54,51 +54,43 @@ export function From - {fromToken && ( - Pendulum - )} + {fromToken && Pendulum} {!fromToken && Pendulum} {fromToken?.assetCode || 'Select'} -
-
- {fromTokenBalance !== undefined && ( - <> - - Your Balance: - - - - - )} -
+
+ {fromTokenBalance !== undefined && ( +
+ + Your Balance: + + + +
+ )}
); diff --git a/src/components/InputKeys/SelectionModal.tsx b/src/components/InputKeys/SelectionModal.tsx index 49eecc21..9311017c 100644 --- a/src/components/InputKeys/SelectionModal.tsx +++ b/src/components/InputKeys/SelectionModal.tsx @@ -97,7 +97,7 @@ function PoolList({ onSelect, selected, mode }: PoolListProps) { diff --git a/src/components/InputKeys/To.tsx b/src/components/InputKeys/To.tsx index 90844c0e..177c8dc4 100644 --- a/src/components/InputKeys/To.tsx +++ b/src/components/InputKeys/To.tsx @@ -2,6 +2,7 @@ import { ArrowPathRoundedSquareIcon, ChevronDownIcon } from '@heroicons/react/20 import { useEffect } from 'preact/compat'; import { Button } from 'react-daisyui'; import { useFormContext } from 'react-hook-form'; +import Big from 'big.js'; import pendulumIcon from '../../assets/pendulum-icon.svg'; import { NumberLoader } from '../Nabla/TokenBalance'; @@ -18,8 +19,7 @@ export interface ToProps { fromToken: TokenDetails | undefined; toToken: TokenDetails | undefined; toAmountQuote: UseTokenOutAmountResult; - fromAmount: number | undefined; - slippage: number; + fromAmount: Big | undefined; fromTokenBalances: { [key: string]: BalanceInfo }; } @@ -30,7 +30,6 @@ export function To({ onOpenSelector, toAmountQuote, fromAmount, - slippage, fromTokenBalances, }: ToProps): JSX.Element | null { const toTokenBalance = @@ -56,7 +55,7 @@ export function To({ ) : toAmountQuote.data !== undefined ? ( `${toAmountQuote.data.amountOut.approximateStrings.atLeast4Decimals}` - ) : fromAmount !== undefined && fromAmount > 0 ? ( + ) : fromAmount !== undefined && fromAmount.gt(0) ? ( ) : null} diff --git a/src/components/Nabla/BalanceState.tsx b/src/components/Nabla/BalanceState.tsx index 27efad23..25921ae2 100644 --- a/src/components/Nabla/BalanceState.tsx +++ b/src/components/Nabla/BalanceState.tsx @@ -1,8 +1,8 @@ import { useEffect, useState } from 'react'; -import { stringDecimalToBN, toBigNumber } from '../../helpers/parseNumbers'; +import { toBigNumber } from '../../helpers/parseNumbers'; import { getApiManagerInstance } from '../../services/polkadot/polkadotApi'; import { TOKEN_CONFIG } from '../../constants/tokenConfig'; -import { stringifyBigWithSignificantDecimals } from '../../helpers/contracts'; +import { parseContractBalanceResponse } from '../../helpers/contracts'; import { ContractBalance } from '../../helpers/contracts'; export interface BalanceInfo extends ContractBalance { canWithdraw: boolean; @@ -41,28 +41,12 @@ export const useAccountBalance = (address?: string): UseAccountBalanceResponse = const response = (await apiComponents.api.query.tokens.accounts(address, config.currencyId)).toHuman() as any; const rawBalance = response?.free || '0'; - const preciseBigDecimal = toBigNumber(rawBalance, TOKEN_CONFIG[key].decimals); - const balanceBigNumber = toBigNumber(rawBalance, 0); + const contractBalance = parseContractBalanceResponse(TOKEN_CONFIG[key].decimals, rawBalance); - const atLeast2Decimals = stringifyBigWithSignificantDecimals(preciseBigDecimal, 2); - const atLeast4Decimals = stringifyBigWithSignificantDecimals(preciseBigDecimal, 4); - - const contractBalance = { - rawBalance: balanceBigNumber, - decimals: config.decimals, - preciseBigDecimal, - preciseString: balanceBigNumber.toString(), - approximateStrings: { - atLeast2Decimals: atLeast2Decimals, - atLeast4Decimals: atLeast4Decimals, - }, - approximateNumber: preciseBigDecimal.toNumber(), - }; - - // if it is offramped, it should always ahve minWithrawalAmount defined + // if it is offramped, it should always have minWithrawalAmount defined if (config.isOfframp && config.minWithdrawalAmount) { const minWithdrawalAmount = toBigNumber(config.minWithdrawalAmount, 0); - const canWithdraw = balanceBigNumber.gte(minWithdrawalAmount); + const canWithdraw = contractBalance.rawBalance.gte(minWithdrawalAmount); newBalances[key] = { ...contractBalance, diff --git a/src/components/Nabla/schema.tsx b/src/components/Nabla/schema.tsx index b56513a9..671363b2 100644 --- a/src/components/Nabla/schema.tsx +++ b/src/components/Nabla/schema.tsx @@ -5,15 +5,6 @@ export type SwapFormValues = { fromAmount: string; to: string; toAmount: string; - slippage: number | undefined; - deadline: number; -}; - -/* eslint-disable @typescript-eslint/no-explicit-any */ -const transformNumber = (value: any, originalValue: any) => { - if (!originalValue) return 0; - if (typeof originalValue === 'string' && originalValue !== '') value = Number(originalValue) ?? 0; - return value; }; const schema = Yup.object().shape({ @@ -21,8 +12,6 @@ const schema = Yup.object().shape({ fromAmount: Yup.string().required(), to: Yup.string().min(5).required(), toAmount: Yup.string().required(), - slippage: Yup.number().nullable().transform(transformNumber), - deadline: Yup.number().nullable().transform(transformNumber), }); export default schema; diff --git a/src/components/Nabla/useSwapForm.tsx b/src/components/Nabla/useSwapForm.tsx index 020f4681..5be44512 100644 --- a/src/components/Nabla/useSwapForm.tsx +++ b/src/components/Nabla/useSwapForm.tsx @@ -1,18 +1,17 @@ import { useState, useCallback, useMemo } from 'react'; - -import { TOKEN_CONFIG, TokenDetails } from '../../constants/tokenConfig'; - +import Big from 'big.js'; import { Resolver, useForm, useWatch } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; -import { SwapFormValues } from './schema'; -import schema from './schema'; + +import { TOKEN_CONFIG, TokenDetails } from '../../constants/tokenConfig'; +import schema, { SwapFormValues } from './schema'; import { storageService } from '../../services/localStorage'; -import { getValidDeadline, getValidSlippage } from '../../helpers/transaction'; import { storageKeys } from '../../constants/localStorage'; -import { config } from '../../config'; import { debounce } from '../../helpers/function'; import { SwapSettings } from '../InputKeys'; + const storageSet = debounce(storageService.set, 1000); +const setStorageForSwapSettings = storageSet.bind(null, storageKeys.SWAP_SETTINGS); export const useSwapForm = () => { const tokensModal = useState(); @@ -23,8 +22,6 @@ export const useSwapForm = () => { return { from: storageValues?.from ?? '', to: storageValues?.to ?? '', - slippage: getValidSlippage(storageValues?.slippage), - deadline: getValidDeadline(storageValues?.deadline ?? 0), }; }, []); @@ -40,27 +37,11 @@ export const useSwapForm = () => { const fromToken = from ? TOKEN_CONFIG[from] : undefined; const toToken = to ? TOKEN_CONFIG[to] : undefined; - const updateStorage = useCallback( - (newValues: Partial) => { - const prev = form.getValues(); - const updated = { - slippage: prev.slippage || config.swap.defaults.slippage, - deadline: prev.deadline || config.swap.defaults.deadline, - ...newValues, - }; - storageSet(storageKeys.SWAP_SETTINGS, updated); - return updated; - }, - [form], - ); - const onFromChange = useCallback( (a: TokenDetails) => { - const f = a.assetCode; - const prev = form.getValues(); - const tokenKey = Object.entries(TOKEN_CONFIG).filter(([key, tokenDetails]) => { - return tokenDetails.assetCode === f; - })[0][0]; + const prev = getValues(); + const tokenKey = Object.keys(TOKEN_CONFIG).find((key) => TOKEN_CONFIG[key]!.assetCode === a.assetCode); + if (!tokenKey) return; const updated = { from: tokenKey, @@ -68,31 +49,32 @@ export const useSwapForm = () => { }; if (updated.to && prev?.to === tokenKey) setValue('to', updated.to); - updateStorage(updated); - form.setValue('from', updated.from); + setStorageForSwapSettings(updated); + setValue('from', tokenKey); setTokenModal(undefined); }, - [form, form.getValues, setTokenModal, form.setValue, updateStorage], + [getValues, setValue, setTokenModal], ); const onToChange = useCallback( (a: TokenDetails) => { - const f = a.assetCode; - const prev = form.getValues(); - const tokenKey = Object.entries(TOKEN_CONFIG).filter(([key, tokenDetails]) => { - return tokenDetails.assetCode === f; - })[0][0]; + const prev = getValues(); + const tokenKey = Object.keys(TOKEN_CONFIG).find((key) => TOKEN_CONFIG[key]!.assetCode === a.assetCode); + if (!tokenKey) return; + const updated = { to: tokenKey, from: prev?.from === tokenKey ? prev?.to : prev?.from, }; - updateStorage(updated); - if (updated.from && prev?.from !== updated.from) form.setValue('from', updated.from); - form.setValue('to', updated.to); + + if (updated.from && prev?.from !== updated.from) setValue('from', updated.from); + setStorageForSwapSettings(updated); + setValue('to', tokenKey); + setTokenModal(undefined); }, - [form, setTokenModal, updateStorage], + [getValues, setTokenModal, setValue], ); const fromAmountString = useWatch({ @@ -101,17 +83,12 @@ export const useSwapForm = () => { defaultValue: '0', }); - const slippage = getValidSlippage( - Number( - useWatch({ - control, - name: 'slippage', - defaultValue: config.swap.defaults.slippage, - }), - ), - ); - - const fromAmount = Number(fromAmountString); + let fromAmount: Big | undefined; + try { + fromAmount = new Big(fromAmountString); + } catch { + // no action required + } return { form, @@ -120,10 +97,9 @@ export const useSwapForm = () => { tokensModal, onFromChange, onToChange, - updateStorage, fromAmount, + fromAmountString, fromToken, toToken, - slippage, }; }; diff --git a/src/components/Sep24Component.tsx b/src/components/Sep24Component.tsx index 70296c1b..3c12f985 100644 --- a/src/components/Sep24Component.tsx +++ b/src/components/Sep24Component.tsx @@ -1,9 +1,9 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState } from 'react'; import { IAnchorSessionParams, ISep24Intermediate, Sep24Result } from '../services/anchor'; import { sep24First, sep24Second } from '../services/anchor'; import { EventStatus } from './GenericEvent'; import { Button } from 'react-daisyui'; -import { sep10 } from '../services/anchor'; + interface Sep24Props { sessionParams: IAnchorSessionParams | null; onSep24Complete: (sep24Reslt: Sep24Result) => void; @@ -11,30 +11,15 @@ interface Sep24Props { addEvent: (message: string, status: EventStatus) => void; } -interface Sep24ProcessStatus { - processStarted: boolean; - waitingSep24Second: boolean; -} - const Sep24: React.FC = ({ sessionParams, onSep24Complete, addEvent }) => { - const [iframe, iframeOpened] = useState(false); const [externalWindowClicked, setExternalWindowClicked] = useState(false); const [sep24IntermediateValues, setSep24IntermediateValues] = useState(null); - const [processStatus, setProcessStatus] = useState({ - processStarted: false, - waitingSep24Second: false, - }); const onExternalWindowClicked = () => { if (sessionParams) { sep24First(sessionParams, addEvent).then((response) => { - setProcessStatus({ - processStarted: true, - waitingSep24Second: false, - }); window.open(`${response.url}`, '_blank'); setSep24IntermediateValues(response); - iframeOpened(true); }); } @@ -44,12 +29,10 @@ const Sep24: React.FC = ({ sessionParams, onSep24Complete, addEvent const handleIframeCompletion = () => { // at this point setSep24IntermediateValues should not be null, as well as // sessionParams - iframeOpened(false); sep24Second(sep24IntermediateValues!, sessionParams!, addEvent).then((response) => { onSep24Complete(response); }); addEvent('Waiting for confirmation from Anchor', EventStatus.Waiting); - setProcessStatus({ processStarted: true, waitingSep24Second: true }); }; return ( diff --git a/src/components/Wallet/WalletConnect/index.tsx b/src/components/Wallet/WalletConnect/index.tsx index c9bd56ad..44fb66ea 100644 --- a/src/components/Wallet/WalletConnect/index.tsx +++ b/src/components/Wallet/WalletConnect/index.tsx @@ -59,7 +59,7 @@ const WalletConnect = () => { await handleConnect(); //@eslint-disable-next-line no-explicit-any - } catch (error: any) { + } catch (error) { console.log(error); } finally { setLoading(false); diff --git a/src/components/Wallet/index.tsx b/src/components/Wallet/index.tsx index 6c924d98..92c2284e 100644 --- a/src/components/Wallet/index.tsx +++ b/src/components/Wallet/index.tsx @@ -3,7 +3,6 @@ import { WalletSelect } from '@talismn/connect-components'; import { Button, Divider } from 'react-daisyui'; import { useGlobalState } from '../../GlobalStateProvider'; import { getAddressForFormat } from '../../helpers/addressFormatter'; -import { CopyableAddress } from '../PublicKey'; import MetamaskWallet from './MetamaskWallet'; import WalletConnect from './WalletConnect'; diff --git a/src/config/index.ts b/src/config/index.ts index 32a3bac6..729294bb 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -49,23 +49,9 @@ export const config = { explorer: 'https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frpc-foucoco.pendulumchain.tech#/explorer/query', }, } satisfies TenantConfig, - transaction: { - settings: { - slippage: { - min: 0.1, - max: 99.9, - }, - deadline: { - min: 1, - max: 1440, - }, - }, - }, swap: { - defaults: { - slippage: 0.5, - deadline: 30, - }, + slippageBasicPoints: 20, + deadline: 30, }, walletConnect: { url: 'wss://relay.walletconnect.com', diff --git a/src/constants/tokenConfig.ts b/src/constants/tokenConfig.ts index 51dbda60..8cd02159 100644 --- a/src/constants/tokenConfig.ts +++ b/src/constants/tokenConfig.ts @@ -1,3 +1,7 @@ +import BrlIcon from '../assets/coins/BRL.png'; +import UsdtIcon from '../assets/coins/USDT.png'; +import EurcIcon from '../assets/coins/EURC.png'; + export interface TokenDetails { currencyId: any; isOfframp: boolean; @@ -11,6 +15,7 @@ export interface TokenDetails { vaultAccountId?: string; minWithdrawalAmount?: string; assetCodeHex?: string; // Optional property + icon: string; } export interface TokenConfig { @@ -35,6 +40,7 @@ export const TOKEN_CONFIG: TokenConfig = { minWithdrawalAmount: '1000000000000', assetCodeHex: '0x42524c00', erc20Address: '6dZCR7KVmrcxBoUTcM3vUgpQagQAW2wg2izMrT3N4reftwW5', + icon: BrlIcon, }, eurc: { tomlFileUrl: 'https://mykobo.co/.well-known/stellar.toml', @@ -51,6 +57,7 @@ export const TOKEN_CONFIG: TokenConfig = { vaultAccountId: '6bsD97dS8ZyomMmp1DLCnCtx25oABtf19dypQKdZe6FBQXSm', erc20Address: '6fA9DRKJ12oTXfSAU7ZZGZ9gEQ92YnyRXeJzW1wXekPzeXZC', minWithdrawalAmount: '10000000000000', + icon: EurcIcon, }, usdt: { assetCode: 'USDT', @@ -59,5 +66,6 @@ export const TOKEN_CONFIG: TokenConfig = { canSwapTo: ['brl', 'eurc'], isOfframp: false, erc20Address: '6cRE6nw1eW8Lq452D39Jw3FeradDmUkoEvCgiRkTYxqmP6cs', + icon: UsdtIcon, }, }; diff --git a/src/helpers/contracts.ts b/src/helpers/contracts.ts index a3a7ce6d..3e5126b7 100644 --- a/src/helpers/contracts.ts +++ b/src/helpers/contracts.ts @@ -51,19 +51,20 @@ export interface ContractBalance { approximateNumber: number; } -export function parseContractBalanceResponse(decimals: number, balanceResponse: INumber): ContractBalance; +export function parseContractBalanceResponse(decimals: number, balanceResponse: INumber | bigint): ContractBalance; export function parseContractBalanceResponse( decimals: number | undefined, - balanceResponse: INumber | undefined, + balanceResponse: INumber | bigint | undefined, ): ContractBalance | undefined; export function parseContractBalanceResponse( decimals: number | undefined, - balanceResponse: INumber | undefined, + balanceResponse: INumber | bigint | undefined, ): ContractBalance | undefined { - const rawBalanceBigInt = balanceResponse?.toBigInt(); - if (rawBalanceBigInt === undefined || decimals === undefined) return undefined; + if (balanceResponse === undefined || decimals === undefined) return undefined; + + const rawBalanceBigInt = typeof balanceResponse === 'bigint' ? balanceResponse : balanceResponse.toBigInt(); const rawBalanceString = rawBalanceBigInt.toString(); const preciseBigDecimal = multiplyByPowerOfTen(new BigNumber(rawBalanceString), -decimals); @@ -102,7 +103,7 @@ export function stringifyBigWithSignificantDecimals(big: BigNumber, decimals: nu return rounded.toFixed(significantDecimals, 0); } -function multiplyByPowerOfTen(bigDecimal: BigNumber, power: number) { +export function multiplyByPowerOfTen(bigDecimal: BigNumber, power: number) { const newBigDecimal = new BigNumber(bigDecimal); if (newBigDecimal.c[0] === 0) return newBigDecimal; diff --git a/src/helpers/transaction.ts b/src/helpers/transaction.ts deleted file mode 100644 index fdc86c2c..00000000 --- a/src/helpers/transaction.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { config } from '../config'; - -const { slippage, deadline } = config.transaction.settings; - -export function getValidSlippage(val: number): number; -export function getValidSlippage(val: number | undefined): number | undefined; - -export function getValidSlippage(val: number | undefined): number | undefined { - return val !== undefined ? Math.min(Math.max(val, slippage.min), slippage.max) : val; -} - -export function getValidDeadline(val: number): number { - return Math.min(Math.max(val, deadline.min), deadline.max); -} diff --git a/src/hooks/nabla/useContractRead.ts b/src/hooks/nabla/useContractRead.ts index 2c0c7245..523867b4 100644 --- a/src/hooks/nabla/useContractRead.ts +++ b/src/hooks/nabla/useContractRead.ts @@ -29,8 +29,8 @@ export type UseContractReadResult = UseQueryResult( key: QueryKey, - api: ApiPromise, - walletAddress: string, + api: ApiPromise | null, + walletAddress: string | undefined, { abi, address, diff --git a/src/hooks/nabla/useTokenAmountOut.ts b/src/hooks/nabla/useTokenAmountOut.ts index f8a9062b..1143e887 100644 --- a/src/hooks/nabla/useTokenAmountOut.ts +++ b/src/hooks/nabla/useTokenAmountOut.ts @@ -1,28 +1,27 @@ import BigNumber from 'big.js'; import { activeOptions, cacheKeys } from '../../constants/cache'; import { routerAbi } from '../../contracts/Router'; -import { ContractBalance, parseContractBalanceResponse } from '../../helpers/contracts'; -import { decimalToCustom, toBigNumber } from '../../helpers/parseNumbers'; +import { ContractBalance, multiplyByPowerOfTen, parseContractBalanceResponse } from '../../helpers/contracts'; import { NABLA_ROUTER } from '../../constants/constants'; import { useContractRead } from './useContractRead'; import { UseQueryResult } from '@tanstack/react-query'; -import { TokenDetails } from '../../constants/tokenConfig'; import { useDebouncedValue } from '../useDebouncedValue'; import { TOKEN_CONFIG } from '../../constants/tokenConfig'; import { WalletAccount } from '@talismn/connect-wallets'; import { ApiPromise } from '../../services/polkadot/polkadotApi'; import { FieldValues, UseFormReturn } from 'react-hook-form'; import { useEffect } from 'preact/hooks'; +import Big from 'big.js'; export type UseTokenOutAmountProps = { wantsSwap: boolean; api: ApiPromise | null; walletAccount: WalletAccount | undefined; - fromAmount: number | null; + fromAmountString: string; fromToken: string; toToken: string; maximumFromAmount: BigNumber | undefined; - slippage: number; + slippageBasisPoints: number; form: UseFormReturn; }; @@ -30,126 +29,85 @@ export interface UseTokenOutAmountResult { isLoading: boolean; enabled: boolean; data: TokenOutData | undefined; - error: string | null; refetch?: UseQueryResult['refetch']; } + export interface TokenOutData { amountOut: ContractBalance; swapFee: ContractBalance; effectiveExchangeRate: string; - minAmountOut: string; } export function useTokenOutAmount({ wantsSwap, api, walletAccount, - fromAmount, + fromAmountString, fromToken, toToken, maximumFromAmount, - slippage, + slippageBasisPoints, form, }: UseTokenOutAmountProps) { const { setError, clearErrors } = form; - // Handle different errors either from form or parameters needed for the swap - const inputHasErrors = form.formState.errors.fromAmount?.message !== undefined; - if (inputHasErrors) { - console.log('errors', form.formState.errors.fromAmount?.message); - return { - isLoading: false, - enabled: false, - data: undefined, - error: form.formState.errors.fromAmount?.message ?? 'The specified swap cannot be performed at the moment', - refetch: undefined, - }; - } - - if (!walletAccount) { - return { isLoading: false, enabled: false, data: undefined, error: 'Wallet not connected', refetch: undefined }; - } - - if (fromToken === '' || toToken === '' || fromAmount === null || api === null || !wantsSwap) { - return { - isLoading: false, - enabled: false, - data: undefined, - error: 'Required parameters are missing', - refetch: undefined, - }; + const debouncedFromAmountString = useDebouncedValue(fromAmountString, 800); + let debouncedAmountBigDecimal: Big | undefined; + try { + debouncedAmountBigDecimal = new Big(debouncedFromAmountString); + } catch { + // no action required } - const fromTokenDetails: TokenDetails = TOKEN_CONFIG[fromToken]; - const toTokenDetails: TokenDetails = TOKEN_CONFIG[toToken]; + const fromTokenDetails = TOKEN_CONFIG[fromToken]; + const toTokenDetails = TOKEN_CONFIG[toToken]; - const debouncedFromAmount = useDebouncedValue(fromAmount, 800); - const debouncedAmountBigDecimal = decimalToCustom(debouncedFromAmount.toString(), fromTokenDetails.decimals); + const fromTokenDecimals = fromTokenDetails?.decimals; - // Even though we check for errors, due to possible delay in value update we need to check that the value is not - // less than 1, or larger than e+20, since BigNumber.toString() will return scientific notation. - // this is no error, but temporary empty return until the value gets properly updated. - if ( - debouncedAmountBigDecimal === undefined || - debouncedAmountBigDecimal.lt(new BigNumber(1)) || - debouncedAmountBigDecimal.e > 20 - ) { - return { isLoading: false, enabled: false, data: undefined, error: '', refetch: undefined }; - } + const amountIn = + fromTokenDecimals !== undefined && debouncedAmountBigDecimal !== undefined + ? multiplyByPowerOfTen(debouncedAmountBigDecimal, fromTokenDecimals).toFixed(0, 0) + : undefined; const enabled = - fromToken !== undefined && - toToken !== undefined && + api !== undefined && + wantsSwap && + fromTokenDetails !== undefined && + toTokenDetails !== undefined && + walletAccount !== undefined && debouncedAmountBigDecimal !== undefined && debouncedAmountBigDecimal.gt(new BigNumber(0)) && (maximumFromAmount === undefined || debouncedAmountBigDecimal.lte(maximumFromAmount)); - const amountIn = debouncedAmountBigDecimal?.toString(); - const { isLoading, fetchStatus, data, error, refetch } = useContractRead( - [cacheKeys.tokenOutAmount, fromTokenDetails.erc20Address, toTokenDetails.erc20Address, amountIn], + [cacheKeys.tokenOutAmount, fromTokenDetails?.erc20Address, toTokenDetails?.erc20Address, amountIn], api, - walletAccount.address, + walletAccount?.address, { abi: routerAbi, address: NABLA_ROUTER, method: 'getAmountOut', - args: [amountIn, [fromTokenDetails.erc20Address, toTokenDetails.erc20Address]], + args: [amountIn, [fromTokenDetails?.erc20Address, toTokenDetails?.erc20Address]], noWalletAddressRequired: true, queryOptions: { ...activeOptions['30s'], enabled, }, parseSuccessOutput: (data) => { - if (toToken === undefined || fromToken === undefined || debouncedAmountBigDecimal === undefined) { + if (toTokenDetails === undefined || fromTokenDetails === undefined || debouncedAmountBigDecimal === undefined) { return undefined; } - const amountOut = parseContractBalanceResponse(toTokenDetails.decimals, data[0]); - const swapFee = parseContractBalanceResponse(toTokenDetails.decimals, data[1]); - // - const decimalDifference = fromTokenDetails.decimals - toTokenDetails.decimals; - let effectiveExchangeRate; - if (decimalDifference > 0) { - const decimalDiffCorrection = new BigNumber(10).pow(decimalDifference); - effectiveExchangeRate = amountOut.rawBalance - .div(debouncedAmountBigDecimal) - .mul(decimalDiffCorrection) - .toString(); - } else { - const decimalDiffCorrection = new BigNumber(10).pow(-decimalDifference); - effectiveExchangeRate = amountOut.rawBalance - .div(debouncedAmountBigDecimal.mul(decimalDiffCorrection)) - .toString(); - } + const bigIntResponse = data[0]?.toBigInt(); + const reducedResponse = (bigIntResponse * BigInt(10000 - slippageBasisPoints)) / 10000n; - const minAmountOut = amountOut.approximateNumber * (1 - slippage / 100); + const amountOut = parseContractBalanceResponse(toTokenDetails.decimals, reducedResponse); + const swapFee = parseContractBalanceResponse(toTokenDetails.decimals, data[1]); return { amountOut, - effectiveExchangeRate, + effectiveExchangeRate: amountOut.preciseBigDecimal.div(debouncedAmountBigDecimal).toString(), swapFee, - minAmountOut: minAmountOut.toString(), }; }, parseError: (error) => { @@ -169,7 +127,7 @@ export function useTokenOutAmount({ }, ); - const pending = (isLoading && fetchStatus !== 'idle') || debouncedFromAmount !== fromAmount; + const pending = (isLoading && fetchStatus !== 'idle') || debouncedFromAmountString !== fromAmountString; useEffect(() => { if (pending) return; if (error === null) { @@ -179,5 +137,5 @@ export function useTokenOutAmount({ } }, [error, pending, clearErrors, setError]); - return { isLoading: pending, enabled, data, error, refetch }; + return { isLoading: pending, enabled, data, refetch }; } diff --git a/src/pages/landing/index.tsx b/src/pages/landing/index.tsx index 0ab0e954..bc497a88 100644 --- a/src/pages/landing/index.tsx +++ b/src/pages/landing/index.tsx @@ -1,8 +1,9 @@ +import Big from 'big.js'; +import { useState, useEffect, useRef } from 'react'; + import '../../../App.css'; -import React, { useState, useEffect, useRef } from 'react'; import InputBox from '../../components/InputKeys'; import { SwapOptions } from '../../components/InputKeys'; - import EventBox from '../../components/GenericEvent'; import { GenericEvent, EventStatus } from '../../components/GenericEvent'; import { fetchTomlValues, IAnchorSessionParams, Sep24Result, getEphemeralKeys, sep10 } from '../../services/anchor'; @@ -19,6 +20,7 @@ import { useGlobalState } from '../../GlobalStateProvider'; import { fetchSigningServicePK } from '../../services/signingService'; import { TOKEN_CONFIG, TokenDetails } from '../../constants/tokenConfig'; import { performSwap } from '../../services/nabla'; +import { stringifyBigWithSignificantDecimals } from '../../helpers/contracts'; enum OperationStatus { Idle, @@ -30,9 +32,17 @@ enum OperationStatus { Error, } +export interface ExecutionInput { + userSubstrateAddress: string; + assetToOfframp: string; + amountIn: Big; + swapOptions: SwapOptions | undefined; // undefined means direct offramp +} + function Landing() { // system status const [status, setStatus] = useState(OperationStatus.Idle); + const [executionInput, setExecutionInput] = useState(undefined); // events state and refs const [events, setEvents] = useState([]); @@ -40,7 +50,6 @@ function Landing() { const [activeEventIndex, setActiveEventIndex] = useState(-1); // seession and operations states - const [userAddress, setUserAddress] = useState(null); const [fundingPK, setFundingPK] = useState(null); const [anchorSessionParams, setAnchorSessionParams] = useState(null); const [stellarOperations, setStellarOperations] = useState(null); @@ -54,30 +63,13 @@ function Landing() { // Wallet states const { walletAccount, dAppName } = useGlobalState(); - const handleOnSubmit = async ( - userSubstrateAddress: string, - swapsFirst: boolean, - selectedAsset: string, - swapOptions: SwapOptions, - maxBalanceFrom: number, - ) => { - setUserAddress(userSubstrateAddress); - - const tokenConfig: TokenDetails = TOKEN_CONFIG[selectedAsset]; + const handleOnSubmit = async ({ userSubstrateAddress, assetToOfframp, amountIn, swapOptions }: ExecutionInput) => { + setExecutionInput({ userSubstrateAddress, assetToOfframp, amountIn, swapOptions }); + const tokenConfig: TokenDetails = TOKEN_CONFIG[assetToOfframp]; const values = await fetchTomlValues(tokenConfig.tomlFileUrl!); - // perform swap if necessary - // if no swapping, the balance to offramp is the initial desired amount - // otherwise, it will be the obtained value from the swap. - let balanceToOfframp = swapOptions.amountIn; - if (swapsFirst) { - balanceToOfframp = await performSwap( - { swap: swapOptions, userAddress: userSubstrateAddress, walletAccount: walletAccount! }, - addEvent, - ); - } - // truncate the value to 2 decimal places - const balanceToOfframpTruncated = Math.trunc(balanceToOfframp * 100) / 100; + const amountToOfframp = swapOptions !== undefined ? swapOptions.minAmountOut : amountIn; + const truncatedAmountToOfframp = stringifyBigWithSignificantDecimals(amountToOfframp.round(2, 0), 2); const token = await sep10(values, addEvent); @@ -85,7 +77,7 @@ function Landing() { token, tomlValues: values, tokenConfig, - offrampAmount: balanceToOfframpTruncated.toString(), + offrampAmount: truncatedAmountToOfframp, }); // showing (rendering) the Sep24 component will trigger the Sep24 process setShowSep24(true); @@ -102,6 +94,34 @@ function Landing() { ); setSep24Result(result); + if (executionInput === undefined) return; + const { userSubstrateAddress, assetToOfframp, amountIn, swapOptions } = executionInput; + + if (swapOptions) { + const enteredAmountDecimal = new Big(result.amount); + if (enteredAmountDecimal.gt(swapOptions.minAmountOut)) { + addEvent( + `The amount you entered is too high. Maximum possible amount to offramp: ${swapOptions.minAmountOut.toString()}), you entered: ${ + result.amount + }.`, + EventStatus.Error, + ); + return; + } + + await performSwap( + { + amountIn, + assetOut: assetToOfframp, + assetIn: swapOptions.assetIn, + minAmountOut: swapOptions.minAmountOut, + userAddress: userSubstrateAddress, + walletAccount: walletAccount!, + }, + addEvent, + ); + } + // set up the ephemeral account and operations we will later neeed try { addEvent('Settings stellar accounts', EventStatus.Waiting); diff --git a/src/services/nabla.ts b/src/services/nabla.ts index 4dbb79c6..783394c6 100644 --- a/src/services/nabla.ts +++ b/src/services/nabla.ts @@ -1,29 +1,32 @@ -import { SwapOptions } from '../components/InputKeys'; +import { Abi } from '@polkadot/api-contract'; +import Big from 'big.js'; +import { readMessage, ReadMessageResult, executeMessage, ExecuteMessageResult } from '@pendulum-chain/api-solang'; + import { EventStatus } from '../components/GenericEvent'; import { getApiManagerInstance } from './polkadot/polkadotApi'; -import { Abi } from '@polkadot/api-contract'; import { erc20WrapperAbi } from '../contracts/ERC20Wrapper'; import { routerAbi } from '../contracts/Router'; import { NABLA_ROUTER } from '../constants/constants'; -import { defaultReadLimits } from '../helpers/contracts'; -import { readMessage, ReadMessageResult, executeMessage, ExecuteMessageResult } from '@pendulum-chain/api-solang'; +import { defaultReadLimits, multiplyByPowerOfTen } from '../helpers/contracts'; import { parseContractBalanceResponse } from '../helpers/contracts'; import { TOKEN_CONFIG } from '../constants/tokenConfig'; import { WalletAccount } from '@talismn/connect-wallets'; import { defaultWriteLimits, createWriteOptions } from '../helpers/contracts'; -import { stringDecimalToBN } from '../helpers/parseNumbers'; import { toBigNumber } from '../helpers/parseNumbers'; export interface PerformSwapProps { - swap: SwapOptions; + amountIn: Big; + assetOut: string; + assetIn: string; + minAmountOut: Big; userAddress: string; walletAccount: WalletAccount; } export async function performSwap( - { swap, userAddress, walletAccount }: PerformSwapProps, + { amountIn, assetOut, assetIn, minAmountOut, userAddress, walletAccount }: PerformSwapProps, renderEvent: (event: string, status: EventStatus) => void, -): Promise { +): Promise { // event attempting swap renderEvent('Attempting swap', EventStatus.Waiting); // get chain api, abi @@ -31,8 +34,8 @@ export async function performSwap( const erc20ContractAbi = new Abi(erc20WrapperAbi, pendulumApiComponents.api.registry.getChainProperties()); const routerAbiObject = new Abi(routerAbi, pendulumApiComponents.api.registry.getChainProperties()); // get asset details - const assetInDetails = TOKEN_CONFIG[swap.assetIn]; - const assetOutDetails = TOKEN_CONFIG[swap.assetOut]; + const assetInDetails = TOKEN_CONFIG[assetIn]; + const assetOutDetails = TOKEN_CONFIG[assetOut]; // call the current allowance of the user const response: ReadMessageResult = await readMessage({ @@ -52,21 +55,22 @@ export async function performSwap( } const currentAllowance = parseContractBalanceResponse(assetInDetails.decimals, response.value); - const amountToSwapBig = stringDecimalToBN(swap.amountIn.toString(), assetInDetails.decimals); - const amountMinBig = stringDecimalToBN(swap.minAmountOut?.toString() ?? '0', assetInDetails.decimals); + const rawAmountToSwapBig = multiplyByPowerOfTen(amountIn, assetInDetails.decimals); + const rawAmountMinBig = multiplyByPowerOfTen(minAmountOut, assetInDetails.decimals); + //maybe do allowance - if (currentAllowance !== undefined && currentAllowance.rawBalance.lt(amountToSwapBig)) { + if (currentAllowance !== undefined && currentAllowance.rawBalance.lt(rawAmountToSwapBig)) { try { renderEvent( `Please sign approval swap: ${toBigNumber( - amountToSwapBig, + rawAmountToSwapBig, assetInDetails.decimals, )} ${assetInDetails.assetCode.toUpperCase()}`, EventStatus.Waiting, ); await approve({ api: pendulumApiComponents.api, - amount: amountToSwapBig.toString(), + amount: rawAmountToSwapBig.toFixed(), // toString can render exponential notation token: assetInDetails.erc20Address!, spender: NABLA_ROUTER, contractAbi: erc20ContractAbi, @@ -88,15 +92,13 @@ export async function performSwap( // Try swap try { renderEvent( - `Please sign transaction to swap ${swap.amountIn} ${assetInDetails.assetCode.toUpperCase()} to ${ - swap.initialDesired - } ${assetOutDetails.assetCode.toUpperCase()} `, + `Please sign transaction to swap ${amountIn} ${assetInDetails.assetCode.toUpperCase()} to ${minAmountOut} ${assetOutDetails.assetCode.toUpperCase()} `, EventStatus.Waiting, ); await doActualSwap({ api: pendulumApiComponents.api, - amount: amountToSwapBig.toString(), - amountMin: amountMinBig.toString(), + amount: rawAmountToSwapBig.toFixed(), // toString can render exponential notation + amountMin: rawAmountMinBig.toFixed(), // toString can render exponential notation tokenIn: assetInDetails.erc20Address!, tokenOut: assetOutDetails.erc20Address!, contractAbi: routerAbiObject, @@ -112,7 +114,7 @@ export async function performSwap( } else { errorMessage = 'Something went wrong'; } - renderEvent(`Could not swap token: ${errorMessage}`, EventStatus.Error); + renderEvent(`Could not swap the required amount of token: ${errorMessage}`, EventStatus.Error); return Promise.reject('Could not swap token'); } @@ -126,9 +128,9 @@ export async function performSwap( const actualOfframpValue = balanceAfterBigDecimal.sub(balanceBeforeBigDecimal); - renderEvent(`Swap successful. Amount to offramp : ${actualOfframpValue}`, EventStatus.Success); + renderEvent(`Swap successful. Amount received: ${actualOfframpValue}`, EventStatus.Success); - return actualOfframpValue.toNumber(); + return actualOfframpValue; } async function approve({ api, token, spender, amount, contractAbi, walletAccount }: any) { From 9ba09812630de4d3ce41509b67d881f2c02dfe98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20Stu=CC=88ber?= <15174476+TorstenStueber@users.noreply.github.com> Date: Fri, 14 Jun 2024 04:25:20 -0300 Subject: [PATCH 2/6] Some fixes --- src/components/InputKeys/From.tsx | 6 +++--- src/components/InputKeys/To.tsx | 14 ++++++++------ src/components/InputKeys/index.tsx | 7 ++++--- src/components/Nabla/BalanceState.tsx | 2 +- src/hooks/nabla/useTokenAmountOut.ts | 12 ++++++++++-- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/components/InputKeys/From.tsx b/src/components/InputKeys/From.tsx index 0970add8..cff616e8 100644 --- a/src/components/InputKeys/From.tsx +++ b/src/components/InputKeys/From.tsx @@ -16,7 +16,7 @@ interface FromProps; - fromTokenBalances: { [key: string]: BalanceInfo }; + tokenBalances: { [key: string]: BalanceInfo }; offrampStarted: boolean; } @@ -27,11 +27,11 @@ export function From) { const { setValue } = useFormContext(); - const fromTokenBalance = tokenId ? fromTokenBalances[tokenId] : undefined; + const fromTokenBalance = tokenId ? tokenBalances[tokenId] : undefined; return (
{/*
{toToken ? : '$ -'}
*/} -
Your balance: {toTokenBalance}
+
+ Your balance:{' '} + {toTokenBalance ? : '0'} +
= ({ onSubmit, dAppName }) => { } // check balance of the asset used to offramp directly or to pay for the swap + console.log('balances', balances); if (balances[from].preciseBigDecimal.lt(fromAmount)) { alert( `Insufficient balance to offramp. Current balance is ${ @@ -253,13 +254,13 @@ const InputBox: React.FC = ({ onSubmit, dAppName }) => { inputHasError={inputHasErrors} form={form} fromFormFieldName="fromAmount" - fromTokenBalances={balances} + tokenBalances={balances} />
{formErrorMessage !== undefined &&

{formErrorMessage}

}
= ({ onSubmit, dAppName }) => { inputHasError={inputHasErrors} form={form} fromFormFieldName="fromAmount" - fromTokenBalances={balances} + tokenBalances={balances} /> )} diff --git a/src/components/Nabla/BalanceState.tsx b/src/components/Nabla/BalanceState.tsx index 25921ae2..a47a6aee 100644 --- a/src/components/Nabla/BalanceState.tsx +++ b/src/components/Nabla/BalanceState.tsx @@ -38,7 +38,7 @@ export const useAccountBalance = (address?: string): UseAccountBalanceResponse = try { for (const [key, config] of Object.entries(TOKEN_CONFIG)) { - const response = (await apiComponents.api.query.tokens.accounts(address, config.currencyId)).toHuman() as any; + const response = (await apiComponents.api.query.tokens.accounts(address, config.currencyId)) as any; const rawBalance = response?.free || '0'; const contractBalance = parseContractBalanceResponse(TOKEN_CONFIG[key].decimals, rawBalance); diff --git a/src/hooks/nabla/useTokenAmountOut.ts b/src/hooks/nabla/useTokenAmountOut.ts index 1143e887..37f02a1d 100644 --- a/src/hooks/nabla/useTokenAmountOut.ts +++ b/src/hooks/nabla/useTokenAmountOut.ts @@ -1,7 +1,12 @@ import BigNumber from 'big.js'; import { activeOptions, cacheKeys } from '../../constants/cache'; import { routerAbi } from '../../contracts/Router'; -import { ContractBalance, multiplyByPowerOfTen, parseContractBalanceResponse } from '../../helpers/contracts'; +import { + ContractBalance, + multiplyByPowerOfTen, + parseContractBalanceResponse, + stringifyBigWithSignificantDecimals, +} from '../../helpers/contracts'; import { NABLA_ROUTER } from '../../constants/constants'; import { useContractRead } from './useContractRead'; import { UseQueryResult } from '@tanstack/react-query'; @@ -106,7 +111,10 @@ export function useTokenOutAmount({ return { amountOut, - effectiveExchangeRate: amountOut.preciseBigDecimal.div(debouncedAmountBigDecimal).toString(), + effectiveExchangeRate: stringifyBigWithSignificantDecimals( + amountOut.preciseBigDecimal.div(debouncedAmountBigDecimal), + 4, + ), swapFee, }; }, From 34c1a32753537d10812cd9a8314fbda574e74fe7 Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Fri, 14 Jun 2024 17:13:29 +0200 Subject: [PATCH 3/6] Fix `yarn test` not working by importing a preset that enhances transpiling vite code --- config/babel.jest.cjs | 1 + jest.config.cjs | 3 -- package.json | 1 + yarn.lock | 67 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 3 deletions(-) diff --git a/config/babel.jest.cjs b/config/babel.jest.cjs index 1ff9b3ca..e18e5f6f 100644 --- a/config/babel.jest.cjs +++ b/config/babel.jest.cjs @@ -10,6 +10,7 @@ module.exports = babelJest.createTransformer({ }, ], '@babel/preset-env', + 'babel-preset-vite' ], plugins: [ [ diff --git a/jest.config.cjs b/jest.config.cjs index 197d4666..36a392be 100644 --- a/jest.config.cjs +++ b/jest.config.cjs @@ -1,8 +1,5 @@ module.exports = { roots: ['/src'], - transform: { - '\\.(ts|tsx)?$': 'babel-jest', - }, testMatch: ['**/?(*.)+(spec|test).{ts,tsx}'], testEnvironment: 'jsdom', moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], diff --git a/package.json b/package.json index a8d62de7..0b9d5e43 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "@types/testing-library__jest-dom": "^5.14.5", "@typescript-eslint/eslint-plugin": "^5.53.0", "@typescript-eslint/parser": "^5.53.0", + "babel-preset-vite": "^1.1.3", "esbuild-plugin-polyfill-node": "^0.3.0", "eslint": "^8.34.0", "eslint-plugin-jest": "^27.2.1", diff --git a/yarn.lock b/yarn.lock index 11a62c6a..802566e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1386,6 +1386,15 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.13.9": + version: 7.24.7 + resolution: "@babel/runtime@npm:7.24.7" + dependencies: + regenerator-runtime: "npm:^0.14.0" + checksum: 7b77f566165dee62db3db0296e71d08cafda3f34e1b0dcefcd68427272e17c1704f4e4369bff76651b07b6e49d3ea5a0ce344818af9116e9292e4381e0918c76 + languageName: node + linkType: hard + "@babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.23.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7": version: 7.23.5 resolution: "@babel/runtime@npm:7.23.5" @@ -4874,6 +4883,19 @@ __metadata: languageName: node linkType: hard +"@types/babel__core@npm:^7.1.12": + version: 7.20.5 + resolution: "@types/babel__core@npm:7.20.5" + dependencies: + "@babel/parser": "npm:^7.20.7" + "@babel/types": "npm:^7.20.7" + "@types/babel__generator": "npm:*" + "@types/babel__template": "npm:*" + "@types/babel__traverse": "npm:*" + checksum: c32838d280b5ab59d62557f9e331d3831f8e547ee10b4f85cb78753d97d521270cebfc73ce501e9fb27fe71884d1ba75e18658692c2f4117543f0fc4e3e118b3 + languageName: node + linkType: hard + "@types/babel__core@npm:^7.1.14": version: 7.20.0 resolution: "@types/babel__core@npm:7.20.0" @@ -6143,6 +6165,37 @@ __metadata: languageName: node linkType: hard +"babel-plugin-transform-vite-meta-env@npm:1.0.3": + version: 1.0.3 + resolution: "babel-plugin-transform-vite-meta-env@npm:1.0.3" + dependencies: + "@babel/runtime": "npm:^7.13.9" + "@types/babel__core": "npm:^7.1.12" + checksum: 60afd6358e3a16a8aae7ee911cd7a2dbdd0427a61f2d3e7eb9eaa85e4c895a1e22c620fdfd166306103f6733c2f6c5de1bc567c371d572b0f785856cc02bda32 + languageName: node + linkType: hard + +"babel-plugin-transform-vite-meta-glob@npm:1.1.2": + version: 1.1.2 + resolution: "babel-plugin-transform-vite-meta-glob@npm:1.1.2" + dependencies: + "@babel/runtime": "npm:^7.13.9" + "@types/babel__core": "npm:^7.1.12" + glob: "npm:^10.3.10" + checksum: 8a73f38a0827f07f2e5cd8f41066eb7fac08ec2ce900adc671cae817a55faf349f4f17946971d3fd80eb5f31657cd58c44e6da8f5a47668e39da0d90facd64bd + languageName: node + linkType: hard + +"babel-plugin-transform-vite-meta-hot@npm:1.0.0": + version: 1.0.0 + resolution: "babel-plugin-transform-vite-meta-hot@npm:1.0.0" + dependencies: + "@babel/runtime": "npm:^7.13.9" + "@types/babel__core": "npm:^7.1.12" + checksum: bcaeecbe89f6f279c8bf90afa2cec0f3e86576179b268cefba9acac4070799a243e66d6e31ec6283068df964a5beb746390ed025b52bb6fc651e69a1610ccaa5 + languageName: node + linkType: hard + "babel-preset-current-node-syntax@npm:^1.0.0": version: 1.0.1 resolution: "babel-preset-current-node-syntax@npm:1.0.1" @@ -6177,6 +6230,19 @@ __metadata: languageName: node linkType: hard +"babel-preset-vite@npm:^1.1.3": + version: 1.1.3 + resolution: "babel-preset-vite@npm:1.1.3" + dependencies: + "@babel/runtime": "npm:^7.13.9" + "@types/babel__core": "npm:^7.1.12" + babel-plugin-transform-vite-meta-env: "npm:1.0.3" + babel-plugin-transform-vite-meta-glob: "npm:1.1.2" + babel-plugin-transform-vite-meta-hot: "npm:1.0.0" + checksum: 243b43c25846a597a03cf36b1b0e6b39d209f5a13207a238bdc9a03b61fcdd450abe2a26595cde17513c321ba63071868def875a54664e45058b5c532f8306a4 + languageName: node + linkType: hard + "babel-runtime@npm:6.26.0": version: 6.26.0 resolution: "babel-runtime@npm:6.26.0" @@ -12610,6 +12676,7 @@ __metadata: "@walletconnect/modal": "npm:^2.6.2" "@walletconnect/universal-provider": "npm:^2.12.2" autoprefixer: "npm:^10.4.19" + babel-preset-vite: "npm:^1.1.3" big.js: "npm:^6.2.1" bn.js: "npm:^5.2.1" buffer: "npm:^6.0.3" From 3bf2a4980305ae4a7033d2c0f1b26f4d5288accb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20Stu=CC=88ber?= <15174476+TorstenStueber@users.noreply.github.com> Date: Sun, 16 Jun 2024 22:00:59 -0300 Subject: [PATCH 4/6] Fix errors: useQuery result must not be undefined --- App.css | 1 - src/components/InputKeys/To.tsx | 6 +++--- src/components/InputKeys/index.tsx | 6 +++--- src/hooks/nabla/useContractRead.ts | 8 ++++---- src/hooks/nabla/useTokenAmountOut.ts | 8 ++++---- src/services/nabla.ts | 2 +- src/services/polkadot/index.tsx | 2 -- 7 files changed, 15 insertions(+), 18 deletions(-) diff --git a/App.css b/App.css index 1d27074d..0654f8be 100644 --- a/App.css +++ b/App.css @@ -127,7 +127,6 @@ body { } .inputBox.active { - width: 35%; margin-top: 5px; } diff --git a/src/components/InputKeys/To.tsx b/src/components/InputKeys/To.tsx index b853fc01..08975973 100644 --- a/src/components/InputKeys/To.tsx +++ b/src/components/InputKeys/To.tsx @@ -52,7 +52,7 @@ export function To({
{toAmountQuote.isLoading ? ( - ) : toAmountQuote.data !== undefined ? ( + ) : toAmountQuote.data !== undefined && toAmountQuote.data !== null ? ( `${toAmountQuote.data.amountOut.approximateStrings.atLeast4Decimals}` ) : fromAmount !== undefined && fromAmount.gt(0) ? (