@nokinc-flur/sdk 2.3.0 → 2.5.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 +397 -430
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +355 -301
- package/dist/index.d.ts +355 -301
- package/dist/index.js +388 -420
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -48,6 +48,7 @@ __export(index_exports, {
|
|
|
48
48
|
CONSUMER_OAC_QR_PREFIX: () => CONSUMER_OAC_QR_PREFIX,
|
|
49
49
|
CONSUMER_OFFLINE_CLAIM_SUBMIT_GRACE_MS: () => CONSUMER_OFFLINE_CLAIM_SUBMIT_GRACE_MS,
|
|
50
50
|
CONSUMER_PAYMENT_REQUEST_DOMAIN: () => CONSUMER_PAYMENT_REQUEST_DOMAIN,
|
|
51
|
+
CONSUMER_REVOCATION_DOMAIN: () => CONSUMER_REVOCATION_DOMAIN,
|
|
51
52
|
CONSUMER_SETTLEMENT_DOMAIN: () => CONSUMER_SETTLEMENT_DOMAIN,
|
|
52
53
|
CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX: () => CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX,
|
|
53
54
|
CUSTODIAL_MODES: () => CUSTODIAL_MODES,
|
|
@@ -109,6 +110,7 @@ __export(index_exports, {
|
|
|
109
110
|
OFFLINE_SMS_SETTLE_SIGNATURE_BYTES: () => OFFLINE_SMS_SETTLE_SIGNATURE_BYTES,
|
|
110
111
|
OFFLINE_SMS_SETTLE_TOKEN_BYTES: () => OFFLINE_SMS_SETTLE_TOKEN_BYTES,
|
|
111
112
|
OFFLINE_SMS_SETTLE_VERSION: () => OFFLINE_SMS_SETTLE_VERSION,
|
|
113
|
+
OacPresentmentRequestSchema: () => OacPresentmentRequestSchema,
|
|
112
114
|
OfflineClaimArtifactSchema: () => OfflineClaimArtifactSchema,
|
|
113
115
|
OfflinePaymentAuthorizationArtifactSchema: () => OfflinePaymentAuthorizationArtifactSchema,
|
|
114
116
|
OfflinePaymentAuthorizationSchema: () => OfflinePaymentAuthorizationSchema,
|
|
@@ -126,9 +128,6 @@ __export(index_exports, {
|
|
|
126
128
|
PASS_STATES: () => PASS_STATES,
|
|
127
129
|
PAYLOAD_FORMAT_INDICATOR_VALUE: () => PAYLOAD_FORMAT_INDICATOR_VALUE,
|
|
128
130
|
PAYOUT_DESTINATION_STATUSES: () => PAYOUT_DESTINATION_STATUSES,
|
|
129
|
-
PAY_CARD_DEFAULT_TTL_MS: () => PAY_CARD_DEFAULT_TTL_MS,
|
|
130
|
-
PAY_CARD_REFRESH_THRESHOLD_MS: () => PAY_CARD_REFRESH_THRESHOLD_MS,
|
|
131
|
-
PAY_CARD_URI_PREFIX: () => PAY_CARD_URI_PREFIX,
|
|
132
131
|
POINT_OF_INITIATION: () => POINT_OF_INITIATION,
|
|
133
132
|
PartnerFundingEventInputSchema: () => PartnerFundingEventInputSchema,
|
|
134
133
|
PartnerFundingSchema: () => PartnerFundingSchema,
|
|
@@ -136,7 +135,6 @@ __export(index_exports, {
|
|
|
136
135
|
PassArtifactSchema: () => PassArtifactSchema,
|
|
137
136
|
PassMetadataSchema: () => PassMetadataSchema,
|
|
138
137
|
PassSchema: () => PassSchema,
|
|
139
|
-
PayCardArtifactSchema: () => PayCardArtifactSchema,
|
|
140
138
|
PayCollectionInputSchema: () => PayCollectionInputSchema,
|
|
141
139
|
PaymentClaimSchema: () => PaymentClaimSchema,
|
|
142
140
|
PaymentIntentArtifactSchema: () => PaymentIntentArtifactSchema,
|
|
@@ -148,6 +146,7 @@ __export(index_exports, {
|
|
|
148
146
|
RECEIPT_CHANNELS: () => RECEIPT_CHANNELS,
|
|
149
147
|
RECEIPT_KINDS: () => RECEIPT_KINDS,
|
|
150
148
|
REPLAY_WINDOW_MS: () => REPLAY_WINDOW_MS,
|
|
149
|
+
REVOCATION_LIST_MAX_ENTRIES: () => REVOCATION_LIST_MAX_ENTRIES,
|
|
151
150
|
ReceiptArtifactSchema: () => ReceiptArtifactSchema,
|
|
152
151
|
ReceiptPayloadSchema: () => ReceiptPayloadSchema,
|
|
153
152
|
ReceiptSchema: () => ReceiptSchema,
|
|
@@ -156,12 +155,14 @@ __export(index_exports, {
|
|
|
156
155
|
RedemptionSchema: () => RedemptionSchema,
|
|
157
156
|
RegisterDeviceKeyP256InputSchema: () => RegisterDeviceKeyP256InputSchema,
|
|
158
157
|
ReversalRecordArtifactSchema: () => ReversalRecordArtifactSchema,
|
|
158
|
+
RevocationListSchema: () => RevocationListSchema,
|
|
159
159
|
RevokeDeviceKeyInputSchema: () => RevokeDeviceKeyInputSchema,
|
|
160
160
|
SETTLEMENT_SCHEDULES: () => SETTLEMENT_SCHEDULES,
|
|
161
161
|
SettleResponseSchema: () => SettleResponseSchema,
|
|
162
162
|
SettlementRecordArtifactSchema: () => SettlementRecordArtifactSchema,
|
|
163
163
|
SettlementSchema: () => SettlementSchema,
|
|
164
164
|
SignedConsumerOACSchema: () => SignedConsumerOACSchema,
|
|
165
|
+
SignedRevocationListSchema: () => SignedRevocationListSchema,
|
|
165
166
|
StatementArtifactSchema: () => StatementArtifactSchema,
|
|
166
167
|
UpsertMerchantProfileInputSchema: () => UpsertMerchantProfileInputSchema,
|
|
167
168
|
UpsertPartnerProfileInputSchema: () => UpsertPartnerProfileInputSchema,
|
|
@@ -175,7 +176,6 @@ __export(index_exports, {
|
|
|
175
176
|
buildConsumerPaymentRequest: () => buildConsumerPaymentRequest,
|
|
176
177
|
buildOAC: () => buildOAC,
|
|
177
178
|
buildPass: () => buildPass,
|
|
178
|
-
buildPayCardSigningInput: () => buildPayCardSigningInput,
|
|
179
179
|
buildPaymentRequest: () => buildPaymentRequest,
|
|
180
180
|
buildReceipt: () => buildReceipt,
|
|
181
181
|
buildRedemption: () => buildRedemption,
|
|
@@ -210,17 +210,16 @@ __export(index_exports, {
|
|
|
210
210
|
createPartnerFundingClient: () => createPartnerFundingClient,
|
|
211
211
|
createPartnerProfileAdminClient: () => createPartnerProfileAdminClient,
|
|
212
212
|
createPassesClient: () => createPassesClient,
|
|
213
|
-
createPayCardArtifactUri: () => createPayCardArtifactUri,
|
|
214
213
|
createReceiptArtifactUri: () => createReceiptArtifactUri,
|
|
215
214
|
createReceiptsClient: () => createReceiptsClient,
|
|
216
215
|
createSoftwareP256Signer: () => createSoftwareP256Signer,
|
|
217
216
|
decodeArtifactUri: () => decodeArtifactUri,
|
|
218
217
|
decodeAuthorizationQR: () => decodeAuthorizationQR,
|
|
219
218
|
decodeBase45: () => decodeBase45,
|
|
219
|
+
decodeConsumerOacRequest: () => decodeConsumerOacRequest,
|
|
220
220
|
decodeConsumerSettlementReceiptQR: () => decodeConsumerSettlementReceiptQR,
|
|
221
221
|
decodeOfflineClaimSmsMessage: () => decodeOfflineClaimSmsMessage,
|
|
222
222
|
decodeOfflineSmsSettleToken: () => decodeOfflineSmsSettleToken,
|
|
223
|
-
decodePayCardArtifact: () => decodePayCardArtifact,
|
|
224
223
|
decodePaymentRequestQR: () => decodePaymentRequestQR,
|
|
225
224
|
decodeUnverifiedConsumerOacQR: () => decodeUnverifiedConsumerOacQR,
|
|
226
225
|
decodeUnverifiedConsumerSettlementReceiptQR: () => decodeUnverifiedConsumerSettlementReceiptQR,
|
|
@@ -240,19 +239,19 @@ __export(index_exports, {
|
|
|
240
239
|
generateDynamicQR: () => generateDynamicQR,
|
|
241
240
|
generateStaticQR: () => generateStaticQR,
|
|
242
241
|
init: () => init,
|
|
243
|
-
inspectPayCardFreshness: () => inspectPayCardFreshness,
|
|
244
242
|
isConsumerOacQR: () => isConsumerOacQR,
|
|
245
243
|
isConsumerPaymentRequestExpired: () => isConsumerPaymentRequestExpired,
|
|
246
244
|
isHardenedArtifactType: () => isHardenedArtifactType,
|
|
247
245
|
isKnownArtifactType: () => isKnownArtifactType,
|
|
246
|
+
isOacRevoked: () => isOacRevoked,
|
|
248
247
|
isPassWithinValidity: () => isPassWithinValidity,
|
|
249
|
-
isPayCardArtifactUri: () => isPayCardArtifactUri,
|
|
250
248
|
moneyMinorToNumber: () => moneyMinorToNumber,
|
|
251
249
|
normalizeE164: () => normalizeE164,
|
|
252
250
|
parseAmountInput: () => parseAmountInput,
|
|
253
251
|
parseNQR: () => parseNQR,
|
|
254
252
|
parseQR: () => parseQR,
|
|
255
253
|
readTLV: () => readTLV,
|
|
254
|
+
revocationListSigningPayload: () => revocationListSigningPayload,
|
|
256
255
|
routingHint: () => routingHint,
|
|
257
256
|
signArtifact: () => signArtifact,
|
|
258
257
|
signAuthorization: () => signAuthorization,
|
|
@@ -275,11 +274,11 @@ __export(index_exports, {
|
|
|
275
274
|
verifyOacOffline: () => verifyOacOffline,
|
|
276
275
|
verifyOfflineSmsSettleToken: () => verifyOfflineSmsSettleToken,
|
|
277
276
|
verifyPass: () => verifyPass,
|
|
278
|
-
verifyPayCardArtifact: () => verifyPayCardArtifact,
|
|
279
277
|
verifyPaymentRequest: () => verifyPaymentRequest,
|
|
280
278
|
verifyReceipt: () => verifyReceipt,
|
|
281
279
|
verifyRedemption: () => verifyRedemption,
|
|
282
280
|
verifyRequestHMAC: () => verifyRequestHMAC,
|
|
281
|
+
verifyRevocationList: () => verifyRevocationList,
|
|
283
282
|
writeTLV: () => writeTLV
|
|
284
283
|
});
|
|
285
284
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -3241,76 +3240,142 @@ function createAccountsClient(opts) {
|
|
|
3241
3240
|
}
|
|
3242
3241
|
|
|
3243
3242
|
// src/me-offline/client.ts
|
|
3243
|
+
var import_zod14 = require("zod");
|
|
3244
|
+
|
|
3245
|
+
// src/me-offline/revocation.ts
|
|
3244
3246
|
var import_zod13 = require("zod");
|
|
3245
|
-
var Sha256Hex = import_zod13.z.string().regex(/^[0-9a-f]{64}$/);
|
|
3246
3247
|
var Base64Std3 = import_zod13.z.string().regex(/^[A-Za-z0-9+/]+={0,2}$/);
|
|
3247
|
-
var
|
|
3248
|
+
var CONSUMER_REVOCATION_DOMAIN = "flur:consumer-offline:v1:revocation";
|
|
3249
|
+
var REVOCATION_LIST_MAX_ENTRIES = 1e5;
|
|
3250
|
+
var RevocationListSchema = import_zod13.z.object({
|
|
3251
|
+
issuerId: import_zod13.z.string().min(1).max(64),
|
|
3252
|
+
/**
|
|
3253
|
+
* Monotonic snapshot counter. A device MUST NOT replace a pinned list with
|
|
3254
|
+
* one carrying a lower sequence — this defeats a downgrade/rollback attack
|
|
3255
|
+
* that replays an older list to resurrect a revoked credential.
|
|
3256
|
+
*/
|
|
3257
|
+
sequence: import_zod13.z.number().int().nonnegative(),
|
|
3258
|
+
issuedAtMs: import_zod13.z.number().int().nonnegative(),
|
|
3259
|
+
/**
|
|
3260
|
+
* Freshness bound. After this instant the list is considered stale and the
|
|
3261
|
+
* verifier treats it as untrustworthy (fail-closed), forcing a re-pin.
|
|
3262
|
+
* Optional so the issuer may publish a list without a hard expiry.
|
|
3263
|
+
*/
|
|
3264
|
+
notAfterMs: import_zod13.z.number().int().positive().optional(),
|
|
3265
|
+
/** OAC ids that are revoked AND not yet past their own validity window. */
|
|
3266
|
+
revokedOacIds: import_zod13.z.array(import_zod13.z.string().uuid()).max(REVOCATION_LIST_MAX_ENTRIES)
|
|
3267
|
+
});
|
|
3268
|
+
var SignedRevocationListSchema = import_zod13.z.object({
|
|
3269
|
+
list: RevocationListSchema,
|
|
3270
|
+
/** ASN.1 DER ECDSA P-256 issuer signature over the signing payload, base64. */
|
|
3271
|
+
issuerSig: Base64Std3.min(16).max(2048),
|
|
3272
|
+
/** Issuer's P-256 public key as SubjectPublicKeyInfo DER, base64. */
|
|
3273
|
+
issuerPublicKeySpkiB64: Base64Std3.min(64).max(4096)
|
|
3274
|
+
});
|
|
3275
|
+
function revocationListSigningPayload(list) {
|
|
3276
|
+
const payload = {
|
|
3277
|
+
domain: CONSUMER_REVOCATION_DOMAIN,
|
|
3278
|
+
issuerId: list.issuerId,
|
|
3279
|
+
sequence: list.sequence,
|
|
3280
|
+
issuedAtMs: list.issuedAtMs,
|
|
3281
|
+
revokedOacIds: list.revokedOacIds
|
|
3282
|
+
};
|
|
3283
|
+
if (list.notAfterMs !== void 0) payload.notAfterMs = list.notAfterMs;
|
|
3284
|
+
return payload;
|
|
3285
|
+
}
|
|
3286
|
+
function verifyRevocationList(signed, trustedKeys, options = {}) {
|
|
3287
|
+
const parsed = SignedRevocationListSchema.safeParse(signed);
|
|
3288
|
+
if (!parsed.success) return { ok: false, reason: "malformed" };
|
|
3289
|
+
const list = parsed.data.list;
|
|
3290
|
+
const nowMs = options.nowMs ?? Date.now();
|
|
3291
|
+
const pinned = trustedKeys.filter(
|
|
3292
|
+
(k) => k.issuerId === list.issuerId && (k.notBeforeMs === void 0 || nowMs >= k.notBeforeMs) && (k.notAfterMs === void 0 || nowMs <= k.notAfterMs)
|
|
3293
|
+
);
|
|
3294
|
+
if (pinned.length === 0) return { ok: false, reason: "untrusted_issuer" };
|
|
3295
|
+
const signingBytes = canonicalJSONBytes(revocationListSigningPayload(list));
|
|
3296
|
+
const signatureOk = pinned.some(
|
|
3297
|
+
(k) => verifyIssuerP256(signingBytes, parsed.data.issuerSig, k.publicKeySpkiB64)
|
|
3298
|
+
);
|
|
3299
|
+
if (!signatureOk) return { ok: false, reason: "signature_invalid" };
|
|
3300
|
+
if (list.notAfterMs !== void 0 && nowMs > list.notAfterMs) {
|
|
3301
|
+
return { ok: false, reason: "stale" };
|
|
3302
|
+
}
|
|
3303
|
+
return { ok: true, list, revokedOacIds: new Set(list.revokedOacIds) };
|
|
3304
|
+
}
|
|
3305
|
+
function isOacRevoked(oacId, revokedOacIds) {
|
|
3306
|
+
return revokedOacIds.has(oacId);
|
|
3307
|
+
}
|
|
3308
|
+
|
|
3309
|
+
// src/me-offline/client.ts
|
|
3310
|
+
var Sha256Hex = import_zod14.z.string().regex(/^[0-9a-f]{64}$/);
|
|
3311
|
+
var Base64Std4 = import_zod14.z.string().regex(/^[A-Za-z0-9+/]+={0,2}$/);
|
|
3312
|
+
var ClaimNonce = import_zod14.z.string().min(8).max(128).refine((value) => !value.includes("|"), {
|
|
3248
3313
|
message: "nonce must not contain |"
|
|
3249
3314
|
});
|
|
3250
3315
|
var ACCOUNT_FUNDED_OAC_MAX_TTL_MS = 1e3 * 60 * 60 * 24;
|
|
3251
|
-
var IssuerTrustKeySchema =
|
|
3252
|
-
issuerId:
|
|
3253
|
-
alg:
|
|
3254
|
-
publicKeySpkiB64:
|
|
3255
|
-
notBeforeMs:
|
|
3256
|
-
notAfterMs:
|
|
3316
|
+
var IssuerTrustKeySchema = import_zod14.z.object({
|
|
3317
|
+
issuerId: import_zod14.z.string().min(1).max(128),
|
|
3318
|
+
alg: import_zod14.z.literal("p256"),
|
|
3319
|
+
publicKeySpkiB64: Base64Std4.min(64).max(4096),
|
|
3320
|
+
notBeforeMs: import_zod14.z.number().int().nonnegative().optional(),
|
|
3321
|
+
notAfterMs: import_zod14.z.number().int().positive().optional()
|
|
3257
3322
|
});
|
|
3258
|
-
var IssuerTrustBundleSchema =
|
|
3259
|
-
keys:
|
|
3323
|
+
var IssuerTrustBundleSchema = import_zod14.z.object({
|
|
3324
|
+
keys: import_zod14.z.array(IssuerTrustKeySchema).min(1)
|
|
3260
3325
|
});
|
|
3261
3326
|
var CONSUMER_OFFLINE_CLAIM_SUBMIT_GRACE_MS = 1e3 * 60 * 60 * 24;
|
|
3262
|
-
var AttestationSecurityLevelSchema =
|
|
3327
|
+
var AttestationSecurityLevelSchema = import_zod14.z.enum([
|
|
3263
3328
|
"STRONGBOX",
|
|
3264
3329
|
"TEE",
|
|
3265
3330
|
"SECURE_ENCLAVE",
|
|
3266
3331
|
"SOFTWARE"
|
|
3267
3332
|
]);
|
|
3268
|
-
var DeviceKeyAlgSchema =
|
|
3269
|
-
var RegisterDeviceKeyP256InputSchema =
|
|
3270
|
-
deviceId:
|
|
3333
|
+
var DeviceKeyAlgSchema = import_zod14.z.literal("p256");
|
|
3334
|
+
var RegisterDeviceKeyP256InputSchema = import_zod14.z.object({
|
|
3335
|
+
deviceId: import_zod14.z.string().min(1).max(128),
|
|
3271
3336
|
/** P-256 SubjectPublicKeyInfo DER, base64. */
|
|
3272
|
-
publicKeySpkiB64:
|
|
3337
|
+
publicKeySpkiB64: Base64Std4.min(64).max(4096),
|
|
3273
3338
|
/** Base64 of the server-issued enrollment challenge string. */
|
|
3274
|
-
challengeB64:
|
|
3339
|
+
challengeB64: Base64Std4.min(8).max(1024),
|
|
3275
3340
|
/** iOS App Attest payload or Android X.509 Key Attestation chain. */
|
|
3276
|
-
attestationChainB64:
|
|
3341
|
+
attestationChainB64: import_zod14.z.array(Base64Std4.min(16).max(16384)).min(1).max(16),
|
|
3277
3342
|
securityLevel: AttestationSecurityLevelSchema
|
|
3278
3343
|
});
|
|
3279
|
-
var P256EnrollmentChallengeInputSchema =
|
|
3280
|
-
deviceId:
|
|
3344
|
+
var P256EnrollmentChallengeInputSchema = import_zod14.z.object({
|
|
3345
|
+
deviceId: import_zod14.z.string().min(1).max(128)
|
|
3281
3346
|
});
|
|
3282
|
-
var P256EnrollmentChallengeResultSchema =
|
|
3283
|
-
challenge:
|
|
3284
|
-
expiresAtMs:
|
|
3347
|
+
var P256EnrollmentChallengeResultSchema = import_zod14.z.object({
|
|
3348
|
+
challenge: import_zod14.z.string().min(16),
|
|
3349
|
+
expiresAtMs: import_zod14.z.number().int().positive()
|
|
3285
3350
|
});
|
|
3286
|
-
var DeviceKeyRecordSchema =
|
|
3287
|
-
id:
|
|
3288
|
-
userId:
|
|
3289
|
-
deviceId:
|
|
3351
|
+
var DeviceKeyRecordSchema = import_zod14.z.object({
|
|
3352
|
+
id: import_zod14.z.string().uuid(),
|
|
3353
|
+
userId: import_zod14.z.string().uuid(),
|
|
3354
|
+
deviceId: import_zod14.z.string(),
|
|
3290
3355
|
/** Always 'p256' on the consumer offline rail. Field retained for forward-compat. */
|
|
3291
3356
|
alg: DeviceKeyAlgSchema.default("p256"),
|
|
3292
3357
|
/** P-256 SubjectPublicKeyInfo DER, base64. */
|
|
3293
|
-
publicKeySpkiB64:
|
|
3358
|
+
publicKeySpkiB64: Base64Std4.nullable().default(null),
|
|
3294
3359
|
securityLevel: AttestationSecurityLevelSchema.nullable().default(null),
|
|
3295
|
-
hardwareBacked:
|
|
3296
|
-
attestedAtMs:
|
|
3297
|
-
createdAtMs:
|
|
3298
|
-
revokedAtMs:
|
|
3360
|
+
hardwareBacked: import_zod14.z.boolean().default(false),
|
|
3361
|
+
attestedAtMs: import_zod14.z.number().int().nonnegative().nullable().default(null),
|
|
3362
|
+
createdAtMs: import_zod14.z.number().int().nonnegative(),
|
|
3363
|
+
revokedAtMs: import_zod14.z.number().int().nonnegative().nullable()
|
|
3299
3364
|
});
|
|
3300
|
-
var ConsumerOACSchema =
|
|
3301
|
-
oacId:
|
|
3302
|
-
issuerId:
|
|
3303
|
-
userId:
|
|
3304
|
-
deviceId:
|
|
3365
|
+
var ConsumerOACSchema = import_zod14.z.object({
|
|
3366
|
+
oacId: import_zod14.z.string().uuid(),
|
|
3367
|
+
issuerId: import_zod14.z.string().min(1).max(64),
|
|
3368
|
+
userId: import_zod14.z.string().uuid(),
|
|
3369
|
+
deviceId: import_zod14.z.string().min(1).max(128),
|
|
3305
3370
|
/**
|
|
3306
3371
|
* Always 'p256'. Required on the wire (backend always emits it).
|
|
3307
3372
|
* Kept as a literal so input/output infer identically and the schema
|
|
3308
3373
|
* can be nested inside other response shapes without Zod input/output
|
|
3309
3374
|
* divergence under tsup DTS bundling.
|
|
3310
3375
|
*/
|
|
3311
|
-
alg:
|
|
3376
|
+
alg: import_zod14.z.literal("p256"),
|
|
3312
3377
|
/** P-256 SubjectPublicKeyInfo DER, base64. */
|
|
3313
|
-
devicePubkeySpkiB64:
|
|
3378
|
+
devicePubkeySpkiB64: Base64Std4.min(64).max(4096),
|
|
3314
3379
|
/**
|
|
3315
3380
|
* Per-transaction / cumulative offline spend ceilings. Zero is valid and
|
|
3316
3381
|
* denotes an identity-only OAC: the credential proves who the holder is and
|
|
@@ -3318,104 +3383,104 @@ var ConsumerOACSchema = import_zod13.z.object({
|
|
|
3318
3383
|
* no offline spend authority (every claim against it routes to REVIEW).
|
|
3319
3384
|
* Issued to zero-balance wallets so they can still be paid offline.
|
|
3320
3385
|
*/
|
|
3321
|
-
perTxCapKobo:
|
|
3322
|
-
cumulativeCapKobo:
|
|
3323
|
-
currency:
|
|
3324
|
-
validFromMs:
|
|
3325
|
-
validUntilMs:
|
|
3326
|
-
counterSeed:
|
|
3327
|
-
issuedAtMs:
|
|
3386
|
+
perTxCapKobo: import_zod14.z.number().int().nonnegative(),
|
|
3387
|
+
cumulativeCapKobo: import_zod14.z.number().int().nonnegative(),
|
|
3388
|
+
currency: import_zod14.z.string().length(3),
|
|
3389
|
+
validFromMs: import_zod14.z.number().int().nonnegative(),
|
|
3390
|
+
validUntilMs: import_zod14.z.number().int().nonnegative(),
|
|
3391
|
+
counterSeed: import_zod14.z.number().int().nonnegative(),
|
|
3392
|
+
issuedAtMs: import_zod14.z.number().int().nonnegative(),
|
|
3328
3393
|
/**
|
|
3329
3394
|
* Issuer-attested identity folded into the OAC so a single signed
|
|
3330
3395
|
* credential serves both Tier B offline-verifiable identity and offline
|
|
3331
3396
|
* spend authority. Verified offline against a pinned issuer key; the
|
|
3332
3397
|
* backend remains authoritative at settlement.
|
|
3333
3398
|
*/
|
|
3334
|
-
phoneE164:
|
|
3335
|
-
displayName:
|
|
3399
|
+
phoneE164: import_zod14.z.string().regex(/^\+[1-9]\d{7,14}$/),
|
|
3400
|
+
displayName: import_zod14.z.string().min(1).max(64)
|
|
3336
3401
|
});
|
|
3337
|
-
var SignedConsumerOACSchema =
|
|
3402
|
+
var SignedConsumerOACSchema = import_zod14.z.object({
|
|
3338
3403
|
oac: ConsumerOACSchema,
|
|
3339
3404
|
/** ASN.1 DER ECDSA P-256 issuer signature, base64. */
|
|
3340
|
-
issuerSig:
|
|
3405
|
+
issuerSig: Base64Std4.min(16).max(2048),
|
|
3341
3406
|
/** Issuer's P-256 public key as SubjectPublicKeyInfo DER, base64. */
|
|
3342
|
-
issuerPublicKeySpkiB64:
|
|
3407
|
+
issuerPublicKeySpkiB64: Base64Std4.min(64).max(4096)
|
|
3343
3408
|
});
|
|
3344
3409
|
var OACRecordSchema = SignedConsumerOACSchema.extend({
|
|
3345
|
-
currentOfflineSpentKobo:
|
|
3346
|
-
status:
|
|
3347
|
-
supersededAtMs:
|
|
3348
|
-
revokedAtMs:
|
|
3410
|
+
currentOfflineSpentKobo: import_zod14.z.number().int().nonnegative(),
|
|
3411
|
+
status: import_zod14.z.enum(["active", "superseded", "expired", "revoked"]),
|
|
3412
|
+
supersededAtMs: import_zod14.z.number().int().nonnegative().nullable(),
|
|
3413
|
+
revokedAtMs: import_zod14.z.number().int().nonnegative().nullable()
|
|
3349
3414
|
});
|
|
3350
|
-
var IssueAccountOacInputSchema =
|
|
3351
|
-
deviceId:
|
|
3352
|
-
perTxCapKobo:
|
|
3353
|
-
cumulativeCapKobo:
|
|
3354
|
-
ttlMs:
|
|
3415
|
+
var IssueAccountOacInputSchema = import_zod14.z.object({
|
|
3416
|
+
deviceId: import_zod14.z.string().min(1).max(128),
|
|
3417
|
+
perTxCapKobo: import_zod14.z.number().int().positive().optional(),
|
|
3418
|
+
cumulativeCapKobo: import_zod14.z.number().int().positive().optional(),
|
|
3419
|
+
ttlMs: import_zod14.z.number().int().min(6e4).max(ACCOUNT_FUNDED_OAC_MAX_TTL_MS).optional()
|
|
3355
3420
|
});
|
|
3356
|
-
var OfflineStatusResultSchema =
|
|
3421
|
+
var OfflineStatusResultSchema = import_zod14.z.object({
|
|
3357
3422
|
active: OACRecordSchema.nullable()
|
|
3358
3423
|
});
|
|
3359
|
-
var ConsumerPaymentClaimSchema =
|
|
3424
|
+
var ConsumerPaymentClaimSchema = import_zod14.z.object({
|
|
3360
3425
|
/** Always 'p256'. Retained for forward-compat and as an explicit domain marker. */
|
|
3361
|
-
alg:
|
|
3362
|
-
oacId:
|
|
3426
|
+
alg: import_zod14.z.literal("p256").default("p256"),
|
|
3427
|
+
oacId: import_zod14.z.string().uuid(),
|
|
3363
3428
|
encounterId: Sha256Hex.optional(),
|
|
3364
|
-
payerUserId:
|
|
3365
|
-
payeeUserId:
|
|
3366
|
-
payerDeviceId:
|
|
3429
|
+
payerUserId: import_zod14.z.string().uuid(),
|
|
3430
|
+
payeeUserId: import_zod14.z.string().uuid(),
|
|
3431
|
+
payerDeviceId: import_zod14.z.string().min(1).max(128),
|
|
3367
3432
|
payerNonce: ClaimNonce,
|
|
3368
3433
|
payeeNonce: ClaimNonce,
|
|
3369
|
-
amountKobo:
|
|
3370
|
-
currency:
|
|
3371
|
-
occurredAtMs:
|
|
3372
|
-
completedAtMs:
|
|
3373
|
-
contextId:
|
|
3374
|
-
requestId:
|
|
3375
|
-
requestMode:
|
|
3376
|
-
requestTakerUserId:
|
|
3377
|
-
requestAmountKobo:
|
|
3378
|
-
requestCurrency:
|
|
3379
|
-
requestReference:
|
|
3380
|
-
requestCreatedAtMs:
|
|
3381
|
-
requestExpiresAtMs:
|
|
3382
|
-
requestNonce:
|
|
3383
|
-
requestTakerDeviceId:
|
|
3384
|
-
requestTakerPubkeySpkiB64:
|
|
3385
|
-
requestTakerSignatureDerB64:
|
|
3386
|
-
payerPubkeySpkiB64:
|
|
3387
|
-
payerSignatureDerB64:
|
|
3388
|
-
payeePubkeySpkiB64:
|
|
3389
|
-
payeeSignatureDerB64:
|
|
3434
|
+
amountKobo: import_zod14.z.number().int().positive(),
|
|
3435
|
+
currency: import_zod14.z.string().length(3).default("NGN"),
|
|
3436
|
+
occurredAtMs: import_zod14.z.number().int().nonnegative(),
|
|
3437
|
+
completedAtMs: import_zod14.z.number().int().nonnegative().optional(),
|
|
3438
|
+
contextId: import_zod14.z.string().max(128).optional(),
|
|
3439
|
+
requestId: import_zod14.z.string().uuid().optional(),
|
|
3440
|
+
requestMode: import_zod14.z.enum(["fixed", "editable"]).optional(),
|
|
3441
|
+
requestTakerUserId: import_zod14.z.string().uuid().optional(),
|
|
3442
|
+
requestAmountKobo: import_zod14.z.number().int().positive().optional(),
|
|
3443
|
+
requestCurrency: import_zod14.z.string().length(3).optional(),
|
|
3444
|
+
requestReference: import_zod14.z.string().max(128).nullable().optional(),
|
|
3445
|
+
requestCreatedAtMs: import_zod14.z.number().int().nonnegative().optional(),
|
|
3446
|
+
requestExpiresAtMs: import_zod14.z.number().int().positive().optional(),
|
|
3447
|
+
requestNonce: import_zod14.z.string().min(8).max(128).optional(),
|
|
3448
|
+
requestTakerDeviceId: import_zod14.z.string().min(1).max(128).nullable().optional(),
|
|
3449
|
+
requestTakerPubkeySpkiB64: Base64Std4.min(64).max(4096).optional(),
|
|
3450
|
+
requestTakerSignatureDerB64: Base64Std4.min(16).max(2048).optional(),
|
|
3451
|
+
payerPubkeySpkiB64: Base64Std4.min(64).max(4096),
|
|
3452
|
+
payerSignatureDerB64: Base64Std4.min(16).max(2048),
|
|
3453
|
+
payeePubkeySpkiB64: Base64Std4.min(64).max(4096).optional(),
|
|
3454
|
+
payeeSignatureDerB64: Base64Std4.min(16).max(2048).optional()
|
|
3390
3455
|
});
|
|
3391
|
-
var ConsumerSettlementSchema =
|
|
3392
|
-
settlementId:
|
|
3456
|
+
var ConsumerSettlementSchema = import_zod14.z.object({
|
|
3457
|
+
settlementId: import_zod14.z.string().uuid(),
|
|
3393
3458
|
settlementKey: Sha256Hex,
|
|
3394
3459
|
encounterId: Sha256Hex,
|
|
3395
|
-
oacId:
|
|
3396
|
-
payerUserId:
|
|
3397
|
-
payeeUserId:
|
|
3398
|
-
amountKobo:
|
|
3399
|
-
currency:
|
|
3400
|
-
status:
|
|
3401
|
-
reviewReason:
|
|
3402
|
-
ledgerRef:
|
|
3460
|
+
oacId: import_zod14.z.string().uuid(),
|
|
3461
|
+
payerUserId: import_zod14.z.string().uuid(),
|
|
3462
|
+
payeeUserId: import_zod14.z.string().uuid(),
|
|
3463
|
+
amountKobo: import_zod14.z.number().int().positive(),
|
|
3464
|
+
currency: import_zod14.z.string().length(3),
|
|
3465
|
+
status: import_zod14.z.enum(["SETTLED", "REVIEW"]),
|
|
3466
|
+
reviewReason: import_zod14.z.string().nullable(),
|
|
3467
|
+
ledgerRef: import_zod14.z.string().nullable(),
|
|
3403
3468
|
/** ASN.1 DER ECDSA P-256 issuer signature, base64. */
|
|
3404
|
-
issuerSig:
|
|
3469
|
+
issuerSig: Base64Std4.min(16).max(2048),
|
|
3405
3470
|
/** Canonical millisecond timestamp signed into the settlement receipt. */
|
|
3406
|
-
issuedAtMs:
|
|
3471
|
+
issuedAtMs: import_zod14.z.number().int().nonnegative(),
|
|
3407
3472
|
/** Compatibility alias for API consumers that predate issuedAtMs. */
|
|
3408
|
-
createdAtMs:
|
|
3473
|
+
createdAtMs: import_zod14.z.number().int().nonnegative().optional()
|
|
3409
3474
|
});
|
|
3410
|
-
var ConsumerSettleResultSchema =
|
|
3475
|
+
var ConsumerSettleResultSchema = import_zod14.z.object({
|
|
3411
3476
|
settlement: ConsumerSettlementSchema,
|
|
3412
3477
|
encounterId: Sha256Hex,
|
|
3413
|
-
replayed:
|
|
3478
|
+
replayed: import_zod14.z.boolean()
|
|
3414
3479
|
});
|
|
3415
|
-
var RevokeDeviceKeyInputSchema =
|
|
3416
|
-
deviceId:
|
|
3480
|
+
var RevokeDeviceKeyInputSchema = import_zod14.z.object({
|
|
3481
|
+
deviceId: import_zod14.z.string().min(1).max(128),
|
|
3417
3482
|
/** Step-up token from /api/v1/auth/send/verify with purpose='offline_revoke'. */
|
|
3418
|
-
sendAuthToken:
|
|
3483
|
+
sendAuthToken: import_zod14.z.string().min(16)
|
|
3419
3484
|
});
|
|
3420
3485
|
function createMeOfflineClient(opts) {
|
|
3421
3486
|
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
@@ -3448,7 +3513,7 @@ function createMeOfflineClient(opts) {
|
|
|
3448
3513
|
}
|
|
3449
3514
|
return parser(raw);
|
|
3450
3515
|
}
|
|
3451
|
-
const deviceKeyItems =
|
|
3516
|
+
const deviceKeyItems = import_zod14.z.object({ items: import_zod14.z.array(DeviceKeyRecordSchema) });
|
|
3452
3517
|
return {
|
|
3453
3518
|
issueP256EnrollmentChallenge: (input) => call(
|
|
3454
3519
|
"POST",
|
|
@@ -3506,6 +3571,12 @@ function createMeOfflineClient(opts) {
|
|
|
3506
3571
|
"/v1/issuer/keys",
|
|
3507
3572
|
void 0,
|
|
3508
3573
|
(raw) => IssuerTrustBundleSchema.parse(raw)
|
|
3574
|
+
),
|
|
3575
|
+
getRevocations: () => call(
|
|
3576
|
+
"GET",
|
|
3577
|
+
"/v1/issuer/revocations",
|
|
3578
|
+
void 0,
|
|
3579
|
+
(raw) => SignedRevocationListSchema.parse(raw)
|
|
3509
3580
|
)
|
|
3510
3581
|
};
|
|
3511
3582
|
}
|
|
@@ -3652,26 +3723,26 @@ function verifyClaimSignature(input) {
|
|
|
3652
3723
|
}
|
|
3653
3724
|
|
|
3654
3725
|
// src/me-offline/request.ts
|
|
3655
|
-
var
|
|
3656
|
-
var
|
|
3726
|
+
var import_zod15 = require("zod");
|
|
3727
|
+
var Base64Std5 = import_zod15.z.string().regex(/^[A-Za-z0-9+/]+={0,2}$/);
|
|
3657
3728
|
var CONSUMER_PAYMENT_REQUEST_DOMAIN = "flur:consumer-offline:v1:request";
|
|
3658
|
-
var ConsumerPaymentRequestEnvelopeSchema =
|
|
3659
|
-
requestId:
|
|
3660
|
-
mode:
|
|
3661
|
-
takerUserId:
|
|
3662
|
-
amountKobo:
|
|
3663
|
-
currency:
|
|
3664
|
-
reference:
|
|
3665
|
-
createdAtMs:
|
|
3666
|
-
expiresAtMs:
|
|
3667
|
-
nonce:
|
|
3668
|
-
takerDeviceId:
|
|
3669
|
-
takerPubkeySpkiB64:
|
|
3670
|
-
takerSignatureDerB64:
|
|
3729
|
+
var ConsumerPaymentRequestEnvelopeSchema = import_zod15.z.object({
|
|
3730
|
+
requestId: import_zod15.z.string().uuid(),
|
|
3731
|
+
mode: import_zod15.z.enum(["fixed", "editable"]),
|
|
3732
|
+
takerUserId: import_zod15.z.string().uuid(),
|
|
3733
|
+
amountKobo: import_zod15.z.number().int().positive(),
|
|
3734
|
+
currency: import_zod15.z.string().length(3).default("NGN"),
|
|
3735
|
+
reference: import_zod15.z.string().max(128).nullable().default(null),
|
|
3736
|
+
createdAtMs: import_zod15.z.number().int().nonnegative(),
|
|
3737
|
+
expiresAtMs: import_zod15.z.number().int().positive(),
|
|
3738
|
+
nonce: import_zod15.z.string().min(8).max(128),
|
|
3739
|
+
takerDeviceId: import_zod15.z.string().min(1).max(128).nullable().default(null),
|
|
3740
|
+
takerPubkeySpkiB64: Base64Std5.min(64).max(4096).optional(),
|
|
3741
|
+
takerSignatureDerB64: Base64Std5.min(16).max(2048).optional()
|
|
3671
3742
|
}).superRefine((value, ctx) => {
|
|
3672
3743
|
if (value.expiresAtMs <= value.createdAtMs) {
|
|
3673
3744
|
ctx.addIssue({
|
|
3674
|
-
code:
|
|
3745
|
+
code: import_zod15.z.ZodIssueCode.custom,
|
|
3675
3746
|
path: ["expiresAtMs"],
|
|
3676
3747
|
message: "expiresAtMs must be greater than createdAtMs"
|
|
3677
3748
|
});
|
|
@@ -3682,21 +3753,21 @@ var ConsumerPaymentRequestEnvelopeSchema = import_zod14.z.object({
|
|
|
3682
3753
|
if (value.mode === "fixed" || hasSignature) {
|
|
3683
3754
|
if (!value.takerDeviceId) {
|
|
3684
3755
|
ctx.addIssue({
|
|
3685
|
-
code:
|
|
3756
|
+
code: import_zod15.z.ZodIssueCode.custom,
|
|
3686
3757
|
path: ["takerDeviceId"],
|
|
3687
3758
|
message: "signed requests require takerDeviceId"
|
|
3688
3759
|
});
|
|
3689
3760
|
}
|
|
3690
3761
|
if (!value.takerPubkeySpkiB64) {
|
|
3691
3762
|
ctx.addIssue({
|
|
3692
|
-
code:
|
|
3763
|
+
code: import_zod15.z.ZodIssueCode.custom,
|
|
3693
3764
|
path: ["takerPubkeySpkiB64"],
|
|
3694
3765
|
message: "signed requests require takerPubkeySpkiB64"
|
|
3695
3766
|
});
|
|
3696
3767
|
}
|
|
3697
3768
|
if (!value.takerSignatureDerB64) {
|
|
3698
3769
|
ctx.addIssue({
|
|
3699
|
-
code:
|
|
3770
|
+
code: import_zod15.z.ZodIssueCode.custom,
|
|
3700
3771
|
path: ["takerSignatureDerB64"],
|
|
3701
3772
|
message: "signed requests require takerSignatureDerB64"
|
|
3702
3773
|
});
|
|
@@ -3867,6 +3938,7 @@ function base64UrlDecodeUtf8(input) {
|
|
|
3867
3938
|
}
|
|
3868
3939
|
|
|
3869
3940
|
// src/me-offline/oac.ts
|
|
3941
|
+
var import_zod16 = require("zod");
|
|
3870
3942
|
var CONSUMER_OAC_DOMAIN = "flur:consumer-offline:v1:oac";
|
|
3871
3943
|
function consumerOacSigningPayload(oac) {
|
|
3872
3944
|
return { domain: CONSUMER_OAC_DOMAIN, ...oac };
|
|
@@ -3892,6 +3964,9 @@ function verifyOacOffline(signed, trustedKeys, options = {}) {
|
|
|
3892
3964
|
}
|
|
3893
3965
|
if (nowMs < oac.validFromMs) return { ok: false, reason: "not_yet_valid" };
|
|
3894
3966
|
if (nowMs >= oac.validUntilMs) return { ok: false, reason: "expired" };
|
|
3967
|
+
if (options.revokedOacIds?.has(oac.oacId)) {
|
|
3968
|
+
return { ok: false, reason: "revoked" };
|
|
3969
|
+
}
|
|
3895
3970
|
return {
|
|
3896
3971
|
ok: true,
|
|
3897
3972
|
oac,
|
|
@@ -3909,15 +3984,28 @@ var CONSUMER_OAC_QR_PREFIX = "FLUROAC1.";
|
|
|
3909
3984
|
function isConsumerOacQR(value) {
|
|
3910
3985
|
return value.startsWith(CONSUMER_OAC_QR_PREFIX);
|
|
3911
3986
|
}
|
|
3912
|
-
|
|
3987
|
+
var OacPresentmentRequestSchema = import_zod16.z.object({
|
|
3988
|
+
/** Requested amount in minor units (kobo). */
|
|
3989
|
+
amountMinor: import_zod16.z.number().int().positive().max(1e12).optional(),
|
|
3990
|
+
/** Purpose/intent code (mirrors the NIBSS intent vocabulary). */
|
|
3991
|
+
intent: import_zod16.z.string().min(1).max(32).optional(),
|
|
3992
|
+
/** Free-text reference / note. */
|
|
3993
|
+
reference: import_zod16.z.string().min(1).max(64).optional()
|
|
3994
|
+
}).strict();
|
|
3995
|
+
function encodeConsumerOacQR(signed, request) {
|
|
3913
3996
|
const parsed = SignedConsumerOACSchema.parse(signed);
|
|
3914
|
-
|
|
3997
|
+
const base = `${CONSUMER_OAC_QR_PREFIX}${base64UrlEncodeUtf82(JSON.stringify(parsed))}`;
|
|
3998
|
+
if (request === void 0) return base;
|
|
3999
|
+
const parsedRequest = OacPresentmentRequestSchema.parse(request);
|
|
4000
|
+
if (Object.keys(parsedRequest).length === 0) return base;
|
|
4001
|
+
return `${base}.${base64UrlEncodeUtf82(JSON.stringify(parsedRequest))}`;
|
|
3915
4002
|
}
|
|
3916
4003
|
function decodeUnverifiedConsumerOacQR(value) {
|
|
3917
4004
|
if (!value.startsWith(CONSUMER_OAC_QR_PREFIX)) {
|
|
3918
4005
|
throw new Error("not a Flur consumer OAC QR");
|
|
3919
4006
|
}
|
|
3920
|
-
const
|
|
4007
|
+
const remainder = value.slice(CONSUMER_OAC_QR_PREFIX.length);
|
|
4008
|
+
const encoded = remainder.split(".", 1)[0];
|
|
3921
4009
|
let raw;
|
|
3922
4010
|
try {
|
|
3923
4011
|
raw = JSON.parse(base64UrlDecodeUtf82(encoded));
|
|
@@ -3926,6 +4014,21 @@ function decodeUnverifiedConsumerOacQR(value) {
|
|
|
3926
4014
|
}
|
|
3927
4015
|
return SignedConsumerOACSchema.parse(raw);
|
|
3928
4016
|
}
|
|
4017
|
+
function decodeConsumerOacRequest(value) {
|
|
4018
|
+
if (!value.startsWith(CONSUMER_OAC_QR_PREFIX)) return null;
|
|
4019
|
+
const remainder = value.slice(CONSUMER_OAC_QR_PREFIX.length);
|
|
4020
|
+
const dot = remainder.indexOf(".");
|
|
4021
|
+
if (dot < 0) return null;
|
|
4022
|
+
const suffix = remainder.slice(dot + 1);
|
|
4023
|
+
if (suffix.length === 0) return null;
|
|
4024
|
+
try {
|
|
4025
|
+
const raw = JSON.parse(base64UrlDecodeUtf82(suffix));
|
|
4026
|
+
const parsed = OacPresentmentRequestSchema.safeParse(raw);
|
|
4027
|
+
return parsed.success ? parsed.data : null;
|
|
4028
|
+
} catch {
|
|
4029
|
+
return null;
|
|
4030
|
+
}
|
|
4031
|
+
}
|
|
3929
4032
|
function base64UrlEncodeUtf82(input) {
|
|
3930
4033
|
const bytes = new TextEncoder().encode(input);
|
|
3931
4034
|
let binary = "";
|
|
@@ -4221,14 +4324,14 @@ function base64UrlToBytes(input) {
|
|
|
4221
4324
|
}
|
|
4222
4325
|
|
|
4223
4326
|
// src/partner-funding/client.ts
|
|
4224
|
-
var
|
|
4225
|
-
var MinorString =
|
|
4226
|
-
var PositiveMinor =
|
|
4227
|
-
|
|
4228
|
-
|
|
4327
|
+
var import_zod17 = require("zod");
|
|
4328
|
+
var MinorString = import_zod17.z.string().regex(/^-?\d+$/);
|
|
4329
|
+
var PositiveMinor = import_zod17.z.union([
|
|
4330
|
+
import_zod17.z.number().int().positive(),
|
|
4331
|
+
import_zod17.z.string().regex(/^[1-9]\d{0,18}$/)
|
|
4229
4332
|
]);
|
|
4230
|
-
var Currency =
|
|
4231
|
-
var Metadata =
|
|
4333
|
+
var Currency = import_zod17.z.string().trim().length(3).transform((v) => v.toUpperCase());
|
|
4334
|
+
var Metadata = import_zod17.z.record(import_zod17.z.unknown());
|
|
4232
4335
|
var PARTNER_KINDS = ["bank", "merchant"];
|
|
4233
4336
|
var CUSTODIAL_MODES = ["agent_of_bank", "flur_virtual_pool"];
|
|
4234
4337
|
var PARTNER_PROFILE_STATUSES = [
|
|
@@ -4255,126 +4358,126 @@ var WITHDRAWAL_STATES = [
|
|
|
4255
4358
|
"failed",
|
|
4256
4359
|
"reversed"
|
|
4257
4360
|
];
|
|
4258
|
-
var PartnerProfileSchema =
|
|
4259
|
-
partnerAccountId:
|
|
4260
|
-
kind:
|
|
4261
|
-
custodialMode:
|
|
4262
|
-
displayName:
|
|
4263
|
-
bankCode:
|
|
4264
|
-
poolAccountNumber:
|
|
4265
|
-
status:
|
|
4361
|
+
var PartnerProfileSchema = import_zod17.z.object({
|
|
4362
|
+
partnerAccountId: import_zod17.z.string().uuid(),
|
|
4363
|
+
kind: import_zod17.z.enum(PARTNER_KINDS),
|
|
4364
|
+
custodialMode: import_zod17.z.enum(CUSTODIAL_MODES),
|
|
4365
|
+
displayName: import_zod17.z.string(),
|
|
4366
|
+
bankCode: import_zod17.z.string().nullable(),
|
|
4367
|
+
poolAccountNumber: import_zod17.z.string().nullable(),
|
|
4368
|
+
status: import_zod17.z.enum(PARTNER_PROFILE_STATUSES),
|
|
4266
4369
|
metadata: Metadata,
|
|
4267
|
-
createdAtMs:
|
|
4268
|
-
updatedAtMs:
|
|
4370
|
+
createdAtMs: import_zod17.z.number().int().nonnegative(),
|
|
4371
|
+
updatedAtMs: import_zod17.z.number().int().nonnegative()
|
|
4269
4372
|
});
|
|
4270
|
-
var UpsertPartnerProfileInputSchema =
|
|
4271
|
-
kind:
|
|
4272
|
-
custodialMode:
|
|
4273
|
-
displayName:
|
|
4274
|
-
bankCode:
|
|
4275
|
-
poolAccountNumber:
|
|
4373
|
+
var UpsertPartnerProfileInputSchema = import_zod17.z.object({
|
|
4374
|
+
kind: import_zod17.z.enum(PARTNER_KINDS),
|
|
4375
|
+
custodialMode: import_zod17.z.enum(CUSTODIAL_MODES),
|
|
4376
|
+
displayName: import_zod17.z.string().trim().min(1).max(200),
|
|
4377
|
+
bankCode: import_zod17.z.string().trim().min(1).max(64).optional(),
|
|
4378
|
+
poolAccountNumber: import_zod17.z.string().trim().min(1).max(64).optional(),
|
|
4276
4379
|
metadata: Metadata.optional()
|
|
4277
4380
|
});
|
|
4278
|
-
var PartnerFundingEventInputSchema =
|
|
4279
|
-
externalRef:
|
|
4280
|
-
direction:
|
|
4281
|
-
userId:
|
|
4282
|
-
accountId:
|
|
4381
|
+
var PartnerFundingEventInputSchema = import_zod17.z.object({
|
|
4382
|
+
externalRef: import_zod17.z.string().trim().min(8).max(128),
|
|
4383
|
+
direction: import_zod17.z.enum(PARTNER_FUNDING_DIRECTIONS).optional(),
|
|
4384
|
+
userId: import_zod17.z.string().uuid().optional(),
|
|
4385
|
+
accountId: import_zod17.z.string().uuid().optional(),
|
|
4283
4386
|
amountMinor: PositiveMinor,
|
|
4284
4387
|
currency: Currency,
|
|
4285
|
-
fundingSource:
|
|
4388
|
+
fundingSource: import_zod17.z.string().trim().min(1).max(64).optional(),
|
|
4286
4389
|
providerMetadata: Metadata.optional()
|
|
4287
4390
|
});
|
|
4288
|
-
var PartnerFundingSchema =
|
|
4289
|
-
fundingId:
|
|
4290
|
-
partnerId:
|
|
4291
|
-
accountId:
|
|
4292
|
-
userId:
|
|
4293
|
-
direction:
|
|
4294
|
-
currency:
|
|
4391
|
+
var PartnerFundingSchema = import_zod17.z.object({
|
|
4392
|
+
fundingId: import_zod17.z.string().uuid(),
|
|
4393
|
+
partnerId: import_zod17.z.string().uuid(),
|
|
4394
|
+
accountId: import_zod17.z.string().uuid(),
|
|
4395
|
+
userId: import_zod17.z.string().uuid().nullable(),
|
|
4396
|
+
direction: import_zod17.z.enum(PARTNER_FUNDING_DIRECTIONS),
|
|
4397
|
+
currency: import_zod17.z.string(),
|
|
4295
4398
|
amountMinor: MinorString,
|
|
4296
|
-
externalRef:
|
|
4297
|
-
status:
|
|
4298
|
-
fundingSource:
|
|
4299
|
-
ledgerRef:
|
|
4399
|
+
externalRef: import_zod17.z.string(),
|
|
4400
|
+
status: import_zod17.z.enum(PARTNER_FUNDING_STATUSES),
|
|
4401
|
+
fundingSource: import_zod17.z.string(),
|
|
4402
|
+
ledgerRef: import_zod17.z.string(),
|
|
4300
4403
|
providerMetadata: Metadata,
|
|
4301
|
-
createdAtMs:
|
|
4302
|
-
updatedAtMs:
|
|
4404
|
+
createdAtMs: import_zod17.z.number().int().nonnegative(),
|
|
4405
|
+
updatedAtMs: import_zod17.z.number().int().nonnegative()
|
|
4303
4406
|
});
|
|
4304
|
-
var IngestFundingResultSchema =
|
|
4407
|
+
var IngestFundingResultSchema = import_zod17.z.object({
|
|
4305
4408
|
funding: PartnerFundingSchema,
|
|
4306
|
-
replayed:
|
|
4409
|
+
replayed: import_zod17.z.boolean()
|
|
4307
4410
|
});
|
|
4308
|
-
var PayoutDestinationSchema =
|
|
4309
|
-
destinationId:
|
|
4310
|
-
accountId:
|
|
4311
|
-
partnerId:
|
|
4312
|
-
bankCode:
|
|
4313
|
-
accountNumber:
|
|
4314
|
-
accountName:
|
|
4315
|
-
status:
|
|
4316
|
-
verifiedAtMs:
|
|
4411
|
+
var PayoutDestinationSchema = import_zod17.z.object({
|
|
4412
|
+
destinationId: import_zod17.z.string().uuid(),
|
|
4413
|
+
accountId: import_zod17.z.string().uuid(),
|
|
4414
|
+
partnerId: import_zod17.z.string().uuid(),
|
|
4415
|
+
bankCode: import_zod17.z.string(),
|
|
4416
|
+
accountNumber: import_zod17.z.string(),
|
|
4417
|
+
accountName: import_zod17.z.string(),
|
|
4418
|
+
status: import_zod17.z.enum(PAYOUT_DESTINATION_STATUSES),
|
|
4419
|
+
verifiedAtMs: import_zod17.z.number().int().nonnegative().nullable(),
|
|
4317
4420
|
metadata: Metadata,
|
|
4318
|
-
createdAtMs:
|
|
4319
|
-
updatedAtMs:
|
|
4421
|
+
createdAtMs: import_zod17.z.number().int().nonnegative(),
|
|
4422
|
+
updatedAtMs: import_zod17.z.number().int().nonnegative()
|
|
4320
4423
|
});
|
|
4321
|
-
var CreatePayoutDestinationInputSchema =
|
|
4322
|
-
partnerId:
|
|
4323
|
-
bankCode:
|
|
4324
|
-
accountNumber:
|
|
4325
|
-
accountName:
|
|
4424
|
+
var CreatePayoutDestinationInputSchema = import_zod17.z.object({
|
|
4425
|
+
partnerId: import_zod17.z.string().uuid(),
|
|
4426
|
+
bankCode: import_zod17.z.string().trim().min(1).max(32),
|
|
4427
|
+
accountNumber: import_zod17.z.string().trim().min(4).max(64),
|
|
4428
|
+
accountName: import_zod17.z.string().trim().min(1).max(200),
|
|
4326
4429
|
metadata: Metadata.optional()
|
|
4327
4430
|
});
|
|
4328
|
-
var ListPayoutDestinationsResultSchema =
|
|
4329
|
-
items:
|
|
4431
|
+
var ListPayoutDestinationsResultSchema = import_zod17.z.object({
|
|
4432
|
+
items: import_zod17.z.array(PayoutDestinationSchema)
|
|
4330
4433
|
});
|
|
4331
|
-
var WithdrawalSchema =
|
|
4332
|
-
withdrawalId:
|
|
4333
|
-
accountId:
|
|
4334
|
-
userId:
|
|
4335
|
-
partnerId:
|
|
4336
|
-
destinationId:
|
|
4337
|
-
currency:
|
|
4434
|
+
var WithdrawalSchema = import_zod17.z.object({
|
|
4435
|
+
withdrawalId: import_zod17.z.string().uuid(),
|
|
4436
|
+
accountId: import_zod17.z.string().uuid(),
|
|
4437
|
+
userId: import_zod17.z.string().uuid(),
|
|
4438
|
+
partnerId: import_zod17.z.string().uuid(),
|
|
4439
|
+
destinationId: import_zod17.z.string().uuid(),
|
|
4440
|
+
currency: import_zod17.z.string(),
|
|
4338
4441
|
amountMinor: MinorString,
|
|
4339
|
-
state:
|
|
4340
|
-
idempotencyKey:
|
|
4341
|
-
providerRef:
|
|
4342
|
-
lastError:
|
|
4343
|
-
ledgerRef:
|
|
4344
|
-
reverseLedgerRef:
|
|
4442
|
+
state: import_zod17.z.enum(WITHDRAWAL_STATES),
|
|
4443
|
+
idempotencyKey: import_zod17.z.string(),
|
|
4444
|
+
providerRef: import_zod17.z.string().nullable(),
|
|
4445
|
+
lastError: import_zod17.z.string().nullable(),
|
|
4446
|
+
ledgerRef: import_zod17.z.string(),
|
|
4447
|
+
reverseLedgerRef: import_zod17.z.string().nullable(),
|
|
4345
4448
|
metadata: Metadata,
|
|
4346
|
-
createdAtMs:
|
|
4347
|
-
updatedAtMs:
|
|
4449
|
+
createdAtMs: import_zod17.z.number().int().nonnegative(),
|
|
4450
|
+
updatedAtMs: import_zod17.z.number().int().nonnegative()
|
|
4348
4451
|
});
|
|
4349
|
-
var CreateWithdrawalInputSchema =
|
|
4350
|
-
destinationId:
|
|
4452
|
+
var CreateWithdrawalInputSchema = import_zod17.z.object({
|
|
4453
|
+
destinationId: import_zod17.z.string().uuid(),
|
|
4351
4454
|
amountMinor: PositiveMinor,
|
|
4352
4455
|
currency: Currency,
|
|
4353
|
-
idempotencyKey:
|
|
4456
|
+
idempotencyKey: import_zod17.z.string().trim().min(8).max(128),
|
|
4354
4457
|
metadata: Metadata.optional()
|
|
4355
4458
|
});
|
|
4356
|
-
var CreateWithdrawalResultSchema =
|
|
4459
|
+
var CreateWithdrawalResultSchema = import_zod17.z.object({
|
|
4357
4460
|
withdrawal: WithdrawalSchema,
|
|
4358
|
-
replayed:
|
|
4461
|
+
replayed: import_zod17.z.boolean()
|
|
4359
4462
|
});
|
|
4360
|
-
var PayoutEventInputSchema =
|
|
4361
|
-
externalRef:
|
|
4362
|
-
withdrawalId:
|
|
4363
|
-
state:
|
|
4364
|
-
providerRef:
|
|
4365
|
-
failureCode:
|
|
4366
|
-
failureMessage:
|
|
4463
|
+
var PayoutEventInputSchema = import_zod17.z.object({
|
|
4464
|
+
externalRef: import_zod17.z.string().trim().min(8).max(128),
|
|
4465
|
+
withdrawalId: import_zod17.z.string().uuid().optional(),
|
|
4466
|
+
state: import_zod17.z.enum(["submitted", "processing", "paid", "failed"]),
|
|
4467
|
+
providerRef: import_zod17.z.string().trim().min(1).max(128).optional(),
|
|
4468
|
+
failureCode: import_zod17.z.string().trim().max(64).optional(),
|
|
4469
|
+
failureMessage: import_zod17.z.string().trim().max(512).optional(),
|
|
4367
4470
|
providerMetadata: Metadata.optional()
|
|
4368
4471
|
});
|
|
4369
|
-
var RecordPayoutEventResultSchema =
|
|
4472
|
+
var RecordPayoutEventResultSchema = import_zod17.z.object({
|
|
4370
4473
|
withdrawal: WithdrawalSchema,
|
|
4371
|
-
replayed:
|
|
4474
|
+
replayed: import_zod17.z.boolean()
|
|
4372
4475
|
});
|
|
4373
|
-
var ReconciliationReportSchema =
|
|
4374
|
-
partnerId:
|
|
4375
|
-
currency:
|
|
4376
|
-
fromMs:
|
|
4377
|
-
toMs:
|
|
4476
|
+
var ReconciliationReportSchema = import_zod17.z.object({
|
|
4477
|
+
partnerId: import_zod17.z.string().uuid(),
|
|
4478
|
+
currency: import_zod17.z.string(),
|
|
4479
|
+
fromMs: import_zod17.z.number().int().nonnegative(),
|
|
4480
|
+
toMs: import_zod17.z.number().int().nonnegative(),
|
|
4378
4481
|
fundingsCreditMinor: MinorString,
|
|
4379
4482
|
fundingsDebitMinor: MinorString,
|
|
4380
4483
|
withdrawalsPaidMinor: MinorString,
|
|
@@ -4383,7 +4486,7 @@ var ReconciliationReportSchema = import_zod15.z.object({
|
|
|
4383
4486
|
expectedReserveBalanceMinor: MinorString,
|
|
4384
4487
|
actualReserveBalanceMinor: MinorString,
|
|
4385
4488
|
imbalanceMinor: MinorString,
|
|
4386
|
-
generatedAtMs:
|
|
4489
|
+
generatedAtMs: import_zod17.z.number().int().nonnegative()
|
|
4387
4490
|
});
|
|
4388
4491
|
function createPartnerFundingClient(partner) {
|
|
4389
4492
|
return {
|
|
@@ -4535,19 +4638,19 @@ function createPartnerProfileAdminClient(opts) {
|
|
|
4535
4638
|
}
|
|
4536
4639
|
|
|
4537
4640
|
// src/artifacts/envelope.ts
|
|
4538
|
-
var
|
|
4641
|
+
var import_zod18 = require("zod");
|
|
4539
4642
|
var FLUR_ARTIFACT_URI_SCHEME = "flur";
|
|
4540
4643
|
var FLUR_ARTIFACT_VERSION = 1;
|
|
4541
4644
|
var FLUR_ARTIFACT_URI_PREFIX = `${FLUR_ARTIFACT_URI_SCHEME}://v${FLUR_ARTIFACT_VERSION}/`;
|
|
4542
4645
|
var ArtifactTypeRe = /^[a-z][a-z0-9_]{1,63}$/;
|
|
4543
|
-
var ArtifactHeaderSchema =
|
|
4544
|
-
v:
|
|
4545
|
-
t:
|
|
4546
|
-
iss:
|
|
4547
|
-
kid:
|
|
4548
|
-
iat:
|
|
4549
|
-
exp:
|
|
4550
|
-
nonce:
|
|
4646
|
+
var ArtifactHeaderSchema = import_zod18.z.object({
|
|
4647
|
+
v: import_zod18.z.literal(FLUR_ARTIFACT_VERSION),
|
|
4648
|
+
t: import_zod18.z.string().regex(ArtifactTypeRe, "invalid artifact type"),
|
|
4649
|
+
iss: import_zod18.z.string().min(1).max(128),
|
|
4650
|
+
kid: import_zod18.z.string().min(1).max(128),
|
|
4651
|
+
iat: import_zod18.z.number().int().nonnegative(),
|
|
4652
|
+
exp: import_zod18.z.number().int().positive().optional(),
|
|
4653
|
+
nonce: import_zod18.z.string().min(8).max(64).regex(/^[A-Za-z0-9_-]+$/, "nonce must be url-safe")
|
|
4551
4654
|
});
|
|
4552
4655
|
var FlurArtifactError = class extends Error {
|
|
4553
4656
|
constructor(message, code) {
|
|
@@ -4686,7 +4789,7 @@ function verifyArtifactSignature(decoded, publicKeySpkiB64, options = {}) {
|
|
|
4686
4789
|
}
|
|
4687
4790
|
|
|
4688
4791
|
// src/artifacts/types.ts
|
|
4689
|
-
var
|
|
4792
|
+
var import_zod19 = require("zod");
|
|
4690
4793
|
var ARTIFACT_TYPES = {
|
|
4691
4794
|
OFFLINE_PAYMENT_AUTHORIZATION: "offline_payment_authorization",
|
|
4692
4795
|
RECEIPT: "receipt",
|
|
@@ -4699,37 +4802,34 @@ var ARTIFACT_TYPES = {
|
|
|
4699
4802
|
LEDGER_JOURNAL_ENTRY: "ledger_journal_entry",
|
|
4700
4803
|
STATEMENT: "statement",
|
|
4701
4804
|
PASS: "pass",
|
|
4702
|
-
IDENTITY: "identity"
|
|
4703
|
-
// Tier B: holder-signed identity attestation for offline trust. The
|
|
4704
|
-
// envelope.iat / envelope.exp express the card's canonical lifetime.
|
|
4705
|
-
PAY_CARD: "pay_card"
|
|
4805
|
+
IDENTITY: "identity"
|
|
4706
4806
|
};
|
|
4707
|
-
var HexString = (length) =>
|
|
4807
|
+
var HexString = (length) => import_zod19.z.string().regex(
|
|
4708
4808
|
new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
|
|
4709
4809
|
`expected ${length}-byte hex string`
|
|
4710
4810
|
);
|
|
4711
|
-
var OfflinePaymentAuthorizationArtifactSchema =
|
|
4811
|
+
var OfflinePaymentAuthorizationArtifactSchema = import_zod19.z.object({
|
|
4712
4812
|
authorization: OfflinePaymentAuthorizationSchema
|
|
4713
4813
|
});
|
|
4714
|
-
var ReceiptArtifactSchema =
|
|
4715
|
-
receiptId:
|
|
4716
|
-
paymentReference:
|
|
4717
|
-
payerUserId:
|
|
4718
|
-
payeeUserId:
|
|
4719
|
-
amountKobo:
|
|
4720
|
-
currency:
|
|
4721
|
-
channel:
|
|
4722
|
-
settledAtMs:
|
|
4723
|
-
ledgerTxnId:
|
|
4724
|
-
memo:
|
|
4814
|
+
var ReceiptArtifactSchema = import_zod19.z.object({
|
|
4815
|
+
receiptId: import_zod19.z.string().min(1).max(64),
|
|
4816
|
+
paymentReference: import_zod19.z.string().min(1).max(64),
|
|
4817
|
+
payerUserId: import_zod19.z.string().min(1).max(64).optional(),
|
|
4818
|
+
payeeUserId: import_zod19.z.string().min(1).max(64),
|
|
4819
|
+
amountKobo: import_zod19.z.number().int().positive(),
|
|
4820
|
+
currency: import_zod19.z.literal("NGN"),
|
|
4821
|
+
channel: import_zod19.z.enum(["online", "offline_reconciled", "pay_link", "nqr"]),
|
|
4822
|
+
settledAtMs: import_zod19.z.number().int().positive(),
|
|
4823
|
+
ledgerTxnId: import_zod19.z.string().min(1).max(64).optional(),
|
|
4824
|
+
memo: import_zod19.z.string().max(140).optional(),
|
|
4725
4825
|
hashChainPrev: HexString(32).optional()
|
|
4726
4826
|
});
|
|
4727
|
-
var ShortId =
|
|
4728
|
-
var PositiveInt =
|
|
4729
|
-
var NonNegativeInt =
|
|
4730
|
-
var Currency2 =
|
|
4731
|
-
var Memo =
|
|
4732
|
-
var NqrPaymentRequestArtifactSchema =
|
|
4827
|
+
var ShortId = import_zod19.z.string().min(1).max(64);
|
|
4828
|
+
var PositiveInt = import_zod19.z.number().int().positive();
|
|
4829
|
+
var NonNegativeInt = import_zod19.z.number().int().nonnegative();
|
|
4830
|
+
var Currency2 = import_zod19.z.literal("NGN");
|
|
4831
|
+
var Memo = import_zod19.z.string().max(140);
|
|
4832
|
+
var NqrPaymentRequestArtifactSchema = import_zod19.z.object({
|
|
4733
4833
|
requestId: ShortId,
|
|
4734
4834
|
payeeUserId: ShortId,
|
|
4735
4835
|
amountKobo: PositiveInt.optional(),
|
|
@@ -4737,7 +4837,7 @@ var NqrPaymentRequestArtifactSchema = import_zod17.z.object({
|
|
|
4737
4837
|
memo: Memo.optional(),
|
|
4738
4838
|
expiresAtMs: PositiveInt.optional()
|
|
4739
4839
|
});
|
|
4740
|
-
var PaymentIntentArtifactSchema =
|
|
4840
|
+
var PaymentIntentArtifactSchema = import_zod19.z.object({
|
|
4741
4841
|
intentId: ShortId,
|
|
4742
4842
|
payerUserId: ShortId,
|
|
4743
4843
|
payeeUserId: ShortId,
|
|
@@ -4746,7 +4846,7 @@ var PaymentIntentArtifactSchema = import_zod17.z.object({
|
|
|
4746
4846
|
idempotencyKey: ShortId,
|
|
4747
4847
|
createdAtMs: PositiveInt
|
|
4748
4848
|
});
|
|
4749
|
-
var OfflineClaimArtifactSchema =
|
|
4849
|
+
var OfflineClaimArtifactSchema = import_zod19.z.object({
|
|
4750
4850
|
claimId: ShortId,
|
|
4751
4851
|
authorizationId: ShortId,
|
|
4752
4852
|
payeeUserId: ShortId,
|
|
@@ -4755,10 +4855,10 @@ var OfflineClaimArtifactSchema = import_zod17.z.object({
|
|
|
4755
4855
|
claimedAtMs: PositiveInt,
|
|
4756
4856
|
paymentReference: ShortId.optional()
|
|
4757
4857
|
});
|
|
4758
|
-
var SettlementRecordArtifactSchema =
|
|
4858
|
+
var SettlementRecordArtifactSchema = import_zod19.z.object({
|
|
4759
4859
|
settlementId: ShortId,
|
|
4760
4860
|
ledgerTxnId: ShortId,
|
|
4761
|
-
sourceRefType:
|
|
4861
|
+
sourceRefType: import_zod19.z.enum([
|
|
4762
4862
|
"offline_authorization",
|
|
4763
4863
|
"offline_claim",
|
|
4764
4864
|
"transfer",
|
|
@@ -4769,12 +4869,12 @@ var SettlementRecordArtifactSchema = import_zod17.z.object({
|
|
|
4769
4869
|
currency: Currency2,
|
|
4770
4870
|
settledAtMs: PositiveInt
|
|
4771
4871
|
});
|
|
4772
|
-
var ReversalRecordArtifactSchema =
|
|
4872
|
+
var ReversalRecordArtifactSchema = import_zod19.z.object({
|
|
4773
4873
|
reversalId: ShortId,
|
|
4774
4874
|
originalTxnId: ShortId,
|
|
4775
4875
|
amountKobo: PositiveInt,
|
|
4776
4876
|
currency: Currency2,
|
|
4777
|
-
reason:
|
|
4877
|
+
reason: import_zod19.z.enum([
|
|
4778
4878
|
"user_dispute",
|
|
4779
4879
|
"fraud",
|
|
4780
4880
|
"duplicate",
|
|
@@ -4784,7 +4884,7 @@ var ReversalRecordArtifactSchema = import_zod17.z.object({
|
|
|
4784
4884
|
reversedAtMs: PositiveInt,
|
|
4785
4885
|
memo: Memo.optional()
|
|
4786
4886
|
});
|
|
4787
|
-
var LedgerJournalEntryArtifactSchema =
|
|
4887
|
+
var LedgerJournalEntryArtifactSchema = import_zod19.z.object({
|
|
4788
4888
|
entryId: ShortId,
|
|
4789
4889
|
journalId: ShortId,
|
|
4790
4890
|
debitAccountId: ShortId,
|
|
@@ -4795,13 +4895,13 @@ var LedgerJournalEntryArtifactSchema = import_zod17.z.object({
|
|
|
4795
4895
|
refType: ShortId.optional(),
|
|
4796
4896
|
refId: ShortId.optional()
|
|
4797
4897
|
});
|
|
4798
|
-
var StatementArtifactSchema =
|
|
4898
|
+
var StatementArtifactSchema = import_zod19.z.object({
|
|
4799
4899
|
statementId: ShortId,
|
|
4800
4900
|
userId: ShortId,
|
|
4801
4901
|
periodStartMs: PositiveInt,
|
|
4802
4902
|
periodEndMs: PositiveInt,
|
|
4803
|
-
openingBalanceKobo:
|
|
4804
|
-
closingBalanceKobo:
|
|
4903
|
+
openingBalanceKobo: import_zod19.z.number().int(),
|
|
4904
|
+
closingBalanceKobo: import_zod19.z.number().int(),
|
|
4805
4905
|
transactionCount: NonNegativeInt,
|
|
4806
4906
|
currency: Currency2,
|
|
4807
4907
|
hashChainPrev: HexString(32).optional()
|
|
@@ -4809,16 +4909,16 @@ var StatementArtifactSchema = import_zod17.z.object({
|
|
|
4809
4909
|
message: "periodEndMs must be greater than periodStartMs",
|
|
4810
4910
|
path: ["periodEndMs"]
|
|
4811
4911
|
});
|
|
4812
|
-
var PassArtifactSchema =
|
|
4912
|
+
var PassArtifactSchema = import_zod19.z.object({
|
|
4813
4913
|
passId: ShortId,
|
|
4814
4914
|
holderId: ShortId,
|
|
4815
|
-
category:
|
|
4816
|
-
title:
|
|
4915
|
+
category: import_zod19.z.enum(["membership", "ticket", "loyalty", "access", "voucher"]),
|
|
4916
|
+
title: import_zod19.z.string().min(1).max(120),
|
|
4817
4917
|
validFromMs: PositiveInt,
|
|
4818
4918
|
validUntilMs: PositiveInt.optional(),
|
|
4819
|
-
metadata:
|
|
4820
|
-
|
|
4821
|
-
|
|
4919
|
+
metadata: import_zod19.z.record(
|
|
4920
|
+
import_zod19.z.string().min(1).max(64),
|
|
4921
|
+
import_zod19.z.union([import_zod19.z.string().max(280), import_zod19.z.number(), import_zod19.z.boolean()])
|
|
4822
4922
|
).optional()
|
|
4823
4923
|
}).refine(
|
|
4824
4924
|
(v) => v.validUntilMs === void 0 || v.validUntilMs > v.validFromMs,
|
|
@@ -4827,10 +4927,10 @@ var PassArtifactSchema = import_zod17.z.object({
|
|
|
4827
4927
|
path: ["validUntilMs"]
|
|
4828
4928
|
}
|
|
4829
4929
|
);
|
|
4830
|
-
var IdentityArtifactSchema =
|
|
4930
|
+
var IdentityArtifactSchema = import_zod19.z.object({
|
|
4831
4931
|
attestationId: ShortId,
|
|
4832
4932
|
subjectId: ShortId,
|
|
4833
|
-
claimType:
|
|
4933
|
+
claimType: import_zod19.z.enum([
|
|
4834
4934
|
"phone_verified",
|
|
4835
4935
|
"email_verified",
|
|
4836
4936
|
"bvn_verified",
|
|
@@ -4840,12 +4940,6 @@ var IdentityArtifactSchema = import_zod17.z.object({
|
|
|
4840
4940
|
claimValueHash: HexString(32),
|
|
4841
4941
|
attestedAtMs: PositiveInt
|
|
4842
4942
|
});
|
|
4843
|
-
var PayCardArtifactSchema = import_zod17.z.object({
|
|
4844
|
-
userId: ShortId,
|
|
4845
|
-
phoneE164: import_zod17.z.string().regex(/^\+[1-9]\d{7,14}$/, "phoneE164 must be normalised E.164"),
|
|
4846
|
-
displayName: import_zod17.z.string().min(1).max(64),
|
|
4847
|
-
devicePubKeySpkiB64: import_zod17.z.string().min(64).max(256).regex(/^[A-Za-z0-9+/]+=*$/, "devicePubKeySpkiB64 must be standard base64")
|
|
4848
|
-
});
|
|
4849
4943
|
var ARTIFACT_BODY_SCHEMAS = {
|
|
4850
4944
|
[ARTIFACT_TYPES.OFFLINE_PAYMENT_AUTHORIZATION]: OfflinePaymentAuthorizationArtifactSchema,
|
|
4851
4945
|
[ARTIFACT_TYPES.RECEIPT]: ReceiptArtifactSchema,
|
|
@@ -4857,8 +4951,7 @@ var ARTIFACT_BODY_SCHEMAS = {
|
|
|
4857
4951
|
[ARTIFACT_TYPES.LEDGER_JOURNAL_ENTRY]: LedgerJournalEntryArtifactSchema,
|
|
4858
4952
|
[ARTIFACT_TYPES.STATEMENT]: StatementArtifactSchema,
|
|
4859
4953
|
[ARTIFACT_TYPES.PASS]: PassArtifactSchema,
|
|
4860
|
-
[ARTIFACT_TYPES.IDENTITY]: IdentityArtifactSchema
|
|
4861
|
-
[ARTIFACT_TYPES.PAY_CARD]: PayCardArtifactSchema
|
|
4954
|
+
[ARTIFACT_TYPES.IDENTITY]: IdentityArtifactSchema
|
|
4862
4955
|
};
|
|
4863
4956
|
var HARDENED_ARTIFACT_TYPES = /* @__PURE__ */ new Set([
|
|
4864
4957
|
ARTIFACT_TYPES.OFFLINE_PAYMENT_AUTHORIZATION,
|
|
@@ -4871,8 +4964,7 @@ var HARDENED_ARTIFACT_TYPES = /* @__PURE__ */ new Set([
|
|
|
4871
4964
|
ARTIFACT_TYPES.LEDGER_JOURNAL_ENTRY,
|
|
4872
4965
|
ARTIFACT_TYPES.STATEMENT,
|
|
4873
4966
|
ARTIFACT_TYPES.PASS,
|
|
4874
|
-
ARTIFACT_TYPES.IDENTITY
|
|
4875
|
-
ARTIFACT_TYPES.PAY_CARD
|
|
4967
|
+
ARTIFACT_TYPES.IDENTITY
|
|
4876
4968
|
]);
|
|
4877
4969
|
function isKnownArtifactType(t) {
|
|
4878
4970
|
return Object.values(ARTIFACT_TYPES).includes(t);
|
|
@@ -4957,130 +5049,6 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4957
5049
|
type: ARTIFACT_TYPES.OFFLINE_PAYMENT_AUTHORIZATION
|
|
4958
5050
|
});
|
|
4959
5051
|
}
|
|
4960
|
-
|
|
4961
|
-
// src/artifacts/paycard.ts
|
|
4962
|
-
var PAY_CARD_DEFAULT_TTL_MS = 90 * 24 * 60 * 60 * 1e3;
|
|
4963
|
-
var PAY_CARD_REFRESH_THRESHOLD_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
4964
|
-
var PAY_CARD_URI_PREFIX = `${FLUR_ARTIFACT_URI_PREFIX}${ARTIFACT_TYPES.PAY_CARD}/`;
|
|
4965
|
-
function createPayCardArtifactUri(input) {
|
|
4966
|
-
if (input.data.userId !== input.issuer) {
|
|
4967
|
-
throw new FlurArtifactError(
|
|
4968
|
-
"pay_card.data.userId must equal envelope issuer",
|
|
4969
|
-
"INVALID_BODY"
|
|
4970
|
-
);
|
|
4971
|
-
}
|
|
4972
|
-
const iat = input.issuedAtSeconds ?? Math.floor(Date.now() / 1e3);
|
|
4973
|
-
const exp = input.expiresAtSeconds ?? iat + Math.floor(PAY_CARD_DEFAULT_TTL_MS / 1e3);
|
|
4974
|
-
return createArtifactUri({
|
|
4975
|
-
type: ARTIFACT_TYPES.PAY_CARD,
|
|
4976
|
-
issuer: input.issuer,
|
|
4977
|
-
keyId: input.keyId,
|
|
4978
|
-
privateKey: input.privateKey,
|
|
4979
|
-
nonce: input.nonce,
|
|
4980
|
-
issuedAtSeconds: iat,
|
|
4981
|
-
expiresAtSeconds: exp,
|
|
4982
|
-
data: input.data
|
|
4983
|
-
});
|
|
4984
|
-
}
|
|
4985
|
-
function isPayCardArtifactUri(uri) {
|
|
4986
|
-
return typeof uri === "string" && uri.startsWith(PAY_CARD_URI_PREFIX);
|
|
4987
|
-
}
|
|
4988
|
-
function decodePayCardArtifact(uri) {
|
|
4989
|
-
if (!isPayCardArtifactUri(uri)) {
|
|
4990
|
-
throw new FlurArtifactError(
|
|
4991
|
-
`URI does not start with ${PAY_CARD_URI_PREFIX}`,
|
|
4992
|
-
"INVALID_URI"
|
|
4993
|
-
);
|
|
4994
|
-
}
|
|
4995
|
-
const decoded = decodeArtifactUri(uri);
|
|
4996
|
-
if (decoded.type !== ARTIFACT_TYPES.PAY_CARD) {
|
|
4997
|
-
throw new FlurArtifactError(
|
|
4998
|
-
`Expected pay_card, got ${decoded.type}`,
|
|
4999
|
-
"TYPE_MISMATCH"
|
|
5000
|
-
);
|
|
5001
|
-
}
|
|
5002
|
-
const parsed = PayCardArtifactSchema.safeParse(decoded.body.data);
|
|
5003
|
-
if (!parsed.success) {
|
|
5004
|
-
throw new FlurArtifactError(
|
|
5005
|
-
`pay_card body invalid: ${parsed.error.message}`,
|
|
5006
|
-
"INVALID_BODY"
|
|
5007
|
-
);
|
|
5008
|
-
}
|
|
5009
|
-
if (parsed.data.userId !== decoded.body.iss) {
|
|
5010
|
-
throw new FlurArtifactError(
|
|
5011
|
-
"pay_card.data.userId must equal envelope issuer",
|
|
5012
|
-
"INVALID_BODY"
|
|
5013
|
-
);
|
|
5014
|
-
}
|
|
5015
|
-
return {
|
|
5016
|
-
body: {
|
|
5017
|
-
...decoded.body,
|
|
5018
|
-
data: parsed.data
|
|
5019
|
-
},
|
|
5020
|
-
sig: decoded.sig,
|
|
5021
|
-
decoded
|
|
5022
|
-
};
|
|
5023
|
-
}
|
|
5024
|
-
function verifyPayCardArtifact(uri, publicKeySpkiB64, options = {}) {
|
|
5025
|
-
if (!isPayCardArtifactUri(uri)) {
|
|
5026
|
-
throw new FlurArtifactError(
|
|
5027
|
-
`URI does not start with ${PAY_CARD_URI_PREFIX}`,
|
|
5028
|
-
"INVALID_URI"
|
|
5029
|
-
);
|
|
5030
|
-
}
|
|
5031
|
-
const verified = verifyArtifactUri(
|
|
5032
|
-
uri,
|
|
5033
|
-
publicKeySpkiB64,
|
|
5034
|
-
options
|
|
5035
|
-
);
|
|
5036
|
-
if (verified.decoded.type !== ARTIFACT_TYPES.PAY_CARD) {
|
|
5037
|
-
throw new FlurArtifactError(
|
|
5038
|
-
`Expected pay_card, got ${verified.decoded.type}`,
|
|
5039
|
-
"TYPE_MISMATCH"
|
|
5040
|
-
);
|
|
5041
|
-
}
|
|
5042
|
-
if (verified.body.data.userId !== verified.body.iss) {
|
|
5043
|
-
throw new FlurArtifactError(
|
|
5044
|
-
"pay_card.data.userId must equal envelope issuer",
|
|
5045
|
-
"INVALID_BODY"
|
|
5046
|
-
);
|
|
5047
|
-
}
|
|
5048
|
-
return {
|
|
5049
|
-
body: verified.body,
|
|
5050
|
-
sig: verified.sig,
|
|
5051
|
-
decoded: verified.decoded
|
|
5052
|
-
};
|
|
5053
|
-
}
|
|
5054
|
-
function inspectPayCardFreshness(decoded, nowMs = Date.now()) {
|
|
5055
|
-
const exp = decoded.body.exp;
|
|
5056
|
-
if (exp === void 0) return "no_expiry";
|
|
5057
|
-
const remainingMs = exp * 1e3 - nowMs;
|
|
5058
|
-
if (remainingMs <= 0) return "expired";
|
|
5059
|
-
if (remainingMs <= PAY_CARD_REFRESH_THRESHOLD_MS)
|
|
5060
|
-
return "refresh_recommended";
|
|
5061
|
-
return "fresh";
|
|
5062
|
-
}
|
|
5063
|
-
function buildPayCardSigningInput(input) {
|
|
5064
|
-
if (input.data.userId !== input.issuer) {
|
|
5065
|
-
throw new FlurArtifactError(
|
|
5066
|
-
"pay_card.data.userId must equal envelope issuer",
|
|
5067
|
-
"INVALID_BODY"
|
|
5068
|
-
);
|
|
5069
|
-
}
|
|
5070
|
-
const parsedData = PayCardArtifactSchema.parse(input.data);
|
|
5071
|
-
const iat = input.issuedAtSeconds ?? Math.floor(Date.now() / 1e3);
|
|
5072
|
-
const exp = input.expiresAtSeconds ?? iat + Math.floor(PAY_CARD_DEFAULT_TTL_MS / 1e3);
|
|
5073
|
-
const body = buildArtifactBody({
|
|
5074
|
-
type: ARTIFACT_TYPES.PAY_CARD,
|
|
5075
|
-
issuer: input.issuer,
|
|
5076
|
-
keyId: input.keyId,
|
|
5077
|
-
data: parsedData,
|
|
5078
|
-
nonce: input.nonce,
|
|
5079
|
-
issuedAtSeconds: iat,
|
|
5080
|
-
expiresAtSeconds: exp
|
|
5081
|
-
});
|
|
5082
|
-
return { body, bodyBytes: canonicalJSONBytes(body) };
|
|
5083
|
-
}
|
|
5084
5052
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5085
5053
|
0 && (module.exports = {
|
|
5086
5054
|
ACCOUNT_FUNDED_OAC_MAX_TTL_MS,
|
|
@@ -5101,6 +5069,7 @@ function buildPayCardSigningInput(input) {
|
|
|
5101
5069
|
CONSUMER_OAC_QR_PREFIX,
|
|
5102
5070
|
CONSUMER_OFFLINE_CLAIM_SUBMIT_GRACE_MS,
|
|
5103
5071
|
CONSUMER_PAYMENT_REQUEST_DOMAIN,
|
|
5072
|
+
CONSUMER_REVOCATION_DOMAIN,
|
|
5104
5073
|
CONSUMER_SETTLEMENT_DOMAIN,
|
|
5105
5074
|
CONSUMER_SETTLEMENT_RECEIPT_QR_PREFIX,
|
|
5106
5075
|
CUSTODIAL_MODES,
|
|
@@ -5162,6 +5131,7 @@ function buildPayCardSigningInput(input) {
|
|
|
5162
5131
|
OFFLINE_SMS_SETTLE_SIGNATURE_BYTES,
|
|
5163
5132
|
OFFLINE_SMS_SETTLE_TOKEN_BYTES,
|
|
5164
5133
|
OFFLINE_SMS_SETTLE_VERSION,
|
|
5134
|
+
OacPresentmentRequestSchema,
|
|
5165
5135
|
OfflineClaimArtifactSchema,
|
|
5166
5136
|
OfflinePaymentAuthorizationArtifactSchema,
|
|
5167
5137
|
OfflinePaymentAuthorizationSchema,
|
|
@@ -5179,9 +5149,6 @@ function buildPayCardSigningInput(input) {
|
|
|
5179
5149
|
PASS_STATES,
|
|
5180
5150
|
PAYLOAD_FORMAT_INDICATOR_VALUE,
|
|
5181
5151
|
PAYOUT_DESTINATION_STATUSES,
|
|
5182
|
-
PAY_CARD_DEFAULT_TTL_MS,
|
|
5183
|
-
PAY_CARD_REFRESH_THRESHOLD_MS,
|
|
5184
|
-
PAY_CARD_URI_PREFIX,
|
|
5185
5152
|
POINT_OF_INITIATION,
|
|
5186
5153
|
PartnerFundingEventInputSchema,
|
|
5187
5154
|
PartnerFundingSchema,
|
|
@@ -5189,7 +5156,6 @@ function buildPayCardSigningInput(input) {
|
|
|
5189
5156
|
PassArtifactSchema,
|
|
5190
5157
|
PassMetadataSchema,
|
|
5191
5158
|
PassSchema,
|
|
5192
|
-
PayCardArtifactSchema,
|
|
5193
5159
|
PayCollectionInputSchema,
|
|
5194
5160
|
PaymentClaimSchema,
|
|
5195
5161
|
PaymentIntentArtifactSchema,
|
|
@@ -5201,6 +5167,7 @@ function buildPayCardSigningInput(input) {
|
|
|
5201
5167
|
RECEIPT_CHANNELS,
|
|
5202
5168
|
RECEIPT_KINDS,
|
|
5203
5169
|
REPLAY_WINDOW_MS,
|
|
5170
|
+
REVOCATION_LIST_MAX_ENTRIES,
|
|
5204
5171
|
ReceiptArtifactSchema,
|
|
5205
5172
|
ReceiptPayloadSchema,
|
|
5206
5173
|
ReceiptSchema,
|
|
@@ -5209,12 +5176,14 @@ function buildPayCardSigningInput(input) {
|
|
|
5209
5176
|
RedemptionSchema,
|
|
5210
5177
|
RegisterDeviceKeyP256InputSchema,
|
|
5211
5178
|
ReversalRecordArtifactSchema,
|
|
5179
|
+
RevocationListSchema,
|
|
5212
5180
|
RevokeDeviceKeyInputSchema,
|
|
5213
5181
|
SETTLEMENT_SCHEDULES,
|
|
5214
5182
|
SettleResponseSchema,
|
|
5215
5183
|
SettlementRecordArtifactSchema,
|
|
5216
5184
|
SettlementSchema,
|
|
5217
5185
|
SignedConsumerOACSchema,
|
|
5186
|
+
SignedRevocationListSchema,
|
|
5218
5187
|
StatementArtifactSchema,
|
|
5219
5188
|
UpsertMerchantProfileInputSchema,
|
|
5220
5189
|
UpsertPartnerProfileInputSchema,
|
|
@@ -5228,7 +5197,6 @@ function buildPayCardSigningInput(input) {
|
|
|
5228
5197
|
buildConsumerPaymentRequest,
|
|
5229
5198
|
buildOAC,
|
|
5230
5199
|
buildPass,
|
|
5231
|
-
buildPayCardSigningInput,
|
|
5232
5200
|
buildPaymentRequest,
|
|
5233
5201
|
buildReceipt,
|
|
5234
5202
|
buildRedemption,
|
|
@@ -5263,17 +5231,16 @@ function buildPayCardSigningInput(input) {
|
|
|
5263
5231
|
createPartnerFundingClient,
|
|
5264
5232
|
createPartnerProfileAdminClient,
|
|
5265
5233
|
createPassesClient,
|
|
5266
|
-
createPayCardArtifactUri,
|
|
5267
5234
|
createReceiptArtifactUri,
|
|
5268
5235
|
createReceiptsClient,
|
|
5269
5236
|
createSoftwareP256Signer,
|
|
5270
5237
|
decodeArtifactUri,
|
|
5271
5238
|
decodeAuthorizationQR,
|
|
5272
5239
|
decodeBase45,
|
|
5240
|
+
decodeConsumerOacRequest,
|
|
5273
5241
|
decodeConsumerSettlementReceiptQR,
|
|
5274
5242
|
decodeOfflineClaimSmsMessage,
|
|
5275
5243
|
decodeOfflineSmsSettleToken,
|
|
5276
|
-
decodePayCardArtifact,
|
|
5277
5244
|
decodePaymentRequestQR,
|
|
5278
5245
|
decodeUnverifiedConsumerOacQR,
|
|
5279
5246
|
decodeUnverifiedConsumerSettlementReceiptQR,
|
|
@@ -5293,19 +5260,19 @@ function buildPayCardSigningInput(input) {
|
|
|
5293
5260
|
generateDynamicQR,
|
|
5294
5261
|
generateStaticQR,
|
|
5295
5262
|
init,
|
|
5296
|
-
inspectPayCardFreshness,
|
|
5297
5263
|
isConsumerOacQR,
|
|
5298
5264
|
isConsumerPaymentRequestExpired,
|
|
5299
5265
|
isHardenedArtifactType,
|
|
5300
5266
|
isKnownArtifactType,
|
|
5267
|
+
isOacRevoked,
|
|
5301
5268
|
isPassWithinValidity,
|
|
5302
|
-
isPayCardArtifactUri,
|
|
5303
5269
|
moneyMinorToNumber,
|
|
5304
5270
|
normalizeE164,
|
|
5305
5271
|
parseAmountInput,
|
|
5306
5272
|
parseNQR,
|
|
5307
5273
|
parseQR,
|
|
5308
5274
|
readTLV,
|
|
5275
|
+
revocationListSigningPayload,
|
|
5309
5276
|
routingHint,
|
|
5310
5277
|
signArtifact,
|
|
5311
5278
|
signAuthorization,
|
|
@@ -5328,11 +5295,11 @@ function buildPayCardSigningInput(input) {
|
|
|
5328
5295
|
verifyOacOffline,
|
|
5329
5296
|
verifyOfflineSmsSettleToken,
|
|
5330
5297
|
verifyPass,
|
|
5331
|
-
verifyPayCardArtifact,
|
|
5332
5298
|
verifyPaymentRequest,
|
|
5333
5299
|
verifyReceipt,
|
|
5334
5300
|
verifyRedemption,
|
|
5335
5301
|
verifyRequestHMAC,
|
|
5302
|
+
verifyRevocationList,
|
|
5336
5303
|
writeTLV
|
|
5337
5304
|
});
|
|
5338
5305
|
//# sourceMappingURL=index.cjs.map
|