@nokinc-flur/sdk 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +864 -172
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +510 -11
- package/dist/index.d.ts +510 -11
- package/dist/index.js +814 -172
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -35,6 +45,9 @@ __export(index_exports, {
|
|
|
35
45
|
COLLECTION_INTENT_STATUSES: () => COLLECTION_INTENT_STATUSES,
|
|
36
46
|
COLLECTION_PAYMENT_STATUSES: () => COLLECTION_PAYMENT_STATUSES,
|
|
37
47
|
CONSUMER_OFFLINE_CLAIM_SUBMIT_GRACE_MS: () => CONSUMER_OFFLINE_CLAIM_SUBMIT_GRACE_MS,
|
|
48
|
+
CONSUMER_PAYMENT_REQUEST_DOMAIN: () => CONSUMER_PAYMENT_REQUEST_DOMAIN,
|
|
49
|
+
CONSUMER_SETTLEMENT_DOMAIN: () => CONSUMER_SETTLEMENT_DOMAIN,
|
|
50
|
+
CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX: () => CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX,
|
|
38
51
|
CUSTODIAL_MODES: () => CUSTODIAL_MODES,
|
|
39
52
|
CollectionIntentSchema: () => CollectionIntentSchema,
|
|
40
53
|
CollectionPaymentResultSchema: () => CollectionPaymentResultSchema,
|
|
@@ -44,6 +57,7 @@ __export(index_exports, {
|
|
|
44
57
|
ConsumerOACRecordSchema: () => OACRecordSchema,
|
|
45
58
|
ConsumerOACSchema: () => ConsumerOACSchema,
|
|
46
59
|
ConsumerPaymentClaimSchema: () => ConsumerPaymentClaimSchema,
|
|
60
|
+
ConsumerPaymentRequestEnvelopeSchema: () => ConsumerPaymentRequestEnvelopeSchema,
|
|
47
61
|
ConsumerSettleResultSchema: () => ConsumerSettleResultSchema,
|
|
48
62
|
ConsumerSettlementSchema: () => ConsumerSettlementSchema,
|
|
49
63
|
CreateCollectionIntentInputSchema: () => CreateCollectionIntentInputSchema,
|
|
@@ -85,6 +99,12 @@ __export(index_exports, {
|
|
|
85
99
|
OAC_DEFAULT_PER_TX_KOBO: () => OAC_DEFAULT_PER_TX_KOBO,
|
|
86
100
|
OAC_DEFAULT_VALIDITY_MS: () => OAC_DEFAULT_VALIDITY_MS,
|
|
87
101
|
OFFLINE_CLAIM_SMS_PREFIX: () => OFFLINE_CLAIM_SMS_PREFIX,
|
|
102
|
+
OFFLINE_SMS_SETTLE_DOMAIN: () => OFFLINE_SMS_SETTLE_DOMAIN,
|
|
103
|
+
OFFLINE_SMS_SETTLE_HEADER_BYTES: () => OFFLINE_SMS_SETTLE_HEADER_BYTES,
|
|
104
|
+
OFFLINE_SMS_SETTLE_PREFIX: () => OFFLINE_SMS_SETTLE_PREFIX,
|
|
105
|
+
OFFLINE_SMS_SETTLE_SIGNATURE_BYTES: () => OFFLINE_SMS_SETTLE_SIGNATURE_BYTES,
|
|
106
|
+
OFFLINE_SMS_SETTLE_TOKEN_BYTES: () => OFFLINE_SMS_SETTLE_TOKEN_BYTES,
|
|
107
|
+
OFFLINE_SMS_SETTLE_VERSION: () => OFFLINE_SMS_SETTLE_VERSION,
|
|
88
108
|
OfflineClaimArtifactSchema: () => OfflineClaimArtifactSchema,
|
|
89
109
|
OfflinePaymentAuthorizationArtifactSchema: () => OfflinePaymentAuthorizationArtifactSchema,
|
|
90
110
|
OfflinePaymentAuthorizationSchema: () => OfflinePaymentAuthorizationSchema,
|
|
@@ -102,6 +122,9 @@ __export(index_exports, {
|
|
|
102
122
|
PASS_STATES: () => PASS_STATES,
|
|
103
123
|
PAYLOAD_FORMAT_INDICATOR_VALUE: () => PAYLOAD_FORMAT_INDICATOR_VALUE,
|
|
104
124
|
PAYOUT_DESTINATION_STATUSES: () => PAYOUT_DESTINATION_STATUSES,
|
|
125
|
+
PAY_CARD_DEFAULT_TTL_MS: () => PAY_CARD_DEFAULT_TTL_MS,
|
|
126
|
+
PAY_CARD_REFRESH_THRESHOLD_MS: () => PAY_CARD_REFRESH_THRESHOLD_MS,
|
|
127
|
+
PAY_CARD_URI_PREFIX: () => PAY_CARD_URI_PREFIX,
|
|
105
128
|
POINT_OF_INITIATION: () => POINT_OF_INITIATION,
|
|
106
129
|
PartnerFundingEventInputSchema: () => PartnerFundingEventInputSchema,
|
|
107
130
|
PartnerFundingSchema: () => PartnerFundingSchema,
|
|
@@ -109,6 +132,7 @@ __export(index_exports, {
|
|
|
109
132
|
PassArtifactSchema: () => PassArtifactSchema,
|
|
110
133
|
PassMetadataSchema: () => PassMetadataSchema,
|
|
111
134
|
PassSchema: () => PassSchema,
|
|
135
|
+
PayCardArtifactSchema: () => PayCardArtifactSchema,
|
|
112
136
|
PayCollectionInputSchema: () => PayCollectionInputSchema,
|
|
113
137
|
PaymentClaimSchema: () => PaymentClaimSchema,
|
|
114
138
|
PaymentIntentArtifactSchema: () => PaymentIntentArtifactSchema,
|
|
@@ -144,18 +168,26 @@ __export(index_exports, {
|
|
|
144
168
|
bodySha256Hex: () => bodySha256Hex,
|
|
145
169
|
buildArtifactBody: () => buildArtifactBody,
|
|
146
170
|
buildAuthorization: () => buildAuthorization,
|
|
171
|
+
buildConsumerPaymentRequest: () => buildConsumerPaymentRequest,
|
|
147
172
|
buildOAC: () => buildOAC,
|
|
148
173
|
buildPass: () => buildPass,
|
|
174
|
+
buildPayCardSigningInput: () => buildPayCardSigningInput,
|
|
149
175
|
buildPaymentRequest: () => buildPaymentRequest,
|
|
150
176
|
buildReceipt: () => buildReceipt,
|
|
151
177
|
buildRedemption: () => buildRedemption,
|
|
178
|
+
buildSmsSettleHeader: () => buildSmsSettleHeader,
|
|
179
|
+
buildSmsSettleSignedBytes: () => domainTag,
|
|
152
180
|
canonicalClaimSigningBytes: () => canonicalClaimSigningBytes,
|
|
153
181
|
canonicalClaimSigningPayload: () => canonicalClaimSigningPayload,
|
|
154
182
|
canonicalJSONBytes: () => canonicalJSONBytes,
|
|
155
183
|
canonicalJSONStringify: () => canonicalJSONStringify,
|
|
156
184
|
canonicalRequestString: () => canonicalRequestString,
|
|
185
|
+
computeConsumerClaimEncounterId: () => computeConsumerClaimEncounterId,
|
|
157
186
|
computeEncounterId: () => computeEncounterId,
|
|
158
187
|
constantTimeEqual: () => constantTimeEqual,
|
|
188
|
+
consumerPaymentRequestSigningBytes: () => consumerPaymentRequestSigningBytes,
|
|
189
|
+
consumerPaymentRequestSigningPayload: () => consumerPaymentRequestSigningPayload,
|
|
190
|
+
consumerSettlementSigningPayload: () => consumerSettlementSigningPayload,
|
|
159
191
|
crc16ccitt: () => crc16ccitt,
|
|
160
192
|
crc16ccittHex: () => crc16ccittHex,
|
|
161
193
|
createAccountsClient: () => createAccountsClient,
|
|
@@ -173,28 +205,40 @@ __export(index_exports, {
|
|
|
173
205
|
createPartnerFundingClient: () => createPartnerFundingClient,
|
|
174
206
|
createPartnerProfileAdminClient: () => createPartnerProfileAdminClient,
|
|
175
207
|
createPassesClient: () => createPassesClient,
|
|
208
|
+
createPayCardArtifactUri: () => createPayCardArtifactUri,
|
|
176
209
|
createReceiptArtifactUri: () => createReceiptArtifactUri,
|
|
177
210
|
createReceiptsClient: () => createReceiptsClient,
|
|
178
211
|
createSoftwareP256Signer: () => createSoftwareP256Signer,
|
|
179
212
|
decodeArtifactUri: () => decodeArtifactUri,
|
|
180
213
|
decodeAuthorizationQR: () => decodeAuthorizationQR,
|
|
181
214
|
decodeBase45: () => decodeBase45,
|
|
215
|
+
decodeConsumerSettlementReceiptQR: () => decodeConsumerSettlementReceiptQR,
|
|
182
216
|
decodeOfflineClaimSmsMessage: () => decodeOfflineClaimSmsMessage,
|
|
217
|
+
decodeOfflineSmsSettleToken: () => decodeOfflineSmsSettleToken,
|
|
218
|
+
decodePayCardArtifact: () => decodePayCardArtifact,
|
|
183
219
|
decodePaymentRequestQR: () => decodePaymentRequestQR,
|
|
220
|
+
decodeUnverifiedConsumerSettlementReceiptQR: () => decodeUnverifiedConsumerSettlementReceiptQR,
|
|
221
|
+
derToRawP256Signature: () => derToRawP256Signature,
|
|
184
222
|
encodeArtifactUri: () => encodeArtifactUri,
|
|
185
223
|
encodeAuthorizationQR: () => encodeAuthorizationQR,
|
|
186
224
|
encodeBase45: () => encodeBase45,
|
|
225
|
+
encodeConsumerSettlementReceiptQR: () => encodeConsumerSettlementReceiptQR,
|
|
187
226
|
encodeNQR: () => encodeNQR,
|
|
188
227
|
encodeOfflineClaimSmsMessage: () => encodeOfflineClaimSmsMessage,
|
|
228
|
+
encodeOfflineSmsSettleToken: () => encodeOfflineSmsSettleToken,
|
|
189
229
|
encodePaymentRequestQR: () => encodePaymentRequestQR,
|
|
190
230
|
extractOfflineClaimSmsToken: () => extractOfflineClaimSmsToken,
|
|
231
|
+
extractOfflineSmsSettleToken: () => extractOfflineSmsSettleToken,
|
|
191
232
|
formatAmount: () => formatAmount,
|
|
192
233
|
generateDynamicQR: () => generateDynamicQR,
|
|
193
234
|
generateStaticQR: () => generateStaticQR,
|
|
194
235
|
init: () => init,
|
|
236
|
+
inspectPayCardFreshness: () => inspectPayCardFreshness,
|
|
237
|
+
isConsumerPaymentRequestExpired: () => isConsumerPaymentRequestExpired,
|
|
195
238
|
isHardenedArtifactType: () => isHardenedArtifactType,
|
|
196
239
|
isKnownArtifactType: () => isKnownArtifactType,
|
|
197
240
|
isPassWithinValidity: () => isPassWithinValidity,
|
|
241
|
+
isPayCardArtifactUri: () => isPayCardArtifactUri,
|
|
198
242
|
moneyMinorToNumber: () => moneyMinorToNumber,
|
|
199
243
|
normalizeE164: () => normalizeE164,
|
|
200
244
|
parseAmountInput: () => parseAmountInput,
|
|
@@ -204,6 +248,7 @@ __export(index_exports, {
|
|
|
204
248
|
routingHint: () => routingHint,
|
|
205
249
|
signArtifact: () => signArtifact,
|
|
206
250
|
signAuthorization: () => signAuthorization,
|
|
251
|
+
signConsumerPaymentRequest: () => signConsumerPaymentRequest,
|
|
207
252
|
signOAC: () => signOAC,
|
|
208
253
|
signPartnerRequest: () => signPartnerRequest,
|
|
209
254
|
signPass: () => signPass,
|
|
@@ -215,8 +260,13 @@ __export(index_exports, {
|
|
|
215
260
|
verifyArtifactUri: () => verifyArtifactUri,
|
|
216
261
|
verifyAuthorization: () => verifyAuthorization,
|
|
217
262
|
verifyClaimSignature: () => verifyClaimSignature,
|
|
263
|
+
verifyConsumerPaymentRequest: () => verifyConsumerPaymentRequest,
|
|
264
|
+
verifyConsumerSettlement: () => verifyConsumerSettlement,
|
|
265
|
+
verifyConsumerSettlementReceiptQR: () => verifyConsumerSettlementReceiptQR,
|
|
218
266
|
verifyOAC: () => verifyOAC,
|
|
267
|
+
verifyOfflineSmsSettleToken: () => verifyOfflineSmsSettleToken,
|
|
219
268
|
verifyPass: () => verifyPass,
|
|
269
|
+
verifyPayCardArtifact: () => verifyPayCardArtifact,
|
|
220
270
|
verifyPaymentRequest: () => verifyPaymentRequest,
|
|
221
271
|
verifyReceipt: () => verifyReceipt,
|
|
222
272
|
verifyRedemption: () => verifyRedemption,
|
|
@@ -3185,6 +3235,9 @@ function createAccountsClient(opts) {
|
|
|
3185
3235
|
var import_zod13 = require("zod");
|
|
3186
3236
|
var Sha256Hex = import_zod13.z.string().regex(/^[0-9a-f]{64}$/);
|
|
3187
3237
|
var Base64Std3 = import_zod13.z.string().regex(/^[A-Za-z0-9+/]+={0,2}$/);
|
|
3238
|
+
var ClaimNonce = import_zod13.z.string().min(8).max(128).refine((value) => !value.includes("|"), {
|
|
3239
|
+
message: "nonce must not contain |"
|
|
3240
|
+
});
|
|
3188
3241
|
var ACCOUNT_FUNDED_OAC_MAX_TTL_MS = 1e3 * 60 * 60 * 24 * 7;
|
|
3189
3242
|
var CONSUMER_OFFLINE_CLAIM_SUBMIT_GRACE_MS = 1e3 * 60 * 60 * 24;
|
|
3190
3243
|
var AttestationSecurityLevelSchema = import_zod13.z.enum([
|
|
@@ -3277,13 +3330,25 @@ var ConsumerPaymentClaimSchema = import_zod13.z.object({
|
|
|
3277
3330
|
payerUserId: import_zod13.z.string().uuid(),
|
|
3278
3331
|
payeeUserId: import_zod13.z.string().uuid(),
|
|
3279
3332
|
payerDeviceId: import_zod13.z.string().min(1).max(128),
|
|
3280
|
-
payerNonce:
|
|
3281
|
-
payeeNonce:
|
|
3333
|
+
payerNonce: ClaimNonce,
|
|
3334
|
+
payeeNonce: ClaimNonce,
|
|
3282
3335
|
amountKobo: import_zod13.z.number().int().positive(),
|
|
3283
3336
|
currency: import_zod13.z.string().length(3).default("NGN"),
|
|
3284
3337
|
occurredAtMs: import_zod13.z.number().int().nonnegative(),
|
|
3285
3338
|
completedAtMs: import_zod13.z.number().int().nonnegative().optional(),
|
|
3286
3339
|
contextId: import_zod13.z.string().max(128).optional(),
|
|
3340
|
+
requestId: import_zod13.z.string().uuid().optional(),
|
|
3341
|
+
requestMode: import_zod13.z.enum(["fixed", "editable"]).optional(),
|
|
3342
|
+
requestTakerUserId: import_zod13.z.string().uuid().optional(),
|
|
3343
|
+
requestAmountKobo: import_zod13.z.number().int().positive().optional(),
|
|
3344
|
+
requestCurrency: import_zod13.z.string().length(3).optional(),
|
|
3345
|
+
requestReference: import_zod13.z.string().max(128).nullable().optional(),
|
|
3346
|
+
requestCreatedAtMs: import_zod13.z.number().int().nonnegative().optional(),
|
|
3347
|
+
requestExpiresAtMs: import_zod13.z.number().int().positive().optional(),
|
|
3348
|
+
requestNonce: import_zod13.z.string().min(8).max(128).optional(),
|
|
3349
|
+
requestTakerDeviceId: import_zod13.z.string().min(1).max(128).nullable().optional(),
|
|
3350
|
+
requestTakerPubkeySpkiB64: Base64Std3.min(64).max(4096).optional(),
|
|
3351
|
+
requestTakerSignatureDerB64: Base64Std3.min(16).max(2048).optional(),
|
|
3287
3352
|
payerPubkeySpkiB64: Base64Std3.min(64).max(4096),
|
|
3288
3353
|
payerSignatureDerB64: Base64Std3.min(16).max(2048),
|
|
3289
3354
|
payeePubkeySpkiB64: Base64Std3.min(64).max(4096).optional(),
|
|
@@ -3303,7 +3368,10 @@ var ConsumerSettlementSchema = import_zod13.z.object({
|
|
|
3303
3368
|
ledgerRef: import_zod13.z.string().nullable(),
|
|
3304
3369
|
/** ASN.1 DER ECDSA P-256 issuer signature, base64. */
|
|
3305
3370
|
issuerSig: Base64Std3.min(16).max(2048),
|
|
3306
|
-
|
|
3371
|
+
/** Canonical millisecond timestamp signed into the settlement receipt. */
|
|
3372
|
+
issuedAtMs: import_zod13.z.number().int().nonnegative(),
|
|
3373
|
+
/** Compatibility alias for API consumers that predate issuedAtMs. */
|
|
3374
|
+
createdAtMs: import_zod13.z.number().int().nonnegative().optional()
|
|
3307
3375
|
});
|
|
3308
3376
|
var ConsumerSettleResultSchema = import_zod13.z.object({
|
|
3309
3377
|
settlement: ConsumerSettlementSchema,
|
|
@@ -3392,13 +3460,21 @@ function createMeOfflineClient(opts) {
|
|
|
3392
3460
|
"/v1/me/offline/claims",
|
|
3393
3461
|
ConsumerPaymentClaimSchema.parse(claim),
|
|
3394
3462
|
(raw) => ConsumerSettleResultSchema.parse(raw)
|
|
3463
|
+
),
|
|
3464
|
+
getSettlement: (idOrKey) => call(
|
|
3465
|
+
"GET",
|
|
3466
|
+
`/v1/me/offline/settlements/${encodeURIComponent(idOrKey)}`,
|
|
3467
|
+
void 0,
|
|
3468
|
+
(raw) => ConsumerSettlementSchema.parse(raw)
|
|
3395
3469
|
)
|
|
3396
3470
|
};
|
|
3397
3471
|
}
|
|
3398
3472
|
|
|
3399
3473
|
// src/me-offline/signer.ts
|
|
3400
3474
|
var import_nist2 = require("@noble/curves/nist");
|
|
3475
|
+
var import_sha2 = require("@noble/hashes/sha2");
|
|
3401
3476
|
var CLAIM_DOMAIN_V2 = "flur:consumer-offline:v2:claim";
|
|
3477
|
+
var ENCOUNTER_DOMAIN2 = "flur:consumer-offline:v1:encounter";
|
|
3402
3478
|
function canonicalClaimSigningPayload(claim) {
|
|
3403
3479
|
return {
|
|
3404
3480
|
domain: CLAIM_DOMAIN_V2,
|
|
@@ -3419,6 +3495,27 @@ function canonicalClaimSigningPayload(claim) {
|
|
|
3419
3495
|
function canonicalClaimSigningBytes(claim) {
|
|
3420
3496
|
return canonicalJSONBytes(canonicalClaimSigningPayload(claim));
|
|
3421
3497
|
}
|
|
3498
|
+
function computeConsumerClaimEncounterId(input) {
|
|
3499
|
+
const material = `${ENCOUNTER_DOMAIN2}|${[
|
|
3500
|
+
assertEncounterPart("oacId", input.oacId),
|
|
3501
|
+
assertEncounterPart("payerUserId", input.payerUserId),
|
|
3502
|
+
assertEncounterPart("payeeUserId", input.payeeUserId),
|
|
3503
|
+
assertEncounterPart("payerNonce", input.payerNonce),
|
|
3504
|
+
assertEncounterPart("payeeNonce", input.payeeNonce)
|
|
3505
|
+
].join("|")}`;
|
|
3506
|
+
return bytesToHex5((0, import_sha2.sha256)(new TextEncoder().encode(material)));
|
|
3507
|
+
}
|
|
3508
|
+
function assertEncounterPart(field, value) {
|
|
3509
|
+
if (value.includes("|")) {
|
|
3510
|
+
throw new Error(`consumer encounter id ${field} must not contain |`);
|
|
3511
|
+
}
|
|
3512
|
+
return value;
|
|
3513
|
+
}
|
|
3514
|
+
function bytesToHex5(bytes) {
|
|
3515
|
+
let out = "";
|
|
3516
|
+
for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
|
|
3517
|
+
return out;
|
|
3518
|
+
}
|
|
3422
3519
|
function bytesToBase642(bytes) {
|
|
3423
3520
|
if (typeof Buffer !== "undefined") {
|
|
3424
3521
|
return Buffer.from(bytes).toString("base64");
|
|
@@ -3514,38 +3611,192 @@ function verifyClaimSignature(input) {
|
|
|
3514
3611
|
}
|
|
3515
3612
|
}
|
|
3516
3613
|
|
|
3517
|
-
// src/me-offline/
|
|
3518
|
-
var
|
|
3519
|
-
var
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3614
|
+
// src/me-offline/request.ts
|
|
3615
|
+
var import_zod14 = require("zod");
|
|
3616
|
+
var Base64Std4 = import_zod14.z.string().regex(/^[A-Za-z0-9+/]+={0,2}$/);
|
|
3617
|
+
var CONSUMER_PAYMENT_REQUEST_DOMAIN = "flur:consumer-offline:v1:request";
|
|
3618
|
+
var ConsumerPaymentRequestEnvelopeSchema = import_zod14.z.object({
|
|
3619
|
+
requestId: import_zod14.z.string().uuid(),
|
|
3620
|
+
mode: import_zod14.z.enum(["fixed", "editable"]),
|
|
3621
|
+
takerUserId: import_zod14.z.string().uuid(),
|
|
3622
|
+
amountKobo: import_zod14.z.number().int().positive(),
|
|
3623
|
+
currency: import_zod14.z.string().length(3).default("NGN"),
|
|
3624
|
+
reference: import_zod14.z.string().max(128).nullable().default(null),
|
|
3625
|
+
createdAtMs: import_zod14.z.number().int().nonnegative(),
|
|
3626
|
+
expiresAtMs: import_zod14.z.number().int().positive(),
|
|
3627
|
+
nonce: import_zod14.z.string().min(8).max(128),
|
|
3628
|
+
takerDeviceId: import_zod14.z.string().min(1).max(128).nullable().default(null),
|
|
3629
|
+
takerPubkeySpkiB64: Base64Std4.min(64).max(4096).optional(),
|
|
3630
|
+
takerSignatureDerB64: Base64Std4.min(16).max(2048).optional()
|
|
3631
|
+
}).superRefine((value, ctx) => {
|
|
3632
|
+
if (value.expiresAtMs <= value.createdAtMs) {
|
|
3633
|
+
ctx.addIssue({
|
|
3634
|
+
code: import_zod14.z.ZodIssueCode.custom,
|
|
3635
|
+
path: ["expiresAtMs"],
|
|
3636
|
+
message: "expiresAtMs must be greater than createdAtMs"
|
|
3637
|
+
});
|
|
3638
|
+
}
|
|
3639
|
+
const hasSignature = Boolean(
|
|
3640
|
+
value.takerPubkeySpkiB64 || value.takerSignatureDerB64
|
|
3641
|
+
);
|
|
3642
|
+
if (value.mode === "fixed" || hasSignature) {
|
|
3643
|
+
if (!value.takerDeviceId) {
|
|
3644
|
+
ctx.addIssue({
|
|
3645
|
+
code: import_zod14.z.ZodIssueCode.custom,
|
|
3646
|
+
path: ["takerDeviceId"],
|
|
3647
|
+
message: "signed requests require takerDeviceId"
|
|
3648
|
+
});
|
|
3649
|
+
}
|
|
3650
|
+
if (!value.takerPubkeySpkiB64) {
|
|
3651
|
+
ctx.addIssue({
|
|
3652
|
+
code: import_zod14.z.ZodIssueCode.custom,
|
|
3653
|
+
path: ["takerPubkeySpkiB64"],
|
|
3654
|
+
message: "signed requests require takerPubkeySpkiB64"
|
|
3655
|
+
});
|
|
3656
|
+
}
|
|
3657
|
+
if (!value.takerSignatureDerB64) {
|
|
3658
|
+
ctx.addIssue({
|
|
3659
|
+
code: import_zod14.z.ZodIssueCode.custom,
|
|
3660
|
+
path: ["takerSignatureDerB64"],
|
|
3661
|
+
message: "signed requests require takerSignatureDerB64"
|
|
3662
|
+
});
|
|
3663
|
+
}
|
|
3664
|
+
}
|
|
3665
|
+
});
|
|
3666
|
+
function buildConsumerPaymentRequest(input) {
|
|
3667
|
+
const unsigned = {
|
|
3668
|
+
requestId: input.requestId,
|
|
3669
|
+
mode: input.mode,
|
|
3670
|
+
takerUserId: input.takerUserId,
|
|
3671
|
+
amountKobo: input.amountKobo,
|
|
3672
|
+
currency: input.currency ?? "NGN",
|
|
3673
|
+
reference: input.reference ?? null,
|
|
3674
|
+
createdAtMs: input.createdAtMs,
|
|
3675
|
+
expiresAtMs: input.expiresAtMs,
|
|
3676
|
+
nonce: input.nonce,
|
|
3677
|
+
takerDeviceId: input.takerDeviceId ?? null
|
|
3678
|
+
};
|
|
3679
|
+
if (unsigned.mode === "fixed" && !unsigned.takerDeviceId) {
|
|
3680
|
+
throw new Error("fixed requests require takerDeviceId");
|
|
3681
|
+
}
|
|
3682
|
+
if (unsigned.expiresAtMs <= unsigned.createdAtMs) {
|
|
3683
|
+
throw new Error("expiresAtMs must be greater than createdAtMs");
|
|
3684
|
+
}
|
|
3685
|
+
return unsigned;
|
|
3524
3686
|
}
|
|
3525
|
-
function
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3687
|
+
function consumerPaymentRequestSigningPayload(request) {
|
|
3688
|
+
return {
|
|
3689
|
+
domain: CONSUMER_PAYMENT_REQUEST_DOMAIN,
|
|
3690
|
+
version: 1,
|
|
3691
|
+
requestId: request.requestId,
|
|
3692
|
+
mode: request.mode,
|
|
3693
|
+
takerUserId: request.takerUserId,
|
|
3694
|
+
amountKobo: request.amountKobo,
|
|
3695
|
+
currency: request.currency,
|
|
3696
|
+
reference: request.reference ?? null,
|
|
3697
|
+
createdAtMs: request.createdAtMs,
|
|
3698
|
+
expiresAtMs: request.expiresAtMs,
|
|
3699
|
+
nonce: request.nonce,
|
|
3700
|
+
takerDeviceId: request.takerDeviceId ?? null
|
|
3701
|
+
};
|
|
3702
|
+
}
|
|
3703
|
+
function consumerPaymentRequestSigningBytes(request) {
|
|
3704
|
+
return canonicalJSONBytes(consumerPaymentRequestSigningPayload(request));
|
|
3705
|
+
}
|
|
3706
|
+
async function signConsumerPaymentRequest(unsigned, signer) {
|
|
3707
|
+
if (signer.alg !== "p256") {
|
|
3708
|
+
throw new Error("consumer payment requests require p256 signer");
|
|
3529
3709
|
}
|
|
3530
|
-
const
|
|
3710
|
+
const publicKey = await signer.getPublicKey();
|
|
3711
|
+
if (publicKey.alg !== "p256") {
|
|
3712
|
+
throw new Error("consumer payment requests require p256 public key");
|
|
3713
|
+
}
|
|
3714
|
+
const signature = await signer.sign(
|
|
3715
|
+
consumerPaymentRequestSigningBytes(unsigned)
|
|
3716
|
+
);
|
|
3717
|
+
return ConsumerPaymentRequestEnvelopeSchema.parse({
|
|
3718
|
+
...unsigned,
|
|
3719
|
+
takerPubkeySpkiB64: publicKey.publicKey,
|
|
3720
|
+
takerSignatureDerB64: signature.signature
|
|
3721
|
+
});
|
|
3722
|
+
}
|
|
3723
|
+
function verifyConsumerPaymentRequest(request) {
|
|
3724
|
+
const parsed = ConsumerPaymentRequestEnvelopeSchema.safeParse(request);
|
|
3725
|
+
if (!parsed.success) return false;
|
|
3726
|
+
const value = parsed.data;
|
|
3727
|
+
if (!value.takerPubkeySpkiB64 || !value.takerSignatureDerB64) return false;
|
|
3728
|
+
return verifyClaimSignature({
|
|
3729
|
+
alg: "p256",
|
|
3730
|
+
bytes: consumerPaymentRequestSigningBytes(value),
|
|
3731
|
+
signature: value.takerSignatureDerB64,
|
|
3732
|
+
publicKey: value.takerPubkeySpkiB64
|
|
3733
|
+
});
|
|
3734
|
+
}
|
|
3735
|
+
function isConsumerPaymentRequestExpired(request, nowMs = Date.now()) {
|
|
3736
|
+
const parsed = ConsumerPaymentRequestEnvelopeSchema.parse(request);
|
|
3737
|
+
return parsed.expiresAtMs <= nowMs;
|
|
3738
|
+
}
|
|
3739
|
+
|
|
3740
|
+
// src/me-offline/settlement.ts
|
|
3741
|
+
var CONSUMER_SETTLEMENT_DOMAIN = "flur:consumer-offline:v1:settlement";
|
|
3742
|
+
var CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX = "FLURSR1.";
|
|
3743
|
+
function consumerSettlementSigningPayload(settlement) {
|
|
3744
|
+
return {
|
|
3745
|
+
domain: CONSUMER_SETTLEMENT_DOMAIN,
|
|
3746
|
+
settlementId: settlement.settlementId,
|
|
3747
|
+
settlementKey: settlement.settlementKey,
|
|
3748
|
+
encounterId: settlement.encounterId,
|
|
3749
|
+
oacId: settlement.oacId,
|
|
3750
|
+
payerUserId: settlement.payerUserId,
|
|
3751
|
+
payeeUserId: settlement.payeeUserId,
|
|
3752
|
+
amountKobo: settlement.amountKobo,
|
|
3753
|
+
currency: settlement.currency,
|
|
3754
|
+
status: settlement.status,
|
|
3755
|
+
reviewReason: settlement.reviewReason,
|
|
3756
|
+
ledgerRef: settlement.ledgerRef,
|
|
3757
|
+
issuedAtMs: settlement.issuedAtMs
|
|
3758
|
+
};
|
|
3759
|
+
}
|
|
3760
|
+
function verifyConsumerSettlement(settlement, issuerPublicKeySpkiB64) {
|
|
3761
|
+
const parsed = ConsumerSettlementSchema.safeParse(settlement);
|
|
3762
|
+
if (!parsed.success) return false;
|
|
3763
|
+
return verifyIssuerP256(
|
|
3764
|
+
canonicalJSONBytes(consumerSettlementSigningPayload(parsed.data)),
|
|
3765
|
+
parsed.data.issuerSig,
|
|
3766
|
+
issuerPublicKeySpkiB64
|
|
3767
|
+
);
|
|
3768
|
+
}
|
|
3769
|
+
function encodeConsumerSettlementReceiptQR(settlement) {
|
|
3770
|
+
const parsed = ConsumerSettlementSchema.parse(settlement);
|
|
3771
|
+
return `${CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX}${base64UrlEncodeUtf8(
|
|
3772
|
+
JSON.stringify(parsed)
|
|
3773
|
+
)}`;
|
|
3774
|
+
}
|
|
3775
|
+
function decodeUnverifiedConsumerSettlementReceiptQR(value) {
|
|
3776
|
+
if (!value.startsWith(CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX)) {
|
|
3777
|
+
throw new Error("not a Flur consumer settlement receipt QR");
|
|
3778
|
+
}
|
|
3779
|
+
const encoded = value.slice(CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX.length);
|
|
3531
3780
|
let raw;
|
|
3532
3781
|
try {
|
|
3533
3782
|
raw = JSON.parse(base64UrlDecodeUtf8(encoded));
|
|
3534
3783
|
} catch {
|
|
3535
|
-
throw new Error("
|
|
3784
|
+
throw new Error("consumer settlement receipt QR is malformed");
|
|
3536
3785
|
}
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3786
|
+
return ConsumerSettlementSchema.parse(raw);
|
|
3787
|
+
}
|
|
3788
|
+
function verifyConsumerSettlementReceiptQR(value, issuerPublicKeySpkiB64) {
|
|
3789
|
+
const settlement = decodeUnverifiedConsumerSettlementReceiptQR(value);
|
|
3790
|
+
if (!verifyConsumerSettlement(settlement, issuerPublicKeySpkiB64)) {
|
|
3791
|
+
throw new Error("consumer settlement receipt QR signature invalid");
|
|
3540
3792
|
}
|
|
3541
|
-
return
|
|
3793
|
+
return settlement;
|
|
3542
3794
|
}
|
|
3543
|
-
function
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
return trimmed.split(/\s+/, 1)[0] ?? null;
|
|
3795
|
+
function decodeConsumerSettlementReceiptQR(value, issuerPublicKeySpkiB64) {
|
|
3796
|
+
if (!issuerPublicKeySpkiB64) {
|
|
3797
|
+
return decodeUnverifiedConsumerSettlementReceiptQR(value);
|
|
3547
3798
|
}
|
|
3548
|
-
return
|
|
3799
|
+
return verifyConsumerSettlementReceiptQR(value, issuerPublicKeySpkiB64);
|
|
3549
3800
|
}
|
|
3550
3801
|
function base64UrlEncodeUtf8(input) {
|
|
3551
3802
|
const bytes = new TextEncoder().encode(input);
|
|
@@ -3575,15 +3826,281 @@ function base64UrlDecodeUtf8(input) {
|
|
|
3575
3826
|
throw new Error("base64 decoder unavailable");
|
|
3576
3827
|
}
|
|
3577
3828
|
|
|
3829
|
+
// src/me-offline/sms.ts
|
|
3830
|
+
var import_nist3 = require("@noble/curves/nist");
|
|
3831
|
+
var OFFLINE_CLAIM_SMS_PREFIX = "FLURC1.";
|
|
3832
|
+
var CLAIM_TOKEN_RE = /(?:^|\s)(FLURC1\.[A-Za-z0-9_-]+={0,2})(?:\s|$)/;
|
|
3833
|
+
function encodeOfflineClaimSmsMessage(claim) {
|
|
3834
|
+
const parsed = ConsumerPaymentClaimSchema.parse(claim);
|
|
3835
|
+
return `${OFFLINE_CLAIM_SMS_PREFIX}${base64UrlEncodeUtf82(
|
|
3836
|
+
JSON.stringify(parsed)
|
|
3837
|
+
)}`;
|
|
3838
|
+
}
|
|
3839
|
+
function decodeOfflineClaimSmsMessage(message) {
|
|
3840
|
+
const token = extractOfflineClaimSmsToken(message);
|
|
3841
|
+
if (!token) throw new Error("offline claim QR token not found");
|
|
3842
|
+
const encoded = token.slice(OFFLINE_CLAIM_SMS_PREFIX.length);
|
|
3843
|
+
let raw;
|
|
3844
|
+
try {
|
|
3845
|
+
raw = JSON.parse(base64UrlDecodeUtf82(encoded));
|
|
3846
|
+
} catch {
|
|
3847
|
+
throw new Error("offline claim QR token is malformed");
|
|
3848
|
+
}
|
|
3849
|
+
const parsed = ConsumerPaymentClaimSchema.safeParse(raw);
|
|
3850
|
+
if (!parsed.success) throw new Error("offline claim QR token is invalid");
|
|
3851
|
+
return parsed.data;
|
|
3852
|
+
}
|
|
3853
|
+
function extractOfflineClaimSmsToken(message) {
|
|
3854
|
+
const trimmed = message.trim();
|
|
3855
|
+
if (trimmed.startsWith(OFFLINE_CLAIM_SMS_PREFIX)) {
|
|
3856
|
+
return trimmed.split(/\s+/, 1)[0] ?? null;
|
|
3857
|
+
}
|
|
3858
|
+
return CLAIM_TOKEN_RE.exec(message)?.[1] ?? null;
|
|
3859
|
+
}
|
|
3860
|
+
var OFFLINE_SMS_SETTLE_PREFIX = "FLURA1.";
|
|
3861
|
+
var OFFLINE_SMS_SETTLE_DOMAIN = "flur:consumer-offline:v1:attest";
|
|
3862
|
+
var OFFLINE_SMS_SETTLE_TOKEN_BYTES = 112;
|
|
3863
|
+
var OFFLINE_SMS_SETTLE_HEADER_BYTES = 48;
|
|
3864
|
+
var OFFLINE_SMS_SETTLE_SIGNATURE_BYTES = 64;
|
|
3865
|
+
var OFFLINE_SMS_SETTLE_VERSION = 1;
|
|
3866
|
+
var TOKEN_RE = /(?:^|[\s,;:()<>"'])(FLURA1\.[A-Za-z0-9_-]{150})/;
|
|
3867
|
+
async function encodeOfflineSmsSettleToken(input, signer) {
|
|
3868
|
+
const header = await buildSmsSettleHeader(input);
|
|
3869
|
+
const sig = await signer.signRaw(domainTag(header));
|
|
3870
|
+
if (sig.length !== OFFLINE_SMS_SETTLE_SIGNATURE_BYTES) {
|
|
3871
|
+
throw new Error(
|
|
3872
|
+
`FLURA1: signer returned ${sig.length}-byte sig; expected ${OFFLINE_SMS_SETTLE_SIGNATURE_BYTES}`
|
|
3873
|
+
);
|
|
3874
|
+
}
|
|
3875
|
+
const out = new Uint8Array(OFFLINE_SMS_SETTLE_TOKEN_BYTES);
|
|
3876
|
+
out.set(header, 0);
|
|
3877
|
+
out.set(sig, OFFLINE_SMS_SETTLE_HEADER_BYTES);
|
|
3878
|
+
return `${OFFLINE_SMS_SETTLE_PREFIX}${bytesToBase64Url(out)}`;
|
|
3879
|
+
}
|
|
3880
|
+
async function buildSmsSettleHeader(input) {
|
|
3881
|
+
assertSafeUint64(input.amountKobo, "amountKobo");
|
|
3882
|
+
if (input.amountKobo <= 0) {
|
|
3883
|
+
throw new Error("FLURA1: amountKobo must be greater than zero");
|
|
3884
|
+
}
|
|
3885
|
+
assertSafeUint48(input.occurredAtMs, "occurredAtMs");
|
|
3886
|
+
const encounterPrefix = (await sha2565(utf8(input.encounterId))).slice(0, 16);
|
|
3887
|
+
const payerPrefix = uuidToBytes(input.payerUserId).slice(0, 8);
|
|
3888
|
+
const payeePrefix = uuidToBytes(input.payeeUserId).slice(0, 8);
|
|
3889
|
+
const header = new Uint8Array(OFFLINE_SMS_SETTLE_HEADER_BYTES);
|
|
3890
|
+
const dv = new DataView(header.buffer);
|
|
3891
|
+
header[0] = OFFLINE_SMS_SETTLE_VERSION;
|
|
3892
|
+
header[1] = 0;
|
|
3893
|
+
header.set(encounterPrefix, 2);
|
|
3894
|
+
header.set(payerPrefix, 18);
|
|
3895
|
+
header.set(payeePrefix, 26);
|
|
3896
|
+
writeUint64BE(dv, 34, input.amountKobo);
|
|
3897
|
+
writeUint48BE(dv, 42, input.occurredAtMs);
|
|
3898
|
+
return header;
|
|
3899
|
+
}
|
|
3900
|
+
function domainTag(header) {
|
|
3901
|
+
if (header.length !== OFFLINE_SMS_SETTLE_HEADER_BYTES) {
|
|
3902
|
+
throw new Error(
|
|
3903
|
+
`FLURA1: header must be ${OFFLINE_SMS_SETTLE_HEADER_BYTES} bytes`
|
|
3904
|
+
);
|
|
3905
|
+
}
|
|
3906
|
+
const domain = utf8(OFFLINE_SMS_SETTLE_DOMAIN);
|
|
3907
|
+
const out = new Uint8Array(domain.length + header.length);
|
|
3908
|
+
out.set(domain, 0);
|
|
3909
|
+
out.set(header, domain.length);
|
|
3910
|
+
return out;
|
|
3911
|
+
}
|
|
3912
|
+
function decodeOfflineSmsSettleToken(message) {
|
|
3913
|
+
const token = extractOfflineSmsSettleToken(message);
|
|
3914
|
+
if (!token) throw new Error("FLURA1: token not found");
|
|
3915
|
+
const encoded = token.slice(OFFLINE_SMS_SETTLE_PREFIX.length);
|
|
3916
|
+
let bytes;
|
|
3917
|
+
try {
|
|
3918
|
+
bytes = base64UrlToBytes(encoded);
|
|
3919
|
+
} catch {
|
|
3920
|
+
throw new Error("FLURA1: token base64url is malformed");
|
|
3921
|
+
}
|
|
3922
|
+
if (bytesToBase64Url(bytes) !== encoded) {
|
|
3923
|
+
throw new Error("FLURA1: token base64url is malformed");
|
|
3924
|
+
}
|
|
3925
|
+
if (bytes.length !== OFFLINE_SMS_SETTLE_TOKEN_BYTES) {
|
|
3926
|
+
throw new Error(
|
|
3927
|
+
`FLURA1: expected ${OFFLINE_SMS_SETTLE_TOKEN_BYTES} bytes, got ${bytes.length}`
|
|
3928
|
+
);
|
|
3929
|
+
}
|
|
3930
|
+
const version = bytes[0];
|
|
3931
|
+
const flags = bytes[1];
|
|
3932
|
+
if (version !== OFFLINE_SMS_SETTLE_VERSION) {
|
|
3933
|
+
throw new Error(`FLURA1: unsupported version ${version}`);
|
|
3934
|
+
}
|
|
3935
|
+
if (flags !== 0) {
|
|
3936
|
+
throw new Error(`FLURA1: reserved flags must be 0, got ${flags}`);
|
|
3937
|
+
}
|
|
3938
|
+
const header = bytes.slice(0, OFFLINE_SMS_SETTLE_HEADER_BYTES);
|
|
3939
|
+
const signature = bytes.slice(OFFLINE_SMS_SETTLE_HEADER_BYTES);
|
|
3940
|
+
const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
3941
|
+
const amountKobo = readUint64BE(dv, 34);
|
|
3942
|
+
if (amountKobo <= 0) {
|
|
3943
|
+
throw new Error("FLURA1: amountKobo must be greater than zero");
|
|
3944
|
+
}
|
|
3945
|
+
return {
|
|
3946
|
+
version,
|
|
3947
|
+
flags,
|
|
3948
|
+
encounterIdPrefixHex: bytesToHex6(bytes.slice(2, 18)),
|
|
3949
|
+
payerUserIdPrefixHex: bytesToHex6(bytes.slice(18, 26)),
|
|
3950
|
+
payeeUserIdPrefixHex: bytesToHex6(bytes.slice(26, 34)),
|
|
3951
|
+
amountKobo,
|
|
3952
|
+
occurredAtMs: readUint48BE(dv, 42),
|
|
3953
|
+
signature,
|
|
3954
|
+
header,
|
|
3955
|
+
signedBytes: domainTag(header)
|
|
3956
|
+
};
|
|
3957
|
+
}
|
|
3958
|
+
function extractOfflineSmsSettleToken(message) {
|
|
3959
|
+
const trimmed = message.trim();
|
|
3960
|
+
if (trimmed.startsWith(OFFLINE_SMS_SETTLE_PREFIX)) {
|
|
3961
|
+
return trimmed.split(/\s+/, 1)[0] ?? null;
|
|
3962
|
+
}
|
|
3963
|
+
return TOKEN_RE.exec(message)?.[1] ?? null;
|
|
3964
|
+
}
|
|
3965
|
+
function verifyOfflineSmsSettleToken(decoded, payerPubkeySpkiB64) {
|
|
3966
|
+
try {
|
|
3967
|
+
const pubRaw = p256SpkiB64ToRaw(payerPubkeySpkiB64);
|
|
3968
|
+
return import_nist3.p256.verify(decoded.signature, decoded.signedBytes, pubRaw, {
|
|
3969
|
+
prehash: true,
|
|
3970
|
+
format: "compact"
|
|
3971
|
+
});
|
|
3972
|
+
} catch {
|
|
3973
|
+
return false;
|
|
3974
|
+
}
|
|
3975
|
+
}
|
|
3976
|
+
function derToRawP256Signature(derBytes) {
|
|
3977
|
+
const sig = import_nist3.p256.Signature.fromBytes(derBytes, "der");
|
|
3978
|
+
const raw = sig.toBytes("compact");
|
|
3979
|
+
if (raw.length !== OFFLINE_SMS_SETTLE_SIGNATURE_BYTES) {
|
|
3980
|
+
throw new Error(
|
|
3981
|
+
`FLURA1: DER\u2192raw produced ${raw.length} bytes; expected ${OFFLINE_SMS_SETTLE_SIGNATURE_BYTES}`
|
|
3982
|
+
);
|
|
3983
|
+
}
|
|
3984
|
+
return raw;
|
|
3985
|
+
}
|
|
3986
|
+
function utf8(s) {
|
|
3987
|
+
return new TextEncoder().encode(s);
|
|
3988
|
+
}
|
|
3989
|
+
async function sha2565(bytes) {
|
|
3990
|
+
const subtle = typeof globalThis !== "undefined" && globalThis.crypto?.subtle || void 0;
|
|
3991
|
+
if (subtle) {
|
|
3992
|
+
const digest = await subtle.digest("SHA-256", bytes);
|
|
3993
|
+
return new Uint8Array(digest);
|
|
3994
|
+
}
|
|
3995
|
+
const { sha256: nobleSha256 } = await import("@noble/hashes/sha2");
|
|
3996
|
+
return nobleSha256(bytes);
|
|
3997
|
+
}
|
|
3998
|
+
function uuidToBytes(uuid) {
|
|
3999
|
+
const hex = uuid.replace(/-/g, "").toLowerCase();
|
|
4000
|
+
if (hex.length !== 32 || !/^[0-9a-f]{32}$/.test(hex)) {
|
|
4001
|
+
throw new Error(`FLURA1: invalid UUID: ${uuid}`);
|
|
4002
|
+
}
|
|
4003
|
+
const out = new Uint8Array(16);
|
|
4004
|
+
for (let i = 0; i < 16; i++) {
|
|
4005
|
+
out[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16);
|
|
4006
|
+
}
|
|
4007
|
+
return out;
|
|
4008
|
+
}
|
|
4009
|
+
function assertSafeUint64(value, field) {
|
|
4010
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
4011
|
+
throw new Error(`FLURA1: ${field} must be a non-negative integer`);
|
|
4012
|
+
}
|
|
4013
|
+
if (value > Number.MAX_SAFE_INTEGER) {
|
|
4014
|
+
throw new Error(`FLURA1: ${field} exceeds Number.MAX_SAFE_INTEGER`);
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
function assertSafeUint48(value, field) {
|
|
4018
|
+
assertSafeUint64(value, field);
|
|
4019
|
+
if (value > 281474976710655) {
|
|
4020
|
+
throw new Error(`FLURA1: ${field} exceeds uint48 range`);
|
|
4021
|
+
}
|
|
4022
|
+
}
|
|
4023
|
+
function writeUint64BE(dv, offset, value) {
|
|
4024
|
+
const high = Math.floor(value / 4294967296);
|
|
4025
|
+
const low = value >>> 0;
|
|
4026
|
+
dv.setUint32(offset, high, false);
|
|
4027
|
+
dv.setUint32(offset + 4, low, false);
|
|
4028
|
+
}
|
|
4029
|
+
function readUint64BE(dv, offset) {
|
|
4030
|
+
const high = dv.getUint32(offset, false);
|
|
4031
|
+
const low = dv.getUint32(offset + 4, false);
|
|
4032
|
+
if (high > 2097151) {
|
|
4033
|
+
throw new Error("FLURA1: amountKobo exceeds Number.MAX_SAFE_INTEGER");
|
|
4034
|
+
}
|
|
4035
|
+
return high * 4294967296 + low;
|
|
4036
|
+
}
|
|
4037
|
+
function writeUint48BE(dv, offset, value) {
|
|
4038
|
+
const high = Math.floor(value / 65536);
|
|
4039
|
+
const low = value & 65535;
|
|
4040
|
+
dv.setUint32(offset, high, false);
|
|
4041
|
+
dv.setUint16(offset + 4, low, false);
|
|
4042
|
+
}
|
|
4043
|
+
function readUint48BE(dv, offset) {
|
|
4044
|
+
const high = dv.getUint32(offset, false);
|
|
4045
|
+
const low = dv.getUint16(offset + 4, false);
|
|
4046
|
+
return high * 65536 + low;
|
|
4047
|
+
}
|
|
4048
|
+
function bytesToHex6(bytes) {
|
|
4049
|
+
let out = "";
|
|
4050
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
4051
|
+
out += bytes[i].toString(16).padStart(2, "0");
|
|
4052
|
+
}
|
|
4053
|
+
return out;
|
|
4054
|
+
}
|
|
4055
|
+
function bytesToBase64Url(bytes) {
|
|
4056
|
+
let base64;
|
|
4057
|
+
if (typeof Buffer !== "undefined") {
|
|
4058
|
+
base64 = Buffer.from(bytes).toString("base64");
|
|
4059
|
+
} else {
|
|
4060
|
+
let binary = "";
|
|
4061
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
4062
|
+
binary += String.fromCharCode(bytes[i]);
|
|
4063
|
+
}
|
|
4064
|
+
if (typeof btoa !== "function") {
|
|
4065
|
+
throw new Error("FLURA1: base64 encoder unavailable");
|
|
4066
|
+
}
|
|
4067
|
+
base64 = btoa(binary);
|
|
4068
|
+
}
|
|
4069
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
4070
|
+
}
|
|
4071
|
+
function base64UrlEncodeUtf82(input) {
|
|
4072
|
+
return bytesToBase64Url(utf8(input));
|
|
4073
|
+
}
|
|
4074
|
+
function base64UrlDecodeUtf82(input) {
|
|
4075
|
+
return new TextDecoder().decode(base64UrlToBytes(input));
|
|
4076
|
+
}
|
|
4077
|
+
function base64UrlToBytes(input) {
|
|
4078
|
+
const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
4079
|
+
const padded = base64.padEnd(
|
|
4080
|
+
base64.length + (4 - base64.length % 4) % 4,
|
|
4081
|
+
"="
|
|
4082
|
+
);
|
|
4083
|
+
if (typeof Buffer !== "undefined") {
|
|
4084
|
+
return new Uint8Array(Buffer.from(padded, "base64"));
|
|
4085
|
+
}
|
|
4086
|
+
if (typeof atob !== "function") {
|
|
4087
|
+
throw new Error("FLURA1: base64 decoder unavailable");
|
|
4088
|
+
}
|
|
4089
|
+
const binary = atob(padded);
|
|
4090
|
+
const out = new Uint8Array(binary.length);
|
|
4091
|
+
for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);
|
|
4092
|
+
return out;
|
|
4093
|
+
}
|
|
4094
|
+
|
|
3578
4095
|
// src/partner-funding/client.ts
|
|
3579
|
-
var
|
|
3580
|
-
var MinorString =
|
|
3581
|
-
var PositiveMinor =
|
|
3582
|
-
|
|
3583
|
-
|
|
4096
|
+
var import_zod15 = require("zod");
|
|
4097
|
+
var MinorString = import_zod15.z.string().regex(/^-?\d+$/);
|
|
4098
|
+
var PositiveMinor = import_zod15.z.union([
|
|
4099
|
+
import_zod15.z.number().int().positive(),
|
|
4100
|
+
import_zod15.z.string().regex(/^[1-9]\d{0,18}$/)
|
|
3584
4101
|
]);
|
|
3585
|
-
var Currency =
|
|
3586
|
-
var Metadata =
|
|
4102
|
+
var Currency = import_zod15.z.string().trim().length(3).transform((v) => v.toUpperCase());
|
|
4103
|
+
var Metadata = import_zod15.z.record(import_zod15.z.unknown());
|
|
3587
4104
|
var PARTNER_KINDS = ["bank", "merchant"];
|
|
3588
4105
|
var CUSTODIAL_MODES = ["agent_of_bank", "flur_virtual_pool"];
|
|
3589
4106
|
var PARTNER_PROFILE_STATUSES = [
|
|
@@ -3610,126 +4127,126 @@ var WITHDRAWAL_STATES = [
|
|
|
3610
4127
|
"failed",
|
|
3611
4128
|
"reversed"
|
|
3612
4129
|
];
|
|
3613
|
-
var PartnerProfileSchema =
|
|
3614
|
-
partnerAccountId:
|
|
3615
|
-
kind:
|
|
3616
|
-
custodialMode:
|
|
3617
|
-
displayName:
|
|
3618
|
-
bankCode:
|
|
3619
|
-
poolAccountNumber:
|
|
3620
|
-
status:
|
|
4130
|
+
var PartnerProfileSchema = import_zod15.z.object({
|
|
4131
|
+
partnerAccountId: import_zod15.z.string().uuid(),
|
|
4132
|
+
kind: import_zod15.z.enum(PARTNER_KINDS),
|
|
4133
|
+
custodialMode: import_zod15.z.enum(CUSTODIAL_MODES),
|
|
4134
|
+
displayName: import_zod15.z.string(),
|
|
4135
|
+
bankCode: import_zod15.z.string().nullable(),
|
|
4136
|
+
poolAccountNumber: import_zod15.z.string().nullable(),
|
|
4137
|
+
status: import_zod15.z.enum(PARTNER_PROFILE_STATUSES),
|
|
3621
4138
|
metadata: Metadata,
|
|
3622
|
-
createdAtMs:
|
|
3623
|
-
updatedAtMs:
|
|
4139
|
+
createdAtMs: import_zod15.z.number().int().nonnegative(),
|
|
4140
|
+
updatedAtMs: import_zod15.z.number().int().nonnegative()
|
|
3624
4141
|
});
|
|
3625
|
-
var UpsertPartnerProfileInputSchema =
|
|
3626
|
-
kind:
|
|
3627
|
-
custodialMode:
|
|
3628
|
-
displayName:
|
|
3629
|
-
bankCode:
|
|
3630
|
-
poolAccountNumber:
|
|
4142
|
+
var UpsertPartnerProfileInputSchema = import_zod15.z.object({
|
|
4143
|
+
kind: import_zod15.z.enum(PARTNER_KINDS),
|
|
4144
|
+
custodialMode: import_zod15.z.enum(CUSTODIAL_MODES),
|
|
4145
|
+
displayName: import_zod15.z.string().trim().min(1).max(200),
|
|
4146
|
+
bankCode: import_zod15.z.string().trim().min(1).max(64).optional(),
|
|
4147
|
+
poolAccountNumber: import_zod15.z.string().trim().min(1).max(64).optional(),
|
|
3631
4148
|
metadata: Metadata.optional()
|
|
3632
4149
|
});
|
|
3633
|
-
var PartnerFundingEventInputSchema =
|
|
3634
|
-
externalRef:
|
|
3635
|
-
direction:
|
|
3636
|
-
userId:
|
|
3637
|
-
accountId:
|
|
4150
|
+
var PartnerFundingEventInputSchema = import_zod15.z.object({
|
|
4151
|
+
externalRef: import_zod15.z.string().trim().min(8).max(128),
|
|
4152
|
+
direction: import_zod15.z.enum(PARTNER_FUNDING_DIRECTIONS).optional(),
|
|
4153
|
+
userId: import_zod15.z.string().uuid().optional(),
|
|
4154
|
+
accountId: import_zod15.z.string().uuid().optional(),
|
|
3638
4155
|
amountMinor: PositiveMinor,
|
|
3639
4156
|
currency: Currency,
|
|
3640
|
-
fundingSource:
|
|
4157
|
+
fundingSource: import_zod15.z.string().trim().min(1).max(64).optional(),
|
|
3641
4158
|
providerMetadata: Metadata.optional()
|
|
3642
4159
|
});
|
|
3643
|
-
var PartnerFundingSchema =
|
|
3644
|
-
fundingId:
|
|
3645
|
-
partnerId:
|
|
3646
|
-
accountId:
|
|
3647
|
-
userId:
|
|
3648
|
-
direction:
|
|
3649
|
-
currency:
|
|
4160
|
+
var PartnerFundingSchema = import_zod15.z.object({
|
|
4161
|
+
fundingId: import_zod15.z.string().uuid(),
|
|
4162
|
+
partnerId: import_zod15.z.string().uuid(),
|
|
4163
|
+
accountId: import_zod15.z.string().uuid(),
|
|
4164
|
+
userId: import_zod15.z.string().uuid().nullable(),
|
|
4165
|
+
direction: import_zod15.z.enum(PARTNER_FUNDING_DIRECTIONS),
|
|
4166
|
+
currency: import_zod15.z.string(),
|
|
3650
4167
|
amountMinor: MinorString,
|
|
3651
|
-
externalRef:
|
|
3652
|
-
status:
|
|
3653
|
-
fundingSource:
|
|
3654
|
-
ledgerRef:
|
|
4168
|
+
externalRef: import_zod15.z.string(),
|
|
4169
|
+
status: import_zod15.z.enum(PARTNER_FUNDING_STATUSES),
|
|
4170
|
+
fundingSource: import_zod15.z.string(),
|
|
4171
|
+
ledgerRef: import_zod15.z.string(),
|
|
3655
4172
|
providerMetadata: Metadata,
|
|
3656
|
-
createdAtMs:
|
|
3657
|
-
updatedAtMs:
|
|
4173
|
+
createdAtMs: import_zod15.z.number().int().nonnegative(),
|
|
4174
|
+
updatedAtMs: import_zod15.z.number().int().nonnegative()
|
|
3658
4175
|
});
|
|
3659
|
-
var IngestFundingResultSchema =
|
|
4176
|
+
var IngestFundingResultSchema = import_zod15.z.object({
|
|
3660
4177
|
funding: PartnerFundingSchema,
|
|
3661
|
-
replayed:
|
|
4178
|
+
replayed: import_zod15.z.boolean()
|
|
3662
4179
|
});
|
|
3663
|
-
var PayoutDestinationSchema =
|
|
3664
|
-
destinationId:
|
|
3665
|
-
accountId:
|
|
3666
|
-
partnerId:
|
|
3667
|
-
bankCode:
|
|
3668
|
-
accountNumber:
|
|
3669
|
-
accountName:
|
|
3670
|
-
status:
|
|
3671
|
-
verifiedAtMs:
|
|
4180
|
+
var PayoutDestinationSchema = import_zod15.z.object({
|
|
4181
|
+
destinationId: import_zod15.z.string().uuid(),
|
|
4182
|
+
accountId: import_zod15.z.string().uuid(),
|
|
4183
|
+
partnerId: import_zod15.z.string().uuid(),
|
|
4184
|
+
bankCode: import_zod15.z.string(),
|
|
4185
|
+
accountNumber: import_zod15.z.string(),
|
|
4186
|
+
accountName: import_zod15.z.string(),
|
|
4187
|
+
status: import_zod15.z.enum(PAYOUT_DESTINATION_STATUSES),
|
|
4188
|
+
verifiedAtMs: import_zod15.z.number().int().nonnegative().nullable(),
|
|
3672
4189
|
metadata: Metadata,
|
|
3673
|
-
createdAtMs:
|
|
3674
|
-
updatedAtMs:
|
|
4190
|
+
createdAtMs: import_zod15.z.number().int().nonnegative(),
|
|
4191
|
+
updatedAtMs: import_zod15.z.number().int().nonnegative()
|
|
3675
4192
|
});
|
|
3676
|
-
var CreatePayoutDestinationInputSchema =
|
|
3677
|
-
partnerId:
|
|
3678
|
-
bankCode:
|
|
3679
|
-
accountNumber:
|
|
3680
|
-
accountName:
|
|
4193
|
+
var CreatePayoutDestinationInputSchema = import_zod15.z.object({
|
|
4194
|
+
partnerId: import_zod15.z.string().uuid(),
|
|
4195
|
+
bankCode: import_zod15.z.string().trim().min(1).max(32),
|
|
4196
|
+
accountNumber: import_zod15.z.string().trim().min(4).max(64),
|
|
4197
|
+
accountName: import_zod15.z.string().trim().min(1).max(200),
|
|
3681
4198
|
metadata: Metadata.optional()
|
|
3682
4199
|
});
|
|
3683
|
-
var ListPayoutDestinationsResultSchema =
|
|
3684
|
-
items:
|
|
4200
|
+
var ListPayoutDestinationsResultSchema = import_zod15.z.object({
|
|
4201
|
+
items: import_zod15.z.array(PayoutDestinationSchema)
|
|
3685
4202
|
});
|
|
3686
|
-
var WithdrawalSchema =
|
|
3687
|
-
withdrawalId:
|
|
3688
|
-
accountId:
|
|
3689
|
-
userId:
|
|
3690
|
-
partnerId:
|
|
3691
|
-
destinationId:
|
|
3692
|
-
currency:
|
|
4203
|
+
var WithdrawalSchema = import_zod15.z.object({
|
|
4204
|
+
withdrawalId: import_zod15.z.string().uuid(),
|
|
4205
|
+
accountId: import_zod15.z.string().uuid(),
|
|
4206
|
+
userId: import_zod15.z.string().uuid(),
|
|
4207
|
+
partnerId: import_zod15.z.string().uuid(),
|
|
4208
|
+
destinationId: import_zod15.z.string().uuid(),
|
|
4209
|
+
currency: import_zod15.z.string(),
|
|
3693
4210
|
amountMinor: MinorString,
|
|
3694
|
-
state:
|
|
3695
|
-
idempotencyKey:
|
|
3696
|
-
providerRef:
|
|
3697
|
-
lastError:
|
|
3698
|
-
ledgerRef:
|
|
3699
|
-
reverseLedgerRef:
|
|
4211
|
+
state: import_zod15.z.enum(WITHDRAWAL_STATES),
|
|
4212
|
+
idempotencyKey: import_zod15.z.string(),
|
|
4213
|
+
providerRef: import_zod15.z.string().nullable(),
|
|
4214
|
+
lastError: import_zod15.z.string().nullable(),
|
|
4215
|
+
ledgerRef: import_zod15.z.string(),
|
|
4216
|
+
reverseLedgerRef: import_zod15.z.string().nullable(),
|
|
3700
4217
|
metadata: Metadata,
|
|
3701
|
-
createdAtMs:
|
|
3702
|
-
updatedAtMs:
|
|
4218
|
+
createdAtMs: import_zod15.z.number().int().nonnegative(),
|
|
4219
|
+
updatedAtMs: import_zod15.z.number().int().nonnegative()
|
|
3703
4220
|
});
|
|
3704
|
-
var CreateWithdrawalInputSchema =
|
|
3705
|
-
destinationId:
|
|
4221
|
+
var CreateWithdrawalInputSchema = import_zod15.z.object({
|
|
4222
|
+
destinationId: import_zod15.z.string().uuid(),
|
|
3706
4223
|
amountMinor: PositiveMinor,
|
|
3707
4224
|
currency: Currency,
|
|
3708
|
-
idempotencyKey:
|
|
4225
|
+
idempotencyKey: import_zod15.z.string().trim().min(8).max(128),
|
|
3709
4226
|
metadata: Metadata.optional()
|
|
3710
4227
|
});
|
|
3711
|
-
var CreateWithdrawalResultSchema =
|
|
4228
|
+
var CreateWithdrawalResultSchema = import_zod15.z.object({
|
|
3712
4229
|
withdrawal: WithdrawalSchema,
|
|
3713
|
-
replayed:
|
|
4230
|
+
replayed: import_zod15.z.boolean()
|
|
3714
4231
|
});
|
|
3715
|
-
var PayoutEventInputSchema =
|
|
3716
|
-
externalRef:
|
|
3717
|
-
withdrawalId:
|
|
3718
|
-
state:
|
|
3719
|
-
providerRef:
|
|
3720
|
-
failureCode:
|
|
3721
|
-
failureMessage:
|
|
4232
|
+
var PayoutEventInputSchema = import_zod15.z.object({
|
|
4233
|
+
externalRef: import_zod15.z.string().trim().min(8).max(128),
|
|
4234
|
+
withdrawalId: import_zod15.z.string().uuid().optional(),
|
|
4235
|
+
state: import_zod15.z.enum(["submitted", "processing", "paid", "failed"]),
|
|
4236
|
+
providerRef: import_zod15.z.string().trim().min(1).max(128).optional(),
|
|
4237
|
+
failureCode: import_zod15.z.string().trim().max(64).optional(),
|
|
4238
|
+
failureMessage: import_zod15.z.string().trim().max(512).optional(),
|
|
3722
4239
|
providerMetadata: Metadata.optional()
|
|
3723
4240
|
});
|
|
3724
|
-
var RecordPayoutEventResultSchema =
|
|
4241
|
+
var RecordPayoutEventResultSchema = import_zod15.z.object({
|
|
3725
4242
|
withdrawal: WithdrawalSchema,
|
|
3726
|
-
replayed:
|
|
4243
|
+
replayed: import_zod15.z.boolean()
|
|
3727
4244
|
});
|
|
3728
|
-
var ReconciliationReportSchema =
|
|
3729
|
-
partnerId:
|
|
3730
|
-
currency:
|
|
3731
|
-
fromMs:
|
|
3732
|
-
toMs:
|
|
4245
|
+
var ReconciliationReportSchema = import_zod15.z.object({
|
|
4246
|
+
partnerId: import_zod15.z.string().uuid(),
|
|
4247
|
+
currency: import_zod15.z.string(),
|
|
4248
|
+
fromMs: import_zod15.z.number().int().nonnegative(),
|
|
4249
|
+
toMs: import_zod15.z.number().int().nonnegative(),
|
|
3733
4250
|
fundingsCreditMinor: MinorString,
|
|
3734
4251
|
fundingsDebitMinor: MinorString,
|
|
3735
4252
|
withdrawalsPaidMinor: MinorString,
|
|
@@ -3738,7 +4255,7 @@ var ReconciliationReportSchema = import_zod14.z.object({
|
|
|
3738
4255
|
expectedReserveBalanceMinor: MinorString,
|
|
3739
4256
|
actualReserveBalanceMinor: MinorString,
|
|
3740
4257
|
imbalanceMinor: MinorString,
|
|
3741
|
-
generatedAtMs:
|
|
4258
|
+
generatedAtMs: import_zod15.z.number().int().nonnegative()
|
|
3742
4259
|
});
|
|
3743
4260
|
function createPartnerFundingClient(partner) {
|
|
3744
4261
|
return {
|
|
@@ -3890,19 +4407,19 @@ function createPartnerProfileAdminClient(opts) {
|
|
|
3890
4407
|
}
|
|
3891
4408
|
|
|
3892
4409
|
// src/artifacts/envelope.ts
|
|
3893
|
-
var
|
|
4410
|
+
var import_zod16 = require("zod");
|
|
3894
4411
|
var FLUR_ARTIFACT_URI_SCHEME = "flur";
|
|
3895
4412
|
var FLUR_ARTIFACT_VERSION = 1;
|
|
3896
4413
|
var FLUR_ARTIFACT_URI_PREFIX = `${FLUR_ARTIFACT_URI_SCHEME}://v${FLUR_ARTIFACT_VERSION}/`;
|
|
3897
4414
|
var ArtifactTypeRe = /^[a-z][a-z0-9_]{1,63}$/;
|
|
3898
|
-
var ArtifactHeaderSchema =
|
|
3899
|
-
v:
|
|
3900
|
-
t:
|
|
3901
|
-
iss:
|
|
3902
|
-
kid:
|
|
3903
|
-
iat:
|
|
3904
|
-
exp:
|
|
3905
|
-
nonce:
|
|
4415
|
+
var ArtifactHeaderSchema = import_zod16.z.object({
|
|
4416
|
+
v: import_zod16.z.literal(FLUR_ARTIFACT_VERSION),
|
|
4417
|
+
t: import_zod16.z.string().regex(ArtifactTypeRe, "invalid artifact type"),
|
|
4418
|
+
iss: import_zod16.z.string().min(1).max(128),
|
|
4419
|
+
kid: import_zod16.z.string().min(1).max(128),
|
|
4420
|
+
iat: import_zod16.z.number().int().nonnegative(),
|
|
4421
|
+
exp: import_zod16.z.number().int().positive().optional(),
|
|
4422
|
+
nonce: import_zod16.z.string().min(8).max(64).regex(/^[A-Za-z0-9_-]+$/, "nonce must be url-safe")
|
|
3906
4423
|
});
|
|
3907
4424
|
var FlurArtifactError = class extends Error {
|
|
3908
4425
|
constructor(message, code) {
|
|
@@ -4041,7 +4558,7 @@ function verifyArtifactSignature(decoded, publicKeySpkiB64, options = {}) {
|
|
|
4041
4558
|
}
|
|
4042
4559
|
|
|
4043
4560
|
// src/artifacts/types.ts
|
|
4044
|
-
var
|
|
4561
|
+
var import_zod17 = require("zod");
|
|
4045
4562
|
var ARTIFACT_TYPES = {
|
|
4046
4563
|
OFFLINE_PAYMENT_AUTHORIZATION: "offline_payment_authorization",
|
|
4047
4564
|
RECEIPT: "receipt",
|
|
@@ -4054,34 +4571,37 @@ var ARTIFACT_TYPES = {
|
|
|
4054
4571
|
LEDGER_JOURNAL_ENTRY: "ledger_journal_entry",
|
|
4055
4572
|
STATEMENT: "statement",
|
|
4056
4573
|
PASS: "pass",
|
|
4057
|
-
IDENTITY: "identity"
|
|
4574
|
+
IDENTITY: "identity",
|
|
4575
|
+
// Tier B: holder-signed identity attestation for offline trust. The
|
|
4576
|
+
// envelope.iat / envelope.exp express the card's canonical lifetime.
|
|
4577
|
+
PAY_CARD: "pay_card"
|
|
4058
4578
|
};
|
|
4059
|
-
var HexString = (length) =>
|
|
4579
|
+
var HexString = (length) => import_zod17.z.string().regex(
|
|
4060
4580
|
new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
|
|
4061
4581
|
`expected ${length}-byte hex string`
|
|
4062
4582
|
);
|
|
4063
|
-
var OfflinePaymentAuthorizationArtifactSchema =
|
|
4583
|
+
var OfflinePaymentAuthorizationArtifactSchema = import_zod17.z.object({
|
|
4064
4584
|
authorization: OfflinePaymentAuthorizationSchema
|
|
4065
4585
|
});
|
|
4066
|
-
var ReceiptArtifactSchema =
|
|
4067
|
-
receiptId:
|
|
4068
|
-
paymentReference:
|
|
4069
|
-
payerUserId:
|
|
4070
|
-
payeeUserId:
|
|
4071
|
-
amountKobo:
|
|
4072
|
-
currency:
|
|
4073
|
-
channel:
|
|
4074
|
-
settledAtMs:
|
|
4075
|
-
ledgerTxnId:
|
|
4076
|
-
memo:
|
|
4586
|
+
var ReceiptArtifactSchema = import_zod17.z.object({
|
|
4587
|
+
receiptId: import_zod17.z.string().min(1).max(64),
|
|
4588
|
+
paymentReference: import_zod17.z.string().min(1).max(64),
|
|
4589
|
+
payerUserId: import_zod17.z.string().min(1).max(64).optional(),
|
|
4590
|
+
payeeUserId: import_zod17.z.string().min(1).max(64),
|
|
4591
|
+
amountKobo: import_zod17.z.number().int().positive(),
|
|
4592
|
+
currency: import_zod17.z.literal("NGN"),
|
|
4593
|
+
channel: import_zod17.z.enum(["online", "offline_reconciled", "pay_link", "nqr"]),
|
|
4594
|
+
settledAtMs: import_zod17.z.number().int().positive(),
|
|
4595
|
+
ledgerTxnId: import_zod17.z.string().min(1).max(64).optional(),
|
|
4596
|
+
memo: import_zod17.z.string().max(140).optional(),
|
|
4077
4597
|
hashChainPrev: HexString(32).optional()
|
|
4078
4598
|
});
|
|
4079
|
-
var ShortId =
|
|
4080
|
-
var PositiveInt =
|
|
4081
|
-
var NonNegativeInt =
|
|
4082
|
-
var Currency2 =
|
|
4083
|
-
var Memo =
|
|
4084
|
-
var NqrPaymentRequestArtifactSchema =
|
|
4599
|
+
var ShortId = import_zod17.z.string().min(1).max(64);
|
|
4600
|
+
var PositiveInt = import_zod17.z.number().int().positive();
|
|
4601
|
+
var NonNegativeInt = import_zod17.z.number().int().nonnegative();
|
|
4602
|
+
var Currency2 = import_zod17.z.literal("NGN");
|
|
4603
|
+
var Memo = import_zod17.z.string().max(140);
|
|
4604
|
+
var NqrPaymentRequestArtifactSchema = import_zod17.z.object({
|
|
4085
4605
|
requestId: ShortId,
|
|
4086
4606
|
payeeUserId: ShortId,
|
|
4087
4607
|
amountKobo: PositiveInt.optional(),
|
|
@@ -4089,7 +4609,7 @@ var NqrPaymentRequestArtifactSchema = import_zod16.z.object({
|
|
|
4089
4609
|
memo: Memo.optional(),
|
|
4090
4610
|
expiresAtMs: PositiveInt.optional()
|
|
4091
4611
|
});
|
|
4092
|
-
var PaymentIntentArtifactSchema =
|
|
4612
|
+
var PaymentIntentArtifactSchema = import_zod17.z.object({
|
|
4093
4613
|
intentId: ShortId,
|
|
4094
4614
|
payerUserId: ShortId,
|
|
4095
4615
|
payeeUserId: ShortId,
|
|
@@ -4098,7 +4618,7 @@ var PaymentIntentArtifactSchema = import_zod16.z.object({
|
|
|
4098
4618
|
idempotencyKey: ShortId,
|
|
4099
4619
|
createdAtMs: PositiveInt
|
|
4100
4620
|
});
|
|
4101
|
-
var OfflineClaimArtifactSchema =
|
|
4621
|
+
var OfflineClaimArtifactSchema = import_zod17.z.object({
|
|
4102
4622
|
claimId: ShortId,
|
|
4103
4623
|
authorizationId: ShortId,
|
|
4104
4624
|
payeeUserId: ShortId,
|
|
@@ -4107,10 +4627,10 @@ var OfflineClaimArtifactSchema = import_zod16.z.object({
|
|
|
4107
4627
|
claimedAtMs: PositiveInt,
|
|
4108
4628
|
paymentReference: ShortId.optional()
|
|
4109
4629
|
});
|
|
4110
|
-
var SettlementRecordArtifactSchema =
|
|
4630
|
+
var SettlementRecordArtifactSchema = import_zod17.z.object({
|
|
4111
4631
|
settlementId: ShortId,
|
|
4112
4632
|
ledgerTxnId: ShortId,
|
|
4113
|
-
sourceRefType:
|
|
4633
|
+
sourceRefType: import_zod17.z.enum([
|
|
4114
4634
|
"offline_authorization",
|
|
4115
4635
|
"offline_claim",
|
|
4116
4636
|
"transfer",
|
|
@@ -4121,12 +4641,12 @@ var SettlementRecordArtifactSchema = import_zod16.z.object({
|
|
|
4121
4641
|
currency: Currency2,
|
|
4122
4642
|
settledAtMs: PositiveInt
|
|
4123
4643
|
});
|
|
4124
|
-
var ReversalRecordArtifactSchema =
|
|
4644
|
+
var ReversalRecordArtifactSchema = import_zod17.z.object({
|
|
4125
4645
|
reversalId: ShortId,
|
|
4126
4646
|
originalTxnId: ShortId,
|
|
4127
4647
|
amountKobo: PositiveInt,
|
|
4128
4648
|
currency: Currency2,
|
|
4129
|
-
reason:
|
|
4649
|
+
reason: import_zod17.z.enum([
|
|
4130
4650
|
"user_dispute",
|
|
4131
4651
|
"fraud",
|
|
4132
4652
|
"duplicate",
|
|
@@ -4136,7 +4656,7 @@ var ReversalRecordArtifactSchema = import_zod16.z.object({
|
|
|
4136
4656
|
reversedAtMs: PositiveInt,
|
|
4137
4657
|
memo: Memo.optional()
|
|
4138
4658
|
});
|
|
4139
|
-
var LedgerJournalEntryArtifactSchema =
|
|
4659
|
+
var LedgerJournalEntryArtifactSchema = import_zod17.z.object({
|
|
4140
4660
|
entryId: ShortId,
|
|
4141
4661
|
journalId: ShortId,
|
|
4142
4662
|
debitAccountId: ShortId,
|
|
@@ -4147,13 +4667,13 @@ var LedgerJournalEntryArtifactSchema = import_zod16.z.object({
|
|
|
4147
4667
|
refType: ShortId.optional(),
|
|
4148
4668
|
refId: ShortId.optional()
|
|
4149
4669
|
});
|
|
4150
|
-
var StatementArtifactSchema =
|
|
4670
|
+
var StatementArtifactSchema = import_zod17.z.object({
|
|
4151
4671
|
statementId: ShortId,
|
|
4152
4672
|
userId: ShortId,
|
|
4153
4673
|
periodStartMs: PositiveInt,
|
|
4154
4674
|
periodEndMs: PositiveInt,
|
|
4155
|
-
openingBalanceKobo:
|
|
4156
|
-
closingBalanceKobo:
|
|
4675
|
+
openingBalanceKobo: import_zod17.z.number().int(),
|
|
4676
|
+
closingBalanceKobo: import_zod17.z.number().int(),
|
|
4157
4677
|
transactionCount: NonNegativeInt,
|
|
4158
4678
|
currency: Currency2,
|
|
4159
4679
|
hashChainPrev: HexString(32).optional()
|
|
@@ -4161,16 +4681,16 @@ var StatementArtifactSchema = import_zod16.z.object({
|
|
|
4161
4681
|
message: "periodEndMs must be greater than periodStartMs",
|
|
4162
4682
|
path: ["periodEndMs"]
|
|
4163
4683
|
});
|
|
4164
|
-
var PassArtifactSchema =
|
|
4684
|
+
var PassArtifactSchema = import_zod17.z.object({
|
|
4165
4685
|
passId: ShortId,
|
|
4166
4686
|
holderId: ShortId,
|
|
4167
|
-
category:
|
|
4168
|
-
title:
|
|
4687
|
+
category: import_zod17.z.enum(["membership", "ticket", "loyalty", "access", "voucher"]),
|
|
4688
|
+
title: import_zod17.z.string().min(1).max(120),
|
|
4169
4689
|
validFromMs: PositiveInt,
|
|
4170
4690
|
validUntilMs: PositiveInt.optional(),
|
|
4171
|
-
metadata:
|
|
4172
|
-
|
|
4173
|
-
|
|
4691
|
+
metadata: import_zod17.z.record(
|
|
4692
|
+
import_zod17.z.string().min(1).max(64),
|
|
4693
|
+
import_zod17.z.union([import_zod17.z.string().max(280), import_zod17.z.number(), import_zod17.z.boolean()])
|
|
4174
4694
|
).optional()
|
|
4175
4695
|
}).refine(
|
|
4176
4696
|
(v) => v.validUntilMs === void 0 || v.validUntilMs > v.validFromMs,
|
|
@@ -4179,10 +4699,10 @@ var PassArtifactSchema = import_zod16.z.object({
|
|
|
4179
4699
|
path: ["validUntilMs"]
|
|
4180
4700
|
}
|
|
4181
4701
|
);
|
|
4182
|
-
var IdentityArtifactSchema =
|
|
4702
|
+
var IdentityArtifactSchema = import_zod17.z.object({
|
|
4183
4703
|
attestationId: ShortId,
|
|
4184
4704
|
subjectId: ShortId,
|
|
4185
|
-
claimType:
|
|
4705
|
+
claimType: import_zod17.z.enum([
|
|
4186
4706
|
"phone_verified",
|
|
4187
4707
|
"email_verified",
|
|
4188
4708
|
"bvn_verified",
|
|
@@ -4192,6 +4712,12 @@ var IdentityArtifactSchema = import_zod16.z.object({
|
|
|
4192
4712
|
claimValueHash: HexString(32),
|
|
4193
4713
|
attestedAtMs: PositiveInt
|
|
4194
4714
|
});
|
|
4715
|
+
var PayCardArtifactSchema = import_zod17.z.object({
|
|
4716
|
+
userId: ShortId,
|
|
4717
|
+
phoneE164: import_zod17.z.string().regex(/^\+[1-9]\d{7,14}$/, "phoneE164 must be normalised E.164"),
|
|
4718
|
+
displayName: import_zod17.z.string().min(1).max(64),
|
|
4719
|
+
devicePubKeySpkiB64: import_zod17.z.string().min(64).max(256).regex(/^[A-Za-z0-9+/]+=*$/, "devicePubKeySpkiB64 must be standard base64")
|
|
4720
|
+
});
|
|
4195
4721
|
var ARTIFACT_BODY_SCHEMAS = {
|
|
4196
4722
|
[ARTIFACT_TYPES.OFFLINE_PAYMENT_AUTHORIZATION]: OfflinePaymentAuthorizationArtifactSchema,
|
|
4197
4723
|
[ARTIFACT_TYPES.RECEIPT]: ReceiptArtifactSchema,
|
|
@@ -4203,7 +4729,8 @@ var ARTIFACT_BODY_SCHEMAS = {
|
|
|
4203
4729
|
[ARTIFACT_TYPES.LEDGER_JOURNAL_ENTRY]: LedgerJournalEntryArtifactSchema,
|
|
4204
4730
|
[ARTIFACT_TYPES.STATEMENT]: StatementArtifactSchema,
|
|
4205
4731
|
[ARTIFACT_TYPES.PASS]: PassArtifactSchema,
|
|
4206
|
-
[ARTIFACT_TYPES.IDENTITY]: IdentityArtifactSchema
|
|
4732
|
+
[ARTIFACT_TYPES.IDENTITY]: IdentityArtifactSchema,
|
|
4733
|
+
[ARTIFACT_TYPES.PAY_CARD]: PayCardArtifactSchema
|
|
4207
4734
|
};
|
|
4208
4735
|
var HARDENED_ARTIFACT_TYPES = /* @__PURE__ */ new Set([
|
|
4209
4736
|
ARTIFACT_TYPES.OFFLINE_PAYMENT_AUTHORIZATION,
|
|
@@ -4216,7 +4743,8 @@ var HARDENED_ARTIFACT_TYPES = /* @__PURE__ */ new Set([
|
|
|
4216
4743
|
ARTIFACT_TYPES.LEDGER_JOURNAL_ENTRY,
|
|
4217
4744
|
ARTIFACT_TYPES.STATEMENT,
|
|
4218
4745
|
ARTIFACT_TYPES.PASS,
|
|
4219
|
-
ARTIFACT_TYPES.IDENTITY
|
|
4746
|
+
ARTIFACT_TYPES.IDENTITY,
|
|
4747
|
+
ARTIFACT_TYPES.PAY_CARD
|
|
4220
4748
|
]);
|
|
4221
4749
|
function isKnownArtifactType(t) {
|
|
4222
4750
|
return Object.values(ARTIFACT_TYPES).includes(t);
|
|
@@ -4301,6 +4829,130 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4301
4829
|
type: ARTIFACT_TYPES.OFFLINE_PAYMENT_AUTHORIZATION
|
|
4302
4830
|
});
|
|
4303
4831
|
}
|
|
4832
|
+
|
|
4833
|
+
// src/artifacts/paycard.ts
|
|
4834
|
+
var PAY_CARD_DEFAULT_TTL_MS = 90 * 24 * 60 * 60 * 1e3;
|
|
4835
|
+
var PAY_CARD_REFRESH_THRESHOLD_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
4836
|
+
var PAY_CARD_URI_PREFIX = `${FLUR_ARTIFACT_URI_PREFIX}${ARTIFACT_TYPES.PAY_CARD}/`;
|
|
4837
|
+
function createPayCardArtifactUri(input) {
|
|
4838
|
+
if (input.data.userId !== input.issuer) {
|
|
4839
|
+
throw new FlurArtifactError(
|
|
4840
|
+
"pay_card.data.userId must equal envelope issuer",
|
|
4841
|
+
"INVALID_BODY"
|
|
4842
|
+
);
|
|
4843
|
+
}
|
|
4844
|
+
const iat = input.issuedAtSeconds ?? Math.floor(Date.now() / 1e3);
|
|
4845
|
+
const exp = input.expiresAtSeconds ?? iat + Math.floor(PAY_CARD_DEFAULT_TTL_MS / 1e3);
|
|
4846
|
+
return createArtifactUri({
|
|
4847
|
+
type: ARTIFACT_TYPES.PAY_CARD,
|
|
4848
|
+
issuer: input.issuer,
|
|
4849
|
+
keyId: input.keyId,
|
|
4850
|
+
privateKey: input.privateKey,
|
|
4851
|
+
nonce: input.nonce,
|
|
4852
|
+
issuedAtSeconds: iat,
|
|
4853
|
+
expiresAtSeconds: exp,
|
|
4854
|
+
data: input.data
|
|
4855
|
+
});
|
|
4856
|
+
}
|
|
4857
|
+
function isPayCardArtifactUri(uri) {
|
|
4858
|
+
return typeof uri === "string" && uri.startsWith(PAY_CARD_URI_PREFIX);
|
|
4859
|
+
}
|
|
4860
|
+
function decodePayCardArtifact(uri) {
|
|
4861
|
+
if (!isPayCardArtifactUri(uri)) {
|
|
4862
|
+
throw new FlurArtifactError(
|
|
4863
|
+
`URI does not start with ${PAY_CARD_URI_PREFIX}`,
|
|
4864
|
+
"INVALID_URI"
|
|
4865
|
+
);
|
|
4866
|
+
}
|
|
4867
|
+
const decoded = decodeArtifactUri(uri);
|
|
4868
|
+
if (decoded.type !== ARTIFACT_TYPES.PAY_CARD) {
|
|
4869
|
+
throw new FlurArtifactError(
|
|
4870
|
+
`Expected pay_card, got ${decoded.type}`,
|
|
4871
|
+
"TYPE_MISMATCH"
|
|
4872
|
+
);
|
|
4873
|
+
}
|
|
4874
|
+
const parsed = PayCardArtifactSchema.safeParse(decoded.body.data);
|
|
4875
|
+
if (!parsed.success) {
|
|
4876
|
+
throw new FlurArtifactError(
|
|
4877
|
+
`pay_card body invalid: ${parsed.error.message}`,
|
|
4878
|
+
"INVALID_BODY"
|
|
4879
|
+
);
|
|
4880
|
+
}
|
|
4881
|
+
if (parsed.data.userId !== decoded.body.iss) {
|
|
4882
|
+
throw new FlurArtifactError(
|
|
4883
|
+
"pay_card.data.userId must equal envelope issuer",
|
|
4884
|
+
"INVALID_BODY"
|
|
4885
|
+
);
|
|
4886
|
+
}
|
|
4887
|
+
return {
|
|
4888
|
+
body: {
|
|
4889
|
+
...decoded.body,
|
|
4890
|
+
data: parsed.data
|
|
4891
|
+
},
|
|
4892
|
+
sig: decoded.sig,
|
|
4893
|
+
decoded
|
|
4894
|
+
};
|
|
4895
|
+
}
|
|
4896
|
+
function verifyPayCardArtifact(uri, publicKeySpkiB64, options = {}) {
|
|
4897
|
+
if (!isPayCardArtifactUri(uri)) {
|
|
4898
|
+
throw new FlurArtifactError(
|
|
4899
|
+
`URI does not start with ${PAY_CARD_URI_PREFIX}`,
|
|
4900
|
+
"INVALID_URI"
|
|
4901
|
+
);
|
|
4902
|
+
}
|
|
4903
|
+
const verified = verifyArtifactUri(
|
|
4904
|
+
uri,
|
|
4905
|
+
publicKeySpkiB64,
|
|
4906
|
+
options
|
|
4907
|
+
);
|
|
4908
|
+
if (verified.decoded.type !== ARTIFACT_TYPES.PAY_CARD) {
|
|
4909
|
+
throw new FlurArtifactError(
|
|
4910
|
+
`Expected pay_card, got ${verified.decoded.type}`,
|
|
4911
|
+
"TYPE_MISMATCH"
|
|
4912
|
+
);
|
|
4913
|
+
}
|
|
4914
|
+
if (verified.body.data.userId !== verified.body.iss) {
|
|
4915
|
+
throw new FlurArtifactError(
|
|
4916
|
+
"pay_card.data.userId must equal envelope issuer",
|
|
4917
|
+
"INVALID_BODY"
|
|
4918
|
+
);
|
|
4919
|
+
}
|
|
4920
|
+
return {
|
|
4921
|
+
body: verified.body,
|
|
4922
|
+
sig: verified.sig,
|
|
4923
|
+
decoded: verified.decoded
|
|
4924
|
+
};
|
|
4925
|
+
}
|
|
4926
|
+
function inspectPayCardFreshness(decoded, nowMs = Date.now()) {
|
|
4927
|
+
const exp = decoded.body.exp;
|
|
4928
|
+
if (exp === void 0) return "no_expiry";
|
|
4929
|
+
const remainingMs = exp * 1e3 - nowMs;
|
|
4930
|
+
if (remainingMs <= 0) return "expired";
|
|
4931
|
+
if (remainingMs <= PAY_CARD_REFRESH_THRESHOLD_MS)
|
|
4932
|
+
return "refresh_recommended";
|
|
4933
|
+
return "fresh";
|
|
4934
|
+
}
|
|
4935
|
+
function buildPayCardSigningInput(input) {
|
|
4936
|
+
if (input.data.userId !== input.issuer) {
|
|
4937
|
+
throw new FlurArtifactError(
|
|
4938
|
+
"pay_card.data.userId must equal envelope issuer",
|
|
4939
|
+
"INVALID_BODY"
|
|
4940
|
+
);
|
|
4941
|
+
}
|
|
4942
|
+
const parsedData = PayCardArtifactSchema.parse(input.data);
|
|
4943
|
+
const iat = input.issuedAtSeconds ?? Math.floor(Date.now() / 1e3);
|
|
4944
|
+
const exp = input.expiresAtSeconds ?? iat + Math.floor(PAY_CARD_DEFAULT_TTL_MS / 1e3);
|
|
4945
|
+
const body = buildArtifactBody({
|
|
4946
|
+
type: ARTIFACT_TYPES.PAY_CARD,
|
|
4947
|
+
issuer: input.issuer,
|
|
4948
|
+
keyId: input.keyId,
|
|
4949
|
+
data: parsedData,
|
|
4950
|
+
nonce: input.nonce,
|
|
4951
|
+
issuedAtSeconds: iat,
|
|
4952
|
+
expiresAtSeconds: exp
|
|
4953
|
+
});
|
|
4954
|
+
return { body, bodyBytes: canonicalJSONBytes(body) };
|
|
4955
|
+
}
|
|
4304
4956
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4305
4957
|
0 && (module.exports = {
|
|
4306
4958
|
ACCOUNT_FUNDED_OAC_MAX_TTL_MS,
|
|
@@ -4318,6 +4970,9 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4318
4970
|
COLLECTION_INTENT_STATUSES,
|
|
4319
4971
|
COLLECTION_PAYMENT_STATUSES,
|
|
4320
4972
|
CONSUMER_OFFLINE_CLAIM_SUBMIT_GRACE_MS,
|
|
4973
|
+
CONSUMER_PAYMENT_REQUEST_DOMAIN,
|
|
4974
|
+
CONSUMER_SETTLEMENT_DOMAIN,
|
|
4975
|
+
CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX,
|
|
4321
4976
|
CUSTODIAL_MODES,
|
|
4322
4977
|
CollectionIntentSchema,
|
|
4323
4978
|
CollectionPaymentResultSchema,
|
|
@@ -4327,6 +4982,7 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4327
4982
|
ConsumerOACRecordSchema,
|
|
4328
4983
|
ConsumerOACSchema,
|
|
4329
4984
|
ConsumerPaymentClaimSchema,
|
|
4985
|
+
ConsumerPaymentRequestEnvelopeSchema,
|
|
4330
4986
|
ConsumerSettleResultSchema,
|
|
4331
4987
|
ConsumerSettlementSchema,
|
|
4332
4988
|
CreateCollectionIntentInputSchema,
|
|
@@ -4368,6 +5024,12 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4368
5024
|
OAC_DEFAULT_PER_TX_KOBO,
|
|
4369
5025
|
OAC_DEFAULT_VALIDITY_MS,
|
|
4370
5026
|
OFFLINE_CLAIM_SMS_PREFIX,
|
|
5027
|
+
OFFLINE_SMS_SETTLE_DOMAIN,
|
|
5028
|
+
OFFLINE_SMS_SETTLE_HEADER_BYTES,
|
|
5029
|
+
OFFLINE_SMS_SETTLE_PREFIX,
|
|
5030
|
+
OFFLINE_SMS_SETTLE_SIGNATURE_BYTES,
|
|
5031
|
+
OFFLINE_SMS_SETTLE_TOKEN_BYTES,
|
|
5032
|
+
OFFLINE_SMS_SETTLE_VERSION,
|
|
4371
5033
|
OfflineClaimArtifactSchema,
|
|
4372
5034
|
OfflinePaymentAuthorizationArtifactSchema,
|
|
4373
5035
|
OfflinePaymentAuthorizationSchema,
|
|
@@ -4385,6 +5047,9 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4385
5047
|
PASS_STATES,
|
|
4386
5048
|
PAYLOAD_FORMAT_INDICATOR_VALUE,
|
|
4387
5049
|
PAYOUT_DESTINATION_STATUSES,
|
|
5050
|
+
PAY_CARD_DEFAULT_TTL_MS,
|
|
5051
|
+
PAY_CARD_REFRESH_THRESHOLD_MS,
|
|
5052
|
+
PAY_CARD_URI_PREFIX,
|
|
4388
5053
|
POINT_OF_INITIATION,
|
|
4389
5054
|
PartnerFundingEventInputSchema,
|
|
4390
5055
|
PartnerFundingSchema,
|
|
@@ -4392,6 +5057,7 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4392
5057
|
PassArtifactSchema,
|
|
4393
5058
|
PassMetadataSchema,
|
|
4394
5059
|
PassSchema,
|
|
5060
|
+
PayCardArtifactSchema,
|
|
4395
5061
|
PayCollectionInputSchema,
|
|
4396
5062
|
PaymentClaimSchema,
|
|
4397
5063
|
PaymentIntentArtifactSchema,
|
|
@@ -4427,18 +5093,26 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4427
5093
|
bodySha256Hex,
|
|
4428
5094
|
buildArtifactBody,
|
|
4429
5095
|
buildAuthorization,
|
|
5096
|
+
buildConsumerPaymentRequest,
|
|
4430
5097
|
buildOAC,
|
|
4431
5098
|
buildPass,
|
|
5099
|
+
buildPayCardSigningInput,
|
|
4432
5100
|
buildPaymentRequest,
|
|
4433
5101
|
buildReceipt,
|
|
4434
5102
|
buildRedemption,
|
|
5103
|
+
buildSmsSettleHeader,
|
|
5104
|
+
buildSmsSettleSignedBytes,
|
|
4435
5105
|
canonicalClaimSigningBytes,
|
|
4436
5106
|
canonicalClaimSigningPayload,
|
|
4437
5107
|
canonicalJSONBytes,
|
|
4438
5108
|
canonicalJSONStringify,
|
|
4439
5109
|
canonicalRequestString,
|
|
5110
|
+
computeConsumerClaimEncounterId,
|
|
4440
5111
|
computeEncounterId,
|
|
4441
5112
|
constantTimeEqual,
|
|
5113
|
+
consumerPaymentRequestSigningBytes,
|
|
5114
|
+
consumerPaymentRequestSigningPayload,
|
|
5115
|
+
consumerSettlementSigningPayload,
|
|
4442
5116
|
crc16ccitt,
|
|
4443
5117
|
crc16ccittHex,
|
|
4444
5118
|
createAccountsClient,
|
|
@@ -4456,28 +5130,40 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4456
5130
|
createPartnerFundingClient,
|
|
4457
5131
|
createPartnerProfileAdminClient,
|
|
4458
5132
|
createPassesClient,
|
|
5133
|
+
createPayCardArtifactUri,
|
|
4459
5134
|
createReceiptArtifactUri,
|
|
4460
5135
|
createReceiptsClient,
|
|
4461
5136
|
createSoftwareP256Signer,
|
|
4462
5137
|
decodeArtifactUri,
|
|
4463
5138
|
decodeAuthorizationQR,
|
|
4464
5139
|
decodeBase45,
|
|
5140
|
+
decodeConsumerSettlementReceiptQR,
|
|
4465
5141
|
decodeOfflineClaimSmsMessage,
|
|
5142
|
+
decodeOfflineSmsSettleToken,
|
|
5143
|
+
decodePayCardArtifact,
|
|
4466
5144
|
decodePaymentRequestQR,
|
|
5145
|
+
decodeUnverifiedConsumerSettlementReceiptQR,
|
|
5146
|
+
derToRawP256Signature,
|
|
4467
5147
|
encodeArtifactUri,
|
|
4468
5148
|
encodeAuthorizationQR,
|
|
4469
5149
|
encodeBase45,
|
|
5150
|
+
encodeConsumerSettlementReceiptQR,
|
|
4470
5151
|
encodeNQR,
|
|
4471
5152
|
encodeOfflineClaimSmsMessage,
|
|
5153
|
+
encodeOfflineSmsSettleToken,
|
|
4472
5154
|
encodePaymentRequestQR,
|
|
4473
5155
|
extractOfflineClaimSmsToken,
|
|
5156
|
+
extractOfflineSmsSettleToken,
|
|
4474
5157
|
formatAmount,
|
|
4475
5158
|
generateDynamicQR,
|
|
4476
5159
|
generateStaticQR,
|
|
4477
5160
|
init,
|
|
5161
|
+
inspectPayCardFreshness,
|
|
5162
|
+
isConsumerPaymentRequestExpired,
|
|
4478
5163
|
isHardenedArtifactType,
|
|
4479
5164
|
isKnownArtifactType,
|
|
4480
5165
|
isPassWithinValidity,
|
|
5166
|
+
isPayCardArtifactUri,
|
|
4481
5167
|
moneyMinorToNumber,
|
|
4482
5168
|
normalizeE164,
|
|
4483
5169
|
parseAmountInput,
|
|
@@ -4487,6 +5173,7 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4487
5173
|
routingHint,
|
|
4488
5174
|
signArtifact,
|
|
4489
5175
|
signAuthorization,
|
|
5176
|
+
signConsumerPaymentRequest,
|
|
4490
5177
|
signOAC,
|
|
4491
5178
|
signPartnerRequest,
|
|
4492
5179
|
signPass,
|
|
@@ -4498,8 +5185,13 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4498
5185
|
verifyArtifactUri,
|
|
4499
5186
|
verifyAuthorization,
|
|
4500
5187
|
verifyClaimSignature,
|
|
5188
|
+
verifyConsumerPaymentRequest,
|
|
5189
|
+
verifyConsumerSettlement,
|
|
5190
|
+
verifyConsumerSettlementReceiptQR,
|
|
4501
5191
|
verifyOAC,
|
|
5192
|
+
verifyOfflineSmsSettleToken,
|
|
4502
5193
|
verifyPass,
|
|
5194
|
+
verifyPayCardArtifact,
|
|
4503
5195
|
verifyPaymentRequest,
|
|
4504
5196
|
verifyReceipt,
|
|
4505
5197
|
verifyRedemption,
|