Skip to content

Commit

Permalink
Merge pull request #620 from enkryptcom/fix/solana-2022-program
Browse files Browse the repository at this point in the history
devop: token 2022 support
  • Loading branch information
kvhnuke authored Feb 21, 2025
2 parents b519d6e + ae0286f commit f122888
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, BNType>;
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<string, BNType>;
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;
6 changes: 4 additions & 2 deletions packages/extension/src/providers/solana/ui/libs/decode-tx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -540,6 +553,8 @@ const updateTransactionFees = async () => {
associatedTokenTo,
from,
toBN(TxInfo.value.value).toNumber(),
[],
programId!.owner,
),
);
} else {
Expand All @@ -549,6 +564,7 @@ const updateTransactionFees = async () => {
associatedTokenTo,
to,
contract,
programId!.owner,
),
);
transaction.add(
Expand All @@ -557,6 +573,8 @@ const updateTransactionFees = async () => {
associatedTokenTo,
from,
toBN(TxInfo.value.value).toNumber(),
[],
programId!.owner,
),
);
storageFee.value =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,6 @@ onBeforeMount(async () => {
}),
);
}
Tx.value.recentBlockhash = (
await solConnection.value.web3.getLatestBlockhash()
).blockhash;
}
const feeMessage =
TxType.value === 'legacy'
Expand Down Expand Up @@ -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;
}
Expand Down
12 changes: 7 additions & 5 deletions packages/swap/src/providers/jupiter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
isValidSolanaAddressAsync,
solAccountExists,
SPL_TOKEN_ATA_ACCOUNT_SIZE_BYTES,
TOKEN_2022_PROGRAM_ID,
WRAPPED_SOL_ADDRESS,
} from "../../utils/solana";
import {
Expand Down Expand Up @@ -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 },
Expand All @@ -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;

Expand All @@ -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,
Expand Down

0 comments on commit f122888

Please sign in to comment.