@profullstack/coinpay 0.6.11 → 0.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profullstack/coinpay",
3
- "version": "0.6.11",
3
+ "version": "0.8.0",
4
4
  "description": "CoinPay SDK & CLI — Accept cryptocurrency payments (BTC, ETH, SOL, POL, BCH, USDC) with wallet and swap support",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -17,6 +17,10 @@
17
17
  "import": "./src/payments.js",
18
18
  "types": "./src/payments.d.ts"
19
19
  },
20
+ "./tokens": {
21
+ "import": "./src/tokens.js",
22
+ "types": "./src/tokens.d.ts"
23
+ },
20
24
  "./card-payments": {
21
25
  "import": "./src/card-payments.js",
22
26
  "types": "./src/card-payments.d.ts"
@@ -32,6 +36,18 @@
32
36
  "./swap": {
33
37
  "import": "./src/swap.js",
34
38
  "types": "./src/swap.d.ts"
39
+ },
40
+ "./x402": {
41
+ "import": "./src/x402.js"
42
+ },
43
+ "./x402-v2": {
44
+ "import": "./src/x402-v2.js"
45
+ },
46
+ "./x402-browser": {
47
+ "import": "./src/x402-browser.js"
48
+ },
49
+ "./x402-pay-server": {
50
+ "import": "./src/x402-pay-server.js"
35
51
  }
36
52
  },
37
53
  "files": [
@@ -87,7 +103,7 @@
87
103
  "node": ">=20.0.0"
88
104
  },
89
105
  "devDependencies": {
90
- "vitest": "^2.1.8",
106
+ "vitest": "^4.1.0",
91
107
  "eslint": "^8.57.0",
92
108
  "prettier": "^3.4.1"
93
109
  },
@@ -96,6 +112,7 @@
96
112
  "@scure/bip39": "^1.4.0",
97
113
  "@scure/bip32": "^1.5.0",
98
114
  "@noble/curves": "^1.6.0",
99
- "@noble/hashes": "^1.5.0"
115
+ "@noble/hashes": "^1.5.0",
116
+ "@inquirer/prompts": "^8.3.0"
100
117
  }
101
118
  }
package/src/auth.js CHANGED
@@ -58,7 +58,8 @@ export async function loginMerchant(client, { email, password }) {
58
58
  * @returns {Promise<Object>} Merchant information
59
59
  */
60
60
  export async function getMe(client) {
61
+ // GET — the /auth/me endpoint is GET-only (a POST returns 405).
61
62
  return client.request('/auth/me', {
62
- method: 'POST',
63
+ method: 'GET',
63
64
  });
64
65
  }
package/src/client.d.ts CHANGED
@@ -41,6 +41,14 @@ export interface ListPaymentsParams {
41
41
  offset?: number;
42
42
  }
43
43
 
44
+ /** Parameters for supported coin/token discovery */
45
+ export interface SupportedCoinsParams {
46
+ /** Business ID. Required for merchant JWTs; optional with business API keys if it matches key scope. */
47
+ businessId?: string;
48
+ /** If true, only active wallets are returned. */
49
+ activeOnly?: boolean;
50
+ }
51
+
44
52
  /** Options for the `waitForPayment` polling method */
45
53
  export interface WaitForPaymentOptions {
46
54
  /** Polling interval in milliseconds (default: `5000`) */
@@ -109,6 +117,36 @@ export interface ListPaymentsResponse {
109
117
  payments: Payment[];
110
118
  }
111
119
 
120
+ /** Supported payment coin record */
121
+ export interface SupportedCoin {
122
+ symbol: string;
123
+ name: string;
124
+ is_active: boolean;
125
+ has_wallet: boolean;
126
+ wallet_source: 'business' | 'merchant_global';
127
+ }
128
+
129
+ /** Checkout token record with lower-case code accepted by createPayment currency */
130
+ export interface SupportedToken extends SupportedCoin {
131
+ code: string;
132
+ ticker: string;
133
+ chain?: string;
134
+ }
135
+
136
+ /** Response from supported coin discovery */
137
+ export interface SupportedCoinsResponse {
138
+ success: boolean;
139
+ coins: SupportedCoin[];
140
+ business_id: string;
141
+ merchant_id?: string;
142
+ total: number;
143
+ }
144
+
145
+ /** Response from token discovery */
146
+ export interface TokensResponse extends SupportedCoinsResponse {
147
+ tokens: SupportedToken[];
148
+ }
149
+
112
150
  /**
113
151
  * CoinPay API Client
114
152
  *
@@ -186,6 +224,20 @@ export class CoinPayClient {
186
224
  */
187
225
  listPayments(params: ListPaymentsParams): Promise<ListPaymentsResponse>;
188
226
 
227
+ /**
228
+ * List supported payment coins for a business.
229
+ *
230
+ * Business wallets win; merchant global wallets are used as fallback.
231
+ */
232
+ getSupportedCoins(params?: SupportedCoinsParams): Promise<SupportedCoinsResponse>;
233
+
234
+ /**
235
+ * List checkout-friendly tokens for a business.
236
+ *
237
+ * Returns lower-case `code` values accepted by `createPayment({ currency })`.
238
+ */
239
+ getTokens(params?: SupportedCoinsParams): Promise<TokensResponse>;
240
+
189
241
  /**
190
242
  * Get a URL pointing to the QR code image for a payment.
191
243
  *
package/src/client.js CHANGED
@@ -279,6 +279,45 @@ export class CoinPayClient {
279
279
  return this.request(`/payments?${params.toString()}`);
280
280
  }
281
281
 
282
+ /**
283
+ * Get supported payment coins for a business.
284
+ *
285
+ * Business API keys derive the business from the key. Passing businessId is
286
+ * still allowed and must match the key scope. Merchant JWTs require
287
+ * businessId.
288
+ *
289
+ * @param {Object} [params]
290
+ * @param {string} [params.businessId] - Business ID
291
+ * @param {boolean} [params.activeOnly] - Only return active wallets
292
+ * @returns {Promise<Object>} Supported coins response
293
+ */
294
+ async getSupportedCoins({ businessId, activeOnly } = {}) {
295
+ const params = new URLSearchParams();
296
+ if (businessId) params.set('business_id', businessId);
297
+ if (activeOnly) params.set('active_only', 'true');
298
+ const query = params.toString();
299
+ return this.request(`/supported-coins${query ? `?${query}` : ''}`);
300
+ }
301
+
302
+ /**
303
+ * Get payment-option tokens for a business.
304
+ *
305
+ * Returns lower-case `code` values accepted by /payments/create, plus
306
+ * display fields for checkout coin pickers.
307
+ *
308
+ * @param {Object} [params]
309
+ * @param {string} [params.businessId] - Business ID
310
+ * @param {boolean} [params.activeOnly] - Only return active wallets
311
+ * @returns {Promise<Object>} Tokens response
312
+ */
313
+ async getTokens({ businessId, activeOnly } = {}) {
314
+ const params = new URLSearchParams();
315
+ if (businessId) params.set('business_id', businessId);
316
+ if (activeOnly) params.set('active_only', 'true');
317
+ const query = params.toString();
318
+ return this.request(`/tokens${query ? `?${query}` : ''}`);
319
+ }
320
+
282
321
  /**
283
322
  * Get payment QR code URL
284
323
  *
@@ -685,22 +724,29 @@ export class CoinPayClient {
685
724
 
686
725
  /**
687
726
  * Create Stripe Connect onboarding link
688
- *
727
+ *
689
728
  * Generates a Stripe Express onboarding link for a merchant.
690
729
  * The merchant must complete this onboarding before they can accept card payments.
691
- *
730
+ *
731
+ * Country is required on the first onboarding call and is locked at Stripe
732
+ * account creation — it cannot be changed afterward. Subsequent calls (e.g.
733
+ * to finish remaining requirements) may omit it; the server reuses the
734
+ * country stored on the business. All Stripe Connect supported countries are
735
+ * accepted (US, CA, GB, AU, DE, FR, JP, SG, ...). See
736
+ * https://stripe.com/global for the full list.
737
+ *
692
738
  * @param {string} businessId - Business ID
693
739
  * @param {Object} [params] - Optional parameters
694
740
  * @param {string} [params.email] - Merchant email (pre-fills onboarding form)
695
- * @param {string} [params.country='US'] - Country code (US, CA, GB, etc.)
741
+ * @param {string} [params.country] - ISO-3166-1 alpha-2 country code (e.g. 'US', 'CA', 'GB'). Required on first onboarding.
696
742
  * @returns {Promise<Object>} Onboarding link and account ID
697
- *
743
+ *
698
744
  * @example
699
745
  * const onboarding = await client.createStripeOnboardingLink('business-id', {
700
746
  * email: 'merchant@example.com',
701
- * country: 'US'
747
+ * country: 'CA'
702
748
  * });
703
- *
749
+ *
704
750
  * // Redirect merchant to onboarding.onboarding_url
705
751
  */
706
752
  async createStripeOnboardingLink(businessId, params = {}) {
@@ -913,4 +959,4 @@ export class CoinPayClient {
913
959
  }
914
960
  }
915
961
 
916
- export default CoinPayClient;
962
+ export default CoinPayClient;
package/src/index.d.ts CHANGED
@@ -12,9 +12,22 @@ export type {
12
12
  PaymentParams,
13
13
  ListPaymentsParams,
14
14
  WaitForPaymentOptions,
15
- CreateBusinessParams
15
+ CreateBusinessParams,
16
+ SupportedCoinsParams,
17
+ SupportedCoin,
18
+ SupportedToken,
19
+ SupportedCoinsResponse,
20
+ TokensResponse,
16
21
  } from './client.js';
17
22
 
23
+ export {
24
+ getTokens,
25
+ getSupportedCoins,
26
+ } from './tokens.js';
27
+ export type {
28
+ TokenDiscoveryParams,
29
+ } from './tokens.js';
30
+
18
31
  // Payment exports
19
32
  export {
20
33
  createPayment,
@@ -31,6 +44,26 @@ export type {
31
44
  ListPaymentsFnParams
32
45
  } from './payments.js';
33
46
 
47
+ // Invoice exports
48
+ export {
49
+ createInvoice,
50
+ getInvoice,
51
+ listInvoices,
52
+ updateInvoice,
53
+ deleteInvoice,
54
+ sendInvoice,
55
+ getInvoicePaymentData,
56
+ InvoiceStatus,
57
+ } from './invoices.js';
58
+ export type {
59
+ Invoice,
60
+ InvoiceStatusType,
61
+ CreateInvoiceParams,
62
+ ListInvoicesParams,
63
+ UpdateInvoiceParams,
64
+ ListInvoicesResult,
65
+ } from './invoices.js';
66
+
34
67
  // Webhook exports
35
68
  export {
36
69
  verifyWebhookSignature,
package/src/index.js CHANGED
@@ -46,6 +46,11 @@ import {
46
46
  PaymentStatus,
47
47
  FiatCurrency,
48
48
  } from './payments.js';
49
+ import {
50
+ getTokens,
51
+ getSupportedCoins,
52
+ getSupportedCoins as getSupportedPaymentCoins,
53
+ } from './tokens.js';
49
54
  import {
50
55
  verifyWebhookSignature,
51
56
  generateWebhookSignature,
@@ -66,6 +71,18 @@ import {
66
71
  authenticateEscrow,
67
72
  } from './escrow.js';
68
73
 
74
+ // Invoice exports
75
+ import {
76
+ createInvoice,
77
+ getInvoice,
78
+ listInvoices,
79
+ updateInvoice,
80
+ deleteInvoice,
81
+ sendInvoice,
82
+ getInvoicePaymentData,
83
+ InvoiceStatus,
84
+ } from './invoices.js';
85
+
69
86
  // Wallet exports
70
87
  import {
71
88
  WalletClient,
@@ -156,6 +173,7 @@ import {
156
173
  verifyX402Payment,
157
174
  settleX402Payment,
158
175
  buildPaymentRequired,
176
+ expectedForProof,
159
177
  convertUsdToAssetAmount,
160
178
  PAYMENT_METHODS,
161
179
  USDC_CONTRACTS,
@@ -170,6 +188,9 @@ export {
170
188
  createPayment,
171
189
  getPayment,
172
190
  listPayments,
191
+ getTokens,
192
+ getSupportedCoins,
193
+ getSupportedPaymentCoins,
173
194
 
174
195
  // Escrow functions
175
196
  createEscrow,
@@ -182,6 +203,16 @@ export {
182
203
  waitForEscrow,
183
204
  authenticateEscrow,
184
205
 
206
+ // Invoice functions
207
+ createInvoice,
208
+ getInvoice,
209
+ listInvoices,
210
+ updateInvoice,
211
+ deleteInvoice,
212
+ sendInvoice,
213
+ getInvoicePaymentData,
214
+ InvoiceStatus,
215
+
185
216
  // Wallet
186
217
  WalletClient,
187
218
  WalletChain,
@@ -263,6 +294,7 @@ export {
263
294
  verifyX402Payment,
264
295
  settleX402Payment,
265
296
  buildPaymentRequired,
297
+ expectedForProof,
266
298
  convertUsdToAssetAmount,
267
299
  PAYMENT_METHODS,
268
300
  USDC_CONTRACTS,
@@ -0,0 +1,77 @@
1
+ import type { CoinPayClient } from './client.js';
2
+
3
+ export const InvoiceStatus: {
4
+ readonly DRAFT: 'draft';
5
+ readonly SENT: 'sent';
6
+ readonly PAID: 'paid';
7
+ readonly OVERDUE: 'overdue';
8
+ readonly CANCELLED: 'cancelled';
9
+ };
10
+
11
+ export type InvoiceStatusType = (typeof InvoiceStatus)[keyof typeof InvoiceStatus];
12
+
13
+ export interface Invoice {
14
+ id: string;
15
+ invoiceNumber?: string;
16
+ businessId?: string;
17
+ clientId?: string;
18
+ currency?: string;
19
+ amount?: number;
20
+ cryptoCurrency?: string;
21
+ cryptoAmount?: string | number;
22
+ status?: InvoiceStatusType;
23
+ dueDate?: string;
24
+ notes?: string;
25
+ walletId?: string;
26
+ merchantWalletAddress?: string;
27
+ paymentAddress?: string;
28
+ stripeCheckoutUrl?: string;
29
+ paidAt?: string;
30
+ sentAt?: string;
31
+ createdAt?: string;
32
+ updatedAt?: string;
33
+ }
34
+
35
+ export interface CreateInvoiceParams {
36
+ businessId?: string;
37
+ clientId?: string;
38
+ currency: string;
39
+ amount: number;
40
+ cryptoCurrency?: string;
41
+ dueDate?: string;
42
+ notes?: string;
43
+ walletId?: string;
44
+ merchantWalletAddress?: string;
45
+ }
46
+
47
+ export interface ListInvoicesParams {
48
+ businessId?: string;
49
+ status?: InvoiceStatusType;
50
+ clientId?: string;
51
+ dateFrom?: string;
52
+ dateTo?: string;
53
+ }
54
+
55
+ export interface UpdateInvoiceParams {
56
+ amount?: number;
57
+ currency?: string;
58
+ cryptoCurrency?: string;
59
+ dueDate?: string;
60
+ notes?: string;
61
+ clientId?: string;
62
+ walletId?: string;
63
+ merchantWalletAddress?: string;
64
+ }
65
+
66
+ export interface ListInvoicesResult {
67
+ invoices: Invoice[];
68
+ total?: number;
69
+ }
70
+
71
+ export function createInvoice(client: CoinPayClient, options: CreateInvoiceParams): Promise<Invoice>;
72
+ export function listInvoices(client: CoinPayClient, filters?: ListInvoicesParams): Promise<ListInvoicesResult>;
73
+ export function getInvoice(client: CoinPayClient, id: string): Promise<Invoice>;
74
+ export function updateInvoice(client: CoinPayClient, id: string, updates: UpdateInvoiceParams): Promise<Invoice>;
75
+ export function deleteInvoice(client: CoinPayClient, id: string): Promise<Record<string, unknown>>;
76
+ export function sendInvoice(client: CoinPayClient, id: string): Promise<Record<string, unknown>>;
77
+ export function getInvoicePaymentData(client: CoinPayClient, id: string): Promise<Record<string, unknown>>;
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Invoice SDK Module
3
+ *
4
+ * Create, manage, and send invoices with crypto + card payment support.
5
+ * Invoices can be sent to clients who pay via generated crypto addresses
6
+ * or optional Stripe checkout.
7
+ *
8
+ * @example
9
+ * import { CoinPayClient } from '@profullstack/coinpay';
10
+ * import { createInvoice, sendInvoice, getInvoicePaymentData } from '@profullstack/coinpay';
11
+ *
12
+ * const client = new CoinPayClient({ apiKey: 'your-key' });
13
+ *
14
+ * // Create an invoice
15
+ * const invoice = await createInvoice(client, {
16
+ * businessId: 'biz_123',
17
+ * currency: 'USD',
18
+ * amount: 250.00,
19
+ * cryptoCurrency: 'ETH',
20
+ * dueDate: '2026-04-01',
21
+ * notes: 'Web development - March 2026',
22
+ * });
23
+ *
24
+ * // Send it to the client
25
+ * const sent = await sendInvoice(client, invoice.id);
26
+ *
27
+ * // Public: get payment data (no auth)
28
+ * const paymentData = await getInvoicePaymentData(client, invoice.id);
29
+ */
30
+
31
+ /**
32
+ * Create a new invoice
33
+ * @param {CoinPayClient} client - API client instance
34
+ * @param {Object} options - Invoice parameters
35
+ * @param {string} [options.businessId] - Business ID (optional for business-scoped API keys)
36
+ * @param {string} [options.clientId] - Client ID (optional)
37
+ * @param {string} options.currency - Fiat currency code (USD, EUR, etc.)
38
+ * @param {number} options.amount - Invoice amount
39
+ * @param {string} [options.cryptoCurrency] - Preferred crypto for payment
40
+ * @param {string} [options.dueDate] - Due date (ISO string or YYYY-MM-DD)
41
+ * @param {string} [options.notes] - Notes / description
42
+ * @param {string} [options.walletId] - Wallet ID for receiving payment
43
+ * @param {string} [options.merchantWalletAddress] - Direct wallet address for receiving payment
44
+ * @returns {Promise<Object>} Created invoice
45
+ */
46
+ export async function createInvoice(client, {
47
+ businessId,
48
+ clientId,
49
+ currency,
50
+ amount,
51
+ cryptoCurrency,
52
+ dueDate,
53
+ notes,
54
+ walletId,
55
+ merchantWalletAddress,
56
+ }) {
57
+ const body = {
58
+ business_id: businessId,
59
+ currency,
60
+ amount,
61
+ };
62
+ if (clientId) body.client_id = clientId;
63
+ if (cryptoCurrency) body.crypto_currency = cryptoCurrency;
64
+ if (dueDate) body.due_date = dueDate;
65
+ if (notes) body.notes = notes;
66
+ if (walletId) body.wallet_id = walletId;
67
+ if (merchantWalletAddress) body.merchant_wallet_address = merchantWalletAddress;
68
+
69
+ const data = await client.request('/invoices', {
70
+ method: 'POST',
71
+ body: JSON.stringify(body),
72
+ });
73
+
74
+ return normalizeInvoice(data);
75
+ }
76
+
77
+ /**
78
+ * List invoices with optional filters
79
+ * @param {CoinPayClient} client
80
+ * @param {Object} [filters]
81
+ * @param {string} [filters.businessId] - Filter by business ID
82
+ * @param {string} [filters.status] - Filter by status (draft, sent, paid, overdue, cancelled)
83
+ * @param {string} [filters.clientId] - Filter by client ID
84
+ * @param {string} [filters.dateFrom] - Filter from date (ISO string)
85
+ * @param {string} [filters.dateTo] - Filter to date (ISO string)
86
+ * @returns {Promise<Object>} { invoices, total?, ... }
87
+ */
88
+ export async function listInvoices(client, filters = {}) {
89
+ const params = new URLSearchParams();
90
+ if (filters.businessId) params.set('business_id', filters.businessId);
91
+ if (filters.status) params.set('status', filters.status);
92
+ if (filters.clientId) params.set('client_id', filters.clientId);
93
+ if (filters.dateFrom) params.set('date_from', filters.dateFrom);
94
+ if (filters.dateTo) params.set('date_to', filters.dateTo);
95
+
96
+ const query = params.toString();
97
+ const endpoint = query ? `/invoices?${query}` : '/invoices';
98
+ const data = await client.request(endpoint);
99
+
100
+ // Handle both array and paginated responses
101
+ if (Array.isArray(data)) {
102
+ return { invoices: data.map(normalizeInvoice) };
103
+ }
104
+
105
+ return {
106
+ invoices: (data.invoices || []).map(normalizeInvoice),
107
+ total: data.total,
108
+ };
109
+ }
110
+
111
+ /**
112
+ * Get a single invoice by ID
113
+ * @param {CoinPayClient} client
114
+ * @param {string} id - Invoice ID
115
+ * @returns {Promise<Object>} Invoice details
116
+ */
117
+ export async function getInvoice(client, id) {
118
+ const data = await client.request(`/invoices/${encodeURIComponent(id)}`);
119
+ return normalizeInvoice(data);
120
+ }
121
+
122
+ /**
123
+ * Update an invoice
124
+ * @param {CoinPayClient} client
125
+ * @param {string} id - Invoice ID
126
+ * @param {Object} updates - Partial invoice fields to update
127
+ * @param {number} [updates.amount] - Updated amount
128
+ * @param {string} [updates.currency] - Updated currency
129
+ * @param {string} [updates.cryptoCurrency] - Updated crypto currency
130
+ * @param {string} [updates.dueDate] - Updated due date
131
+ * @param {string} [updates.notes] - Updated notes
132
+ * @param {string} [updates.clientId] - Updated client ID
133
+ * @param {string} [updates.walletId] - Updated wallet ID
134
+ * @param {string} [updates.merchantWalletAddress] - Updated wallet address
135
+ * @returns {Promise<Object>} Updated invoice
136
+ */
137
+ export async function updateInvoice(client, id, updates) {
138
+ const body = {};
139
+ if (updates.amount !== undefined) body.amount = updates.amount;
140
+ if (updates.currency !== undefined) body.currency = updates.currency;
141
+ if (updates.cryptoCurrency !== undefined) body.crypto_currency = updates.cryptoCurrency;
142
+ if (updates.dueDate !== undefined) body.due_date = updates.dueDate;
143
+ if (updates.notes !== undefined) body.notes = updates.notes;
144
+ if (updates.clientId !== undefined) body.client_id = updates.clientId;
145
+ if (updates.walletId !== undefined) body.wallet_id = updates.walletId;
146
+ if (updates.merchantWalletAddress !== undefined) body.merchant_wallet_address = updates.merchantWalletAddress;
147
+
148
+ const data = await client.request(`/invoices/${encodeURIComponent(id)}`, {
149
+ method: 'PUT',
150
+ body: JSON.stringify(body),
151
+ });
152
+
153
+ return normalizeInvoice(data);
154
+ }
155
+
156
+ /**
157
+ * Delete a draft invoice
158
+ * @param {CoinPayClient} client
159
+ * @param {string} id - Invoice ID (must be in draft status)
160
+ * @returns {Promise<Object>} Deletion confirmation
161
+ */
162
+ export async function deleteInvoice(client, id) {
163
+ return client.request(`/invoices/${encodeURIComponent(id)}`, {
164
+ method: 'DELETE',
165
+ });
166
+ }
167
+
168
+ /**
169
+ * Send an invoice to the client
170
+ * Generates a payment address and optional Stripe checkout link.
171
+ * @param {CoinPayClient} client
172
+ * @param {string} id - Invoice ID
173
+ * @returns {Promise<Object>} Send result with payment details
174
+ */
175
+ export async function sendInvoice(client, id) {
176
+ const data = await client.request(`/invoices/${encodeURIComponent(id)}/send`, {
177
+ method: 'POST',
178
+ });
179
+ return data;
180
+ }
181
+
182
+ /**
183
+ * Get invoice payment data (public, no auth required)
184
+ * Used by clients/customers to view payment instructions.
185
+ * @param {CoinPayClient} client
186
+ * @param {string} id - Invoice ID
187
+ * @returns {Promise<Object>} Payment data (address, amount, status, etc.)
188
+ */
189
+ export async function getInvoicePaymentData(client, id) {
190
+ const data = await client.requestUnauthenticated(`/invoices/${encodeURIComponent(id)}/pay`);
191
+ return data;
192
+ }
193
+
194
+ // ── Constants ──
195
+
196
+ /**
197
+ * Invoice status constants
198
+ */
199
+ export const InvoiceStatus = {
200
+ DRAFT: 'draft',
201
+ SENT: 'sent',
202
+ PAID: 'paid',
203
+ OVERDUE: 'overdue',
204
+ CANCELLED: 'cancelled',
205
+ };
206
+
207
+ // ── Helpers ──
208
+
209
+ function normalizeInvoice(data) {
210
+ if (!data) return data;
211
+
212
+ // Single-invoice API responses are wrapped, while older SDK callers and
213
+ // tests may still supply the invoice object directly.
214
+ const invoice = data.invoice ?? data;
215
+
216
+ return {
217
+ id: invoice.id,
218
+ invoiceNumber: invoice.invoice_number,
219
+ businessId: invoice.business_id,
220
+ clientId: invoice.client_id,
221
+ currency: invoice.currency,
222
+ amount: invoice.amount,
223
+ cryptoCurrency: invoice.crypto_currency,
224
+ cryptoAmount: invoice.crypto_amount,
225
+ status: invoice.status,
226
+ dueDate: invoice.due_date,
227
+ notes: invoice.notes,
228
+ walletId: invoice.wallet_id,
229
+ merchantWalletAddress: invoice.merchant_wallet_address,
230
+ paymentAddress: invoice.payment_address,
231
+ stripeCheckoutUrl: invoice.stripe_checkout_url,
232
+ paidAt: invoice.paid_at,
233
+ sentAt: invoice.sent_at,
234
+ createdAt: invoice.created_at,
235
+ updatedAt: invoice.updated_at,
236
+ };
237
+ }
@@ -0,0 +1,14 @@
1
+ import { CoinPayClient, SupportedCoinsParams, SupportedCoinsResponse, TokensResponse } from './client.js';
2
+
3
+ export interface TokenDiscoveryParams extends SupportedCoinsParams {
4
+ /** API key — required if `client` is not provided */
5
+ apiKey?: string;
6
+ /** Existing CoinPayClient instance */
7
+ client?: CoinPayClient;
8
+ }
9
+
10
+ /** List checkout-friendly tokens for a business. */
11
+ export function getTokens(params?: TokenDiscoveryParams): Promise<TokensResponse>;
12
+
13
+ /** List supported payment coins for a business. */
14
+ export function getSupportedCoins(params?: TokenDiscoveryParams): Promise<SupportedCoinsResponse>;