UNPKG

four-flap-meme-sdk

Version:

SDK for Flap bonding curve and four.meme TokenManager

177 lines (176 loc) 8.1 kB
import { Contract, JsonRpcProvider, Wallet } from 'ethers'; import TM2Abi from '../abis/TokenManager2.json' with { type: 'json' }; import Helper3Abi from '../abis/TokenManagerHelper3.json' with { type: 'json' }; import { Contract as EContract } from 'ethers'; import { ADDRESSES } from '../utils/constants.js'; import { TM1 } from './tm1.js'; import { TM2 } from './tm2.js'; export async function createTokenOnChain(params) { const { chain, rpcUrl, signerPrivateKey, args, signature, valueWei } = params; const provider = new JsonRpcProvider(rpcUrl); const signer = new Wallet(signerPrivateKey, provider); // 使用 Four.meme 平台原始合约地址(API 签名是给原始合约的) const FOUR_ORIGINAL_TM2 = '0x5c952063c7fc8610FFDB798152D69F0B9550762b'; const tm2 = new Contract(FOUR_ORIGINAL_TM2, TM2Abi, signer); const tx = await tm2.createToken(args, signature, { value: valueWei ?? 0n }); const receipt = await tx.wait(); // 解析 TokenCreate 事件获取代币地址 let tokenAddress; if (receipt && receipt.logs) { for (const log of receipt.logs) { try { const parsed = tm2.interface.parseLog({ topics: log.topics, data: log.data }); if (parsed && parsed.name === 'TokenCreate') { tokenAddress = parsed.args.token; break; } } catch (e) { // 忽略无法解析的日志 } } } return { receipt, tokenAddress }; } export async function tryBuy(chain, rpcUrl, token, amount, funds, proxyAddressOverride) { const helper3Addresses = { BSC: ADDRESSES.BSC.TokenManagerHelper3, BASE: ADDRESSES.BASE.TokenManagerHelper3, ARBITRUM_ONE: ADDRESSES.ARBITRUM_ONE.TokenManagerHelper3, }; const provider = new JsonRpcProvider(rpcUrl); // 优先用代理预览(若提供) if (proxyAddressOverride) { const proxyAbi = [ 'function previewBuy(address token, uint256 funds) view returns (uint256)', ]; const proxy = new EContract(proxyAddressOverride, proxyAbi, provider); const estimatedAmount = await proxy.previewBuy(token, funds); return { tokenManager: 'proxy', quote: '0x0000000000000000000000000000000000000000', estimatedAmount, estimatedCost: funds, estimatedFee: 0n, amountMsgValue: funds, amountApproval: 0n, amountFunds: funds, }; } const helper = new Contract(helper3Addresses[chain], Helper3Abi, provider); const r = await helper.tryBuy(token, amount, funds); return { tokenManager: r.tokenManager, quote: r.quote, estimatedAmount: r.estimatedAmount, estimatedCost: r.estimatedCost, estimatedFee: r.estimatedFee, amountMsgValue: r.amountMsgValue, amountApproval: r.amountApproval, amountFunds: r.amountFunds, }; } export async function trySell(chain, rpcUrl, token, amount, proxyAddressOverride) { const helper3Addresses = { BSC: ADDRESSES.BSC.TokenManagerHelper3, BASE: ADDRESSES.BASE.TokenManagerHelper3, ARBITRUM_ONE: ADDRESSES.ARBITRUM_ONE.TokenManagerHelper3, }; const provider = new JsonRpcProvider(rpcUrl); // 优先用代理预览(若提供) if (proxyAddressOverride) { const proxyAbi = [ 'function previewSell(address token, uint256 amount) view returns (uint256)', ]; const proxy = new EContract(proxyAddressOverride, proxyAbi, provider); const funds = await proxy.previewSell(token, amount); return { tokenManager: 'proxy', quote: '0x0000000000000000000000000000000000000000', funds, fee: 0n, }; } const helper = new Contract(helper3Addresses[chain], Helper3Abi, provider); const r = await helper.trySell(token, amount); return { tokenManager: r.tokenManager, quote: r.quote, funds: r.funds, fee: r.fee, }; } export async function buyTokenWithFunds(chain, rpcUrl, signerPrivateKey, token, funds, minAmount, to, origin = 0n) { const provider = new JsonRpcProvider(rpcUrl); const signer = new Wallet(signerPrivateKey, provider); const tm2 = new Contract(ADDRESSES[chain].TokenManagerV2, TM2Abi, signer); if (to) { const tx = await tm2.buyTokenAMAP(origin, token, to, funds, minAmount, { value: funds }); return await tx.wait(); } else { const tx = await tm2.buyTokenAMAP(token, funds, minAmount, { value: funds }); return await tx.wait(); } } export async function sellToken(chain, rpcUrl, signerPrivateKey, token, amount, minFunds, origin = 0n) { const provider = new JsonRpcProvider(rpcUrl); const signer = new Wallet(signerPrivateKey, provider); const tm2 = new Contract(ADDRESSES[chain].TokenManagerV2, TM2Abi, signer); // 使用明确的函数签名避免歧义 const tx = await tm2['sellToken(uint256,address,uint256,uint256)'](origin, token, amount, minFunds); return await tx.wait(); } // 统一路由:根据 Helper3.getTokenInfo.version 选择 V1 或 V2 export async function tradeBuy(chain, rpcUrl, token, params) { const helper3Addresses = { BSC: ADDRESSES.BSC.TokenManagerHelper3, BASE: ADDRESSES.BASE.TokenManagerHelper3, ARBITRUM_ONE: ADDRESSES.ARBITRUM_ONE.TokenManagerHelper3, }; const provider = new JsonRpcProvider(rpcUrl); const helper = new Contract(helper3Addresses[chain], Helper3Abi, provider); const info = await helper.getTokenInfo(token); const version = info.version; if (version === 1n) { if (chain !== 'BSC') throw new Error('TokenManager V1 only supported on BSC'); const tm1 = TM1.connectByChain('BSC', rpcUrl); if (params.type === 'funds') return await tm1.purchaseTokenAMAP(token, params.funds, params.minAmount, params.origin, params.to); return await tm1.purchaseToken(token, params.amount, params.maxFunds, params.origin, params.to); } if (chain !== 'BSC') throw new Error('TokenManager V2 only supported on BSC'); const tm2 = TM2.connectByChain('BSC', rpcUrl); if (params.type === 'funds') return await tm2.buyTokenAMAP(params.origin ?? 0n, token, params.to ?? undefined, params.funds, params.minAmount); return await tm2.buyToken(params.origin ?? 0n, token, params.to ?? undefined, params.amount, params.maxFunds); } export async function tradeSell(chain, rpcUrl, token, params) { const helper3Addresses = { BSC: ADDRESSES.BSC.TokenManagerHelper3, BASE: ADDRESSES.BASE.TokenManagerHelper3, ARBITRUM_ONE: ADDRESSES.ARBITRUM_ONE.TokenManagerHelper3, }; const provider = new JsonRpcProvider(rpcUrl); const helper = new Contract(helper3Addresses[chain], Helper3Abi, provider); const info = await helper.getTokenInfo(token); const version = info.version; if (version === 1n) { if (chain !== 'BSC') throw new Error('TokenManager V1 only supported on BSC'); const tm1 = TM1.connectByChain('BSC', rpcUrl); if (params.type === 'router' && params.from) return await tm1.saleToken(token, params.amount, params.origin, params.from, params.minFunds, params.feeRate, params.feeRecipient); return await tm1.saleToken(token, params.amount, params.origin, undefined, params.minFunds); } if (chain !== 'BSC') throw new Error('TokenManager V2 only supported on BSC'); const tm2 = TM2.connectByChain('BSC', rpcUrl); if (params.type === 'router') return await tm2.sellTokenFrom(params.origin ?? 0n, token, params.from, params.amount, params.minFunds, params.feeRate, params.feeRecipient); if (params.minFunds !== undefined) return await tm2.sellToken(params.origin ?? 0n, token, params.amount, params.minFunds); return await tm2.sellToken(token, params.amount); }