UNPKG

@crateprotocol/yi

Version:

The TypeScript SDK for Yi Token by Crate Protocol.

206 lines (198 loc) 5.44 kB
import { newProgramMap } from "@saberhq/anchor-contrib"; import type { AugmentedProvider, Provider, TransactionEnvelope, } from "@saberhq/solana-contrib"; import { SolanaAugmentedProvider } from "@saberhq/solana-contrib"; import type { Token, TokenAmount, u64 } from "@saberhq/token-utils"; import { createInitMintInstructions, getOrCreateATA, getOrCreateATAs, TOKEN_PROGRAM_ID, } from "@saberhq/token-utils"; import type { PublicKey, Signer } from "@solana/web3.js"; import { Keypair, SystemProgram } from "@solana/web3.js"; import type { YiPrograms } from "."; import { findYiTokenAddress } from "."; import { YI_ADDRESSES, YI_IDLS } from "./constants"; /** * Yi SDK. */ export class YiSDK { constructor( readonly provider: AugmentedProvider, readonly programs: YiPrograms ) {} /** * Creates a new instance of the SDK with the given keypair. */ withSigner(signer: Signer): YiSDK { return YiSDK.load({ provider: this.provider.withSigner(signer), }); } /** * Loads the SDK. * @returns */ static load({ provider }: { provider: Provider }): YiSDK { const programs: YiPrograms = newProgramMap<YiPrograms>( provider, YI_IDLS, YI_ADDRESSES ); return new YiSDK(new SolanaAugmentedProvider(provider), programs); } /** * Creates a new Yi Token. * @returns */ async createYiToken({ underlyingToken, stakeFeeMillibps = 0, unstakeFeeMillibps = 0, mintKP = Keypair.generate(), payer = this.provider.wallet.publicKey, }: { underlyingToken: Token; stakeFeeMillibps?: number; unstakeFeeMillibps?: number; /** * Keypair of the mint of the YiToken. */ mintKP?: Signer; payer?: PublicKey; }): Promise<{ tx: TransactionEnvelope; mint: PublicKey; yiToken: PublicKey; }> { const [yiToken] = await findYiTokenAddress(mintKP.publicKey); const underlyingTokens = await getOrCreateATA({ provider: this.provider, mint: underlyingToken.mintAccount, owner: yiToken, }); const initMintTX = await createInitMintInstructions({ provider: this.provider, mintKP, decimals: underlyingToken.decimals, mintAuthority: yiToken, freezeAuthority: yiToken, }); return { yiToken, mint: mintKP.publicKey, tx: initMintTX.combine( this.provider.newTX([ underlyingTokens.instruction, this.programs.Yi.instruction.createYiTokenWithFees( stakeFeeMillibps, unstakeFeeMillibps, { accounts: { mint: mintKP.publicKey, yiToken, underlyingTokenMint: underlyingToken.mintAccount, underlyingTokens: underlyingTokens.address, payer, systemProgram: SystemProgram.programId, }, } ), ]) ), }; } /** * Stakes underlying tokens for Yi tokens. * @returns */ async stake({ yiTokenMint, amount, authority = this.provider.wallet.publicKey, }: { /** * Mint of the Yi token. */ yiTokenMint: PublicKey; /** * Amount of underlying tokens to stake. */ amount: u64; /** * Authority staking tokens. */ authority?: PublicKey; }): Promise<TransactionEnvelope> { const [yiToken] = await findYiTokenAddress(yiTokenMint); const yiTokenData = await this.programs.Yi.account.yiToken.fetch(yiToken); const authorityATAs = await getOrCreateATAs({ provider: this.provider, mints: { underlying: yiTokenData.underlyingTokenMint, yi: yiTokenData.mint, }, owner: authority, }); return this.provider.newTX([ authorityATAs.createAccountInstructions.yi, this.programs.Yi.instruction.stake(amount, { accounts: { yiToken, yiMint: yiTokenMint, sourceTokens: authorityATAs.accounts.underlying, sourceAuthority: authority, yiUnderlyingTokens: yiTokenData.underlyingTokens, destinationYiTokens: authorityATAs.accounts.yi, tokenProgram: TOKEN_PROGRAM_ID, }, }), ]); } /** * Unstakes Yi tokens. * @returns */ async unstake({ amount, authority = this.provider.wallet.publicKey, }: { /** * Yi Token Amount */ amount: TokenAmount; /** * Authority unstaking tokens. */ authority?: PublicKey; }): Promise<TransactionEnvelope> { const [yiToken] = await findYiTokenAddress(amount.token.mintAccount); const yiTokenData = await this.programs.Yi.account.yiToken.fetch(yiToken); const authorityATAs = await getOrCreateATAs({ provider: this.provider, mints: { underlying: yiTokenData.underlyingTokenMint, yi: yiTokenData.mint, }, owner: authority, }); return this.provider.newTX([ ...authorityATAs.instructions, this.programs.Yi.instruction.unstake(amount.toU64(), { accounts: { yiToken, yiMint: amount.token.mintAccount, sourceYiTokens: authorityATAs.accounts.yi, sourceAuthority: authority, yiUnderlyingTokens: yiTokenData.underlyingTokens, destinationUnderlyingTokens: authorityATAs.accounts.underlying, tokenProgram: TOKEN_PROGRAM_ID, }, }), ]); } }