@peable.to/contracts 3.1.0 → 4.1.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.
Files changed (43) hide show
  1. package/dist/cjs/resources/billingEngine/public.js +22 -3
  2. package/dist/cjs/resources/checkout/checkoutSessions.js +34 -9
  3. package/dist/cjs/resources/checkout/merchants.js +10 -23
  4. package/dist/cjs/resources/checkout/paymentMethodConfigurations.js +56 -10
  5. package/dist/cjs/resources/connect/balance.js +5 -0
  6. package/dist/cjs/resources/connect/connectedAccounts.js +11 -12
  7. package/dist/cjs/resources/connect/onboarding.js +13 -24
  8. package/dist/cjs/resources/payments/paymentIntents.js +39 -2
  9. package/dist/cjs/vocabulary/checkout.js +18 -1
  10. package/dist/cjs/vocabulary/errors.js +5 -3
  11. package/dist/cjs/vocabulary/paymentMethodConfigurations.js +24 -4
  12. package/dist/esm/resources/billingEngine/public.js +22 -3
  13. package/dist/esm/resources/checkout/checkoutSessions.js +35 -10
  14. package/dist/esm/resources/checkout/merchants.js +10 -23
  15. package/dist/esm/resources/checkout/paymentMethodConfigurations.js +57 -11
  16. package/dist/esm/resources/connect/balance.js +5 -0
  17. package/dist/esm/resources/connect/connectedAccounts.js +11 -12
  18. package/dist/esm/resources/connect/onboarding.js +12 -23
  19. package/dist/esm/resources/payments/paymentIntents.js +39 -2
  20. package/dist/esm/vocabulary/checkout.js +17 -0
  21. package/dist/esm/vocabulary/errors.js +5 -3
  22. package/dist/esm/vocabulary/paymentMethodConfigurations.js +25 -5
  23. package/dist/types/resources/billingEngine/index.d.ts +16 -2
  24. package/dist/types/resources/billingEngine/public.d.ts +32 -3
  25. package/dist/types/resources/checkout/checkoutSessions.d.ts +96 -31
  26. package/dist/types/resources/checkout/index.d.ts +406 -41
  27. package/dist/types/resources/checkout/merchants.d.ts +17 -28
  28. package/dist/types/resources/checkout/paymentMethodConfigurations.d.ts +440 -8
  29. package/dist/types/resources/connect/balance.d.ts +98 -5
  30. package/dist/types/resources/connect/connectedAccounts.d.ts +4 -4
  31. package/dist/types/resources/connect/index.d.ts +101 -10
  32. package/dist/types/resources/connect/onboarding.d.ts +15 -15
  33. package/dist/types/resources/connect/payouts.d.ts +64 -2
  34. package/dist/types/resources/payments/index.d.ts +310 -0
  35. package/dist/types/resources/payments/paymentIntents.d.ts +380 -0
  36. package/dist/types/resources/payments/testHelpers.d.ts +31 -0
  37. package/dist/types/resources/tax/deadlines.d.ts +3 -3
  38. package/dist/types/resources/tax/index.d.ts +2 -2
  39. package/dist/types/resources/tax/registrations.d.ts +2 -2
  40. package/dist/types/vocabulary/checkout.d.ts +13 -0
  41. package/dist/types/vocabulary/errors.d.ts +5 -3
  42. package/dist/types/vocabulary/paymentMethodConfigurations.d.ts +21 -7
  43. package/package.json +1 -1
@@ -8,6 +8,7 @@ const params_1 = require("../../common/params");
8
8
  const primitives_1 = require("../../common/primitives");
9
9
  const route_1 = require("../../route");
10
10
  const billingPortal_1 = require("../../vocabulary/billingPortal");
11
+ const checkout_1 = require("../../vocabulary/checkout");
11
12
  const invoices_1 = require("../../vocabulary/invoices");
12
13
  const subscriptions_1 = require("../../vocabulary/subscriptions");
13
14
  const billingPortal_2 = require("./billingPortal");
@@ -57,7 +58,17 @@ exports.publicInvoiceSchema = (0, objects_1.defineObject)('public_invoice', 'Pub
57
58
  paid_at: primitives_1.unixSeconds.nullable(),
58
59
  payment_method_types: zod_1.z
59
60
  .array(zod_1.z.enum(invoices_1.PUBLIC_INVOICE_PAYMENT_METHOD_TYPES))
60
- .describe("Which rail pays it: a card through the provider's fields, FairCoin from the payer's wallet."),
61
+ .describe("What the payer may choose: `['card', 'faircoin']` on a fiat invoice, `['faircoin']` on a FAIR one. FairCoin is always offered (ADR 0021); on a fiat invoice it is quoted when chosen."),
62
+ faircoin: zod_1.z
63
+ .object({
64
+ available: zod_1.z.boolean(),
65
+ unavailable_reason: zod_1.z
66
+ .enum(checkout_1.FAIRCOIN_UNAVAILABLE_REASONS)
67
+ .nullable()
68
+ .describe('Why FairCoin cannot be paid with right now; it is still shown, never hidden.'),
69
+ })
70
+ .strict()
71
+ .describe('Whether the payer can choose FairCoin now (ADR 0021).'),
61
72
  invoice_pdf: zod_1.z.string(),
62
73
  })
63
74
  .strict());
@@ -181,7 +192,15 @@ exports.portalPaymentMethodUpdateResultSchema = (0, objects_1.defineComponent)('
181
192
  })
182
193
  .strict());
183
194
  // ---- Requests ------------------------------------------------------------------------
184
- exports.payPublicInvoiceParams = params_2.emptyBody;
195
+ /** How the payer pays the invoice (ADR 0021 D3). */
196
+ exports.payPublicInvoiceParams = zod_1.z
197
+ .object({
198
+ payment_method_type: zod_1.z
199
+ .enum(invoices_1.PUBLIC_INVOICE_PAYMENT_METHOD_TYPES)
200
+ .optional()
201
+ .describe("One of the invoice's `payment_method_types`. Default: the rail of its currency (`card` on a fiat invoice). `faircoin` on a fiat invoice quotes the amount due in FAIR for 10 minutes; paying again with the other method replaces a payment that has not started moving money."),
202
+ })
203
+ .strict();
185
204
  /** A portal action on one of the customer's subscriptions. */
186
205
  exports.portalSubscriptionParams = zod_1.z.object({ subscription: params_1.idParam }).strict();
187
206
  /** Switch a (single-item) subscription to one of the configuration's plans, or change its quantity. */
@@ -224,7 +243,7 @@ exports.publicBillingRoutes = [
224
243
  path: '/v1/invoices/public/{token}/pay',
225
244
  tag: 'Hosted invoices',
226
245
  summary: 'Pay a hosted invoice',
227
- description: 'The PaymentIntent the payer completes — a card through the provider’s own fields, FairCoin from the payer’s wallet. The same invoice answers the same intent while it can still be paid.',
246
+ description: 'The PaymentIntent the payer completes in the method they chose — a card through the provider’s own fields, or FairCoin from the payer’s wallet (quoted on a fiat invoice, ADR 0021). The same invoice answers the same intent while it can still be paid in that method.',
228
247
  auth: 'public',
229
248
  params: invoiceToken,
230
249
  body: exports.payPublicInvoiceParams,
@@ -33,8 +33,13 @@ const sessionFields = {
33
33
  .describe("The language checkout renders in; `null` follows the payer's browser."),
34
34
  submit_type: zod_1.z.enum(checkout_1.CHECKOUT_SUBMIT_TYPES),
35
35
  currency: primitives_1.currency,
36
- rail: shared_1.railSchema,
37
- network: primitives_1.network.nullable().describe('FairCoin rail only; `null` on a card session.'),
36
+ rail: shared_1.railSchema.describe("The rail that settles the order's currency: `faircoin` for a FAIR order, `card` for a fiat one. FairCoin is offered on every order beside it (`payment_method_types`, ADR 0021)."),
37
+ network: primitives_1.network
38
+ .nullable()
39
+ .describe('The FairCoin network a FairCoin payment of this order uses — the merchant’s (or the seller’s); `null` when the payee has no FairCoin key yet (test mode) and in `setup` mode.'),
40
+ payment_method_types: zod_1.z
41
+ .array(shared_1.railSchema)
42
+ .describe("What the payer may choose: `['card', 'faircoin']` on a fiat order (`['faircoin']` when the merchant offered FairCoin only), `['faircoin']` on a FAIR one. FairCoin is always offered (ADR 0021); `['card']` in `setup` mode."),
38
43
  amount_subtotal: primitives_1.amount,
39
44
  amount_total: primitives_1.amount,
40
45
  total_details: shared_1.checkoutTotalDetailsSchema,
@@ -49,7 +54,6 @@ const sessionFields = {
49
54
  exports.checkoutSessionSchema = (0, objects_2.defineObject)('checkout_session', 'CheckoutSession', zod_1.z
50
55
  .object({
51
56
  ...sessionFields,
52
- payment_method_types: zod_1.z.array(shared_1.railSchema),
53
57
  discounts: zod_1.z.array(shared_1.checkoutDiscountSchema),
54
58
  customer: (0, objects_2.expandable)('customer', '`cus_…` (expandable) — given on create, or created at completion.').nullable(),
55
59
  customer_email: zod_1.z.string().nullable(),
@@ -93,8 +97,8 @@ exports.checkoutSessionSchema = (0, objects_2.defineObject)('checkout_session',
93
97
  submit_type: 'auto',
94
98
  currency: 'EUR',
95
99
  rail: 'card',
96
- network: null,
97
- payment_method_types: ['card'],
100
+ network: 'mainnet',
101
+ payment_method_types: ['card', 'faircoin'],
98
102
  amount_subtotal: '1999',
99
103
  amount_total: '1999',
100
104
  total_details: { amount_discount: '0', amount_tax: '0', amount_shipping: '0' },
@@ -182,6 +186,17 @@ exports.checkoutSessionPublicSchema = (0, objects_2.defineComponent)('CheckoutSe
182
186
  .string()
183
187
  .nullable()
184
188
  .describe("The card provider's PUBLIC key for this session's mode, so the payment fields can mount before the payment exists. `null` on FairCoin."),
189
+ faircoin: zod_1.z
190
+ .object({
191
+ available: zod_1.z.boolean(),
192
+ unavailable_reason: zod_1.z
193
+ .enum(checkout_1.FAIRCOIN_UNAVAILABLE_REASONS)
194
+ .nullable()
195
+ .describe('Why FairCoin cannot be paid with right now; it is still shown, never hidden.'),
196
+ })
197
+ .strict()
198
+ .nullable()
199
+ .describe('Whether the payer can choose FairCoin now (ADR 0021). On a fiat order the FAIR amount is quoted when the payer chooses it (`payment_intent.faircoin.quote`). `null` in `setup` mode.'),
185
200
  })
186
201
  .strict());
187
202
  // ---- Merchant create/update ---------------------------------------------------
@@ -282,9 +297,9 @@ exports.createCheckoutSessionParams = zod_1.z
282
297
  payment_method_types: zod_1.z
283
298
  .array(zod_1.z.enum(['card', 'faircoin']))
284
299
  .min(1)
285
- .max(1)
300
+ .max(2)
286
301
  .optional()
287
- .describe("`['card']` or `['faircoin']` — the rail the line items' currency allows."),
302
+ .describe("Must include `faircoin`, which is always offered (ADR 0021; leaving it out is 400 `payment_method_locked`). On a fiat order `['card', 'faircoin']` (the default) or `['faircoin']` — a FairCoin-only order, the fiat methods being the merchant's to turn off; on a FAIR order `['faircoin']`. Which card methods are offered comes from the payment method configuration."),
288
303
  locale: shared_1.localeParam.optional(),
289
304
  ui_mode: zod_1.z.enum(checkout_1.CHECKOUT_UI_MODES).optional(),
290
305
  success_url: shared_1.redirectUrlParam
@@ -428,8 +443,18 @@ exports.updateCheckoutSessionPublicParams = zod_1.z
428
443
  .optional(),
429
444
  })
430
445
  .strict();
431
- /** `POST /v1/checkout_sessions/{id}/public/confirm` takes nothing: the order is the session's. */
432
- exports.confirmCheckoutSessionPublicParams = zod_1.z.object({}).strict();
446
+ /**
447
+ * `POST /v1/checkout_sessions/{id}/public/confirm` — the order is the
448
+ * session's; the payer only chooses how to pay it (ADR 0021 D3).
449
+ */
450
+ exports.confirmCheckoutSessionPublicParams = zod_1.z
451
+ .object({
452
+ payment_method_type: zod_1.z
453
+ .enum(['card', 'faircoin'])
454
+ .optional()
455
+ .describe("How the payer pays: one of the session's `payment_method_types`. Default: the rail of the order's currency (`card` on a fiat order). `faircoin` on a fiat order quotes its total in FAIR for 10 minutes; confirming again with the other method replaces a payment that has not started moving money."),
456
+ })
457
+ .strict();
433
458
  /** `POST /v1/test_helpers/checkout_sessions/{id}/expire` takes nothing. */
434
459
  exports.expireCheckoutSessionTestHelperParams = zod_1.z.object({}).strict();
435
460
  const sessionId = { id: 'The Checkout Session (`cs_…`).' };
@@ -20,13 +20,11 @@ exports.merchantSchema = (0, objects_1.defineObject)('merchant', 'Merchant', zod
20
20
  livemode: primitives_1.livemode.describe('`true` for a `production` merchant (ADR 0017).'),
21
21
  oxy_app_id: zod_1.z.string().describe('The Oxy application this merchant belongs to.'),
22
22
  environment: zod_1.z.enum(merchants_1.MERCHANT_ENVIRONMENTS),
23
- network: primitives_1.network
24
- .nullable()
25
- .describe('The FairCoin chain this merchant accepts on; `null` on a card-only merchant. Nullable together with `xpub`.'),
26
- xpub: zod_1.z
23
+ network: primitives_1.network.describe("The FairCoin network this merchant's payments use — its environment's: `mainnet` live, `testnet` otherwise (ADR 0021 D5)."),
24
+ owner_account: zod_1.z
27
25
  .string()
28
26
  .nullable()
29
- .describe('The watch-only account key receive addresses derive from; `null` on a card-only merchant.'),
27
+ .describe('The Oxy account (a person or an organization) that owns the application — its Peable wallet receives the merchant’s FairCoin (ADR 0021 D5). No key is ever registered. `null` until Peable has seen the owner.'),
30
28
  required_confirmations: zod_1.z.number().int().positive(),
31
29
  display_name: zod_1.z
32
30
  .string()
@@ -53,7 +51,7 @@ exports.merchantSchema = (0, objects_1.defineObject)('merchant', 'Merchant', zod
53
51
  oxy_app_id: 'app_0193b8f2c1a87d3e9f4b',
54
52
  environment: 'development',
55
53
  network: 'testnet',
56
- xpub: 'tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba',
54
+ owner_account: '0193b8f2-c1a8-7d3e-9f4a-5b6c7d8e9f01',
57
55
  required_confirmations: 6,
58
56
  display_name: 'Jenny’s Plants',
59
57
  created: 1793750400,
@@ -69,32 +67,21 @@ const displayName = zod_1.z.string().min(1).max(64);
69
67
  const avatarFileId = zod_1.z.string().min(1).max(128);
70
68
  const merchantDescription = zod_1.z.string().min(1).max(512);
71
69
  /**
72
- * `POST /v1/merchants`. The FairCoin half is OPTIONAL — both `network` and
73
- * `xpub`, or neither: a card-only merchant supplies no key for a chain it
74
- * never intends to use.
70
+ * `POST /v1/merchants`. No FairCoin key and no network: the network is the
71
+ * environment's, and FairCoin is received into the Peable wallet of the
72
+ * account that owns the application (ADR 0021 D5).
75
73
  */
76
74
  exports.registerMerchantParams = zod_1.z
77
75
  .object({
78
- network: primitives_1.network.optional(),
79
- xpub: zod_1.z
80
- .string()
81
- .min(1)
82
- .optional()
83
- .describe('A watch-only account xpub. A private extended key is refused.'),
84
76
  required_confirmations: zod_1.z.number().int().positive().optional(),
85
77
  display_name: displayName.optional(),
86
78
  avatar_file_id: avatarFileId.optional(),
87
79
  description: merchantDescription.optional(),
88
80
  })
89
- .strict()
90
- .refine((body) => (body.network === undefined) === (body.xpub === undefined), {
91
- message: 'accepting FairCoin needs both a network and a watch-only xpub, or neither — ' +
92
- 'omit both to register a card-only merchant',
93
- });
81
+ .strict();
94
82
  /**
95
- * `POST /v1/merchants/me`. `null` clears a field. The key, network and
96
- * environment never change: addresses already derived from the key, and the
97
- * test/live firewall, depend on them.
83
+ * `POST /v1/merchants/me`. `null` clears a field. The network and environment
84
+ * never change: the test/live firewall depends on them.
98
85
  */
99
86
  exports.updateMerchantParams = zod_1.z
100
87
  .object({
@@ -9,11 +9,13 @@ const primitives_1 = require("../../common/primitives");
9
9
  const route_1 = require("../../route");
10
10
  const paymentMethodConfigurations_1 = require("../../vocabulary/paymentMethodConfigurations");
11
11
  /**
12
- * Payment method breadth on the card rail — which methods a merchant's payers
13
- * are offered (`pmc_…`), and the web domains wallets may run on (`pmd_…`).
14
- * Both are Orbit's objects; the provider's configuration and domain are
15
- * bindings behind them (ADR 0016). Card data and bank credentials are entered
16
- * in the provider's hosted fields and never reach Peable (PCI SAQ-A).
12
+ * Payment method breadth — which methods a merchant's payers are offered
13
+ * (`pmc_…`), and the web domains wallets may run on (`pmd_…`). FairCoin is an
14
+ * entry of every configuration and is locked on (ADR 0021 D2); the card-rail
15
+ * methods are the merchant's choice. Both are Orbit's objects; the provider's
16
+ * configuration and domain are bindings behind them (ADR 0016). Card data and
17
+ * bank credentials are entered in the provider's hosted fields and never reach
18
+ * Peable (PCI SAQ-A).
17
19
  */
18
20
  /** The merchant's choice (`none`: Orbit's default) and what is in effect. */
19
21
  exports.paymentMethodDisplayPreferenceSchema = zod_1.z
@@ -28,13 +30,28 @@ exports.paymentMethodConfigurationEntrySchema = (0, objects_1.defineComponent)('
28
30
  .boolean()
29
31
  .describe('Whether payers can be offered this method: it is on and nothing prevents it.'),
30
32
  display_preference: exports.paymentMethodDisplayPreferenceSchema,
33
+ locked: zod_1.z
34
+ .boolean()
35
+ .describe('Whether the merchant can change it. Only `faircoin` is locked: it is always on, because every payer can always pay with FairCoin (ADR 0021), and setting it `off` is refused with `payment_method_locked`.'),
31
36
  unavailable_reason: zod_1.z
32
37
  .enum(paymentMethodConfigurations_1.PAYMENT_METHOD_UNAVAILABLE_REASONS)
33
38
  .nullable()
34
39
  .describe('Why it cannot be offered whatever the merchant chooses; `null` when it can.'),
35
- currencies: zod_1.z.array(primitives_1.fiatCurrency).describe('The payment currencies it is offered on.'),
40
+ currencies: zod_1.z.array(primitives_1.currency).describe('The payment currencies it is offered on.'),
36
41
  })
37
42
  .strict());
43
+ /** One entry of the configuration's documented example (abbreviated currency lists). */
44
+ function exampleEntry(preference, value, overrides = {}) {
45
+ const unavailable_reason = overrides.unavailable_reason ?? null;
46
+ return {
47
+ available: value === 'on' && unavailable_reason === null,
48
+ display_preference: { preference, value },
49
+ locked: false,
50
+ unavailable_reason,
51
+ currencies: ['EUR', 'USD', 'GBP'],
52
+ ...overrides,
53
+ };
54
+ }
38
55
  const entryFields = Object.fromEntries(paymentMethodConfigurations_1.PAYMENT_METHOD_CONFIGURATION_TYPES.map((type) => [type, exports.paymentMethodConfigurationEntrySchema]));
39
56
  exports.paymentMethodConfigurationSchema = (0, objects_1.defineObject)('payment_method_configuration', 'PaymentMethodConfiguration', zod_1.z
40
57
  .object({
@@ -52,7 +69,32 @@ exports.paymentMethodConfigurationSchema = (0, objects_1.defineObject)('payment_
52
69
  updated_at: primitives_1.unixSeconds,
53
70
  ...entryFields,
54
71
  })
55
- .strict());
72
+ .strict(), {
73
+ examples: [
74
+ {
75
+ id: 'pmc_0193b8f2c1a87d3e9f4b',
76
+ object: 'payment_method_configuration',
77
+ livemode: false,
78
+ name: 'Default',
79
+ active: true,
80
+ is_default: true,
81
+ created: 1793750400,
82
+ updated_at: 1793750400,
83
+ faircoin: exampleEntry('on', 'on', { locked: true, currencies: ['FAIR', 'EUR', 'USD'] }),
84
+ card: exampleEntry('none', 'on'),
85
+ apple_pay: exampleEntry('none', 'on'),
86
+ google_pay: exampleEntry('none', 'on'),
87
+ sepa_debit: exampleEntry('on', 'on', { currencies: ['EUR'] }),
88
+ ideal: exampleEntry('none', 'off', { currencies: ['EUR'] }),
89
+ bancontact: exampleEntry('none', 'off', { currencies: ['EUR'] }),
90
+ eps: exampleEntry('none', 'off', { currencies: ['EUR'] }),
91
+ bizum: exampleEntry('none', 'off', {
92
+ currencies: ['EUR'],
93
+ unavailable_reason: 'provider_unsupported',
94
+ }),
95
+ },
96
+ ],
97
+ });
56
98
  /** A wallet's standing on one domain. */
57
99
  exports.paymentMethodDomainWalletStatusSchema = (0, objects_1.defineComponent)('PaymentMethodDomainWalletStatus', zod_1.z
58
100
  .object({
@@ -95,7 +137,11 @@ exports.paymentMethodDomainSchema = (0, objects_1.defineObject)('payment_method_
95
137
  },
96
138
  ],
97
139
  });
98
- /** One method's setting in a create or update. `none` returns it to Orbit's default. */
140
+ /**
141
+ * One method's setting in a create or update. `none` returns it to Orbit's
142
+ * default. For `faircoin` only `on` and `none` are accepted, and neither stores
143
+ * anything: it is always on, and `off` is refused with `payment_method_locked`.
144
+ */
99
145
  exports.paymentMethodConfigurationEntryParams = zod_1.z
100
146
  .object({
101
147
  display_preference: zod_1.z.object({ preference: zod_1.z.enum(['on', 'off', 'none']) }).strict(),
@@ -153,7 +199,7 @@ exports.paymentMethodConfigurationRoutes = [
153
199
  path: '/v1/payment_method_configurations',
154
200
  tag: 'Payment method configurations',
155
201
  summary: 'Create a payment method configuration',
156
- description: 'An additional, non-default configuration. Turning `on` a method the processing provider does not offer is refused.',
202
+ description: 'An additional, non-default configuration. Turning `on` a method the processing provider does not offer is refused, and so is turning `faircoin` `off` (`payment_method_locked`): FairCoin is always offered.',
157
203
  auth: 'service',
158
204
  scope: 'payments:write',
159
205
  idempotent: true,
@@ -181,7 +227,7 @@ exports.paymentMethodConfigurationRoutes = [
181
227
  path: '/v1/payment_method_configurations/{id}',
182
228
  tag: 'Payment method configurations',
183
229
  summary: 'Update a payment method configuration',
184
- description: 'Method settings are merged; the default configuration is always active.',
230
+ description: 'Method settings are merged; the default configuration is always active. `faircoin` is locked on: setting it `off` is refused with `payment_method_locked`.',
185
231
  auth: 'service',
186
232
  scope: 'payments:write',
187
233
  idempotent: true,
@@ -7,6 +7,7 @@ const objects_1 = require("../../common/objects");
7
7
  const params_1 = require("../../common/params");
8
8
  const primitives_1 = require("../../common/primitives");
9
9
  const route_1 = require("../../route");
10
+ const paymentIntents_1 = require("../payments/paymentIntents");
10
11
  const connect_1 = require("../../vocabulary/connect");
11
12
  /**
12
13
  * Balance and balance transactions (ADR 0015 §3–§5).
@@ -90,6 +91,9 @@ exports.balanceTransactionSchema = (0, objects_1.defineObject)('balance_transact
90
91
  created: primitives_1.unixSeconds.describe('When it happened at its source.'),
91
92
  description: zod_1.z.string().nullable(),
92
93
  exchange_rate: zod_1.z.number().nullable(),
94
+ faircoin_quote: paymentIntents_1.faircoinQuoteSchema
95
+ .nullable()
96
+ .describe('A FairCoin payment of a fiat order: the quote it was priced at — its fiat equivalent (ADR 0021). Informational; no fiat moved.'),
93
97
  fee_details: zod_1.z.array(exports.balanceTransactionFeeDetailSchema),
94
98
  source: zod_1.z
95
99
  .string()
@@ -121,6 +125,7 @@ exports.balanceTransactionSchema = (0, objects_1.defineObject)('balance_transact
121
125
  created: 1793750400,
122
126
  description: 'Order 6735',
123
127
  exchange_rate: null,
128
+ faircoin_quote: null,
124
129
  fee_details: [{ amount: '88', currency: 'EUR', type: 'processing_fee' }],
125
130
  source: 'ch_0193b8f2f7c94b1d8e02',
126
131
  payout: null,
@@ -18,25 +18,24 @@ const account_1 = require("./account");
18
18
  * ADR 0001 D3: a merchant integrates against Peable and never learns which
19
19
  * acquirer sat behind their seller, because the day that changes should be a
20
20
  * Peable deploy and not a merchant migration. No `acct_…`, no provider name —
21
- * and no seller xpub (ADR 0012 D6): an account xpub reveals every address of
22
- * that account, so a platform holding it would learn the seller's whole history
23
- * and balance. Nothing a platform does needs it; each payment carries its own
21
+ * and no key of any kind: a seller's FairCoin is paid into the Peable wallet
22
+ * of their own Oxy account (ADR 0021 D5), and each payment carries its own
24
23
  * address.
25
24
  */
26
25
  const capabilityStatus = zod_1.z.enum(connect_1.ACCOUNT_CAPABILITY_STATUSES);
27
- /** The FairCoin half of a seller's account. The seller's xpub is deliberately ABSENT (ADR 0012 D6). */
26
+ /** The FairCoin half of a seller's account: paid into the Peable wallet of the seller's own Oxy account (ADR 0021 D5). */
28
27
  exports.connectedAccountFaircoinSchema = (0, objects_1.defineComponent)('ConnectedAccountFaircoin', zod_1.z
29
28
  .object({
30
29
  network: primitives_1.network.describe('The chain the seller is paid on. Fixed when the half was opened.'),
31
30
  status: zod_1.z
32
31
  .enum(connect_1.CONNECTED_ACCOUNT_FAIRCOIN_STATUSES)
33
- .describe('`pending`: the seller has not registered a key yet (an on-behalf payment is refused, `account_not_ready`). `active`: payments derive addresses from their key.'),
32
+ .describe('`pending`: the seller has not confirmed yet (an on-behalf payment is refused, `account_not_ready`). `active`: the seller confirmed, and payments go to the Peable wallet of their Oxy account.'),
34
33
  oxy_user_id: zod_1.z
35
34
  .string()
36
- .describe('The Oxy user who may register the key — and, once `active`, who did.'),
35
+ .describe('The seller’s Oxy account — the only one that may confirm, and the one whose Peable wallet receives.'),
37
36
  registered_at: primitives_1.unixSeconds
38
37
  .nullable()
39
- .describe('When the seller registered their key. `null` while `pending`.'),
38
+ .describe('When the seller confirmed. `null` while `pending`.'),
40
39
  })
41
40
  .strict());
42
41
  exports.connectedAccountSchema = (0, objects_1.defineObject)('connected_account', 'ConnectedAccount', zod_1.z
@@ -112,9 +111,9 @@ const OXY_USER_ID_MAX = 128;
112
111
  * `POST /v1/connected_accounts`: open (or return) the account for one seller.
113
112
  *
114
113
  * Two halves, at least one: the CARD half (`country` + `business_type`, both or
115
- * neither) and the FAIRCOIN half (`faircoin`). There is deliberately no `xpub`
116
- * here: the key comes from the SELLER's own session, never from the platform
117
- * (ADR 0012 D3).
114
+ * neither) and the FAIRCOIN half (`faircoin`). There is no key: the seller's
115
+ * FairCoin goes to their own account's Peable wallet, confirmed only from the
116
+ * SELLER's own session (ADR 0012 D3, ADR 0021 D5).
118
117
  */
119
118
  exports.createConnectedAccountParams = zod_1.z
120
119
  .object({
@@ -141,7 +140,7 @@ exports.createConnectedAccountParams = zod_1.z
141
140
  .string()
142
141
  .min(1)
143
142
  .max(OXY_USER_ID_MAX)
144
- .describe("The seller's Oxy user id — the only person who may register the key."),
143
+ .describe("The seller's Oxy account id — the only one that may confirm, and whose Peable wallet receives."),
145
144
  })
146
145
  .strict()
147
146
  .optional()
@@ -165,7 +164,7 @@ exports.createConnectedAccountLinkParams = zod_1.z
165
164
  rail: zod_1.z
166
165
  .enum(connect_1.CONNECTED_ACCOUNT_RAILS)
167
166
  .optional()
168
- .describe("Which half to onboard: `card` (the default) is the provider's hosted onboarding; `faircoin` is Peable's own page where the SELLER registers their watch-only key."),
167
+ .describe("Which half to onboard: `card` (the default) is the provider's hosted onboarding; `faircoin` is Peable's own page where the SELLER confirms, in their own Oxy session, that their FairCoin is paid into their Peable wallet."),
169
168
  })
170
169
  .strict();
171
170
  const accountIdParam = { accountId: 'The connected account (`ca_…`).' };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.connectOnboardingRoutes = exports.registerFaircoinKeyParams = exports.connectOnboardingCompleteSchema = exports.connectOnboardingSchema = void 0;
3
+ exports.connectOnboardingRoutes = exports.confirmFaircoinOnboardingParams = exports.connectOnboardingCompleteSchema = exports.connectOnboardingSchema = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const objects_1 = require("../../common/objects");
6
6
  const primitives_1 = require("../../common/primitives");
@@ -10,10 +10,10 @@ const shared_1 = require("../checkout/shared");
10
10
  * The SELLER-facing half of FairCoin connected accounts (ADR 0012 D3).
11
11
  *
12
12
  * A platform mints an onboarding link for a seller's account; the SELLER opens
13
- * it signed in with Oxy and registers the watch-only key their FairCoin will be
14
- * paid to. These routes are `auth: 'user'` — the seller's own session, never a
15
- * service token — because the key that decides who receives a seller's money is
16
- * accepted only from the seller. A platform cannot reach them at all, and the
13
+ * it signed in with Oxy and confirms that their FairCoin is paid into the
14
+ * Peable wallet of that account (ADR 0021 D5). These routes are `auth: 'user'`
15
+ * — the seller's own session, never a service token — because who receives a
16
+ * seller's money is the seller's consent. A platform cannot reach them at all, and the
17
17
  * link token alone is not enough without the session it names.
18
18
  */
19
19
  exports.connectOnboardingSchema = (0, objects_1.defineObject)('connect_onboarding', 'ConnectOnboarding', zod_1.z
@@ -38,22 +38,11 @@ exports.connectOnboardingCompleteSchema = (0, objects_1.defineComponent)('Connec
38
38
  })
39
39
  .strict());
40
40
  /**
41
- * An extended public key is 111 characters in base58check; the bound is a
42
- * request-size guard with headroom, not a format check — the non-custody
43
- * firewall (`assertWatchOnly`) is.
41
+ * `POST /v1/connect/onboarding/{token}/faircoin` takes nothing: the seller
42
+ * confirms, in their own Oxy session, that their FairCoin is paid into the
43
+ * Peable wallet of that account (ADR 0021 D5). No key travels.
44
44
  */
45
- const XPUB_MAX_LENGTH = 200;
46
- /** `POST /v1/connect/onboarding/{token}/faircoin` — the seller's watch-only ACCOUNT xpub. */
47
- exports.registerFaircoinKeyParams = zod_1.z
48
- .object({
49
- xpub: zod_1.z
50
- .string()
51
- .trim()
52
- .min(1)
53
- .max(XPUB_MAX_LENGTH)
54
- .describe('A watch-only extended PUBLIC key. A private extended key is refused (`watch_only_violation`) and never stored.'),
55
- })
56
- .strict();
45
+ exports.confirmFaircoinOnboardingParams = zod_1.z.object({}).strict();
57
46
  const tokenParam = { token: 'The onboarding link token (the last segment of its `url`).' };
58
47
  exports.connectOnboardingRoutes = [
59
48
  (0, route_1.defineRoute)({
@@ -68,15 +57,15 @@ exports.connectOnboardingRoutes = [
68
57
  response: exports.connectOnboardingSchema,
69
58
  }),
70
59
  (0, route_1.defineRoute)({
71
- operationId: 'registerConnectOnboardingFaircoinKey',
60
+ operationId: 'confirmConnectOnboardingFaircoin',
72
61
  method: 'post',
73
62
  path: '/v1/connect/onboarding/{token}/faircoin',
74
63
  tag: 'Connect onboarding',
75
- summary: "Register the seller's FairCoin key",
76
- description: 'The ONLY way a key reaches a connected account: runs the non-custody firewall, consumes the link and tells the platform (`connected_account.updated`), in one transaction. The key is immutable once registered and never appears on any response.',
64
+ summary: 'Confirm FairCoin payments into the seller’s Peable wallet',
65
+ description: 'The seller, signed in as the account the link names, confirms that FairCoin paid to them goes to that account’s Peable wallet (ADR 0021 D5) — the only way a FairCoin half becomes payable. No key is sent: addresses derive from the account’s public identity key. 409 `faircoin_wallet_missing` while the account has no Peable wallet yet. Consumes the link and tells the platform (`connected_account.updated`) in one transaction.',
77
66
  auth: 'user',
78
67
  params: tokenParam,
79
- body: exports.registerFaircoinKeyParams,
68
+ body: exports.confirmFaircoinOnboardingParams,
80
69
  response: exports.connectOnboardingCompleteSchema,
81
70
  }),
82
71
  ];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.paymentIntentRoutes = exports.clientSecretQuery = exports.retrievePaymentIntentQuery = exports.clientSecretParam = exports.listPaymentIntentsQuery = exports.submitPaymentIntentTxParams = exports.cancelPaymentIntentParams = exports.capturePaymentIntentParams = exports.confirmPaymentIntentParams = exports.updatePaymentIntentParams = exports.createPaymentIntentParams = exports.connectedAccountParam = exports.railParams = exports.paymentIntentSchema = exports.paymentIntentClientActionSchema = exports.clientActionSchema = exports.paymentIntentTransferDataSchema = exports.paymentIntentFaircoinSchema = exports.paymentIntentNextActionSchema = exports.paymentErrorSchema = void 0;
3
+ exports.paymentIntentRoutes = exports.clientSecretQuery = exports.retrievePaymentIntentQuery = exports.clientSecretParam = exports.listPaymentIntentsQuery = exports.submitPaymentIntentTxParams = exports.cancelPaymentIntentParams = exports.capturePaymentIntentParams = exports.confirmPaymentIntentParams = exports.updatePaymentIntentParams = exports.createPaymentIntentParams = exports.connectedAccountParam = exports.railParams = exports.paymentIntentSchema = exports.paymentIntentClientActionSchema = exports.clientActionSchema = exports.paymentIntentTransferDataSchema = exports.paymentIntentFaircoinSchema = exports.faircoinQuoteSchema = exports.paymentIntentNextActionSchema = exports.paymentErrorSchema = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const address_1 = require("../../common/address");
6
6
  const envelopes_1 = require("../../common/envelopes");
@@ -52,6 +52,39 @@ exports.paymentIntentNextActionSchema = (0, objects_1.defineComponent)('PaymentI
52
52
  .strict(),
53
53
  zod_1.z.object({ type: zod_1.z.literal('use_peable_sdk') }).strict(),
54
54
  ]));
55
+ /**
56
+ * The FairCoin price of a FIAT order (ADR 0021 D4), carried by the FairCoin
57
+ * payment the payer chose for it. Pricing, never exchange: the payer pays
58
+ * `amount` FAIR (the intent's) to the payee's own address, and no fiat moves.
59
+ * `rate` is for display; the FAIR amount is exactly
60
+ * `ceil(amount ÷ rate)` computed from the sources' own figures.
61
+ */
62
+ exports.faircoinQuoteSchema = (0, objects_1.defineComponent)('FaircoinQuote', zod_1.z
63
+ .object({
64
+ currency: primitives_1.fiatCurrency.describe("The order's currency."),
65
+ amount: primitives_1.amount.describe("The order's total in base units of `currency` (tax included)."),
66
+ rate: zod_1.z.string().describe('`currency` per 1 FAIR, rounded to 10 significant digits.'),
67
+ price: zod_1.z
68
+ .object({
69
+ source: zod_1.z.literal('wfair-base'),
70
+ usd_per_fair: zod_1.z.string().describe("The FairCoin Explorer's FAIR/USD price."),
71
+ observed_at: primitives_1.unixSeconds,
72
+ })
73
+ .strict(),
74
+ reference_rates: zod_1.z
75
+ .object({
76
+ source: zod_1.z.literal('ecb'),
77
+ usd_per_eur: zod_1.z.string(),
78
+ currency_per_eur: zod_1.z.string().describe('`1` for EUR.'),
79
+ observed_at: primitives_1.unixSeconds,
80
+ })
81
+ .strict()
82
+ .nullable()
83
+ .describe("The European Central Bank's reference rates; `null` for a USD order."),
84
+ quoted_at: primitives_1.unixSeconds,
85
+ expires_at: primitives_1.unixSeconds.describe('The payment expires with its quote unless already broadcast.'),
86
+ })
87
+ .strict());
55
88
  /**
56
89
  * The chain side of a FairCoin payment. `txid` and `confirmations` describe the
57
90
  * transaction the payer reported: `null`/`0` while `requires_action`, the
@@ -62,10 +95,13 @@ exports.paymentIntentFaircoinSchema = (0, objects_1.defineComponent)('PaymentInt
62
95
  network: primitives_1.network,
63
96
  address: zod_1.z
64
97
  .string()
65
- .describe("Watch-only receive address derived per intent from the merchant's (or seller's) xpub."),
98
+ .describe("Receive address in the Peable wallet of the account this payment pays (the merchant's owner, or the seller), derived per payment from that account's public identity key (ADR 0021 D5)."),
66
99
  txid: primitives_1.nullableString,
67
100
  confirmations: zod_1.z.number().int().nonnegative(),
68
101
  required_confirmations: zod_1.z.number().int().nonnegative(),
102
+ quote: exports.faircoinQuoteSchema
103
+ .nullable()
104
+ .describe('The fiat order this payment pays, as quoted (ADR 0021); `null` on a FAIR-priced payment.'),
69
105
  })
70
106
  .strict());
71
107
  /** Where a destination charge's funds go (`transfer_data`, ADR 0015 §2). */
@@ -196,6 +232,7 @@ exports.paymentIntentSchema = (0, objects_1.defineObject)('payment_intent', 'Pay
196
232
  txid: null,
197
233
  confirmations: 0,
198
234
  required_confirmations: 6,
235
+ quote: null,
199
236
  },
200
237
  merchant_id: 'merch_0193b8f2c1a87d3e9f4a',
201
238
  connected_account: null,
@@ -4,7 +4,24 @@
4
4
  // the wallet import them without the schemas (`@peable.to/contracts/vocabulary`,
5
5
  // re-exported by `@peable.to/shared-types`).
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.PAYMENT_LINK_LIMITS = exports.CHECKOUT_SESSION_ID_TEMPLATE = exports.CHECKOUT_LIMITS = exports.CHECKOUT_TAX_ID_TYPES = exports.CHECKOUT_CUSTOM_FIELD_TYPES = exports.CHECKOUT_BILLING_ADDRESS_COLLECTIONS = exports.CHECKOUT_CUSTOMER_CREATIONS = exports.CHECKOUT_SUBMIT_TYPES = exports.CHECKOUT_LOCALES = exports.CHECKOUT_UI_MODES = exports.CHECKOUT_PAYMENT_STATUSES = exports.CHECKOUT_SESSION_STATUSES = exports.CHECKOUT_SESSION_MODES = void 0;
7
+ exports.PAYMENT_LINK_LIMITS = exports.CHECKOUT_SESSION_ID_TEMPLATE = exports.CHECKOUT_LIMITS = exports.CHECKOUT_TAX_ID_TYPES = exports.CHECKOUT_CUSTOM_FIELD_TYPES = exports.CHECKOUT_BILLING_ADDRESS_COLLECTIONS = exports.CHECKOUT_CUSTOMER_CREATIONS = exports.CHECKOUT_SUBMIT_TYPES = exports.CHECKOUT_LOCALES = exports.CHECKOUT_UI_MODES = exports.CHECKOUT_PAYMENT_STATUSES = exports.CHECKOUT_SESSION_STATUSES = exports.CHECKOUT_SESSION_MODES = exports.FAIRCOIN_UNAVAILABLE_REASONS = void 0;
8
+ /**
9
+ * Why FairCoin cannot be paid with on an order right now (ADR 0021). It is
10
+ * still offered — never hidden — and says why:
11
+ *
12
+ * - `faircoin_wallet_missing` — the Peable wallet of the account that receives
13
+ * (the merchant's owner, or the seller) isn't set up yet: no identity key;
14
+ * - `faircoin_network_closed` — this deployment does not open payments on the
15
+ * order's FairCoin network yet (ADR 0002's gate);
16
+ * - `price_unavailable` — no fresh FairCoin price exists to quote a fiat order;
17
+ * - `temporarily_unavailable` — whether the wallet exists could not be checked.
18
+ */
19
+ exports.FAIRCOIN_UNAVAILABLE_REASONS = [
20
+ 'faircoin_wallet_missing',
21
+ 'faircoin_network_closed',
22
+ 'price_unavailable',
23
+ 'temporarily_unavailable',
24
+ ];
8
25
  exports.CHECKOUT_SESSION_MODES = ['payment', 'setup', 'subscription'];
9
26
  exports.CHECKOUT_SESSION_STATUSES = ['open', 'complete', 'expired'];
10
27
  exports.CHECKOUT_PAYMENT_STATUSES = ['paid', 'unpaid', 'no_payment_required'];
@@ -60,6 +60,7 @@ exports.ERROR_CODE_DESCRIPTIONS = {
60
60
  parameter_missing: 'A required parameter is missing; `param` names it.',
61
61
  parameter_unknown: 'The request carries a parameter this route does not accept; `param` names it.',
62
62
  payment_intent_unexpected_state: 'The PaymentIntent is in a status that does not allow this operation.',
63
+ payment_method_locked: 'The payment method cannot be turned off or removed: FairCoin is always offered to every payer; `param` names the field.',
63
64
  payout_not_allowed: 'Payouts cannot be created for this account.',
64
65
  rate_limited: 'Too many requests; back off and retry.',
65
66
  refund_not_cancelable: 'The refund has already left a cancelable state.',
@@ -70,7 +71,6 @@ exports.ERROR_CODE_DESCRIPTIONS = {
70
71
  test_mode_only: 'This operation exists in test mode only.',
71
72
  too_many_streams: 'Too many live streams are open for this merchant.',
72
73
  url_invalid: 'The URL is not an allowed https URL.',
73
- watch_only_violation: 'The extended key carries a private key. Peable only ever accepts watch-only (public) keys.',
74
74
  webhook_endpoint_disabled: 'The webhook endpoint is disabled.',
75
75
  webhook_endpoint_limit_reached: 'The merchant already has the maximum number of webhook endpoints.',
76
76
  account_not_ready: 'The connected account cannot take this payment yet: its onboarding or a capability is incomplete.',
@@ -131,6 +131,9 @@ exports.ERROR_CODE_DESCRIPTIONS = {
131
131
  promotion_code_minimum_amount: 'The purchase is below the promotion code minimum amount.',
132
132
  payment_method_missing: 'No payment method is available to charge.',
133
133
  faircoin_cannot_debit: 'A FairCoin invoice cannot be charged automatically: the payer signs every payment.',
134
+ faircoin_price_unavailable: 'No fresh FairCoin price exists right now, so this order cannot be quoted in FAIR. The other payment methods still work; try FairCoin again shortly.',
135
+ faircoin_wallet_missing: "The Peable wallet that receives this payment (the merchant owner's, or the seller's) isn't set up yet, so it cannot be paid in FairCoin. The other payment methods still work.",
136
+ faircoin_network_closed: 'FairCoin payments on this network are not open on this deployment yet. The other payment methods still work.',
134
137
  credit_note_exceeds_invoice: "The credit note's amount exceeds what the invoice can still credit.",
135
138
  test_clock_unexpected_state: 'The test clock is advancing; wait until it is ready.',
136
139
  meter_event_customer_missing: 'The meter event names no customer of this merchant.',
@@ -143,8 +146,7 @@ exports.ERROR_CODE_DESCRIPTIONS = {
143
146
  // Connect onboarding (ADR 0012 D3): the seller-facing refusals.
144
147
  link_expired: 'The onboarding link has expired or was already used; `refresh_url` is where the seller gets a fresh one.',
145
148
  wrong_seller: 'The onboarding link names a different Oxy account; sign in as the seller it was minted for.',
146
- already_registered: 'The seller already registered a FairCoin key, and it cannot be changed.',
147
- key_in_use: 'The key already receives payments for another account.',
149
+ already_registered: 'The seller already confirmed FairCoin payments into their Peable wallet.',
148
150
  no_faircoin_half: 'The connected account has no FairCoin half to register a key for.',
149
151
  // The dashboard routes (`/v1/dashboard/*`, Orbit): the signed-in person, not a credential.
150
152
  merchant_missing: 'The application has no merchant in this environment yet; register one (Orbit shows "Set up payments").',