@peable.to/contracts 1.1.0 → 2.0.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.
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.billingRoutes = exports.cancelBillingSubscriptionParams = exports.billingFaircoinFxQuoteSchema = exports.billingFaircoinRenewalChoiceSchema = exports.billingFaircoinRenewalRevocationSchema = exports.billingFaircoinRenewalConsentSchema = exports.retrieveBillingInvoiceAuthorityQuery = exports.billingFinalInvoiceAuthoritySchema = exports.billingFinalInvoiceSchema = exports.billingInvoiceAuthoritySourceSchema = exports.billingInvoiceTaxLineSchema = exports.billingInvoiceStateSchema = exports.billingPaidInvoiceSchema = exports.createBillingPortalParams = exports.billingCheckoutOperationRecoverySchema = exports.billingCheckoutOperationSourceSchema = exports.billingCheckoutOperationParams = exports.retrieveBillingCheckoutOperationQuery = exports.billingCheckoutObservationSchema = exports.billingSubscriptionSchema = exports.billingEmbeddedCheckoutBindingSchema = exports.billingEmbeddedCheckoutActionSchema = exports.billingEmbeddedCheckoutConfigurationSchema = exports.billingEmbeddedCheckoutScopeSchema = exports.billingEmbeddedCheckoutSessionSchema = exports.billingCheckoutSessionSchema = exports.billingHostedSessionSchema = exports.createBillingCheckoutParams = exports.billingTaxQuoteSchema = exports.createBillingTaxQuoteParams = exports.billingCustomerSchema = exports.ensureBillingCustomerParams = exports.billingRailListSchema = exports.billingRailOptionSchema = exports.billingRailOfferSchema = exports.billingPriceRef = exports.billingCustomerRef = exports.billingInstant = exports.billingReturnUrl = exports.billingRailId = exports.billingIdempotencyKey = exports.billingReference = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const objects_1 = require("../../common/objects");
6
+ const primitives_1 = require("../../common/primitives");
6
7
  const route_1 = require("../../route");
7
8
  const catalog_1 = require("../../vocabulary/catalog");
8
9
  /**
@@ -50,8 +51,6 @@ exports.billingReturnUrl = zod_1.z
50
51
  }, 'An HTTPS return URL without credentials is required');
51
52
  /** An instant in signed billing evidence: integer Unix seconds that stay a safe integer. */
52
53
  exports.billingInstant = zod_1.z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
53
- /** A whole number of minor units (cents) in signed billing evidence. */
54
- const minorUnits = zod_1.z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
55
54
  /** A billing customer reference (`cus_…`). */
56
55
  exports.billingCustomerRef = zod_1.z
57
56
  .string()
@@ -85,7 +84,7 @@ exports.billingRailOfferSchema = (0, objects_1.defineComponent)('BillingRailOffe
85
84
  plan_id: zod_1.z.string(),
86
85
  interval: billingInterval,
87
86
  currency: zod_1.z.string(),
88
- gross_minor_units: zod_1.z.number().int(),
87
+ gross_minor_units: primitives_1.amount,
89
88
  tax_treatment: taxTreatment,
90
89
  })
91
90
  .strict());
@@ -134,10 +133,10 @@ exports.createBillingTaxQuoteParams = zod_1.z
134
133
  customer_location_evidence_id: exports.billingReference.describe('A `tax.location_evidence` id (`taxloc_…`) recorded for this `store_id`.'),
135
134
  })
136
135
  .strict();
137
- /** A signed, immutable, single-use Peable Tax quote (schema version 2). */
136
+ /** A signed, immutable, single-use Peable Tax quote (schema version 3). */
138
137
  exports.billingTaxQuoteSchema = (0, objects_1.defineComponent)('BillingTaxQuote', zod_1.z
139
138
  .object({
140
- schema_version: zod_1.z.literal(2),
139
+ schema_version: zod_1.z.literal(3),
141
140
  source: zod_1.z
142
141
  .object({
143
142
  merchant_id: exports.billingReference,
@@ -152,9 +151,9 @@ exports.billingTaxQuoteSchema = (0, objects_1.defineComponent)('BillingTaxQuote'
152
151
  .object({
153
152
  id: exports.billingReference,
154
153
  currency: zod_1.z.string().regex(/^[A-Z]{3}$/),
155
- gross_minor_units: minorUnits,
156
- net_minor_units: minorUnits,
157
- tax_minor_units: minorUnits,
154
+ gross_minor_units: primitives_1.amount,
155
+ net_minor_units: primitives_1.amount,
156
+ tax_minor_units: primitives_1.amount,
158
157
  tax_treatment: taxTreatment,
159
158
  seller_id: exports.billingReference,
160
159
  invoice_issuer_id: exports.billingReference,
@@ -223,7 +222,7 @@ exports.billingEmbeddedCheckoutActionSchema = (0, objects_1.defineComponent)('Bi
223
222
  session_id: zod_1.z.string(),
224
223
  client_secret: zod_1.z.string(),
225
224
  publishable_key: zod_1.z.string(),
226
- amount_minor_units: zod_1.z.number().int(),
225
+ amount_minor_units: primitives_1.amount,
227
226
  currency: zod_1.z.string(),
228
227
  })
229
228
  .strict());
@@ -353,10 +352,9 @@ exports.billingPaidInvoiceSchema = (0, objects_1.defineComponent)('BillingPaidIn
353
352
  plan_id: zod_1.z.string(),
354
353
  livemode: zod_1.z.boolean(),
355
354
  currency: zod_1.z.string(),
356
- amount_paid: zod_1.z.string(),
357
- net_amount: zod_1.z.string().nullable(),
358
- tax_amount: zod_1.z
359
- .string()
355
+ amount_paid: primitives_1.amount,
356
+ net_amount: primitives_1.amount.nullable(),
357
+ tax_amount: primitives_1.amount
360
358
  .nullable()
361
359
  .describe('A provider observation, not a tax quote or seller configuration.'),
362
360
  period_start: zod_1.z.number().int(),
@@ -368,7 +366,7 @@ exports.billingPaidInvoiceSchema = (0, objects_1.defineComponent)('BillingPaidIn
368
366
  exports.billingInvoiceStateSchema = (0, objects_1.defineComponent)('BillingInvoiceState', exports.billingPaidInvoiceSchema
369
367
  .extend({
370
368
  charge_id: zod_1.z.string(),
371
- amount_refunded: zod_1.z.string(),
369
+ amount_refunded: primitives_1.amount,
372
370
  state: zod_1.z.enum(['paid', 'fully_refunded', 'partially_refunded']),
373
371
  })
374
372
  .strict());
@@ -380,8 +378,8 @@ exports.billingInvoiceTaxLineSchema = (0, objects_1.defineComponent)('BillingInv
380
378
  state: zod_1.z.string().nullable(),
381
379
  tax_type: zod_1.z.string().nullable(),
382
380
  rate_percentage: zod_1.z.string().nullable(),
383
- taxable_minor_units: minorUnits,
384
- tax_minor_units: minorUnits,
381
+ taxable_minor_units: primitives_1.amount,
382
+ tax_minor_units: primitives_1.amount,
385
383
  inclusive: zod_1.z.boolean(),
386
384
  taxability_reason: zod_1.z.string().min(1),
387
385
  })
@@ -409,10 +407,10 @@ exports.billingFinalInvoiceSchema = (0, objects_1.defineComponent)('BillingFinal
409
407
  .object({
410
408
  platform: zod_1.z.literal('peable'),
411
409
  currency: zod_1.z.string().regex(/^[A-Z]{3}$/),
412
- gross_minor_units: minorUnits,
413
- net_minor_units: minorUnits,
414
- tax_minor_units: minorUnits,
415
- merchant_fee_minor_units: minorUnits,
410
+ gross_minor_units: primitives_1.amount,
411
+ net_minor_units: primitives_1.amount,
412
+ tax_minor_units: primitives_1.amount,
413
+ merchant_fee_minor_units: primitives_1.amount,
416
414
  tax_treatment: taxTreatment,
417
415
  seller_id: exports.billingReference,
418
416
  invoice_issuer_id: exports.billingReference,
@@ -455,10 +453,10 @@ exports.billingFinalInvoiceSchema = (0, objects_1.defineComponent)('BillingFinal
455
453
  .describe('Present only when asked for (`include=tax_lines`): the frozen Peable Tax lines behind `tax_minor_units`, covered by the same signature.'),
456
454
  })
457
455
  .strict());
458
- /** A signed final invoice authority (schema version 2). Verify it against the pinned keys. */
456
+ /** A signed final invoice authority (schema version 3). Verify it against the pinned keys. */
459
457
  exports.billingFinalInvoiceAuthoritySchema = (0, objects_1.defineComponent)('BillingFinalInvoiceAuthority', zod_1.z
460
458
  .object({
461
- schema_version: zod_1.z.literal(2),
459
+ schema_version: zod_1.z.literal(3),
462
460
  source: exports.billingInvoiceAuthoritySourceSchema,
463
461
  invoice: exports.billingFinalInvoiceSchema,
464
462
  method: zod_1.z.enum(['card', 'faircoin']),
@@ -526,7 +524,7 @@ exports.billingFaircoinFxQuoteSchema = (0, objects_1.defineComponent)('BillingFa
526
524
  .object({
527
525
  id: zod_1.z.string(),
528
526
  currency: zod_1.z.literal('USD'),
529
- gross_minor_units: zod_1.z.number().int(),
527
+ gross_minor_units: primitives_1.amount,
530
528
  amount_base_units: zod_1.z.string(),
531
529
  usd_per_fair: zod_1.z.string(),
532
530
  source: zod_1.z.string(),
@@ -6,7 +6,8 @@ const objects_1 = require("../../common/objects");
6
6
  const primitives_1 = require("../../common/primitives");
7
7
  const route_1 = require("../../route");
8
8
  const tax_1 = require("../../vocabulary/tax");
9
- const shared_1 = require("./shared");
9
+ const shared_1 = require("../catalog/shared");
10
+ const shared_2 = require("./shared");
10
11
  /**
11
12
  * A tax calculation (`taxcalc_…`, ADR 0011): a frozen answer. Peable decides
12
13
  * whether a registration covers the customer's evidenced location and asks
@@ -15,14 +16,14 @@ const shared_1 = require("./shared");
15
16
  */
16
17
  exports.taxBreakdownEntrySchema = (0, objects_1.defineComponent)('TaxBreakdownEntry', zod_1.z
17
18
  .object({
18
- country: shared_1.taxCountry,
19
- state: shared_1.taxState,
19
+ country: shared_2.taxCountry,
20
+ state: shared_2.taxState,
20
21
  level: primitives_1.nullableString.describe('The jurisdiction level (`country`, `state`, …).'),
21
22
  display_name: primitives_1.nullableString,
22
23
  tax_type: primitives_1.nullableString.describe('`vat`, `sales_tax`, …; `null` when no tax is imposed.'),
23
24
  rate_percentage: primitives_1.nullableString.describe('Decimal string, e.g. `"20.0"`; `null` when no tax is imposed.'),
24
- taxable_amount: shared_1.taxMinorAmount,
25
- amount: shared_1.taxMinorAmount,
25
+ taxable_amount: primitives_1.signedAmount,
26
+ amount: primitives_1.signedAmount,
26
27
  inclusive: zod_1.z.boolean(),
27
28
  taxability_reason: zod_1.z
28
29
  .string()
@@ -35,9 +36,9 @@ exports.taxCalculationLineItemSchema = (0, objects_1.defineComponent)('TaxCalcul
35
36
  quantity: zod_1.z.number().int(),
36
37
  tax_code: zod_1.z.string(),
37
38
  tax_behavior: zod_1.z.enum(tax_1.TAX_BEHAVIORS),
38
- amount: shared_1.taxMinorAmount.describe('As given: includes tax when inclusive.'),
39
- amount_tax: shared_1.taxMinorAmount,
40
- amount_net: shared_1.taxMinorAmount.describe('Excluding tax.'),
39
+ amount: primitives_1.signedAmount.describe('As given: includes tax when inclusive.'),
40
+ amount_tax: primitives_1.signedAmount,
41
+ amount_net: primitives_1.signedAmount.describe('Excluding tax.'),
41
42
  breakdown: zod_1.z.array(exports.taxBreakdownEntrySchema),
42
43
  })
43
44
  .strict());
@@ -53,12 +54,12 @@ exports.taxCalculationSchema = (0, objects_1.defineObject)('tax.calculation', 'T
53
54
  provider: primitives_1.nullableString,
54
55
  provider_calculation_ref: primitives_1.nullableString,
55
56
  customer_location_evidence_id: zod_1.z.string().describe('`taxloc_…`.'),
56
- country: shared_1.taxCountry,
57
- state: shared_1.taxState,
58
- amount_total: shared_1.taxMinorAmount.describe('What the customer pays.'),
59
- amount_net: shared_1.taxMinorAmount,
60
- tax_amount_exclusive: shared_1.taxMinorAmount,
61
- tax_amount_inclusive: shared_1.taxMinorAmount,
57
+ country: shared_2.taxCountry,
58
+ state: shared_2.taxState,
59
+ amount_total: primitives_1.amount.describe('What the customer pays.'),
60
+ amount_net: primitives_1.amount,
61
+ tax_amount_exclusive: primitives_1.amount,
62
+ tax_amount_inclusive: primitives_1.amount,
62
63
  line_items: zod_1.z.array(exports.taxCalculationLineItemSchema),
63
64
  tax_date: primitives_1.unixSeconds,
64
65
  created: primitives_1.unixSeconds,
@@ -78,19 +79,19 @@ exports.taxCalculationSchema = (0, objects_1.defineObject)('tax.calculation', 'T
78
79
  customer_location_evidence_id: 'taxloc_0193b8f2c1a87d3e9f4a',
79
80
  country: 'DE',
80
81
  state: null,
81
- amount_total: 1190,
82
- amount_net: 1000,
83
- tax_amount_exclusive: 190,
84
- tax_amount_inclusive: 0,
82
+ amount_total: '1190',
83
+ amount_net: '1000',
84
+ tax_amount_exclusive: '190',
85
+ tax_amount_inclusive: '0',
85
86
  line_items: [
86
87
  {
87
88
  reference: 'plan_pro_monthly',
88
89
  quantity: 1,
89
90
  tax_code: 'txcd_10103001',
90
91
  tax_behavior: 'exclusive',
91
- amount: 1000,
92
- amount_tax: 190,
93
- amount_net: 1000,
92
+ amount: '1000',
93
+ amount_tax: '190',
94
+ amount_net: '1000',
94
95
  breakdown: [
95
96
  {
96
97
  country: 'DE',
@@ -99,8 +100,8 @@ exports.taxCalculationSchema = (0, objects_1.defineObject)('tax.calculation', 'T
99
100
  display_name: 'VAT',
100
101
  tax_type: 'vat',
101
102
  rate_percentage: '19.0',
102
- taxable_amount: 1000,
103
- amount: 190,
103
+ taxable_amount: '1000',
104
+ amount: '190',
104
105
  inclusive: false,
105
106
  taxability_reason: 'standard_rated',
106
107
  },
@@ -114,15 +115,17 @@ exports.taxCalculationSchema = (0, objects_1.defineObject)('tax.calculation', 'T
114
115
  },
115
116
  ],
116
117
  });
118
+ /**
119
+ * The largest line a tax provider is asked to price: the provider's own API
120
+ * counts amounts in integers that stay exact in a JS number (Stripe Tax).
121
+ */
122
+ const TAX_LINE_AMOUNT_MAX = BigInt(Number.MAX_SAFE_INTEGER);
117
123
  exports.taxLineItemParams = zod_1.z
118
124
  .object({
119
125
  reference: zod_1.z.string().min(1).max(200),
120
- amount: zod_1.z
121
- .number()
122
- .int()
123
- .nonnegative()
124
- .safe()
125
- .describe('Unit amount × quantity, minor units. Includes tax when inclusive.'),
126
+ amount: shared_1.baseUnitAmountParam
127
+ .refine((value) => BigInt(value) <= TAX_LINE_AMOUNT_MAX, 'exceeds the largest amount a tax provider prices')
128
+ .describe('Unit amount × quantity, base units. Includes tax when inclusive.'),
126
129
  quantity: zod_1.z.number().int().positive().max(1000000).optional(),
127
130
  tax_code: zod_1.z
128
131
  .string()
@@ -137,7 +140,7 @@ exports.taxLineItemParams = zod_1.z
137
140
  exports.createTaxCalculationParams = zod_1.z
138
141
  .object({
139
142
  currency: zod_1.z.string().regex(/^[A-Za-z]{3}$/),
140
- customer_location_evidence_id: shared_1.taxReferenceParam.describe('Sufficient, unexpired evidence (`taxloc_…`).'),
143
+ customer_location_evidence_id: shared_2.taxReferenceParam.describe('Sufficient, unexpired evidence (`taxloc_…`).'),
141
144
  line_items: zod_1.z
142
145
  .array(exports.taxLineItemParams)
143
146
  .min(1)
@@ -26,8 +26,8 @@ exports.taxReportRowSchema = (0, objects_1.defineComponent)('TaxReportRow', zod_
26
26
  currency: zod_1.z.string().describe('Uppercase ISO 4217.'),
27
27
  transactions: zod_1.z.number().int().nonnegative(),
28
28
  reversals: zod_1.z.number().int().nonnegative().describe('Reversals netted into this row.'),
29
- taxable_amount: shared_1.taxMinorAmount,
30
- tax_amount: shared_1.taxMinorAmount,
29
+ taxable_amount: primitives_1.signedAmount,
30
+ tax_amount: primitives_1.signedAmount,
31
31
  })
32
32
  .strict());
33
33
  exports.taxReportSchema = (0, objects_1.defineObject)('tax.report', 'TaxReport', zod_1.z
@@ -55,8 +55,8 @@ exports.taxReportSchema = (0, objects_1.defineObject)('tax.report', 'TaxReport',
55
55
  currency: 'EUR',
56
56
  transactions: 42,
57
57
  reversals: 1,
58
- taxable_amount: 41000,
59
- tax_amount: 7790,
58
+ taxable_amount: '41000',
59
+ tax_amount: '7790',
60
60
  },
61
61
  ],
62
62
  },
@@ -1,17 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.complianceIdParam = exports.complianceTextParam = exports.complianceStateParam = exports.complianceCountryParam = exports.taxFacts = exports.taxCoverageLimitSchema = exports.taxRuleSourceSchema = exports.taxInstantParam = exports.taxReferenceParam = exports.taxMinorAmount = exports.taxState = exports.taxCountry = void 0;
3
+ exports.complianceIdParam = exports.complianceTextParam = exports.complianceStateParam = exports.complianceCountryParam = exports.taxFacts = exports.taxCoverageLimitSchema = exports.taxRuleSourceSchema = exports.taxInstantParam = exports.taxReferenceParam = exports.taxState = exports.taxCountry = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const objects_1 = require("../../common/objects");
6
6
  const params_1 = require("../../common/params");
7
7
  /**
8
8
  * Building blocks every Peable Tax resource shares.
9
9
  *
10
- * Tax AMOUNTS (calculations, transactions, the report) are integer JSON
11
- * numbers in the currency's minor unit, as Peable Tax has always answered
12
- * them: unlike a FAIR amount, a tax amount is denominated in a fiat currency
13
- * and is bounded by the safe-integer checks the calculator applies. Business
14
- * compliance (ADR 0020) amounts are base-unit strings, as ADR 0014 D1 has it.
10
+ * Every tax amount — a calculation's, a transaction's, a reversal's, a report
11
+ * row's, a compliance measure's — is a base-unit integer STRING of its
12
+ * `currency`, as ADR 0014 D1 has it for every amount on the wire: `amount`
13
+ * where it cannot be negative, `signedAmount` where a reversal makes it so
14
+ * (a line item and its breakdown carry a reversal's negative share, and a
15
+ * report row nets them in).
15
16
  */
16
17
  /** ISO 3166-1 alpha-2, as returned. */
17
18
  exports.taxCountry = zod_1.z.string().describe('ISO 3166-1 alpha-2.');
@@ -20,11 +21,6 @@ exports.taxState = zod_1.z
20
21
  .string()
21
22
  .nullable()
22
23
  .describe('ISO 3166-2 subdivision without the country prefix (`CA`, `QC`).');
23
- /** A minor-unit integer amount (cents), signed: a reversal's amounts are negative. */
24
- exports.taxMinorAmount = zod_1.z
25
- .number()
26
- .int()
27
- .describe('Minor units of `currency` (cents), as an integer.');
28
24
  /** A Peable-side reference: a product, a customer, a refund. */
29
25
  exports.taxReferenceParam = zod_1.z
30
26
  .string()
@@ -8,8 +8,8 @@ const params_1 = require("../../common/params");
8
8
  const primitives_1 = require("../../common/primitives");
9
9
  const route_1 = require("../../route");
10
10
  const tax_1 = require("../../vocabulary/tax");
11
+ const shared_1 = require("../catalog/shared");
11
12
  const calculations_1 = require("./calculations");
12
- const shared_1 = require("./shared");
13
13
  /**
14
14
  * A tax transaction (`taxtxn_…`, ADR 0011/0013): a calculation that was paid,
15
15
  * created by Peable when the payment it priced is accepted on its rail. The
@@ -24,9 +24,9 @@ const shared_1 = require("./shared");
24
24
  */
25
25
  exports.taxTransactionReversalSchema = (0, objects_1.defineComponent)('TaxTransactionReversal', zod_1.z
26
26
  .object({
27
- amount_total: shared_1.taxMinorAmount,
28
- amount_net: shared_1.taxMinorAmount,
29
- tax_amount: shared_1.taxMinorAmount,
27
+ amount_total: primitives_1.signedAmount,
28
+ amount_net: primitives_1.signedAmount,
29
+ tax_amount: primitives_1.signedAmount,
30
30
  line_items: zod_1.z.array(calculations_1.taxCalculationLineItemSchema),
31
31
  })
32
32
  .strict());
@@ -59,13 +59,10 @@ exports.createTaxReversalParams = zod_1.z
59
59
  .max(200)
60
60
  .regex(/^[A-Za-z0-9_.:-]+$/)
61
61
  .describe("The refund's own reference; a repeated reference returns the same reversal."),
62
- amount: zod_1.z
63
- .number()
64
- .int()
65
- .positive()
66
- .safe()
62
+ amount: shared_1.baseUnitAmountParam
63
+ .refine((value) => value !== '0', 'must be positive')
67
64
  .optional()
68
- .describe('Gross minor units refunded (what the payer got back). Omitted: everything not yet reversed.'),
65
+ .describe('Gross base units refunded (what the payer got back). Omitted: everything not yet reversed.'),
69
66
  })
70
67
  .strict();
71
68
  exports.taxTransactionRoutes = [
@@ -16,7 +16,7 @@ exports.isBaseUnitString = isBaseUnitString;
16
16
  * chain rail, and on the card rail the fiat set the provider settles for the
17
17
  * payment methods Orbit offers (cards, wallets, SEPA Debit, iDEAL, Bancontact,
18
18
  * EPS). A local method narrows it further per payment
19
- * (`PAYMENT_METHOD_CURRENCIES` in `paymentMethodConfiguration.ts`).
19
+ * (`PAYMENT_METHOD_CURRENCIES` in `paymentMethodConfigurations.ts`).
20
20
  *
21
21
  * A closed set, and the database mirrors it as a CHECK
22
22
  * (`db/schema/valueSets.ts`). ADR 0001 D4: the scale of an amount is a property
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  // Payment method breadth on the card rail (`pmc_…`, `pmd_…`). Zod-free.
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.PAYMENT_METHOD_UNAVAILABLE_REASONS = exports.PAYMENT_METHOD_CONFIGURATION_TYPES = void 0;
4
+ exports.PAYMENT_METHOD_CURRENCIES = exports.PAYMENT_METHOD_UNAVAILABLE_REASONS = exports.PAYMENT_METHOD_CONFIGURATION_TYPES = void 0;
5
+ const money_1 = require("./money");
5
6
  /**
6
7
  * The methods a configuration can turn on.
7
8
  *
@@ -34,3 +35,18 @@ exports.PAYMENT_METHOD_UNAVAILABLE_REASONS = [
34
35
  'provider_unsupported',
35
36
  'requires_card',
36
37
  ];
38
+ /**
39
+ * The currencies each method can take a payment in. A method is offered on a
40
+ * payment only when its currency is listed — so iDEAL never appears on a USD
41
+ * payment, and a payer is never shown a method that would fail.
42
+ */
43
+ exports.PAYMENT_METHOD_CURRENCIES = Object.freeze({
44
+ card: money_1.FIAT_CURRENCY_CODES,
45
+ apple_pay: money_1.FIAT_CURRENCY_CODES,
46
+ google_pay: money_1.FIAT_CURRENCY_CODES,
47
+ sepa_debit: ['EUR'],
48
+ ideal: ['EUR'],
49
+ bancontact: ['EUR'],
50
+ eps: ['EUR'],
51
+ bizum: ['EUR'],
52
+ });
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { defineComponent } from '../../common/objects.js';
3
+ import { amount } from '../../common/primitives.js';
3
4
  import { defineRoute } from '../../route.js';
4
5
  import { BILLING_RAIL_RENEWALS, BILLING_RAIL_SETTLEMENTS, BILLING_SUBSCRIPTION_STATUSES, } from '../../vocabulary/catalog.js';
5
6
  /**
@@ -47,8 +48,6 @@ export const billingReturnUrl = z
47
48
  }, 'An HTTPS return URL without credentials is required');
48
49
  /** An instant in signed billing evidence: integer Unix seconds that stay a safe integer. */
49
50
  export const billingInstant = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
50
- /** A whole number of minor units (cents) in signed billing evidence. */
51
- const minorUnits = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
52
51
  /** A billing customer reference (`cus_…`). */
53
52
  export const billingCustomerRef = z
54
53
  .string()
@@ -82,7 +81,7 @@ export const billingRailOfferSchema = defineComponent('BillingRailOffer', z
82
81
  plan_id: z.string(),
83
82
  interval: billingInterval,
84
83
  currency: z.string(),
85
- gross_minor_units: z.number().int(),
84
+ gross_minor_units: amount,
86
85
  tax_treatment: taxTreatment,
87
86
  })
88
87
  .strict());
@@ -131,10 +130,10 @@ export const createBillingTaxQuoteParams = z
131
130
  customer_location_evidence_id: billingReference.describe('A `tax.location_evidence` id (`taxloc_…`) recorded for this `store_id`.'),
132
131
  })
133
132
  .strict();
134
- /** A signed, immutable, single-use Peable Tax quote (schema version 2). */
133
+ /** A signed, immutable, single-use Peable Tax quote (schema version 3). */
135
134
  export const billingTaxQuoteSchema = defineComponent('BillingTaxQuote', z
136
135
  .object({
137
- schema_version: z.literal(2),
136
+ schema_version: z.literal(3),
138
137
  source: z
139
138
  .object({
140
139
  merchant_id: billingReference,
@@ -149,9 +148,9 @@ export const billingTaxQuoteSchema = defineComponent('BillingTaxQuote', z
149
148
  .object({
150
149
  id: billingReference,
151
150
  currency: z.string().regex(/^[A-Z]{3}$/),
152
- gross_minor_units: minorUnits,
153
- net_minor_units: minorUnits,
154
- tax_minor_units: minorUnits,
151
+ gross_minor_units: amount,
152
+ net_minor_units: amount,
153
+ tax_minor_units: amount,
155
154
  tax_treatment: taxTreatment,
156
155
  seller_id: billingReference,
157
156
  invoice_issuer_id: billingReference,
@@ -220,7 +219,7 @@ export const billingEmbeddedCheckoutActionSchema = defineComponent('BillingEmbed
220
219
  session_id: z.string(),
221
220
  client_secret: z.string(),
222
221
  publishable_key: z.string(),
223
- amount_minor_units: z.number().int(),
222
+ amount_minor_units: amount,
224
223
  currency: z.string(),
225
224
  })
226
225
  .strict());
@@ -350,10 +349,9 @@ export const billingPaidInvoiceSchema = defineComponent('BillingPaidInvoice', z
350
349
  plan_id: z.string(),
351
350
  livemode: z.boolean(),
352
351
  currency: z.string(),
353
- amount_paid: z.string(),
354
- net_amount: z.string().nullable(),
355
- tax_amount: z
356
- .string()
352
+ amount_paid: amount,
353
+ net_amount: amount.nullable(),
354
+ tax_amount: amount
357
355
  .nullable()
358
356
  .describe('A provider observation, not a tax quote or seller configuration.'),
359
357
  period_start: z.number().int(),
@@ -365,7 +363,7 @@ export const billingPaidInvoiceSchema = defineComponent('BillingPaidInvoice', z
365
363
  export const billingInvoiceStateSchema = defineComponent('BillingInvoiceState', billingPaidInvoiceSchema
366
364
  .extend({
367
365
  charge_id: z.string(),
368
- amount_refunded: z.string(),
366
+ amount_refunded: amount,
369
367
  state: z.enum(['paid', 'fully_refunded', 'partially_refunded']),
370
368
  })
371
369
  .strict());
@@ -377,8 +375,8 @@ export const billingInvoiceTaxLineSchema = defineComponent('BillingInvoiceTaxLin
377
375
  state: z.string().nullable(),
378
376
  tax_type: z.string().nullable(),
379
377
  rate_percentage: z.string().nullable(),
380
- taxable_minor_units: minorUnits,
381
- tax_minor_units: minorUnits,
378
+ taxable_minor_units: amount,
379
+ tax_minor_units: amount,
382
380
  inclusive: z.boolean(),
383
381
  taxability_reason: z.string().min(1),
384
382
  })
@@ -406,10 +404,10 @@ export const billingFinalInvoiceSchema = defineComponent('BillingFinalInvoice',
406
404
  .object({
407
405
  platform: z.literal('peable'),
408
406
  currency: z.string().regex(/^[A-Z]{3}$/),
409
- gross_minor_units: minorUnits,
410
- net_minor_units: minorUnits,
411
- tax_minor_units: minorUnits,
412
- merchant_fee_minor_units: minorUnits,
407
+ gross_minor_units: amount,
408
+ net_minor_units: amount,
409
+ tax_minor_units: amount,
410
+ merchant_fee_minor_units: amount,
413
411
  tax_treatment: taxTreatment,
414
412
  seller_id: billingReference,
415
413
  invoice_issuer_id: billingReference,
@@ -452,10 +450,10 @@ export const billingFinalInvoiceSchema = defineComponent('BillingFinalInvoice',
452
450
  .describe('Present only when asked for (`include=tax_lines`): the frozen Peable Tax lines behind `tax_minor_units`, covered by the same signature.'),
453
451
  })
454
452
  .strict());
455
- /** A signed final invoice authority (schema version 2). Verify it against the pinned keys. */
453
+ /** A signed final invoice authority (schema version 3). Verify it against the pinned keys. */
456
454
  export const billingFinalInvoiceAuthoritySchema = defineComponent('BillingFinalInvoiceAuthority', z
457
455
  .object({
458
- schema_version: z.literal(2),
456
+ schema_version: z.literal(3),
459
457
  source: billingInvoiceAuthoritySourceSchema,
460
458
  invoice: billingFinalInvoiceSchema,
461
459
  method: z.enum(['card', 'faircoin']),
@@ -523,7 +521,7 @@ export const billingFaircoinFxQuoteSchema = defineComponent('BillingFaircoinFxQu
523
521
  .object({
524
522
  id: z.string(),
525
523
  currency: z.literal('USD'),
526
- gross_minor_units: z.number().int(),
524
+ gross_minor_units: amount,
527
525
  amount_base_units: z.string(),
528
526
  usd_per_fair: z.string(),
529
527
  source: z.string(),
@@ -1,9 +1,10 @@
1
1
  import { z } from 'zod';
2
2
  import { defineComponent, defineObject } from '../../common/objects.js';
3
- import { livemode, nullableString, unixSeconds } from '../../common/primitives.js';
3
+ import { amount, livemode, nullableString, signedAmount, unixSeconds, } from '../../common/primitives.js';
4
4
  import { defineRoute } from '../../route.js';
5
5
  import { TAX_BEHAVIORS, TAX_COLLECTIONS } from '../../vocabulary/tax.js';
6
- import { taxCountry, taxMinorAmount, taxReferenceParam, taxState } from './shared.js';
6
+ import { baseUnitAmountParam } from '../catalog/shared.js';
7
+ import { taxCountry, taxReferenceParam, taxState } from './shared.js';
7
8
  /**
8
9
  * A tax calculation (`taxcalc_…`, ADR 0011): a frozen answer. Peable decides
9
10
  * whether a registration covers the customer's evidenced location and asks
@@ -18,8 +19,8 @@ export const taxBreakdownEntrySchema = defineComponent('TaxBreakdownEntry', z
18
19
  display_name: nullableString,
19
20
  tax_type: nullableString.describe('`vat`, `sales_tax`, …; `null` when no tax is imposed.'),
20
21
  rate_percentage: nullableString.describe('Decimal string, e.g. `"20.0"`; `null` when no tax is imposed.'),
21
- taxable_amount: taxMinorAmount,
22
- amount: taxMinorAmount,
22
+ taxable_amount: signedAmount,
23
+ amount: signedAmount,
23
24
  inclusive: z.boolean(),
24
25
  taxability_reason: z
25
26
  .string()
@@ -32,9 +33,9 @@ export const taxCalculationLineItemSchema = defineComponent('TaxCalculationLineI
32
33
  quantity: z.number().int(),
33
34
  tax_code: z.string(),
34
35
  tax_behavior: z.enum(TAX_BEHAVIORS),
35
- amount: taxMinorAmount.describe('As given: includes tax when inclusive.'),
36
- amount_tax: taxMinorAmount,
37
- amount_net: taxMinorAmount.describe('Excluding tax.'),
36
+ amount: signedAmount.describe('As given: includes tax when inclusive.'),
37
+ amount_tax: signedAmount,
38
+ amount_net: signedAmount.describe('Excluding tax.'),
38
39
  breakdown: z.array(taxBreakdownEntrySchema),
39
40
  })
40
41
  .strict());
@@ -52,10 +53,10 @@ export const taxCalculationSchema = defineObject('tax.calculation', 'TaxCalculat
52
53
  customer_location_evidence_id: z.string().describe('`taxloc_…`.'),
53
54
  country: taxCountry,
54
55
  state: taxState,
55
- amount_total: taxMinorAmount.describe('What the customer pays.'),
56
- amount_net: taxMinorAmount,
57
- tax_amount_exclusive: taxMinorAmount,
58
- tax_amount_inclusive: taxMinorAmount,
56
+ amount_total: amount.describe('What the customer pays.'),
57
+ amount_net: amount,
58
+ tax_amount_exclusive: amount,
59
+ tax_amount_inclusive: amount,
59
60
  line_items: z.array(taxCalculationLineItemSchema),
60
61
  tax_date: unixSeconds,
61
62
  created: unixSeconds,
@@ -75,19 +76,19 @@ export const taxCalculationSchema = defineObject('tax.calculation', 'TaxCalculat
75
76
  customer_location_evidence_id: 'taxloc_0193b8f2c1a87d3e9f4a',
76
77
  country: 'DE',
77
78
  state: null,
78
- amount_total: 1190,
79
- amount_net: 1000,
80
- tax_amount_exclusive: 190,
81
- tax_amount_inclusive: 0,
79
+ amount_total: '1190',
80
+ amount_net: '1000',
81
+ tax_amount_exclusive: '190',
82
+ tax_amount_inclusive: '0',
82
83
  line_items: [
83
84
  {
84
85
  reference: 'plan_pro_monthly',
85
86
  quantity: 1,
86
87
  tax_code: 'txcd_10103001',
87
88
  tax_behavior: 'exclusive',
88
- amount: 1000,
89
- amount_tax: 190,
90
- amount_net: 1000,
89
+ amount: '1000',
90
+ amount_tax: '190',
91
+ amount_net: '1000',
91
92
  breakdown: [
92
93
  {
93
94
  country: 'DE',
@@ -96,8 +97,8 @@ export const taxCalculationSchema = defineObject('tax.calculation', 'TaxCalculat
96
97
  display_name: 'VAT',
97
98
  tax_type: 'vat',
98
99
  rate_percentage: '19.0',
99
- taxable_amount: 1000,
100
- amount: 190,
100
+ taxable_amount: '1000',
101
+ amount: '190',
101
102
  inclusive: false,
102
103
  taxability_reason: 'standard_rated',
103
104
  },
@@ -111,15 +112,17 @@ export const taxCalculationSchema = defineObject('tax.calculation', 'TaxCalculat
111
112
  },
112
113
  ],
113
114
  });
115
+ /**
116
+ * The largest line a tax provider is asked to price: the provider's own API
117
+ * counts amounts in integers that stay exact in a JS number (Stripe Tax).
118
+ */
119
+ const TAX_LINE_AMOUNT_MAX = BigInt(Number.MAX_SAFE_INTEGER);
114
120
  export const taxLineItemParams = z
115
121
  .object({
116
122
  reference: z.string().min(1).max(200),
117
- amount: z
118
- .number()
119
- .int()
120
- .nonnegative()
121
- .safe()
122
- .describe('Unit amount × quantity, minor units. Includes tax when inclusive.'),
123
+ amount: baseUnitAmountParam
124
+ .refine((value) => BigInt(value) <= TAX_LINE_AMOUNT_MAX, 'exceeds the largest amount a tax provider prices')
125
+ .describe('Unit amount × quantity, base units. Includes tax when inclusive.'),
123
126
  quantity: z.number().int().positive().max(1000000).optional(),
124
127
  tax_code: z
125
128
  .string()