bnksy-sdk
Version:
567 lines (566 loc) • 16 kB
JavaScript
// src/index.ts
import { Wallet } from "ethers";
var BanksySDK = class {
constructor(config) {
// Crypto payout sub-module
this.cryptoPayout = null;
this.apiKey = config.apiKey;
this.serverUrl = (config.serverUrl || "https://api.banksy.io").replace(/\/$/, "");
this.pixPayout = new PixPayoutModule(this);
this.fiatCryptoPayout = new FiatCryptoPayoutModule(this);
}
// ============ Payment Methods ============
/**
* Create a new payment
* Supports: Crypto, PIX, Fiat-to-Crypto
*/
async createPayment(options) {
const body = {
successCallback: options.successCallback,
failureCallback: options.failureCallback
};
if (options.crypto) {
body.crypto = options.crypto;
if (options.fiatAmount && options.fiatCurrency) {
body.fiatAmount = options.fiatAmount;
body.fiatCurrency = options.fiatCurrency;
} else {
body.amount = options.amount;
}
} else if (options.currency) {
body.currency = options.currency;
body.amount = options.amount;
}
if (options.externalClientId) body.externalClientId = options.externalClientId;
if (options.context) body.context = options.context;
if (options.customerName) body.customerName = options.customerName;
if (options.customerEmail) body.customerEmail = options.customerEmail;
if (options.customerPhone) body.customerPhone = options.customerPhone;
if (options.details) body.details = options.details;
const response = await this.request("POST", "/sdk/payment/create", body);
return { success: true, payment: response };
}
/**
* Get payment by ID
*/
async getPayment(paymentId) {
return this.request("GET", `/sdk/payment/${paymentId}`);
}
/**
* Get payment status
*/
async getPaymentStatus(paymentId) {
return this.request("GET", `/sdk/payment/status/${paymentId}`);
}
/**
* Get multiple payments by IDs
*/
async getPayments(ids) {
return this.request("POST", "/sdk/payment/getPayments", { ids });
}
/**
* Get all payments with pagination
*/
async getAllPayments(options) {
const params = new URLSearchParams();
if (options?.status) params.append("status", options.status);
if (options?.skip !== void 0) params.append("skip", options.skip.toString());
if (options?.limit !== void 0) params.append("limit", options.limit.toString());
const query = params.toString();
return this.request("GET", `/sdk/payment/all${query ? `?${query}` : ""}`);
}
/**
* Verify a payment (mark as verified)
*/
async verifyPayment(paymentId) {
return this.request("PATCH", `/sdk/payment/verify/${paymentId}`);
}
/**
* Confirm a payment manually
*/
async confirmPayment(paymentId, options) {
return this.request("POST", "/sdk/payment/confirm", {
id: paymentId,
...options
});
}
/**
* Create a refund for a payment
*/
async createRefund(paymentId, options) {
return this.request("POST", `/sdk/payment/refund/${paymentId}`, options || {});
}
// ============ Withdraw Methods ============
/**
* Create a crypto withdrawal
*/
async createWithdraw(options) {
return this.request("POST", "/sdk/withdraw/create", options);
}
/**
* Create a bank withdrawal
*/
async createBankWithdraw(options) {
return this.request("POST", "/sdk/withdraw/create-bank", options);
}
// ============ Utility Methods ============
/**
* Check API status
*/
async checkStatus() {
return this.request("GET", "/sdk/common/status");
}
/**
* Get available payment providers
*/
async getProviders() {
return this.request("GET", "/sdk/common/providers");
}
/**
* Get supported crypto contracts
*/
async getContracts() {
return this.request("GET", "/sdk/common/contracts");
}
/**
* Get API key info
*/
async getKeyInfo() {
return this.request("GET", "/sdk/common/getKey");
}
// ============ Crypto Payout Methods ============
/**
* Initialize crypto payout module
* Required for processing payouts via PayoutProcessor contract
*/
initCryptoPayout(config) {
this.cryptoPayout = new CryptoPayoutModule(this, config);
return this.cryptoPayout;
}
// ============ Internal Methods ============
/**
* Make authenticated request to Banksy server
*/
async request(method, path, body) {
const url = `${this.serverUrl}${path}`;
const headers = {
"Content-Type": "application/json",
"x-auth": this.apiKey
};
const options = {
method,
headers
};
if (body && method !== "GET") {
options.body = JSON.stringify(body);
}
const response = await fetch(url, options);
const json = await response.json();
if (!response.ok) {
throw new Error(json.error || json.message || `Request failed: ${response.status}`);
}
if (json.data !== void 0) {
return json.data;
}
return json;
}
/**
* Get server URL (for sub-modules)
*/
getServerUrl() {
return this.serverUrl;
}
/**
* Get API key (for sub-modules)
*/
getApiKey() {
return this.apiKey;
}
};
var CryptoPayoutModule = class {
constructor(sdk, config) {
this.sdk = sdk;
this.wallet = new Wallet(config.privateKey);
const apiKey = sdk.getApiKey();
this.network = apiKey.includes("_test_") ? "sepolia" : "mainnet";
}
/**
* Get client registration status
*/
async getClientStatus() {
return this.request(
"GET",
`/sdk/crypto-payout/client/status?wallet=${this.wallet.address}`
);
}
/**
* Get wallet balances
*/
async getBalanceInfo() {
return this.request(
"GET",
`/sdk/crypto-payout/balance?wallet=${this.wallet.address}`
);
}
/**
* Check if contract is paused
*/
async isPaused() {
const response = await this.request("GET", "/sdk/crypto-payout/status");
return response.paused;
}
/**
* Calculate payout breakdown
*/
async calculatePayout(amount) {
return this.request(
"GET",
`/sdk/crypto-payout/calculate?wallet=${this.wallet.address}&amount=${amount}`
);
}
/**
* Check if approval is needed
*/
async needsApproval(amount) {
const response = await this.request(
"GET",
`/sdk/crypto-payout/check-approval?wallet=${this.wallet.address}&amount=${amount}`
);
return response.needsApproval;
}
/**
* Approve USDT spending
*/
async approve(amount) {
const txRequest = await this.request(
"POST",
"/sdk/crypto-payout/approve/prepare",
{ wallet: this.wallet.address, amount }
);
const txHash = await this.signAndBroadcast(txRequest);
await this.request("POST", "/sdk/crypto-payout/approve/confirm", {
wallet: this.wallet.address,
txHash
});
return txHash;
}
/**
* Process a single payout
*/
async processPayout(recipient, amount, reference) {
await this.preflight(amount);
const txRequest = await this.request(
"POST",
"/sdk/crypto-payout/process/prepare",
{
wallet: this.wallet.address,
recipient,
amount,
reference: reference || ""
}
);
const txHash = await this.signAndBroadcast(txRequest);
return this.request(
"POST",
"/sdk/crypto-payout/process/confirm",
{
wallet: this.wallet.address,
txHash,
recipient,
amount,
reference
}
);
}
/**
* Process batch payouts
*/
async processPayoutsBatch(payouts) {
const total = payouts.reduce((sum, p) => sum + parseFloat(p.amount), 0);
await this.preflight(total.toString());
const txRequest = await this.request(
"POST",
"/sdk/crypto-payout/batch/prepare",
{
wallet: this.wallet.address,
payouts: payouts.map((p) => ({
recipient: p.recipient,
amount: p.amount,
reference: p.reference || ""
}))
}
);
const txHash = await this.signAndBroadcast(txRequest);
return this.request(
"POST",
"/sdk/crypto-payout/batch/confirm",
{
wallet: this.wallet.address,
txHash,
payouts
}
);
}
/**
* Estimate gas for payout
*/
async estimateGas(recipient, amount) {
return this.request(
"POST",
"/sdk/crypto-payout/estimate-gas",
{ wallet: this.wallet.address, recipient, amount }
);
}
/**
* Get wallet address
*/
getAddress() {
return this.wallet.address;
}
/**
* Get network
*/
getNetwork() {
return this.network;
}
// Private methods
async request(method, path, body) {
const url = `${this.sdk.getServerUrl()}${path}`;
const headers = {
"Content-Type": "application/json",
"x-auth": this.sdk.getApiKey(),
"X-Network": this.network
};
const options = {
method,
headers
};
if (body && method !== "GET") {
options.body = JSON.stringify(body);
}
const response = await fetch(url, options);
const json = await response.json();
if (!response.ok || json.success === false) {
throw new Error(json.error || json.message || "Request failed");
}
return json.data !== void 0 ? json.data : json;
}
async signAndBroadcast(txRequest) {
const tx = {
to: txRequest.to,
data: txRequest.data,
value: txRequest.value,
gasLimit: txRequest.gasLimit,
chainId: txRequest.chainId,
nonce: txRequest.nonce,
type: 2,
maxFeePerGas: txRequest.maxFeePerGas,
maxPriorityFeePerGas: txRequest.maxPriorityFeePerGas
};
const signedTx = await this.wallet.signTransaction(tx);
const result = await this.request(
"POST",
"/sdk/crypto-payout/broadcast",
{ signedTransaction: signedTx }
);
return result.txHash;
}
async preflight(amount) {
const balance = await this.getBalanceInfo();
if (parseFloat(balance.usdtBalance) < parseFloat(amount)) {
throw new Error(
`Insufficient USDT balance. Have: ${balance.usdtBalance}, Need: ${amount}`
);
}
if (parseFloat(balance.allowance) < parseFloat(amount)) {
throw new Error(
`Insufficient allowance. Have: ${balance.allowance}, Need: ${amount}. Call approve() first.`
);
}
const paused = await this.isPaused();
if (paused) {
throw new Error("PayoutProcessor contract is currently paused");
}
}
};
var PixPayoutModule = class {
constructor(sdk) {
this.sdk = sdk;
}
/**
* Create a PIX payout (send money to recipient in Brazil)
*/
async create(options) {
return this.sdk.request("POST", "/sdk/pix-payout/create", {
amount: options.amount,
pixKey: options.pixKey,
pixKeyType: options.pixKeyType,
recipient: options.recipient,
reference: options.reference
});
}
/**
* Get payout by ID
*/
async get(payoutId) {
return this.sdk.request("GET", `/sdk/pix-payout/${payoutId}`);
}
/**
* Get payout status
*/
async getStatus(payoutId) {
return this.sdk.request("GET", `/sdk/pix-payout/status/${payoutId}`);
}
/**
* List payouts with pagination
*/
async list(options) {
const params = new URLSearchParams();
if (options?.status) params.append("status", options.status);
if (options?.skip !== void 0) params.append("skip", options.skip.toString());
if (options?.limit !== void 0) params.append("limit", options.limit.toString());
const query = params.toString();
return this.sdk.request("GET", `/sdk/pix-payout/list${query ? `?${query}` : ""}`);
}
/**
* Get StarsPay account balance
*/
async getBalance() {
return this.sdk.request("GET", "/sdk/pix-payout/balance");
}
/**
* Validate a CPF document
*/
async validateCPF(cpf) {
return this.sdk.request("POST", "/sdk/pix-payout/validate-cpf", { cpf });
}
};
var FiatCryptoPayoutModule = class {
constructor(sdk) {
this.sdk = sdk;
const apiKey = sdk.getApiKey();
this.network = apiKey.includes("_test_") ? "sepolia" : "mainnet";
}
/**
* Get supported fiat currencies
*/
async getSupportedCurrencies() {
return this.request("GET", "/sdk/fiat-crypto-payout/supported-currencies");
}
/**
* Get current exchange rate
*/
async getExchangeRate(fiatCurrency = "USD", cryptoToken = "USDT") {
return this.request(
"GET",
`/sdk/fiat-crypto-payout/rate?fiatCurrency=${fiatCurrency}&cryptoToken=${cryptoToken}`
);
}
/**
* Get a quote for fiat-to-crypto payout (preview before creating)
*/
async getQuote(options) {
return this.request("POST", "/sdk/fiat-crypto-payout/quote", {
wallet: options.wallet,
fiatAmount: options.fiatAmount,
fiatCurrency: options.fiatCurrency || "USD",
cryptoToken: options.cryptoToken || "USDT"
});
}
/**
* Create a fiat-to-crypto payout
* Step 1: Creates payout record and locks in exchange rate
*/
async create(options) {
return this.request("POST", "/sdk/fiat-crypto-payout/create", {
wallet: options.wallet,
recipient: options.recipient,
fiatAmount: options.fiatAmount,
fiatCurrency: options.fiatCurrency || "USD",
cryptoToken: options.cryptoToken || "USDT",
reference: options.reference,
metadata: options.metadata
});
}
/**
* Prepare payout transaction for signing
* Step 2: Gets transaction data after payout is created
*/
async prepare(payoutId, wallet) {
return this.request("POST", `/sdk/fiat-crypto-payout/${payoutId}/prepare`, { wallet });
}
/**
* Confirm payout after transaction is broadcasted
* Step 3: Confirms the payout with transaction hash
*/
async confirm(payoutId, txHash) {
return this.request("POST", `/sdk/fiat-crypto-payout/${payoutId}/confirm`, { txHash });
}
/**
* Get payout by ID
*/
async get(payoutId) {
return this.request("GET", `/sdk/fiat-crypto-payout/${payoutId}`);
}
/**
* List payouts with pagination
*/
async list(options) {
const params = new URLSearchParams();
if (options?.page) params.append("page", options.page.toString());
if (options?.limit) params.append("limit", options.limit.toString());
if (options?.status) params.append("status", options.status);
if (options?.fiatCurrency) params.append("fiatCurrency", options.fiatCurrency);
if (options?.wallet) params.append("wallet", options.wallet);
if (options?.startDate) params.append("startDate", options.startDate);
if (options?.endDate) params.append("endDate", options.endDate);
const query = params.toString();
return this.request("GET", `/sdk/fiat-crypto-payout/list${query ? `?${query}` : ""}`);
}
/**
* Cancel a pending payout
*/
async cancel(payoutId) {
return this.request("POST", `/sdk/fiat-crypto-payout/${payoutId}/cancel`);
}
/**
* Get current network
*/
getNetwork() {
return this.network;
}
// Private request method with network header
async request(method, path, body) {
const url = `${this.sdk.getServerUrl()}${path}`;
const headers = {
"Content-Type": "application/json",
"x-auth": this.sdk.getApiKey(),
"X-Network": this.network
};
const options = {
method,
headers
};
if (body && method !== "GET") {
options.body = JSON.stringify(body);
}
const response = await fetch(url, options);
const json = await response.json();
if (!response.ok || json.success === false) {
throw new Error(json.error || json.message || "Request failed");
}
return json.data !== void 0 ? json.data : json;
}
};
function createBanksySDK(config) {
return new BanksySDK(config);
}
var index_default = BanksySDK;
export {
BanksySDK,
CryptoPayoutModule,
FiatCryptoPayoutModule,
PixPayoutModule,
createBanksySDK,
index_default as default
};