UNPKG

four-flap-meme-sdk

Version:

SDK for Flap bonding curve and four.meme TokenManager

105 lines (104 loc) 4.17 kB
export class FourClient { constructor(cfg) { // 默认使用 Cloudflare Workers 代理,已配置 CORS,浏览器可直接使用 this.baseUrl = cfg?.baseUrl || 'https://throbbing-shape-a160.paulalsop072.workers.dev'; } async generateNonce(req) { const r = await fetch(`${this.baseUrl}/v1/private/user/nonce/generate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(req), }); const j = await r.json(); // code 可能是字符串 '0' 或数字 0 if (j.code !== '0' && j.code !== 0) { throw new Error(`generateNonce failed: ${JSON.stringify(j)}`); } return j.data; } async loginDex(body) { const r = await fetch(`${this.baseUrl}/v1/private/user/login/dex`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); const j = await r.json(); if (j.code !== '0' && j.code !== 0) { throw new Error(`login failed: ${JSON.stringify(j)}`); } return j.data; // access_token } async uploadImage(accessToken, file, filename) { const form = new FormData(); // 如果提供了文件名,使用它;否则根据 MIME 类型生成 const finalFilename = filename || this.getFilenameFromBlob(file); form.append('file', file, finalFilename); const r = await fetch(`${this.baseUrl}/v1/private/token/upload`, { method: 'POST', headers: { 'meme-web-access': accessToken }, body: form, }); const j = await r.json(); if (j.code !== '0' && j.code !== 0) { throw new Error(`upload failed: ${JSON.stringify(j)}`); } return j.data; // imgUrl } getFilenameFromBlob(blob) { const mimeToExt = { 'image/jpeg': 'jpg', 'image/jpg': 'jpg', 'image/png': 'png', 'image/gif': 'gif', 'image/bmp': 'bmp', 'image/webp': 'webp', }; const ext = mimeToExt[blob.type] || 'png'; return `image-${Date.now()}.${ext}`; } async createToken(accessToken, req) { const r = await fetch(`${this.baseUrl}/v1/private/token/create`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'meme-web-access': accessToken }, body: JSON.stringify(req), }); const j = await r.json(); if (j.code !== '0' && j.code !== 0) { throw new Error(`createToken failed: ${JSON.stringify(j)}`); } return j.data; } async getPublicConfig() { const r = await fetch(`${this.baseUrl}/v1/public/config`); return await r.json(); } async getTokenByAddress(address, accessToken) { const r = await fetch(`${this.baseUrl}/v1/private/token/get?address=${address}`, { headers: accessToken ? { 'meme-web-access': accessToken } : undefined, }); const j = await r.json(); if (j.code && j.code !== '0' && j.code !== 0) { throw new Error(`getTokenByAddress failed: ${JSON.stringify(j)}`); } return j.data ?? j; } async getTokensByAddresses(addresses, accessToken) { if (!Array.isArray(addresses) || addresses.length === 0) return []; const tasks = addresses.map((addr) => this.getTokenByAddress(addr, accessToken).catch((e) => ({ address: addr, error: String(e) }))); return await Promise.all(tasks); } async getTokenById(id, accessToken) { const r = await fetch(`${this.baseUrl}/v1/private/token/getById?id=${id}`, { headers: accessToken ? { 'meme-web-access': accessToken } : undefined, }); const j = await r.json(); if (j.code && j.code !== '0' && j.code !== 0) { throw new Error(`getTokenById failed: ${JSON.stringify(j)}`); } return j.data ?? j; } } export function buildLoginMessage(nonce) { return `You are sign in Meme ${nonce}`; }