UNPKG

four-flap-meme-sdk

Version:

SDK for Flap bonding curve and four.meme TokenManager

68 lines (67 loc) 2.66 kB
import { Wallet, AbiCoder, Contract, JsonRpcProvider } from 'ethers'; import { FLAP_PORTAL_ADDRESSES } from './constants.js'; import { CHAIN } from '../utils/constants.js'; /** * 构建 Permit Piggyback 数据 * 自动签名并使用正确的 Portal 代理地址 * * @param chain 链名称 * @param privateKey 用户私钥 * @param tokenAddress ERC20 代币地址(需要支持 EIP-2612 Permit) * @param value 授权金额 * @param deadline 截止时间戳 * @param nonce Permit nonce(通常从代币合约的 nonces(owner) 获取) * @returns Permit Piggyback 编码数据(Hex string) */ export async function buildPermitPiggybackAuto(chain, privateKey, tokenAddress, value, deadline, nonce, opts) { const spender = FLAP_PORTAL_ADDRESSES[chain]; if (!spender) { throw new Error(`Flap Portal not deployed on ${chain}`); } // 创建钱包 const wallet = new Wallet(privateKey); const owner = wallet.address; // 获取 chainId const chainId = CHAIN[chain].chainId; // 读取代币 name(优先 override,其次链上查询,不可用时回退为空字符串) let tokenName = opts?.tokenNameOverride ?? ''; if (!tokenName && opts?.rpcUrl) { try { const erc20 = new Contract(tokenAddress, ['function name() view returns (string)'], new JsonRpcProvider(opts.rpcUrl)); tokenName = await erc20.name(); } catch { } } // 构建 EIP-2612 Permit 消息(name 可能为空字符串,符合部分实现) const domain = { name: tokenName, version: '1', chainId, verifyingContract: tokenAddress, }; const types = { Permit: [ { name: 'owner', type: 'address' }, { name: 'spender', type: 'address' }, { name: 'value', type: 'uint256' }, { name: 'nonce', type: 'uint256' }, { name: 'deadline', type: 'uint256' }, ], }; const message = { owner, spender, value: value.toString(), nonce: nonce.toString(), deadline: deadline.toString(), }; // 签名 const signature = await wallet.signTypedData(domain, types, message); // 解析签名为 v, r, s const r = `0x${signature.slice(2, 66)}`; const s = `0x${signature.slice(66, 130)}`; const v = parseInt(signature.slice(130, 132), 16); // 使用 ethers AbiCoder 编码 Permit Piggyback 数据 const abiCoder = AbiCoder.defaultAbiCoder(); return abiCoder.encode(['address', 'address', 'uint256', 'uint256', 'uint8', 'bytes32', 'bytes32'], [owner, spender, value, deadline, v, r, s]); }