@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 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,