+
{allChains.map((c) => (
-
- Sending two transactions: Approve and Swap
+
+ {needsApproval
+ ? 'Sending two transactions: Approve and Swap'
+ : 'Sending swap transaction'}
+
+
+ {`Sign with ${connector?.name || 'wallet'} to proceed`}
-
{`Sign with ${
- connector?.name || 'wallet'
- } to proceed`}
>
)
diff --git a/src/features/swap/SwapForm.tsx b/src/features/swap/SwapForm.tsx
index 917d8de..b8e567f 100644
--- a/src/features/swap/SwapForm.tsx
+++ b/src/features/swap/SwapForm.tsx
@@ -20,7 +20,7 @@ import { reset as blockReset } from 'src/features/blocks/blockSlice'
import { resetTokenPrices } from 'src/features/chart/tokenPriceSlice'
import { useAppDispatch, useAppSelector } from 'src/features/store/hooks'
import { SettingsMenu } from 'src/features/swap/SettingsMenu'
-import { setFormValues, reset as swapReset } from 'src/features/swap/swapSlice'
+import { setConfirmView, setFormValues, reset as swapReset } from 'src/features/swap/swapSlice'
import { SwapDirection, SwapFormValues } from 'src/features/swap/types'
import { useFormValidator } from 'src/features/swap/useFormValidator'
import { useSwapQuote } from 'src/features/swap/useSwapQuote'
@@ -60,18 +60,21 @@ export function SwapFormCard() {
}
function SwapForm() {
- const balances = useAppSelector((s) => s.account.balances)
+ const { balances, lastUpdated } = useAppSelector((s) => s.account)
const { showSlippage } = useAppSelector((s) => s.swap)
const dispatch = useAppDispatch()
const onSubmit = (values: SwapFormValues) => {
dispatch(setFormValues(values))
+ dispatch(setConfirmView(true)) // Switch to confirm view
}
- const validateForm = useFormValidator(balances)
+ const validateForm = useFormValidator(balances, lastUpdated)
+ const storedFormValues = useAppSelector((s) => s.swap.formValues) // Get stored form values
+ const initialFormValues = storedFormValues || initialValues // Use stored values if they exist
return (
- initialValues={initialValues}
+ initialValues={initialFormValues}
onSubmit={onSubmit}
validate={validateForm}
validateOnChange={true}
@@ -329,7 +332,7 @@ function SubmitButton() {
const showLongError = typeof error === 'string' && error?.length > 50
return (
-
+
{showLongError ? (
{error}
) : null}
diff --git a/src/features/swap/swapSlice.ts b/src/features/swap/swapSlice.ts
index 26477bc..32d45db 100644
--- a/src/features/swap/swapSlice.ts
+++ b/src/features/swap/swapSlice.ts
@@ -6,6 +6,7 @@ export interface SwapState {
toCeloRates: ToCeloRates
showSlippage: boolean
showChart: boolean
+ confirmView: boolean
}
const initialState: SwapState = {
@@ -13,6 +14,7 @@ const initialState: SwapState = {
toCeloRates: {},
showSlippage: false,
showChart: false,
+ confirmView: false,
}
export const swapSlice = createSlice({
@@ -29,8 +31,12 @@ export const swapSlice = createSlice({
state.showChart = action.payload
},
reset: () => initialState,
+ setConfirmView(state, action) {
+ state.confirmView = action.payload
+ },
},
})
-export const { setFormValues, setShowSlippage, setShowChart, reset } = swapSlice.actions
+export const { setFormValues, setShowSlippage, setShowChart, reset, setConfirmView } =
+ swapSlice.actions
export const swapReducer = swapSlice.reducer
diff --git a/src/features/swap/useAllowance.tsx b/src/features/swap/useAllowance.tsx
new file mode 100644
index 0000000..467bab6
--- /dev/null
+++ b/src/features/swap/useAllowance.tsx
@@ -0,0 +1,43 @@
+import { useQuery } from '@tanstack/react-query'
+import { Contract } from 'ethers'
+import { ERC20_ABI } from 'src/config/consts'
+import { BrokerAddresses } from 'src/config/exchanges'
+import { TokenId, getTokenAddress } from 'src/config/tokens'
+import { getProvider } from 'src/features/providers'
+import { logger } from 'src/utils/logger'
+
+async function fetchAllowance(
+ tokenAddr: string,
+ accountAddress: string,
+ chainId: number
+): Promise
{
+ logger.info(`Fetching allowance for token ${tokenAddr} on chain ${chainId}`)
+ const provider = getProvider(chainId)
+ const contract = new Contract(tokenAddr, ERC20_ABI, provider)
+ const brokerAddress = BrokerAddresses[chainId as keyof typeof BrokerAddresses]
+
+ const allowance = await contract.allowance(accountAddress, brokerAddress)
+ logger.info(`Allowance: ${allowance.toString()}`)
+ return allowance.toString()
+}
+
+export function useAllowance(chainId: number, tokenId: TokenId, accountAddress?: string) {
+ const { data: allowance, isLoading } = useQuery(
+ ['tokenAllowance', chainId, tokenId, accountAddress],
+ async () => {
+ if (!accountAddress) return '0'
+ const tokenAddr = getTokenAddress(tokenId, chainId)
+ return fetchAllowance(tokenAddr, accountAddress, chainId)
+ },
+ {
+ retry: false,
+ enabled: Boolean(accountAddress && chainId && tokenId),
+ staleTime: 5000, // Consider allowance stale after 5 seconds
+ }
+ )
+
+ return {
+ allowance: allowance || '0',
+ isLoading,
+ }
+}
diff --git a/src/features/swap/useFormValidator.ts b/src/features/swap/useFormValidator.ts
index 410731f..4f26f1a 100644
--- a/src/features/swap/useFormValidator.ts
+++ b/src/features/swap/useFormValidator.ts
@@ -9,11 +9,12 @@ import { areAmountsNearlyEqual, parseAmount, toWei } from 'src/utils/amount'
import { logger } from 'src/utils/logger'
import { useChainId } from 'wagmi'
-export function useFormValidator(balances: AccountBalances) {
+export function useFormValidator(balances: AccountBalances, lastUpdated: number | null) {
const chainId = useChainId()
return useCallback(
(values?: SwapFormValues): Promise> => {
return (async () => {
+ if (!lastUpdated) return { fromTokenId: 'Balance still loading' }
if (!values || !values.amount) return { amount: 'Amount Required' }
const parsedAmount = parseAmount(values.amount)
if (!parsedAmount) return { amount: 'Amount is Invalid' }
@@ -33,7 +34,7 @@ export function useFormValidator(balances: AccountBalances) {
return {}
})
},
- [balances, chainId]
+ [balances, chainId, lastUpdated]
)
}
diff --git a/src/features/swap/useSwapQuote.ts b/src/features/swap/useSwapQuote.ts
index 5510006..f6842ba 100644
--- a/src/features/swap/useSwapQuote.ts
+++ b/src/features/swap/useSwapQuote.ts
@@ -48,7 +48,7 @@ export function useSwapQuote(
quoteWei = (await mento.getAmountIn(fromTokenAddr, toTokenAddr, amountWeiBN)).toString()
}
- const quote = fromWei(quoteWei, quoteDecimals).toString()
+ const quote = fromWei(quoteWei, quoteDecimals)
const rateIn = calcExchangeRate(amountWei, amountDecimals, quoteWei, quoteDecimals)
const rate = isSwapIn ? rateIn : invertExchangeRate(rateIn)
diff --git a/src/features/swap/useSwapTransaction.ts b/src/features/swap/useSwapTransaction.ts
index 6680883..3532161 100644
--- a/src/features/swap/useSwapTransaction.ts
+++ b/src/features/swap/useSwapTransaction.ts
@@ -36,8 +36,10 @@ export function useSwapTransaction(
!isApproveConfirmed ||
new BigNumber(amountInWei).lte(0) ||
new BigNumber(thresholdAmountInWei).lte(0)
- )
+ ) {
+ logger.debug('Skipping swap transaction')
return null
+ }
const sdk = await getMentoSdk(chainId)
const fromTokenAddr = getTokenAddress(fromToken, chainId)
const toTokenAddr = getTokenAddress(toToken, chainId)
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index 9b3d369..1fdf637 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -6,11 +6,15 @@ import { SwapConfirmCard } from 'src/features/swap/SwapConfirm'
import { SwapFormCard } from 'src/features/swap/SwapForm'
export default function SwapPage() {
- const { formValues, showChart } = useAppSelector((state) => state.swap)
+ const { formValues, showChart, confirmView } = useAppSelector((state) => state.swap)
return (
- {!formValues ? : }
+ {!formValues || !confirmView ? (
+
+ ) : (
+
+ )}{' '}
{config.showPriceChart && showChart && (
diff --git a/src/utils/amount.ts b/src/utils/amount.ts
index b5eb359..f3a98d6 100644
--- a/src/utils/amount.ts
+++ b/src/utils/amount.ts
@@ -11,11 +11,11 @@ export type NumberT = BigNumber.Value
export function fromWei(
value: NumberT | null | undefined,
decimals = STANDARD_TOKEN_DECIMALS
-): number {
- if (!value) return 0
+): string {
+ if (!value) return '0'
const valueString = value.toString().trim()
const flooredValue = new BigNumber(valueString).toFixed(0, BigNumber.ROUND_FLOOR)
- return parseFloat(formatUnits(flooredValue, decimals))
+ return formatUnits(flooredValue, decimals)
}
// Similar to fromWei above but rounds to set number of decimals
diff --git a/yarn.lock b/yarn.lock
index 3da01b0..36bc5bd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1940,7 +1940,7 @@ __metadata:
jest: ^29.5.0
jsbi: ^4.3.0
lottie-react: ^2.4.0
- next: 13.5.7-canary.37
+ next: 14.2.15
postcss: ^8.4.32
prettier: ^2.8.8
react: ^18.2.0
@@ -2124,10 +2124,10 @@ __metadata:
languageName: node
linkType: hard
-"@next/env@npm:13.5.7-canary.37":
- version: 13.5.7-canary.37
- resolution: "@next/env@npm:13.5.7-canary.37"
- checksum: cbeba53f806a30fdbbbaa48785b0784702953d2e4e3a7bc6a14cb7e6e6e005232050cc627368b233257b1d60bcc41af5cfd6d0ee789497e4c4736f40e3956177
+"@next/env@npm:14.2.15":
+ version: 14.2.15
+ resolution: "@next/env@npm:14.2.15"
+ checksum: bf794604ee62e86ca092120c790815c0caf367009966baa14e75dbd8454a59df524327539d5febc7da42841c3bf6a10443ae0f95280599352a8def56291857fd
languageName: node
linkType: hard
@@ -2140,65 +2140,65 @@ __metadata:
languageName: node
linkType: hard
-"@next/swc-darwin-arm64@npm:13.5.7-canary.37":
- version: 13.5.7-canary.37
- resolution: "@next/swc-darwin-arm64@npm:13.5.7-canary.37"
+"@next/swc-darwin-arm64@npm:14.2.15":
+ version: 14.2.15
+ resolution: "@next/swc-darwin-arm64@npm:14.2.15"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
-"@next/swc-darwin-x64@npm:13.5.7-canary.37":
- version: 13.5.7-canary.37
- resolution: "@next/swc-darwin-x64@npm:13.5.7-canary.37"
+"@next/swc-darwin-x64@npm:14.2.15":
+ version: 14.2.15
+ resolution: "@next/swc-darwin-x64@npm:14.2.15"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
-"@next/swc-linux-arm64-gnu@npm:13.5.7-canary.37":
- version: 13.5.7-canary.37
- resolution: "@next/swc-linux-arm64-gnu@npm:13.5.7-canary.37"
+"@next/swc-linux-arm64-gnu@npm:14.2.15":
+ version: 14.2.15
+ resolution: "@next/swc-linux-arm64-gnu@npm:14.2.15"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
-"@next/swc-linux-arm64-musl@npm:13.5.7-canary.37":
- version: 13.5.7-canary.37
- resolution: "@next/swc-linux-arm64-musl@npm:13.5.7-canary.37"
+"@next/swc-linux-arm64-musl@npm:14.2.15":
+ version: 14.2.15
+ resolution: "@next/swc-linux-arm64-musl@npm:14.2.15"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
-"@next/swc-linux-x64-gnu@npm:13.5.7-canary.37":
- version: 13.5.7-canary.37
- resolution: "@next/swc-linux-x64-gnu@npm:13.5.7-canary.37"
+"@next/swc-linux-x64-gnu@npm:14.2.15":
+ version: 14.2.15
+ resolution: "@next/swc-linux-x64-gnu@npm:14.2.15"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
-"@next/swc-linux-x64-musl@npm:13.5.7-canary.37":
- version: 13.5.7-canary.37
- resolution: "@next/swc-linux-x64-musl@npm:13.5.7-canary.37"
+"@next/swc-linux-x64-musl@npm:14.2.15":
+ version: 14.2.15
+ resolution: "@next/swc-linux-x64-musl@npm:14.2.15"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
-"@next/swc-win32-arm64-msvc@npm:13.5.7-canary.37":
- version: 13.5.7-canary.37
- resolution: "@next/swc-win32-arm64-msvc@npm:13.5.7-canary.37"
+"@next/swc-win32-arm64-msvc@npm:14.2.15":
+ version: 14.2.15
+ resolution: "@next/swc-win32-arm64-msvc@npm:14.2.15"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
-"@next/swc-win32-ia32-msvc@npm:13.5.7-canary.37":
- version: 13.5.7-canary.37
- resolution: "@next/swc-win32-ia32-msvc@npm:13.5.7-canary.37"
+"@next/swc-win32-ia32-msvc@npm:14.2.15":
+ version: 14.2.15
+ resolution: "@next/swc-win32-ia32-msvc@npm:14.2.15"
conditions: os=win32 & cpu=ia32
languageName: node
linkType: hard
-"@next/swc-win32-x64-msvc@npm:13.5.7-canary.37":
- version: 13.5.7-canary.37
- resolution: "@next/swc-win32-x64-msvc@npm:13.5.7-canary.37"
+"@next/swc-win32-x64-msvc@npm:14.2.15":
+ version: 14.2.15
+ resolution: "@next/swc-win32-x64-msvc@npm:14.2.15"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
@@ -2633,12 +2633,20 @@ __metadata:
languageName: node
linkType: hard
-"@swc/helpers@npm:0.5.2":
- version: 0.5.2
- resolution: "@swc/helpers@npm:0.5.2"
+"@swc/counter@npm:^0.1.3":
+ version: 0.1.3
+ resolution: "@swc/counter@npm:0.1.3"
+ checksum: df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598
+ languageName: node
+ linkType: hard
+
+"@swc/helpers@npm:0.5.5":
+ version: 0.5.5
+ resolution: "@swc/helpers@npm:0.5.5"
dependencies:
+ "@swc/counter": ^0.1.3
tslib: ^2.4.0
- checksum: 51d7e3d8bd56818c49d6bfbd715f0dbeedc13cf723af41166e45c03e37f109336bbcb57a1f2020f4015957721aeb21e1a7fff281233d797ff7d3dd1f447fa258
+ checksum: d4f207b191e54b29460804ddf2984ba6ece1d679a0b2f6a9c765dcf27bba92c5769e7965668a4546fb9f1021eaf0ff9be4bf5c235ce12adcd65acdfe77187d11
languageName: node
linkType: hard
@@ -4661,13 +4669,20 @@ __metadata:
languageName: node
linkType: hard
-"caniuse-lite@npm:^1.0.30001400, caniuse-lite@npm:^1.0.30001406, caniuse-lite@npm:^1.0.30001449, caniuse-lite@npm:^1.0.30001464":
+"caniuse-lite@npm:^1.0.30001400, caniuse-lite@npm:^1.0.30001449, caniuse-lite@npm:^1.0.30001464":
version: 1.0.30001568
resolution: "caniuse-lite@npm:1.0.30001568"
checksum: 7092aaa246dc8531fbca5b47be91e92065db7e5c04cc9e3d864e848f8f1be769ac6754429e843a5e939f7331a771e8b0a1bc3b13495c66b748c65e2f5bdb1220
languageName: node
linkType: hard
+"caniuse-lite@npm:^1.0.30001579":
+ version: 1.0.30001690
+ resolution: "caniuse-lite@npm:1.0.30001690"
+ checksum: f2c1b595f15d8de4d9ccd155d61ac9f00ac62f1515870505a0186266fd52aef169fcddc90d8a4814e52b77107244806466fadc2c216662f23f1022a430e735ee
+ languageName: node
+ linkType: hard
+
"case@npm:^1.6.3":
version: 1.6.3
resolution: "case@npm:1.6.3"
@@ -6394,13 +6409,6 @@ __metadata:
languageName: node
linkType: hard
-"glob-to-regexp@npm:^0.4.1":
- version: 0.4.1
- resolution: "glob-to-regexp@npm:0.4.1"
- checksum: e795f4e8f06d2a15e86f76e4d92751cf8bbfcf0157cea5c2f0f35678a8195a750b34096b1256e436f0cebc1883b5ff0888c47348443e69546a5a87f9e1eb1167
- languageName: node
- linkType: hard
-
"glob@npm:7.1.6":
version: 7.1.6
resolution: "glob@npm:7.1.6"
@@ -6508,7 +6516,7 @@ __metadata:
languageName: node
linkType: hard
-"graceful-fs@npm:^4.1.2":
+"graceful-fs@npm:^4.2.11":
version: 4.2.11
resolution: "graceful-fs@npm:4.2.11"
checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7
@@ -8456,28 +8464,29 @@ __metadata:
languageName: node
linkType: hard
-"next@npm:13.5.7-canary.37":
- version: 13.5.7-canary.37
- resolution: "next@npm:13.5.7-canary.37"
+"next@npm:14.2.15":
+ version: 14.2.15
+ resolution: "next@npm:14.2.15"
dependencies:
- "@next/env": 13.5.7-canary.37
- "@next/swc-darwin-arm64": 13.5.7-canary.37
- "@next/swc-darwin-x64": 13.5.7-canary.37
- "@next/swc-linux-arm64-gnu": 13.5.7-canary.37
- "@next/swc-linux-arm64-musl": 13.5.7-canary.37
- "@next/swc-linux-x64-gnu": 13.5.7-canary.37
- "@next/swc-linux-x64-musl": 13.5.7-canary.37
- "@next/swc-win32-arm64-msvc": 13.5.7-canary.37
- "@next/swc-win32-ia32-msvc": 13.5.7-canary.37
- "@next/swc-win32-x64-msvc": 13.5.7-canary.37
- "@swc/helpers": 0.5.2
+ "@next/env": 14.2.15
+ "@next/swc-darwin-arm64": 14.2.15
+ "@next/swc-darwin-x64": 14.2.15
+ "@next/swc-linux-arm64-gnu": 14.2.15
+ "@next/swc-linux-arm64-musl": 14.2.15
+ "@next/swc-linux-x64-gnu": 14.2.15
+ "@next/swc-linux-x64-musl": 14.2.15
+ "@next/swc-win32-arm64-msvc": 14.2.15
+ "@next/swc-win32-ia32-msvc": 14.2.15
+ "@next/swc-win32-x64-msvc": 14.2.15
+ "@swc/helpers": 0.5.5
busboy: 1.6.0
- caniuse-lite: ^1.0.30001406
+ caniuse-lite: ^1.0.30001579
+ graceful-fs: ^4.2.11
postcss: 8.4.31
styled-jsx: 5.1.1
- watchpack: 2.4.0
peerDependencies:
"@opentelemetry/api": ^1.1.0
+ "@playwright/test": ^1.41.2
react: ^18.2.0
react-dom: ^18.2.0
sass: ^1.3.0
@@ -8503,11 +8512,13 @@ __metadata:
peerDependenciesMeta:
"@opentelemetry/api":
optional: true
+ "@playwright/test":
+ optional: true
sass:
optional: true
bin:
next: dist/bin/next
- checksum: 1b10587ee764d86e4a9135359fdf6d636f549326518a8c45efdbc6fc55ad8dd4e3214d6db7bc0ec35992b87c07ae34da4452a794c16a60e1aa59d5f324ce0183
+ checksum: bed22817ea82c679e78c1f1e6530991ae89f3c51d547a876dddcda4a3b34cbb970af7c714793e1a1f0a1974859ccc97e10b5aceb61e9807ea94318116e8e7dd6
languageName: node
linkType: hard
@@ -11076,16 +11087,6 @@ __metadata:
languageName: node
linkType: hard
-"watchpack@npm:2.4.0":
- version: 2.4.0
- resolution: "watchpack@npm:2.4.0"
- dependencies:
- glob-to-regexp: ^0.4.1
- graceful-fs: ^4.1.2
- checksum: 23d4bc58634dbe13b86093e01c6a68d8096028b664ab7139d58f0c37d962d549a940e98f2f201cecdabd6f9c340338dc73ef8bf094a2249ef582f35183d1a131
- languageName: node
- linkType: hard
-
"webextension-polyfill-ts@npm:^0.22.0":
version: 0.22.0
resolution: "webextension-polyfill-ts@npm:0.22.0"