@nokinc-flur/sdk 1.1.5 → 2.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.
package/dist/index.js CHANGED
@@ -1,11 +1,201 @@
1
1
  // src/client.ts
2
- import { z as z5 } from "zod";
2
+ import { z as z4 } from "zod";
3
3
 
4
4
  // src/contracts.ts
5
- import { z as z2 } from "zod";
6
-
7
- // src/me-offline/client.ts
8
5
  import { z } from "zod";
6
+ var E164Regex = /^\+[1-9]\d{7,14}$/;
7
+ var UuidSchema = z.string().uuid();
8
+ var IsoDateSchema = z.string().datetime({ offset: true });
9
+ var CurrencySchema = z.string().trim().length(3).transform((value) => value.toUpperCase());
10
+ var HealthResponseSchema = z.object({
11
+ ok: z.boolean()
12
+ });
13
+ var WelcomeResponseSchema = z.object({
14
+ message: z.string()
15
+ });
16
+ var OnboardingStartRequestSchema = z.object({
17
+ phoneE164: z.string().regex(E164Regex),
18
+ appInstanceId: z.string().min(3),
19
+ platform: z.enum(["android", "ios", "web"]),
20
+ turnstileToken: z.string().min(20).optional(),
21
+ appAttestation: z.object({
22
+ provider: z.enum(["android", "ios", "web"]),
23
+ token: z.string().min(24)
24
+ }).optional(),
25
+ firstName: z.string().trim().min(1).max(80).optional(),
26
+ lastName: z.string().trim().min(1).max(80).optional()
27
+ });
28
+ var OnboardingStartResponseSchema = z.object({
29
+ requestId: z.string().min(1),
30
+ checkUrl: z.string().url().optional(),
31
+ expiresInSec: z.number().int().positive(),
32
+ fallback: z.enum(["SILENT_AUTH", "OTP"])
33
+ });
34
+ var OnboardingCompleteRequestSchema = z.object({
35
+ requestId: z.string().min(1),
36
+ code: z.string().min(1).max(32),
37
+ appInstanceId: z.string().min(3),
38
+ fingerprintHash: z.string().min(3).optional()
39
+ });
40
+ var OnboardingCompleteResponseSchema = z.object({
41
+ sessionToken: z.string().min(1),
42
+ userId: UuidSchema,
43
+ restricted: z.boolean(),
44
+ risk_reasons: z.array(
45
+ z.enum(["SIM_SWAP_RECENT", "ROAMING", "CARRIER_CHANGED"])
46
+ ),
47
+ stepUpRequired: z.boolean().optional(),
48
+ riskStatus: z.enum(["ok", "unavailable"]).optional()
49
+ });
50
+ var RegisterDeviceRequestSchema = z.object({
51
+ userId: UuidSchema,
52
+ appInstanceId: z.string().min(3),
53
+ platform: z.string().min(2),
54
+ model: z.string().optional(),
55
+ networkSignals: z.object({
56
+ ip: z.string().min(3),
57
+ asn: z.number().int().optional(),
58
+ country: z.string().min(2).optional(),
59
+ carrier: z.string().optional()
60
+ })
61
+ });
62
+ var RegisterDeviceResponseSchema = z.object({
63
+ deviceId: z.string().min(1),
64
+ fingerprintHash: z.string().min(1),
65
+ driftScore: z.number(),
66
+ trustState: z.enum(["TRUSTED_PRIMARY", "TRUSTED_SECONDARY", "UNVERIFIED"]),
67
+ stepUpRequired: z.boolean()
68
+ });
69
+ var AuthRefreshRequestSchema = z.object({
70
+ userId: UuidSchema,
71
+ refreshToken: z.string().min(8),
72
+ appInstanceId: z.string().min(3),
73
+ fingerprintHash: z.string().min(3)
74
+ });
75
+ var AuthRefreshResponseSchema = z.object({
76
+ refreshToken: z.string().min(8),
77
+ stepUpRequired: z.boolean()
78
+ });
79
+ var AuthLogoutRequestSchema = z.object({
80
+ userId: UuidSchema,
81
+ refreshToken: z.string().min(8)
82
+ });
83
+ var PinSetRequestSchema = z.object({
84
+ userId: UuidSchema,
85
+ pin: z.string().regex(/^\d{6}$/)
86
+ });
87
+ var PinVerifyRequestSchema = z.object({
88
+ userId: UuidSchema,
89
+ pin: z.string().regex(/^\d{6}$/)
90
+ });
91
+ var OkResponseSchema = z.object({
92
+ ok: z.boolean()
93
+ });
94
+ var RegisterSendDeviceKeyRequestSchema = z.object({
95
+ userId: UuidSchema,
96
+ deviceId: z.string().min(3),
97
+ publicKey: z.string().min(32)
98
+ });
99
+ var SEND_AUTH_PURPOSES = ["send_money", "offline_revoke"];
100
+ var SendChallengeRequestSchema = z.object({
101
+ userId: UuidSchema,
102
+ deviceId: z.string().min(3),
103
+ purpose: z.enum(SEND_AUTH_PURPOSES).optional()
104
+ });
105
+ var SendChallengeResponseSchema = z.object({
106
+ challengeId: UuidSchema,
107
+ nonce: z.string().min(1),
108
+ expiresAt: IsoDateSchema
109
+ });
110
+ var SendVerifyRequestSchema = z.object({
111
+ userId: UuidSchema,
112
+ deviceId: z.string().min(3),
113
+ challengeId: UuidSchema,
114
+ signature: z.string().min(16)
115
+ });
116
+ var SendVerifyResponseSchema = z.object({
117
+ sendAuthToken: z.string().min(16)
118
+ });
119
+ var ResolveRecipientRequestSchema = z.object({
120
+ identifier: z.string().min(3)
121
+ });
122
+ var ResolveRecipientResponseSchema = z.object({
123
+ recipientUserId: UuidSchema,
124
+ displayName: z.string().min(1),
125
+ normalizedIdentifier: z.string().regex(E164Regex),
126
+ isActive: z.boolean()
127
+ });
128
+ var CreateTransferRequestSchema = z.object({
129
+ recipientIdentifier: z.string().min(3),
130
+ amountMinor: z.number().int().positive(),
131
+ currency: CurrencySchema,
132
+ sendAuthToken: z.string().min(16)
133
+ });
134
+ var TransferStatusSchema = z.enum(["SETTLED", "PENDING_REVIEW", "DECLINED"]);
135
+ var TransferResponseSchema = z.object({
136
+ transactionId: z.string().min(1),
137
+ status: TransferStatusSchema,
138
+ userStatus: TransferStatusSchema,
139
+ recipientName: z.string().min(1),
140
+ timestamp: IsoDateSchema
141
+ });
142
+ var DirectionSchema = z.enum(["OUTGOING", "INCOMING"]);
143
+ var AccountActivityItemSchema = z.object({
144
+ id: z.string().min(1),
145
+ type: z.string().min(1),
146
+ direction: DirectionSchema,
147
+ name: z.string().min(1),
148
+ identifier: z.string().min(1),
149
+ amountMinor: z.number().int(),
150
+ currency: CurrencySchema,
151
+ status: z.string().min(1),
152
+ timestamp: IsoDateSchema
153
+ });
154
+ var AccountSummaryResponseSchema = z.object({
155
+ /** Authenticated user's stable internal id. */
156
+ userId: UuidSchema,
157
+ /**
158
+ * 10-digit Nigeria Uniform Bank Account Number (NUBAN) allocated by the
159
+ * bank partner. `null` when the user has no partner-allocated account yet.
160
+ */
161
+ nuban: z.string().regex(/^[0-9]{10}$/).nullable(),
162
+ balance: z.number().int(),
163
+ currency: CurrencySchema,
164
+ dailySendLimit: z.number().int().nonnegative(),
165
+ dailySendRemaining: z.number().int().nonnegative(),
166
+ kycTier: z.string().min(1),
167
+ kycStatus: z.string().min(1),
168
+ recentActivity: z.array(AccountActivityItemSchema)
169
+ });
170
+ var TransactionsListResponseSchema = z.object({
171
+ items: z.array(AccountActivityItemSchema),
172
+ nextCursor: z.string().nullable()
173
+ });
174
+ var TransactionDetailResponseSchema = z.object({
175
+ transactionId: z.string().min(1),
176
+ type: z.string().min(1),
177
+ direction: DirectionSchema,
178
+ counterpartyName: z.string().min(1),
179
+ counterpartyIdentifier: z.string().min(1),
180
+ amountMinor: z.number().int(),
181
+ currency: CurrencySchema,
182
+ status: z.string().min(1),
183
+ timestamp: IsoDateSchema
184
+ });
185
+ var PushRegisterRequestSchema = z.object({
186
+ deviceId: z.string().min(3),
187
+ platform: z.enum(["ios", "android", "web"]),
188
+ token: z.string().min(16)
189
+ });
190
+ var CreatePayLinkResponseSchema = z.object({
191
+ token: z.string().min(1)
192
+ });
193
+ var ResolvePayLinkResponseSchema = z.object({
194
+ recipientUserId: UuidSchema,
195
+ displayName: z.string().min(1),
196
+ normalizedIdentifier: z.string().regex(E164Regex),
197
+ isActive: z.boolean()
198
+ });
9
199
 
10
200
  // src/errors.ts
11
201
  var backendErrorCodeSet = /* @__PURE__ */ new Set([
@@ -109,556 +299,9 @@ async function mapToFlurError(res) {
109
299
  });
110
300
  }
111
301
 
112
- // src/me-offline/client.ts
113
- var Hex64 = z.string().regex(/^[0-9a-f]{64}$/i);
114
- var Sha256Hex = z.string().regex(/^[0-9a-f]{64}$/i);
115
- var Base64Std = z.string().regex(/^[A-Za-z0-9+/]+={0,2}$/);
116
- var RegisterDeviceKeyInputSchema = z.object({
117
- deviceId: z.string().min(1).max(128),
118
- publicKeyHex: Hex64
119
- });
120
- var AttestationSecurityLevelSchema = z.enum([
121
- "STRONGBOX",
122
- "TEE",
123
- "SECURE_ENCLAVE",
124
- "SOFTWARE"
125
- ]);
126
- var DeviceKeyAlgSchema = z.literal("p256");
127
- var RegisterDeviceKeyP256InputSchema = z.object({
128
- deviceId: z.string().min(1).max(128),
129
- /** P-256 SubjectPublicKeyInfo DER, base64. */
130
- publicKeySpkiB64: Base64Std.min(64).max(4096),
131
- /** Base64 of the server-issued enrollment challenge string. */
132
- challengeB64: Base64Std.min(8).max(1024),
133
- /** iOS App Attest payload or Android X.509 Key Attestation chain. */
134
- attestationChainB64: z.array(Base64Std.min(16).max(16384)).min(1).max(16),
135
- securityLevel: AttestationSecurityLevelSchema
136
- });
137
- var P256EnrollmentChallengeInputSchema = z.object({
138
- deviceId: z.string().min(1).max(128)
139
- });
140
- var P256EnrollmentChallengeResultSchema = z.object({
141
- challenge: z.string().min(16),
142
- expiresAtMs: z.number().int().positive()
143
- });
144
- var DeviceKeyRecordSchema = z.object({
145
- id: z.string().uuid(),
146
- userId: z.string().uuid(),
147
- deviceId: z.string(),
148
- /** Always 'p256' on the consumer offline rail. Field retained for forward-compat. */
149
- alg: DeviceKeyAlgSchema.default("p256"),
150
- /** Legacy ed25519 hex key. Always null on new records (kept for back-compat reads). */
151
- publicKeyHex: Hex64.nullable().default(null),
152
- /** P-256 SubjectPublicKeyInfo DER, base64. Required for new records. */
153
- publicKeySpkiB64: Base64Std.nullable().default(null),
154
- securityLevel: AttestationSecurityLevelSchema.nullable().default(null),
155
- hardwareBacked: z.boolean().default(false),
156
- attestedAtMs: z.number().int().nonnegative().nullable().default(null),
157
- createdAtMs: z.number().int().nonnegative(),
158
- revokedAtMs: z.number().int().nonnegative().nullable()
159
- });
160
- var ConsumerOACSchema = z.object({
161
- oacId: z.string().uuid(),
162
- issuerId: z.string().min(1).max(64),
163
- userId: z.string().uuid(),
164
- deviceId: z.string().min(1).max(128),
165
- /**
166
- * Always 'p256'. Required on the wire (backend always emits it).
167
- * Kept as a literal so input/output infer identically and the schema
168
- * can be nested inside other response shapes without Zod input/output
169
- * divergence under tsup DTS bundling.
170
- */
171
- alg: z.literal("p256"),
172
- /** P-256 SubjectPublicKeyInfo DER, base64. */
173
- devicePubkeySpkiB64: Base64Std.min(64).max(4096),
174
- perTxCapKobo: z.number().int().positive(),
175
- cumulativeCapKobo: z.number().int().positive(),
176
- currency: z.string().length(3),
177
- validFromMs: z.number().int().nonnegative(),
178
- validUntilMs: z.number().int().nonnegative(),
179
- counterSeed: z.number().int().nonnegative(),
180
- issuedAtMs: z.number().int().nonnegative()
181
- });
182
- var SignedConsumerOACSchema = z.object({
183
- oac: ConsumerOACSchema,
184
- /** ASN.1 DER ECDSA P-256 issuer signature, base64. */
185
- issuerSig: Base64Std.min(16).max(2048),
186
- /** Issuer's P-256 public key as SubjectPublicKeyInfo DER, base64. */
187
- issuerPublicKeySpkiB64: Base64Std.min(64).max(4096)
188
- });
189
- var OACRecordSchema = SignedConsumerOACSchema.extend({
190
- currentOfflineSpentKobo: z.number().int().nonnegative(),
191
- status: z.enum([
192
- "active",
193
- "superseded",
194
- "expired",
195
- "revoked",
196
- "disabling",
197
- "draining",
198
- "closed"
199
- ]),
200
- supersededAtMs: z.number().int().nonnegative().nullable(),
201
- revokedAtMs: z.number().int().nonnegative().nullable(),
202
- holdId: z.string().uuid().nullable().optional()
203
- });
204
- var IssueOACInputSchema = z.object({
205
- deviceId: z.string().min(1).max(128),
206
- perTxCapKobo: z.number().int().positive().optional(),
207
- cumulativeCapKobo: z.number().int().positive().optional(),
208
- ttlMs: z.number().int().min(6e4).max(1e3 * 60 * 60 * 24 * 7).optional(),
209
- spendableOnlineKobo: z.number().int().nonnegative().optional()
210
- });
211
- var IssueAccountOacInputSchema = z.object({
212
- deviceId: z.string().min(1).max(128),
213
- perTxCapKobo: z.number().int().positive().optional(),
214
- cumulativeCapKobo: z.number().int().positive().optional(),
215
- ttlMs: z.number().int().min(6e4).max(1e3 * 60 * 60 * 24 * 7).optional()
216
- });
217
- var EnableOfflineInputSchema = z.object({
218
- deviceId: z.string().min(1).max(128),
219
- amountKobo: z.number().int().positive(),
220
- perTxCapKobo: z.number().int().positive().optional(),
221
- ttlMs: z.number().int().min(6e4).max(1e3 * 60 * 60 * 24 * 7).optional(),
222
- installId: z.string().min(1).max(128),
223
- partnerId: z.string().min(1).max(64).optional()
224
- });
225
- var ProvisionOfflineAllowanceInputSchema = EnableOfflineInputSchema;
226
- var DisableOfflineInputSchema = z.object({
227
- deviceId: z.string().min(1).max(128),
228
- installId: z.string().min(1).max(128).optional(),
229
- claims: z.array(z.unknown()).max(256).optional()
230
- });
231
- var OfflineHoldRecordSchema = z.object({
232
- holdId: z.string().uuid(),
233
- userId: z.string().uuid(),
234
- deviceId: z.string(),
235
- partnerId: z.string(),
236
- adapterKind: z.string(),
237
- externalHoldRef: z.string().nullable(),
238
- amountKobo: z.number().int().nonnegative(),
239
- capturedKobo: z.number().int().nonnegative(),
240
- releasedKobo: z.number().int().nonnegative(),
241
- remainingKobo: z.number().int().nonnegative(),
242
- currency: z.string().length(3),
243
- status: z.enum([
244
- "placing",
245
- "active",
246
- "disabling",
247
- "draining",
248
- "closed",
249
- "revoked",
250
- "failed"
251
- ]),
252
- installId: z.string().nullable(),
253
- drainDeadlineMs: z.number().int().nonnegative(),
254
- disableRequestedAtMs: z.number().int().nonnegative().nullable(),
255
- createdAtMs: z.number().int().nonnegative(),
256
- closedAtMs: z.number().int().nonnegative().nullable(),
257
- isTrusted: z.boolean().optional()
258
- });
259
- var EnableOfflineResultSchema = z.object({
260
- hold: OfflineHoldRecordSchema,
261
- oac: OACRecordSchema
262
- });
263
- var ProvisionOfflineAllowanceResultSchema = EnableOfflineResultSchema;
264
- var DisableOfflineResultSchema = z.object({
265
- hold: OfflineHoldRecordSchema,
266
- trusted: z.boolean(),
267
- settledClaims: z.number().int().nonnegative()
268
- });
269
- var OfflineStatusResultSchema = z.object({
270
- hold: OfflineHoldRecordSchema.nullable(),
271
- active: OACRecordSchema.nullable()
272
- });
273
- var OfflineStateResultSchema = z.object({
274
- active: OACRecordSchema.nullable()
275
- });
276
- var ConsumerPaymentClaimSchema = z.object({
277
- /** Always 'p256'. Retained for forward-compat and as an explicit domain marker. */
278
- alg: z.literal("p256").default("p256"),
279
- oacId: z.string().uuid(),
280
- encounterId: Sha256Hex.optional(),
281
- payerUserId: z.string().uuid(),
282
- payeeUserId: z.string().uuid(),
283
- payerDeviceId: z.string().min(1).max(128),
284
- payerNonce: z.string().min(8).max(128),
285
- payeeNonce: z.string().min(8).max(128),
286
- amountKobo: z.number().int().positive(),
287
- currency: z.string().length(3).default("NGN"),
288
- occurredAtMs: z.number().int().nonnegative(),
289
- completedAtMs: z.number().int().nonnegative().optional(),
290
- contextId: z.string().max(128).optional(),
291
- payerPubkeySpkiB64: Base64Std.min(64).max(4096),
292
- payerSignatureDerB64: Base64Std.min(16).max(2048),
293
- payeePubkeySpkiB64: Base64Std.min(64).max(4096).optional(),
294
- payeeSignatureDerB64: Base64Std.min(16).max(2048).optional()
295
- });
296
- var ConsumerSettlementSchema = z.object({
297
- settlementId: z.string().uuid(),
298
- settlementKey: Sha256Hex,
299
- encounterId: Sha256Hex,
300
- oacId: z.string().uuid(),
301
- payerUserId: z.string().uuid(),
302
- payeeUserId: z.string().uuid(),
303
- amountKobo: z.number().int().positive(),
304
- currency: z.string().length(3),
305
- status: z.enum(["SETTLED", "REVIEW"]),
306
- reviewReason: z.string().nullable(),
307
- ledgerRef: z.string().nullable(),
308
- /** ASN.1 DER ECDSA P-256 issuer signature, base64. */
309
- issuerSig: Base64Std.min(16).max(2048),
310
- createdAtMs: z.number().int().nonnegative()
311
- });
312
- var ConsumerSettleResultSchema = z.object({
313
- settlement: ConsumerSettlementSchema,
314
- encounterId: Sha256Hex,
315
- replayed: z.boolean()
316
- });
317
- var RevokeDeviceKeyInputSchema = z.object({
318
- deviceId: z.string().min(1).max(128),
319
- /** Step-up token from /api/v1/auth/send/verify with purpose='offline_revoke'. */
320
- sendAuthToken: z.string().min(16)
321
- });
322
- function createMeOfflineClient(opts) {
323
- const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
324
- if (!fetchImpl) {
325
- throw new Error("createMeOfflineClient: no fetch implementation available");
326
- }
327
- const baseUrl = opts.baseUrl.replace(/\/$/, "");
328
- async function call(method, path, body, parser) {
329
- const init2 = {
330
- method,
331
- headers: {
332
- "content-type": "application/json",
333
- accept: "application/json"
334
- }
335
- };
336
- if (body !== void 0) init2.body = JSON.stringify(body);
337
- const resp = await fetchImpl(`${baseUrl}${path}`, init2);
338
- const text = await resp.text();
339
- let raw = void 0;
340
- if (text) {
341
- try {
342
- raw = JSON.parse(text);
343
- } catch {
344
- }
345
- }
346
- if (!resp.ok) {
347
- const code = raw && typeof raw === "object" && "code" in raw && typeof raw.code === "string" ? raw.code : `http_${resp.status}`;
348
- const message = raw && typeof raw === "object" && "message" in raw && typeof raw.message === "string" ? raw.message : `request failed with status ${resp.status}`;
349
- throw new FlurApiError(resp.status, code, message, raw);
350
- }
351
- return parser(raw);
352
- }
353
- const deviceKeyItems = z.object({ items: z.array(DeviceKeyRecordSchema) });
354
- return {
355
- registerDeviceKey: (input) => call(
356
- "POST",
357
- "/v1/me/offline/keys",
358
- RegisterDeviceKeyInputSchema.parse(input),
359
- (raw) => DeviceKeyRecordSchema.parse(raw)
360
- ),
361
- issueP256EnrollmentChallenge: (input) => call(
362
- "POST",
363
- "/v1/me/offline/keys/p256/challenge",
364
- P256EnrollmentChallengeInputSchema.parse(input),
365
- (raw) => P256EnrollmentChallengeResultSchema.parse(raw)
366
- ),
367
- registerDeviceKeyP256: (input) => call(
368
- "POST",
369
- "/v1/me/offline/keys/p256",
370
- RegisterDeviceKeyP256InputSchema.parse(input),
371
- (raw) => DeviceKeyRecordSchema.parse(raw)
372
- ),
373
- listDeviceKeys: () => call(
374
- "GET",
375
- "/v1/me/offline/keys",
376
- void 0,
377
- (raw) => deviceKeyItems.parse(raw)
378
- ),
379
- revokeDeviceKey: (input) => call(
380
- "POST",
381
- "/v1/me/offline/keys/revoke",
382
- RevokeDeviceKeyInputSchema.parse(input),
383
- () => void 0
384
- ),
385
- issueAccountOac: (input) => call(
386
- "POST",
387
- "/v1/me/offline/oac",
388
- IssueAccountOacInputSchema.parse(input),
389
- (raw) => OACRecordSchema.parse(raw)
390
- ),
391
- provisionAllowance: (input) => call(
392
- "POST",
393
- "/v1/me/offline/allowance",
394
- ProvisionOfflineAllowanceInputSchema.parse(input),
395
- (raw) => ProvisionOfflineAllowanceResultSchema.parse(raw)
396
- ),
397
- enable: (input) => call(
398
- "POST",
399
- "/v1/me/offline/enable",
400
- EnableOfflineInputSchema.parse(input),
401
- (raw) => EnableOfflineResultSchema.parse(raw)
402
- ),
403
- refresh: (input) => call(
404
- "POST",
405
- "/v1/me/offline/refresh",
406
- IssueOACInputSchema.parse(input),
407
- (raw) => OACRecordSchema.parse(raw)
408
- ),
409
- disable: (input) => call(
410
- "POST",
411
- "/v1/me/offline/disable",
412
- DisableOfflineInputSchema.parse(input),
413
- (raw) => DisableOfflineResultSchema.parse(raw)
414
- ),
415
- getStatus: (deviceId) => {
416
- const qs = deviceId ? `?deviceId=${encodeURIComponent(deviceId)}` : "";
417
- return call(
418
- "GET",
419
- `/v1/me/offline/status${qs}`,
420
- void 0,
421
- (raw) => OfflineStatusResultSchema.parse(raw)
422
- );
423
- },
424
- getState: (deviceId) => {
425
- const qs = deviceId ? `?deviceId=${encodeURIComponent(deviceId)}` : "";
426
- return call(
427
- "GET",
428
- `/v1/me/offline/state${qs}`,
429
- void 0,
430
- (raw) => OfflineStateResultSchema.parse(raw)
431
- );
432
- },
433
- submitClaim: (claim) => call(
434
- "POST",
435
- "/v1/me/offline/claims",
436
- ConsumerPaymentClaimSchema.parse(claim),
437
- (raw) => ConsumerSettleResultSchema.parse(raw)
438
- )
439
- };
440
- }
441
-
442
- // src/contracts.ts
443
- var E164Regex = /^\+[1-9]\d{7,14}$/;
444
- var UuidSchema = z2.string().uuid();
445
- var IsoDateSchema = z2.string().datetime({ offset: true });
446
- var CurrencySchema = z2.string().trim().length(3).transform((value) => value.toUpperCase());
447
- var HealthResponseSchema = z2.object({
448
- ok: z2.boolean()
449
- });
450
- var WelcomeResponseSchema = z2.object({
451
- message: z2.string()
452
- });
453
- var OnboardingStartRequestSchema = z2.object({
454
- phoneE164: z2.string().regex(E164Regex),
455
- appInstanceId: z2.string().min(3),
456
- platform: z2.enum(["android", "ios", "web"]),
457
- turnstileToken: z2.string().min(20).optional(),
458
- appAttestation: z2.object({
459
- provider: z2.enum(["android", "ios", "web"]),
460
- token: z2.string().min(24)
461
- }).optional(),
462
- firstName: z2.string().trim().min(1).max(80).optional(),
463
- lastName: z2.string().trim().min(1).max(80).optional()
464
- });
465
- var OnboardingStartResponseSchema = z2.object({
466
- requestId: z2.string().min(1),
467
- checkUrl: z2.string().url().optional(),
468
- expiresInSec: z2.number().int().positive(),
469
- fallback: z2.enum(["SILENT_AUTH", "OTP"])
470
- });
471
- var OnboardingCompleteRequestSchema = z2.object({
472
- requestId: z2.string().min(1),
473
- code: z2.string().min(1).max(32),
474
- appInstanceId: z2.string().min(3),
475
- fingerprintHash: z2.string().min(3).optional()
476
- });
477
- var OnboardingCompleteResponseSchema = z2.object({
478
- sessionToken: z2.string().min(1),
479
- userId: UuidSchema,
480
- restricted: z2.boolean(),
481
- risk_reasons: z2.array(
482
- z2.enum(["SIM_SWAP_RECENT", "ROAMING", "CARRIER_CHANGED"])
483
- ),
484
- stepUpRequired: z2.boolean().optional(),
485
- riskStatus: z2.enum(["ok", "unavailable"]).optional()
486
- });
487
- var RegisterDeviceRequestSchema = z2.object({
488
- userId: UuidSchema,
489
- appInstanceId: z2.string().min(3),
490
- platform: z2.string().min(2),
491
- model: z2.string().optional(),
492
- networkSignals: z2.object({
493
- ip: z2.string().min(3),
494
- asn: z2.number().int().optional(),
495
- country: z2.string().min(2).optional(),
496
- carrier: z2.string().optional()
497
- })
498
- });
499
- var RegisterDeviceResponseSchema = z2.object({
500
- deviceId: z2.string().min(1),
501
- fingerprintHash: z2.string().min(1),
502
- driftScore: z2.number(),
503
- trustState: z2.enum(["TRUSTED_PRIMARY", "TRUSTED_SECONDARY", "UNVERIFIED"]),
504
- stepUpRequired: z2.boolean()
505
- });
506
- var AuthRefreshRequestSchema = z2.object({
507
- userId: UuidSchema,
508
- refreshToken: z2.string().min(8),
509
- appInstanceId: z2.string().min(3),
510
- fingerprintHash: z2.string().min(3)
511
- });
512
- var AuthRefreshResponseSchema = z2.object({
513
- refreshToken: z2.string().min(8),
514
- stepUpRequired: z2.boolean()
515
- });
516
- var AuthLogoutRequestSchema = z2.object({
517
- userId: UuidSchema,
518
- refreshToken: z2.string().min(8)
519
- });
520
- var PinSetRequestSchema = z2.object({
521
- userId: UuidSchema,
522
- pin: z2.string().regex(/^\d{6}$/)
523
- });
524
- var PinVerifyRequestSchema = z2.object({
525
- userId: UuidSchema,
526
- pin: z2.string().regex(/^\d{6}$/)
527
- });
528
- var OkResponseSchema = z2.object({
529
- ok: z2.boolean()
530
- });
531
- var RegisterSendDeviceKeyRequestSchema = z2.object({
532
- userId: UuidSchema,
533
- deviceId: z2.string().min(3),
534
- publicKey: z2.string().min(32)
535
- });
536
- var SEND_AUTH_PURPOSES = ["send_money", "offline_revoke"];
537
- var SendChallengeRequestSchema = z2.object({
538
- userId: UuidSchema,
539
- deviceId: z2.string().min(3),
540
- purpose: z2.enum(SEND_AUTH_PURPOSES).optional()
541
- });
542
- var SendChallengeResponseSchema = z2.object({
543
- challengeId: UuidSchema,
544
- nonce: z2.string().min(1),
545
- expiresAt: IsoDateSchema
546
- });
547
- var SendVerifyRequestSchema = z2.object({
548
- userId: UuidSchema,
549
- deviceId: z2.string().min(3),
550
- challengeId: UuidSchema,
551
- signature: z2.string().min(16)
552
- });
553
- var SendVerifyResponseSchema = z2.object({
554
- sendAuthToken: z2.string().min(16)
555
- });
556
- var ResolveRecipientRequestSchema = z2.object({
557
- identifier: z2.string().min(3)
558
- });
559
- var ResolveRecipientResponseSchema = z2.object({
560
- recipientUserId: UuidSchema,
561
- displayName: z2.string().min(1),
562
- normalizedIdentifier: z2.string().regex(E164Regex),
563
- isActive: z2.boolean()
564
- });
565
- var CreateTransferRequestSchema = z2.object({
566
- recipientIdentifier: z2.string().min(3),
567
- amountMinor: z2.number().int().positive(),
568
- currency: CurrencySchema,
569
- sendAuthToken: z2.string().min(16)
570
- });
571
- var TransferStatusSchema = z2.enum(["SETTLED", "PENDING_REVIEW", "DECLINED"]);
572
- var TransferResponseSchema = z2.object({
573
- transactionId: z2.string().min(1),
574
- status: TransferStatusSchema,
575
- userStatus: TransferStatusSchema,
576
- recipientName: z2.string().min(1),
577
- timestamp: IsoDateSchema,
578
- /**
579
- * Fresh issuer-signed OACs returned by the backend's post-commit
580
- * rotation hook on `SETTLED` transfers.
581
- *
582
- * In the current backend implementation this hook rotates LEGACY
583
- * hold-backed OACs only. Account-funded (no-hold) OACs introduced by
584
- * the unified-pay-rails refactor are NOT rotated here — their
585
- * cumulative spend counter and main-balance check are enforced at
586
- * claim submission time via `createTransfer` under the per-sender
587
- * advisory lock, so a stale no-hold OAC cannot authorise overspending
588
- * (it can only resolve to REVIEW on submission).
589
- *
590
- * Optional: omitted when the sender has no registered hold-backed
591
- * devices, when the refresh failed (best-effort), or on retry replays
592
- * that pre-date the refresh. When present, the entries supersede any
593
- * locally cached OACs for the listed devices; when absent, clients
594
- * should fall back to `/v1/me/offline/refresh`.
595
- *
596
- * Each entry is validated against the canonical `OACRecordSchema`,
597
- * so consumers can trust the runtime shape matches the static type.
598
- */
599
- offlineOacs: OACRecordSchema.array().optional()
600
- });
601
- var DirectionSchema = z2.enum(["OUTGOING", "INCOMING"]);
602
- var AccountActivityItemSchema = z2.object({
603
- id: z2.string().min(1),
604
- type: z2.string().min(1),
605
- direction: DirectionSchema,
606
- name: z2.string().min(1),
607
- identifier: z2.string().min(1),
608
- amountMinor: z2.number().int(),
609
- currency: CurrencySchema,
610
- status: z2.string().min(1),
611
- timestamp: IsoDateSchema
612
- });
613
- var AccountSummaryResponseSchema = z2.object({
614
- /** Authenticated user's stable internal id. */
615
- userId: UuidSchema,
616
- /**
617
- * 10-digit Nigeria Uniform Bank Account Number (NUBAN) allocated by the
618
- * bank partner. `null` when the user has no partner-allocated account yet.
619
- */
620
- nuban: z2.string().regex(/^[0-9]{10}$/).nullable(),
621
- balance: z2.number().int(),
622
- currency: CurrencySchema,
623
- dailySendLimit: z2.number().int().nonnegative(),
624
- dailySendRemaining: z2.number().int().nonnegative(),
625
- kycTier: z2.string().min(1),
626
- kycStatus: z2.string().min(1),
627
- recentActivity: z2.array(AccountActivityItemSchema)
628
- });
629
- var TransactionsListResponseSchema = z2.object({
630
- items: z2.array(AccountActivityItemSchema),
631
- nextCursor: z2.string().nullable()
632
- });
633
- var TransactionDetailResponseSchema = z2.object({
634
- transactionId: z2.string().min(1),
635
- type: z2.string().min(1),
636
- direction: DirectionSchema,
637
- counterpartyName: z2.string().min(1),
638
- counterpartyIdentifier: z2.string().min(1),
639
- amountMinor: z2.number().int(),
640
- currency: CurrencySchema,
641
- status: z2.string().min(1),
642
- timestamp: IsoDateSchema
643
- });
644
- var PushRegisterRequestSchema = z2.object({
645
- deviceId: z2.string().min(3),
646
- platform: z2.enum(["ios", "android", "web"]),
647
- token: z2.string().min(16)
648
- });
649
- var CreatePayLinkResponseSchema = z2.object({
650
- token: z2.string().min(1)
651
- });
652
- var ResolvePayLinkResponseSchema = z2.object({
653
- recipientUserId: UuidSchema,
654
- displayName: z2.string().min(1),
655
- normalizedIdentifier: z2.string().regex(E164Regex),
656
- isActive: z2.boolean()
657
- });
658
-
659
302
  // src/primitives.ts
660
- import { z as z3 } from "zod";
661
- var CurrencyCodeSchema = z3.string().trim().length(3).transform((value) => value.toUpperCase());
303
+ import { z as z2 } from "zod";
304
+ var CurrencyCodeSchema = z2.string().trim().length(3).transform((value) => value.toUpperCase());
662
305
  var currencyFractionDigits = {
663
306
  NGN: 2,
664
307
  USD: 2,
@@ -752,7 +395,7 @@ function moneyMinorToNumber(amountMinor) {
752
395
  }
753
396
 
754
397
  // src/collections/client.ts
755
- import { z as z4 } from "zod";
398
+ import { z as z3 } from "zod";
756
399
  var MERCHANT_PROFILE_STATUSES = [
757
400
  "pending",
758
401
  "active",
@@ -782,172 +425,172 @@ var MERCHANT_PAYOUT_STATUSES = [
782
425
  "failed",
783
426
  "cancelled"
784
427
  ];
785
- var MoneyKoboSchema = z4.number().int().positive().max(Number.MAX_SAFE_INTEGER);
786
- var MetadataSchema = z4.record(
787
- z4.union([z4.string(), z4.number(), z4.boolean(), z4.null()])
428
+ var MoneyKoboSchema = z3.number().int().positive().max(Number.MAX_SAFE_INTEGER);
429
+ var MetadataSchema = z3.record(
430
+ z3.union([z3.string(), z3.number(), z3.boolean(), z3.null()])
788
431
  );
789
- var CurrencySchema2 = z4.string().trim().length(3).transform((value) => value.toUpperCase());
790
- var ReferenceSchema = z4.string().trim().min(6).max(128).regex(/^[A-Za-z0-9._:-]+$/);
791
- var MerchantProfileSchema = z4.object({
792
- accountId: z4.string().uuid(),
793
- legalName: z4.string(),
794
- tradingName: z4.string(),
795
- merchantCategoryCode: z4.string().regex(/^\d{4}$/),
796
- nqrMerchantId: z4.string(),
797
- settlementBankCode: z4.string(),
798
- settlementAccountNumber: z4.string(),
799
- settlementAccountName: z4.string(),
800
- settlementSchedule: z4.enum(SETTLEMENT_SCHEDULES),
801
- status: z4.enum(MERCHANT_PROFILE_STATUSES),
802
- offlineEnabled: z4.boolean(),
432
+ var CurrencySchema2 = z3.string().trim().length(3).transform((value) => value.toUpperCase());
433
+ var ReferenceSchema = z3.string().trim().min(6).max(128).regex(/^[A-Za-z0-9._:-]+$/);
434
+ var MerchantProfileSchema = z3.object({
435
+ accountId: z3.string().uuid(),
436
+ legalName: z3.string(),
437
+ tradingName: z3.string(),
438
+ merchantCategoryCode: z3.string().regex(/^\d{4}$/),
439
+ nqrMerchantId: z3.string(),
440
+ settlementBankCode: z3.string(),
441
+ settlementAccountNumber: z3.string(),
442
+ settlementAccountName: z3.string(),
443
+ settlementSchedule: z3.enum(SETTLEMENT_SCHEDULES),
444
+ status: z3.enum(MERCHANT_PROFILE_STATUSES),
445
+ offlineEnabled: z3.boolean(),
803
446
  perTxLimitKobo: MoneyKoboSchema,
804
447
  dailyLimitKobo: MoneyKoboSchema,
805
448
  metadata: MetadataSchema,
806
- createdAtMs: z4.number().int().nonnegative(),
807
- updatedAtMs: z4.number().int().nonnegative()
449
+ createdAtMs: z3.number().int().nonnegative(),
450
+ updatedAtMs: z3.number().int().nonnegative()
808
451
  });
809
- var UpsertMerchantProfileInputSchema = z4.object({
810
- legalName: z4.string().trim().min(1).max(200),
811
- tradingName: z4.string().trim().min(1).max(25),
812
- merchantCategoryCode: z4.string().trim().regex(/^\d{4}$/),
813
- nqrMerchantId: z4.string().trim().min(3).max(64),
814
- settlementBankCode: z4.string().trim().min(2).max(16),
815
- settlementAccountNumber: z4.string().trim().min(5).max(32),
816
- settlementAccountName: z4.string().trim().min(1).max(200),
817
- settlementSchedule: z4.enum(SETTLEMENT_SCHEDULES).optional(),
818
- status: z4.enum(MERCHANT_PROFILE_STATUSES).optional(),
819
- offlineEnabled: z4.boolean().optional(),
452
+ var UpsertMerchantProfileInputSchema = z3.object({
453
+ legalName: z3.string().trim().min(1).max(200),
454
+ tradingName: z3.string().trim().min(1).max(25),
455
+ merchantCategoryCode: z3.string().trim().regex(/^\d{4}$/),
456
+ nqrMerchantId: z3.string().trim().min(3).max(64),
457
+ settlementBankCode: z3.string().trim().min(2).max(16),
458
+ settlementAccountNumber: z3.string().trim().min(5).max(32),
459
+ settlementAccountName: z3.string().trim().min(1).max(200),
460
+ settlementSchedule: z3.enum(SETTLEMENT_SCHEDULES).optional(),
461
+ status: z3.enum(MERCHANT_PROFILE_STATUSES).optional(),
462
+ offlineEnabled: z3.boolean().optional(),
820
463
  perTxLimitKobo: MoneyKoboSchema.optional(),
821
464
  dailyLimitKobo: MoneyKoboSchema.optional(),
822
465
  metadata: MetadataSchema.optional()
823
466
  });
824
- var CollectionIntentSchema = z4.object({
825
- intentId: z4.string().uuid(),
826
- accountId: z4.string().uuid(),
827
- terminalId: z4.string().uuid().nullable(),
828
- reference: z4.string(),
829
- amountKobo: z4.number().int().positive().nullable(),
830
- currency: z4.string().length(3),
831
- status: z4.enum(COLLECTION_INTENT_STATUSES),
832
- description: z4.string().nullable(),
833
- nqrPayload: z4.string(),
834
- provider: z4.string(),
835
- providerReference: z4.string().nullable(),
467
+ var CollectionIntentSchema = z3.object({
468
+ intentId: z3.string().uuid(),
469
+ accountId: z3.string().uuid(),
470
+ terminalId: z3.string().uuid().nullable(),
471
+ reference: z3.string(),
472
+ amountKobo: z3.number().int().positive().nullable(),
473
+ currency: z3.string().length(3),
474
+ status: z3.enum(COLLECTION_INTENT_STATUSES),
475
+ description: z3.string().nullable(),
476
+ nqrPayload: z3.string(),
477
+ provider: z3.string(),
478
+ providerReference: z3.string().nullable(),
836
479
  metadata: MetadataSchema,
837
- expiresAtMs: z4.number().int().nonnegative().nullable(),
838
- paidAtMs: z4.number().int().nonnegative().nullable(),
839
- createdAtMs: z4.number().int().nonnegative(),
840
- updatedAtMs: z4.number().int().nonnegative()
480
+ expiresAtMs: z3.number().int().nonnegative().nullable(),
481
+ paidAtMs: z3.number().int().nonnegative().nullable(),
482
+ createdAtMs: z3.number().int().nonnegative(),
483
+ updatedAtMs: z3.number().int().nonnegative()
841
484
  });
842
- var CreateCollectionIntentInputSchema = z4.object({
485
+ var CreateCollectionIntentInputSchema = z3.object({
843
486
  reference: ReferenceSchema.optional(),
844
487
  amountKobo: MoneyKoboSchema.optional(),
845
488
  currency: CurrencySchema2.optional(),
846
- terminalId: z4.string().uuid().optional(),
847
- terminalLabel: z4.string().trim().min(1).max(25).optional(),
848
- merchantCity: z4.string().trim().min(1).max(15).optional(),
849
- description: z4.string().trim().min(1).max(280).optional(),
850
- expiresAtMs: z4.number().int().positive().optional(),
851
- provider: z4.string().trim().min(1).max(40).optional(),
489
+ terminalId: z3.string().uuid().optional(),
490
+ terminalLabel: z3.string().trim().min(1).max(25).optional(),
491
+ merchantCity: z3.string().trim().min(1).max(15).optional(),
492
+ description: z3.string().trim().min(1).max(280).optional(),
493
+ expiresAtMs: z3.number().int().positive().optional(),
494
+ provider: z3.string().trim().min(1).max(40).optional(),
852
495
  metadata: MetadataSchema.optional()
853
496
  });
854
- var PublicCollectionIntentSchema = z4.object({
855
- intentId: z4.string().uuid(),
856
- reference: z4.string(),
857
- amountKobo: z4.number().int().positive().nullable(),
858
- currency: z4.string().length(3),
859
- status: z4.enum(COLLECTION_INTENT_STATUSES),
860
- merchantAccountId: z4.string().uuid(),
861
- merchantName: z4.string(),
862
- merchantCategoryCode: z4.string(),
863
- description: z4.string().nullable(),
864
- expiresAtMs: z4.number().int().nonnegative().nullable()
497
+ var PublicCollectionIntentSchema = z3.object({
498
+ intentId: z3.string().uuid(),
499
+ reference: z3.string(),
500
+ amountKobo: z3.number().int().positive().nullable(),
501
+ currency: z3.string().length(3),
502
+ status: z3.enum(COLLECTION_INTENT_STATUSES),
503
+ merchantAccountId: z3.string().uuid(),
504
+ merchantName: z3.string(),
505
+ merchantCategoryCode: z3.string(),
506
+ description: z3.string().nullable(),
507
+ expiresAtMs: z3.number().int().nonnegative().nullable()
865
508
  });
866
- var PayCollectionInputSchema = z4.object({
509
+ var PayCollectionInputSchema = z3.object({
867
510
  reference: ReferenceSchema,
868
511
  amountKobo: MoneyKoboSchema.optional(),
869
512
  currency: CurrencySchema2.optional(),
870
- idempotencyKey: z4.string().trim().min(8).max(160).optional()
513
+ idempotencyKey: z3.string().trim().min(8).max(160).optional()
871
514
  });
872
- var CollectionPaymentSchema = z4.object({
873
- paymentId: z4.string().uuid(),
874
- intentId: z4.string().uuid(),
875
- accountId: z4.string().uuid(),
876
- payerUserId: z4.string().uuid().nullable(),
877
- merchantOwnerUserId: z4.string().uuid(),
515
+ var CollectionPaymentSchema = z3.object({
516
+ paymentId: z3.string().uuid(),
517
+ intentId: z3.string().uuid(),
518
+ accountId: z3.string().uuid(),
519
+ payerUserId: z3.string().uuid().nullable(),
520
+ merchantOwnerUserId: z3.string().uuid(),
878
521
  amountKobo: MoneyKoboSchema,
879
- currency: z4.string().length(3),
880
- status: z4.enum(COLLECTION_PAYMENT_STATUSES),
881
- provider: z4.string(),
882
- providerReference: z4.string().nullable(),
883
- idempotencyKey: z4.string().nullable(),
884
- ledgerRef: z4.string(),
885
- failureCode: z4.string().nullable(),
886
- failureMessage: z4.string().nullable(),
887
- paidAtMs: z4.number().int().nonnegative().nullable(),
888
- createdAtMs: z4.number().int().nonnegative(),
889
- updatedAtMs: z4.number().int().nonnegative()
522
+ currency: z3.string().length(3),
523
+ status: z3.enum(COLLECTION_PAYMENT_STATUSES),
524
+ provider: z3.string(),
525
+ providerReference: z3.string().nullable(),
526
+ idempotencyKey: z3.string().nullable(),
527
+ ledgerRef: z3.string(),
528
+ failureCode: z3.string().nullable(),
529
+ failureMessage: z3.string().nullable(),
530
+ paidAtMs: z3.number().int().nonnegative().nullable(),
531
+ createdAtMs: z3.number().int().nonnegative(),
532
+ updatedAtMs: z3.number().int().nonnegative()
890
533
  });
891
- var CollectionPaymentResultSchema = z4.object({
534
+ var CollectionPaymentResultSchema = z3.object({
892
535
  payment: CollectionPaymentSchema,
893
536
  intent: CollectionIntentSchema,
894
- receipt: z4.unknown().optional(),
895
- replayed: z4.boolean()
537
+ receipt: z3.unknown().optional(),
538
+ replayed: z3.boolean()
896
539
  });
897
- var CollectionReportSummarySchema = z4.object({
898
- accountId: z4.string().uuid(),
899
- fromMs: z4.number().int().nonnegative(),
900
- toMs: z4.number().int().nonnegative(),
901
- currency: z4.string().length(3),
902
- paidCount: z4.number().int().nonnegative(),
903
- paidAmountKobo: z4.number().int().nonnegative(),
904
- pendingCount: z4.number().int().nonnegative(),
905
- failedCount: z4.number().int().nonnegative(),
906
- reversedCount: z4.number().int().nonnegative(),
907
- availableBalanceKobo: z4.number().int().nonnegative()
540
+ var CollectionReportSummarySchema = z3.object({
541
+ accountId: z3.string().uuid(),
542
+ fromMs: z3.number().int().nonnegative(),
543
+ toMs: z3.number().int().nonnegative(),
544
+ currency: z3.string().length(3),
545
+ paidCount: z3.number().int().nonnegative(),
546
+ paidAmountKobo: z3.number().int().nonnegative(),
547
+ pendingCount: z3.number().int().nonnegative(),
548
+ failedCount: z3.number().int().nonnegative(),
549
+ reversedCount: z3.number().int().nonnegative(),
550
+ availableBalanceKobo: z3.number().int().nonnegative()
908
551
  });
909
- var CollectionStatementSchema = z4.object({
910
- accountId: z4.string().uuid(),
911
- year: z4.number().int(),
912
- month: z4.number().int().min(1).max(12),
913
- currency: z4.string().length(3),
914
- totalPaidKobo: z4.number().int().nonnegative(),
915
- items: z4.array(CollectionPaymentSchema)
552
+ var CollectionStatementSchema = z3.object({
553
+ accountId: z3.string().uuid(),
554
+ year: z3.number().int(),
555
+ month: z3.number().int().min(1).max(12),
556
+ currency: z3.string().length(3),
557
+ totalPaidKobo: z3.number().int().nonnegative(),
558
+ items: z3.array(CollectionPaymentSchema)
916
559
  });
917
- var CreatePayoutInputSchema = z4.object({
560
+ var CreatePayoutInputSchema = z3.object({
918
561
  amountKobo: MoneyKoboSchema,
919
562
  currency: CurrencySchema2.optional(),
920
- idempotencyKey: z4.string().trim().min(8).max(160)
563
+ idempotencyKey: z3.string().trim().min(8).max(160)
921
564
  });
922
- var MerchantPayoutSchema = z4.object({
923
- payoutId: z4.string().uuid(),
924
- accountId: z4.string().uuid(),
565
+ var MerchantPayoutSchema = z3.object({
566
+ payoutId: z3.string().uuid(),
567
+ accountId: z3.string().uuid(),
925
568
  amountKobo: MoneyKoboSchema,
926
- currency: z4.string().length(3),
927
- status: z4.enum(MERCHANT_PAYOUT_STATUSES),
928
- idempotencyKey: z4.string().nullable(),
929
- ledgerRef: z4.string(),
930
- providerReference: z4.string().nullable(),
931
- requestedByUserId: z4.string().uuid().nullable(),
932
- failureCode: z4.string().nullable(),
933
- failureMessage: z4.string().nullable(),
934
- createdAtMs: z4.number().int().nonnegative(),
935
- updatedAtMs: z4.number().int().nonnegative()
569
+ currency: z3.string().length(3),
570
+ status: z3.enum(MERCHANT_PAYOUT_STATUSES),
571
+ idempotencyKey: z3.string().nullable(),
572
+ ledgerRef: z3.string(),
573
+ providerReference: z3.string().nullable(),
574
+ requestedByUserId: z3.string().uuid().nullable(),
575
+ failureCode: z3.string().nullable(),
576
+ failureMessage: z3.string().nullable(),
577
+ createdAtMs: z3.number().int().nonnegative(),
578
+ updatedAtMs: z3.number().int().nonnegative()
936
579
  });
937
- var ProviderEventInputSchema = z4.object({
938
- provider: z4.string().trim().min(1).max(80),
939
- eventId: z4.string().trim().min(1).max(160),
940
- eventType: z4.string().trim().min(1).max(120),
941
- payload: z4.record(z4.unknown()).optional()
580
+ var ProviderEventInputSchema = z3.object({
581
+ provider: z3.string().trim().min(1).max(80),
582
+ eventId: z3.string().trim().min(1).max(160),
583
+ eventType: z3.string().trim().min(1).max(120),
584
+ payload: z3.record(z3.unknown()).optional()
942
585
  });
943
- var ProviderEventRecordSchema = z4.object({
944
- id: z4.string().uuid(),
945
- provider: z4.string(),
946
- eventId: z4.string(),
947
- eventType: z4.string(),
948
- signatureVerified: z4.boolean(),
949
- receivedAtMs: z4.number().int().nonnegative(),
950
- processedAtMs: z4.number().int().nonnegative().nullable()
586
+ var ProviderEventRecordSchema = z3.object({
587
+ id: z3.string().uuid(),
588
+ provider: z3.string(),
589
+ eventId: z3.string(),
590
+ eventType: z3.string(),
591
+ signatureVerified: z3.boolean(),
592
+ receivedAtMs: z3.number().int().nonnegative(),
593
+ processedAtMs: z3.number().int().nonnegative().nullable()
951
594
  });
952
595
  function createCollectionsClient(opts) {
953
596
  const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
@@ -1462,7 +1105,7 @@ var FlurClient = class {
1462
1105
  try {
1463
1106
  body = requestSchema ? JSON.stringify(requestSchema.parse(input)) : init2.body;
1464
1107
  } catch (err) {
1465
- if (err instanceof z5.ZodError) {
1108
+ if (err instanceof z4.ZodError) {
1466
1109
  throw new FlurError("Invalid request payload", "INVALID_REQUEST", {
1467
1110
  details: err.flatten()
1468
1111
  });
@@ -1490,7 +1133,7 @@ var FlurClient = class {
1490
1133
  try {
1491
1134
  return responseSchema.parse(payload);
1492
1135
  } catch (err) {
1493
- if (err instanceof z5.ZodError) {
1136
+ if (err instanceof z4.ZodError) {
1494
1137
  throw new FlurError(
1495
1138
  "SDK contract validation failed",
1496
1139
  "INVALID_REQUEST",
@@ -1921,7 +1564,7 @@ function constantTimeEqual(a, b) {
1921
1564
  }
1922
1565
 
1923
1566
  // src/offline/oac.ts
1924
- import { z as z6 } from "zod";
1567
+ import { z as z5 } from "zod";
1925
1568
 
1926
1569
  // src/crypto/p256-issuer.ts
1927
1570
  import { p256 } from "@noble/curves/nist";
@@ -2003,20 +1646,20 @@ function verifyIssuerP256(bytes, signatureB64, issuerPublicKeySpkiB64) {
2003
1646
  var OAC_DEFAULT_PER_TX_KOBO = 5e5;
2004
1647
  var OAC_DEFAULT_CUMULATIVE_KOBO = 2e6;
2005
1648
  var OAC_DEFAULT_VALIDITY_MS = 24 * 60 * 60 * 1e3;
2006
- var Base64Std2 = z6.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (standard) string");
2007
- var OACSchema = z6.object({
2008
- userId: z6.string().min(1),
2009
- deviceId: z6.string().min(1),
1649
+ var Base64Std = z5.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (standard) string");
1650
+ var OACSchema = z5.object({
1651
+ userId: z5.string().min(1),
1652
+ deviceId: z5.string().min(1),
2010
1653
  /** SubjectPublicKeyInfo DER, base64 (P-256). */
2011
- devicePublicKey: Base64Std2,
2012
- perTxCapKobo: z6.number().int().nonnegative(),
2013
- cumulativeCapKobo: z6.number().int().nonnegative(),
2014
- validFromMs: z6.number().int().nonnegative(),
2015
- validUntilMs: z6.number().int().positive(),
2016
- counterSeed: z6.number().int().nonnegative(),
2017
- nonce: z6.string().min(1),
1654
+ devicePublicKey: Base64Std,
1655
+ perTxCapKobo: z5.number().int().nonnegative(),
1656
+ cumulativeCapKobo: z5.number().int().nonnegative(),
1657
+ validFromMs: z5.number().int().nonnegative(),
1658
+ validUntilMs: z5.number().int().positive(),
1659
+ counterSeed: z5.number().int().nonnegative(),
1660
+ nonce: z5.string().min(1),
2018
1661
  /** ASN.1 DER ECDSA(SHA-256) signature, base64. */
2019
- issuerSig: Base64Std2
1662
+ issuerSig: Base64Std
2020
1663
  }).refine((v) => v.validUntilMs > v.validFromMs, {
2021
1664
  message: "validUntilMs must be greater than validFromMs"
2022
1665
  }).refine((v) => v.perTxCapKobo <= v.cumulativeCapKobo, {
@@ -2110,19 +1753,19 @@ function decodeBase45(s) {
2110
1753
  }
2111
1754
 
2112
1755
  // src/offline/messages.ts
2113
- import { z as z7 } from "zod";
2114
- var Base64Sig = z7.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (standard) signature");
2115
- var OfflinePaymentRequestSchema = z7.object({
2116
- reference: z7.string().min(1),
2117
- amountKobo: z7.number().int().positive(),
1756
+ import { z as z6 } from "zod";
1757
+ var Base64Sig = z6.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (standard) signature");
1758
+ var OfflinePaymentRequestSchema = z6.object({
1759
+ reference: z6.string().min(1),
1760
+ amountKobo: z6.number().int().positive(),
2118
1761
  merchantOAC: OACSchema,
2119
- expiresAtMs: z7.number().int().positive(),
1762
+ expiresAtMs: z6.number().int().positive(),
2120
1763
  merchantSig: Base64Sig
2121
1764
  });
2122
- var OfflinePaymentAuthorizationSchema = z7.object({
1765
+ var OfflinePaymentAuthorizationSchema = z6.object({
2123
1766
  request: OfflinePaymentRequestSchema,
2124
1767
  payerOAC: OACSchema,
2125
- payerCounter: z7.number().int().positive(),
1768
+ payerCounter: z6.number().int().positive(),
2126
1769
  payerSig: Base64Sig
2127
1770
  });
2128
1771
  function buildPaymentRequest(input) {
@@ -2234,60 +1877,60 @@ function decodeAuthorizationQR(s) {
2234
1877
  }
2235
1878
 
2236
1879
  // src/offline/settlements.ts
2237
- import { z as z8 } from "zod";
1880
+ import { z as z7 } from "zod";
2238
1881
  import { sha256 } from "@noble/hashes/sha256";
2239
1882
  import { bytesToHex } from "@noble/hashes/utils";
2240
- var OfflineTokenSchema = z8.object({
2241
- tokenId: z8.string().uuid(),
2242
- tokenSerial: z8.string(),
2243
- issuerAccountId: z8.string().uuid(),
2244
- payerUserId: z8.string().uuid(),
2245
- maxAmountKobo: z8.number().int().positive(),
2246
- currency: z8.string().length(3),
2247
- issuedAtMs: z8.number().int().nonnegative(),
2248
- expiresAtMs: z8.number().int().nonnegative(),
2249
- issuerSig: z8.string()
1883
+ var OfflineTokenSchema = z7.object({
1884
+ tokenId: z7.string().uuid(),
1885
+ tokenSerial: z7.string(),
1886
+ issuerAccountId: z7.string().uuid(),
1887
+ payerUserId: z7.string().uuid(),
1888
+ maxAmountKobo: z7.number().int().positive(),
1889
+ currency: z7.string().length(3),
1890
+ issuedAtMs: z7.number().int().nonnegative(),
1891
+ expiresAtMs: z7.number().int().nonnegative(),
1892
+ issuerSig: z7.string()
2250
1893
  });
2251
- var PaymentClaimSchema = z8.object({
2252
- encounterId: z8.string().regex(/^[0-9a-f]{64}$/i).optional(),
2253
- tokenSerial: z8.string(),
2254
- payerUserId: z8.string().uuid(),
2255
- payeeUserId: z8.string().uuid(),
2256
- payerNonce: z8.string(),
2257
- payeeNonce: z8.string(),
2258
- amountKobo: z8.number().int().positive(),
2259
- currency: z8.string().length(3).default("NGN"),
2260
- occurredAtMs: z8.number().int().nonnegative(),
2261
- completedAtMs: z8.number().int().nonnegative().optional(),
2262
- contextId: z8.string().optional(),
1894
+ var PaymentClaimSchema = z7.object({
1895
+ encounterId: z7.string().regex(/^[0-9a-f]{64}$/i).optional(),
1896
+ tokenSerial: z7.string(),
1897
+ payerUserId: z7.string().uuid(),
1898
+ payeeUserId: z7.string().uuid(),
1899
+ payerNonce: z7.string(),
1900
+ payeeNonce: z7.string(),
1901
+ amountKobo: z7.number().int().positive(),
1902
+ currency: z7.string().length(3).default("NGN"),
1903
+ occurredAtMs: z7.number().int().nonnegative(),
1904
+ completedAtMs: z7.number().int().nonnegative().optional(),
1905
+ contextId: z7.string().optional(),
2263
1906
  // Stage 2c: P-256 device keys are now SubjectPublicKeyInfo DER, base64.
2264
1907
  // Signatures are ASN.1 DER ECDSA(SHA-256), base64. Backwards-incompatible
2265
1908
  // wire change; the backend has the matching widening in offline-settlements
2266
1909
  // service + zod schema.
2267
- payerPubkey: z8.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
2268
- payerSignature: z8.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
2269
- payeePubkey: z8.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/).optional(),
2270
- payeeSignature: z8.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/).optional()
1910
+ payerPubkey: z7.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
1911
+ payerSignature: z7.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
1912
+ payeePubkey: z7.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/).optional(),
1913
+ payeeSignature: z7.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/).optional()
2271
1914
  });
2272
- var SettlementSchema = z8.object({
2273
- settlementId: z8.string().uuid(),
2274
- settlementKey: z8.string().regex(/^[0-9a-f]{64}$/i),
2275
- encounterId: z8.string().regex(/^[0-9a-f]{64}$/i),
2276
- issuerAccountId: z8.string().uuid(),
2277
- tokenSerial: z8.string(),
2278
- payerUserId: z8.string().uuid(),
2279
- payeeUserId: z8.string().uuid(),
2280
- amountKobo: z8.number().int().nonnegative(),
2281
- currency: z8.string().length(3),
2282
- receiptId: z8.string().nullable(),
2283
- status: z8.enum(["SETTLED", "REVIEW", "REJECTED"]),
2284
- issuerSig: z8.string(),
2285
- createdAtMs: z8.number().int().nonnegative()
1915
+ var SettlementSchema = z7.object({
1916
+ settlementId: z7.string().uuid(),
1917
+ settlementKey: z7.string().regex(/^[0-9a-f]{64}$/i),
1918
+ encounterId: z7.string().regex(/^[0-9a-f]{64}$/i),
1919
+ issuerAccountId: z7.string().uuid(),
1920
+ tokenSerial: z7.string(),
1921
+ payerUserId: z7.string().uuid(),
1922
+ payeeUserId: z7.string().uuid(),
1923
+ amountKobo: z7.number().int().nonnegative(),
1924
+ currency: z7.string().length(3),
1925
+ receiptId: z7.string().nullable(),
1926
+ status: z7.enum(["SETTLED", "REVIEW", "REJECTED"]),
1927
+ issuerSig: z7.string(),
1928
+ createdAtMs: z7.number().int().nonnegative()
2286
1929
  });
2287
- var SettleResponseSchema = z8.object({
1930
+ var SettleResponseSchema = z7.object({
2288
1931
  settlement: SettlementSchema,
2289
- encounterId: z8.string().regex(/^[0-9a-f]{64}$/i),
2290
- replayed: z8.boolean()
1932
+ encounterId: z7.string().regex(/^[0-9a-f]{64}$/i),
1933
+ replayed: z7.boolean()
2291
1934
  });
2292
1935
  var ENCOUNTER_DOMAIN = "offline:v1:encounter";
2293
1936
  async function sha256Hex(input) {
@@ -2461,7 +2104,7 @@ function createHmacFetch(opts) {
2461
2104
  }
2462
2105
 
2463
2106
  // src/partner/client.ts
2464
- import { z as z9 } from "zod";
2107
+ import { z as z8 } from "zod";
2465
2108
  import { sha256 as sha2563 } from "@noble/hashes/sha256";
2466
2109
  import { hmac as hmac2 } from "@noble/hashes/hmac";
2467
2110
  import { bytesToHex as bytesToHex4 } from "@noble/hashes/utils";
@@ -2485,18 +2128,18 @@ var PARTNER_SCOPES = [
2485
2128
  "partner:payout:write",
2486
2129
  "partner:reconciliation:read"
2487
2130
  ];
2488
- var ApiCredentialPublicSchema = z9.object({
2489
- id: z9.string().uuid(),
2490
- accountId: z9.string().uuid(),
2491
- keyId: z9.string(),
2492
- scopes: z9.array(z9.enum(PARTNER_SCOPES)),
2493
- label: z9.string().nullable(),
2494
- createdAtMs: z9.number().int().nonnegative(),
2495
- lastUsedAtMs: z9.number().int().nonnegative().nullable(),
2496
- revokedAtMs: z9.number().int().nonnegative().nullable()
2131
+ var ApiCredentialPublicSchema = z8.object({
2132
+ id: z8.string().uuid(),
2133
+ accountId: z8.string().uuid(),
2134
+ keyId: z8.string(),
2135
+ scopes: z8.array(z8.enum(PARTNER_SCOPES)),
2136
+ label: z8.string().nullable(),
2137
+ createdAtMs: z8.number().int().nonnegative(),
2138
+ lastUsedAtMs: z8.number().int().nonnegative().nullable(),
2139
+ revokedAtMs: z8.number().int().nonnegative().nullable()
2497
2140
  });
2498
2141
  var MintedApiCredentialSchema = ApiCredentialPublicSchema.extend({
2499
- secret: z9.string().min(1)
2142
+ secret: z8.string().min(1)
2500
2143
  });
2501
2144
  var enc = new TextEncoder();
2502
2145
  async function sha256Hex2(input) {
@@ -2653,8 +2296,8 @@ function createApiCredentialsAdminClient(opts) {
2653
2296
  }
2654
2297
  return parser(raw);
2655
2298
  }
2656
- const listSchema = z9.object({
2657
- items: z9.array(ApiCredentialPublicSchema)
2299
+ const listSchema = z8.object({
2300
+ items: z8.array(ApiCredentialPublicSchema)
2658
2301
  });
2659
2302
  return {
2660
2303
  list: (accountId) => call(
@@ -2679,7 +2322,7 @@ function createApiCredentialsAdminClient(opts) {
2679
2322
  }
2680
2323
 
2681
2324
  // src/passes/pass.ts
2682
- import { z as z10 } from "zod";
2325
+ import { z as z9 } from "zod";
2683
2326
  var PASS_KINDS = [
2684
2327
  "ride-ticket",
2685
2328
  "transit-pass",
@@ -2695,39 +2338,39 @@ var PASS_STATES = [
2695
2338
  "expired",
2696
2339
  "revoked"
2697
2340
  ];
2698
- var PassMetadataSchema = z10.record(
2699
- z10.union([z10.string(), z10.number(), z10.boolean(), z10.null()])
2341
+ var PassMetadataSchema = z9.record(
2342
+ z9.union([z9.string(), z9.number(), z9.boolean(), z9.null()])
2700
2343
  );
2701
- var PassSchema = z10.object({
2702
- passId: z10.string().min(1),
2344
+ var PassSchema = z9.object({
2345
+ passId: z9.string().min(1),
2703
2346
  /** Optional client/template grouping id (server may omit). */
2704
- templateId: z10.string().min(1).optional(),
2347
+ templateId: z9.string().min(1).optional(),
2705
2348
  /** Optional human-facing holder identity (server may omit). The cryptographic binding
2706
2349
  * is `holderDevicePubkey` below. */
2707
- holderUserId: z10.string().min(1).optional(),
2708
- kind: z10.enum(PASS_KINDS),
2709
- issuerId: z10.string().min(1),
2710
- issuedAtMs: z10.number().int().nonnegative(),
2711
- validFromMs: z10.number().int().nonnegative(),
2712
- validUntilMs: z10.number().int().positive(),
2713
- state: z10.enum(PASS_STATES),
2350
+ holderUserId: z9.string().min(1).optional(),
2351
+ kind: z9.enum(PASS_KINDS),
2352
+ issuerId: z9.string().min(1),
2353
+ issuedAtMs: z9.number().int().nonnegative(),
2354
+ validFromMs: z9.number().int().nonnegative(),
2355
+ validUntilMs: z9.number().int().positive(),
2356
+ state: z9.enum(PASS_STATES),
2714
2357
  metadata: PassMetadataSchema,
2715
- nonce: z10.string().min(1),
2358
+ nonce: z9.string().min(1),
2716
2359
  /** Device id this pass is bound to (FK to backend `device_keys`). */
2717
- holderDeviceId: z10.string().min(1),
2360
+ holderDeviceId: z9.string().min(1),
2718
2361
  /** SubjectPublicKeyInfo DER (P-256) of the bound device, base64. The redemption
2719
2362
  * signature is verified against this key — it is the security-critical binding. */
2720
- holderDevicePubkey: z10.string().min(64).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
2363
+ holderDevicePubkey: z9.string().min(64).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
2721
2364
  /** Optional fixed amount for monetary passes (vouchers, gift cards) in kobo. */
2722
- amountKobo: z10.number().int().nonnegative().optional(),
2365
+ amountKobo: z9.number().int().nonnegative().optional(),
2723
2366
  /** ISO-4217-ish currency code; required on the wire. SDK builders default to NGN. */
2724
- currency: z10.string().min(3).max(8),
2367
+ currency: z9.string().min(3).max(8),
2725
2368
  /** Monotonic redemption counter floor. Redemption.counter MUST be > counterSeed. */
2726
- counterSeed: z10.number().int().nonnegative(),
2369
+ counterSeed: z9.number().int().nonnegative(),
2727
2370
  /** Optional cumulative spend cap in kobo across all redemptions of this pass. */
2728
- cumulativeCapKobo: z10.number().int().nonnegative().optional(),
2371
+ cumulativeCapKobo: z9.number().int().nonnegative().optional(),
2729
2372
  /** ASN.1 DER ECDSA P-256 signature, base64. */
2730
- issuerSig: z10.string().min(64).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/)
2373
+ issuerSig: z9.string().min(64).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/)
2731
2374
  }).refine((v) => v.validUntilMs > v.validFromMs, {
2732
2375
  message: "validUntilMs must be greater than validFromMs"
2733
2376
  });
@@ -2784,20 +2427,20 @@ function isPassWithinValidity(pass, nowMs) {
2784
2427
  }
2785
2428
 
2786
2429
  // src/passes/redemption.ts
2787
- import { z as z11 } from "zod";
2788
- var Base64Std3 = z11.string().min(16).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (std)");
2789
- var RedemptionSchema = z11.object({
2430
+ import { z as z10 } from "zod";
2431
+ var Base64Std2 = z10.string().min(16).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (std)");
2432
+ var RedemptionSchema = z10.object({
2790
2433
  pass: PassSchema,
2791
- redeemerId: z11.string().min(1),
2792
- redeemedAtMs: z11.number().int().nonnegative(),
2434
+ redeemerId: z10.string().min(1),
2435
+ redeemedAtMs: z10.number().int().nonnegative(),
2793
2436
  /** Strictly monotonic counter scoped to a single pass. Must be > pass.counterSeed
2794
2437
  * and > the redeemer's lastSeenCounter for this pass. */
2795
- counter: z11.number().int().positive(),
2438
+ counter: z10.number().int().positive(),
2796
2439
  /** Amount being redeemed in kobo (0 for non-monetary passes like ride tickets). */
2797
- amountKobo: z11.number().int().nonnegative(),
2798
- nonce: z11.string().min(1),
2440
+ amountKobo: z10.number().int().nonnegative(),
2441
+ nonce: z10.string().min(1),
2799
2442
  /** ASN.1 DER ECDSA P-256 signature over canonicalJSONBytes(unsigned), base64. */
2800
- holderSig: Base64Std3
2443
+ holderSig: Base64Std2
2801
2444
  });
2802
2445
  var REDEEMABLE_STATES = /* @__PURE__ */ new Set(["issued", "active"]);
2803
2446
  function buildRedemption(input) {
@@ -2879,40 +2522,40 @@ function verifyRedemption(r, issuerPublicKeySpkiB64) {
2879
2522
  }
2880
2523
 
2881
2524
  // src/receipts/receipt.ts
2882
- import { z as z12 } from "zod";
2525
+ import { z as z11 } from "zod";
2883
2526
  var RECEIPT_CHANNELS = ["cash", "pass"];
2884
2527
  var RECEIPT_KINDS = RECEIPT_CHANNELS;
2885
- var ReceiptPayloadSchema = z12.record(
2886
- z12.union([z12.string(), z12.number(), z12.boolean(), z12.null()])
2528
+ var ReceiptPayloadSchema = z11.record(
2529
+ z11.union([z11.string(), z11.number(), z11.boolean(), z11.null()])
2887
2530
  );
2888
- var ReceiptSchema = z12.object({
2889
- receiptId: z12.string().min(1),
2890
- channel: z12.enum(RECEIPT_CHANNELS),
2531
+ var ReceiptSchema = z11.object({
2532
+ receiptId: z11.string().min(1),
2533
+ channel: z11.enum(RECEIPT_CHANNELS),
2891
2534
  /** Cash-channel: send_intents.id. Required when channel === 'cash'. */
2892
- intentId: z12.string().min(1).optional(),
2535
+ intentId: z11.string().min(1).optional(),
2893
2536
  /** Pass-channel: pass_redemptions.id. Required when channel === 'pass'. */
2894
- passRedemptionId: z12.string().min(1).optional(),
2895
- payerUserId: z12.string().min(1),
2896
- payeeUserId: z12.string().min(1),
2897
- amountKobo: z12.number().int().nonnegative(),
2898
- currency: z12.string().min(3).max(8),
2899
- issuedAtMs: z12.number().int().nonnegative(),
2900
- issuerId: z12.string().min(1),
2537
+ passRedemptionId: z11.string().min(1).optional(),
2538
+ payerUserId: z11.string().min(1),
2539
+ payeeUserId: z11.string().min(1),
2540
+ amountKobo: z11.number().int().nonnegative(),
2541
+ currency: z11.string().min(3).max(8),
2542
+ issuedAtMs: z11.number().int().nonnegative(),
2543
+ issuerId: z11.string().min(1),
2901
2544
  payload: ReceiptPayloadSchema,
2902
2545
  /** ASN.1 DER ECDSA P-256 signature, base64. */
2903
- issuerSig: z12.string().min(64).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/)
2546
+ issuerSig: z11.string().min(64).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/)
2904
2547
  }).superRefine((v, ctx) => {
2905
2548
  if (v.channel === "cash") {
2906
2549
  if (!v.intentId) {
2907
2550
  ctx.addIssue({
2908
- code: z12.ZodIssueCode.custom,
2551
+ code: z11.ZodIssueCode.custom,
2909
2552
  message: "cash receipts require intentId",
2910
2553
  path: ["intentId"]
2911
2554
  });
2912
2555
  }
2913
2556
  if (v.passRedemptionId) {
2914
2557
  ctx.addIssue({
2915
- code: z12.ZodIssueCode.custom,
2558
+ code: z11.ZodIssueCode.custom,
2916
2559
  message: "cash receipts must not carry passRedemptionId",
2917
2560
  path: ["passRedemptionId"]
2918
2561
  });
@@ -2920,14 +2563,14 @@ var ReceiptSchema = z12.object({
2920
2563
  } else if (v.channel === "pass") {
2921
2564
  if (!v.passRedemptionId) {
2922
2565
  ctx.addIssue({
2923
- code: z12.ZodIssueCode.custom,
2566
+ code: z11.ZodIssueCode.custom,
2924
2567
  message: "pass receipts require passRedemptionId",
2925
2568
  path: ["passRedemptionId"]
2926
2569
  });
2927
2570
  }
2928
2571
  if (v.intentId) {
2929
2572
  ctx.addIssue({
2930
- code: z12.ZodIssueCode.custom,
2573
+ code: z11.ZodIssueCode.custom,
2931
2574
  message: "pass receipts must not carry intentId",
2932
2575
  path: ["intentId"]
2933
2576
  });
@@ -3229,28 +2872,244 @@ function init(opts) {
3229
2872
  }
3230
2873
 
3231
2874
  // src/accounts/client.ts
3232
- import { z as z13 } from "zod";
2875
+ import { z as z12 } from "zod";
3233
2876
  var ACCOUNT_TYPES = ["personal", "business", "partner"];
3234
2877
  var ACCOUNT_STATUSES = ["active", "suspended", "closed"];
3235
2878
  var MEMBERSHIP_ROLES = ["owner", "admin", "driver", "staff"];
3236
- var AccountSchema = z13.object({
3237
- accountId: z13.string().uuid(),
3238
- type: z13.enum(ACCOUNT_TYPES),
3239
- displayName: z13.string().min(1),
3240
- status: z13.enum(ACCOUNT_STATUSES),
3241
- ownerUserId: z13.string().uuid().nullable(),
3242
- createdAtMs: z13.number().int().nonnegative()
2879
+ var AccountSchema = z12.object({
2880
+ accountId: z12.string().uuid(),
2881
+ type: z12.enum(ACCOUNT_TYPES),
2882
+ displayName: z12.string().min(1),
2883
+ status: z12.enum(ACCOUNT_STATUSES),
2884
+ ownerUserId: z12.string().uuid().nullable(),
2885
+ createdAtMs: z12.number().int().nonnegative()
2886
+ });
2887
+ var AccountMembershipSchema = z12.object({
2888
+ accountId: z12.string().uuid(),
2889
+ userId: z12.string().uuid(),
2890
+ role: z12.enum(MEMBERSHIP_ROLES),
2891
+ createdAtMs: z12.number().int().nonnegative()
2892
+ });
2893
+ function createAccountsClient(opts) {
2894
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
2895
+ if (!fetchImpl) {
2896
+ throw new Error("createAccountsClient: no fetch implementation available");
2897
+ }
2898
+ const baseUrl = opts.baseUrl.replace(/\/$/, "");
2899
+ async function call(method, path, body, parser) {
2900
+ const init2 = {
2901
+ method,
2902
+ headers: {
2903
+ "content-type": "application/json",
2904
+ accept: "application/json"
2905
+ }
2906
+ };
2907
+ if (body !== void 0) init2.body = JSON.stringify(body);
2908
+ const resp = await fetchImpl(`${baseUrl}${path}`, init2);
2909
+ const text = await resp.text();
2910
+ let raw = void 0;
2911
+ if (text) {
2912
+ try {
2913
+ raw = JSON.parse(text);
2914
+ } catch {
2915
+ }
2916
+ }
2917
+ if (!resp.ok) {
2918
+ const code = raw && typeof raw === "object" && "code" in raw && typeof raw.code === "string" ? raw.code : `http_${resp.status}`;
2919
+ const message = raw && typeof raw === "object" && "message" in raw && typeof raw.message === "string" ? raw.message : `request failed with status ${resp.status}`;
2920
+ throw new FlurApiError(resp.status, code, message, raw);
2921
+ }
2922
+ return parser(raw);
2923
+ }
2924
+ const itemsSchema = z12.object({ items: z12.array(AccountSchema) });
2925
+ const memberItemsSchema = z12.object({
2926
+ items: z12.array(AccountMembershipSchema)
2927
+ });
2928
+ return {
2929
+ listMyAccounts: () => call(
2930
+ "GET",
2931
+ "/v1/accounts/me",
2932
+ void 0,
2933
+ (raw) => itemsSchema.parse(raw)
2934
+ ),
2935
+ getAccount: (accountId) => call(
2936
+ "GET",
2937
+ `/v1/accounts/${encodeURIComponent(accountId)}`,
2938
+ void 0,
2939
+ (raw) => AccountSchema.parse(raw)
2940
+ ),
2941
+ listMembers: (accountId) => call(
2942
+ "GET",
2943
+ `/v1/accounts/${encodeURIComponent(accountId)}/members`,
2944
+ void 0,
2945
+ (raw) => memberItemsSchema.parse(raw)
2946
+ ),
2947
+ createBusinessAccount: (input) => call("POST", "/v1/accounts", input, (raw) => AccountSchema.parse(raw)),
2948
+ addMember: (accountId, input) => call(
2949
+ "POST",
2950
+ `/v1/accounts/${encodeURIComponent(accountId)}/members`,
2951
+ input,
2952
+ (raw) => AccountMembershipSchema.parse(raw)
2953
+ )
2954
+ };
2955
+ }
2956
+
2957
+ // src/me-offline/client.ts
2958
+ import { z as z13 } from "zod";
2959
+ var Sha256Hex = z13.string().regex(/^[0-9a-f]{64}$/);
2960
+ var Base64Std3 = z13.string().regex(/^[A-Za-z0-9+/]+={0,2}$/);
2961
+ var ClaimNonce = z13.string().min(8).max(128).refine((value) => !value.includes("|"), {
2962
+ message: "nonce must not contain |"
2963
+ });
2964
+ var ACCOUNT_FUNDED_OAC_MAX_TTL_MS = 1e3 * 60 * 60 * 24 * 7;
2965
+ var CONSUMER_OFFLINE_CLAIM_SUBMIT_GRACE_MS = 1e3 * 60 * 60 * 24;
2966
+ var AttestationSecurityLevelSchema = z13.enum([
2967
+ "STRONGBOX",
2968
+ "TEE",
2969
+ "SECURE_ENCLAVE",
2970
+ "SOFTWARE"
2971
+ ]);
2972
+ var DeviceKeyAlgSchema = z13.literal("p256");
2973
+ var RegisterDeviceKeyP256InputSchema = z13.object({
2974
+ deviceId: z13.string().min(1).max(128),
2975
+ /** P-256 SubjectPublicKeyInfo DER, base64. */
2976
+ publicKeySpkiB64: Base64Std3.min(64).max(4096),
2977
+ /** Base64 of the server-issued enrollment challenge string. */
2978
+ challengeB64: Base64Std3.min(8).max(1024),
2979
+ /** iOS App Attest payload or Android X.509 Key Attestation chain. */
2980
+ attestationChainB64: z13.array(Base64Std3.min(16).max(16384)).min(1).max(16),
2981
+ securityLevel: AttestationSecurityLevelSchema
2982
+ });
2983
+ var P256EnrollmentChallengeInputSchema = z13.object({
2984
+ deviceId: z13.string().min(1).max(128)
2985
+ });
2986
+ var P256EnrollmentChallengeResultSchema = z13.object({
2987
+ challenge: z13.string().min(16),
2988
+ expiresAtMs: z13.number().int().positive()
2989
+ });
2990
+ var DeviceKeyRecordSchema = z13.object({
2991
+ id: z13.string().uuid(),
2992
+ userId: z13.string().uuid(),
2993
+ deviceId: z13.string(),
2994
+ /** Always 'p256' on the consumer offline rail. Field retained for forward-compat. */
2995
+ alg: DeviceKeyAlgSchema.default("p256"),
2996
+ /** P-256 SubjectPublicKeyInfo DER, base64. */
2997
+ publicKeySpkiB64: Base64Std3.nullable().default(null),
2998
+ securityLevel: AttestationSecurityLevelSchema.nullable().default(null),
2999
+ hardwareBacked: z13.boolean().default(false),
3000
+ attestedAtMs: z13.number().int().nonnegative().nullable().default(null),
3001
+ createdAtMs: z13.number().int().nonnegative(),
3002
+ revokedAtMs: z13.number().int().nonnegative().nullable()
3003
+ });
3004
+ var ConsumerOACSchema = z13.object({
3005
+ oacId: z13.string().uuid(),
3006
+ issuerId: z13.string().min(1).max(64),
3007
+ userId: z13.string().uuid(),
3008
+ deviceId: z13.string().min(1).max(128),
3009
+ /**
3010
+ * Always 'p256'. Required on the wire (backend always emits it).
3011
+ * Kept as a literal so input/output infer identically and the schema
3012
+ * can be nested inside other response shapes without Zod input/output
3013
+ * divergence under tsup DTS bundling.
3014
+ */
3015
+ alg: z13.literal("p256"),
3016
+ /** P-256 SubjectPublicKeyInfo DER, base64. */
3017
+ devicePubkeySpkiB64: Base64Std3.min(64).max(4096),
3018
+ perTxCapKobo: z13.number().int().positive(),
3019
+ cumulativeCapKobo: z13.number().int().positive(),
3020
+ currency: z13.string().length(3),
3021
+ validFromMs: z13.number().int().nonnegative(),
3022
+ validUntilMs: z13.number().int().nonnegative(),
3023
+ counterSeed: z13.number().int().nonnegative(),
3024
+ issuedAtMs: z13.number().int().nonnegative()
3025
+ });
3026
+ var SignedConsumerOACSchema = z13.object({
3027
+ oac: ConsumerOACSchema,
3028
+ /** ASN.1 DER ECDSA P-256 issuer signature, base64. */
3029
+ issuerSig: Base64Std3.min(16).max(2048),
3030
+ /** Issuer's P-256 public key as SubjectPublicKeyInfo DER, base64. */
3031
+ issuerPublicKeySpkiB64: Base64Std3.min(64).max(4096)
3243
3032
  });
3244
- var AccountMembershipSchema = z13.object({
3245
- accountId: z13.string().uuid(),
3246
- userId: z13.string().uuid(),
3247
- role: z13.enum(MEMBERSHIP_ROLES),
3248
- createdAtMs: z13.number().int().nonnegative()
3033
+ var OACRecordSchema = SignedConsumerOACSchema.extend({
3034
+ currentOfflineSpentKobo: z13.number().int().nonnegative(),
3035
+ status: z13.enum(["active", "superseded", "expired", "revoked"]),
3036
+ supersededAtMs: z13.number().int().nonnegative().nullable(),
3037
+ revokedAtMs: z13.number().int().nonnegative().nullable()
3249
3038
  });
3250
- function createAccountsClient(opts) {
3039
+ var IssueAccountOacInputSchema = z13.object({
3040
+ deviceId: z13.string().min(1).max(128),
3041
+ perTxCapKobo: z13.number().int().positive().optional(),
3042
+ cumulativeCapKobo: z13.number().int().positive().optional(),
3043
+ ttlMs: z13.number().int().min(6e4).max(ACCOUNT_FUNDED_OAC_MAX_TTL_MS).optional()
3044
+ });
3045
+ var OfflineStatusResultSchema = z13.object({
3046
+ active: OACRecordSchema.nullable()
3047
+ });
3048
+ var ConsumerPaymentClaimSchema = z13.object({
3049
+ /** Always 'p256'. Retained for forward-compat and as an explicit domain marker. */
3050
+ alg: z13.literal("p256").default("p256"),
3051
+ oacId: z13.string().uuid(),
3052
+ encounterId: Sha256Hex.optional(),
3053
+ payerUserId: z13.string().uuid(),
3054
+ payeeUserId: z13.string().uuid(),
3055
+ payerDeviceId: z13.string().min(1).max(128),
3056
+ payerNonce: ClaimNonce,
3057
+ payeeNonce: ClaimNonce,
3058
+ amountKobo: z13.number().int().positive(),
3059
+ currency: z13.string().length(3).default("NGN"),
3060
+ occurredAtMs: z13.number().int().nonnegative(),
3061
+ completedAtMs: z13.number().int().nonnegative().optional(),
3062
+ contextId: z13.string().max(128).optional(),
3063
+ requestId: z13.string().uuid().optional(),
3064
+ requestMode: z13.enum(["fixed", "editable"]).optional(),
3065
+ requestTakerUserId: z13.string().uuid().optional(),
3066
+ requestAmountKobo: z13.number().int().positive().optional(),
3067
+ requestCurrency: z13.string().length(3).optional(),
3068
+ requestReference: z13.string().max(128).nullable().optional(),
3069
+ requestCreatedAtMs: z13.number().int().nonnegative().optional(),
3070
+ requestExpiresAtMs: z13.number().int().positive().optional(),
3071
+ requestNonce: z13.string().min(8).max(128).optional(),
3072
+ requestTakerDeviceId: z13.string().min(1).max(128).nullable().optional(),
3073
+ requestTakerPubkeySpkiB64: Base64Std3.min(64).max(4096).optional(),
3074
+ requestTakerSignatureDerB64: Base64Std3.min(16).max(2048).optional(),
3075
+ payerPubkeySpkiB64: Base64Std3.min(64).max(4096),
3076
+ payerSignatureDerB64: Base64Std3.min(16).max(2048),
3077
+ payeePubkeySpkiB64: Base64Std3.min(64).max(4096).optional(),
3078
+ payeeSignatureDerB64: Base64Std3.min(16).max(2048).optional()
3079
+ });
3080
+ var ConsumerSettlementSchema = z13.object({
3081
+ settlementId: z13.string().uuid(),
3082
+ settlementKey: Sha256Hex,
3083
+ encounterId: Sha256Hex,
3084
+ oacId: z13.string().uuid(),
3085
+ payerUserId: z13.string().uuid(),
3086
+ payeeUserId: z13.string().uuid(),
3087
+ amountKobo: z13.number().int().positive(),
3088
+ currency: z13.string().length(3),
3089
+ status: z13.enum(["SETTLED", "REVIEW"]),
3090
+ reviewReason: z13.string().nullable(),
3091
+ ledgerRef: z13.string().nullable(),
3092
+ /** ASN.1 DER ECDSA P-256 issuer signature, base64. */
3093
+ issuerSig: Base64Std3.min(16).max(2048),
3094
+ /** Canonical millisecond timestamp signed into the settlement receipt. */
3095
+ issuedAtMs: z13.number().int().nonnegative(),
3096
+ /** Compatibility alias for API consumers that predate issuedAtMs. */
3097
+ createdAtMs: z13.number().int().nonnegative().optional()
3098
+ });
3099
+ var ConsumerSettleResultSchema = z13.object({
3100
+ settlement: ConsumerSettlementSchema,
3101
+ encounterId: Sha256Hex,
3102
+ replayed: z13.boolean()
3103
+ });
3104
+ var RevokeDeviceKeyInputSchema = z13.object({
3105
+ deviceId: z13.string().min(1).max(128),
3106
+ /** Step-up token from /api/v1/auth/send/verify with purpose='offline_revoke'. */
3107
+ sendAuthToken: z13.string().min(16)
3108
+ });
3109
+ function createMeOfflineClient(opts) {
3251
3110
  const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
3252
3111
  if (!fetchImpl) {
3253
- throw new Error("createAccountsClient: no fetch implementation available");
3112
+ throw new Error("createMeOfflineClient: no fetch implementation available");
3254
3113
  }
3255
3114
  const baseUrl = opts.baseUrl.replace(/\/$/, "");
3256
3115
  async function call(method, path, body, parser) {
@@ -3278,42 +3137,67 @@ function createAccountsClient(opts) {
3278
3137
  }
3279
3138
  return parser(raw);
3280
3139
  }
3281
- const itemsSchema = z13.object({ items: z13.array(AccountSchema) });
3282
- const memberItemsSchema = z13.object({
3283
- items: z13.array(AccountMembershipSchema)
3284
- });
3140
+ const deviceKeyItems = z13.object({ items: z13.array(DeviceKeyRecordSchema) });
3285
3141
  return {
3286
- listMyAccounts: () => call(
3287
- "GET",
3288
- "/v1/accounts/me",
3289
- void 0,
3290
- (raw) => itemsSchema.parse(raw)
3142
+ issueP256EnrollmentChallenge: (input) => call(
3143
+ "POST",
3144
+ "/v1/me/offline/keys/p256/challenge",
3145
+ P256EnrollmentChallengeInputSchema.parse(input),
3146
+ (raw) => P256EnrollmentChallengeResultSchema.parse(raw)
3291
3147
  ),
3292
- getAccount: (accountId) => call(
3293
- "GET",
3294
- `/v1/accounts/${encodeURIComponent(accountId)}`,
3295
- void 0,
3296
- (raw) => AccountSchema.parse(raw)
3148
+ registerDeviceKeyP256: (input) => call(
3149
+ "POST",
3150
+ "/v1/me/offline/keys/p256",
3151
+ RegisterDeviceKeyP256InputSchema.parse(input),
3152
+ (raw) => DeviceKeyRecordSchema.parse(raw)
3297
3153
  ),
3298
- listMembers: (accountId) => call(
3154
+ listDeviceKeys: () => call(
3299
3155
  "GET",
3300
- `/v1/accounts/${encodeURIComponent(accountId)}/members`,
3156
+ "/v1/me/offline/keys",
3301
3157
  void 0,
3302
- (raw) => memberItemsSchema.parse(raw)
3158
+ (raw) => deviceKeyItems.parse(raw)
3303
3159
  ),
3304
- createBusinessAccount: (input) => call("POST", "/v1/accounts", input, (raw) => AccountSchema.parse(raw)),
3305
- addMember: (accountId, input) => call(
3160
+ revokeDeviceKey: (input) => call(
3306
3161
  "POST",
3307
- `/v1/accounts/${encodeURIComponent(accountId)}/members`,
3308
- input,
3309
- (raw) => AccountMembershipSchema.parse(raw)
3162
+ "/v1/me/offline/keys/revoke",
3163
+ RevokeDeviceKeyInputSchema.parse(input),
3164
+ () => void 0
3165
+ ),
3166
+ issueAccountOac: (input) => call(
3167
+ "POST",
3168
+ "/v1/me/offline/oac",
3169
+ IssueAccountOacInputSchema.parse(input),
3170
+ (raw) => OACRecordSchema.parse(raw)
3171
+ ),
3172
+ getStatus: (deviceId) => {
3173
+ const qs = deviceId ? `?deviceId=${encodeURIComponent(deviceId)}` : "";
3174
+ return call(
3175
+ "GET",
3176
+ `/v1/me/offline/status${qs}`,
3177
+ void 0,
3178
+ (raw) => OfflineStatusResultSchema.parse(raw)
3179
+ );
3180
+ },
3181
+ submitClaim: (claim) => call(
3182
+ "POST",
3183
+ "/v1/me/offline/claims",
3184
+ ConsumerPaymentClaimSchema.parse(claim),
3185
+ (raw) => ConsumerSettleResultSchema.parse(raw)
3186
+ ),
3187
+ getSettlement: (idOrKey) => call(
3188
+ "GET",
3189
+ `/v1/me/offline/settlements/${encodeURIComponent(idOrKey)}`,
3190
+ void 0,
3191
+ (raw) => ConsumerSettlementSchema.parse(raw)
3310
3192
  )
3311
3193
  };
3312
3194
  }
3313
3195
 
3314
3196
  // src/me-offline/signer.ts
3315
3197
  import { p256 as p2562 } from "@noble/curves/nist";
3198
+ import { sha256 as sha2564 } from "@noble/hashes/sha2";
3316
3199
  var CLAIM_DOMAIN_V2 = "flur:consumer-offline:v2:claim";
3200
+ var ENCOUNTER_DOMAIN2 = "flur:consumer-offline:v1:encounter";
3317
3201
  function canonicalClaimSigningPayload(claim) {
3318
3202
  return {
3319
3203
  domain: CLAIM_DOMAIN_V2,
@@ -3334,6 +3218,27 @@ function canonicalClaimSigningPayload(claim) {
3334
3218
  function canonicalClaimSigningBytes(claim) {
3335
3219
  return canonicalJSONBytes(canonicalClaimSigningPayload(claim));
3336
3220
  }
3221
+ function computeConsumerClaimEncounterId(input) {
3222
+ const material = `${ENCOUNTER_DOMAIN2}|${[
3223
+ assertEncounterPart("oacId", input.oacId),
3224
+ assertEncounterPart("payerUserId", input.payerUserId),
3225
+ assertEncounterPart("payeeUserId", input.payeeUserId),
3226
+ assertEncounterPart("payerNonce", input.payerNonce),
3227
+ assertEncounterPart("payeeNonce", input.payeeNonce)
3228
+ ].join("|")}`;
3229
+ return bytesToHex5(sha2564(new TextEncoder().encode(material)));
3230
+ }
3231
+ function assertEncounterPart(field, value) {
3232
+ if (value.includes("|")) {
3233
+ throw new Error(`consumer encounter id ${field} must not contain |`);
3234
+ }
3235
+ return value;
3236
+ }
3237
+ function bytesToHex5(bytes) {
3238
+ let out = "";
3239
+ for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
3240
+ return out;
3241
+ }
3337
3242
  function bytesToBase642(bytes) {
3338
3243
  if (typeof Buffer !== "undefined") {
3339
3244
  return Buffer.from(bytes).toString("base64");
@@ -3429,38 +3334,192 @@ function verifyClaimSignature(input) {
3429
3334
  }
3430
3335
  }
3431
3336
 
3432
- // src/me-offline/sms.ts
3433
- var OFFLINE_CLAIM_SMS_PREFIX = "FLURC1.";
3434
- var TOKEN_RE = /(?:^|\s)(FLURC1\.[A-Za-z0-9_-]+={0,2})(?:\s|$)/;
3435
- function encodeOfflineClaimSmsMessage(claim) {
3436
- const parsed = ConsumerPaymentClaimSchema.parse(claim);
3437
- const json = JSON.stringify(parsed);
3438
- return `${OFFLINE_CLAIM_SMS_PREFIX}${base64UrlEncodeUtf8(json)}`;
3337
+ // src/me-offline/request.ts
3338
+ import { z as z14 } from "zod";
3339
+ var Base64Std4 = z14.string().regex(/^[A-Za-z0-9+/]+={0,2}$/);
3340
+ var CONSUMER_PAYMENT_REQUEST_DOMAIN = "flur:consumer-offline:v1:request";
3341
+ var ConsumerPaymentRequestEnvelopeSchema = z14.object({
3342
+ requestId: z14.string().uuid(),
3343
+ mode: z14.enum(["fixed", "editable"]),
3344
+ takerUserId: z14.string().uuid(),
3345
+ amountKobo: z14.number().int().positive(),
3346
+ currency: z14.string().length(3).default("NGN"),
3347
+ reference: z14.string().max(128).nullable().default(null),
3348
+ createdAtMs: z14.number().int().nonnegative(),
3349
+ expiresAtMs: z14.number().int().positive(),
3350
+ nonce: z14.string().min(8).max(128),
3351
+ takerDeviceId: z14.string().min(1).max(128).nullable().default(null),
3352
+ takerPubkeySpkiB64: Base64Std4.min(64).max(4096).optional(),
3353
+ takerSignatureDerB64: Base64Std4.min(16).max(2048).optional()
3354
+ }).superRefine((value, ctx) => {
3355
+ if (value.expiresAtMs <= value.createdAtMs) {
3356
+ ctx.addIssue({
3357
+ code: z14.ZodIssueCode.custom,
3358
+ path: ["expiresAtMs"],
3359
+ message: "expiresAtMs must be greater than createdAtMs"
3360
+ });
3361
+ }
3362
+ const hasSignature = Boolean(
3363
+ value.takerPubkeySpkiB64 || value.takerSignatureDerB64
3364
+ );
3365
+ if (value.mode === "fixed" || hasSignature) {
3366
+ if (!value.takerDeviceId) {
3367
+ ctx.addIssue({
3368
+ code: z14.ZodIssueCode.custom,
3369
+ path: ["takerDeviceId"],
3370
+ message: "signed requests require takerDeviceId"
3371
+ });
3372
+ }
3373
+ if (!value.takerPubkeySpkiB64) {
3374
+ ctx.addIssue({
3375
+ code: z14.ZodIssueCode.custom,
3376
+ path: ["takerPubkeySpkiB64"],
3377
+ message: "signed requests require takerPubkeySpkiB64"
3378
+ });
3379
+ }
3380
+ if (!value.takerSignatureDerB64) {
3381
+ ctx.addIssue({
3382
+ code: z14.ZodIssueCode.custom,
3383
+ path: ["takerSignatureDerB64"],
3384
+ message: "signed requests require takerSignatureDerB64"
3385
+ });
3386
+ }
3387
+ }
3388
+ });
3389
+ function buildConsumerPaymentRequest(input) {
3390
+ const unsigned = {
3391
+ requestId: input.requestId,
3392
+ mode: input.mode,
3393
+ takerUserId: input.takerUserId,
3394
+ amountKobo: input.amountKobo,
3395
+ currency: input.currency ?? "NGN",
3396
+ reference: input.reference ?? null,
3397
+ createdAtMs: input.createdAtMs,
3398
+ expiresAtMs: input.expiresAtMs,
3399
+ nonce: input.nonce,
3400
+ takerDeviceId: input.takerDeviceId ?? null
3401
+ };
3402
+ if (unsigned.mode === "fixed" && !unsigned.takerDeviceId) {
3403
+ throw new Error("fixed requests require takerDeviceId");
3404
+ }
3405
+ if (unsigned.expiresAtMs <= unsigned.createdAtMs) {
3406
+ throw new Error("expiresAtMs must be greater than createdAtMs");
3407
+ }
3408
+ return unsigned;
3439
3409
  }
3440
- function decodeOfflineClaimSmsMessage(message) {
3441
- const token = extractOfflineClaimSmsToken(message);
3442
- if (!token) {
3443
- throw new Error("offline claim SMS token not found");
3410
+ function consumerPaymentRequestSigningPayload(request) {
3411
+ return {
3412
+ domain: CONSUMER_PAYMENT_REQUEST_DOMAIN,
3413
+ version: 1,
3414
+ requestId: request.requestId,
3415
+ mode: request.mode,
3416
+ takerUserId: request.takerUserId,
3417
+ amountKobo: request.amountKobo,
3418
+ currency: request.currency,
3419
+ reference: request.reference ?? null,
3420
+ createdAtMs: request.createdAtMs,
3421
+ expiresAtMs: request.expiresAtMs,
3422
+ nonce: request.nonce,
3423
+ takerDeviceId: request.takerDeviceId ?? null
3424
+ };
3425
+ }
3426
+ function consumerPaymentRequestSigningBytes(request) {
3427
+ return canonicalJSONBytes(consumerPaymentRequestSigningPayload(request));
3428
+ }
3429
+ async function signConsumerPaymentRequest(unsigned, signer) {
3430
+ if (signer.alg !== "p256") {
3431
+ throw new Error("consumer payment requests require p256 signer");
3444
3432
  }
3445
- const encoded = token.slice(OFFLINE_CLAIM_SMS_PREFIX.length);
3433
+ const publicKey = await signer.getPublicKey();
3434
+ if (publicKey.alg !== "p256") {
3435
+ throw new Error("consumer payment requests require p256 public key");
3436
+ }
3437
+ const signature = await signer.sign(
3438
+ consumerPaymentRequestSigningBytes(unsigned)
3439
+ );
3440
+ return ConsumerPaymentRequestEnvelopeSchema.parse({
3441
+ ...unsigned,
3442
+ takerPubkeySpkiB64: publicKey.publicKey,
3443
+ takerSignatureDerB64: signature.signature
3444
+ });
3445
+ }
3446
+ function verifyConsumerPaymentRequest(request) {
3447
+ const parsed = ConsumerPaymentRequestEnvelopeSchema.safeParse(request);
3448
+ if (!parsed.success) return false;
3449
+ const value = parsed.data;
3450
+ if (!value.takerPubkeySpkiB64 || !value.takerSignatureDerB64) return false;
3451
+ return verifyClaimSignature({
3452
+ alg: "p256",
3453
+ bytes: consumerPaymentRequestSigningBytes(value),
3454
+ signature: value.takerSignatureDerB64,
3455
+ publicKey: value.takerPubkeySpkiB64
3456
+ });
3457
+ }
3458
+ function isConsumerPaymentRequestExpired(request, nowMs = Date.now()) {
3459
+ const parsed = ConsumerPaymentRequestEnvelopeSchema.parse(request);
3460
+ return parsed.expiresAtMs <= nowMs;
3461
+ }
3462
+
3463
+ // src/me-offline/settlement.ts
3464
+ var CONSUMER_SETTLEMENT_DOMAIN = "flur:consumer-offline:v1:settlement";
3465
+ var CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX = "FLURSR1.";
3466
+ function consumerSettlementSigningPayload(settlement) {
3467
+ return {
3468
+ domain: CONSUMER_SETTLEMENT_DOMAIN,
3469
+ settlementId: settlement.settlementId,
3470
+ settlementKey: settlement.settlementKey,
3471
+ encounterId: settlement.encounterId,
3472
+ oacId: settlement.oacId,
3473
+ payerUserId: settlement.payerUserId,
3474
+ payeeUserId: settlement.payeeUserId,
3475
+ amountKobo: settlement.amountKobo,
3476
+ currency: settlement.currency,
3477
+ status: settlement.status,
3478
+ reviewReason: settlement.reviewReason,
3479
+ ledgerRef: settlement.ledgerRef,
3480
+ issuedAtMs: settlement.issuedAtMs
3481
+ };
3482
+ }
3483
+ function verifyConsumerSettlement(settlement, issuerPublicKeySpkiB64) {
3484
+ const parsed = ConsumerSettlementSchema.safeParse(settlement);
3485
+ if (!parsed.success) return false;
3486
+ return verifyIssuerP256(
3487
+ canonicalJSONBytes(consumerSettlementSigningPayload(parsed.data)),
3488
+ parsed.data.issuerSig,
3489
+ issuerPublicKeySpkiB64
3490
+ );
3491
+ }
3492
+ function encodeConsumerSettlementReceiptQR(settlement) {
3493
+ const parsed = ConsumerSettlementSchema.parse(settlement);
3494
+ return `${CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX}${base64UrlEncodeUtf8(
3495
+ JSON.stringify(parsed)
3496
+ )}`;
3497
+ }
3498
+ function decodeUnverifiedConsumerSettlementReceiptQR(value) {
3499
+ if (!value.startsWith(CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX)) {
3500
+ throw new Error("not a Flur consumer settlement receipt QR");
3501
+ }
3502
+ const encoded = value.slice(CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX.length);
3446
3503
  let raw;
3447
3504
  try {
3448
3505
  raw = JSON.parse(base64UrlDecodeUtf8(encoded));
3449
3506
  } catch {
3450
- throw new Error("offline claim SMS token is malformed");
3507
+ throw new Error("consumer settlement receipt QR is malformed");
3451
3508
  }
3452
- const parsed = ConsumerPaymentClaimSchema.safeParse(raw);
3453
- if (!parsed.success) {
3454
- throw new Error("offline claim SMS token is invalid");
3509
+ return ConsumerSettlementSchema.parse(raw);
3510
+ }
3511
+ function verifyConsumerSettlementReceiptQR(value, issuerPublicKeySpkiB64) {
3512
+ const settlement = decodeUnverifiedConsumerSettlementReceiptQR(value);
3513
+ if (!verifyConsumerSettlement(settlement, issuerPublicKeySpkiB64)) {
3514
+ throw new Error("consumer settlement receipt QR signature invalid");
3455
3515
  }
3456
- return parsed.data;
3516
+ return settlement;
3457
3517
  }
3458
- function extractOfflineClaimSmsToken(message) {
3459
- const trimmed = message.trim();
3460
- if (trimmed.startsWith(OFFLINE_CLAIM_SMS_PREFIX)) {
3461
- return trimmed.split(/\s+/, 1)[0] ?? null;
3518
+ function decodeConsumerSettlementReceiptQR(value, issuerPublicKeySpkiB64) {
3519
+ if (!issuerPublicKeySpkiB64) {
3520
+ return decodeUnverifiedConsumerSettlementReceiptQR(value);
3462
3521
  }
3463
- return TOKEN_RE.exec(message)?.[1] ?? null;
3522
+ return verifyConsumerSettlementReceiptQR(value, issuerPublicKeySpkiB64);
3464
3523
  }
3465
3524
  function base64UrlEncodeUtf8(input) {
3466
3525
  const bytes = new TextEncoder().encode(input);
@@ -3490,15 +3549,281 @@ function base64UrlDecodeUtf8(input) {
3490
3549
  throw new Error("base64 decoder unavailable");
3491
3550
  }
3492
3551
 
3552
+ // src/me-offline/sms.ts
3553
+ import { p256 as p2563 } from "@noble/curves/nist";
3554
+ var OFFLINE_CLAIM_SMS_PREFIX = "FLURC1.";
3555
+ var CLAIM_TOKEN_RE = /(?:^|\s)(FLURC1\.[A-Za-z0-9_-]+={0,2})(?:\s|$)/;
3556
+ function encodeOfflineClaimSmsMessage(claim) {
3557
+ const parsed = ConsumerPaymentClaimSchema.parse(claim);
3558
+ return `${OFFLINE_CLAIM_SMS_PREFIX}${base64UrlEncodeUtf82(
3559
+ JSON.stringify(parsed)
3560
+ )}`;
3561
+ }
3562
+ function decodeOfflineClaimSmsMessage(message) {
3563
+ const token = extractOfflineClaimSmsToken(message);
3564
+ if (!token) throw new Error("offline claim QR token not found");
3565
+ const encoded = token.slice(OFFLINE_CLAIM_SMS_PREFIX.length);
3566
+ let raw;
3567
+ try {
3568
+ raw = JSON.parse(base64UrlDecodeUtf82(encoded));
3569
+ } catch {
3570
+ throw new Error("offline claim QR token is malformed");
3571
+ }
3572
+ const parsed = ConsumerPaymentClaimSchema.safeParse(raw);
3573
+ if (!parsed.success) throw new Error("offline claim QR token is invalid");
3574
+ return parsed.data;
3575
+ }
3576
+ function extractOfflineClaimSmsToken(message) {
3577
+ const trimmed = message.trim();
3578
+ if (trimmed.startsWith(OFFLINE_CLAIM_SMS_PREFIX)) {
3579
+ return trimmed.split(/\s+/, 1)[0] ?? null;
3580
+ }
3581
+ return CLAIM_TOKEN_RE.exec(message)?.[1] ?? null;
3582
+ }
3583
+ var OFFLINE_SMS_SETTLE_PREFIX = "FLURA1.";
3584
+ var OFFLINE_SMS_SETTLE_DOMAIN = "flur:consumer-offline:v1:attest";
3585
+ var OFFLINE_SMS_SETTLE_TOKEN_BYTES = 112;
3586
+ var OFFLINE_SMS_SETTLE_HEADER_BYTES = 48;
3587
+ var OFFLINE_SMS_SETTLE_SIGNATURE_BYTES = 64;
3588
+ var OFFLINE_SMS_SETTLE_VERSION = 1;
3589
+ var TOKEN_RE = /(?:^|[\s,;:()<>"'])(FLURA1\.[A-Za-z0-9_-]{150})/;
3590
+ async function encodeOfflineSmsSettleToken(input, signer) {
3591
+ const header = await buildSmsSettleHeader(input);
3592
+ const sig = await signer.signRaw(domainTag(header));
3593
+ if (sig.length !== OFFLINE_SMS_SETTLE_SIGNATURE_BYTES) {
3594
+ throw new Error(
3595
+ `FLURA1: signer returned ${sig.length}-byte sig; expected ${OFFLINE_SMS_SETTLE_SIGNATURE_BYTES}`
3596
+ );
3597
+ }
3598
+ const out = new Uint8Array(OFFLINE_SMS_SETTLE_TOKEN_BYTES);
3599
+ out.set(header, 0);
3600
+ out.set(sig, OFFLINE_SMS_SETTLE_HEADER_BYTES);
3601
+ return `${OFFLINE_SMS_SETTLE_PREFIX}${bytesToBase64Url(out)}`;
3602
+ }
3603
+ async function buildSmsSettleHeader(input) {
3604
+ assertSafeUint64(input.amountKobo, "amountKobo");
3605
+ if (input.amountKobo <= 0) {
3606
+ throw new Error("FLURA1: amountKobo must be greater than zero");
3607
+ }
3608
+ assertSafeUint48(input.occurredAtMs, "occurredAtMs");
3609
+ const encounterPrefix = (await sha2565(utf8(input.encounterId))).slice(0, 16);
3610
+ const payerPrefix = uuidToBytes(input.payerUserId).slice(0, 8);
3611
+ const payeePrefix = uuidToBytes(input.payeeUserId).slice(0, 8);
3612
+ const header = new Uint8Array(OFFLINE_SMS_SETTLE_HEADER_BYTES);
3613
+ const dv = new DataView(header.buffer);
3614
+ header[0] = OFFLINE_SMS_SETTLE_VERSION;
3615
+ header[1] = 0;
3616
+ header.set(encounterPrefix, 2);
3617
+ header.set(payerPrefix, 18);
3618
+ header.set(payeePrefix, 26);
3619
+ writeUint64BE(dv, 34, input.amountKobo);
3620
+ writeUint48BE(dv, 42, input.occurredAtMs);
3621
+ return header;
3622
+ }
3623
+ function domainTag(header) {
3624
+ if (header.length !== OFFLINE_SMS_SETTLE_HEADER_BYTES) {
3625
+ throw new Error(
3626
+ `FLURA1: header must be ${OFFLINE_SMS_SETTLE_HEADER_BYTES} bytes`
3627
+ );
3628
+ }
3629
+ const domain = utf8(OFFLINE_SMS_SETTLE_DOMAIN);
3630
+ const out = new Uint8Array(domain.length + header.length);
3631
+ out.set(domain, 0);
3632
+ out.set(header, domain.length);
3633
+ return out;
3634
+ }
3635
+ function decodeOfflineSmsSettleToken(message) {
3636
+ const token = extractOfflineSmsSettleToken(message);
3637
+ if (!token) throw new Error("FLURA1: token not found");
3638
+ const encoded = token.slice(OFFLINE_SMS_SETTLE_PREFIX.length);
3639
+ let bytes;
3640
+ try {
3641
+ bytes = base64UrlToBytes(encoded);
3642
+ } catch {
3643
+ throw new Error("FLURA1: token base64url is malformed");
3644
+ }
3645
+ if (bytesToBase64Url(bytes) !== encoded) {
3646
+ throw new Error("FLURA1: token base64url is malformed");
3647
+ }
3648
+ if (bytes.length !== OFFLINE_SMS_SETTLE_TOKEN_BYTES) {
3649
+ throw new Error(
3650
+ `FLURA1: expected ${OFFLINE_SMS_SETTLE_TOKEN_BYTES} bytes, got ${bytes.length}`
3651
+ );
3652
+ }
3653
+ const version = bytes[0];
3654
+ const flags = bytes[1];
3655
+ if (version !== OFFLINE_SMS_SETTLE_VERSION) {
3656
+ throw new Error(`FLURA1: unsupported version ${version}`);
3657
+ }
3658
+ if (flags !== 0) {
3659
+ throw new Error(`FLURA1: reserved flags must be 0, got ${flags}`);
3660
+ }
3661
+ const header = bytes.slice(0, OFFLINE_SMS_SETTLE_HEADER_BYTES);
3662
+ const signature = bytes.slice(OFFLINE_SMS_SETTLE_HEADER_BYTES);
3663
+ const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
3664
+ const amountKobo = readUint64BE(dv, 34);
3665
+ if (amountKobo <= 0) {
3666
+ throw new Error("FLURA1: amountKobo must be greater than zero");
3667
+ }
3668
+ return {
3669
+ version,
3670
+ flags,
3671
+ encounterIdPrefixHex: bytesToHex6(bytes.slice(2, 18)),
3672
+ payerUserIdPrefixHex: bytesToHex6(bytes.slice(18, 26)),
3673
+ payeeUserIdPrefixHex: bytesToHex6(bytes.slice(26, 34)),
3674
+ amountKobo,
3675
+ occurredAtMs: readUint48BE(dv, 42),
3676
+ signature,
3677
+ header,
3678
+ signedBytes: domainTag(header)
3679
+ };
3680
+ }
3681
+ function extractOfflineSmsSettleToken(message) {
3682
+ const trimmed = message.trim();
3683
+ if (trimmed.startsWith(OFFLINE_SMS_SETTLE_PREFIX)) {
3684
+ return trimmed.split(/\s+/, 1)[0] ?? null;
3685
+ }
3686
+ return TOKEN_RE.exec(message)?.[1] ?? null;
3687
+ }
3688
+ function verifyOfflineSmsSettleToken(decoded, payerPubkeySpkiB64) {
3689
+ try {
3690
+ const pubRaw = p256SpkiB64ToRaw(payerPubkeySpkiB64);
3691
+ return p2563.verify(decoded.signature, decoded.signedBytes, pubRaw, {
3692
+ prehash: true,
3693
+ format: "compact"
3694
+ });
3695
+ } catch {
3696
+ return false;
3697
+ }
3698
+ }
3699
+ function derToRawP256Signature(derBytes) {
3700
+ const sig = p2563.Signature.fromBytes(derBytes, "der");
3701
+ const raw = sig.toBytes("compact");
3702
+ if (raw.length !== OFFLINE_SMS_SETTLE_SIGNATURE_BYTES) {
3703
+ throw new Error(
3704
+ `FLURA1: DER\u2192raw produced ${raw.length} bytes; expected ${OFFLINE_SMS_SETTLE_SIGNATURE_BYTES}`
3705
+ );
3706
+ }
3707
+ return raw;
3708
+ }
3709
+ function utf8(s) {
3710
+ return new TextEncoder().encode(s);
3711
+ }
3712
+ async function sha2565(bytes) {
3713
+ const subtle = typeof globalThis !== "undefined" && globalThis.crypto?.subtle || void 0;
3714
+ if (subtle) {
3715
+ const digest = await subtle.digest("SHA-256", bytes);
3716
+ return new Uint8Array(digest);
3717
+ }
3718
+ const { sha256: nobleSha256 } = await import("@noble/hashes/sha2");
3719
+ return nobleSha256(bytes);
3720
+ }
3721
+ function uuidToBytes(uuid) {
3722
+ const hex = uuid.replace(/-/g, "").toLowerCase();
3723
+ if (hex.length !== 32 || !/^[0-9a-f]{32}$/.test(hex)) {
3724
+ throw new Error(`FLURA1: invalid UUID: ${uuid}`);
3725
+ }
3726
+ const out = new Uint8Array(16);
3727
+ for (let i = 0; i < 16; i++) {
3728
+ out[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16);
3729
+ }
3730
+ return out;
3731
+ }
3732
+ function assertSafeUint64(value, field) {
3733
+ if (!Number.isInteger(value) || value < 0) {
3734
+ throw new Error(`FLURA1: ${field} must be a non-negative integer`);
3735
+ }
3736
+ if (value > Number.MAX_SAFE_INTEGER) {
3737
+ throw new Error(`FLURA1: ${field} exceeds Number.MAX_SAFE_INTEGER`);
3738
+ }
3739
+ }
3740
+ function assertSafeUint48(value, field) {
3741
+ assertSafeUint64(value, field);
3742
+ if (value > 281474976710655) {
3743
+ throw new Error(`FLURA1: ${field} exceeds uint48 range`);
3744
+ }
3745
+ }
3746
+ function writeUint64BE(dv, offset, value) {
3747
+ const high = Math.floor(value / 4294967296);
3748
+ const low = value >>> 0;
3749
+ dv.setUint32(offset, high, false);
3750
+ dv.setUint32(offset + 4, low, false);
3751
+ }
3752
+ function readUint64BE(dv, offset) {
3753
+ const high = dv.getUint32(offset, false);
3754
+ const low = dv.getUint32(offset + 4, false);
3755
+ if (high > 2097151) {
3756
+ throw new Error("FLURA1: amountKobo exceeds Number.MAX_SAFE_INTEGER");
3757
+ }
3758
+ return high * 4294967296 + low;
3759
+ }
3760
+ function writeUint48BE(dv, offset, value) {
3761
+ const high = Math.floor(value / 65536);
3762
+ const low = value & 65535;
3763
+ dv.setUint32(offset, high, false);
3764
+ dv.setUint16(offset + 4, low, false);
3765
+ }
3766
+ function readUint48BE(dv, offset) {
3767
+ const high = dv.getUint32(offset, false);
3768
+ const low = dv.getUint16(offset + 4, false);
3769
+ return high * 65536 + low;
3770
+ }
3771
+ function bytesToHex6(bytes) {
3772
+ let out = "";
3773
+ for (let i = 0; i < bytes.length; i++) {
3774
+ out += bytes[i].toString(16).padStart(2, "0");
3775
+ }
3776
+ return out;
3777
+ }
3778
+ function bytesToBase64Url(bytes) {
3779
+ let base64;
3780
+ if (typeof Buffer !== "undefined") {
3781
+ base64 = Buffer.from(bytes).toString("base64");
3782
+ } else {
3783
+ let binary = "";
3784
+ for (let i = 0; i < bytes.length; i++) {
3785
+ binary += String.fromCharCode(bytes[i]);
3786
+ }
3787
+ if (typeof btoa !== "function") {
3788
+ throw new Error("FLURA1: base64 encoder unavailable");
3789
+ }
3790
+ base64 = btoa(binary);
3791
+ }
3792
+ return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
3793
+ }
3794
+ function base64UrlEncodeUtf82(input) {
3795
+ return bytesToBase64Url(utf8(input));
3796
+ }
3797
+ function base64UrlDecodeUtf82(input) {
3798
+ return new TextDecoder().decode(base64UrlToBytes(input));
3799
+ }
3800
+ function base64UrlToBytes(input) {
3801
+ const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
3802
+ const padded = base64.padEnd(
3803
+ base64.length + (4 - base64.length % 4) % 4,
3804
+ "="
3805
+ );
3806
+ if (typeof Buffer !== "undefined") {
3807
+ return new Uint8Array(Buffer.from(padded, "base64"));
3808
+ }
3809
+ if (typeof atob !== "function") {
3810
+ throw new Error("FLURA1: base64 decoder unavailable");
3811
+ }
3812
+ const binary = atob(padded);
3813
+ const out = new Uint8Array(binary.length);
3814
+ for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);
3815
+ return out;
3816
+ }
3817
+
3493
3818
  // src/partner-funding/client.ts
3494
- import { z as z14 } from "zod";
3495
- var MinorString = z14.string().regex(/^-?\d+$/);
3496
- var PositiveMinor = z14.union([
3497
- z14.number().int().positive(),
3498
- z14.string().regex(/^[1-9]\d{0,18}$/)
3819
+ import { z as z15 } from "zod";
3820
+ var MinorString = z15.string().regex(/^-?\d+$/);
3821
+ var PositiveMinor = z15.union([
3822
+ z15.number().int().positive(),
3823
+ z15.string().regex(/^[1-9]\d{0,18}$/)
3499
3824
  ]);
3500
- var Currency = z14.string().trim().length(3).transform((v) => v.toUpperCase());
3501
- var Metadata = z14.record(z14.unknown());
3825
+ var Currency = z15.string().trim().length(3).transform((v) => v.toUpperCase());
3826
+ var Metadata = z15.record(z15.unknown());
3502
3827
  var PARTNER_KINDS = ["bank", "merchant"];
3503
3828
  var CUSTODIAL_MODES = ["agent_of_bank", "flur_virtual_pool"];
3504
3829
  var PARTNER_PROFILE_STATUSES = [
@@ -3525,126 +3850,126 @@ var WITHDRAWAL_STATES = [
3525
3850
  "failed",
3526
3851
  "reversed"
3527
3852
  ];
3528
- var PartnerProfileSchema = z14.object({
3529
- partnerAccountId: z14.string().uuid(),
3530
- kind: z14.enum(PARTNER_KINDS),
3531
- custodialMode: z14.enum(CUSTODIAL_MODES),
3532
- displayName: z14.string(),
3533
- bankCode: z14.string().nullable(),
3534
- poolAccountNumber: z14.string().nullable(),
3535
- status: z14.enum(PARTNER_PROFILE_STATUSES),
3853
+ var PartnerProfileSchema = z15.object({
3854
+ partnerAccountId: z15.string().uuid(),
3855
+ kind: z15.enum(PARTNER_KINDS),
3856
+ custodialMode: z15.enum(CUSTODIAL_MODES),
3857
+ displayName: z15.string(),
3858
+ bankCode: z15.string().nullable(),
3859
+ poolAccountNumber: z15.string().nullable(),
3860
+ status: z15.enum(PARTNER_PROFILE_STATUSES),
3536
3861
  metadata: Metadata,
3537
- createdAtMs: z14.number().int().nonnegative(),
3538
- updatedAtMs: z14.number().int().nonnegative()
3862
+ createdAtMs: z15.number().int().nonnegative(),
3863
+ updatedAtMs: z15.number().int().nonnegative()
3539
3864
  });
3540
- var UpsertPartnerProfileInputSchema = z14.object({
3541
- kind: z14.enum(PARTNER_KINDS),
3542
- custodialMode: z14.enum(CUSTODIAL_MODES),
3543
- displayName: z14.string().trim().min(1).max(200),
3544
- bankCode: z14.string().trim().min(1).max(64).optional(),
3545
- poolAccountNumber: z14.string().trim().min(1).max(64).optional(),
3865
+ var UpsertPartnerProfileInputSchema = z15.object({
3866
+ kind: z15.enum(PARTNER_KINDS),
3867
+ custodialMode: z15.enum(CUSTODIAL_MODES),
3868
+ displayName: z15.string().trim().min(1).max(200),
3869
+ bankCode: z15.string().trim().min(1).max(64).optional(),
3870
+ poolAccountNumber: z15.string().trim().min(1).max(64).optional(),
3546
3871
  metadata: Metadata.optional()
3547
3872
  });
3548
- var PartnerFundingEventInputSchema = z14.object({
3549
- externalRef: z14.string().trim().min(8).max(128),
3550
- direction: z14.enum(PARTNER_FUNDING_DIRECTIONS).optional(),
3551
- userId: z14.string().uuid().optional(),
3552
- accountId: z14.string().uuid().optional(),
3873
+ var PartnerFundingEventInputSchema = z15.object({
3874
+ externalRef: z15.string().trim().min(8).max(128),
3875
+ direction: z15.enum(PARTNER_FUNDING_DIRECTIONS).optional(),
3876
+ userId: z15.string().uuid().optional(),
3877
+ accountId: z15.string().uuid().optional(),
3553
3878
  amountMinor: PositiveMinor,
3554
3879
  currency: Currency,
3555
- fundingSource: z14.string().trim().min(1).max(64).optional(),
3880
+ fundingSource: z15.string().trim().min(1).max(64).optional(),
3556
3881
  providerMetadata: Metadata.optional()
3557
3882
  });
3558
- var PartnerFundingSchema = z14.object({
3559
- fundingId: z14.string().uuid(),
3560
- partnerId: z14.string().uuid(),
3561
- accountId: z14.string().uuid(),
3562
- userId: z14.string().uuid().nullable(),
3563
- direction: z14.enum(PARTNER_FUNDING_DIRECTIONS),
3564
- currency: z14.string(),
3883
+ var PartnerFundingSchema = z15.object({
3884
+ fundingId: z15.string().uuid(),
3885
+ partnerId: z15.string().uuid(),
3886
+ accountId: z15.string().uuid(),
3887
+ userId: z15.string().uuid().nullable(),
3888
+ direction: z15.enum(PARTNER_FUNDING_DIRECTIONS),
3889
+ currency: z15.string(),
3565
3890
  amountMinor: MinorString,
3566
- externalRef: z14.string(),
3567
- status: z14.enum(PARTNER_FUNDING_STATUSES),
3568
- fundingSource: z14.string(),
3569
- ledgerRef: z14.string(),
3891
+ externalRef: z15.string(),
3892
+ status: z15.enum(PARTNER_FUNDING_STATUSES),
3893
+ fundingSource: z15.string(),
3894
+ ledgerRef: z15.string(),
3570
3895
  providerMetadata: Metadata,
3571
- createdAtMs: z14.number().int().nonnegative(),
3572
- updatedAtMs: z14.number().int().nonnegative()
3896
+ createdAtMs: z15.number().int().nonnegative(),
3897
+ updatedAtMs: z15.number().int().nonnegative()
3573
3898
  });
3574
- var IngestFundingResultSchema = z14.object({
3899
+ var IngestFundingResultSchema = z15.object({
3575
3900
  funding: PartnerFundingSchema,
3576
- replayed: z14.boolean()
3901
+ replayed: z15.boolean()
3577
3902
  });
3578
- var PayoutDestinationSchema = z14.object({
3579
- destinationId: z14.string().uuid(),
3580
- accountId: z14.string().uuid(),
3581
- partnerId: z14.string().uuid(),
3582
- bankCode: z14.string(),
3583
- accountNumber: z14.string(),
3584
- accountName: z14.string(),
3585
- status: z14.enum(PAYOUT_DESTINATION_STATUSES),
3586
- verifiedAtMs: z14.number().int().nonnegative().nullable(),
3903
+ var PayoutDestinationSchema = z15.object({
3904
+ destinationId: z15.string().uuid(),
3905
+ accountId: z15.string().uuid(),
3906
+ partnerId: z15.string().uuid(),
3907
+ bankCode: z15.string(),
3908
+ accountNumber: z15.string(),
3909
+ accountName: z15.string(),
3910
+ status: z15.enum(PAYOUT_DESTINATION_STATUSES),
3911
+ verifiedAtMs: z15.number().int().nonnegative().nullable(),
3587
3912
  metadata: Metadata,
3588
- createdAtMs: z14.number().int().nonnegative(),
3589
- updatedAtMs: z14.number().int().nonnegative()
3913
+ createdAtMs: z15.number().int().nonnegative(),
3914
+ updatedAtMs: z15.number().int().nonnegative()
3590
3915
  });
3591
- var CreatePayoutDestinationInputSchema = z14.object({
3592
- partnerId: z14.string().uuid(),
3593
- bankCode: z14.string().trim().min(1).max(32),
3594
- accountNumber: z14.string().trim().min(4).max(64),
3595
- accountName: z14.string().trim().min(1).max(200),
3916
+ var CreatePayoutDestinationInputSchema = z15.object({
3917
+ partnerId: z15.string().uuid(),
3918
+ bankCode: z15.string().trim().min(1).max(32),
3919
+ accountNumber: z15.string().trim().min(4).max(64),
3920
+ accountName: z15.string().trim().min(1).max(200),
3596
3921
  metadata: Metadata.optional()
3597
3922
  });
3598
- var ListPayoutDestinationsResultSchema = z14.object({
3599
- items: z14.array(PayoutDestinationSchema)
3923
+ var ListPayoutDestinationsResultSchema = z15.object({
3924
+ items: z15.array(PayoutDestinationSchema)
3600
3925
  });
3601
- var WithdrawalSchema = z14.object({
3602
- withdrawalId: z14.string().uuid(),
3603
- accountId: z14.string().uuid(),
3604
- userId: z14.string().uuid(),
3605
- partnerId: z14.string().uuid(),
3606
- destinationId: z14.string().uuid(),
3607
- currency: z14.string(),
3926
+ var WithdrawalSchema = z15.object({
3927
+ withdrawalId: z15.string().uuid(),
3928
+ accountId: z15.string().uuid(),
3929
+ userId: z15.string().uuid(),
3930
+ partnerId: z15.string().uuid(),
3931
+ destinationId: z15.string().uuid(),
3932
+ currency: z15.string(),
3608
3933
  amountMinor: MinorString,
3609
- state: z14.enum(WITHDRAWAL_STATES),
3610
- idempotencyKey: z14.string(),
3611
- providerRef: z14.string().nullable(),
3612
- lastError: z14.string().nullable(),
3613
- ledgerRef: z14.string(),
3614
- reverseLedgerRef: z14.string().nullable(),
3934
+ state: z15.enum(WITHDRAWAL_STATES),
3935
+ idempotencyKey: z15.string(),
3936
+ providerRef: z15.string().nullable(),
3937
+ lastError: z15.string().nullable(),
3938
+ ledgerRef: z15.string(),
3939
+ reverseLedgerRef: z15.string().nullable(),
3615
3940
  metadata: Metadata,
3616
- createdAtMs: z14.number().int().nonnegative(),
3617
- updatedAtMs: z14.number().int().nonnegative()
3941
+ createdAtMs: z15.number().int().nonnegative(),
3942
+ updatedAtMs: z15.number().int().nonnegative()
3618
3943
  });
3619
- var CreateWithdrawalInputSchema = z14.object({
3620
- destinationId: z14.string().uuid(),
3944
+ var CreateWithdrawalInputSchema = z15.object({
3945
+ destinationId: z15.string().uuid(),
3621
3946
  amountMinor: PositiveMinor,
3622
3947
  currency: Currency,
3623
- idempotencyKey: z14.string().trim().min(8).max(128),
3948
+ idempotencyKey: z15.string().trim().min(8).max(128),
3624
3949
  metadata: Metadata.optional()
3625
3950
  });
3626
- var CreateWithdrawalResultSchema = z14.object({
3951
+ var CreateWithdrawalResultSchema = z15.object({
3627
3952
  withdrawal: WithdrawalSchema,
3628
- replayed: z14.boolean()
3953
+ replayed: z15.boolean()
3629
3954
  });
3630
- var PayoutEventInputSchema = z14.object({
3631
- externalRef: z14.string().trim().min(8).max(128),
3632
- withdrawalId: z14.string().uuid().optional(),
3633
- state: z14.enum(["submitted", "processing", "paid", "failed"]),
3634
- providerRef: z14.string().trim().min(1).max(128).optional(),
3635
- failureCode: z14.string().trim().max(64).optional(),
3636
- failureMessage: z14.string().trim().max(512).optional(),
3955
+ var PayoutEventInputSchema = z15.object({
3956
+ externalRef: z15.string().trim().min(8).max(128),
3957
+ withdrawalId: z15.string().uuid().optional(),
3958
+ state: z15.enum(["submitted", "processing", "paid", "failed"]),
3959
+ providerRef: z15.string().trim().min(1).max(128).optional(),
3960
+ failureCode: z15.string().trim().max(64).optional(),
3961
+ failureMessage: z15.string().trim().max(512).optional(),
3637
3962
  providerMetadata: Metadata.optional()
3638
3963
  });
3639
- var RecordPayoutEventResultSchema = z14.object({
3964
+ var RecordPayoutEventResultSchema = z15.object({
3640
3965
  withdrawal: WithdrawalSchema,
3641
- replayed: z14.boolean()
3966
+ replayed: z15.boolean()
3642
3967
  });
3643
- var ReconciliationReportSchema = z14.object({
3644
- partnerId: z14.string().uuid(),
3645
- currency: z14.string(),
3646
- fromMs: z14.number().int().nonnegative(),
3647
- toMs: z14.number().int().nonnegative(),
3968
+ var ReconciliationReportSchema = z15.object({
3969
+ partnerId: z15.string().uuid(),
3970
+ currency: z15.string(),
3971
+ fromMs: z15.number().int().nonnegative(),
3972
+ toMs: z15.number().int().nonnegative(),
3648
3973
  fundingsCreditMinor: MinorString,
3649
3974
  fundingsDebitMinor: MinorString,
3650
3975
  withdrawalsPaidMinor: MinorString,
@@ -3653,7 +3978,7 @@ var ReconciliationReportSchema = z14.object({
3653
3978
  expectedReserveBalanceMinor: MinorString,
3654
3979
  actualReserveBalanceMinor: MinorString,
3655
3980
  imbalanceMinor: MinorString,
3656
- generatedAtMs: z14.number().int().nonnegative()
3981
+ generatedAtMs: z15.number().int().nonnegative()
3657
3982
  });
3658
3983
  function createPartnerFundingClient(partner) {
3659
3984
  return {
@@ -3805,19 +4130,19 @@ function createPartnerProfileAdminClient(opts) {
3805
4130
  }
3806
4131
 
3807
4132
  // src/artifacts/envelope.ts
3808
- import { z as z15 } from "zod";
4133
+ import { z as z16 } from "zod";
3809
4134
  var FLUR_ARTIFACT_URI_SCHEME = "flur";
3810
4135
  var FLUR_ARTIFACT_VERSION = 1;
3811
4136
  var FLUR_ARTIFACT_URI_PREFIX = `${FLUR_ARTIFACT_URI_SCHEME}://v${FLUR_ARTIFACT_VERSION}/`;
3812
4137
  var ArtifactTypeRe = /^[a-z][a-z0-9_]{1,63}$/;
3813
- var ArtifactHeaderSchema = z15.object({
3814
- v: z15.literal(FLUR_ARTIFACT_VERSION),
3815
- t: z15.string().regex(ArtifactTypeRe, "invalid artifact type"),
3816
- iss: z15.string().min(1).max(128),
3817
- kid: z15.string().min(1).max(128),
3818
- iat: z15.number().int().nonnegative(),
3819
- exp: z15.number().int().positive().optional(),
3820
- nonce: z15.string().min(8).max(64).regex(/^[A-Za-z0-9_-]+$/, "nonce must be url-safe")
4138
+ var ArtifactHeaderSchema = z16.object({
4139
+ v: z16.literal(FLUR_ARTIFACT_VERSION),
4140
+ t: z16.string().regex(ArtifactTypeRe, "invalid artifact type"),
4141
+ iss: z16.string().min(1).max(128),
4142
+ kid: z16.string().min(1).max(128),
4143
+ iat: z16.number().int().nonnegative(),
4144
+ exp: z16.number().int().positive().optional(),
4145
+ nonce: z16.string().min(8).max(64).regex(/^[A-Za-z0-9_-]+$/, "nonce must be url-safe")
3821
4146
  });
3822
4147
  var FlurArtifactError = class extends Error {
3823
4148
  constructor(message, code) {
@@ -3956,7 +4281,7 @@ function verifyArtifactSignature(decoded, publicKeySpkiB64, options = {}) {
3956
4281
  }
3957
4282
 
3958
4283
  // src/artifacts/types.ts
3959
- import { z as z16 } from "zod";
4284
+ import { z as z17 } from "zod";
3960
4285
  var ARTIFACT_TYPES = {
3961
4286
  OFFLINE_PAYMENT_AUTHORIZATION: "offline_payment_authorization",
3962
4287
  RECEIPT: "receipt",
@@ -3971,32 +4296,32 @@ var ARTIFACT_TYPES = {
3971
4296
  PASS: "pass",
3972
4297
  IDENTITY: "identity"
3973
4298
  };
3974
- var HexString = (length) => z16.string().regex(
4299
+ var HexString = (length) => z17.string().regex(
3975
4300
  new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
3976
4301
  `expected ${length}-byte hex string`
3977
4302
  );
3978
- var OfflinePaymentAuthorizationArtifactSchema = z16.object({
4303
+ var OfflinePaymentAuthorizationArtifactSchema = z17.object({
3979
4304
  authorization: OfflinePaymentAuthorizationSchema
3980
4305
  });
3981
- var ReceiptArtifactSchema = z16.object({
3982
- receiptId: z16.string().min(1).max(64),
3983
- paymentReference: z16.string().min(1).max(64),
3984
- payerUserId: z16.string().min(1).max(64).optional(),
3985
- payeeUserId: z16.string().min(1).max(64),
3986
- amountKobo: z16.number().int().positive(),
3987
- currency: z16.literal("NGN"),
3988
- channel: z16.enum(["online", "offline_reconciled", "pay_link", "nqr"]),
3989
- settledAtMs: z16.number().int().positive(),
3990
- ledgerTxnId: z16.string().min(1).max(64).optional(),
3991
- memo: z16.string().max(140).optional(),
4306
+ var ReceiptArtifactSchema = z17.object({
4307
+ receiptId: z17.string().min(1).max(64),
4308
+ paymentReference: z17.string().min(1).max(64),
4309
+ payerUserId: z17.string().min(1).max(64).optional(),
4310
+ payeeUserId: z17.string().min(1).max(64),
4311
+ amountKobo: z17.number().int().positive(),
4312
+ currency: z17.literal("NGN"),
4313
+ channel: z17.enum(["online", "offline_reconciled", "pay_link", "nqr"]),
4314
+ settledAtMs: z17.number().int().positive(),
4315
+ ledgerTxnId: z17.string().min(1).max(64).optional(),
4316
+ memo: z17.string().max(140).optional(),
3992
4317
  hashChainPrev: HexString(32).optional()
3993
4318
  });
3994
- var ShortId = z16.string().min(1).max(64);
3995
- var PositiveInt = z16.number().int().positive();
3996
- var NonNegativeInt = z16.number().int().nonnegative();
3997
- var Currency2 = z16.literal("NGN");
3998
- var Memo = z16.string().max(140);
3999
- var NqrPaymentRequestArtifactSchema = z16.object({
4319
+ var ShortId = z17.string().min(1).max(64);
4320
+ var PositiveInt = z17.number().int().positive();
4321
+ var NonNegativeInt = z17.number().int().nonnegative();
4322
+ var Currency2 = z17.literal("NGN");
4323
+ var Memo = z17.string().max(140);
4324
+ var NqrPaymentRequestArtifactSchema = z17.object({
4000
4325
  requestId: ShortId,
4001
4326
  payeeUserId: ShortId,
4002
4327
  amountKobo: PositiveInt.optional(),
@@ -4004,7 +4329,7 @@ var NqrPaymentRequestArtifactSchema = z16.object({
4004
4329
  memo: Memo.optional(),
4005
4330
  expiresAtMs: PositiveInt.optional()
4006
4331
  });
4007
- var PaymentIntentArtifactSchema = z16.object({
4332
+ var PaymentIntentArtifactSchema = z17.object({
4008
4333
  intentId: ShortId,
4009
4334
  payerUserId: ShortId,
4010
4335
  payeeUserId: ShortId,
@@ -4013,7 +4338,7 @@ var PaymentIntentArtifactSchema = z16.object({
4013
4338
  idempotencyKey: ShortId,
4014
4339
  createdAtMs: PositiveInt
4015
4340
  });
4016
- var OfflineClaimArtifactSchema = z16.object({
4341
+ var OfflineClaimArtifactSchema = z17.object({
4017
4342
  claimId: ShortId,
4018
4343
  authorizationId: ShortId,
4019
4344
  payeeUserId: ShortId,
@@ -4022,10 +4347,10 @@ var OfflineClaimArtifactSchema = z16.object({
4022
4347
  claimedAtMs: PositiveInt,
4023
4348
  paymentReference: ShortId.optional()
4024
4349
  });
4025
- var SettlementRecordArtifactSchema = z16.object({
4350
+ var SettlementRecordArtifactSchema = z17.object({
4026
4351
  settlementId: ShortId,
4027
4352
  ledgerTxnId: ShortId,
4028
- sourceRefType: z16.enum([
4353
+ sourceRefType: z17.enum([
4029
4354
  "offline_authorization",
4030
4355
  "offline_claim",
4031
4356
  "transfer",
@@ -4036,12 +4361,12 @@ var SettlementRecordArtifactSchema = z16.object({
4036
4361
  currency: Currency2,
4037
4362
  settledAtMs: PositiveInt
4038
4363
  });
4039
- var ReversalRecordArtifactSchema = z16.object({
4364
+ var ReversalRecordArtifactSchema = z17.object({
4040
4365
  reversalId: ShortId,
4041
4366
  originalTxnId: ShortId,
4042
4367
  amountKobo: PositiveInt,
4043
4368
  currency: Currency2,
4044
- reason: z16.enum([
4369
+ reason: z17.enum([
4045
4370
  "user_dispute",
4046
4371
  "fraud",
4047
4372
  "duplicate",
@@ -4051,7 +4376,7 @@ var ReversalRecordArtifactSchema = z16.object({
4051
4376
  reversedAtMs: PositiveInt,
4052
4377
  memo: Memo.optional()
4053
4378
  });
4054
- var LedgerJournalEntryArtifactSchema = z16.object({
4379
+ var LedgerJournalEntryArtifactSchema = z17.object({
4055
4380
  entryId: ShortId,
4056
4381
  journalId: ShortId,
4057
4382
  debitAccountId: ShortId,
@@ -4062,13 +4387,13 @@ var LedgerJournalEntryArtifactSchema = z16.object({
4062
4387
  refType: ShortId.optional(),
4063
4388
  refId: ShortId.optional()
4064
4389
  });
4065
- var StatementArtifactSchema = z16.object({
4390
+ var StatementArtifactSchema = z17.object({
4066
4391
  statementId: ShortId,
4067
4392
  userId: ShortId,
4068
4393
  periodStartMs: PositiveInt,
4069
4394
  periodEndMs: PositiveInt,
4070
- openingBalanceKobo: z16.number().int(),
4071
- closingBalanceKobo: z16.number().int(),
4395
+ openingBalanceKobo: z17.number().int(),
4396
+ closingBalanceKobo: z17.number().int(),
4072
4397
  transactionCount: NonNegativeInt,
4073
4398
  currency: Currency2,
4074
4399
  hashChainPrev: HexString(32).optional()
@@ -4076,16 +4401,16 @@ var StatementArtifactSchema = z16.object({
4076
4401
  message: "periodEndMs must be greater than periodStartMs",
4077
4402
  path: ["periodEndMs"]
4078
4403
  });
4079
- var PassArtifactSchema = z16.object({
4404
+ var PassArtifactSchema = z17.object({
4080
4405
  passId: ShortId,
4081
4406
  holderId: ShortId,
4082
- category: z16.enum(["membership", "ticket", "loyalty", "access", "voucher"]),
4083
- title: z16.string().min(1).max(120),
4407
+ category: z17.enum(["membership", "ticket", "loyalty", "access", "voucher"]),
4408
+ title: z17.string().min(1).max(120),
4084
4409
  validFromMs: PositiveInt,
4085
4410
  validUntilMs: PositiveInt.optional(),
4086
- metadata: z16.record(
4087
- z16.string().min(1).max(64),
4088
- z16.union([z16.string().max(280), z16.number(), z16.boolean()])
4411
+ metadata: z17.record(
4412
+ z17.string().min(1).max(64),
4413
+ z17.union([z17.string().max(280), z17.number(), z17.boolean()])
4089
4414
  ).optional()
4090
4415
  }).refine(
4091
4416
  (v) => v.validUntilMs === void 0 || v.validUntilMs > v.validFromMs,
@@ -4094,10 +4419,10 @@ var PassArtifactSchema = z16.object({
4094
4419
  path: ["validUntilMs"]
4095
4420
  }
4096
4421
  );
4097
- var IdentityArtifactSchema = z16.object({
4422
+ var IdentityArtifactSchema = z17.object({
4098
4423
  attestationId: ShortId,
4099
4424
  subjectId: ShortId,
4100
- claimType: z16.enum([
4425
+ claimType: z17.enum([
4101
4426
  "phone_verified",
4102
4427
  "email_verified",
4103
4428
  "bvn_verified",
@@ -4217,6 +4542,7 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
4217
4542
  });
4218
4543
  }
4219
4544
  export {
4545
+ ACCOUNT_FUNDED_OAC_MAX_TTL_MS,
4220
4546
  ACCOUNT_STATUSES,
4221
4547
  ACCOUNT_TYPES,
4222
4548
  ADDITIONAL_DATA_SUBFIELD,
@@ -4230,6 +4556,10 @@ export {
4230
4556
  CLAIM_DOMAIN_V2,
4231
4557
  COLLECTION_INTENT_STATUSES,
4232
4558
  COLLECTION_PAYMENT_STATUSES,
4559
+ CONSUMER_OFFLINE_CLAIM_SUBMIT_GRACE_MS,
4560
+ CONSUMER_PAYMENT_REQUEST_DOMAIN,
4561
+ CONSUMER_SETTLEMENT_DOMAIN,
4562
+ CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX,
4233
4563
  CUSTODIAL_MODES,
4234
4564
  CollectionIntentSchema,
4235
4565
  CollectionPaymentResultSchema,
@@ -4239,6 +4569,7 @@ export {
4239
4569
  OACRecordSchema as ConsumerOACRecordSchema,
4240
4570
  ConsumerOACSchema,
4241
4571
  ConsumerPaymentClaimSchema,
4572
+ ConsumerPaymentRequestEnvelopeSchema,
4242
4573
  ConsumerSettleResultSchema,
4243
4574
  ConsumerSettlementSchema,
4244
4575
  CreateCollectionIntentInputSchema,
@@ -4248,10 +4579,6 @@ export {
4248
4579
  CreateWithdrawalResultSchema,
4249
4580
  DeviceKeyAlgSchema,
4250
4581
  DeviceKeyRecordSchema,
4251
- DisableOfflineInputSchema,
4252
- DisableOfflineResultSchema,
4253
- EnableOfflineInputSchema,
4254
- EnableOfflineResultSchema,
4255
4582
  FIELD,
4256
4583
  FLUR_ARTIFACT_URI_PREFIX,
4257
4584
  FLUR_ARTIFACT_URI_SCHEME,
@@ -4267,7 +4594,6 @@ export {
4267
4594
  IdentityArtifactSchema,
4268
4595
  IngestFundingResultSchema,
4269
4596
  IssueAccountOacInputSchema,
4270
- IssueOACInputSchema,
4271
4597
  LedgerJournalEntryArtifactSchema,
4272
4598
  ListPayoutDestinationsResultSchema,
4273
4599
  MEMBERSHIP_ROLES,
@@ -4285,12 +4611,16 @@ export {
4285
4611
  OAC_DEFAULT_PER_TX_KOBO,
4286
4612
  OAC_DEFAULT_VALIDITY_MS,
4287
4613
  OFFLINE_CLAIM_SMS_PREFIX,
4614
+ OFFLINE_SMS_SETTLE_DOMAIN,
4615
+ OFFLINE_SMS_SETTLE_HEADER_BYTES,
4616
+ OFFLINE_SMS_SETTLE_PREFIX,
4617
+ OFFLINE_SMS_SETTLE_SIGNATURE_BYTES,
4618
+ OFFLINE_SMS_SETTLE_TOKEN_BYTES,
4619
+ OFFLINE_SMS_SETTLE_VERSION,
4288
4620
  OfflineClaimArtifactSchema,
4289
- OfflineHoldRecordSchema,
4290
4621
  OfflinePaymentAuthorizationArtifactSchema,
4291
4622
  OfflinePaymentAuthorizationSchema,
4292
4623
  OfflinePaymentRequestSchema,
4293
- OfflineStateResultSchema,
4294
4624
  OfflineStatusResultSchema,
4295
4625
  OfflineTokenSchema,
4296
4626
  P256EnrollmentChallengeInputSchema,
@@ -4318,8 +4648,6 @@ export {
4318
4648
  PayoutEventInputSchema,
4319
4649
  ProviderEventInputSchema,
4320
4650
  ProviderEventRecordSchema,
4321
- ProvisionOfflineAllowanceInputSchema,
4322
- ProvisionOfflineAllowanceResultSchema,
4323
4651
  PublicCollectionIntentSchema,
4324
4652
  RECEIPT_CHANNELS,
4325
4653
  RECEIPT_KINDS,
@@ -4330,7 +4658,6 @@ export {
4330
4658
  ReconciliationReportSchema,
4331
4659
  RecordPayoutEventResultSchema,
4332
4660
  RedemptionSchema,
4333
- RegisterDeviceKeyInputSchema,
4334
4661
  RegisterDeviceKeyP256InputSchema,
4335
4662
  ReversalRecordArtifactSchema,
4336
4663
  RevokeDeviceKeyInputSchema,
@@ -4349,18 +4676,25 @@ export {
4349
4676
  bodySha256Hex,
4350
4677
  buildArtifactBody,
4351
4678
  buildAuthorization,
4679
+ buildConsumerPaymentRequest,
4352
4680
  buildOAC,
4353
4681
  buildPass,
4354
4682
  buildPaymentRequest,
4355
4683
  buildReceipt,
4356
4684
  buildRedemption,
4685
+ buildSmsSettleHeader,
4686
+ domainTag as buildSmsSettleSignedBytes,
4357
4687
  canonicalClaimSigningBytes,
4358
4688
  canonicalClaimSigningPayload,
4359
4689
  canonicalJSONBytes,
4360
4690
  canonicalJSONStringify,
4361
4691
  canonicalRequestString,
4692
+ computeConsumerClaimEncounterId,
4362
4693
  computeEncounterId,
4363
4694
  constantTimeEqual,
4695
+ consumerPaymentRequestSigningBytes,
4696
+ consumerPaymentRequestSigningPayload,
4697
+ consumerSettlementSigningPayload,
4364
4698
  crc16ccitt,
4365
4699
  crc16ccittHex,
4366
4700
  createAccountsClient,
@@ -4384,19 +4718,27 @@ export {
4384
4718
  decodeArtifactUri,
4385
4719
  decodeAuthorizationQR,
4386
4720
  decodeBase45,
4721
+ decodeConsumerSettlementReceiptQR,
4387
4722
  decodeOfflineClaimSmsMessage,
4723
+ decodeOfflineSmsSettleToken,
4388
4724
  decodePaymentRequestQR,
4725
+ decodeUnverifiedConsumerSettlementReceiptQR,
4726
+ derToRawP256Signature,
4389
4727
  encodeArtifactUri,
4390
4728
  encodeAuthorizationQR,
4391
4729
  encodeBase45,
4730
+ encodeConsumerSettlementReceiptQR,
4392
4731
  encodeNQR,
4393
4732
  encodeOfflineClaimSmsMessage,
4733
+ encodeOfflineSmsSettleToken,
4394
4734
  encodePaymentRequestQR,
4395
4735
  extractOfflineClaimSmsToken,
4736
+ extractOfflineSmsSettleToken,
4396
4737
  formatAmount,
4397
4738
  generateDynamicQR,
4398
4739
  generateStaticQR,
4399
4740
  init,
4741
+ isConsumerPaymentRequestExpired,
4400
4742
  isHardenedArtifactType,
4401
4743
  isKnownArtifactType,
4402
4744
  isPassWithinValidity,
@@ -4409,6 +4751,7 @@ export {
4409
4751
  routingHint,
4410
4752
  signArtifact,
4411
4753
  signAuthorization,
4754
+ signConsumerPaymentRequest,
4412
4755
  signOAC,
4413
4756
  signPartnerRequest,
4414
4757
  signPass,
@@ -4420,7 +4763,11 @@ export {
4420
4763
  verifyArtifactUri,
4421
4764
  verifyAuthorization,
4422
4765
  verifyClaimSignature,
4766
+ verifyConsumerPaymentRequest,
4767
+ verifyConsumerSettlement,
4768
+ verifyConsumerSettlementReceiptQR,
4423
4769
  verifyOAC,
4770
+ verifyOfflineSmsSettleToken,
4424
4771
  verifyPass,
4425
4772
  verifyPaymentRequest,
4426
4773
  verifyReceipt,