From be97e512b9154ee01a271157309c9ed88b6f112c Mon Sep 17 00:00:00 2001 From: tjs Date: Thu, 15 Dec 2022 17:51:19 -0500 Subject: [PATCH] wip2 --- components/swap/RoutesModal.tsx | 4 +- components/swap/SwapReviewRouteInfo.tsx | 108 ++++++++++++++++++------ utils/constants.ts | 3 + yarn.lock | 8 +- 4 files changed, 89 insertions(+), 34 deletions(-) diff --git a/components/swap/RoutesModal.tsx b/components/swap/RoutesModal.tsx index fb3c5fcf..1d5e0f84 100644 --- a/components/swap/RoutesModal.tsx +++ b/components/swap/RoutesModal.tsx @@ -24,7 +24,7 @@ const RoutesModal = ({ inputTokenSymbol, outputTokenInfo, }: RoutesModalProps) => { - const { mangoTokens } = useJupiterMints() + const { jupiterTokens } = useJupiterMints() const handleSelectRoute = (route: RouteInfo) => { setSelectedRoute(route) @@ -79,7 +79,7 @@ const RoutesModal = ({ { - mangoTokens.find( + jupiterTokens.find( (item) => item?.address === r?.outputMint?.toString() )?.symbol diff --git a/components/swap/SwapReviewRouteInfo.tsx b/components/swap/SwapReviewRouteInfo.tsx index 9d905e19..6347ec35 100644 --- a/components/swap/SwapReviewRouteInfo.tsx +++ b/components/swap/SwapReviewRouteInfo.tsx @@ -9,9 +9,10 @@ import { TransactionInstruction, PublicKey, VersionedTransaction, - MessageCompiledInstruction, Connection, - MessageV0, + TransactionMessage, + AddressLookupTableAccount, + MessageAddressTableLookup, // VersionedMessage, } from '@solana/web3.js' import Decimal from 'decimal.js' @@ -39,7 +40,7 @@ import useJupiterMints from '../../hooks/useJupiterMints' import { RouteInfo } from 'types/jupiter' import useJupiterSwapData from './useJupiterSwapData' // import { Transaction } from '@solana/web3.js' -import { SOUND_SETTINGS_KEY } from 'utils/constants' +import { JUPITER_V4_PROGRAM_ID, SOUND_SETTINGS_KEY } from 'utils/constants' import useLocalStorageState from 'hooks/useLocalStorageState' import { Howl } from 'howler' import { INITIAL_SOUND_SETTINGS } from '@components/settings/SoundSettings' @@ -54,12 +55,71 @@ type JupiterRouteInfoProps = { slippage: number } -const parseJupiterRoute = async ( +const deserializeJupiterIxAndAlt = async ( + connection: Connection, + swapTransaction: string +): Promise<[TransactionInstruction[], AddressLookupTableAccount[]]> => { + const parsedSwapTransaction = VersionedTransaction.deserialize( + Buffer.from(swapTransaction, 'base64') + ) + const message = parsedSwapTransaction.message + const lookups = message.addressTableLookups + const addressLookupTablesResponses = await Promise.all( + message.addressTableLookups.map((alt) => + connection.getAddressLookupTable(alt.accountKey) + ) + ) + const addressLookupTables: AddressLookupTableAccount[] = + addressLookupTablesResponses + .map((alt) => alt.value) + .filter((x): x is AddressLookupTableAccount => x !== null) + const accountKeys = message.staticAccountKeys + + const zippedLookupsAndAddressLookupTables: [ + MessageAddressTableLookup, + AddressLookupTableAccount + ][] = lookups.map((l, index) => [l, addressLookupTables[index]]) + + for (const [lookups, table] of zippedLookupsAndAddressLookupTables) { + accountKeys.concat( + lookups.writableIndexes.map((_, index) => table.state.addresses[index]) + ) + } + + for (const [lookups, table] of zippedLookupsAndAddressLookupTables) { + accountKeys.concat( + lookups.readonlyIndexes.map((_, index) => table.state.addresses[index]) + ) + } + console.log('message before decompile', message) + + const decompiledMessage = TransactionMessage.decompile(message, { + addressLookupTableAccounts: addressLookupTables, + }) + + const txInstructions: TransactionInstruction[] = + decompiledMessage.instructions.map( + (ix) => + new TransactionInstruction({ + data: ix.data, + programId: ix.programId, + keys: ix.keys.map((_, index) => ({ + pubkey: accountKeys[index], + isSigner: message.isAccountSigner(index), + isWritable: message.isAccountWritable(index), + })), + }) + ) + + return [txInstructions, addressLookupTables] +} + +const fetchJupiterTransaction = async ( connection: Connection, selectedRoute: RouteInfo, userPublicKey: PublicKey, slippage: number -): Promise => { +): Promise<[TransactionInstruction[], AddressLookupTableAccount[]]> => { const transactions = await ( await fetch('https://quote-api.jup.ag/v4/swap', { method: 'POST', @@ -80,31 +140,22 @@ const parseJupiterRoute = async ( ).json() const { swapTransaction } = transactions - const parsedSwapTransaction = VersionedTransaction.deserialize( - Buffer.from(swapTransaction, 'base64') + + const [ixs, alts] = await deserializeJupiterIxAndAlt( + connection, + swapTransaction ) - console.log('parsedSwapTransaction: ', parsedSwapTransaction) + // const isSetupIx = (pk: PublicKey): boolean => { k == ata_program || k == token_program }; + const isJupiterIx = (pk: PublicKey): boolean => + pk.toString() === JUPITER_V4_PROGRAM_ID - for (const alt of parsedSwapTransaction.message.addressTableLookups) { - const lookupTableAccount = await connection.getAddressLookupTable( - alt.accountKey - ) - const accountKeys = parsedSwapTransaction.message.staticAccountKeys + console.log('ixs', ixs) - console.log('lookupTableAccount', lookupTableAccount) - } + const filtered_jup_ixs = ixs.filter((ix) => isJupiterIx(ix.programId)) + console.log('filtered_jup_ixs', filtered_jup_ixs) - // const instructions = [] - // for (const ix of parsedSwapTransaction.instructions) { - // if ( - // ix.programId.toBase58() === 'JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB' - // ) { - // instructions.push(ix) - // } - // } - - return parsedSwapTransaction.message.compiledInstructions + return [filtered_jup_ixs, alts] } const EMPTY_COINGECKO_PRICES = { @@ -130,7 +181,7 @@ const SwapReviewRouteInfo = ({ const [feeValue] = useState(null) const [submitting, setSubmitting] = useState(false) const [coingeckoPrices, setCoingeckoPrices] = useState(EMPTY_COINGECKO_PRICES) - const { mangoTokens } = useJupiterMints() + const { jupiterTokens } = useJupiterMints() const { inputTokenInfo, outputTokenInfo } = useJupiterSwapData() const inputBank = mangoStore((s) => s.swap.inputBank) const [soundSettings] = useLocalStorageState( @@ -189,7 +240,7 @@ const SwapReviewRouteInfo = ({ if (!mangoAccount || !group || !inputBank || !outputBank) return - const ixs = await parseJupiterRoute( + const [ixs, alts] = await fetchJupiterTransaction( connection, selectedRoute, mangoAccount.owner, @@ -205,6 +256,7 @@ const SwapReviewRouteInfo = ({ amountIn: amountIn.toNumber(), outputMintPk: outputBank.mint, userDefinedInstructions: ixs, + userDefinedAlts: alts, flashLoanType: { swap: {} }, }) set((s) => { @@ -480,7 +532,7 @@ const SwapReviewRouteInfo = ({ ) : ( selectedRoute?.marketInfos.map((info, index) => { - const feeToken = mangoTokens.find( + const feeToken = jupiterTokens.find( (item) => item?.address === info.lpFee?.mint ) return ( diff --git a/utils/constants.ts b/utils/constants.ts index 8fda48a1..a951e898 100644 --- a/utils/constants.ts +++ b/utils/constants.ts @@ -7,6 +7,9 @@ export const MANGO_MINT = 'MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac' export const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' export const OUTPUT_TOKEN_DEFAULT = 'SOL' +export const JUPITER_V4_PROGRAM_ID = + 'JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB' + export const IS_ONBOARDED_KEY = 'isOnboarded-0.1' export const SHOW_ZERO_BALANCES_KEY = 'show-zero-balances-0.1' diff --git a/yarn.lock b/yarn.lock index 74ed4c37..305ad03c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -52,7 +52,7 @@ "@blockworks-foundation/mango-v4@https://tylersssss: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@github.com/blockworks-foundation/mango-v4.git#main": version "0.0.1-beta.6" - resolved "https://tylersssss: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@github.com/blockworks-foundation/mango-v4.git#2cd8c048f3eb25b40a4124464a95240f362488b1" + resolved "https://tylersssss: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@github.com/blockworks-foundation/mango-v4.git#237ecd3847c4a2adefa93f57800455047bf91698" dependencies: "@project-serum/anchor" "^0.25.0" "@project-serum/serum" "^0.13.65" @@ -395,9 +395,9 @@ integrity sha512-Rk4SkJFaXZiznFyC/t77Q0NKS4FL7TLJJsVG2V2oiEq3kJVeTdxysEe/yRWSpnWMe808XRDJ+VFh5pt/FN5plw== "@noble/hashes@^1.1.2": - version "1.1.4" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.4.tgz#2611ebf5764c1bf754da7c7794de4fb30512336d" - integrity sha512-+PYsVPrTSqtVjatKt2A/Proukn2Yrz61OBThOCKErc5w2/r1Fh37vbDv0Eah7pyNltrmacjwTvdw3JoR+WE4TA== + version "1.1.5" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11" + integrity sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ== "@noble/secp256k1@^1.6.3": version "1.7.0"