feat: add support for transfer authority

This commit is contained in:
bartosz-lipinski 2021-01-05 23:24:34 -06:00
parent d30ac691b1
commit 52d1d939c9
12 changed files with 109 additions and 52 deletions

View File

@ -147,14 +147,14 @@ export const borrow = async (
); );
// create approval for transfer transactions // create approval for transfer transactions
approve( const transferAuthority = approve(
instructions, instructions,
cleanupInstructions, cleanupInstructions,
fromAccount, fromAccount,
authority,
wallet.publicKey, wallet.publicKey,
fromLamports fromLamports
); );
signers.push(transferAuthority);
const dexMarketAddress = borrowReserve.info.dexMarketOption const dexMarketAddress = borrowReserve.info.dexMarketOption
? borrowReserve.info.dexMarket ? borrowReserve.info.dexMarket
@ -189,7 +189,9 @@ export const borrow = async (
obligationTokenOutput, obligationTokenOutput,
wallet.publicKey, wallet.publicKey,
depositReserve.info.lendingMarket,
authority, authority,
transferAuthority.publicKey,
dexMarketAddress, dexMarketAddress,
dexOrderBookSide, dexOrderBookSide,

View File

@ -58,15 +58,16 @@ export const deposit = async (
); );
// create approval for transfer transactions // create approval for transfer transactions
approve( const transferAuthority = approve(
instructions, instructions,
cleanupInstructions, cleanupInstructions,
fromAccount, fromAccount,
authority,
wallet.publicKey, wallet.publicKey,
amountLamports amountLamports
); );
signers.push(transferAuthority);
let toAccount: PublicKey; let toAccount: PublicKey;
if (isInitalized) { if (isInitalized) {
// get destination account // get destination account
@ -90,7 +91,9 @@ export const deposit = async (
amountLamports, amountLamports,
fromAccount, fromAccount,
toAccount, toAccount,
reserve.lendingMarket,
authority, authority,
transferAuthority.publicKey,
reserveAddress, reserveAddress,
reserve.liquiditySupply, reserve.liquiditySupply,
reserve.collateralMint reserve.collateralMint
@ -112,6 +115,7 @@ export const deposit = async (
reserve.collateralSupply, reserve.collateralSupply,
reserve.lendingMarket, reserve.lendingMarket,
authority, authority,
transferAuthority.publicKey,
reserve.dexMarket reserve.dexMarket
) )
); );

View File

@ -55,14 +55,14 @@ export const liquidate = async (
); );
// create approval for transfer transactions // create approval for transfer transactions
approve( const transferAuthority = approve(
instructions, instructions,
cleanupInstructions, cleanupInstructions,
fromAccount, fromAccount,
authority,
wallet.publicKey, wallet.publicKey,
amountLamports amountLamports
); );
signers.push(transferAuthority);
// get destination account // get destination account
const toAccount = await findOrCreateAccountByMint( const toAccount = await findOrCreateAccountByMint(
@ -104,7 +104,9 @@ export const liquidate = async (
withdrawReserve.pubkey, withdrawReserve.pubkey,
withdrawReserve.info.collateralSupply, withdrawReserve.info.collateralSupply,
obligation.pubkey, obligation.pubkey,
repayReserve.info.lendingMarket,
authority, authority,
transferAuthority.publicKey,
dexMarketAddress, dexMarketAddress,
dexOrderBookSide, dexOrderBookSide,
memory memory

View File

@ -51,14 +51,14 @@ export const repay = async (
const fromAccount = from.pubkey; const fromAccount = from.pubkey;
// create approval for transfer transactions // create approval for transfer transactions
approve( const transferAuthority = approve(
instructions, instructions,
cleanupInstructions, cleanupInstructions,
fromAccount, fromAccount,
authority,
wallet.publicKey, wallet.publicKey,
amountLamports amountLamports
); );
signers.push(transferAuthority);
// get destination account // get destination account
const toAccount = await findOrCreateAccountByMint( const toAccount = await findOrCreateAccountByMint(
@ -76,9 +76,11 @@ export const repay = async (
instructions, instructions,
cleanupInstructions, cleanupInstructions,
obligationToken.pubkey, obligationToken.pubkey,
authority,
wallet.publicKey, wallet.publicKey,
obligationToken.info.amount.toNumber() obligationToken.info.amount.toNumber(),
// reuse transfer authority
transferAuthority.publicKey,
); );
// TODO: add obligation // TODO: add obligation
@ -95,7 +97,9 @@ export const repay = async (
obligation.pubkey, obligation.pubkey,
obligation.info.tokenMint, obligation.info.tokenMint,
obligationToken.pubkey, obligationToken.pubkey,
authority repayReserve.info.lendingMarket,
authority,
transferAuthority.publicKey,
) )
); );

View File

@ -38,15 +38,16 @@ export const withdraw = async (
const fromAccount = from.pubkey; const fromAccount = from.pubkey;
// create approval for transfer transactions // create approval for transfer transactions
approve( const transferAuthority = approve(
instructions, instructions,
cleanupInstructions, cleanupInstructions,
fromAccount, fromAccount,
authority,
wallet.publicKey, wallet.publicKey,
amountLamports amountLamports
); );
signers.push(transferAuthority);
// get destination account // get destination account
const toAccount = await findOrCreateAccountByMint( const toAccount = await findOrCreateAccountByMint(
wallet.publicKey, wallet.publicKey,
@ -66,7 +67,9 @@ export const withdraw = async (
reserveAddress, reserveAddress,
reserve.collateralMint, reserve.collateralMint,
reserve.liquiditySupply, reserve.liquiditySupply,
authority reserve.lendingMarket,
authority,
transferAuthority.publicKey,
) )
); );

View File

@ -1,4 +1,4 @@
import { AccountInfo, PublicKey, TransactionInstruction } from "@solana/web3.js"; import { Account, AccountInfo, PublicKey, TransactionInstruction } from "@solana/web3.js";
import { AccountInfo as TokenAccountInfo, Token } from "@solana/spl-token"; import { AccountInfo as TokenAccountInfo, Token } from "@solana/spl-token";
import { TOKEN_PROGRAM_ID } from "../utils/ids"; import { TOKEN_PROGRAM_ID } from "../utils/ids";
@ -13,16 +13,20 @@ export function approve(
instructions: TransactionInstruction[], instructions: TransactionInstruction[],
cleanupInstructions: TransactionInstruction[], cleanupInstructions: TransactionInstruction[],
account: PublicKey, account: PublicKey,
delegate: PublicKey,
owner: PublicKey, owner: PublicKey,
amount: number, amount: number,
): void {
// if delegate is not passed ephemeral transfer authority is used
delegate?: PublicKey,
): Account {
const tokenProgram = TOKEN_PROGRAM_ID; const tokenProgram = TOKEN_PROGRAM_ID;
const transferAuthority = new Account();
instructions.push( instructions.push(
Token.createApproveInstruction( Token.createApproveInstruction(
tokenProgram, tokenProgram,
account, account,
delegate, delegate ?? transferAuthority.publicKey,
owner, owner,
[], [],
amount amount
@ -36,4 +40,6 @@ export function approve(
owner, owner,
[]), []),
); );
return transferAuthority;
} }

View File

@ -15,23 +15,26 @@ export enum BorrowAmountType {
/// Borrow tokens from a reserve by depositing collateral tokens. The number of borrowed tokens /// Borrow tokens from a reserve by depositing collateral tokens. The number of borrowed tokens
/// is calculated by market price. The debt obligation is tokenized. /// is calculated by market price. The debt obligation is tokenized.
/// ///
/// 0. `[writable]` Collateral input SPL Token account, $authority can transfer $collateral_amount /// 0. `[writable]` Source collateral token account, minted by deposit reserve collateral mint,
/// 1. `[writable]` Liquidity output SPL Token account /// $authority can transfer $collateral_amount
/// 1. `[writable]` Destination liquidity token account, minted by borrow reserve liquidity mint
/// 2. `[writable]` Deposit reserve account. /// 2. `[writable]` Deposit reserve account.
/// 3. `[writable]` Deposit reserve collateral supply SPL Token account /// 3. `[writable]` Deposit reserve collateral supply SPL Token account
/// 4. `[writable]` Borrow reserve account. /// 4. `[writable]` Borrow reserve account.
/// 5. `[writable]` Borrow reserve liquidity supply SPL Token account /// 5. `[writable]` Borrow reserve liquidity supply SPL Token account
/// 6. `[writable]` Obligation - uninitialized /// 6. `[writable]` Obligation
/// 7. `[writable]` Obligation token mint - uninitialized /// 7. `[writable]` Obligation token mint
/// 8. `[writable]` Obligation token output - uninitialized /// 8. `[writable]` Obligation token output
/// 9. `[]` Obligation token owner /// 9. `[]` Obligation token owner
/// 10 `[]` Derived lending market authority ($authority). /// 10 `[]` Lending market account.
/// 11 `[]` Dex market /// 11 `[]` Derived lending market authority.
/// 12 `[]` Dex order book side // could be bid/ask /// 12 `[]` User transfer authority ($authority).
/// 13 `[]` Temporary memory /// 13 `[]` Dex market
/// 14 `[]` Clock sysvar /// 14 `[]` Dex market order book side
/// 15 `[]` Rent sysvar /// 15 `[]` Temporary memory
/// 16 '[]` Token program id /// 16 `[]` Clock sysvar
/// 17 `[]` Rent sysvar
/// 18 '[]` Token program id
export const borrowInstruction = ( export const borrowInstruction = (
amount: number | BN, amount: number | BN,
amountType: BorrowAmountType, amountType: BorrowAmountType,
@ -47,7 +50,9 @@ export const borrowInstruction = (
obligationTokenOutput: PublicKey, obligationTokenOutput: PublicKey,
obligationTokenOwner: PublicKey, obligationTokenOwner: PublicKey,
lendingMarket: PublicKey,
lendingMarketAuthority: PublicKey, lendingMarketAuthority: PublicKey,
transferAuthority: PublicKey,
dexMarket: PublicKey, dexMarket: PublicKey,
dexOrderBookSide: PublicKey, dexOrderBookSide: PublicKey,
@ -89,7 +94,11 @@ export const borrowInstruction = (
{ pubkey: obligationMint, isSigner: false, isWritable: true }, { pubkey: obligationMint, isSigner: false, isWritable: true },
{ pubkey: obligationTokenOutput, isSigner: false, isWritable: true }, { pubkey: obligationTokenOutput, isSigner: false, isWritable: true },
{ pubkey: obligationTokenOwner, isSigner: false, isWritable: false }, { pubkey: obligationTokenOwner, isSigner: false, isWritable: false },
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: lendingMarketAuthority, isSigner: false, isWritable: false }, { pubkey: lendingMarketAuthority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
{ pubkey: dexMarket, isSigner: false, isWritable: false }, { pubkey: dexMarket, isSigner: false, isWritable: false },
{ pubkey: dexOrderBookSide, isSigner: false, isWritable: false }, { pubkey: dexOrderBookSide, isSigner: false, isWritable: false },
{ pubkey: memory, isSigner: false, isWritable: false }, { pubkey: memory, isSigner: false, isWritable: false },

View File

@ -11,19 +11,23 @@ import { LendingReserve } from './reserve';
/// Deposit liquidity into a reserve. The output is a collateral token representing ownership /// Deposit liquidity into a reserve. The output is a collateral token representing ownership
/// of the reserve liquidity pool. /// of the reserve liquidity pool.
/// ///
/// 0. `[writable]` Liquidity input SPL Token account. $authority can transfer $liquidity_amount /// 0. `[writable]` Source liquidity token account. $authority can transfer $liquidity_amount
/// 1. `[writable]` Collateral output SPL Token account, /// 1. `[writable]` Destination collateral token account.
/// 2. `[writable]` Reserve account. /// 2. `[writable]` Reserve account.
/// 3. `[writable]` Reserve liquidity supply SPL Token account. /// 3. `[writable]` Reserve liquidity supply SPL Token account.
/// 4. `[writable]` Reserve collateral SPL Token mint. /// 4. `[writable]` Reserve collateral SPL Token mint.
/// 5. `[]` Derived lending market authority ($authority). /// 5. `[]` Lending market account.
/// 6. `[]` Clock sysvar /// 6. `[]` Derived lending market authority.
/// 7. '[]` Token program id /// 7. `[]` User transfer authority ($authority).
/// 8. `[]` Clock sysvar
/// 9. '[]` Token program id
export const depositInstruction = ( export const depositInstruction = (
liquidityAmount: number | BN, liquidityAmount: number | BN,
from: PublicKey, // Liquidity input SPL Token account. $authority can transfer $liquidity_amount from: PublicKey, // Liquidity input SPL Token account. $authority can transfer $liquidity_amount
to: PublicKey, // Collateral output SPL Token account, to: PublicKey, // Collateral output SPL Token account,
lendingMarket: PublicKey,
reserveAuthority: PublicKey, reserveAuthority: PublicKey,
transferAuthority: PublicKey,
reserveAccount: PublicKey, reserveAccount: PublicKey,
reserveSupply: PublicKey, reserveSupply: PublicKey,
collateralMint: PublicKey collateralMint: PublicKey
@ -45,7 +49,9 @@ export const depositInstruction = (
{ pubkey: reserveAccount, isSigner: false, isWritable: true }, { pubkey: reserveAccount, isSigner: false, isWritable: true },
{ pubkey: reserveSupply, isSigner: false, isWritable: true }, { pubkey: reserveSupply, isSigner: false, isWritable: true },
{ pubkey: collateralMint, isSigner: false, isWritable: true }, { pubkey: collateralMint, isSigner: false, isWritable: true },
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: reserveAuthority, isSigner: false, isWritable: false }, { pubkey: reserveAuthority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
]; ];

View File

@ -7,19 +7,22 @@ import { TOKEN_PROGRAM_ID, LENDING_PROGRAM_ID } from '../../utils/ids';
/// Purchase collateral tokens at a discount rate if the chosen obligation is unhealthy. /// Purchase collateral tokens at a discount rate if the chosen obligation is unhealthy.
/// ///
/// 0. `[writable]` Liquidity input SPL Token account, $authority can transfer $liquidity_amount /// 0. `[writable]` Source liquidity token account, minted by repay reserve liquidity mint
/// 1. `[writable]` Collateral output SPL Token account /// $authority can transfer $collateral_amount
/// 1. `[writable]` Destination collateral token account, minted by withdraw reserve collateral mint
/// 2. `[writable]` Repay reserve account. /// 2. `[writable]` Repay reserve account.
/// 3. `[writable]` Repay reserve liquidity supply SPL Token account /// 3. `[writable]` Repay reserve liquidity supply SPL Token account
/// 4. `[writable]` Withdraw reserve account. /// 4. `[writable]` Withdraw reserve account.
/// 5. `[writable]` Withdraw reserve collateral supply SPL Token account /// 5. `[writable]` Withdraw reserve collateral supply SPL Token account
/// 6. `[writable]` Obligation - initialized /// 6. `[writable]` Obligation - initialized
/// 7. `[]` Derived lending market authority ($authority). /// 7. `[]` Lending market account.
/// 8. `[]` Dex market /// 8. `[]` Derived lending market authority.
/// 9. `[]` Dex market orders /// 9. `[]` User transfer authority ($authority).
/// 10 `[]` Temporary memory /// 10 `[]` Dex market
/// 11 `[]` Clock sysvar /// 11 `[]` Dex market order book side
/// 12 `[]` Token program id /// 12 `[]` Temporary memory
/// 13 `[]` Clock sysvar
/// 14 `[]` Token program id
export const liquidateInstruction = ( export const liquidateInstruction = (
liquidityAmount: number | BN, liquidityAmount: number | BN,
from: PublicKey, // Liquidity input SPL Token account. $authority can transfer $liquidity_amount from: PublicKey, // Liquidity input SPL Token account. $authority can transfer $liquidity_amount
@ -29,7 +32,9 @@ export const liquidateInstruction = (
withdrawReserve: PublicKey, withdrawReserve: PublicKey,
withdrawReserveCollateralSupply: PublicKey, withdrawReserveCollateralSupply: PublicKey,
obligation: PublicKey, obligation: PublicKey,
lendingMarket: PublicKey,
authority: PublicKey, authority: PublicKey,
transferAuthority: PublicKey,
dexMarket: PublicKey, dexMarket: PublicKey,
dexOrderBookSide: PublicKey, dexOrderBookSide: PublicKey,
memory: PublicKey memory: PublicKey
@ -61,7 +66,9 @@ export const liquidateInstruction = (
{ pubkey: obligation, isSigner: false, isWritable: true }, { pubkey: obligation, isSigner: false, isWritable: true },
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: authority, isSigner: false, isWritable: false }, { pubkey: authority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
{ pubkey: dexMarket, isSigner: false, isWritable: false }, { pubkey: dexMarket, isSigner: false, isWritable: false },
{ pubkey: dexOrderBookSide, isSigner: false, isWritable: false }, { pubkey: dexOrderBookSide, isSigner: false, isWritable: false },

View File

@ -8,18 +8,21 @@ import { TOKEN_PROGRAM_ID, LENDING_PROGRAM_ID } from '../../utils/ids';
/// Repay loaned tokens to a reserve and receive collateral tokens. The obligation balance /// Repay loaned tokens to a reserve and receive collateral tokens. The obligation balance
/// will be recalculated for interest. /// will be recalculated for interest.
/// ///
/// 0. `[writable]` Liquidity input SPL Token account, $authority can transfer $liquidity_amount /// 0. `[writable]` Source liquidity token account, minted by repay reserve liquidity mint
/// 1. `[writable]` Collateral output SPL Token account /// $authority can transfer $collateral_amount
/// 1. `[writable]` Destination collateral token account, minted by withdraw reserve collateral mint
/// 2. `[writable]` Repay reserve account. /// 2. `[writable]` Repay reserve account.
/// 3. `[writable]` Repay reserve liquidity supply SPL Token account /// 3. `[writable]` Repay reserve liquidity supply SPL Token account
/// 4. `[]` Withdraw reserve account. /// 4. `[]` Withdraw reserve account.
/// 5. `[writable]` Withdraw reserve collateral supply SPL Token account /// 5. `[writable]` Withdraw reserve collateral supply SPL Token account
/// 6. `[writable]` Obligation - initialized /// 6. `[writable]` Obligation - initialized
/// 7. `[writable]` Obligation token mint, $authority can transfer calculated amount /// 7. `[writable]` Obligation token mint
/// 8. `[writable]` Obligation token input /// 8. `[writable]` Obligation token input, $authority can transfer calculated amount
/// 9. `[]` Derived lending market authority ($authority). /// 9. `[]` Lending market account.
/// 10 `[]` Clock sysvar /// 10 `[]` Derived lending market authority.
/// 11 `[]` Token program id /// 11 `[]` User transfer authority ($authority).
/// 12 `[]` Clock sysvar
/// 13 `[]` Token program id
export const repayInstruction = ( export const repayInstruction = (
liquidityAmount: number | BN, liquidityAmount: number | BN,
from: PublicKey, // Liquidity input SPL Token account. $authority can transfer $liquidity_amount from: PublicKey, // Liquidity input SPL Token account. $authority can transfer $liquidity_amount
@ -31,7 +34,9 @@ export const repayInstruction = (
obligation: PublicKey, obligation: PublicKey,
obligationMint: PublicKey, obligationMint: PublicKey,
obligationInput: PublicKey, obligationInput: PublicKey,
authority: PublicKey lendingMarket: PublicKey,
authority: PublicKey,
transferAuthority: PublicKey,
): TransactionInstruction => { ): TransactionInstruction => {
const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), Layout.uint64('liquidityAmount')]); const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), Layout.uint64('liquidityAmount')]);
@ -62,7 +67,10 @@ export const repayInstruction = (
{ pubkey: obligationMint, isSigner: false, isWritable: true }, { pubkey: obligationMint, isSigner: false, isWritable: true },
{ pubkey: obligationInput, isSigner: false, isWritable: true }, { pubkey: obligationInput, isSigner: false, isWritable: true },
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: authority, isSigner: false, isWritable: false }, { pubkey: authority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
]; ];

View File

@ -114,6 +114,7 @@ export const initReserveInstruction = (
collateralSupply: PublicKey, collateralSupply: PublicKey,
lendingMarket: PublicKey, lendingMarket: PublicKey,
lendingMarketAuthority: PublicKey, lendingMarketAuthority: PublicKey,
transferAuthority: PublicKey,
dexMarket: PublicKey // TODO: optional dexMarket: PublicKey // TODO: optional
): TransactionInstruction => { ): TransactionInstruction => {
@ -145,6 +146,7 @@ export const initReserveInstruction = (
// NOTE: Why lending market needs to be a signer? // NOTE: Why lending market needs to be a signer?
{ pubkey: lendingMarket, isSigner: true, isWritable: true }, { pubkey: lendingMarket, isSigner: true, isWritable: true },
{ pubkey: lendingMarketAuthority, isSigner: false, isWritable: false }, { pubkey: lendingMarketAuthority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },

View File

@ -12,7 +12,9 @@ export const withdrawInstruction = (
reserveAccount: PublicKey, reserveAccount: PublicKey,
collateralMint: PublicKey, collateralMint: PublicKey,
reserveSupply: PublicKey, reserveSupply: PublicKey,
authority: PublicKey lendingMarket: PublicKey,
authority: PublicKey,
transferAuthority: PublicKey,
): TransactionInstruction => { ): TransactionInstruction => {
const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), Layout.uint64('collateralAmount')]); const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), Layout.uint64('collateralAmount')]);
@ -31,7 +33,9 @@ export const withdrawInstruction = (
{ pubkey: reserveAccount, isSigner: false, isWritable: true }, { pubkey: reserveAccount, isSigner: false, isWritable: true },
{ pubkey: collateralMint, isSigner: false, isWritable: true }, { pubkey: collateralMint, isSigner: false, isWritable: true },
{ pubkey: reserveSupply, isSigner: false, isWritable: true }, { pubkey: reserveSupply, isSigner: false, isWritable: true },
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: authority, isSigner: false, isWritable: false }, { pubkey: authority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
]; ];