@gramio/crypto-pay-api
Version:
CryptoPay / CryptoBot API client
208 lines (201 loc) • 5.89 kB
JavaScript
;
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;