@usdctofiat/offramp 3.0.3 → 4.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/CHANGELOG.md +42 -1
- package/README.md +128 -23
- package/dist/{chunk-4KKKDDES.js → chunk-QMO7HTBZ.js} +255 -96
- package/dist/chunk-QMO7HTBZ.js.map +1 -0
- package/dist/{errors-D9bV_DWE.d.cts → errors-DYCRKcnY.d.cts} +44 -6
- package/dist/{errors-D9bV_DWE.d.ts → errors-DYCRKcnY.d.ts} +44 -6
- package/dist/index.cjs +259 -92
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +71 -6
- package/dist/index.d.ts +71 -6
- package/dist/index.js +9 -3
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +329 -111
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +24 -13
- package/dist/react.d.ts +24 -13
- package/dist/react.js +106 -27
- package/dist/react.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-4KKKDDES.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -40,8 +40,9 @@ __export(index_exports, {
|
|
|
40
40
|
PLATFORMS: () => PLATFORMS,
|
|
41
41
|
PLATFORM_LIMITS: () => PLATFORM_LIMITS,
|
|
42
42
|
close: () => close,
|
|
43
|
+
completePeerExtensionRegistration: () => completePeerExtensionRegistration,
|
|
43
44
|
createOfframp: () => createOfframp,
|
|
44
|
-
createPeerExtensionSdk: () =>
|
|
45
|
+
createPeerExtensionSdk: () => createPeerExtensionSdk,
|
|
45
46
|
createTelemetryContext: () => createTelemetryContext,
|
|
46
47
|
delegate: () => delegate,
|
|
47
48
|
deposits: () => deposits,
|
|
@@ -49,16 +50,18 @@ __export(index_exports, {
|
|
|
49
50
|
emitEvent: () => emitEvent,
|
|
50
51
|
enableOtc: () => enableOtc,
|
|
51
52
|
getOtcLink: () => getOtcLink,
|
|
53
|
+
getPeerExtensionRegistrationAuthParams: () => getPeerExtensionRegistrationAuthParams,
|
|
52
54
|
getPeerExtensionRegistrationInfo: () => getPeerExtensionRegistrationInfo,
|
|
53
|
-
getPeerExtensionState: () =>
|
|
55
|
+
getPeerExtensionState: () => getPeerExtensionState,
|
|
54
56
|
getPlatformLimits: () => getPlatformLimits,
|
|
55
|
-
isPeerExtensionAvailable: () =>
|
|
57
|
+
isPeerExtensionAvailable: () => isPeerExtensionAvailable,
|
|
58
|
+
isPeerExtensionMetadataBridgeAvailable: () => isPeerExtensionMetadataBridgeAvailable,
|
|
56
59
|
isPeerExtensionRegistrationError: () => isPeerExtensionRegistrationError,
|
|
57
60
|
isValidIBAN: () => isValidIBAN,
|
|
58
61
|
normalizePaypalMeUsername: () => normalizePaypalMeUsername,
|
|
59
62
|
offramp: () => offramp,
|
|
60
|
-
openPeerExtensionInstallPage: () =>
|
|
61
|
-
peerExtensionSdk: () =>
|
|
63
|
+
openPeerExtensionInstallPage: () => openPeerExtensionInstallPage,
|
|
64
|
+
peerExtensionSdk: () => peerExtensionSdk,
|
|
62
65
|
sanitizeAttributionId: () => sanitizeAttributionId,
|
|
63
66
|
sendTelemetryEvent: () => sendTelemetryEvent,
|
|
64
67
|
undelegate: () => undelegate
|
|
@@ -72,11 +75,15 @@ var import_sdk5 = require("@zkp2p/sdk");
|
|
|
72
75
|
|
|
73
76
|
// src/config.ts
|
|
74
77
|
var import_sdk = require("@zkp2p/sdk");
|
|
75
|
-
var SDK_VERSION = "
|
|
78
|
+
var SDK_VERSION = "4.0.0";
|
|
76
79
|
var BASE_CHAIN_ID = 8453;
|
|
77
80
|
var RUNTIME_ENV = "production";
|
|
78
81
|
var API_BASE_URL = "https://api.zkp2p.xyz";
|
|
79
82
|
var BASE_RPC_URL = "https://mainnet.base.org";
|
|
83
|
+
function resolveApiBaseUrl(override) {
|
|
84
|
+
const trimmed = override?.trim();
|
|
85
|
+
return (trimmed && trimmed.length > 0 ? trimmed : API_BASE_URL).replace(/\/$/, "");
|
|
86
|
+
}
|
|
80
87
|
var contracts = (0, import_sdk.getContracts)(BASE_CHAIN_ID, RUNTIME_ENV);
|
|
81
88
|
var addresses = contracts.addresses;
|
|
82
89
|
var addrs = addresses;
|
|
@@ -93,6 +100,7 @@ var DEFAULT_INTENT_GUARDIAN_ADDRESS = "0xe29a5BD4D0CEbA6C125A0361E7D20ab4eA275C2
|
|
|
93
100
|
var REFERRER = "galleonlabs";
|
|
94
101
|
var MIN_DEPOSIT_USDC = 1;
|
|
95
102
|
var MIN_ORDER_USDC = 1;
|
|
103
|
+
var MAX_ORDER_USDC = 2500;
|
|
96
104
|
var INDEXER_MAX_ATTEMPTS = 12;
|
|
97
105
|
var INDEXER_INITIAL_DELAY_MS = 1e3;
|
|
98
106
|
var INDEXER_MAX_DELAY_MS = 1e4;
|
|
@@ -101,6 +109,41 @@ var PAYEE_REGISTRATION_TIMEOUT_MS = 8e3;
|
|
|
101
109
|
// src/platforms.ts
|
|
102
110
|
var import_sdk2 = require("@zkp2p/sdk");
|
|
103
111
|
var import_zod = require("zod");
|
|
112
|
+
|
|
113
|
+
// src/errors.ts
|
|
114
|
+
var MakersCreateError = class extends Error {
|
|
115
|
+
status;
|
|
116
|
+
body;
|
|
117
|
+
constructor(message, status, body) {
|
|
118
|
+
super(message);
|
|
119
|
+
this.name = "MakersCreateError";
|
|
120
|
+
this.status = status;
|
|
121
|
+
this.body = body;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
var OfframpError = class extends Error {
|
|
125
|
+
code;
|
|
126
|
+
step;
|
|
127
|
+
cause;
|
|
128
|
+
txHash;
|
|
129
|
+
depositId;
|
|
130
|
+
constructor(message, code, step, cause, details) {
|
|
131
|
+
super(message);
|
|
132
|
+
this.name = "OfframpError";
|
|
133
|
+
this.code = code;
|
|
134
|
+
this.step = step;
|
|
135
|
+
this.cause = cause;
|
|
136
|
+
this.txHash = details?.txHash;
|
|
137
|
+
this.depositId = details?.depositId;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
function isUserCancellation(error) {
|
|
141
|
+
if (!(error instanceof Error)) return false;
|
|
142
|
+
const msg = error.message.toLowerCase();
|
|
143
|
+
return msg.includes("user rejected") || msg.includes("user denied") || msg.includes("user cancelled") || msg.includes("rejected the request") || msg.includes("action_rejected");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// src/platforms.ts
|
|
104
147
|
var PAYMENT_CATALOG = (0, import_sdk2.getPaymentMethodsCatalog)(BASE_CHAIN_ID, RUNTIME_ENV);
|
|
105
148
|
var ZELLE_HASH_LOOKUP_NAMES = ["zelle", "zelle-bofa", "zelle-chase", "zelle-citi"];
|
|
106
149
|
var FALLBACK_CURRENCIES = {
|
|
@@ -461,6 +504,113 @@ function getPeerExtensionRegistrationInfo(platform) {
|
|
|
461
504
|
const entry = getPlatformById(platform);
|
|
462
505
|
return entry?.extensionRegistration ?? null;
|
|
463
506
|
}
|
|
507
|
+
function getPeerExtensionRegistrationAuthParams(platform, options = {}) {
|
|
508
|
+
const info = getPeerExtensionRegistrationInfo(platform);
|
|
509
|
+
if (!info) return null;
|
|
510
|
+
const params = {
|
|
511
|
+
actionType: `transfer_${info.providerId}`,
|
|
512
|
+
captureMode: "sellerCredential",
|
|
513
|
+
platform: info.providerId
|
|
514
|
+
};
|
|
515
|
+
if (options.attestationServiceUrl) {
|
|
516
|
+
params.attestationServiceUrl = options.attestationServiceUrl;
|
|
517
|
+
}
|
|
518
|
+
return params;
|
|
519
|
+
}
|
|
520
|
+
function resolveRegistrationProcessor(platform) {
|
|
521
|
+
const info = getPeerExtensionRegistrationInfo(platform.id);
|
|
522
|
+
if (info?.providerId === "paypal" || info?.providerId === "wise") {
|
|
523
|
+
return info.providerId;
|
|
524
|
+
}
|
|
525
|
+
throw new Error(`${platform.name} does not require Peer extension registration.`);
|
|
526
|
+
}
|
|
527
|
+
async function postMakerCreate(processorName, payload, apiBaseUrl = API_BASE_URL) {
|
|
528
|
+
const controller = new AbortController();
|
|
529
|
+
const timeout = setTimeout(() => controller.abort(), PAYEE_REGISTRATION_TIMEOUT_MS);
|
|
530
|
+
try {
|
|
531
|
+
const res = await fetch(`${apiBaseUrl}/v2/makers/create`, {
|
|
532
|
+
method: "POST",
|
|
533
|
+
headers: { "Content-Type": "application/json" },
|
|
534
|
+
body: JSON.stringify({ processorName, ...payload }),
|
|
535
|
+
signal: controller.signal
|
|
536
|
+
});
|
|
537
|
+
if (!res.ok) {
|
|
538
|
+
const txt = await res.text().catch(() => "");
|
|
539
|
+
let detail = txt || res.statusText;
|
|
540
|
+
try {
|
|
541
|
+
const parsed = JSON.parse(txt);
|
|
542
|
+
if (typeof parsed.message === "string" && parsed.message.trim()) {
|
|
543
|
+
detail = parsed.message;
|
|
544
|
+
}
|
|
545
|
+
} catch {
|
|
546
|
+
}
|
|
547
|
+
throw new MakersCreateError(
|
|
548
|
+
`makers/create failed (${res.status}): ${detail}`,
|
|
549
|
+
res.status,
|
|
550
|
+
txt
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
const json = await res.json();
|
|
554
|
+
if (!json.success || !json.responseObject?.hashedOnchainId) {
|
|
555
|
+
throw new MakersCreateError(
|
|
556
|
+
json.message || "makers/create returned no hashedOnchainId",
|
|
557
|
+
json.statusCode ?? null,
|
|
558
|
+
""
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
return json.responseObject.hashedOnchainId;
|
|
562
|
+
} finally {
|
|
563
|
+
clearTimeout(timeout);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
function requireSarCredentialCapture(capturedMetadata) {
|
|
567
|
+
const capture = capturedMetadata.sarCredentialCapture;
|
|
568
|
+
if (!capture?.credentialBundle) {
|
|
569
|
+
throw new Error("Peer metadata did not include a seller credential bundle.");
|
|
570
|
+
}
|
|
571
|
+
if (!capture.offchainId) {
|
|
572
|
+
throw new Error("Peer metadata did not include seller credential offchainId.");
|
|
573
|
+
}
|
|
574
|
+
return capture;
|
|
575
|
+
}
|
|
576
|
+
async function uploadSellerCredentialBundle(processorName, offchainId, bundle) {
|
|
577
|
+
const params = processorName === "wise" ? { platform: "wise", bundle } : { platform: processorName, offchainId, bundle };
|
|
578
|
+
return (0, import_sdk2.apiUploadSellerCredentialBundle)(params, API_BASE_URL, PAYEE_REGISTRATION_TIMEOUT_MS);
|
|
579
|
+
}
|
|
580
|
+
async function completePeerExtensionRegistration(input) {
|
|
581
|
+
const processorName = resolveRegistrationProcessor(input.platform);
|
|
582
|
+
if (input.capturedMetadata.platform !== processorName) {
|
|
583
|
+
throw new Error(
|
|
584
|
+
`Peer metadata is for ${input.capturedMetadata.platform}, not ${processorName}.`
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
const sarCredentialCapture = requireSarCredentialCapture(input.capturedMetadata);
|
|
588
|
+
const bundle = sarCredentialCapture.credentialBundle;
|
|
589
|
+
if (bundle.platform.toLowerCase() !== processorName) {
|
|
590
|
+
throw new Error("Seller credential bundle platform does not match registration platform.");
|
|
591
|
+
}
|
|
592
|
+
const validation = input.platform.validate(input.identifier);
|
|
593
|
+
if (!validation.valid) {
|
|
594
|
+
throw new Error(validation.error || "Invalid identifier");
|
|
595
|
+
}
|
|
596
|
+
const payload = buildDepositData(processorName, sarCredentialCapture.offchainId);
|
|
597
|
+
if (payload.offchainId !== validation.normalized) {
|
|
598
|
+
throw new Error("Seller credential offchainId does not match registration identifier.");
|
|
599
|
+
}
|
|
600
|
+
const hashedOnchainId = bundle.payeeIdHash;
|
|
601
|
+
const sellerCredentialResponse = await uploadSellerCredentialBundle(
|
|
602
|
+
processorName,
|
|
603
|
+
payload.offchainId,
|
|
604
|
+
bundle
|
|
605
|
+
);
|
|
606
|
+
return {
|
|
607
|
+
processorName,
|
|
608
|
+
offchainId: payload.offchainId,
|
|
609
|
+
hashedOnchainId,
|
|
610
|
+
sellerCredentialResponse,
|
|
611
|
+
sellerCredentialStatus: sellerCredentialResponse.responseObject
|
|
612
|
+
};
|
|
613
|
+
}
|
|
464
614
|
var EXTENSION_REGISTRATION_ERROR_PATTERNS = ["creating the maker", "create the maker"];
|
|
465
615
|
function isPeerExtensionRegistrationError(platform, message, statusCode) {
|
|
466
616
|
const info = getPeerExtensionRegistrationInfo(platform);
|
|
@@ -472,39 +622,6 @@ function isPeerExtensionRegistrationError(platform, message, statusCode) {
|
|
|
472
622
|
return EXTENSION_REGISTRATION_ERROR_PATTERNS.some((p) => lower.includes(p));
|
|
473
623
|
}
|
|
474
624
|
|
|
475
|
-
// src/errors.ts
|
|
476
|
-
var MakersCreateError = class extends Error {
|
|
477
|
-
status;
|
|
478
|
-
body;
|
|
479
|
-
constructor(message, status, body) {
|
|
480
|
-
super(message);
|
|
481
|
-
this.name = "MakersCreateError";
|
|
482
|
-
this.status = status;
|
|
483
|
-
this.body = body;
|
|
484
|
-
}
|
|
485
|
-
};
|
|
486
|
-
var OfframpError = class extends Error {
|
|
487
|
-
code;
|
|
488
|
-
step;
|
|
489
|
-
cause;
|
|
490
|
-
txHash;
|
|
491
|
-
depositId;
|
|
492
|
-
constructor(message, code, step, cause, details) {
|
|
493
|
-
super(message);
|
|
494
|
-
this.name = "OfframpError";
|
|
495
|
-
this.code = code;
|
|
496
|
-
this.step = step;
|
|
497
|
-
this.cause = cause;
|
|
498
|
-
this.txHash = details?.txHash;
|
|
499
|
-
this.depositId = details?.depositId;
|
|
500
|
-
}
|
|
501
|
-
};
|
|
502
|
-
function isUserCancellation(error) {
|
|
503
|
-
if (!(error instanceof Error)) return false;
|
|
504
|
-
const msg = error.message.toLowerCase();
|
|
505
|
-
return msg.includes("user rejected") || msg.includes("user denied") || msg.includes("user cancelled") || msg.includes("rejected the request") || msg.includes("action_rejected");
|
|
506
|
-
}
|
|
507
|
-
|
|
508
625
|
// src/otc.ts
|
|
509
626
|
var import_viem = require("viem");
|
|
510
627
|
var import_chains = require("viem/chains");
|
|
@@ -512,13 +629,13 @@ var import_WhitelistPreIntentHook = __toESM(require("@zkp2p/contracts-v2/abis/ba
|
|
|
512
629
|
|
|
513
630
|
// src/sdk-client.ts
|
|
514
631
|
var import_sdk3 = require("@zkp2p/sdk");
|
|
515
|
-
function createSdkClient(walletClient) {
|
|
632
|
+
function createSdkClient(walletClient, apiBaseUrl = API_BASE_URL) {
|
|
516
633
|
return new import_sdk3.OfframpClient({
|
|
517
634
|
walletClient,
|
|
518
635
|
chainId: BASE_CHAIN_ID,
|
|
519
636
|
runtimeEnv: RUNTIME_ENV,
|
|
520
637
|
rpcUrl: BASE_RPC_URL,
|
|
521
|
-
baseApiUrl:
|
|
638
|
+
baseApiUrl: apiBaseUrl
|
|
522
639
|
});
|
|
523
640
|
}
|
|
524
641
|
|
|
@@ -929,50 +1046,11 @@ function extractDepositIdFromLogs(logs) {
|
|
|
929
1046
|
}
|
|
930
1047
|
return null;
|
|
931
1048
|
}
|
|
932
|
-
async function
|
|
1049
|
+
async function validatePayeeDetails(processorName, offchainId, apiBaseUrl = API_BASE_URL) {
|
|
933
1050
|
const controller = new AbortController();
|
|
934
1051
|
const timeout = setTimeout(() => controller.abort(), PAYEE_REGISTRATION_TIMEOUT_MS);
|
|
935
1052
|
try {
|
|
936
|
-
const res = await fetch(`${
|
|
937
|
-
method: "POST",
|
|
938
|
-
headers: { "Content-Type": "application/json" },
|
|
939
|
-
body: JSON.stringify({ processorName, ...payload }),
|
|
940
|
-
signal: controller.signal
|
|
941
|
-
});
|
|
942
|
-
if (!res.ok) {
|
|
943
|
-
const txt = await res.text().catch(() => "");
|
|
944
|
-
let detail = txt || res.statusText;
|
|
945
|
-
try {
|
|
946
|
-
const parsed = JSON.parse(txt);
|
|
947
|
-
if (typeof parsed.message === "string" && parsed.message.trim()) {
|
|
948
|
-
detail = parsed.message;
|
|
949
|
-
}
|
|
950
|
-
} catch {
|
|
951
|
-
}
|
|
952
|
-
throw new MakersCreateError(
|
|
953
|
-
`makers/create failed (${res.status}): ${detail}`,
|
|
954
|
-
res.status,
|
|
955
|
-
txt
|
|
956
|
-
);
|
|
957
|
-
}
|
|
958
|
-
const json = await res.json();
|
|
959
|
-
if (!json.success || !json.responseObject?.hashedOnchainId) {
|
|
960
|
-
throw new MakersCreateError(
|
|
961
|
-
json.message || "makers/create returned no hashedOnchainId",
|
|
962
|
-
json.statusCode ?? null,
|
|
963
|
-
""
|
|
964
|
-
);
|
|
965
|
-
}
|
|
966
|
-
return json.responseObject.hashedOnchainId;
|
|
967
|
-
} finally {
|
|
968
|
-
clearTimeout(timeout);
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
async function validatePayeeDetails(processorName, offchainId) {
|
|
972
|
-
const controller = new AbortController();
|
|
973
|
-
const timeout = setTimeout(() => controller.abort(), PAYEE_REGISTRATION_TIMEOUT_MS);
|
|
974
|
-
try {
|
|
975
|
-
const res = await fetch(`${API_BASE_URL}/v2/makers/validate`, {
|
|
1053
|
+
const res = await fetch(`${apiBaseUrl}/v2/makers/validate`, {
|
|
976
1054
|
method: "POST",
|
|
977
1055
|
headers: { "Content-Type": "application/json" },
|
|
978
1056
|
body: JSON.stringify({ processorName, offchainId }),
|
|
@@ -1050,10 +1128,11 @@ async function findUndelegatedDeposit(walletAddress) {
|
|
|
1050
1128
|
return null;
|
|
1051
1129
|
}
|
|
1052
1130
|
}
|
|
1053
|
-
async function offramp(walletClient, params, onProgress, telemetryContext) {
|
|
1131
|
+
async function offramp(walletClient, params, onProgress, telemetryContext, apiBaseUrl) {
|
|
1054
1132
|
const { amount, platform, currency, identifier } = params;
|
|
1055
1133
|
const platformId = platform.id;
|
|
1056
1134
|
const currencyCode = currency.code;
|
|
1135
|
+
const resolvedApiBaseUrl = resolveApiBaseUrl(apiBaseUrl);
|
|
1057
1136
|
const telemetry = telemetryContext ?? createTelemetryContext({
|
|
1058
1137
|
sdkVersion: SDK_VERSION,
|
|
1059
1138
|
telemetry: true,
|
|
@@ -1098,7 +1177,7 @@ async function offramp(walletClient, params, onProgress, telemetryContext) {
|
|
|
1098
1177
|
const existing = await findUndelegatedDeposit(walletAddress);
|
|
1099
1178
|
if (existing) {
|
|
1100
1179
|
emitProgress({ step: "resuming", depositId: existing.depositId });
|
|
1101
|
-
const client2 = createSdkClient(walletClient);
|
|
1180
|
+
const client2 = createSdkClient(walletClient, resolvedApiBaseUrl);
|
|
1102
1181
|
const txOverrides2 = { referrer: [REFERRER] };
|
|
1103
1182
|
try {
|
|
1104
1183
|
const result2 = await client2.setRateManager({
|
|
@@ -1134,7 +1213,7 @@ async function offramp(walletClient, params, onProgress, telemetryContext) {
|
|
|
1134
1213
|
const truncatedAmount = amt.toFixed(6).replace(/\.?0+$/, "");
|
|
1135
1214
|
const amountUnits = usdcToUnits(truncatedAmount);
|
|
1136
1215
|
const minUnits = usdcToUnits(String(MIN_ORDER_USDC));
|
|
1137
|
-
const maxUnits = usdcToUnits(String(Math.min(amt,
|
|
1216
|
+
const maxUnits = usdcToUnits(String(Math.min(amt, MAX_ORDER_USDC)));
|
|
1138
1217
|
try {
|
|
1139
1218
|
const publicClient = (0, import_viem3.createPublicClient)({ chain: import_chains3.base, transport: (0, import_viem3.http)(BASE_RPC_URL) });
|
|
1140
1219
|
const balance = await publicClient.readContract({
|
|
@@ -1163,7 +1242,11 @@ async function offramp(walletClient, params, onProgress, telemetryContext) {
|
|
|
1163
1242
|
}
|
|
1164
1243
|
const canonicalName = platformId.startsWith("zelle") ? "zelle" : platformId;
|
|
1165
1244
|
if (!getPeerExtensionRegistrationInfo(platformId)) {
|
|
1166
|
-
const outcome = await validatePayeeDetails(
|
|
1245
|
+
const outcome = await validatePayeeDetails(
|
|
1246
|
+
canonicalName,
|
|
1247
|
+
normalizedIdentifier,
|
|
1248
|
+
resolvedApiBaseUrl
|
|
1249
|
+
);
|
|
1167
1250
|
if (outcome === "invalid") {
|
|
1168
1251
|
throw new OfframpError(
|
|
1169
1252
|
`Couldn't verify that ${platform.name} ${platform.identifier.label.toLowerCase()}. Double-check it and try again.`,
|
|
@@ -1172,7 +1255,7 @@ async function offramp(walletClient, params, onProgress, telemetryContext) {
|
|
|
1172
1255
|
);
|
|
1173
1256
|
}
|
|
1174
1257
|
}
|
|
1175
|
-
const client = createSdkClient(walletClient);
|
|
1258
|
+
const client = createSdkClient(walletClient, resolvedApiBaseUrl);
|
|
1176
1259
|
const txOverrides = { referrer: [REFERRER] };
|
|
1177
1260
|
emitProgress({ step: "approving" });
|
|
1178
1261
|
try {
|
|
@@ -1198,13 +1281,13 @@ async function offramp(walletClient, params, onProgress, telemetryContext) {
|
|
|
1198
1281
|
let hashedOnchainId;
|
|
1199
1282
|
try {
|
|
1200
1283
|
const payeePayload = buildDepositData(canonicalName, normalizedIdentifier);
|
|
1201
|
-
hashedOnchainId = await
|
|
1284
|
+
hashedOnchainId = await postMakerCreate(canonicalName, payeePayload, resolvedApiBaseUrl);
|
|
1202
1285
|
} catch (err) {
|
|
1203
1286
|
const status = err instanceof MakersCreateError ? err.status : null;
|
|
1204
1287
|
const message = err instanceof Error ? err.message : String(err);
|
|
1205
1288
|
if (isPeerExtensionRegistrationError(canonicalName, message, status)) {
|
|
1206
1289
|
throw new OfframpError(
|
|
1207
|
-
`${platform.name} maker is not yet registered in the Peer extension.
|
|
1290
|
+
`${platform.name} maker is not yet registered in the Peer extension. Register this handle with Peer, then retry.`,
|
|
1208
1291
|
"EXTENSION_REGISTRATION_REQUIRED",
|
|
1209
1292
|
"registering",
|
|
1210
1293
|
err
|
|
@@ -1396,6 +1479,14 @@ var CURRENCIES = buildCurrencies();
|
|
|
1396
1479
|
// src/offramp.ts
|
|
1397
1480
|
var IDEMPOTENCY_TTL_MS = 10 * 60 * 1e3;
|
|
1398
1481
|
var IDEMPOTENCY_STORAGE_PREFIX = "offramp:idempotency:";
|
|
1482
|
+
var warnedIdempotencyUnavailable = false;
|
|
1483
|
+
function warnIdempotencyUnavailableOnce() {
|
|
1484
|
+
if (warnedIdempotencyUnavailable) return;
|
|
1485
|
+
warnedIdempotencyUnavailable = true;
|
|
1486
|
+
console.warn(
|
|
1487
|
+
"[offramp] idempotencyKey was provided but sessionStorage is unavailable (Node/worker runtime). The idempotency cache is browser-only and no-ops here, so retries can create duplicate deposits. For server-side dedup, call deposits(walletAddress) and reuse an existing open deposit before creating one."
|
|
1488
|
+
);
|
|
1489
|
+
}
|
|
1399
1490
|
function getWalletAddress(walletClient) {
|
|
1400
1491
|
const address = walletClient.account?.address;
|
|
1401
1492
|
if (!address) {
|
|
@@ -1466,8 +1557,10 @@ function buildCurrencyGroups() {
|
|
|
1466
1557
|
var Offramp = class {
|
|
1467
1558
|
walletClient;
|
|
1468
1559
|
telemetry;
|
|
1560
|
+
apiBaseUrl;
|
|
1469
1561
|
constructor(options) {
|
|
1470
1562
|
this.walletClient = options.walletClient;
|
|
1563
|
+
this.apiBaseUrl = options.apiBaseUrl;
|
|
1471
1564
|
this.telemetry = createTelemetryContext({
|
|
1472
1565
|
sdkVersion: SDK_VERSION,
|
|
1473
1566
|
telemetry: options.telemetry,
|
|
@@ -1490,6 +1583,9 @@ var Offramp = class {
|
|
|
1490
1583
|
referralId: flowTelemetry.referralId
|
|
1491
1584
|
};
|
|
1492
1585
|
const sanitizedKey = sanitizeAttributionId(params.idempotencyKey);
|
|
1586
|
+
if (sanitizedKey && typeof sessionStorage === "undefined") {
|
|
1587
|
+
warnIdempotencyUnavailableOnce();
|
|
1588
|
+
}
|
|
1493
1589
|
const walletAddress = sanitizedKey ? getWalletAddress(this.walletClient) : null;
|
|
1494
1590
|
const storageKey = walletAddress && sanitizedKey ? getIdempotencyStorageKey(walletAddress, sanitizedKey) : null;
|
|
1495
1591
|
if (storageKey) {
|
|
@@ -1500,7 +1596,8 @@ var Offramp = class {
|
|
|
1500
1596
|
this.walletClient,
|
|
1501
1597
|
sanitizedParams,
|
|
1502
1598
|
onProgress,
|
|
1503
|
-
flowTelemetry
|
|
1599
|
+
flowTelemetry,
|
|
1600
|
+
this.apiBaseUrl
|
|
1504
1601
|
);
|
|
1505
1602
|
if (storageKey) {
|
|
1506
1603
|
writeIdempotencyResult(storageKey, result);
|
|
@@ -1556,8 +1653,8 @@ var OFFRAMP_ERROR_CODES = {
|
|
|
1556
1653
|
* handle in the Peer extension yet. Thrown from `offramp()` for PayPal
|
|
1557
1654
|
* and Wise when `/v2/makers/create` returns 400 or a "creating the maker"
|
|
1558
1655
|
* message. Recover by prompting the user through the Peer extension via
|
|
1559
|
-
* `usePeerExtensionRegistration(platform)` (React) or
|
|
1560
|
-
*
|
|
1656
|
+
* `usePeerExtensionRegistration(platform)` (React) or
|
|
1657
|
+
* `completePeerExtensionRegistration(...)`, then retrying `offramp()`.
|
|
1561
1658
|
*/
|
|
1562
1659
|
EXTENSION_REGISTRATION_REQUIRED: "EXTENSION_REGISTRATION_REQUIRED",
|
|
1563
1660
|
DEPOSIT_FAILED: "DEPOSIT_FAILED",
|
|
@@ -1569,6 +1666,73 @@ var OFFRAMP_ERROR_CODES = {
|
|
|
1569
1666
|
|
|
1570
1667
|
// src/extension.ts
|
|
1571
1668
|
var import_sdk7 = require("@zkp2p/sdk");
|
|
1669
|
+
var resolveWindow = (options) => {
|
|
1670
|
+
if (options?.window) {
|
|
1671
|
+
return options.window;
|
|
1672
|
+
}
|
|
1673
|
+
if (typeof window === "undefined") {
|
|
1674
|
+
return void 0;
|
|
1675
|
+
}
|
|
1676
|
+
return window;
|
|
1677
|
+
};
|
|
1678
|
+
var requirePeer = (options) => {
|
|
1679
|
+
const resolvedWindow = resolveWindow(options);
|
|
1680
|
+
if (!resolvedWindow) {
|
|
1681
|
+
throw new Error("Peer extension SDK requires a browser window.");
|
|
1682
|
+
}
|
|
1683
|
+
if (!resolvedWindow.peer) {
|
|
1684
|
+
throw new Error("Peer extension not available. Install or enable the Peer extension.");
|
|
1685
|
+
}
|
|
1686
|
+
return resolvedWindow.peer;
|
|
1687
|
+
};
|
|
1688
|
+
var isPeerExtensionAvailable = (options) => {
|
|
1689
|
+
const resolvedWindow = resolveWindow(options);
|
|
1690
|
+
return Boolean(resolvedWindow?.peer);
|
|
1691
|
+
};
|
|
1692
|
+
var hasHeadlessMetadataBridge = (peer) => typeof peer.authenticate === "function" && typeof peer.onMetadataMessage === "function";
|
|
1693
|
+
var requirePeerMetadataBridge = (options) => {
|
|
1694
|
+
const peer = requirePeer(options);
|
|
1695
|
+
if (!hasHeadlessMetadataBridge(peer)) {
|
|
1696
|
+
throw new Error("Peer extension metadata bridge unavailable. Install or update Peer.");
|
|
1697
|
+
}
|
|
1698
|
+
return peer;
|
|
1699
|
+
};
|
|
1700
|
+
var isPeerExtensionMetadataBridgeAvailable = (options) => {
|
|
1701
|
+
const resolvedWindow = resolveWindow(options);
|
|
1702
|
+
return Boolean(resolvedWindow?.peer && hasHeadlessMetadataBridge(resolvedWindow.peer));
|
|
1703
|
+
};
|
|
1704
|
+
var openPeerExtensionInstallPage = (options) => {
|
|
1705
|
+
const resolvedWindow = resolveWindow(options);
|
|
1706
|
+
if (!resolvedWindow) {
|
|
1707
|
+
throw new Error("Peer extension SDK requires a browser window.");
|
|
1708
|
+
}
|
|
1709
|
+
resolvedWindow.open(import_sdk7.PEER_EXTENSION_CHROME_URL, "_blank", "noopener,noreferrer");
|
|
1710
|
+
};
|
|
1711
|
+
var getPeerExtensionState = async (options) => {
|
|
1712
|
+
if (!isPeerExtensionAvailable(options)) {
|
|
1713
|
+
return "needs_install";
|
|
1714
|
+
}
|
|
1715
|
+
try {
|
|
1716
|
+
const status = await requirePeer(options).checkConnectionStatus();
|
|
1717
|
+
return status === "connected" ? "ready" : "needs_connection";
|
|
1718
|
+
} catch {
|
|
1719
|
+
return "needs_connection";
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1722
|
+
var createPeerExtensionSdk = (options = {}) => {
|
|
1723
|
+
const sdk = (0, import_sdk7.createPeerExtensionSdk)(options);
|
|
1724
|
+
return {
|
|
1725
|
+
isAvailable: () => isPeerExtensionAvailable(options),
|
|
1726
|
+
requestConnection: () => requirePeer(options).requestConnection(),
|
|
1727
|
+
checkConnectionStatus: () => requirePeer(options).checkConnectionStatus(),
|
|
1728
|
+
getVersion: () => requirePeer(options).getVersion(),
|
|
1729
|
+
authenticate: (params) => requirePeerMetadataBridge(options).authenticate(params),
|
|
1730
|
+
onMetadataMessage: (callback) => requirePeerMetadataBridge(options).onMetadataMessage(callback),
|
|
1731
|
+
openInstallPage: () => sdk.openInstallPage(),
|
|
1732
|
+
getState: () => sdk.getState()
|
|
1733
|
+
};
|
|
1734
|
+
};
|
|
1735
|
+
var peerExtensionSdk = createPeerExtensionSdk();
|
|
1572
1736
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1573
1737
|
0 && (module.exports = {
|
|
1574
1738
|
CURRENCIES,
|
|
@@ -1581,6 +1745,7 @@ var import_sdk7 = require("@zkp2p/sdk");
|
|
|
1581
1745
|
PLATFORMS,
|
|
1582
1746
|
PLATFORM_LIMITS,
|
|
1583
1747
|
close,
|
|
1748
|
+
completePeerExtensionRegistration,
|
|
1584
1749
|
createOfframp,
|
|
1585
1750
|
createPeerExtensionSdk,
|
|
1586
1751
|
createTelemetryContext,
|
|
@@ -1590,10 +1755,12 @@ var import_sdk7 = require("@zkp2p/sdk");
|
|
|
1590
1755
|
emitEvent,
|
|
1591
1756
|
enableOtc,
|
|
1592
1757
|
getOtcLink,
|
|
1758
|
+
getPeerExtensionRegistrationAuthParams,
|
|
1593
1759
|
getPeerExtensionRegistrationInfo,
|
|
1594
1760
|
getPeerExtensionState,
|
|
1595
1761
|
getPlatformLimits,
|
|
1596
1762
|
isPeerExtensionAvailable,
|
|
1763
|
+
isPeerExtensionMetadataBridgeAvailable,
|
|
1597
1764
|
isPeerExtensionRegistrationError,
|
|
1598
1765
|
isValidIBAN,
|
|
1599
1766
|
normalizePaypalMeUsername,
|