@voyage_ai/v402-web-ts 0.2.1 → 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 +8 -4
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +120 -130
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +122 -138
- 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 +817 -247
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +835 -256
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/styles.css +1 -1
- package/package.json +9 -2
package/dist/react/index.mjs
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
1
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
2
5
|
var __esm = (fn, res) => function __init() {
|
|
3
6
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
4
7
|
};
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
5
21
|
|
|
6
22
|
// src/types/common.ts
|
|
7
23
|
var PROD_BACK_URL;
|
|
@@ -79,6 +95,24 @@ var init_types = __esm({
|
|
|
79
95
|
});
|
|
80
96
|
|
|
81
97
|
// src/utils/wallet.ts
|
|
98
|
+
var wallet_exports = {};
|
|
99
|
+
__export(wallet_exports, {
|
|
100
|
+
clearAllWalletAddresses: () => clearAllWalletAddresses,
|
|
101
|
+
clearWalletDisconnection: () => clearWalletDisconnection,
|
|
102
|
+
formatAddress: () => formatAddress,
|
|
103
|
+
getAllWalletAddresses: () => getAllWalletAddresses,
|
|
104
|
+
getCachedWalletAddress: () => getCachedWalletAddress,
|
|
105
|
+
getConnectedNetworkType: () => getConnectedNetworkType,
|
|
106
|
+
getWalletDisplayName: () => getWalletDisplayName,
|
|
107
|
+
getWalletInstallUrl: () => getWalletInstallUrl,
|
|
108
|
+
getWalletProvider: () => getWalletProvider,
|
|
109
|
+
isWalletInstalled: () => isWalletInstalled,
|
|
110
|
+
isWalletManuallyDisconnected: () => isWalletManuallyDisconnected,
|
|
111
|
+
markWalletDisconnected: () => markWalletDisconnected,
|
|
112
|
+
removeWalletAddress: () => removeWalletAddress,
|
|
113
|
+
saveConnectedNetworkType: () => saveConnectedNetworkType,
|
|
114
|
+
saveWalletAddress: () => saveWalletAddress
|
|
115
|
+
});
|
|
82
116
|
function isWalletInstalled(networkType) {
|
|
83
117
|
if (typeof window === "undefined") {
|
|
84
118
|
return false;
|
|
@@ -93,6 +127,20 @@ function isWalletInstalled(networkType) {
|
|
|
93
127
|
return false;
|
|
94
128
|
}
|
|
95
129
|
}
|
|
130
|
+
function getWalletProvider(networkType) {
|
|
131
|
+
if (typeof window === "undefined") {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
switch (networkType) {
|
|
135
|
+
case "evm" /* EVM */:
|
|
136
|
+
return window.ethereum;
|
|
137
|
+
case "solana" /* SOLANA */:
|
|
138
|
+
case "svm" /* SVM */:
|
|
139
|
+
return window.solana || window.phantom;
|
|
140
|
+
default:
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
96
144
|
function formatAddress(address) {
|
|
97
145
|
if (!address || address.length < 10) {
|
|
98
146
|
return address;
|
|
@@ -167,6 +215,17 @@ function getWalletInstallUrl(networkType) {
|
|
|
167
215
|
return "#";
|
|
168
216
|
}
|
|
169
217
|
}
|
|
218
|
+
function getWalletDisplayName(networkType) {
|
|
219
|
+
switch (networkType) {
|
|
220
|
+
case "evm" /* EVM */:
|
|
221
|
+
return "MetaMask";
|
|
222
|
+
case "solana" /* SOLANA */:
|
|
223
|
+
case "svm" /* SVM */:
|
|
224
|
+
return "Phantom";
|
|
225
|
+
default:
|
|
226
|
+
return "Unknown Wallet";
|
|
227
|
+
}
|
|
228
|
+
}
|
|
170
229
|
function getAllWalletAddresses() {
|
|
171
230
|
if (typeof window === "undefined") {
|
|
172
231
|
return {};
|
|
@@ -199,6 +258,11 @@ function removeWalletAddress(networkType) {
|
|
|
199
258
|
delete addresses[networkType];
|
|
200
259
|
localStorage.setItem(WALLET_ADDRESSES_KEY, JSON.stringify(addresses));
|
|
201
260
|
}
|
|
261
|
+
function clearAllWalletAddresses() {
|
|
262
|
+
if (typeof window !== "undefined") {
|
|
263
|
+
localStorage.removeItem(WALLET_ADDRESSES_KEY);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
202
266
|
var WALLET_DISCONNECTED_KEY, WALLET_DISCONNECTED_NETWORKS_KEY, CONNECTED_NETWORK_TYPE_KEY, WALLET_ADDRESSES_KEY;
|
|
203
267
|
var init_wallet = __esm({
|
|
204
268
|
"src/utils/wallet.ts"() {
|
|
@@ -221,7 +285,7 @@ init_wallet();
|
|
|
221
285
|
|
|
222
286
|
// src/utils/wallet-connect.ts
|
|
223
287
|
init_wallet();
|
|
224
|
-
async function connectWallet(networkType) {
|
|
288
|
+
async function connectWallet(networkType, forceSelect = false) {
|
|
225
289
|
if (typeof window === "undefined") {
|
|
226
290
|
throw new Error("\u8BF7\u5728\u6D4F\u89C8\u5668\u73AF\u5883\u4E2D\u4F7F\u7528");
|
|
227
291
|
}
|
|
@@ -232,6 +296,26 @@ async function connectWallet(networkType) {
|
|
|
232
296
|
throw new Error("\u8BF7\u5B89\u88C5 MetaMask \u6216\u5176\u4ED6\u4EE5\u592A\u574A\u94B1\u5305");
|
|
233
297
|
}
|
|
234
298
|
const ethereum = window.ethereum;
|
|
299
|
+
if (forceSelect) {
|
|
300
|
+
try {
|
|
301
|
+
const permissions = await ethereum.request({
|
|
302
|
+
method: "wallet_requestPermissions",
|
|
303
|
+
params: [{ eth_accounts: {} }]
|
|
304
|
+
});
|
|
305
|
+
const accountsPermission = permissions?.find(
|
|
306
|
+
(p) => p.parentCapability === "eth_accounts"
|
|
307
|
+
);
|
|
308
|
+
if (accountsPermission?.caveats?.[0]?.value?.length > 0) {
|
|
309
|
+
address = accountsPermission.caveats[0].value[0];
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
} catch (err) {
|
|
313
|
+
if (err.code === 4001) {
|
|
314
|
+
throw new Error("\u7528\u6237\u53D6\u6D88\u4E86\u94B1\u5305\u8FDE\u63A5");
|
|
315
|
+
}
|
|
316
|
+
console.warn("wallet_requestPermissions failed, falling back to eth_requestAccounts");
|
|
317
|
+
}
|
|
318
|
+
}
|
|
235
319
|
const accounts = await ethereum.request({
|
|
236
320
|
method: "eth_requestAccounts",
|
|
237
321
|
params: []
|
|
@@ -244,10 +328,34 @@ async function connectWallet(networkType) {
|
|
|
244
328
|
}
|
|
245
329
|
case "solana" /* SOLANA */:
|
|
246
330
|
case "svm" /* SVM */: {
|
|
247
|
-
const
|
|
331
|
+
const phantom = window.phantom?.solana || window.solana;
|
|
332
|
+
const solflare = window.solflare;
|
|
333
|
+
let solana = phantom;
|
|
334
|
+
if (!solana && solflare?.isSolflare) {
|
|
335
|
+
solana = solflare;
|
|
336
|
+
}
|
|
248
337
|
if (!solana) {
|
|
249
338
|
throw new Error("\u8BF7\u5B89\u88C5 Phantom \u6216\u5176\u4ED6 Solana \u94B1\u5305");
|
|
250
339
|
}
|
|
340
|
+
if (forceSelect) {
|
|
341
|
+
try {
|
|
342
|
+
if (phantom?.isConnected) {
|
|
343
|
+
await phantom.disconnect();
|
|
344
|
+
}
|
|
345
|
+
if (solflare?.isConnected) {
|
|
346
|
+
await solflare.disconnect();
|
|
347
|
+
}
|
|
348
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
349
|
+
} catch (err) {
|
|
350
|
+
console.warn("Failed to disconnect Solana wallet:", err);
|
|
351
|
+
}
|
|
352
|
+
} else if (solana.isConnected) {
|
|
353
|
+
try {
|
|
354
|
+
await solana.disconnect();
|
|
355
|
+
} catch (err) {
|
|
356
|
+
console.warn("Failed to disconnect Solana wallet:", err);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
251
359
|
const response = await solana.connect();
|
|
252
360
|
address = response.publicKey.toString();
|
|
253
361
|
break;
|
|
@@ -260,6 +368,60 @@ async function connectWallet(networkType) {
|
|
|
260
368
|
saveWalletAddress(networkType, address);
|
|
261
369
|
return address;
|
|
262
370
|
}
|
|
371
|
+
async function disconnectAllSolanaWallets() {
|
|
372
|
+
if (typeof window === "undefined") return;
|
|
373
|
+
const phantom = window.phantom?.solana || window.solana;
|
|
374
|
+
const solflare = window.solflare;
|
|
375
|
+
const disconnectPromises = [];
|
|
376
|
+
if (phantom?.isConnected) {
|
|
377
|
+
disconnectPromises.push(
|
|
378
|
+
phantom.disconnect().catch(
|
|
379
|
+
(err) => console.warn("Failed to disconnect Phantom:", err)
|
|
380
|
+
)
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
if (solflare?.isConnected) {
|
|
384
|
+
disconnectPromises.push(
|
|
385
|
+
solflare.disconnect().catch(
|
|
386
|
+
(err) => console.warn("Failed to disconnect Solflare:", err)
|
|
387
|
+
)
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
await Promise.all(disconnectPromises);
|
|
391
|
+
}
|
|
392
|
+
async function disconnectWallet(networkType, clearAll = false) {
|
|
393
|
+
const targetNetwork = networkType || getConnectedNetworkType();
|
|
394
|
+
if (targetNetwork && typeof window !== "undefined") {
|
|
395
|
+
try {
|
|
396
|
+
switch (targetNetwork) {
|
|
397
|
+
case "solana" /* SOLANA */:
|
|
398
|
+
case "svm" /* SVM */: {
|
|
399
|
+
await disconnectAllSolanaWallets();
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
// EVM 钱包(如 MetaMask)没有真正的 disconnect API
|
|
403
|
+
// 只清除本地状态,下次连接时会重新请求权限
|
|
404
|
+
case "evm" /* EVM */:
|
|
405
|
+
default:
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
} catch (err) {
|
|
409
|
+
console.warn("Failed to disconnect wallet:", err);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (clearAll) {
|
|
413
|
+
const { clearAllWalletAddresses: clearAllWalletAddresses2 } = (init_wallet(), __toCommonJS(wallet_exports));
|
|
414
|
+
clearAllWalletAddresses2();
|
|
415
|
+
markWalletDisconnected();
|
|
416
|
+
await disconnectAllSolanaWallets();
|
|
417
|
+
} else if (networkType) {
|
|
418
|
+
removeWalletAddress(networkType);
|
|
419
|
+
} else {
|
|
420
|
+
if (targetNetwork) {
|
|
421
|
+
removeWalletAddress(targetNetwork);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
263
425
|
async function getCurrentWallet(networkType) {
|
|
264
426
|
if (typeof window === "undefined") {
|
|
265
427
|
return null;
|
|
@@ -361,24 +523,232 @@ async function switchNetwork(networkType) {
|
|
|
361
523
|
return null;
|
|
362
524
|
}
|
|
363
525
|
|
|
526
|
+
// src/utils/wallet-discovery.ts
|
|
527
|
+
var SOLANA_WALLETS = [
|
|
528
|
+
{
|
|
529
|
+
id: "phantom",
|
|
530
|
+
name: "Phantom",
|
|
531
|
+
// Phantom official icon
|
|
532
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZD0iTTExMC41IDY0QzExMC41IDg5Ljk1NjggODkuMjAxIDExMSA2My41IDExMUg0MS41QzM2LjI1MzMgMTExIDMyIDEwNi43NDcgMzIgMTAxLjVWNTQuNUMzMiAzMS4wMjggNTEuMDI4IDEyIDc0LjUgMTJDOTcuOTcyIDEyIDExNyAzMS4wMjggMTE3IDU0LjVWNTUuNUMxMTcgNTguNTM3NiAxMTQuNTM4IDYxIDExMS41IDYxSDEwOS41QzEwNi40NjIgNjEgMTA0IDYzLjQ2MjQgMTA0IDY2LjVWNjhDMTA0IDcxLjg2NiAxMDcuMTM0IDc1IDExMSA3NUgxMTEuNUMxMTQuNTM4IDc1IDExNyA3Mi41Mzc2IDExNyA2OS41VjY0SDExMC41WiIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzEyOF8xMjgpIi8+CjxwYXRoIGQ9Ik00OC41IDY3QzUxLjUzNzYgNjcgNTQgNjQuNTM3NiA1NCA2MS41QzU0IDU4LjQ2MjQgNTEuNTM3NiA1NiA0OC41IDU2QzQ1LjQ2MjQgNTYgNDMgNTguNDYyNCA0MyA2MS41QzQzIDY0LjUzNzYgNDUuNDYyNCA2NyA0OC41IDY3WiIgZmlsbD0iIzFCMUIxQiIvPgo8cGF0aCBkPSJNNzMuNSA2N0M3Ni41Mzc2IDY3IDc5IDY0LjUzNzYgNzkgNjEuNUM3OSA1OC40NjI0IDc2LjUzNzYgNTYgNzMuNSA1NkM3MC40NjI0IDU2IDY4IDU4LjQ2MjQgNjggNjEuNUM2OCA2NC41Mzc2IDcwLjQ2MjQgNjcgNzMuNSA2N1oiIGZpbGw9IiMxQjFCMUIiLz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl8xMjhfMTI4IiB4MT0iMTE3IiB5MT0iMTIiIHgyPSIxMTciIHkyPSIxMTEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRkZGRiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRkZGRkYiIHN0b3Atb3BhY2l0eT0iMC44MiIvPgo8L2xpbmVhckdyYWRpZW50Pgo8L2RlZnM+Cjwvc3ZnPg==",
|
|
533
|
+
detect: () => window.phantom?.solana
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
id: "solflare",
|
|
537
|
+
name: "Solflare",
|
|
538
|
+
// Solflare icon
|
|
539
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNGQzZEMDEiLz4KPHBhdGggZD0iTTk2IDY0TDY0IDMyTDMyIDY0TDY0IDk2TDk2IDY0WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+",
|
|
540
|
+
detect: () => window.solflare
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
id: "backpack",
|
|
544
|
+
name: "Backpack",
|
|
545
|
+
// Backpack icon (red coral color)
|
|
546
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNFMzM0MzAiLz4KPHBhdGggZD0iTTQwIDQ4SDg4VjgwQzg4IDg4LjgzNjYgODAuODM2NiA5NiA3MiA5Nkg1NkM0Ny4xNjM0IDk2IDQwIDg4LjgzNjYgNDAgODBWNDhaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNTIgMzJINzZWNDhINTJWMzJaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
|
|
547
|
+
detect: () => window.backpack
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
id: "okx-solana",
|
|
551
|
+
name: "OKX Wallet",
|
|
552
|
+
// OKX icon
|
|
553
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9ImJsYWNrIi8+CjxyZWN0IHg9IjI0IiB5PSIyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iNTIiIHk9IjI0IiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSI4MCIgeT0iMjQiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjI0IiB5PSI1MiIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjUyIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSIyNCIgeT0iODAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjUyIiB5PSI4MCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjgwIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
|
|
554
|
+
detect: () => window.okxwallet?.solana
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
id: "coinbase-solana",
|
|
558
|
+
name: "Coinbase Wallet",
|
|
559
|
+
// Coinbase icon (blue)
|
|
560
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwMDUyRkYiLz4KPGNpcmNsZSBjeD0iNjQiIGN5PSI2NCIgcj0iMzYiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjQ4IiB5PSI1NiIgd2lkdGg9IjMyIiBoZWlnaHQ9IjE2IiByeD0iNCIgZmlsbD0iIzAwNTJGRiIvPgo8L3N2Zz4=",
|
|
561
|
+
detect: () => window.coinbaseSolana
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
id: "trust-solana",
|
|
565
|
+
name: "Trust Wallet",
|
|
566
|
+
// Trust Wallet icon
|
|
567
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwNTAwRkYiLz4KPHBhdGggZD0iTTY0IDI0QzY0IDI0IDk2IDQwIDk2IDY0Qzk2IDg4IDY0IDEwNCA2NCAxMDRDNjQgMTA0IDMyIDg4IDMyIDY0QzMyIDQwIDY0IDI0IDY0IDI0WiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSI2IiBmaWxsPSJub25lIi8+Cjwvc3ZnPg==",
|
|
568
|
+
detect: () => window.trustwallet?.solana
|
|
569
|
+
}
|
|
570
|
+
];
|
|
571
|
+
var evmWallets = /* @__PURE__ */ new Map();
|
|
572
|
+
var evmDiscoveryListeners = /* @__PURE__ */ new Set();
|
|
573
|
+
var evmDiscoveryInitialized = false;
|
|
574
|
+
var currentConnectedWallet = null;
|
|
575
|
+
function initEVMWalletDiscovery() {
|
|
576
|
+
if (typeof window === "undefined" || evmDiscoveryInitialized) return;
|
|
577
|
+
evmDiscoveryInitialized = true;
|
|
578
|
+
window.addEventListener("eip6963:announceProvider", ((event) => {
|
|
579
|
+
const { info, provider } = event.detail;
|
|
580
|
+
evmWallets.set(info.uuid, { info, provider });
|
|
581
|
+
evmDiscoveryListeners.forEach((listener) => listener());
|
|
582
|
+
}));
|
|
583
|
+
window.dispatchEvent(new Event("eip6963:requestProvider"));
|
|
584
|
+
}
|
|
585
|
+
function getEVMWallets() {
|
|
586
|
+
const wallets = [];
|
|
587
|
+
const detectedNames = /* @__PURE__ */ new Set();
|
|
588
|
+
evmWallets.forEach((detail, uuid) => {
|
|
589
|
+
if (!detectedNames.has(detail.info.name)) {
|
|
590
|
+
wallets.push({
|
|
591
|
+
id: uuid,
|
|
592
|
+
name: detail.info.name,
|
|
593
|
+
icon: detail.info.icon,
|
|
594
|
+
networkType: "evm" /* EVM */,
|
|
595
|
+
provider: detail.provider,
|
|
596
|
+
installed: true
|
|
597
|
+
});
|
|
598
|
+
detectedNames.add(detail.info.name);
|
|
599
|
+
}
|
|
600
|
+
});
|
|
601
|
+
if (wallets.length === 0 && typeof window !== "undefined" && window.ethereum) {
|
|
602
|
+
const ethereum = window.ethereum;
|
|
603
|
+
const walletName = ethereum.isMetaMask ? "MetaMask" : ethereum.isCoinbaseWallet ? "Coinbase Wallet" : ethereum.isOkxWallet ? "OKX Wallet" : "Browser Wallet";
|
|
604
|
+
if (!detectedNames.has(walletName)) {
|
|
605
|
+
wallets.push({
|
|
606
|
+
id: "injected",
|
|
607
|
+
name: walletName,
|
|
608
|
+
icon: "",
|
|
609
|
+
// Will use first letter as avatar
|
|
610
|
+
networkType: "evm" /* EVM */,
|
|
611
|
+
provider: ethereum,
|
|
612
|
+
installed: true
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
return wallets;
|
|
617
|
+
}
|
|
618
|
+
function onEVMWalletsChanged(callback) {
|
|
619
|
+
evmDiscoveryListeners.add(callback);
|
|
620
|
+
return () => {
|
|
621
|
+
evmDiscoveryListeners.delete(callback);
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
function getSolanaWallets() {
|
|
625
|
+
if (typeof window === "undefined") return [];
|
|
626
|
+
const wallets = [];
|
|
627
|
+
const detectedProviders = /* @__PURE__ */ new Set();
|
|
628
|
+
const detectedNames = /* @__PURE__ */ new Set();
|
|
629
|
+
for (const wallet of SOLANA_WALLETS) {
|
|
630
|
+
const provider = wallet.detect();
|
|
631
|
+
if (provider && !detectedNames.has(wallet.name)) {
|
|
632
|
+
wallets.push({
|
|
633
|
+
id: wallet.id,
|
|
634
|
+
name: wallet.name,
|
|
635
|
+
icon: wallet.icon,
|
|
636
|
+
networkType: "solana" /* SOLANA */,
|
|
637
|
+
provider,
|
|
638
|
+
installed: true
|
|
639
|
+
});
|
|
640
|
+
detectedProviders.add(provider);
|
|
641
|
+
detectedNames.add(wallet.name);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
const windowSolana = window.solana;
|
|
645
|
+
if (windowSolana && !detectedProviders.has(windowSolana)) {
|
|
646
|
+
const walletName = windowSolana.isPhantom ? "Phantom" : windowSolana.isSolflare ? "Solflare" : windowSolana.isBackpack ? "Backpack" : windowSolana.walletName || "Solana Wallet";
|
|
647
|
+
if (!detectedNames.has(walletName)) {
|
|
648
|
+
wallets.push({
|
|
649
|
+
id: "solana-unknown",
|
|
650
|
+
name: walletName,
|
|
651
|
+
icon: "",
|
|
652
|
+
// Will use first letter as avatar
|
|
653
|
+
networkType: "solana" /* SOLANA */,
|
|
654
|
+
provider: windowSolana,
|
|
655
|
+
installed: true
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return wallets;
|
|
660
|
+
}
|
|
661
|
+
function getWalletsForNetwork(networkType) {
|
|
662
|
+
switch (networkType) {
|
|
663
|
+
case "evm" /* EVM */:
|
|
664
|
+
return getEVMWallets();
|
|
665
|
+
case "solana" /* SOLANA */:
|
|
666
|
+
case "svm" /* SVM */:
|
|
667
|
+
return getSolanaWallets();
|
|
668
|
+
default:
|
|
669
|
+
return [];
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
async function connectEVMWallet(wallet) {
|
|
673
|
+
if (!wallet.provider) {
|
|
674
|
+
throw new Error(`\u94B1\u5305 ${wallet.name} \u4E0D\u53EF\u7528`);
|
|
675
|
+
}
|
|
676
|
+
const accounts = await wallet.provider.request({
|
|
677
|
+
method: "eth_requestAccounts",
|
|
678
|
+
params: []
|
|
679
|
+
});
|
|
680
|
+
if (!accounts || accounts.length === 0) {
|
|
681
|
+
throw new Error("\u672A\u80FD\u83B7\u53D6\u5230\u94B1\u5305\u5730\u5740");
|
|
682
|
+
}
|
|
683
|
+
return accounts[0];
|
|
684
|
+
}
|
|
685
|
+
async function connectSolanaWallet(wallet) {
|
|
686
|
+
if (!wallet.provider) {
|
|
687
|
+
throw new Error(`\u94B1\u5305 ${wallet.name} \u4E0D\u53EF\u7528`);
|
|
688
|
+
}
|
|
689
|
+
if (wallet.provider.isConnected) {
|
|
690
|
+
try {
|
|
691
|
+
await wallet.provider.disconnect();
|
|
692
|
+
} catch (err) {
|
|
693
|
+
console.warn("Failed to disconnect before connecting:", err);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
const response = await wallet.provider.connect();
|
|
697
|
+
return response.publicKey.toString();
|
|
698
|
+
}
|
|
699
|
+
async function connectToWallet(wallet) {
|
|
700
|
+
let address;
|
|
701
|
+
switch (wallet.networkType) {
|
|
702
|
+
case "evm" /* EVM */:
|
|
703
|
+
address = await connectEVMWallet(wallet);
|
|
704
|
+
break;
|
|
705
|
+
case "solana" /* SOLANA */:
|
|
706
|
+
case "svm" /* SVM */:
|
|
707
|
+
address = await connectSolanaWallet(wallet);
|
|
708
|
+
break;
|
|
709
|
+
default:
|
|
710
|
+
throw new Error("\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B");
|
|
711
|
+
}
|
|
712
|
+
currentConnectedWallet = wallet;
|
|
713
|
+
return address;
|
|
714
|
+
}
|
|
715
|
+
function setCurrentConnectedWallet(wallet) {
|
|
716
|
+
currentConnectedWallet = wallet;
|
|
717
|
+
}
|
|
718
|
+
function clearConnectedWallet() {
|
|
719
|
+
currentConnectedWallet = null;
|
|
720
|
+
}
|
|
721
|
+
function getWalletProviderForPayment(networkType) {
|
|
722
|
+
if (currentConnectedWallet && currentConnectedWallet.networkType === networkType) {
|
|
723
|
+
return currentConnectedWallet.provider;
|
|
724
|
+
}
|
|
725
|
+
if (typeof window === "undefined") return null;
|
|
726
|
+
switch (networkType) {
|
|
727
|
+
case "evm" /* EVM */:
|
|
728
|
+
return window.ethereum;
|
|
729
|
+
case "solana" /* SOLANA */:
|
|
730
|
+
case "svm" /* SVM */:
|
|
731
|
+
return window.phantom?.solana || window.solana;
|
|
732
|
+
default:
|
|
733
|
+
return null;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
if (typeof window !== "undefined") {
|
|
737
|
+
initEVMWalletDiscovery();
|
|
738
|
+
}
|
|
739
|
+
|
|
364
740
|
// src/services/svm/payment-header.ts
|
|
365
|
-
import {
|
|
366
|
-
ComputeBudgetProgram,
|
|
367
|
-
Connection,
|
|
368
|
-
PublicKey,
|
|
369
|
-
TransactionMessage,
|
|
370
|
-
VersionedTransaction
|
|
371
|
-
} from "@solana/web3.js";
|
|
741
|
+
import { ComputeBudgetProgram, Connection, PublicKey, TransactionMessage, VersionedTransaction } from "@solana/web3.js";
|
|
372
742
|
import {
|
|
373
743
|
createTransferCheckedInstruction,
|
|
374
|
-
|
|
744
|
+
getAssociatedTokenAddressSync,
|
|
375
745
|
getMint,
|
|
376
746
|
TOKEN_2022_PROGRAM_ID,
|
|
377
747
|
TOKEN_PROGRAM_ID
|
|
378
748
|
} from "@solana/spl-token";
|
|
379
749
|
async function createSvmPaymentHeader(params) {
|
|
380
750
|
const { wallet, paymentRequirements, x402Version, rpcUrl } = params;
|
|
381
|
-
const connection = new Connection(rpcUrl
|
|
751
|
+
const connection = new Connection(rpcUrl);
|
|
382
752
|
const feePayer = paymentRequirements?.extra?.feePayer;
|
|
383
753
|
if (typeof feePayer !== "string" || !feePayer) {
|
|
384
754
|
throw new Error("Missing facilitator feePayer in payment requirements (extra.feePayer).");
|
|
@@ -392,83 +762,85 @@ async function createSvmPaymentHeader(params) {
|
|
|
392
762
|
if (!paymentRequirements?.payTo) {
|
|
393
763
|
throw new Error("Missing payTo in payment requirements");
|
|
394
764
|
}
|
|
395
|
-
const
|
|
396
|
-
const instructions = [];
|
|
397
|
-
instructions.push(
|
|
398
|
-
ComputeBudgetProgram.setComputeUnitLimit({
|
|
399
|
-
units: 7e3
|
|
400
|
-
// Sufficient for SPL token transfer
|
|
401
|
-
})
|
|
402
|
-
);
|
|
403
|
-
instructions.push(
|
|
404
|
-
ComputeBudgetProgram.setComputeUnitPrice({
|
|
405
|
-
microLamports: 1
|
|
406
|
-
// Minimal price
|
|
407
|
-
})
|
|
408
|
-
);
|
|
765
|
+
const destinationPubkey = new PublicKey(paymentRequirements.payTo);
|
|
409
766
|
if (!paymentRequirements.asset) {
|
|
410
767
|
throw new Error("Missing token mint for SPL transfer");
|
|
411
768
|
}
|
|
412
769
|
const mintPubkey = new PublicKey(paymentRequirements.asset);
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
770
|
+
const mintAccountInfo = await connection.getAccountInfo(mintPubkey);
|
|
771
|
+
if (!mintAccountInfo) {
|
|
772
|
+
throw new Error(`Mint account ${mintPubkey.toBase58()} not found`);
|
|
773
|
+
}
|
|
774
|
+
const tokenProgramId = mintAccountInfo.owner.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
|
|
775
|
+
const mint = await getMint(connection, mintPubkey, void 0, tokenProgramId);
|
|
776
|
+
const sourceAta = getAssociatedTokenAddressSync(
|
|
417
777
|
mintPubkey,
|
|
418
778
|
userPubkey,
|
|
419
779
|
false,
|
|
420
|
-
|
|
780
|
+
tokenProgramId
|
|
421
781
|
);
|
|
422
|
-
const destinationAta =
|
|
782
|
+
const destinationAta = getAssociatedTokenAddressSync(
|
|
423
783
|
mintPubkey,
|
|
424
|
-
|
|
784
|
+
destinationPubkey,
|
|
425
785
|
false,
|
|
426
|
-
|
|
786
|
+
tokenProgramId
|
|
427
787
|
);
|
|
428
|
-
const sourceAtaInfo = await connection.getAccountInfo(sourceAta
|
|
788
|
+
const sourceAtaInfo = await connection.getAccountInfo(sourceAta);
|
|
429
789
|
if (!sourceAtaInfo) {
|
|
430
790
|
throw new Error(
|
|
431
791
|
`User does not have an Associated Token Account for ${paymentRequirements.asset}. Please create one first or ensure you have the required token.`
|
|
432
792
|
);
|
|
433
793
|
}
|
|
434
|
-
const destAtaInfo = await connection.getAccountInfo(destinationAta
|
|
794
|
+
const destAtaInfo = await connection.getAccountInfo(destinationAta);
|
|
435
795
|
if (!destAtaInfo) {
|
|
436
796
|
throw new Error(
|
|
437
797
|
`Destination does not have an Associated Token Account for ${paymentRequirements.asset}. The receiver must create their token account before receiving payments.`
|
|
438
798
|
);
|
|
439
799
|
}
|
|
440
|
-
const
|
|
441
|
-
|
|
800
|
+
const instructions = [
|
|
801
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
802
|
+
units: 7e3
|
|
803
|
+
// Sufficient for SPL token transfer
|
|
804
|
+
}),
|
|
805
|
+
ComputeBudgetProgram.setComputeUnitPrice({
|
|
806
|
+
microLamports: 1
|
|
807
|
+
// Minimal price
|
|
808
|
+
}),
|
|
442
809
|
createTransferCheckedInstruction(
|
|
443
810
|
sourceAta,
|
|
444
811
|
mintPubkey,
|
|
445
812
|
destinationAta,
|
|
446
813
|
userPubkey,
|
|
447
|
-
|
|
814
|
+
BigInt(paymentRequirements.maxAmountRequired),
|
|
448
815
|
mint.decimals,
|
|
449
816
|
[],
|
|
450
|
-
|
|
817
|
+
tokenProgramId
|
|
451
818
|
)
|
|
452
|
-
|
|
453
|
-
const { blockhash } = await connection.getLatestBlockhash(
|
|
454
|
-
const
|
|
819
|
+
];
|
|
820
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
821
|
+
const messageV0 = new TransactionMessage({
|
|
455
822
|
payerKey: feePayerPubkey,
|
|
456
823
|
recentBlockhash: blockhash,
|
|
457
824
|
instructions
|
|
458
825
|
}).compileToV0Message();
|
|
459
|
-
const transaction = new VersionedTransaction(
|
|
826
|
+
const transaction = new VersionedTransaction(messageV0);
|
|
460
827
|
if (typeof wallet?.signTransaction !== "function") {
|
|
461
828
|
throw new Error("Connected wallet does not support signTransaction");
|
|
462
829
|
}
|
|
463
|
-
let
|
|
830
|
+
let signedTransaction;
|
|
464
831
|
try {
|
|
465
|
-
|
|
832
|
+
signedTransaction = await wallet.signTransaction(transaction);
|
|
466
833
|
console.log("\u2705 Transaction signed successfully");
|
|
467
834
|
} catch (error) {
|
|
468
835
|
console.error("\u274C Failed to sign transaction:", error);
|
|
469
836
|
throw wrapPaymentError(error);
|
|
470
837
|
}
|
|
471
|
-
const
|
|
838
|
+
const serializedBytes = signedTransaction.serialize();
|
|
839
|
+
let binary = "";
|
|
840
|
+
for (let i = 0; i < serializedBytes.length; i++) {
|
|
841
|
+
binary += String.fromCharCode(serializedBytes[i]);
|
|
842
|
+
}
|
|
843
|
+
const serializedTransaction = btoa(binary);
|
|
472
844
|
const paymentPayload = {
|
|
473
845
|
x402Version,
|
|
474
846
|
scheme: paymentRequirements.scheme,
|
|
@@ -477,7 +849,7 @@ async function createSvmPaymentHeader(params) {
|
|
|
477
849
|
transaction: serializedTransaction
|
|
478
850
|
}
|
|
479
851
|
};
|
|
480
|
-
const paymentHeader =
|
|
852
|
+
const paymentHeader = btoa(JSON.stringify(paymentPayload));
|
|
481
853
|
return paymentHeader;
|
|
482
854
|
}
|
|
483
855
|
function getDefaultSolanaRpcUrl(network) {
|
|
@@ -493,7 +865,7 @@ function getDefaultSolanaRpcUrl(network) {
|
|
|
493
865
|
// src/services/svm/payment-handler.ts
|
|
494
866
|
init_types();
|
|
495
867
|
async function handleSvmPayment(endpoint, config, requestInit) {
|
|
496
|
-
const { wallet,
|
|
868
|
+
const { wallet, rpcUrl, maxPaymentAmount } = config;
|
|
497
869
|
const initialResponse = await fetch(endpoint, {
|
|
498
870
|
...requestInit,
|
|
499
871
|
method: requestInit?.method || "POST"
|
|
@@ -502,26 +874,10 @@ async function handleSvmPayment(endpoint, config, requestInit) {
|
|
|
502
874
|
return initialResponse;
|
|
503
875
|
}
|
|
504
876
|
const rawResponse = await initialResponse.json();
|
|
505
|
-
|
|
506
|
-
"X-PAYMENT header is required",
|
|
507
|
-
"missing X-PAYMENT header",
|
|
508
|
-
"payment_required"
|
|
509
|
-
];
|
|
510
|
-
if (rawResponse.error && !IGNORED_ERRORS.includes(rawResponse.error)) {
|
|
877
|
+
if (rawResponse.error && !IGNORED_402_ERRORS.includes(rawResponse.error)) {
|
|
511
878
|
console.error(`\u274C Payment verification failed: ${rawResponse.error}`);
|
|
512
|
-
const
|
|
513
|
-
|
|
514
|
-
"invalid_signature": "Invalid payment signature",
|
|
515
|
-
"expired": "Payment authorization has expired",
|
|
516
|
-
"already_used": "This payment has already been used",
|
|
517
|
-
"network_mismatch": "Payment network does not match",
|
|
518
|
-
"invalid_payment": "Invalid payment data",
|
|
519
|
-
"verification_failed": "Payment verification failed",
|
|
520
|
-
"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."
|
|
521
|
-
};
|
|
522
|
-
const errorMessage = ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
|
|
523
|
-
const error = new Error(errorMessage);
|
|
524
|
-
throw wrapPaymentError(error);
|
|
879
|
+
const errorMessage = PAYMENT_ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
|
|
880
|
+
throw wrapPaymentError(new Error(errorMessage));
|
|
525
881
|
}
|
|
526
882
|
const x402Version = rawResponse.x402Version;
|
|
527
883
|
const parsedPaymentRequirements = rawResponse.accepts || [];
|
|
@@ -571,26 +927,10 @@ async function handleSvmPayment(endpoint, config, requestInit) {
|
|
|
571
927
|
if (retryResponse.status === 402) {
|
|
572
928
|
try {
|
|
573
929
|
const retryData = await retryResponse.json();
|
|
574
|
-
|
|
575
|
-
"X-PAYMENT header is required",
|
|
576
|
-
"missing X-PAYMENT header",
|
|
577
|
-
"payment_required"
|
|
578
|
-
];
|
|
579
|
-
if (retryData.error && !IGNORED_ERRORS2.includes(retryData.error)) {
|
|
930
|
+
if (retryData.error && !IGNORED_402_ERRORS.includes(retryData.error)) {
|
|
580
931
|
console.error(`\u274C Payment verification failed: ${retryData.error}`);
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
"invalid_signature": "Invalid payment signature",
|
|
584
|
-
"expired": "Payment authorization has expired",
|
|
585
|
-
"already_used": "This payment has already been used",
|
|
586
|
-
"network_mismatch": "Payment network does not match",
|
|
587
|
-
"invalid_payment": "Invalid payment data",
|
|
588
|
-
"verification_failed": "Payment verification failed",
|
|
589
|
-
"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."
|
|
590
|
-
};
|
|
591
|
-
const errorMessage = ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
|
|
592
|
-
const error = new Error(errorMessage);
|
|
593
|
-
throw wrapPaymentError(error);
|
|
932
|
+
const errorMessage = PAYMENT_ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
|
|
933
|
+
throw wrapPaymentError(new Error(errorMessage));
|
|
594
934
|
}
|
|
595
935
|
} catch (error) {
|
|
596
936
|
if (error instanceof PaymentOperationError) {
|
|
@@ -717,6 +1057,15 @@ function getChainIdFromNetwork(network) {
|
|
|
717
1057
|
|
|
718
1058
|
// src/services/evm/payment-handler.ts
|
|
719
1059
|
init_types();
|
|
1060
|
+
var NETWORK_NAMES = {
|
|
1061
|
+
1: "Ethereum Mainnet",
|
|
1062
|
+
11155111: "Sepolia Testnet",
|
|
1063
|
+
8453: "Base Mainnet",
|
|
1064
|
+
84532: "Base Sepolia Testnet",
|
|
1065
|
+
137: "Polygon Mainnet",
|
|
1066
|
+
42161: "Arbitrum One",
|
|
1067
|
+
10: "Optimism Mainnet"
|
|
1068
|
+
};
|
|
720
1069
|
async function handleEvmPayment(endpoint, config, requestInit) {
|
|
721
1070
|
const { wallet, network, maxPaymentAmount } = config;
|
|
722
1071
|
const initialResponse = await fetch(endpoint, {
|
|
@@ -727,25 +1076,10 @@ async function handleEvmPayment(endpoint, config, requestInit) {
|
|
|
727
1076
|
return initialResponse;
|
|
728
1077
|
}
|
|
729
1078
|
const rawResponse = await initialResponse.json();
|
|
730
|
-
|
|
731
|
-
"X-PAYMENT header is required",
|
|
732
|
-
"missing X-PAYMENT header",
|
|
733
|
-
"payment_required"
|
|
734
|
-
];
|
|
735
|
-
if (rawResponse.error && !IGNORED_ERRORS.includes(rawResponse.error)) {
|
|
1079
|
+
if (rawResponse.error && !IGNORED_402_ERRORS.includes(rawResponse.error)) {
|
|
736
1080
|
console.error(`\u274C Payment verification failed: ${rawResponse.error}`);
|
|
737
|
-
const
|
|
738
|
-
|
|
739
|
-
"invalid_signature": "Invalid payment signature",
|
|
740
|
-
"expired": "Payment authorization has expired",
|
|
741
|
-
"already_used": "This payment has already been used",
|
|
742
|
-
"network_mismatch": "Payment network does not match",
|
|
743
|
-
"invalid_payment": "Invalid payment data",
|
|
744
|
-
"verification_failed": "Payment verification failed"
|
|
745
|
-
};
|
|
746
|
-
const errorMessage = ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
|
|
747
|
-
const error = new Error(errorMessage);
|
|
748
|
-
throw wrapPaymentError(error);
|
|
1081
|
+
const errorMessage = PAYMENT_ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
|
|
1082
|
+
throw wrapPaymentError(new Error(errorMessage));
|
|
749
1083
|
}
|
|
750
1084
|
const x402Version = rawResponse.x402Version;
|
|
751
1085
|
const parsedPaymentRequirements = rawResponse.accepts || [];
|
|
@@ -777,19 +1111,10 @@ async function handleEvmPayment(endpoint, config, requestInit) {
|
|
|
777
1111
|
console.warn("\u26A0\uFE0F Failed to get current chainId:", error);
|
|
778
1112
|
}
|
|
779
1113
|
}
|
|
780
|
-
const networkNames = {
|
|
781
|
-
1: "Ethereum Mainnet",
|
|
782
|
-
11155111: "Sepolia Testnet",
|
|
783
|
-
8453: "Base Mainnet",
|
|
784
|
-
84532: "Base Sepolia Testnet",
|
|
785
|
-
137: "Polygon Mainnet",
|
|
786
|
-
42161: "Arbitrum One",
|
|
787
|
-
10: "Optimism Mainnet"
|
|
788
|
-
};
|
|
789
1114
|
if (currentChainId && currentChainId !== targetChainId) {
|
|
790
1115
|
if (!wallet.switchChain) {
|
|
791
|
-
const currentNetworkName =
|
|
792
|
-
const targetNetworkName =
|
|
1116
|
+
const currentNetworkName = NETWORK_NAMES[currentChainId] || `Chain ${currentChainId}`;
|
|
1117
|
+
const targetNetworkName = NETWORK_NAMES[targetChainId] || selectedRequirements.network;
|
|
793
1118
|
const error = new Error(
|
|
794
1119
|
`Network mismatch: Your wallet is connected to ${currentNetworkName}, but payment requires ${targetNetworkName}. Please switch to ${targetNetworkName} manually in your wallet.`
|
|
795
1120
|
);
|
|
@@ -801,7 +1126,7 @@ async function handleEvmPayment(endpoint, config, requestInit) {
|
|
|
801
1126
|
console.log(`\u2705 Successfully switched to chain ${targetChainId}`);
|
|
802
1127
|
} catch (error) {
|
|
803
1128
|
console.error("\u274C Failed to switch chain:", error);
|
|
804
|
-
const targetNetworkName =
|
|
1129
|
+
const targetNetworkName = NETWORK_NAMES[targetChainId] || selectedRequirements.network;
|
|
805
1130
|
const wrappedError = wrapPaymentError(error);
|
|
806
1131
|
let finalError;
|
|
807
1132
|
if (wrappedError.code === "USER_REJECTED" /* USER_REJECTED */) {
|
|
@@ -855,25 +1180,10 @@ async function handleEvmPayment(endpoint, config, requestInit) {
|
|
|
855
1180
|
if (retryResponse.status === 402) {
|
|
856
1181
|
try {
|
|
857
1182
|
const retryData = await retryResponse.json();
|
|
858
|
-
|
|
859
|
-
"X-PAYMENT header is required",
|
|
860
|
-
"missing X-PAYMENT header",
|
|
861
|
-
"payment_required"
|
|
862
|
-
];
|
|
863
|
-
if (retryData.error && !IGNORED_ERRORS2.includes(retryData.error)) {
|
|
1183
|
+
if (retryData.error && !IGNORED_402_ERRORS.includes(retryData.error)) {
|
|
864
1184
|
console.error(`\u274C Payment verification failed: ${retryData.error}`);
|
|
865
|
-
const
|
|
866
|
-
|
|
867
|
-
"invalid_signature": "Invalid payment signature",
|
|
868
|
-
"expired": "Payment authorization has expired",
|
|
869
|
-
"already_used": "This payment has already been used",
|
|
870
|
-
"network_mismatch": "Payment network does not match",
|
|
871
|
-
"invalid_payment": "Invalid payment data",
|
|
872
|
-
"verification_failed": "Payment verification failed"
|
|
873
|
-
};
|
|
874
|
-
const errorMessage = ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
|
|
875
|
-
const error = new Error(errorMessage);
|
|
876
|
-
throw wrapPaymentError(error);
|
|
1185
|
+
const errorMessage = PAYMENT_ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
|
|
1186
|
+
throw wrapPaymentError(new Error(errorMessage));
|
|
877
1187
|
}
|
|
878
1188
|
} catch (error) {
|
|
879
1189
|
if (error instanceof PaymentOperationError) {
|
|
@@ -921,9 +1231,9 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
|
|
|
921
1231
|
}
|
|
922
1232
|
} : {};
|
|
923
1233
|
if (networkType === "solana" /* SOLANA */ || networkType === "svm" /* SVM */) {
|
|
924
|
-
const solana =
|
|
1234
|
+
const solana = getWalletProviderForPayment(networkType);
|
|
925
1235
|
if (!solana) {
|
|
926
|
-
throw new Error("\u8BF7\
|
|
1236
|
+
throw new Error("\u8BF7\u5148\u8FDE\u63A5 Solana \u94B1\u5305");
|
|
927
1237
|
}
|
|
928
1238
|
if (!solana.isConnected) {
|
|
929
1239
|
await solana.connect();
|
|
@@ -934,10 +1244,11 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
|
|
|
934
1244
|
// Will use backend's network configuration
|
|
935
1245
|
}, requestInit);
|
|
936
1246
|
} else if (networkType === "evm" /* EVM */) {
|
|
937
|
-
|
|
938
|
-
|
|
1247
|
+
const ethereum = getWalletProviderForPayment(networkType);
|
|
1248
|
+
if (!ethereum) {
|
|
1249
|
+
throw new Error("\u8BF7\u5148\u8FDE\u63A5 EVM \u94B1\u5305");
|
|
939
1250
|
}
|
|
940
|
-
const provider = new ethers2.BrowserProvider(
|
|
1251
|
+
const provider = new ethers2.BrowserProvider(ethereum);
|
|
941
1252
|
const signer = await provider.getSigner();
|
|
942
1253
|
const wallet = {
|
|
943
1254
|
address: await signer.getAddress(),
|
|
@@ -951,7 +1262,7 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
|
|
|
951
1262
|
},
|
|
952
1263
|
// Switch to a different chain
|
|
953
1264
|
switchChain: async (chainId) => {
|
|
954
|
-
await
|
|
1265
|
+
await ethereum.request({
|
|
955
1266
|
method: "wallet_switchEthereumChain",
|
|
956
1267
|
params: [{ chainId }]
|
|
957
1268
|
});
|
|
@@ -1006,6 +1317,21 @@ function getNetworkDisplayName(network) {
|
|
|
1006
1317
|
}
|
|
1007
1318
|
|
|
1008
1319
|
// src/utils/payment-error-handler.ts
|
|
1320
|
+
var IGNORED_402_ERRORS = [
|
|
1321
|
+
"X-PAYMENT header is required",
|
|
1322
|
+
"missing X-PAYMENT header",
|
|
1323
|
+
"payment_required"
|
|
1324
|
+
];
|
|
1325
|
+
var PAYMENT_ERROR_MESSAGES = {
|
|
1326
|
+
"insufficient_funds": "Insufficient balance to complete this payment",
|
|
1327
|
+
"invalid_signature": "Invalid payment signature",
|
|
1328
|
+
"expired": "Payment authorization has expired",
|
|
1329
|
+
"already_used": "This payment has already been used",
|
|
1330
|
+
"network_mismatch": "Payment network does not match",
|
|
1331
|
+
"invalid_payment": "Invalid payment data",
|
|
1332
|
+
"verification_failed": "Payment verification failed",
|
|
1333
|
+
"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."
|
|
1334
|
+
};
|
|
1009
1335
|
function parsePaymentError(error) {
|
|
1010
1336
|
if (!error) {
|
|
1011
1337
|
return {
|
|
@@ -1209,13 +1535,18 @@ var WalletStore = class {
|
|
|
1209
1535
|
});
|
|
1210
1536
|
}
|
|
1211
1537
|
// Connect wallet
|
|
1212
|
-
|
|
1538
|
+
// @param forceSelect - 强制弹出钱包选择界面,用于切换账户
|
|
1539
|
+
async connect(type, forceSelect = false) {
|
|
1213
1540
|
if (this.state.address && this.state.networkType && this.state.networkType !== type) {
|
|
1214
1541
|
saveWalletAddress(this.state.networkType, this.state.address);
|
|
1215
1542
|
}
|
|
1216
1543
|
this.setState({ isConnecting: true, error: null });
|
|
1217
1544
|
try {
|
|
1218
|
-
const walletAddress = await connectWallet(type);
|
|
1545
|
+
const walletAddress = await connectWallet(type, forceSelect);
|
|
1546
|
+
const wallets = getWalletsForNetwork(type);
|
|
1547
|
+
if (wallets.length > 0) {
|
|
1548
|
+
setCurrentConnectedWallet(wallets[0]);
|
|
1549
|
+
}
|
|
1219
1550
|
this.setState({
|
|
1220
1551
|
address: walletAddress,
|
|
1221
1552
|
networkType: type,
|
|
@@ -1229,6 +1560,30 @@ var WalletStore = class {
|
|
|
1229
1560
|
throw err;
|
|
1230
1561
|
}
|
|
1231
1562
|
}
|
|
1563
|
+
// Connect to a specific wallet (from wallet discovery)
|
|
1564
|
+
async connectWithWallet(wallet) {
|
|
1565
|
+
if (this.state.address && this.state.networkType && this.state.networkType !== wallet.networkType) {
|
|
1566
|
+
saveWalletAddress(this.state.networkType, this.state.address);
|
|
1567
|
+
}
|
|
1568
|
+
this.setState({ isConnecting: true, error: null });
|
|
1569
|
+
try {
|
|
1570
|
+
const walletAddress = await connectToWallet(wallet);
|
|
1571
|
+
clearWalletDisconnection(wallet.networkType);
|
|
1572
|
+
saveConnectedNetworkType(wallet.networkType);
|
|
1573
|
+
saveWalletAddress(wallet.networkType, walletAddress);
|
|
1574
|
+
this.setState({
|
|
1575
|
+
address: walletAddress,
|
|
1576
|
+
networkType: wallet.networkType,
|
|
1577
|
+
isConnecting: false
|
|
1578
|
+
});
|
|
1579
|
+
} catch (err) {
|
|
1580
|
+
this.setState({
|
|
1581
|
+
error: err.message || "Failed to connect wallet",
|
|
1582
|
+
isConnecting: false
|
|
1583
|
+
});
|
|
1584
|
+
throw err;
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1232
1587
|
// Switch network (use cached wallet if available)
|
|
1233
1588
|
async switchNetwork(type) {
|
|
1234
1589
|
if (this.state.address && this.state.networkType) {
|
|
@@ -1260,9 +1615,15 @@ var WalletStore = class {
|
|
|
1260
1615
|
}
|
|
1261
1616
|
}
|
|
1262
1617
|
// Disconnect wallet
|
|
1263
|
-
disconnect() {
|
|
1618
|
+
async disconnect() {
|
|
1264
1619
|
const currentNetwork = this.state.networkType;
|
|
1620
|
+
clearConnectedWallet();
|
|
1265
1621
|
if (currentNetwork) {
|
|
1622
|
+
try {
|
|
1623
|
+
await disconnectWallet(currentNetwork);
|
|
1624
|
+
} catch (err) {
|
|
1625
|
+
console.warn("Failed to disconnect wallet provider:", err);
|
|
1626
|
+
}
|
|
1266
1627
|
this.handleDisconnect(currentNetwork);
|
|
1267
1628
|
} else {
|
|
1268
1629
|
this.setState({
|
|
@@ -1306,7 +1667,8 @@ function useWallet() {
|
|
|
1306
1667
|
);
|
|
1307
1668
|
return {
|
|
1308
1669
|
...state,
|
|
1309
|
-
connect: (type) => walletStore.connect(type),
|
|
1670
|
+
connect: (type, forceSelect) => walletStore.connect(type, forceSelect),
|
|
1671
|
+
connectWithWallet: (wallet) => walletStore.connectWithWallet(wallet),
|
|
1310
1672
|
switchNetwork: (type) => walletStore.switchNetwork(type),
|
|
1311
1673
|
ensureNetwork: (type) => walletStore.ensureNetwork(type),
|
|
1312
1674
|
disconnect: () => walletStore.disconnect(),
|
|
@@ -1415,7 +1777,218 @@ function usePaymentInfo(merchantId, endpoint = PROD_BACK_URL, additionalParams)
|
|
|
1415
1777
|
}
|
|
1416
1778
|
|
|
1417
1779
|
// src/react/components/WalletConnect.tsx
|
|
1418
|
-
import
|
|
1780
|
+
import React2, { useState as useState4 } from "react";
|
|
1781
|
+
|
|
1782
|
+
// src/react/components/WalletSelectModal.tsx
|
|
1783
|
+
import React, { useEffect as useEffect3, useState as useState3 } from "react";
|
|
1784
|
+
import { createPortal } from "react-dom";
|
|
1785
|
+
var overlayStyle = {
|
|
1786
|
+
position: "fixed",
|
|
1787
|
+
top: 0,
|
|
1788
|
+
left: 0,
|
|
1789
|
+
right: 0,
|
|
1790
|
+
bottom: 0,
|
|
1791
|
+
backgroundColor: "rgba(0, 0, 0, 0.4)",
|
|
1792
|
+
display: "flex",
|
|
1793
|
+
alignItems: "center",
|
|
1794
|
+
justifyContent: "center",
|
|
1795
|
+
zIndex: 99999
|
|
1796
|
+
};
|
|
1797
|
+
var modalStyle = {
|
|
1798
|
+
backgroundColor: "#ffffff",
|
|
1799
|
+
borderRadius: "12px",
|
|
1800
|
+
padding: "16px",
|
|
1801
|
+
maxWidth: "320px",
|
|
1802
|
+
width: "90%",
|
|
1803
|
+
maxHeight: "70vh",
|
|
1804
|
+
overflow: "auto",
|
|
1805
|
+
boxShadow: "0 10px 25px rgba(0, 0, 0, 0.15)"
|
|
1806
|
+
};
|
|
1807
|
+
var headerStyle = {
|
|
1808
|
+
display: "flex",
|
|
1809
|
+
alignItems: "center",
|
|
1810
|
+
justifyContent: "space-between",
|
|
1811
|
+
marginBottom: "12px"
|
|
1812
|
+
};
|
|
1813
|
+
var titleStyle = {
|
|
1814
|
+
fontSize: "15px",
|
|
1815
|
+
fontWeight: 600,
|
|
1816
|
+
color: "#1a1a1a",
|
|
1817
|
+
margin: 0
|
|
1818
|
+
};
|
|
1819
|
+
var closeButtonStyle = {
|
|
1820
|
+
background: "none",
|
|
1821
|
+
border: "none",
|
|
1822
|
+
fontSize: "20px",
|
|
1823
|
+
cursor: "pointer",
|
|
1824
|
+
color: "#666",
|
|
1825
|
+
padding: "2px 6px",
|
|
1826
|
+
lineHeight: 1,
|
|
1827
|
+
borderRadius: "4px"
|
|
1828
|
+
};
|
|
1829
|
+
var subtitleStyle = {
|
|
1830
|
+
fontSize: "12px",
|
|
1831
|
+
color: "#666",
|
|
1832
|
+
marginBottom: "12px"
|
|
1833
|
+
};
|
|
1834
|
+
var walletListStyle = {
|
|
1835
|
+
display: "flex",
|
|
1836
|
+
flexDirection: "column",
|
|
1837
|
+
gap: "6px"
|
|
1838
|
+
};
|
|
1839
|
+
var getWalletItemStyle = (isHovered) => ({
|
|
1840
|
+
display: "flex",
|
|
1841
|
+
alignItems: "center",
|
|
1842
|
+
gap: "10px",
|
|
1843
|
+
padding: "10px 12px",
|
|
1844
|
+
border: "1px solid #e5e5e5",
|
|
1845
|
+
borderRadius: "8px",
|
|
1846
|
+
cursor: "pointer",
|
|
1847
|
+
transition: "all 0.15s ease",
|
|
1848
|
+
backgroundColor: isHovered ? "#f5f5f5" : "#ffffff",
|
|
1849
|
+
borderColor: isHovered ? "#d0d0d0" : "#e5e5e5"
|
|
1850
|
+
});
|
|
1851
|
+
var walletIconStyle = {
|
|
1852
|
+
width: "32px",
|
|
1853
|
+
height: "32px",
|
|
1854
|
+
borderRadius: "8px",
|
|
1855
|
+
objectFit: "contain",
|
|
1856
|
+
backgroundColor: "#f5f5f5"
|
|
1857
|
+
};
|
|
1858
|
+
var getAvatarColor = (name) => {
|
|
1859
|
+
const colors2 = [
|
|
1860
|
+
"#6366f1",
|
|
1861
|
+
// indigo
|
|
1862
|
+
"#8b5cf6",
|
|
1863
|
+
// violet
|
|
1864
|
+
"#ec4899",
|
|
1865
|
+
// pink
|
|
1866
|
+
"#f43f5e",
|
|
1867
|
+
// rose
|
|
1868
|
+
"#f97316",
|
|
1869
|
+
// orange
|
|
1870
|
+
"#eab308",
|
|
1871
|
+
// yellow
|
|
1872
|
+
"#22c55e",
|
|
1873
|
+
// green
|
|
1874
|
+
"#14b8a6",
|
|
1875
|
+
// teal
|
|
1876
|
+
"#06b6d4",
|
|
1877
|
+
// cyan
|
|
1878
|
+
"#3b82f6"
|
|
1879
|
+
// blue
|
|
1880
|
+
];
|
|
1881
|
+
const index = name.charCodeAt(0) % colors2.length;
|
|
1882
|
+
return colors2[index];
|
|
1883
|
+
};
|
|
1884
|
+
var getWalletIconPlaceholderStyle = (walletName) => ({
|
|
1885
|
+
width: "32px",
|
|
1886
|
+
height: "32px",
|
|
1887
|
+
borderRadius: "8px",
|
|
1888
|
+
backgroundColor: getAvatarColor(walletName),
|
|
1889
|
+
display: "flex",
|
|
1890
|
+
alignItems: "center",
|
|
1891
|
+
justifyContent: "center",
|
|
1892
|
+
fontSize: "14px",
|
|
1893
|
+
fontWeight: 600,
|
|
1894
|
+
color: "#ffffff"
|
|
1895
|
+
});
|
|
1896
|
+
var walletNameStyle = {
|
|
1897
|
+
fontSize: "14px",
|
|
1898
|
+
fontWeight: 500,
|
|
1899
|
+
color: "#1a1a1a"
|
|
1900
|
+
};
|
|
1901
|
+
var emptyStateStyle = {
|
|
1902
|
+
textAlign: "center",
|
|
1903
|
+
padding: "24px 12px",
|
|
1904
|
+
color: "#666"
|
|
1905
|
+
};
|
|
1906
|
+
var emptyTitleStyle = {
|
|
1907
|
+
fontSize: "14px",
|
|
1908
|
+
fontWeight: 500,
|
|
1909
|
+
marginBottom: "6px",
|
|
1910
|
+
color: "#1a1a1a"
|
|
1911
|
+
};
|
|
1912
|
+
var emptyDescStyle = {
|
|
1913
|
+
fontSize: "12px",
|
|
1914
|
+
color: "#888"
|
|
1915
|
+
};
|
|
1916
|
+
function WalletItem({
|
|
1917
|
+
wallet,
|
|
1918
|
+
isHovered,
|
|
1919
|
+
onSelect,
|
|
1920
|
+
onHover
|
|
1921
|
+
}) {
|
|
1922
|
+
const [iconError, setIconError] = useState3(false);
|
|
1923
|
+
return /* @__PURE__ */ React.createElement(
|
|
1924
|
+
"div",
|
|
1925
|
+
{
|
|
1926
|
+
style: getWalletItemStyle(isHovered),
|
|
1927
|
+
onClick: onSelect,
|
|
1928
|
+
onMouseEnter: () => onHover(true),
|
|
1929
|
+
onMouseLeave: () => onHover(false)
|
|
1930
|
+
},
|
|
1931
|
+
wallet.icon && !iconError ? /* @__PURE__ */ React.createElement(
|
|
1932
|
+
"img",
|
|
1933
|
+
{
|
|
1934
|
+
src: wallet.icon,
|
|
1935
|
+
alt: wallet.name,
|
|
1936
|
+
style: walletIconStyle,
|
|
1937
|
+
onError: () => setIconError(true)
|
|
1938
|
+
}
|
|
1939
|
+
) : /* @__PURE__ */ React.createElement("div", { style: getWalletIconPlaceholderStyle(wallet.name) }, wallet.name.charAt(0).toUpperCase()),
|
|
1940
|
+
/* @__PURE__ */ React.createElement("span", { style: walletNameStyle }, wallet.name)
|
|
1941
|
+
);
|
|
1942
|
+
}
|
|
1943
|
+
function WalletSelectModal({
|
|
1944
|
+
isOpen,
|
|
1945
|
+
networkType,
|
|
1946
|
+
onSelect,
|
|
1947
|
+
onClose
|
|
1948
|
+
}) {
|
|
1949
|
+
const [wallets, setWallets] = useState3([]);
|
|
1950
|
+
const [hoveredWallet, setHoveredWallet] = useState3(null);
|
|
1951
|
+
const [mounted, setMounted] = useState3(false);
|
|
1952
|
+
useEffect3(() => {
|
|
1953
|
+
setMounted(true);
|
|
1954
|
+
return () => setMounted(false);
|
|
1955
|
+
}, []);
|
|
1956
|
+
useEffect3(() => {
|
|
1957
|
+
if (!isOpen) return;
|
|
1958
|
+
initEVMWalletDiscovery();
|
|
1959
|
+
const updateWallets = () => {
|
|
1960
|
+
setWallets(getWalletsForNetwork(networkType));
|
|
1961
|
+
};
|
|
1962
|
+
updateWallets();
|
|
1963
|
+
const unsubscribe = onEVMWalletsChanged(updateWallets);
|
|
1964
|
+
const timer = setTimeout(updateWallets, 500);
|
|
1965
|
+
return () => {
|
|
1966
|
+
unsubscribe();
|
|
1967
|
+
clearTimeout(timer);
|
|
1968
|
+
};
|
|
1969
|
+
}, [isOpen, networkType]);
|
|
1970
|
+
if (!isOpen || !mounted) return null;
|
|
1971
|
+
const handleOverlayClick = (e) => {
|
|
1972
|
+
if (e.target === e.currentTarget) {
|
|
1973
|
+
onClose();
|
|
1974
|
+
}
|
|
1975
|
+
};
|
|
1976
|
+
const networkName = getNetworkDisplayName(networkType);
|
|
1977
|
+
const modalContent = /* @__PURE__ */ React.createElement("div", { style: overlayStyle, onClick: handleOverlayClick }, /* @__PURE__ */ React.createElement("div", { style: modalStyle }, /* @__PURE__ */ React.createElement("div", { style: headerStyle }, /* @__PURE__ */ React.createElement("h3", { style: titleStyle }, "Select Wallet"), /* @__PURE__ */ React.createElement("button", { style: closeButtonStyle, onClick: onClose }, "\xD7")), /* @__PURE__ */ React.createElement("p", { style: subtitleStyle }, "Connect a ", networkName, " wallet"), wallets.length > 0 ? /* @__PURE__ */ React.createElement("div", { style: walletListStyle }, wallets.map((wallet) => /* @__PURE__ */ React.createElement(
|
|
1978
|
+
WalletItem,
|
|
1979
|
+
{
|
|
1980
|
+
key: wallet.id,
|
|
1981
|
+
wallet,
|
|
1982
|
+
isHovered: hoveredWallet === wallet.id,
|
|
1983
|
+
onSelect: () => onSelect(wallet),
|
|
1984
|
+
onHover: (hovered) => setHoveredWallet(hovered ? wallet.id : null)
|
|
1985
|
+
}
|
|
1986
|
+
))) : /* @__PURE__ */ React.createElement("div", { style: emptyStateStyle }, /* @__PURE__ */ React.createElement("p", { style: emptyTitleStyle }, "No wallets found"), /* @__PURE__ */ React.createElement("p", { style: emptyDescStyle }, "Please install a ", networkName, " wallet extension."))));
|
|
1987
|
+
if (typeof document !== "undefined") {
|
|
1988
|
+
return createPortal(modalContent, document.body);
|
|
1989
|
+
}
|
|
1990
|
+
return modalContent;
|
|
1991
|
+
}
|
|
1419
1992
|
|
|
1420
1993
|
// src/react/styles/inline-styles.ts
|
|
1421
1994
|
var isDarkMode = () => {
|
|
@@ -1532,18 +2105,6 @@ var getDisconnectButtonStyle = (isHovered) => {
|
|
|
1532
2105
|
color: "#ffffff"
|
|
1533
2106
|
};
|
|
1534
2107
|
};
|
|
1535
|
-
var getInstallLinkStyle = (isHovered) => {
|
|
1536
|
-
const c = getColors();
|
|
1537
|
-
return {
|
|
1538
|
-
display: "inline-block",
|
|
1539
|
-
padding: "0.5rem",
|
|
1540
|
-
fontSize: "0.8125rem",
|
|
1541
|
-
color: c.textSecondary,
|
|
1542
|
-
textDecoration: isHovered ? "underline" : "none",
|
|
1543
|
-
textAlign: "center",
|
|
1544
|
-
fontWeight: 500
|
|
1545
|
-
};
|
|
1546
|
-
};
|
|
1547
2108
|
var walletAddressStyle = {
|
|
1548
2109
|
display: "flex",
|
|
1549
2110
|
flexDirection: "column",
|
|
@@ -1601,46 +2162,55 @@ function WalletConnect({
|
|
|
1601
2162
|
supportedNetworks = ["solana" /* SOLANA */, "evm" /* EVM */],
|
|
1602
2163
|
className = "",
|
|
1603
2164
|
onConnect,
|
|
1604
|
-
onDisconnect
|
|
2165
|
+
onDisconnect,
|
|
2166
|
+
showSwitchWallet = true
|
|
1605
2167
|
}) {
|
|
1606
|
-
const { address, networkType, isConnecting, error,
|
|
1607
|
-
const [hoveredButton, setHoveredButton] =
|
|
1608
|
-
const [
|
|
1609
|
-
const
|
|
2168
|
+
const { address, networkType, isConnecting, error, connectWithWallet, disconnect } = useWallet();
|
|
2169
|
+
const [hoveredButton, setHoveredButton] = useState4(null);
|
|
2170
|
+
const [walletSelectOpen, setWalletSelectOpen] = useState4(false);
|
|
2171
|
+
const [selectedNetworkType, setSelectedNetworkType] = useState4(null);
|
|
2172
|
+
const handleOpenWalletSelect = (network) => {
|
|
2173
|
+
setSelectedNetworkType(network);
|
|
2174
|
+
setWalletSelectOpen(true);
|
|
2175
|
+
};
|
|
2176
|
+
const handleWalletSelect = async (wallet) => {
|
|
2177
|
+
setWalletSelectOpen(false);
|
|
1610
2178
|
try {
|
|
1611
|
-
await
|
|
2179
|
+
await connectWithWallet(wallet);
|
|
1612
2180
|
} catch (err) {
|
|
1613
2181
|
}
|
|
1614
2182
|
};
|
|
1615
|
-
const handleDisconnect = () => {
|
|
1616
|
-
disconnect();
|
|
2183
|
+
const handleDisconnect = async () => {
|
|
2184
|
+
await disconnect();
|
|
1617
2185
|
onDisconnect?.();
|
|
1618
2186
|
};
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
2187
|
+
const handleSwitchWallet = () => {
|
|
2188
|
+
if (networkType) {
|
|
2189
|
+
setSelectedNetworkType(networkType);
|
|
2190
|
+
setWalletSelectOpen(true);
|
|
2191
|
+
}
|
|
2192
|
+
};
|
|
2193
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("div", { style: { ...containerStyle, ...className ? {} : {} }, className }, !address ? /* @__PURE__ */ React2.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ React2.createElement("h3", { style: getTitleStyle() }, "Connect Wallet"), supportedNetworks.length === 0 ? /* @__PURE__ */ React2.createElement("p", { style: getHintStyle() }, "Please install a supported wallet extension") : /* @__PURE__ */ React2.createElement("div", { style: buttonsContainerStyle }, supportedNetworks.map((network) => /* @__PURE__ */ React2.createElement("div", { key: network, style: walletOptionStyle }, /* @__PURE__ */ React2.createElement(
|
|
2194
|
+
"button",
|
|
2195
|
+
{
|
|
2196
|
+
style: getConnectButtonStyle(isConnecting, hoveredButton === network),
|
|
2197
|
+
onClick: () => handleOpenWalletSelect(network),
|
|
2198
|
+
disabled: isConnecting,
|
|
2199
|
+
onMouseEnter: () => setHoveredButton(network),
|
|
2200
|
+
onMouseLeave: () => setHoveredButton(null)
|
|
2201
|
+
},
|
|
2202
|
+
isConnecting ? "Connecting..." : getNetworkDisplayName(network)
|
|
2203
|
+
)))), error && /* @__PURE__ */ React2.createElement("p", { style: getErrorStyle() }, error), /* @__PURE__ */ React2.createElement("p", { style: getHintStyle() }, "Select a network to see available wallets")) : /* @__PURE__ */ React2.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ React2.createElement("div", { style: walletAddressStyle }, /* @__PURE__ */ React2.createElement("span", { style: getLabelStyle() }, "Connected ", networkType && `(${getNetworkDisplayName(networkType)})`), /* @__PURE__ */ React2.createElement("span", { style: getAddressStyle() }, formatAddress(address))), /* @__PURE__ */ React2.createElement("div", { style: walletActionsStyle }, showSwitchWallet && /* @__PURE__ */ React2.createElement(
|
|
2204
|
+
"button",
|
|
2205
|
+
{
|
|
2206
|
+
style: getConnectButtonStyle(isConnecting, hoveredButton === "switch"),
|
|
2207
|
+
onClick: handleSwitchWallet,
|
|
2208
|
+
disabled: isConnecting,
|
|
2209
|
+
onMouseEnter: () => setHoveredButton("switch"),
|
|
2210
|
+
onMouseLeave: () => setHoveredButton(null)
|
|
2211
|
+
},
|
|
2212
|
+
isConnecting ? "Switching..." : "Switch Wallet"
|
|
2213
|
+
), /* @__PURE__ */ React2.createElement(
|
|
1644
2214
|
"button",
|
|
1645
2215
|
{
|
|
1646
2216
|
style: getDisconnectButtonStyle(hoveredButton === "disconnect"),
|
|
@@ -1649,11 +2219,19 @@ function WalletConnect({
|
|
|
1649
2219
|
onMouseLeave: () => setHoveredButton(null)
|
|
1650
2220
|
},
|
|
1651
2221
|
"Disconnect"
|
|
1652
|
-
)), /* @__PURE__ */
|
|
2222
|
+
)), /* @__PURE__ */ React2.createElement("p", { style: getHintStyle() }, 'Click "Switch Wallet" to change wallet or account'))), selectedNetworkType && /* @__PURE__ */ React2.createElement(
|
|
2223
|
+
WalletSelectModal,
|
|
2224
|
+
{
|
|
2225
|
+
isOpen: walletSelectOpen,
|
|
2226
|
+
networkType: selectedNetworkType,
|
|
2227
|
+
onSelect: handleWalletSelect,
|
|
2228
|
+
onClose: () => setWalletSelectOpen(false)
|
|
2229
|
+
}
|
|
2230
|
+
));
|
|
1653
2231
|
}
|
|
1654
2232
|
|
|
1655
2233
|
// src/react/components/V402Checkout.tsx
|
|
1656
|
-
import
|
|
2234
|
+
import React4, { useEffect as useEffect4, useState as useState5 } from "react";
|
|
1657
2235
|
import { Button, Card, Divider, message, Spin, Tooltip, Typography } from "antd";
|
|
1658
2236
|
import {
|
|
1659
2237
|
DisconnectOutlined,
|
|
@@ -1666,9 +2244,9 @@ import {
|
|
|
1666
2244
|
init_common();
|
|
1667
2245
|
|
|
1668
2246
|
// src/react/utils/CryptoIcons.tsx
|
|
1669
|
-
import
|
|
2247
|
+
import React3 from "react";
|
|
1670
2248
|
var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
|
|
1671
|
-
return /* @__PURE__ */
|
|
2249
|
+
return /* @__PURE__ */ React3.createElement(
|
|
1672
2250
|
"svg",
|
|
1673
2251
|
{
|
|
1674
2252
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1678,14 +2256,14 @@ var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
|
|
|
1678
2256
|
className,
|
|
1679
2257
|
style
|
|
1680
2258
|
},
|
|
1681
|
-
/* @__PURE__ */
|
|
1682
|
-
/* @__PURE__ */
|
|
2259
|
+
/* @__PURE__ */ React3.createElement("desc", null, "Solana SOL Fill Streamline Icon: https://streamlinehq.com"),
|
|
2260
|
+
/* @__PURE__ */ React3.createElement("g", { fill: "none", fillRule: "evenodd" }, /* @__PURE__ */ React3.createElement(
|
|
1683
2261
|
"path",
|
|
1684
2262
|
{
|
|
1685
2263
|
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",
|
|
1686
2264
|
strokeWidth: "0.6667"
|
|
1687
2265
|
}
|
|
1688
|
-
), /* @__PURE__ */
|
|
2266
|
+
), /* @__PURE__ */ React3.createElement(
|
|
1689
2267
|
"path",
|
|
1690
2268
|
{
|
|
1691
2269
|
fill: "#000000",
|
|
@@ -1696,7 +2274,7 @@ var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
|
|
|
1696
2274
|
);
|
|
1697
2275
|
};
|
|
1698
2276
|
var BaseIcon = ({ width = 24, height = 24, className, style }) => {
|
|
1699
|
-
return /* @__PURE__ */
|
|
2277
|
+
return /* @__PURE__ */ React3.createElement(
|
|
1700
2278
|
"svg",
|
|
1701
2279
|
{
|
|
1702
2280
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1710,8 +2288,8 @@ var BaseIcon = ({ width = 24, height = 24, className, style }) => {
|
|
|
1710
2288
|
className,
|
|
1711
2289
|
style
|
|
1712
2290
|
},
|
|
1713
|
-
/* @__PURE__ */
|
|
1714
|
-
/* @__PURE__ */
|
|
2291
|
+
/* @__PURE__ */ React3.createElement("desc", null, "Brand Coinbase Streamline Icon: https://streamlinehq.com"),
|
|
2292
|
+
/* @__PURE__ */ React3.createElement(
|
|
1715
2293
|
"path",
|
|
1716
2294
|
{
|
|
1717
2295
|
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",
|
|
@@ -1769,14 +2347,14 @@ function V402Checkout({
|
|
|
1769
2347
|
{ autoSwitch: !!targetNetwork, switchOnMount: true }
|
|
1770
2348
|
);
|
|
1771
2349
|
const { isProcessing, setIsProcessing, result, setResult, error, setError } = usePayment();
|
|
1772
|
-
const [paymentDetails, setPaymentDetails] =
|
|
2350
|
+
const [paymentDetails, setPaymentDetails] = useState5(null);
|
|
1773
2351
|
const handleDisconnect = () => {
|
|
1774
2352
|
disconnect();
|
|
1775
2353
|
setResult(null);
|
|
1776
2354
|
setError(null);
|
|
1777
2355
|
notify.info("Wallet Disconnected", "Your wallet has been disconnected successfully.");
|
|
1778
2356
|
};
|
|
1779
|
-
|
|
2357
|
+
useEffect4(() => {
|
|
1780
2358
|
if (paymentInfo && paymentInfo.length > 0) {
|
|
1781
2359
|
const firstPayment = paymentInfo[0];
|
|
1782
2360
|
const rawAmount = firstPayment.maxAmountRequired?.toString() || "0";
|
|
@@ -1791,7 +2369,7 @@ function V402Checkout({
|
|
|
1791
2369
|
});
|
|
1792
2370
|
}
|
|
1793
2371
|
}, [paymentInfo]);
|
|
1794
|
-
|
|
2372
|
+
useEffect4(() => {
|
|
1795
2373
|
if (targetNetwork && !fetchingPaymentInfo && ensureNetwork) {
|
|
1796
2374
|
ensureNetwork(targetNetwork).catch((err) => {
|
|
1797
2375
|
console.error("Failed to ensure network:", err);
|
|
@@ -1831,12 +2409,12 @@ function V402Checkout({
|
|
|
1831
2409
|
const networkColor = paymentDetails ? getNetworkColor(paymentDetails.network) : "#8c8c8c";
|
|
1832
2410
|
const loadingColor = "#8c8c8c";
|
|
1833
2411
|
const hasInvalidCheckoutId = !fetchingPaymentInfo && (!paymentInfo || paymentInfo.length === 0);
|
|
1834
|
-
return /* @__PURE__ */
|
|
2412
|
+
return /* @__PURE__ */ React4.createElement(
|
|
1835
2413
|
"div",
|
|
1836
2414
|
{
|
|
1837
2415
|
className: isModal ? "bg-white" : "h-screen bg-white flex items-center justify-center p-4 overflow-hidden"
|
|
1838
2416
|
},
|
|
1839
|
-
/* @__PURE__ */
|
|
2417
|
+
/* @__PURE__ */ React4.createElement(
|
|
1840
2418
|
"div",
|
|
1841
2419
|
{
|
|
1842
2420
|
className: "flex gap-4 items-center justify-center",
|
|
@@ -1846,7 +2424,7 @@ function V402Checkout({
|
|
|
1846
2424
|
width: "100%"
|
|
1847
2425
|
}
|
|
1848
2426
|
},
|
|
1849
|
-
/* @__PURE__ */
|
|
2427
|
+
/* @__PURE__ */ React4.createElement(
|
|
1850
2428
|
Card,
|
|
1851
2429
|
{
|
|
1852
2430
|
className: "flex-shrink-0",
|
|
@@ -1862,7 +2440,7 @@ function V402Checkout({
|
|
|
1862
2440
|
},
|
|
1863
2441
|
styles: { body: { padding: isModal ? "0px" : "32px 24px" } }
|
|
1864
2442
|
},
|
|
1865
|
-
/* @__PURE__ */
|
|
2443
|
+
/* @__PURE__ */ React4.createElement("div", { className: "flex items-center gap-3 mb-4" }, /* @__PURE__ */ React4.createElement(
|
|
1866
2444
|
"div",
|
|
1867
2445
|
{
|
|
1868
2446
|
className: "w-12 h-12 rounded-xl flex items-center justify-center",
|
|
@@ -1871,22 +2449,22 @@ function V402Checkout({
|
|
|
1871
2449
|
transition: "background 0.3s ease"
|
|
1872
2450
|
}
|
|
1873
2451
|
},
|
|
1874
|
-
hasInvalidCheckoutId ? /* @__PURE__ */
|
|
1875
|
-
), /* @__PURE__ */
|
|
2452
|
+
hasInvalidCheckoutId ? /* @__PURE__ */ React4.createElement("span", { style: { fontSize: "20px", color: "white", fontWeight: "bold" } }, "\u2717") : paymentDetails && NetworkIcon ? /* @__PURE__ */ React4.createElement(NetworkIcon, { width: 24, height: 24 }) : /* @__PURE__ */ React4.createElement(LoadingOutlined, { style: { fontSize: "20px", color: "white" }, spin: true })
|
|
2453
|
+
), /* @__PURE__ */ React4.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React4.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React4.createElement(Title, { level: 4, style: { margin: 0, fontSize: "18px", fontWeight: 600 } }, title || "Echo Payment OnVoyage"), !hasInvalidCheckoutId && /* @__PURE__ */ React4.createElement(
|
|
1876
2454
|
Tooltip,
|
|
1877
2455
|
{
|
|
1878
2456
|
title: tooltipText,
|
|
1879
2457
|
placement: "top"
|
|
1880
2458
|
},
|
|
1881
|
-
/* @__PURE__ */
|
|
2459
|
+
/* @__PURE__ */ React4.createElement(
|
|
1882
2460
|
InfoCircleOutlined,
|
|
1883
2461
|
{
|
|
1884
2462
|
style: { fontSize: "14px", color: "#8c8c8c", cursor: "help" }
|
|
1885
2463
|
}
|
|
1886
2464
|
)
|
|
1887
|
-
)), /* @__PURE__ */
|
|
1888
|
-
/* @__PURE__ */
|
|
1889
|
-
hasInvalidCheckoutId && /* @__PURE__ */
|
|
2465
|
+
)), /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, subtitle))),
|
|
2466
|
+
/* @__PURE__ */ React4.createElement("div", { className: "text-center mb-5" }, /* @__PURE__ */ React4.createElement("div", { className: "inline-flex items-center justify-center w-12 h-12 rounded-full bg-gray-50 mb-3" }, /* @__PURE__ */ React4.createElement(LockOutlined, { style: { fontSize: "20px", color: "#595959" } })), /* @__PURE__ */ React4.createElement(Title, { level: 3, style: { margin: "0 0 6px 0", fontSize: "20px", fontWeight: 600 } }, "Payment Required"), /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Pay ", paymentDetails ? `$${paymentDetails.amount} ${paymentDetails.currency}` : "the required amount", " to access")),
|
|
2467
|
+
hasInvalidCheckoutId && /* @__PURE__ */ React4.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ React4.createElement(
|
|
1890
2468
|
"div",
|
|
1891
2469
|
{
|
|
1892
2470
|
className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
|
|
@@ -1895,15 +2473,15 @@ function V402Checkout({
|
|
|
1895
2473
|
boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
|
|
1896
2474
|
}
|
|
1897
2475
|
},
|
|
1898
|
-
/* @__PURE__ */
|
|
1899
|
-
), /* @__PURE__ */
|
|
2476
|
+
/* @__PURE__ */ React4.createElement("span", { style: { fontSize: "32px", color: "white" } }, "!")
|
|
2477
|
+
), /* @__PURE__ */ React4.createElement(
|
|
1900
2478
|
Title,
|
|
1901
2479
|
{
|
|
1902
2480
|
level: 4,
|
|
1903
2481
|
style: { margin: "0 0 12px 0", fontSize: "18px", fontWeight: 600, color: "#262626" }
|
|
1904
2482
|
},
|
|
1905
2483
|
"Invalid Checkout ID"
|
|
1906
|
-
), /* @__PURE__ */
|
|
2484
|
+
), /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", display: "block", marginBottom: "16px" } }, "The checkout ID you provided is invalid or has expired."), /* @__PURE__ */ React4.createElement(
|
|
1907
2485
|
"div",
|
|
1908
2486
|
{
|
|
1909
2487
|
style: {
|
|
@@ -1914,33 +2492,33 @@ function V402Checkout({
|
|
|
1914
2492
|
marginTop: "16px"
|
|
1915
2493
|
}
|
|
1916
2494
|
},
|
|
1917
|
-
/* @__PURE__ */
|
|
2495
|
+
/* @__PURE__ */ React4.createElement(Text, { style: {
|
|
1918
2496
|
fontSize: "13px",
|
|
1919
2497
|
color: "#dc2626",
|
|
1920
2498
|
lineHeight: "1.6",
|
|
1921
2499
|
fontWeight: 500
|
|
1922
2500
|
} }, "Failed to load payment information. Please check your checkout ID.")
|
|
1923
2501
|
)),
|
|
1924
|
-
!hasInvalidCheckoutId && fetchingPaymentInfo && /* @__PURE__ */
|
|
1925
|
-
!hasInvalidCheckoutId && !fetchingPaymentInfo && !address && /* @__PURE__ */
|
|
1926
|
-
!hasInvalidCheckoutId && address && /* @__PURE__ */
|
|
2502
|
+
!hasInvalidCheckoutId && fetchingPaymentInfo && /* @__PURE__ */ React4.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ React4.createElement(Text, { style: { color: "#8c8c8c" } }, "Loading payment information...")),
|
|
2503
|
+
!hasInvalidCheckoutId && !fetchingPaymentInfo && !address && /* @__PURE__ */ React4.createElement("div", null, /* @__PURE__ */ React4.createElement(WalletConnect, { supportedNetworks })),
|
|
2504
|
+
!hasInvalidCheckoutId && address && /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(
|
|
1927
2505
|
"div",
|
|
1928
2506
|
{
|
|
1929
2507
|
className: "bg-gray-50 rounded-lg p-3 mb-4",
|
|
1930
2508
|
style: { border: "1px solid #f0f0f0" }
|
|
1931
2509
|
},
|
|
1932
|
-
/* @__PURE__ */
|
|
2510
|
+
/* @__PURE__ */ React4.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React4.createElement("div", { className: "flex items-center gap-3 flex-1" }, /* @__PURE__ */ React4.createElement(
|
|
1933
2511
|
"div",
|
|
1934
2512
|
{
|
|
1935
2513
|
className: "w-10 h-10 rounded-full bg-black flex items-center justify-center text-white text-sm font-semibold"
|
|
1936
2514
|
},
|
|
1937
2515
|
address.slice(0, 2).toUpperCase()
|
|
1938
|
-
), /* @__PURE__ */
|
|
2516
|
+
), /* @__PURE__ */ React4.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React4.createElement(Text, { style: {
|
|
1939
2517
|
display: "block",
|
|
1940
2518
|
fontSize: "12px",
|
|
1941
2519
|
color: "#8c8c8c",
|
|
1942
2520
|
marginBottom: "2px"
|
|
1943
|
-
} }, "Connected Wallet"), /* @__PURE__ */
|
|
2521
|
+
} }, "Connected Wallet"), /* @__PURE__ */ React4.createElement(
|
|
1944
2522
|
Text,
|
|
1945
2523
|
{
|
|
1946
2524
|
style: {
|
|
@@ -1950,17 +2528,17 @@ function V402Checkout({
|
|
|
1950
2528
|
}
|
|
1951
2529
|
},
|
|
1952
2530
|
formatAddress(address)
|
|
1953
|
-
))), /* @__PURE__ */
|
|
2531
|
+
))), /* @__PURE__ */ React4.createElement(
|
|
1954
2532
|
Button,
|
|
1955
2533
|
{
|
|
1956
2534
|
type: "text",
|
|
1957
2535
|
size: "small",
|
|
1958
|
-
icon: /* @__PURE__ */
|
|
2536
|
+
icon: /* @__PURE__ */ React4.createElement(DisconnectOutlined, null),
|
|
1959
2537
|
onClick: handleDisconnect,
|
|
1960
2538
|
style: { color: "#ff4d4f" }
|
|
1961
2539
|
}
|
|
1962
2540
|
))
|
|
1963
|
-
), paymentDetails && /* @__PURE__ */
|
|
2541
|
+
), paymentDetails && /* @__PURE__ */ React4.createElement("div", { className: "bg-gray-50 rounded-lg p-3 mb-4", style: { border: "1px solid #f0f0f0" } }, /* @__PURE__ */ React4.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Payment Amount"), /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "18px", fontWeight: 600 } }, "$", paymentDetails.amount)), /* @__PURE__ */ React4.createElement(Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ React4.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Currency"), /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.currency)), /* @__PURE__ */ React4.createElement(Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ React4.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Network"), /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.network)), /* @__PURE__ */ React4.createElement(Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ React4.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Wallet Address"), /* @__PURE__ */ React4.createElement(Text, { style: {
|
|
1964
2542
|
fontSize: "11px",
|
|
1965
2543
|
fontWeight: 500,
|
|
1966
2544
|
fontFamily: "Monaco, monospace",
|
|
@@ -1968,15 +2546,15 @@ function V402Checkout({
|
|
|
1968
2546
|
textAlign: "right",
|
|
1969
2547
|
maxWidth: "60%",
|
|
1970
2548
|
lineHeight: 1.4
|
|
1971
|
-
} }, address))), /* @__PURE__ */
|
|
2549
|
+
} }, address))), /* @__PURE__ */ React4.createElement(
|
|
1972
2550
|
"div",
|
|
1973
2551
|
{
|
|
1974
2552
|
className: "flex items-center justify-center gap-2 mb-3 p-2 rounded-lg",
|
|
1975
2553
|
style: { background: "#f6ffed", border: "1px solid #d9f7be" }
|
|
1976
2554
|
},
|
|
1977
|
-
/* @__PURE__ */
|
|
1978
|
-
/* @__PURE__ */
|
|
1979
|
-
), /* @__PURE__ */
|
|
2555
|
+
/* @__PURE__ */ React4.createElement(SafetyOutlined, { style: { color: "#52c41a", fontSize: "13px" } }),
|
|
2556
|
+
/* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "12px", color: "#52c41a", fontWeight: 500 } }, "Secure payment powered by v402pay")
|
|
2557
|
+
), /* @__PURE__ */ React4.createElement(
|
|
1980
2558
|
Button,
|
|
1981
2559
|
{
|
|
1982
2560
|
type: "primary",
|
|
@@ -1998,7 +2576,7 @@ function V402Checkout({
|
|
|
1998
2576
|
}
|
|
1999
2577
|
},
|
|
2000
2578
|
isProcessing ? "Processing..." : !paymentDetails ? "Loading..." : `Pay $${paymentDetails.amount} ${paymentDetails.currency}`
|
|
2001
|
-
), /* @__PURE__ */
|
|
2579
|
+
), /* @__PURE__ */ React4.createElement("div", { className: "text-center" }, /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Don't have USDC?", " "), /* @__PURE__ */ React4.createElement(
|
|
2002
2580
|
"a",
|
|
2003
2581
|
{
|
|
2004
2582
|
href: "https://faucet.circle.com/",
|
|
@@ -2007,26 +2585,26 @@ function V402Checkout({
|
|
|
2007
2585
|
className: "text-blue-600 hover:text-blue-700 text-sm font-medium inline-flex items-center gap-1"
|
|
2008
2586
|
},
|
|
2009
2587
|
"Get it here ",
|
|
2010
|
-
/* @__PURE__ */
|
|
2011
|
-
)), isModal && result && /* @__PURE__ */
|
|
2588
|
+
/* @__PURE__ */ React4.createElement(LinkOutlined, { style: { fontSize: "12px" } })
|
|
2589
|
+
)), isModal && result && /* @__PURE__ */ React4.createElement(
|
|
2012
2590
|
"div",
|
|
2013
2591
|
{
|
|
2014
2592
|
className: "mt-4 p-4 rounded-lg",
|
|
2015
2593
|
style: { background: "#f6ffed", border: "1px solid #b7eb8f" }
|
|
2016
2594
|
},
|
|
2017
|
-
/* @__PURE__ */
|
|
2595
|
+
/* @__PURE__ */ React4.createElement("div", { className: "text-center" }, /* @__PURE__ */ React4.createElement("span", { style: { fontSize: "20px" } }, "\u2713"), /* @__PURE__ */ React4.createElement(Text, { style: {
|
|
2018
2596
|
fontSize: "14px",
|
|
2019
2597
|
color: "#52c41a",
|
|
2020
2598
|
fontWeight: 600,
|
|
2021
2599
|
marginLeft: "8px"
|
|
2022
2600
|
} }, "Payment Successful!"))
|
|
2023
|
-
), isModal && error && /* @__PURE__ */
|
|
2601
|
+
), isModal && error && /* @__PURE__ */ React4.createElement(
|
|
2024
2602
|
"div",
|
|
2025
2603
|
{
|
|
2026
2604
|
className: "mt-4 p-4 rounded-lg",
|
|
2027
2605
|
style: { background: "#fff2f0", border: "1px solid #ffccc7" }
|
|
2028
2606
|
},
|
|
2029
|
-
/* @__PURE__ */
|
|
2607
|
+
/* @__PURE__ */ React4.createElement("div", { className: "text-center mb-3" }, /* @__PURE__ */ React4.createElement("span", { style: { fontSize: "20px" } }, "\u2717"), /* @__PURE__ */ React4.createElement(Text, { style: {
|
|
2030
2608
|
fontSize: "14px",
|
|
2031
2609
|
color: "#ff4d4f",
|
|
2032
2610
|
fontWeight: 600,
|
|
@@ -2034,7 +2612,7 @@ function V402Checkout({
|
|
|
2034
2612
|
display: "block",
|
|
2035
2613
|
marginTop: "4px"
|
|
2036
2614
|
} }, "Payment Failed")),
|
|
2037
|
-
/* @__PURE__ */
|
|
2615
|
+
/* @__PURE__ */ React4.createElement(Text, { style: {
|
|
2038
2616
|
fontSize: "13px",
|
|
2039
2617
|
color: "#ff4d4f",
|
|
2040
2618
|
display: "block",
|
|
@@ -2042,11 +2620,11 @@ function V402Checkout({
|
|
|
2042
2620
|
} }, error)
|
|
2043
2621
|
))
|
|
2044
2622
|
),
|
|
2045
|
-
!isModal && (isProcessing || result || error) && /* @__PURE__ */
|
|
2623
|
+
!isModal && (isProcessing || result || error) && /* @__PURE__ */ React4.createElement(
|
|
2046
2624
|
Card,
|
|
2047
2625
|
{
|
|
2048
|
-
title: /* @__PURE__ */
|
|
2049
|
-
extra: !isProcessing && /* @__PURE__ */
|
|
2626
|
+
title: /* @__PURE__ */ React4.createElement("div", { className: "flex items-center gap-2" }, isProcessing && !result && !error ? /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(LoadingOutlined, { style: { color: "#14b8a6", fontSize: "16px" } }), /* @__PURE__ */ React4.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Processing Payment")) : result ? /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement("span", { style: { color: "#52c41a", fontSize: "18px" } }, "\u2713"), /* @__PURE__ */ React4.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Successful")) : /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement("span", { style: { color: "#ff4d4f", fontSize: "18px" } }, "\u2717"), /* @__PURE__ */ React4.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Failed"))),
|
|
2627
|
+
extra: !isProcessing && /* @__PURE__ */ React4.createElement(
|
|
2050
2628
|
Button,
|
|
2051
2629
|
{
|
|
2052
2630
|
type: "text",
|
|
@@ -2074,7 +2652,7 @@ function V402Checkout({
|
|
|
2074
2652
|
}
|
|
2075
2653
|
}
|
|
2076
2654
|
},
|
|
2077
|
-
isProcessing && !result && !error && /* @__PURE__ */
|
|
2655
|
+
isProcessing && !result && !error && /* @__PURE__ */ React4.createElement("div", { className: "text-center py-10" }, /* @__PURE__ */ React4.createElement("div", { className: "relative inline-block" }, /* @__PURE__ */ React4.createElement(
|
|
2078
2656
|
"div",
|
|
2079
2657
|
{
|
|
2080
2658
|
className: "absolute inset-0 rounded-full blur-xl opacity-40",
|
|
@@ -2083,12 +2661,12 @@ function V402Checkout({
|
|
|
2083
2661
|
animation: "pulse 2s ease-in-out infinite"
|
|
2084
2662
|
}
|
|
2085
2663
|
}
|
|
2086
|
-
), /* @__PURE__ */
|
|
2664
|
+
), /* @__PURE__ */ React4.createElement(
|
|
2087
2665
|
Spin,
|
|
2088
2666
|
{
|
|
2089
|
-
indicator: /* @__PURE__ */
|
|
2667
|
+
indicator: /* @__PURE__ */ React4.createElement(LoadingOutlined, { style: { fontSize: 56, color: "#14b8a6" } })
|
|
2090
2668
|
}
|
|
2091
|
-
)), /* @__PURE__ */
|
|
2669
|
+
)), /* @__PURE__ */ React4.createElement("div", { className: "mt-6" }, /* @__PURE__ */ React4.createElement(Text, { strong: true, style: { fontSize: "18px", color: "#262626", letterSpacing: "-0.02em" } }, "Verifying Payment")), /* @__PURE__ */ React4.createElement("div", { className: "mt-2 mb-6" }, /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", lineHeight: "1.6" } }, "Please wait while we confirm your transaction")), /* @__PURE__ */ React4.createElement(
|
|
2092
2670
|
"div",
|
|
2093
2671
|
{
|
|
2094
2672
|
className: "mt-4 p-4 rounded-xl",
|
|
@@ -2097,9 +2675,9 @@ function V402Checkout({
|
|
|
2097
2675
|
border: "1px solid #ccfbf1"
|
|
2098
2676
|
}
|
|
2099
2677
|
},
|
|
2100
|
-
/* @__PURE__ */
|
|
2678
|
+
/* @__PURE__ */ React4.createElement("div", { className: "flex items-center justify-center gap-2" }, /* @__PURE__ */ React4.createElement("span", { style: { fontSize: "16px" } }, "\u23F1\uFE0F"), /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "13px", color: "#0f766e", fontWeight: 500 } }, "This may take a few moments"))
|
|
2101
2679
|
)),
|
|
2102
|
-
result && /* @__PURE__ */
|
|
2680
|
+
result && /* @__PURE__ */ React4.createElement("div", null, /* @__PURE__ */ React4.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ React4.createElement(
|
|
2103
2681
|
"div",
|
|
2104
2682
|
{
|
|
2105
2683
|
className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
|
|
@@ -2108,13 +2686,13 @@ function V402Checkout({
|
|
|
2108
2686
|
boxShadow: "0 4px 20px rgba(16, 185, 129, 0.3)"
|
|
2109
2687
|
}
|
|
2110
2688
|
},
|
|
2111
|
-
/* @__PURE__ */
|
|
2112
|
-
), /* @__PURE__ */
|
|
2689
|
+
/* @__PURE__ */ React4.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2713")
|
|
2690
|
+
), /* @__PURE__ */ React4.createElement("div", null, /* @__PURE__ */ React4.createElement(Text, { strong: true, style: {
|
|
2113
2691
|
fontSize: "20px",
|
|
2114
2692
|
color: "#262626",
|
|
2115
2693
|
display: "block",
|
|
2116
2694
|
marginBottom: "8px"
|
|
2117
|
-
} }, "Payment Successful!"), /* @__PURE__ */
|
|
2695
|
+
} }, "Payment Successful!"), /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Your transaction has been confirmed"))), /* @__PURE__ */ React4.createElement(Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "RESPONSE DATA")), /* @__PURE__ */ React4.createElement(
|
|
2118
2696
|
"pre",
|
|
2119
2697
|
{
|
|
2120
2698
|
style: {
|
|
@@ -2134,7 +2712,7 @@ function V402Checkout({
|
|
|
2134
2712
|
},
|
|
2135
2713
|
JSON.stringify(result, null, 2)
|
|
2136
2714
|
)),
|
|
2137
|
-
error && /* @__PURE__ */
|
|
2715
|
+
error && /* @__PURE__ */ React4.createElement("div", null, /* @__PURE__ */ React4.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ React4.createElement(
|
|
2138
2716
|
"div",
|
|
2139
2717
|
{
|
|
2140
2718
|
className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
|
|
@@ -2143,13 +2721,13 @@ function V402Checkout({
|
|
|
2143
2721
|
boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
|
|
2144
2722
|
}
|
|
2145
2723
|
},
|
|
2146
|
-
/* @__PURE__ */
|
|
2147
|
-
), /* @__PURE__ */
|
|
2724
|
+
/* @__PURE__ */ React4.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2717")
|
|
2725
|
+
), /* @__PURE__ */ React4.createElement("div", null, /* @__PURE__ */ React4.createElement(Text, { strong: true, style: {
|
|
2148
2726
|
fontSize: "20px",
|
|
2149
2727
|
color: "#262626",
|
|
2150
2728
|
display: "block",
|
|
2151
2729
|
marginBottom: "8px"
|
|
2152
|
-
} }, "Payment Failed"), /* @__PURE__ */
|
|
2730
|
+
} }, "Payment Failed"), /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Something went wrong with your transaction"))), /* @__PURE__ */ React4.createElement(Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ React4.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "ERROR DETAILS")), /* @__PURE__ */ React4.createElement(
|
|
2153
2731
|
"div",
|
|
2154
2732
|
{
|
|
2155
2733
|
style: {
|
|
@@ -2159,13 +2737,13 @@ function V402Checkout({
|
|
|
2159
2737
|
border: "1px solid #fee2e2"
|
|
2160
2738
|
}
|
|
2161
2739
|
},
|
|
2162
|
-
/* @__PURE__ */
|
|
2740
|
+
/* @__PURE__ */ React4.createElement(Text, { style: {
|
|
2163
2741
|
fontSize: "14px",
|
|
2164
2742
|
color: "#dc2626",
|
|
2165
2743
|
lineHeight: "1.6",
|
|
2166
2744
|
fontWeight: 500
|
|
2167
2745
|
} }, error)
|
|
2168
|
-
), /* @__PURE__ */
|
|
2746
|
+
), /* @__PURE__ */ React4.createElement("div", { className: "mt-4 text-center" }, /* @__PURE__ */ React4.createElement(
|
|
2169
2747
|
Button,
|
|
2170
2748
|
{
|
|
2171
2749
|
size: "large",
|
|
@@ -2186,7 +2764,7 @@ function V402Checkout({
|
|
|
2186
2764
|
)))
|
|
2187
2765
|
)
|
|
2188
2766
|
),
|
|
2189
|
-
/* @__PURE__ */
|
|
2767
|
+
/* @__PURE__ */ React4.createElement("style", { dangerouslySetInnerHTML: {
|
|
2190
2768
|
__html: `
|
|
2191
2769
|
@keyframes slideInRight {
|
|
2192
2770
|
from {
|
|
@@ -2216,6 +2794,7 @@ function V402Checkout({
|
|
|
2216
2794
|
export {
|
|
2217
2795
|
V402Checkout,
|
|
2218
2796
|
WalletConnect,
|
|
2797
|
+
WalletSelectModal,
|
|
2219
2798
|
usePageNetwork,
|
|
2220
2799
|
usePayment,
|
|
2221
2800
|
usePaymentInfo,
|