UNPKG

yamaswap-sdk

Version:
231 lines (205 loc) 7.81 kB
import ETFTOKEN from "../abis/CryptoETFToken.json"; import CETO from "../abis/CryptoETFOracle.json"; import ROUTER from "../abis/CryptoETFRouter.json"; import ETFFACTORY from "../abis/CryptoETFTokenFactory.json"; import { Contract, ethers } from "ethers"; import type { ETFCreateParams, ETFBurnParams, MintETFTokenParams, ETFCreateResult, MintETFResult } from '../types/params'; export class DexClientEVM { public readonly factory: Contract; public readonly router: Contract; public readonly oracle: Contract; public readonly signer: ethers.JsonRpcSigner; // 常量定义 private readonly WETH: string; constructor( signer: ethers.JsonRpcSigner, addresses: { TWAP: string; CETO: string; ETFROUTER: string; ETFFACTORY: string; WETH: string; } // , network: "localhost" | "arbitrumSepolia" | "sepolia" ) { this.factory = new ethers.Contract(addresses.ETFFACTORY, ETFFACTORY.abi, signer); this.router = new ethers.Contract(addresses.ETFROUTER, ROUTER.abi, signer); this.oracle = new ethers.Contract(addresses.CETO, CETO.abi, signer); this.signer = signer; this.WETH = addresses.WETH; } public async createETF(params: ETFCreateParams): Promise<ETFCreateResult> { try { const { name, symbol, description: tokenUri, assets } = params; // 检查是否已存在 const existingETF = await this.factory.etfListM(symbol); if (existingETF !== ethers.ZeroAddress) { return { success: false, error: 'ETF already exists', data: { etfAddress: existingETF, symbol } }; } // 创建 ETF const tx = await this.factory.createETF( name, symbol, tokenUri, assets.map(asset => ({ tokenAddress: asset.token, distribution: asset.weight // 5000 })) ); await tx.wait(); // 获取创建的 ETF 地址 const etfAddress = await this.factory.etfListM(symbol); console.log(`Created ETF at address: ${etfAddress}`); return { success: true, txid: tx.hash, data: { etfAddress, symbol, name } }; } catch (error) { console.error("Error in createETF:", error); return { success: false, txid: '', error: error instanceof Error ? error.message : 'Failed to create ETF' }; } } public async purchaseETF(params: MintETFTokenParams): Promise<MintETFResult> { try { const { etfAddress, lamports } = params; // 检查用户余额 const userAddress = await this.signer.getAddress(); const balance = await this.signer.provider?.getBalance(userAddress); console.log( "USER ETH=>", ethers.formatEther(balance) ); // 获取最新 NAV const nav = await this.oracle.nav(etfAddress, this.WETH, 10); console.log('Current ETF NAV:', ethers.formatEther(nav), 'ETH'); // 设置截止时间 const deadline = Math.round(Date.now() / 1000) + 100; // 购买 ETF const tx = await this.router.purchaseWithExactEth( etfAddress, this.signer.address, 0, deadline, { value: ethers.parseUnits(lamports.toString()) } ); const receipt = await tx.wait(); // 获取 ETF 合约实例 const etfBalance = await this.getETFBalance(etfAddress); return { success: true, txid: receipt.transactionHash, data: { balance: etfBalance.toString(), etfAddress } }; } catch (error) { console.error("Error in purchaseETF:", error); return { success: false, txid: '', error: error instanceof Error ? error.message : 'Failed to purchase ETF' }; } } public async burnETF(params: ETFBurnParams): Promise<MintETFResult> { try { const { etfAddress, lamports } = params; const deadline = Math.round(Date.now() / 1000) + 100; // 赎回 ETF const tx = await this.router.redeemWithExactEth( etfAddress, lamports, this.signer.address, 0, deadline ); const receipt = await tx.wait(); const etfBalance = await this.getETFBalance(etfAddress); return { success: true, txid: receipt.transactionHash, data: { balance: etfBalance.toString(), etfAddress } }; } catch (error) { console.error("Error in burnETF:", error); return { success: false, txid: '', error: error instanceof Error ? error.message : 'Failed to burn ETF' }; } } // 查询方法 public async getETFInfo(etfAddress: string) { const etfContract = new ethers.Contract(etfAddress, ETFTOKEN.abi, this.signer); const totalSupply = await etfContract.totalSupply(); // 获取组成部分信息 const constituentTokens = await etfContract.getConstituentTokens(); const reserves = await Promise.all( constituentTokens.map(async (token: string) => ({ token, reserve: await etfContract.constitunentsReserves(token) })) ); return { totalSupply: totalSupply.toString(), reserves }; } public async getETFBalance(etfAddress: string) { const etfContract = new ethers.Contract(etfAddress, ETFTOKEN.abi, this.signer); return await etfContract.balanceOf(this.signer.address); } public async getNav(etfAddress: string) { return await this.oracle.nav(etfAddress, this.WETH, 10); } // async function checkResult(etf, ceto) { // console.log("======BEGIN TO CHECK STATE====="); // const [signer1] = await ethers.getSigners(); // const etfC = await ethers.getContractAt(ETFTOKENABI, etf); // console.log("MINT TOTAL ETF=>", await etfC.totalSupply()); // //检查etf reverse // for (const _consti of constitunents) { // let _token = await ethers.getContractAt(ERC20ABI, _consti.tokenAddress); // console.log( // "RESERVE %s IN ETF=>%s", // _consti.tokenAddress, // await etfC.constitunentsReserves(_consti.tokenAddress) // ); // console.log( // "ERC20 %s BALANCE=>", // _consti.tokenAddress, // await _token.balanceOf(etf) // ); // } // console.log( // "AFTER EFT NAV=>", // ethers.formatEther(await ceto.nav(etf, WETH, 10)), // "ETH" // ); // console.log( // "USER ETH=>", // ethers.formatEther(await ethers.provider.getBalance(signer1.address)) // ); // } }