@nokinc-flur/sdk 1.0.5 → 1.0.6

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,5 +1,5 @@
1
1
  // src/client.ts
2
- import { z as z3 } from "zod";
2
+ import { z as z4 } from "zod";
3
3
 
4
4
  // src/contracts.ts
5
5
  import { z } from "zod";
@@ -387,6 +387,341 @@ function moneyMinorToNumber(amountMinor) {
387
387
  return asNumber;
388
388
  }
389
389
 
390
+ // src/collections/client.ts
391
+ import { z as z3 } from "zod";
392
+ var MERCHANT_PROFILE_STATUSES = [
393
+ "pending",
394
+ "active",
395
+ "suspended",
396
+ "closed"
397
+ ];
398
+ var SETTLEMENT_SCHEDULES = ["manual", "daily", "t1"];
399
+ var COLLECTION_INTENT_STATUSES = [
400
+ "created",
401
+ "pending",
402
+ "paid",
403
+ "expired",
404
+ "cancelled",
405
+ "failed",
406
+ "reversed"
407
+ ];
408
+ var COLLECTION_PAYMENT_STATUSES = [
409
+ "pending",
410
+ "paid",
411
+ "failed",
412
+ "reversed"
413
+ ];
414
+ var MERCHANT_PAYOUT_STATUSES = [
415
+ "requested",
416
+ "processing",
417
+ "paid",
418
+ "failed",
419
+ "cancelled"
420
+ ];
421
+ var MoneyKoboSchema = z3.number().int().positive().max(Number.MAX_SAFE_INTEGER);
422
+ var MetadataSchema = z3.record(
423
+ z3.union([z3.string(), z3.number(), z3.boolean(), z3.null()])
424
+ );
425
+ var CurrencySchema2 = z3.string().trim().length(3).transform((value) => value.toUpperCase());
426
+ var ReferenceSchema = z3.string().trim().min(6).max(128).regex(/^[A-Za-z0-9._:-]+$/);
427
+ var MerchantProfileSchema = z3.object({
428
+ accountId: z3.string().uuid(),
429
+ legalName: z3.string(),
430
+ tradingName: z3.string(),
431
+ merchantCategoryCode: z3.string().regex(/^\d{4}$/),
432
+ nqrMerchantId: z3.string(),
433
+ settlementBankCode: z3.string(),
434
+ settlementAccountNumber: z3.string(),
435
+ settlementAccountName: z3.string(),
436
+ settlementSchedule: z3.enum(SETTLEMENT_SCHEDULES),
437
+ status: z3.enum(MERCHANT_PROFILE_STATUSES),
438
+ offlineEnabled: z3.boolean(),
439
+ perTxLimitKobo: MoneyKoboSchema,
440
+ dailyLimitKobo: MoneyKoboSchema,
441
+ metadata: MetadataSchema,
442
+ createdAtMs: z3.number().int().nonnegative(),
443
+ updatedAtMs: z3.number().int().nonnegative()
444
+ });
445
+ var UpsertMerchantProfileInputSchema = z3.object({
446
+ legalName: z3.string().trim().min(1).max(200),
447
+ tradingName: z3.string().trim().min(1).max(25),
448
+ merchantCategoryCode: z3.string().trim().regex(/^\d{4}$/),
449
+ nqrMerchantId: z3.string().trim().min(3).max(64),
450
+ settlementBankCode: z3.string().trim().min(2).max(16),
451
+ settlementAccountNumber: z3.string().trim().min(5).max(32),
452
+ settlementAccountName: z3.string().trim().min(1).max(200),
453
+ settlementSchedule: z3.enum(SETTLEMENT_SCHEDULES).optional(),
454
+ status: z3.enum(MERCHANT_PROFILE_STATUSES).optional(),
455
+ offlineEnabled: z3.boolean().optional(),
456
+ perTxLimitKobo: MoneyKoboSchema.optional(),
457
+ dailyLimitKobo: MoneyKoboSchema.optional(),
458
+ metadata: MetadataSchema.optional()
459
+ });
460
+ var CollectionIntentSchema = z3.object({
461
+ intentId: z3.string().uuid(),
462
+ accountId: z3.string().uuid(),
463
+ terminalId: z3.string().uuid().nullable(),
464
+ reference: z3.string(),
465
+ amountKobo: z3.number().int().positive().nullable(),
466
+ currency: z3.string().length(3),
467
+ status: z3.enum(COLLECTION_INTENT_STATUSES),
468
+ description: z3.string().nullable(),
469
+ nqrPayload: z3.string(),
470
+ provider: z3.string(),
471
+ providerReference: z3.string().nullable(),
472
+ metadata: MetadataSchema,
473
+ expiresAtMs: z3.number().int().nonnegative().nullable(),
474
+ paidAtMs: z3.number().int().nonnegative().nullable(),
475
+ createdAtMs: z3.number().int().nonnegative(),
476
+ updatedAtMs: z3.number().int().nonnegative()
477
+ });
478
+ var CreateCollectionIntentInputSchema = z3.object({
479
+ reference: ReferenceSchema.optional(),
480
+ amountKobo: MoneyKoboSchema.optional(),
481
+ currency: CurrencySchema2.optional(),
482
+ terminalId: z3.string().uuid().optional(),
483
+ terminalLabel: z3.string().trim().min(1).max(25).optional(),
484
+ merchantCity: z3.string().trim().min(1).max(15).optional(),
485
+ description: z3.string().trim().min(1).max(280).optional(),
486
+ expiresAtMs: z3.number().int().positive().optional(),
487
+ provider: z3.string().trim().min(1).max(40).optional(),
488
+ metadata: MetadataSchema.optional()
489
+ });
490
+ var PublicCollectionIntentSchema = z3.object({
491
+ intentId: z3.string().uuid(),
492
+ reference: z3.string(),
493
+ amountKobo: z3.number().int().positive().nullable(),
494
+ currency: z3.string().length(3),
495
+ status: z3.enum(COLLECTION_INTENT_STATUSES),
496
+ merchantAccountId: z3.string().uuid(),
497
+ merchantName: z3.string(),
498
+ merchantCategoryCode: z3.string(),
499
+ description: z3.string().nullable(),
500
+ expiresAtMs: z3.number().int().nonnegative().nullable()
501
+ });
502
+ var PayCollectionInputSchema = z3.object({
503
+ reference: ReferenceSchema,
504
+ amountKobo: MoneyKoboSchema.optional(),
505
+ currency: CurrencySchema2.optional(),
506
+ idempotencyKey: z3.string().trim().min(8).max(160).optional()
507
+ });
508
+ var CollectionPaymentSchema = z3.object({
509
+ paymentId: z3.string().uuid(),
510
+ intentId: z3.string().uuid(),
511
+ accountId: z3.string().uuid(),
512
+ payerUserId: z3.string().uuid().nullable(),
513
+ merchantOwnerUserId: z3.string().uuid(),
514
+ amountKobo: MoneyKoboSchema,
515
+ currency: z3.string().length(3),
516
+ status: z3.enum(COLLECTION_PAYMENT_STATUSES),
517
+ provider: z3.string(),
518
+ providerReference: z3.string().nullable(),
519
+ idempotencyKey: z3.string().nullable(),
520
+ ledgerRef: z3.string(),
521
+ failureCode: z3.string().nullable(),
522
+ failureMessage: z3.string().nullable(),
523
+ paidAtMs: z3.number().int().nonnegative().nullable(),
524
+ createdAtMs: z3.number().int().nonnegative(),
525
+ updatedAtMs: z3.number().int().nonnegative()
526
+ });
527
+ var CollectionPaymentResultSchema = z3.object({
528
+ payment: CollectionPaymentSchema,
529
+ intent: CollectionIntentSchema,
530
+ receipt: z3.unknown().optional(),
531
+ replayed: z3.boolean()
532
+ });
533
+ var CollectionReportSummarySchema = z3.object({
534
+ accountId: z3.string().uuid(),
535
+ fromMs: z3.number().int().nonnegative(),
536
+ toMs: z3.number().int().nonnegative(),
537
+ currency: z3.string().length(3),
538
+ paidCount: z3.number().int().nonnegative(),
539
+ paidAmountKobo: z3.number().int().nonnegative(),
540
+ pendingCount: z3.number().int().nonnegative(),
541
+ failedCount: z3.number().int().nonnegative(),
542
+ reversedCount: z3.number().int().nonnegative(),
543
+ availableBalanceKobo: z3.number().int().nonnegative()
544
+ });
545
+ var CollectionStatementSchema = z3.object({
546
+ accountId: z3.string().uuid(),
547
+ year: z3.number().int(),
548
+ month: z3.number().int().min(1).max(12),
549
+ currency: z3.string().length(3),
550
+ totalPaidKobo: z3.number().int().nonnegative(),
551
+ items: z3.array(CollectionPaymentSchema)
552
+ });
553
+ var CreatePayoutInputSchema = z3.object({
554
+ amountKobo: MoneyKoboSchema,
555
+ currency: CurrencySchema2.optional(),
556
+ idempotencyKey: z3.string().trim().min(8).max(160)
557
+ });
558
+ var MerchantPayoutSchema = z3.object({
559
+ payoutId: z3.string().uuid(),
560
+ accountId: z3.string().uuid(),
561
+ amountKobo: MoneyKoboSchema,
562
+ currency: z3.string().length(3),
563
+ status: z3.enum(MERCHANT_PAYOUT_STATUSES),
564
+ idempotencyKey: z3.string().nullable(),
565
+ ledgerRef: z3.string(),
566
+ providerReference: z3.string().nullable(),
567
+ requestedByUserId: z3.string().uuid().nullable(),
568
+ failureCode: z3.string().nullable(),
569
+ failureMessage: z3.string().nullable(),
570
+ createdAtMs: z3.number().int().nonnegative(),
571
+ updatedAtMs: z3.number().int().nonnegative()
572
+ });
573
+ var ProviderEventInputSchema = z3.object({
574
+ provider: z3.string().trim().min(1).max(80),
575
+ eventId: z3.string().trim().min(1).max(160),
576
+ eventType: z3.string().trim().min(1).max(120),
577
+ payload: z3.record(z3.unknown()).optional()
578
+ });
579
+ var ProviderEventRecordSchema = z3.object({
580
+ id: z3.string().uuid(),
581
+ provider: z3.string(),
582
+ eventId: z3.string(),
583
+ eventType: z3.string(),
584
+ signatureVerified: z3.boolean(),
585
+ receivedAtMs: z3.number().int().nonnegative(),
586
+ processedAtMs: z3.number().int().nonnegative().nullable()
587
+ });
588
+ function createCollectionsClient(opts) {
589
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
590
+ if (!fetchImpl) {
591
+ throw new Error(
592
+ "createCollectionsClient: no fetch implementation available"
593
+ );
594
+ }
595
+ const baseUrl = opts.baseUrl.replace(/\/$/, "");
596
+ async function call(method, path, body, parser) {
597
+ const init2 = {
598
+ method,
599
+ headers: { accept: "application/json" }
600
+ };
601
+ if (body !== void 0) {
602
+ init2.body = JSON.stringify(body);
603
+ init2.headers = { ...init2.headers, "content-type": "application/json" };
604
+ }
605
+ const resp = await fetchImpl(`${baseUrl}${path}`, init2);
606
+ const text = await resp.text();
607
+ let raw;
608
+ if (text) {
609
+ try {
610
+ raw = JSON.parse(text);
611
+ } catch {
612
+ raw = text;
613
+ }
614
+ }
615
+ if (!resp.ok) {
616
+ const code = raw && typeof raw === "object" && "code" in raw && typeof raw.code === "string" ? raw.code : `http_${resp.status}`;
617
+ const message = raw && typeof raw === "object" && "message" in raw && typeof raw.message === "string" ? raw.message : `request failed with status ${resp.status}`;
618
+ throw new FlurApiError(resp.status, code, message, raw);
619
+ }
620
+ return parser(raw);
621
+ }
622
+ return {
623
+ upsertMerchantProfile: (accountId, input) => call(
624
+ "PUT",
625
+ `/v1/accounts/${encodeURIComponent(accountId)}/merchant-profile`,
626
+ UpsertMerchantProfileInputSchema.parse(input),
627
+ (raw) => MerchantProfileSchema.parse(raw)
628
+ ),
629
+ getMerchantProfile: (accountId) => call(
630
+ "GET",
631
+ `/v1/accounts/${encodeURIComponent(accountId)}/merchant-profile`,
632
+ void 0,
633
+ (raw) => MerchantProfileSchema.parse(raw)
634
+ ),
635
+ createIntent: (input) => call(
636
+ "POST",
637
+ "/v1/collections/intents",
638
+ CreateCollectionIntentInputSchema.parse(input),
639
+ (raw) => CollectionIntentSchema.parse(raw)
640
+ ),
641
+ getIntent: (intentId) => call(
642
+ "GET",
643
+ `/v1/collections/intents/${encodeURIComponent(intentId)}`,
644
+ void 0,
645
+ (raw) => CollectionIntentSchema.parse(raw)
646
+ ),
647
+ resolveIntent: (reference) => call(
648
+ "GET",
649
+ `/v1/collections/resolve/${encodeURIComponent(reference)}`,
650
+ void 0,
651
+ (raw) => PublicCollectionIntentSchema.parse(raw)
652
+ ),
653
+ pay: (input) => call(
654
+ "POST",
655
+ "/v1/collections/pay",
656
+ PayCollectionInputSchema.parse(input),
657
+ (raw) => CollectionPaymentResultSchema.parse(raw)
658
+ ),
659
+ reportSummary: (input) => {
660
+ const qs = new URLSearchParams({
661
+ fromMs: String(input.fromMs),
662
+ toMs: String(input.toMs)
663
+ });
664
+ if (input.currency) qs.set("currency", input.currency);
665
+ return call(
666
+ "GET",
667
+ `/v1/collections/reports/summary?${qs.toString()}`,
668
+ void 0,
669
+ (raw) => CollectionReportSummarySchema.parse(raw)
670
+ );
671
+ },
672
+ monthlyStatement: (input) => {
673
+ const qs = new URLSearchParams({
674
+ year: String(input.year),
675
+ month: String(input.month)
676
+ });
677
+ if (input.currency) qs.set("currency", input.currency);
678
+ return call(
679
+ "GET",
680
+ `/v1/collections/statements/monthly?${qs.toString()}`,
681
+ void 0,
682
+ (raw) => CollectionStatementSchema.parse(raw)
683
+ );
684
+ },
685
+ createPayout: (input) => call(
686
+ "POST",
687
+ "/v1/collections/payouts",
688
+ CreatePayoutInputSchema.parse(input),
689
+ (raw) => MerchantPayoutSchema.parse(raw)
690
+ ),
691
+ getPayout: (payoutId) => call(
692
+ "GET",
693
+ `/v1/collections/payouts/${encodeURIComponent(payoutId)}`,
694
+ void 0,
695
+ (raw) => MerchantPayoutSchema.parse(raw)
696
+ ),
697
+ recordProviderEvent: (input) => call(
698
+ "POST",
699
+ "/v1/collections/provider-events",
700
+ ProviderEventInputSchema.parse(input),
701
+ (raw) => ProviderEventRecordSchema.parse(raw)
702
+ )
703
+ };
704
+ }
705
+ function createPartnerCollectionsClient(opts) {
706
+ const client = createCollectionsClient(opts);
707
+ return {
708
+ createIntent: client.createIntent,
709
+ getIntent: client.getIntent,
710
+ reportSummary: client.reportSummary,
711
+ monthlyStatement: client.monthlyStatement,
712
+ createPayout: client.createPayout,
713
+ getPayout: client.getPayout,
714
+ recordProviderEvent: client.recordProviderEvent
715
+ };
716
+ }
717
+ function createConsumerCollectionsClient(opts) {
718
+ const client = createCollectionsClient(opts);
719
+ return {
720
+ resolveIntent: client.resolveIntent,
721
+ pay: client.pay
722
+ };
723
+ }
724
+
390
725
  // src/client.ts
391
726
  var FlurClient = class {
392
727
  baseUrl;
@@ -635,6 +970,36 @@ var FlurClient = class {
635
970
  }
636
971
  );
637
972
  }
973
+ async resolveCollection(reference, options) {
974
+ return this.requestJson(
975
+ `/v1/collections/resolve/${encodeURIComponent(reference)}`,
976
+ {
977
+ method: "GET",
978
+ headers: {
979
+ authorization: `Bearer ${options.accessToken}`
980
+ }
981
+ },
982
+ void 0,
983
+ PublicCollectionIntentSchema
984
+ );
985
+ }
986
+ async payCollection(input, options) {
987
+ const idempotencyKey = input.idempotencyKey ?? options.idempotencyKey ?? getSecureRandomUuid();
988
+ return this.requestJson(
989
+ "/v1/collections/pay",
990
+ {
991
+ method: "POST",
992
+ headers: {
993
+ "content-type": "application/json",
994
+ authorization: `Bearer ${options.accessToken}`,
995
+ "x-idempotency-key": idempotencyKey
996
+ }
997
+ },
998
+ PayCollectionInputSchema,
999
+ CollectionPaymentResultSchema,
1000
+ { ...input, idempotencyKey }
1001
+ );
1002
+ }
638
1003
  async accountSummary(options) {
639
1004
  return this.requestJson(
640
1005
  "/api/v1/account/summary",
@@ -733,7 +1098,7 @@ var FlurClient = class {
733
1098
  try {
734
1099
  body = requestSchema ? JSON.stringify(requestSchema.parse(input)) : init2.body;
735
1100
  } catch (err) {
736
- if (err instanceof z3.ZodError) {
1101
+ if (err instanceof z4.ZodError) {
737
1102
  throw new FlurError("Invalid request payload", "INVALID_REQUEST", {
738
1103
  details: err.flatten()
739
1104
  });
@@ -761,7 +1126,7 @@ var FlurClient = class {
761
1126
  try {
762
1127
  return responseSchema.parse(payload);
763
1128
  } catch (err) {
764
- if (err instanceof z3.ZodError) {
1129
+ if (err instanceof z4.ZodError) {
765
1130
  throw new FlurError(
766
1131
  "SDK contract validation failed",
767
1132
  "INVALID_REQUEST",
@@ -1219,24 +1584,24 @@ function verifyCanonical(value, signature, publicKey) {
1219
1584
  }
1220
1585
 
1221
1586
  // src/offline/oac.ts
1222
- import { z as z4 } from "zod";
1587
+ import { z as z5 } from "zod";
1223
1588
  var OAC_DEFAULT_PER_TX_KOBO = 5e5;
1224
1589
  var OAC_DEFAULT_CUMULATIVE_KOBO = 2e6;
1225
1590
  var OAC_DEFAULT_VALIDITY_MS = 24 * 60 * 60 * 1e3;
1226
- var HexString = (length) => z4.string().regex(
1591
+ var HexString = (length) => z5.string().regex(
1227
1592
  new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
1228
1593
  `expected ${length}-byte hex string`
1229
1594
  );
1230
- var OACSchema = z4.object({
1231
- userId: z4.string().min(1),
1232
- deviceId: z4.string().min(1),
1595
+ var OACSchema = z5.object({
1596
+ userId: z5.string().min(1),
1597
+ deviceId: z5.string().min(1),
1233
1598
  devicePublicKey: HexString(32),
1234
- perTxCapKobo: z4.number().int().nonnegative(),
1235
- cumulativeCapKobo: z4.number().int().nonnegative(),
1236
- validFromMs: z4.number().int().nonnegative(),
1237
- validUntilMs: z4.number().int().positive(),
1238
- counterSeed: z4.number().int().nonnegative(),
1239
- nonce: z4.string().min(1),
1599
+ perTxCapKobo: z5.number().int().nonnegative(),
1600
+ cumulativeCapKobo: z5.number().int().nonnegative(),
1601
+ validFromMs: z5.number().int().nonnegative(),
1602
+ validUntilMs: z5.number().int().positive(),
1603
+ counterSeed: z5.number().int().nonnegative(),
1604
+ nonce: z5.string().min(1),
1240
1605
  issuerSig: HexString(64)
1241
1606
  }).refine((v) => v.validUntilMs > v.validFromMs, {
1242
1607
  message: "validUntilMs must be greater than validFromMs"
@@ -1343,19 +1708,19 @@ function decodeBase45(s) {
1343
1708
  }
1344
1709
 
1345
1710
  // src/offline/messages.ts
1346
- import { z as z5 } from "zod";
1347
- var HexSig = z5.string().regex(/^[0-9a-fA-F]{128}$/, "expected 64-byte hex signature");
1348
- var OfflinePaymentRequestSchema = z5.object({
1349
- reference: z5.string().min(1),
1350
- amountKobo: z5.number().int().positive(),
1711
+ import { z as z6 } from "zod";
1712
+ var HexSig = z6.string().regex(/^[0-9a-fA-F]{128}$/, "expected 64-byte hex signature");
1713
+ var OfflinePaymentRequestSchema = z6.object({
1714
+ reference: z6.string().min(1),
1715
+ amountKobo: z6.number().int().positive(),
1351
1716
  merchantOAC: OACSchema,
1352
- expiresAtMs: z5.number().int().positive(),
1717
+ expiresAtMs: z6.number().int().positive(),
1353
1718
  merchantSig: HexSig
1354
1719
  });
1355
- var OfflinePaymentAuthorizationSchema = z5.object({
1720
+ var OfflinePaymentAuthorizationSchema = z6.object({
1356
1721
  request: OfflinePaymentRequestSchema,
1357
1722
  payerOAC: OACSchema,
1358
- payerCounter: z5.number().int().positive(),
1723
+ payerCounter: z6.number().int().positive(),
1359
1724
  payerSig: HexSig
1360
1725
  });
1361
1726
  function buildPaymentRequest(input) {
@@ -1464,56 +1829,56 @@ function decodeAuthorizationQR(s) {
1464
1829
  }
1465
1830
 
1466
1831
  // src/offline/settlements.ts
1467
- import { z as z6 } from "zod";
1832
+ import { z as z7 } from "zod";
1468
1833
  import { sha256 } from "@noble/hashes/sha256";
1469
1834
  import { bytesToHex as bytesToHex2 } from "@noble/hashes/utils";
1470
- var OfflineTokenSchema = z6.object({
1471
- tokenId: z6.string().uuid(),
1472
- tokenSerial: z6.string(),
1473
- issuerAccountId: z6.string().uuid(),
1474
- payerUserId: z6.string().uuid(),
1475
- maxAmountKobo: z6.number().int().positive(),
1476
- currency: z6.string().length(3),
1477
- issuedAtMs: z6.number().int().nonnegative(),
1478
- expiresAtMs: z6.number().int().nonnegative(),
1479
- issuerSig: z6.string()
1480
- });
1481
- var PaymentClaimSchema = z6.object({
1482
- encounterId: z6.string().regex(/^[0-9a-f]{64}$/i).optional(),
1483
- tokenSerial: z6.string(),
1484
- payerUserId: z6.string().uuid(),
1485
- payeeUserId: z6.string().uuid(),
1486
- payerNonce: z6.string(),
1487
- payeeNonce: z6.string(),
1488
- amountKobo: z6.number().int().positive(),
1489
- currency: z6.string().length(3).default("NGN"),
1490
- occurredAtMs: z6.number().int().nonnegative(),
1491
- completedAtMs: z6.number().int().nonnegative().optional(),
1492
- contextId: z6.string().optional(),
1493
- payerPubkey: z6.string().regex(/^[0-9a-f]{64}$/i),
1494
- payerSignature: z6.string().regex(/^[0-9a-f]+$/i),
1495
- payeePubkey: z6.string().regex(/^[0-9a-f]{64}$/i).optional(),
1496
- payeeSignature: z6.string().regex(/^[0-9a-f]+$/i).optional()
1497
- });
1498
- var SettlementSchema = z6.object({
1499
- settlementId: z6.string().uuid(),
1500
- settlementKey: z6.string().regex(/^[0-9a-f]{64}$/i),
1501
- encounterId: z6.string().regex(/^[0-9a-f]{64}$/i),
1502
- issuerAccountId: z6.string().uuid(),
1503
- tokenSerial: z6.string(),
1504
- payerUserId: z6.string().uuid(),
1505
- payeeUserId: z6.string().uuid(),
1506
- amountKobo: z6.number().int().nonnegative(),
1507
- currency: z6.string().length(3),
1508
- receiptId: z6.string().nullable(),
1509
- status: z6.enum(["SETTLED", "REVIEW", "REJECTED"]),
1510
- issuerSig: z6.string(),
1511
- createdAtMs: z6.number().int().nonnegative()
1512
- });
1513
- var SettleResponseSchema = z6.object({
1835
+ var OfflineTokenSchema = z7.object({
1836
+ tokenId: z7.string().uuid(),
1837
+ tokenSerial: z7.string(),
1838
+ issuerAccountId: z7.string().uuid(),
1839
+ payerUserId: z7.string().uuid(),
1840
+ maxAmountKobo: z7.number().int().positive(),
1841
+ currency: z7.string().length(3),
1842
+ issuedAtMs: z7.number().int().nonnegative(),
1843
+ expiresAtMs: z7.number().int().nonnegative(),
1844
+ issuerSig: z7.string()
1845
+ });
1846
+ var PaymentClaimSchema = z7.object({
1847
+ encounterId: z7.string().regex(/^[0-9a-f]{64}$/i).optional(),
1848
+ tokenSerial: z7.string(),
1849
+ payerUserId: z7.string().uuid(),
1850
+ payeeUserId: z7.string().uuid(),
1851
+ payerNonce: z7.string(),
1852
+ payeeNonce: z7.string(),
1853
+ amountKobo: z7.number().int().positive(),
1854
+ currency: z7.string().length(3).default("NGN"),
1855
+ occurredAtMs: z7.number().int().nonnegative(),
1856
+ completedAtMs: z7.number().int().nonnegative().optional(),
1857
+ contextId: z7.string().optional(),
1858
+ payerPubkey: z7.string().regex(/^[0-9a-f]{64}$/i),
1859
+ payerSignature: z7.string().regex(/^[0-9a-f]+$/i),
1860
+ payeePubkey: z7.string().regex(/^[0-9a-f]{64}$/i).optional(),
1861
+ payeeSignature: z7.string().regex(/^[0-9a-f]+$/i).optional()
1862
+ });
1863
+ var SettlementSchema = z7.object({
1864
+ settlementId: z7.string().uuid(),
1865
+ settlementKey: z7.string().regex(/^[0-9a-f]{64}$/i),
1866
+ encounterId: z7.string().regex(/^[0-9a-f]{64}$/i),
1867
+ issuerAccountId: z7.string().uuid(),
1868
+ tokenSerial: z7.string(),
1869
+ payerUserId: z7.string().uuid(),
1870
+ payeeUserId: z7.string().uuid(),
1871
+ amountKobo: z7.number().int().nonnegative(),
1872
+ currency: z7.string().length(3),
1873
+ receiptId: z7.string().nullable(),
1874
+ status: z7.enum(["SETTLED", "REVIEW", "REJECTED"]),
1875
+ issuerSig: z7.string(),
1876
+ createdAtMs: z7.number().int().nonnegative()
1877
+ });
1878
+ var SettleResponseSchema = z7.object({
1514
1879
  settlement: SettlementSchema,
1515
- encounterId: z6.string().regex(/^[0-9a-f]{64}$/i),
1516
- replayed: z6.boolean()
1880
+ encounterId: z7.string().regex(/^[0-9a-f]{64}$/i),
1881
+ replayed: z7.boolean()
1517
1882
  });
1518
1883
  var ENCOUNTER_DOMAIN = "offline:v1:encounter";
1519
1884
  async function sha256Hex(input) {
@@ -1686,134 +2051,352 @@ function createHmacFetch(opts) {
1686
2051
  });
1687
2052
  }
1688
2053
 
1689
- // src/passes/pass.ts
1690
- import { z as z7 } from "zod";
1691
- var PASS_KINDS = [
1692
- "ride-ticket",
1693
- "transit-pass",
1694
- "event-ticket",
1695
- "voucher",
1696
- "loyalty",
1697
- "receipt-link"
1698
- ];
1699
- var PASS_STATES = [
1700
- "issued",
1701
- "active",
1702
- "redeemed",
1703
- "expired",
1704
- "revoked"
2054
+ // src/partner/client.ts
2055
+ import { z as z8 } from "zod";
2056
+ import { sha256 as sha2563 } from "@noble/hashes/sha256";
2057
+ import { hmac as hmac2 } from "@noble/hashes/hmac";
2058
+ import { bytesToHex as bytesToHex4 } from "@noble/hashes/utils";
2059
+ var PARTNER_SCOPES = [
2060
+ "passes:write",
2061
+ "passes:read",
2062
+ "passes:redeem",
2063
+ "receipts:write",
2064
+ "receipts:read",
2065
+ "offline:issue",
2066
+ "offline:settle",
2067
+ "offline:read",
2068
+ "collections:write",
2069
+ "collections:read",
2070
+ "collections:pay",
2071
+ "collections:webhook",
2072
+ "reports:read",
2073
+ "payouts:write",
2074
+ "payouts:read",
2075
+ "partner:funding:write",
2076
+ "partner:payout:write",
2077
+ "partner:reconciliation:read"
1705
2078
  ];
1706
- var HexString2 = (length) => z7.string().regex(
1707
- new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
1708
- `expected ${length}-byte hex string`
1709
- );
1710
- var PassMetadataSchema = z7.record(
1711
- z7.union([z7.string(), z7.number(), z7.boolean(), z7.null()])
1712
- );
1713
- var PassSchema = z7.object({
1714
- passId: z7.string().min(1),
1715
- /** Optional client/template grouping id (server may omit). */
1716
- templateId: z7.string().min(1).optional(),
1717
- /** Optional human-facing holder identity (server may omit). The cryptographic binding
1718
- * is `holderDevicePubkey` below. */
1719
- holderUserId: z7.string().min(1).optional(),
1720
- kind: z7.enum(PASS_KINDS),
1721
- issuerId: z7.string().min(1),
1722
- issuedAtMs: z7.number().int().nonnegative(),
1723
- validFromMs: z7.number().int().nonnegative(),
1724
- validUntilMs: z7.number().int().positive(),
1725
- state: z7.enum(PASS_STATES),
1726
- metadata: PassMetadataSchema,
1727
- nonce: z7.string().min(1),
1728
- /** Device id this pass is bound to (FK to backend `device_keys`). */
1729
- holderDeviceId: z7.string().min(1),
1730
- /** 32-byte hex Ed25519 public key of the bound device. The redemption signature
1731
- * is verified against this key — it is the security-critical binding. */
1732
- holderDevicePubkey: HexString2(32),
1733
- /** Optional fixed amount for monetary passes (vouchers, gift cards) in kobo. */
1734
- amountKobo: z7.number().int().nonnegative().optional(),
1735
- /** ISO-4217-ish currency code; required on the wire. SDK builders default to NGN. */
1736
- currency: z7.string().min(3).max(8),
1737
- /** Monotonic redemption counter floor. Redemption.counter MUST be > counterSeed. */
1738
- counterSeed: z7.number().int().nonnegative(),
1739
- /** Optional cumulative spend cap in kobo across all redemptions of this pass. */
1740
- cumulativeCapKobo: z7.number().int().nonnegative().optional(),
1741
- issuerSig: HexString2(64)
1742
- }).refine((v) => v.validUntilMs > v.validFromMs, {
1743
- message: "validUntilMs must be greater than validFromMs"
2079
+ var ApiCredentialPublicSchema = z8.object({
2080
+ id: z8.string().uuid(),
2081
+ accountId: z8.string().uuid(),
2082
+ keyId: z8.string(),
2083
+ scopes: z8.array(z8.enum(PARTNER_SCOPES)),
2084
+ label: z8.string().nullable(),
2085
+ createdAtMs: z8.number().int().nonnegative(),
2086
+ lastUsedAtMs: z8.number().int().nonnegative().nullable(),
2087
+ revokedAtMs: z8.number().int().nonnegative().nullable()
1744
2088
  });
1745
- function buildPass(input) {
1746
- if (input.validUntilMs <= input.validFromMs) {
1747
- throw new Error("validUntilMs must be greater than validFromMs");
1748
- }
1749
- const out = {
1750
- passId: input.passId,
1751
- kind: input.kind,
1752
- issuerId: input.issuerId,
1753
- issuedAtMs: input.issuedAtMs,
1754
- validFromMs: input.validFromMs,
1755
- validUntilMs: input.validUntilMs,
1756
- state: input.state,
1757
- metadata: input.metadata,
1758
- nonce: input.nonce,
1759
- holderDeviceId: input.holderDeviceId,
1760
- holderDevicePubkey: input.holderDevicePubkey,
1761
- currency: input.currency ?? "NGN",
1762
- counterSeed: input.counterSeed
1763
- };
1764
- if (typeof input.templateId === "string") out.templateId = input.templateId;
1765
- if (typeof input.holderUserId === "string")
1766
- out.holderUserId = input.holderUserId;
1767
- if (typeof input.amountKobo === "number") out.amountKobo = input.amountKobo;
1768
- if (typeof input.cumulativeCapKobo === "number") {
1769
- out.cumulativeCapKobo = input.cumulativeCapKobo;
1770
- }
1771
- return out;
2089
+ var MintedApiCredentialSchema = ApiCredentialPublicSchema.extend({
2090
+ secret: z8.string().min(1)
2091
+ });
2092
+ var enc = new TextEncoder();
2093
+ async function sha256Hex2(input) {
2094
+ const data = typeof input === "string" ? enc.encode(input) : input;
2095
+ return bytesToHex4(sha2563(data));
1772
2096
  }
1773
- function signPass(unsigned, issuerPrivateKey) {
1774
- const issuerSig = bytesToHex(
1775
- sign(canonicalJSONBytes(unsigned), issuerPrivateKey)
1776
- );
1777
- return { ...unsigned, issuerSig };
2097
+ async function hmacSha256Hex(keyHex, message) {
2098
+ return bytesToHex4(hmac2(sha2563, enc.encode(keyHex), enc.encode(message)));
1778
2099
  }
1779
- function verifyPass(pass, issuerPublicKey) {
1780
- try {
1781
- const parsed = PassSchema.parse(pass);
1782
- const { issuerSig, ...unsigned } = parsed;
1783
- return verify(
1784
- canonicalJSONBytes(unsigned),
1785
- hexToBytes(issuerSig),
1786
- issuerPublicKey
1787
- );
1788
- } catch {
1789
- return false;
1790
- }
2100
+ function defaultNonce2() {
2101
+ const c = globalThis.crypto;
2102
+ if (c?.randomUUID) return c.randomUUID();
2103
+ return `${Date.now().toString(16)}-${Math.random().toString(16).slice(2)}`;
1791
2104
  }
1792
- function isPassWithinValidity(pass, nowMs) {
1793
- return nowMs >= pass.validFromMs && nowMs < pass.validUntilMs;
2105
+ function canonical(params) {
2106
+ return [
2107
+ params.method.toUpperCase(),
2108
+ params.path,
2109
+ params.ts,
2110
+ params.nonce,
2111
+ params.bodyHash
2112
+ ].join("\n");
1794
2113
  }
1795
-
1796
- // src/passes/redemption.ts
1797
- import { z as z8 } from "zod";
1798
- var HexSig2 = z8.string().regex(/^[0-9a-fA-F]{128}$/, "expected 64-byte hex signature");
1799
- var RedemptionSchema = z8.object({
1800
- pass: PassSchema,
1801
- redeemerId: z8.string().min(1),
1802
- redeemedAtMs: z8.number().int().nonnegative(),
1803
- /** Strictly monotonic counter scoped to a single pass. Must be > pass.counterSeed
1804
- * and > the redeemer's lastSeenCounter for this pass. */
1805
- counter: z8.number().int().positive(),
1806
- /** Amount being redeemed in kobo (0 for non-monetary passes like ride tickets). */
1807
- amountKobo: z8.number().int().nonnegative(),
1808
- nonce: z8.string().min(1),
1809
- holderSig: HexSig2
1810
- });
1811
- var REDEEMABLE_STATES = /* @__PURE__ */ new Set(["issued", "active"]);
1812
- function buildRedemption(input) {
1813
- if (!REDEEMABLE_STATES.has(input.pass.state)) {
1814
- throw new Error(`pass not in redeemable state: ${input.pass.state}`);
1815
- }
1816
- if (input.redeemedAtMs < input.pass.validFromMs) {
2114
+ async function signPartnerRequest(params) {
2115
+ const ts = String(Math.floor((params.nowMs ?? Date.now()) / 1e3));
2116
+ const nonce = params.nonce ?? defaultNonce2();
2117
+ const bodyData = typeof params.body === "string" ? enc.encode(params.body) : params.body ?? new Uint8Array();
2118
+ const bodyHash = await sha256Hex2(bodyData);
2119
+ const message = canonical({
2120
+ method: params.method,
2121
+ path: params.path,
2122
+ ts,
2123
+ nonce,
2124
+ bodyHash
2125
+ });
2126
+ const signingKey = await sha256Hex2(params.secret);
2127
+ const sig = await hmacSha256Hex(signingKey, message);
2128
+ return {
2129
+ authorization: `Flur-Hmac key=${params.keyId}, ts=${ts}, nonce=${nonce}, sig=${sig}`,
2130
+ ts,
2131
+ nonce,
2132
+ bodyHash
2133
+ };
2134
+ }
2135
+ function createFlurPartnerClient(opts) {
2136
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
2137
+ if (!fetchImpl) {
2138
+ throw new Error(
2139
+ "createFlurPartnerClient: no fetch implementation available"
2140
+ );
2141
+ }
2142
+ const baseUrl = opts.baseUrl.replace(/\/$/, "");
2143
+ const scopeHeader = normalizeScopeHeader(opts.scope);
2144
+ async function makeSignedInit(method, path, body) {
2145
+ const sig = await signPartnerRequest({
2146
+ keyId: opts.keyId,
2147
+ secret: opts.secret,
2148
+ method,
2149
+ path,
2150
+ body: body ?? "",
2151
+ nowMs: opts.nowMs?.(),
2152
+ nonce: opts.nonce?.()
2153
+ });
2154
+ const headers = {
2155
+ authorization: sig.authorization,
2156
+ accept: "application/json"
2157
+ };
2158
+ if (scopeHeader) headers["x-flur-scope"] = scopeHeader;
2159
+ if (body !== void 0) headers["content-type"] = "application/json";
2160
+ const init2 = { method, headers };
2161
+ if (body !== void 0) init2.body = body;
2162
+ return init2;
2163
+ }
2164
+ async function request(opts2) {
2165
+ const bodyStr = opts2.body === void 0 ? void 0 : JSON.stringify(opts2.body);
2166
+ const init2 = await makeSignedInit(opts2.method, opts2.path, bodyStr);
2167
+ const resp = await fetchImpl(`${baseUrl}${opts2.path}`, init2);
2168
+ const text = await resp.text();
2169
+ let raw;
2170
+ if (text) {
2171
+ try {
2172
+ raw = JSON.parse(text);
2173
+ } catch {
2174
+ }
2175
+ }
2176
+ if (!resp.ok) {
2177
+ const code = raw && typeof raw === "object" && "code" in raw && typeof raw.code === "string" ? raw.code : `http_${resp.status}`;
2178
+ const message = raw && typeof raw === "object" && "message" in raw && typeof raw.message === "string" ? raw.message : `request failed with status ${resp.status}`;
2179
+ throw new FlurApiError(resp.status, code, message, raw);
2180
+ }
2181
+ return raw;
2182
+ }
2183
+ const fetchLike = async (input, init2) => {
2184
+ const url = typeof input === "string" ? input : input.toString();
2185
+ const u = new URL(url, baseUrl);
2186
+ const path = `${u.pathname}${u.search}`;
2187
+ const method = (init2?.method ?? "GET").toUpperCase();
2188
+ let bodyStr;
2189
+ if (init2?.body) {
2190
+ bodyStr = typeof init2.body === "string" ? init2.body : init2.body.toString();
2191
+ }
2192
+ const signed = await makeSignedInit(method, path, bodyStr);
2193
+ return fetchImpl(`${baseUrl}${path}`, {
2194
+ ...init2,
2195
+ ...signed,
2196
+ headers: {
2197
+ ...init2?.headers,
2198
+ ...signed.headers
2199
+ }
2200
+ });
2201
+ };
2202
+ return { request, fetch: fetchLike };
2203
+ }
2204
+ function normalizeScopeHeader(scope) {
2205
+ if (!scope || scope.length === 0) return void 0;
2206
+ const unique = Array.from(new Set(scope));
2207
+ for (const item of unique) {
2208
+ if (!PARTNER_SCOPES.includes(item)) {
2209
+ throw new Error(`unsupported partner scope: ${item}`);
2210
+ }
2211
+ }
2212
+ return unique.join(" ");
2213
+ }
2214
+ function createApiCredentialsAdminClient(opts) {
2215
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
2216
+ if (!fetchImpl) {
2217
+ throw new Error(
2218
+ "createApiCredentialsAdminClient: no fetch implementation available"
2219
+ );
2220
+ }
2221
+ const baseUrl = opts.baseUrl.replace(/\/$/, "");
2222
+ async function call(method, path, body, parser) {
2223
+ const init2 = {
2224
+ method,
2225
+ headers: {
2226
+ "content-type": "application/json",
2227
+ accept: "application/json"
2228
+ }
2229
+ };
2230
+ if (body !== void 0) init2.body = JSON.stringify(body);
2231
+ const resp = await fetchImpl(`${baseUrl}${path}`, init2);
2232
+ const text = await resp.text();
2233
+ let raw;
2234
+ if (text) {
2235
+ try {
2236
+ raw = JSON.parse(text);
2237
+ } catch {
2238
+ }
2239
+ }
2240
+ if (!resp.ok) {
2241
+ const code = raw && typeof raw === "object" && "code" in raw && typeof raw.code === "string" ? raw.code : `http_${resp.status}`;
2242
+ const message = raw && typeof raw === "object" && "message" in raw && typeof raw.message === "string" ? raw.message : `request failed with status ${resp.status}`;
2243
+ throw new FlurApiError(resp.status, code, message, raw);
2244
+ }
2245
+ return parser(raw);
2246
+ }
2247
+ const listSchema = z8.object({
2248
+ items: z8.array(ApiCredentialPublicSchema)
2249
+ });
2250
+ return {
2251
+ list: (accountId) => call(
2252
+ "GET",
2253
+ `/v1/accounts/${accountId}/api-credentials`,
2254
+ void 0,
2255
+ (raw) => listSchema.parse(raw)
2256
+ ),
2257
+ mint: (accountId, input) => call(
2258
+ "POST",
2259
+ `/v1/accounts/${accountId}/api-credentials`,
2260
+ input,
2261
+ (raw) => MintedApiCredentialSchema.parse(raw)
2262
+ ),
2263
+ revoke: (accountId, credentialId) => call(
2264
+ "DELETE",
2265
+ `/v1/accounts/${accountId}/api-credentials/${credentialId}`,
2266
+ void 0,
2267
+ (raw) => ApiCredentialPublicSchema.parse(raw)
2268
+ )
2269
+ };
2270
+ }
2271
+
2272
+ // src/passes/pass.ts
2273
+ import { z as z9 } from "zod";
2274
+ var PASS_KINDS = [
2275
+ "ride-ticket",
2276
+ "transit-pass",
2277
+ "event-ticket",
2278
+ "voucher",
2279
+ "loyalty",
2280
+ "receipt-link"
2281
+ ];
2282
+ var PASS_STATES = [
2283
+ "issued",
2284
+ "active",
2285
+ "redeemed",
2286
+ "expired",
2287
+ "revoked"
2288
+ ];
2289
+ var HexString2 = (length) => z9.string().regex(
2290
+ new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
2291
+ `expected ${length}-byte hex string`
2292
+ );
2293
+ var PassMetadataSchema = z9.record(
2294
+ z9.union([z9.string(), z9.number(), z9.boolean(), z9.null()])
2295
+ );
2296
+ var PassSchema = z9.object({
2297
+ passId: z9.string().min(1),
2298
+ /** Optional client/template grouping id (server may omit). */
2299
+ templateId: z9.string().min(1).optional(),
2300
+ /** Optional human-facing holder identity (server may omit). The cryptographic binding
2301
+ * is `holderDevicePubkey` below. */
2302
+ holderUserId: z9.string().min(1).optional(),
2303
+ kind: z9.enum(PASS_KINDS),
2304
+ issuerId: z9.string().min(1),
2305
+ issuedAtMs: z9.number().int().nonnegative(),
2306
+ validFromMs: z9.number().int().nonnegative(),
2307
+ validUntilMs: z9.number().int().positive(),
2308
+ state: z9.enum(PASS_STATES),
2309
+ metadata: PassMetadataSchema,
2310
+ nonce: z9.string().min(1),
2311
+ /** Device id this pass is bound to (FK to backend `device_keys`). */
2312
+ holderDeviceId: z9.string().min(1),
2313
+ /** 32-byte hex Ed25519 public key of the bound device. The redemption signature
2314
+ * is verified against this key — it is the security-critical binding. */
2315
+ holderDevicePubkey: HexString2(32),
2316
+ /** Optional fixed amount for monetary passes (vouchers, gift cards) in kobo. */
2317
+ amountKobo: z9.number().int().nonnegative().optional(),
2318
+ /** ISO-4217-ish currency code; required on the wire. SDK builders default to NGN. */
2319
+ currency: z9.string().min(3).max(8),
2320
+ /** Monotonic redemption counter floor. Redemption.counter MUST be > counterSeed. */
2321
+ counterSeed: z9.number().int().nonnegative(),
2322
+ /** Optional cumulative spend cap in kobo across all redemptions of this pass. */
2323
+ cumulativeCapKobo: z9.number().int().nonnegative().optional(),
2324
+ issuerSig: HexString2(64)
2325
+ }).refine((v) => v.validUntilMs > v.validFromMs, {
2326
+ message: "validUntilMs must be greater than validFromMs"
2327
+ });
2328
+ function buildPass(input) {
2329
+ if (input.validUntilMs <= input.validFromMs) {
2330
+ throw new Error("validUntilMs must be greater than validFromMs");
2331
+ }
2332
+ const out = {
2333
+ passId: input.passId,
2334
+ kind: input.kind,
2335
+ issuerId: input.issuerId,
2336
+ issuedAtMs: input.issuedAtMs,
2337
+ validFromMs: input.validFromMs,
2338
+ validUntilMs: input.validUntilMs,
2339
+ state: input.state,
2340
+ metadata: input.metadata,
2341
+ nonce: input.nonce,
2342
+ holderDeviceId: input.holderDeviceId,
2343
+ holderDevicePubkey: input.holderDevicePubkey,
2344
+ currency: input.currency ?? "NGN",
2345
+ counterSeed: input.counterSeed
2346
+ };
2347
+ if (typeof input.templateId === "string") out.templateId = input.templateId;
2348
+ if (typeof input.holderUserId === "string")
2349
+ out.holderUserId = input.holderUserId;
2350
+ if (typeof input.amountKobo === "number") out.amountKobo = input.amountKobo;
2351
+ if (typeof input.cumulativeCapKobo === "number") {
2352
+ out.cumulativeCapKobo = input.cumulativeCapKobo;
2353
+ }
2354
+ return out;
2355
+ }
2356
+ function signPass(unsigned, issuerPrivateKey) {
2357
+ const issuerSig = bytesToHex(
2358
+ sign(canonicalJSONBytes(unsigned), issuerPrivateKey)
2359
+ );
2360
+ return { ...unsigned, issuerSig };
2361
+ }
2362
+ function verifyPass(pass, issuerPublicKey) {
2363
+ try {
2364
+ const parsed = PassSchema.parse(pass);
2365
+ const { issuerSig, ...unsigned } = parsed;
2366
+ return verify(
2367
+ canonicalJSONBytes(unsigned),
2368
+ hexToBytes(issuerSig),
2369
+ issuerPublicKey
2370
+ );
2371
+ } catch {
2372
+ return false;
2373
+ }
2374
+ }
2375
+ function isPassWithinValidity(pass, nowMs) {
2376
+ return nowMs >= pass.validFromMs && nowMs < pass.validUntilMs;
2377
+ }
2378
+
2379
+ // src/passes/redemption.ts
2380
+ import { z as z10 } from "zod";
2381
+ var HexSig2 = z10.string().regex(/^[0-9a-fA-F]{128}$/, "expected 64-byte hex signature");
2382
+ var RedemptionSchema = z10.object({
2383
+ pass: PassSchema,
2384
+ redeemerId: z10.string().min(1),
2385
+ redeemedAtMs: z10.number().int().nonnegative(),
2386
+ /** Strictly monotonic counter scoped to a single pass. Must be > pass.counterSeed
2387
+ * and > the redeemer's lastSeenCounter for this pass. */
2388
+ counter: z10.number().int().positive(),
2389
+ /** Amount being redeemed in kobo (0 for non-monetary passes like ride tickets). */
2390
+ amountKobo: z10.number().int().nonnegative(),
2391
+ nonce: z10.string().min(1),
2392
+ holderSig: HexSig2
2393
+ });
2394
+ var REDEEMABLE_STATES = /* @__PURE__ */ new Set(["issued", "active"]);
2395
+ function buildRedemption(input) {
2396
+ if (!REDEEMABLE_STATES.has(input.pass.state)) {
2397
+ throw new Error(`pass not in redeemable state: ${input.pass.state}`);
2398
+ }
2399
+ if (input.redeemedAtMs < input.pass.validFromMs) {
1817
2400
  throw new Error("redeemedAtMs is before pass validFromMs");
1818
2401
  }
1819
2402
  if (input.redeemedAtMs >= input.pass.validUntilMs) {
@@ -1891,43 +2474,43 @@ function verifyRedemption(r, issuerPublicKey) {
1891
2474
  }
1892
2475
 
1893
2476
  // src/receipts/receipt.ts
1894
- import { z as z9 } from "zod";
2477
+ import { z as z11 } from "zod";
1895
2478
  var RECEIPT_CHANNELS = ["cash", "pass"];
1896
2479
  var RECEIPT_KINDS = RECEIPT_CHANNELS;
1897
- var HexString3 = (length) => z9.string().regex(
2480
+ var HexString3 = (length) => z11.string().regex(
1898
2481
  new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
1899
2482
  `expected ${length}-byte hex string`
1900
2483
  );
1901
- var ReceiptPayloadSchema = z9.record(
1902
- z9.union([z9.string(), z9.number(), z9.boolean(), z9.null()])
2484
+ var ReceiptPayloadSchema = z11.record(
2485
+ z11.union([z11.string(), z11.number(), z11.boolean(), z11.null()])
1903
2486
  );
1904
- var ReceiptSchema = z9.object({
1905
- receiptId: z9.string().min(1),
1906
- channel: z9.enum(RECEIPT_CHANNELS),
2487
+ var ReceiptSchema = z11.object({
2488
+ receiptId: z11.string().min(1),
2489
+ channel: z11.enum(RECEIPT_CHANNELS),
1907
2490
  /** Cash-channel: send_intents.id. Required when channel === 'cash'. */
1908
- intentId: z9.string().min(1).optional(),
2491
+ intentId: z11.string().min(1).optional(),
1909
2492
  /** Pass-channel: pass_redemptions.id. Required when channel === 'pass'. */
1910
- passRedemptionId: z9.string().min(1).optional(),
1911
- payerUserId: z9.string().min(1),
1912
- payeeUserId: z9.string().min(1),
1913
- amountKobo: z9.number().int().nonnegative(),
1914
- currency: z9.string().min(3).max(8),
1915
- issuedAtMs: z9.number().int().nonnegative(),
1916
- issuerId: z9.string().min(1),
2493
+ passRedemptionId: z11.string().min(1).optional(),
2494
+ payerUserId: z11.string().min(1),
2495
+ payeeUserId: z11.string().min(1),
2496
+ amountKobo: z11.number().int().nonnegative(),
2497
+ currency: z11.string().min(3).max(8),
2498
+ issuedAtMs: z11.number().int().nonnegative(),
2499
+ issuerId: z11.string().min(1),
1917
2500
  payload: ReceiptPayloadSchema,
1918
2501
  issuerSig: HexString3(64)
1919
2502
  }).superRefine((v, ctx) => {
1920
2503
  if (v.channel === "cash") {
1921
2504
  if (!v.intentId) {
1922
2505
  ctx.addIssue({
1923
- code: z9.ZodIssueCode.custom,
2506
+ code: z11.ZodIssueCode.custom,
1924
2507
  message: "cash receipts require intentId",
1925
2508
  path: ["intentId"]
1926
2509
  });
1927
2510
  }
1928
2511
  if (v.passRedemptionId) {
1929
2512
  ctx.addIssue({
1930
- code: z9.ZodIssueCode.custom,
2513
+ code: z11.ZodIssueCode.custom,
1931
2514
  message: "cash receipts must not carry passRedemptionId",
1932
2515
  path: ["passRedemptionId"]
1933
2516
  });
@@ -1935,14 +2518,14 @@ var ReceiptSchema = z9.object({
1935
2518
  } else if (v.channel === "pass") {
1936
2519
  if (!v.passRedemptionId) {
1937
2520
  ctx.addIssue({
1938
- code: z9.ZodIssueCode.custom,
2521
+ code: z11.ZodIssueCode.custom,
1939
2522
  message: "pass receipts require passRedemptionId",
1940
2523
  path: ["passRedemptionId"]
1941
2524
  });
1942
2525
  }
1943
2526
  if (v.intentId) {
1944
2527
  ctx.addIssue({
1945
- code: z9.ZodIssueCode.custom,
2528
+ code: z11.ZodIssueCode.custom,
1946
2529
  message: "pass receipts must not carry intentId",
1947
2530
  path: ["intentId"]
1948
2531
  });
@@ -2181,317 +2764,90 @@ function createReceiptsClient(opts) {
2181
2764
  verifyReceipt: (receipt, issuerPublicKey) => verifyReceipt(receipt, issuerPublicKey)
2182
2765
  };
2183
2766
  }
2184
-
2185
- // src/client/flur.ts
2186
- function generateStaticQR(input) {
2187
- return encodeNQR({ ...input, pointOfInitiation: "static" });
2188
- }
2189
- function generateDynamicQR(input) {
2190
- return encodeNQR({ ...input, pointOfInitiation: "dynamic" });
2191
- }
2192
- function parseQR(payload) {
2193
- return parseNQR(payload);
2194
- }
2195
- function init(opts) {
2196
- const signedFetch = createHmacFetch({
2197
- apiKey: opts.apiKey,
2198
- apiSecret: opts.apiSecret,
2199
- fetchImpl: opts.fetchImpl,
2200
- scope: opts.scope
2201
- });
2202
- const baseUrl = opts.baseUrl.replace(/\/$/, "");
2203
- function subscribeToPayments(s) {
2204
- const controller = new AbortController();
2205
- let cancelled = false;
2206
- (async () => {
2207
- try {
2208
- const url = `${baseUrl}/v1/payments/subscribe?reference=${encodeURIComponent(s.reference)}`;
2209
- const resp = await signedFetch(url, {
2210
- method: "GET",
2211
- headers: { accept: "text/event-stream" },
2212
- signal: controller.signal
2213
- });
2214
- if (!resp.body) return;
2215
- const reader = resp.body.getReader();
2216
- const decoder = new TextDecoder();
2217
- let buffer = "";
2218
- while (!cancelled) {
2219
- const { value, done } = await reader.read();
2220
- if (done) return;
2221
- buffer += decoder.decode(value, { stream: true });
2222
- let idx;
2223
- while ((idx = buffer.indexOf("\n\n")) >= 0) {
2224
- const chunk = buffer.slice(0, idx);
2225
- buffer = buffer.slice(idx + 2);
2226
- for (const line of chunk.split("\n")) {
2227
- if (!line.startsWith("data:")) continue;
2228
- const json = line.slice(5).trim();
2229
- if (!json) continue;
2230
- try {
2231
- s.onEvent(JSON.parse(json));
2232
- } catch (err) {
2233
- s.onError?.(err);
2234
- }
2235
- }
2236
- }
2237
- }
2238
- } catch (err) {
2239
- if (!cancelled) s.onError?.(err);
2240
- }
2241
- })();
2242
- return () => {
2243
- cancelled = true;
2244
- controller.abort();
2245
- };
2246
- }
2247
- const cash = {
2248
- generateStaticQR,
2249
- generateDynamicQR,
2250
- parseQR,
2251
- subscribeToPayments
2252
- };
2253
- const passes = createPassesClient({ baseUrl, fetchImpl: signedFetch });
2254
- const receipts = createReceiptsClient({ baseUrl, fetchImpl: signedFetch });
2255
- return {
2256
- // top-level back-compat surface
2257
- generateStaticQR,
2258
- generateDynamicQR,
2259
- parseQR,
2260
- subscribeToPayments,
2261
- // namespaces
2262
- cash,
2263
- passes,
2264
- receipts
2265
- };
2266
- }
2267
-
2268
- // src/accounts/client.ts
2269
- import { z as z10 } from "zod";
2270
- var ACCOUNT_TYPES = ["personal", "business", "partner"];
2271
- var ACCOUNT_STATUSES = ["active", "suspended", "closed"];
2272
- var MEMBERSHIP_ROLES = ["owner", "admin", "driver", "staff"];
2273
- var AccountSchema = z10.object({
2274
- accountId: z10.string().uuid(),
2275
- type: z10.enum(ACCOUNT_TYPES),
2276
- displayName: z10.string().min(1),
2277
- status: z10.enum(ACCOUNT_STATUSES),
2278
- ownerUserId: z10.string().uuid().nullable(),
2279
- createdAtMs: z10.number().int().nonnegative()
2280
- });
2281
- var AccountMembershipSchema = z10.object({
2282
- accountId: z10.string().uuid(),
2283
- userId: z10.string().uuid(),
2284
- role: z10.enum(MEMBERSHIP_ROLES),
2285
- createdAtMs: z10.number().int().nonnegative()
2286
- });
2287
- function createAccountsClient(opts) {
2288
- const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
2289
- if (!fetchImpl) {
2290
- throw new Error("createAccountsClient: no fetch implementation available");
2291
- }
2292
- const baseUrl = opts.baseUrl.replace(/\/$/, "");
2293
- async function call(method, path, body, parser) {
2294
- const init2 = {
2295
- method,
2296
- headers: {
2297
- "content-type": "application/json",
2298
- accept: "application/json"
2299
- }
2300
- };
2301
- if (body !== void 0) init2.body = JSON.stringify(body);
2302
- const resp = await fetchImpl(`${baseUrl}${path}`, init2);
2303
- const text = await resp.text();
2304
- let raw = void 0;
2305
- if (text) {
2306
- try {
2307
- raw = JSON.parse(text);
2308
- } catch {
2309
- }
2310
- }
2311
- if (!resp.ok) {
2312
- const code = raw && typeof raw === "object" && "code" in raw && typeof raw.code === "string" ? raw.code : `http_${resp.status}`;
2313
- const message = raw && typeof raw === "object" && "message" in raw && typeof raw.message === "string" ? raw.message : `request failed with status ${resp.status}`;
2314
- throw new FlurApiError(resp.status, code, message, raw);
2315
- }
2316
- return parser(raw);
2317
- }
2318
- const itemsSchema = z10.object({ items: z10.array(AccountSchema) });
2319
- const memberItemsSchema = z10.object({
2320
- items: z10.array(AccountMembershipSchema)
2321
- });
2322
- return {
2323
- listMyAccounts: () => call(
2324
- "GET",
2325
- "/v1/accounts/me",
2326
- void 0,
2327
- (raw) => itemsSchema.parse(raw)
2328
- ),
2329
- getAccount: (accountId) => call(
2330
- "GET",
2331
- `/v1/accounts/${encodeURIComponent(accountId)}`,
2332
- void 0,
2333
- (raw) => AccountSchema.parse(raw)
2334
- ),
2335
- listMembers: (accountId) => call(
2336
- "GET",
2337
- `/v1/accounts/${encodeURIComponent(accountId)}/members`,
2338
- void 0,
2339
- (raw) => memberItemsSchema.parse(raw)
2340
- ),
2341
- createBusinessAccount: (input) => call("POST", "/v1/accounts", input, (raw) => AccountSchema.parse(raw)),
2342
- addMember: (accountId, input) => call(
2343
- "POST",
2344
- `/v1/accounts/${encodeURIComponent(accountId)}/members`,
2345
- input,
2346
- (raw) => AccountMembershipSchema.parse(raw)
2347
- )
2348
- };
2349
- }
2350
-
2351
- // src/partner/client.ts
2352
- import { z as z11 } from "zod";
2353
- import { sha256 as sha2563 } from "@noble/hashes/sha256";
2354
- import { hmac as hmac2 } from "@noble/hashes/hmac";
2355
- import { bytesToHex as bytesToHex4 } from "@noble/hashes/utils";
2356
- var PARTNER_SCOPES = [
2357
- "passes:write",
2358
- "passes:read",
2359
- "passes:redeem",
2360
- "receipts:write",
2361
- "receipts:read",
2362
- "offline:issue",
2363
- "offline:settle",
2364
- "offline:read"
2365
- ];
2366
- var ApiCredentialPublicSchema = z11.object({
2367
- id: z11.string().uuid(),
2368
- accountId: z11.string().uuid(),
2369
- keyId: z11.string(),
2370
- scopes: z11.array(z11.enum(PARTNER_SCOPES)),
2371
- label: z11.string().nullable(),
2372
- createdAtMs: z11.number().int().nonnegative(),
2373
- lastUsedAtMs: z11.number().int().nonnegative().nullable(),
2374
- revokedAtMs: z11.number().int().nonnegative().nullable()
2375
- });
2376
- var MintedApiCredentialSchema = ApiCredentialPublicSchema.extend({
2377
- secret: z11.string().min(1)
2378
- });
2379
- var enc = new TextEncoder();
2380
- async function sha256Hex2(input) {
2381
- const data = typeof input === "string" ? enc.encode(input) : input;
2382
- return bytesToHex4(sha2563(data));
2383
- }
2384
- async function hmacSha256Hex(keyHex, message) {
2385
- return bytesToHex4(hmac2(sha2563, enc.encode(keyHex), enc.encode(message)));
2386
- }
2387
- function defaultNonce2() {
2388
- const c = globalThis.crypto;
2389
- if (c?.randomUUID) return c.randomUUID();
2390
- return `${Date.now().toString(16)}-${Math.random().toString(16).slice(2)}`;
2391
- }
2392
- function canonical(params) {
2393
- return [
2394
- params.method.toUpperCase(),
2395
- params.path,
2396
- params.ts,
2397
- params.nonce,
2398
- params.bodyHash
2399
- ].join("\n");
2400
- }
2401
- async function signPartnerRequest(params) {
2402
- const ts = String(Math.floor((params.nowMs ?? Date.now()) / 1e3));
2403
- const nonce = params.nonce ?? defaultNonce2();
2404
- const bodyData = typeof params.body === "string" ? enc.encode(params.body) : params.body ?? new Uint8Array();
2405
- const bodyHash = await sha256Hex2(bodyData);
2406
- const message = canonical({
2407
- method: params.method,
2408
- path: params.path,
2409
- ts,
2410
- nonce,
2411
- bodyHash
2412
- });
2413
- const signingKey = await sha256Hex2(params.secret);
2414
- const sig = await hmacSha256Hex(signingKey, message);
2415
- return {
2416
- authorization: `Flur-Hmac key=${params.keyId}, ts=${ts}, nonce=${nonce}, sig=${sig}`,
2417
- ts,
2418
- nonce,
2419
- bodyHash
2420
- };
2767
+
2768
+ // src/client/flur.ts
2769
+ function generateStaticQR(input) {
2770
+ return encodeNQR({ ...input, pointOfInitiation: "static" });
2421
2771
  }
2422
- function createFlurPartnerClient(opts) {
2423
- const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
2424
- if (!fetchImpl) {
2425
- throw new Error(
2426
- "createFlurPartnerClient: no fetch implementation available"
2427
- );
2428
- }
2772
+ function generateDynamicQR(input) {
2773
+ return encodeNQR({ ...input, pointOfInitiation: "dynamic" });
2774
+ }
2775
+ function parseQR(payload) {
2776
+ return parseNQR(payload);
2777
+ }
2778
+ function init(opts) {
2779
+ const partner = createFlurPartnerClient({
2780
+ baseUrl: opts.baseUrl,
2781
+ keyId: opts.apiKey,
2782
+ secret: opts.apiSecret,
2783
+ fetchImpl: opts.fetchImpl,
2784
+ scope: opts.scope
2785
+ });
2786
+ const signedFetch = partner.fetch;
2429
2787
  const baseUrl = opts.baseUrl.replace(/\/$/, "");
2430
- async function makeSignedInit(method, path, body) {
2431
- const sig = await signPartnerRequest({
2432
- keyId: opts.keyId,
2433
- secret: opts.secret,
2434
- method,
2435
- path,
2436
- body: body ?? "",
2437
- nowMs: opts.nowMs?.(),
2438
- nonce: opts.nonce?.()
2788
+ function subscribeToPayments(s) {
2789
+ let cancelled = false;
2790
+ queueMicrotask(() => {
2791
+ if (cancelled) return;
2792
+ s.onError?.(
2793
+ new Error(
2794
+ "cash.subscribeToPayments is not available on this backend release; use collections reports or provider webhooks for payment status."
2795
+ )
2796
+ );
2439
2797
  });
2440
- const headers = {
2441
- authorization: sig.authorization,
2442
- accept: "application/json"
2798
+ return () => {
2799
+ cancelled = true;
2443
2800
  };
2444
- if (body !== void 0) headers["content-type"] = "application/json";
2445
- const init2 = { method, headers };
2446
- if (body !== void 0) init2.body = body;
2447
- return init2;
2448
- }
2449
- async function request(opts2) {
2450
- const bodyStr = opts2.body === void 0 ? void 0 : JSON.stringify(opts2.body);
2451
- const init2 = await makeSignedInit(opts2.method, opts2.path, bodyStr);
2452
- const resp = await fetchImpl(`${baseUrl}${opts2.path}`, init2);
2453
- const text = await resp.text();
2454
- let raw;
2455
- if (text) {
2456
- try {
2457
- raw = JSON.parse(text);
2458
- } catch {
2459
- }
2460
- }
2461
- if (!resp.ok) {
2462
- const code = raw && typeof raw === "object" && "code" in raw && typeof raw.code === "string" ? raw.code : `http_${resp.status}`;
2463
- const message = raw && typeof raw === "object" && "message" in raw && typeof raw.message === "string" ? raw.message : `request failed with status ${resp.status}`;
2464
- throw new FlurApiError(resp.status, code, message, raw);
2465
- }
2466
- return raw;
2467
2801
  }
2468
- const fetchLike = async (input, init2) => {
2469
- const url = typeof input === "string" ? input : input.toString();
2470
- const u = new URL(url, baseUrl);
2471
- const path = `${u.pathname}${u.search}`;
2472
- const method = (init2?.method ?? "GET").toUpperCase();
2473
- let bodyStr;
2474
- if (init2?.body) {
2475
- bodyStr = typeof init2.body === "string" ? init2.body : init2.body.toString();
2476
- }
2477
- const signed = await makeSignedInit(method, path, bodyStr);
2478
- return fetchImpl(`${baseUrl}${path}`, {
2479
- ...init2,
2480
- ...signed,
2481
- headers: {
2482
- ...init2?.headers,
2483
- ...signed.headers
2484
- }
2485
- });
2802
+ const cash = {
2803
+ generateStaticQR,
2804
+ generateDynamicQR,
2805
+ parseQR,
2806
+ subscribeToPayments
2807
+ };
2808
+ const passes = createPassesClient({ baseUrl, fetchImpl: signedFetch });
2809
+ const receipts = createReceiptsClient({ baseUrl, fetchImpl: signedFetch });
2810
+ const collections = createPartnerCollectionsClient({
2811
+ baseUrl,
2812
+ fetchImpl: signedFetch
2813
+ });
2814
+ return {
2815
+ // top-level back-compat surface
2816
+ generateStaticQR,
2817
+ generateDynamicQR,
2818
+ parseQR,
2819
+ subscribeToPayments,
2820
+ // namespaces
2821
+ cash,
2822
+ collections,
2823
+ passes,
2824
+ receipts
2486
2825
  };
2487
- return { request, fetch: fetchLike };
2488
2826
  }
2489
- function createApiCredentialsAdminClient(opts) {
2827
+
2828
+ // src/accounts/client.ts
2829
+ import { z as z12 } from "zod";
2830
+ var ACCOUNT_TYPES = ["personal", "business", "partner"];
2831
+ var ACCOUNT_STATUSES = ["active", "suspended", "closed"];
2832
+ var MEMBERSHIP_ROLES = ["owner", "admin", "driver", "staff"];
2833
+ var AccountSchema = z12.object({
2834
+ accountId: z12.string().uuid(),
2835
+ type: z12.enum(ACCOUNT_TYPES),
2836
+ displayName: z12.string().min(1),
2837
+ status: z12.enum(ACCOUNT_STATUSES),
2838
+ ownerUserId: z12.string().uuid().nullable(),
2839
+ createdAtMs: z12.number().int().nonnegative()
2840
+ });
2841
+ var AccountMembershipSchema = z12.object({
2842
+ accountId: z12.string().uuid(),
2843
+ userId: z12.string().uuid(),
2844
+ role: z12.enum(MEMBERSHIP_ROLES),
2845
+ createdAtMs: z12.number().int().nonnegative()
2846
+ });
2847
+ function createAccountsClient(opts) {
2490
2848
  const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
2491
2849
  if (!fetchImpl) {
2492
- throw new Error(
2493
- "createApiCredentialsAdminClient: no fetch implementation available"
2494
- );
2850
+ throw new Error("createAccountsClient: no fetch implementation available");
2495
2851
  }
2496
2852
  const baseUrl = opts.baseUrl.replace(/\/$/, "");
2497
2853
  async function call(method, path, body, parser) {
@@ -2505,7 +2861,7 @@ function createApiCredentialsAdminClient(opts) {
2505
2861
  if (body !== void 0) init2.body = JSON.stringify(body);
2506
2862
  const resp = await fetchImpl(`${baseUrl}${path}`, init2);
2507
2863
  const text = await resp.text();
2508
- let raw;
2864
+ let raw = void 0;
2509
2865
  if (text) {
2510
2866
  try {
2511
2867
  raw = JSON.parse(text);
@@ -2519,70 +2875,78 @@ function createApiCredentialsAdminClient(opts) {
2519
2875
  }
2520
2876
  return parser(raw);
2521
2877
  }
2522
- const listSchema = z11.object({
2523
- items: z11.array(ApiCredentialPublicSchema)
2878
+ const itemsSchema = z12.object({ items: z12.array(AccountSchema) });
2879
+ const memberItemsSchema = z12.object({
2880
+ items: z12.array(AccountMembershipSchema)
2524
2881
  });
2525
2882
  return {
2526
- list: (accountId) => call(
2883
+ listMyAccounts: () => call(
2527
2884
  "GET",
2528
- `/v1/accounts/${accountId}/api-credentials`,
2885
+ "/v1/accounts/me",
2529
2886
  void 0,
2530
- (raw) => listSchema.parse(raw)
2887
+ (raw) => itemsSchema.parse(raw)
2531
2888
  ),
2532
- mint: (accountId, input) => call(
2533
- "POST",
2534
- `/v1/accounts/${accountId}/api-credentials`,
2535
- input,
2536
- (raw) => MintedApiCredentialSchema.parse(raw)
2889
+ getAccount: (accountId) => call(
2890
+ "GET",
2891
+ `/v1/accounts/${encodeURIComponent(accountId)}`,
2892
+ void 0,
2893
+ (raw) => AccountSchema.parse(raw)
2537
2894
  ),
2538
- revoke: (accountId, credentialId) => call(
2539
- "DELETE",
2540
- `/v1/accounts/${accountId}/api-credentials/${credentialId}`,
2895
+ listMembers: (accountId) => call(
2896
+ "GET",
2897
+ `/v1/accounts/${encodeURIComponent(accountId)}/members`,
2541
2898
  void 0,
2542
- (raw) => ApiCredentialPublicSchema.parse(raw)
2899
+ (raw) => memberItemsSchema.parse(raw)
2900
+ ),
2901
+ createBusinessAccount: (input) => call("POST", "/v1/accounts", input, (raw) => AccountSchema.parse(raw)),
2902
+ addMember: (accountId, input) => call(
2903
+ "POST",
2904
+ `/v1/accounts/${encodeURIComponent(accountId)}/members`,
2905
+ input,
2906
+ (raw) => AccountMembershipSchema.parse(raw)
2543
2907
  )
2544
2908
  };
2545
2909
  }
2546
2910
 
2547
2911
  // src/me-offline/client.ts
2548
- import { z as z12 } from "zod";
2549
- var Hex64 = z12.string().regex(/^[0-9a-f]{64}$/i);
2550
- var HexAny = z12.string().regex(/^[0-9a-f]+$/i);
2551
- var Sha256Hex = z12.string().regex(/^[0-9a-f]{64}$/i);
2552
- var RegisterDeviceKeyInputSchema = z12.object({
2553
- deviceId: z12.string().min(1).max(128),
2912
+ import { z as z13 } from "zod";
2913
+ var Hex64 = z13.string().regex(/^[0-9a-f]{64}$/i);
2914
+ var HexAny = z13.string().regex(/^[0-9a-f]+$/i);
2915
+ var Sha256Hex = z13.string().regex(/^[0-9a-f]{64}$/i);
2916
+ var RegisterDeviceKeyInputSchema = z13.object({
2917
+ deviceId: z13.string().min(1).max(128),
2554
2918
  publicKeyHex: Hex64
2555
2919
  });
2556
- var DeviceKeyRecordSchema = z12.object({
2557
- id: z12.string().uuid(),
2558
- userId: z12.string().uuid(),
2559
- deviceId: z12.string(),
2920
+ var DeviceKeyRecordSchema = z13.object({
2921
+ id: z13.string().uuid(),
2922
+ userId: z13.string().uuid(),
2923
+ deviceId: z13.string(),
2560
2924
  publicKeyHex: Hex64,
2561
- createdAtMs: z12.number().int().nonnegative(),
2562
- revokedAtMs: z12.number().int().nonnegative().nullable()
2925
+ createdAtMs: z13.number().int().nonnegative(),
2926
+ revokedAtMs: z13.number().int().nonnegative().nullable()
2563
2927
  });
2564
- var ConsumerOACSchema = z12.object({
2565
- oacId: z12.string().uuid(),
2566
- issuerId: z12.string().min(1).max(64),
2567
- userId: z12.string().uuid(),
2568
- deviceId: z12.string().min(1).max(128),
2928
+ var ConsumerOACSchema = z13.object({
2929
+ oacId: z13.string().uuid(),
2930
+ issuerId: z13.string().min(1).max(64),
2931
+ userId: z13.string().uuid(),
2932
+ deviceId: z13.string().min(1).max(128),
2569
2933
  devicePubkeyHex: Hex64,
2570
- perTxCapKobo: z12.number().int().positive(),
2571
- cumulativeCapKobo: z12.number().int().positive(),
2572
- currency: z12.string().length(3),
2573
- validFromMs: z12.number().int().nonnegative(),
2574
- validUntilMs: z12.number().int().nonnegative(),
2575
- counterSeed: z12.number().int().nonnegative(),
2576
- issuedAtMs: z12.number().int().nonnegative()
2577
- });
2578
- var SignedConsumerOACSchema = z12.object({
2934
+ perTxCapKobo: z13.number().int().positive(),
2935
+ cumulativeCapKobo: z13.number().int().positive(),
2936
+ currency: z13.string().length(3),
2937
+ validFromMs: z13.number().int().nonnegative(),
2938
+ validUntilMs: z13.number().int().nonnegative(),
2939
+ counterSeed: z13.number().int().nonnegative(),
2940
+ issuedAtMs: z13.number().int().nonnegative()
2941
+ });
2942
+ var SignedConsumerOACSchema = z13.object({
2579
2943
  oac: ConsumerOACSchema,
2580
2944
  issuerSig: HexAny,
2581
2945
  issuerPublicKeyHex: Hex64
2582
2946
  });
2583
2947
  var OACRecordSchema = SignedConsumerOACSchema.extend({
2584
- currentOfflineSpentKobo: z12.number().int().nonnegative(),
2585
- status: z12.enum([
2948
+ currentOfflineSpentKobo: z13.number().int().nonnegative(),
2949
+ status: z13.enum([
2586
2950
  "active",
2587
2951
  "superseded",
2588
2952
  "expired",
@@ -2591,43 +2955,43 @@ var OACRecordSchema = SignedConsumerOACSchema.extend({
2591
2955
  "draining",
2592
2956
  "closed"
2593
2957
  ]),
2594
- supersededAtMs: z12.number().int().nonnegative().nullable(),
2595
- revokedAtMs: z12.number().int().nonnegative().nullable(),
2596
- holdId: z12.string().uuid().nullable().optional()
2597
- });
2598
- var IssueOACInputSchema = z12.object({
2599
- deviceId: z12.string().min(1).max(128),
2600
- perTxCapKobo: z12.number().int().positive().optional(),
2601
- cumulativeCapKobo: z12.number().int().positive().optional(),
2602
- ttlMs: z12.number().int().min(6e4).max(1e3 * 60 * 60 * 24 * 7).optional(),
2603
- spendableOnlineKobo: z12.number().int().nonnegative().optional()
2604
- });
2605
- var EnableOfflineInputSchema = z12.object({
2606
- deviceId: z12.string().min(1).max(128),
2607
- amountKobo: z12.number().int().positive(),
2608
- perTxCapKobo: z12.number().int().positive().optional(),
2609
- ttlMs: z12.number().int().min(6e4).max(1e3 * 60 * 60 * 24 * 7).optional(),
2610
- installId: z12.string().min(1).max(128),
2611
- partnerId: z12.string().min(1).max(64).optional()
2612
- });
2613
- var DisableOfflineInputSchema = z12.object({
2614
- deviceId: z12.string().min(1).max(128),
2615
- installId: z12.string().min(1).max(128).optional(),
2616
- claims: z12.array(z12.unknown()).max(256).optional()
2617
- });
2618
- var OfflineHoldRecordSchema = z12.object({
2619
- holdId: z12.string().uuid(),
2620
- userId: z12.string().uuid(),
2621
- deviceId: z12.string(),
2622
- partnerId: z12.string(),
2623
- adapterKind: z12.string(),
2624
- externalHoldRef: z12.string().nullable(),
2625
- amountKobo: z12.number().int().nonnegative(),
2626
- capturedKobo: z12.number().int().nonnegative(),
2627
- releasedKobo: z12.number().int().nonnegative(),
2628
- remainingKobo: z12.number().int().nonnegative(),
2629
- currency: z12.string().length(3),
2630
- status: z12.enum([
2958
+ supersededAtMs: z13.number().int().nonnegative().nullable(),
2959
+ revokedAtMs: z13.number().int().nonnegative().nullable(),
2960
+ holdId: z13.string().uuid().nullable().optional()
2961
+ });
2962
+ var IssueOACInputSchema = z13.object({
2963
+ deviceId: z13.string().min(1).max(128),
2964
+ perTxCapKobo: z13.number().int().positive().optional(),
2965
+ cumulativeCapKobo: z13.number().int().positive().optional(),
2966
+ ttlMs: z13.number().int().min(6e4).max(1e3 * 60 * 60 * 24 * 7).optional(),
2967
+ spendableOnlineKobo: z13.number().int().nonnegative().optional()
2968
+ });
2969
+ var EnableOfflineInputSchema = z13.object({
2970
+ deviceId: z13.string().min(1).max(128),
2971
+ amountKobo: z13.number().int().positive(),
2972
+ perTxCapKobo: z13.number().int().positive().optional(),
2973
+ ttlMs: z13.number().int().min(6e4).max(1e3 * 60 * 60 * 24 * 7).optional(),
2974
+ installId: z13.string().min(1).max(128),
2975
+ partnerId: z13.string().min(1).max(64).optional()
2976
+ });
2977
+ var DisableOfflineInputSchema = z13.object({
2978
+ deviceId: z13.string().min(1).max(128),
2979
+ installId: z13.string().min(1).max(128).optional(),
2980
+ claims: z13.array(z13.unknown()).max(256).optional()
2981
+ });
2982
+ var OfflineHoldRecordSchema = z13.object({
2983
+ holdId: z13.string().uuid(),
2984
+ userId: z13.string().uuid(),
2985
+ deviceId: z13.string(),
2986
+ partnerId: z13.string(),
2987
+ adapterKind: z13.string(),
2988
+ externalHoldRef: z13.string().nullable(),
2989
+ amountKobo: z13.number().int().nonnegative(),
2990
+ capturedKobo: z13.number().int().nonnegative(),
2991
+ releasedKobo: z13.number().int().nonnegative(),
2992
+ remainingKobo: z13.number().int().nonnegative(),
2993
+ currency: z13.string().length(3),
2994
+ status: z13.enum([
2631
2995
  "placing",
2632
2996
  "active",
2633
2997
  "disabling",
@@ -2636,71 +3000,71 @@ var OfflineHoldRecordSchema = z12.object({
2636
3000
  "revoked",
2637
3001
  "failed"
2638
3002
  ]),
2639
- installId: z12.string().nullable(),
2640
- drainDeadlineMs: z12.number().int().nonnegative(),
2641
- disableRequestedAtMs: z12.number().int().nonnegative().nullable(),
2642
- createdAtMs: z12.number().int().nonnegative(),
2643
- closedAtMs: z12.number().int().nonnegative().nullable(),
2644
- isTrusted: z12.boolean().optional()
2645
- });
2646
- var EnableOfflineResultSchema = z12.object({
3003
+ installId: z13.string().nullable(),
3004
+ drainDeadlineMs: z13.number().int().nonnegative(),
3005
+ disableRequestedAtMs: z13.number().int().nonnegative().nullable(),
3006
+ createdAtMs: z13.number().int().nonnegative(),
3007
+ closedAtMs: z13.number().int().nonnegative().nullable(),
3008
+ isTrusted: z13.boolean().optional()
3009
+ });
3010
+ var EnableOfflineResultSchema = z13.object({
2647
3011
  hold: OfflineHoldRecordSchema,
2648
3012
  oac: OACRecordSchema
2649
3013
  });
2650
- var DisableOfflineResultSchema = z12.object({
3014
+ var DisableOfflineResultSchema = z13.object({
2651
3015
  hold: OfflineHoldRecordSchema,
2652
- trusted: z12.boolean(),
2653
- settledClaims: z12.number().int().nonnegative()
3016
+ trusted: z13.boolean(),
3017
+ settledClaims: z13.number().int().nonnegative()
2654
3018
  });
2655
- var OfflineStatusResultSchema = z12.object({
3019
+ var OfflineStatusResultSchema = z13.object({
2656
3020
  hold: OfflineHoldRecordSchema.nullable(),
2657
3021
  active: OACRecordSchema.nullable()
2658
3022
  });
2659
- var OfflineStateResultSchema = z12.object({
3023
+ var OfflineStateResultSchema = z13.object({
2660
3024
  active: OACRecordSchema.nullable()
2661
3025
  });
2662
- var ConsumerPaymentClaimSchema = z12.object({
2663
- oacId: z12.string().uuid(),
3026
+ var ConsumerPaymentClaimSchema = z13.object({
3027
+ oacId: z13.string().uuid(),
2664
3028
  encounterId: Sha256Hex.optional(),
2665
- payerUserId: z12.string().uuid(),
2666
- payeeUserId: z12.string().uuid(),
2667
- payerDeviceId: z12.string().min(1).max(128),
2668
- payerNonce: z12.string().min(8).max(128),
2669
- payeeNonce: z12.string().min(8).max(128),
2670
- amountKobo: z12.number().int().positive(),
2671
- currency: z12.string().length(3).default("NGN"),
2672
- occurredAtMs: z12.number().int().nonnegative(),
2673
- completedAtMs: z12.number().int().nonnegative().optional(),
2674
- contextId: z12.string().max(128).optional(),
3029
+ payerUserId: z13.string().uuid(),
3030
+ payeeUserId: z13.string().uuid(),
3031
+ payerDeviceId: z13.string().min(1).max(128),
3032
+ payerNonce: z13.string().min(8).max(128),
3033
+ payeeNonce: z13.string().min(8).max(128),
3034
+ amountKobo: z13.number().int().positive(),
3035
+ currency: z13.string().length(3).default("NGN"),
3036
+ occurredAtMs: z13.number().int().nonnegative(),
3037
+ completedAtMs: z13.number().int().nonnegative().optional(),
3038
+ contextId: z13.string().max(128).optional(),
2675
3039
  payerPubkeyHex: Hex64,
2676
3040
  payerSignature: HexAny,
2677
3041
  payeePubkeyHex: Hex64.optional(),
2678
3042
  payeeSignature: HexAny.optional()
2679
3043
  });
2680
- var ConsumerSettlementSchema = z12.object({
2681
- settlementId: z12.string().uuid(),
3044
+ var ConsumerSettlementSchema = z13.object({
3045
+ settlementId: z13.string().uuid(),
2682
3046
  settlementKey: Sha256Hex,
2683
3047
  encounterId: Sha256Hex,
2684
- oacId: z12.string().uuid(),
2685
- payerUserId: z12.string().uuid(),
2686
- payeeUserId: z12.string().uuid(),
2687
- amountKobo: z12.number().int().positive(),
2688
- currency: z12.string().length(3),
2689
- status: z12.enum(["SETTLED", "REVIEW"]),
2690
- reviewReason: z12.string().nullable(),
2691
- ledgerRef: z12.string().nullable(),
3048
+ oacId: z13.string().uuid(),
3049
+ payerUserId: z13.string().uuid(),
3050
+ payeeUserId: z13.string().uuid(),
3051
+ amountKobo: z13.number().int().positive(),
3052
+ currency: z13.string().length(3),
3053
+ status: z13.enum(["SETTLED", "REVIEW"]),
3054
+ reviewReason: z13.string().nullable(),
3055
+ ledgerRef: z13.string().nullable(),
2692
3056
  issuerSig: HexAny,
2693
- createdAtMs: z12.number().int().nonnegative()
3057
+ createdAtMs: z13.number().int().nonnegative()
2694
3058
  });
2695
- var ConsumerSettleResultSchema = z12.object({
3059
+ var ConsumerSettleResultSchema = z13.object({
2696
3060
  settlement: ConsumerSettlementSchema,
2697
3061
  encounterId: Sha256Hex,
2698
- replayed: z12.boolean()
3062
+ replayed: z13.boolean()
2699
3063
  });
2700
- var RevokeDeviceKeyInputSchema = z12.object({
2701
- deviceId: z12.string().min(1).max(128),
3064
+ var RevokeDeviceKeyInputSchema = z13.object({
3065
+ deviceId: z13.string().min(1).max(128),
2702
3066
  /** Step-up token from /api/v1/auth/send/verify with purpose='offline_revoke'. */
2703
- sendAuthToken: z12.string().min(16)
3067
+ sendAuthToken: z13.string().min(16)
2704
3068
  });
2705
3069
  function createMeOfflineClient(opts) {
2706
3070
  const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
@@ -2733,7 +3097,7 @@ function createMeOfflineClient(opts) {
2733
3097
  }
2734
3098
  return parser(raw);
2735
3099
  }
2736
- const deviceKeyItems = z12.object({ items: z12.array(DeviceKeyRecordSchema) });
3100
+ const deviceKeyItems = z13.object({ items: z13.array(DeviceKeyRecordSchema) });
2737
3101
  return {
2738
3102
  registerDeviceKey: (input) => call(
2739
3103
  "POST",
@@ -2797,6 +3161,320 @@ function createMeOfflineClient(opts) {
2797
3161
  )
2798
3162
  };
2799
3163
  }
3164
+
3165
+ // src/partner-funding/client.ts
3166
+ import { z as z14 } from "zod";
3167
+ var MinorString = z14.string().regex(/^-?\d+$/);
3168
+ var PositiveMinor = z14.union([
3169
+ z14.number().int().positive(),
3170
+ z14.string().regex(/^[1-9]\d{0,18}$/)
3171
+ ]);
3172
+ var Currency = z14.string().trim().length(3).transform((v) => v.toUpperCase());
3173
+ var Metadata = z14.record(z14.unknown());
3174
+ var PARTNER_KINDS = ["bank", "merchant"];
3175
+ var CUSTODIAL_MODES = ["agent_of_bank", "flur_virtual_pool"];
3176
+ var PARTNER_PROFILE_STATUSES = [
3177
+ "active",
3178
+ "suspended",
3179
+ "closed"
3180
+ ];
3181
+ var PARTNER_FUNDING_DIRECTIONS = ["credit", "debit"];
3182
+ var PARTNER_FUNDING_STATUSES = [
3183
+ "pending",
3184
+ "posted",
3185
+ "failed"
3186
+ ];
3187
+ var PAYOUT_DESTINATION_STATUSES = [
3188
+ "pending",
3189
+ "verified",
3190
+ "disabled"
3191
+ ];
3192
+ var WITHDRAWAL_STATES = [
3193
+ "requested",
3194
+ "submitted",
3195
+ "processing",
3196
+ "paid",
3197
+ "failed",
3198
+ "reversed"
3199
+ ];
3200
+ var PartnerProfileSchema = z14.object({
3201
+ partnerAccountId: z14.string().uuid(),
3202
+ kind: z14.enum(PARTNER_KINDS),
3203
+ custodialMode: z14.enum(CUSTODIAL_MODES),
3204
+ displayName: z14.string(),
3205
+ bankCode: z14.string().nullable(),
3206
+ poolAccountNumber: z14.string().nullable(),
3207
+ status: z14.enum(PARTNER_PROFILE_STATUSES),
3208
+ metadata: Metadata,
3209
+ createdAtMs: z14.number().int().nonnegative(),
3210
+ updatedAtMs: z14.number().int().nonnegative()
3211
+ });
3212
+ var UpsertPartnerProfileInputSchema = z14.object({
3213
+ kind: z14.enum(PARTNER_KINDS),
3214
+ custodialMode: z14.enum(CUSTODIAL_MODES),
3215
+ displayName: z14.string().trim().min(1).max(200),
3216
+ bankCode: z14.string().trim().min(1).max(64).optional(),
3217
+ poolAccountNumber: z14.string().trim().min(1).max(64).optional(),
3218
+ metadata: Metadata.optional()
3219
+ });
3220
+ var PartnerFundingEventInputSchema = z14.object({
3221
+ externalRef: z14.string().trim().min(8).max(128),
3222
+ direction: z14.enum(PARTNER_FUNDING_DIRECTIONS).optional(),
3223
+ userId: z14.string().uuid().optional(),
3224
+ accountId: z14.string().uuid().optional(),
3225
+ amountMinor: PositiveMinor,
3226
+ currency: Currency,
3227
+ fundingSource: z14.string().trim().min(1).max(64).optional(),
3228
+ providerMetadata: Metadata.optional()
3229
+ });
3230
+ var PartnerFundingSchema = z14.object({
3231
+ fundingId: z14.string().uuid(),
3232
+ partnerId: z14.string().uuid(),
3233
+ accountId: z14.string().uuid(),
3234
+ userId: z14.string().uuid().nullable(),
3235
+ direction: z14.enum(PARTNER_FUNDING_DIRECTIONS),
3236
+ currency: z14.string(),
3237
+ amountMinor: MinorString,
3238
+ externalRef: z14.string(),
3239
+ status: z14.enum(PARTNER_FUNDING_STATUSES),
3240
+ fundingSource: z14.string(),
3241
+ ledgerRef: z14.string(),
3242
+ providerMetadata: Metadata,
3243
+ createdAtMs: z14.number().int().nonnegative(),
3244
+ updatedAtMs: z14.number().int().nonnegative()
3245
+ });
3246
+ var IngestFundingResultSchema = z14.object({
3247
+ funding: PartnerFundingSchema,
3248
+ replayed: z14.boolean()
3249
+ });
3250
+ var PayoutDestinationSchema = z14.object({
3251
+ destinationId: z14.string().uuid(),
3252
+ accountId: z14.string().uuid(),
3253
+ partnerId: z14.string().uuid(),
3254
+ bankCode: z14.string(),
3255
+ accountNumber: z14.string(),
3256
+ accountName: z14.string(),
3257
+ status: z14.enum(PAYOUT_DESTINATION_STATUSES),
3258
+ verifiedAtMs: z14.number().int().nonnegative().nullable(),
3259
+ metadata: Metadata,
3260
+ createdAtMs: z14.number().int().nonnegative(),
3261
+ updatedAtMs: z14.number().int().nonnegative()
3262
+ });
3263
+ var CreatePayoutDestinationInputSchema = z14.object({
3264
+ partnerId: z14.string().uuid(),
3265
+ bankCode: z14.string().trim().min(1).max(32),
3266
+ accountNumber: z14.string().trim().min(4).max(64),
3267
+ accountName: z14.string().trim().min(1).max(200),
3268
+ metadata: Metadata.optional()
3269
+ });
3270
+ var ListPayoutDestinationsResultSchema = z14.object({
3271
+ items: z14.array(PayoutDestinationSchema)
3272
+ });
3273
+ var WithdrawalSchema = z14.object({
3274
+ withdrawalId: z14.string().uuid(),
3275
+ accountId: z14.string().uuid(),
3276
+ userId: z14.string().uuid(),
3277
+ partnerId: z14.string().uuid(),
3278
+ destinationId: z14.string().uuid(),
3279
+ currency: z14.string(),
3280
+ amountMinor: MinorString,
3281
+ state: z14.enum(WITHDRAWAL_STATES),
3282
+ idempotencyKey: z14.string(),
3283
+ providerRef: z14.string().nullable(),
3284
+ lastError: z14.string().nullable(),
3285
+ ledgerRef: z14.string(),
3286
+ reverseLedgerRef: z14.string().nullable(),
3287
+ metadata: Metadata,
3288
+ createdAtMs: z14.number().int().nonnegative(),
3289
+ updatedAtMs: z14.number().int().nonnegative()
3290
+ });
3291
+ var CreateWithdrawalInputSchema = z14.object({
3292
+ destinationId: z14.string().uuid(),
3293
+ amountMinor: PositiveMinor,
3294
+ currency: Currency,
3295
+ idempotencyKey: z14.string().trim().min(8).max(128),
3296
+ metadata: Metadata.optional()
3297
+ });
3298
+ var CreateWithdrawalResultSchema = z14.object({
3299
+ withdrawal: WithdrawalSchema,
3300
+ replayed: z14.boolean()
3301
+ });
3302
+ var PayoutEventInputSchema = z14.object({
3303
+ externalRef: z14.string().trim().min(8).max(128),
3304
+ withdrawalId: z14.string().uuid().optional(),
3305
+ state: z14.enum(["submitted", "processing", "paid", "failed"]),
3306
+ providerRef: z14.string().trim().min(1).max(128).optional(),
3307
+ failureCode: z14.string().trim().max(64).optional(),
3308
+ failureMessage: z14.string().trim().max(512).optional(),
3309
+ providerMetadata: Metadata.optional()
3310
+ });
3311
+ var RecordPayoutEventResultSchema = z14.object({
3312
+ withdrawal: WithdrawalSchema,
3313
+ replayed: z14.boolean()
3314
+ });
3315
+ var ReconciliationReportSchema = z14.object({
3316
+ partnerId: z14.string().uuid(),
3317
+ currency: z14.string(),
3318
+ fromMs: z14.number().int().nonnegative(),
3319
+ toMs: z14.number().int().nonnegative(),
3320
+ fundingsCreditMinor: MinorString,
3321
+ fundingsDebitMinor: MinorString,
3322
+ withdrawalsPaidMinor: MinorString,
3323
+ withdrawalsReversedMinor: MinorString,
3324
+ withdrawalsInFlightMinor: MinorString,
3325
+ expectedReserveBalanceMinor: MinorString,
3326
+ actualReserveBalanceMinor: MinorString,
3327
+ imbalanceMinor: MinorString,
3328
+ generatedAtMs: z14.number().int().nonnegative()
3329
+ });
3330
+ function createPartnerFundingClient(partner) {
3331
+ return {
3332
+ ingestFunding: async (input) => {
3333
+ const body = PartnerFundingEventInputSchema.parse(input);
3334
+ const raw = await partner.request({
3335
+ method: "POST",
3336
+ path: "/v1/partners/fundings",
3337
+ body
3338
+ });
3339
+ return IngestFundingResultSchema.parse(raw);
3340
+ },
3341
+ recordPayoutEvent: async (input) => {
3342
+ const body = PayoutEventInputSchema.parse(input);
3343
+ const raw = await partner.request({
3344
+ method: "POST",
3345
+ path: "/v1/partners/payouts/events",
3346
+ body
3347
+ });
3348
+ return RecordPayoutEventResultSchema.parse(raw);
3349
+ },
3350
+ reconciliation: async (input) => {
3351
+ const qs = new URLSearchParams({
3352
+ currency: input.currency
3353
+ });
3354
+ if (typeof input.fromMs === "number")
3355
+ qs.set("fromMs", String(input.fromMs));
3356
+ if (typeof input.toMs === "number") qs.set("toMs", String(input.toMs));
3357
+ const raw = await partner.request({
3358
+ method: "GET",
3359
+ path: `/v1/partners/reconciliation/daily?${qs.toString()}`
3360
+ });
3361
+ return ReconciliationReportSchema.parse(raw);
3362
+ }
3363
+ };
3364
+ }
3365
+ function createConsumerWithdrawalsClient(opts) {
3366
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
3367
+ if (!fetchImpl) {
3368
+ throw new Error(
3369
+ "createConsumerWithdrawalsClient: no fetch implementation available"
3370
+ );
3371
+ }
3372
+ const baseUrl = opts.baseUrl.replace(/\/$/, "");
3373
+ async function call(method, path, body, parser) {
3374
+ const init2 = {
3375
+ method,
3376
+ headers: { accept: "application/json" }
3377
+ };
3378
+ if (body !== void 0) {
3379
+ init2.body = JSON.stringify(body);
3380
+ init2.headers = { ...init2.headers, "content-type": "application/json" };
3381
+ }
3382
+ const resp = await fetchImpl(`${baseUrl}${path}`, init2);
3383
+ const text = await resp.text();
3384
+ let raw;
3385
+ if (text) {
3386
+ try {
3387
+ raw = JSON.parse(text);
3388
+ } catch {
3389
+ raw = text;
3390
+ }
3391
+ }
3392
+ if (!resp.ok) {
3393
+ const code = raw && typeof raw === "object" && "code" in raw && typeof raw.code === "string" ? raw.code : `http_${resp.status}`;
3394
+ const message = raw && typeof raw === "object" && "message" in raw && typeof raw.message === "string" ? raw.message : `request failed with status ${resp.status}`;
3395
+ throw new FlurApiError(resp.status, code, message, raw);
3396
+ }
3397
+ return parser(raw);
3398
+ }
3399
+ return {
3400
+ listDestinations: () => call(
3401
+ "GET",
3402
+ "/v1/me/payout-destinations",
3403
+ void 0,
3404
+ (raw) => ListPayoutDestinationsResultSchema.parse(raw)
3405
+ ),
3406
+ createDestination: (input) => call(
3407
+ "POST",
3408
+ "/v1/me/payout-destinations",
3409
+ CreatePayoutDestinationInputSchema.parse(input),
3410
+ (raw) => PayoutDestinationSchema.parse(raw)
3411
+ ),
3412
+ verifyDestination: (destinationId) => call(
3413
+ "POST",
3414
+ `/v1/me/payout-destinations/${encodeURIComponent(destinationId)}/verify`,
3415
+ {},
3416
+ (raw) => PayoutDestinationSchema.parse(raw)
3417
+ ),
3418
+ disableDestination: (destinationId) => call(
3419
+ "POST",
3420
+ `/v1/me/payout-destinations/${encodeURIComponent(destinationId)}/disable`,
3421
+ {},
3422
+ (raw) => PayoutDestinationSchema.parse(raw)
3423
+ ),
3424
+ createWithdrawal: (input) => call(
3425
+ "POST",
3426
+ "/v1/me/withdrawals",
3427
+ CreateWithdrawalInputSchema.parse(input),
3428
+ (raw) => CreateWithdrawalResultSchema.parse(raw)
3429
+ ),
3430
+ getWithdrawal: (withdrawalId) => call(
3431
+ "GET",
3432
+ `/v1/me/withdrawals/${encodeURIComponent(withdrawalId)}`,
3433
+ void 0,
3434
+ (raw) => WithdrawalSchema.parse(raw)
3435
+ )
3436
+ };
3437
+ }
3438
+ function createPartnerProfileAdminClient(opts) {
3439
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
3440
+ if (!fetchImpl) {
3441
+ throw new Error(
3442
+ "createPartnerProfileAdminClient: no fetch implementation available"
3443
+ );
3444
+ }
3445
+ const baseUrl = opts.baseUrl.replace(/\/$/, "");
3446
+ return {
3447
+ upsertProfile: async (partnerAccountId, input) => {
3448
+ const body = {
3449
+ partnerAccountId,
3450
+ ...UpsertPartnerProfileInputSchema.parse(input)
3451
+ };
3452
+ const resp = await fetchImpl(`${baseUrl}/v1/partners/profile`, {
3453
+ method: "POST",
3454
+ headers: {
3455
+ "content-type": "application/json",
3456
+ accept: "application/json"
3457
+ },
3458
+ body: JSON.stringify(body)
3459
+ });
3460
+ const text = await resp.text();
3461
+ let raw;
3462
+ if (text) {
3463
+ try {
3464
+ raw = JSON.parse(text);
3465
+ } catch {
3466
+ raw = text;
3467
+ }
3468
+ }
3469
+ if (!resp.ok) {
3470
+ const code = raw && typeof raw === "object" && "code" in raw && typeof raw.code === "string" ? raw.code : `http_${resp.status}`;
3471
+ const message = raw && typeof raw === "object" && "message" in raw && typeof raw.message === "string" ? raw.message : `request failed with status ${resp.status}`;
3472
+ throw new FlurApiError(resp.status, code, message, raw);
3473
+ }
3474
+ return PartnerProfileSchema.parse(raw);
3475
+ }
3476
+ };
3477
+ }
2800
3478
  export {
2801
3479
  ACCOUNT_STATUSES,
2802
3480
  ACCOUNT_TYPES,
@@ -2804,11 +3482,24 @@ export {
2804
3482
  AccountMembershipSchema,
2805
3483
  AccountSchema,
2806
3484
  ApiCredentialPublicSchema,
3485
+ COLLECTION_INTENT_STATUSES,
3486
+ COLLECTION_PAYMENT_STATUSES,
3487
+ CUSTODIAL_MODES,
3488
+ CollectionIntentSchema,
3489
+ CollectionPaymentResultSchema,
3490
+ CollectionPaymentSchema,
3491
+ CollectionReportSummarySchema,
3492
+ CollectionStatementSchema,
2807
3493
  OACRecordSchema as ConsumerOACRecordSchema,
2808
3494
  ConsumerOACSchema,
2809
3495
  ConsumerPaymentClaimSchema,
2810
3496
  ConsumerSettleResultSchema,
2811
3497
  ConsumerSettlementSchema,
3498
+ CreateCollectionIntentInputSchema,
3499
+ CreatePayoutDestinationInputSchema,
3500
+ CreatePayoutInputSchema,
3501
+ CreateWithdrawalInputSchema,
3502
+ CreateWithdrawalResultSchema,
2812
3503
  DeviceKeyRecordSchema,
2813
3504
  DisableOfflineInputSchema,
2814
3505
  DisableOfflineResultSchema,
@@ -2821,8 +3512,14 @@ export {
2821
3512
  FlurError,
2822
3513
  FlurExpiredError,
2823
3514
  FlurReplayError,
3515
+ IngestFundingResultSchema,
2824
3516
  IssueOACInputSchema,
3517
+ ListPayoutDestinationsResultSchema,
2825
3518
  MEMBERSHIP_ROLES,
3519
+ MERCHANT_PAYOUT_STATUSES,
3520
+ MERCHANT_PROFILE_STATUSES,
3521
+ MerchantPayoutSchema,
3522
+ MerchantProfileSchema,
2826
3523
  MintedApiCredentialSchema,
2827
3524
  NGN_CURRENCY_CODE,
2828
3525
  NG_COUNTRY_CODE,
@@ -2837,25 +3534,46 @@ export {
2837
3534
  OfflineStateResultSchema,
2838
3535
  OfflineStatusResultSchema,
2839
3536
  OfflineTokenSchema,
3537
+ PARTNER_FUNDING_DIRECTIONS,
3538
+ PARTNER_FUNDING_STATUSES,
3539
+ PARTNER_KINDS,
3540
+ PARTNER_PROFILE_STATUSES,
2840
3541
  PARTNER_SCOPES,
2841
3542
  PASS_KINDS,
2842
3543
  PASS_STATES,
2843
3544
  PAYLOAD_FORMAT_INDICATOR_VALUE,
3545
+ PAYOUT_DESTINATION_STATUSES,
2844
3546
  POINT_OF_INITIATION,
3547
+ PartnerFundingEventInputSchema,
3548
+ PartnerFundingSchema,
3549
+ PartnerProfileSchema,
2845
3550
  PassMetadataSchema,
2846
3551
  PassSchema,
3552
+ PayCollectionInputSchema,
2847
3553
  PaymentClaimSchema,
3554
+ PayoutDestinationSchema,
3555
+ PayoutEventInputSchema,
3556
+ ProviderEventInputSchema,
3557
+ ProviderEventRecordSchema,
3558
+ PublicCollectionIntentSchema,
2848
3559
  RECEIPT_CHANNELS,
2849
3560
  RECEIPT_KINDS,
2850
3561
  REPLAY_WINDOW_MS,
2851
3562
  ReceiptPayloadSchema,
2852
3563
  ReceiptSchema,
3564
+ ReconciliationReportSchema,
3565
+ RecordPayoutEventResultSchema,
2853
3566
  RedemptionSchema,
2854
3567
  RegisterDeviceKeyInputSchema,
2855
3568
  RevokeDeviceKeyInputSchema,
3569
+ SETTLEMENT_SCHEDULES,
2856
3570
  SettleResponseSchema,
2857
3571
  SettlementSchema,
2858
3572
  SignedConsumerOACSchema,
3573
+ UpsertMerchantProfileInputSchema,
3574
+ UpsertPartnerProfileInputSchema,
3575
+ WITHDRAWAL_STATES,
3576
+ WithdrawalSchema,
2859
3577
  bodySha256Hex,
2860
3578
  buildAuthorization,
2861
3579
  buildOAC,
@@ -2872,10 +3590,16 @@ export {
2872
3590
  crc16ccittHex,
2873
3591
  createAccountsClient,
2874
3592
  createApiCredentialsAdminClient,
3593
+ createCollectionsClient,
3594
+ createConsumerCollectionsClient,
3595
+ createConsumerWithdrawalsClient,
2875
3596
  createFlurPartnerClient,
2876
3597
  createHmacFetch,
2877
3598
  createMeOfflineClient,
2878
3599
  createOfflineSettlementsClient,
3600
+ createPartnerCollectionsClient,
3601
+ createPartnerFundingClient,
3602
+ createPartnerProfileAdminClient,
2879
3603
  createPassesClient,
2880
3604
  createReceiptsClient,
2881
3605
  decodeAuthorizationQR,