UNPKG

@gramio/crypto-pay-api

Version:
208 lines (201 loc) 5.89 kB
'use strict'; var node_crypto = require('node:crypto'); function checkSignature(token, signature, body) { const secret = typeof token === "string" ? node_crypto.createHash("sha256").update(token).digest() : token; const checkString = JSON.stringify(body); const hmac = node_crypto.createHmac("sha256", secret).update(checkString).digest("hex"); return hmac === signature; } const HEADER_NAME = "crypto-pay-api-signature"; const frameworks = { elysia: ({ body, headers }) => ({ body, response: () => new Response("OK"), getSignatureHeader: () => headers[HEADER_NAME] }), fastify: (request, reply) => ({ body: request.body, response: () => reply.send("OK"), getSignatureHeader: () => request.headers[HEADER_NAME] }), hono: (c) => ({ body: c.req.json(), response: () => c.text("OK"), getSignatureHeader: () => c.req.header(HEADER_NAME) }), express: (req, res) => ({ body: req.body, response: () => res.send("OK"), getSignatureHeader: () => req.headers[HEADER_NAME] }), koa: (ctx) => ({ body: ctx.request.body, response: () => { ctx.body = "OK"; }, getSignatureHeader: () => ctx.request.header[HEADER_NAME] }), http: (req, res) => ({ body: new Promise((resolve) => { let body = ""; req.on("data", (chunk) => { body += chunk.toString(); }); req.on("end", () => resolve(JSON.parse(body))); }), response: () => res.writeHead(200).end("OK"), getSignatureHeader: () => req.headers[HEADER_NAME] }), "std/http": (req) => ({ body: req.json(), response: () => new Response("OK"), getSignatureHeader: () => req.headers.get(HEADER_NAME) }), "Bun.serve": (req) => ({ body: req.json(), response: () => new Response("OK"), getSignatureHeader: () => req.headers.get(HEADER_NAME) }) }; function webhookHandler(client, framework) { const frameworkAdapter = frameworks[framework]; return async (...args) => { const { body, response, getSignatureHeader } = frameworkAdapter( ...args ); await client.emit(await body, getSignatureHeader()); if (response) return response(); }; } class CryptoPayAPI { /** * Creates a new CryptoPayAPI instance. * @param apiKey - The API key to use for authentication. * @param network - The network to use for the API. */ constructor(apiKey, network = "mainnet") { this.apiKey = apiKey; this.endpoint = network === "mainnet" ? "https://pay.crypt.bot/" : "https://testnet-pay.crypt.bot/"; } endpoint; listeners = []; async request(method, params) { const url = `${this.endpoint}api/${method}`; const response = await fetch(url, { method: "POST", body: JSON.stringify(params), headers: { "Content-Type": "application/json", "Crypto-Pay-API-Token": this.apiKey } }); const data = await response.json(); if (!data.ok) { throw new Error( `${method} failed: ${data.error.code} - ${data.error.name}` ); } return data.result; } async emit(data, signature) { const isSignatureValid = checkSignature(this.apiKey, signature, data); if (!isSignatureValid) return false; for (const listener of this.listeners) { await listener(data); } return true; } on(_event, listener) { this.listeners.push(listener); } /** * Tests the authentication token and retrieves basic app information. * @returns {@link AppInfo} wrapped in {@link ApiResponse}. */ getMe() { return this.request("getMe", {}); } /** * Creates a new invoice and returns the created invoice object. * @param params Parameters accepted by createInvoice method. */ createInvoice(params) { return this.request("createInvoice", params); } /** * Deletes one or multiple invoices by ID. * @param params List of invoice IDs to delete. */ deleteInvoice(params) { return this.request("deleteInvoice", params); } /** * Creates a crypto check (voucher). * @param params Check creation parameters. */ createCheck(params) { return this.request("createCheck", params); } /** * Deletes existing checks by IDs. * @param params List of check IDs to delete. */ deleteCheck(params) { return this.request("deleteCheck", params); } /** * Transfers funds from the app balance to a Telegram user. * @param params Transfer parameters including user ID and asset. */ transfer(params) { return this.request("transfer", params); } /** * Retrieves invoices optionally filtered by status, period or identifiers. * @param params Optional filtering parameters. */ getInvoices(params = {}) { return this.request("getInvoices", params); } /** * Retrieves checks optionally filtered by status or period. * @param params Optional filtering parameters. */ getChecks(params = {}) { return this.request("getChecks", params); } /** * Retrieves transfers optionally filtered by identifiers or period. * @param params Optional filtering parameters. */ getTransfers(params = {}) { return this.request("getTransfers", params); } /** * Retrieves current asset balances of the app wallet. */ getBalance() { return this.request("getBalance", {}); } /** * Retrieves current exchange rates for supported crypto assets. */ getExchangeRates() { return this.request("getExchangeRates", {}); } /** * Retrieves list of currencies supported by the platform. */ getCurrencies() { return this.request("getCurrencies", {}); } /** * Retrieves aggregated application statistics for a specified period. * @param params Date range parameters. */ getStats(params) { return this.request("getStats", params); } } exports.CryptoPayAPI = CryptoPayAPI; exports.webhookHandler = webhookHandler;