@nokinc-flur/sdk 1.1.4 → 1.1.5

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.cjs CHANGED
@@ -69,6 +69,7 @@ __export(index_exports, {
69
69
  HARDENED_ARTIFACT_TYPES: () => HARDENED_ARTIFACT_TYPES,
70
70
  IdentityArtifactSchema: () => IdentityArtifactSchema,
71
71
  IngestFundingResultSchema: () => IngestFundingResultSchema,
72
+ IssueAccountOacInputSchema: () => IssueAccountOacInputSchema,
72
73
  IssueOACInputSchema: () => IssueOACInputSchema,
73
74
  LedgerJournalEntryArtifactSchema: () => LedgerJournalEntryArtifactSchema,
74
75
  ListPayoutDestinationsResultSchema: () => ListPayoutDestinationsResultSchema,
@@ -233,203 +234,13 @@ __export(index_exports, {
233
234
  module.exports = __toCommonJS(index_exports);
234
235
 
235
236
  // src/client.ts
236
- var import_zod4 = require("zod");
237
+ var import_zod5 = require("zod");
237
238
 
238
239
  // src/contracts.ts
240
+ var import_zod2 = require("zod");
241
+
242
+ // src/me-offline/client.ts
239
243
  var import_zod = require("zod");
240
- var E164Regex = /^\+[1-9]\d{7,14}$/;
241
- var UuidSchema = import_zod.z.string().uuid();
242
- var IsoDateSchema = import_zod.z.string().datetime({ offset: true });
243
- var CurrencySchema = import_zod.z.string().trim().length(3).transform((value) => value.toUpperCase());
244
- var HealthResponseSchema = import_zod.z.object({
245
- ok: import_zod.z.boolean()
246
- });
247
- var WelcomeResponseSchema = import_zod.z.object({
248
- message: import_zod.z.string()
249
- });
250
- var OnboardingStartRequestSchema = import_zod.z.object({
251
- phoneE164: import_zod.z.string().regex(E164Regex),
252
- appInstanceId: import_zod.z.string().min(3),
253
- platform: import_zod.z.enum(["android", "ios", "web"]),
254
- turnstileToken: import_zod.z.string().min(20).optional(),
255
- appAttestation: import_zod.z.object({
256
- provider: import_zod.z.enum(["android", "ios", "web"]),
257
- token: import_zod.z.string().min(24)
258
- }).optional(),
259
- firstName: import_zod.z.string().trim().min(1).max(80).optional(),
260
- lastName: import_zod.z.string().trim().min(1).max(80).optional()
261
- });
262
- var OnboardingStartResponseSchema = import_zod.z.object({
263
- requestId: import_zod.z.string().min(1),
264
- checkUrl: import_zod.z.string().url().optional(),
265
- expiresInSec: import_zod.z.number().int().positive(),
266
- fallback: import_zod.z.enum(["SILENT_AUTH", "OTP"])
267
- });
268
- var OnboardingCompleteRequestSchema = import_zod.z.object({
269
- requestId: import_zod.z.string().min(1),
270
- code: import_zod.z.string().min(1).max(32),
271
- appInstanceId: import_zod.z.string().min(3),
272
- fingerprintHash: import_zod.z.string().min(3).optional()
273
- });
274
- var OnboardingCompleteResponseSchema = import_zod.z.object({
275
- sessionToken: import_zod.z.string().min(1),
276
- userId: UuidSchema,
277
- restricted: import_zod.z.boolean(),
278
- risk_reasons: import_zod.z.array(
279
- import_zod.z.enum(["SIM_SWAP_RECENT", "ROAMING", "CARRIER_CHANGED"])
280
- ),
281
- stepUpRequired: import_zod.z.boolean().optional(),
282
- riskStatus: import_zod.z.enum(["ok", "unavailable"]).optional()
283
- });
284
- var RegisterDeviceRequestSchema = import_zod.z.object({
285
- userId: UuidSchema,
286
- appInstanceId: import_zod.z.string().min(3),
287
- platform: import_zod.z.string().min(2),
288
- model: import_zod.z.string().optional(),
289
- networkSignals: import_zod.z.object({
290
- ip: import_zod.z.string().min(3),
291
- asn: import_zod.z.number().int().optional(),
292
- country: import_zod.z.string().min(2).optional(),
293
- carrier: import_zod.z.string().optional()
294
- })
295
- });
296
- var RegisterDeviceResponseSchema = import_zod.z.object({
297
- deviceId: import_zod.z.string().min(1),
298
- fingerprintHash: import_zod.z.string().min(1),
299
- driftScore: import_zod.z.number(),
300
- trustState: import_zod.z.enum(["TRUSTED_PRIMARY", "TRUSTED_SECONDARY", "UNVERIFIED"]),
301
- stepUpRequired: import_zod.z.boolean()
302
- });
303
- var AuthRefreshRequestSchema = import_zod.z.object({
304
- userId: UuidSchema,
305
- refreshToken: import_zod.z.string().min(8),
306
- appInstanceId: import_zod.z.string().min(3),
307
- fingerprintHash: import_zod.z.string().min(3)
308
- });
309
- var AuthRefreshResponseSchema = import_zod.z.object({
310
- refreshToken: import_zod.z.string().min(8),
311
- stepUpRequired: import_zod.z.boolean()
312
- });
313
- var AuthLogoutRequestSchema = import_zod.z.object({
314
- userId: UuidSchema,
315
- refreshToken: import_zod.z.string().min(8)
316
- });
317
- var PinSetRequestSchema = import_zod.z.object({
318
- userId: UuidSchema,
319
- pin: import_zod.z.string().regex(/^\d{6}$/)
320
- });
321
- var PinVerifyRequestSchema = import_zod.z.object({
322
- userId: UuidSchema,
323
- pin: import_zod.z.string().regex(/^\d{6}$/)
324
- });
325
- var OkResponseSchema = import_zod.z.object({
326
- ok: import_zod.z.boolean()
327
- });
328
- var RegisterSendDeviceKeyRequestSchema = import_zod.z.object({
329
- userId: UuidSchema,
330
- deviceId: import_zod.z.string().min(3),
331
- publicKey: import_zod.z.string().min(32)
332
- });
333
- var SEND_AUTH_PURPOSES = ["send_money", "offline_revoke"];
334
- var SendChallengeRequestSchema = import_zod.z.object({
335
- userId: UuidSchema,
336
- deviceId: import_zod.z.string().min(3),
337
- purpose: import_zod.z.enum(SEND_AUTH_PURPOSES).optional()
338
- });
339
- var SendChallengeResponseSchema = import_zod.z.object({
340
- challengeId: UuidSchema,
341
- nonce: import_zod.z.string().min(1),
342
- expiresAt: IsoDateSchema
343
- });
344
- var SendVerifyRequestSchema = import_zod.z.object({
345
- userId: UuidSchema,
346
- deviceId: import_zod.z.string().min(3),
347
- challengeId: UuidSchema,
348
- signature: import_zod.z.string().min(16)
349
- });
350
- var SendVerifyResponseSchema = import_zod.z.object({
351
- sendAuthToken: import_zod.z.string().min(16)
352
- });
353
- var ResolveRecipientRequestSchema = import_zod.z.object({
354
- identifier: import_zod.z.string().min(3)
355
- });
356
- var ResolveRecipientResponseSchema = import_zod.z.object({
357
- recipientUserId: UuidSchema,
358
- displayName: import_zod.z.string().min(1),
359
- normalizedIdentifier: import_zod.z.string().regex(E164Regex),
360
- isActive: import_zod.z.boolean()
361
- });
362
- var CreateTransferRequestSchema = import_zod.z.object({
363
- recipientIdentifier: import_zod.z.string().min(3),
364
- amountMinor: import_zod.z.number().int().positive(),
365
- currency: CurrencySchema,
366
- sendAuthToken: import_zod.z.string().min(16)
367
- });
368
- var TransferStatusSchema = import_zod.z.enum(["SETTLED", "PENDING_REVIEW", "DECLINED"]);
369
- var TransferResponseSchema = import_zod.z.object({
370
- transactionId: import_zod.z.string().min(1),
371
- status: TransferStatusSchema,
372
- userStatus: TransferStatusSchema,
373
- recipientName: import_zod.z.string().min(1),
374
- timestamp: IsoDateSchema
375
- });
376
- var DirectionSchema = import_zod.z.enum(["OUTGOING", "INCOMING"]);
377
- var AccountActivityItemSchema = import_zod.z.object({
378
- id: import_zod.z.string().min(1),
379
- type: import_zod.z.string().min(1),
380
- direction: DirectionSchema,
381
- name: import_zod.z.string().min(1),
382
- identifier: import_zod.z.string().min(1),
383
- amountMinor: import_zod.z.number().int(),
384
- currency: CurrencySchema,
385
- status: import_zod.z.string().min(1),
386
- timestamp: IsoDateSchema
387
- });
388
- var AccountSummaryResponseSchema = import_zod.z.object({
389
- /** Authenticated user's stable internal id. */
390
- userId: UuidSchema,
391
- /**
392
- * 10-digit Nigeria Uniform Bank Account Number (NUBAN) allocated by the
393
- * bank partner. `null` when the user has no partner-allocated account yet.
394
- */
395
- nuban: import_zod.z.string().regex(/^[0-9]{10}$/).nullable(),
396
- balance: import_zod.z.number().int(),
397
- currency: CurrencySchema,
398
- dailySendLimit: import_zod.z.number().int().nonnegative(),
399
- dailySendRemaining: import_zod.z.number().int().nonnegative(),
400
- kycTier: import_zod.z.string().min(1),
401
- kycStatus: import_zod.z.string().min(1),
402
- recentActivity: import_zod.z.array(AccountActivityItemSchema)
403
- });
404
- var TransactionsListResponseSchema = import_zod.z.object({
405
- items: import_zod.z.array(AccountActivityItemSchema),
406
- nextCursor: import_zod.z.string().nullable()
407
- });
408
- var TransactionDetailResponseSchema = import_zod.z.object({
409
- transactionId: import_zod.z.string().min(1),
410
- type: import_zod.z.string().min(1),
411
- direction: DirectionSchema,
412
- counterpartyName: import_zod.z.string().min(1),
413
- counterpartyIdentifier: import_zod.z.string().min(1),
414
- amountMinor: import_zod.z.number().int(),
415
- currency: CurrencySchema,
416
- status: import_zod.z.string().min(1),
417
- timestamp: IsoDateSchema
418
- });
419
- var PushRegisterRequestSchema = import_zod.z.object({
420
- deviceId: import_zod.z.string().min(3),
421
- platform: import_zod.z.enum(["ios", "android", "web"]),
422
- token: import_zod.z.string().min(16)
423
- });
424
- var CreatePayLinkResponseSchema = import_zod.z.object({
425
- token: import_zod.z.string().min(1)
426
- });
427
- var ResolvePayLinkResponseSchema = import_zod.z.object({
428
- recipientUserId: UuidSchema,
429
- displayName: import_zod.z.string().min(1),
430
- normalizedIdentifier: import_zod.z.string().regex(E164Regex),
431
- isActive: import_zod.z.boolean()
432
- });
433
244
 
434
245
  // src/errors.ts
435
246
  var backendErrorCodeSet = /* @__PURE__ */ new Set([
@@ -533,9 +344,556 @@ async function mapToFlurError(res) {
533
344
  });
534
345
  }
535
346
 
347
+ // src/me-offline/client.ts
348
+ var Hex64 = import_zod.z.string().regex(/^[0-9a-f]{64}$/i);
349
+ var Sha256Hex = import_zod.z.string().regex(/^[0-9a-f]{64}$/i);
350
+ var Base64Std = import_zod.z.string().regex(/^[A-Za-z0-9+/]+={0,2}$/);
351
+ var RegisterDeviceKeyInputSchema = import_zod.z.object({
352
+ deviceId: import_zod.z.string().min(1).max(128),
353
+ publicKeyHex: Hex64
354
+ });
355
+ var AttestationSecurityLevelSchema = import_zod.z.enum([
356
+ "STRONGBOX",
357
+ "TEE",
358
+ "SECURE_ENCLAVE",
359
+ "SOFTWARE"
360
+ ]);
361
+ var DeviceKeyAlgSchema = import_zod.z.literal("p256");
362
+ var RegisterDeviceKeyP256InputSchema = import_zod.z.object({
363
+ deviceId: import_zod.z.string().min(1).max(128),
364
+ /** P-256 SubjectPublicKeyInfo DER, base64. */
365
+ publicKeySpkiB64: Base64Std.min(64).max(4096),
366
+ /** Base64 of the server-issued enrollment challenge string. */
367
+ challengeB64: Base64Std.min(8).max(1024),
368
+ /** iOS App Attest payload or Android X.509 Key Attestation chain. */
369
+ attestationChainB64: import_zod.z.array(Base64Std.min(16).max(16384)).min(1).max(16),
370
+ securityLevel: AttestationSecurityLevelSchema
371
+ });
372
+ var P256EnrollmentChallengeInputSchema = import_zod.z.object({
373
+ deviceId: import_zod.z.string().min(1).max(128)
374
+ });
375
+ var P256EnrollmentChallengeResultSchema = import_zod.z.object({
376
+ challenge: import_zod.z.string().min(16),
377
+ expiresAtMs: import_zod.z.number().int().positive()
378
+ });
379
+ var DeviceKeyRecordSchema = import_zod.z.object({
380
+ id: import_zod.z.string().uuid(),
381
+ userId: import_zod.z.string().uuid(),
382
+ deviceId: import_zod.z.string(),
383
+ /** Always 'p256' on the consumer offline rail. Field retained for forward-compat. */
384
+ alg: DeviceKeyAlgSchema.default("p256"),
385
+ /** Legacy ed25519 hex key. Always null on new records (kept for back-compat reads). */
386
+ publicKeyHex: Hex64.nullable().default(null),
387
+ /** P-256 SubjectPublicKeyInfo DER, base64. Required for new records. */
388
+ publicKeySpkiB64: Base64Std.nullable().default(null),
389
+ securityLevel: AttestationSecurityLevelSchema.nullable().default(null),
390
+ hardwareBacked: import_zod.z.boolean().default(false),
391
+ attestedAtMs: import_zod.z.number().int().nonnegative().nullable().default(null),
392
+ createdAtMs: import_zod.z.number().int().nonnegative(),
393
+ revokedAtMs: import_zod.z.number().int().nonnegative().nullable()
394
+ });
395
+ var ConsumerOACSchema = import_zod.z.object({
396
+ oacId: import_zod.z.string().uuid(),
397
+ issuerId: import_zod.z.string().min(1).max(64),
398
+ userId: import_zod.z.string().uuid(),
399
+ deviceId: import_zod.z.string().min(1).max(128),
400
+ /**
401
+ * Always 'p256'. Required on the wire (backend always emits it).
402
+ * Kept as a literal so input/output infer identically and the schema
403
+ * can be nested inside other response shapes without Zod input/output
404
+ * divergence under tsup DTS bundling.
405
+ */
406
+ alg: import_zod.z.literal("p256"),
407
+ /** P-256 SubjectPublicKeyInfo DER, base64. */
408
+ devicePubkeySpkiB64: Base64Std.min(64).max(4096),
409
+ perTxCapKobo: import_zod.z.number().int().positive(),
410
+ cumulativeCapKobo: import_zod.z.number().int().positive(),
411
+ currency: import_zod.z.string().length(3),
412
+ validFromMs: import_zod.z.number().int().nonnegative(),
413
+ validUntilMs: import_zod.z.number().int().nonnegative(),
414
+ counterSeed: import_zod.z.number().int().nonnegative(),
415
+ issuedAtMs: import_zod.z.number().int().nonnegative()
416
+ });
417
+ var SignedConsumerOACSchema = import_zod.z.object({
418
+ oac: ConsumerOACSchema,
419
+ /** ASN.1 DER ECDSA P-256 issuer signature, base64. */
420
+ issuerSig: Base64Std.min(16).max(2048),
421
+ /** Issuer's P-256 public key as SubjectPublicKeyInfo DER, base64. */
422
+ issuerPublicKeySpkiB64: Base64Std.min(64).max(4096)
423
+ });
424
+ var OACRecordSchema = SignedConsumerOACSchema.extend({
425
+ currentOfflineSpentKobo: import_zod.z.number().int().nonnegative(),
426
+ status: import_zod.z.enum([
427
+ "active",
428
+ "superseded",
429
+ "expired",
430
+ "revoked",
431
+ "disabling",
432
+ "draining",
433
+ "closed"
434
+ ]),
435
+ supersededAtMs: import_zod.z.number().int().nonnegative().nullable(),
436
+ revokedAtMs: import_zod.z.number().int().nonnegative().nullable(),
437
+ holdId: import_zod.z.string().uuid().nullable().optional()
438
+ });
439
+ var IssueOACInputSchema = import_zod.z.object({
440
+ deviceId: import_zod.z.string().min(1).max(128),
441
+ perTxCapKobo: import_zod.z.number().int().positive().optional(),
442
+ cumulativeCapKobo: import_zod.z.number().int().positive().optional(),
443
+ ttlMs: import_zod.z.number().int().min(6e4).max(1e3 * 60 * 60 * 24 * 7).optional(),
444
+ spendableOnlineKobo: import_zod.z.number().int().nonnegative().optional()
445
+ });
446
+ var IssueAccountOacInputSchema = import_zod.z.object({
447
+ deviceId: import_zod.z.string().min(1).max(128),
448
+ perTxCapKobo: import_zod.z.number().int().positive().optional(),
449
+ cumulativeCapKobo: import_zod.z.number().int().positive().optional(),
450
+ ttlMs: import_zod.z.number().int().min(6e4).max(1e3 * 60 * 60 * 24 * 7).optional()
451
+ });
452
+ var EnableOfflineInputSchema = import_zod.z.object({
453
+ deviceId: import_zod.z.string().min(1).max(128),
454
+ amountKobo: import_zod.z.number().int().positive(),
455
+ perTxCapKobo: import_zod.z.number().int().positive().optional(),
456
+ ttlMs: import_zod.z.number().int().min(6e4).max(1e3 * 60 * 60 * 24 * 7).optional(),
457
+ installId: import_zod.z.string().min(1).max(128),
458
+ partnerId: import_zod.z.string().min(1).max(64).optional()
459
+ });
460
+ var ProvisionOfflineAllowanceInputSchema = EnableOfflineInputSchema;
461
+ var DisableOfflineInputSchema = import_zod.z.object({
462
+ deviceId: import_zod.z.string().min(1).max(128),
463
+ installId: import_zod.z.string().min(1).max(128).optional(),
464
+ claims: import_zod.z.array(import_zod.z.unknown()).max(256).optional()
465
+ });
466
+ var OfflineHoldRecordSchema = import_zod.z.object({
467
+ holdId: import_zod.z.string().uuid(),
468
+ userId: import_zod.z.string().uuid(),
469
+ deviceId: import_zod.z.string(),
470
+ partnerId: import_zod.z.string(),
471
+ adapterKind: import_zod.z.string(),
472
+ externalHoldRef: import_zod.z.string().nullable(),
473
+ amountKobo: import_zod.z.number().int().nonnegative(),
474
+ capturedKobo: import_zod.z.number().int().nonnegative(),
475
+ releasedKobo: import_zod.z.number().int().nonnegative(),
476
+ remainingKobo: import_zod.z.number().int().nonnegative(),
477
+ currency: import_zod.z.string().length(3),
478
+ status: import_zod.z.enum([
479
+ "placing",
480
+ "active",
481
+ "disabling",
482
+ "draining",
483
+ "closed",
484
+ "revoked",
485
+ "failed"
486
+ ]),
487
+ installId: import_zod.z.string().nullable(),
488
+ drainDeadlineMs: import_zod.z.number().int().nonnegative(),
489
+ disableRequestedAtMs: import_zod.z.number().int().nonnegative().nullable(),
490
+ createdAtMs: import_zod.z.number().int().nonnegative(),
491
+ closedAtMs: import_zod.z.number().int().nonnegative().nullable(),
492
+ isTrusted: import_zod.z.boolean().optional()
493
+ });
494
+ var EnableOfflineResultSchema = import_zod.z.object({
495
+ hold: OfflineHoldRecordSchema,
496
+ oac: OACRecordSchema
497
+ });
498
+ var ProvisionOfflineAllowanceResultSchema = EnableOfflineResultSchema;
499
+ var DisableOfflineResultSchema = import_zod.z.object({
500
+ hold: OfflineHoldRecordSchema,
501
+ trusted: import_zod.z.boolean(),
502
+ settledClaims: import_zod.z.number().int().nonnegative()
503
+ });
504
+ var OfflineStatusResultSchema = import_zod.z.object({
505
+ hold: OfflineHoldRecordSchema.nullable(),
506
+ active: OACRecordSchema.nullable()
507
+ });
508
+ var OfflineStateResultSchema = import_zod.z.object({
509
+ active: OACRecordSchema.nullable()
510
+ });
511
+ var ConsumerPaymentClaimSchema = import_zod.z.object({
512
+ /** Always 'p256'. Retained for forward-compat and as an explicit domain marker. */
513
+ alg: import_zod.z.literal("p256").default("p256"),
514
+ oacId: import_zod.z.string().uuid(),
515
+ encounterId: Sha256Hex.optional(),
516
+ payerUserId: import_zod.z.string().uuid(),
517
+ payeeUserId: import_zod.z.string().uuid(),
518
+ payerDeviceId: import_zod.z.string().min(1).max(128),
519
+ payerNonce: import_zod.z.string().min(8).max(128),
520
+ payeeNonce: import_zod.z.string().min(8).max(128),
521
+ amountKobo: import_zod.z.number().int().positive(),
522
+ currency: import_zod.z.string().length(3).default("NGN"),
523
+ occurredAtMs: import_zod.z.number().int().nonnegative(),
524
+ completedAtMs: import_zod.z.number().int().nonnegative().optional(),
525
+ contextId: import_zod.z.string().max(128).optional(),
526
+ payerPubkeySpkiB64: Base64Std.min(64).max(4096),
527
+ payerSignatureDerB64: Base64Std.min(16).max(2048),
528
+ payeePubkeySpkiB64: Base64Std.min(64).max(4096).optional(),
529
+ payeeSignatureDerB64: Base64Std.min(16).max(2048).optional()
530
+ });
531
+ var ConsumerSettlementSchema = import_zod.z.object({
532
+ settlementId: import_zod.z.string().uuid(),
533
+ settlementKey: Sha256Hex,
534
+ encounterId: Sha256Hex,
535
+ oacId: import_zod.z.string().uuid(),
536
+ payerUserId: import_zod.z.string().uuid(),
537
+ payeeUserId: import_zod.z.string().uuid(),
538
+ amountKobo: import_zod.z.number().int().positive(),
539
+ currency: import_zod.z.string().length(3),
540
+ status: import_zod.z.enum(["SETTLED", "REVIEW"]),
541
+ reviewReason: import_zod.z.string().nullable(),
542
+ ledgerRef: import_zod.z.string().nullable(),
543
+ /** ASN.1 DER ECDSA P-256 issuer signature, base64. */
544
+ issuerSig: Base64Std.min(16).max(2048),
545
+ createdAtMs: import_zod.z.number().int().nonnegative()
546
+ });
547
+ var ConsumerSettleResultSchema = import_zod.z.object({
548
+ settlement: ConsumerSettlementSchema,
549
+ encounterId: Sha256Hex,
550
+ replayed: import_zod.z.boolean()
551
+ });
552
+ var RevokeDeviceKeyInputSchema = import_zod.z.object({
553
+ deviceId: import_zod.z.string().min(1).max(128),
554
+ /** Step-up token from /api/v1/auth/send/verify with purpose='offline_revoke'. */
555
+ sendAuthToken: import_zod.z.string().min(16)
556
+ });
557
+ function createMeOfflineClient(opts) {
558
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
559
+ if (!fetchImpl) {
560
+ throw new Error("createMeOfflineClient: no fetch implementation available");
561
+ }
562
+ const baseUrl = opts.baseUrl.replace(/\/$/, "");
563
+ async function call(method, path, body, parser) {
564
+ const init2 = {
565
+ method,
566
+ headers: {
567
+ "content-type": "application/json",
568
+ accept: "application/json"
569
+ }
570
+ };
571
+ if (body !== void 0) init2.body = JSON.stringify(body);
572
+ const resp = await fetchImpl(`${baseUrl}${path}`, init2);
573
+ const text = await resp.text();
574
+ let raw = void 0;
575
+ if (text) {
576
+ try {
577
+ raw = JSON.parse(text);
578
+ } catch {
579
+ }
580
+ }
581
+ if (!resp.ok) {
582
+ const code = raw && typeof raw === "object" && "code" in raw && typeof raw.code === "string" ? raw.code : `http_${resp.status}`;
583
+ const message = raw && typeof raw === "object" && "message" in raw && typeof raw.message === "string" ? raw.message : `request failed with status ${resp.status}`;
584
+ throw new FlurApiError(resp.status, code, message, raw);
585
+ }
586
+ return parser(raw);
587
+ }
588
+ const deviceKeyItems = import_zod.z.object({ items: import_zod.z.array(DeviceKeyRecordSchema) });
589
+ return {
590
+ registerDeviceKey: (input) => call(
591
+ "POST",
592
+ "/v1/me/offline/keys",
593
+ RegisterDeviceKeyInputSchema.parse(input),
594
+ (raw) => DeviceKeyRecordSchema.parse(raw)
595
+ ),
596
+ issueP256EnrollmentChallenge: (input) => call(
597
+ "POST",
598
+ "/v1/me/offline/keys/p256/challenge",
599
+ P256EnrollmentChallengeInputSchema.parse(input),
600
+ (raw) => P256EnrollmentChallengeResultSchema.parse(raw)
601
+ ),
602
+ registerDeviceKeyP256: (input) => call(
603
+ "POST",
604
+ "/v1/me/offline/keys/p256",
605
+ RegisterDeviceKeyP256InputSchema.parse(input),
606
+ (raw) => DeviceKeyRecordSchema.parse(raw)
607
+ ),
608
+ listDeviceKeys: () => call(
609
+ "GET",
610
+ "/v1/me/offline/keys",
611
+ void 0,
612
+ (raw) => deviceKeyItems.parse(raw)
613
+ ),
614
+ revokeDeviceKey: (input) => call(
615
+ "POST",
616
+ "/v1/me/offline/keys/revoke",
617
+ RevokeDeviceKeyInputSchema.parse(input),
618
+ () => void 0
619
+ ),
620
+ issueAccountOac: (input) => call(
621
+ "POST",
622
+ "/v1/me/offline/oac",
623
+ IssueAccountOacInputSchema.parse(input),
624
+ (raw) => OACRecordSchema.parse(raw)
625
+ ),
626
+ provisionAllowance: (input) => call(
627
+ "POST",
628
+ "/v1/me/offline/allowance",
629
+ ProvisionOfflineAllowanceInputSchema.parse(input),
630
+ (raw) => ProvisionOfflineAllowanceResultSchema.parse(raw)
631
+ ),
632
+ enable: (input) => call(
633
+ "POST",
634
+ "/v1/me/offline/enable",
635
+ EnableOfflineInputSchema.parse(input),
636
+ (raw) => EnableOfflineResultSchema.parse(raw)
637
+ ),
638
+ refresh: (input) => call(
639
+ "POST",
640
+ "/v1/me/offline/refresh",
641
+ IssueOACInputSchema.parse(input),
642
+ (raw) => OACRecordSchema.parse(raw)
643
+ ),
644
+ disable: (input) => call(
645
+ "POST",
646
+ "/v1/me/offline/disable",
647
+ DisableOfflineInputSchema.parse(input),
648
+ (raw) => DisableOfflineResultSchema.parse(raw)
649
+ ),
650
+ getStatus: (deviceId) => {
651
+ const qs = deviceId ? `?deviceId=${encodeURIComponent(deviceId)}` : "";
652
+ return call(
653
+ "GET",
654
+ `/v1/me/offline/status${qs}`,
655
+ void 0,
656
+ (raw) => OfflineStatusResultSchema.parse(raw)
657
+ );
658
+ },
659
+ getState: (deviceId) => {
660
+ const qs = deviceId ? `?deviceId=${encodeURIComponent(deviceId)}` : "";
661
+ return call(
662
+ "GET",
663
+ `/v1/me/offline/state${qs}`,
664
+ void 0,
665
+ (raw) => OfflineStateResultSchema.parse(raw)
666
+ );
667
+ },
668
+ submitClaim: (claim) => call(
669
+ "POST",
670
+ "/v1/me/offline/claims",
671
+ ConsumerPaymentClaimSchema.parse(claim),
672
+ (raw) => ConsumerSettleResultSchema.parse(raw)
673
+ )
674
+ };
675
+ }
676
+
677
+ // src/contracts.ts
678
+ var E164Regex = /^\+[1-9]\d{7,14}$/;
679
+ var UuidSchema = import_zod2.z.string().uuid();
680
+ var IsoDateSchema = import_zod2.z.string().datetime({ offset: true });
681
+ var CurrencySchema = import_zod2.z.string().trim().length(3).transform((value) => value.toUpperCase());
682
+ var HealthResponseSchema = import_zod2.z.object({
683
+ ok: import_zod2.z.boolean()
684
+ });
685
+ var WelcomeResponseSchema = import_zod2.z.object({
686
+ message: import_zod2.z.string()
687
+ });
688
+ var OnboardingStartRequestSchema = import_zod2.z.object({
689
+ phoneE164: import_zod2.z.string().regex(E164Regex),
690
+ appInstanceId: import_zod2.z.string().min(3),
691
+ platform: import_zod2.z.enum(["android", "ios", "web"]),
692
+ turnstileToken: import_zod2.z.string().min(20).optional(),
693
+ appAttestation: import_zod2.z.object({
694
+ provider: import_zod2.z.enum(["android", "ios", "web"]),
695
+ token: import_zod2.z.string().min(24)
696
+ }).optional(),
697
+ firstName: import_zod2.z.string().trim().min(1).max(80).optional(),
698
+ lastName: import_zod2.z.string().trim().min(1).max(80).optional()
699
+ });
700
+ var OnboardingStartResponseSchema = import_zod2.z.object({
701
+ requestId: import_zod2.z.string().min(1),
702
+ checkUrl: import_zod2.z.string().url().optional(),
703
+ expiresInSec: import_zod2.z.number().int().positive(),
704
+ fallback: import_zod2.z.enum(["SILENT_AUTH", "OTP"])
705
+ });
706
+ var OnboardingCompleteRequestSchema = import_zod2.z.object({
707
+ requestId: import_zod2.z.string().min(1),
708
+ code: import_zod2.z.string().min(1).max(32),
709
+ appInstanceId: import_zod2.z.string().min(3),
710
+ fingerprintHash: import_zod2.z.string().min(3).optional()
711
+ });
712
+ var OnboardingCompleteResponseSchema = import_zod2.z.object({
713
+ sessionToken: import_zod2.z.string().min(1),
714
+ userId: UuidSchema,
715
+ restricted: import_zod2.z.boolean(),
716
+ risk_reasons: import_zod2.z.array(
717
+ import_zod2.z.enum(["SIM_SWAP_RECENT", "ROAMING", "CARRIER_CHANGED"])
718
+ ),
719
+ stepUpRequired: import_zod2.z.boolean().optional(),
720
+ riskStatus: import_zod2.z.enum(["ok", "unavailable"]).optional()
721
+ });
722
+ var RegisterDeviceRequestSchema = import_zod2.z.object({
723
+ userId: UuidSchema,
724
+ appInstanceId: import_zod2.z.string().min(3),
725
+ platform: import_zod2.z.string().min(2),
726
+ model: import_zod2.z.string().optional(),
727
+ networkSignals: import_zod2.z.object({
728
+ ip: import_zod2.z.string().min(3),
729
+ asn: import_zod2.z.number().int().optional(),
730
+ country: import_zod2.z.string().min(2).optional(),
731
+ carrier: import_zod2.z.string().optional()
732
+ })
733
+ });
734
+ var RegisterDeviceResponseSchema = import_zod2.z.object({
735
+ deviceId: import_zod2.z.string().min(1),
736
+ fingerprintHash: import_zod2.z.string().min(1),
737
+ driftScore: import_zod2.z.number(),
738
+ trustState: import_zod2.z.enum(["TRUSTED_PRIMARY", "TRUSTED_SECONDARY", "UNVERIFIED"]),
739
+ stepUpRequired: import_zod2.z.boolean()
740
+ });
741
+ var AuthRefreshRequestSchema = import_zod2.z.object({
742
+ userId: UuidSchema,
743
+ refreshToken: import_zod2.z.string().min(8),
744
+ appInstanceId: import_zod2.z.string().min(3),
745
+ fingerprintHash: import_zod2.z.string().min(3)
746
+ });
747
+ var AuthRefreshResponseSchema = import_zod2.z.object({
748
+ refreshToken: import_zod2.z.string().min(8),
749
+ stepUpRequired: import_zod2.z.boolean()
750
+ });
751
+ var AuthLogoutRequestSchema = import_zod2.z.object({
752
+ userId: UuidSchema,
753
+ refreshToken: import_zod2.z.string().min(8)
754
+ });
755
+ var PinSetRequestSchema = import_zod2.z.object({
756
+ userId: UuidSchema,
757
+ pin: import_zod2.z.string().regex(/^\d{6}$/)
758
+ });
759
+ var PinVerifyRequestSchema = import_zod2.z.object({
760
+ userId: UuidSchema,
761
+ pin: import_zod2.z.string().regex(/^\d{6}$/)
762
+ });
763
+ var OkResponseSchema = import_zod2.z.object({
764
+ ok: import_zod2.z.boolean()
765
+ });
766
+ var RegisterSendDeviceKeyRequestSchema = import_zod2.z.object({
767
+ userId: UuidSchema,
768
+ deviceId: import_zod2.z.string().min(3),
769
+ publicKey: import_zod2.z.string().min(32)
770
+ });
771
+ var SEND_AUTH_PURPOSES = ["send_money", "offline_revoke"];
772
+ var SendChallengeRequestSchema = import_zod2.z.object({
773
+ userId: UuidSchema,
774
+ deviceId: import_zod2.z.string().min(3),
775
+ purpose: import_zod2.z.enum(SEND_AUTH_PURPOSES).optional()
776
+ });
777
+ var SendChallengeResponseSchema = import_zod2.z.object({
778
+ challengeId: UuidSchema,
779
+ nonce: import_zod2.z.string().min(1),
780
+ expiresAt: IsoDateSchema
781
+ });
782
+ var SendVerifyRequestSchema = import_zod2.z.object({
783
+ userId: UuidSchema,
784
+ deviceId: import_zod2.z.string().min(3),
785
+ challengeId: UuidSchema,
786
+ signature: import_zod2.z.string().min(16)
787
+ });
788
+ var SendVerifyResponseSchema = import_zod2.z.object({
789
+ sendAuthToken: import_zod2.z.string().min(16)
790
+ });
791
+ var ResolveRecipientRequestSchema = import_zod2.z.object({
792
+ identifier: import_zod2.z.string().min(3)
793
+ });
794
+ var ResolveRecipientResponseSchema = import_zod2.z.object({
795
+ recipientUserId: UuidSchema,
796
+ displayName: import_zod2.z.string().min(1),
797
+ normalizedIdentifier: import_zod2.z.string().regex(E164Regex),
798
+ isActive: import_zod2.z.boolean()
799
+ });
800
+ var CreateTransferRequestSchema = import_zod2.z.object({
801
+ recipientIdentifier: import_zod2.z.string().min(3),
802
+ amountMinor: import_zod2.z.number().int().positive(),
803
+ currency: CurrencySchema,
804
+ sendAuthToken: import_zod2.z.string().min(16)
805
+ });
806
+ var TransferStatusSchema = import_zod2.z.enum(["SETTLED", "PENDING_REVIEW", "DECLINED"]);
807
+ var TransferResponseSchema = import_zod2.z.object({
808
+ transactionId: import_zod2.z.string().min(1),
809
+ status: TransferStatusSchema,
810
+ userStatus: TransferStatusSchema,
811
+ recipientName: import_zod2.z.string().min(1),
812
+ timestamp: IsoDateSchema,
813
+ /**
814
+ * Fresh issuer-signed OACs returned by the backend's post-commit
815
+ * rotation hook on `SETTLED` transfers.
816
+ *
817
+ * In the current backend implementation this hook rotates LEGACY
818
+ * hold-backed OACs only. Account-funded (no-hold) OACs introduced by
819
+ * the unified-pay-rails refactor are NOT rotated here — their
820
+ * cumulative spend counter and main-balance check are enforced at
821
+ * claim submission time via `createTransfer` under the per-sender
822
+ * advisory lock, so a stale no-hold OAC cannot authorise overspending
823
+ * (it can only resolve to REVIEW on submission).
824
+ *
825
+ * Optional: omitted when the sender has no registered hold-backed
826
+ * devices, when the refresh failed (best-effort), or on retry replays
827
+ * that pre-date the refresh. When present, the entries supersede any
828
+ * locally cached OACs for the listed devices; when absent, clients
829
+ * should fall back to `/v1/me/offline/refresh`.
830
+ *
831
+ * Each entry is validated against the canonical `OACRecordSchema`,
832
+ * so consumers can trust the runtime shape matches the static type.
833
+ */
834
+ offlineOacs: OACRecordSchema.array().optional()
835
+ });
836
+ var DirectionSchema = import_zod2.z.enum(["OUTGOING", "INCOMING"]);
837
+ var AccountActivityItemSchema = import_zod2.z.object({
838
+ id: import_zod2.z.string().min(1),
839
+ type: import_zod2.z.string().min(1),
840
+ direction: DirectionSchema,
841
+ name: import_zod2.z.string().min(1),
842
+ identifier: import_zod2.z.string().min(1),
843
+ amountMinor: import_zod2.z.number().int(),
844
+ currency: CurrencySchema,
845
+ status: import_zod2.z.string().min(1),
846
+ timestamp: IsoDateSchema
847
+ });
848
+ var AccountSummaryResponseSchema = import_zod2.z.object({
849
+ /** Authenticated user's stable internal id. */
850
+ userId: UuidSchema,
851
+ /**
852
+ * 10-digit Nigeria Uniform Bank Account Number (NUBAN) allocated by the
853
+ * bank partner. `null` when the user has no partner-allocated account yet.
854
+ */
855
+ nuban: import_zod2.z.string().regex(/^[0-9]{10}$/).nullable(),
856
+ balance: import_zod2.z.number().int(),
857
+ currency: CurrencySchema,
858
+ dailySendLimit: import_zod2.z.number().int().nonnegative(),
859
+ dailySendRemaining: import_zod2.z.number().int().nonnegative(),
860
+ kycTier: import_zod2.z.string().min(1),
861
+ kycStatus: import_zod2.z.string().min(1),
862
+ recentActivity: import_zod2.z.array(AccountActivityItemSchema)
863
+ });
864
+ var TransactionsListResponseSchema = import_zod2.z.object({
865
+ items: import_zod2.z.array(AccountActivityItemSchema),
866
+ nextCursor: import_zod2.z.string().nullable()
867
+ });
868
+ var TransactionDetailResponseSchema = import_zod2.z.object({
869
+ transactionId: import_zod2.z.string().min(1),
870
+ type: import_zod2.z.string().min(1),
871
+ direction: DirectionSchema,
872
+ counterpartyName: import_zod2.z.string().min(1),
873
+ counterpartyIdentifier: import_zod2.z.string().min(1),
874
+ amountMinor: import_zod2.z.number().int(),
875
+ currency: CurrencySchema,
876
+ status: import_zod2.z.string().min(1),
877
+ timestamp: IsoDateSchema
878
+ });
879
+ var PushRegisterRequestSchema = import_zod2.z.object({
880
+ deviceId: import_zod2.z.string().min(3),
881
+ platform: import_zod2.z.enum(["ios", "android", "web"]),
882
+ token: import_zod2.z.string().min(16)
883
+ });
884
+ var CreatePayLinkResponseSchema = import_zod2.z.object({
885
+ token: import_zod2.z.string().min(1)
886
+ });
887
+ var ResolvePayLinkResponseSchema = import_zod2.z.object({
888
+ recipientUserId: UuidSchema,
889
+ displayName: import_zod2.z.string().min(1),
890
+ normalizedIdentifier: import_zod2.z.string().regex(E164Regex),
891
+ isActive: import_zod2.z.boolean()
892
+ });
893
+
536
894
  // src/primitives.ts
537
- var import_zod2 = require("zod");
538
- var CurrencyCodeSchema = import_zod2.z.string().trim().length(3).transform((value) => value.toUpperCase());
895
+ var import_zod3 = require("zod");
896
+ var CurrencyCodeSchema = import_zod3.z.string().trim().length(3).transform((value) => value.toUpperCase());
539
897
  var currencyFractionDigits = {
540
898
  NGN: 2,
541
899
  USD: 2,
@@ -629,7 +987,7 @@ function moneyMinorToNumber(amountMinor) {
629
987
  }
630
988
 
631
989
  // src/collections/client.ts
632
- var import_zod3 = require("zod");
990
+ var import_zod4 = require("zod");
633
991
  var MERCHANT_PROFILE_STATUSES = [
634
992
  "pending",
635
993
  "active",
@@ -659,172 +1017,172 @@ var MERCHANT_PAYOUT_STATUSES = [
659
1017
  "failed",
660
1018
  "cancelled"
661
1019
  ];
662
- var MoneyKoboSchema = import_zod3.z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
663
- var MetadataSchema = import_zod3.z.record(
664
- import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number(), import_zod3.z.boolean(), import_zod3.z.null()])
1020
+ var MoneyKoboSchema = import_zod4.z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
1021
+ var MetadataSchema = import_zod4.z.record(
1022
+ import_zod4.z.union([import_zod4.z.string(), import_zod4.z.number(), import_zod4.z.boolean(), import_zod4.z.null()])
665
1023
  );
666
- var CurrencySchema2 = import_zod3.z.string().trim().length(3).transform((value) => value.toUpperCase());
667
- var ReferenceSchema = import_zod3.z.string().trim().min(6).max(128).regex(/^[A-Za-z0-9._:-]+$/);
668
- var MerchantProfileSchema = import_zod3.z.object({
669
- accountId: import_zod3.z.string().uuid(),
670
- legalName: import_zod3.z.string(),
671
- tradingName: import_zod3.z.string(),
672
- merchantCategoryCode: import_zod3.z.string().regex(/^\d{4}$/),
673
- nqrMerchantId: import_zod3.z.string(),
674
- settlementBankCode: import_zod3.z.string(),
675
- settlementAccountNumber: import_zod3.z.string(),
676
- settlementAccountName: import_zod3.z.string(),
677
- settlementSchedule: import_zod3.z.enum(SETTLEMENT_SCHEDULES),
678
- status: import_zod3.z.enum(MERCHANT_PROFILE_STATUSES),
679
- offlineEnabled: import_zod3.z.boolean(),
1024
+ var CurrencySchema2 = import_zod4.z.string().trim().length(3).transform((value) => value.toUpperCase());
1025
+ var ReferenceSchema = import_zod4.z.string().trim().min(6).max(128).regex(/^[A-Za-z0-9._:-]+$/);
1026
+ var MerchantProfileSchema = import_zod4.z.object({
1027
+ accountId: import_zod4.z.string().uuid(),
1028
+ legalName: import_zod4.z.string(),
1029
+ tradingName: import_zod4.z.string(),
1030
+ merchantCategoryCode: import_zod4.z.string().regex(/^\d{4}$/),
1031
+ nqrMerchantId: import_zod4.z.string(),
1032
+ settlementBankCode: import_zod4.z.string(),
1033
+ settlementAccountNumber: import_zod4.z.string(),
1034
+ settlementAccountName: import_zod4.z.string(),
1035
+ settlementSchedule: import_zod4.z.enum(SETTLEMENT_SCHEDULES),
1036
+ status: import_zod4.z.enum(MERCHANT_PROFILE_STATUSES),
1037
+ offlineEnabled: import_zod4.z.boolean(),
680
1038
  perTxLimitKobo: MoneyKoboSchema,
681
1039
  dailyLimitKobo: MoneyKoboSchema,
682
1040
  metadata: MetadataSchema,
683
- createdAtMs: import_zod3.z.number().int().nonnegative(),
684
- updatedAtMs: import_zod3.z.number().int().nonnegative()
1041
+ createdAtMs: import_zod4.z.number().int().nonnegative(),
1042
+ updatedAtMs: import_zod4.z.number().int().nonnegative()
685
1043
  });
686
- var UpsertMerchantProfileInputSchema = import_zod3.z.object({
687
- legalName: import_zod3.z.string().trim().min(1).max(200),
688
- tradingName: import_zod3.z.string().trim().min(1).max(25),
689
- merchantCategoryCode: import_zod3.z.string().trim().regex(/^\d{4}$/),
690
- nqrMerchantId: import_zod3.z.string().trim().min(3).max(64),
691
- settlementBankCode: import_zod3.z.string().trim().min(2).max(16),
692
- settlementAccountNumber: import_zod3.z.string().trim().min(5).max(32),
693
- settlementAccountName: import_zod3.z.string().trim().min(1).max(200),
694
- settlementSchedule: import_zod3.z.enum(SETTLEMENT_SCHEDULES).optional(),
695
- status: import_zod3.z.enum(MERCHANT_PROFILE_STATUSES).optional(),
696
- offlineEnabled: import_zod3.z.boolean().optional(),
1044
+ var UpsertMerchantProfileInputSchema = import_zod4.z.object({
1045
+ legalName: import_zod4.z.string().trim().min(1).max(200),
1046
+ tradingName: import_zod4.z.string().trim().min(1).max(25),
1047
+ merchantCategoryCode: import_zod4.z.string().trim().regex(/^\d{4}$/),
1048
+ nqrMerchantId: import_zod4.z.string().trim().min(3).max(64),
1049
+ settlementBankCode: import_zod4.z.string().trim().min(2).max(16),
1050
+ settlementAccountNumber: import_zod4.z.string().trim().min(5).max(32),
1051
+ settlementAccountName: import_zod4.z.string().trim().min(1).max(200),
1052
+ settlementSchedule: import_zod4.z.enum(SETTLEMENT_SCHEDULES).optional(),
1053
+ status: import_zod4.z.enum(MERCHANT_PROFILE_STATUSES).optional(),
1054
+ offlineEnabled: import_zod4.z.boolean().optional(),
697
1055
  perTxLimitKobo: MoneyKoboSchema.optional(),
698
1056
  dailyLimitKobo: MoneyKoboSchema.optional(),
699
1057
  metadata: MetadataSchema.optional()
700
1058
  });
701
- var CollectionIntentSchema = import_zod3.z.object({
702
- intentId: import_zod3.z.string().uuid(),
703
- accountId: import_zod3.z.string().uuid(),
704
- terminalId: import_zod3.z.string().uuid().nullable(),
705
- reference: import_zod3.z.string(),
706
- amountKobo: import_zod3.z.number().int().positive().nullable(),
707
- currency: import_zod3.z.string().length(3),
708
- status: import_zod3.z.enum(COLLECTION_INTENT_STATUSES),
709
- description: import_zod3.z.string().nullable(),
710
- nqrPayload: import_zod3.z.string(),
711
- provider: import_zod3.z.string(),
712
- providerReference: import_zod3.z.string().nullable(),
1059
+ var CollectionIntentSchema = import_zod4.z.object({
1060
+ intentId: import_zod4.z.string().uuid(),
1061
+ accountId: import_zod4.z.string().uuid(),
1062
+ terminalId: import_zod4.z.string().uuid().nullable(),
1063
+ reference: import_zod4.z.string(),
1064
+ amountKobo: import_zod4.z.number().int().positive().nullable(),
1065
+ currency: import_zod4.z.string().length(3),
1066
+ status: import_zod4.z.enum(COLLECTION_INTENT_STATUSES),
1067
+ description: import_zod4.z.string().nullable(),
1068
+ nqrPayload: import_zod4.z.string(),
1069
+ provider: import_zod4.z.string(),
1070
+ providerReference: import_zod4.z.string().nullable(),
713
1071
  metadata: MetadataSchema,
714
- expiresAtMs: import_zod3.z.number().int().nonnegative().nullable(),
715
- paidAtMs: import_zod3.z.number().int().nonnegative().nullable(),
716
- createdAtMs: import_zod3.z.number().int().nonnegative(),
717
- updatedAtMs: import_zod3.z.number().int().nonnegative()
1072
+ expiresAtMs: import_zod4.z.number().int().nonnegative().nullable(),
1073
+ paidAtMs: import_zod4.z.number().int().nonnegative().nullable(),
1074
+ createdAtMs: import_zod4.z.number().int().nonnegative(),
1075
+ updatedAtMs: import_zod4.z.number().int().nonnegative()
718
1076
  });
719
- var CreateCollectionIntentInputSchema = import_zod3.z.object({
1077
+ var CreateCollectionIntentInputSchema = import_zod4.z.object({
720
1078
  reference: ReferenceSchema.optional(),
721
1079
  amountKobo: MoneyKoboSchema.optional(),
722
1080
  currency: CurrencySchema2.optional(),
723
- terminalId: import_zod3.z.string().uuid().optional(),
724
- terminalLabel: import_zod3.z.string().trim().min(1).max(25).optional(),
725
- merchantCity: import_zod3.z.string().trim().min(1).max(15).optional(),
726
- description: import_zod3.z.string().trim().min(1).max(280).optional(),
727
- expiresAtMs: import_zod3.z.number().int().positive().optional(),
728
- provider: import_zod3.z.string().trim().min(1).max(40).optional(),
1081
+ terminalId: import_zod4.z.string().uuid().optional(),
1082
+ terminalLabel: import_zod4.z.string().trim().min(1).max(25).optional(),
1083
+ merchantCity: import_zod4.z.string().trim().min(1).max(15).optional(),
1084
+ description: import_zod4.z.string().trim().min(1).max(280).optional(),
1085
+ expiresAtMs: import_zod4.z.number().int().positive().optional(),
1086
+ provider: import_zod4.z.string().trim().min(1).max(40).optional(),
729
1087
  metadata: MetadataSchema.optional()
730
1088
  });
731
- var PublicCollectionIntentSchema = import_zod3.z.object({
732
- intentId: import_zod3.z.string().uuid(),
733
- reference: import_zod3.z.string(),
734
- amountKobo: import_zod3.z.number().int().positive().nullable(),
735
- currency: import_zod3.z.string().length(3),
736
- status: import_zod3.z.enum(COLLECTION_INTENT_STATUSES),
737
- merchantAccountId: import_zod3.z.string().uuid(),
738
- merchantName: import_zod3.z.string(),
739
- merchantCategoryCode: import_zod3.z.string(),
740
- description: import_zod3.z.string().nullable(),
741
- expiresAtMs: import_zod3.z.number().int().nonnegative().nullable()
1089
+ var PublicCollectionIntentSchema = import_zod4.z.object({
1090
+ intentId: import_zod4.z.string().uuid(),
1091
+ reference: import_zod4.z.string(),
1092
+ amountKobo: import_zod4.z.number().int().positive().nullable(),
1093
+ currency: import_zod4.z.string().length(3),
1094
+ status: import_zod4.z.enum(COLLECTION_INTENT_STATUSES),
1095
+ merchantAccountId: import_zod4.z.string().uuid(),
1096
+ merchantName: import_zod4.z.string(),
1097
+ merchantCategoryCode: import_zod4.z.string(),
1098
+ description: import_zod4.z.string().nullable(),
1099
+ expiresAtMs: import_zod4.z.number().int().nonnegative().nullable()
742
1100
  });
743
- var PayCollectionInputSchema = import_zod3.z.object({
1101
+ var PayCollectionInputSchema = import_zod4.z.object({
744
1102
  reference: ReferenceSchema,
745
1103
  amountKobo: MoneyKoboSchema.optional(),
746
1104
  currency: CurrencySchema2.optional(),
747
- idempotencyKey: import_zod3.z.string().trim().min(8).max(160).optional()
1105
+ idempotencyKey: import_zod4.z.string().trim().min(8).max(160).optional()
748
1106
  });
749
- var CollectionPaymentSchema = import_zod3.z.object({
750
- paymentId: import_zod3.z.string().uuid(),
751
- intentId: import_zod3.z.string().uuid(),
752
- accountId: import_zod3.z.string().uuid(),
753
- payerUserId: import_zod3.z.string().uuid().nullable(),
754
- merchantOwnerUserId: import_zod3.z.string().uuid(),
1107
+ var CollectionPaymentSchema = import_zod4.z.object({
1108
+ paymentId: import_zod4.z.string().uuid(),
1109
+ intentId: import_zod4.z.string().uuid(),
1110
+ accountId: import_zod4.z.string().uuid(),
1111
+ payerUserId: import_zod4.z.string().uuid().nullable(),
1112
+ merchantOwnerUserId: import_zod4.z.string().uuid(),
755
1113
  amountKobo: MoneyKoboSchema,
756
- currency: import_zod3.z.string().length(3),
757
- status: import_zod3.z.enum(COLLECTION_PAYMENT_STATUSES),
758
- provider: import_zod3.z.string(),
759
- providerReference: import_zod3.z.string().nullable(),
760
- idempotencyKey: import_zod3.z.string().nullable(),
761
- ledgerRef: import_zod3.z.string(),
762
- failureCode: import_zod3.z.string().nullable(),
763
- failureMessage: import_zod3.z.string().nullable(),
764
- paidAtMs: import_zod3.z.number().int().nonnegative().nullable(),
765
- createdAtMs: import_zod3.z.number().int().nonnegative(),
766
- updatedAtMs: import_zod3.z.number().int().nonnegative()
1114
+ currency: import_zod4.z.string().length(3),
1115
+ status: import_zod4.z.enum(COLLECTION_PAYMENT_STATUSES),
1116
+ provider: import_zod4.z.string(),
1117
+ providerReference: import_zod4.z.string().nullable(),
1118
+ idempotencyKey: import_zod4.z.string().nullable(),
1119
+ ledgerRef: import_zod4.z.string(),
1120
+ failureCode: import_zod4.z.string().nullable(),
1121
+ failureMessage: import_zod4.z.string().nullable(),
1122
+ paidAtMs: import_zod4.z.number().int().nonnegative().nullable(),
1123
+ createdAtMs: import_zod4.z.number().int().nonnegative(),
1124
+ updatedAtMs: import_zod4.z.number().int().nonnegative()
767
1125
  });
768
- var CollectionPaymentResultSchema = import_zod3.z.object({
1126
+ var CollectionPaymentResultSchema = import_zod4.z.object({
769
1127
  payment: CollectionPaymentSchema,
770
1128
  intent: CollectionIntentSchema,
771
- receipt: import_zod3.z.unknown().optional(),
772
- replayed: import_zod3.z.boolean()
1129
+ receipt: import_zod4.z.unknown().optional(),
1130
+ replayed: import_zod4.z.boolean()
773
1131
  });
774
- var CollectionReportSummarySchema = import_zod3.z.object({
775
- accountId: import_zod3.z.string().uuid(),
776
- fromMs: import_zod3.z.number().int().nonnegative(),
777
- toMs: import_zod3.z.number().int().nonnegative(),
778
- currency: import_zod3.z.string().length(3),
779
- paidCount: import_zod3.z.number().int().nonnegative(),
780
- paidAmountKobo: import_zod3.z.number().int().nonnegative(),
781
- pendingCount: import_zod3.z.number().int().nonnegative(),
782
- failedCount: import_zod3.z.number().int().nonnegative(),
783
- reversedCount: import_zod3.z.number().int().nonnegative(),
784
- availableBalanceKobo: import_zod3.z.number().int().nonnegative()
1132
+ var CollectionReportSummarySchema = import_zod4.z.object({
1133
+ accountId: import_zod4.z.string().uuid(),
1134
+ fromMs: import_zod4.z.number().int().nonnegative(),
1135
+ toMs: import_zod4.z.number().int().nonnegative(),
1136
+ currency: import_zod4.z.string().length(3),
1137
+ paidCount: import_zod4.z.number().int().nonnegative(),
1138
+ paidAmountKobo: import_zod4.z.number().int().nonnegative(),
1139
+ pendingCount: import_zod4.z.number().int().nonnegative(),
1140
+ failedCount: import_zod4.z.number().int().nonnegative(),
1141
+ reversedCount: import_zod4.z.number().int().nonnegative(),
1142
+ availableBalanceKobo: import_zod4.z.number().int().nonnegative()
785
1143
  });
786
- var CollectionStatementSchema = import_zod3.z.object({
787
- accountId: import_zod3.z.string().uuid(),
788
- year: import_zod3.z.number().int(),
789
- month: import_zod3.z.number().int().min(1).max(12),
790
- currency: import_zod3.z.string().length(3),
791
- totalPaidKobo: import_zod3.z.number().int().nonnegative(),
792
- items: import_zod3.z.array(CollectionPaymentSchema)
1144
+ var CollectionStatementSchema = import_zod4.z.object({
1145
+ accountId: import_zod4.z.string().uuid(),
1146
+ year: import_zod4.z.number().int(),
1147
+ month: import_zod4.z.number().int().min(1).max(12),
1148
+ currency: import_zod4.z.string().length(3),
1149
+ totalPaidKobo: import_zod4.z.number().int().nonnegative(),
1150
+ items: import_zod4.z.array(CollectionPaymentSchema)
793
1151
  });
794
- var CreatePayoutInputSchema = import_zod3.z.object({
1152
+ var CreatePayoutInputSchema = import_zod4.z.object({
795
1153
  amountKobo: MoneyKoboSchema,
796
1154
  currency: CurrencySchema2.optional(),
797
- idempotencyKey: import_zod3.z.string().trim().min(8).max(160)
1155
+ idempotencyKey: import_zod4.z.string().trim().min(8).max(160)
798
1156
  });
799
- var MerchantPayoutSchema = import_zod3.z.object({
800
- payoutId: import_zod3.z.string().uuid(),
801
- accountId: import_zod3.z.string().uuid(),
1157
+ var MerchantPayoutSchema = import_zod4.z.object({
1158
+ payoutId: import_zod4.z.string().uuid(),
1159
+ accountId: import_zod4.z.string().uuid(),
802
1160
  amountKobo: MoneyKoboSchema,
803
- currency: import_zod3.z.string().length(3),
804
- status: import_zod3.z.enum(MERCHANT_PAYOUT_STATUSES),
805
- idempotencyKey: import_zod3.z.string().nullable(),
806
- ledgerRef: import_zod3.z.string(),
807
- providerReference: import_zod3.z.string().nullable(),
808
- requestedByUserId: import_zod3.z.string().uuid().nullable(),
809
- failureCode: import_zod3.z.string().nullable(),
810
- failureMessage: import_zod3.z.string().nullable(),
811
- createdAtMs: import_zod3.z.number().int().nonnegative(),
812
- updatedAtMs: import_zod3.z.number().int().nonnegative()
1161
+ currency: import_zod4.z.string().length(3),
1162
+ status: import_zod4.z.enum(MERCHANT_PAYOUT_STATUSES),
1163
+ idempotencyKey: import_zod4.z.string().nullable(),
1164
+ ledgerRef: import_zod4.z.string(),
1165
+ providerReference: import_zod4.z.string().nullable(),
1166
+ requestedByUserId: import_zod4.z.string().uuid().nullable(),
1167
+ failureCode: import_zod4.z.string().nullable(),
1168
+ failureMessage: import_zod4.z.string().nullable(),
1169
+ createdAtMs: import_zod4.z.number().int().nonnegative(),
1170
+ updatedAtMs: import_zod4.z.number().int().nonnegative()
813
1171
  });
814
- var ProviderEventInputSchema = import_zod3.z.object({
815
- provider: import_zod3.z.string().trim().min(1).max(80),
816
- eventId: import_zod3.z.string().trim().min(1).max(160),
817
- eventType: import_zod3.z.string().trim().min(1).max(120),
818
- payload: import_zod3.z.record(import_zod3.z.unknown()).optional()
1172
+ var ProviderEventInputSchema = import_zod4.z.object({
1173
+ provider: import_zod4.z.string().trim().min(1).max(80),
1174
+ eventId: import_zod4.z.string().trim().min(1).max(160),
1175
+ eventType: import_zod4.z.string().trim().min(1).max(120),
1176
+ payload: import_zod4.z.record(import_zod4.z.unknown()).optional()
819
1177
  });
820
- var ProviderEventRecordSchema = import_zod3.z.object({
821
- id: import_zod3.z.string().uuid(),
822
- provider: import_zod3.z.string(),
823
- eventId: import_zod3.z.string(),
824
- eventType: import_zod3.z.string(),
825
- signatureVerified: import_zod3.z.boolean(),
826
- receivedAtMs: import_zod3.z.number().int().nonnegative(),
827
- processedAtMs: import_zod3.z.number().int().nonnegative().nullable()
1178
+ var ProviderEventRecordSchema = import_zod4.z.object({
1179
+ id: import_zod4.z.string().uuid(),
1180
+ provider: import_zod4.z.string(),
1181
+ eventId: import_zod4.z.string(),
1182
+ eventType: import_zod4.z.string(),
1183
+ signatureVerified: import_zod4.z.boolean(),
1184
+ receivedAtMs: import_zod4.z.number().int().nonnegative(),
1185
+ processedAtMs: import_zod4.z.number().int().nonnegative().nullable()
828
1186
  });
829
1187
  function createCollectionsClient(opts) {
830
1188
  const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
@@ -1339,7 +1697,7 @@ var FlurClient = class {
1339
1697
  try {
1340
1698
  body = requestSchema ? JSON.stringify(requestSchema.parse(input)) : init2.body;
1341
1699
  } catch (err) {
1342
- if (err instanceof import_zod4.z.ZodError) {
1700
+ if (err instanceof import_zod5.z.ZodError) {
1343
1701
  throw new FlurError("Invalid request payload", "INVALID_REQUEST", {
1344
1702
  details: err.flatten()
1345
1703
  });
@@ -1367,7 +1725,7 @@ var FlurClient = class {
1367
1725
  try {
1368
1726
  return responseSchema.parse(payload);
1369
1727
  } catch (err) {
1370
- if (err instanceof import_zod4.z.ZodError) {
1728
+ if (err instanceof import_zod5.z.ZodError) {
1371
1729
  throw new FlurError(
1372
1730
  "SDK contract validation failed",
1373
1731
  "INVALID_REQUEST",
@@ -1798,7 +2156,7 @@ function constantTimeEqual(a, b) {
1798
2156
  }
1799
2157
 
1800
2158
  // src/offline/oac.ts
1801
- var import_zod5 = require("zod");
2159
+ var import_zod6 = require("zod");
1802
2160
 
1803
2161
  // src/crypto/p256-issuer.ts
1804
2162
  var import_nist = require("@noble/curves/nist");
@@ -1880,20 +2238,20 @@ function verifyIssuerP256(bytes, signatureB64, issuerPublicKeySpkiB64) {
1880
2238
  var OAC_DEFAULT_PER_TX_KOBO = 5e5;
1881
2239
  var OAC_DEFAULT_CUMULATIVE_KOBO = 2e6;
1882
2240
  var OAC_DEFAULT_VALIDITY_MS = 24 * 60 * 60 * 1e3;
1883
- var Base64Std = import_zod5.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (standard) string");
1884
- var OACSchema = import_zod5.z.object({
1885
- userId: import_zod5.z.string().min(1),
1886
- deviceId: import_zod5.z.string().min(1),
2241
+ var Base64Std2 = import_zod6.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (standard) string");
2242
+ var OACSchema = import_zod6.z.object({
2243
+ userId: import_zod6.z.string().min(1),
2244
+ deviceId: import_zod6.z.string().min(1),
1887
2245
  /** SubjectPublicKeyInfo DER, base64 (P-256). */
1888
- devicePublicKey: Base64Std,
1889
- perTxCapKobo: import_zod5.z.number().int().nonnegative(),
1890
- cumulativeCapKobo: import_zod5.z.number().int().nonnegative(),
1891
- validFromMs: import_zod5.z.number().int().nonnegative(),
1892
- validUntilMs: import_zod5.z.number().int().positive(),
1893
- counterSeed: import_zod5.z.number().int().nonnegative(),
1894
- nonce: import_zod5.z.string().min(1),
2246
+ devicePublicKey: Base64Std2,
2247
+ perTxCapKobo: import_zod6.z.number().int().nonnegative(),
2248
+ cumulativeCapKobo: import_zod6.z.number().int().nonnegative(),
2249
+ validFromMs: import_zod6.z.number().int().nonnegative(),
2250
+ validUntilMs: import_zod6.z.number().int().positive(),
2251
+ counterSeed: import_zod6.z.number().int().nonnegative(),
2252
+ nonce: import_zod6.z.string().min(1),
1895
2253
  /** ASN.1 DER ECDSA(SHA-256) signature, base64. */
1896
- issuerSig: Base64Std
2254
+ issuerSig: Base64Std2
1897
2255
  }).refine((v) => v.validUntilMs > v.validFromMs, {
1898
2256
  message: "validUntilMs must be greater than validFromMs"
1899
2257
  }).refine((v) => v.perTxCapKobo <= v.cumulativeCapKobo, {
@@ -1987,19 +2345,19 @@ function decodeBase45(s) {
1987
2345
  }
1988
2346
 
1989
2347
  // src/offline/messages.ts
1990
- var import_zod6 = require("zod");
1991
- var Base64Sig = import_zod6.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (standard) signature");
1992
- var OfflinePaymentRequestSchema = import_zod6.z.object({
1993
- reference: import_zod6.z.string().min(1),
1994
- amountKobo: import_zod6.z.number().int().positive(),
2348
+ var import_zod7 = require("zod");
2349
+ var Base64Sig = import_zod7.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (standard) signature");
2350
+ var OfflinePaymentRequestSchema = import_zod7.z.object({
2351
+ reference: import_zod7.z.string().min(1),
2352
+ amountKobo: import_zod7.z.number().int().positive(),
1995
2353
  merchantOAC: OACSchema,
1996
- expiresAtMs: import_zod6.z.number().int().positive(),
2354
+ expiresAtMs: import_zod7.z.number().int().positive(),
1997
2355
  merchantSig: Base64Sig
1998
2356
  });
1999
- var OfflinePaymentAuthorizationSchema = import_zod6.z.object({
2357
+ var OfflinePaymentAuthorizationSchema = import_zod7.z.object({
2000
2358
  request: OfflinePaymentRequestSchema,
2001
2359
  payerOAC: OACSchema,
2002
- payerCounter: import_zod6.z.number().int().positive(),
2360
+ payerCounter: import_zod7.z.number().int().positive(),
2003
2361
  payerSig: Base64Sig
2004
2362
  });
2005
2363
  function buildPaymentRequest(input) {
@@ -2111,60 +2469,60 @@ function decodeAuthorizationQR(s) {
2111
2469
  }
2112
2470
 
2113
2471
  // src/offline/settlements.ts
2114
- var import_zod7 = require("zod");
2472
+ var import_zod8 = require("zod");
2115
2473
  var import_sha256 = require("@noble/hashes/sha256");
2116
2474
  var import_utils = require("@noble/hashes/utils");
2117
- var OfflineTokenSchema = import_zod7.z.object({
2118
- tokenId: import_zod7.z.string().uuid(),
2119
- tokenSerial: import_zod7.z.string(),
2120
- issuerAccountId: import_zod7.z.string().uuid(),
2121
- payerUserId: import_zod7.z.string().uuid(),
2122
- maxAmountKobo: import_zod7.z.number().int().positive(),
2123
- currency: import_zod7.z.string().length(3),
2124
- issuedAtMs: import_zod7.z.number().int().nonnegative(),
2125
- expiresAtMs: import_zod7.z.number().int().nonnegative(),
2126
- issuerSig: import_zod7.z.string()
2475
+ var OfflineTokenSchema = import_zod8.z.object({
2476
+ tokenId: import_zod8.z.string().uuid(),
2477
+ tokenSerial: import_zod8.z.string(),
2478
+ issuerAccountId: import_zod8.z.string().uuid(),
2479
+ payerUserId: import_zod8.z.string().uuid(),
2480
+ maxAmountKobo: import_zod8.z.number().int().positive(),
2481
+ currency: import_zod8.z.string().length(3),
2482
+ issuedAtMs: import_zod8.z.number().int().nonnegative(),
2483
+ expiresAtMs: import_zod8.z.number().int().nonnegative(),
2484
+ issuerSig: import_zod8.z.string()
2127
2485
  });
2128
- var PaymentClaimSchema = import_zod7.z.object({
2129
- encounterId: import_zod7.z.string().regex(/^[0-9a-f]{64}$/i).optional(),
2130
- tokenSerial: import_zod7.z.string(),
2131
- payerUserId: import_zod7.z.string().uuid(),
2132
- payeeUserId: import_zod7.z.string().uuid(),
2133
- payerNonce: import_zod7.z.string(),
2134
- payeeNonce: import_zod7.z.string(),
2135
- amountKobo: import_zod7.z.number().int().positive(),
2136
- currency: import_zod7.z.string().length(3).default("NGN"),
2137
- occurredAtMs: import_zod7.z.number().int().nonnegative(),
2138
- completedAtMs: import_zod7.z.number().int().nonnegative().optional(),
2139
- contextId: import_zod7.z.string().optional(),
2486
+ var PaymentClaimSchema = import_zod8.z.object({
2487
+ encounterId: import_zod8.z.string().regex(/^[0-9a-f]{64}$/i).optional(),
2488
+ tokenSerial: import_zod8.z.string(),
2489
+ payerUserId: import_zod8.z.string().uuid(),
2490
+ payeeUserId: import_zod8.z.string().uuid(),
2491
+ payerNonce: import_zod8.z.string(),
2492
+ payeeNonce: import_zod8.z.string(),
2493
+ amountKobo: import_zod8.z.number().int().positive(),
2494
+ currency: import_zod8.z.string().length(3).default("NGN"),
2495
+ occurredAtMs: import_zod8.z.number().int().nonnegative(),
2496
+ completedAtMs: import_zod8.z.number().int().nonnegative().optional(),
2497
+ contextId: import_zod8.z.string().optional(),
2140
2498
  // Stage 2c: P-256 device keys are now SubjectPublicKeyInfo DER, base64.
2141
2499
  // Signatures are ASN.1 DER ECDSA(SHA-256), base64. Backwards-incompatible
2142
2500
  // wire change; the backend has the matching widening in offline-settlements
2143
2501
  // service + zod schema.
2144
- payerPubkey: import_zod7.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
2145
- payerSignature: import_zod7.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
2146
- payeePubkey: import_zod7.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/).optional(),
2147
- payeeSignature: import_zod7.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/).optional()
2502
+ payerPubkey: import_zod8.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
2503
+ payerSignature: import_zod8.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
2504
+ payeePubkey: import_zod8.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/).optional(),
2505
+ payeeSignature: import_zod8.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/).optional()
2148
2506
  });
2149
- var SettlementSchema = import_zod7.z.object({
2150
- settlementId: import_zod7.z.string().uuid(),
2151
- settlementKey: import_zod7.z.string().regex(/^[0-9a-f]{64}$/i),
2152
- encounterId: import_zod7.z.string().regex(/^[0-9a-f]{64}$/i),
2153
- issuerAccountId: import_zod7.z.string().uuid(),
2154
- tokenSerial: import_zod7.z.string(),
2155
- payerUserId: import_zod7.z.string().uuid(),
2156
- payeeUserId: import_zod7.z.string().uuid(),
2157
- amountKobo: import_zod7.z.number().int().nonnegative(),
2158
- currency: import_zod7.z.string().length(3),
2159
- receiptId: import_zod7.z.string().nullable(),
2160
- status: import_zod7.z.enum(["SETTLED", "REVIEW", "REJECTED"]),
2161
- issuerSig: import_zod7.z.string(),
2162
- createdAtMs: import_zod7.z.number().int().nonnegative()
2507
+ var SettlementSchema = import_zod8.z.object({
2508
+ settlementId: import_zod8.z.string().uuid(),
2509
+ settlementKey: import_zod8.z.string().regex(/^[0-9a-f]{64}$/i),
2510
+ encounterId: import_zod8.z.string().regex(/^[0-9a-f]{64}$/i),
2511
+ issuerAccountId: import_zod8.z.string().uuid(),
2512
+ tokenSerial: import_zod8.z.string(),
2513
+ payerUserId: import_zod8.z.string().uuid(),
2514
+ payeeUserId: import_zod8.z.string().uuid(),
2515
+ amountKobo: import_zod8.z.number().int().nonnegative(),
2516
+ currency: import_zod8.z.string().length(3),
2517
+ receiptId: import_zod8.z.string().nullable(),
2518
+ status: import_zod8.z.enum(["SETTLED", "REVIEW", "REJECTED"]),
2519
+ issuerSig: import_zod8.z.string(),
2520
+ createdAtMs: import_zod8.z.number().int().nonnegative()
2163
2521
  });
2164
- var SettleResponseSchema = import_zod7.z.object({
2522
+ var SettleResponseSchema = import_zod8.z.object({
2165
2523
  settlement: SettlementSchema,
2166
- encounterId: import_zod7.z.string().regex(/^[0-9a-f]{64}$/i),
2167
- replayed: import_zod7.z.boolean()
2524
+ encounterId: import_zod8.z.string().regex(/^[0-9a-f]{64}$/i),
2525
+ replayed: import_zod8.z.boolean()
2168
2526
  });
2169
2527
  var ENCOUNTER_DOMAIN = "offline:v1:encounter";
2170
2528
  async function sha256Hex(input) {
@@ -2338,7 +2696,7 @@ function createHmacFetch(opts) {
2338
2696
  }
2339
2697
 
2340
2698
  // src/partner/client.ts
2341
- var import_zod8 = require("zod");
2699
+ var import_zod9 = require("zod");
2342
2700
  var import_sha2563 = require("@noble/hashes/sha256");
2343
2701
  var import_hmac4 = require("@noble/hashes/hmac");
2344
2702
  var import_utils2 = require("@noble/hashes/utils");
@@ -2362,18 +2720,18 @@ var PARTNER_SCOPES = [
2362
2720
  "partner:payout:write",
2363
2721
  "partner:reconciliation:read"
2364
2722
  ];
2365
- var ApiCredentialPublicSchema = import_zod8.z.object({
2366
- id: import_zod8.z.string().uuid(),
2367
- accountId: import_zod8.z.string().uuid(),
2368
- keyId: import_zod8.z.string(),
2369
- scopes: import_zod8.z.array(import_zod8.z.enum(PARTNER_SCOPES)),
2370
- label: import_zod8.z.string().nullable(),
2371
- createdAtMs: import_zod8.z.number().int().nonnegative(),
2372
- lastUsedAtMs: import_zod8.z.number().int().nonnegative().nullable(),
2373
- revokedAtMs: import_zod8.z.number().int().nonnegative().nullable()
2723
+ var ApiCredentialPublicSchema = import_zod9.z.object({
2724
+ id: import_zod9.z.string().uuid(),
2725
+ accountId: import_zod9.z.string().uuid(),
2726
+ keyId: import_zod9.z.string(),
2727
+ scopes: import_zod9.z.array(import_zod9.z.enum(PARTNER_SCOPES)),
2728
+ label: import_zod9.z.string().nullable(),
2729
+ createdAtMs: import_zod9.z.number().int().nonnegative(),
2730
+ lastUsedAtMs: import_zod9.z.number().int().nonnegative().nullable(),
2731
+ revokedAtMs: import_zod9.z.number().int().nonnegative().nullable()
2374
2732
  });
2375
2733
  var MintedApiCredentialSchema = ApiCredentialPublicSchema.extend({
2376
- secret: import_zod8.z.string().min(1)
2734
+ secret: import_zod9.z.string().min(1)
2377
2735
  });
2378
2736
  var enc = new TextEncoder();
2379
2737
  async function sha256Hex2(input) {
@@ -2530,8 +2888,8 @@ function createApiCredentialsAdminClient(opts) {
2530
2888
  }
2531
2889
  return parser(raw);
2532
2890
  }
2533
- const listSchema = import_zod8.z.object({
2534
- items: import_zod8.z.array(ApiCredentialPublicSchema)
2891
+ const listSchema = import_zod9.z.object({
2892
+ items: import_zod9.z.array(ApiCredentialPublicSchema)
2535
2893
  });
2536
2894
  return {
2537
2895
  list: (accountId) => call(
@@ -2556,7 +2914,7 @@ function createApiCredentialsAdminClient(opts) {
2556
2914
  }
2557
2915
 
2558
2916
  // src/passes/pass.ts
2559
- var import_zod9 = require("zod");
2917
+ var import_zod10 = require("zod");
2560
2918
  var PASS_KINDS = [
2561
2919
  "ride-ticket",
2562
2920
  "transit-pass",
@@ -2572,39 +2930,39 @@ var PASS_STATES = [
2572
2930
  "expired",
2573
2931
  "revoked"
2574
2932
  ];
2575
- var PassMetadataSchema = import_zod9.z.record(
2576
- import_zod9.z.union([import_zod9.z.string(), import_zod9.z.number(), import_zod9.z.boolean(), import_zod9.z.null()])
2933
+ var PassMetadataSchema = import_zod10.z.record(
2934
+ import_zod10.z.union([import_zod10.z.string(), import_zod10.z.number(), import_zod10.z.boolean(), import_zod10.z.null()])
2577
2935
  );
2578
- var PassSchema = import_zod9.z.object({
2579
- passId: import_zod9.z.string().min(1),
2936
+ var PassSchema = import_zod10.z.object({
2937
+ passId: import_zod10.z.string().min(1),
2580
2938
  /** Optional client/template grouping id (server may omit). */
2581
- templateId: import_zod9.z.string().min(1).optional(),
2939
+ templateId: import_zod10.z.string().min(1).optional(),
2582
2940
  /** Optional human-facing holder identity (server may omit). The cryptographic binding
2583
2941
  * is `holderDevicePubkey` below. */
2584
- holderUserId: import_zod9.z.string().min(1).optional(),
2585
- kind: import_zod9.z.enum(PASS_KINDS),
2586
- issuerId: import_zod9.z.string().min(1),
2587
- issuedAtMs: import_zod9.z.number().int().nonnegative(),
2588
- validFromMs: import_zod9.z.number().int().nonnegative(),
2589
- validUntilMs: import_zod9.z.number().int().positive(),
2590
- state: import_zod9.z.enum(PASS_STATES),
2942
+ holderUserId: import_zod10.z.string().min(1).optional(),
2943
+ kind: import_zod10.z.enum(PASS_KINDS),
2944
+ issuerId: import_zod10.z.string().min(1),
2945
+ issuedAtMs: import_zod10.z.number().int().nonnegative(),
2946
+ validFromMs: import_zod10.z.number().int().nonnegative(),
2947
+ validUntilMs: import_zod10.z.number().int().positive(),
2948
+ state: import_zod10.z.enum(PASS_STATES),
2591
2949
  metadata: PassMetadataSchema,
2592
- nonce: import_zod9.z.string().min(1),
2950
+ nonce: import_zod10.z.string().min(1),
2593
2951
  /** Device id this pass is bound to (FK to backend `device_keys`). */
2594
- holderDeviceId: import_zod9.z.string().min(1),
2952
+ holderDeviceId: import_zod10.z.string().min(1),
2595
2953
  /** SubjectPublicKeyInfo DER (P-256) of the bound device, base64. The redemption
2596
2954
  * signature is verified against this key — it is the security-critical binding. */
2597
- holderDevicePubkey: import_zod9.z.string().min(64).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
2955
+ holderDevicePubkey: import_zod10.z.string().min(64).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
2598
2956
  /** Optional fixed amount for monetary passes (vouchers, gift cards) in kobo. */
2599
- amountKobo: import_zod9.z.number().int().nonnegative().optional(),
2957
+ amountKobo: import_zod10.z.number().int().nonnegative().optional(),
2600
2958
  /** ISO-4217-ish currency code; required on the wire. SDK builders default to NGN. */
2601
- currency: import_zod9.z.string().min(3).max(8),
2959
+ currency: import_zod10.z.string().min(3).max(8),
2602
2960
  /** Monotonic redemption counter floor. Redemption.counter MUST be > counterSeed. */
2603
- counterSeed: import_zod9.z.number().int().nonnegative(),
2961
+ counterSeed: import_zod10.z.number().int().nonnegative(),
2604
2962
  /** Optional cumulative spend cap in kobo across all redemptions of this pass. */
2605
- cumulativeCapKobo: import_zod9.z.number().int().nonnegative().optional(),
2963
+ cumulativeCapKobo: import_zod10.z.number().int().nonnegative().optional(),
2606
2964
  /** ASN.1 DER ECDSA P-256 signature, base64. */
2607
- issuerSig: import_zod9.z.string().min(64).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/)
2965
+ issuerSig: import_zod10.z.string().min(64).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/)
2608
2966
  }).refine((v) => v.validUntilMs > v.validFromMs, {
2609
2967
  message: "validUntilMs must be greater than validFromMs"
2610
2968
  });
@@ -2661,20 +3019,20 @@ function isPassWithinValidity(pass, nowMs) {
2661
3019
  }
2662
3020
 
2663
3021
  // src/passes/redemption.ts
2664
- var import_zod10 = require("zod");
2665
- var Base64Std2 = import_zod10.z.string().min(16).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (std)");
2666
- var RedemptionSchema = import_zod10.z.object({
3022
+ var import_zod11 = require("zod");
3023
+ var Base64Std3 = import_zod11.z.string().min(16).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (std)");
3024
+ var RedemptionSchema = import_zod11.z.object({
2667
3025
  pass: PassSchema,
2668
- redeemerId: import_zod10.z.string().min(1),
2669
- redeemedAtMs: import_zod10.z.number().int().nonnegative(),
3026
+ redeemerId: import_zod11.z.string().min(1),
3027
+ redeemedAtMs: import_zod11.z.number().int().nonnegative(),
2670
3028
  /** Strictly monotonic counter scoped to a single pass. Must be > pass.counterSeed
2671
3029
  * and > the redeemer's lastSeenCounter for this pass. */
2672
- counter: import_zod10.z.number().int().positive(),
3030
+ counter: import_zod11.z.number().int().positive(),
2673
3031
  /** Amount being redeemed in kobo (0 for non-monetary passes like ride tickets). */
2674
- amountKobo: import_zod10.z.number().int().nonnegative(),
2675
- nonce: import_zod10.z.string().min(1),
3032
+ amountKobo: import_zod11.z.number().int().nonnegative(),
3033
+ nonce: import_zod11.z.string().min(1),
2676
3034
  /** ASN.1 DER ECDSA P-256 signature over canonicalJSONBytes(unsigned), base64. */
2677
- holderSig: Base64Std2
3035
+ holderSig: Base64Std3
2678
3036
  });
2679
3037
  var REDEEMABLE_STATES = /* @__PURE__ */ new Set(["issued", "active"]);
2680
3038
  function buildRedemption(input) {
@@ -2756,40 +3114,40 @@ function verifyRedemption(r, issuerPublicKeySpkiB64) {
2756
3114
  }
2757
3115
 
2758
3116
  // src/receipts/receipt.ts
2759
- var import_zod11 = require("zod");
3117
+ var import_zod12 = require("zod");
2760
3118
  var RECEIPT_CHANNELS = ["cash", "pass"];
2761
3119
  var RECEIPT_KINDS = RECEIPT_CHANNELS;
2762
- var ReceiptPayloadSchema = import_zod11.z.record(
2763
- import_zod11.z.union([import_zod11.z.string(), import_zod11.z.number(), import_zod11.z.boolean(), import_zod11.z.null()])
3120
+ var ReceiptPayloadSchema = import_zod12.z.record(
3121
+ import_zod12.z.union([import_zod12.z.string(), import_zod12.z.number(), import_zod12.z.boolean(), import_zod12.z.null()])
2764
3122
  );
2765
- var ReceiptSchema = import_zod11.z.object({
2766
- receiptId: import_zod11.z.string().min(1),
2767
- channel: import_zod11.z.enum(RECEIPT_CHANNELS),
3123
+ var ReceiptSchema = import_zod12.z.object({
3124
+ receiptId: import_zod12.z.string().min(1),
3125
+ channel: import_zod12.z.enum(RECEIPT_CHANNELS),
2768
3126
  /** Cash-channel: send_intents.id. Required when channel === 'cash'. */
2769
- intentId: import_zod11.z.string().min(1).optional(),
3127
+ intentId: import_zod12.z.string().min(1).optional(),
2770
3128
  /** Pass-channel: pass_redemptions.id. Required when channel === 'pass'. */
2771
- passRedemptionId: import_zod11.z.string().min(1).optional(),
2772
- payerUserId: import_zod11.z.string().min(1),
2773
- payeeUserId: import_zod11.z.string().min(1),
2774
- amountKobo: import_zod11.z.number().int().nonnegative(),
2775
- currency: import_zod11.z.string().min(3).max(8),
2776
- issuedAtMs: import_zod11.z.number().int().nonnegative(),
2777
- issuerId: import_zod11.z.string().min(1),
3129
+ passRedemptionId: import_zod12.z.string().min(1).optional(),
3130
+ payerUserId: import_zod12.z.string().min(1),
3131
+ payeeUserId: import_zod12.z.string().min(1),
3132
+ amountKobo: import_zod12.z.number().int().nonnegative(),
3133
+ currency: import_zod12.z.string().min(3).max(8),
3134
+ issuedAtMs: import_zod12.z.number().int().nonnegative(),
3135
+ issuerId: import_zod12.z.string().min(1),
2778
3136
  payload: ReceiptPayloadSchema,
2779
3137
  /** ASN.1 DER ECDSA P-256 signature, base64. */
2780
- issuerSig: import_zod11.z.string().min(64).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/)
3138
+ issuerSig: import_zod12.z.string().min(64).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/)
2781
3139
  }).superRefine((v, ctx) => {
2782
3140
  if (v.channel === "cash") {
2783
3141
  if (!v.intentId) {
2784
3142
  ctx.addIssue({
2785
- code: import_zod11.z.ZodIssueCode.custom,
3143
+ code: import_zod12.z.ZodIssueCode.custom,
2786
3144
  message: "cash receipts require intentId",
2787
3145
  path: ["intentId"]
2788
3146
  });
2789
3147
  }
2790
3148
  if (v.passRedemptionId) {
2791
3149
  ctx.addIssue({
2792
- code: import_zod11.z.ZodIssueCode.custom,
3150
+ code: import_zod12.z.ZodIssueCode.custom,
2793
3151
  message: "cash receipts must not carry passRedemptionId",
2794
3152
  path: ["passRedemptionId"]
2795
3153
  });
@@ -2797,14 +3155,14 @@ var ReceiptSchema = import_zod11.z.object({
2797
3155
  } else if (v.channel === "pass") {
2798
3156
  if (!v.passRedemptionId) {
2799
3157
  ctx.addIssue({
2800
- code: import_zod11.z.ZodIssueCode.custom,
3158
+ code: import_zod12.z.ZodIssueCode.custom,
2801
3159
  message: "pass receipts require passRedemptionId",
2802
3160
  path: ["passRedemptionId"]
2803
3161
  });
2804
3162
  }
2805
3163
  if (v.intentId) {
2806
3164
  ctx.addIssue({
2807
- code: import_zod11.z.ZodIssueCode.custom,
3165
+ code: import_zod12.z.ZodIssueCode.custom,
2808
3166
  message: "pass receipts must not carry intentId",
2809
3167
  path: ["intentId"]
2810
3168
  });
@@ -3106,23 +3464,23 @@ function init(opts) {
3106
3464
  }
3107
3465
 
3108
3466
  // src/accounts/client.ts
3109
- var import_zod12 = require("zod");
3467
+ var import_zod13 = require("zod");
3110
3468
  var ACCOUNT_TYPES = ["personal", "business", "partner"];
3111
3469
  var ACCOUNT_STATUSES = ["active", "suspended", "closed"];
3112
3470
  var MEMBERSHIP_ROLES = ["owner", "admin", "driver", "staff"];
3113
- var AccountSchema = import_zod12.z.object({
3114
- accountId: import_zod12.z.string().uuid(),
3115
- type: import_zod12.z.enum(ACCOUNT_TYPES),
3116
- displayName: import_zod12.z.string().min(1),
3117
- status: import_zod12.z.enum(ACCOUNT_STATUSES),
3118
- ownerUserId: import_zod12.z.string().uuid().nullable(),
3119
- createdAtMs: import_zod12.z.number().int().nonnegative()
3471
+ var AccountSchema = import_zod13.z.object({
3472
+ accountId: import_zod13.z.string().uuid(),
3473
+ type: import_zod13.z.enum(ACCOUNT_TYPES),
3474
+ displayName: import_zod13.z.string().min(1),
3475
+ status: import_zod13.z.enum(ACCOUNT_STATUSES),
3476
+ ownerUserId: import_zod13.z.string().uuid().nullable(),
3477
+ createdAtMs: import_zod13.z.number().int().nonnegative()
3120
3478
  });
3121
- var AccountMembershipSchema = import_zod12.z.object({
3122
- accountId: import_zod12.z.string().uuid(),
3123
- userId: import_zod12.z.string().uuid(),
3124
- role: import_zod12.z.enum(MEMBERSHIP_ROLES),
3125
- createdAtMs: import_zod12.z.number().int().nonnegative()
3479
+ var AccountMembershipSchema = import_zod13.z.object({
3480
+ accountId: import_zod13.z.string().uuid(),
3481
+ userId: import_zod13.z.string().uuid(),
3482
+ role: import_zod13.z.enum(MEMBERSHIP_ROLES),
3483
+ createdAtMs: import_zod13.z.number().int().nonnegative()
3126
3484
  });
3127
3485
  function createAccountsClient(opts) {
3128
3486
  const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
@@ -3155,9 +3513,9 @@ function createAccountsClient(opts) {
3155
3513
  }
3156
3514
  return parser(raw);
3157
3515
  }
3158
- const itemsSchema = import_zod12.z.object({ items: import_zod12.z.array(AccountSchema) });
3159
- const memberItemsSchema = import_zod12.z.object({
3160
- items: import_zod12.z.array(AccountMembershipSchema)
3516
+ const itemsSchema = import_zod13.z.object({ items: import_zod13.z.array(AccountSchema) });
3517
+ const memberItemsSchema = import_zod13.z.object({
3518
+ items: import_zod13.z.array(AccountMembershipSchema)
3161
3519
  });
3162
3520
  return {
3163
3521
  listMyAccounts: () => call(
@@ -3188,320 +3546,6 @@ function createAccountsClient(opts) {
3188
3546
  };
3189
3547
  }
3190
3548
 
3191
- // src/me-offline/client.ts
3192
- var import_zod13 = require("zod");
3193
- var Hex64 = import_zod13.z.string().regex(/^[0-9a-f]{64}$/i);
3194
- var Sha256Hex = import_zod13.z.string().regex(/^[0-9a-f]{64}$/i);
3195
- var Base64Std3 = import_zod13.z.string().regex(/^[A-Za-z0-9+/]+={0,2}$/);
3196
- var RegisterDeviceKeyInputSchema = import_zod13.z.object({
3197
- deviceId: import_zod13.z.string().min(1).max(128),
3198
- publicKeyHex: Hex64
3199
- });
3200
- var AttestationSecurityLevelSchema = import_zod13.z.enum([
3201
- "STRONGBOX",
3202
- "TEE",
3203
- "SECURE_ENCLAVE",
3204
- "SOFTWARE"
3205
- ]);
3206
- var DeviceKeyAlgSchema = import_zod13.z.literal("p256");
3207
- var RegisterDeviceKeyP256InputSchema = import_zod13.z.object({
3208
- deviceId: import_zod13.z.string().min(1).max(128),
3209
- /** P-256 SubjectPublicKeyInfo DER, base64. */
3210
- publicKeySpkiB64: Base64Std3.min(64).max(4096),
3211
- /** Base64 of the server-issued enrollment challenge string. */
3212
- challengeB64: Base64Std3.min(8).max(1024),
3213
- /** iOS App Attest payload or Android X.509 Key Attestation chain. */
3214
- attestationChainB64: import_zod13.z.array(Base64Std3.min(16).max(16384)).min(1).max(16),
3215
- securityLevel: AttestationSecurityLevelSchema
3216
- });
3217
- var P256EnrollmentChallengeInputSchema = import_zod13.z.object({
3218
- deviceId: import_zod13.z.string().min(1).max(128)
3219
- });
3220
- var P256EnrollmentChallengeResultSchema = import_zod13.z.object({
3221
- challenge: import_zod13.z.string().min(16),
3222
- expiresAtMs: import_zod13.z.number().int().positive()
3223
- });
3224
- var DeviceKeyRecordSchema = import_zod13.z.object({
3225
- id: import_zod13.z.string().uuid(),
3226
- userId: import_zod13.z.string().uuid(),
3227
- deviceId: import_zod13.z.string(),
3228
- /** Always 'p256' on the consumer offline rail. Field retained for forward-compat. */
3229
- alg: DeviceKeyAlgSchema.default("p256"),
3230
- /** Legacy ed25519 hex key. Always null on new records (kept for back-compat reads). */
3231
- publicKeyHex: Hex64.nullable().default(null),
3232
- /** P-256 SubjectPublicKeyInfo DER, base64. Required for new records. */
3233
- publicKeySpkiB64: Base64Std3.nullable().default(null),
3234
- securityLevel: AttestationSecurityLevelSchema.nullable().default(null),
3235
- hardwareBacked: import_zod13.z.boolean().default(false),
3236
- attestedAtMs: import_zod13.z.number().int().nonnegative().nullable().default(null),
3237
- createdAtMs: import_zod13.z.number().int().nonnegative(),
3238
- revokedAtMs: import_zod13.z.number().int().nonnegative().nullable()
3239
- });
3240
- var ConsumerOACSchema = import_zod13.z.object({
3241
- oacId: import_zod13.z.string().uuid(),
3242
- issuerId: import_zod13.z.string().min(1).max(64),
3243
- userId: import_zod13.z.string().uuid(),
3244
- deviceId: import_zod13.z.string().min(1).max(128),
3245
- /** Always 'p256'. Field retained for forward-compat. */
3246
- alg: import_zod13.z.literal("p256").default("p256"),
3247
- /** P-256 SubjectPublicKeyInfo DER, base64. */
3248
- devicePubkeySpkiB64: Base64Std3.min(64).max(4096),
3249
- perTxCapKobo: import_zod13.z.number().int().positive(),
3250
- cumulativeCapKobo: import_zod13.z.number().int().positive(),
3251
- currency: import_zod13.z.string().length(3),
3252
- validFromMs: import_zod13.z.number().int().nonnegative(),
3253
- validUntilMs: import_zod13.z.number().int().nonnegative(),
3254
- counterSeed: import_zod13.z.number().int().nonnegative(),
3255
- issuedAtMs: import_zod13.z.number().int().nonnegative()
3256
- });
3257
- var SignedConsumerOACSchema = import_zod13.z.object({
3258
- oac: ConsumerOACSchema,
3259
- /** ASN.1 DER ECDSA P-256 issuer signature, base64. */
3260
- issuerSig: Base64Std3.min(16).max(2048),
3261
- /** Issuer's P-256 public key as SubjectPublicKeyInfo DER, base64. */
3262
- issuerPublicKeySpkiB64: Base64Std3.min(64).max(4096)
3263
- });
3264
- var OACRecordSchema = SignedConsumerOACSchema.extend({
3265
- currentOfflineSpentKobo: import_zod13.z.number().int().nonnegative(),
3266
- status: import_zod13.z.enum([
3267
- "active",
3268
- "superseded",
3269
- "expired",
3270
- "revoked",
3271
- "disabling",
3272
- "draining",
3273
- "closed"
3274
- ]),
3275
- supersededAtMs: import_zod13.z.number().int().nonnegative().nullable(),
3276
- revokedAtMs: import_zod13.z.number().int().nonnegative().nullable(),
3277
- holdId: import_zod13.z.string().uuid().nullable().optional()
3278
- });
3279
- var IssueOACInputSchema = import_zod13.z.object({
3280
- deviceId: import_zod13.z.string().min(1).max(128),
3281
- perTxCapKobo: import_zod13.z.number().int().positive().optional(),
3282
- cumulativeCapKobo: import_zod13.z.number().int().positive().optional(),
3283
- ttlMs: import_zod13.z.number().int().min(6e4).max(1e3 * 60 * 60 * 24 * 7).optional(),
3284
- spendableOnlineKobo: import_zod13.z.number().int().nonnegative().optional()
3285
- });
3286
- var EnableOfflineInputSchema = import_zod13.z.object({
3287
- deviceId: import_zod13.z.string().min(1).max(128),
3288
- amountKobo: import_zod13.z.number().int().positive(),
3289
- perTxCapKobo: import_zod13.z.number().int().positive().optional(),
3290
- ttlMs: import_zod13.z.number().int().min(6e4).max(1e3 * 60 * 60 * 24 * 7).optional(),
3291
- installId: import_zod13.z.string().min(1).max(128),
3292
- partnerId: import_zod13.z.string().min(1).max(64).optional()
3293
- });
3294
- var ProvisionOfflineAllowanceInputSchema = EnableOfflineInputSchema;
3295
- var DisableOfflineInputSchema = import_zod13.z.object({
3296
- deviceId: import_zod13.z.string().min(1).max(128),
3297
- installId: import_zod13.z.string().min(1).max(128).optional(),
3298
- claims: import_zod13.z.array(import_zod13.z.unknown()).max(256).optional()
3299
- });
3300
- var OfflineHoldRecordSchema = import_zod13.z.object({
3301
- holdId: import_zod13.z.string().uuid(),
3302
- userId: import_zod13.z.string().uuid(),
3303
- deviceId: import_zod13.z.string(),
3304
- partnerId: import_zod13.z.string(),
3305
- adapterKind: import_zod13.z.string(),
3306
- externalHoldRef: import_zod13.z.string().nullable(),
3307
- amountKobo: import_zod13.z.number().int().nonnegative(),
3308
- capturedKobo: import_zod13.z.number().int().nonnegative(),
3309
- releasedKobo: import_zod13.z.number().int().nonnegative(),
3310
- remainingKobo: import_zod13.z.number().int().nonnegative(),
3311
- currency: import_zod13.z.string().length(3),
3312
- status: import_zod13.z.enum([
3313
- "placing",
3314
- "active",
3315
- "disabling",
3316
- "draining",
3317
- "closed",
3318
- "revoked",
3319
- "failed"
3320
- ]),
3321
- installId: import_zod13.z.string().nullable(),
3322
- drainDeadlineMs: import_zod13.z.number().int().nonnegative(),
3323
- disableRequestedAtMs: import_zod13.z.number().int().nonnegative().nullable(),
3324
- createdAtMs: import_zod13.z.number().int().nonnegative(),
3325
- closedAtMs: import_zod13.z.number().int().nonnegative().nullable(),
3326
- isTrusted: import_zod13.z.boolean().optional()
3327
- });
3328
- var EnableOfflineResultSchema = import_zod13.z.object({
3329
- hold: OfflineHoldRecordSchema,
3330
- oac: OACRecordSchema
3331
- });
3332
- var ProvisionOfflineAllowanceResultSchema = EnableOfflineResultSchema;
3333
- var DisableOfflineResultSchema = import_zod13.z.object({
3334
- hold: OfflineHoldRecordSchema,
3335
- trusted: import_zod13.z.boolean(),
3336
- settledClaims: import_zod13.z.number().int().nonnegative()
3337
- });
3338
- var OfflineStatusResultSchema = import_zod13.z.object({
3339
- hold: OfflineHoldRecordSchema.nullable(),
3340
- active: OACRecordSchema.nullable()
3341
- });
3342
- var OfflineStateResultSchema = import_zod13.z.object({
3343
- active: OACRecordSchema.nullable()
3344
- });
3345
- var ConsumerPaymentClaimSchema = import_zod13.z.object({
3346
- /** Always 'p256'. Retained for forward-compat and as an explicit domain marker. */
3347
- alg: import_zod13.z.literal("p256").default("p256"),
3348
- oacId: import_zod13.z.string().uuid(),
3349
- encounterId: Sha256Hex.optional(),
3350
- payerUserId: import_zod13.z.string().uuid(),
3351
- payeeUserId: import_zod13.z.string().uuid(),
3352
- payerDeviceId: import_zod13.z.string().min(1).max(128),
3353
- payerNonce: import_zod13.z.string().min(8).max(128),
3354
- payeeNonce: import_zod13.z.string().min(8).max(128),
3355
- amountKobo: import_zod13.z.number().int().positive(),
3356
- currency: import_zod13.z.string().length(3).default("NGN"),
3357
- occurredAtMs: import_zod13.z.number().int().nonnegative(),
3358
- completedAtMs: import_zod13.z.number().int().nonnegative().optional(),
3359
- contextId: import_zod13.z.string().max(128).optional(),
3360
- payerPubkeySpkiB64: Base64Std3.min(64).max(4096),
3361
- payerSignatureDerB64: Base64Std3.min(16).max(2048),
3362
- payeePubkeySpkiB64: Base64Std3.min(64).max(4096).optional(),
3363
- payeeSignatureDerB64: Base64Std3.min(16).max(2048).optional()
3364
- });
3365
- var ConsumerSettlementSchema = import_zod13.z.object({
3366
- settlementId: import_zod13.z.string().uuid(),
3367
- settlementKey: Sha256Hex,
3368
- encounterId: Sha256Hex,
3369
- oacId: import_zod13.z.string().uuid(),
3370
- payerUserId: import_zod13.z.string().uuid(),
3371
- payeeUserId: import_zod13.z.string().uuid(),
3372
- amountKobo: import_zod13.z.number().int().positive(),
3373
- currency: import_zod13.z.string().length(3),
3374
- status: import_zod13.z.enum(["SETTLED", "REVIEW"]),
3375
- reviewReason: import_zod13.z.string().nullable(),
3376
- ledgerRef: import_zod13.z.string().nullable(),
3377
- /** ASN.1 DER ECDSA P-256 issuer signature, base64. */
3378
- issuerSig: Base64Std3.min(16).max(2048),
3379
- createdAtMs: import_zod13.z.number().int().nonnegative()
3380
- });
3381
- var ConsumerSettleResultSchema = import_zod13.z.object({
3382
- settlement: ConsumerSettlementSchema,
3383
- encounterId: Sha256Hex,
3384
- replayed: import_zod13.z.boolean()
3385
- });
3386
- var RevokeDeviceKeyInputSchema = import_zod13.z.object({
3387
- deviceId: import_zod13.z.string().min(1).max(128),
3388
- /** Step-up token from /api/v1/auth/send/verify with purpose='offline_revoke'. */
3389
- sendAuthToken: import_zod13.z.string().min(16)
3390
- });
3391
- function createMeOfflineClient(opts) {
3392
- const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
3393
- if (!fetchImpl) {
3394
- throw new Error("createMeOfflineClient: no fetch implementation available");
3395
- }
3396
- const baseUrl = opts.baseUrl.replace(/\/$/, "");
3397
- async function call(method, path, body, parser) {
3398
- const init2 = {
3399
- method,
3400
- headers: {
3401
- "content-type": "application/json",
3402
- accept: "application/json"
3403
- }
3404
- };
3405
- if (body !== void 0) init2.body = JSON.stringify(body);
3406
- const resp = await fetchImpl(`${baseUrl}${path}`, init2);
3407
- const text = await resp.text();
3408
- let raw = void 0;
3409
- if (text) {
3410
- try {
3411
- raw = JSON.parse(text);
3412
- } catch {
3413
- }
3414
- }
3415
- if (!resp.ok) {
3416
- const code = raw && typeof raw === "object" && "code" in raw && typeof raw.code === "string" ? raw.code : `http_${resp.status}`;
3417
- const message = raw && typeof raw === "object" && "message" in raw && typeof raw.message === "string" ? raw.message : `request failed with status ${resp.status}`;
3418
- throw new FlurApiError(resp.status, code, message, raw);
3419
- }
3420
- return parser(raw);
3421
- }
3422
- const deviceKeyItems = import_zod13.z.object({ items: import_zod13.z.array(DeviceKeyRecordSchema) });
3423
- return {
3424
- registerDeviceKey: (input) => call(
3425
- "POST",
3426
- "/v1/me/offline/keys",
3427
- RegisterDeviceKeyInputSchema.parse(input),
3428
- (raw) => DeviceKeyRecordSchema.parse(raw)
3429
- ),
3430
- issueP256EnrollmentChallenge: (input) => call(
3431
- "POST",
3432
- "/v1/me/offline/keys/p256/challenge",
3433
- P256EnrollmentChallengeInputSchema.parse(input),
3434
- (raw) => P256EnrollmentChallengeResultSchema.parse(raw)
3435
- ),
3436
- registerDeviceKeyP256: (input) => call(
3437
- "POST",
3438
- "/v1/me/offline/keys/p256",
3439
- RegisterDeviceKeyP256InputSchema.parse(input),
3440
- (raw) => DeviceKeyRecordSchema.parse(raw)
3441
- ),
3442
- listDeviceKeys: () => call(
3443
- "GET",
3444
- "/v1/me/offline/keys",
3445
- void 0,
3446
- (raw) => deviceKeyItems.parse(raw)
3447
- ),
3448
- revokeDeviceKey: (input) => call(
3449
- "POST",
3450
- "/v1/me/offline/keys/revoke",
3451
- RevokeDeviceKeyInputSchema.parse(input),
3452
- () => void 0
3453
- ),
3454
- provisionAllowance: (input) => call(
3455
- "POST",
3456
- "/v1/me/offline/allowance",
3457
- ProvisionOfflineAllowanceInputSchema.parse(input),
3458
- (raw) => ProvisionOfflineAllowanceResultSchema.parse(raw)
3459
- ),
3460
- enable: (input) => call(
3461
- "POST",
3462
- "/v1/me/offline/enable",
3463
- EnableOfflineInputSchema.parse(input),
3464
- (raw) => EnableOfflineResultSchema.parse(raw)
3465
- ),
3466
- refresh: (input) => call(
3467
- "POST",
3468
- "/v1/me/offline/refresh",
3469
- IssueOACInputSchema.parse(input),
3470
- (raw) => OACRecordSchema.parse(raw)
3471
- ),
3472
- disable: (input) => call(
3473
- "POST",
3474
- "/v1/me/offline/disable",
3475
- DisableOfflineInputSchema.parse(input),
3476
- (raw) => DisableOfflineResultSchema.parse(raw)
3477
- ),
3478
- getStatus: (deviceId) => {
3479
- const qs = deviceId ? `?deviceId=${encodeURIComponent(deviceId)}` : "";
3480
- return call(
3481
- "GET",
3482
- `/v1/me/offline/status${qs}`,
3483
- void 0,
3484
- (raw) => OfflineStatusResultSchema.parse(raw)
3485
- );
3486
- },
3487
- getState: (deviceId) => {
3488
- const qs = deviceId ? `?deviceId=${encodeURIComponent(deviceId)}` : "";
3489
- return call(
3490
- "GET",
3491
- `/v1/me/offline/state${qs}`,
3492
- void 0,
3493
- (raw) => OfflineStateResultSchema.parse(raw)
3494
- );
3495
- },
3496
- submitClaim: (claim) => call(
3497
- "POST",
3498
- "/v1/me/offline/claims",
3499
- ConsumerPaymentClaimSchema.parse(claim),
3500
- (raw) => ConsumerSettleResultSchema.parse(raw)
3501
- )
3502
- };
3503
- }
3504
-
3505
3549
  // src/me-offline/signer.ts
3506
3550
  var import_nist2 = require("@noble/curves/nist");
3507
3551
  var CLAIM_DOMAIN_V2 = "flur:consumer-offline:v2:claim";
@@ -4458,6 +4502,7 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
4458
4502
  HARDENED_ARTIFACT_TYPES,
4459
4503
  IdentityArtifactSchema,
4460
4504
  IngestFundingResultSchema,
4505
+ IssueAccountOacInputSchema,
4461
4506
  IssueOACInputSchema,
4462
4507
  LedgerJournalEntryArtifactSchema,
4463
4508
  ListPayoutDestinationsResultSchema,