@nokinc-flur/sdk 1.1.0 → 1.1.1
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 +467 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1520 -1
- package/dist/index.d.ts +1520 -1
- package/dist/index.js +435 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -23,9 +23,12 @@ __export(index_exports, {
|
|
|
23
23
|
ACCOUNT_STATUSES: () => ACCOUNT_STATUSES,
|
|
24
24
|
ACCOUNT_TYPES: () => ACCOUNT_TYPES,
|
|
25
25
|
ADDITIONAL_DATA_SUBFIELD: () => ADDITIONAL_DATA_SUBFIELD,
|
|
26
|
+
ARTIFACT_BODY_SCHEMAS: () => ARTIFACT_BODY_SCHEMAS,
|
|
27
|
+
ARTIFACT_TYPES: () => ARTIFACT_TYPES,
|
|
26
28
|
AccountMembershipSchema: () => AccountMembershipSchema,
|
|
27
29
|
AccountSchema: () => AccountSchema,
|
|
28
30
|
ApiCredentialPublicSchema: () => ApiCredentialPublicSchema,
|
|
31
|
+
ArtifactHeaderSchema: () => ArtifactHeaderSchema,
|
|
29
32
|
COLLECTION_INTENT_STATUSES: () => COLLECTION_INTENT_STATUSES,
|
|
30
33
|
COLLECTION_PAYMENT_STATUSES: () => COLLECTION_PAYMENT_STATUSES,
|
|
31
34
|
CUSTODIAL_MODES: () => CUSTODIAL_MODES,
|
|
@@ -50,14 +53,21 @@ __export(index_exports, {
|
|
|
50
53
|
EnableOfflineInputSchema: () => EnableOfflineInputSchema,
|
|
51
54
|
EnableOfflineResultSchema: () => EnableOfflineResultSchema,
|
|
52
55
|
FIELD: () => FIELD,
|
|
56
|
+
FLUR_ARTIFACT_URI_PREFIX: () => FLUR_ARTIFACT_URI_PREFIX,
|
|
57
|
+
FLUR_ARTIFACT_URI_SCHEME: () => FLUR_ARTIFACT_URI_SCHEME,
|
|
58
|
+
FLUR_ARTIFACT_VERSION: () => FLUR_ARTIFACT_VERSION,
|
|
53
59
|
FlurApiError: () => FlurApiError,
|
|
60
|
+
FlurArtifactError: () => FlurArtifactError,
|
|
54
61
|
FlurCapExceededError: () => FlurCapExceededError,
|
|
55
62
|
FlurClient: () => FlurClient,
|
|
56
63
|
FlurError: () => FlurError,
|
|
57
64
|
FlurExpiredError: () => FlurExpiredError,
|
|
58
65
|
FlurReplayError: () => FlurReplayError,
|
|
66
|
+
HARDENED_ARTIFACT_TYPES: () => HARDENED_ARTIFACT_TYPES,
|
|
67
|
+
IdentityArtifactSchema: () => IdentityArtifactSchema,
|
|
59
68
|
IngestFundingResultSchema: () => IngestFundingResultSchema,
|
|
60
69
|
IssueOACInputSchema: () => IssueOACInputSchema,
|
|
70
|
+
LedgerJournalEntryArtifactSchema: () => LedgerJournalEntryArtifactSchema,
|
|
61
71
|
ListPayoutDestinationsResultSchema: () => ListPayoutDestinationsResultSchema,
|
|
62
72
|
MEMBERSHIP_ROLES: () => MEMBERSHIP_ROLES,
|
|
63
73
|
MERCHANT_PAYOUT_STATUSES: () => MERCHANT_PAYOUT_STATUSES,
|
|
@@ -68,11 +78,14 @@ __export(index_exports, {
|
|
|
68
78
|
NGN_CURRENCY_CODE: () => NGN_CURRENCY_CODE,
|
|
69
79
|
NG_COUNTRY_CODE: () => NG_COUNTRY_CODE,
|
|
70
80
|
NQRParseError: () => NQRParseError,
|
|
81
|
+
NqrPaymentRequestArtifactSchema: () => NqrPaymentRequestArtifactSchema,
|
|
71
82
|
OACSchema: () => OACSchema,
|
|
72
83
|
OAC_DEFAULT_CUMULATIVE_KOBO: () => OAC_DEFAULT_CUMULATIVE_KOBO,
|
|
73
84
|
OAC_DEFAULT_PER_TX_KOBO: () => OAC_DEFAULT_PER_TX_KOBO,
|
|
74
85
|
OAC_DEFAULT_VALIDITY_MS: () => OAC_DEFAULT_VALIDITY_MS,
|
|
86
|
+
OfflineClaimArtifactSchema: () => OfflineClaimArtifactSchema,
|
|
75
87
|
OfflineHoldRecordSchema: () => OfflineHoldRecordSchema,
|
|
88
|
+
OfflinePaymentAuthorizationArtifactSchema: () => OfflinePaymentAuthorizationArtifactSchema,
|
|
76
89
|
OfflinePaymentAuthorizationSchema: () => OfflinePaymentAuthorizationSchema,
|
|
77
90
|
OfflinePaymentRequestSchema: () => OfflinePaymentRequestSchema,
|
|
78
91
|
OfflineStateResultSchema: () => OfflineStateResultSchema,
|
|
@@ -91,10 +104,12 @@ __export(index_exports, {
|
|
|
91
104
|
PartnerFundingEventInputSchema: () => PartnerFundingEventInputSchema,
|
|
92
105
|
PartnerFundingSchema: () => PartnerFundingSchema,
|
|
93
106
|
PartnerProfileSchema: () => PartnerProfileSchema,
|
|
107
|
+
PassArtifactSchema: () => PassArtifactSchema,
|
|
94
108
|
PassMetadataSchema: () => PassMetadataSchema,
|
|
95
109
|
PassSchema: () => PassSchema,
|
|
96
110
|
PayCollectionInputSchema: () => PayCollectionInputSchema,
|
|
97
111
|
PaymentClaimSchema: () => PaymentClaimSchema,
|
|
112
|
+
PaymentIntentArtifactSchema: () => PaymentIntentArtifactSchema,
|
|
98
113
|
PayoutDestinationSchema: () => PayoutDestinationSchema,
|
|
99
114
|
PayoutEventInputSchema: () => PayoutEventInputSchema,
|
|
100
115
|
ProviderEventInputSchema: () => ProviderEventInputSchema,
|
|
@@ -103,22 +118,29 @@ __export(index_exports, {
|
|
|
103
118
|
RECEIPT_CHANNELS: () => RECEIPT_CHANNELS,
|
|
104
119
|
RECEIPT_KINDS: () => RECEIPT_KINDS,
|
|
105
120
|
REPLAY_WINDOW_MS: () => REPLAY_WINDOW_MS,
|
|
121
|
+
ReceiptArtifactSchema: () => ReceiptArtifactSchema,
|
|
106
122
|
ReceiptPayloadSchema: () => ReceiptPayloadSchema,
|
|
107
123
|
ReceiptSchema: () => ReceiptSchema,
|
|
108
124
|
ReconciliationReportSchema: () => ReconciliationReportSchema,
|
|
109
125
|
RecordPayoutEventResultSchema: () => RecordPayoutEventResultSchema,
|
|
110
126
|
RedemptionSchema: () => RedemptionSchema,
|
|
111
127
|
RegisterDeviceKeyInputSchema: () => RegisterDeviceKeyInputSchema,
|
|
128
|
+
ReversalRecordArtifactSchema: () => ReversalRecordArtifactSchema,
|
|
112
129
|
RevokeDeviceKeyInputSchema: () => RevokeDeviceKeyInputSchema,
|
|
113
130
|
SETTLEMENT_SCHEDULES: () => SETTLEMENT_SCHEDULES,
|
|
114
131
|
SettleResponseSchema: () => SettleResponseSchema,
|
|
132
|
+
SettlementRecordArtifactSchema: () => SettlementRecordArtifactSchema,
|
|
115
133
|
SettlementSchema: () => SettlementSchema,
|
|
116
134
|
SignedConsumerOACSchema: () => SignedConsumerOACSchema,
|
|
135
|
+
StatementArtifactSchema: () => StatementArtifactSchema,
|
|
117
136
|
UpsertMerchantProfileInputSchema: () => UpsertMerchantProfileInputSchema,
|
|
118
137
|
UpsertPartnerProfileInputSchema: () => UpsertPartnerProfileInputSchema,
|
|
119
138
|
WITHDRAWAL_STATES: () => WITHDRAWAL_STATES,
|
|
120
139
|
WithdrawalSchema: () => WithdrawalSchema,
|
|
140
|
+
base64UrlDecode: () => base64UrlDecode,
|
|
141
|
+
base64UrlEncode: () => base64UrlEncode,
|
|
121
142
|
bodySha256Hex: () => bodySha256Hex,
|
|
143
|
+
buildArtifactBody: () => buildArtifactBody,
|
|
122
144
|
buildAuthorization: () => buildAuthorization,
|
|
123
145
|
buildOAC: () => buildOAC,
|
|
124
146
|
buildPass: () => buildPass,
|
|
@@ -134,21 +156,26 @@ __export(index_exports, {
|
|
|
134
156
|
crc16ccittHex: () => crc16ccittHex,
|
|
135
157
|
createAccountsClient: () => createAccountsClient,
|
|
136
158
|
createApiCredentialsAdminClient: () => createApiCredentialsAdminClient,
|
|
159
|
+
createArtifactUri: () => createArtifactUri,
|
|
137
160
|
createCollectionsClient: () => createCollectionsClient,
|
|
138
161
|
createConsumerCollectionsClient: () => createConsumerCollectionsClient,
|
|
139
162
|
createConsumerWithdrawalsClient: () => createConsumerWithdrawalsClient,
|
|
140
163
|
createFlurPartnerClient: () => createFlurPartnerClient,
|
|
141
164
|
createHmacFetch: () => createHmacFetch,
|
|
142
165
|
createMeOfflineClient: () => createMeOfflineClient,
|
|
166
|
+
createOfflinePaymentAuthorizationArtifactUri: () => createOfflinePaymentAuthorizationArtifactUri,
|
|
143
167
|
createOfflineSettlementsClient: () => createOfflineSettlementsClient,
|
|
144
168
|
createPartnerCollectionsClient: () => createPartnerCollectionsClient,
|
|
145
169
|
createPartnerFundingClient: () => createPartnerFundingClient,
|
|
146
170
|
createPartnerProfileAdminClient: () => createPartnerProfileAdminClient,
|
|
147
171
|
createPassesClient: () => createPassesClient,
|
|
172
|
+
createReceiptArtifactUri: () => createReceiptArtifactUri,
|
|
148
173
|
createReceiptsClient: () => createReceiptsClient,
|
|
174
|
+
decodeArtifactUri: () => decodeArtifactUri,
|
|
149
175
|
decodeAuthorizationQR: () => decodeAuthorizationQR,
|
|
150
176
|
decodeBase45: () => decodeBase45,
|
|
151
177
|
decodePaymentRequestQR: () => decodePaymentRequestQR,
|
|
178
|
+
encodeArtifactUri: () => encodeArtifactUri,
|
|
152
179
|
encodeAuthorizationQR: () => encodeAuthorizationQR,
|
|
153
180
|
encodeBase45: () => encodeBase45,
|
|
154
181
|
encodeNQR: () => encodeNQR,
|
|
@@ -158,6 +185,8 @@ __export(index_exports, {
|
|
|
158
185
|
generateKeyPair: () => generateKeyPair,
|
|
159
186
|
generateStaticQR: () => generateStaticQR,
|
|
160
187
|
init: () => init,
|
|
188
|
+
isHardenedArtifactType: () => isHardenedArtifactType,
|
|
189
|
+
isKnownArtifactType: () => isKnownArtifactType,
|
|
161
190
|
isPassWithinValidity: () => isPassWithinValidity,
|
|
162
191
|
moneyMinorToNumber: () => moneyMinorToNumber,
|
|
163
192
|
normalizeE164: () => normalizeE164,
|
|
@@ -168,6 +197,7 @@ __export(index_exports, {
|
|
|
168
197
|
readTLV: () => readTLV,
|
|
169
198
|
routingHint: () => routingHint,
|
|
170
199
|
sign: () => sign,
|
|
200
|
+
signArtifact: () => signArtifact,
|
|
171
201
|
signAuthorization: () => signAuthorization,
|
|
172
202
|
signCanonical: () => signCanonical,
|
|
173
203
|
signOAC: () => signOAC,
|
|
@@ -178,6 +208,8 @@ __export(index_exports, {
|
|
|
178
208
|
signRedemption: () => signRedemption,
|
|
179
209
|
signRequestHMAC: () => signRequestHMAC,
|
|
180
210
|
verify: () => verify,
|
|
211
|
+
verifyArtifactSignature: () => verifyArtifactSignature,
|
|
212
|
+
verifyArtifactUri: () => verifyArtifactUri,
|
|
181
213
|
verifyAuthorization: () => verifyAuthorization,
|
|
182
214
|
verifyCanonical: () => verifyCanonical,
|
|
183
215
|
verifyOAC: () => verifyOAC,
|
|
@@ -3674,14 +3706,420 @@ function createPartnerProfileAdminClient(opts) {
|
|
|
3674
3706
|
}
|
|
3675
3707
|
};
|
|
3676
3708
|
}
|
|
3709
|
+
|
|
3710
|
+
// src/artifacts/envelope.ts
|
|
3711
|
+
var import_zod15 = require("zod");
|
|
3712
|
+
var FLUR_ARTIFACT_URI_SCHEME = "flur";
|
|
3713
|
+
var FLUR_ARTIFACT_VERSION = 1;
|
|
3714
|
+
var FLUR_ARTIFACT_URI_PREFIX = `${FLUR_ARTIFACT_URI_SCHEME}://v${FLUR_ARTIFACT_VERSION}/`;
|
|
3715
|
+
var ArtifactTypeRe = /^[a-z][a-z0-9_]{1,63}$/;
|
|
3716
|
+
var ArtifactHeaderSchema = import_zod15.z.object({
|
|
3717
|
+
v: import_zod15.z.literal(FLUR_ARTIFACT_VERSION),
|
|
3718
|
+
t: import_zod15.z.string().regex(ArtifactTypeRe, "invalid artifact type"),
|
|
3719
|
+
iss: import_zod15.z.string().min(1).max(128),
|
|
3720
|
+
kid: import_zod15.z.string().min(1).max(128),
|
|
3721
|
+
iat: import_zod15.z.number().int().nonnegative(),
|
|
3722
|
+
exp: import_zod15.z.number().int().positive().optional(),
|
|
3723
|
+
nonce: import_zod15.z.string().min(8).max(64).regex(/^[A-Za-z0-9_-]+$/, "nonce must be url-safe")
|
|
3724
|
+
});
|
|
3725
|
+
var FlurArtifactError = class extends Error {
|
|
3726
|
+
constructor(message, code) {
|
|
3727
|
+
super(message);
|
|
3728
|
+
this.code = code;
|
|
3729
|
+
this.name = "FlurArtifactError";
|
|
3730
|
+
}
|
|
3731
|
+
code;
|
|
3732
|
+
};
|
|
3733
|
+
function base64UrlEncode(bytes) {
|
|
3734
|
+
let bin = "";
|
|
3735
|
+
for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
|
|
3736
|
+
const b64 = typeof btoa === "function" ? btoa(bin) : Buffer.from(bytes).toString("base64");
|
|
3737
|
+
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
3738
|
+
}
|
|
3739
|
+
function base64UrlDecode(s) {
|
|
3740
|
+
const pad = s.length % 4 === 0 ? "" : "=".repeat(4 - s.length % 4);
|
|
3741
|
+
const b64 = s.replace(/-/g, "+").replace(/_/g, "/") + pad;
|
|
3742
|
+
if (typeof atob === "function") {
|
|
3743
|
+
const bin = atob(b64);
|
|
3744
|
+
const out = new Uint8Array(bin.length);
|
|
3745
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
3746
|
+
return out;
|
|
3747
|
+
}
|
|
3748
|
+
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
3749
|
+
}
|
|
3750
|
+
function buildArtifactBody(input) {
|
|
3751
|
+
if (!ArtifactTypeRe.test(input.type)) {
|
|
3752
|
+
throw new FlurArtifactError(
|
|
3753
|
+
`Invalid artifact type: ${input.type}`,
|
|
3754
|
+
"INVALID_TYPE"
|
|
3755
|
+
);
|
|
3756
|
+
}
|
|
3757
|
+
const iat = input.issuedAtSeconds ?? Math.floor(Date.now() / 1e3);
|
|
3758
|
+
const header = {
|
|
3759
|
+
v: FLUR_ARTIFACT_VERSION,
|
|
3760
|
+
t: input.type,
|
|
3761
|
+
iss: input.issuer,
|
|
3762
|
+
kid: input.keyId,
|
|
3763
|
+
iat,
|
|
3764
|
+
...input.expiresAtSeconds !== void 0 ? { exp: input.expiresAtSeconds } : {},
|
|
3765
|
+
nonce: input.nonce
|
|
3766
|
+
};
|
|
3767
|
+
ArtifactHeaderSchema.parse(header);
|
|
3768
|
+
return { ...header, data: input.data };
|
|
3769
|
+
}
|
|
3770
|
+
function signArtifact(body, privateKey) {
|
|
3771
|
+
const sig = bytesToHex(sign(canonicalJSONBytes(body), privateKey));
|
|
3772
|
+
return { body, sig };
|
|
3773
|
+
}
|
|
3774
|
+
function encodeArtifactUri(signed) {
|
|
3775
|
+
const bodyBytes = canonicalJSONBytes(signed.body);
|
|
3776
|
+
const bodyB64 = base64UrlEncode(bodyBytes);
|
|
3777
|
+
const sigB64 = base64UrlEncode(hexToBytes(signed.sig));
|
|
3778
|
+
return `${FLUR_ARTIFACT_URI_PREFIX}${signed.body.t}/${bodyB64}.${sigB64}`;
|
|
3779
|
+
}
|
|
3780
|
+
function decodeArtifactUri(uri) {
|
|
3781
|
+
if (!uri.startsWith(FLUR_ARTIFACT_URI_PREFIX)) {
|
|
3782
|
+
throw new FlurArtifactError(
|
|
3783
|
+
`URI does not start with ${FLUR_ARTIFACT_URI_PREFIX}`,
|
|
3784
|
+
"INVALID_URI"
|
|
3785
|
+
);
|
|
3786
|
+
}
|
|
3787
|
+
const rest = uri.slice(FLUR_ARTIFACT_URI_PREFIX.length);
|
|
3788
|
+
const slash = rest.indexOf("/");
|
|
3789
|
+
if (slash <= 0) {
|
|
3790
|
+
throw new FlurArtifactError("Missing artifact type segment", "INVALID_URI");
|
|
3791
|
+
}
|
|
3792
|
+
const type = rest.slice(0, slash);
|
|
3793
|
+
const payload = rest.slice(slash + 1);
|
|
3794
|
+
const dot = payload.indexOf(".");
|
|
3795
|
+
if (dot <= 0 || dot === payload.length - 1) {
|
|
3796
|
+
throw new FlurArtifactError(
|
|
3797
|
+
"Missing body/signature separator",
|
|
3798
|
+
"INVALID_URI"
|
|
3799
|
+
);
|
|
3800
|
+
}
|
|
3801
|
+
if (!ArtifactTypeRe.test(type)) {
|
|
3802
|
+
throw new FlurArtifactError(
|
|
3803
|
+
`Invalid artifact type: ${type}`,
|
|
3804
|
+
"INVALID_TYPE"
|
|
3805
|
+
);
|
|
3806
|
+
}
|
|
3807
|
+
const bodyBytes = base64UrlDecode(payload.slice(0, dot));
|
|
3808
|
+
const sigBytes = base64UrlDecode(payload.slice(dot + 1));
|
|
3809
|
+
if (sigBytes.length !== 64) {
|
|
3810
|
+
throw new FlurArtifactError(
|
|
3811
|
+
`Signature must be 64 bytes, got ${sigBytes.length}`,
|
|
3812
|
+
"INVALID_SIGNATURE"
|
|
3813
|
+
);
|
|
3814
|
+
}
|
|
3815
|
+
let bodyJson;
|
|
3816
|
+
try {
|
|
3817
|
+
bodyJson = JSON.parse(new TextDecoder().decode(bodyBytes));
|
|
3818
|
+
} catch {
|
|
3819
|
+
throw new FlurArtifactError("Body is not valid JSON", "INVALID_BODY");
|
|
3820
|
+
}
|
|
3821
|
+
const headerOnly = ArtifactHeaderSchema.safeParse(bodyJson);
|
|
3822
|
+
if (!headerOnly.success) {
|
|
3823
|
+
throw new FlurArtifactError(
|
|
3824
|
+
`Body header invalid: ${headerOnly.error.message}`,
|
|
3825
|
+
"INVALID_BODY"
|
|
3826
|
+
);
|
|
3827
|
+
}
|
|
3828
|
+
if (headerOnly.data.t !== type) {
|
|
3829
|
+
throw new FlurArtifactError(
|
|
3830
|
+
`URI type ${type} does not match body type ${headerOnly.data.t}`,
|
|
3831
|
+
"TYPE_MISMATCH"
|
|
3832
|
+
);
|
|
3833
|
+
}
|
|
3834
|
+
return {
|
|
3835
|
+
type,
|
|
3836
|
+
bodyBytes,
|
|
3837
|
+
body: bodyJson,
|
|
3838
|
+
sig: bytesToHex(sigBytes)
|
|
3839
|
+
};
|
|
3840
|
+
}
|
|
3841
|
+
function verifyArtifactSignature(decoded, publicKey, options = {}) {
|
|
3842
|
+
if (options.enforceExpiry !== false && decoded.body.exp !== void 0) {
|
|
3843
|
+
const now = options.nowSeconds ?? Math.floor(Date.now() / 1e3);
|
|
3844
|
+
if (decoded.body.exp < now) {
|
|
3845
|
+
throw new FlurArtifactError("Artifact has expired", "EXPIRED");
|
|
3846
|
+
}
|
|
3847
|
+
}
|
|
3848
|
+
return verify(decoded.bodyBytes, hexToBytes(decoded.sig), publicKey);
|
|
3849
|
+
}
|
|
3850
|
+
|
|
3851
|
+
// src/artifacts/types.ts
|
|
3852
|
+
var import_zod16 = require("zod");
|
|
3853
|
+
var ARTIFACT_TYPES = {
|
|
3854
|
+
OFFLINE_PAYMENT_AUTHORIZATION: "offline_payment_authorization",
|
|
3855
|
+
RECEIPT: "receipt",
|
|
3856
|
+
// --- stubs, schemas to be hardened in follow-ups ---
|
|
3857
|
+
NQR_PAYMENT_REQUEST: "nqr_payment_request",
|
|
3858
|
+
PAYMENT_INTENT: "payment_intent",
|
|
3859
|
+
OFFLINE_CLAIM: "offline_claim",
|
|
3860
|
+
SETTLEMENT_RECORD: "settlement_record",
|
|
3861
|
+
REVERSAL_RECORD: "reversal_record",
|
|
3862
|
+
LEDGER_JOURNAL_ENTRY: "ledger_journal_entry",
|
|
3863
|
+
STATEMENT: "statement",
|
|
3864
|
+
PASS: "pass",
|
|
3865
|
+
IDENTITY: "identity"
|
|
3866
|
+
};
|
|
3867
|
+
var HexString4 = (length) => import_zod16.z.string().regex(
|
|
3868
|
+
new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
|
|
3869
|
+
`expected ${length}-byte hex string`
|
|
3870
|
+
);
|
|
3871
|
+
var OfflinePaymentAuthorizationArtifactSchema = import_zod16.z.object({
|
|
3872
|
+
authorization: OfflinePaymentAuthorizationSchema
|
|
3873
|
+
});
|
|
3874
|
+
var ReceiptArtifactSchema = import_zod16.z.object({
|
|
3875
|
+
receiptId: import_zod16.z.string().min(1).max(64),
|
|
3876
|
+
paymentReference: import_zod16.z.string().min(1).max(64),
|
|
3877
|
+
payerUserId: import_zod16.z.string().min(1).max(64).optional(),
|
|
3878
|
+
payeeUserId: import_zod16.z.string().min(1).max(64),
|
|
3879
|
+
amountKobo: import_zod16.z.number().int().positive(),
|
|
3880
|
+
currency: import_zod16.z.literal("NGN"),
|
|
3881
|
+
channel: import_zod16.z.enum(["online", "offline_reconciled", "pay_link", "nqr"]),
|
|
3882
|
+
settledAtMs: import_zod16.z.number().int().positive(),
|
|
3883
|
+
ledgerTxnId: import_zod16.z.string().min(1).max(64).optional(),
|
|
3884
|
+
memo: import_zod16.z.string().max(140).optional(),
|
|
3885
|
+
hashChainPrev: HexString4(32).optional()
|
|
3886
|
+
});
|
|
3887
|
+
var ShortId = import_zod16.z.string().min(1).max(64);
|
|
3888
|
+
var PositiveInt = import_zod16.z.number().int().positive();
|
|
3889
|
+
var NonNegativeInt = import_zod16.z.number().int().nonnegative();
|
|
3890
|
+
var Currency2 = import_zod16.z.literal("NGN");
|
|
3891
|
+
var Memo = import_zod16.z.string().max(140);
|
|
3892
|
+
var NqrPaymentRequestArtifactSchema = import_zod16.z.object({
|
|
3893
|
+
requestId: ShortId,
|
|
3894
|
+
payeeUserId: ShortId,
|
|
3895
|
+
amountKobo: PositiveInt.optional(),
|
|
3896
|
+
currency: Currency2,
|
|
3897
|
+
memo: Memo.optional(),
|
|
3898
|
+
expiresAtMs: PositiveInt.optional()
|
|
3899
|
+
});
|
|
3900
|
+
var PaymentIntentArtifactSchema = import_zod16.z.object({
|
|
3901
|
+
intentId: ShortId,
|
|
3902
|
+
payerUserId: ShortId,
|
|
3903
|
+
payeeUserId: ShortId,
|
|
3904
|
+
amountKobo: PositiveInt,
|
|
3905
|
+
currency: Currency2,
|
|
3906
|
+
idempotencyKey: ShortId,
|
|
3907
|
+
createdAtMs: PositiveInt
|
|
3908
|
+
});
|
|
3909
|
+
var OfflineClaimArtifactSchema = import_zod16.z.object({
|
|
3910
|
+
claimId: ShortId,
|
|
3911
|
+
authorizationId: ShortId,
|
|
3912
|
+
payeeUserId: ShortId,
|
|
3913
|
+
claimedAmountKobo: PositiveInt,
|
|
3914
|
+
currency: Currency2,
|
|
3915
|
+
claimedAtMs: PositiveInt,
|
|
3916
|
+
paymentReference: ShortId.optional()
|
|
3917
|
+
});
|
|
3918
|
+
var SettlementRecordArtifactSchema = import_zod16.z.object({
|
|
3919
|
+
settlementId: ShortId,
|
|
3920
|
+
ledgerTxnId: ShortId,
|
|
3921
|
+
sourceRefType: import_zod16.z.enum([
|
|
3922
|
+
"offline_authorization",
|
|
3923
|
+
"offline_claim",
|
|
3924
|
+
"transfer",
|
|
3925
|
+
"pay_link"
|
|
3926
|
+
]),
|
|
3927
|
+
sourceRefId: ShortId,
|
|
3928
|
+
amountKobo: PositiveInt,
|
|
3929
|
+
currency: Currency2,
|
|
3930
|
+
settledAtMs: PositiveInt
|
|
3931
|
+
});
|
|
3932
|
+
var ReversalRecordArtifactSchema = import_zod16.z.object({
|
|
3933
|
+
reversalId: ShortId,
|
|
3934
|
+
originalTxnId: ShortId,
|
|
3935
|
+
amountKobo: PositiveInt,
|
|
3936
|
+
currency: Currency2,
|
|
3937
|
+
reason: import_zod16.z.enum([
|
|
3938
|
+
"user_dispute",
|
|
3939
|
+
"fraud",
|
|
3940
|
+
"duplicate",
|
|
3941
|
+
"admin_correction",
|
|
3942
|
+
"other"
|
|
3943
|
+
]),
|
|
3944
|
+
reversedAtMs: PositiveInt,
|
|
3945
|
+
memo: Memo.optional()
|
|
3946
|
+
});
|
|
3947
|
+
var LedgerJournalEntryArtifactSchema = import_zod16.z.object({
|
|
3948
|
+
entryId: ShortId,
|
|
3949
|
+
journalId: ShortId,
|
|
3950
|
+
debitAccountId: ShortId,
|
|
3951
|
+
creditAccountId: ShortId,
|
|
3952
|
+
amountKobo: PositiveInt,
|
|
3953
|
+
currency: Currency2,
|
|
3954
|
+
postedAtMs: PositiveInt,
|
|
3955
|
+
refType: ShortId.optional(),
|
|
3956
|
+
refId: ShortId.optional()
|
|
3957
|
+
});
|
|
3958
|
+
var StatementArtifactSchema = import_zod16.z.object({
|
|
3959
|
+
statementId: ShortId,
|
|
3960
|
+
userId: ShortId,
|
|
3961
|
+
periodStartMs: PositiveInt,
|
|
3962
|
+
periodEndMs: PositiveInt,
|
|
3963
|
+
openingBalanceKobo: import_zod16.z.number().int(),
|
|
3964
|
+
closingBalanceKobo: import_zod16.z.number().int(),
|
|
3965
|
+
transactionCount: NonNegativeInt,
|
|
3966
|
+
currency: Currency2,
|
|
3967
|
+
hashChainPrev: HexString4(32).optional()
|
|
3968
|
+
}).refine((v) => v.periodEndMs > v.periodStartMs, {
|
|
3969
|
+
message: "periodEndMs must be greater than periodStartMs",
|
|
3970
|
+
path: ["periodEndMs"]
|
|
3971
|
+
});
|
|
3972
|
+
var PassArtifactSchema = import_zod16.z.object({
|
|
3973
|
+
passId: ShortId,
|
|
3974
|
+
holderId: ShortId,
|
|
3975
|
+
category: import_zod16.z.enum(["membership", "ticket", "loyalty", "access", "voucher"]),
|
|
3976
|
+
title: import_zod16.z.string().min(1).max(120),
|
|
3977
|
+
validFromMs: PositiveInt,
|
|
3978
|
+
validUntilMs: PositiveInt.optional(),
|
|
3979
|
+
metadata: import_zod16.z.record(
|
|
3980
|
+
import_zod16.z.string().min(1).max(64),
|
|
3981
|
+
import_zod16.z.union([import_zod16.z.string().max(280), import_zod16.z.number(), import_zod16.z.boolean()])
|
|
3982
|
+
).optional()
|
|
3983
|
+
}).refine(
|
|
3984
|
+
(v) => v.validUntilMs === void 0 || v.validUntilMs > v.validFromMs,
|
|
3985
|
+
{
|
|
3986
|
+
message: "validUntilMs must be greater than validFromMs",
|
|
3987
|
+
path: ["validUntilMs"]
|
|
3988
|
+
}
|
|
3989
|
+
);
|
|
3990
|
+
var IdentityArtifactSchema = import_zod16.z.object({
|
|
3991
|
+
attestationId: ShortId,
|
|
3992
|
+
subjectId: ShortId,
|
|
3993
|
+
claimType: import_zod16.z.enum([
|
|
3994
|
+
"phone_verified",
|
|
3995
|
+
"email_verified",
|
|
3996
|
+
"bvn_verified",
|
|
3997
|
+
"kyc_tier",
|
|
3998
|
+
"age_band"
|
|
3999
|
+
]),
|
|
4000
|
+
claimValueHash: HexString4(32),
|
|
4001
|
+
attestedAtMs: PositiveInt
|
|
4002
|
+
});
|
|
4003
|
+
var ARTIFACT_BODY_SCHEMAS = {
|
|
4004
|
+
[ARTIFACT_TYPES.OFFLINE_PAYMENT_AUTHORIZATION]: OfflinePaymentAuthorizationArtifactSchema,
|
|
4005
|
+
[ARTIFACT_TYPES.RECEIPT]: ReceiptArtifactSchema,
|
|
4006
|
+
[ARTIFACT_TYPES.NQR_PAYMENT_REQUEST]: NqrPaymentRequestArtifactSchema,
|
|
4007
|
+
[ARTIFACT_TYPES.PAYMENT_INTENT]: PaymentIntentArtifactSchema,
|
|
4008
|
+
[ARTIFACT_TYPES.OFFLINE_CLAIM]: OfflineClaimArtifactSchema,
|
|
4009
|
+
[ARTIFACT_TYPES.SETTLEMENT_RECORD]: SettlementRecordArtifactSchema,
|
|
4010
|
+
[ARTIFACT_TYPES.REVERSAL_RECORD]: ReversalRecordArtifactSchema,
|
|
4011
|
+
[ARTIFACT_TYPES.LEDGER_JOURNAL_ENTRY]: LedgerJournalEntryArtifactSchema,
|
|
4012
|
+
[ARTIFACT_TYPES.STATEMENT]: StatementArtifactSchema,
|
|
4013
|
+
[ARTIFACT_TYPES.PASS]: PassArtifactSchema,
|
|
4014
|
+
[ARTIFACT_TYPES.IDENTITY]: IdentityArtifactSchema
|
|
4015
|
+
};
|
|
4016
|
+
var HARDENED_ARTIFACT_TYPES = /* @__PURE__ */ new Set([
|
|
4017
|
+
ARTIFACT_TYPES.OFFLINE_PAYMENT_AUTHORIZATION,
|
|
4018
|
+
ARTIFACT_TYPES.RECEIPT,
|
|
4019
|
+
ARTIFACT_TYPES.NQR_PAYMENT_REQUEST,
|
|
4020
|
+
ARTIFACT_TYPES.PAYMENT_INTENT,
|
|
4021
|
+
ARTIFACT_TYPES.OFFLINE_CLAIM,
|
|
4022
|
+
ARTIFACT_TYPES.SETTLEMENT_RECORD,
|
|
4023
|
+
ARTIFACT_TYPES.REVERSAL_RECORD,
|
|
4024
|
+
ARTIFACT_TYPES.LEDGER_JOURNAL_ENTRY,
|
|
4025
|
+
ARTIFACT_TYPES.STATEMENT,
|
|
4026
|
+
ARTIFACT_TYPES.PASS,
|
|
4027
|
+
ARTIFACT_TYPES.IDENTITY
|
|
4028
|
+
]);
|
|
4029
|
+
function isKnownArtifactType(t) {
|
|
4030
|
+
return Object.values(ARTIFACT_TYPES).includes(t);
|
|
4031
|
+
}
|
|
4032
|
+
function isHardenedArtifactType(t) {
|
|
4033
|
+
return HARDENED_ARTIFACT_TYPES.has(t);
|
|
4034
|
+
}
|
|
4035
|
+
|
|
4036
|
+
// src/artifacts/codec.ts
|
|
4037
|
+
function createArtifactUri(input) {
|
|
4038
|
+
if (!isKnownArtifactType(input.type)) {
|
|
4039
|
+
throw new FlurArtifactError(
|
|
4040
|
+
`Unknown artifact type: ${input.type}`,
|
|
4041
|
+
"INVALID_TYPE"
|
|
4042
|
+
);
|
|
4043
|
+
}
|
|
4044
|
+
if (!isHardenedArtifactType(input.type)) {
|
|
4045
|
+
throw new FlurArtifactError(
|
|
4046
|
+
`Artifact type ${input.type} is not yet hardened for emission`,
|
|
4047
|
+
"INVALID_TYPE"
|
|
4048
|
+
);
|
|
4049
|
+
}
|
|
4050
|
+
const schema = ARTIFACT_BODY_SCHEMAS[input.type];
|
|
4051
|
+
const parsedData = schema.parse(input.data);
|
|
4052
|
+
const body = buildArtifactBody({
|
|
4053
|
+
type: input.type,
|
|
4054
|
+
issuer: input.issuer,
|
|
4055
|
+
keyId: input.keyId,
|
|
4056
|
+
data: parsedData,
|
|
4057
|
+
nonce: input.nonce,
|
|
4058
|
+
issuedAtSeconds: input.issuedAtSeconds,
|
|
4059
|
+
expiresAtSeconds: input.expiresAtSeconds
|
|
4060
|
+
});
|
|
4061
|
+
const signed = signArtifact(body, input.privateKey);
|
|
4062
|
+
return { uri: encodeArtifactUri(signed), signed };
|
|
4063
|
+
}
|
|
4064
|
+
function verifyArtifactUri(uri, publicKey, options = {}) {
|
|
4065
|
+
const decoded = decodeArtifactUri(uri);
|
|
4066
|
+
if (!isKnownArtifactType(decoded.type)) {
|
|
4067
|
+
throw new FlurArtifactError(
|
|
4068
|
+
`Unknown artifact type: ${decoded.type}`,
|
|
4069
|
+
"INVALID_TYPE"
|
|
4070
|
+
);
|
|
4071
|
+
}
|
|
4072
|
+
if (!isHardenedArtifactType(decoded.type)) {
|
|
4073
|
+
throw new FlurArtifactError(
|
|
4074
|
+
`Artifact type ${decoded.type} is not yet hardened for verification`,
|
|
4075
|
+
"INVALID_TYPE"
|
|
4076
|
+
);
|
|
4077
|
+
}
|
|
4078
|
+
const schema = ARTIFACT_BODY_SCHEMAS[decoded.type];
|
|
4079
|
+
const dataParsed = schema.safeParse(decoded.body.data);
|
|
4080
|
+
if (!dataParsed.success) {
|
|
4081
|
+
throw new FlurArtifactError(
|
|
4082
|
+
`Artifact body invalid: ${dataParsed.error.message}`,
|
|
4083
|
+
"INVALID_BODY"
|
|
4084
|
+
);
|
|
4085
|
+
}
|
|
4086
|
+
const ok = verifyArtifactSignature(decoded, publicKey, options);
|
|
4087
|
+
if (!ok) {
|
|
4088
|
+
throw new FlurArtifactError(
|
|
4089
|
+
"Artifact signature verification failed",
|
|
4090
|
+
"INVALID_SIGNATURE"
|
|
4091
|
+
);
|
|
4092
|
+
}
|
|
4093
|
+
return {
|
|
4094
|
+
type: decoded.type,
|
|
4095
|
+
body: decoded.body,
|
|
4096
|
+
sig: decoded.sig,
|
|
4097
|
+
decoded
|
|
4098
|
+
};
|
|
4099
|
+
}
|
|
4100
|
+
function createReceiptArtifactUri(input) {
|
|
4101
|
+
return createArtifactUri({
|
|
4102
|
+
...input,
|
|
4103
|
+
type: ARTIFACT_TYPES.RECEIPT
|
|
4104
|
+
});
|
|
4105
|
+
}
|
|
4106
|
+
function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
4107
|
+
return createArtifactUri({
|
|
4108
|
+
...input,
|
|
4109
|
+
type: ARTIFACT_TYPES.OFFLINE_PAYMENT_AUTHORIZATION
|
|
4110
|
+
});
|
|
4111
|
+
}
|
|
3677
4112
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3678
4113
|
0 && (module.exports = {
|
|
3679
4114
|
ACCOUNT_STATUSES,
|
|
3680
4115
|
ACCOUNT_TYPES,
|
|
3681
4116
|
ADDITIONAL_DATA_SUBFIELD,
|
|
4117
|
+
ARTIFACT_BODY_SCHEMAS,
|
|
4118
|
+
ARTIFACT_TYPES,
|
|
3682
4119
|
AccountMembershipSchema,
|
|
3683
4120
|
AccountSchema,
|
|
3684
4121
|
ApiCredentialPublicSchema,
|
|
4122
|
+
ArtifactHeaderSchema,
|
|
3685
4123
|
COLLECTION_INTENT_STATUSES,
|
|
3686
4124
|
COLLECTION_PAYMENT_STATUSES,
|
|
3687
4125
|
CUSTODIAL_MODES,
|
|
@@ -3706,14 +4144,21 @@ function createPartnerProfileAdminClient(opts) {
|
|
|
3706
4144
|
EnableOfflineInputSchema,
|
|
3707
4145
|
EnableOfflineResultSchema,
|
|
3708
4146
|
FIELD,
|
|
4147
|
+
FLUR_ARTIFACT_URI_PREFIX,
|
|
4148
|
+
FLUR_ARTIFACT_URI_SCHEME,
|
|
4149
|
+
FLUR_ARTIFACT_VERSION,
|
|
3709
4150
|
FlurApiError,
|
|
4151
|
+
FlurArtifactError,
|
|
3710
4152
|
FlurCapExceededError,
|
|
3711
4153
|
FlurClient,
|
|
3712
4154
|
FlurError,
|
|
3713
4155
|
FlurExpiredError,
|
|
3714
4156
|
FlurReplayError,
|
|
4157
|
+
HARDENED_ARTIFACT_TYPES,
|
|
4158
|
+
IdentityArtifactSchema,
|
|
3715
4159
|
IngestFundingResultSchema,
|
|
3716
4160
|
IssueOACInputSchema,
|
|
4161
|
+
LedgerJournalEntryArtifactSchema,
|
|
3717
4162
|
ListPayoutDestinationsResultSchema,
|
|
3718
4163
|
MEMBERSHIP_ROLES,
|
|
3719
4164
|
MERCHANT_PAYOUT_STATUSES,
|
|
@@ -3724,11 +4169,14 @@ function createPartnerProfileAdminClient(opts) {
|
|
|
3724
4169
|
NGN_CURRENCY_CODE,
|
|
3725
4170
|
NG_COUNTRY_CODE,
|
|
3726
4171
|
NQRParseError,
|
|
4172
|
+
NqrPaymentRequestArtifactSchema,
|
|
3727
4173
|
OACSchema,
|
|
3728
4174
|
OAC_DEFAULT_CUMULATIVE_KOBO,
|
|
3729
4175
|
OAC_DEFAULT_PER_TX_KOBO,
|
|
3730
4176
|
OAC_DEFAULT_VALIDITY_MS,
|
|
4177
|
+
OfflineClaimArtifactSchema,
|
|
3731
4178
|
OfflineHoldRecordSchema,
|
|
4179
|
+
OfflinePaymentAuthorizationArtifactSchema,
|
|
3732
4180
|
OfflinePaymentAuthorizationSchema,
|
|
3733
4181
|
OfflinePaymentRequestSchema,
|
|
3734
4182
|
OfflineStateResultSchema,
|
|
@@ -3747,10 +4195,12 @@ function createPartnerProfileAdminClient(opts) {
|
|
|
3747
4195
|
PartnerFundingEventInputSchema,
|
|
3748
4196
|
PartnerFundingSchema,
|
|
3749
4197
|
PartnerProfileSchema,
|
|
4198
|
+
PassArtifactSchema,
|
|
3750
4199
|
PassMetadataSchema,
|
|
3751
4200
|
PassSchema,
|
|
3752
4201
|
PayCollectionInputSchema,
|
|
3753
4202
|
PaymentClaimSchema,
|
|
4203
|
+
PaymentIntentArtifactSchema,
|
|
3754
4204
|
PayoutDestinationSchema,
|
|
3755
4205
|
PayoutEventInputSchema,
|
|
3756
4206
|
ProviderEventInputSchema,
|
|
@@ -3759,22 +4209,29 @@ function createPartnerProfileAdminClient(opts) {
|
|
|
3759
4209
|
RECEIPT_CHANNELS,
|
|
3760
4210
|
RECEIPT_KINDS,
|
|
3761
4211
|
REPLAY_WINDOW_MS,
|
|
4212
|
+
ReceiptArtifactSchema,
|
|
3762
4213
|
ReceiptPayloadSchema,
|
|
3763
4214
|
ReceiptSchema,
|
|
3764
4215
|
ReconciliationReportSchema,
|
|
3765
4216
|
RecordPayoutEventResultSchema,
|
|
3766
4217
|
RedemptionSchema,
|
|
3767
4218
|
RegisterDeviceKeyInputSchema,
|
|
4219
|
+
ReversalRecordArtifactSchema,
|
|
3768
4220
|
RevokeDeviceKeyInputSchema,
|
|
3769
4221
|
SETTLEMENT_SCHEDULES,
|
|
3770
4222
|
SettleResponseSchema,
|
|
4223
|
+
SettlementRecordArtifactSchema,
|
|
3771
4224
|
SettlementSchema,
|
|
3772
4225
|
SignedConsumerOACSchema,
|
|
4226
|
+
StatementArtifactSchema,
|
|
3773
4227
|
UpsertMerchantProfileInputSchema,
|
|
3774
4228
|
UpsertPartnerProfileInputSchema,
|
|
3775
4229
|
WITHDRAWAL_STATES,
|
|
3776
4230
|
WithdrawalSchema,
|
|
4231
|
+
base64UrlDecode,
|
|
4232
|
+
base64UrlEncode,
|
|
3777
4233
|
bodySha256Hex,
|
|
4234
|
+
buildArtifactBody,
|
|
3778
4235
|
buildAuthorization,
|
|
3779
4236
|
buildOAC,
|
|
3780
4237
|
buildPass,
|
|
@@ -3790,21 +4247,26 @@ function createPartnerProfileAdminClient(opts) {
|
|
|
3790
4247
|
crc16ccittHex,
|
|
3791
4248
|
createAccountsClient,
|
|
3792
4249
|
createApiCredentialsAdminClient,
|
|
4250
|
+
createArtifactUri,
|
|
3793
4251
|
createCollectionsClient,
|
|
3794
4252
|
createConsumerCollectionsClient,
|
|
3795
4253
|
createConsumerWithdrawalsClient,
|
|
3796
4254
|
createFlurPartnerClient,
|
|
3797
4255
|
createHmacFetch,
|
|
3798
4256
|
createMeOfflineClient,
|
|
4257
|
+
createOfflinePaymentAuthorizationArtifactUri,
|
|
3799
4258
|
createOfflineSettlementsClient,
|
|
3800
4259
|
createPartnerCollectionsClient,
|
|
3801
4260
|
createPartnerFundingClient,
|
|
3802
4261
|
createPartnerProfileAdminClient,
|
|
3803
4262
|
createPassesClient,
|
|
4263
|
+
createReceiptArtifactUri,
|
|
3804
4264
|
createReceiptsClient,
|
|
4265
|
+
decodeArtifactUri,
|
|
3805
4266
|
decodeAuthorizationQR,
|
|
3806
4267
|
decodeBase45,
|
|
3807
4268
|
decodePaymentRequestQR,
|
|
4269
|
+
encodeArtifactUri,
|
|
3808
4270
|
encodeAuthorizationQR,
|
|
3809
4271
|
encodeBase45,
|
|
3810
4272
|
encodeNQR,
|
|
@@ -3814,6 +4276,8 @@ function createPartnerProfileAdminClient(opts) {
|
|
|
3814
4276
|
generateKeyPair,
|
|
3815
4277
|
generateStaticQR,
|
|
3816
4278
|
init,
|
|
4279
|
+
isHardenedArtifactType,
|
|
4280
|
+
isKnownArtifactType,
|
|
3817
4281
|
isPassWithinValidity,
|
|
3818
4282
|
moneyMinorToNumber,
|
|
3819
4283
|
normalizeE164,
|
|
@@ -3824,6 +4288,7 @@ function createPartnerProfileAdminClient(opts) {
|
|
|
3824
4288
|
readTLV,
|
|
3825
4289
|
routingHint,
|
|
3826
4290
|
sign,
|
|
4291
|
+
signArtifact,
|
|
3827
4292
|
signAuthorization,
|
|
3828
4293
|
signCanonical,
|
|
3829
4294
|
signOAC,
|
|
@@ -3834,6 +4299,8 @@ function createPartnerProfileAdminClient(opts) {
|
|
|
3834
4299
|
signRedemption,
|
|
3835
4300
|
signRequestHMAC,
|
|
3836
4301
|
verify,
|
|
4302
|
+
verifyArtifactSignature,
|
|
4303
|
+
verifyArtifactUri,
|
|
3837
4304
|
verifyAuthorization,
|
|
3838
4305
|
verifyCanonical,
|
|
3839
4306
|
verifyOAC,
|