diff --git a/src/helpers/horizon/createHorizonTransaction.ts b/src/helpers/horizon/createHorizonTransaction.ts index d31086f1..f06cd981 100644 --- a/src/helpers/horizon/createHorizonTransaction.ts +++ b/src/helpers/horizon/createHorizonTransaction.ts @@ -1,31 +1,33 @@ import { SorobanContextType, useSorobanReact } from "@soroban-react/core"; import { InterfaceTrade, TradeType } from "state/routing/types"; -import {Asset, TransactionBuilder, Operation, BASE_FEE} from "@stellar/stellar-sdk"; +import { Asset, TransactionBuilder, Operation, BASE_FEE } from "@stellar/stellar-sdk"; import { getAmount } from "./getHorizonPath"; import BigNumber from "bignumber.js"; -export const createStellarPathPayment = async (trade: InterfaceTrade, allowedSlippage:any, sorobanContext: SorobanContextType) => { - const {address, activeConnector, serverHorizon, activeChain} = sorobanContext; - if(!address || !activeConnector || !serverHorizon || !activeChain) return; +export const createStellarPathPayment = async (trade: InterfaceTrade, allowedSlippage: any, sorobanContext: SorobanContextType) => { + const { address, activeConnector, serverHorizon, activeChain } = sorobanContext; + if (!address || !activeConnector || !serverHorizon || !activeChain) return; const amount = getAmount(trade.inputAmount?.value!); const sourceAsset = new Asset(trade.inputAmount?.currency.code!, trade.inputAmount?.currency.issuer) const destinationAsset = new Asset(trade.outputAmount?.currency.code!, trade.outputAmount?.currency.issuer) + const destinationAmount = getAmount(trade.outputAmount?.value!); const account = await serverHorizon?.loadAccount(address!); const path = trade.path?.map((asset) => { const assetParts = asset.split(":") - if(assetParts.length == 1 && assetParts[0] == "native"){ + if (assetParts.length == 1 && assetParts[0] == "native") { return Asset.native() } return new Asset(assetParts[0], assetParts[1]) }) - if(!account){ + + if (!account) { throw new Error("Account not found") } let transaction; - if(!amount || !sourceAsset || !destinationAsset || !path) throw new Error("Invalid trade"); - if(trade.tradeType == TradeType.EXACT_INPUT){ + if (!amount || !sourceAsset || !destinationAsset || !path || !destinationAmount) throw new Error("Invalid trade"); + if (trade.tradeType == TradeType.EXACT_INPUT) { const percentageSlippage = new BigNumber(100).minus(allowedSlippage).dividedBy(100); - const destMin = new BigNumber(amount).multipliedBy(percentageSlippage).toFixed(7).toString(); + const destMin = new BigNumber(destinationAmount).multipliedBy(percentageSlippage).toFixed(7).toString(); transaction = new TransactionBuilder(account, { fee: BASE_FEE, networkPassphrase: activeChain?.networkPassphrase @@ -49,20 +51,31 @@ export const createStellarPathPayment = async (trade: InterfaceTrade, allowedSli sendMax: sendMax, destination: address, destAsset: destinationAsset, - destAmount: amount, + destAmount: destinationAmount, + path: path })).setTimeout(180).build(); } const transactionXDR = transaction.toXDR(); const signedTransaction = await activeConnector?.signTransaction(transactionXDR, { networkPassphrase: activeChain?.networkPassphrase, }); - if(!signedTransaction){ + if (!signedTransaction) { throw new Error("Couldn't sign transaction"); } const transactionToSubmit = TransactionBuilder.fromXDR( signedTransaction!, activeChain?.networkPassphrase ?? '', ); - const transactionResult = await serverHorizon?.submitTransaction(transactionToSubmit); - return transactionResult; + try { + const transactionResult = await serverHorizon?.submitTransaction(transactionToSubmit); + return transactionResult; + } catch (e) { + console.log("Error", e); + // @ts-ignore + if (e.response.data.extras.result_codes.operations.includes("op_under_dest_min")) { + throw new Error("Try increasing slippage"); + // @ts-ignore + } + throw e + } } diff --git a/src/hooks/useSwapCallback.tsx b/src/hooks/useSwapCallback.tsx index c42b953a..d963c502 100644 --- a/src/hooks/useSwapCallback.tsx +++ b/src/hooks/useSwapCallback.tsx @@ -162,7 +162,7 @@ export function useSwapCallback( const notificationMessage = `${formatTokenAmount(currencyA ?? '0')} ${trade?.inputAmount ?.currency.code} for ${formatTokenAmount(currencyB ?? '0')} ${trade?.outputAmount - ?.currency.code}`; + ?.currency.code}`; sendNotification(notificationMessage, 'Swapped', SnackbarIconType.SWAP, SnackbarContext); @@ -208,7 +208,7 @@ export function useSwapCallback( const notificationMessage = `${formatTokenAmount(currencyA ?? '0')} ${trade?.inputAmount ?.currency.code} for ${formatTokenAmount(currencyB ?? '0')} ${trade?.outputAmount - ?.currency.code}`; + ?.currency.code}`; sendNotification(notificationMessage, 'Swapped', SnackbarIconType.SWAP, SnackbarContext); @@ -226,12 +226,16 @@ export function useSwapCallback( const result = await createStellarPathPayment(trade, allowedSlippage, sorobanContext); const notificationMessage = `${formatTokenAmount(trade.inputAmount?.value ?? '0')} ${trade ?.inputAmount?.currency.code} for ${formatTokenAmount( - trade.outputAmount?.value ?? '0', - )} ${trade?.outputAmount?.currency.code}`; + trade.outputAmount?.value ?? '0', + )} ${trade?.outputAmount?.currency.code}`; sendNotification(notificationMessage, 'Swapped', SnackbarIconType.SWAP, SnackbarContext); return result!; } catch (error: any) { console.error(error); + // If error comes from throw new Error("Try increasing slippage"); throw that error + if (error.message === 'Try increasing slippage') { + throw error; + } throw new Error('Cannot create path payment') } default: