diff --git a/packages/extension/src/providers/ethereum/libs/assets-handlers/solanachain.ts b/packages/extension/src/providers/ethereum/libs/assets-handlers/solanachain.ts index 6d01483c5..ac68039d8 100644 --- a/packages/extension/src/providers/ethereum/libs/assets-handlers/solanachain.ts +++ b/packages/extension/src/providers/ethereum/libs/assets-handlers/solanachain.ts @@ -2,56 +2,47 @@ import { TokenBalance } from './types/tokenbalance-mew'; import { NATIVE_TOKEN_ADDRESS } from '../common'; import { numberToHex } from '@enkryptcom/utils'; import { BaseNetwork } from '@/types/base-network'; -import { - Connection, - GetProgramAccountsFilter, - PublicKey, -} from '@solana/web3.js'; -import { TOKEN_PROGRAM_ID } from '@solana/spl-token'; +import { Connection, PublicKey } from '@solana/web3.js'; +import { TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; import { BNType } from '@/providers/common/types'; import { toBN } from 'web3-utils'; const getBalances = (network: BaseNetwork, address: string) => { const solConnection = new Connection(network.node); - const filters: GetProgramAccountsFilter[] = [ - { - dataSize: 165, - }, - { - memcmp: { - offset: 32, - bytes: address, - }, - }, - ]; - return solConnection - .getParsedProgramAccounts(TOKEN_PROGRAM_ID, { filters: filters }) - .then(accounts => { - const balances: TokenBalance[] = []; - const balanceObj = {} as Record; - accounts.forEach(acc => { - const balance = numberToHex( - (acc.account.data as any).parsed.info.tokenAmount.amount, - ); - if (balance === '0x0') return; - const contract = (acc.account.data as any).parsed.info.mint; - if (!balanceObj[contract]) balanceObj[contract] = toBN(0); - balanceObj[contract] = balanceObj[contract].add(toBN(balance)); - }); - Object.keys(balanceObj).forEach(contract => { - balances.push({ - balance: numberToHex(balanceObj[contract]), - contract, - }); + return Promise.all([ + solConnection.getParsedTokenAccountsByOwner(new PublicKey(address), { + programId: TOKEN_PROGRAM_ID, + }), + solConnection.getParsedTokenAccountsByOwner(new PublicKey(address), { + programId: TOKEN_2022_PROGRAM_ID, + }), + ]).then(([tokenAccounts, tokenAccounts2022]) => { + const accounts = tokenAccounts.value.concat(tokenAccounts2022.value); + const balances: TokenBalance[] = []; + const balanceObj = {} as Record; + accounts.forEach(acc => { + const balance = numberToHex( + (acc.account.data as any).parsed.info.tokenAmount.amount, + ); + if (balance === '0x0') return; + const contract = (acc.account.data as any).parsed.info.mint; + if (!balanceObj[contract]) balanceObj[contract] = toBN(0); + balanceObj[contract] = balanceObj[contract].add(toBN(balance)); + }); + Object.keys(balanceObj).forEach(contract => { + balances.push({ + balance: numberToHex(balanceObj[contract]), + contract, }); - return solConnection.getBalance(new PublicKey(address)).then(balance => { - balances.unshift({ - balance: numberToHex(balance), - contract: NATIVE_TOKEN_ADDRESS, - }); - return balances; + }); + return solConnection.getBalance(new PublicKey(address)).then(balance => { + balances.unshift({ + balance: numberToHex(balance), + contract: NATIVE_TOKEN_ADDRESS, }); + return balances; }); + }); }; export default getBalances; diff --git a/packages/extension/src/providers/solana/ui/libs/decode-tx.ts b/packages/extension/src/providers/solana/ui/libs/decode-tx.ts index 1febd162b..d0fe33c1d 100644 --- a/packages/extension/src/providers/solana/ui/libs/decode-tx.ts +++ b/packages/extension/src/providers/solana/ui/libs/decode-tx.ts @@ -2,6 +2,7 @@ import { NATIVE_TOKEN_ADDRESS } from '@/providers/ethereum/libs/common'; import { ACCOUNT_SIZE, AccountLayout, + TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID, } from '@solana/spl-token'; import { @@ -77,8 +78,9 @@ const decodeTransaction = async ( .accounts!.filter(a => { const data = Buffer.from(a!.data[0], 'base64'); return ( - a!.owner === TOKEN_PROGRAM_ID.toBase58() && - data.length === ACCOUNT_SIZE + (a!.owner === TOKEN_PROGRAM_ID.toBase58() || + a!.owner === TOKEN_2022_PROGRAM_ID.toBase58()) && + data.length >= ACCOUNT_SIZE ); }) .map(a => { diff --git a/packages/extension/src/providers/solana/ui/send-transaction/index.vue b/packages/extension/src/providers/solana/ui/send-transaction/index.vue index 80acc2c6d..6e581975e 100644 --- a/packages/extension/src/providers/solana/ui/send-transaction/index.vue +++ b/packages/extension/src/providers/solana/ui/send-transaction/index.vue @@ -525,11 +525,24 @@ const updateTransactionFees = async () => { (!isSendToken.value && selectedNft.value.type === NFTType.SolanaToken) ) { const contract = new PublicKey(TxInfo.value.contract); - const associatedTokenTo = getAssociatedTokenAddressSync(contract, to); - const associatedTokenFrom = getAssociatedTokenAddressSync(contract, from); + const programId = await solConnection.value!.web3.getAccountInfo(contract); + const associatedTokenTo = getAssociatedTokenAddressSync( + contract, + to, + undefined, + programId!.owner, + ); + const associatedTokenFrom = getAssociatedTokenAddressSync( + contract, + from, + undefined, + programId!.owner, + ); const validATA = await getAccount( solConnection.value!.web3, associatedTokenTo, + undefined, + programId!.owner, ) .then(() => true) .catch(() => false); @@ -540,6 +553,8 @@ const updateTransactionFees = async () => { associatedTokenTo, from, toBN(TxInfo.value.value).toNumber(), + [], + programId!.owner, ), ); } else { @@ -549,6 +564,7 @@ const updateTransactionFees = async () => { associatedTokenTo, to, contract, + programId!.owner, ), ); transaction.add( @@ -557,6 +573,8 @@ const updateTransactionFees = async () => { associatedTokenTo, from, toBN(TxInfo.value.value).toNumber(), + [], + programId!.owner, ), ); storageFee.value = diff --git a/packages/extension/src/providers/solana/ui/sol-verify-transaction.vue b/packages/extension/src/providers/solana/ui/sol-verify-transaction.vue index 5583c329c..33497b149 100644 --- a/packages/extension/src/providers/solana/ui/sol-verify-transaction.vue +++ b/packages/extension/src/providers/solana/ui/sol-verify-transaction.vue @@ -236,9 +236,6 @@ onBeforeMount(async () => { }), ); } - Tx.value.recentBlockhash = ( - await solConnection.value.web3.getLatestBlockhash() - ).blockhash; } const feeMessage = TxType.value === 'legacy' @@ -282,9 +279,15 @@ const approve = async () => { }); const latestBlockHash = (await solConnection.value!.web3.getLatestBlockhash()) .blockhash; - if (TxType.value === 'legacy') { + if ( + TxType.value === 'legacy' && + !(Tx.value as LegacyTransaction).recentBlockhash + ) { (Tx.value as LegacyTransaction).recentBlockhash = latestBlockHash; - } else { + } else if ( + TxType.value !== 'legacy' && + !(Tx.value as VersionedTransaction).message.recentBlockhash + ) { (Tx.value as VersionedTransaction).message.recentBlockhash = latestBlockHash; } diff --git a/packages/swap/src/providers/jupiter/index.ts b/packages/swap/src/providers/jupiter/index.ts index aee0608cd..cd397e778 100644 --- a/packages/swap/src/providers/jupiter/index.ts +++ b/packages/swap/src/providers/jupiter/index.ts @@ -20,6 +20,7 @@ import { isValidSolanaAddressAsync, solAccountExists, SPL_TOKEN_ATA_ACCOUNT_SIZE_BYTES, + TOKEN_2022_PROGRAM_ID, WRAPPED_SOL_ADDRESS, } from "../../utils/solana"; import { @@ -317,12 +318,16 @@ export class Jupiter extends ProviderClass { dstMint, dstTokenProgramId, ); + const srcTokenProgramId = await getTokenProgramOfMint(this.conn, srcMint); + + const isSrcToken2022 = + srcTokenProgramId.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58(); const swap = await getJupiterSwap( { quote, signerPubkey: fromPubkey, - referrerATAPubkey, + referrerATAPubkey: isSrcToken2022 ? undefined : referrerATAPubkey, dstATAPubkey, }, { signal }, @@ -331,9 +336,6 @@ export class Jupiter extends ProviderClass { let tx = VersionedTransaction.deserialize( Buffer.from(swap.swapTransaction, "base64"), ); - - const srcTokenProgramId = await getTokenProgramOfMint(this.conn, srcMint); - /** Rent from having to create ATA accounts for the wallet & mint and the referral fee holder & mint */ let rentFees = 0; @@ -346,7 +348,7 @@ export class Jupiter extends ProviderClass { ` ATA pubkey: ${referrerATAPubkey.toBase58()},` + ` Source mint: ${srcMint.toBase58()}`, ); - } else { + } else if (!referrerATAExists && !isSrcToken2022) { // The referral fee ATA account needs to be created or else we can't receive fees for this transaction const extraRentFees = await this.conn.getMinimumBalanceForRentExemption( JUPITER_REFERRAL_ATA_ACCOUNT_SIZE_BYTES,