@profullstack/coinpay 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/bin/coinpay.js +3 -0
- package/package.json +1 -1
- package/src/client.d.ts +4 -0
- package/src/client.js +8 -1
- package/src/finances-commands.js +25 -1
- package/src/finances-reports.js +10 -0
- package/src/payments.d.ts +4 -0
- package/src/payments.js +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ All notable changes to `@profullstack/coinpay` will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.23.0] - 2026-10-21
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `createPayment({ successUrl, cancelUrl })`, like Stripe Checkout: once the payment confirms, the
|
|
12
|
+
hosted pay page sends the customer to `successUrl` (`{PAYMENT_ID}` is replaced with the payment id);
|
|
13
|
+
`cancelUrl` is the "Back to merchant" link from an expired checkout. Before this the crypto checkout
|
|
14
|
+
had no way to return the buyer and left them on "Payment Complete!".
|
|
15
|
+
|
|
8
16
|
## [0.22.0] - 2026-10-19
|
|
9
17
|
|
|
10
18
|
### Added
|
package/bin/coinpay.js
CHANGED
|
@@ -710,6 +710,9 @@ ${colors.cyan}Commands:${colors.reset}
|
|
|
710
710
|
books summary Totals by tax category (--period 2026|2026-Q3|2026-08, --scope)
|
|
711
711
|
books export CPA pack (--period, --scope, --format csv|pdf|html|json, --output;
|
|
712
712
|
--with-documents: a ZIP with the period's tax documents, up to 8 MiB)
|
|
713
|
+
pnl Profit and loss, personal and business as separate files
|
|
714
|
+
(--scope personal|business, --months 3 (default: last 3
|
|
715
|
+
complete months) or --from/--to, --name "Holder", --format pdf|html|csv|json)
|
|
713
716
|
payloads [list|download <id>] Raw provider responses, exactly as received
|
|
714
717
|
reports send <id> Email a report (--to a@x,b@y, --format pdf,csv, --message, --no-attach)
|
|
715
718
|
books send Email the CPA pack (--to, --period, --scope, --format,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@profullstack/coinpay",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "CoinPay SDK & CLI \u2014 Accept cryptocurrency and card payments (BTC, ETH, SOL, POL, BCH, USDC) with wallet, swap and a live finances dashboard",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
package/src/client.d.ts
CHANGED
|
@@ -27,6 +27,10 @@ export interface PaymentParams {
|
|
|
27
27
|
description?: string;
|
|
28
28
|
/** Custom metadata attached to the payment (e.g., `{ orderId: 'ORD-123' }`) */
|
|
29
29
|
metadata?: Record<string, unknown>;
|
|
30
|
+
/** Where the pay page sends the customer once the payment confirms, like Stripe's `success_url`. `{PAYMENT_ID}` is replaced with the payment id. */
|
|
31
|
+
successUrl?: string;
|
|
32
|
+
/** Where "Back to merchant" goes from an expired or abandoned checkout */
|
|
33
|
+
cancelUrl?: string;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
/** Parameters for listing payments */
|
package/src/client.js
CHANGED
|
@@ -228,6 +228,8 @@ export class CoinPayClient {
|
|
|
228
228
|
* @param {string} params.blockchain - Blockchain/cryptocurrency (BTC, ETH, SOL, POL, BCH, USDC_ETH, USDC_POL, USDC_SOL)
|
|
229
229
|
* @param {string} [params.description] - Payment description (shown to customer)
|
|
230
230
|
* @param {Object} [params.metadata] - Custom metadata (e.g., { orderId: 'ORD-123', customerId: 'CUST-456' })
|
|
231
|
+
* @param {string} [params.successUrl] - Where the pay page sends the customer once the payment confirms, like Stripe's success_url. {PAYMENT_ID} is replaced with the payment id.
|
|
232
|
+
* @param {string} [params.cancelUrl] - Where "Back to merchant" goes from an expired or abandoned checkout
|
|
231
233
|
* @returns {Promise<Object>} Created payment with address and QR code
|
|
232
234
|
*
|
|
233
235
|
* @example
|
|
@@ -238,7 +240,8 @@ export class CoinPayClient {
|
|
|
238
240
|
* currency: 'USD',
|
|
239
241
|
* blockchain: 'BTC',
|
|
240
242
|
* description: 'Order #12345',
|
|
241
|
-
* metadata: { orderId: '12345', customerEmail: 'customer@example.com' }
|
|
243
|
+
* metadata: { orderId: '12345', customerEmail: 'customer@example.com' },
|
|
244
|
+
* successUrl: 'https://yoursite.com/orders/12345?payment={PAYMENT_ID}',
|
|
242
245
|
* });
|
|
243
246
|
*
|
|
244
247
|
* // Display payment.payment_address and payment.qr_code to customer
|
|
@@ -250,6 +253,8 @@ export class CoinPayClient {
|
|
|
250
253
|
blockchain,
|
|
251
254
|
description,
|
|
252
255
|
metadata,
|
|
256
|
+
successUrl,
|
|
257
|
+
cancelUrl,
|
|
253
258
|
}) {
|
|
254
259
|
// Map to API field names (snake_case)
|
|
255
260
|
return this.request('/payments/create', {
|
|
@@ -261,6 +266,8 @@ export class CoinPayClient {
|
|
|
261
266
|
blockchain: blockchain?.toUpperCase(),
|
|
262
267
|
description,
|
|
263
268
|
metadata,
|
|
269
|
+
success_url: successUrl,
|
|
270
|
+
cancel_url: cancelUrl,
|
|
264
271
|
}),
|
|
265
272
|
});
|
|
266
273
|
}
|
package/src/finances-commands.js
CHANGED
|
@@ -802,6 +802,30 @@ export async function runFinancesCommand(subcommand, args, flags, ctx) {
|
|
|
802
802
|
throw new CliExit(EXIT.INVALID, 'Usage: coinpay finances books [queue|confirm <id>|confirm-all --yes|categorize|rules [add|delete]|summary|export|send]');
|
|
803
803
|
}
|
|
804
804
|
|
|
805
|
+
case 'pnl':
|
|
806
|
+
case 'profit-loss': {
|
|
807
|
+
const scopes = listFlag(flags.scope);
|
|
808
|
+
const wanted = scopes.length ? scopes : ['personal', 'business'];
|
|
809
|
+
for (const s of wanted) if (s !== 'personal' && s !== 'business') throw new CliExit(EXIT.INVALID, `--scope must be personal, business or both (got ${s})`);
|
|
810
|
+
const format = typeof flags.format === 'string' ? flags.format.toLowerCase() : 'pdf';
|
|
811
|
+
if (!['pdf', 'html', 'csv', 'json'].includes(format)) throw new CliExit(EXIT.INVALID, '--format must be pdf, html, csv or json');
|
|
812
|
+
const months = flags.months === undefined ? undefined : Number(flags.months);
|
|
813
|
+
if (months !== undefined && (!Number.isInteger(months) || months < 1 || months > 24)) throw new CliExit(EXIT.INVALID, '--months must be 1 to 24');
|
|
814
|
+
const period = typeof flags.period === 'string' ? flags.period : undefined;
|
|
815
|
+
const from = typeof flags.from === 'string' ? flags.from : undefined;
|
|
816
|
+
const to = typeof flags.to === 'string' ? flags.to : undefined;
|
|
817
|
+
const timezone = typeof flags.timezone === 'string' ? flags.timezone : undefined;
|
|
818
|
+
const name = typeof flags.name === 'string' ? flags.name : undefined;
|
|
819
|
+
const written = [];
|
|
820
|
+
for (const scope of wanted) {
|
|
821
|
+
const file = await api.exportPnl(client, { scope, months, period, from, to, timezone, name, format });
|
|
822
|
+
const output = typeof flags.output === 'string' && wanted.length === 1 ? flags.output : file.filename || `pnl-${scope}.${format}`;
|
|
823
|
+
written.push({ scope, output: writeDownload(output, Buffer.from(file.bytes), { overwrite: flags.overwrite === true }), bytes: file.bytes.length });
|
|
824
|
+
}
|
|
825
|
+
emit({ files: written }, written.map((w) => `Wrote ${w.output} (${w.scope}, ${w.bytes} bytes)`).join('\n'));
|
|
826
|
+
return EXIT.OK;
|
|
827
|
+
}
|
|
828
|
+
|
|
805
829
|
case 'digest': {
|
|
806
830
|
const action = args[0] || 'show';
|
|
807
831
|
const DAY_NAMES = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
|
@@ -966,4 +990,4 @@ export async function runFinancesCommand(subcommand, args, flags, ctx) {
|
|
|
966
990
|
}
|
|
967
991
|
}
|
|
968
992
|
|
|
969
|
-
export const EXTENDED_SUBCOMMANDS = ['connect', 'disconnect', 'consent', 'backfill', 'jobs', 'coverage', 'report', 'reports', 'statements', 'books', 'payloads', 'digest', 'due', 'due-soon', 'recurring', 'due-day', 'daily'];
|
|
993
|
+
export const EXTENDED_SUBCOMMANDS = ['connect', 'disconnect', 'consent', 'backfill', 'jobs', 'coverage', 'report', 'reports', 'statements', 'books', 'pnl', 'profit-loss', 'payloads', 'digest', 'due', 'due-soon', 'recurring', 'due-day', 'daily'];
|
package/src/finances-reports.js
CHANGED
|
@@ -397,6 +397,16 @@ export async function exportBooks(client, { period, from, to, timezone, scope, f
|
|
|
397
397
|
return client.requestBinary(`/finances/books/export${query({ period, from, to, timezone, scope, format, with_documents: withDocuments ? 1 : undefined })}`);
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
+
// ── Profit and loss ──
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Profit and loss statement for one scope. With no period it covers the
|
|
404
|
+
* last `months` complete calendar months (server default 3).
|
|
405
|
+
*/
|
|
406
|
+
export async function exportPnl(client, { scope, months, period, from, to, timezone, name, format = 'pdf' } = {}) {
|
|
407
|
+
return client.requestBinary(`/finances/pnl${query({ scope, months, period, from, to, timezone, name, format })}`);
|
|
408
|
+
}
|
|
409
|
+
|
|
400
410
|
// ── Raw provider payloads ──
|
|
401
411
|
|
|
402
412
|
export async function listFinancePayloads(client, { connectionId, limit, offset } = {}) {
|
package/src/payments.d.ts
CHANGED
|
@@ -25,6 +25,10 @@ export interface CreatePaymentParams {
|
|
|
25
25
|
description?: string;
|
|
26
26
|
/** Custom metadata for your records */
|
|
27
27
|
metadata?: Record<string, unknown>;
|
|
28
|
+
/** Where the pay page sends the customer once the payment confirms, like Stripe's `success_url`. `{PAYMENT_ID}` is replaced with the payment id. */
|
|
29
|
+
successUrl?: string;
|
|
30
|
+
/** Where "Back to merchant" goes from an expired or abandoned checkout */
|
|
31
|
+
cancelUrl?: string;
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
/** Parameters for the standalone `getPayment` function */
|
package/src/payments.js
CHANGED
|
@@ -34,6 +34,8 @@ import { CoinPayClient } from './client.js';
|
|
|
34
34
|
* @param {string} params.blockchain - Blockchain to use (BTC, ETH, SOL, POL, BCH, USDC_ETH, USDC_POL, USDC_SOL)
|
|
35
35
|
* @param {string} [params.description] - Payment description shown to customer
|
|
36
36
|
* @param {Object} [params.metadata] - Custom metadata for your records
|
|
37
|
+
* @param {string} [params.successUrl] - Where the pay page sends the customer after the payment confirms ({PAYMENT_ID} is filled in)
|
|
38
|
+
* @param {string} [params.cancelUrl] - Where "Back to merchant" goes from an expired checkout
|
|
37
39
|
* @returns {Promise<Object>} Created payment with address and QR code
|
|
38
40
|
*
|
|
39
41
|
* @example
|
|
@@ -60,6 +62,8 @@ export async function createPayment({
|
|
|
60
62
|
blockchain,
|
|
61
63
|
description,
|
|
62
64
|
metadata,
|
|
65
|
+
successUrl,
|
|
66
|
+
cancelUrl,
|
|
63
67
|
}) {
|
|
64
68
|
const coinpay = client || new CoinPayClient({ apiKey });
|
|
65
69
|
|
|
@@ -70,6 +74,8 @@ export async function createPayment({
|
|
|
70
74
|
blockchain,
|
|
71
75
|
description,
|
|
72
76
|
metadata,
|
|
77
|
+
successUrl,
|
|
78
|
+
cancelUrl,
|
|
73
79
|
});
|
|
74
80
|
}
|
|
75
81
|
|