@zkp2p/pay-shared 2.0.0 → 3.1.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 +97 -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,53 @@ 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
|
+
};
|
|
232
|
+
export type QuoteAvailabilityRequest = {
|
|
233
|
+
amount: string;
|
|
234
|
+
quoteMode: CheckoutModeType;
|
|
235
|
+
fiatCurrency?: string;
|
|
236
|
+
destinationChainId: string | number;
|
|
237
|
+
destinationToken: string;
|
|
238
|
+
destinationAddress: string;
|
|
239
|
+
/** Max suggestions PER DIRECTION (1-10, API default 3). A response can carry up to 2x this. */
|
|
240
|
+
nearbyQuotesCount?: number;
|
|
241
|
+
};
|
|
242
|
+
export type QuoteAvailabilitySuggestion = {
|
|
243
|
+
suggestedAmount: string;
|
|
244
|
+
percentDifference: string;
|
|
245
|
+
rail: string;
|
|
246
|
+
paymentAmount: string;
|
|
247
|
+
paymentCurrency: string;
|
|
248
|
+
tokenAmount: string;
|
|
249
|
+
conversionRate: string;
|
|
250
|
+
};
|
|
251
|
+
export type QuoteAvailabilitySuggestions = {
|
|
252
|
+
below: QuoteAvailabilitySuggestion[];
|
|
253
|
+
above: QuoteAvailabilitySuggestion[];
|
|
254
|
+
};
|
|
255
|
+
/** `nearbySuggestions` is always null when `available` is true. */
|
|
256
|
+
export type QuoteAvailability = {
|
|
257
|
+
available: boolean;
|
|
258
|
+
quoteCount: number;
|
|
259
|
+
nearbySuggestions: QuoteAvailabilitySuggestions | null;
|
|
260
|
+
};
|
|
211
261
|
export type CheckoutQuotes = {
|
|
212
262
|
orderId: string;
|
|
213
263
|
fiatCurrency: string;
|
|
214
264
|
platforms: CheckoutQuoteEntry[];
|
|
265
|
+
nearbySuggestions?: CheckoutNearbySuggestions;
|
|
215
266
|
};
|
|
216
267
|
export type CheckoutPayment = {
|
|
217
268
|
id: string;
|
|
@@ -256,8 +307,6 @@ export type CreateOrderResponse = {
|
|
|
256
307
|
order: CheckoutOrder;
|
|
257
308
|
orderToken: string;
|
|
258
309
|
};
|
|
259
|
-
export type CreateCheckoutResponse = CreateOrderResponse;
|
|
260
|
-
export type CheckoutCreateResponse = CreateOrderResponse;
|
|
261
310
|
export type CreatePaymentRequest = {
|
|
262
311
|
rail: string;
|
|
263
312
|
paymentMethodId?: string;
|
|
@@ -266,6 +315,7 @@ export type CreatePaymentRequest = {
|
|
|
266
315
|
replacementPaymentId?: string;
|
|
267
316
|
quoteLimit?: number;
|
|
268
317
|
excludedPayToValues?: string[];
|
|
318
|
+
refundTo?: string;
|
|
269
319
|
};
|
|
270
320
|
export type CheckoutPaymentCreationResponse = CheckoutPayment & {
|
|
271
321
|
relayerTransactionId?: string;
|
|
@@ -291,24 +341,14 @@ export type MerchantConfig = {
|
|
|
291
341
|
sweepEnabled: boolean;
|
|
292
342
|
recipientOverrideEnabled: boolean;
|
|
293
343
|
disableBranding: boolean;
|
|
344
|
+
dynamicOrdersEnabled: boolean;
|
|
294
345
|
merchantCheckoutTheme: MerchantCheckoutTheme;
|
|
295
346
|
platformReferralFeeConfig: ReferralFeeConfig | null;
|
|
296
347
|
referralSplitConfig: ReferralSplitConfig | null;
|
|
348
|
+
flatFeePricing: boolean;
|
|
297
349
|
createdAt: string;
|
|
298
350
|
updatedAt: string | null;
|
|
299
351
|
};
|
|
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
352
|
export type MerchantUser = {
|
|
313
353
|
id: string;
|
|
314
354
|
email: string | null;
|
|
@@ -325,11 +365,13 @@ export type MerchantProfile = {
|
|
|
325
365
|
logoUrl: string | null;
|
|
326
366
|
industryType: string | null;
|
|
327
367
|
industryOtherText: string | null;
|
|
368
|
+
integrationPath: MerchantIntegrationPathValue | null;
|
|
369
|
+
onboardingCompletedAt: string | null;
|
|
370
|
+
onboardingSkippedAt: string | null;
|
|
328
371
|
apiKey: string;
|
|
329
372
|
environment: MerchantEnvironmentType;
|
|
330
373
|
sandboxMerchantId: string | null;
|
|
331
374
|
inPersonCheckoutEnabled: boolean;
|
|
332
|
-
migrationStatus: MerchantMigrationStatusType;
|
|
333
375
|
evmWalletAddress: string | null;
|
|
334
376
|
solanaWalletAddress: string | null;
|
|
335
377
|
v1EvmWalletAddress: string | null;
|
|
@@ -547,6 +589,7 @@ type CreateSessionBaseRequest = {
|
|
|
547
589
|
cancelUrl?: string;
|
|
548
590
|
metadata?: Record<string, string>;
|
|
549
591
|
enabledPaymentPlatforms?: PaymentPlatformType[];
|
|
592
|
+
dynamicOrdersEnabled?: boolean;
|
|
550
593
|
};
|
|
551
594
|
type CreateSessionExactTokenRequest = CreateSessionBaseRequest & {
|
|
552
595
|
checkoutMode?: 'exact-token';
|
|
@@ -668,10 +711,41 @@ export interface OrderBridgeInfo {
|
|
|
668
711
|
fallbackToOrigin?: boolean;
|
|
669
712
|
failureMessage?: string | null;
|
|
670
713
|
}
|
|
714
|
+
export declare const MerchantIntegrationPath: {
|
|
715
|
+
readonly CUSTOM_API: "CUSTOM_API";
|
|
716
|
+
readonly WOOCOMMERCE: "WOOCOMMERCE";
|
|
717
|
+
readonly IN_PERSON: "IN_PERSON";
|
|
718
|
+
readonly TELEGRAM: "TELEGRAM";
|
|
719
|
+
readonly SHOPIFY: "SHOPIFY";
|
|
720
|
+
};
|
|
721
|
+
export type MerchantIntegrationPathValue = typeof MerchantIntegrationPath[keyof typeof MerchantIntegrationPath];
|
|
722
|
+
export declare const OnboardingStepStatus: {
|
|
723
|
+
readonly DONE: "done";
|
|
724
|
+
readonly TODO: "todo";
|
|
725
|
+
};
|
|
726
|
+
export type OnboardingStepStatusValue = typeof OnboardingStepStatus[keyof typeof OnboardingStepStatus];
|
|
727
|
+
export declare const OnboardingStepVerifiedBy: {
|
|
728
|
+
readonly AUTO: "auto";
|
|
729
|
+
readonly MANUAL: "manual";
|
|
730
|
+
};
|
|
731
|
+
export type OnboardingStepVerifiedByValue = typeof OnboardingStepVerifiedBy[keyof typeof OnboardingStepVerifiedBy];
|
|
732
|
+
export type OnboardingStepState = {
|
|
733
|
+
id: string;
|
|
734
|
+
status: OnboardingStepStatusValue;
|
|
735
|
+
verifiedBy: OnboardingStepVerifiedByValue;
|
|
736
|
+
};
|
|
737
|
+
export type MerchantOnboardingResponse = {
|
|
738
|
+
path: MerchantIntegrationPathValue | null;
|
|
739
|
+
sandboxApiKey: string | null;
|
|
740
|
+
completedAt: string | null;
|
|
741
|
+
skippedAt: string | null;
|
|
742
|
+
steps: OnboardingStepState[];
|
|
743
|
+
};
|
|
671
744
|
export declare const WebhookEventType: {
|
|
672
745
|
readonly ORDER_CREATED: "ORDER_CREATED";
|
|
673
746
|
readonly ORDER_FULFILLED: "ORDER_FULFILLED";
|
|
674
747
|
readonly ORDER_CANCELLED: "ORDER_CANCELLED";
|
|
748
|
+
readonly ORDER_RESIZED: "ORDER_RESIZED";
|
|
675
749
|
readonly PAYMENT_CREATED: "PAYMENT_CREATED";
|
|
676
750
|
readonly PAYMENT_SETTLED: "PAYMENT_SETTLED";
|
|
677
751
|
readonly PAYMENT_CANCELLED: "PAYMENT_CANCELLED";
|
|
@@ -705,9 +779,6 @@ export type Webhook = {
|
|
|
705
779
|
createdAt: string;
|
|
706
780
|
updatedAt: string;
|
|
707
781
|
};
|
|
708
|
-
export type WebhookWithSecret = Webhook & {
|
|
709
|
-
secret: string;
|
|
710
|
-
};
|
|
711
782
|
export type WebhookDelivery = {
|
|
712
783
|
id: string;
|
|
713
784
|
webhookId: string;
|
|
@@ -729,6 +800,10 @@ export type WebhookPayload = {
|
|
|
729
800
|
payment: CheckoutPayment | null;
|
|
730
801
|
refund: Record<string, unknown> | null;
|
|
731
802
|
paymentBridge: Record<string, unknown> | null;
|
|
803
|
+
resize?: {
|
|
804
|
+
previousAmountUsdc: string;
|
|
805
|
+
newAmountUsdc: string;
|
|
806
|
+
};
|
|
732
807
|
};
|
|
733
808
|
};
|
|
734
809
|
export type CreateWebhookRequest = {
|
|
@@ -736,7 +811,10 @@ export type CreateWebhookRequest = {
|
|
|
736
811
|
events?: WebhookEventTypeValue[];
|
|
737
812
|
customHeaders?: WebhookHeader[];
|
|
738
813
|
};
|
|
739
|
-
export type CreateWebhookResponse =
|
|
814
|
+
export type CreateWebhookResponse = {
|
|
815
|
+
webhook: Webhook;
|
|
816
|
+
secret: string;
|
|
817
|
+
};
|
|
740
818
|
export type UpdateWebhookRequest = {
|
|
741
819
|
url?: string;
|
|
742
820
|
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