From 27163a0a77a153c735ffa2e80de259f7b430f450 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 12 Dec 2024 22:39:54 +0800 Subject: [PATCH 1/4] fix: lifi bridges final trade quote (#8348) --- .../getTradeQuote/getTradeQuote.ts | 32 +++++++++++++++---- .../src/swappers/LifiSwapper/utils/types.ts | 9 ++++-- packages/swapper/src/types.ts | 3 +- .../useGetTradeQuotes/getTradeQuoteInput.ts | 3 +- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/packages/swapper/src/swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts index cd5569a04cd..36cb50c3b1d 100644 --- a/packages/swapper/src/swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts @@ -35,7 +35,7 @@ import { transformLifiStepFeeData } from '../utils/transformLifiFeeData/transfor import type { LifiTradeQuote } from '../utils/types' export async function getTrade( - input: GetEvmTradeQuoteInput & { lifiAllowedTools?: string[] | undefined }, + input: GetEvmTradeQuoteInput, deps: SwapperDeps, lifiChainMap: Map, ): Promise> { @@ -97,9 +97,12 @@ export async function getTrade( // are currently incompatible with our fee calculations, leading to incorrect fee display, // reverts, partial swaps, wrong received tokens (due to out-of-gas mid-trade), etc. For now, // these bridges are disabled. - bridges: { deny: ['stargate', 'stargateV2', 'stargateV2Bus', 'amarok', 'arbitrum'] }, - ...(lifiAllowedTools && { - exchanges: { allow: lifiAllowedTools }, + bridges: { + deny: ['stargate', 'stargateV2', 'stargateV2Bus', 'amarok', 'arbitrum'], + ...(lifiAllowedTools?.bridges ? { allow: lifiAllowedTools.bridges } : {}), + }, + ...(lifiAllowedTools?.exchanges && { + exchanges: { allow: lifiAllowedTools.exchanges }, }), allowSwitchChain: true, fee: affiliateBpsDecimalPercentage.isZero() @@ -245,13 +248,30 @@ export async function getTrade( .dividedBy(bn(selectedLifiRoute.fromAmount)) .toString() + const lifiBridgeTools = selectedLifiRoute.steps + .filter( + current => current.includedSteps?.some(includedStep => includedStep.type === 'cross'), + ) + .map(current => current.tool) + + const lifiExchangeTools = selectedLifiRoute.steps + .filter( + current => + // A step tool is an exchange (swap) tool if all of its steps are non-cross-chain steps + current.includedSteps?.every(includedStep => includedStep.type !== 'cross'), + ) + .map(current => current.tool) + return { id: selectedLifiRoute.id, // TODO(gomes): when https://github.com/shapeshift/web/pull/8309 goes in, this goes out // We do need receiveAddress in *input* to send it as fromAddress for routes req for more reliable rates, but with receiveAddress currently being the quotes/rates discriminator, // we need to exclude it from method in *output* receiveAddress: input.quoteOrRate === 'quote' ? receiveAddress : undefined, - lifiTools: selectedLifiRoute.steps.map(step => step.tool), + lifiTools: { + bridges: lifiBridgeTools.length ? lifiBridgeTools : undefined, + exchanges: lifiExchangeTools.length ? lifiExchangeTools : undefined, + }, affiliateBps, potentialAffiliateBps, steps, @@ -297,7 +317,7 @@ export async function getTrade( // This isn't a mistake - With Li.Fi, we get the exact same thing back whether quote or rate, however, the input *is* different export const getTradeQuote = ( - input: GetEvmTradeQuoteInputBase & { lifiAllowedTools?: string[] | undefined }, + input: GetEvmTradeQuoteInputBase, deps: SwapperDeps, lifiChainMap: Map, ): Promise> => getTrade(input, deps, lifiChainMap) diff --git a/packages/swapper/src/swappers/LifiSwapper/utils/types.ts b/packages/swapper/src/swappers/LifiSwapper/utils/types.ts index 9bb4f8679f1..386cde78476 100644 --- a/packages/swapper/src/swappers/LifiSwapper/utils/types.ts +++ b/packages/swapper/src/swappers/LifiSwapper/utils/types.ts @@ -2,13 +2,18 @@ import type { Route } from '@lifi/sdk' import type { TradeQuote, TradeRate } from '../../../types' +export type LifiTools = { + bridges: string[] | undefined + exchanges: string[] | undefined +} + export interface LifiTradeQuote extends TradeQuote { selectedLifiRoute?: Route - lifiTools?: string[] | undefined + lifiTools?: LifiTools } export interface LifiTradeRate extends TradeRate { selectedLifiRoute?: Route - lifiTools?: string[] | undefined + lifiTools?: LifiTools } export type LifiTool = { diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 96d6d6a6ec9..116887f5af5 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -29,6 +29,7 @@ import type { InterpolationOptions } from 'node-polyglot' import type { Address } from 'viem' import type { CowMessageToSign } from './swappers/CowSwapper/types' +import type { LifiTools } from './swappers/LifiSwapper/utils/types' import type { makeSwapperAxiosServiceMonadic } from './utils' // TODO: Rename all properties in this type to be camel case and not react specific @@ -157,7 +158,7 @@ type CommonTradeInputBase = { potentialAffiliateBps: string affiliateBps: string allowMultiHop: boolean - lifiAllowedTools?: string[] | undefined + lifiAllowedTools?: LifiTools slippageTolerancePercentageDecimal?: string } diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts index 49113591382..651315425a1 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts @@ -2,6 +2,7 @@ import { CHAIN_NAMESPACE, fromChainId } from '@shapeshiftoss/caip' import type { HDWallet } from '@shapeshiftoss/hdwallet-core' import { supportsETH } from '@shapeshiftoss/hdwallet-core' import type { GetTradeQuoteInput } from '@shapeshiftoss/swapper' +import type { LifiTradeQuote } from '@shapeshiftoss/swapper/src/swappers/LifiSwapper/utils/types' import type { Asset, CosmosSdkChainId, EvmChainId, UtxoChainId } from '@shapeshiftoss/types' import { UtxoAccountType } from '@shapeshiftoss/types' import type { TradeQuoteInputCommonArgs } from 'components/MultiHopTrade/types' @@ -19,7 +20,7 @@ export type GetTradeQuoteInputArgs = { slippageTolerancePercentageDecimal?: string sellAmountBeforeFeesCryptoPrecision: string allowMultiHop: boolean - lifiAllowedTools?: string[] + lifiAllowedTools?: LifiTradeQuote['lifiTools'] | undefined // Potential affiliate bps - may be waved out either entirely or partially with FOX discounts potentialAffiliateBps: string // Actual affiliate bps - if the FOX discounts is off, this will be the same as *affiliateBps* From d13960cb7bc145a7cb46c539e39a8639b26d143c Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:02:26 +0300 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20chainflip=20final=20trade=20quote=20?= =?UTF-8?q?when=20selling=20Solana=20assets=20to=20non-So=E2=80=A6=20(#838?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 95a3bbf360f..368b191502f 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -122,6 +122,8 @@ export const getTradeQuote = async ( if (!swapResponse.id) throw Error('Missing Swap Id') if (!swapResponse.address) throw Error('Missing Deposit Channel') + const depositAddress = swapResponse.address + const getFeeData = async () => { const { chainNamespace } = fromAssetId(sellAsset.assetId) @@ -130,7 +132,7 @@ export const getTradeQuote = async ( case CHAIN_NAMESPACE.Solana: { const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) const getFeeDataInput: GetFeeDataInput = { - to: input.receiveAddress, + to: depositAddress, value: sellAmount, chainSpecific: { from: input.sendAddress!, @@ -155,7 +157,7 @@ export const getTradeQuote = async ( if (!step.chainflipSpecific) step.chainflipSpecific = { chainflipSwapId: swapResponse.id, - chainflipDepositAddress: swapResponse.address, + chainflipDepositAddress: depositAddress, } step.chainflipSpecific.chainflipSwapId = swapResponse.id From 42b1dada645213fb0bb4c42c19353176f7561ef1 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:28:33 +0300 Subject: [PATCH 3/4] fix: phantom BTC sends (#8385) --- .../src/utxo/UtxoBaseAdapter.ts | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts b/packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts index 37fb4ee00f1..d688afcc903 100644 --- a/packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts +++ b/packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts @@ -331,14 +331,25 @@ export abstract class UtxoBaseAdapter implements IChainAd await Promise.all(uniqueAddresses.map(assertAddressNotSanctioned)) + const bip44Params = this.getBip44Params({ + accountNumber, + accountType, + isChange: true, + addressIndex: account.chainSpecific.nextChangeAddressIndex, + }) + const signTxInputs: BTCSignTxInput[] = [] for (const input of inputs) { - if (!input.path) throw new Error('invalid input') - const data = await this.providers.http.getTransaction({ txid: input.txid }) signTxInputs.push({ - addressNList: bip32ToAddressNList(input.path), + // UTXO inputs are not guaranteed to have paths. + // They will in the case of an /api/v1/account//utxos account + // However, if we got utxos from an /api/v1/account/
/utxos account (i.e UTXOs for a single address), these will *not* contain a path, which is fine, + // as the path will be the same for *all* UTXOs i.e can be derived from BIP44Params (we're dealing with a single address) + addressNList: input.path + ? bip32ToAddressNList(input.path) + : toAddressNList({ ...bip44Params }), scriptType: accountTypeToScriptType[accountType], amount: String(input.value), vout: input.vout, @@ -347,13 +358,6 @@ export abstract class UtxoBaseAdapter implements IChainAd }) } - const bip44Params = this.getBip44Params({ - accountNumber, - accountType, - isChange: true, - addressIndex: account.chainSpecific.nextChangeAddressIndex, - }) - const addressNList = toAddressNList(bip44Params) const signTxOutputs = outputs.map(output => { From 3375df4e20275790b259e91d082a5e5c5f9d85e0 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Wed, 18 Dec 2024 00:55:38 +0300 Subject: [PATCH 4/4] fix: mergefix release (#8389) fix: lifi bridges final trade quote (#8348)