@nokinc-flur/sdk 1.1.2 → 1.1.4
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 +455 -147
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +659 -110
- package/dist/index.d.ts +659 -110
- package/dist/index.js +441 -143
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,8 @@ __export(index_exports, {
|
|
|
29
29
|
AccountSchema: () => AccountSchema,
|
|
30
30
|
ApiCredentialPublicSchema: () => ApiCredentialPublicSchema,
|
|
31
31
|
ArtifactHeaderSchema: () => ArtifactHeaderSchema,
|
|
32
|
+
AttestationSecurityLevelSchema: () => AttestationSecurityLevelSchema,
|
|
33
|
+
CLAIM_DOMAIN_V2: () => CLAIM_DOMAIN_V2,
|
|
32
34
|
COLLECTION_INTENT_STATUSES: () => COLLECTION_INTENT_STATUSES,
|
|
33
35
|
COLLECTION_PAYMENT_STATUSES: () => COLLECTION_PAYMENT_STATUSES,
|
|
34
36
|
CUSTODIAL_MODES: () => CUSTODIAL_MODES,
|
|
@@ -47,6 +49,7 @@ __export(index_exports, {
|
|
|
47
49
|
CreatePayoutInputSchema: () => CreatePayoutInputSchema,
|
|
48
50
|
CreateWithdrawalInputSchema: () => CreateWithdrawalInputSchema,
|
|
49
51
|
CreateWithdrawalResultSchema: () => CreateWithdrawalResultSchema,
|
|
52
|
+
DeviceKeyAlgSchema: () => DeviceKeyAlgSchema,
|
|
50
53
|
DeviceKeyRecordSchema: () => DeviceKeyRecordSchema,
|
|
51
54
|
DisableOfflineInputSchema: () => DisableOfflineInputSchema,
|
|
52
55
|
DisableOfflineResultSchema: () => DisableOfflineResultSchema,
|
|
@@ -83,6 +86,7 @@ __export(index_exports, {
|
|
|
83
86
|
OAC_DEFAULT_CUMULATIVE_KOBO: () => OAC_DEFAULT_CUMULATIVE_KOBO,
|
|
84
87
|
OAC_DEFAULT_PER_TX_KOBO: () => OAC_DEFAULT_PER_TX_KOBO,
|
|
85
88
|
OAC_DEFAULT_VALIDITY_MS: () => OAC_DEFAULT_VALIDITY_MS,
|
|
89
|
+
OFFLINE_CLAIM_SMS_PREFIX: () => OFFLINE_CLAIM_SMS_PREFIX,
|
|
86
90
|
OfflineClaimArtifactSchema: () => OfflineClaimArtifactSchema,
|
|
87
91
|
OfflineHoldRecordSchema: () => OfflineHoldRecordSchema,
|
|
88
92
|
OfflinePaymentAuthorizationArtifactSchema: () => OfflinePaymentAuthorizationArtifactSchema,
|
|
@@ -91,6 +95,8 @@ __export(index_exports, {
|
|
|
91
95
|
OfflineStateResultSchema: () => OfflineStateResultSchema,
|
|
92
96
|
OfflineStatusResultSchema: () => OfflineStatusResultSchema,
|
|
93
97
|
OfflineTokenSchema: () => OfflineTokenSchema,
|
|
98
|
+
P256EnrollmentChallengeInputSchema: () => P256EnrollmentChallengeInputSchema,
|
|
99
|
+
P256EnrollmentChallengeResultSchema: () => P256EnrollmentChallengeResultSchema,
|
|
94
100
|
PARTNER_FUNDING_DIRECTIONS: () => PARTNER_FUNDING_DIRECTIONS,
|
|
95
101
|
PARTNER_FUNDING_STATUSES: () => PARTNER_FUNDING_STATUSES,
|
|
96
102
|
PARTNER_KINDS: () => PARTNER_KINDS,
|
|
@@ -114,6 +120,8 @@ __export(index_exports, {
|
|
|
114
120
|
PayoutEventInputSchema: () => PayoutEventInputSchema,
|
|
115
121
|
ProviderEventInputSchema: () => ProviderEventInputSchema,
|
|
116
122
|
ProviderEventRecordSchema: () => ProviderEventRecordSchema,
|
|
123
|
+
ProvisionOfflineAllowanceInputSchema: () => ProvisionOfflineAllowanceInputSchema,
|
|
124
|
+
ProvisionOfflineAllowanceResultSchema: () => ProvisionOfflineAllowanceResultSchema,
|
|
117
125
|
PublicCollectionIntentSchema: () => PublicCollectionIntentSchema,
|
|
118
126
|
RECEIPT_CHANNELS: () => RECEIPT_CHANNELS,
|
|
119
127
|
RECEIPT_KINDS: () => RECEIPT_KINDS,
|
|
@@ -125,6 +133,7 @@ __export(index_exports, {
|
|
|
125
133
|
RecordPayoutEventResultSchema: () => RecordPayoutEventResultSchema,
|
|
126
134
|
RedemptionSchema: () => RedemptionSchema,
|
|
127
135
|
RegisterDeviceKeyInputSchema: () => RegisterDeviceKeyInputSchema,
|
|
136
|
+
RegisterDeviceKeyP256InputSchema: () => RegisterDeviceKeyP256InputSchema,
|
|
128
137
|
ReversalRecordArtifactSchema: () => ReversalRecordArtifactSchema,
|
|
129
138
|
RevokeDeviceKeyInputSchema: () => RevokeDeviceKeyInputSchema,
|
|
130
139
|
SETTLEMENT_SCHEDULES: () => SETTLEMENT_SCHEDULES,
|
|
@@ -147,6 +156,8 @@ __export(index_exports, {
|
|
|
147
156
|
buildPaymentRequest: () => buildPaymentRequest,
|
|
148
157
|
buildReceipt: () => buildReceipt,
|
|
149
158
|
buildRedemption: () => buildRedemption,
|
|
159
|
+
canonicalClaimSigningBytes: () => canonicalClaimSigningBytes,
|
|
160
|
+
canonicalClaimSigningPayload: () => canonicalClaimSigningPayload,
|
|
150
161
|
canonicalJSONBytes: () => canonicalJSONBytes,
|
|
151
162
|
canonicalJSONStringify: () => canonicalJSONStringify,
|
|
152
163
|
canonicalRequestString: () => canonicalRequestString,
|
|
@@ -171,18 +182,21 @@ __export(index_exports, {
|
|
|
171
182
|
createPassesClient: () => createPassesClient,
|
|
172
183
|
createReceiptArtifactUri: () => createReceiptArtifactUri,
|
|
173
184
|
createReceiptsClient: () => createReceiptsClient,
|
|
185
|
+
createSoftwareP256Signer: () => createSoftwareP256Signer,
|
|
174
186
|
decodeArtifactUri: () => decodeArtifactUri,
|
|
175
187
|
decodeAuthorizationQR: () => decodeAuthorizationQR,
|
|
176
188
|
decodeBase45: () => decodeBase45,
|
|
189
|
+
decodeOfflineClaimSmsMessage: () => decodeOfflineClaimSmsMessage,
|
|
177
190
|
decodePaymentRequestQR: () => decodePaymentRequestQR,
|
|
178
191
|
encodeArtifactUri: () => encodeArtifactUri,
|
|
179
192
|
encodeAuthorizationQR: () => encodeAuthorizationQR,
|
|
180
193
|
encodeBase45: () => encodeBase45,
|
|
181
194
|
encodeNQR: () => encodeNQR,
|
|
195
|
+
encodeOfflineClaimSmsMessage: () => encodeOfflineClaimSmsMessage,
|
|
182
196
|
encodePaymentRequestQR: () => encodePaymentRequestQR,
|
|
197
|
+
extractOfflineClaimSmsToken: () => extractOfflineClaimSmsToken,
|
|
183
198
|
formatAmount: () => formatAmount,
|
|
184
199
|
generateDynamicQR: () => generateDynamicQR,
|
|
185
|
-
generateKeyPair: () => generateKeyPair,
|
|
186
200
|
generateStaticQR: () => generateStaticQR,
|
|
187
201
|
init: () => init,
|
|
188
202
|
isHardenedArtifactType: () => isHardenedArtifactType,
|
|
@@ -193,13 +207,10 @@ __export(index_exports, {
|
|
|
193
207
|
parseAmountInput: () => parseAmountInput,
|
|
194
208
|
parseNQR: () => parseNQR,
|
|
195
209
|
parseQR: () => parseQR,
|
|
196
|
-
publicKeyFromPrivate: () => publicKeyFromPrivate,
|
|
197
210
|
readTLV: () => readTLV,
|
|
198
211
|
routingHint: () => routingHint,
|
|
199
|
-
sign: () => sign,
|
|
200
212
|
signArtifact: () => signArtifact,
|
|
201
213
|
signAuthorization: () => signAuthorization,
|
|
202
|
-
signCanonical: () => signCanonical,
|
|
203
214
|
signOAC: () => signOAC,
|
|
204
215
|
signPartnerRequest: () => signPartnerRequest,
|
|
205
216
|
signPass: () => signPass,
|
|
@@ -207,11 +218,10 @@ __export(index_exports, {
|
|
|
207
218
|
signReceipt: () => signReceipt,
|
|
208
219
|
signRedemption: () => signRedemption,
|
|
209
220
|
signRequestHMAC: () => signRequestHMAC,
|
|
210
|
-
verify: () => verify,
|
|
211
221
|
verifyArtifactSignature: () => verifyArtifactSignature,
|
|
212
222
|
verifyArtifactUri: () => verifyArtifactUri,
|
|
213
223
|
verifyAuthorization: () => verifyAuthorization,
|
|
214
|
-
|
|
224
|
+
verifyClaimSignature: () => verifyClaimSignature,
|
|
215
225
|
verifyOAC: () => verifyOAC,
|
|
216
226
|
verifyPass: () => verifyPass,
|
|
217
227
|
verifyPaymentRequest: () => verifyPaymentRequest,
|
|
@@ -1787,64 +1797,113 @@ function constantTimeEqual(a, b) {
|
|
|
1787
1797
|
return diff === 0;
|
|
1788
1798
|
}
|
|
1789
1799
|
|
|
1790
|
-
// src/
|
|
1791
|
-
var
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1800
|
+
// src/offline/oac.ts
|
|
1801
|
+
var import_zod5 = require("zod");
|
|
1802
|
+
|
|
1803
|
+
// src/crypto/p256-issuer.ts
|
|
1804
|
+
var import_nist = require("@noble/curves/nist");
|
|
1805
|
+
function bytesToBase64(bytes) {
|
|
1806
|
+
if (typeof Buffer !== "undefined") {
|
|
1807
|
+
return Buffer.from(bytes).toString("base64");
|
|
1808
|
+
}
|
|
1809
|
+
let bin = "";
|
|
1810
|
+
for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
|
|
1811
|
+
return btoa(bin);
|
|
1796
1812
|
}
|
|
1797
|
-
function
|
|
1798
|
-
|
|
1813
|
+
function base64ToBytes(b64) {
|
|
1814
|
+
if (typeof Buffer !== "undefined") {
|
|
1815
|
+
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
1816
|
+
}
|
|
1817
|
+
const bin = atob(b64);
|
|
1818
|
+
const out = new Uint8Array(bin.length);
|
|
1819
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
1820
|
+
return out;
|
|
1821
|
+
}
|
|
1822
|
+
var P256_SPKI_HEADER = new Uint8Array([
|
|
1823
|
+
48,
|
|
1824
|
+
89,
|
|
1825
|
+
48,
|
|
1826
|
+
19,
|
|
1827
|
+
6,
|
|
1828
|
+
7,
|
|
1829
|
+
42,
|
|
1830
|
+
134,
|
|
1831
|
+
72,
|
|
1832
|
+
206,
|
|
1833
|
+
61,
|
|
1834
|
+
2,
|
|
1835
|
+
1,
|
|
1836
|
+
6,
|
|
1837
|
+
8,
|
|
1838
|
+
42,
|
|
1839
|
+
134,
|
|
1840
|
+
72,
|
|
1841
|
+
206,
|
|
1842
|
+
61,
|
|
1843
|
+
3,
|
|
1844
|
+
1,
|
|
1845
|
+
7,
|
|
1846
|
+
3,
|
|
1847
|
+
66,
|
|
1848
|
+
0
|
|
1849
|
+
]);
|
|
1850
|
+
function p256SpkiB64ToRaw(spkiB64) {
|
|
1851
|
+
const spki = base64ToBytes(spkiB64);
|
|
1852
|
+
if (spki.length !== P256_SPKI_HEADER.length + 65) {
|
|
1853
|
+
throw new Error("p256: invalid SPKI length");
|
|
1854
|
+
}
|
|
1855
|
+
for (let i = 0; i < P256_SPKI_HEADER.length; i++) {
|
|
1856
|
+
if (spki[i] !== P256_SPKI_HEADER[i]) {
|
|
1857
|
+
throw new Error("p256: invalid SPKI header");
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
return spki.slice(P256_SPKI_HEADER.length);
|
|
1799
1861
|
}
|
|
1800
|
-
function
|
|
1801
|
-
|
|
1862
|
+
function signIssuerP256(bytes, issuerPrivateKey) {
|
|
1863
|
+
const sig = import_nist.p256.sign(bytes, issuerPrivateKey, { prehash: true });
|
|
1864
|
+
return bytesToBase64(sig.toBytes("der"));
|
|
1802
1865
|
}
|
|
1803
|
-
function
|
|
1866
|
+
function verifyIssuerP256(bytes, signatureB64, issuerPublicKeySpkiB64) {
|
|
1804
1867
|
try {
|
|
1805
|
-
|
|
1868
|
+
const pubRaw = p256SpkiB64ToRaw(issuerPublicKeySpkiB64);
|
|
1869
|
+
const sigBytes = base64ToBytes(signatureB64);
|
|
1870
|
+
return import_nist.p256.verify(sigBytes, bytes, pubRaw, {
|
|
1871
|
+
prehash: true,
|
|
1872
|
+
format: "der"
|
|
1873
|
+
});
|
|
1806
1874
|
} catch {
|
|
1807
1875
|
return false;
|
|
1808
1876
|
}
|
|
1809
1877
|
}
|
|
1810
|
-
function signCanonical(value, privateKey) {
|
|
1811
|
-
return sign(canonicalJSONBytes(value), privateKey);
|
|
1812
|
-
}
|
|
1813
|
-
function verifyCanonical(value, signature, publicKey) {
|
|
1814
|
-
return verify(canonicalJSONBytes(value), signature, publicKey);
|
|
1815
|
-
}
|
|
1816
1878
|
|
|
1817
1879
|
// src/offline/oac.ts
|
|
1818
|
-
var import_zod5 = require("zod");
|
|
1819
1880
|
var OAC_DEFAULT_PER_TX_KOBO = 5e5;
|
|
1820
1881
|
var OAC_DEFAULT_CUMULATIVE_KOBO = 2e6;
|
|
1821
1882
|
var OAC_DEFAULT_VALIDITY_MS = 24 * 60 * 60 * 1e3;
|
|
1822
|
-
var
|
|
1823
|
-
new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
|
|
1824
|
-
`expected ${length}-byte hex string`
|
|
1825
|
-
);
|
|
1883
|
+
var Base64Std = import_zod5.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (standard) string");
|
|
1826
1884
|
var OACSchema = import_zod5.z.object({
|
|
1827
1885
|
userId: import_zod5.z.string().min(1),
|
|
1828
1886
|
deviceId: import_zod5.z.string().min(1),
|
|
1829
|
-
|
|
1887
|
+
/** SubjectPublicKeyInfo DER, base64 (P-256). */
|
|
1888
|
+
devicePublicKey: Base64Std,
|
|
1830
1889
|
perTxCapKobo: import_zod5.z.number().int().nonnegative(),
|
|
1831
1890
|
cumulativeCapKobo: import_zod5.z.number().int().nonnegative(),
|
|
1832
1891
|
validFromMs: import_zod5.z.number().int().nonnegative(),
|
|
1833
1892
|
validUntilMs: import_zod5.z.number().int().positive(),
|
|
1834
1893
|
counterSeed: import_zod5.z.number().int().nonnegative(),
|
|
1835
1894
|
nonce: import_zod5.z.string().min(1),
|
|
1836
|
-
|
|
1895
|
+
/** ASN.1 DER ECDSA(SHA-256) signature, base64. */
|
|
1896
|
+
issuerSig: Base64Std
|
|
1837
1897
|
}).refine((v) => v.validUntilMs > v.validFromMs, {
|
|
1838
1898
|
message: "validUntilMs must be greater than validFromMs"
|
|
1839
1899
|
}).refine((v) => v.perTxCapKobo <= v.cumulativeCapKobo, {
|
|
1840
1900
|
message: "perTxCapKobo must not exceed cumulativeCapKobo"
|
|
1841
1901
|
});
|
|
1842
1902
|
function buildOAC(input) {
|
|
1843
|
-
const devicePublicKey = typeof input.devicePublicKey === "string" ? input.devicePublicKey : bytesToHex(input.devicePublicKey);
|
|
1844
1903
|
return {
|
|
1845
1904
|
userId: input.userId,
|
|
1846
1905
|
deviceId: input.deviceId,
|
|
1847
|
-
devicePublicKey,
|
|
1906
|
+
devicePublicKey: input.devicePublicKey,
|
|
1848
1907
|
perTxCapKobo: input.perTxCapKobo ?? OAC_DEFAULT_PER_TX_KOBO,
|
|
1849
1908
|
cumulativeCapKobo: input.cumulativeCapKobo ?? OAC_DEFAULT_CUMULATIVE_KOBO,
|
|
1850
1909
|
validFromMs: input.validFromMs,
|
|
@@ -1854,36 +1913,25 @@ function buildOAC(input) {
|
|
|
1854
1913
|
};
|
|
1855
1914
|
}
|
|
1856
1915
|
function signOAC(unsigned, issuerPrivateKey) {
|
|
1857
|
-
const issuerSig =
|
|
1858
|
-
|
|
1916
|
+
const issuerSig = signIssuerP256(
|
|
1917
|
+
canonicalJSONBytes(unsigned),
|
|
1918
|
+
issuerPrivateKey
|
|
1859
1919
|
);
|
|
1860
1920
|
return { ...unsigned, issuerSig };
|
|
1861
1921
|
}
|
|
1862
|
-
function verifyOAC(oac,
|
|
1922
|
+
function verifyOAC(oac, issuerPublicKeySpkiB64) {
|
|
1863
1923
|
try {
|
|
1864
1924
|
const parsed = OACSchema.parse(oac);
|
|
1865
1925
|
const { issuerSig, ...unsigned } = parsed;
|
|
1866
|
-
return
|
|
1926
|
+
return verifyIssuerP256(
|
|
1867
1927
|
canonicalJSONBytes(unsigned),
|
|
1868
|
-
|
|
1869
|
-
|
|
1928
|
+
issuerSig,
|
|
1929
|
+
issuerPublicKeySpkiB64
|
|
1870
1930
|
);
|
|
1871
1931
|
} catch {
|
|
1872
1932
|
return false;
|
|
1873
1933
|
}
|
|
1874
1934
|
}
|
|
1875
|
-
function bytesToHex(b) {
|
|
1876
|
-
let s = "";
|
|
1877
|
-
for (let i = 0; i < b.length; i++) s += b[i].toString(16).padStart(2, "0");
|
|
1878
|
-
return s;
|
|
1879
|
-
}
|
|
1880
|
-
function hexToBytes(s) {
|
|
1881
|
-
if (s.length % 2 !== 0) throw new Error("hex: odd length");
|
|
1882
|
-
const out = new Uint8Array(s.length / 2);
|
|
1883
|
-
for (let i = 0; i < out.length; i++)
|
|
1884
|
-
out[i] = parseInt(s.slice(i * 2, i * 2 + 2), 16);
|
|
1885
|
-
return out;
|
|
1886
|
-
}
|
|
1887
1935
|
|
|
1888
1936
|
// src/offline/codec.ts
|
|
1889
1937
|
var ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
|
|
@@ -1940,19 +1988,19 @@ function decodeBase45(s) {
|
|
|
1940
1988
|
|
|
1941
1989
|
// src/offline/messages.ts
|
|
1942
1990
|
var import_zod6 = require("zod");
|
|
1943
|
-
var
|
|
1991
|
+
var Base64Sig = import_zod6.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (standard) signature");
|
|
1944
1992
|
var OfflinePaymentRequestSchema = import_zod6.z.object({
|
|
1945
1993
|
reference: import_zod6.z.string().min(1),
|
|
1946
1994
|
amountKobo: import_zod6.z.number().int().positive(),
|
|
1947
1995
|
merchantOAC: OACSchema,
|
|
1948
1996
|
expiresAtMs: import_zod6.z.number().int().positive(),
|
|
1949
|
-
merchantSig:
|
|
1997
|
+
merchantSig: Base64Sig
|
|
1950
1998
|
});
|
|
1951
1999
|
var OfflinePaymentAuthorizationSchema = import_zod6.z.object({
|
|
1952
2000
|
request: OfflinePaymentRequestSchema,
|
|
1953
2001
|
payerOAC: OACSchema,
|
|
1954
2002
|
payerCounter: import_zod6.z.number().int().positive(),
|
|
1955
|
-
payerSig:
|
|
2003
|
+
payerSig: Base64Sig
|
|
1956
2004
|
});
|
|
1957
2005
|
function buildPaymentRequest(input) {
|
|
1958
2006
|
if (!Number.isInteger(input.amountKobo) || input.amountKobo <= 0) {
|
|
@@ -1969,27 +2017,28 @@ function buildPaymentRequest(input) {
|
|
|
1969
2017
|
};
|
|
1970
2018
|
}
|
|
1971
2019
|
function signPaymentRequest(unsigned, merchantDevicePrivateKey) {
|
|
1972
|
-
const merchantSig =
|
|
1973
|
-
|
|
2020
|
+
const merchantSig = signIssuerP256(
|
|
2021
|
+
canonicalJSONBytes(unsigned),
|
|
2022
|
+
merchantDevicePrivateKey
|
|
1974
2023
|
);
|
|
1975
2024
|
return { ...unsigned, merchantSig };
|
|
1976
2025
|
}
|
|
1977
|
-
function verifyPaymentRequest(req,
|
|
2026
|
+
function verifyPaymentRequest(req, issuerPublicKeySpkiB64) {
|
|
1978
2027
|
try {
|
|
1979
2028
|
const parsed = OfflinePaymentRequestSchema.parse(req);
|
|
1980
2029
|
const { issuerSig: merchantOacSig, ...merchantOacUnsigned } = parsed.merchantOAC;
|
|
1981
|
-
if (!
|
|
2030
|
+
if (!verifyIssuerP256(
|
|
1982
2031
|
canonicalJSONBytes(merchantOacUnsigned),
|
|
1983
|
-
|
|
1984
|
-
|
|
2032
|
+
merchantOacSig,
|
|
2033
|
+
issuerPublicKeySpkiB64
|
|
1985
2034
|
)) {
|
|
1986
2035
|
return false;
|
|
1987
2036
|
}
|
|
1988
2037
|
const { merchantSig, ...unsigned } = parsed;
|
|
1989
|
-
return
|
|
2038
|
+
return verifyIssuerP256(
|
|
1990
2039
|
canonicalJSONBytes(unsigned),
|
|
1991
|
-
|
|
1992
|
-
|
|
2040
|
+
merchantSig,
|
|
2041
|
+
parsed.merchantOAC.devicePublicKey
|
|
1993
2042
|
);
|
|
1994
2043
|
} catch {
|
|
1995
2044
|
return false;
|
|
@@ -2009,28 +2058,30 @@ function buildAuthorization(input) {
|
|
|
2009
2058
|
};
|
|
2010
2059
|
}
|
|
2011
2060
|
function signAuthorization(unsigned, payerDevicePrivateKey) {
|
|
2012
|
-
const payerSig =
|
|
2013
|
-
|
|
2061
|
+
const payerSig = signIssuerP256(
|
|
2062
|
+
canonicalJSONBytes(unsigned),
|
|
2063
|
+
payerDevicePrivateKey
|
|
2014
2064
|
);
|
|
2015
2065
|
return { ...unsigned, payerSig };
|
|
2016
2066
|
}
|
|
2017
|
-
function verifyAuthorization(auth,
|
|
2067
|
+
function verifyAuthorization(auth, issuerPublicKeySpkiB64) {
|
|
2018
2068
|
try {
|
|
2019
2069
|
const parsed = OfflinePaymentAuthorizationSchema.parse(auth);
|
|
2020
|
-
if (!verifyPaymentRequest(parsed.request,
|
|
2070
|
+
if (!verifyPaymentRequest(parsed.request, issuerPublicKeySpkiB64))
|
|
2071
|
+
return false;
|
|
2021
2072
|
const { issuerSig: payerOacSig, ...payerOacUnsigned } = parsed.payerOAC;
|
|
2022
|
-
if (!
|
|
2073
|
+
if (!verifyIssuerP256(
|
|
2023
2074
|
canonicalJSONBytes(payerOacUnsigned),
|
|
2024
|
-
|
|
2025
|
-
|
|
2075
|
+
payerOacSig,
|
|
2076
|
+
issuerPublicKeySpkiB64
|
|
2026
2077
|
)) {
|
|
2027
2078
|
return false;
|
|
2028
2079
|
}
|
|
2029
2080
|
const { payerSig, ...unsigned } = parsed;
|
|
2030
|
-
return
|
|
2081
|
+
return verifyIssuerP256(
|
|
2031
2082
|
canonicalJSONBytes(unsigned),
|
|
2032
|
-
|
|
2033
|
-
|
|
2083
|
+
payerSig,
|
|
2084
|
+
parsed.payerOAC.devicePublicKey
|
|
2034
2085
|
);
|
|
2035
2086
|
} catch {
|
|
2036
2087
|
return false;
|
|
@@ -2086,10 +2137,14 @@ var PaymentClaimSchema = import_zod7.z.object({
|
|
|
2086
2137
|
occurredAtMs: import_zod7.z.number().int().nonnegative(),
|
|
2087
2138
|
completedAtMs: import_zod7.z.number().int().nonnegative().optional(),
|
|
2088
2139
|
contextId: import_zod7.z.string().optional(),
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2140
|
+
// Stage 2c: P-256 device keys are now SubjectPublicKeyInfo DER, base64.
|
|
2141
|
+
// Signatures are ASN.1 DER ECDSA(SHA-256), base64. Backwards-incompatible
|
|
2142
|
+
// wire change; the backend has the matching widening in offline-settlements
|
|
2143
|
+
// service + zod schema.
|
|
2144
|
+
payerPubkey: import_zod7.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
|
|
2145
|
+
payerSignature: import_zod7.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
|
|
2146
|
+
payeePubkey: import_zod7.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/).optional(),
|
|
2147
|
+
payeeSignature: import_zod7.z.string().min(16).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/).optional()
|
|
2093
2148
|
});
|
|
2094
2149
|
var SettlementSchema = import_zod7.z.object({
|
|
2095
2150
|
settlementId: import_zod7.z.string().uuid(),
|
|
@@ -2517,10 +2572,6 @@ var PASS_STATES = [
|
|
|
2517
2572
|
"expired",
|
|
2518
2573
|
"revoked"
|
|
2519
2574
|
];
|
|
2520
|
-
var HexString2 = (length) => import_zod9.z.string().regex(
|
|
2521
|
-
new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
|
|
2522
|
-
`expected ${length}-byte hex string`
|
|
2523
|
-
);
|
|
2524
2575
|
var PassMetadataSchema = import_zod9.z.record(
|
|
2525
2576
|
import_zod9.z.union([import_zod9.z.string(), import_zod9.z.number(), import_zod9.z.boolean(), import_zod9.z.null()])
|
|
2526
2577
|
);
|
|
@@ -2541,9 +2592,9 @@ var PassSchema = import_zod9.z.object({
|
|
|
2541
2592
|
nonce: import_zod9.z.string().min(1),
|
|
2542
2593
|
/** Device id this pass is bound to (FK to backend `device_keys`). */
|
|
2543
2594
|
holderDeviceId: import_zod9.z.string().min(1),
|
|
2544
|
-
/**
|
|
2545
|
-
* is verified against this key — it is the security-critical binding. */
|
|
2546
|
-
holderDevicePubkey:
|
|
2595
|
+
/** SubjectPublicKeyInfo DER (P-256) of the bound device, base64. The redemption
|
|
2596
|
+
* signature is verified against this key — it is the security-critical binding. */
|
|
2597
|
+
holderDevicePubkey: import_zod9.z.string().min(64).max(4096).regex(/^[A-Za-z0-9+/]+={0,2}$/),
|
|
2547
2598
|
/** Optional fixed amount for monetary passes (vouchers, gift cards) in kobo. */
|
|
2548
2599
|
amountKobo: import_zod9.z.number().int().nonnegative().optional(),
|
|
2549
2600
|
/** ISO-4217-ish currency code; required on the wire. SDK builders default to NGN. */
|
|
@@ -2552,7 +2603,8 @@ var PassSchema = import_zod9.z.object({
|
|
|
2552
2603
|
counterSeed: import_zod9.z.number().int().nonnegative(),
|
|
2553
2604
|
/** Optional cumulative spend cap in kobo across all redemptions of this pass. */
|
|
2554
2605
|
cumulativeCapKobo: import_zod9.z.number().int().nonnegative().optional(),
|
|
2555
|
-
|
|
2606
|
+
/** ASN.1 DER ECDSA P-256 signature, base64. */
|
|
2607
|
+
issuerSig: import_zod9.z.string().min(64).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/)
|
|
2556
2608
|
}).refine((v) => v.validUntilMs > v.validFromMs, {
|
|
2557
2609
|
message: "validUntilMs must be greater than validFromMs"
|
|
2558
2610
|
});
|
|
@@ -2585,19 +2637,20 @@ function buildPass(input) {
|
|
|
2585
2637
|
return out;
|
|
2586
2638
|
}
|
|
2587
2639
|
function signPass(unsigned, issuerPrivateKey) {
|
|
2588
|
-
const issuerSig =
|
|
2589
|
-
|
|
2640
|
+
const issuerSig = signIssuerP256(
|
|
2641
|
+
canonicalJSONBytes(unsigned),
|
|
2642
|
+
issuerPrivateKey
|
|
2590
2643
|
);
|
|
2591
2644
|
return { ...unsigned, issuerSig };
|
|
2592
2645
|
}
|
|
2593
|
-
function verifyPass(pass,
|
|
2646
|
+
function verifyPass(pass, issuerPublicKeySpkiB64) {
|
|
2594
2647
|
try {
|
|
2595
2648
|
const parsed = PassSchema.parse(pass);
|
|
2596
2649
|
const { issuerSig, ...unsigned } = parsed;
|
|
2597
|
-
return
|
|
2650
|
+
return verifyIssuerP256(
|
|
2598
2651
|
canonicalJSONBytes(unsigned),
|
|
2599
|
-
|
|
2600
|
-
|
|
2652
|
+
issuerSig,
|
|
2653
|
+
issuerPublicKeySpkiB64
|
|
2601
2654
|
);
|
|
2602
2655
|
} catch {
|
|
2603
2656
|
return false;
|
|
@@ -2609,7 +2662,7 @@ function isPassWithinValidity(pass, nowMs) {
|
|
|
2609
2662
|
|
|
2610
2663
|
// src/passes/redemption.ts
|
|
2611
2664
|
var import_zod10 = require("zod");
|
|
2612
|
-
var
|
|
2665
|
+
var Base64Std2 = import_zod10.z.string().min(16).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/, "expected base64 (std)");
|
|
2613
2666
|
var RedemptionSchema = import_zod10.z.object({
|
|
2614
2667
|
pass: PassSchema,
|
|
2615
2668
|
redeemerId: import_zod10.z.string().min(1),
|
|
@@ -2620,7 +2673,8 @@ var RedemptionSchema = import_zod10.z.object({
|
|
|
2620
2673
|
/** Amount being redeemed in kobo (0 for non-monetary passes like ride tickets). */
|
|
2621
2674
|
amountKobo: import_zod10.z.number().int().nonnegative(),
|
|
2622
2675
|
nonce: import_zod10.z.string().min(1),
|
|
2623
|
-
|
|
2676
|
+
/** ASN.1 DER ECDSA P-256 signature over canonicalJSONBytes(unsigned), base64. */
|
|
2677
|
+
holderSig: Base64Std2
|
|
2624
2678
|
});
|
|
2625
2679
|
var REDEEMABLE_STATES = /* @__PURE__ */ new Set(["issued", "active"]);
|
|
2626
2680
|
function buildRedemption(input) {
|
|
@@ -2674,31 +2728,28 @@ function buildRedemption(input) {
|
|
|
2674
2728
|
};
|
|
2675
2729
|
}
|
|
2676
2730
|
function signRedemption(unsigned, holderDevicePrivateKey) {
|
|
2677
|
-
const holderSig =
|
|
2678
|
-
|
|
2731
|
+
const holderSig = signIssuerP256(
|
|
2732
|
+
canonicalJSONBytes(unsigned),
|
|
2733
|
+
holderDevicePrivateKey
|
|
2679
2734
|
);
|
|
2680
2735
|
return { ...unsigned, holderSig };
|
|
2681
2736
|
}
|
|
2682
|
-
function verifyRedemption(r,
|
|
2737
|
+
function verifyRedemption(r, issuerPublicKeySpkiB64) {
|
|
2683
2738
|
try {
|
|
2684
2739
|
const parsed = RedemptionSchema.parse(r);
|
|
2685
2740
|
if (parsed.counter <= parsed.pass.counterSeed) return false;
|
|
2686
2741
|
const { issuerSig, ...passUnsigned } = parsed.pass;
|
|
2687
|
-
if (!
|
|
2742
|
+
if (!verifyIssuerP256(
|
|
2688
2743
|
canonicalJSONBytes(passUnsigned),
|
|
2689
|
-
|
|
2690
|
-
|
|
2744
|
+
issuerSig,
|
|
2745
|
+
issuerPublicKeySpkiB64
|
|
2691
2746
|
)) {
|
|
2692
2747
|
return false;
|
|
2693
2748
|
}
|
|
2694
|
-
const
|
|
2695
|
-
if (typeof
|
|
2749
|
+
const holderPub = parsed.pass.holderDevicePubkey;
|
|
2750
|
+
if (typeof holderPub !== "string") return false;
|
|
2696
2751
|
const { holderSig, ...unsigned } = parsed;
|
|
2697
|
-
return
|
|
2698
|
-
canonicalJSONBytes(unsigned),
|
|
2699
|
-
hexToBytes(holderSig),
|
|
2700
|
-
hexToBytes(holderHex)
|
|
2701
|
-
);
|
|
2752
|
+
return verifyIssuerP256(canonicalJSONBytes(unsigned), holderSig, holderPub);
|
|
2702
2753
|
} catch {
|
|
2703
2754
|
return false;
|
|
2704
2755
|
}
|
|
@@ -2708,10 +2759,6 @@ function verifyRedemption(r, issuerPublicKey) {
|
|
|
2708
2759
|
var import_zod11 = require("zod");
|
|
2709
2760
|
var RECEIPT_CHANNELS = ["cash", "pass"];
|
|
2710
2761
|
var RECEIPT_KINDS = RECEIPT_CHANNELS;
|
|
2711
|
-
var HexString3 = (length) => import_zod11.z.string().regex(
|
|
2712
|
-
new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
|
|
2713
|
-
`expected ${length}-byte hex string`
|
|
2714
|
-
);
|
|
2715
2762
|
var ReceiptPayloadSchema = import_zod11.z.record(
|
|
2716
2763
|
import_zod11.z.union([import_zod11.z.string(), import_zod11.z.number(), import_zod11.z.boolean(), import_zod11.z.null()])
|
|
2717
2764
|
);
|
|
@@ -2729,7 +2776,8 @@ var ReceiptSchema = import_zod11.z.object({
|
|
|
2729
2776
|
issuedAtMs: import_zod11.z.number().int().nonnegative(),
|
|
2730
2777
|
issuerId: import_zod11.z.string().min(1),
|
|
2731
2778
|
payload: ReceiptPayloadSchema,
|
|
2732
|
-
|
|
2779
|
+
/** ASN.1 DER ECDSA P-256 signature, base64. */
|
|
2780
|
+
issuerSig: import_zod11.z.string().min(64).max(2048).regex(/^[A-Za-z0-9+/]+={0,2}$/)
|
|
2733
2781
|
}).superRefine((v, ctx) => {
|
|
2734
2782
|
if (v.channel === "cash") {
|
|
2735
2783
|
if (!v.intentId) {
|
|
@@ -2795,19 +2843,20 @@ function buildReceipt(input) {
|
|
|
2795
2843
|
return out;
|
|
2796
2844
|
}
|
|
2797
2845
|
function signReceipt(unsigned, issuerPrivateKey) {
|
|
2798
|
-
const issuerSig =
|
|
2799
|
-
|
|
2846
|
+
const issuerSig = signIssuerP256(
|
|
2847
|
+
canonicalJSONBytes(unsigned),
|
|
2848
|
+
issuerPrivateKey
|
|
2800
2849
|
);
|
|
2801
2850
|
return { ...unsigned, issuerSig };
|
|
2802
2851
|
}
|
|
2803
|
-
function verifyReceipt(r,
|
|
2852
|
+
function verifyReceipt(r, issuerPublicKeySpkiB64) {
|
|
2804
2853
|
try {
|
|
2805
2854
|
const parsed = ReceiptSchema.parse(r);
|
|
2806
2855
|
const { issuerSig, ...unsigned } = parsed;
|
|
2807
|
-
return
|
|
2856
|
+
return verifyIssuerP256(
|
|
2808
2857
|
canonicalJSONBytes(unsigned),
|
|
2809
|
-
|
|
2810
|
-
|
|
2858
|
+
issuerSig,
|
|
2859
|
+
issuerPublicKeySpkiB64
|
|
2811
2860
|
);
|
|
2812
2861
|
} catch {
|
|
2813
2862
|
return false;
|
|
@@ -3142,17 +3191,49 @@ function createAccountsClient(opts) {
|
|
|
3142
3191
|
// src/me-offline/client.ts
|
|
3143
3192
|
var import_zod13 = require("zod");
|
|
3144
3193
|
var Hex64 = import_zod13.z.string().regex(/^[0-9a-f]{64}$/i);
|
|
3145
|
-
var HexAny = import_zod13.z.string().regex(/^[0-9a-f]+$/i);
|
|
3146
3194
|
var Sha256Hex = import_zod13.z.string().regex(/^[0-9a-f]{64}$/i);
|
|
3195
|
+
var Base64Std3 = import_zod13.z.string().regex(/^[A-Za-z0-9+/]+={0,2}$/);
|
|
3147
3196
|
var RegisterDeviceKeyInputSchema = import_zod13.z.object({
|
|
3148
3197
|
deviceId: import_zod13.z.string().min(1).max(128),
|
|
3149
3198
|
publicKeyHex: Hex64
|
|
3150
3199
|
});
|
|
3200
|
+
var AttestationSecurityLevelSchema = import_zod13.z.enum([
|
|
3201
|
+
"STRONGBOX",
|
|
3202
|
+
"TEE",
|
|
3203
|
+
"SECURE_ENCLAVE",
|
|
3204
|
+
"SOFTWARE"
|
|
3205
|
+
]);
|
|
3206
|
+
var DeviceKeyAlgSchema = import_zod13.z.literal("p256");
|
|
3207
|
+
var RegisterDeviceKeyP256InputSchema = import_zod13.z.object({
|
|
3208
|
+
deviceId: import_zod13.z.string().min(1).max(128),
|
|
3209
|
+
/** P-256 SubjectPublicKeyInfo DER, base64. */
|
|
3210
|
+
publicKeySpkiB64: Base64Std3.min(64).max(4096),
|
|
3211
|
+
/** Base64 of the server-issued enrollment challenge string. */
|
|
3212
|
+
challengeB64: Base64Std3.min(8).max(1024),
|
|
3213
|
+
/** iOS App Attest payload or Android X.509 Key Attestation chain. */
|
|
3214
|
+
attestationChainB64: import_zod13.z.array(Base64Std3.min(16).max(16384)).min(1).max(16),
|
|
3215
|
+
securityLevel: AttestationSecurityLevelSchema
|
|
3216
|
+
});
|
|
3217
|
+
var P256EnrollmentChallengeInputSchema = import_zod13.z.object({
|
|
3218
|
+
deviceId: import_zod13.z.string().min(1).max(128)
|
|
3219
|
+
});
|
|
3220
|
+
var P256EnrollmentChallengeResultSchema = import_zod13.z.object({
|
|
3221
|
+
challenge: import_zod13.z.string().min(16),
|
|
3222
|
+
expiresAtMs: import_zod13.z.number().int().positive()
|
|
3223
|
+
});
|
|
3151
3224
|
var DeviceKeyRecordSchema = import_zod13.z.object({
|
|
3152
3225
|
id: import_zod13.z.string().uuid(),
|
|
3153
3226
|
userId: import_zod13.z.string().uuid(),
|
|
3154
3227
|
deviceId: import_zod13.z.string(),
|
|
3155
|
-
|
|
3228
|
+
/** Always 'p256' on the consumer offline rail. Field retained for forward-compat. */
|
|
3229
|
+
alg: DeviceKeyAlgSchema.default("p256"),
|
|
3230
|
+
/** Legacy ed25519 hex key. Always null on new records (kept for back-compat reads). */
|
|
3231
|
+
publicKeyHex: Hex64.nullable().default(null),
|
|
3232
|
+
/** P-256 SubjectPublicKeyInfo DER, base64. Required for new records. */
|
|
3233
|
+
publicKeySpkiB64: Base64Std3.nullable().default(null),
|
|
3234
|
+
securityLevel: AttestationSecurityLevelSchema.nullable().default(null),
|
|
3235
|
+
hardwareBacked: import_zod13.z.boolean().default(false),
|
|
3236
|
+
attestedAtMs: import_zod13.z.number().int().nonnegative().nullable().default(null),
|
|
3156
3237
|
createdAtMs: import_zod13.z.number().int().nonnegative(),
|
|
3157
3238
|
revokedAtMs: import_zod13.z.number().int().nonnegative().nullable()
|
|
3158
3239
|
});
|
|
@@ -3161,7 +3242,10 @@ var ConsumerOACSchema = import_zod13.z.object({
|
|
|
3161
3242
|
issuerId: import_zod13.z.string().min(1).max(64),
|
|
3162
3243
|
userId: import_zod13.z.string().uuid(),
|
|
3163
3244
|
deviceId: import_zod13.z.string().min(1).max(128),
|
|
3164
|
-
|
|
3245
|
+
/** Always 'p256'. Field retained for forward-compat. */
|
|
3246
|
+
alg: import_zod13.z.literal("p256").default("p256"),
|
|
3247
|
+
/** P-256 SubjectPublicKeyInfo DER, base64. */
|
|
3248
|
+
devicePubkeySpkiB64: Base64Std3.min(64).max(4096),
|
|
3165
3249
|
perTxCapKobo: import_zod13.z.number().int().positive(),
|
|
3166
3250
|
cumulativeCapKobo: import_zod13.z.number().int().positive(),
|
|
3167
3251
|
currency: import_zod13.z.string().length(3),
|
|
@@ -3172,8 +3256,10 @@ var ConsumerOACSchema = import_zod13.z.object({
|
|
|
3172
3256
|
});
|
|
3173
3257
|
var SignedConsumerOACSchema = import_zod13.z.object({
|
|
3174
3258
|
oac: ConsumerOACSchema,
|
|
3175
|
-
|
|
3176
|
-
|
|
3259
|
+
/** ASN.1 DER ECDSA P-256 issuer signature, base64. */
|
|
3260
|
+
issuerSig: Base64Std3.min(16).max(2048),
|
|
3261
|
+
/** Issuer's P-256 public key as SubjectPublicKeyInfo DER, base64. */
|
|
3262
|
+
issuerPublicKeySpkiB64: Base64Std3.min(64).max(4096)
|
|
3177
3263
|
});
|
|
3178
3264
|
var OACRecordSchema = SignedConsumerOACSchema.extend({
|
|
3179
3265
|
currentOfflineSpentKobo: import_zod13.z.number().int().nonnegative(),
|
|
@@ -3205,6 +3291,7 @@ var EnableOfflineInputSchema = import_zod13.z.object({
|
|
|
3205
3291
|
installId: import_zod13.z.string().min(1).max(128),
|
|
3206
3292
|
partnerId: import_zod13.z.string().min(1).max(64).optional()
|
|
3207
3293
|
});
|
|
3294
|
+
var ProvisionOfflineAllowanceInputSchema = EnableOfflineInputSchema;
|
|
3208
3295
|
var DisableOfflineInputSchema = import_zod13.z.object({
|
|
3209
3296
|
deviceId: import_zod13.z.string().min(1).max(128),
|
|
3210
3297
|
installId: import_zod13.z.string().min(1).max(128).optional(),
|
|
@@ -3242,6 +3329,7 @@ var EnableOfflineResultSchema = import_zod13.z.object({
|
|
|
3242
3329
|
hold: OfflineHoldRecordSchema,
|
|
3243
3330
|
oac: OACRecordSchema
|
|
3244
3331
|
});
|
|
3332
|
+
var ProvisionOfflineAllowanceResultSchema = EnableOfflineResultSchema;
|
|
3245
3333
|
var DisableOfflineResultSchema = import_zod13.z.object({
|
|
3246
3334
|
hold: OfflineHoldRecordSchema,
|
|
3247
3335
|
trusted: import_zod13.z.boolean(),
|
|
@@ -3255,6 +3343,8 @@ var OfflineStateResultSchema = import_zod13.z.object({
|
|
|
3255
3343
|
active: OACRecordSchema.nullable()
|
|
3256
3344
|
});
|
|
3257
3345
|
var ConsumerPaymentClaimSchema = import_zod13.z.object({
|
|
3346
|
+
/** Always 'p256'. Retained for forward-compat and as an explicit domain marker. */
|
|
3347
|
+
alg: import_zod13.z.literal("p256").default("p256"),
|
|
3258
3348
|
oacId: import_zod13.z.string().uuid(),
|
|
3259
3349
|
encounterId: Sha256Hex.optional(),
|
|
3260
3350
|
payerUserId: import_zod13.z.string().uuid(),
|
|
@@ -3267,10 +3357,10 @@ var ConsumerPaymentClaimSchema = import_zod13.z.object({
|
|
|
3267
3357
|
occurredAtMs: import_zod13.z.number().int().nonnegative(),
|
|
3268
3358
|
completedAtMs: import_zod13.z.number().int().nonnegative().optional(),
|
|
3269
3359
|
contextId: import_zod13.z.string().max(128).optional(),
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3360
|
+
payerPubkeySpkiB64: Base64Std3.min(64).max(4096),
|
|
3361
|
+
payerSignatureDerB64: Base64Std3.min(16).max(2048),
|
|
3362
|
+
payeePubkeySpkiB64: Base64Std3.min(64).max(4096).optional(),
|
|
3363
|
+
payeeSignatureDerB64: Base64Std3.min(16).max(2048).optional()
|
|
3274
3364
|
});
|
|
3275
3365
|
var ConsumerSettlementSchema = import_zod13.z.object({
|
|
3276
3366
|
settlementId: import_zod13.z.string().uuid(),
|
|
@@ -3284,7 +3374,8 @@ var ConsumerSettlementSchema = import_zod13.z.object({
|
|
|
3284
3374
|
status: import_zod13.z.enum(["SETTLED", "REVIEW"]),
|
|
3285
3375
|
reviewReason: import_zod13.z.string().nullable(),
|
|
3286
3376
|
ledgerRef: import_zod13.z.string().nullable(),
|
|
3287
|
-
|
|
3377
|
+
/** ASN.1 DER ECDSA P-256 issuer signature, base64. */
|
|
3378
|
+
issuerSig: Base64Std3.min(16).max(2048),
|
|
3288
3379
|
createdAtMs: import_zod13.z.number().int().nonnegative()
|
|
3289
3380
|
});
|
|
3290
3381
|
var ConsumerSettleResultSchema = import_zod13.z.object({
|
|
@@ -3336,6 +3427,18 @@ function createMeOfflineClient(opts) {
|
|
|
3336
3427
|
RegisterDeviceKeyInputSchema.parse(input),
|
|
3337
3428
|
(raw) => DeviceKeyRecordSchema.parse(raw)
|
|
3338
3429
|
),
|
|
3430
|
+
issueP256EnrollmentChallenge: (input) => call(
|
|
3431
|
+
"POST",
|
|
3432
|
+
"/v1/me/offline/keys/p256/challenge",
|
|
3433
|
+
P256EnrollmentChallengeInputSchema.parse(input),
|
|
3434
|
+
(raw) => P256EnrollmentChallengeResultSchema.parse(raw)
|
|
3435
|
+
),
|
|
3436
|
+
registerDeviceKeyP256: (input) => call(
|
|
3437
|
+
"POST",
|
|
3438
|
+
"/v1/me/offline/keys/p256",
|
|
3439
|
+
RegisterDeviceKeyP256InputSchema.parse(input),
|
|
3440
|
+
(raw) => DeviceKeyRecordSchema.parse(raw)
|
|
3441
|
+
),
|
|
3339
3442
|
listDeviceKeys: () => call(
|
|
3340
3443
|
"GET",
|
|
3341
3444
|
"/v1/me/offline/keys",
|
|
@@ -3348,6 +3451,12 @@ function createMeOfflineClient(opts) {
|
|
|
3348
3451
|
RevokeDeviceKeyInputSchema.parse(input),
|
|
3349
3452
|
() => void 0
|
|
3350
3453
|
),
|
|
3454
|
+
provisionAllowance: (input) => call(
|
|
3455
|
+
"POST",
|
|
3456
|
+
"/v1/me/offline/allowance",
|
|
3457
|
+
ProvisionOfflineAllowanceInputSchema.parse(input),
|
|
3458
|
+
(raw) => ProvisionOfflineAllowanceResultSchema.parse(raw)
|
|
3459
|
+
),
|
|
3351
3460
|
enable: (input) => call(
|
|
3352
3461
|
"POST",
|
|
3353
3462
|
"/v1/me/offline/enable",
|
|
@@ -3393,6 +3502,185 @@ function createMeOfflineClient(opts) {
|
|
|
3393
3502
|
};
|
|
3394
3503
|
}
|
|
3395
3504
|
|
|
3505
|
+
// src/me-offline/signer.ts
|
|
3506
|
+
var import_nist2 = require("@noble/curves/nist");
|
|
3507
|
+
var CLAIM_DOMAIN_V2 = "flur:consumer-offline:v2:claim";
|
|
3508
|
+
function canonicalClaimSigningPayload(claim) {
|
|
3509
|
+
return {
|
|
3510
|
+
domain: CLAIM_DOMAIN_V2,
|
|
3511
|
+
alg: claim.alg,
|
|
3512
|
+
oacId: claim.oacId,
|
|
3513
|
+
payerUserId: claim.payerUserId,
|
|
3514
|
+
payeeUserId: claim.payeeUserId,
|
|
3515
|
+
payerDeviceId: claim.payerDeviceId,
|
|
3516
|
+
payerNonce: claim.payerNonce,
|
|
3517
|
+
payeeNonce: claim.payeeNonce,
|
|
3518
|
+
amountKobo: claim.amountKobo,
|
|
3519
|
+
currency: claim.currency,
|
|
3520
|
+
occurredAtMs: claim.occurredAtMs,
|
|
3521
|
+
completedAtMs: claim.completedAtMs ?? null,
|
|
3522
|
+
contextId: claim.contextId ?? null
|
|
3523
|
+
};
|
|
3524
|
+
}
|
|
3525
|
+
function canonicalClaimSigningBytes(claim) {
|
|
3526
|
+
return canonicalJSONBytes(canonicalClaimSigningPayload(claim));
|
|
3527
|
+
}
|
|
3528
|
+
function bytesToBase642(bytes) {
|
|
3529
|
+
if (typeof Buffer !== "undefined") {
|
|
3530
|
+
return Buffer.from(bytes).toString("base64");
|
|
3531
|
+
}
|
|
3532
|
+
let bin = "";
|
|
3533
|
+
for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
|
|
3534
|
+
return btoa(bin);
|
|
3535
|
+
}
|
|
3536
|
+
function base64ToBytes2(b64) {
|
|
3537
|
+
if (typeof Buffer !== "undefined") {
|
|
3538
|
+
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
3539
|
+
}
|
|
3540
|
+
const bin = atob(b64);
|
|
3541
|
+
const out = new Uint8Array(bin.length);
|
|
3542
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
3543
|
+
return out;
|
|
3544
|
+
}
|
|
3545
|
+
var P256_SPKI_HEADER2 = new Uint8Array([
|
|
3546
|
+
48,
|
|
3547
|
+
89,
|
|
3548
|
+
48,
|
|
3549
|
+
19,
|
|
3550
|
+
6,
|
|
3551
|
+
7,
|
|
3552
|
+
42,
|
|
3553
|
+
134,
|
|
3554
|
+
72,
|
|
3555
|
+
206,
|
|
3556
|
+
61,
|
|
3557
|
+
2,
|
|
3558
|
+
1,
|
|
3559
|
+
6,
|
|
3560
|
+
8,
|
|
3561
|
+
42,
|
|
3562
|
+
134,
|
|
3563
|
+
72,
|
|
3564
|
+
206,
|
|
3565
|
+
61,
|
|
3566
|
+
3,
|
|
3567
|
+
1,
|
|
3568
|
+
7,
|
|
3569
|
+
3,
|
|
3570
|
+
66,
|
|
3571
|
+
0
|
|
3572
|
+
]);
|
|
3573
|
+
function p256PublicKeyToSpkiB64(rawUncompressed) {
|
|
3574
|
+
if (rawUncompressed.length !== 65 || rawUncompressed[0] !== 4) {
|
|
3575
|
+
throw new Error("p256: expected 65-byte uncompressed point");
|
|
3576
|
+
}
|
|
3577
|
+
const out = new Uint8Array(P256_SPKI_HEADER2.length + rawUncompressed.length);
|
|
3578
|
+
out.set(P256_SPKI_HEADER2, 0);
|
|
3579
|
+
out.set(rawUncompressed, P256_SPKI_HEADER2.length);
|
|
3580
|
+
return bytesToBase642(out);
|
|
3581
|
+
}
|
|
3582
|
+
function p256SpkiB64ToPublicKey(spkiB64) {
|
|
3583
|
+
const spki = base64ToBytes2(spkiB64);
|
|
3584
|
+
if (spki.length !== P256_SPKI_HEADER2.length + 65) {
|
|
3585
|
+
throw new Error("p256: invalid SPKI length");
|
|
3586
|
+
}
|
|
3587
|
+
for (let i = 0; i < P256_SPKI_HEADER2.length; i++) {
|
|
3588
|
+
if (spki[i] !== P256_SPKI_HEADER2[i]) {
|
|
3589
|
+
throw new Error("p256: invalid SPKI header");
|
|
3590
|
+
}
|
|
3591
|
+
}
|
|
3592
|
+
return spki.slice(P256_SPKI_HEADER2.length);
|
|
3593
|
+
}
|
|
3594
|
+
function createSoftwareP256Signer(privateKey) {
|
|
3595
|
+
const raw = import_nist2.p256.getPublicKey(privateKey, false);
|
|
3596
|
+
const spkiB64 = p256PublicKeyToSpkiB64(raw);
|
|
3597
|
+
return {
|
|
3598
|
+
alg: "p256",
|
|
3599
|
+
async getPublicKey() {
|
|
3600
|
+
return { alg: "p256", publicKey: spkiB64 };
|
|
3601
|
+
},
|
|
3602
|
+
async sign(bytes) {
|
|
3603
|
+
const sig = import_nist2.p256.sign(bytes, privateKey, { prehash: true });
|
|
3604
|
+
const der = sig.toBytes("der");
|
|
3605
|
+
return { alg: "p256", signature: bytesToBase642(der) };
|
|
3606
|
+
}
|
|
3607
|
+
};
|
|
3608
|
+
}
|
|
3609
|
+
function verifyClaimSignature(input) {
|
|
3610
|
+
try {
|
|
3611
|
+
if (input.alg !== "p256") return false;
|
|
3612
|
+
const sigDer = base64ToBytes2(input.signature);
|
|
3613
|
+
const pub = p256SpkiB64ToPublicKey(input.publicKey);
|
|
3614
|
+
return import_nist2.p256.verify(sigDer, input.bytes, pub, {
|
|
3615
|
+
prehash: true,
|
|
3616
|
+
format: "der"
|
|
3617
|
+
});
|
|
3618
|
+
} catch {
|
|
3619
|
+
return false;
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
|
|
3623
|
+
// src/me-offline/sms.ts
|
|
3624
|
+
var OFFLINE_CLAIM_SMS_PREFIX = "FLURC1.";
|
|
3625
|
+
var TOKEN_RE = /(?:^|\s)(FLURC1\.[A-Za-z0-9_-]+={0,2})(?:\s|$)/;
|
|
3626
|
+
function encodeOfflineClaimSmsMessage(claim) {
|
|
3627
|
+
const parsed = ConsumerPaymentClaimSchema.parse(claim);
|
|
3628
|
+
const json = JSON.stringify(parsed);
|
|
3629
|
+
return `${OFFLINE_CLAIM_SMS_PREFIX}${base64UrlEncodeUtf8(json)}`;
|
|
3630
|
+
}
|
|
3631
|
+
function decodeOfflineClaimSmsMessage(message) {
|
|
3632
|
+
const token = extractOfflineClaimSmsToken(message);
|
|
3633
|
+
if (!token) {
|
|
3634
|
+
throw new Error("offline claim SMS token not found");
|
|
3635
|
+
}
|
|
3636
|
+
const encoded = token.slice(OFFLINE_CLAIM_SMS_PREFIX.length);
|
|
3637
|
+
let raw;
|
|
3638
|
+
try {
|
|
3639
|
+
raw = JSON.parse(base64UrlDecodeUtf8(encoded));
|
|
3640
|
+
} catch {
|
|
3641
|
+
throw new Error("offline claim SMS token is malformed");
|
|
3642
|
+
}
|
|
3643
|
+
const parsed = ConsumerPaymentClaimSchema.safeParse(raw);
|
|
3644
|
+
if (!parsed.success) {
|
|
3645
|
+
throw new Error("offline claim SMS token is invalid");
|
|
3646
|
+
}
|
|
3647
|
+
return parsed.data;
|
|
3648
|
+
}
|
|
3649
|
+
function extractOfflineClaimSmsToken(message) {
|
|
3650
|
+
const trimmed = message.trim();
|
|
3651
|
+
if (trimmed.startsWith(OFFLINE_CLAIM_SMS_PREFIX)) {
|
|
3652
|
+
return trimmed.split(/\s+/, 1)[0] ?? null;
|
|
3653
|
+
}
|
|
3654
|
+
return TOKEN_RE.exec(message)?.[1] ?? null;
|
|
3655
|
+
}
|
|
3656
|
+
function base64UrlEncodeUtf8(input) {
|
|
3657
|
+
const bytes = new TextEncoder().encode(input);
|
|
3658
|
+
let binary = "";
|
|
3659
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
3660
|
+
const base64 = typeof btoa === "function" ? btoa(binary) : typeof Buffer !== "undefined" ? Buffer.from(bytes).toString("base64") : void 0;
|
|
3661
|
+
if (!base64) throw new Error("base64 encoder unavailable");
|
|
3662
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
3663
|
+
}
|
|
3664
|
+
function base64UrlDecodeUtf8(input) {
|
|
3665
|
+
const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
3666
|
+
const padded = base64.padEnd(
|
|
3667
|
+
base64.length + (4 - base64.length % 4) % 4,
|
|
3668
|
+
"="
|
|
3669
|
+
);
|
|
3670
|
+
if (typeof atob === "function") {
|
|
3671
|
+
const binary = atob(padded);
|
|
3672
|
+
const bytes = new Uint8Array(binary.length);
|
|
3673
|
+
for (let index = 0; index < binary.length; index++) {
|
|
3674
|
+
bytes[index] = binary.charCodeAt(index);
|
|
3675
|
+
}
|
|
3676
|
+
return new TextDecoder().decode(bytes);
|
|
3677
|
+
}
|
|
3678
|
+
if (typeof Buffer !== "undefined") {
|
|
3679
|
+
return Buffer.from(padded, "base64").toString("utf8");
|
|
3680
|
+
}
|
|
3681
|
+
throw new Error("base64 decoder unavailable");
|
|
3682
|
+
}
|
|
3683
|
+
|
|
3396
3684
|
// src/partner-funding/client.ts
|
|
3397
3685
|
var import_zod14 = require("zod");
|
|
3398
3686
|
var MinorString = import_zod14.z.string().regex(/^-?\d+$/);
|
|
@@ -3768,14 +4056,15 @@ function buildArtifactBody(input) {
|
|
|
3768
4056
|
return { ...header, data: input.data };
|
|
3769
4057
|
}
|
|
3770
4058
|
function signArtifact(body, privateKey) {
|
|
3771
|
-
const sig =
|
|
4059
|
+
const sig = signIssuerP256(canonicalJSONBytes(body), privateKey);
|
|
3772
4060
|
return { body, sig };
|
|
3773
4061
|
}
|
|
3774
4062
|
function encodeArtifactUri(signed) {
|
|
3775
4063
|
const bodyBytes = canonicalJSONBytes(signed.body);
|
|
3776
4064
|
const bodyB64 = base64UrlEncode(bodyBytes);
|
|
3777
|
-
const
|
|
3778
|
-
|
|
4065
|
+
const sigBytes = base64UrlDecode(signed.sig);
|
|
4066
|
+
const sigB64Url = base64UrlEncode(sigBytes);
|
|
4067
|
+
return `${FLUR_ARTIFACT_URI_PREFIX}${signed.body.t}/${bodyB64}.${sigB64Url}`;
|
|
3779
4068
|
}
|
|
3780
4069
|
function decodeArtifactUri(uri) {
|
|
3781
4070
|
if (!uri.startsWith(FLUR_ARTIFACT_URI_PREFIX)) {
|
|
@@ -3806,9 +4095,9 @@ function decodeArtifactUri(uri) {
|
|
|
3806
4095
|
}
|
|
3807
4096
|
const bodyBytes = base64UrlDecode(payload.slice(0, dot));
|
|
3808
4097
|
const sigBytes = base64UrlDecode(payload.slice(dot + 1));
|
|
3809
|
-
if (sigBytes.length
|
|
4098
|
+
if (sigBytes.length < 64 || sigBytes.length > 80) {
|
|
3810
4099
|
throw new FlurArtifactError(
|
|
3811
|
-
`Signature
|
|
4100
|
+
`Signature length out of range: ${sigBytes.length}`,
|
|
3812
4101
|
"INVALID_SIGNATURE"
|
|
3813
4102
|
);
|
|
3814
4103
|
}
|
|
@@ -3835,17 +4124,26 @@ function decodeArtifactUri(uri) {
|
|
|
3835
4124
|
type,
|
|
3836
4125
|
bodyBytes,
|
|
3837
4126
|
body: bodyJson,
|
|
3838
|
-
|
|
4127
|
+
// Encode as standard base64 (not url-safe) for sig field consistency.
|
|
4128
|
+
sig: encodeStdBase64(sigBytes)
|
|
3839
4129
|
};
|
|
3840
4130
|
}
|
|
3841
|
-
function
|
|
4131
|
+
function encodeStdBase64(bytes) {
|
|
4132
|
+
if (typeof Buffer !== "undefined") {
|
|
4133
|
+
return Buffer.from(bytes).toString("base64");
|
|
4134
|
+
}
|
|
4135
|
+
let bin = "";
|
|
4136
|
+
for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
|
|
4137
|
+
return typeof btoa === "function" ? btoa(bin) : "";
|
|
4138
|
+
}
|
|
4139
|
+
function verifyArtifactSignature(decoded, publicKeySpkiB64, options = {}) {
|
|
3842
4140
|
if (options.enforceExpiry !== false && decoded.body.exp !== void 0) {
|
|
3843
4141
|
const now = options.nowSeconds ?? Math.floor(Date.now() / 1e3);
|
|
3844
4142
|
if (decoded.body.exp < now) {
|
|
3845
4143
|
throw new FlurArtifactError("Artifact has expired", "EXPIRED");
|
|
3846
4144
|
}
|
|
3847
4145
|
}
|
|
3848
|
-
return
|
|
4146
|
+
return verifyIssuerP256(decoded.bodyBytes, decoded.sig, publicKeySpkiB64);
|
|
3849
4147
|
}
|
|
3850
4148
|
|
|
3851
4149
|
// src/artifacts/types.ts
|
|
@@ -3864,7 +4162,7 @@ var ARTIFACT_TYPES = {
|
|
|
3864
4162
|
PASS: "pass",
|
|
3865
4163
|
IDENTITY: "identity"
|
|
3866
4164
|
};
|
|
3867
|
-
var
|
|
4165
|
+
var HexString = (length) => import_zod16.z.string().regex(
|
|
3868
4166
|
new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
|
|
3869
4167
|
`expected ${length}-byte hex string`
|
|
3870
4168
|
);
|
|
@@ -3882,7 +4180,7 @@ var ReceiptArtifactSchema = import_zod16.z.object({
|
|
|
3882
4180
|
settledAtMs: import_zod16.z.number().int().positive(),
|
|
3883
4181
|
ledgerTxnId: import_zod16.z.string().min(1).max(64).optional(),
|
|
3884
4182
|
memo: import_zod16.z.string().max(140).optional(),
|
|
3885
|
-
hashChainPrev:
|
|
4183
|
+
hashChainPrev: HexString(32).optional()
|
|
3886
4184
|
});
|
|
3887
4185
|
var ShortId = import_zod16.z.string().min(1).max(64);
|
|
3888
4186
|
var PositiveInt = import_zod16.z.number().int().positive();
|
|
@@ -3964,7 +4262,7 @@ var StatementArtifactSchema = import_zod16.z.object({
|
|
|
3964
4262
|
closingBalanceKobo: import_zod16.z.number().int(),
|
|
3965
4263
|
transactionCount: NonNegativeInt,
|
|
3966
4264
|
currency: Currency2,
|
|
3967
|
-
hashChainPrev:
|
|
4265
|
+
hashChainPrev: HexString(32).optional()
|
|
3968
4266
|
}).refine((v) => v.periodEndMs > v.periodStartMs, {
|
|
3969
4267
|
message: "periodEndMs must be greater than periodStartMs",
|
|
3970
4268
|
path: ["periodEndMs"]
|
|
@@ -3997,7 +4295,7 @@ var IdentityArtifactSchema = import_zod16.z.object({
|
|
|
3997
4295
|
"kyc_tier",
|
|
3998
4296
|
"age_band"
|
|
3999
4297
|
]),
|
|
4000
|
-
claimValueHash:
|
|
4298
|
+
claimValueHash: HexString(32),
|
|
4001
4299
|
attestedAtMs: PositiveInt
|
|
4002
4300
|
});
|
|
4003
4301
|
var ARTIFACT_BODY_SCHEMAS = {
|
|
@@ -4061,7 +4359,7 @@ function createArtifactUri(input) {
|
|
|
4061
4359
|
const signed = signArtifact(body, input.privateKey);
|
|
4062
4360
|
return { uri: encodeArtifactUri(signed), signed };
|
|
4063
4361
|
}
|
|
4064
|
-
function verifyArtifactUri(uri,
|
|
4362
|
+
function verifyArtifactUri(uri, publicKeySpkiB64, options = {}) {
|
|
4065
4363
|
const decoded = decodeArtifactUri(uri);
|
|
4066
4364
|
if (!isKnownArtifactType(decoded.type)) {
|
|
4067
4365
|
throw new FlurArtifactError(
|
|
@@ -4083,7 +4381,7 @@ function verifyArtifactUri(uri, publicKey, options = {}) {
|
|
|
4083
4381
|
"INVALID_BODY"
|
|
4084
4382
|
);
|
|
4085
4383
|
}
|
|
4086
|
-
const ok = verifyArtifactSignature(decoded,
|
|
4384
|
+
const ok = verifyArtifactSignature(decoded, publicKeySpkiB64, options);
|
|
4087
4385
|
if (!ok) {
|
|
4088
4386
|
throw new FlurArtifactError(
|
|
4089
4387
|
"Artifact signature verification failed",
|
|
@@ -4120,6 +4418,8 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4120
4418
|
AccountSchema,
|
|
4121
4419
|
ApiCredentialPublicSchema,
|
|
4122
4420
|
ArtifactHeaderSchema,
|
|
4421
|
+
AttestationSecurityLevelSchema,
|
|
4422
|
+
CLAIM_DOMAIN_V2,
|
|
4123
4423
|
COLLECTION_INTENT_STATUSES,
|
|
4124
4424
|
COLLECTION_PAYMENT_STATUSES,
|
|
4125
4425
|
CUSTODIAL_MODES,
|
|
@@ -4138,6 +4438,7 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4138
4438
|
CreatePayoutInputSchema,
|
|
4139
4439
|
CreateWithdrawalInputSchema,
|
|
4140
4440
|
CreateWithdrawalResultSchema,
|
|
4441
|
+
DeviceKeyAlgSchema,
|
|
4141
4442
|
DeviceKeyRecordSchema,
|
|
4142
4443
|
DisableOfflineInputSchema,
|
|
4143
4444
|
DisableOfflineResultSchema,
|
|
@@ -4174,6 +4475,7 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4174
4475
|
OAC_DEFAULT_CUMULATIVE_KOBO,
|
|
4175
4476
|
OAC_DEFAULT_PER_TX_KOBO,
|
|
4176
4477
|
OAC_DEFAULT_VALIDITY_MS,
|
|
4478
|
+
OFFLINE_CLAIM_SMS_PREFIX,
|
|
4177
4479
|
OfflineClaimArtifactSchema,
|
|
4178
4480
|
OfflineHoldRecordSchema,
|
|
4179
4481
|
OfflinePaymentAuthorizationArtifactSchema,
|
|
@@ -4182,6 +4484,8 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4182
4484
|
OfflineStateResultSchema,
|
|
4183
4485
|
OfflineStatusResultSchema,
|
|
4184
4486
|
OfflineTokenSchema,
|
|
4487
|
+
P256EnrollmentChallengeInputSchema,
|
|
4488
|
+
P256EnrollmentChallengeResultSchema,
|
|
4185
4489
|
PARTNER_FUNDING_DIRECTIONS,
|
|
4186
4490
|
PARTNER_FUNDING_STATUSES,
|
|
4187
4491
|
PARTNER_KINDS,
|
|
@@ -4205,6 +4509,8 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4205
4509
|
PayoutEventInputSchema,
|
|
4206
4510
|
ProviderEventInputSchema,
|
|
4207
4511
|
ProviderEventRecordSchema,
|
|
4512
|
+
ProvisionOfflineAllowanceInputSchema,
|
|
4513
|
+
ProvisionOfflineAllowanceResultSchema,
|
|
4208
4514
|
PublicCollectionIntentSchema,
|
|
4209
4515
|
RECEIPT_CHANNELS,
|
|
4210
4516
|
RECEIPT_KINDS,
|
|
@@ -4216,6 +4522,7 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4216
4522
|
RecordPayoutEventResultSchema,
|
|
4217
4523
|
RedemptionSchema,
|
|
4218
4524
|
RegisterDeviceKeyInputSchema,
|
|
4525
|
+
RegisterDeviceKeyP256InputSchema,
|
|
4219
4526
|
ReversalRecordArtifactSchema,
|
|
4220
4527
|
RevokeDeviceKeyInputSchema,
|
|
4221
4528
|
SETTLEMENT_SCHEDULES,
|
|
@@ -4238,6 +4545,8 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4238
4545
|
buildPaymentRequest,
|
|
4239
4546
|
buildReceipt,
|
|
4240
4547
|
buildRedemption,
|
|
4548
|
+
canonicalClaimSigningBytes,
|
|
4549
|
+
canonicalClaimSigningPayload,
|
|
4241
4550
|
canonicalJSONBytes,
|
|
4242
4551
|
canonicalJSONStringify,
|
|
4243
4552
|
canonicalRequestString,
|
|
@@ -4262,18 +4571,21 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4262
4571
|
createPassesClient,
|
|
4263
4572
|
createReceiptArtifactUri,
|
|
4264
4573
|
createReceiptsClient,
|
|
4574
|
+
createSoftwareP256Signer,
|
|
4265
4575
|
decodeArtifactUri,
|
|
4266
4576
|
decodeAuthorizationQR,
|
|
4267
4577
|
decodeBase45,
|
|
4578
|
+
decodeOfflineClaimSmsMessage,
|
|
4268
4579
|
decodePaymentRequestQR,
|
|
4269
4580
|
encodeArtifactUri,
|
|
4270
4581
|
encodeAuthorizationQR,
|
|
4271
4582
|
encodeBase45,
|
|
4272
4583
|
encodeNQR,
|
|
4584
|
+
encodeOfflineClaimSmsMessage,
|
|
4273
4585
|
encodePaymentRequestQR,
|
|
4586
|
+
extractOfflineClaimSmsToken,
|
|
4274
4587
|
formatAmount,
|
|
4275
4588
|
generateDynamicQR,
|
|
4276
|
-
generateKeyPair,
|
|
4277
4589
|
generateStaticQR,
|
|
4278
4590
|
init,
|
|
4279
4591
|
isHardenedArtifactType,
|
|
@@ -4284,13 +4596,10 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4284
4596
|
parseAmountInput,
|
|
4285
4597
|
parseNQR,
|
|
4286
4598
|
parseQR,
|
|
4287
|
-
publicKeyFromPrivate,
|
|
4288
4599
|
readTLV,
|
|
4289
4600
|
routingHint,
|
|
4290
|
-
sign,
|
|
4291
4601
|
signArtifact,
|
|
4292
4602
|
signAuthorization,
|
|
4293
|
-
signCanonical,
|
|
4294
4603
|
signOAC,
|
|
4295
4604
|
signPartnerRequest,
|
|
4296
4605
|
signPass,
|
|
@@ -4298,11 +4607,10 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
|
|
|
4298
4607
|
signReceipt,
|
|
4299
4608
|
signRedemption,
|
|
4300
4609
|
signRequestHMAC,
|
|
4301
|
-
verify,
|
|
4302
4610
|
verifyArtifactSignature,
|
|
4303
4611
|
verifyArtifactUri,
|
|
4304
4612
|
verifyAuthorization,
|
|
4305
|
-
|
|
4613
|
+
verifyClaimSignature,
|
|
4306
4614
|
verifyOAC,
|
|
4307
4615
|
verifyPass,
|
|
4308
4616
|
verifyPaymentRequest,
|