diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index 0b4267a0a24..26f1d7b6d4b 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -3,6 +3,7 @@ import { ASSET_NAMESPACE, CHAIN_NAMESPACE, CHAIN_REFERENCE, + fromAssetId, solAssetId, toAssetId, wrappedSolAssetId, @@ -12,6 +13,7 @@ import type { KnownChainIds } from '@shapeshiftoss/types' import { bn, bnOrZero, convertDecimalPercentageToBasisPoints } from '@shapeshiftoss/utils' import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' +import { PublicKey } from '@solana/web3.js' import { v4 as uuid } from 'uuid' import type { @@ -23,7 +25,7 @@ import type { } from '../../../types' import { SwapperName, TradeQuoteError } from '../../../types' import { getInputOutputRate, makeSwapErrorRight } from '../../../utils' -import { JUPITER_COMPUTE_UNIT_MARGIN_MULTIPLIER } from '../utils/constants' +import { JUPITER_COMPUTE_UNIT_MARGIN_MULTIPLIER, TOKEN_2022_PROGRAM_ID } from '../utils/constants' import { calculateAccountCreationCosts, createSwapInstructions, @@ -38,7 +40,7 @@ export const getTradeQuote = async ( const { sellAsset, buyAsset, - affiliateBps, + affiliateBps: _affiliateBps, receiveAddress, accountNumber, sendAddress, @@ -99,10 +101,31 @@ export const getTradeQuote = async ( ) } + const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) + + const buyAssetAddress = + buyAsset.assetId === solAssetId + ? fromAssetId(wrappedSolAssetId).assetReference + : fromAssetId(buyAsset.assetId).assetReference + + const sellAssetAddress = + sellAsset.assetId === solAssetId + ? fromAssetId(wrappedSolAssetId).assetReference + : fromAssetId(sellAsset.assetId).assetReference + + const sellTokenInfo = await adapter + .getConnection() + .getAccountInfo(new PublicKey(sellAssetAddress)) + const buyTokenInfo = await adapter.getConnection().getAccountInfo(new PublicKey(buyAssetAddress)) + const isSellTokenToken2022 = sellTokenInfo?.owner.toString() === TOKEN_2022_PROGRAM_ID.toString() + const isBuyTokenToken2022 = buyTokenInfo?.owner.toString() === TOKEN_2022_PROGRAM_ID.toString() + + const affiliateBps = isSellTokenToken2022 && isBuyTokenToken2022 ? '0' : _affiliateBps + const maybePriceResponse = await getJupiterPrice({ apiUrl: jupiterUrl, - sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, - destinationAsset: buyAsset.assetId === solAssetId ? wrappedSolAssetId : buyAsset.assetId, + sourceAssetAddress: sellAssetAddress, + destinationAssetAddress: buyAssetAddress, commissionBps: affiliateBps, amount: sellAmount, slippageBps: _slippageTolerancePercentageDecimal @@ -126,8 +149,6 @@ export const getTradeQuote = async ( // e.g for 0.5% bps, Jupiter represents this as 50. 50/100 = 0.5, then we div by 100 again to honour our decimal format e.g 0.5/100 = 0.005 bn(priceResponse.slippageBps).div(100).div(100).toString() - const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) - const { instructions, addressLookupTableAddresses } = await createSwapInstructions({ priceResponse, sendAddress, diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts index 886ff7cc8cc..4cb194ea393 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts @@ -13,6 +13,7 @@ import type { KnownChainIds } from '@shapeshiftoss/types' import { bn, bnOrZero, convertDecimalPercentageToBasisPoints } from '@shapeshiftoss/utils' import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' +import { PublicKey } from '@solana/web3.js' import { v4 as uuid } from 'uuid' import type { @@ -24,7 +25,7 @@ import type { } from '../../../types' import { SwapperName, TradeQuoteError } from '../../../types' import { getInputOutputRate, makeSwapErrorRight } from '../../../utils' -import { SOLANA_RANDOM_ADDRESS } from '../utils/constants' +import { SOLANA_RANDOM_ADDRESS, TOKEN_2022_PROGRAM_ID } from '../utils/constants' import { calculateAccountCreationCosts, createSwapInstructions, @@ -40,7 +41,7 @@ export const getTradeRate = async ( sellAsset, buyAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, - affiliateBps, + affiliateBps: _affiliateBps, receiveAddress, accountNumber, slippageTolerancePercentageDecimal: _slippageTolerancePercentageDecimal, @@ -90,10 +91,31 @@ export const getTradeRate = async ( ) } + const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) + + const buyAssetAddress = + buyAsset.assetId === solAssetId + ? fromAssetId(wrappedSolAssetId).assetReference + : fromAssetId(buyAsset.assetId).assetReference + + const sellAssetAddress = + sellAsset.assetId === solAssetId + ? fromAssetId(wrappedSolAssetId).assetReference + : fromAssetId(sellAsset.assetId).assetReference + + const sellTokenInfo = await adapter + .getConnection() + .getAccountInfo(new PublicKey(sellAssetAddress)) + const buyTokenInfo = await adapter.getConnection().getAccountInfo(new PublicKey(buyAssetAddress)) + const isSellTokenToken2022 = sellTokenInfo?.owner.toString() === TOKEN_2022_PROGRAM_ID.toString() + const isBuyTokenToken2022 = buyTokenInfo?.owner.toString() === TOKEN_2022_PROGRAM_ID.toString() + + const affiliateBps = isSellTokenToken2022 && isBuyTokenToken2022 ? '0' : _affiliateBps + const maybePriceResponse = await getJupiterPrice({ apiUrl: jupiterUrl, - sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, - destinationAsset: buyAsset.assetId === solAssetId ? wrappedSolAssetId : buyAsset.assetId, + sourceAssetAddress: sellAssetAddress, + destinationAssetAddress: buyAssetAddress, commissionBps: affiliateBps, amount: sellAmount, slippageBps: _slippageTolerancePercentageDecimal @@ -130,8 +152,6 @@ export const getTradeRate = async ( return { networkFeeCryptoBaseUnit: fast.txFee } } - const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) - const protocolFees: Record = priceResponse.routePlan.reduce( (acc, route) => { const feeAssetId = toAssetId({ diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index 0c90528ebab..005d49e009a 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -31,8 +31,8 @@ const JUPITER_TRANSACTION_MAX_ACCOUNTS = 54 type GetJupiterQuoteArgs = { apiUrl: string - sourceAsset: string - destinationAsset: string + sourceAssetAddress: string + destinationAssetAddress: string commissionBps: string amount: string slippageBps: string | undefined @@ -60,16 +60,16 @@ type CreateInstructionsParams = { export const getJupiterPrice = ({ apiUrl, - sourceAsset, - destinationAsset, + sourceAssetAddress, + destinationAssetAddress, commissionBps, amount, slippageBps, }: GetJupiterQuoteArgs): Promise, SwapErrorRight>> => jupiterService.get( `${apiUrl}/quote` + - `?inputMint=${fromAssetId(sourceAsset).assetReference}` + - `&outputMint=${fromAssetId(destinationAsset).assetReference}` + + `?inputMint=${sourceAssetAddress}` + + `&outputMint=${destinationAssetAddress}` + `&amount=${amount}` + (slippageBps ? `&slippageBps=${slippageBps}` : `&autoSlippage=true`) + `&maxAccounts=${JUPITER_TRANSACTION_MAX_ACCOUNTS}` + diff --git a/src/state/slices/tradeQuoteSlice/selectors.ts b/src/state/slices/tradeQuoteSlice/selectors.ts index bfadb3101d5..fba7704b3b9 100644 --- a/src/state/slices/tradeQuoteSlice/selectors.ts +++ b/src/state/slices/tradeQuoteSlice/selectors.ts @@ -566,6 +566,8 @@ export const selectTradeQuoteAffiliateFeeAfterDiscountUsd = createSelector( selectActiveQuoteAffiliateBps, (calculatedFees, affiliateBps) => { if (!affiliateBps) return + if (affiliateBps === '0') return bn(0) + return calculatedFees.feeUsd }, )