UNPKG

@saberhq/token-utils

Version:

Token-related math and transaction utilities for Solana.

226 lines (208 loc) 5.45 kB
/** * This file is a port of serum-common, which was built for web3.js 0.x. */ import type { Provider } from "@saberhq/solana-contrib"; import type { MintInfo } from "@solana/spl-token"; import { Token as SPLToken, TOKEN_PROGRAM_ID } from "@solana/spl-token"; import type { TransactionInstruction } from "@solana/web3.js"; import { Keypair, PublicKey, SystemProgram, Transaction, } from "@solana/web3.js"; import type BN from "bn.js"; import { deserializeAccount, deserializeMint, MintLayout, Token, } from "./index.js"; import type { TokenAccountData } from "./layout.js"; export * as token from "./token.js"; export type { ProgramAccount } from "@saberhq/solana-contrib"; /** * Default number of decimals of a token. */ export const DEFAULT_TOKEN_DECIMALS = 6; export const SPL_SHARED_MEMORY_ID = new PublicKey( "shmem4EWT2sPdVGvTZCzXXRAURL9G5vpPxNwSeKhHUL", ); export async function createMint( provider: Provider, authority?: PublicKey, decimals?: number, ): Promise<PublicKey> { if (authority === undefined) { authority = provider.wallet.publicKey; } const mint = Keypair.generate(); const instructions = await createMintInstructions( provider, authority, mint.publicKey, decimals, ); const tx = new Transaction(); tx.add(...instructions); await provider.send(tx, [mint]); return mint.publicKey; } /** * Creates a Token. * * @param provider * @param authority The mint authority. * @param decimals Number of decimals. * @returns */ export async function createToken( provider: Provider, authority?: PublicKey, decimals = 6, ): Promise<Token> { return Token.fromMint( await createMint(provider, authority, decimals), decimals, ); } export async function createMintInstructions( provider: Provider, authority: PublicKey, mint: PublicKey, decimals = 6, ): Promise<TransactionInstruction[]> { const instructions = [ SystemProgram.createAccount({ fromPubkey: provider.wallet.publicKey, newAccountPubkey: mint, space: MintLayout.span, lamports: await provider.connection.getMinimumBalanceForRentExemption( MintLayout.span, ), programId: TOKEN_PROGRAM_ID, }), SPLToken.createInitMintInstruction( TOKEN_PROGRAM_ID, mint, decimals, authority, null, ), ]; return instructions; } export async function createMintAndVault( provider: Provider, amount: BN, owner?: PublicKey, decimals?: number, ): Promise<[PublicKey, PublicKey]> { if (owner === undefined) { owner = provider.wallet.publicKey; } const mint = Keypair.generate(); const vault = Keypair.generate(); const tx = new Transaction(); tx.add( ...(await createMintInstructions( provider, provider.wallet.publicKey, mint.publicKey, decimals, )), SystemProgram.createAccount({ fromPubkey: provider.wallet.publicKey, newAccountPubkey: vault.publicKey, space: 165, lamports: await provider.connection.getMinimumBalanceForRentExemption(165), programId: TOKEN_PROGRAM_ID, }), SPLToken.createInitAccountInstruction( TOKEN_PROGRAM_ID, mint.publicKey, vault.publicKey, owner, ), SPLToken.createMintToInstruction( TOKEN_PROGRAM_ID, mint.publicKey, vault.publicKey, provider.wallet.publicKey, [], amount, ), ); await provider.send(tx, [mint, vault]); return [mint.publicKey, vault.publicKey]; } export async function createTokenAccountInstrs( provider: Provider, newAccountPubkey: PublicKey, mint: PublicKey, owner: PublicKey, lamports?: number, ): Promise<TransactionInstruction[]> { if (lamports === undefined) { lamports = await provider.connection.getMinimumBalanceForRentExemption(165); } return [ SystemProgram.createAccount({ fromPubkey: provider.wallet.publicKey, newAccountPubkey, space: 165, lamports, programId: TOKEN_PROGRAM_ID, }), SPLToken.createInitAccountInstruction( TOKEN_PROGRAM_ID, mint, newAccountPubkey, owner, ), ]; } export async function createAccountRentExempt( provider: Provider, programId: PublicKey, size: number, ): Promise<Keypair> { const acc = Keypair.generate(); const tx = new Transaction(); tx.add( SystemProgram.createAccount({ fromPubkey: provider.wallet.publicKey, newAccountPubkey: acc.publicKey, space: size, lamports: await provider.connection.getMinimumBalanceForRentExemption(size), programId, }), ); await provider.send(tx, [acc]); return acc; } export async function getMintInfo( provider: Provider, addr: PublicKey, ): Promise<MintInfo> { const depositorAccInfo = await provider.getAccountInfo(addr); if (depositorAccInfo === null) { throw new Error("Failed to find token mint account"); } return deserializeMint(depositorAccInfo.accountInfo.data); } export async function getTokenAccount( provider: Provider, addr: PublicKey, ): Promise<TokenAccountData> { const depositorAccInfo = await provider.getAccountInfo(addr); if (depositorAccInfo === null) { throw new Error("Failed to find token account"); } return deserializeAccount(depositorAccInfo.accountInfo.data); } export function sleep(ms: number): Promise<void> { return new Promise((resolve) => setTimeout(resolve, ms)); }