yamaswap-sdk
Version:
ETF SDK for Solana and Evm
81 lines (72 loc) • 3.29 kB
text/typescript
import { PublicKey } from '@solana/web3.js';
import { getAccount, getAssociatedTokenAddressSync, TokenAccountNotFoundError, Account } from '@solana/spl-token';
import { ETFInvalidParamsError, ETFInsufficientBalanceError, ETFNotExistsError } from './error';
import { DexClient } from '../core/client';
// Start of Selection
import { ETFInfo } from './queries';
import { ETFCreateParams, MintETFTokenParams } from '../types/params';
export async function checkATAExists(client: DexClient, tokens: PublicKey[], owner: PublicKey, isContract: boolean = false): Promise<Account | undefined> {
for (const token of tokens) {
const tokenAccountAddress = getAssociatedTokenAddressSync(token, owner, isContract);
try {
return await getAccount(client.connection, tokenAccountAddress);
} catch (e) {
if (e instanceof TokenAccountNotFoundError) {
throw new TokenAccountNotFoundError(`账户 ${tokenAccountAddress.toBase58()} 不存在`);
}
throw e;
}
}
return undefined;
}
export async function checkBalance(client: DexClient, etfAddress: PublicKey, owner: PublicKey, requiredAmount: number): Promise<void> {
const balance = await client.queries.getETFBalance(etfAddress, owner);
if (balance < requiredAmount) {
throw new ETFInsufficientBalanceError(`用户代币账户余额不足,所需: ${requiredAmount}, 当前: ${balance}`);
}
}
export async function checkETFExists(client: DexClient, etfAddress: PublicKey): Promise<ETFInfo> {
const etfInfo = await client.queries.getETFInfo(etfAddress);
if (typeof etfInfo === 'string') {
throw new ETFNotExistsError(etfInfo);
}
return etfInfo;
}
export function validateETFCreateParams(params: ETFCreateParams): void {
const { assets } = params;
// check if the constituent is not empty
if (!assets?.length) {
throw new ETFInvalidParamsError('ETF组成部分不能为空');
}
const totalWeight = assets.reduce((sum, item) => sum + item.weight, 0);
if (totalWeight !== 100) {
throw new ETFInvalidParamsError(`ETF组成部分权重之和必须为100,当前为: ${totalWeight}`);
}
// check if the token address is valid
const tokenSet = new Set<string>();
for (const item of assets) {
let tokenKey: PublicKey;
try {
tokenKey = new PublicKey(item.token);
} catch (e) {
throw new ETFInvalidParamsError(`无效的代币地址: ${item.token}`);
}
// check if there are duplicate tokens
if (tokenSet.has(tokenKey.toBase58())) {
throw new ETFInvalidParamsError(`存在重复的代币地址: ${item.token}`);
}
tokenSet.add(tokenKey.toBase58());
if (item.weight <= 0) {
throw new ETFInvalidParamsError(`代币权重必须大于0: ${item.token}`);
}
}
}
export function validateMintETFParams(params: MintETFTokenParams): void {
if (params.lamports <= 0) {
throw new ETFInvalidParamsError('购买份额必须大于0');
}
// maximum limit 1000000 SOL
if (params.lamports > 1e15) { // 1000000 * 1e9
throw new ETFInvalidParamsError('购买份额超过最大限制(1000000 SOL)');
}
}