@voyage_ai/v402-web-ts 0.2.0 → 0.3.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 +467 -130
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +121 -131
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +123 -139
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +39 -9
- package/dist/react/index.d.ts +39 -9
- package/dist/react/index.js +818 -248
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +836 -257
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/styles.css +1 -1
- package/package.json +9 -2
package/dist/react/index.js
CHANGED
|
@@ -35,7 +35,7 @@ var PROD_BACK_URL;
|
|
|
35
35
|
var init_common = __esm({
|
|
36
36
|
"src/types/common.ts"() {
|
|
37
37
|
"use strict";
|
|
38
|
-
PROD_BACK_URL = "https://v402pay.onvoyage.ai/api/pay";
|
|
38
|
+
PROD_BACK_URL = true ? "https://v402pay.onvoyage.ai/api/pay" : "https://v402pay.onvoyage.ai/api/pay";
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
41
|
|
|
@@ -98,6 +98,24 @@ var init_types = __esm({
|
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
// src/utils/wallet.ts
|
|
101
|
+
var wallet_exports = {};
|
|
102
|
+
__export(wallet_exports, {
|
|
103
|
+
clearAllWalletAddresses: () => clearAllWalletAddresses,
|
|
104
|
+
clearWalletDisconnection: () => clearWalletDisconnection,
|
|
105
|
+
formatAddress: () => formatAddress,
|
|
106
|
+
getAllWalletAddresses: () => getAllWalletAddresses,
|
|
107
|
+
getCachedWalletAddress: () => getCachedWalletAddress,
|
|
108
|
+
getConnectedNetworkType: () => getConnectedNetworkType,
|
|
109
|
+
getWalletDisplayName: () => getWalletDisplayName,
|
|
110
|
+
getWalletInstallUrl: () => getWalletInstallUrl,
|
|
111
|
+
getWalletProvider: () => getWalletProvider,
|
|
112
|
+
isWalletInstalled: () => isWalletInstalled,
|
|
113
|
+
isWalletManuallyDisconnected: () => isWalletManuallyDisconnected,
|
|
114
|
+
markWalletDisconnected: () => markWalletDisconnected,
|
|
115
|
+
removeWalletAddress: () => removeWalletAddress,
|
|
116
|
+
saveConnectedNetworkType: () => saveConnectedNetworkType,
|
|
117
|
+
saveWalletAddress: () => saveWalletAddress
|
|
118
|
+
});
|
|
101
119
|
function isWalletInstalled(networkType) {
|
|
102
120
|
if (typeof window === "undefined") {
|
|
103
121
|
return false;
|
|
@@ -112,6 +130,20 @@ function isWalletInstalled(networkType) {
|
|
|
112
130
|
return false;
|
|
113
131
|
}
|
|
114
132
|
}
|
|
133
|
+
function getWalletProvider(networkType) {
|
|
134
|
+
if (typeof window === "undefined") {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
switch (networkType) {
|
|
138
|
+
case "evm" /* EVM */:
|
|
139
|
+
return window.ethereum;
|
|
140
|
+
case "solana" /* SOLANA */:
|
|
141
|
+
case "svm" /* SVM */:
|
|
142
|
+
return window.solana || window.phantom;
|
|
143
|
+
default:
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
115
147
|
function formatAddress(address) {
|
|
116
148
|
if (!address || address.length < 10) {
|
|
117
149
|
return address;
|
|
@@ -186,6 +218,17 @@ function getWalletInstallUrl(networkType) {
|
|
|
186
218
|
return "#";
|
|
187
219
|
}
|
|
188
220
|
}
|
|
221
|
+
function getWalletDisplayName(networkType) {
|
|
222
|
+
switch (networkType) {
|
|
223
|
+
case "evm" /* EVM */:
|
|
224
|
+
return "MetaMask";
|
|
225
|
+
case "solana" /* SOLANA */:
|
|
226
|
+
case "svm" /* SVM */:
|
|
227
|
+
return "Phantom";
|
|
228
|
+
default:
|
|
229
|
+
return "Unknown Wallet";
|
|
230
|
+
}
|
|
231
|
+
}
|
|
189
232
|
function getAllWalletAddresses() {
|
|
190
233
|
if (typeof window === "undefined") {
|
|
191
234
|
return {};
|
|
@@ -218,6 +261,11 @@ function removeWalletAddress(networkType) {
|
|
|
218
261
|
delete addresses[networkType];
|
|
219
262
|
localStorage.setItem(WALLET_ADDRESSES_KEY, JSON.stringify(addresses));
|
|
220
263
|
}
|
|
264
|
+
function clearAllWalletAddresses() {
|
|
265
|
+
if (typeof window !== "undefined") {
|
|
266
|
+
localStorage.removeItem(WALLET_ADDRESSES_KEY);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
221
269
|
var WALLET_DISCONNECTED_KEY, WALLET_DISCONNECTED_NETWORKS_KEY, CONNECTED_NETWORK_TYPE_KEY, WALLET_ADDRESSES_KEY;
|
|
222
270
|
var init_wallet = __esm({
|
|
223
271
|
"src/utils/wallet.ts"() {
|
|
@@ -234,6 +282,7 @@ var index_exports = {};
|
|
|
234
282
|
__export(index_exports, {
|
|
235
283
|
V402Checkout: () => V402Checkout,
|
|
236
284
|
WalletConnect: () => WalletConnect,
|
|
285
|
+
WalletSelectModal: () => WalletSelectModal,
|
|
237
286
|
usePageNetwork: () => usePageNetwork,
|
|
238
287
|
usePayment: () => usePayment,
|
|
239
288
|
usePaymentInfo: () => usePaymentInfo,
|
|
@@ -250,7 +299,7 @@ init_wallet();
|
|
|
250
299
|
|
|
251
300
|
// src/utils/wallet-connect.ts
|
|
252
301
|
init_wallet();
|
|
253
|
-
async function connectWallet(networkType) {
|
|
302
|
+
async function connectWallet(networkType, forceSelect = false) {
|
|
254
303
|
if (typeof window === "undefined") {
|
|
255
304
|
throw new Error("\u8BF7\u5728\u6D4F\u89C8\u5668\u73AF\u5883\u4E2D\u4F7F\u7528");
|
|
256
305
|
}
|
|
@@ -261,6 +310,26 @@ async function connectWallet(networkType) {
|
|
|
261
310
|
throw new Error("\u8BF7\u5B89\u88C5 MetaMask \u6216\u5176\u4ED6\u4EE5\u592A\u574A\u94B1\u5305");
|
|
262
311
|
}
|
|
263
312
|
const ethereum = window.ethereum;
|
|
313
|
+
if (forceSelect) {
|
|
314
|
+
try {
|
|
315
|
+
const permissions = await ethereum.request({
|
|
316
|
+
method: "wallet_requestPermissions",
|
|
317
|
+
params: [{ eth_accounts: {} }]
|
|
318
|
+
});
|
|
319
|
+
const accountsPermission = permissions?.find(
|
|
320
|
+
(p) => p.parentCapability === "eth_accounts"
|
|
321
|
+
);
|
|
322
|
+
if (accountsPermission?.caveats?.[0]?.value?.length > 0) {
|
|
323
|
+
address = accountsPermission.caveats[0].value[0];
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
} catch (err) {
|
|
327
|
+
if (err.code === 4001) {
|
|
328
|
+
throw new Error("\u7528\u6237\u53D6\u6D88\u4E86\u94B1\u5305\u8FDE\u63A5");
|
|
329
|
+
}
|
|
330
|
+
console.warn("wallet_requestPermissions failed, falling back to eth_requestAccounts");
|
|
331
|
+
}
|
|
332
|
+
}
|
|
264
333
|
const accounts = await ethereum.request({
|
|
265
334
|
method: "eth_requestAccounts",
|
|
266
335
|
params: []
|
|
@@ -273,10 +342,34 @@ async function connectWallet(networkType) {
|
|
|
273
342
|
}
|
|
274
343
|
case "solana" /* SOLANA */:
|
|
275
344
|
case "svm" /* SVM */: {
|
|
276
|
-
const
|
|
345
|
+
const phantom = window.phantom?.solana || window.solana;
|
|
346
|
+
const solflare = window.solflare;
|
|
347
|
+
let solana = phantom;
|
|
348
|
+
if (!solana && solflare?.isSolflare) {
|
|
349
|
+
solana = solflare;
|
|
350
|
+
}
|
|
277
351
|
if (!solana) {
|
|
278
352
|
throw new Error("\u8BF7\u5B89\u88C5 Phantom \u6216\u5176\u4ED6 Solana \u94B1\u5305");
|
|
279
353
|
}
|
|
354
|
+
if (forceSelect) {
|
|
355
|
+
try {
|
|
356
|
+
if (phantom?.isConnected) {
|
|
357
|
+
await phantom.disconnect();
|
|
358
|
+
}
|
|
359
|
+
if (solflare?.isConnected) {
|
|
360
|
+
await solflare.disconnect();
|
|
361
|
+
}
|
|
362
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
363
|
+
} catch (err) {
|
|
364
|
+
console.warn("Failed to disconnect Solana wallet:", err);
|
|
365
|
+
}
|
|
366
|
+
} else if (solana.isConnected) {
|
|
367
|
+
try {
|
|
368
|
+
await solana.disconnect();
|
|
369
|
+
} catch (err) {
|
|
370
|
+
console.warn("Failed to disconnect Solana wallet:", err);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
280
373
|
const response = await solana.connect();
|
|
281
374
|
address = response.publicKey.toString();
|
|
282
375
|
break;
|
|
@@ -289,6 +382,60 @@ async function connectWallet(networkType) {
|
|
|
289
382
|
saveWalletAddress(networkType, address);
|
|
290
383
|
return address;
|
|
291
384
|
}
|
|
385
|
+
async function disconnectAllSolanaWallets() {
|
|
386
|
+
if (typeof window === "undefined") return;
|
|
387
|
+
const phantom = window.phantom?.solana || window.solana;
|
|
388
|
+
const solflare = window.solflare;
|
|
389
|
+
const disconnectPromises = [];
|
|
390
|
+
if (phantom?.isConnected) {
|
|
391
|
+
disconnectPromises.push(
|
|
392
|
+
phantom.disconnect().catch(
|
|
393
|
+
(err) => console.warn("Failed to disconnect Phantom:", err)
|
|
394
|
+
)
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
if (solflare?.isConnected) {
|
|
398
|
+
disconnectPromises.push(
|
|
399
|
+
solflare.disconnect().catch(
|
|
400
|
+
(err) => console.warn("Failed to disconnect Solflare:", err)
|
|
401
|
+
)
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
await Promise.all(disconnectPromises);
|
|
405
|
+
}
|
|
406
|
+
async function disconnectWallet(networkType, clearAll = false) {
|
|
407
|
+
const targetNetwork = networkType || getConnectedNetworkType();
|
|
408
|
+
if (targetNetwork && typeof window !== "undefined") {
|
|
409
|
+
try {
|
|
410
|
+
switch (targetNetwork) {
|
|
411
|
+
case "solana" /* SOLANA */:
|
|
412
|
+
case "svm" /* SVM */: {
|
|
413
|
+
await disconnectAllSolanaWallets();
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
416
|
+
// EVM 钱包(如 MetaMask)没有真正的 disconnect API
|
|
417
|
+
// 只清除本地状态,下次连接时会重新请求权限
|
|
418
|
+
case "evm" /* EVM */:
|
|
419
|
+
default:
|
|
420
|
+
break;
|
|
421
|
+
}
|
|
422
|
+
} catch (err) {
|
|
423
|
+
console.warn("Failed to disconnect wallet:", err);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
if (clearAll) {
|
|
427
|
+
const { clearAllWalletAddresses: clearAllWalletAddresses2 } = (init_wallet(), __toCommonJS(wallet_exports));
|
|
428
|
+
clearAllWalletAddresses2();
|
|
429
|
+
markWalletDisconnected();
|
|
430
|
+
await disconnectAllSolanaWallets();
|
|
431
|
+
} else if (networkType) {
|
|
432
|
+
removeWalletAddress(networkType);
|
|
433
|
+
} else {
|
|
434
|
+
if (targetNetwork) {
|
|
435
|
+
removeWalletAddress(targetNetwork);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
292
439
|
async function getCurrentWallet(networkType) {
|
|
293
440
|
if (typeof window === "undefined") {
|
|
294
441
|
return null;
|
|
@@ -390,12 +537,226 @@ async function switchNetwork(networkType) {
|
|
|
390
537
|
return null;
|
|
391
538
|
}
|
|
392
539
|
|
|
540
|
+
// src/utils/wallet-discovery.ts
|
|
541
|
+
var SOLANA_WALLETS = [
|
|
542
|
+
{
|
|
543
|
+
id: "phantom",
|
|
544
|
+
name: "Phantom",
|
|
545
|
+
// Phantom official icon
|
|
546
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZD0iTTExMC41IDY0QzExMC41IDg5Ljk1NjggODkuMjAxIDExMSA2My41IDExMUg0MS41QzM2LjI1MzMgMTExIDMyIDEwNi43NDcgMzIgMTAxLjVWNTQuNUMzMiAzMS4wMjggNTEuMDI4IDEyIDc0LjUgMTJDOTcuOTcyIDEyIDExNyAzMS4wMjggMTE3IDU0LjVWNTUuNUMxMTcgNTguNTM3NiAxMTQuNTM4IDYxIDExMS41IDYxSDEwOS41QzEwNi40NjIgNjEgMTA0IDYzLjQ2MjQgMTA0IDY2LjVWNjhDMTA0IDcxLjg2NiAxMDcuMTM0IDc1IDExMSA3NUgxMTEuNUMxMTQuNTM4IDc1IDExNyA3Mi41Mzc2IDExNyA2OS41VjY0SDExMC41WiIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzEyOF8xMjgpIi8+CjxwYXRoIGQ9Ik00OC41IDY3QzUxLjUzNzYgNjcgNTQgNjQuNTM3NiA1NCA2MS41QzU0IDU4LjQ2MjQgNTEuNTM3NiA1NiA0OC41IDU2QzQ1LjQ2MjQgNTYgNDMgNTguNDYyNCA0MyA2MS41QzQzIDY0LjUzNzYgNDUuNDYyNCA2NyA0OC41IDY3WiIgZmlsbD0iIzFCMUIxQiIvPgo8cGF0aCBkPSJNNzMuNSA2N0M3Ni41Mzc2IDY3IDc5IDY0LjUzNzYgNzkgNjEuNUM3OSA1OC40NjI0IDc2LjUzNzYgNTYgNzMuNSA1NkM3MC40NjI0IDU2IDY4IDU4LjQ2MjQgNjggNjEuNUM2OCA2NC41Mzc2IDcwLjQ2MjQgNjcgNzMuNSA2N1oiIGZpbGw9IiMxQjFCMUIiLz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl8xMjhfMTI4IiB4MT0iMTE3IiB5MT0iMTIiIHgyPSIxMTciIHkyPSIxMTEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRkZGRiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRkZGRkYiIHN0b3Atb3BhY2l0eT0iMC44MiIvPgo8L2xpbmVhckdyYWRpZW50Pgo8L2RlZnM+Cjwvc3ZnPg==",
|
|
547
|
+
detect: () => window.phantom?.solana
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
id: "solflare",
|
|
551
|
+
name: "Solflare",
|
|
552
|
+
// Solflare icon
|
|
553
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNGQzZEMDEiLz4KPHBhdGggZD0iTTk2IDY0TDY0IDMyTDMyIDY0TDY0IDk2TDk2IDY0WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+",
|
|
554
|
+
detect: () => window.solflare
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
id: "backpack",
|
|
558
|
+
name: "Backpack",
|
|
559
|
+
// Backpack icon (red coral color)
|
|
560
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNFMzM0MzAiLz4KPHBhdGggZD0iTTQwIDQ4SDg4VjgwQzg4IDg4LjgzNjYgODAuODM2NiA5NiA3MiA5Nkg1NkM0Ny4xNjM0IDk2IDQwIDg4LjgzNjYgNDAgODBWNDhaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNTIgMzJINzZWNDhINTJWMzJaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
|
|
561
|
+
detect: () => window.backpack
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
id: "okx-solana",
|
|
565
|
+
name: "OKX Wallet",
|
|
566
|
+
// OKX icon
|
|
567
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9ImJsYWNrIi8+CjxyZWN0IHg9IjI0IiB5PSIyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iNTIiIHk9IjI0IiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSI4MCIgeT0iMjQiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjI0IiB5PSI1MiIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjUyIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSIyNCIgeT0iODAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjUyIiB5PSI4MCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjgwIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
|
|
568
|
+
detect: () => window.okxwallet?.solana
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
id: "coinbase-solana",
|
|
572
|
+
name: "Coinbase Wallet",
|
|
573
|
+
// Coinbase icon (blue)
|
|
574
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwMDUyRkYiLz4KPGNpcmNsZSBjeD0iNjQiIGN5PSI2NCIgcj0iMzYiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjQ4IiB5PSI1NiIgd2lkdGg9IjMyIiBoZWlnaHQ9IjE2IiByeD0iNCIgZmlsbD0iIzAwNTJGRiIvPgo8L3N2Zz4=",
|
|
575
|
+
detect: () => window.coinbaseSolana
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
id: "trust-solana",
|
|
579
|
+
name: "Trust Wallet",
|
|
580
|
+
// Trust Wallet icon
|
|
581
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwNTAwRkYiLz4KPHBhdGggZD0iTTY0IDI0QzY0IDI0IDk2IDQwIDk2IDY0Qzk2IDg4IDY0IDEwNCA2NCAxMDRDNjQgMTA0IDMyIDg4IDMyIDY0QzMyIDQwIDY0IDI0IDY0IDI0WiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSI2IiBmaWxsPSJub25lIi8+Cjwvc3ZnPg==",
|
|
582
|
+
detect: () => window.trustwallet?.solana
|
|
583
|
+
}
|
|
584
|
+
];
|
|
585
|
+
var evmWallets = /* @__PURE__ */ new Map();
|
|
586
|
+
var evmDiscoveryListeners = /* @__PURE__ */ new Set();
|
|
587
|
+
var evmDiscoveryInitialized = false;
|
|
588
|
+
var currentConnectedWallet = null;
|
|
589
|
+
function initEVMWalletDiscovery() {
|
|
590
|
+
if (typeof window === "undefined" || evmDiscoveryInitialized) return;
|
|
591
|
+
evmDiscoveryInitialized = true;
|
|
592
|
+
window.addEventListener("eip6963:announceProvider", ((event) => {
|
|
593
|
+
const { info, provider } = event.detail;
|
|
594
|
+
evmWallets.set(info.uuid, { info, provider });
|
|
595
|
+
evmDiscoveryListeners.forEach((listener) => listener());
|
|
596
|
+
}));
|
|
597
|
+
window.dispatchEvent(new Event("eip6963:requestProvider"));
|
|
598
|
+
}
|
|
599
|
+
function getEVMWallets() {
|
|
600
|
+
const wallets = [];
|
|
601
|
+
const detectedNames = /* @__PURE__ */ new Set();
|
|
602
|
+
evmWallets.forEach((detail, uuid) => {
|
|
603
|
+
if (!detectedNames.has(detail.info.name)) {
|
|
604
|
+
wallets.push({
|
|
605
|
+
id: uuid,
|
|
606
|
+
name: detail.info.name,
|
|
607
|
+
icon: detail.info.icon,
|
|
608
|
+
networkType: "evm" /* EVM */,
|
|
609
|
+
provider: detail.provider,
|
|
610
|
+
installed: true
|
|
611
|
+
});
|
|
612
|
+
detectedNames.add(detail.info.name);
|
|
613
|
+
}
|
|
614
|
+
});
|
|
615
|
+
if (wallets.length === 0 && typeof window !== "undefined" && window.ethereum) {
|
|
616
|
+
const ethereum = window.ethereum;
|
|
617
|
+
const walletName = ethereum.isMetaMask ? "MetaMask" : ethereum.isCoinbaseWallet ? "Coinbase Wallet" : ethereum.isOkxWallet ? "OKX Wallet" : "Browser Wallet";
|
|
618
|
+
if (!detectedNames.has(walletName)) {
|
|
619
|
+
wallets.push({
|
|
620
|
+
id: "injected",
|
|
621
|
+
name: walletName,
|
|
622
|
+
icon: "",
|
|
623
|
+
// Will use first letter as avatar
|
|
624
|
+
networkType: "evm" /* EVM */,
|
|
625
|
+
provider: ethereum,
|
|
626
|
+
installed: true
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
return wallets;
|
|
631
|
+
}
|
|
632
|
+
function onEVMWalletsChanged(callback) {
|
|
633
|
+
evmDiscoveryListeners.add(callback);
|
|
634
|
+
return () => {
|
|
635
|
+
evmDiscoveryListeners.delete(callback);
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function getSolanaWallets() {
|
|
639
|
+
if (typeof window === "undefined") return [];
|
|
640
|
+
const wallets = [];
|
|
641
|
+
const detectedProviders = /* @__PURE__ */ new Set();
|
|
642
|
+
const detectedNames = /* @__PURE__ */ new Set();
|
|
643
|
+
for (const wallet of SOLANA_WALLETS) {
|
|
644
|
+
const provider = wallet.detect();
|
|
645
|
+
if (provider && !detectedNames.has(wallet.name)) {
|
|
646
|
+
wallets.push({
|
|
647
|
+
id: wallet.id,
|
|
648
|
+
name: wallet.name,
|
|
649
|
+
icon: wallet.icon,
|
|
650
|
+
networkType: "solana" /* SOLANA */,
|
|
651
|
+
provider,
|
|
652
|
+
installed: true
|
|
653
|
+
});
|
|
654
|
+
detectedProviders.add(provider);
|
|
655
|
+
detectedNames.add(wallet.name);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
const windowSolana = window.solana;
|
|
659
|
+
if (windowSolana && !detectedProviders.has(windowSolana)) {
|
|
660
|
+
const walletName = windowSolana.isPhantom ? "Phantom" : windowSolana.isSolflare ? "Solflare" : windowSolana.isBackpack ? "Backpack" : windowSolana.walletName || "Solana Wallet";
|
|
661
|
+
if (!detectedNames.has(walletName)) {
|
|
662
|
+
wallets.push({
|
|
663
|
+
id: "solana-unknown",
|
|
664
|
+
name: walletName,
|
|
665
|
+
icon: "",
|
|
666
|
+
// Will use first letter as avatar
|
|
667
|
+
networkType: "solana" /* SOLANA */,
|
|
668
|
+
provider: windowSolana,
|
|
669
|
+
installed: true
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
return wallets;
|
|
674
|
+
}
|
|
675
|
+
function getWalletsForNetwork(networkType) {
|
|
676
|
+
switch (networkType) {
|
|
677
|
+
case "evm" /* EVM */:
|
|
678
|
+
return getEVMWallets();
|
|
679
|
+
case "solana" /* SOLANA */:
|
|
680
|
+
case "svm" /* SVM */:
|
|
681
|
+
return getSolanaWallets();
|
|
682
|
+
default:
|
|
683
|
+
return [];
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
async function connectEVMWallet(wallet) {
|
|
687
|
+
if (!wallet.provider) {
|
|
688
|
+
throw new Error(`\u94B1\u5305 ${wallet.name} \u4E0D\u53EF\u7528`);
|
|
689
|
+
}
|
|
690
|
+
const accounts = await wallet.provider.request({
|
|
691
|
+
method: "eth_requestAccounts",
|
|
692
|
+
params: []
|
|
693
|
+
});
|
|
694
|
+
if (!accounts || accounts.length === 0) {
|
|
695
|
+
throw new Error("\u672A\u80FD\u83B7\u53D6\u5230\u94B1\u5305\u5730\u5740");
|
|
696
|
+
}
|
|
697
|
+
return accounts[0];
|
|
698
|
+
}
|
|
699
|
+
async function connectSolanaWallet(wallet) {
|
|
700
|
+
if (!wallet.provider) {
|
|
701
|
+
throw new Error(`\u94B1\u5305 ${wallet.name} \u4E0D\u53EF\u7528`);
|
|
702
|
+
}
|
|
703
|
+
if (wallet.provider.isConnected) {
|
|
704
|
+
try {
|
|
705
|
+
await wallet.provider.disconnect();
|
|
706
|
+
} catch (err) {
|
|
707
|
+
console.warn("Failed to disconnect before connecting:", err);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
const response = await wallet.provider.connect();
|
|
711
|
+
return response.publicKey.toString();
|
|
712
|
+
}
|
|
713
|
+
async function connectToWallet(wallet) {
|
|
714
|
+
let address;
|
|
715
|
+
switch (wallet.networkType) {
|
|
716
|
+
case "evm" /* EVM */:
|
|
717
|
+
address = await connectEVMWallet(wallet);
|
|
718
|
+
break;
|
|
719
|
+
case "solana" /* SOLANA */:
|
|
720
|
+
case "svm" /* SVM */:
|
|
721
|
+
address = await connectSolanaWallet(wallet);
|
|
722
|
+
break;
|
|
723
|
+
default:
|
|
724
|
+
throw new Error("\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B");
|
|
725
|
+
}
|
|
726
|
+
currentConnectedWallet = wallet;
|
|
727
|
+
return address;
|
|
728
|
+
}
|
|
729
|
+
function setCurrentConnectedWallet(wallet) {
|
|
730
|
+
currentConnectedWallet = wallet;
|
|
731
|
+
}
|
|
732
|
+
function clearConnectedWallet() {
|
|
733
|
+
currentConnectedWallet = null;
|
|
734
|
+
}
|
|
735
|
+
function getWalletProviderForPayment(networkType) {
|
|
736
|
+
if (currentConnectedWallet && currentConnectedWallet.networkType === networkType) {
|
|
737
|
+
return currentConnectedWallet.provider;
|
|
738
|
+
}
|
|
739
|
+
if (typeof window === "undefined") return null;
|
|
740
|
+
switch (networkType) {
|
|
741
|
+
case "evm" /* EVM */:
|
|
742
|
+
return window.ethereum;
|
|
743
|
+
case "solana" /* SOLANA */:
|
|
744
|
+
case "svm" /* SVM */:
|
|
745
|
+
return window.phantom?.solana || window.solana;
|
|
746
|
+
default:
|
|
747
|
+
return null;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
if (typeof window !== "undefined") {
|
|
751
|
+
initEVMWalletDiscovery();
|
|
752
|
+
}
|
|
753
|
+
|
|
393
754
|
// src/services/svm/payment-header.ts
|
|
394
755
|
var import_web3 = require("@solana/web3.js");
|
|
395
756
|
var import_spl_token = require("@solana/spl-token");
|
|
396
757
|
async function createSvmPaymentHeader(params) {
|
|
397
758
|
const { wallet, paymentRequirements, x402Version, rpcUrl } = params;
|
|
398
|
-
const connection = new import_web3.Connection(rpcUrl
|
|
759
|
+
const connection = new import_web3.Connection(rpcUrl);
|
|
399
760
|
const feePayer = paymentRequirements?.extra?.feePayer;
|
|
400
761
|
if (typeof feePayer !== "string" || !feePayer) {
|
|
401
762
|
throw new Error("Missing facilitator feePayer in payment requirements (extra.feePayer).");
|
|
@@ -409,83 +770,85 @@ async function createSvmPaymentHeader(params) {
|
|
|
409
770
|
if (!paymentRequirements?.payTo) {
|
|
410
771
|
throw new Error("Missing payTo in payment requirements");
|
|
411
772
|
}
|
|
412
|
-
const
|
|
413
|
-
const instructions = [];
|
|
414
|
-
instructions.push(
|
|
415
|
-
import_web3.ComputeBudgetProgram.setComputeUnitLimit({
|
|
416
|
-
units: 7e3
|
|
417
|
-
// Sufficient for SPL token transfer
|
|
418
|
-
})
|
|
419
|
-
);
|
|
420
|
-
instructions.push(
|
|
421
|
-
import_web3.ComputeBudgetProgram.setComputeUnitPrice({
|
|
422
|
-
microLamports: 1
|
|
423
|
-
// Minimal price
|
|
424
|
-
})
|
|
425
|
-
);
|
|
773
|
+
const destinationPubkey = new import_web3.PublicKey(paymentRequirements.payTo);
|
|
426
774
|
if (!paymentRequirements.asset) {
|
|
427
775
|
throw new Error("Missing token mint for SPL transfer");
|
|
428
776
|
}
|
|
429
777
|
const mintPubkey = new import_web3.PublicKey(paymentRequirements.asset);
|
|
430
|
-
const
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
778
|
+
const mintAccountInfo = await connection.getAccountInfo(mintPubkey);
|
|
779
|
+
if (!mintAccountInfo) {
|
|
780
|
+
throw new Error(`Mint account ${mintPubkey.toBase58()} not found`);
|
|
781
|
+
}
|
|
782
|
+
const tokenProgramId = mintAccountInfo.owner.equals(import_spl_token.TOKEN_2022_PROGRAM_ID) ? import_spl_token.TOKEN_2022_PROGRAM_ID : import_spl_token.TOKEN_PROGRAM_ID;
|
|
783
|
+
const mint = await (0, import_spl_token.getMint)(connection, mintPubkey, void 0, tokenProgramId);
|
|
784
|
+
const sourceAta = (0, import_spl_token.getAssociatedTokenAddressSync)(
|
|
434
785
|
mintPubkey,
|
|
435
786
|
userPubkey,
|
|
436
787
|
false,
|
|
437
|
-
|
|
788
|
+
tokenProgramId
|
|
438
789
|
);
|
|
439
|
-
const destinationAta =
|
|
790
|
+
const destinationAta = (0, import_spl_token.getAssociatedTokenAddressSync)(
|
|
440
791
|
mintPubkey,
|
|
441
|
-
|
|
792
|
+
destinationPubkey,
|
|
442
793
|
false,
|
|
443
|
-
|
|
794
|
+
tokenProgramId
|
|
444
795
|
);
|
|
445
|
-
const sourceAtaInfo = await connection.getAccountInfo(sourceAta
|
|
796
|
+
const sourceAtaInfo = await connection.getAccountInfo(sourceAta);
|
|
446
797
|
if (!sourceAtaInfo) {
|
|
447
798
|
throw new Error(
|
|
448
799
|
`User does not have an Associated Token Account for ${paymentRequirements.asset}. Please create one first or ensure you have the required token.`
|
|
449
800
|
);
|
|
450
801
|
}
|
|
451
|
-
const destAtaInfo = await connection.getAccountInfo(destinationAta
|
|
802
|
+
const destAtaInfo = await connection.getAccountInfo(destinationAta);
|
|
452
803
|
if (!destAtaInfo) {
|
|
453
804
|
throw new Error(
|
|
454
805
|
`Destination does not have an Associated Token Account for ${paymentRequirements.asset}. The receiver must create their token account before receiving payments.`
|
|
455
806
|
);
|
|
456
807
|
}
|
|
457
|
-
const
|
|
458
|
-
|
|
808
|
+
const instructions = [
|
|
809
|
+
import_web3.ComputeBudgetProgram.setComputeUnitLimit({
|
|
810
|
+
units: 7e3
|
|
811
|
+
// Sufficient for SPL token transfer
|
|
812
|
+
}),
|
|
813
|
+
import_web3.ComputeBudgetProgram.setComputeUnitPrice({
|
|
814
|
+
microLamports: 1
|
|
815
|
+
// Minimal price
|
|
816
|
+
}),
|
|
459
817
|
(0, import_spl_token.createTransferCheckedInstruction)(
|
|
460
818
|
sourceAta,
|
|
461
819
|
mintPubkey,
|
|
462
820
|
destinationAta,
|
|
463
821
|
userPubkey,
|
|
464
|
-
|
|
822
|
+
BigInt(paymentRequirements.maxAmountRequired),
|
|
465
823
|
mint.decimals,
|
|
466
824
|
[],
|
|
467
|
-
|
|
825
|
+
tokenProgramId
|
|
468
826
|
)
|
|
469
|
-
|
|
470
|
-
const { blockhash } = await connection.getLatestBlockhash(
|
|
471
|
-
const
|
|
827
|
+
];
|
|
828
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
829
|
+
const messageV0 = new import_web3.TransactionMessage({
|
|
472
830
|
payerKey: feePayerPubkey,
|
|
473
831
|
recentBlockhash: blockhash,
|
|
474
832
|
instructions
|
|
475
833
|
}).compileToV0Message();
|
|
476
|
-
const transaction = new import_web3.VersionedTransaction(
|
|
834
|
+
const transaction = new import_web3.VersionedTransaction(messageV0);
|
|
477
835
|
if (typeof wallet?.signTransaction !== "function") {
|
|
478
836
|
throw new Error("Connected wallet does not support signTransaction");
|
|
479
837
|
}
|
|
480
|
-
let
|
|
838
|
+
let signedTransaction;
|
|
481
839
|
try {
|
|
482
|
-
|
|
840
|
+
signedTransaction = await wallet.signTransaction(transaction);
|
|
483
841
|
console.log("\u2705 Transaction signed successfully");
|
|
484
842
|
} catch (error) {
|
|
485
843
|
console.error("\u274C Failed to sign transaction:", error);
|
|
486
844
|
throw wrapPaymentError(error);
|
|
487
845
|
}
|
|
488
|
-
const
|
|
846
|
+
const serializedBytes = signedTransaction.serialize();
|
|
847
|
+
let binary = "";
|
|
848
|
+
for (let i = 0; i < serializedBytes.length; i++) {
|
|
849
|
+
binary += String.fromCharCode(serializedBytes[i]);
|
|
850
|
+
}
|
|
851
|
+
const serializedTransaction = btoa(binary);
|
|
489
852
|
const paymentPayload = {
|
|
490
853
|
x402Version,
|
|
491
854
|
scheme: paymentRequirements.scheme,
|
|
@@ -494,7 +857,7 @@ async function createSvmPaymentHeader(params) {
|
|
|
494
857
|
transaction: serializedTransaction
|
|
495
858
|
}
|
|
496
859
|
};
|
|
497
|
-
const paymentHeader =
|
|
860
|
+
const paymentHeader = btoa(JSON.stringify(paymentPayload));
|
|
498
861
|
return paymentHeader;
|
|
499
862
|
}
|
|
500
863
|
function getDefaultSolanaRpcUrl(network) {
|
|
@@ -510,7 +873,7 @@ function getDefaultSolanaRpcUrl(network) {
|
|
|
510
873
|
// src/services/svm/payment-handler.ts
|
|
511
874
|
init_types();
|
|
512
875
|
async function handleSvmPayment(endpoint, config, requestInit) {
|
|
513
|
-
const { wallet,
|
|
876
|
+
const { wallet, rpcUrl, maxPaymentAmount } = config;
|
|
514
877
|
const initialResponse = await fetch(endpoint, {
|
|
515
878
|
...requestInit,
|
|
516
879
|
method: requestInit?.method || "POST"
|
|
@@ -519,26 +882,10 @@ async function handleSvmPayment(endpoint, config, requestInit) {
|
|
|
519
882
|
return initialResponse;
|
|
520
883
|
}
|
|
521
884
|
const rawResponse = await initialResponse.json();
|
|
522
|
-
|
|
523
|
-
"X-PAYMENT header is required",
|
|
524
|
-
"missing X-PAYMENT header",
|
|
525
|
-
"payment_required"
|
|
526
|
-
];
|
|
527
|
-
if (rawResponse.error && !IGNORED_ERRORS.includes(rawResponse.error)) {
|
|
885
|
+
if (rawResponse.error && !IGNORED_402_ERRORS.includes(rawResponse.error)) {
|
|
528
886
|
console.error(`\u274C Payment verification failed: ${rawResponse.error}`);
|
|
529
|
-
const
|
|
530
|
-
|
|
531
|
-
"invalid_signature": "Invalid payment signature",
|
|
532
|
-
"expired": "Payment authorization has expired",
|
|
533
|
-
"already_used": "This payment has already been used",
|
|
534
|
-
"network_mismatch": "Payment network does not match",
|
|
535
|
-
"invalid_payment": "Invalid payment data",
|
|
536
|
-
"verification_failed": "Payment verification failed",
|
|
537
|
-
"invalid_exact_svm_payload_transaction_simulation_failed": "Transaction simulation failed due to insufficient balance. Please check your wallet balance carefully and ensure you have enough funds to cover the payment and transaction fees."
|
|
538
|
-
};
|
|
539
|
-
const errorMessage = ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
|
|
540
|
-
const error = new Error(errorMessage);
|
|
541
|
-
throw wrapPaymentError(error);
|
|
887
|
+
const errorMessage = PAYMENT_ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
|
|
888
|
+
throw wrapPaymentError(new Error(errorMessage));
|
|
542
889
|
}
|
|
543
890
|
const x402Version = rawResponse.x402Version;
|
|
544
891
|
const parsedPaymentRequirements = rawResponse.accepts || [];
|
|
@@ -588,26 +935,10 @@ async function handleSvmPayment(endpoint, config, requestInit) {
|
|
|
588
935
|
if (retryResponse.status === 402) {
|
|
589
936
|
try {
|
|
590
937
|
const retryData = await retryResponse.json();
|
|
591
|
-
|
|
592
|
-
"X-PAYMENT header is required",
|
|
593
|
-
"missing X-PAYMENT header",
|
|
594
|
-
"payment_required"
|
|
595
|
-
];
|
|
596
|
-
if (retryData.error && !IGNORED_ERRORS2.includes(retryData.error)) {
|
|
938
|
+
if (retryData.error && !IGNORED_402_ERRORS.includes(retryData.error)) {
|
|
597
939
|
console.error(`\u274C Payment verification failed: ${retryData.error}`);
|
|
598
|
-
const
|
|
599
|
-
|
|
600
|
-
"invalid_signature": "Invalid payment signature",
|
|
601
|
-
"expired": "Payment authorization has expired",
|
|
602
|
-
"already_used": "This payment has already been used",
|
|
603
|
-
"network_mismatch": "Payment network does not match",
|
|
604
|
-
"invalid_payment": "Invalid payment data",
|
|
605
|
-
"verification_failed": "Payment verification failed",
|
|
606
|
-
"invalid_exact_svm_payload_transaction_simulation_failed": "Transaction simulation failed due to insufficient balance. Please check your wallet balance carefully and ensure you have enough funds to cover the payment and transaction fees."
|
|
607
|
-
};
|
|
608
|
-
const errorMessage = ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
|
|
609
|
-
const error = new Error(errorMessage);
|
|
610
|
-
throw wrapPaymentError(error);
|
|
940
|
+
const errorMessage = PAYMENT_ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
|
|
941
|
+
throw wrapPaymentError(new Error(errorMessage));
|
|
611
942
|
}
|
|
612
943
|
} catch (error) {
|
|
613
944
|
if (error instanceof PaymentOperationError) {
|
|
@@ -734,6 +1065,15 @@ function getChainIdFromNetwork(network) {
|
|
|
734
1065
|
|
|
735
1066
|
// src/services/evm/payment-handler.ts
|
|
736
1067
|
init_types();
|
|
1068
|
+
var NETWORK_NAMES = {
|
|
1069
|
+
1: "Ethereum Mainnet",
|
|
1070
|
+
11155111: "Sepolia Testnet",
|
|
1071
|
+
8453: "Base Mainnet",
|
|
1072
|
+
84532: "Base Sepolia Testnet",
|
|
1073
|
+
137: "Polygon Mainnet",
|
|
1074
|
+
42161: "Arbitrum One",
|
|
1075
|
+
10: "Optimism Mainnet"
|
|
1076
|
+
};
|
|
737
1077
|
async function handleEvmPayment(endpoint, config, requestInit) {
|
|
738
1078
|
const { wallet, network, maxPaymentAmount } = config;
|
|
739
1079
|
const initialResponse = await fetch(endpoint, {
|
|
@@ -744,25 +1084,10 @@ async function handleEvmPayment(endpoint, config, requestInit) {
|
|
|
744
1084
|
return initialResponse;
|
|
745
1085
|
}
|
|
746
1086
|
const rawResponse = await initialResponse.json();
|
|
747
|
-
|
|
748
|
-
"X-PAYMENT header is required",
|
|
749
|
-
"missing X-PAYMENT header",
|
|
750
|
-
"payment_required"
|
|
751
|
-
];
|
|
752
|
-
if (rawResponse.error && !IGNORED_ERRORS.includes(rawResponse.error)) {
|
|
1087
|
+
if (rawResponse.error && !IGNORED_402_ERRORS.includes(rawResponse.error)) {
|
|
753
1088
|
console.error(`\u274C Payment verification failed: ${rawResponse.error}`);
|
|
754
|
-
const
|
|
755
|
-
|
|
756
|
-
"invalid_signature": "Invalid payment signature",
|
|
757
|
-
"expired": "Payment authorization has expired",
|
|
758
|
-
"already_used": "This payment has already been used",
|
|
759
|
-
"network_mismatch": "Payment network does not match",
|
|
760
|
-
"invalid_payment": "Invalid payment data",
|
|
761
|
-
"verification_failed": "Payment verification failed"
|
|
762
|
-
};
|
|
763
|
-
const errorMessage = ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
|
|
764
|
-
const error = new Error(errorMessage);
|
|
765
|
-
throw wrapPaymentError(error);
|
|
1089
|
+
const errorMessage = PAYMENT_ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
|
|
1090
|
+
throw wrapPaymentError(new Error(errorMessage));
|
|
766
1091
|
}
|
|
767
1092
|
const x402Version = rawResponse.x402Version;
|
|
768
1093
|
const parsedPaymentRequirements = rawResponse.accepts || [];
|
|
@@ -794,19 +1119,10 @@ async function handleEvmPayment(endpoint, config, requestInit) {
|
|
|
794
1119
|
console.warn("\u26A0\uFE0F Failed to get current chainId:", error);
|
|
795
1120
|
}
|
|
796
1121
|
}
|
|
797
|
-
const networkNames = {
|
|
798
|
-
1: "Ethereum Mainnet",
|
|
799
|
-
11155111: "Sepolia Testnet",
|
|
800
|
-
8453: "Base Mainnet",
|
|
801
|
-
84532: "Base Sepolia Testnet",
|
|
802
|
-
137: "Polygon Mainnet",
|
|
803
|
-
42161: "Arbitrum One",
|
|
804
|
-
10: "Optimism Mainnet"
|
|
805
|
-
};
|
|
806
1122
|
if (currentChainId && currentChainId !== targetChainId) {
|
|
807
1123
|
if (!wallet.switchChain) {
|
|
808
|
-
const currentNetworkName =
|
|
809
|
-
const targetNetworkName =
|
|
1124
|
+
const currentNetworkName = NETWORK_NAMES[currentChainId] || `Chain ${currentChainId}`;
|
|
1125
|
+
const targetNetworkName = NETWORK_NAMES[targetChainId] || selectedRequirements.network;
|
|
810
1126
|
const error = new Error(
|
|
811
1127
|
`Network mismatch: Your wallet is connected to ${currentNetworkName}, but payment requires ${targetNetworkName}. Please switch to ${targetNetworkName} manually in your wallet.`
|
|
812
1128
|
);
|
|
@@ -818,7 +1134,7 @@ async function handleEvmPayment(endpoint, config, requestInit) {
|
|
|
818
1134
|
console.log(`\u2705 Successfully switched to chain ${targetChainId}`);
|
|
819
1135
|
} catch (error) {
|
|
820
1136
|
console.error("\u274C Failed to switch chain:", error);
|
|
821
|
-
const targetNetworkName =
|
|
1137
|
+
const targetNetworkName = NETWORK_NAMES[targetChainId] || selectedRequirements.network;
|
|
822
1138
|
const wrappedError = wrapPaymentError(error);
|
|
823
1139
|
let finalError;
|
|
824
1140
|
if (wrappedError.code === "USER_REJECTED" /* USER_REJECTED */) {
|
|
@@ -872,25 +1188,10 @@ async function handleEvmPayment(endpoint, config, requestInit) {
|
|
|
872
1188
|
if (retryResponse.status === 402) {
|
|
873
1189
|
try {
|
|
874
1190
|
const retryData = await retryResponse.json();
|
|
875
|
-
|
|
876
|
-
"X-PAYMENT header is required",
|
|
877
|
-
"missing X-PAYMENT header",
|
|
878
|
-
"payment_required"
|
|
879
|
-
];
|
|
880
|
-
if (retryData.error && !IGNORED_ERRORS2.includes(retryData.error)) {
|
|
1191
|
+
if (retryData.error && !IGNORED_402_ERRORS.includes(retryData.error)) {
|
|
881
1192
|
console.error(`\u274C Payment verification failed: ${retryData.error}`);
|
|
882
|
-
const
|
|
883
|
-
|
|
884
|
-
"invalid_signature": "Invalid payment signature",
|
|
885
|
-
"expired": "Payment authorization has expired",
|
|
886
|
-
"already_used": "This payment has already been used",
|
|
887
|
-
"network_mismatch": "Payment network does not match",
|
|
888
|
-
"invalid_payment": "Invalid payment data",
|
|
889
|
-
"verification_failed": "Payment verification failed"
|
|
890
|
-
};
|
|
891
|
-
const errorMessage = ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
|
|
892
|
-
const error = new Error(errorMessage);
|
|
893
|
-
throw wrapPaymentError(error);
|
|
1193
|
+
const errorMessage = PAYMENT_ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
|
|
1194
|
+
throw wrapPaymentError(new Error(errorMessage));
|
|
894
1195
|
}
|
|
895
1196
|
} catch (error) {
|
|
896
1197
|
if (error instanceof PaymentOperationError) {
|
|
@@ -938,9 +1239,9 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
|
|
|
938
1239
|
}
|
|
939
1240
|
} : {};
|
|
940
1241
|
if (networkType === "solana" /* SOLANA */ || networkType === "svm" /* SVM */) {
|
|
941
|
-
const solana =
|
|
1242
|
+
const solana = getWalletProviderForPayment(networkType);
|
|
942
1243
|
if (!solana) {
|
|
943
|
-
throw new Error("\u8BF7\
|
|
1244
|
+
throw new Error("\u8BF7\u5148\u8FDE\u63A5 Solana \u94B1\u5305");
|
|
944
1245
|
}
|
|
945
1246
|
if (!solana.isConnected) {
|
|
946
1247
|
await solana.connect();
|
|
@@ -951,10 +1252,11 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
|
|
|
951
1252
|
// Will use backend's network configuration
|
|
952
1253
|
}, requestInit);
|
|
953
1254
|
} else if (networkType === "evm" /* EVM */) {
|
|
954
|
-
|
|
955
|
-
|
|
1255
|
+
const ethereum = getWalletProviderForPayment(networkType);
|
|
1256
|
+
if (!ethereum) {
|
|
1257
|
+
throw new Error("\u8BF7\u5148\u8FDE\u63A5 EVM \u94B1\u5305");
|
|
956
1258
|
}
|
|
957
|
-
const provider = new import_ethers2.ethers.BrowserProvider(
|
|
1259
|
+
const provider = new import_ethers2.ethers.BrowserProvider(ethereum);
|
|
958
1260
|
const signer = await provider.getSigner();
|
|
959
1261
|
const wallet = {
|
|
960
1262
|
address: await signer.getAddress(),
|
|
@@ -968,7 +1270,7 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
|
|
|
968
1270
|
},
|
|
969
1271
|
// Switch to a different chain
|
|
970
1272
|
switchChain: async (chainId) => {
|
|
971
|
-
await
|
|
1273
|
+
await ethereum.request({
|
|
972
1274
|
method: "wallet_switchEthereumChain",
|
|
973
1275
|
params: [{ chainId }]
|
|
974
1276
|
});
|
|
@@ -1023,6 +1325,21 @@ function getNetworkDisplayName(network) {
|
|
|
1023
1325
|
}
|
|
1024
1326
|
|
|
1025
1327
|
// src/utils/payment-error-handler.ts
|
|
1328
|
+
var IGNORED_402_ERRORS = [
|
|
1329
|
+
"X-PAYMENT header is required",
|
|
1330
|
+
"missing X-PAYMENT header",
|
|
1331
|
+
"payment_required"
|
|
1332
|
+
];
|
|
1333
|
+
var PAYMENT_ERROR_MESSAGES = {
|
|
1334
|
+
"insufficient_funds": "Insufficient balance to complete this payment",
|
|
1335
|
+
"invalid_signature": "Invalid payment signature",
|
|
1336
|
+
"expired": "Payment authorization has expired",
|
|
1337
|
+
"already_used": "This payment has already been used",
|
|
1338
|
+
"network_mismatch": "Payment network does not match",
|
|
1339
|
+
"invalid_payment": "Invalid payment data",
|
|
1340
|
+
"verification_failed": "Payment verification failed",
|
|
1341
|
+
"invalid_exact_svm_payload_transaction_simulation_failed": "Transaction simulation failed due to insufficient balance. Please check your wallet balance carefully and ensure you have enough funds to cover the payment and transaction fees."
|
|
1342
|
+
};
|
|
1026
1343
|
function parsePaymentError(error) {
|
|
1027
1344
|
if (!error) {
|
|
1028
1345
|
return {
|
|
@@ -1226,13 +1543,18 @@ var WalletStore = class {
|
|
|
1226
1543
|
});
|
|
1227
1544
|
}
|
|
1228
1545
|
// Connect wallet
|
|
1229
|
-
|
|
1546
|
+
// @param forceSelect - 强制弹出钱包选择界面,用于切换账户
|
|
1547
|
+
async connect(type, forceSelect = false) {
|
|
1230
1548
|
if (this.state.address && this.state.networkType && this.state.networkType !== type) {
|
|
1231
1549
|
saveWalletAddress(this.state.networkType, this.state.address);
|
|
1232
1550
|
}
|
|
1233
1551
|
this.setState({ isConnecting: true, error: null });
|
|
1234
1552
|
try {
|
|
1235
|
-
const walletAddress = await connectWallet(type);
|
|
1553
|
+
const walletAddress = await connectWallet(type, forceSelect);
|
|
1554
|
+
const wallets = getWalletsForNetwork(type);
|
|
1555
|
+
if (wallets.length > 0) {
|
|
1556
|
+
setCurrentConnectedWallet(wallets[0]);
|
|
1557
|
+
}
|
|
1236
1558
|
this.setState({
|
|
1237
1559
|
address: walletAddress,
|
|
1238
1560
|
networkType: type,
|
|
@@ -1246,6 +1568,30 @@ var WalletStore = class {
|
|
|
1246
1568
|
throw err;
|
|
1247
1569
|
}
|
|
1248
1570
|
}
|
|
1571
|
+
// Connect to a specific wallet (from wallet discovery)
|
|
1572
|
+
async connectWithWallet(wallet) {
|
|
1573
|
+
if (this.state.address && this.state.networkType && this.state.networkType !== wallet.networkType) {
|
|
1574
|
+
saveWalletAddress(this.state.networkType, this.state.address);
|
|
1575
|
+
}
|
|
1576
|
+
this.setState({ isConnecting: true, error: null });
|
|
1577
|
+
try {
|
|
1578
|
+
const walletAddress = await connectToWallet(wallet);
|
|
1579
|
+
clearWalletDisconnection(wallet.networkType);
|
|
1580
|
+
saveConnectedNetworkType(wallet.networkType);
|
|
1581
|
+
saveWalletAddress(wallet.networkType, walletAddress);
|
|
1582
|
+
this.setState({
|
|
1583
|
+
address: walletAddress,
|
|
1584
|
+
networkType: wallet.networkType,
|
|
1585
|
+
isConnecting: false
|
|
1586
|
+
});
|
|
1587
|
+
} catch (err) {
|
|
1588
|
+
this.setState({
|
|
1589
|
+
error: err.message || "Failed to connect wallet",
|
|
1590
|
+
isConnecting: false
|
|
1591
|
+
});
|
|
1592
|
+
throw err;
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1249
1595
|
// Switch network (use cached wallet if available)
|
|
1250
1596
|
async switchNetwork(type) {
|
|
1251
1597
|
if (this.state.address && this.state.networkType) {
|
|
@@ -1277,9 +1623,15 @@ var WalletStore = class {
|
|
|
1277
1623
|
}
|
|
1278
1624
|
}
|
|
1279
1625
|
// Disconnect wallet
|
|
1280
|
-
disconnect() {
|
|
1626
|
+
async disconnect() {
|
|
1281
1627
|
const currentNetwork = this.state.networkType;
|
|
1628
|
+
clearConnectedWallet();
|
|
1282
1629
|
if (currentNetwork) {
|
|
1630
|
+
try {
|
|
1631
|
+
await disconnectWallet(currentNetwork);
|
|
1632
|
+
} catch (err) {
|
|
1633
|
+
console.warn("Failed to disconnect wallet provider:", err);
|
|
1634
|
+
}
|
|
1283
1635
|
this.handleDisconnect(currentNetwork);
|
|
1284
1636
|
} else {
|
|
1285
1637
|
this.setState({
|
|
@@ -1323,7 +1675,8 @@ function useWallet() {
|
|
|
1323
1675
|
);
|
|
1324
1676
|
return {
|
|
1325
1677
|
...state,
|
|
1326
|
-
connect: (type) => walletStore.connect(type),
|
|
1678
|
+
connect: (type, forceSelect) => walletStore.connect(type, forceSelect),
|
|
1679
|
+
connectWithWallet: (wallet) => walletStore.connectWithWallet(wallet),
|
|
1327
1680
|
switchNetwork: (type) => walletStore.switchNetwork(type),
|
|
1328
1681
|
ensureNetwork: (type) => walletStore.ensureNetwork(type),
|
|
1329
1682
|
disconnect: () => walletStore.disconnect(),
|
|
@@ -1432,7 +1785,218 @@ function usePaymentInfo(merchantId, endpoint = PROD_BACK_URL, additionalParams)
|
|
|
1432
1785
|
}
|
|
1433
1786
|
|
|
1434
1787
|
// src/react/components/WalletConnect.tsx
|
|
1788
|
+
var import_react6 = __toESM(require("react"));
|
|
1789
|
+
|
|
1790
|
+
// src/react/components/WalletSelectModal.tsx
|
|
1435
1791
|
var import_react5 = __toESM(require("react"));
|
|
1792
|
+
var import_react_dom = require("react-dom");
|
|
1793
|
+
var overlayStyle = {
|
|
1794
|
+
position: "fixed",
|
|
1795
|
+
top: 0,
|
|
1796
|
+
left: 0,
|
|
1797
|
+
right: 0,
|
|
1798
|
+
bottom: 0,
|
|
1799
|
+
backgroundColor: "rgba(0, 0, 0, 0.4)",
|
|
1800
|
+
display: "flex",
|
|
1801
|
+
alignItems: "center",
|
|
1802
|
+
justifyContent: "center",
|
|
1803
|
+
zIndex: 99999
|
|
1804
|
+
};
|
|
1805
|
+
var modalStyle = {
|
|
1806
|
+
backgroundColor: "#ffffff",
|
|
1807
|
+
borderRadius: "12px",
|
|
1808
|
+
padding: "16px",
|
|
1809
|
+
maxWidth: "320px",
|
|
1810
|
+
width: "90%",
|
|
1811
|
+
maxHeight: "70vh",
|
|
1812
|
+
overflow: "auto",
|
|
1813
|
+
boxShadow: "0 10px 25px rgba(0, 0, 0, 0.15)"
|
|
1814
|
+
};
|
|
1815
|
+
var headerStyle = {
|
|
1816
|
+
display: "flex",
|
|
1817
|
+
alignItems: "center",
|
|
1818
|
+
justifyContent: "space-between",
|
|
1819
|
+
marginBottom: "12px"
|
|
1820
|
+
};
|
|
1821
|
+
var titleStyle = {
|
|
1822
|
+
fontSize: "15px",
|
|
1823
|
+
fontWeight: 600,
|
|
1824
|
+
color: "#1a1a1a",
|
|
1825
|
+
margin: 0
|
|
1826
|
+
};
|
|
1827
|
+
var closeButtonStyle = {
|
|
1828
|
+
background: "none",
|
|
1829
|
+
border: "none",
|
|
1830
|
+
fontSize: "20px",
|
|
1831
|
+
cursor: "pointer",
|
|
1832
|
+
color: "#666",
|
|
1833
|
+
padding: "2px 6px",
|
|
1834
|
+
lineHeight: 1,
|
|
1835
|
+
borderRadius: "4px"
|
|
1836
|
+
};
|
|
1837
|
+
var subtitleStyle = {
|
|
1838
|
+
fontSize: "12px",
|
|
1839
|
+
color: "#666",
|
|
1840
|
+
marginBottom: "12px"
|
|
1841
|
+
};
|
|
1842
|
+
var walletListStyle = {
|
|
1843
|
+
display: "flex",
|
|
1844
|
+
flexDirection: "column",
|
|
1845
|
+
gap: "6px"
|
|
1846
|
+
};
|
|
1847
|
+
var getWalletItemStyle = (isHovered) => ({
|
|
1848
|
+
display: "flex",
|
|
1849
|
+
alignItems: "center",
|
|
1850
|
+
gap: "10px",
|
|
1851
|
+
padding: "10px 12px",
|
|
1852
|
+
border: "1px solid #e5e5e5",
|
|
1853
|
+
borderRadius: "8px",
|
|
1854
|
+
cursor: "pointer",
|
|
1855
|
+
transition: "all 0.15s ease",
|
|
1856
|
+
backgroundColor: isHovered ? "#f5f5f5" : "#ffffff",
|
|
1857
|
+
borderColor: isHovered ? "#d0d0d0" : "#e5e5e5"
|
|
1858
|
+
});
|
|
1859
|
+
var walletIconStyle = {
|
|
1860
|
+
width: "32px",
|
|
1861
|
+
height: "32px",
|
|
1862
|
+
borderRadius: "8px",
|
|
1863
|
+
objectFit: "contain",
|
|
1864
|
+
backgroundColor: "#f5f5f5"
|
|
1865
|
+
};
|
|
1866
|
+
var getAvatarColor = (name) => {
|
|
1867
|
+
const colors2 = [
|
|
1868
|
+
"#6366f1",
|
|
1869
|
+
// indigo
|
|
1870
|
+
"#8b5cf6",
|
|
1871
|
+
// violet
|
|
1872
|
+
"#ec4899",
|
|
1873
|
+
// pink
|
|
1874
|
+
"#f43f5e",
|
|
1875
|
+
// rose
|
|
1876
|
+
"#f97316",
|
|
1877
|
+
// orange
|
|
1878
|
+
"#eab308",
|
|
1879
|
+
// yellow
|
|
1880
|
+
"#22c55e",
|
|
1881
|
+
// green
|
|
1882
|
+
"#14b8a6",
|
|
1883
|
+
// teal
|
|
1884
|
+
"#06b6d4",
|
|
1885
|
+
// cyan
|
|
1886
|
+
"#3b82f6"
|
|
1887
|
+
// blue
|
|
1888
|
+
];
|
|
1889
|
+
const index = name.charCodeAt(0) % colors2.length;
|
|
1890
|
+
return colors2[index];
|
|
1891
|
+
};
|
|
1892
|
+
var getWalletIconPlaceholderStyle = (walletName) => ({
|
|
1893
|
+
width: "32px",
|
|
1894
|
+
height: "32px",
|
|
1895
|
+
borderRadius: "8px",
|
|
1896
|
+
backgroundColor: getAvatarColor(walletName),
|
|
1897
|
+
display: "flex",
|
|
1898
|
+
alignItems: "center",
|
|
1899
|
+
justifyContent: "center",
|
|
1900
|
+
fontSize: "14px",
|
|
1901
|
+
fontWeight: 600,
|
|
1902
|
+
color: "#ffffff"
|
|
1903
|
+
});
|
|
1904
|
+
var walletNameStyle = {
|
|
1905
|
+
fontSize: "14px",
|
|
1906
|
+
fontWeight: 500,
|
|
1907
|
+
color: "#1a1a1a"
|
|
1908
|
+
};
|
|
1909
|
+
var emptyStateStyle = {
|
|
1910
|
+
textAlign: "center",
|
|
1911
|
+
padding: "24px 12px",
|
|
1912
|
+
color: "#666"
|
|
1913
|
+
};
|
|
1914
|
+
var emptyTitleStyle = {
|
|
1915
|
+
fontSize: "14px",
|
|
1916
|
+
fontWeight: 500,
|
|
1917
|
+
marginBottom: "6px",
|
|
1918
|
+
color: "#1a1a1a"
|
|
1919
|
+
};
|
|
1920
|
+
var emptyDescStyle = {
|
|
1921
|
+
fontSize: "12px",
|
|
1922
|
+
color: "#888"
|
|
1923
|
+
};
|
|
1924
|
+
function WalletItem({
|
|
1925
|
+
wallet,
|
|
1926
|
+
isHovered,
|
|
1927
|
+
onSelect,
|
|
1928
|
+
onHover
|
|
1929
|
+
}) {
|
|
1930
|
+
const [iconError, setIconError] = (0, import_react5.useState)(false);
|
|
1931
|
+
return /* @__PURE__ */ import_react5.default.createElement(
|
|
1932
|
+
"div",
|
|
1933
|
+
{
|
|
1934
|
+
style: getWalletItemStyle(isHovered),
|
|
1935
|
+
onClick: onSelect,
|
|
1936
|
+
onMouseEnter: () => onHover(true),
|
|
1937
|
+
onMouseLeave: () => onHover(false)
|
|
1938
|
+
},
|
|
1939
|
+
wallet.icon && !iconError ? /* @__PURE__ */ import_react5.default.createElement(
|
|
1940
|
+
"img",
|
|
1941
|
+
{
|
|
1942
|
+
src: wallet.icon,
|
|
1943
|
+
alt: wallet.name,
|
|
1944
|
+
style: walletIconStyle,
|
|
1945
|
+
onError: () => setIconError(true)
|
|
1946
|
+
}
|
|
1947
|
+
) : /* @__PURE__ */ import_react5.default.createElement("div", { style: getWalletIconPlaceholderStyle(wallet.name) }, wallet.name.charAt(0).toUpperCase()),
|
|
1948
|
+
/* @__PURE__ */ import_react5.default.createElement("span", { style: walletNameStyle }, wallet.name)
|
|
1949
|
+
);
|
|
1950
|
+
}
|
|
1951
|
+
function WalletSelectModal({
|
|
1952
|
+
isOpen,
|
|
1953
|
+
networkType,
|
|
1954
|
+
onSelect,
|
|
1955
|
+
onClose
|
|
1956
|
+
}) {
|
|
1957
|
+
const [wallets, setWallets] = (0, import_react5.useState)([]);
|
|
1958
|
+
const [hoveredWallet, setHoveredWallet] = (0, import_react5.useState)(null);
|
|
1959
|
+
const [mounted, setMounted] = (0, import_react5.useState)(false);
|
|
1960
|
+
(0, import_react5.useEffect)(() => {
|
|
1961
|
+
setMounted(true);
|
|
1962
|
+
return () => setMounted(false);
|
|
1963
|
+
}, []);
|
|
1964
|
+
(0, import_react5.useEffect)(() => {
|
|
1965
|
+
if (!isOpen) return;
|
|
1966
|
+
initEVMWalletDiscovery();
|
|
1967
|
+
const updateWallets = () => {
|
|
1968
|
+
setWallets(getWalletsForNetwork(networkType));
|
|
1969
|
+
};
|
|
1970
|
+
updateWallets();
|
|
1971
|
+
const unsubscribe = onEVMWalletsChanged(updateWallets);
|
|
1972
|
+
const timer = setTimeout(updateWallets, 500);
|
|
1973
|
+
return () => {
|
|
1974
|
+
unsubscribe();
|
|
1975
|
+
clearTimeout(timer);
|
|
1976
|
+
};
|
|
1977
|
+
}, [isOpen, networkType]);
|
|
1978
|
+
if (!isOpen || !mounted) return null;
|
|
1979
|
+
const handleOverlayClick = (e) => {
|
|
1980
|
+
if (e.target === e.currentTarget) {
|
|
1981
|
+
onClose();
|
|
1982
|
+
}
|
|
1983
|
+
};
|
|
1984
|
+
const networkName = getNetworkDisplayName(networkType);
|
|
1985
|
+
const modalContent = /* @__PURE__ */ import_react5.default.createElement("div", { style: overlayStyle, onClick: handleOverlayClick }, /* @__PURE__ */ import_react5.default.createElement("div", { style: modalStyle }, /* @__PURE__ */ import_react5.default.createElement("div", { style: headerStyle }, /* @__PURE__ */ import_react5.default.createElement("h3", { style: titleStyle }, "Select Wallet"), /* @__PURE__ */ import_react5.default.createElement("button", { style: closeButtonStyle, onClick: onClose }, "\xD7")), /* @__PURE__ */ import_react5.default.createElement("p", { style: subtitleStyle }, "Connect a ", networkName, " wallet"), wallets.length > 0 ? /* @__PURE__ */ import_react5.default.createElement("div", { style: walletListStyle }, wallets.map((wallet) => /* @__PURE__ */ import_react5.default.createElement(
|
|
1986
|
+
WalletItem,
|
|
1987
|
+
{
|
|
1988
|
+
key: wallet.id,
|
|
1989
|
+
wallet,
|
|
1990
|
+
isHovered: hoveredWallet === wallet.id,
|
|
1991
|
+
onSelect: () => onSelect(wallet),
|
|
1992
|
+
onHover: (hovered) => setHoveredWallet(hovered ? wallet.id : null)
|
|
1993
|
+
}
|
|
1994
|
+
))) : /* @__PURE__ */ import_react5.default.createElement("div", { style: emptyStateStyle }, /* @__PURE__ */ import_react5.default.createElement("p", { style: emptyTitleStyle }, "No wallets found"), /* @__PURE__ */ import_react5.default.createElement("p", { style: emptyDescStyle }, "Please install a ", networkName, " wallet extension."))));
|
|
1995
|
+
if (typeof document !== "undefined") {
|
|
1996
|
+
return (0, import_react_dom.createPortal)(modalContent, document.body);
|
|
1997
|
+
}
|
|
1998
|
+
return modalContent;
|
|
1999
|
+
}
|
|
1436
2000
|
|
|
1437
2001
|
// src/react/styles/inline-styles.ts
|
|
1438
2002
|
var isDarkMode = () => {
|
|
@@ -1549,18 +2113,6 @@ var getDisconnectButtonStyle = (isHovered) => {
|
|
|
1549
2113
|
color: "#ffffff"
|
|
1550
2114
|
};
|
|
1551
2115
|
};
|
|
1552
|
-
var getInstallLinkStyle = (isHovered) => {
|
|
1553
|
-
const c = getColors();
|
|
1554
|
-
return {
|
|
1555
|
-
display: "inline-block",
|
|
1556
|
-
padding: "0.5rem",
|
|
1557
|
-
fontSize: "0.8125rem",
|
|
1558
|
-
color: c.textSecondary,
|
|
1559
|
-
textDecoration: isHovered ? "underline" : "none",
|
|
1560
|
-
textAlign: "center",
|
|
1561
|
-
fontWeight: 500
|
|
1562
|
-
};
|
|
1563
|
-
};
|
|
1564
2116
|
var walletAddressStyle = {
|
|
1565
2117
|
display: "flex",
|
|
1566
2118
|
flexDirection: "column",
|
|
@@ -1618,46 +2170,55 @@ function WalletConnect({
|
|
|
1618
2170
|
supportedNetworks = ["solana" /* SOLANA */, "evm" /* EVM */],
|
|
1619
2171
|
className = "",
|
|
1620
2172
|
onConnect,
|
|
1621
|
-
onDisconnect
|
|
2173
|
+
onDisconnect,
|
|
2174
|
+
showSwitchWallet = true
|
|
1622
2175
|
}) {
|
|
1623
|
-
const { address, networkType, isConnecting, error,
|
|
1624
|
-
const [hoveredButton, setHoveredButton] = (0,
|
|
1625
|
-
const [
|
|
1626
|
-
const
|
|
2176
|
+
const { address, networkType, isConnecting, error, connectWithWallet, disconnect } = useWallet();
|
|
2177
|
+
const [hoveredButton, setHoveredButton] = (0, import_react6.useState)(null);
|
|
2178
|
+
const [walletSelectOpen, setWalletSelectOpen] = (0, import_react6.useState)(false);
|
|
2179
|
+
const [selectedNetworkType, setSelectedNetworkType] = (0, import_react6.useState)(null);
|
|
2180
|
+
const handleOpenWalletSelect = (network) => {
|
|
2181
|
+
setSelectedNetworkType(network);
|
|
2182
|
+
setWalletSelectOpen(true);
|
|
2183
|
+
};
|
|
2184
|
+
const handleWalletSelect = async (wallet) => {
|
|
2185
|
+
setWalletSelectOpen(false);
|
|
1627
2186
|
try {
|
|
1628
|
-
await
|
|
2187
|
+
await connectWithWallet(wallet);
|
|
1629
2188
|
} catch (err) {
|
|
1630
2189
|
}
|
|
1631
2190
|
};
|
|
1632
|
-
const handleDisconnect = () => {
|
|
1633
|
-
disconnect();
|
|
2191
|
+
const handleDisconnect = async () => {
|
|
2192
|
+
await disconnect();
|
|
1634
2193
|
onDisconnect?.();
|
|
1635
2194
|
};
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
2195
|
+
const handleSwitchWallet = () => {
|
|
2196
|
+
if (networkType) {
|
|
2197
|
+
setSelectedNetworkType(networkType);
|
|
2198
|
+
setWalletSelectOpen(true);
|
|
2199
|
+
}
|
|
2200
|
+
};
|
|
2201
|
+
return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement("div", { style: { ...containerStyle, ...className ? {} : {} }, className }, !address ? /* @__PURE__ */ import_react6.default.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ import_react6.default.createElement("h3", { style: getTitleStyle() }, "Connect Wallet"), supportedNetworks.length === 0 ? /* @__PURE__ */ import_react6.default.createElement("p", { style: getHintStyle() }, "Please install a supported wallet extension") : /* @__PURE__ */ import_react6.default.createElement("div", { style: buttonsContainerStyle }, supportedNetworks.map((network) => /* @__PURE__ */ import_react6.default.createElement("div", { key: network, style: walletOptionStyle }, /* @__PURE__ */ import_react6.default.createElement(
|
|
2202
|
+
"button",
|
|
2203
|
+
{
|
|
2204
|
+
style: getConnectButtonStyle(isConnecting, hoveredButton === network),
|
|
2205
|
+
onClick: () => handleOpenWalletSelect(network),
|
|
2206
|
+
disabled: isConnecting,
|
|
2207
|
+
onMouseEnter: () => setHoveredButton(network),
|
|
2208
|
+
onMouseLeave: () => setHoveredButton(null)
|
|
2209
|
+
},
|
|
2210
|
+
isConnecting ? "Connecting..." : getNetworkDisplayName(network)
|
|
2211
|
+
)))), error && /* @__PURE__ */ import_react6.default.createElement("p", { style: getErrorStyle() }, error), /* @__PURE__ */ import_react6.default.createElement("p", { style: getHintStyle() }, "Select a network to see available wallets")) : /* @__PURE__ */ import_react6.default.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ import_react6.default.createElement("div", { style: walletAddressStyle }, /* @__PURE__ */ import_react6.default.createElement("span", { style: getLabelStyle() }, "Connected ", networkType && `(${getNetworkDisplayName(networkType)})`), /* @__PURE__ */ import_react6.default.createElement("span", { style: getAddressStyle() }, formatAddress(address))), /* @__PURE__ */ import_react6.default.createElement("div", { style: walletActionsStyle }, showSwitchWallet && /* @__PURE__ */ import_react6.default.createElement(
|
|
2212
|
+
"button",
|
|
2213
|
+
{
|
|
2214
|
+
style: getConnectButtonStyle(isConnecting, hoveredButton === "switch"),
|
|
2215
|
+
onClick: handleSwitchWallet,
|
|
2216
|
+
disabled: isConnecting,
|
|
2217
|
+
onMouseEnter: () => setHoveredButton("switch"),
|
|
2218
|
+
onMouseLeave: () => setHoveredButton(null)
|
|
2219
|
+
},
|
|
2220
|
+
isConnecting ? "Switching..." : "Switch Wallet"
|
|
2221
|
+
), /* @__PURE__ */ import_react6.default.createElement(
|
|
1661
2222
|
"button",
|
|
1662
2223
|
{
|
|
1663
2224
|
style: getDisconnectButtonStyle(hoveredButton === "disconnect"),
|
|
@@ -1666,19 +2227,27 @@ function WalletConnect({
|
|
|
1666
2227
|
onMouseLeave: () => setHoveredButton(null)
|
|
1667
2228
|
},
|
|
1668
2229
|
"Disconnect"
|
|
1669
|
-
)), /* @__PURE__ */
|
|
2230
|
+
)), /* @__PURE__ */ import_react6.default.createElement("p", { style: getHintStyle() }, 'Click "Switch Wallet" to change wallet or account'))), selectedNetworkType && /* @__PURE__ */ import_react6.default.createElement(
|
|
2231
|
+
WalletSelectModal,
|
|
2232
|
+
{
|
|
2233
|
+
isOpen: walletSelectOpen,
|
|
2234
|
+
networkType: selectedNetworkType,
|
|
2235
|
+
onSelect: handleWalletSelect,
|
|
2236
|
+
onClose: () => setWalletSelectOpen(false)
|
|
2237
|
+
}
|
|
2238
|
+
));
|
|
1670
2239
|
}
|
|
1671
2240
|
|
|
1672
2241
|
// src/react/components/V402Checkout.tsx
|
|
1673
|
-
var
|
|
2242
|
+
var import_react8 = __toESM(require("react"));
|
|
1674
2243
|
var import_antd = require("antd");
|
|
1675
2244
|
var import_icons = require("@ant-design/icons");
|
|
1676
2245
|
init_common();
|
|
1677
2246
|
|
|
1678
2247
|
// src/react/utils/CryptoIcons.tsx
|
|
1679
|
-
var
|
|
2248
|
+
var import_react7 = __toESM(require("react"));
|
|
1680
2249
|
var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
|
|
1681
|
-
return /* @__PURE__ */
|
|
2250
|
+
return /* @__PURE__ */ import_react7.default.createElement(
|
|
1682
2251
|
"svg",
|
|
1683
2252
|
{
|
|
1684
2253
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1688,14 +2257,14 @@ var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
|
|
|
1688
2257
|
className,
|
|
1689
2258
|
style
|
|
1690
2259
|
},
|
|
1691
|
-
/* @__PURE__ */
|
|
1692
|
-
/* @__PURE__ */
|
|
2260
|
+
/* @__PURE__ */ import_react7.default.createElement("desc", null, "Solana SOL Fill Streamline Icon: https://streamlinehq.com"),
|
|
2261
|
+
/* @__PURE__ */ import_react7.default.createElement("g", { fill: "none", fillRule: "evenodd" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
1693
2262
|
"path",
|
|
1694
2263
|
{
|
|
1695
2264
|
d: "M16 0v16H0V0h16ZM8.395333333333333 15.505333333333333l-0.007333333333333332 0.0013333333333333333 -0.047333333333333324 0.023333333333333334 -0.013333333333333332 0.0026666666666666666 -0.009333333333333332 -0.0026666666666666666 -0.047333333333333324 -0.023333333333333334c-0.006666666666666666 -0.0026666666666666666 -0.012666666666666666 -0.0006666666666666666 -0.016 0.003333333333333333l-0.0026666666666666666 0.006666666666666666 -0.011333333333333334 0.2853333333333333 0.003333333333333333 0.013333333333333332 0.006666666666666666 0.008666666666666666 0.06933333333333333 0.049333333333333326 0.009999999999999998 0.0026666666666666666 0.008 -0.0026666666666666666 0.06933333333333333 -0.049333333333333326 0.008 -0.010666666666666666 0.0026666666666666666 -0.011333333333333334 -0.011333333333333334 -0.2846666666666666c-0.0013333333333333333 -0.006666666666666666 -0.005999999999999999 -0.011333333333333334 -0.011333333333333334 -0.011999999999999999Zm0.17666666666666667 -0.07533333333333334 -0.008666666666666666 0.0013333333333333333 -0.12333333333333332 0.062 -0.006666666666666666 0.006666666666666666 -0.002 0.007333333333333332 0.011999999999999999 0.2866666666666666 0.003333333333333333 0.008 0.005333333333333333 0.004666666666666666 0.134 0.062c0.008 0.0026666666666666666 0.015333333333333332 0 0.019333333333333334 -0.005333333333333333l0.0026666666666666666 -0.009333333333333332 -0.02266666666666667 -0.4093333333333333c-0.002 -0.008 -0.006666666666666666 -0.013333333333333332 -0.013333333333333332 -0.014666666666666665Zm-0.4766666666666666 0.0013333333333333333a0.015333333333333332 0.015333333333333332 0 0 0 -0.018 0.004l-0.004 0.009333333333333332 -0.02266666666666667 0.4093333333333333c0 0.008 0.004666666666666666 0.013333333333333332 0.011333333333333334 0.016l0.009999999999999998 -0.0013333333333333333 0.134 -0.062 0.006666666666666666 -0.005333333333333333 0.0026666666666666666 -0.007333333333333332 0.011333333333333334 -0.2866666666666666 -0.002 -0.008 -0.006666666666666666 -0.006666666666666666 -0.12266666666666666 -0.06133333333333333Z",
|
|
1696
2265
|
strokeWidth: "0.6667"
|
|
1697
2266
|
}
|
|
1698
|
-
), /* @__PURE__ */
|
|
2267
|
+
), /* @__PURE__ */ import_react7.default.createElement(
|
|
1699
2268
|
"path",
|
|
1700
2269
|
{
|
|
1701
2270
|
fill: "#000000",
|
|
@@ -1706,7 +2275,7 @@ var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
|
|
|
1706
2275
|
);
|
|
1707
2276
|
};
|
|
1708
2277
|
var BaseIcon = ({ width = 24, height = 24, className, style }) => {
|
|
1709
|
-
return /* @__PURE__ */
|
|
2278
|
+
return /* @__PURE__ */ import_react7.default.createElement(
|
|
1710
2279
|
"svg",
|
|
1711
2280
|
{
|
|
1712
2281
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1720,8 +2289,8 @@ var BaseIcon = ({ width = 24, height = 24, className, style }) => {
|
|
|
1720
2289
|
className,
|
|
1721
2290
|
style
|
|
1722
2291
|
},
|
|
1723
|
-
/* @__PURE__ */
|
|
1724
|
-
/* @__PURE__ */
|
|
2292
|
+
/* @__PURE__ */ import_react7.default.createElement("desc", null, "Brand Coinbase Streamline Icon: https://streamlinehq.com"),
|
|
2293
|
+
/* @__PURE__ */ import_react7.default.createElement(
|
|
1725
2294
|
"path",
|
|
1726
2295
|
{
|
|
1727
2296
|
d: "M12.95 22c-4.503 0 -8.445 -3.04 -9.61 -7.413 -1.165 -4.373 0.737 -8.988 4.638 -11.25a9.906 9.906 0 0 1 12.008 1.598l-3.335 3.367a5.185 5.185 0 0 0 -7.354 0.013 5.252 5.252 0 0 0 0 7.393 5.185 5.185 0 0 0 7.354 0.013L20 19.088A9.887 9.887 0 0 1 12.95 22z",
|
|
@@ -1779,14 +2348,14 @@ function V402Checkout({
|
|
|
1779
2348
|
{ autoSwitch: !!targetNetwork, switchOnMount: true }
|
|
1780
2349
|
);
|
|
1781
2350
|
const { isProcessing, setIsProcessing, result, setResult, error, setError } = usePayment();
|
|
1782
|
-
const [paymentDetails, setPaymentDetails] = (0,
|
|
2351
|
+
const [paymentDetails, setPaymentDetails] = (0, import_react8.useState)(null);
|
|
1783
2352
|
const handleDisconnect = () => {
|
|
1784
2353
|
disconnect();
|
|
1785
2354
|
setResult(null);
|
|
1786
2355
|
setError(null);
|
|
1787
2356
|
notify.info("Wallet Disconnected", "Your wallet has been disconnected successfully.");
|
|
1788
2357
|
};
|
|
1789
|
-
(0,
|
|
2358
|
+
(0, import_react8.useEffect)(() => {
|
|
1790
2359
|
if (paymentInfo && paymentInfo.length > 0) {
|
|
1791
2360
|
const firstPayment = paymentInfo[0];
|
|
1792
2361
|
const rawAmount = firstPayment.maxAmountRequired?.toString() || "0";
|
|
@@ -1801,7 +2370,7 @@ function V402Checkout({
|
|
|
1801
2370
|
});
|
|
1802
2371
|
}
|
|
1803
2372
|
}, [paymentInfo]);
|
|
1804
|
-
(0,
|
|
2373
|
+
(0, import_react8.useEffect)(() => {
|
|
1805
2374
|
if (targetNetwork && !fetchingPaymentInfo && ensureNetwork) {
|
|
1806
2375
|
ensureNetwork(targetNetwork).catch((err) => {
|
|
1807
2376
|
console.error("Failed to ensure network:", err);
|
|
@@ -1841,12 +2410,12 @@ function V402Checkout({
|
|
|
1841
2410
|
const networkColor = paymentDetails ? getNetworkColor(paymentDetails.network) : "#8c8c8c";
|
|
1842
2411
|
const loadingColor = "#8c8c8c";
|
|
1843
2412
|
const hasInvalidCheckoutId = !fetchingPaymentInfo && (!paymentInfo || paymentInfo.length === 0);
|
|
1844
|
-
return /* @__PURE__ */
|
|
2413
|
+
return /* @__PURE__ */ import_react8.default.createElement(
|
|
1845
2414
|
"div",
|
|
1846
2415
|
{
|
|
1847
2416
|
className: isModal ? "bg-white" : "h-screen bg-white flex items-center justify-center p-4 overflow-hidden"
|
|
1848
2417
|
},
|
|
1849
|
-
/* @__PURE__ */
|
|
2418
|
+
/* @__PURE__ */ import_react8.default.createElement(
|
|
1850
2419
|
"div",
|
|
1851
2420
|
{
|
|
1852
2421
|
className: "flex gap-4 items-center justify-center",
|
|
@@ -1856,7 +2425,7 @@ function V402Checkout({
|
|
|
1856
2425
|
width: "100%"
|
|
1857
2426
|
}
|
|
1858
2427
|
},
|
|
1859
|
-
/* @__PURE__ */
|
|
2428
|
+
/* @__PURE__ */ import_react8.default.createElement(
|
|
1860
2429
|
import_antd.Card,
|
|
1861
2430
|
{
|
|
1862
2431
|
className: "flex-shrink-0",
|
|
@@ -1872,7 +2441,7 @@ function V402Checkout({
|
|
|
1872
2441
|
},
|
|
1873
2442
|
styles: { body: { padding: isModal ? "0px" : "32px 24px" } }
|
|
1874
2443
|
},
|
|
1875
|
-
/* @__PURE__ */
|
|
2444
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-3 mb-4" }, /* @__PURE__ */ import_react8.default.createElement(
|
|
1876
2445
|
"div",
|
|
1877
2446
|
{
|
|
1878
2447
|
className: "w-12 h-12 rounded-xl flex items-center justify-center",
|
|
@@ -1881,22 +2450,22 @@ function V402Checkout({
|
|
|
1881
2450
|
transition: "background 0.3s ease"
|
|
1882
2451
|
}
|
|
1883
2452
|
},
|
|
1884
|
-
hasInvalidCheckoutId ? /* @__PURE__ */
|
|
1885
|
-
), /* @__PURE__ */
|
|
2453
|
+
hasInvalidCheckoutId ? /* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "20px", color: "white", fontWeight: "bold" } }, "\u2717") : paymentDetails && NetworkIcon ? /* @__PURE__ */ import_react8.default.createElement(NetworkIcon, { width: 24, height: 24 }) : /* @__PURE__ */ import_react8.default.createElement(import_icons.LoadingOutlined, { style: { fontSize: "20px", color: "white" }, spin: true })
|
|
2454
|
+
), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-1" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react8.default.createElement(Title, { level: 4, style: { margin: 0, fontSize: "18px", fontWeight: 600 } }, title || "Echo Payment OnVoyage"), !hasInvalidCheckoutId && /* @__PURE__ */ import_react8.default.createElement(
|
|
1886
2455
|
import_antd.Tooltip,
|
|
1887
2456
|
{
|
|
1888
2457
|
title: tooltipText,
|
|
1889
2458
|
placement: "top"
|
|
1890
2459
|
},
|
|
1891
|
-
/* @__PURE__ */
|
|
2460
|
+
/* @__PURE__ */ import_react8.default.createElement(
|
|
1892
2461
|
import_icons.InfoCircleOutlined,
|
|
1893
2462
|
{
|
|
1894
2463
|
style: { fontSize: "14px", color: "#8c8c8c", cursor: "help" }
|
|
1895
2464
|
}
|
|
1896
2465
|
)
|
|
1897
|
-
)), /* @__PURE__ */
|
|
1898
|
-
/* @__PURE__ */
|
|
1899
|
-
hasInvalidCheckoutId && /* @__PURE__ */
|
|
2466
|
+
)), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, subtitle))),
|
|
2467
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center mb-5" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "inline-flex items-center justify-center w-12 h-12 rounded-full bg-gray-50 mb-3" }, /* @__PURE__ */ import_react8.default.createElement(import_icons.LockOutlined, { style: { fontSize: "20px", color: "#595959" } })), /* @__PURE__ */ import_react8.default.createElement(Title, { level: 3, style: { margin: "0 0 6px 0", fontSize: "20px", fontWeight: 600 } }, "Payment Required"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Pay ", paymentDetails ? `$${paymentDetails.amount} ${paymentDetails.currency}` : "the required amount", " to access")),
|
|
2468
|
+
hasInvalidCheckoutId && /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ import_react8.default.createElement(
|
|
1900
2469
|
"div",
|
|
1901
2470
|
{
|
|
1902
2471
|
className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
|
|
@@ -1905,15 +2474,15 @@ function V402Checkout({
|
|
|
1905
2474
|
boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
|
|
1906
2475
|
}
|
|
1907
2476
|
},
|
|
1908
|
-
/* @__PURE__ */
|
|
1909
|
-
), /* @__PURE__ */
|
|
2477
|
+
/* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "!")
|
|
2478
|
+
), /* @__PURE__ */ import_react8.default.createElement(
|
|
1910
2479
|
Title,
|
|
1911
2480
|
{
|
|
1912
2481
|
level: 4,
|
|
1913
2482
|
style: { margin: "0 0 12px 0", fontSize: "18px", fontWeight: 600, color: "#262626" }
|
|
1914
2483
|
},
|
|
1915
2484
|
"Invalid Checkout ID"
|
|
1916
|
-
), /* @__PURE__ */
|
|
2485
|
+
), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", display: "block", marginBottom: "16px" } }, "The checkout ID you provided is invalid or has expired."), /* @__PURE__ */ import_react8.default.createElement(
|
|
1917
2486
|
"div",
|
|
1918
2487
|
{
|
|
1919
2488
|
style: {
|
|
@@ -1924,33 +2493,33 @@ function V402Checkout({
|
|
|
1924
2493
|
marginTop: "16px"
|
|
1925
2494
|
}
|
|
1926
2495
|
},
|
|
1927
|
-
/* @__PURE__ */
|
|
2496
|
+
/* @__PURE__ */ import_react8.default.createElement(Text, { style: {
|
|
1928
2497
|
fontSize: "13px",
|
|
1929
2498
|
color: "#dc2626",
|
|
1930
2499
|
lineHeight: "1.6",
|
|
1931
2500
|
fontWeight: 500
|
|
1932
2501
|
} }, "Failed to load payment information. Please check your checkout ID.")
|
|
1933
2502
|
)),
|
|
1934
|
-
!hasInvalidCheckoutId && fetchingPaymentInfo && /* @__PURE__ */
|
|
1935
|
-
!hasInvalidCheckoutId && !fetchingPaymentInfo && !address && /* @__PURE__ */
|
|
1936
|
-
!hasInvalidCheckoutId && address && /* @__PURE__ */
|
|
2503
|
+
!hasInvalidCheckoutId && fetchingPaymentInfo && /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { color: "#8c8c8c" } }, "Loading payment information...")),
|
|
2504
|
+
!hasInvalidCheckoutId && !fetchingPaymentInfo && !address && /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement(WalletConnect, { supportedNetworks })),
|
|
2505
|
+
!hasInvalidCheckoutId && address && /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(
|
|
1937
2506
|
"div",
|
|
1938
2507
|
{
|
|
1939
2508
|
className: "bg-gray-50 rounded-lg p-3 mb-4",
|
|
1940
2509
|
style: { border: "1px solid #f0f0f0" }
|
|
1941
2510
|
},
|
|
1942
|
-
/* @__PURE__ */
|
|
2511
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-3 flex-1" }, /* @__PURE__ */ import_react8.default.createElement(
|
|
1943
2512
|
"div",
|
|
1944
2513
|
{
|
|
1945
2514
|
className: "w-10 h-10 rounded-full bg-black flex items-center justify-center text-white text-sm font-semibold"
|
|
1946
2515
|
},
|
|
1947
2516
|
address.slice(0, 2).toUpperCase()
|
|
1948
|
-
), /* @__PURE__ */
|
|
2517
|
+
), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: {
|
|
1949
2518
|
display: "block",
|
|
1950
2519
|
fontSize: "12px",
|
|
1951
2520
|
color: "#8c8c8c",
|
|
1952
2521
|
marginBottom: "2px"
|
|
1953
|
-
} }, "Connected Wallet"), /* @__PURE__ */
|
|
2522
|
+
} }, "Connected Wallet"), /* @__PURE__ */ import_react8.default.createElement(
|
|
1954
2523
|
Text,
|
|
1955
2524
|
{
|
|
1956
2525
|
style: {
|
|
@@ -1960,17 +2529,17 @@ function V402Checkout({
|
|
|
1960
2529
|
}
|
|
1961
2530
|
},
|
|
1962
2531
|
formatAddress(address)
|
|
1963
|
-
))), /* @__PURE__ */
|
|
2532
|
+
))), /* @__PURE__ */ import_react8.default.createElement(
|
|
1964
2533
|
import_antd.Button,
|
|
1965
2534
|
{
|
|
1966
2535
|
type: "text",
|
|
1967
2536
|
size: "small",
|
|
1968
|
-
icon: /* @__PURE__ */
|
|
2537
|
+
icon: /* @__PURE__ */ import_react8.default.createElement(import_icons.DisconnectOutlined, null),
|
|
1969
2538
|
onClick: handleDisconnect,
|
|
1970
2539
|
style: { color: "#ff4d4f" }
|
|
1971
2540
|
}
|
|
1972
2541
|
))
|
|
1973
|
-
), paymentDetails && /* @__PURE__ */
|
|
2542
|
+
), paymentDetails && /* @__PURE__ */ import_react8.default.createElement("div", { className: "bg-gray-50 rounded-lg p-3 mb-4", style: { border: "1px solid #f0f0f0" } }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Payment Amount"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "18px", fontWeight: 600 } }, "$", paymentDetails.amount)), /* @__PURE__ */ import_react8.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Currency"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.currency)), /* @__PURE__ */ import_react8.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Network"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.network)), /* @__PURE__ */ import_react8.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Wallet Address"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: {
|
|
1974
2543
|
fontSize: "11px",
|
|
1975
2544
|
fontWeight: 500,
|
|
1976
2545
|
fontFamily: "Monaco, monospace",
|
|
@@ -1978,15 +2547,15 @@ function V402Checkout({
|
|
|
1978
2547
|
textAlign: "right",
|
|
1979
2548
|
maxWidth: "60%",
|
|
1980
2549
|
lineHeight: 1.4
|
|
1981
|
-
} }, address))), /* @__PURE__ */
|
|
2550
|
+
} }, address))), /* @__PURE__ */ import_react8.default.createElement(
|
|
1982
2551
|
"div",
|
|
1983
2552
|
{
|
|
1984
2553
|
className: "flex items-center justify-center gap-2 mb-3 p-2 rounded-lg",
|
|
1985
2554
|
style: { background: "#f6ffed", border: "1px solid #d9f7be" }
|
|
1986
2555
|
},
|
|
1987
|
-
/* @__PURE__ */
|
|
1988
|
-
/* @__PURE__ */
|
|
1989
|
-
), /* @__PURE__ */
|
|
2556
|
+
/* @__PURE__ */ import_react8.default.createElement(import_icons.SafetyOutlined, { style: { color: "#52c41a", fontSize: "13px" } }),
|
|
2557
|
+
/* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "12px", color: "#52c41a", fontWeight: 500 } }, "Secure payment powered by v402pay")
|
|
2558
|
+
), /* @__PURE__ */ import_react8.default.createElement(
|
|
1990
2559
|
import_antd.Button,
|
|
1991
2560
|
{
|
|
1992
2561
|
type: "primary",
|
|
@@ -2008,7 +2577,7 @@ function V402Checkout({
|
|
|
2008
2577
|
}
|
|
2009
2578
|
},
|
|
2010
2579
|
isProcessing ? "Processing..." : !paymentDetails ? "Loading..." : `Pay $${paymentDetails.amount} ${paymentDetails.currency}`
|
|
2011
|
-
), /* @__PURE__ */
|
|
2580
|
+
), /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Don't have USDC?", " "), /* @__PURE__ */ import_react8.default.createElement(
|
|
2012
2581
|
"a",
|
|
2013
2582
|
{
|
|
2014
2583
|
href: "https://faucet.circle.com/",
|
|
@@ -2017,26 +2586,26 @@ function V402Checkout({
|
|
|
2017
2586
|
className: "text-blue-600 hover:text-blue-700 text-sm font-medium inline-flex items-center gap-1"
|
|
2018
2587
|
},
|
|
2019
2588
|
"Get it here ",
|
|
2020
|
-
/* @__PURE__ */
|
|
2021
|
-
)), isModal && result && /* @__PURE__ */
|
|
2589
|
+
/* @__PURE__ */ import_react8.default.createElement(import_icons.LinkOutlined, { style: { fontSize: "12px" } })
|
|
2590
|
+
)), isModal && result && /* @__PURE__ */ import_react8.default.createElement(
|
|
2022
2591
|
"div",
|
|
2023
2592
|
{
|
|
2024
2593
|
className: "mt-4 p-4 rounded-lg",
|
|
2025
2594
|
style: { background: "#f6ffed", border: "1px solid #b7eb8f" }
|
|
2026
2595
|
},
|
|
2027
|
-
/* @__PURE__ */
|
|
2596
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center" }, /* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "20px" } }, "\u2713"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: {
|
|
2028
2597
|
fontSize: "14px",
|
|
2029
2598
|
color: "#52c41a",
|
|
2030
2599
|
fontWeight: 600,
|
|
2031
2600
|
marginLeft: "8px"
|
|
2032
2601
|
} }, "Payment Successful!"))
|
|
2033
|
-
), isModal && error && /* @__PURE__ */
|
|
2602
|
+
), isModal && error && /* @__PURE__ */ import_react8.default.createElement(
|
|
2034
2603
|
"div",
|
|
2035
2604
|
{
|
|
2036
2605
|
className: "mt-4 p-4 rounded-lg",
|
|
2037
2606
|
style: { background: "#fff2f0", border: "1px solid #ffccc7" }
|
|
2038
2607
|
},
|
|
2039
|
-
/* @__PURE__ */
|
|
2608
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center mb-3" }, /* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "20px" } }, "\u2717"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: {
|
|
2040
2609
|
fontSize: "14px",
|
|
2041
2610
|
color: "#ff4d4f",
|
|
2042
2611
|
fontWeight: 600,
|
|
@@ -2044,7 +2613,7 @@ function V402Checkout({
|
|
|
2044
2613
|
display: "block",
|
|
2045
2614
|
marginTop: "4px"
|
|
2046
2615
|
} }, "Payment Failed")),
|
|
2047
|
-
/* @__PURE__ */
|
|
2616
|
+
/* @__PURE__ */ import_react8.default.createElement(Text, { style: {
|
|
2048
2617
|
fontSize: "13px",
|
|
2049
2618
|
color: "#ff4d4f",
|
|
2050
2619
|
display: "block",
|
|
@@ -2052,11 +2621,11 @@ function V402Checkout({
|
|
|
2052
2621
|
} }, error)
|
|
2053
2622
|
))
|
|
2054
2623
|
),
|
|
2055
|
-
!isModal && (isProcessing || result || error) && /* @__PURE__ */
|
|
2624
|
+
!isModal && (isProcessing || result || error) && /* @__PURE__ */ import_react8.default.createElement(
|
|
2056
2625
|
import_antd.Card,
|
|
2057
2626
|
{
|
|
2058
|
-
title: /* @__PURE__ */
|
|
2059
|
-
extra: !isProcessing && /* @__PURE__ */
|
|
2627
|
+
title: /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-2" }, isProcessing && !result && !error ? /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(import_icons.LoadingOutlined, { style: { color: "#14b8a6", fontSize: "16px" } }), /* @__PURE__ */ import_react8.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Processing Payment")) : result ? /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement("span", { style: { color: "#52c41a", fontSize: "18px" } }, "\u2713"), /* @__PURE__ */ import_react8.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Successful")) : /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement("span", { style: { color: "#ff4d4f", fontSize: "18px" } }, "\u2717"), /* @__PURE__ */ import_react8.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Failed"))),
|
|
2628
|
+
extra: !isProcessing && /* @__PURE__ */ import_react8.default.createElement(
|
|
2060
2629
|
import_antd.Button,
|
|
2061
2630
|
{
|
|
2062
2631
|
type: "text",
|
|
@@ -2084,7 +2653,7 @@ function V402Checkout({
|
|
|
2084
2653
|
}
|
|
2085
2654
|
}
|
|
2086
2655
|
},
|
|
2087
|
-
isProcessing && !result && !error && /* @__PURE__ */
|
|
2656
|
+
isProcessing && !result && !error && /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center py-10" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "relative inline-block" }, /* @__PURE__ */ import_react8.default.createElement(
|
|
2088
2657
|
"div",
|
|
2089
2658
|
{
|
|
2090
2659
|
className: "absolute inset-0 rounded-full blur-xl opacity-40",
|
|
@@ -2093,12 +2662,12 @@ function V402Checkout({
|
|
|
2093
2662
|
animation: "pulse 2s ease-in-out infinite"
|
|
2094
2663
|
}
|
|
2095
2664
|
}
|
|
2096
|
-
), /* @__PURE__ */
|
|
2665
|
+
), /* @__PURE__ */ import_react8.default.createElement(
|
|
2097
2666
|
import_antd.Spin,
|
|
2098
2667
|
{
|
|
2099
|
-
indicator: /* @__PURE__ */
|
|
2668
|
+
indicator: /* @__PURE__ */ import_react8.default.createElement(import_icons.LoadingOutlined, { style: { fontSize: 56, color: "#14b8a6" } })
|
|
2100
2669
|
}
|
|
2101
|
-
)), /* @__PURE__ */
|
|
2670
|
+
)), /* @__PURE__ */ import_react8.default.createElement("div", { className: "mt-6" }, /* @__PURE__ */ import_react8.default.createElement(Text, { strong: true, style: { fontSize: "18px", color: "#262626", letterSpacing: "-0.02em" } }, "Verifying Payment")), /* @__PURE__ */ import_react8.default.createElement("div", { className: "mt-2 mb-6" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", lineHeight: "1.6" } }, "Please wait while we confirm your transaction")), /* @__PURE__ */ import_react8.default.createElement(
|
|
2102
2671
|
"div",
|
|
2103
2672
|
{
|
|
2104
2673
|
className: "mt-4 p-4 rounded-xl",
|
|
@@ -2107,9 +2676,9 @@ function V402Checkout({
|
|
|
2107
2676
|
border: "1px solid #ccfbf1"
|
|
2108
2677
|
}
|
|
2109
2678
|
},
|
|
2110
|
-
/* @__PURE__ */
|
|
2679
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center justify-center gap-2" }, /* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "16px" } }, "\u23F1\uFE0F"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#0f766e", fontWeight: 500 } }, "This may take a few moments"))
|
|
2111
2680
|
)),
|
|
2112
|
-
result && /* @__PURE__ */
|
|
2681
|
+
result && /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ import_react8.default.createElement(
|
|
2113
2682
|
"div",
|
|
2114
2683
|
{
|
|
2115
2684
|
className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
|
|
@@ -2118,13 +2687,13 @@ function V402Checkout({
|
|
|
2118
2687
|
boxShadow: "0 4px 20px rgba(16, 185, 129, 0.3)"
|
|
2119
2688
|
}
|
|
2120
2689
|
},
|
|
2121
|
-
/* @__PURE__ */
|
|
2122
|
-
), /* @__PURE__ */
|
|
2690
|
+
/* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2713")
|
|
2691
|
+
), /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement(Text, { strong: true, style: {
|
|
2123
2692
|
fontSize: "20px",
|
|
2124
2693
|
color: "#262626",
|
|
2125
2694
|
display: "block",
|
|
2126
2695
|
marginBottom: "8px"
|
|
2127
|
-
} }, "Payment Successful!"), /* @__PURE__ */
|
|
2696
|
+
} }, "Payment Successful!"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Your transaction has been confirmed"))), /* @__PURE__ */ import_react8.default.createElement(import_antd.Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "RESPONSE DATA")), /* @__PURE__ */ import_react8.default.createElement(
|
|
2128
2697
|
"pre",
|
|
2129
2698
|
{
|
|
2130
2699
|
style: {
|
|
@@ -2144,7 +2713,7 @@ function V402Checkout({
|
|
|
2144
2713
|
},
|
|
2145
2714
|
JSON.stringify(result, null, 2)
|
|
2146
2715
|
)),
|
|
2147
|
-
error && /* @__PURE__ */
|
|
2716
|
+
error && /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ import_react8.default.createElement(
|
|
2148
2717
|
"div",
|
|
2149
2718
|
{
|
|
2150
2719
|
className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
|
|
@@ -2153,13 +2722,13 @@ function V402Checkout({
|
|
|
2153
2722
|
boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
|
|
2154
2723
|
}
|
|
2155
2724
|
},
|
|
2156
|
-
/* @__PURE__ */
|
|
2157
|
-
), /* @__PURE__ */
|
|
2725
|
+
/* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2717")
|
|
2726
|
+
), /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement(Text, { strong: true, style: {
|
|
2158
2727
|
fontSize: "20px",
|
|
2159
2728
|
color: "#262626",
|
|
2160
2729
|
display: "block",
|
|
2161
2730
|
marginBottom: "8px"
|
|
2162
|
-
} }, "Payment Failed"), /* @__PURE__ */
|
|
2731
|
+
} }, "Payment Failed"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Something went wrong with your transaction"))), /* @__PURE__ */ import_react8.default.createElement(import_antd.Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "ERROR DETAILS")), /* @__PURE__ */ import_react8.default.createElement(
|
|
2163
2732
|
"div",
|
|
2164
2733
|
{
|
|
2165
2734
|
style: {
|
|
@@ -2169,13 +2738,13 @@ function V402Checkout({
|
|
|
2169
2738
|
border: "1px solid #fee2e2"
|
|
2170
2739
|
}
|
|
2171
2740
|
},
|
|
2172
|
-
/* @__PURE__ */
|
|
2741
|
+
/* @__PURE__ */ import_react8.default.createElement(Text, { style: {
|
|
2173
2742
|
fontSize: "14px",
|
|
2174
2743
|
color: "#dc2626",
|
|
2175
2744
|
lineHeight: "1.6",
|
|
2176
2745
|
fontWeight: 500
|
|
2177
2746
|
} }, error)
|
|
2178
|
-
), /* @__PURE__ */
|
|
2747
|
+
), /* @__PURE__ */ import_react8.default.createElement("div", { className: "mt-4 text-center" }, /* @__PURE__ */ import_react8.default.createElement(
|
|
2179
2748
|
import_antd.Button,
|
|
2180
2749
|
{
|
|
2181
2750
|
size: "large",
|
|
@@ -2196,7 +2765,7 @@ function V402Checkout({
|
|
|
2196
2765
|
)))
|
|
2197
2766
|
)
|
|
2198
2767
|
),
|
|
2199
|
-
/* @__PURE__ */
|
|
2768
|
+
/* @__PURE__ */ import_react8.default.createElement("style", { dangerouslySetInnerHTML: {
|
|
2200
2769
|
__html: `
|
|
2201
2770
|
@keyframes slideInRight {
|
|
2202
2771
|
from {
|
|
@@ -2227,6 +2796,7 @@ function V402Checkout({
|
|
|
2227
2796
|
0 && (module.exports = {
|
|
2228
2797
|
V402Checkout,
|
|
2229
2798
|
WalletConnect,
|
|
2799
|
+
WalletSelectModal,
|
|
2230
2800
|
usePageNetwork,
|
|
2231
2801
|
usePayment,
|
|
2232
2802
|
usePaymentInfo,
|