From a9365ba7535fa656adc12c0b2c7a3a994349639b Mon Sep 17 00:00:00 2001 From: ChefEric <173023571+chef-eric@users.noreply.github.com> Date: Wed, 12 Feb 2025 22:26:39 +0800 Subject: [PATCH] fix: add liquidity support native TON --- apps/ton/public/lists/testnet.json | 8 + apps/ton/src/hooks/swap/useAllCommonPairs.ts | 12 +- apps/ton/src/hooks/useUserAddress.ts | 8 + apps/ton/src/ton/generateQueryId.ts | 7 +- .../ton/logic/liquidity/useAddLiquidity.ts | 142 ++++++------------ apps/ton/src/ton/logic/swap/useSwap.ts | 8 +- 6 files changed, 74 insertions(+), 111 deletions(-) create mode 100644 apps/ton/src/hooks/useUserAddress.ts diff --git a/apps/ton/public/lists/testnet.json b/apps/ton/public/lists/testnet.json index 1534627983d5c..b55f42cac4a11 100644 --- a/apps/ton/public/lists/testnet.json +++ b/apps/ton/public/lists/testnet.json @@ -66,6 +66,14 @@ "symbol": "PAN", "decimals": 9, "logoURI": "https://cache.tonapi.io/imgproxy/lDgkbWC5IEAEMkI7blExSx5wvL0-g9yrw2RwfUMKbSg/rs:fill:200:200:1/g:no/aHR0cHM6Ly93d3cucHJlbWllcmtpdGNoZW4uaW4vd3AtY29udGVudC91cGxvYWRzLzIwMjEvMDMvTlMtRnJ5cGFuLTEuanBn.webp" + }, + { + "chainId": -3, + "address": "kQD0zbW5arqfo7uaNs7TiBckhPp0m8xZgsMs6qdBU85p9UVB", + "name": "claude", + "symbol": "CLAUDE", + "decimals": 9, + "logoURI": "https://cache.tonapi.io/imgproxy/cOMlJuViiVXDCkAghnyNj7plX8pAZ9pv3WhklvebpTY/rs:fill:200:200:1/g:no/aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3RvbmtlZXBlci9vcGVudG9uYXBpL21hc3Rlci9wa2cvcmVmZXJlbmNlcy9tZWRpYS90b2tlbl9wbGFjZWhvbGRlci5wbmc.webp" } ] } diff --git a/apps/ton/src/hooks/swap/useAllCommonPairs.ts b/apps/ton/src/hooks/swap/useAllCommonPairs.ts index a8d62b45989ae..7164ef5c589e8 100644 --- a/apps/ton/src/hooks/swap/useAllCommonPairs.ts +++ b/apps/ton/src/hooks/swap/useAllCommonPairs.ts @@ -5,6 +5,7 @@ import { Currency, Token, Pair, CurrencyAmount } from '@pancakeswap/ton-v2-sdk' import { ADDITIONAL_BASES, BASES_TO_CHECK_TRADES_AGAINST, CUSTOM_BASES } from 'config/constants/exchange' import { useAtomValue } from 'jotai' import { poolDataQueriesAtom } from 'ton/atom/liquidity/poolDataQueriesAtom' +import { useUserAddress } from 'hooks/useUserAddress' export function useAllCommonPairs(currencyA?: Currency, currencyB?: Currency): { isLoading: boolean; data: Pair[] } { const chainId = currencyA?.chainId @@ -83,20 +84,21 @@ export function useAllCommonPairs(currencyA?: Currency, currencyB?: Currency): { } const usePairs = (pairs: [Token, Token][]) => { + const userAddress = useUserAddress() const pairsAddress = useMemo( () => pairs.map(([token0, token1]) => token0.sortsBefore(token1) ? { - token0Address: token0.wrapped.address, - token1Address: token1.wrapped.address, + token0Address: token0.isNative ? userAddress.toString() : token0.wrapped.address, + token1Address: token1.isNative ? userAddress.toString() : token1.wrapped.address, } : { - token0Address: token1.wrapped.address, - token1Address: token0.wrapped.address, + token1Address: token0.isNative ? userAddress.toString() : token0.wrapped.address, + token0Address: token1.isNative ? userAddress.toString() : token1.wrapped.address, }, ), - [pairs], + [pairs, userAddress], ) const result = useAtomValue(poolDataQueriesAtom(pairsAddress)) return useMemo(() => { diff --git a/apps/ton/src/hooks/useUserAddress.ts b/apps/ton/src/hooks/useUserAddress.ts new file mode 100644 index 0000000000000..4bfb05816ee16 --- /dev/null +++ b/apps/ton/src/hooks/useUserAddress.ts @@ -0,0 +1,8 @@ +import { useAtomValue } from 'jotai' +import { addressAtom } from 'ton/atom/addressAtom' +import { parseAddress } from 'ton/utils/address' + +export const useUserAddress = () => { + const userAddress = useAtomValue(addressAtom) + return parseAddress(userAddress) +} diff --git a/apps/ton/src/ton/generateQueryId.ts b/apps/ton/src/ton/generateQueryId.ts index b9418aec10f3c..f9106791c35e3 100644 --- a/apps/ton/src/ton/generateQueryId.ts +++ b/apps/ton/src/ton/generateQueryId.ts @@ -1,8 +1,5 @@ -import { Address } from '@ton/core' - -export function generateQueryId(userAddress: Address): bigint { +export function generateQueryId(): bigint { const timestamp = BigInt(Date.now()) // Current time in milliseconds const randomPart = BigInt(Math.floor(Math.random() * 1000)) // Random 3 digits - const addressPart = BigInt(parseInt(userAddress.toString().slice(-6), 16)) // Last 6 hex digits of the address - return (timestamp * 1000n + randomPart) ^ addressPart + return timestamp * 100000n + randomPart } diff --git a/apps/ton/src/ton/logic/liquidity/useAddLiquidity.ts b/apps/ton/src/ton/logic/liquidity/useAddLiquidity.ts index 2fbdf59bd224b..cc3149b25f6f6 100644 --- a/apps/ton/src/ton/logic/liquidity/useAddLiquidity.ts +++ b/apps/ton/src/ton/logic/liquidity/useAddLiquidity.ts @@ -1,13 +1,14 @@ import { Currency, storeAddLiquidity } from '@pancakeswap/ton-v2-sdk' -import { storeJettonTransferMessage } from '@ton-community/assets-sdk' +import { JETTON_TRANSFER_NOTIFICATION_OPCODE, storeJettonTransferMessage } from '@ton-community/assets-sdk' import { beginCell, toNano } from '@ton/core' import { SendTransactionRequest, useTonConnectUI } from '@tonconnect/ui-react' +import { useUserAddress } from 'hooks/useUserAddress' import { useAtomValue } from 'jotai' import { useCallback } from 'react' -import { addressAtom } from 'ton/atom/addressAtom' import { routerContractAtom } from 'ton/atom/contracts/routerContractAtom' import { TonContext } from 'ton/context/TonContext' -import { getJettonWalletAddress, parseAddress } from 'ton/utils/address' +import { generateQueryId } from 'ton/generateQueryId' +import { getJettonWalletAddress } from 'ton/utils/address' interface AddLiquidityArgs { token0: Currency @@ -20,23 +21,24 @@ interface AddLiquidityArgs { export const useAddLiquidity = () => { const [tonUI] = useTonConnectUI() - const userAddress_ = useAtomValue(addressAtom) + const userAddress = useUserAddress() const routerAddress = useAtomValue(routerContractAtom).address const addLiquidity = useCallback( async ({ token0, token1, amount0, amount1 }: AddLiquidityArgs) => { const client = TonContext.instance.getClient() - const userAddress = parseAddress(userAddress_) const userJettonWallet0 = await getJettonWalletAddress(client, userAddress, token0) const userJettonWallet1 = await getJettonWalletAddress(client, userAddress, token1) const routerJettonWallet0 = await getJettonWalletAddress(client, routerAddress, token0) const routerJettonWallet1 = await getJettonWalletAddress(client, routerAddress, token1) - const newForwardPayload0 = beginCell() + const queryId = generateQueryId() + + const forwardPayload0 = beginCell() .store( storeAddLiquidity({ - queryId: 1n, + queryId, $$type: 'AddLiquidity', minLPOut: 2n, tokenWallet: routerJettonWallet1, @@ -46,21 +48,21 @@ export const useAddLiquidity = () => { const payload0 = beginCell() .store( storeJettonTransferMessage({ - queryId: 1n, + queryId, amount: amount0, destination: routerAddress, responseDestination: userAddress, customPayload: null, forwardAmount: toNano('0.3'), - forwardPayload: newForwardPayload0, + forwardPayload: forwardPayload0, }), ) .endCell() - const newForwardPayload1 = beginCell() + const forwardPayload1 = beginCell() .store( storeAddLiquidity({ - queryId: 2n, + queryId, $$type: 'AddLiquidity', minLPOut: 2n, tokenWallet: routerJettonWallet0, @@ -70,13 +72,13 @@ export const useAddLiquidity = () => { const payload1 = beginCell() .store( storeJettonTransferMessage({ - queryId: 2n, + queryId, amount: amount1, destination: routerAddress, responseDestination: userAddress, customPayload: null, forwardAmount: toNano('0.3'), - forwardPayload: newForwardPayload1, + forwardPayload: forwardPayload1, }), ) .endCell() @@ -84,94 +86,42 @@ export const useAddLiquidity = () => { const txRequest: SendTransactionRequest = { validUntil: Math.floor(Date.now() / 1000) + 60 * 2, messages: [ - { - address: userJettonWallet0.toString(), - amount: toNano('0.2').toString(), - payload: payload0.toBoc().toString('base64'), - }, - { - address: userJettonWallet1.toString(), - amount: toNano('0.2').toString(), - payload: payload1.toBoc().toString('base64'), - }, + token0.isNative + ? { + address: routerAddress.toString(), + amount: (BigInt(amount0) + toNano('0.3')).toString(), // TON amount + gas + payload: beginCell() + .storeUint(JETTON_TRANSFER_NOTIFICATION_OPCODE, 32) + .storeUint(queryId, 64) + .storeCoins(amount0) + .storeAddress(userAddress) + .storeMaybeRef(forwardPayload0) + .endCell() + .toBoc() + .toString('base64'), + } + : { + address: userJettonWallet0.toString(), + amount: toNano('0.6').toString(), + payload: payload0.toBoc().toString('base64'), + }, + token1.isNative + ? { + address: routerAddress.toString(), + amount: (BigInt(amount1) + toNano('0.3')).toString(), // TON amount + gas + payload: forwardPayload1.toBoc().toString('base64'), + } + : { + address: userJettonWallet1.toString(), + amount: toNano('0.6').toString(), + payload: payload1.toBoc().toString('base64'), + }, ], } tonUI.sendTransaction(txRequest) - - /// NEW WAY OF SENDING ADD LIQUIDITY TXN - - // const newForwardPayload0 = beginCell() - // .store( - // storeAddLiquidity({ - // queryId: 1n, - // $$type: 'AddLiquidity', - // minLPOut: 0n, - // newAmount0: amount0, - // newAmount1: amount1, - // }), - // ) - // .endCell() - - // const payload0 = beginCell() - // .store( - // storeJettonTransferMessage({ - // queryId: 1n, - // amount: amount0, - // destination: routerAddress, - // responseDestination: walletAddress, - // customPayload: null, - // forwardAmount: toNano('0.1'), - // forwardPayload: newForwardPayload0, - // }), - // ) - // .endCell() - - // const newForwardPayload1 = beginCell() - // .store( - // storeAddLiquidity({ - // queryId: 2n, - // $$type: 'AddLiquidity', - // minLPOut: 0n, - // newAmount0: amount0, - // newAmount1: amount1, - // }), - // ) - // .endCell() - - // const payload1 = beginCell() - // .store( - // storeJettonTransferMessage({ - // queryId: 2n, - // amount: amount1, - // destination: routerAddress, - // responseDestination: walletAddress, - // customPayload: null, - // forwardAmount: toNano('0.1'), - // forwardPayload: newForwardPayload1, - // }), - // ) - // .endCell() - - const newTxRequest: SendTransactionRequest = { - validUntil: Math.floor(Date.now() / 1000) + 60 * 2, - messages: [ - { - address: userJettonWallet0.toString(), - amount: toNano('0.6').toString(), - payload: payload0.toBoc().toString('base64'), - }, - { - address: userJettonWallet1.toString(), - amount: toNano('0.6').toString(), - payload: payload1.toBoc().toString('base64'), - }, - ], - } - - tonUI.sendTransaction(newTxRequest) }, - [tonUI, userAddress_, routerAddress], + [tonUI, userAddress, routerAddress], ) return { diff --git a/apps/ton/src/ton/logic/swap/useSwap.ts b/apps/ton/src/ton/logic/swap/useSwap.ts index bd681b7adce6a..c5ff3d2b7b859 100644 --- a/apps/ton/src/ton/logic/swap/useSwap.ts +++ b/apps/ton/src/ton/logic/swap/useSwap.ts @@ -2,9 +2,8 @@ import { Contracts, Currency, TonContractNames, storeSwap } from '@pancakeswap/t import { storeJettonTransferMessage } from '@ton-community/assets-sdk' import { beginCell, toNano } from '@ton/core' import { SendTransactionRequest, useTonConnectUI } from '@tonconnect/ui-react' -import { useAtomValue } from 'jotai' +import { useUserAddress } from 'hooks/useUserAddress' import { useCallback } from 'react' -import { addressAtom } from 'ton/atom/addressAtom' import { TonContext } from 'ton/context/TonContext' import { getJettonWalletAddress, parseAddress } from 'ton/utils/address' @@ -16,13 +15,12 @@ interface SwapArgs { } export const useSwap = () => { - const userAddress_ = useAtomValue(addressAtom) const [tonUI] = useTonConnectUI() + const userAddress = useUserAddress() const swap = useCallback( async ({ amount0, minOut, token0, token1 }: SwapArgs) => { const client = TonContext.instance.getClient() - const userAddress = parseAddress(userAddress_) const routerAddress = parseAddress(Contracts[TonContractNames.PCSRouter].testnet.address) const userJettonWallet0 = await getJettonWalletAddress(client, userAddress, token0) @@ -73,7 +71,7 @@ export const useSwap = () => { tonUI.sendTransaction(txRequest) }, - [userAddress_, tonUI], + [userAddress, tonUI], ) return {