-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: port addTokensToVault action to SDK (#128)
- Loading branch information
1 parent
292d5c7
commit d5c8983
Showing
3 changed files
with
168 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import BN from 'bn.js'; | ||
import { AccountLayout } from '@solana/spl-token'; | ||
import { | ||
Vault, | ||
SafetyDepositBox, | ||
AddTokenToInactiveVault, | ||
} from '@metaplex-foundation/mpl-token-vault'; | ||
import { Connection, TransactionSignature, PublicKey, Keypair } from '@solana/web3.js'; | ||
|
||
import { Wallet } from '../wallet'; | ||
import { createApproveTxs } from './shared'; | ||
import { sendTransaction } from './transactions'; | ||
import { CreateTokenAccount } from '../programs'; | ||
import { TransactionsBatch } from '../utils/transactions-batch'; | ||
|
||
interface Token2Add { | ||
tokenAccount: PublicKey; | ||
tokenMint: PublicKey; | ||
amount: BN; | ||
} | ||
|
||
interface SafetyDepositTokenStore { | ||
txId: TransactionSignature; | ||
tokenAccount: PublicKey; | ||
tokenStoreAccount: PublicKey; | ||
tokenMint: PublicKey; | ||
} | ||
|
||
interface AddTokensToVaultParams { | ||
connection: Connection; | ||
wallet: Wallet; | ||
vault: PublicKey; | ||
nfts: Token2Add[]; | ||
} | ||
|
||
interface AddTokensToVaultResponse { | ||
safetyDepositTokenStores: SafetyDepositTokenStore[]; | ||
} | ||
|
||
export const addTokensToVault = async ({ | ||
connection, | ||
wallet, | ||
vault, | ||
nfts, | ||
}: AddTokensToVaultParams): Promise<AddTokensToVaultResponse> => { | ||
const txOptions = { feePayer: wallet.publicKey }; | ||
const safetyDepositTokenStores: SafetyDepositTokenStore[] = []; | ||
|
||
const vaultAuthority = await Vault.getPDA(vault); | ||
const accountRent = await connection.getMinimumBalanceForRentExemption(AccountLayout.span); | ||
|
||
for (const nft of nfts) { | ||
const tokenTxBatch = new TransactionsBatch({ transactions: [] }); | ||
const safetyDepositBox = await SafetyDepositBox.getPDA(vault, nft.tokenMint); | ||
|
||
const tokenStoreAccount = Keypair.generate(); | ||
const tokenStoreAccountTx = new CreateTokenAccount(txOptions, { | ||
newAccountPubkey: tokenStoreAccount.publicKey, | ||
lamports: accountRent, | ||
mint: nft.tokenMint, | ||
owner: vaultAuthority, | ||
}); | ||
tokenTxBatch.addTransaction(tokenStoreAccountTx); | ||
tokenTxBatch.addSigner(tokenStoreAccount); | ||
|
||
const { authority: transferAuthority, createApproveTx } = createApproveTxs({ | ||
account: nft.tokenAccount, | ||
owner: wallet.publicKey, | ||
amount: nft.amount.toNumber(), | ||
}); | ||
tokenTxBatch.addTransaction(createApproveTx); | ||
tokenTxBatch.addSigner(transferAuthority); | ||
|
||
const addTokenTx = new AddTokenToInactiveVault(txOptions, { | ||
vault, | ||
vaultAuthority: wallet.publicKey, | ||
tokenAccount: nft.tokenAccount, | ||
tokenStoreAccount: tokenStoreAccount.publicKey, | ||
transferAuthority: transferAuthority.publicKey, | ||
safetyDepositBox: safetyDepositBox, | ||
amount: nft.amount, | ||
}); | ||
tokenTxBatch.addTransaction(addTokenTx); | ||
|
||
const txId = await sendTransaction({ | ||
connection, | ||
wallet, | ||
txs: tokenTxBatch.transactions, | ||
signers: tokenTxBatch.signers, | ||
}); | ||
|
||
safetyDepositTokenStores.push({ | ||
txId, | ||
tokenStoreAccount: tokenStoreAccount.publicKey, | ||
tokenMint: nft.tokenMint, | ||
tokenAccount: nft.tokenAccount, | ||
}); | ||
} | ||
|
||
return { safetyDepositTokenStores }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import BN from 'bn.js'; | ||
import { Transaction } from '@metaplex-foundation/mpl-core'; | ||
import { airdrop, LOCALHOST } from '@metaplex-foundation/amman'; | ||
import { Keypair, sendAndConfirmTransaction } from '@solana/web3.js'; | ||
|
||
import { Connection, NodeWallet } from '../../src'; | ||
import { | ||
addTokensToVault, | ||
createExternalPriceAccount, | ||
createVault, | ||
prepareTokenAccountAndMintTxs, | ||
} from '../../src/actions'; | ||
|
||
describe('addTokensToVault action', () => { | ||
test('creation and adding of multiple mint tokens to newly created vault', async () => { | ||
const payer = Keypair.generate(); | ||
const wallet = new NodeWallet(payer); | ||
const connection = new Connection(LOCALHOST, 'confirmed'); | ||
await airdrop(connection, payer.publicKey, 10); | ||
|
||
const TOKEN_AMOUNT = 2; | ||
const externalPriceAccountData = await createExternalPriceAccount({ connection, wallet }); | ||
|
||
const { vault } = await createVault({ | ||
connection, | ||
wallet, | ||
...externalPriceAccountData, | ||
}); | ||
|
||
const testNfts = []; | ||
|
||
for (let i = 0; i < TOKEN_AMOUNT; i++) { | ||
const { | ||
mint, | ||
recipient: tokenAccount, | ||
createAssociatedTokenAccountTx, | ||
createMintTx, | ||
mintToTx, | ||
} = await prepareTokenAccountAndMintTxs(connection, wallet.publicKey); | ||
|
||
await sendAndConfirmTransaction( | ||
connection, | ||
Transaction.fromCombined([createMintTx, createAssociatedTokenAccountTx, mintToTx]), | ||
[payer, mint, wallet.payer], | ||
); | ||
|
||
testNfts.push({ | ||
tokenAccount, | ||
tokenMint: mint.publicKey, | ||
amount: new BN(1), | ||
}); | ||
} | ||
|
||
const { safetyDepositTokenStores } = await addTokensToVault({ | ||
connection, | ||
wallet, | ||
vault, | ||
nfts: testNfts, | ||
}); | ||
|
||
expect(safetyDepositTokenStores.length).toEqual(testNfts.length); | ||
expect(safetyDepositTokenStores.map(({ tokenMint }) => tokenMint).join(',')).toEqual( | ||
testNfts.map(({ tokenMint }) => tokenMint).join(','), | ||
); | ||
}); | ||
}); |