| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- import { getCreateAccountInstruction } from '@solana-program/system';
- import {
- Address,
- BaseTransactionMessage,
- Commitment,
- Rpc,
- RpcSubscriptions,
- SolanaRpcApi,
- SolanaRpcSubscriptionsApi,
- TransactionMessageWithBlockhashLifetime,
- TransactionMessageWithFeePayer,
- TransactionPlan,
- TransactionPlanResult,
- TransactionPlanner,
- TransactionSigner,
- airdropFactory,
- appendTransactionMessageInstructions,
- assertIsSendableTransaction,
- assertIsTransactionWithBlockhashLifetime,
- createSolanaRpc,
- createSolanaRpcSubscriptions,
- createTransactionMessage,
- createTransactionPlanExecutor,
- createTransactionPlanner,
- generateKeyPairSigner,
- getSignatureFromTransaction,
- lamports,
- pipe,
- sendAndConfirmTransactionFactory,
- setTransactionMessageFeePayerSigner,
- setTransactionMessageLifetimeUsingBlockhash,
- signTransactionMessageWithSigners,
- } from '@solana/kit';
- import {
- TOKEN_PROGRAM_ADDRESS,
- findAssociatedTokenPda,
- getInitializeAccountInstruction,
- getInitializeMintInstruction,
- getMintSize,
- getMintToATAInstructionPlan,
- getMintToInstruction,
- getTokenSize,
- } from '../src';
- type Client = {
- rpc: Rpc<SolanaRpcApi>;
- rpcSubscriptions: RpcSubscriptions<SolanaRpcSubscriptionsApi>;
- sendTransactionPlan: (
- transactionPlan: TransactionPlan
- ) => Promise<TransactionPlanResult>;
- };
- export const createDefaultSolanaClient = (): Client => {
- const rpc = createSolanaRpc('http://127.0.0.1:8899');
- const rpcSubscriptions = createSolanaRpcSubscriptions('ws://127.0.0.1:8900');
- const sendAndConfirm = sendAndConfirmTransactionFactory({
- rpc,
- rpcSubscriptions,
- });
- const transactionPlanExecutor = createTransactionPlanExecutor({
- executeTransactionMessage: async (transactionMessage) => {
- const signedTransaction =
- await signTransactionMessageWithSigners(transactionMessage);
- assertIsSendableTransaction(signedTransaction);
- assertIsTransactionWithBlockhashLifetime(signedTransaction);
- await sendAndConfirm(signedTransaction, { commitment: 'confirmed' });
- return { transaction: signedTransaction };
- },
- });
- const sendTransactionPlan = async (transactionPlan: TransactionPlan) => {
- return transactionPlanExecutor(transactionPlan);
- };
- return { rpc, rpcSubscriptions, sendTransactionPlan };
- };
- export const generateKeyPairSignerWithSol = async (
- client: Client,
- putativeLamports: bigint = 1_000_000_000n
- ) => {
- const signer = await generateKeyPairSigner();
- await airdropFactory(client)({
- recipientAddress: signer.address,
- lamports: lamports(putativeLamports),
- commitment: 'confirmed',
- });
- return signer;
- };
- export const createDefaultTransaction = async (
- client: Client,
- feePayer: TransactionSigner
- ) => {
- const { value: latestBlockhash } = await client.rpc
- .getLatestBlockhash()
- .send();
- return pipe(
- createTransactionMessage({ version: 0 }),
- (tx) => setTransactionMessageFeePayerSigner(feePayer, tx),
- (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx)
- );
- };
- export const signAndSendTransaction = async (
- client: Client,
- transactionMessage: BaseTransactionMessage &
- TransactionMessageWithFeePayer &
- TransactionMessageWithBlockhashLifetime,
- commitment: Commitment = 'confirmed'
- ) => {
- const signedTransaction =
- await signTransactionMessageWithSigners(transactionMessage);
- const signature = getSignatureFromTransaction(signedTransaction);
- assertIsSendableTransaction(signedTransaction);
- assertIsTransactionWithBlockhashLifetime(signedTransaction);
- await sendAndConfirmTransactionFactory(client)(signedTransaction, {
- commitment,
- });
- return signature;
- };
- export const createDefaultTransactionPlanner = (
- client: Client,
- feePayer: TransactionSigner
- ): TransactionPlanner => {
- return createTransactionPlanner({
- createTransactionMessage: async () => {
- const { value: latestBlockhash } = await client.rpc
- .getLatestBlockhash()
- .send();
- return pipe(
- createTransactionMessage({ version: 0 }),
- (tx) => setTransactionMessageFeePayerSigner(feePayer, tx),
- (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx)
- );
- },
- });
- };
- export const getBalance = async (client: Client, address: Address) =>
- (await client.rpc.getBalance(address, { commitment: 'confirmed' }).send())
- .value;
- export const createMint = async (
- client: Client,
- payer: TransactionSigner,
- mintAuthority: Address,
- decimals: number = 0
- ): Promise<Address> => {
- const space = BigInt(getMintSize());
- const [transactionMessage, rent, mint] = await Promise.all([
- createDefaultTransaction(client, payer),
- client.rpc.getMinimumBalanceForRentExemption(space).send(),
- generateKeyPairSigner(),
- ]);
- const instructions = [
- getCreateAccountInstruction({
- payer,
- newAccount: mint,
- lamports: rent,
- space,
- programAddress: TOKEN_PROGRAM_ADDRESS,
- }),
- getInitializeMintInstruction({
- mint: mint.address,
- decimals,
- mintAuthority,
- }),
- ];
- await pipe(
- transactionMessage,
- (tx) => appendTransactionMessageInstructions(instructions, tx),
- (tx) => signAndSendTransaction(client, tx)
- );
- return mint.address;
- };
- export const createToken = async (
- client: Client,
- payer: TransactionSigner,
- mint: Address,
- owner: Address
- ): Promise<Address> => {
- const space = BigInt(getTokenSize());
- const [transactionMessage, rent, token] = await Promise.all([
- createDefaultTransaction(client, payer),
- client.rpc.getMinimumBalanceForRentExemption(space).send(),
- generateKeyPairSigner(),
- ]);
- const instructions = [
- getCreateAccountInstruction({
- payer,
- newAccount: token,
- lamports: rent,
- space,
- programAddress: TOKEN_PROGRAM_ADDRESS,
- }),
- getInitializeAccountInstruction({ account: token.address, mint, owner }),
- ];
- await pipe(
- transactionMessage,
- (tx) => appendTransactionMessageInstructions(instructions, tx),
- (tx) => signAndSendTransaction(client, tx)
- );
- return token.address;
- };
- export const createTokenWithAmount = async (
- client: Client,
- payer: TransactionSigner,
- mintAuthority: TransactionSigner,
- mint: Address,
- owner: Address,
- amount: bigint
- ): Promise<Address> => {
- const space = BigInt(getTokenSize());
- const [transactionMessage, rent, token] = await Promise.all([
- createDefaultTransaction(client, payer),
- client.rpc.getMinimumBalanceForRentExemption(space).send(),
- generateKeyPairSigner(),
- ]);
- const instructions = [
- getCreateAccountInstruction({
- payer,
- newAccount: token,
- lamports: rent,
- space,
- programAddress: TOKEN_PROGRAM_ADDRESS,
- }),
- getInitializeAccountInstruction({ account: token.address, mint, owner }),
- getMintToInstruction({ mint, token: token.address, mintAuthority, amount }),
- ];
- await pipe(
- transactionMessage,
- (tx) => appendTransactionMessageInstructions(instructions, tx),
- (tx) => signAndSendTransaction(client, tx)
- );
- return token.address;
- };
- export const createTokenPdaWithAmount = async (
- client: Client,
- payer: TransactionSigner,
- mintAuthority: TransactionSigner,
- mint: Address,
- owner: Address,
- amount: bigint,
- decimals: number
- ): Promise<Address> => {
- const [token] = await findAssociatedTokenPda({
- owner,
- mint,
- tokenProgram: TOKEN_PROGRAM_ADDRESS,
- });
- const transactionPlan = await createDefaultTransactionPlanner(
- client,
- payer
- )(
- getMintToATAInstructionPlan({
- payer,
- ata: token,
- owner,
- mint,
- mintAuthority,
- amount,
- decimals,
- })
- );
- await client.sendTransactionPlan(transactionPlan);
- return token;
- };
|