@nokinc-flur/sdk 1.0.4 → 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.cjs +1512 -415
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2962 -93
- package/dist/index.d.ts +2962 -93
- package/dist/index.js +1448 -415
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/client.ts
|
|
2
|
-
import { z as
|
|
2
|
+
import { z as z4 } from "zod";
|
|
3
3
|
|
|
4
4
|
// src/contracts.ts
|
|
5
5
|
import { z } from "zod";
|
|
@@ -41,7 +41,9 @@ var OnboardingCompleteResponseSchema = z.object({
|
|
|
41
41
|
sessionToken: z.string().min(1),
|
|
42
42
|
userId: UuidSchema,
|
|
43
43
|
restricted: z.boolean(),
|
|
44
|
-
risk_reasons: z.array(
|
|
44
|
+
risk_reasons: z.array(
|
|
45
|
+
z.enum(["SIM_SWAP_RECENT", "ROAMING", "CARRIER_CHANGED"])
|
|
46
|
+
),
|
|
45
47
|
stepUpRequired: z.boolean().optional(),
|
|
46
48
|
riskStatus: z.enum(["ok", "unavailable"]).optional()
|
|
47
49
|
});
|
|
@@ -94,9 +96,11 @@ var RegisterSendDeviceKeyRequestSchema = z.object({
|
|
|
94
96
|
deviceId: z.string().min(3),
|
|
95
97
|
publicKey: z.string().min(32)
|
|
96
98
|
});
|
|
99
|
+
var SEND_AUTH_PURPOSES = ["send_money", "offline_revoke"];
|
|
97
100
|
var SendChallengeRequestSchema = z.object({
|
|
98
101
|
userId: UuidSchema,
|
|
99
|
-
deviceId: z.string().min(3)
|
|
102
|
+
deviceId: z.string().min(3),
|
|
103
|
+
purpose: z.enum(SEND_AUTH_PURPOSES).optional()
|
|
100
104
|
});
|
|
101
105
|
var SendChallengeResponseSchema = z.object({
|
|
102
106
|
challengeId: UuidSchema,
|
|
@@ -383,6 +387,341 @@ function moneyMinorToNumber(amountMinor) {
|
|
|
383
387
|
return asNumber;
|
|
384
388
|
}
|
|
385
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
|
+
|
|
386
725
|
// src/client.ts
|
|
387
726
|
var FlurClient = class {
|
|
388
727
|
baseUrl;
|
|
@@ -396,10 +735,20 @@ var FlurClient = class {
|
|
|
396
735
|
this.getExtraHeaders = opts.getExtraHeaders;
|
|
397
736
|
}
|
|
398
737
|
async health() {
|
|
399
|
-
return this.requestJson(
|
|
738
|
+
return this.requestJson(
|
|
739
|
+
"/health",
|
|
740
|
+
{ method: "GET" },
|
|
741
|
+
void 0,
|
|
742
|
+
HealthResponseSchema
|
|
743
|
+
);
|
|
400
744
|
}
|
|
401
745
|
async welcome() {
|
|
402
|
-
return this.requestJson(
|
|
746
|
+
return this.requestJson(
|
|
747
|
+
"/welcome",
|
|
748
|
+
{ method: "GET" },
|
|
749
|
+
void 0,
|
|
750
|
+
WelcomeResponseSchema
|
|
751
|
+
);
|
|
403
752
|
}
|
|
404
753
|
async onboardingStart(input) {
|
|
405
754
|
return this.requestJson(
|
|
@@ -544,24 +893,33 @@ var FlurClient = class {
|
|
|
544
893
|
}
|
|
545
894
|
async registerBiometricDeviceKey(input) {
|
|
546
895
|
const publicKey = await input.signer.getOrCreateKeyPair(input.deviceId);
|
|
547
|
-
return this.registerSendDeviceKey(
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
896
|
+
return this.registerSendDeviceKey(
|
|
897
|
+
{
|
|
898
|
+
userId: input.userId,
|
|
899
|
+
deviceId: input.deviceId,
|
|
900
|
+
publicKey
|
|
901
|
+
},
|
|
902
|
+
{ accessToken: input.accessToken }
|
|
903
|
+
);
|
|
552
904
|
}
|
|
553
905
|
async authorizeSendWithBiometric(input) {
|
|
554
|
-
const challenge = await this.createSendChallenge(
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
906
|
+
const challenge = await this.createSendChallenge(
|
|
907
|
+
{
|
|
908
|
+
userId: input.userId,
|
|
909
|
+
deviceId: input.deviceId
|
|
910
|
+
},
|
|
911
|
+
{ accessToken: input.accessToken }
|
|
912
|
+
);
|
|
558
913
|
const signature = await input.signer.sign(challenge.nonce);
|
|
559
|
-
return this.verifySendChallenge(
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
914
|
+
return this.verifySendChallenge(
|
|
915
|
+
{
|
|
916
|
+
userId: input.userId,
|
|
917
|
+
deviceId: input.deviceId,
|
|
918
|
+
challengeId: challenge.challengeId,
|
|
919
|
+
signature
|
|
920
|
+
},
|
|
921
|
+
{ accessToken: input.accessToken }
|
|
922
|
+
);
|
|
565
923
|
}
|
|
566
924
|
async resolveRecipient(input, options) {
|
|
567
925
|
return this.requestJson(
|
|
@@ -612,6 +970,36 @@ var FlurClient = class {
|
|
|
612
970
|
}
|
|
613
971
|
);
|
|
614
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
|
+
}
|
|
615
1003
|
async accountSummary(options) {
|
|
616
1004
|
return this.requestJson(
|
|
617
1005
|
"/api/v1/account/summary",
|
|
@@ -710,7 +1098,7 @@ var FlurClient = class {
|
|
|
710
1098
|
try {
|
|
711
1099
|
body = requestSchema ? JSON.stringify(requestSchema.parse(input)) : init2.body;
|
|
712
1100
|
} catch (err) {
|
|
713
|
-
if (err instanceof
|
|
1101
|
+
if (err instanceof z4.ZodError) {
|
|
714
1102
|
throw new FlurError("Invalid request payload", "INVALID_REQUEST", {
|
|
715
1103
|
details: err.flatten()
|
|
716
1104
|
});
|
|
@@ -726,17 +1114,26 @@ var FlurClient = class {
|
|
|
726
1114
|
...init2.headers,
|
|
727
1115
|
...extraHeaders
|
|
728
1116
|
};
|
|
729
|
-
const res = await this.fetchImpl(url, {
|
|
1117
|
+
const res = await this.fetchImpl(url, {
|
|
1118
|
+
...init2,
|
|
1119
|
+
headers: finalHeaders,
|
|
1120
|
+
body,
|
|
1121
|
+
signal: controller.signal
|
|
1122
|
+
});
|
|
730
1123
|
if (!res.ok) throw await mapToFlurError(res);
|
|
731
1124
|
const payload = await res.json();
|
|
732
1125
|
if (!responseSchema) return payload;
|
|
733
1126
|
try {
|
|
734
1127
|
return responseSchema.parse(payload);
|
|
735
1128
|
} catch (err) {
|
|
736
|
-
if (err instanceof
|
|
737
|
-
throw new FlurError(
|
|
738
|
-
|
|
739
|
-
|
|
1129
|
+
if (err instanceof z4.ZodError) {
|
|
1130
|
+
throw new FlurError(
|
|
1131
|
+
"SDK contract validation failed",
|
|
1132
|
+
"INVALID_REQUEST",
|
|
1133
|
+
{
|
|
1134
|
+
details: err.flatten()
|
|
1135
|
+
}
|
|
1136
|
+
);
|
|
740
1137
|
}
|
|
741
1138
|
throw err;
|
|
742
1139
|
}
|
|
@@ -745,7 +1142,9 @@ var FlurClient = class {
|
|
|
745
1142
|
throw new FlurError("Request timed out", "TIMEOUT");
|
|
746
1143
|
}
|
|
747
1144
|
if (err instanceof FlurError) throw err;
|
|
748
|
-
throw new FlurError("Network error", "NETWORK_ERROR", {
|
|
1145
|
+
throw new FlurError("Network error", "NETWORK_ERROR", {
|
|
1146
|
+
details: String(err)
|
|
1147
|
+
});
|
|
749
1148
|
} finally {
|
|
750
1149
|
clearTimeout(t);
|
|
751
1150
|
}
|
|
@@ -755,7 +1154,10 @@ function getSecureRandomUuid() {
|
|
|
755
1154
|
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
756
1155
|
return globalThis.crypto.randomUUID();
|
|
757
1156
|
}
|
|
758
|
-
throw new FlurError(
|
|
1157
|
+
throw new FlurError(
|
|
1158
|
+
"Secure UUID generator unavailable; provide idempotencyKey",
|
|
1159
|
+
"INVALID_REQUEST"
|
|
1160
|
+
);
|
|
759
1161
|
}
|
|
760
1162
|
|
|
761
1163
|
// src/nqr/fields.ts
|
|
@@ -1182,24 +1584,24 @@ function verifyCanonical(value, signature, publicKey) {
|
|
|
1182
1584
|
}
|
|
1183
1585
|
|
|
1184
1586
|
// src/offline/oac.ts
|
|
1185
|
-
import { z as
|
|
1587
|
+
import { z as z5 } from "zod";
|
|
1186
1588
|
var OAC_DEFAULT_PER_TX_KOBO = 5e5;
|
|
1187
1589
|
var OAC_DEFAULT_CUMULATIVE_KOBO = 2e6;
|
|
1188
1590
|
var OAC_DEFAULT_VALIDITY_MS = 24 * 60 * 60 * 1e3;
|
|
1189
|
-
var HexString = (length) =>
|
|
1591
|
+
var HexString = (length) => z5.string().regex(
|
|
1190
1592
|
new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
|
|
1191
1593
|
`expected ${length}-byte hex string`
|
|
1192
1594
|
);
|
|
1193
|
-
var OACSchema =
|
|
1194
|
-
userId:
|
|
1195
|
-
deviceId:
|
|
1595
|
+
var OACSchema = z5.object({
|
|
1596
|
+
userId: z5.string().min(1),
|
|
1597
|
+
deviceId: z5.string().min(1),
|
|
1196
1598
|
devicePublicKey: HexString(32),
|
|
1197
|
-
perTxCapKobo:
|
|
1198
|
-
cumulativeCapKobo:
|
|
1199
|
-
validFromMs:
|
|
1200
|
-
validUntilMs:
|
|
1201
|
-
counterSeed:
|
|
1202
|
-
nonce:
|
|
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),
|
|
1203
1605
|
issuerSig: HexString(64)
|
|
1204
1606
|
}).refine((v) => v.validUntilMs > v.validFromMs, {
|
|
1205
1607
|
message: "validUntilMs must be greater than validFromMs"
|
|
@@ -1306,19 +1708,19 @@ function decodeBase45(s) {
|
|
|
1306
1708
|
}
|
|
1307
1709
|
|
|
1308
1710
|
// src/offline/messages.ts
|
|
1309
|
-
import { z as
|
|
1310
|
-
var HexSig =
|
|
1311
|
-
var OfflinePaymentRequestSchema =
|
|
1312
|
-
reference:
|
|
1313
|
-
amountKobo:
|
|
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(),
|
|
1314
1716
|
merchantOAC: OACSchema,
|
|
1315
|
-
expiresAtMs:
|
|
1717
|
+
expiresAtMs: z6.number().int().positive(),
|
|
1316
1718
|
merchantSig: HexSig
|
|
1317
1719
|
});
|
|
1318
|
-
var OfflinePaymentAuthorizationSchema =
|
|
1720
|
+
var OfflinePaymentAuthorizationSchema = z6.object({
|
|
1319
1721
|
request: OfflinePaymentRequestSchema,
|
|
1320
1722
|
payerOAC: OACSchema,
|
|
1321
|
-
payerCounter:
|
|
1723
|
+
payerCounter: z6.number().int().positive(),
|
|
1322
1724
|
payerSig: HexSig
|
|
1323
1725
|
});
|
|
1324
1726
|
function buildPaymentRequest(input) {
|
|
@@ -1427,56 +1829,56 @@ function decodeAuthorizationQR(s) {
|
|
|
1427
1829
|
}
|
|
1428
1830
|
|
|
1429
1831
|
// src/offline/settlements.ts
|
|
1430
|
-
import { z as
|
|
1832
|
+
import { z as z7 } from "zod";
|
|
1431
1833
|
import { sha256 } from "@noble/hashes/sha256";
|
|
1432
1834
|
import { bytesToHex as bytesToHex2 } from "@noble/hashes/utils";
|
|
1433
|
-
var OfflineTokenSchema =
|
|
1434
|
-
tokenId:
|
|
1435
|
-
tokenSerial:
|
|
1436
|
-
issuerAccountId:
|
|
1437
|
-
payerUserId:
|
|
1438
|
-
maxAmountKobo:
|
|
1439
|
-
currency:
|
|
1440
|
-
issuedAtMs:
|
|
1441
|
-
expiresAtMs:
|
|
1442
|
-
issuerSig:
|
|
1443
|
-
});
|
|
1444
|
-
var PaymentClaimSchema =
|
|
1445
|
-
encounterId:
|
|
1446
|
-
tokenSerial:
|
|
1447
|
-
payerUserId:
|
|
1448
|
-
payeeUserId:
|
|
1449
|
-
payerNonce:
|
|
1450
|
-
payeeNonce:
|
|
1451
|
-
amountKobo:
|
|
1452
|
-
currency:
|
|
1453
|
-
occurredAtMs:
|
|
1454
|
-
completedAtMs:
|
|
1455
|
-
contextId:
|
|
1456
|
-
payerPubkey:
|
|
1457
|
-
payerSignature:
|
|
1458
|
-
payeePubkey:
|
|
1459
|
-
payeeSignature:
|
|
1460
|
-
});
|
|
1461
|
-
var SettlementSchema =
|
|
1462
|
-
settlementId:
|
|
1463
|
-
settlementKey:
|
|
1464
|
-
encounterId:
|
|
1465
|
-
issuerAccountId:
|
|
1466
|
-
tokenSerial:
|
|
1467
|
-
payerUserId:
|
|
1468
|
-
payeeUserId:
|
|
1469
|
-
amountKobo:
|
|
1470
|
-
currency:
|
|
1471
|
-
receiptId:
|
|
1472
|
-
status:
|
|
1473
|
-
issuerSig:
|
|
1474
|
-
createdAtMs:
|
|
1475
|
-
});
|
|
1476
|
-
var SettleResponseSchema =
|
|
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({
|
|
1477
1879
|
settlement: SettlementSchema,
|
|
1478
|
-
encounterId:
|
|
1479
|
-
replayed:
|
|
1880
|
+
encounterId: z7.string().regex(/^[0-9a-f]{64}$/i),
|
|
1881
|
+
replayed: z7.boolean()
|
|
1480
1882
|
});
|
|
1481
1883
|
var ENCOUNTER_DOMAIN = "offline:v1:encounter";
|
|
1482
1884
|
async function sha256Hex(input) {
|
|
@@ -1649,126 +2051,344 @@ function createHmacFetch(opts) {
|
|
|
1649
2051
|
});
|
|
1650
2052
|
}
|
|
1651
2053
|
|
|
1652
|
-
// src/
|
|
1653
|
-
import { z as
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
"
|
|
1659
|
-
"
|
|
1660
|
-
"
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
"
|
|
1664
|
-
"
|
|
1665
|
-
"
|
|
1666
|
-
"
|
|
1667
|
-
"
|
|
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"
|
|
1668
2078
|
];
|
|
1669
|
-
var
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
)
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
)
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
/** Optional client/template grouping id (server may omit). */
|
|
1679
|
-
templateId: z7.string().min(1).optional(),
|
|
1680
|
-
/** Optional human-facing holder identity (server may omit). The cryptographic binding
|
|
1681
|
-
* is `holderDevicePubkey` below. */
|
|
1682
|
-
holderUserId: z7.string().min(1).optional(),
|
|
1683
|
-
kind: z7.enum(PASS_KINDS),
|
|
1684
|
-
issuerId: z7.string().min(1),
|
|
1685
|
-
issuedAtMs: z7.number().int().nonnegative(),
|
|
1686
|
-
validFromMs: z7.number().int().nonnegative(),
|
|
1687
|
-
validUntilMs: z7.number().int().positive(),
|
|
1688
|
-
state: z7.enum(PASS_STATES),
|
|
1689
|
-
metadata: PassMetadataSchema,
|
|
1690
|
-
nonce: z7.string().min(1),
|
|
1691
|
-
/** Device id this pass is bound to (FK to backend `device_keys`). */
|
|
1692
|
-
holderDeviceId: z7.string().min(1),
|
|
1693
|
-
/** 32-byte hex Ed25519 public key of the bound device. The redemption signature
|
|
1694
|
-
* is verified against this key — it is the security-critical binding. */
|
|
1695
|
-
holderDevicePubkey: HexString2(32),
|
|
1696
|
-
/** Optional fixed amount for monetary passes (vouchers, gift cards) in kobo. */
|
|
1697
|
-
amountKobo: z7.number().int().nonnegative().optional(),
|
|
1698
|
-
/** ISO-4217-ish currency code; required on the wire. SDK builders default to NGN. */
|
|
1699
|
-
currency: z7.string().min(3).max(8),
|
|
1700
|
-
/** Monotonic redemption counter floor. Redemption.counter MUST be > counterSeed. */
|
|
1701
|
-
counterSeed: z7.number().int().nonnegative(),
|
|
1702
|
-
/** Optional cumulative spend cap in kobo across all redemptions of this pass. */
|
|
1703
|
-
cumulativeCapKobo: z7.number().int().nonnegative().optional(),
|
|
1704
|
-
issuerSig: HexString2(64)
|
|
1705
|
-
}).refine((v) => v.validUntilMs > v.validFromMs, {
|
|
1706
|
-
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()
|
|
1707
2088
|
});
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
issuerId: input.issuerId,
|
|
1716
|
-
issuedAtMs: input.issuedAtMs,
|
|
1717
|
-
validFromMs: input.validFromMs,
|
|
1718
|
-
validUntilMs: input.validUntilMs,
|
|
1719
|
-
state: input.state,
|
|
1720
|
-
metadata: input.metadata,
|
|
1721
|
-
nonce: input.nonce,
|
|
1722
|
-
holderDeviceId: input.holderDeviceId,
|
|
1723
|
-
holderDevicePubkey: input.holderDevicePubkey,
|
|
1724
|
-
currency: input.currency ?? "NGN",
|
|
1725
|
-
counterSeed: input.counterSeed
|
|
1726
|
-
};
|
|
1727
|
-
if (typeof input.templateId === "string") out.templateId = input.templateId;
|
|
1728
|
-
if (typeof input.holderUserId === "string")
|
|
1729
|
-
out.holderUserId = input.holderUserId;
|
|
1730
|
-
if (typeof input.amountKobo === "number") out.amountKobo = input.amountKobo;
|
|
1731
|
-
if (typeof input.cumulativeCapKobo === "number") {
|
|
1732
|
-
out.cumulativeCapKobo = input.cumulativeCapKobo;
|
|
1733
|
-
}
|
|
1734
|
-
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));
|
|
1735
2096
|
}
|
|
1736
|
-
function
|
|
1737
|
-
|
|
1738
|
-
sign(canonicalJSONBytes(unsigned), issuerPrivateKey)
|
|
1739
|
-
);
|
|
1740
|
-
return { ...unsigned, issuerSig };
|
|
2097
|
+
async function hmacSha256Hex(keyHex, message) {
|
|
2098
|
+
return bytesToHex4(hmac2(sha2563, enc.encode(keyHex), enc.encode(message)));
|
|
1741
2099
|
}
|
|
1742
|
-
function
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
return verify(
|
|
1747
|
-
canonicalJSONBytes(unsigned),
|
|
1748
|
-
hexToBytes(issuerSig),
|
|
1749
|
-
issuerPublicKey
|
|
1750
|
-
);
|
|
1751
|
-
} catch {
|
|
1752
|
-
return false;
|
|
1753
|
-
}
|
|
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)}`;
|
|
1754
2104
|
}
|
|
1755
|
-
function
|
|
1756
|
-
return
|
|
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");
|
|
1757
2113
|
}
|
|
1758
|
-
|
|
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
|
+
|
|
1759
2379
|
// src/passes/redemption.ts
|
|
1760
|
-
import { z as
|
|
1761
|
-
var HexSig2 =
|
|
1762
|
-
var RedemptionSchema =
|
|
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({
|
|
1763
2383
|
pass: PassSchema,
|
|
1764
|
-
redeemerId:
|
|
1765
|
-
redeemedAtMs:
|
|
2384
|
+
redeemerId: z10.string().min(1),
|
|
2385
|
+
redeemedAtMs: z10.number().int().nonnegative(),
|
|
1766
2386
|
/** Strictly monotonic counter scoped to a single pass. Must be > pass.counterSeed
|
|
1767
2387
|
* and > the redeemer's lastSeenCounter for this pass. */
|
|
1768
|
-
counter:
|
|
2388
|
+
counter: z10.number().int().positive(),
|
|
1769
2389
|
/** Amount being redeemed in kobo (0 for non-monetary passes like ride tickets). */
|
|
1770
|
-
amountKobo:
|
|
1771
|
-
nonce:
|
|
2390
|
+
amountKobo: z10.number().int().nonnegative(),
|
|
2391
|
+
nonce: z10.string().min(1),
|
|
1772
2392
|
holderSig: HexSig2
|
|
1773
2393
|
});
|
|
1774
2394
|
var REDEEMABLE_STATES = /* @__PURE__ */ new Set(["issued", "active"]);
|
|
@@ -1854,43 +2474,43 @@ function verifyRedemption(r, issuerPublicKey) {
|
|
|
1854
2474
|
}
|
|
1855
2475
|
|
|
1856
2476
|
// src/receipts/receipt.ts
|
|
1857
|
-
import { z as
|
|
2477
|
+
import { z as z11 } from "zod";
|
|
1858
2478
|
var RECEIPT_CHANNELS = ["cash", "pass"];
|
|
1859
2479
|
var RECEIPT_KINDS = RECEIPT_CHANNELS;
|
|
1860
|
-
var HexString3 = (length) =>
|
|
2480
|
+
var HexString3 = (length) => z11.string().regex(
|
|
1861
2481
|
new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
|
|
1862
2482
|
`expected ${length}-byte hex string`
|
|
1863
2483
|
);
|
|
1864
|
-
var ReceiptPayloadSchema =
|
|
1865
|
-
|
|
2484
|
+
var ReceiptPayloadSchema = z11.record(
|
|
2485
|
+
z11.union([z11.string(), z11.number(), z11.boolean(), z11.null()])
|
|
1866
2486
|
);
|
|
1867
|
-
var ReceiptSchema =
|
|
1868
|
-
receiptId:
|
|
1869
|
-
channel:
|
|
2487
|
+
var ReceiptSchema = z11.object({
|
|
2488
|
+
receiptId: z11.string().min(1),
|
|
2489
|
+
channel: z11.enum(RECEIPT_CHANNELS),
|
|
1870
2490
|
/** Cash-channel: send_intents.id. Required when channel === 'cash'. */
|
|
1871
|
-
intentId:
|
|
2491
|
+
intentId: z11.string().min(1).optional(),
|
|
1872
2492
|
/** Pass-channel: pass_redemptions.id. Required when channel === 'pass'. */
|
|
1873
|
-
passRedemptionId:
|
|
1874
|
-
payerUserId:
|
|
1875
|
-
payeeUserId:
|
|
1876
|
-
amountKobo:
|
|
1877
|
-
currency:
|
|
1878
|
-
issuedAtMs:
|
|
1879
|
-
issuerId:
|
|
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),
|
|
1880
2500
|
payload: ReceiptPayloadSchema,
|
|
1881
2501
|
issuerSig: HexString3(64)
|
|
1882
2502
|
}).superRefine((v, ctx) => {
|
|
1883
2503
|
if (v.channel === "cash") {
|
|
1884
2504
|
if (!v.intentId) {
|
|
1885
2505
|
ctx.addIssue({
|
|
1886
|
-
code:
|
|
2506
|
+
code: z11.ZodIssueCode.custom,
|
|
1887
2507
|
message: "cash receipts require intentId",
|
|
1888
2508
|
path: ["intentId"]
|
|
1889
2509
|
});
|
|
1890
2510
|
}
|
|
1891
2511
|
if (v.passRedemptionId) {
|
|
1892
2512
|
ctx.addIssue({
|
|
1893
|
-
code:
|
|
2513
|
+
code: z11.ZodIssueCode.custom,
|
|
1894
2514
|
message: "cash receipts must not carry passRedemptionId",
|
|
1895
2515
|
path: ["passRedemptionId"]
|
|
1896
2516
|
});
|
|
@@ -1898,14 +2518,14 @@ var ReceiptSchema = z9.object({
|
|
|
1898
2518
|
} else if (v.channel === "pass") {
|
|
1899
2519
|
if (!v.passRedemptionId) {
|
|
1900
2520
|
ctx.addIssue({
|
|
1901
|
-
code:
|
|
2521
|
+
code: z11.ZodIssueCode.custom,
|
|
1902
2522
|
message: "pass receipts require passRedemptionId",
|
|
1903
2523
|
path: ["passRedemptionId"]
|
|
1904
2524
|
});
|
|
1905
2525
|
}
|
|
1906
2526
|
if (v.intentId) {
|
|
1907
2527
|
ctx.addIssue({
|
|
1908
|
-
code:
|
|
2528
|
+
code: z11.ZodIssueCode.custom,
|
|
1909
2529
|
message: "pass receipts must not carry intentId",
|
|
1910
2530
|
path: ["intentId"]
|
|
1911
2531
|
});
|
|
@@ -2156,55 +2776,27 @@ function parseQR(payload) {
|
|
|
2156
2776
|
return parseNQR(payload);
|
|
2157
2777
|
}
|
|
2158
2778
|
function init(opts) {
|
|
2159
|
-
const
|
|
2160
|
-
|
|
2161
|
-
|
|
2779
|
+
const partner = createFlurPartnerClient({
|
|
2780
|
+
baseUrl: opts.baseUrl,
|
|
2781
|
+
keyId: opts.apiKey,
|
|
2782
|
+
secret: opts.apiSecret,
|
|
2162
2783
|
fetchImpl: opts.fetchImpl,
|
|
2163
2784
|
scope: opts.scope
|
|
2164
2785
|
});
|
|
2786
|
+
const signedFetch = partner.fetch;
|
|
2165
2787
|
const baseUrl = opts.baseUrl.replace(/\/$/, "");
|
|
2166
2788
|
function subscribeToPayments(s) {
|
|
2167
|
-
const controller = new AbortController();
|
|
2168
2789
|
let cancelled = false;
|
|
2169
|
-
(
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
if (!resp.body) return;
|
|
2178
|
-
const reader = resp.body.getReader();
|
|
2179
|
-
const decoder = new TextDecoder();
|
|
2180
|
-
let buffer = "";
|
|
2181
|
-
while (!cancelled) {
|
|
2182
|
-
const { value, done } = await reader.read();
|
|
2183
|
-
if (done) return;
|
|
2184
|
-
buffer += decoder.decode(value, { stream: true });
|
|
2185
|
-
let idx;
|
|
2186
|
-
while ((idx = buffer.indexOf("\n\n")) >= 0) {
|
|
2187
|
-
const chunk = buffer.slice(0, idx);
|
|
2188
|
-
buffer = buffer.slice(idx + 2);
|
|
2189
|
-
for (const line of chunk.split("\n")) {
|
|
2190
|
-
if (!line.startsWith("data:")) continue;
|
|
2191
|
-
const json = line.slice(5).trim();
|
|
2192
|
-
if (!json) continue;
|
|
2193
|
-
try {
|
|
2194
|
-
s.onEvent(JSON.parse(json));
|
|
2195
|
-
} catch (err) {
|
|
2196
|
-
s.onError?.(err);
|
|
2197
|
-
}
|
|
2198
|
-
}
|
|
2199
|
-
}
|
|
2200
|
-
}
|
|
2201
|
-
} catch (err) {
|
|
2202
|
-
if (!cancelled) s.onError?.(err);
|
|
2203
|
-
}
|
|
2204
|
-
})();
|
|
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
|
+
);
|
|
2797
|
+
});
|
|
2205
2798
|
return () => {
|
|
2206
2799
|
cancelled = true;
|
|
2207
|
-
controller.abort();
|
|
2208
2800
|
};
|
|
2209
2801
|
}
|
|
2210
2802
|
const cash = {
|
|
@@ -2215,6 +2807,10 @@ function init(opts) {
|
|
|
2215
2807
|
};
|
|
2216
2808
|
const passes = createPassesClient({ baseUrl, fetchImpl: signedFetch });
|
|
2217
2809
|
const receipts = createReceiptsClient({ baseUrl, fetchImpl: signedFetch });
|
|
2810
|
+
const collections = createPartnerCollectionsClient({
|
|
2811
|
+
baseUrl,
|
|
2812
|
+
fetchImpl: signedFetch
|
|
2813
|
+
});
|
|
2218
2814
|
return {
|
|
2219
2815
|
// top-level back-compat surface
|
|
2220
2816
|
generateStaticQR,
|
|
@@ -2223,29 +2819,30 @@ function init(opts) {
|
|
|
2223
2819
|
subscribeToPayments,
|
|
2224
2820
|
// namespaces
|
|
2225
2821
|
cash,
|
|
2822
|
+
collections,
|
|
2226
2823
|
passes,
|
|
2227
2824
|
receipts
|
|
2228
2825
|
};
|
|
2229
2826
|
}
|
|
2230
2827
|
|
|
2231
2828
|
// src/accounts/client.ts
|
|
2232
|
-
import { z as
|
|
2829
|
+
import { z as z12 } from "zod";
|
|
2233
2830
|
var ACCOUNT_TYPES = ["personal", "business", "partner"];
|
|
2234
2831
|
var ACCOUNT_STATUSES = ["active", "suspended", "closed"];
|
|
2235
2832
|
var MEMBERSHIP_ROLES = ["owner", "admin", "driver", "staff"];
|
|
2236
|
-
var AccountSchema =
|
|
2237
|
-
accountId:
|
|
2238
|
-
type:
|
|
2239
|
-
displayName:
|
|
2240
|
-
status:
|
|
2241
|
-
ownerUserId:
|
|
2242
|
-
createdAtMs:
|
|
2243
|
-
});
|
|
2244
|
-
var AccountMembershipSchema =
|
|
2245
|
-
accountId:
|
|
2246
|
-
userId:
|
|
2247
|
-
role:
|
|
2248
|
-
createdAtMs:
|
|
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()
|
|
2249
2846
|
});
|
|
2250
2847
|
function createAccountsClient(opts) {
|
|
2251
2848
|
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
@@ -2278,9 +2875,9 @@ function createAccountsClient(opts) {
|
|
|
2278
2875
|
}
|
|
2279
2876
|
return parser(raw);
|
|
2280
2877
|
}
|
|
2281
|
-
const itemsSchema =
|
|
2282
|
-
const memberItemsSchema =
|
|
2283
|
-
items:
|
|
2878
|
+
const itemsSchema = z12.object({ items: z12.array(AccountSchema) });
|
|
2879
|
+
const memberItemsSchema = z12.object({
|
|
2880
|
+
items: z12.array(AccountMembershipSchema)
|
|
2284
2881
|
});
|
|
2285
2882
|
return {
|
|
2286
2883
|
listMyAccounts: () => call(
|
|
@@ -2311,110 +2908,182 @@ function createAccountsClient(opts) {
|
|
|
2311
2908
|
};
|
|
2312
2909
|
}
|
|
2313
2910
|
|
|
2314
|
-
// src/
|
|
2315
|
-
import { z as
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
var
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
"passes:redeem",
|
|
2323
|
-
"receipts:write",
|
|
2324
|
-
"receipts:read",
|
|
2325
|
-
"offline:issue",
|
|
2326
|
-
"offline:settle",
|
|
2327
|
-
"offline:read"
|
|
2328
|
-
];
|
|
2329
|
-
var ApiCredentialPublicSchema = z11.object({
|
|
2330
|
-
id: z11.string().uuid(),
|
|
2331
|
-
accountId: z11.string().uuid(),
|
|
2332
|
-
keyId: z11.string(),
|
|
2333
|
-
scopes: z11.array(z11.enum(PARTNER_SCOPES)),
|
|
2334
|
-
label: z11.string().nullable(),
|
|
2335
|
-
createdAtMs: z11.number().int().nonnegative(),
|
|
2336
|
-
lastUsedAtMs: z11.number().int().nonnegative().nullable(),
|
|
2337
|
-
revokedAtMs: z11.number().int().nonnegative().nullable()
|
|
2911
|
+
// src/me-offline/client.ts
|
|
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),
|
|
2918
|
+
publicKeyHex: Hex64
|
|
2338
2919
|
});
|
|
2339
|
-
var
|
|
2340
|
-
|
|
2920
|
+
var DeviceKeyRecordSchema = z13.object({
|
|
2921
|
+
id: z13.string().uuid(),
|
|
2922
|
+
userId: z13.string().uuid(),
|
|
2923
|
+
deviceId: z13.string(),
|
|
2924
|
+
publicKeyHex: Hex64,
|
|
2925
|
+
createdAtMs: z13.number().int().nonnegative(),
|
|
2926
|
+
revokedAtMs: z13.number().int().nonnegative().nullable()
|
|
2341
2927
|
});
|
|
2342
|
-
var
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
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),
|
|
2933
|
+
devicePubkeyHex: Hex64,
|
|
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({
|
|
2943
|
+
oac: ConsumerOACSchema,
|
|
2944
|
+
issuerSig: HexAny,
|
|
2945
|
+
issuerPublicKeyHex: Hex64
|
|
2946
|
+
});
|
|
2947
|
+
var OACRecordSchema = SignedConsumerOACSchema.extend({
|
|
2948
|
+
currentOfflineSpentKobo: z13.number().int().nonnegative(),
|
|
2949
|
+
status: z13.enum([
|
|
2950
|
+
"active",
|
|
2951
|
+
"superseded",
|
|
2952
|
+
"expired",
|
|
2953
|
+
"revoked",
|
|
2954
|
+
"disabling",
|
|
2955
|
+
"draining",
|
|
2956
|
+
"closed"
|
|
2957
|
+
]),
|
|
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([
|
|
2995
|
+
"placing",
|
|
2996
|
+
"active",
|
|
2997
|
+
"disabling",
|
|
2998
|
+
"draining",
|
|
2999
|
+
"closed",
|
|
3000
|
+
"revoked",
|
|
3001
|
+
"failed"
|
|
3002
|
+
]),
|
|
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({
|
|
3011
|
+
hold: OfflineHoldRecordSchema,
|
|
3012
|
+
oac: OACRecordSchema
|
|
3013
|
+
});
|
|
3014
|
+
var DisableOfflineResultSchema = z13.object({
|
|
3015
|
+
hold: OfflineHoldRecordSchema,
|
|
3016
|
+
trusted: z13.boolean(),
|
|
3017
|
+
settledClaims: z13.number().int().nonnegative()
|
|
3018
|
+
});
|
|
3019
|
+
var OfflineStatusResultSchema = z13.object({
|
|
3020
|
+
hold: OfflineHoldRecordSchema.nullable(),
|
|
3021
|
+
active: OACRecordSchema.nullable()
|
|
3022
|
+
});
|
|
3023
|
+
var OfflineStateResultSchema = z13.object({
|
|
3024
|
+
active: OACRecordSchema.nullable()
|
|
3025
|
+
});
|
|
3026
|
+
var ConsumerPaymentClaimSchema = z13.object({
|
|
3027
|
+
oacId: z13.string().uuid(),
|
|
3028
|
+
encounterId: Sha256Hex.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(),
|
|
3039
|
+
payerPubkeyHex: Hex64,
|
|
3040
|
+
payerSignature: HexAny,
|
|
3041
|
+
payeePubkeyHex: Hex64.optional(),
|
|
3042
|
+
payeeSignature: HexAny.optional()
|
|
3043
|
+
});
|
|
3044
|
+
var ConsumerSettlementSchema = z13.object({
|
|
3045
|
+
settlementId: z13.string().uuid(),
|
|
3046
|
+
settlementKey: Sha256Hex,
|
|
3047
|
+
encounterId: Sha256Hex,
|
|
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(),
|
|
3056
|
+
issuerSig: HexAny,
|
|
3057
|
+
createdAtMs: z13.number().int().nonnegative()
|
|
3058
|
+
});
|
|
3059
|
+
var ConsumerSettleResultSchema = z13.object({
|
|
3060
|
+
settlement: ConsumerSettlementSchema,
|
|
3061
|
+
encounterId: Sha256Hex,
|
|
3062
|
+
replayed: z13.boolean()
|
|
3063
|
+
});
|
|
3064
|
+
var RevokeDeviceKeyInputSchema = z13.object({
|
|
3065
|
+
deviceId: z13.string().min(1).max(128),
|
|
3066
|
+
/** Step-up token from /api/v1/auth/send/verify with purpose='offline_revoke'. */
|
|
3067
|
+
sendAuthToken: z13.string().min(16)
|
|
3068
|
+
});
|
|
3069
|
+
function createMeOfflineClient(opts) {
|
|
2386
3070
|
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
2387
3071
|
if (!fetchImpl) {
|
|
2388
|
-
throw new Error(
|
|
2389
|
-
"createFlurPartnerClient: no fetch implementation available"
|
|
2390
|
-
);
|
|
3072
|
+
throw new Error("createMeOfflineClient: no fetch implementation available");
|
|
2391
3073
|
}
|
|
2392
3074
|
const baseUrl = opts.baseUrl.replace(/\/$/, "");
|
|
2393
|
-
async function
|
|
2394
|
-
const
|
|
2395
|
-
keyId: opts.keyId,
|
|
2396
|
-
secret: opts.secret,
|
|
3075
|
+
async function call(method, path, body, parser) {
|
|
3076
|
+
const init2 = {
|
|
2397
3077
|
method,
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
});
|
|
2403
|
-
const headers = {
|
|
2404
|
-
authorization: sig.authorization,
|
|
2405
|
-
accept: "application/json"
|
|
3078
|
+
headers: {
|
|
3079
|
+
"content-type": "application/json",
|
|
3080
|
+
accept: "application/json"
|
|
3081
|
+
}
|
|
2406
3082
|
};
|
|
2407
|
-
if (body !== void 0)
|
|
2408
|
-
const
|
|
2409
|
-
if (body !== void 0) init2.body = body;
|
|
2410
|
-
return init2;
|
|
2411
|
-
}
|
|
2412
|
-
async function request(opts2) {
|
|
2413
|
-
const bodyStr = opts2.body === void 0 ? void 0 : JSON.stringify(opts2.body);
|
|
2414
|
-
const init2 = await makeSignedInit(opts2.method, opts2.path, bodyStr);
|
|
2415
|
-
const resp = await fetchImpl(`${baseUrl}${opts2.path}`, init2);
|
|
3083
|
+
if (body !== void 0) init2.body = JSON.stringify(body);
|
|
3084
|
+
const resp = await fetchImpl(`${baseUrl}${path}`, init2);
|
|
2416
3085
|
const text = await resp.text();
|
|
2417
|
-
let raw;
|
|
3086
|
+
let raw = void 0;
|
|
2418
3087
|
if (text) {
|
|
2419
3088
|
try {
|
|
2420
3089
|
raw = JSON.parse(text);
|
|
@@ -2426,46 +3095,290 @@ function createFlurPartnerClient(opts) {
|
|
|
2426
3095
|
const message = raw && typeof raw === "object" && "message" in raw && typeof raw.message === "string" ? raw.message : `request failed with status ${resp.status}`;
|
|
2427
3096
|
throw new FlurApiError(resp.status, code, message, raw);
|
|
2428
3097
|
}
|
|
2429
|
-
return raw;
|
|
3098
|
+
return parser(raw);
|
|
2430
3099
|
}
|
|
2431
|
-
const
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
3100
|
+
const deviceKeyItems = z13.object({ items: z13.array(DeviceKeyRecordSchema) });
|
|
3101
|
+
return {
|
|
3102
|
+
registerDeviceKey: (input) => call(
|
|
3103
|
+
"POST",
|
|
3104
|
+
"/v1/me/offline/keys",
|
|
3105
|
+
RegisterDeviceKeyInputSchema.parse(input),
|
|
3106
|
+
(raw) => DeviceKeyRecordSchema.parse(raw)
|
|
3107
|
+
),
|
|
3108
|
+
listDeviceKeys: () => call(
|
|
3109
|
+
"GET",
|
|
3110
|
+
"/v1/me/offline/keys",
|
|
3111
|
+
void 0,
|
|
3112
|
+
(raw) => deviceKeyItems.parse(raw)
|
|
3113
|
+
),
|
|
3114
|
+
revokeDeviceKey: (input) => call(
|
|
3115
|
+
"POST",
|
|
3116
|
+
"/v1/me/offline/keys/revoke",
|
|
3117
|
+
RevokeDeviceKeyInputSchema.parse(input),
|
|
3118
|
+
() => void 0
|
|
3119
|
+
),
|
|
3120
|
+
enable: (input) => call(
|
|
3121
|
+
"POST",
|
|
3122
|
+
"/v1/me/offline/enable",
|
|
3123
|
+
EnableOfflineInputSchema.parse(input),
|
|
3124
|
+
(raw) => EnableOfflineResultSchema.parse(raw)
|
|
3125
|
+
),
|
|
3126
|
+
refresh: (input) => call(
|
|
3127
|
+
"POST",
|
|
3128
|
+
"/v1/me/offline/refresh",
|
|
3129
|
+
IssueOACInputSchema.parse(input),
|
|
3130
|
+
(raw) => OACRecordSchema.parse(raw)
|
|
3131
|
+
),
|
|
3132
|
+
disable: (input) => call(
|
|
3133
|
+
"POST",
|
|
3134
|
+
"/v1/me/offline/disable",
|
|
3135
|
+
DisableOfflineInputSchema.parse(input),
|
|
3136
|
+
(raw) => DisableOfflineResultSchema.parse(raw)
|
|
3137
|
+
),
|
|
3138
|
+
getStatus: (deviceId) => {
|
|
3139
|
+
const qs = deviceId ? `?deviceId=${encodeURIComponent(deviceId)}` : "";
|
|
3140
|
+
return call(
|
|
3141
|
+
"GET",
|
|
3142
|
+
`/v1/me/offline/status${qs}`,
|
|
3143
|
+
void 0,
|
|
3144
|
+
(raw) => OfflineStatusResultSchema.parse(raw)
|
|
3145
|
+
);
|
|
3146
|
+
},
|
|
3147
|
+
getState: (deviceId) => {
|
|
3148
|
+
const qs = deviceId ? `?deviceId=${encodeURIComponent(deviceId)}` : "";
|
|
3149
|
+
return call(
|
|
3150
|
+
"GET",
|
|
3151
|
+
`/v1/me/offline/state${qs}`,
|
|
3152
|
+
void 0,
|
|
3153
|
+
(raw) => OfflineStateResultSchema.parse(raw)
|
|
3154
|
+
);
|
|
3155
|
+
},
|
|
3156
|
+
submitClaim: (claim) => call(
|
|
3157
|
+
"POST",
|
|
3158
|
+
"/v1/me/offline/claims",
|
|
3159
|
+
ConsumerPaymentClaimSchema.parse(claim),
|
|
3160
|
+
(raw) => ConsumerSettleResultSchema.parse(raw)
|
|
3161
|
+
)
|
|
3162
|
+
};
|
|
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);
|
|
2439
3362
|
}
|
|
2440
|
-
const signed = await makeSignedInit(method, path, bodyStr);
|
|
2441
|
-
return fetchImpl(`${baseUrl}${path}`, {
|
|
2442
|
-
...init2,
|
|
2443
|
-
...signed,
|
|
2444
|
-
headers: {
|
|
2445
|
-
...init2?.headers,
|
|
2446
|
-
...signed.headers
|
|
2447
|
-
}
|
|
2448
|
-
});
|
|
2449
3363
|
};
|
|
2450
|
-
return { request, fetch: fetchLike };
|
|
2451
3364
|
}
|
|
2452
|
-
function
|
|
3365
|
+
function createConsumerWithdrawalsClient(opts) {
|
|
2453
3366
|
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
2454
3367
|
if (!fetchImpl) {
|
|
2455
3368
|
throw new Error(
|
|
2456
|
-
"
|
|
3369
|
+
"createConsumerWithdrawalsClient: no fetch implementation available"
|
|
2457
3370
|
);
|
|
2458
3371
|
}
|
|
2459
3372
|
const baseUrl = opts.baseUrl.replace(/\/$/, "");
|
|
2460
3373
|
async function call(method, path, body, parser) {
|
|
2461
3374
|
const init2 = {
|
|
2462
3375
|
method,
|
|
2463
|
-
headers: {
|
|
2464
|
-
"content-type": "application/json",
|
|
2465
|
-
accept: "application/json"
|
|
2466
|
-
}
|
|
3376
|
+
headers: { accept: "application/json" }
|
|
2467
3377
|
};
|
|
2468
|
-
if (body !== void 0)
|
|
3378
|
+
if (body !== void 0) {
|
|
3379
|
+
init2.body = JSON.stringify(body);
|
|
3380
|
+
init2.headers = { ...init2.headers, "content-type": "application/json" };
|
|
3381
|
+
}
|
|
2469
3382
|
const resp = await fetchImpl(`${baseUrl}${path}`, init2);
|
|
2470
3383
|
const text = await resp.text();
|
|
2471
3384
|
let raw;
|
|
@@ -2473,6 +3386,7 @@ function createApiCredentialsAdminClient(opts) {
|
|
|
2473
3386
|
try {
|
|
2474
3387
|
raw = JSON.parse(text);
|
|
2475
3388
|
} catch {
|
|
3389
|
+
raw = text;
|
|
2476
3390
|
}
|
|
2477
3391
|
}
|
|
2478
3392
|
if (!resp.ok) {
|
|
@@ -2482,30 +3396,85 @@ function createApiCredentialsAdminClient(opts) {
|
|
|
2482
3396
|
}
|
|
2483
3397
|
return parser(raw);
|
|
2484
3398
|
}
|
|
2485
|
-
const listSchema = z11.object({
|
|
2486
|
-
items: z11.array(ApiCredentialPublicSchema)
|
|
2487
|
-
});
|
|
2488
3399
|
return {
|
|
2489
|
-
|
|
3400
|
+
listDestinations: () => call(
|
|
2490
3401
|
"GET",
|
|
2491
|
-
|
|
3402
|
+
"/v1/me/payout-destinations",
|
|
2492
3403
|
void 0,
|
|
2493
|
-
(raw) =>
|
|
3404
|
+
(raw) => ListPayoutDestinationsResultSchema.parse(raw)
|
|
2494
3405
|
),
|
|
2495
|
-
|
|
3406
|
+
createDestination: (input) => call(
|
|
2496
3407
|
"POST",
|
|
2497
|
-
|
|
2498
|
-
input,
|
|
2499
|
-
(raw) =>
|
|
3408
|
+
"/v1/me/payout-destinations",
|
|
3409
|
+
CreatePayoutDestinationInputSchema.parse(input),
|
|
3410
|
+
(raw) => PayoutDestinationSchema.parse(raw)
|
|
2500
3411
|
),
|
|
2501
|
-
|
|
2502
|
-
"
|
|
2503
|
-
`/v1/
|
|
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)}`,
|
|
2504
3433
|
void 0,
|
|
2505
|
-
(raw) =>
|
|
3434
|
+
(raw) => WithdrawalSchema.parse(raw)
|
|
2506
3435
|
)
|
|
2507
3436
|
};
|
|
2508
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
|
+
}
|
|
2509
3478
|
export {
|
|
2510
3479
|
ACCOUNT_STATUSES,
|
|
2511
3480
|
ACCOUNT_TYPES,
|
|
@@ -2513,6 +3482,29 @@ export {
|
|
|
2513
3482
|
AccountMembershipSchema,
|
|
2514
3483
|
AccountSchema,
|
|
2515
3484
|
ApiCredentialPublicSchema,
|
|
3485
|
+
COLLECTION_INTENT_STATUSES,
|
|
3486
|
+
COLLECTION_PAYMENT_STATUSES,
|
|
3487
|
+
CUSTODIAL_MODES,
|
|
3488
|
+
CollectionIntentSchema,
|
|
3489
|
+
CollectionPaymentResultSchema,
|
|
3490
|
+
CollectionPaymentSchema,
|
|
3491
|
+
CollectionReportSummarySchema,
|
|
3492
|
+
CollectionStatementSchema,
|
|
3493
|
+
OACRecordSchema as ConsumerOACRecordSchema,
|
|
3494
|
+
ConsumerOACSchema,
|
|
3495
|
+
ConsumerPaymentClaimSchema,
|
|
3496
|
+
ConsumerSettleResultSchema,
|
|
3497
|
+
ConsumerSettlementSchema,
|
|
3498
|
+
CreateCollectionIntentInputSchema,
|
|
3499
|
+
CreatePayoutDestinationInputSchema,
|
|
3500
|
+
CreatePayoutInputSchema,
|
|
3501
|
+
CreateWithdrawalInputSchema,
|
|
3502
|
+
CreateWithdrawalResultSchema,
|
|
3503
|
+
DeviceKeyRecordSchema,
|
|
3504
|
+
DisableOfflineInputSchema,
|
|
3505
|
+
DisableOfflineResultSchema,
|
|
3506
|
+
EnableOfflineInputSchema,
|
|
3507
|
+
EnableOfflineResultSchema,
|
|
2516
3508
|
FIELD,
|
|
2517
3509
|
FlurApiError,
|
|
2518
3510
|
FlurCapExceededError,
|
|
@@ -2520,7 +3512,14 @@ export {
|
|
|
2520
3512
|
FlurError,
|
|
2521
3513
|
FlurExpiredError,
|
|
2522
3514
|
FlurReplayError,
|
|
3515
|
+
IngestFundingResultSchema,
|
|
3516
|
+
IssueOACInputSchema,
|
|
3517
|
+
ListPayoutDestinationsResultSchema,
|
|
2523
3518
|
MEMBERSHIP_ROLES,
|
|
3519
|
+
MERCHANT_PAYOUT_STATUSES,
|
|
3520
|
+
MERCHANT_PROFILE_STATUSES,
|
|
3521
|
+
MerchantPayoutSchema,
|
|
3522
|
+
MerchantProfileSchema,
|
|
2524
3523
|
MintedApiCredentialSchema,
|
|
2525
3524
|
NGN_CURRENCY_CODE,
|
|
2526
3525
|
NG_COUNTRY_CODE,
|
|
@@ -2529,25 +3528,52 @@ export {
|
|
|
2529
3528
|
OAC_DEFAULT_CUMULATIVE_KOBO,
|
|
2530
3529
|
OAC_DEFAULT_PER_TX_KOBO,
|
|
2531
3530
|
OAC_DEFAULT_VALIDITY_MS,
|
|
3531
|
+
OfflineHoldRecordSchema,
|
|
2532
3532
|
OfflinePaymentAuthorizationSchema,
|
|
2533
3533
|
OfflinePaymentRequestSchema,
|
|
3534
|
+
OfflineStateResultSchema,
|
|
3535
|
+
OfflineStatusResultSchema,
|
|
2534
3536
|
OfflineTokenSchema,
|
|
3537
|
+
PARTNER_FUNDING_DIRECTIONS,
|
|
3538
|
+
PARTNER_FUNDING_STATUSES,
|
|
3539
|
+
PARTNER_KINDS,
|
|
3540
|
+
PARTNER_PROFILE_STATUSES,
|
|
2535
3541
|
PARTNER_SCOPES,
|
|
2536
3542
|
PASS_KINDS,
|
|
2537
3543
|
PASS_STATES,
|
|
2538
3544
|
PAYLOAD_FORMAT_INDICATOR_VALUE,
|
|
3545
|
+
PAYOUT_DESTINATION_STATUSES,
|
|
2539
3546
|
POINT_OF_INITIATION,
|
|
3547
|
+
PartnerFundingEventInputSchema,
|
|
3548
|
+
PartnerFundingSchema,
|
|
3549
|
+
PartnerProfileSchema,
|
|
2540
3550
|
PassMetadataSchema,
|
|
2541
3551
|
PassSchema,
|
|
3552
|
+
PayCollectionInputSchema,
|
|
2542
3553
|
PaymentClaimSchema,
|
|
3554
|
+
PayoutDestinationSchema,
|
|
3555
|
+
PayoutEventInputSchema,
|
|
3556
|
+
ProviderEventInputSchema,
|
|
3557
|
+
ProviderEventRecordSchema,
|
|
3558
|
+
PublicCollectionIntentSchema,
|
|
2543
3559
|
RECEIPT_CHANNELS,
|
|
2544
3560
|
RECEIPT_KINDS,
|
|
2545
3561
|
REPLAY_WINDOW_MS,
|
|
2546
3562
|
ReceiptPayloadSchema,
|
|
2547
3563
|
ReceiptSchema,
|
|
3564
|
+
ReconciliationReportSchema,
|
|
3565
|
+
RecordPayoutEventResultSchema,
|
|
2548
3566
|
RedemptionSchema,
|
|
3567
|
+
RegisterDeviceKeyInputSchema,
|
|
3568
|
+
RevokeDeviceKeyInputSchema,
|
|
3569
|
+
SETTLEMENT_SCHEDULES,
|
|
2549
3570
|
SettleResponseSchema,
|
|
2550
3571
|
SettlementSchema,
|
|
3572
|
+
SignedConsumerOACSchema,
|
|
3573
|
+
UpsertMerchantProfileInputSchema,
|
|
3574
|
+
UpsertPartnerProfileInputSchema,
|
|
3575
|
+
WITHDRAWAL_STATES,
|
|
3576
|
+
WithdrawalSchema,
|
|
2551
3577
|
bodySha256Hex,
|
|
2552
3578
|
buildAuthorization,
|
|
2553
3579
|
buildOAC,
|
|
@@ -2564,9 +3590,16 @@ export {
|
|
|
2564
3590
|
crc16ccittHex,
|
|
2565
3591
|
createAccountsClient,
|
|
2566
3592
|
createApiCredentialsAdminClient,
|
|
3593
|
+
createCollectionsClient,
|
|
3594
|
+
createConsumerCollectionsClient,
|
|
3595
|
+
createConsumerWithdrawalsClient,
|
|
2567
3596
|
createFlurPartnerClient,
|
|
2568
3597
|
createHmacFetch,
|
|
3598
|
+
createMeOfflineClient,
|
|
2569
3599
|
createOfflineSettlementsClient,
|
|
3600
|
+
createPartnerCollectionsClient,
|
|
3601
|
+
createPartnerFundingClient,
|
|
3602
|
+
createPartnerProfileAdminClient,
|
|
2570
3603
|
createPassesClient,
|
|
2571
3604
|
createReceiptsClient,
|
|
2572
3605
|
decodeAuthorizationQR,
|