@peable.to/sdk 0.3.0 → 0.4.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/README.md CHANGED
@@ -22,3 +22,29 @@ The remote outcome may be unknown: recover explicitly with the same durable key.
22
22
  optional second `{ idempotencyKey }` argument, forwarding the existing header.
23
23
  Refund/transfer `externalRef` remains their durable business identity; the option
24
24
  neither replaces it nor changes gateway financial semantics.
25
+
26
+ ### Connect for FairCoin (0.4.0)
27
+
28
+ Pay a marketplace's sellers in FairCoin straight to their own wallets
29
+ (ADR 0012, guide in `docs/connect-faircoin.md`):
30
+
31
+ ```ts
32
+ const seller = await peable.accounts.create({
33
+ externalRef: store.id,
34
+ faircoin: { network: 'testnet', oxyUserId: store.ownerOxyUserId },
35
+ });
36
+ const link = await peable.accountLinks.create({
37
+ account: seller.id, rail: 'faircoin', returnUrl, refreshUrl,
38
+ });
39
+ // the seller registers their key at link.url, signed in with Oxy;
40
+ // you receive connected_account.updated with faircoin.status === 'active'
41
+ const intent = await peable.paymentIntents.create(
42
+ { amount: '250000000', rail: 'faircoin', network: 'testnet', connectedAccount: seller.id },
43
+ { idempotencyKey: `order:${order.id}` },
44
+ );
45
+ ```
46
+
47
+ `peable.accounts` is `peable.connectedAccounts` under its Stripe name. Events for
48
+ an on-behalf payment carry `event.account`; `intent.canExpire` is `false` once a
49
+ payer has broadcast, so never cancel an order on `expiresAt` alone. A seller
50
+ without a registered key is a 409 with `error.code === 'account_not_ready'`.
@@ -94,7 +94,9 @@ function errorFromResponse(status, body) {
94
94
  let upstreamCode;
95
95
  let message = `Peable request failed with status ${status}`;
96
96
  if (isNestedGatewayErrorBody(body)) {
97
- upstreamCode = body.error.type;
97
+ // The specific reason when the gateway names one (`account_not_ready`),
98
+ // else the broad `type` — which is all any error carried before.
99
+ upstreamCode = typeof body.error.code === 'string' ? body.error.code : body.error.type;
98
100
  message = body.error.message;
99
101
  }
100
102
  else if (isFlatGatewayErrorBody(body)) {
package/dist/cjs/index.js CHANGED
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ContributionsResource = exports.WebhooksResource = exports.WEBHOOK_SIGNATURE_HEADER = exports.PeableSignatureVerificationError = exports.PeableApiError = exports.PeablePermissionError = exports.PeableInvalidRequestError = exports.PeableAuthenticationError = exports.PeableError = exports.DEFAULT_OXY_API_URL = exports.DEFAULT_GATEWAY_BASE_URL = exports.Peable = exports.PEABLE_BILLING_AUTHORITY_KEYS = void 0;
3
+ exports.ContributionsResource = exports.WebhooksResource = exports.WEBHOOK_SIGNATURE_HEADER = exports.EXPIRABLE_STATUSES = exports.canExpire = exports.ConnectedAccountsResource = exports.AccountLinksResource = exports.PeableSignatureVerificationError = exports.PeableApiError = exports.PeablePermissionError = exports.PeableInvalidRequestError = exports.PeableAuthenticationError = exports.PeableError = exports.DEFAULT_OXY_API_URL = exports.DEFAULT_GATEWAY_BASE_URL = exports.Peable = exports.PEABLE_BILLING_AUTHORITY_KEYS = exports.TaxResource = void 0;
4
4
  const billing_1 = require("./resources/billing");
5
+ const tax_1 = require("./resources/tax");
6
+ var tax_2 = require("./resources/tax");
7
+ Object.defineProperty(exports, "TaxResource", { enumerable: true, get: function () { return tax_2.TaxResource; } });
5
8
  /** Production Peable's pinned billing-authority public keys, by key id. */
6
9
  var shared_types_1 = require("@peable.to/shared-types");
7
10
  Object.defineProperty(exports, "PEABLE_BILLING_AUTHORITY_KEYS", { enumerable: true, get: function () { return shared_types_1.PEABLE_BILLING_AUTHORITY_KEYS; } });
@@ -48,12 +51,15 @@ class Peable {
48
51
  : (0, serviceToken_1.createServiceTokenProvider)(config);
49
52
  const client = (0, client_1.createRestClient)({ baseURL: resolved.baseURL, requestTimeoutMs: resolved.requestTimeoutMs }, tokenProvider);
50
53
  this.billing = new billing_1.BillingResource(client, resolved.invoiceAuthorityKeys, resolved.taxQuoteAuthorityKeys);
54
+ this.tax = new tax_1.TaxResource(client);
51
55
  this.paymentIntents = new paymentIntents_1.PaymentIntentsResource(client);
52
56
  this.paymentLinks = new paymentLinks_1.PaymentLinksResource(client);
53
57
  this.checkout = new checkoutSessions_1.CheckoutResource(client);
54
58
  this.webhooks = new webhooks_1.WebhooksResource();
55
59
  this.merchants = new merchants_1.MerchantsResource(client);
56
60
  this.connectedAccounts = new connectedAccounts_1.ConnectedAccountsResource(client);
61
+ this.accounts = this.connectedAccounts;
62
+ this.accountLinks = new connectedAccounts_1.AccountLinksResource(this.connectedAccounts);
57
63
  this.refunds = new refunds_1.RefundsResource(client);
58
64
  this.transfers = new transfers_1.TransfersResource(client);
59
65
  this.disputes = new merchants_1.DisputesResource(client);
@@ -70,6 +76,13 @@ Object.defineProperty(exports, "PeableInvalidRequestError", { enumerable: true,
70
76
  Object.defineProperty(exports, "PeablePermissionError", { enumerable: true, get: function () { return errors_1.PeablePermissionError; } });
71
77
  Object.defineProperty(exports, "PeableApiError", { enumerable: true, get: function () { return errors_1.PeableApiError; } });
72
78
  Object.defineProperty(exports, "PeableSignatureVerificationError", { enumerable: true, get: function () { return errors_1.PeableSignatureVerificationError; } });
79
+ var connectedAccounts_2 = require("./resources/connectedAccounts");
80
+ Object.defineProperty(exports, "AccountLinksResource", { enumerable: true, get: function () { return connectedAccounts_2.AccountLinksResource; } });
81
+ Object.defineProperty(exports, "ConnectedAccountsResource", { enumerable: true, get: function () { return connectedAccounts_2.ConnectedAccountsResource; } });
82
+ /** Whether an intent can still expire — `false` once a FairCoin payer has broadcast (ADR 0012 D9). */
83
+ var shared_types_2 = require("@peable.to/shared-types");
84
+ Object.defineProperty(exports, "canExpire", { enumerable: true, get: function () { return shared_types_2.canExpire; } });
85
+ Object.defineProperty(exports, "EXPIRABLE_STATUSES", { enumerable: true, get: function () { return shared_types_2.EXPIRABLE_STATUSES; } });
73
86
  var webhooks_2 = require("./resources/webhooks");
74
87
  Object.defineProperty(exports, "WEBHOOK_SIGNATURE_HEADER", { enumerable: true, get: function () { return webhooks_2.WEBHOOK_SIGNATURE_HEADER; } });
75
88
  Object.defineProperty(exports, "WebhooksResource", { enumerable: true, get: function () { return webhooks_2.WebhooksResource; } });
@@ -84,10 +84,11 @@ class BillingResource {
84
84
  }
85
85
  return result;
86
86
  }
87
- async retrieveFinalInvoiceAuthority(subscriptionRef, invoiceRef) {
87
+ async retrieveFinalInvoiceAuthority(subscriptionRef, invoiceRef, options = {}) {
88
88
  if (!this.invoiceAuthorityKeys || Object.keys(this.invoiceAuthorityKeys).length === 0)
89
89
  throw new Error('Peable: invoice authority verification is unconfigured');
90
- const authority = await this.client.request('GET', `/v1/billing/subscriptions/${encodeURIComponent(subscriptionRef)}/invoice_authorities/${encodeURIComponent(invoiceRef)}`);
90
+ const withTaxLines = options.include?.includes('tax_lines') === true;
91
+ const authority = await this.client.request('GET', `/v1/billing/subscriptions/${encodeURIComponent(subscriptionRef)}/invoice_authorities/${encodeURIComponent(invoiceRef)}`, withTaxLines ? { query: { include: 'tax_lines' } } : undefined);
91
92
  try {
92
93
  const pinnedKey = this.invoiceAuthorityKeys[authority.signature.keyId];
93
94
  if (authority.schemaVersion !== 1 ||
@@ -101,7 +102,12 @@ class BillingResource {
101
102
  !Number.isFinite(Date.parse(authority.invoice.issuedAt)) ||
102
103
  Date.parse(authority.invoice.issuedAt) > Date.now() ||
103
104
  !Number.isFinite(Date.parse(authority.invoice.expiresAt)) ||
104
- Date.parse(authority.invoice.expiresAt) <= Date.now())
105
+ Date.parse(authority.invoice.expiresAt) <= Date.now() ||
106
+ // Lines are present exactly when asked for, and add up to the tax.
107
+ withTaxLines !== Array.isArray(authority.invoice.taxLines) ||
108
+ (authority.invoice.taxLines !== undefined &&
109
+ authority.invoice.taxLines.reduce((sum, line) => sum + line.taxMinorUnits, 0) !==
110
+ authority.invoice.taxMinorUnits))
105
111
  throw new Error('Invalid authority');
106
112
  if (authority.method === 'faircoin') {
107
113
  const quote = authority.invoice.faircoinQuote;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ConnectedAccountsResource = void 0;
3
+ exports.AccountLinksResource = exports.ConnectedAccountsResource = void 0;
4
4
  class ConnectedAccountsResource {
5
5
  constructor(client) {
6
6
  this.client = client;
@@ -61,3 +61,19 @@ class ConnectedAccountsResource {
61
61
  }
62
62
  }
63
63
  exports.ConnectedAccountsResource = ConnectedAccountsResource;
64
+ /**
65
+ * `peable.accountLinks` — onboarding links, Stripe-named.
66
+ *
67
+ * The same operation as `connectedAccounts.createAccountLink`, addressed the
68
+ * way Stripe Connect integrators expect: `accountLinks.create({ account, … })`.
69
+ */
70
+ class AccountLinksResource {
71
+ constructor(accounts) {
72
+ this.accounts = accounts;
73
+ }
74
+ create(params) {
75
+ const { account, ...link } = params;
76
+ return this.accounts.createAccountLink(account, link);
77
+ }
78
+ }
79
+ exports.AccountLinksResource = AccountLinksResource;
@@ -5,6 +5,14 @@ class PaymentIntentsResource {
5
5
  constructor(client) {
6
6
  this.client = client;
7
7
  }
8
+ /**
9
+ * Create a payment. With `connectedAccount: 'ca_…'` it is made ON BEHALF OF
10
+ * that seller (ADR 0012): FairCoin only, the address derives from the
11
+ * seller's own key so the coins go straight to their wallet, and you still
12
+ * own the payment and receive its webhooks (each tagged `event.account`).
13
+ * A seller who has not registered their key yet is a 409 with
14
+ * `code: 'account_not_ready'`.
15
+ */
8
16
  create(params, options) {
9
17
  return this.client.request('POST', '/v1/payment_intents', {
10
18
  body: params,
@@ -20,6 +28,7 @@ class PaymentIntentsResource {
20
28
  status: params.status,
21
29
  limit: params.limit,
22
30
  starting_after: params.starting_after,
31
+ connected_account: params.connected_account,
23
32
  },
24
33
  });
25
34
  }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TaxResource = void 0;
4
+ /**
5
+ * Peable Tax for the merchant's server: what its tax settings and
6
+ * registrations are, recording where a customer is, calculating, and reading
7
+ * back what was collected. Registrations and the owner's approval are managed
8
+ * in the Peable dashboard, never by a service credential.
9
+ *
10
+ * At checkout: `locationEvidence.create` with what you know of the customer
11
+ * (billing address, payment-method or bank country, the IP address and the
12
+ * country you resolved it to). Language, currency or timezone are not
13
+ * evidence and are refused. Pass the returned id as `customerLocationEvidenceId`
14
+ * to `billing.createTaxQuote` or `tax.calculations.create`.
15
+ */
16
+ class TaxResource {
17
+ constructor(client) {
18
+ this.client = client;
19
+ this.locationEvidence = {
20
+ create: (params) => client.request('POST', '/v1/tax/location_evidence', { body: params }),
21
+ retrieve: (id) => client.request('GET', `/v1/tax/location_evidence/${encodeURIComponent(id)}`),
22
+ };
23
+ this.calculations = {
24
+ create: (params) => client.request('POST', '/v1/tax/calculations', { body: params }),
25
+ retrieve: (id) => client.request('GET', `/v1/tax/calculations/${encodeURIComponent(id)}`),
26
+ };
27
+ this.products = {
28
+ list: () => client.request('GET', '/v1/tax/products'),
29
+ setTaxCode: (productRef, taxCode) => client.request('PUT', `/v1/tax/products/${encodeURIComponent(productRef)}`, {
30
+ body: { taxCode },
31
+ }),
32
+ };
33
+ this.transactions = {
34
+ list: (params) => client.request('GET', '/v1/tax/transactions', {
35
+ query: {
36
+ from: params.from,
37
+ to: params.to,
38
+ limit: params.limit,
39
+ startingAfter: params.startingAfter,
40
+ },
41
+ }),
42
+ createReversal: (id, params) => client.request('POST', `/v1/tax/transactions/${encodeURIComponent(id)}/reversals`, {
43
+ body: params,
44
+ }),
45
+ };
46
+ this.reports = {
47
+ summary: (params) => client.request('GET', '/v1/tax/reports/summary', {
48
+ query: { from: params.from, to: params.to },
49
+ }),
50
+ };
51
+ }
52
+ /** The merchant's tax settings: status (`active` once the owner approved), head office, defaults. */
53
+ retrieveSettings() {
54
+ return this.client.request('GET', '/v1/tax/settings');
55
+ }
56
+ listRegistrations() {
57
+ return this.client.request('GET', '/v1/tax/registrations');
58
+ }
59
+ listCodes() {
60
+ return this.client.request('GET', '/v1/tax/codes');
61
+ }
62
+ }
63
+ exports.TaxResource = TaxResource;
@@ -84,7 +84,9 @@ export function errorFromResponse(status, body) {
84
84
  let upstreamCode;
85
85
  let message = `Peable request failed with status ${status}`;
86
86
  if (isNestedGatewayErrorBody(body)) {
87
- upstreamCode = body.error.type;
87
+ // The specific reason when the gateway names one (`account_not_ready`),
88
+ // else the broad `type` — which is all any error carried before.
89
+ upstreamCode = typeof body.error.code === 'string' ? body.error.code : body.error.type;
88
90
  message = body.error.message;
89
91
  }
90
92
  else if (isFlatGatewayErrorBody(body)) {
package/dist/esm/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { BillingResource } from './resources/billing.js';
2
+ import { TaxResource } from './resources/tax.js';
3
+ export { TaxResource } from './resources/tax.js';
2
4
  /** Production Peable's pinned billing-authority public keys, by key id. */
3
5
  export { PEABLE_BILLING_AUTHORITY_KEYS } from '@peable.to/shared-types';
4
6
  // Server entry (`@peable.to/sdk`) — the merchant-authed SDK. Configured with a
@@ -16,7 +18,7 @@ import { PaymentIntentsResource } from './resources/paymentIntents.js';
16
18
  import { PaymentLinksResource } from './resources/paymentLinks.js';
17
19
  import { CheckoutResource } from './resources/checkoutSessions.js';
18
20
  import { WebhooksResource } from './resources/webhooks.js';
19
- import { ConnectedAccountsResource } from './resources/connectedAccounts.js';
21
+ import { AccountLinksResource, ConnectedAccountsResource } from './resources/connectedAccounts.js';
20
22
  import { DisputesResource, MerchantsResource } from './resources/merchants.js';
21
23
  import { RefundsResource } from './resources/refunds.js';
22
24
  import { TransfersResource } from './resources/transfers.js';
@@ -44,12 +46,15 @@ export class Peable {
44
46
  : createServiceTokenProvider(config);
45
47
  const client = createRestClient({ baseURL: resolved.baseURL, requestTimeoutMs: resolved.requestTimeoutMs }, tokenProvider);
46
48
  this.billing = new BillingResource(client, resolved.invoiceAuthorityKeys, resolved.taxQuoteAuthorityKeys);
49
+ this.tax = new TaxResource(client);
47
50
  this.paymentIntents = new PaymentIntentsResource(client);
48
51
  this.paymentLinks = new PaymentLinksResource(client);
49
52
  this.checkout = new CheckoutResource(client);
50
53
  this.webhooks = new WebhooksResource();
51
54
  this.merchants = new MerchantsResource(client);
52
55
  this.connectedAccounts = new ConnectedAccountsResource(client);
56
+ this.accounts = this.connectedAccounts;
57
+ this.accountLinks = new AccountLinksResource(this.connectedAccounts);
53
58
  this.refunds = new RefundsResource(client);
54
59
  this.transfers = new TransfersResource(client);
55
60
  this.disputes = new DisputesResource(client);
@@ -57,5 +62,8 @@ export class Peable {
57
62
  }
58
63
  export { DEFAULT_GATEWAY_BASE_URL, DEFAULT_OXY_API_URL } from './core/config.js';
59
64
  export { PeableError, PeableAuthenticationError, PeableInvalidRequestError, PeablePermissionError, PeableApiError, PeableSignatureVerificationError, } from './core/errors.js';
65
+ export { AccountLinksResource, ConnectedAccountsResource } from './resources/connectedAccounts.js';
66
+ /** Whether an intent can still expire — `false` once a FairCoin payer has broadcast (ADR 0012 D9). */
67
+ export { canExpire, EXPIRABLE_STATUSES } from '@peable.to/shared-types';
60
68
  export { WEBHOOK_SIGNATURE_HEADER, WebhooksResource } from './resources/webhooks.js';
61
69
  export { ContributionsResource } from './resources/contributions.js';
@@ -81,10 +81,11 @@ export class BillingResource {
81
81
  }
82
82
  return result;
83
83
  }
84
- async retrieveFinalInvoiceAuthority(subscriptionRef, invoiceRef) {
84
+ async retrieveFinalInvoiceAuthority(subscriptionRef, invoiceRef, options = {}) {
85
85
  if (!this.invoiceAuthorityKeys || Object.keys(this.invoiceAuthorityKeys).length === 0)
86
86
  throw new Error('Peable: invoice authority verification is unconfigured');
87
- const authority = await this.client.request('GET', `/v1/billing/subscriptions/${encodeURIComponent(subscriptionRef)}/invoice_authorities/${encodeURIComponent(invoiceRef)}`);
87
+ const withTaxLines = options.include?.includes('tax_lines') === true;
88
+ const authority = await this.client.request('GET', `/v1/billing/subscriptions/${encodeURIComponent(subscriptionRef)}/invoice_authorities/${encodeURIComponent(invoiceRef)}`, withTaxLines ? { query: { include: 'tax_lines' } } : undefined);
88
89
  try {
89
90
  const pinnedKey = this.invoiceAuthorityKeys[authority.signature.keyId];
90
91
  if (authority.schemaVersion !== 1 ||
@@ -98,7 +99,12 @@ export class BillingResource {
98
99
  !Number.isFinite(Date.parse(authority.invoice.issuedAt)) ||
99
100
  Date.parse(authority.invoice.issuedAt) > Date.now() ||
100
101
  !Number.isFinite(Date.parse(authority.invoice.expiresAt)) ||
101
- Date.parse(authority.invoice.expiresAt) <= Date.now())
102
+ Date.parse(authority.invoice.expiresAt) <= Date.now() ||
103
+ // Lines are present exactly when asked for, and add up to the tax.
104
+ withTaxLines !== Array.isArray(authority.invoice.taxLines) ||
105
+ (authority.invoice.taxLines !== undefined &&
106
+ authority.invoice.taxLines.reduce((sum, line) => sum + line.taxMinorUnits, 0) !==
107
+ authority.invoice.taxMinorUnits))
102
108
  throw new Error('Invalid authority');
103
109
  if (authority.method === 'faircoin') {
104
110
  const quote = authority.invoice.faircoinQuote;
@@ -57,3 +57,18 @@ export class ConnectedAccountsResource {
57
57
  return this.client.request('POST', `/v1/connected_accounts/${encodeURIComponent(accountId)}/account_links`, { body: params });
58
58
  }
59
59
  }
60
+ /**
61
+ * `peable.accountLinks` — onboarding links, Stripe-named.
62
+ *
63
+ * The same operation as `connectedAccounts.createAccountLink`, addressed the
64
+ * way Stripe Connect integrators expect: `accountLinks.create({ account, … })`.
65
+ */
66
+ export class AccountLinksResource {
67
+ constructor(accounts) {
68
+ this.accounts = accounts;
69
+ }
70
+ create(params) {
71
+ const { account, ...link } = params;
72
+ return this.accounts.createAccountLink(account, link);
73
+ }
74
+ }
@@ -2,6 +2,14 @@ export class PaymentIntentsResource {
2
2
  constructor(client) {
3
3
  this.client = client;
4
4
  }
5
+ /**
6
+ * Create a payment. With `connectedAccount: 'ca_…'` it is made ON BEHALF OF
7
+ * that seller (ADR 0012): FairCoin only, the address derives from the
8
+ * seller's own key so the coins go straight to their wallet, and you still
9
+ * own the payment and receive its webhooks (each tagged `event.account`).
10
+ * A seller who has not registered their key yet is a 409 with
11
+ * `code: 'account_not_ready'`.
12
+ */
5
13
  create(params, options) {
6
14
  return this.client.request('POST', '/v1/payment_intents', {
7
15
  body: params,
@@ -17,6 +25,7 @@ export class PaymentIntentsResource {
17
25
  status: params.status,
18
26
  limit: params.limit,
19
27
  starting_after: params.starting_after,
28
+ connected_account: params.connected_account,
20
29
  },
21
30
  });
22
31
  }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Peable Tax for the merchant's server: what its tax settings and
3
+ * registrations are, recording where a customer is, calculating, and reading
4
+ * back what was collected. Registrations and the owner's approval are managed
5
+ * in the Peable dashboard, never by a service credential.
6
+ *
7
+ * At checkout: `locationEvidence.create` with what you know of the customer
8
+ * (billing address, payment-method or bank country, the IP address and the
9
+ * country you resolved it to). Language, currency or timezone are not
10
+ * evidence and are refused. Pass the returned id as `customerLocationEvidenceId`
11
+ * to `billing.createTaxQuote` or `tax.calculations.create`.
12
+ */
13
+ export class TaxResource {
14
+ constructor(client) {
15
+ this.client = client;
16
+ this.locationEvidence = {
17
+ create: (params) => client.request('POST', '/v1/tax/location_evidence', { body: params }),
18
+ retrieve: (id) => client.request('GET', `/v1/tax/location_evidence/${encodeURIComponent(id)}`),
19
+ };
20
+ this.calculations = {
21
+ create: (params) => client.request('POST', '/v1/tax/calculations', { body: params }),
22
+ retrieve: (id) => client.request('GET', `/v1/tax/calculations/${encodeURIComponent(id)}`),
23
+ };
24
+ this.products = {
25
+ list: () => client.request('GET', '/v1/tax/products'),
26
+ setTaxCode: (productRef, taxCode) => client.request('PUT', `/v1/tax/products/${encodeURIComponent(productRef)}`, {
27
+ body: { taxCode },
28
+ }),
29
+ };
30
+ this.transactions = {
31
+ list: (params) => client.request('GET', '/v1/tax/transactions', {
32
+ query: {
33
+ from: params.from,
34
+ to: params.to,
35
+ limit: params.limit,
36
+ startingAfter: params.startingAfter,
37
+ },
38
+ }),
39
+ createReversal: (id, params) => client.request('POST', `/v1/tax/transactions/${encodeURIComponent(id)}/reversals`, {
40
+ body: params,
41
+ }),
42
+ };
43
+ this.reports = {
44
+ summary: (params) => client.request('GET', '/v1/tax/reports/summary', {
45
+ query: { from: params.from, to: params.to },
46
+ }),
47
+ };
48
+ }
49
+ /** The merchant's tax settings: status (`active` once the owner approved), head office, defaults. */
50
+ retrieveSettings() {
51
+ return this.client.request('GET', '/v1/tax/settings');
52
+ }
53
+ listRegistrations() {
54
+ return this.client.request('GET', '/v1/tax/registrations');
55
+ }
56
+ listCodes() {
57
+ return this.client.request('GET', '/v1/tax/codes');
58
+ }
59
+ }
@@ -1,6 +1,8 @@
1
1
  import { BillingResource } from './resources/billing';
2
- export type { BillingRequestOptions } from './resources/billing';
3
- export type { CreateBillingTaxQuoteParams, BillingTaxQuote, BillingInvoiceAuthoritySource, BillingFinalInvoice, BillingFinalInvoiceAuthority, BillingFaircoinRenewalChoice, BillingFaircoinRenewalConsent, BillingFaircoinRenewalRevocation, BillingObservation, BillingCustomer, BillingHostedSession, BillingCheckoutSession, BillingCheckoutObservation, RetrieveBillingCheckoutOperationParams, BillingCheckoutOperationSource, BillingCheckoutOperationRecovery, BillingPaidInvoice, BillingInvoiceState, BillingSubscription, CreateBillingCheckoutParams, CreateBillingPortalParams, EnsureBillingCustomerParams, BillingRail, BillingRailSettlement, BillingRailOffer, BillingRailOption, BillingRailList, } from '@peable.to/shared-types';
2
+ import { TaxResource } from './resources/tax';
3
+ export { TaxResource } from './resources/tax';
4
+ export type { BillingRequestOptions, RetrieveFinalInvoiceAuthorityOptions, } from './resources/billing';
5
+ export type { CreateBillingTaxQuoteParams, BillingTaxQuote, BillingInvoiceAuthoritySource, BillingFinalInvoice, BillingFinalInvoiceAuthority, BillingFaircoinRenewalChoice, BillingFaircoinRenewalConsent, BillingFaircoinRenewalRevocation, BillingObservation, BillingCustomer, BillingHostedSession, BillingCheckoutSession, BillingCheckoutObservation, RetrieveBillingCheckoutOperationParams, BillingCheckoutOperationSource, BillingCheckoutOperationRecovery, BillingPaidInvoice, BillingInvoiceState, BillingSubscription, CreateBillingCheckoutParams, CreateBillingPortalParams, EnsureBillingCustomerParams, BillingRail, BillingRailSettlement, BillingRailOffer, BillingRailOption, BillingRailList, BillingInvoiceTaxLine, TaxRegistrationScheme, TaxLocationEvidenceType, TaxBehavior, TaxAddress, TaxCode, TaxCalculationAccount, TaxSettings, TaxRegistration, TaxProductCode, TaxLocationEvidenceItem, CreateTaxLocationEvidenceParams, TaxLocationEvidence, TaxLineItemParams, CreateTaxCalculationParams, TaxBreakdownEntry, TaxCalculationLineItem, TaxCalculation, TaxTransaction, TaxTransactionList, ListTaxTransactionsParams, TaxReportRow, TaxReport, } from '@peable.to/shared-types';
4
6
  /** Production Peable's pinned billing-authority public keys, by key id. */
5
7
  export { PEABLE_BILLING_AUTHORITY_KEYS } from '@peable.to/shared-types';
6
8
  import { type PeableConfig } from './core/config';
@@ -8,7 +10,7 @@ import { PaymentIntentsResource } from './resources/paymentIntents';
8
10
  import { PaymentLinksResource } from './resources/paymentLinks';
9
11
  import { CheckoutResource } from './resources/checkoutSessions';
10
12
  import { WebhooksResource } from './resources/webhooks';
11
- import { ConnectedAccountsResource } from './resources/connectedAccounts';
13
+ import { AccountLinksResource, ConnectedAccountsResource } from './resources/connectedAccounts';
12
14
  import { DisputesResource, MerchantsResource } from './resources/merchants';
13
15
  import { RefundsResource } from './resources/refunds';
14
16
  import { TransfersResource } from './resources/transfers';
@@ -30,6 +32,8 @@ import { TransfersResource } from './resources/transfers';
30
32
  */
31
33
  export declare class Peable {
32
34
  readonly billing: BillingResource;
35
+ /** Peable Tax: location evidence, calculations, and what was collected. */
36
+ readonly tax: TaxResource;
33
37
  readonly paymentIntents: PaymentIntentsResource;
34
38
  readonly paymentLinks: PaymentLinksResource;
35
39
  readonly checkout: CheckoutResource;
@@ -38,6 +42,14 @@ export declare class Peable {
38
42
  readonly merchants: MerchantsResource;
39
43
  /** Sellers a marketplace onboards, and their readiness. */
40
44
  readonly connectedAccounts: ConnectedAccountsResource;
45
+ /**
46
+ * The same sellers, Stripe-named: `accounts.create/retrieve/list` is
47
+ * `connectedAccounts.create/retrieve/list` — one resource, two names, so a
48
+ * Stripe Connect integration reads the way its authors expect.
49
+ */
50
+ readonly accounts: ConnectedAccountsResource;
51
+ /** Onboarding links, Stripe-named: `accountLinks.create({ account, rail, … })`. */
52
+ readonly accountLinks: AccountLinksResource;
41
53
  /** Money going back to a payer. */
42
54
  readonly refunds: RefundsResource;
43
55
  /** Money going out to a seller, and coming back from one. */
@@ -54,7 +66,16 @@ export type { RestClient, RestClientRequestOptions } from './core/client';
54
66
  export type { ServiceTokenProvider } from './core/serviceToken';
55
67
  export type { CreateCheckoutSessionOptions } from './resources/checkoutSessions';
56
68
  export type { CreatePaymentIntentOptions, PaymentIntentClientAction, PaymentIntentListParams, PaymentIntentList, } from './resources/paymentIntents';
57
- export type { AccountLink, AccountLinkParams, ConnectedAccountList, ConnectedAccountListParams, CreateConnectedAccountParams, } from './resources/connectedAccounts';
69
+ export type { AccountLink, AccountLinkParams, ConnectedAccountList, ConnectedAccountListParams, CreateAccountLinkParams, CreateConnectedAccountParams, } from './resources/connectedAccounts';
70
+ export { AccountLinksResource, ConnectedAccountsResource } from './resources/connectedAccounts';
71
+ /**
72
+ * The wire shapes a platform handles, re-exported so a Connect integration needs
73
+ * one import: the seller (`ConnectedAccount` and its FairCoin half), the
74
+ * payment, and the typed webhook event — whose `account` names the seller.
75
+ */
76
+ export type { ConnectedAccount, ConnectedAccountFaircoin, ConnectedAccountFaircoinStatus, ConnectedAccountRail, CheckoutSession, CreateCheckoutSessionParams, CreatePaymentIntentParams, PaymentIntent, PaymentIntentStatus, WebhookEvent, WebhookEventType, } from '@peable.to/shared-types';
77
+ /** Whether an intent can still expire — `false` once a FairCoin payer has broadcast (ADR 0012 D9). */
78
+ export { canExpire, EXPIRABLE_STATUSES } from '@peable.to/shared-types';
58
79
  export type { DisputeEvidenceParams, DisputeList, RegisterMerchantParams, UpdateMerchantParams, } from './resources/merchants';
59
80
  export type { CreateRefundParams, RefundList } from './resources/refunds';
60
81
  export type { CreateTransferParams, ReverseTransferParams, TransferList, } from './resources/transfers';
@@ -3,6 +3,12 @@ import type { RestClient } from '../core/client';
3
3
  export interface BillingRequestOptions {
4
4
  idempotencyKey: string;
5
5
  }
6
+ export interface RetrieveFinalInvoiceAuthorityOptions {
7
+ /** `tax_lines`: include the frozen Peable Tax lines, covered by the signature
8
+ * (FairCoin and other Peable-signed rails). Omitted: the authority is exactly
9
+ * the 0.3.x shape. */
10
+ include?: readonly 'tax_lines'[];
11
+ }
6
12
  /** Recurring billing is separate from one-off checkout and marketplace transfers. */
7
13
  export declare class BillingResource {
8
14
  private readonly client;
@@ -27,7 +33,7 @@ export declare class BillingResource {
27
33
  * Missing/pending/indeterminate never authorizes another create or cancellation. */
28
34
  retrieveCheckoutOperation(params: RetrieveBillingCheckoutOperationParams): Promise<BillingCheckoutOperationRecovery>;
29
35
  createTaxQuote(params: CreateBillingTaxQuoteParams): Promise<BillingTaxQuote>;
30
- retrieveFinalInvoiceAuthority(subscriptionRef: string, invoiceRef: string): Promise<BillingFinalInvoiceAuthority>;
36
+ retrieveFinalInvoiceAuthority(subscriptionRef: string, invoiceRef: string, options?: RetrieveFinalInvoiceAuthorityOptions): Promise<BillingFinalInvoiceAuthority>;
31
37
  retrievePaidInvoice(subscriptionRef: string, invoiceRef: string): Promise<BillingPaidInvoice>;
32
38
  retrieveInvoiceState(subscriptionRef: string, invoiceRef: string): Promise<BillingInvoiceState>;
33
39
  retrieveSubscription(ref: string): Promise<BillingSubscription>;
@@ -1,4 +1,4 @@
1
- import type { ConnectedAccount } from '@peable.to/shared-types';
1
+ import type { AccountLink, ConnectedAccount, NetworkType } from '@peable.to/shared-types';
2
2
  import type { RestClient } from '../core/client';
3
3
  /**
4
4
  * Sellers a marketplace onboards through Peable.
@@ -13,13 +13,36 @@ import type { RestClient } from '../core/client';
13
13
  * whose response never arrived leaves the merchant without the `ca_…` and still
14
14
  * holding the reference they chose.
15
15
  */
16
- export interface CreateConnectedAccountParams {
16
+ /**
17
+ * Open a seller — on the card rail, the FairCoin rail, or both — under ONE
18
+ * `ca_…` (ADR 0012 D1). At least one half is required.
19
+ *
20
+ * Repeating a create converges on the seller's existing account and ADDS a half
21
+ * it does not have yet, so a card seller can be given FairCoin later (and the
22
+ * reverse) without a second id.
23
+ */
24
+ export type CreateConnectedAccountParams = {
17
25
  /** The merchant's own id for this seller. The idempotency, and durable. */
18
26
  externalRef: string;
19
- /** ISO 3166-1 alpha-2. Case-insensitive; the gateway upper-cases it. */
27
+ /**
28
+ * The FairCoin half: the chain the seller is paid on and the seller's Oxy
29
+ * user id — the ONLY person the onboarding page lets register the key.
30
+ * There is no key here, by design: the seller registers it themselves, in
31
+ * their own Oxy session, through `accountLinks.create({ rail: 'faircoin' })`.
32
+ * A non-production credential can only open `testnet`.
33
+ */
34
+ faircoin?: {
35
+ network: NetworkType;
36
+ oxyUserId: string;
37
+ };
38
+ } & ({
39
+ /** ISO 3166-1 alpha-2. Case-insensitive; the gateway upper-cases it. Opens the CARD half. */
20
40
  country: string;
21
41
  businessType: 'individual' | 'company';
22
- }
42
+ } | {
43
+ country?: undefined;
44
+ businessType?: undefined;
45
+ });
23
46
  export interface ConnectedAccountListParams {
24
47
  limit?: number;
25
48
  /** A `ca_…` from a previous page — the gateway resolves it, scoped to you. */
@@ -31,15 +54,19 @@ export interface ConnectedAccountList {
31
54
  has_more: boolean;
32
55
  }
33
56
  export interface AccountLinkParams {
34
- /** Where the provider sends a seller whose link expired mid-flow. */
57
+ /** Where an EXPIRED link sends the seller, to ask you for a fresh one. */
35
58
  refreshUrl: string;
59
+ /** Where the seller lands when onboarding is done. Proves nothing — read the account. */
36
60
  returnUrl: string;
61
+ /**
62
+ * Which half to onboard. `card` (the default) is the provider's hosted KYC;
63
+ * `faircoin` is Peable's page in the wallet, where the seller — signed in
64
+ * with Oxy as the account's `oxyUserId` — registers their watch-only key
65
+ * (ADR 0012 D3). The FairCoin link works for an hour and only for that user.
66
+ */
67
+ rail?: 'card' | 'faircoin';
37
68
  }
38
- export interface AccountLink {
39
- object: 'account_link';
40
- url: string;
41
- expiresAt: string;
42
- }
69
+ export type { AccountLink };
43
70
  export declare class ConnectedAccountsResource {
44
71
  private readonly client;
45
72
  constructor(client: RestClient);
@@ -82,3 +109,19 @@ export declare class ConnectedAccountsResource {
82
109
  */
83
110
  createAccountLink(accountId: string, params: AccountLinkParams): Promise<AccountLink>;
84
111
  }
112
+ /** `accountLinks.create` — Stripe's `AccountLink.create`, naming the account in the body. */
113
+ export interface CreateAccountLinkParams extends AccountLinkParams {
114
+ /** The seller's `ca_…`. */
115
+ account: string;
116
+ }
117
+ /**
118
+ * `peable.accountLinks` — onboarding links, Stripe-named.
119
+ *
120
+ * The same operation as `connectedAccounts.createAccountLink`, addressed the
121
+ * way Stripe Connect integrators expect: `accountLinks.create({ account, … })`.
122
+ */
123
+ export declare class AccountLinksResource {
124
+ private readonly accounts;
125
+ constructor(accounts: ConnectedAccountsResource);
126
+ create(params: CreateAccountLinkParams): Promise<AccountLink>;
127
+ }
@@ -4,6 +4,8 @@ export interface PaymentIntentListParams {
4
4
  status?: PaymentIntentStatus;
5
5
  limit?: number;
6
6
  starting_after?: string;
7
+ /** Only the payments made on behalf of this seller (`ca_…`, ADR 0012). */
8
+ connected_account?: string;
7
9
  }
8
10
  export interface PaymentIntentList {
9
11
  object: 'list';
@@ -40,6 +42,14 @@ export interface CreatePaymentIntentOptions {
40
42
  export declare class PaymentIntentsResource {
41
43
  private readonly client;
42
44
  constructor(client: RestClient);
45
+ /**
46
+ * Create a payment. With `connectedAccount: 'ca_…'` it is made ON BEHALF OF
47
+ * that seller (ADR 0012): FairCoin only, the address derives from the
48
+ * seller's own key so the coins go straight to their wallet, and you still
49
+ * own the payment and receive its webhooks (each tagged `event.account`).
50
+ * A seller who has not registered their key yet is a 409 with
51
+ * `code: 'account_not_ready'`.
52
+ */
43
53
  create(params: CreatePaymentIntentParams, options: CreatePaymentIntentOptions): Promise<PaymentIntent>;
44
54
  retrieve(id: string): Promise<PaymentIntent>;
45
55
  list(params?: PaymentIntentListParams): Promise<PaymentIntentList>;
@@ -0,0 +1,55 @@
1
+ import type { CreateTaxCalculationParams, CreateTaxReversalParams, CreateTaxLocationEvidenceParams, ListTaxTransactionsParams, TaxCalculation, TaxCode, TaxLocationEvidence, TaxProductCode, TaxRegistration, TaxReport, TaxSettings, TaxTransaction, TaxTransactionList } from '@peable.to/shared-types';
2
+ import type { RestClient } from '../core/client';
3
+ interface List<T> {
4
+ object: 'list';
5
+ data: T[];
6
+ }
7
+ /**
8
+ * Peable Tax for the merchant's server: what its tax settings and
9
+ * registrations are, recording where a customer is, calculating, and reading
10
+ * back what was collected. Registrations and the owner's approval are managed
11
+ * in the Peable dashboard, never by a service credential.
12
+ *
13
+ * At checkout: `locationEvidence.create` with what you know of the customer
14
+ * (billing address, payment-method or bank country, the IP address and the
15
+ * country you resolved it to). Language, currency or timezone are not
16
+ * evidence and are refused. Pass the returned id as `customerLocationEvidenceId`
17
+ * to `billing.createTaxQuote` or `tax.calculations.create`.
18
+ */
19
+ export declare class TaxResource {
20
+ private readonly client;
21
+ readonly locationEvidence: {
22
+ create(params: CreateTaxLocationEvidenceParams): Promise<TaxLocationEvidence>;
23
+ retrieve(id: string): Promise<TaxLocationEvidence>;
24
+ };
25
+ readonly calculations: {
26
+ create(params: CreateTaxCalculationParams): Promise<TaxCalculation>;
27
+ retrieve(id: string): Promise<TaxCalculation>;
28
+ };
29
+ readonly products: {
30
+ list(): Promise<List<TaxProductCode>>;
31
+ /** Set a product's (billing plan's) tax code, e.g. `txcd_10103000` for SaaS. */
32
+ setTaxCode(productRef: string, taxCode: string): Promise<TaxProductCode>;
33
+ };
34
+ readonly transactions: {
35
+ /** Paid sales and their frozen calculations, oldest first; refunds appear
36
+ * as `type: "reversal"` rows naming the sale they reverse. */
37
+ list(params: ListTaxTransactionsParams): Promise<TaxTransactionList>;
38
+ /** Record a refund made outside Peable (a FairCoin sale refunded from your
39
+ * own wallet). Card refunds and credit notes are reversed automatically. */
40
+ createReversal(id: string, params: CreateTaxReversalParams): Promise<TaxTransaction>;
41
+ };
42
+ readonly reports: {
43
+ /** Totals per jurisdiction, registration, tax type and rate, for filings. */
44
+ summary(params: {
45
+ from: string;
46
+ to: string;
47
+ }): Promise<TaxReport>;
48
+ };
49
+ constructor(client: RestClient);
50
+ /** The merchant's tax settings: status (`active` once the owner approved), head office, defaults. */
51
+ retrieveSettings(): Promise<TaxSettings>;
52
+ listRegistrations(): Promise<List<TaxRegistration>>;
53
+ listCodes(): Promise<List<TaxCode>>;
54
+ }
55
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peable.to/sdk",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Peable SDK — a Stripe-ergonomics TypeScript client over the Peable Gateway REST + realtime contract. Server entry (`@peable.to/sdk`) mints Oxy service tokens from an ApplicationCredential and exposes paymentIntents/paymentLinks/checkout.sessions/webhooks; browser entry (`@peable.to/sdk/checkout`) is the anonymous payer-side client core.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -87,10 +87,10 @@
87
87
  "dev": "tsc --watch",
88
88
  "typecheck": "tsc --noEmit",
89
89
  "test": "bun test",
90
- "prepublishOnly": "bun run clean && bun run build"
90
+ "prepublishOnly": "bun run clean && bun run typecheck && bun run test && bun run build"
91
91
  },
92
92
  "dependencies": {
93
- "@peable.to/shared-types": "0.4.0",
93
+ "@peable.to/shared-types": "0.5.0",
94
94
  "qrcode-generator": "^2.0.4",
95
95
  "socket.io-client": "^4.8.3",
96
96
  "@peable.to/contracts": "0.1.0",