@@ -10,6 +10,8 @@ import {
1010 PublicKey ,
1111 Transaction ,
1212 TransactionVersion ,
13+ AddressLookupTableProgram ,
14+ AddressLookupTableAccount ,
1315} from '@solana/web3.js' ;
1416import SolanaAPI from '@/providers/solana/libs/api' ;
1517import { SolanaNetwork } from '../../types/sol-network' ;
@@ -48,6 +50,47 @@ const assetFetch = (
4850 } ) . then ( res => res . json ( ) ) ;
4951} ;
5052
53+ export async function fetchRelevantAddresses (
54+ solAPI : SolanaAPI ,
55+ lookupTableKeys : PublicKey [ ] ,
56+ relevantIndexes : Set < number > ,
57+ ) : Promise < PublicKey [ ] > {
58+ const relevantAddresses : PublicKey [ ] = [ ] ;
59+ for ( const key of lookupTableKeys ) {
60+ const accountInfo = await solAPI . web3 . getAccountInfo ( key ) ;
61+ if (
62+ accountInfo ?. data &&
63+ accountInfo . owner . equals ( AddressLookupTableProgram . programId )
64+ ) {
65+ try {
66+ const lookupTableAccount = AddressLookupTableAccount . deserialize (
67+ accountInfo . data ,
68+ ) ;
69+ if ( lookupTableAccount && lookupTableAccount . addresses ) {
70+ lookupTableAccount . addresses . forEach ( async ( address , index ) => {
71+ if ( relevantIndexes . has ( index ) ) {
72+ const addressInfo = await solAPI . web3 . getAccountInfo ( address ) ;
73+ if (
74+ ( addressInfo ?. owner . toBase58 ( ) ===
75+ TOKEN_PROGRAM_ID . toBase58 ( ) ||
76+ addressInfo ?. owner . toBase58 ( ) ===
77+ TOKEN_2022_PROGRAM_ID . toBase58 ( ) ) &&
78+ addressInfo . data . length >= ACCOUNT_SIZE
79+ ) {
80+ relevantAddresses . push ( address ) ;
81+ }
82+ }
83+ } ) ;
84+ }
85+ } catch {
86+ console . error ( 'Failed to deserialize address lookup table account' ) ;
87+ }
88+ }
89+ }
90+
91+ return relevantAddresses ;
92+ }
93+
5194const decodeTransaction = async (
5295 tx : VersionedTransaction | Transaction ,
5396 from : PublicKey ,
@@ -57,22 +100,50 @@ const decodeTransaction = async (
57100 const solAPI = ( await network . api ( ) ) . api as SolanaAPI ;
58101 const allBalances = await network . getAllTokenInfo ( from . toBase58 ( ) ) ;
59102 const marketData = new MarketData ( ) ;
103+ let accounts : string [ ] = [ ] ;
104+ if ( version !== 'legacy' ) {
105+ const relevantIndexes = new Set < number > ( ) ;
106+
107+ // Retrieve addresses from the LUTs and the message
108+ const addressTableLookupKeys = (
109+ tx as VersionedTransaction
110+ ) . message . addressTableLookups . map (
111+ lookup => new PublicKey ( lookup . accountKey ) ,
112+ ) ;
113+
114+ ( tx as VersionedTransaction ) . message . addressTableLookups . forEach ( lookup => {
115+ lookup . writableIndexes . forEach ( index => relevantIndexes . add ( index ) ) ;
116+ lookup . readonlyIndexes . forEach ( index => relevantIndexes . add ( index ) ) ;
117+ } ) ;
118+
119+ const lookupTableAccounts = await fetchRelevantAddresses (
120+ solAPI ,
121+ addressTableLookupKeys ,
122+ relevantIndexes ,
123+ ) ;
124+
125+ accounts = [
126+ ...( tx as VersionedTransaction ) . message . staticAccountKeys . map ( k =>
127+ k . toBase58 ( ) ,
128+ ) ,
129+ ...lookupTableAccounts . map ( k => k . toBase58 ( ) ) ,
130+ ] ;
131+ }
60132 return (
61133 version !== 'legacy'
62134 ? solAPI . web3 . simulateTransaction ( tx as VersionedTransaction , {
63135 accounts : {
64- addresses : (
65- tx as VersionedTransaction
66- ) . message . staticAccountKeys . map ( k => k . toBase58 ( ) ) ,
136+ addresses : accounts ,
67137 encoding : 'base64' ,
68138 } ,
69139 } )
70140 : solAPI . web3 . simulateTransaction ( tx as Transaction , undefined , true )
71141 ) . then ( async result => {
72142 if ( result . value . err ) return null ;
143+ console . log ( result . value ) ;
73144 const nativeChange = {
74145 contract : NATIVE_TOKEN_ADDRESS ,
75- amount : BigInt ( result . value . accounts ! [ 0 ] ! . lamports ) ,
146+ amount : BigInt ( result . value . accounts ! [ 1 ] ! . lamports ) ,
76147 } ;
77148 const balanceChanges = result . value
78149 . accounts ! . filter ( a => {
0 commit comments