@zkp2p/pay-shared 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/addressEncoding.d.ts +5 -0
- package/dist/addressEncoding.js +126 -0
- package/dist/addressValidators.d.ts +2 -0
- package/dist/addressValidators.js +14 -0
- package/dist/bitcoin.js +71 -5
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/onboarding.d.ts +39 -0
- package/dist/onboarding.js +150 -0
- package/dist/payeeFeeCap.d.ts +21 -0
- package/dist/payeeFeeCap.js +105 -0
- package/dist/types.d.ts +68 -19
- package/dist/types.js +17 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function sha256(value: Uint8Array): Uint8Array;
|
|
2
|
+
export declare function doubleSha256(value: Uint8Array): Uint8Array;
|
|
3
|
+
export declare function decodeBase58(value: string): Uint8Array | null;
|
|
4
|
+
export declare function encodeBase58(value: Uint8Array): string;
|
|
5
|
+
export declare function hasBase58CheckChecksum(value: string, version: number): boolean;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
2
|
+
const SHA256_CONSTANTS = new Uint32Array([
|
|
3
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
|
4
|
+
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
5
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
|
6
|
+
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
7
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
|
8
|
+
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
9
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
|
10
|
+
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
11
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
|
12
|
+
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
13
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
|
14
|
+
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
15
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
|
16
|
+
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
17
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
18
|
+
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
19
|
+
]);
|
|
20
|
+
function rotateRight(value, shift) {
|
|
21
|
+
return (value >>> shift) | (value << (32 - shift));
|
|
22
|
+
}
|
|
23
|
+
export function sha256(value) {
|
|
24
|
+
const paddedLength = Math.ceil((value.length + 9) / 64) * 64;
|
|
25
|
+
const message = new Uint8Array(paddedLength);
|
|
26
|
+
message.set(value);
|
|
27
|
+
message[value.length] = 0x80;
|
|
28
|
+
const bitLength = BigInt(value.length) * 8n;
|
|
29
|
+
const view = new DataView(message.buffer);
|
|
30
|
+
view.setUint32(paddedLength - 8, Number(bitLength >> 32n), false);
|
|
31
|
+
view.setUint32(paddedLength - 4, Number(bitLength & 0xffffffffn), false);
|
|
32
|
+
const hash = new Uint32Array([
|
|
33
|
+
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
|
34
|
+
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
|
|
35
|
+
]);
|
|
36
|
+
const words = new Uint32Array(64);
|
|
37
|
+
for (let offset = 0; offset < paddedLength; offset += 64) {
|
|
38
|
+
for (let index = 0; index < 16; index += 1) {
|
|
39
|
+
words[index] = view.getUint32(offset + (index * 4), false);
|
|
40
|
+
}
|
|
41
|
+
for (let index = 16; index < 64; index += 1) {
|
|
42
|
+
const previous15 = words[index - 15];
|
|
43
|
+
const previous2 = words[index - 2];
|
|
44
|
+
const sigma0 = rotateRight(previous15, 7) ^ rotateRight(previous15, 18) ^ (previous15 >>> 3);
|
|
45
|
+
const sigma1 = rotateRight(previous2, 17) ^ rotateRight(previous2, 19) ^ (previous2 >>> 10);
|
|
46
|
+
words[index] = (words[index - 16] + sigma0 + words[index - 7] + sigma1) >>> 0;
|
|
47
|
+
}
|
|
48
|
+
let [a, b, c, d, e, f, g, h] = hash;
|
|
49
|
+
for (let index = 0; index < 64; index += 1) {
|
|
50
|
+
const sum1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
|
|
51
|
+
const choice = (e & f) ^ (~e & g);
|
|
52
|
+
const temporary1 = (h + sum1 + choice + SHA256_CONSTANTS[index] + words[index]) >>> 0;
|
|
53
|
+
const sum0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22);
|
|
54
|
+
const majority = (a & b) ^ (a & c) ^ (b & c);
|
|
55
|
+
const temporary2 = (sum0 + majority) >>> 0;
|
|
56
|
+
h = g;
|
|
57
|
+
g = f;
|
|
58
|
+
f = e;
|
|
59
|
+
e = (d + temporary1) >>> 0;
|
|
60
|
+
d = c;
|
|
61
|
+
c = b;
|
|
62
|
+
b = a;
|
|
63
|
+
a = (temporary1 + temporary2) >>> 0;
|
|
64
|
+
}
|
|
65
|
+
hash[0] = (hash[0] + a) >>> 0;
|
|
66
|
+
hash[1] = (hash[1] + b) >>> 0;
|
|
67
|
+
hash[2] = (hash[2] + c) >>> 0;
|
|
68
|
+
hash[3] = (hash[3] + d) >>> 0;
|
|
69
|
+
hash[4] = (hash[4] + e) >>> 0;
|
|
70
|
+
hash[5] = (hash[5] + f) >>> 0;
|
|
71
|
+
hash[6] = (hash[6] + g) >>> 0;
|
|
72
|
+
hash[7] = (hash[7] + h) >>> 0;
|
|
73
|
+
}
|
|
74
|
+
const digest = new Uint8Array(32);
|
|
75
|
+
const digestView = new DataView(digest.buffer);
|
|
76
|
+
hash.forEach((word, index) => digestView.setUint32(index * 4, word, false));
|
|
77
|
+
return digest;
|
|
78
|
+
}
|
|
79
|
+
export function doubleSha256(value) {
|
|
80
|
+
return sha256(sha256(value));
|
|
81
|
+
}
|
|
82
|
+
export function decodeBase58(value) {
|
|
83
|
+
let decodedValue = 0n;
|
|
84
|
+
for (const character of value) {
|
|
85
|
+
const digit = BASE58_ALPHABET.indexOf(character);
|
|
86
|
+
if (digit === -1) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
decodedValue = (decodedValue * 58n) + BigInt(digit);
|
|
90
|
+
}
|
|
91
|
+
const bytes = [];
|
|
92
|
+
while (decodedValue > 0n) {
|
|
93
|
+
bytes.push(Number(decodedValue & 0xffn));
|
|
94
|
+
decodedValue >>= 8n;
|
|
95
|
+
}
|
|
96
|
+
bytes.reverse();
|
|
97
|
+
const leadingZeroes = value.match(/^1*/)?.[0].length ?? 0;
|
|
98
|
+
const decoded = new Uint8Array(leadingZeroes + bytes.length);
|
|
99
|
+
decoded.set(bytes, leadingZeroes);
|
|
100
|
+
return decoded;
|
|
101
|
+
}
|
|
102
|
+
export function encodeBase58(value) {
|
|
103
|
+
let encodedValue = 0n;
|
|
104
|
+
for (const byte of value) {
|
|
105
|
+
encodedValue = (encodedValue << 8n) + BigInt(byte);
|
|
106
|
+
}
|
|
107
|
+
let encoded = '';
|
|
108
|
+
while (encodedValue > 0n) {
|
|
109
|
+
encoded = BASE58_ALPHABET[Number(encodedValue % 58n)] + encoded;
|
|
110
|
+
encodedValue /= 58n;
|
|
111
|
+
}
|
|
112
|
+
let leadingZeroes = 0;
|
|
113
|
+
while (leadingZeroes < value.length && value[leadingZeroes] === 0) {
|
|
114
|
+
leadingZeroes += 1;
|
|
115
|
+
}
|
|
116
|
+
return '1'.repeat(leadingZeroes) + encoded;
|
|
117
|
+
}
|
|
118
|
+
export function hasBase58CheckChecksum(value, version) {
|
|
119
|
+
const decoded = decodeBase58(value);
|
|
120
|
+
if (decoded === null || decoded.length !== 25 || decoded[0] !== version) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
const payload = decoded.subarray(0, 21);
|
|
124
|
+
const expectedChecksum = doubleSha256(payload).subarray(0, 4);
|
|
125
|
+
return decoded.subarray(21).every((byte, index) => byte === expectedChecksum[index]);
|
|
126
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { decodeBase58, encodeBase58, hasBase58CheckChecksum, } from './addressEncoding.js';
|
|
2
|
+
export function isValidSolanaAddress(value) {
|
|
3
|
+
if (!/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(value)) {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
const decoded = decodeBase58(value);
|
|
7
|
+
return decoded !== null
|
|
8
|
+
&& decoded.length === 32
|
|
9
|
+
&& encodeBase58(decoded) === value;
|
|
10
|
+
}
|
|
11
|
+
export function isValidTronAddress(value) {
|
|
12
|
+
return /^T[1-9A-HJ-NP-Za-km-z]{33}$/.test(value)
|
|
13
|
+
&& hasBase58CheckChecksum(value, 0x41);
|
|
14
|
+
}
|
package/dist/bitcoin.js
CHANGED
|
@@ -1,13 +1,79 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
1
|
+
import { hasBase58CheckChecksum } from './addressEncoding.js';
|
|
2
|
+
const BECH32_ALPHABET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
|
|
3
|
+
const BECH32_CHECKSUM = 1;
|
|
4
|
+
const BECH32M_CHECKSUM = 0x2bc830a3;
|
|
5
|
+
function calculatePolymod(values) {
|
|
6
|
+
const generators = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
|
|
7
|
+
let checksum = 1;
|
|
8
|
+
for (const value of values) {
|
|
9
|
+
const highBits = checksum >>> 25;
|
|
10
|
+
checksum = (((checksum & 0x1ffffff) << 5) ^ value) >>> 0;
|
|
11
|
+
for (let index = 0; index < generators.length; index += 1) {
|
|
12
|
+
if (((highBits >>> index) & 1) !== 0) {
|
|
13
|
+
checksum = (checksum ^ generators[index]) >>> 0;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return checksum;
|
|
18
|
+
}
|
|
19
|
+
function convertWitnessProgram(values) {
|
|
20
|
+
const decoded = [];
|
|
21
|
+
let accumulator = 0;
|
|
22
|
+
let bits = 0;
|
|
23
|
+
for (const value of values) {
|
|
24
|
+
accumulator = (accumulator << 5) | value;
|
|
25
|
+
bits += 5;
|
|
26
|
+
while (bits >= 8) {
|
|
27
|
+
bits -= 8;
|
|
28
|
+
decoded.push((accumulator >>> bits) & 0xff);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (bits >= 5 || ((accumulator << (8 - bits)) & 0xff) !== 0) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return Uint8Array.from(decoded);
|
|
35
|
+
}
|
|
36
|
+
function isValidBech32Address(value) {
|
|
37
|
+
if (value.length > 90 || (value !== value.toLowerCase() && value !== value.toUpperCase())) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const normalized = value.toLowerCase();
|
|
41
|
+
const separatorIndex = normalized.lastIndexOf('1');
|
|
42
|
+
if (separatorIndex !== 2 || normalized.slice(0, separatorIndex) !== 'bc') {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
const data = [...normalized.slice(separatorIndex + 1)]
|
|
46
|
+
.map((character) => BECH32_ALPHABET.indexOf(character));
|
|
47
|
+
if (data.length < 7 || data.some((item) => item === -1)) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const hrpValues = [
|
|
51
|
+
...[...'bc'].map((character) => character.charCodeAt(0) >>> 5),
|
|
52
|
+
0,
|
|
53
|
+
...[...'bc'].map((character) => character.charCodeAt(0) & 31),
|
|
54
|
+
];
|
|
55
|
+
const witnessVersion = data[0];
|
|
56
|
+
const polymod = calculatePolymod([...hrpValues, ...data]);
|
|
57
|
+
if (witnessVersion > 16
|
|
58
|
+
|| (witnessVersion === 0 && polymod !== BECH32_CHECKSUM)
|
|
59
|
+
|| (witnessVersion > 0 && polymod !== BECH32M_CHECKSUM)) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
const witnessProgram = convertWitnessProgram(data.slice(1, -6));
|
|
63
|
+
if (witnessProgram === null || witnessProgram.length < 2 || witnessProgram.length > 40) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return witnessVersion !== 0 || witnessProgram.length === 20 || witnessProgram.length === 32;
|
|
67
|
+
}
|
|
3
68
|
export function isValidBitcoinAddress(value) {
|
|
4
69
|
const trimmed = value.trim();
|
|
5
70
|
if (!trimmed) {
|
|
6
71
|
return false;
|
|
7
72
|
}
|
|
8
73
|
if (trimmed.toLowerCase().startsWith('bc1')) {
|
|
9
|
-
|
|
10
|
-
return isUniformCase && BITCOIN_BECH32_ADDRESS_REGEX.test(trimmed);
|
|
74
|
+
return isValidBech32Address(trimmed);
|
|
11
75
|
}
|
|
12
|
-
return
|
|
76
|
+
return /^[13][1-9A-HJ-NP-Za-km-z]{25,34}$/.test(trimmed)
|
|
77
|
+
&& (hasBase58CheckChecksum(trimmed, 0x00)
|
|
78
|
+
|| hasBase58CheckChecksum(trimmed, 0x05));
|
|
13
79
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,9 @@ export * from './crypto.js';
|
|
|
5
5
|
export * from './rails.js';
|
|
6
6
|
export * from './buyerTee.js';
|
|
7
7
|
export * from './bitcoin.js';
|
|
8
|
+
export * from './addressValidators.js';
|
|
8
9
|
export * from './fiatAmount.js';
|
|
9
10
|
export * from './paypalSarPhase.js';
|
|
10
11
|
export * from './paypalSarVerify.js';
|
|
12
|
+
export * from './payeeFeeCap.js';
|
|
13
|
+
export * from './onboarding.js';
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,9 @@ export * from './crypto.js';
|
|
|
5
5
|
export * from './rails.js';
|
|
6
6
|
export * from './buyerTee.js';
|
|
7
7
|
export * from './bitcoin.js';
|
|
8
|
+
export * from './addressValidators.js';
|
|
8
9
|
export * from './fiatAmount.js';
|
|
9
10
|
export * from './paypalSarPhase.js';
|
|
10
11
|
export * from './paypalSarVerify.js';
|
|
12
|
+
export * from './payeeFeeCap.js';
|
|
13
|
+
export * from './onboarding.js';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { MerchantIntegrationPathValue, OnboardingStepState, OnboardingStepVerifiedByValue } from './types.js';
|
|
2
|
+
export type OnboardingFacts = {
|
|
3
|
+
hasName: boolean;
|
|
4
|
+
hasLogo: boolean;
|
|
5
|
+
hasIndustry: boolean;
|
|
6
|
+
hasIntegrationPath: boolean;
|
|
7
|
+
hasWebhook: boolean;
|
|
8
|
+
hasSandboxOrder: boolean;
|
|
9
|
+
hasSandboxFulfilledOrder: boolean;
|
|
10
|
+
hasLiveOrder: boolean;
|
|
11
|
+
hasLiveFulfilledOrder: boolean;
|
|
12
|
+
manualSteps: readonly string[];
|
|
13
|
+
};
|
|
14
|
+
export declare const OnboardingStepId: {
|
|
15
|
+
readonly PROFILE: "profile";
|
|
16
|
+
readonly INDUSTRY: "industry";
|
|
17
|
+
readonly PATH: "path";
|
|
18
|
+
readonly RAILS: "rails";
|
|
19
|
+
readonly INTEGRATION: "integration";
|
|
20
|
+
readonly WEBHOOK: "webhook";
|
|
21
|
+
readonly GO_LIVE: "goLive";
|
|
22
|
+
readonly DOWNLOAD_PLUGIN: "downloadPlugin";
|
|
23
|
+
readonly PLUGIN_API_KEY: "pluginApiKey";
|
|
24
|
+
readonly TEST_ORDER: "testOrder";
|
|
25
|
+
readonly FIRST_QR: "firstQr";
|
|
26
|
+
readonly LINK_BOT: "linkBot";
|
|
27
|
+
readonly REQUEST_SETUP: "requestSetup";
|
|
28
|
+
};
|
|
29
|
+
export type OnboardingStepIdValue = typeof OnboardingStepId[keyof typeof OnboardingStepId];
|
|
30
|
+
export type OnboardingStepRegistryEntry = {
|
|
31
|
+
readonly id: OnboardingStepIdValue;
|
|
32
|
+
readonly paths: readonly MerchantIntegrationPathValue[] | 'ALL';
|
|
33
|
+
readonly verifiedBy: OnboardingStepVerifiedByValue;
|
|
34
|
+
readonly inChecklist: boolean;
|
|
35
|
+
readonly impliesPrevious: boolean;
|
|
36
|
+
};
|
|
37
|
+
export declare const ONBOARDING_STEP_REGISTRY: readonly OnboardingStepRegistryEntry[];
|
|
38
|
+
export declare function resolveOnboardingSteps(facts: OnboardingFacts, path: MerchantIntegrationPathValue | null): OnboardingStepState[];
|
|
39
|
+
export declare function isOnboardingComplete(steps: readonly OnboardingStepState[]): boolean;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { MerchantIntegrationPath, OnboardingStepStatus, OnboardingStepVerifiedBy, } from './types.js';
|
|
2
|
+
export const OnboardingStepId = {
|
|
3
|
+
PROFILE: 'profile',
|
|
4
|
+
INDUSTRY: 'industry',
|
|
5
|
+
PATH: 'path',
|
|
6
|
+
RAILS: 'rails',
|
|
7
|
+
INTEGRATION: 'integration',
|
|
8
|
+
WEBHOOK: 'webhook',
|
|
9
|
+
GO_LIVE: 'goLive',
|
|
10
|
+
DOWNLOAD_PLUGIN: 'downloadPlugin',
|
|
11
|
+
PLUGIN_API_KEY: 'pluginApiKey',
|
|
12
|
+
TEST_ORDER: 'testOrder',
|
|
13
|
+
FIRST_QR: 'firstQr',
|
|
14
|
+
LINK_BOT: 'linkBot',
|
|
15
|
+
REQUEST_SETUP: 'requestSetup',
|
|
16
|
+
};
|
|
17
|
+
export const ONBOARDING_STEP_REGISTRY = [
|
|
18
|
+
{ id: OnboardingStepId.PROFILE, paths: 'ALL', verifiedBy: OnboardingStepVerifiedBy.AUTO, inChecklist: true, impliesPrevious: true },
|
|
19
|
+
{ id: OnboardingStepId.INDUSTRY, paths: 'ALL', verifiedBy: OnboardingStepVerifiedBy.AUTO, inChecklist: true, impliesPrevious: true },
|
|
20
|
+
{
|
|
21
|
+
id: OnboardingStepId.RAILS,
|
|
22
|
+
paths: 'ALL',
|
|
23
|
+
verifiedBy: OnboardingStepVerifiedBy.AUTO,
|
|
24
|
+
inChecklist: false,
|
|
25
|
+
// This step is unconditionally satisfied and carries no information, so allowing
|
|
26
|
+
// it to imply earlier steps would mark every merchant's onboarding complete.
|
|
27
|
+
impliesPrevious: false,
|
|
28
|
+
},
|
|
29
|
+
{ id: OnboardingStepId.PATH, paths: 'ALL', verifiedBy: OnboardingStepVerifiedBy.AUTO, inChecklist: true, impliesPrevious: true },
|
|
30
|
+
{
|
|
31
|
+
id: OnboardingStepId.INTEGRATION,
|
|
32
|
+
paths: [MerchantIntegrationPath.CUSTOM_API],
|
|
33
|
+
verifiedBy: OnboardingStepVerifiedBy.AUTO,
|
|
34
|
+
inChecklist: true,
|
|
35
|
+
impliesPrevious: true,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: OnboardingStepId.WEBHOOK,
|
|
39
|
+
paths: [MerchantIntegrationPath.CUSTOM_API],
|
|
40
|
+
verifiedBy: OnboardingStepVerifiedBy.AUTO,
|
|
41
|
+
inChecklist: true,
|
|
42
|
+
impliesPrevious: false,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: OnboardingStepId.LINK_BOT,
|
|
46
|
+
paths: [MerchantIntegrationPath.TELEGRAM],
|
|
47
|
+
verifiedBy: OnboardingStepVerifiedBy.AUTO,
|
|
48
|
+
inChecklist: true,
|
|
49
|
+
impliesPrevious: true,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: OnboardingStepId.GO_LIVE,
|
|
53
|
+
paths: [MerchantIntegrationPath.CUSTOM_API, MerchantIntegrationPath.TELEGRAM],
|
|
54
|
+
verifiedBy: OnboardingStepVerifiedBy.AUTO,
|
|
55
|
+
inChecklist: true,
|
|
56
|
+
impliesPrevious: true,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: OnboardingStepId.DOWNLOAD_PLUGIN,
|
|
60
|
+
paths: [MerchantIntegrationPath.WOOCOMMERCE],
|
|
61
|
+
verifiedBy: OnboardingStepVerifiedBy.MANUAL,
|
|
62
|
+
inChecklist: true,
|
|
63
|
+
impliesPrevious: true,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: OnboardingStepId.PLUGIN_API_KEY,
|
|
67
|
+
paths: [MerchantIntegrationPath.WOOCOMMERCE],
|
|
68
|
+
verifiedBy: OnboardingStepVerifiedBy.MANUAL,
|
|
69
|
+
inChecklist: true,
|
|
70
|
+
impliesPrevious: true,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: OnboardingStepId.TEST_ORDER,
|
|
74
|
+
paths: [MerchantIntegrationPath.WOOCOMMERCE],
|
|
75
|
+
verifiedBy: OnboardingStepVerifiedBy.AUTO,
|
|
76
|
+
inChecklist: true,
|
|
77
|
+
impliesPrevious: true,
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: OnboardingStepId.GO_LIVE,
|
|
81
|
+
paths: [MerchantIntegrationPath.WOOCOMMERCE],
|
|
82
|
+
verifiedBy: OnboardingStepVerifiedBy.AUTO,
|
|
83
|
+
inChecklist: true,
|
|
84
|
+
impliesPrevious: true,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: OnboardingStepId.FIRST_QR,
|
|
88
|
+
paths: [MerchantIntegrationPath.IN_PERSON],
|
|
89
|
+
verifiedBy: OnboardingStepVerifiedBy.AUTO,
|
|
90
|
+
inChecklist: true,
|
|
91
|
+
// In-person merchants only need to show a Scan to Pay QR. Waiting for a real
|
|
92
|
+
// customer payment would leave unopened shops stuck in onboarding.
|
|
93
|
+
impliesPrevious: true,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: OnboardingStepId.REQUEST_SETUP,
|
|
97
|
+
paths: [MerchantIntegrationPath.SHOPIFY],
|
|
98
|
+
verifiedBy: OnboardingStepVerifiedBy.MANUAL,
|
|
99
|
+
inChecklist: true,
|
|
100
|
+
impliesPrevious: true,
|
|
101
|
+
},
|
|
102
|
+
];
|
|
103
|
+
const autoStepPredicates = {
|
|
104
|
+
[OnboardingStepId.PROFILE]: (facts) => facts.hasName && facts.hasLogo,
|
|
105
|
+
[OnboardingStepId.INDUSTRY]: (facts) => facts.hasIndustry,
|
|
106
|
+
[OnboardingStepId.PATH]: (facts) => facts.hasIntegrationPath,
|
|
107
|
+
[OnboardingStepId.RAILS]: () => true,
|
|
108
|
+
[OnboardingStepId.INTEGRATION]: (facts) => facts.hasSandboxFulfilledOrder,
|
|
109
|
+
[OnboardingStepId.WEBHOOK]: (facts) => facts.hasWebhook,
|
|
110
|
+
[OnboardingStepId.TEST_ORDER]: (facts) => facts.hasSandboxFulfilledOrder,
|
|
111
|
+
[OnboardingStepId.LINK_BOT]: (facts) => facts.hasSandboxFulfilledOrder,
|
|
112
|
+
[OnboardingStepId.GO_LIVE]: (facts) => facts.hasLiveFulfilledOrder,
|
|
113
|
+
[OnboardingStepId.FIRST_QR]: (facts) => facts.hasSandboxOrder,
|
|
114
|
+
};
|
|
115
|
+
export function resolveOnboardingSteps(facts, path) {
|
|
116
|
+
const entries = ONBOARDING_STEP_REGISTRY.filter((entry) => entry.paths === 'ALL' || (path !== null && entry.paths.includes(path)));
|
|
117
|
+
// Load-bearing override: merchants already taking payments must remain free of
|
|
118
|
+
// the onboarding checklist, even when they have no selected integration path.
|
|
119
|
+
if (facts.hasLiveFulfilledOrder) {
|
|
120
|
+
return entries.map((entry) => ({
|
|
121
|
+
id: entry.id,
|
|
122
|
+
status: OnboardingStepStatus.DONE,
|
|
123
|
+
verifiedBy: entry.verifiedBy,
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
126
|
+
const steps = entries.map((entry) => {
|
|
127
|
+
const isDone = entry.verifiedBy === OnboardingStepVerifiedBy.MANUAL
|
|
128
|
+
? facts.manualSteps.includes(entry.id)
|
|
129
|
+
: autoStepPredicates[entry.id]?.(facts) ?? false;
|
|
130
|
+
return {
|
|
131
|
+
id: entry.id,
|
|
132
|
+
status: isDone ? OnboardingStepStatus.DONE : OnboardingStepStatus.TODO,
|
|
133
|
+
verifiedBy: entry.verifiedBy,
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
let laterStepIsDone = false;
|
|
137
|
+
for (let index = steps.length - 1; index >= 0; index -= 1) {
|
|
138
|
+
if (laterStepIsDone) {
|
|
139
|
+
steps[index] = { ...steps[index], status: OnboardingStepStatus.DONE };
|
|
140
|
+
}
|
|
141
|
+
else if (steps[index].status === OnboardingStepStatus.DONE
|
|
142
|
+
&& entries[index].impliesPrevious) {
|
|
143
|
+
laterStepIsDone = true;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return steps;
|
|
147
|
+
}
|
|
148
|
+
export function isOnboardingComplete(steps) {
|
|
149
|
+
return steps.every((step) => step.status === OnboardingStepStatus.DONE);
|
|
150
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type PayeeFeeEntry = {
|
|
2
|
+
readonly recipient: string;
|
|
3
|
+
readonly feeBps: number;
|
|
4
|
+
};
|
|
5
|
+
export type PayeeReferralFeeCapacityResult = {
|
|
6
|
+
readonly referralFees: PayeeFeeEntry[];
|
|
7
|
+
readonly configuredPlatformReferralFeeBps: number;
|
|
8
|
+
readonly adjustedPlatformReferralFeeBps: number;
|
|
9
|
+
readonly otherReferralFeeAmount: string;
|
|
10
|
+
readonly platformFeeCapacityAmount: string;
|
|
11
|
+
readonly insufficientCapacity: boolean;
|
|
12
|
+
readonly requiredNetCovered: boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare function resolvePayeeReferralFeeCapacity(input: {
|
|
15
|
+
readonly grossSignalAmount: string;
|
|
16
|
+
readonly quotedTokenOutput: string;
|
|
17
|
+
readonly requiredNetAmount: string;
|
|
18
|
+
readonly platformRecipient: string;
|
|
19
|
+
readonly referralFees: readonly PayeeFeeEntry[];
|
|
20
|
+
}): PayeeReferralFeeCapacityResult;
|
|
21
|
+
export declare function computeNetAfterPreciseFees(grossAmount: string, feeRates18dec: readonly string[]): string;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const BPS_DENOMINATOR = 10000n;
|
|
2
|
+
const PRECISE_FEE_DENOMINATOR = 10n ** 18n;
|
|
3
|
+
const UNSIGNED_INTEGER_PATTERN = /^\d+$/;
|
|
4
|
+
export function resolvePayeeReferralFeeCapacity(input) {
|
|
5
|
+
const grossSignalAmount = parsePositiveUnits(input.grossSignalAmount, 'gross signal amount');
|
|
6
|
+
const quotedTokenOutput = parsePositiveUnits(input.quotedTokenOutput, 'quoted token output');
|
|
7
|
+
const requiredNetAmount = parsePositiveUnits(input.requiredNetAmount, 'required net amount');
|
|
8
|
+
if (quotedTokenOutput > grossSignalAmount) {
|
|
9
|
+
throw new RangeError('Quoted token output cannot exceed gross signal amount');
|
|
10
|
+
}
|
|
11
|
+
const platformRecipient = input.platformRecipient.trim().toLowerCase();
|
|
12
|
+
if (platformRecipient === '') {
|
|
13
|
+
throw new RangeError('Platform recipient is required');
|
|
14
|
+
}
|
|
15
|
+
const platformEntries = input.referralFees.filter((entry) => entry.recipient.trim().toLowerCase() === platformRecipient);
|
|
16
|
+
if (platformEntries.length > 1) {
|
|
17
|
+
throw new RangeError('Duplicate platform referral fee entries');
|
|
18
|
+
}
|
|
19
|
+
input.referralFees.forEach(validateFeeEntry);
|
|
20
|
+
const configuredPlatformReferralFeeBps = platformEntries[0]?.feeBps ?? 0;
|
|
21
|
+
const otherReferralFeeAmount = input.referralFees.reduce((total, entry) => {
|
|
22
|
+
if (entry.recipient.trim().toLowerCase() === platformRecipient) {
|
|
23
|
+
return total;
|
|
24
|
+
}
|
|
25
|
+
return total + computeBpsFee(grossSignalAmount, entry.feeBps);
|
|
26
|
+
}, 0n);
|
|
27
|
+
const platformFeeCapacityAmount = quotedTokenOutput - requiredNetAmount - otherReferralFeeAmount;
|
|
28
|
+
const insufficientCapacity = platformFeeCapacityAmount < 0n;
|
|
29
|
+
const adjustedPlatformReferralFeeBps = insufficientCapacity
|
|
30
|
+
? 0
|
|
31
|
+
: findLargestFittingBps(grossSignalAmount, platformFeeCapacityAmount, configuredPlatformReferralFeeBps);
|
|
32
|
+
const adjustedPlatformFeeAmount = computeBpsFee(grossSignalAmount, adjustedPlatformReferralFeeBps);
|
|
33
|
+
const requiredNetCovered = quotedTokenOutput
|
|
34
|
+
- otherReferralFeeAmount
|
|
35
|
+
- adjustedPlatformFeeAmount >= requiredNetAmount;
|
|
36
|
+
return {
|
|
37
|
+
referralFees: input.referralFees.flatMap((entry) => {
|
|
38
|
+
if (entry.recipient.trim().toLowerCase() !== platformRecipient) {
|
|
39
|
+
return [{ ...entry }];
|
|
40
|
+
}
|
|
41
|
+
return adjustedPlatformReferralFeeBps === 0
|
|
42
|
+
? []
|
|
43
|
+
: [{ ...entry, feeBps: adjustedPlatformReferralFeeBps }];
|
|
44
|
+
}),
|
|
45
|
+
configuredPlatformReferralFeeBps,
|
|
46
|
+
adjustedPlatformReferralFeeBps,
|
|
47
|
+
otherReferralFeeAmount: otherReferralFeeAmount.toString(),
|
|
48
|
+
platformFeeCapacityAmount: platformFeeCapacityAmount.toString(),
|
|
49
|
+
insufficientCapacity,
|
|
50
|
+
requiredNetCovered,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function computeNetAfterPreciseFees(grossAmount, feeRates18dec) {
|
|
54
|
+
const gross = parsePositiveUnits(grossAmount, 'gross amount');
|
|
55
|
+
const totalFees = feeRates18dec.reduce((total, feeRate) => {
|
|
56
|
+
const rate = parseUnsignedUnits(feeRate, 'precise fee rate');
|
|
57
|
+
if (rate > PRECISE_FEE_DENOMINATOR) {
|
|
58
|
+
throw new RangeError('Precise fee rate cannot exceed 100%');
|
|
59
|
+
}
|
|
60
|
+
return total + (gross * rate / PRECISE_FEE_DENOMINATOR);
|
|
61
|
+
}, 0n);
|
|
62
|
+
if (totalFees > gross) {
|
|
63
|
+
throw new RangeError('Precise fees exceed gross amount');
|
|
64
|
+
}
|
|
65
|
+
return (gross - totalFees).toString();
|
|
66
|
+
}
|
|
67
|
+
function findLargestFittingBps(grossAmount, capacity, configuredBps) {
|
|
68
|
+
let low = 0;
|
|
69
|
+
let high = configuredBps;
|
|
70
|
+
while (low < high) {
|
|
71
|
+
const candidate = Math.ceil((low + high) / 2);
|
|
72
|
+
if (computeBpsFee(grossAmount, candidate) <= capacity) {
|
|
73
|
+
low = candidate;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
high = candidate - 1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return low;
|
|
80
|
+
}
|
|
81
|
+
function computeBpsFee(grossAmount, feeBps) {
|
|
82
|
+
return grossAmount * BigInt(feeBps) / BPS_DENOMINATOR;
|
|
83
|
+
}
|
|
84
|
+
function validateFeeEntry(entry) {
|
|
85
|
+
if (entry.recipient.trim() === '') {
|
|
86
|
+
throw new RangeError('Referral fee recipient is required');
|
|
87
|
+
}
|
|
88
|
+
if (!Number.isInteger(entry.feeBps) || entry.feeBps < 0 || entry.feeBps > 10000) {
|
|
89
|
+
throw new RangeError(`Invalid referral fee bps: ${entry.feeBps}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function parsePositiveUnits(value, label) {
|
|
93
|
+
const parsed = parseUnsignedUnits(value, label);
|
|
94
|
+
if (parsed <= 0n) {
|
|
95
|
+
throw new RangeError(`${label} must be positive`);
|
|
96
|
+
}
|
|
97
|
+
return parsed;
|
|
98
|
+
}
|
|
99
|
+
function parseUnsignedUnits(value, label) {
|
|
100
|
+
const normalized = value.trim();
|
|
101
|
+
if (!UNSIGNED_INTEGER_PATTERN.test(normalized)) {
|
|
102
|
+
throw new RangeError(`${label} must be an unsigned integer`);
|
|
103
|
+
}
|
|
104
|
+
return BigInt(normalized);
|
|
105
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -112,6 +112,7 @@ type CreateOrderRequestBase = {
|
|
|
112
112
|
destinationChainId?: number;
|
|
113
113
|
feePayer?: FeePayerType;
|
|
114
114
|
enabledRails?: string[];
|
|
115
|
+
dynamicOrdersEnabled?: boolean;
|
|
115
116
|
successUrl?: string | null;
|
|
116
117
|
cancelUrl?: string | null;
|
|
117
118
|
notes?: Record<string, unknown> | null;
|
|
@@ -140,6 +141,7 @@ export type MerchantCheckoutTheme = {
|
|
|
140
141
|
buttonTextColor?: string | null;
|
|
141
142
|
defaultMaxFeePercentage?: number;
|
|
142
143
|
payWithCryptoEnabled?: boolean;
|
|
144
|
+
currencySelectorEnabled?: boolean;
|
|
143
145
|
[key: string]: unknown;
|
|
144
146
|
};
|
|
145
147
|
export type CheckoutMerchant = {
|
|
@@ -174,6 +176,11 @@ export type CheckoutOrder = {
|
|
|
174
176
|
cancelUrl: string | null;
|
|
175
177
|
notes: unknown | null;
|
|
176
178
|
metadata: unknown | null;
|
|
179
|
+
/** Merchant-requested fiat price; non-null only for pristine, un-resized fiat-input orders. */
|
|
180
|
+
requestedFiat?: {
|
|
181
|
+
amount: string;
|
|
182
|
+
currency: string;
|
|
183
|
+
} | null;
|
|
177
184
|
bridgeInfo?: OrderBridgeInfo | null;
|
|
178
185
|
referralSplitConfig: ReferralSplitConfig | null;
|
|
179
186
|
cancelledAt: string | null;
|
|
@@ -189,6 +196,7 @@ export type CheckoutPaymentQuote = {
|
|
|
189
196
|
amount: string;
|
|
190
197
|
toAddress: string;
|
|
191
198
|
escrowAddress?: string;
|
|
199
|
+
orchestratorAddress?: string;
|
|
192
200
|
fiatCurrencyCode?: string;
|
|
193
201
|
payeeDetails: string;
|
|
194
202
|
};
|
|
@@ -208,10 +216,24 @@ export type CheckoutQuoteEntry = {
|
|
|
208
216
|
spreadPercentage: number;
|
|
209
217
|
sellerAutomatedReleaseAvailable?: boolean;
|
|
210
218
|
};
|
|
219
|
+
export type CheckoutNearbySuggestion = {
|
|
220
|
+
resizeAmountUsdc: string;
|
|
221
|
+
paymentAmount: string;
|
|
222
|
+
paymentCurrency: string;
|
|
223
|
+
tokenAmount: string;
|
|
224
|
+
percentDifference: string;
|
|
225
|
+
rail: string;
|
|
226
|
+
};
|
|
227
|
+
export type CheckoutNearbySuggestions = {
|
|
228
|
+
status: 'suggestions' | 'none' | 'ineligible' | 'unavailable';
|
|
229
|
+
below: CheckoutNearbySuggestion[];
|
|
230
|
+
above: CheckoutNearbySuggestion[];
|
|
231
|
+
};
|
|
211
232
|
export type CheckoutQuotes = {
|
|
212
233
|
orderId: string;
|
|
213
234
|
fiatCurrency: string;
|
|
214
235
|
platforms: CheckoutQuoteEntry[];
|
|
236
|
+
nearbySuggestions?: CheckoutNearbySuggestions;
|
|
215
237
|
};
|
|
216
238
|
export type CheckoutPayment = {
|
|
217
239
|
id: string;
|
|
@@ -256,8 +278,6 @@ export type CreateOrderResponse = {
|
|
|
256
278
|
order: CheckoutOrder;
|
|
257
279
|
orderToken: string;
|
|
258
280
|
};
|
|
259
|
-
export type CreateCheckoutResponse = CreateOrderResponse;
|
|
260
|
-
export type CheckoutCreateResponse = CreateOrderResponse;
|
|
261
281
|
export type CreatePaymentRequest = {
|
|
262
282
|
rail: string;
|
|
263
283
|
paymentMethodId?: string;
|
|
@@ -266,6 +286,7 @@ export type CreatePaymentRequest = {
|
|
|
266
286
|
replacementPaymentId?: string;
|
|
267
287
|
quoteLimit?: number;
|
|
268
288
|
excludedPayToValues?: string[];
|
|
289
|
+
refundTo?: string;
|
|
269
290
|
};
|
|
270
291
|
export type CheckoutPaymentCreationResponse = CheckoutPayment & {
|
|
271
292
|
relayerTransactionId?: string;
|
|
@@ -291,24 +312,14 @@ export type MerchantConfig = {
|
|
|
291
312
|
sweepEnabled: boolean;
|
|
292
313
|
recipientOverrideEnabled: boolean;
|
|
293
314
|
disableBranding: boolean;
|
|
315
|
+
dynamicOrdersEnabled: boolean;
|
|
294
316
|
merchantCheckoutTheme: MerchantCheckoutTheme;
|
|
295
317
|
platformReferralFeeConfig: ReferralFeeConfig | null;
|
|
296
318
|
referralSplitConfig: ReferralSplitConfig | null;
|
|
319
|
+
flatFeePricing: boolean;
|
|
297
320
|
createdAt: string;
|
|
298
321
|
updatedAt: string | null;
|
|
299
322
|
};
|
|
300
|
-
export declare const DashboardPrivyApp: {
|
|
301
|
-
readonly LEGACY: "LEGACY";
|
|
302
|
-
readonly V1: "V1";
|
|
303
|
-
};
|
|
304
|
-
export type DashboardPrivyAppType = typeof DashboardPrivyApp[keyof typeof DashboardPrivyApp];
|
|
305
|
-
export declare const MerchantMigrationStatus: {
|
|
306
|
-
readonly PENDING: "PENDING";
|
|
307
|
-
readonly MIGRATING: "MIGRATING";
|
|
308
|
-
readonly COMPLETE: "COMPLETE";
|
|
309
|
-
readonly FAILED: "FAILED";
|
|
310
|
-
};
|
|
311
|
-
export type MerchantMigrationStatusType = typeof MerchantMigrationStatus[keyof typeof MerchantMigrationStatus];
|
|
312
323
|
export type MerchantUser = {
|
|
313
324
|
id: string;
|
|
314
325
|
email: string | null;
|
|
@@ -325,11 +336,13 @@ export type MerchantProfile = {
|
|
|
325
336
|
logoUrl: string | null;
|
|
326
337
|
industryType: string | null;
|
|
327
338
|
industryOtherText: string | null;
|
|
339
|
+
integrationPath: MerchantIntegrationPathValue | null;
|
|
340
|
+
onboardingCompletedAt: string | null;
|
|
341
|
+
onboardingSkippedAt: string | null;
|
|
328
342
|
apiKey: string;
|
|
329
343
|
environment: MerchantEnvironmentType;
|
|
330
344
|
sandboxMerchantId: string | null;
|
|
331
345
|
inPersonCheckoutEnabled: boolean;
|
|
332
|
-
migrationStatus: MerchantMigrationStatusType;
|
|
333
346
|
evmWalletAddress: string | null;
|
|
334
347
|
solanaWalletAddress: string | null;
|
|
335
348
|
v1EvmWalletAddress: string | null;
|
|
@@ -547,6 +560,7 @@ type CreateSessionBaseRequest = {
|
|
|
547
560
|
cancelUrl?: string;
|
|
548
561
|
metadata?: Record<string, string>;
|
|
549
562
|
enabledPaymentPlatforms?: PaymentPlatformType[];
|
|
563
|
+
dynamicOrdersEnabled?: boolean;
|
|
550
564
|
};
|
|
551
565
|
type CreateSessionExactTokenRequest = CreateSessionBaseRequest & {
|
|
552
566
|
checkoutMode?: 'exact-token';
|
|
@@ -668,10 +682,41 @@ export interface OrderBridgeInfo {
|
|
|
668
682
|
fallbackToOrigin?: boolean;
|
|
669
683
|
failureMessage?: string | null;
|
|
670
684
|
}
|
|
685
|
+
export declare const MerchantIntegrationPath: {
|
|
686
|
+
readonly CUSTOM_API: "CUSTOM_API";
|
|
687
|
+
readonly WOOCOMMERCE: "WOOCOMMERCE";
|
|
688
|
+
readonly IN_PERSON: "IN_PERSON";
|
|
689
|
+
readonly TELEGRAM: "TELEGRAM";
|
|
690
|
+
readonly SHOPIFY: "SHOPIFY";
|
|
691
|
+
};
|
|
692
|
+
export type MerchantIntegrationPathValue = typeof MerchantIntegrationPath[keyof typeof MerchantIntegrationPath];
|
|
693
|
+
export declare const OnboardingStepStatus: {
|
|
694
|
+
readonly DONE: "done";
|
|
695
|
+
readonly TODO: "todo";
|
|
696
|
+
};
|
|
697
|
+
export type OnboardingStepStatusValue = typeof OnboardingStepStatus[keyof typeof OnboardingStepStatus];
|
|
698
|
+
export declare const OnboardingStepVerifiedBy: {
|
|
699
|
+
readonly AUTO: "auto";
|
|
700
|
+
readonly MANUAL: "manual";
|
|
701
|
+
};
|
|
702
|
+
export type OnboardingStepVerifiedByValue = typeof OnboardingStepVerifiedBy[keyof typeof OnboardingStepVerifiedBy];
|
|
703
|
+
export type OnboardingStepState = {
|
|
704
|
+
id: string;
|
|
705
|
+
status: OnboardingStepStatusValue;
|
|
706
|
+
verifiedBy: OnboardingStepVerifiedByValue;
|
|
707
|
+
};
|
|
708
|
+
export type MerchantOnboardingResponse = {
|
|
709
|
+
path: MerchantIntegrationPathValue | null;
|
|
710
|
+
sandboxApiKey: string | null;
|
|
711
|
+
completedAt: string | null;
|
|
712
|
+
skippedAt: string | null;
|
|
713
|
+
steps: OnboardingStepState[];
|
|
714
|
+
};
|
|
671
715
|
export declare const WebhookEventType: {
|
|
672
716
|
readonly ORDER_CREATED: "ORDER_CREATED";
|
|
673
717
|
readonly ORDER_FULFILLED: "ORDER_FULFILLED";
|
|
674
718
|
readonly ORDER_CANCELLED: "ORDER_CANCELLED";
|
|
719
|
+
readonly ORDER_RESIZED: "ORDER_RESIZED";
|
|
675
720
|
readonly PAYMENT_CREATED: "PAYMENT_CREATED";
|
|
676
721
|
readonly PAYMENT_SETTLED: "PAYMENT_SETTLED";
|
|
677
722
|
readonly PAYMENT_CANCELLED: "PAYMENT_CANCELLED";
|
|
@@ -705,9 +750,6 @@ export type Webhook = {
|
|
|
705
750
|
createdAt: string;
|
|
706
751
|
updatedAt: string;
|
|
707
752
|
};
|
|
708
|
-
export type WebhookWithSecret = Webhook & {
|
|
709
|
-
secret: string;
|
|
710
|
-
};
|
|
711
753
|
export type WebhookDelivery = {
|
|
712
754
|
id: string;
|
|
713
755
|
webhookId: string;
|
|
@@ -729,6 +771,10 @@ export type WebhookPayload = {
|
|
|
729
771
|
payment: CheckoutPayment | null;
|
|
730
772
|
refund: Record<string, unknown> | null;
|
|
731
773
|
paymentBridge: Record<string, unknown> | null;
|
|
774
|
+
resize?: {
|
|
775
|
+
previousAmountUsdc: string;
|
|
776
|
+
newAmountUsdc: string;
|
|
777
|
+
};
|
|
732
778
|
};
|
|
733
779
|
};
|
|
734
780
|
export type CreateWebhookRequest = {
|
|
@@ -736,7 +782,10 @@ export type CreateWebhookRequest = {
|
|
|
736
782
|
events?: WebhookEventTypeValue[];
|
|
737
783
|
customHeaders?: WebhookHeader[];
|
|
738
784
|
};
|
|
739
|
-
export type CreateWebhookResponse =
|
|
785
|
+
export type CreateWebhookResponse = {
|
|
786
|
+
webhook: Webhook;
|
|
787
|
+
secret: string;
|
|
788
|
+
};
|
|
740
789
|
export type UpdateWebhookRequest = {
|
|
741
790
|
url?: string;
|
|
742
791
|
events?: WebhookEventTypeValue[];
|
package/dist/types.js
CHANGED
|
@@ -90,16 +90,6 @@ export const CheckoutPaymentMemoPolicy = {
|
|
|
90
90
|
REQUIRED: 'REQUIRED',
|
|
91
91
|
EMPTY: 'EMPTY',
|
|
92
92
|
};
|
|
93
|
-
export const DashboardPrivyApp = {
|
|
94
|
-
LEGACY: 'LEGACY',
|
|
95
|
-
V1: 'V1',
|
|
96
|
-
};
|
|
97
|
-
export const MerchantMigrationStatus = {
|
|
98
|
-
PENDING: 'PENDING',
|
|
99
|
-
MIGRATING: 'MIGRATING',
|
|
100
|
-
COMPLETE: 'COMPLETE',
|
|
101
|
-
FAILED: 'FAILED',
|
|
102
|
-
};
|
|
103
93
|
// Structured error codes for Order failures
|
|
104
94
|
export const OrderErrorCode = {
|
|
105
95
|
// Proof verification errors
|
|
@@ -131,11 +121,28 @@ export const TrancheCurrency = {
|
|
|
131
121
|
USD: 'USD',
|
|
132
122
|
USDC: 'USDC',
|
|
133
123
|
};
|
|
124
|
+
// ============ Merchant Onboarding Types ============
|
|
125
|
+
export const MerchantIntegrationPath = {
|
|
126
|
+
CUSTOM_API: 'CUSTOM_API',
|
|
127
|
+
WOOCOMMERCE: 'WOOCOMMERCE',
|
|
128
|
+
IN_PERSON: 'IN_PERSON',
|
|
129
|
+
TELEGRAM: 'TELEGRAM',
|
|
130
|
+
SHOPIFY: 'SHOPIFY',
|
|
131
|
+
};
|
|
132
|
+
export const OnboardingStepStatus = {
|
|
133
|
+
DONE: 'done',
|
|
134
|
+
TODO: 'todo',
|
|
135
|
+
};
|
|
136
|
+
export const OnboardingStepVerifiedBy = {
|
|
137
|
+
AUTO: 'auto',
|
|
138
|
+
MANUAL: 'manual',
|
|
139
|
+
};
|
|
134
140
|
// ============ Webhook Types ============
|
|
135
141
|
export const WebhookEventType = {
|
|
136
142
|
ORDER_CREATED: 'ORDER_CREATED',
|
|
137
143
|
ORDER_FULFILLED: 'ORDER_FULFILLED',
|
|
138
144
|
ORDER_CANCELLED: 'ORDER_CANCELLED',
|
|
145
|
+
ORDER_RESIZED: 'ORDER_RESIZED',
|
|
139
146
|
PAYMENT_CREATED: 'PAYMENT_CREATED',
|
|
140
147
|
PAYMENT_SETTLED: 'PAYMENT_SETTLED',
|
|
141
148
|
PAYMENT_CANCELLED: 'PAYMENT_CANCELLED',
|
package/package.json
CHANGED