@voyage_ai/v402-web-ts 0.1.1 → 0.1.3
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/dist/index.d.mts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +156 -106
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +139 -88
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +62 -52
- package/dist/react/index.d.ts +62 -52
- package/dist/react/index.js +901 -227
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +884 -203
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/styles.css +1 -168
- package/package.json +33 -10
- package/dist/react/components/PaymentButton.tsx +0 -119
- package/dist/react/components/WalletConnect.tsx +0 -152
- package/dist/react/hooks/usePayment.ts +0 -109
- package/dist/react/hooks/usePaymentInfo.ts +0 -94
- package/dist/react/hooks/useWallet.ts +0 -174
- package/dist/react/hooks/useWalletStore.ts +0 -61
- package/dist/react/index.ts +0 -42
- package/dist/react/store/walletStore.ts +0 -181
- package/dist/react/styles/inline-styles.ts +0 -227
package/dist/react/index.js
CHANGED
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,64 +30,75 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
30
|
-
// src/react/index.ts
|
|
31
|
-
var index_exports = {};
|
|
32
|
-
__export(index_exports, {
|
|
33
|
-
PaymentButton: () => PaymentButton,
|
|
34
|
-
WalletConnect: () => WalletConnect,
|
|
35
|
-
usePayment: () => usePayment,
|
|
36
|
-
usePaymentInfo: () => usePaymentInfo,
|
|
37
|
-
useWallet: () => useWallet
|
|
38
|
-
});
|
|
39
|
-
module.exports = __toCommonJS(index_exports);
|
|
40
|
-
|
|
41
|
-
// src/react/hooks/useWalletStore.ts
|
|
42
|
-
var import_react = require("react");
|
|
43
|
-
|
|
44
|
-
// src/types/index.ts
|
|
45
|
-
var import_types3 = require("x402/types");
|
|
46
|
-
|
|
47
33
|
// src/types/common.ts
|
|
48
|
-
var PROD_BACK_URL
|
|
34
|
+
var PROD_BACK_URL, DEV_BACK_URL;
|
|
35
|
+
var init_common = __esm({
|
|
36
|
+
"src/types/common.ts"() {
|
|
37
|
+
"use strict";
|
|
38
|
+
PROD_BACK_URL = "https://v402.onvoyage.ai/api/pay";
|
|
39
|
+
DEV_BACK_URL = "http://localhost:3000/api/pay";
|
|
40
|
+
}
|
|
41
|
+
});
|
|
49
42
|
|
|
50
43
|
// src/types/svm.ts
|
|
51
|
-
var import_zod
|
|
52
|
-
var
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
44
|
+
var import_zod, import_types, SolanaNetworkSchema, SolanaPaymentPayloadSchema;
|
|
45
|
+
var init_svm = __esm({
|
|
46
|
+
"src/types/svm.ts"() {
|
|
47
|
+
"use strict";
|
|
48
|
+
import_zod = require("zod");
|
|
49
|
+
import_types = require("x402/types");
|
|
50
|
+
SolanaNetworkSchema = import_zod.z.enum([
|
|
51
|
+
"solana-devnet",
|
|
52
|
+
"solana",
|
|
53
|
+
"solana-mainnet"
|
|
54
|
+
// Alias for mainnet
|
|
55
|
+
]);
|
|
56
|
+
SolanaPaymentPayloadSchema = import_zod.z.object({
|
|
57
|
+
x402Version: import_zod.z.literal(1),
|
|
58
|
+
scheme: import_zod.z.literal("exact"),
|
|
59
|
+
network: SolanaNetworkSchema,
|
|
60
|
+
payload: import_types.ExactSvmPayloadSchema
|
|
61
|
+
});
|
|
62
|
+
}
|
|
64
63
|
});
|
|
65
64
|
|
|
66
65
|
// src/types/evm.ts
|
|
67
|
-
var import_zod2
|
|
68
|
-
var
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
66
|
+
var import_zod2, import_types2, EvmNetworkSchema, EvmPaymentPayloadSchema;
|
|
67
|
+
var init_evm = __esm({
|
|
68
|
+
"src/types/evm.ts"() {
|
|
69
|
+
"use strict";
|
|
70
|
+
import_zod2 = require("zod");
|
|
71
|
+
import_types2 = require("x402/types");
|
|
72
|
+
EvmNetworkSchema = import_zod2.z.enum([
|
|
73
|
+
"ethereum",
|
|
74
|
+
"sepolia",
|
|
75
|
+
"base",
|
|
76
|
+
"base-sepolia",
|
|
77
|
+
"polygon",
|
|
78
|
+
"arbitrum",
|
|
79
|
+
"optimism"
|
|
80
|
+
]);
|
|
81
|
+
EvmPaymentPayloadSchema = import_zod2.z.object({
|
|
82
|
+
x402Version: import_zod2.z.literal(1),
|
|
83
|
+
scheme: import_zod2.z.literal("exact"),
|
|
84
|
+
network: EvmNetworkSchema,
|
|
85
|
+
payload: import_types2.ExactEvmPayloadSchema
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// src/types/index.ts
|
|
91
|
+
var import_types3;
|
|
92
|
+
var init_types = __esm({
|
|
93
|
+
"src/types/index.ts"() {
|
|
94
|
+
"use strict";
|
|
95
|
+
import_types3 = require("x402/types");
|
|
96
|
+
init_svm();
|
|
97
|
+
init_evm();
|
|
98
|
+
}
|
|
83
99
|
});
|
|
84
100
|
|
|
85
101
|
// src/utils/wallet.ts
|
|
86
|
-
var WALLET_DISCONNECTED_KEY = "wallet_manually_disconnected";
|
|
87
|
-
var CONNECTED_NETWORK_TYPE_KEY = "connected_network_type";
|
|
88
102
|
function isWalletInstalled(networkType) {
|
|
89
103
|
if (typeof window === "undefined") {
|
|
90
104
|
return false;
|
|
@@ -105,22 +119,50 @@ function formatAddress(address) {
|
|
|
105
119
|
}
|
|
106
120
|
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
|
107
121
|
}
|
|
108
|
-
function
|
|
122
|
+
function getDisconnectedNetworks() {
|
|
123
|
+
if (typeof window === "undefined") {
|
|
124
|
+
return {};
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
const cached = localStorage.getItem(WALLET_DISCONNECTED_NETWORKS_KEY);
|
|
128
|
+
return cached ? JSON.parse(cached) : {};
|
|
129
|
+
} catch (error) {
|
|
130
|
+
return {};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function markWalletDisconnected(networkType) {
|
|
109
134
|
if (typeof window !== "undefined") {
|
|
110
|
-
|
|
111
|
-
|
|
135
|
+
if (networkType) {
|
|
136
|
+
const disconnected = getDisconnectedNetworks();
|
|
137
|
+
disconnected[networkType] = true;
|
|
138
|
+
localStorage.setItem(WALLET_DISCONNECTED_NETWORKS_KEY, JSON.stringify(disconnected));
|
|
139
|
+
} else {
|
|
140
|
+
localStorage.setItem(WALLET_DISCONNECTED_KEY, "true");
|
|
141
|
+
localStorage.removeItem(CONNECTED_NETWORK_TYPE_KEY);
|
|
142
|
+
}
|
|
112
143
|
}
|
|
113
144
|
}
|
|
114
|
-
function clearWalletDisconnection() {
|
|
145
|
+
function clearWalletDisconnection(networkType) {
|
|
115
146
|
if (typeof window !== "undefined") {
|
|
116
|
-
|
|
147
|
+
if (networkType) {
|
|
148
|
+
const disconnected = getDisconnectedNetworks();
|
|
149
|
+
delete disconnected[networkType];
|
|
150
|
+
localStorage.setItem(WALLET_DISCONNECTED_NETWORKS_KEY, JSON.stringify(disconnected));
|
|
151
|
+
} else {
|
|
152
|
+
localStorage.removeItem(WALLET_DISCONNECTED_KEY);
|
|
153
|
+
}
|
|
117
154
|
}
|
|
118
155
|
}
|
|
119
|
-
function isWalletManuallyDisconnected() {
|
|
156
|
+
function isWalletManuallyDisconnected(networkType) {
|
|
120
157
|
if (typeof window === "undefined") {
|
|
121
158
|
return false;
|
|
122
159
|
}
|
|
123
|
-
|
|
160
|
+
if (networkType) {
|
|
161
|
+
const disconnected = getDisconnectedNetworks();
|
|
162
|
+
return disconnected[networkType] === true;
|
|
163
|
+
} else {
|
|
164
|
+
return localStorage.getItem(WALLET_DISCONNECTED_KEY) === "true";
|
|
165
|
+
}
|
|
124
166
|
}
|
|
125
167
|
function saveConnectedNetworkType(networkType) {
|
|
126
168
|
if (typeof window !== "undefined") {
|
|
@@ -145,8 +187,70 @@ function getWalletInstallUrl(networkType) {
|
|
|
145
187
|
return "#";
|
|
146
188
|
}
|
|
147
189
|
}
|
|
190
|
+
function getAllWalletAddresses() {
|
|
191
|
+
if (typeof window === "undefined") {
|
|
192
|
+
return {};
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
const cached = localStorage.getItem(WALLET_ADDRESSES_KEY);
|
|
196
|
+
return cached ? JSON.parse(cached) : {};
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.error("Failed to parse wallet addresses cache:", error);
|
|
199
|
+
return {};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function saveWalletAddress(networkType, address) {
|
|
203
|
+
if (typeof window === "undefined") {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const addresses = getAllWalletAddresses();
|
|
207
|
+
addresses[networkType] = address;
|
|
208
|
+
localStorage.setItem(WALLET_ADDRESSES_KEY, JSON.stringify(addresses));
|
|
209
|
+
}
|
|
210
|
+
function getCachedWalletAddress(networkType) {
|
|
211
|
+
const addresses = getAllWalletAddresses();
|
|
212
|
+
return addresses[networkType] || null;
|
|
213
|
+
}
|
|
214
|
+
function removeWalletAddress(networkType) {
|
|
215
|
+
if (typeof window === "undefined") {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const addresses = getAllWalletAddresses();
|
|
219
|
+
delete addresses[networkType];
|
|
220
|
+
localStorage.setItem(WALLET_ADDRESSES_KEY, JSON.stringify(addresses));
|
|
221
|
+
}
|
|
222
|
+
var WALLET_DISCONNECTED_KEY, WALLET_DISCONNECTED_NETWORKS_KEY, CONNECTED_NETWORK_TYPE_KEY, WALLET_ADDRESSES_KEY;
|
|
223
|
+
var init_wallet = __esm({
|
|
224
|
+
"src/utils/wallet.ts"() {
|
|
225
|
+
"use strict";
|
|
226
|
+
WALLET_DISCONNECTED_KEY = "wallet_manually_disconnected";
|
|
227
|
+
WALLET_DISCONNECTED_NETWORKS_KEY = "wallet_disconnected_networks";
|
|
228
|
+
CONNECTED_NETWORK_TYPE_KEY = "connected_network_type";
|
|
229
|
+
WALLET_ADDRESSES_KEY = "wallet_addresses_cache";
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// src/react/index.ts
|
|
234
|
+
var index_exports = {};
|
|
235
|
+
__export(index_exports, {
|
|
236
|
+
V402Checkout: () => V402Checkout,
|
|
237
|
+
WalletConnect: () => WalletConnect,
|
|
238
|
+
usePageNetwork: () => usePageNetwork,
|
|
239
|
+
usePayment: () => usePayment,
|
|
240
|
+
usePaymentInfo: () => usePaymentInfo,
|
|
241
|
+
useWallet: () => useWallet
|
|
242
|
+
});
|
|
243
|
+
module.exports = __toCommonJS(index_exports);
|
|
244
|
+
var import_styles = require("./styles.css");
|
|
245
|
+
|
|
246
|
+
// src/react/hooks/useWalletStore.ts
|
|
247
|
+
var import_react = require("react");
|
|
248
|
+
|
|
249
|
+
// src/utils/index.ts
|
|
250
|
+
init_wallet();
|
|
148
251
|
|
|
149
252
|
// src/utils/wallet-connect.ts
|
|
253
|
+
init_wallet();
|
|
150
254
|
async function connectWallet(networkType) {
|
|
151
255
|
if (typeof window === "undefined") {
|
|
152
256
|
throw new Error("\u8BF7\u5728\u6D4F\u89C8\u5668\u73AF\u5883\u4E2D\u4F7F\u7528");
|
|
@@ -181,13 +285,11 @@ async function connectWallet(networkType) {
|
|
|
181
285
|
default:
|
|
182
286
|
throw new Error("\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B");
|
|
183
287
|
}
|
|
184
|
-
clearWalletDisconnection();
|
|
288
|
+
clearWalletDisconnection(networkType);
|
|
185
289
|
saveConnectedNetworkType(networkType);
|
|
290
|
+
saveWalletAddress(networkType, address);
|
|
186
291
|
return address;
|
|
187
292
|
}
|
|
188
|
-
function disconnectWallet() {
|
|
189
|
-
markWalletDisconnected();
|
|
190
|
-
}
|
|
191
293
|
async function getCurrentWallet(networkType) {
|
|
192
294
|
if (typeof window === "undefined") {
|
|
193
295
|
return null;
|
|
@@ -196,28 +298,36 @@ async function getCurrentWallet(networkType) {
|
|
|
196
298
|
if (!type) {
|
|
197
299
|
return null;
|
|
198
300
|
}
|
|
301
|
+
const cachedAddress = getCachedWalletAddress(type);
|
|
199
302
|
try {
|
|
303
|
+
let currentAddress = null;
|
|
200
304
|
switch (type) {
|
|
201
305
|
case "evm" /* EVM */: {
|
|
202
|
-
if (!window.ethereum) return
|
|
306
|
+
if (!window.ethereum) return cachedAddress;
|
|
203
307
|
const accounts = await window.ethereum.request({
|
|
204
308
|
method: "eth_accounts",
|
|
205
309
|
params: []
|
|
206
310
|
});
|
|
207
|
-
|
|
311
|
+
currentAddress = accounts && accounts.length > 0 ? accounts[0] : null;
|
|
312
|
+
break;
|
|
208
313
|
}
|
|
209
314
|
case "solana" /* SOLANA */:
|
|
210
315
|
case "svm" /* SVM */: {
|
|
211
316
|
const solana = window.solana;
|
|
212
|
-
if (!solana || !solana.isConnected) return
|
|
213
|
-
|
|
317
|
+
if (!solana || !solana.isConnected) return cachedAddress;
|
|
318
|
+
currentAddress = solana.publicKey?.toString() || null;
|
|
319
|
+
break;
|
|
214
320
|
}
|
|
215
321
|
default:
|
|
216
|
-
return
|
|
322
|
+
return cachedAddress;
|
|
217
323
|
}
|
|
324
|
+
if (currentAddress && currentAddress !== cachedAddress) {
|
|
325
|
+
saveWalletAddress(type, currentAddress);
|
|
326
|
+
}
|
|
327
|
+
return currentAddress || cachedAddress;
|
|
218
328
|
} catch (error) {
|
|
219
329
|
console.error("Failed to get current wallet:", error);
|
|
220
|
-
return
|
|
330
|
+
return cachedAddress;
|
|
221
331
|
}
|
|
222
332
|
}
|
|
223
333
|
function onAccountsChanged(callback) {
|
|
@@ -268,6 +378,18 @@ function onWalletDisconnect(callback) {
|
|
|
268
378
|
solana.removeListener?.("disconnect", handler);
|
|
269
379
|
};
|
|
270
380
|
}
|
|
381
|
+
async function switchNetwork(networkType) {
|
|
382
|
+
const cachedAddress = getCachedWalletAddress(networkType);
|
|
383
|
+
if (cachedAddress) {
|
|
384
|
+
saveConnectedNetworkType(networkType);
|
|
385
|
+
clearWalletDisconnection(networkType);
|
|
386
|
+
const currentAddress = await getCurrentWallet(networkType);
|
|
387
|
+
if (currentAddress) {
|
|
388
|
+
return currentAddress;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
271
393
|
|
|
272
394
|
// src/services/svm/payment-header.ts
|
|
273
395
|
var import_web3 = require("@solana/web3.js");
|
|
@@ -347,12 +469,12 @@ async function createSvmPaymentHeader(params) {
|
|
|
347
469
|
)
|
|
348
470
|
);
|
|
349
471
|
const { blockhash } = await connection.getLatestBlockhash("confirmed");
|
|
350
|
-
const
|
|
472
|
+
const message2 = new import_web3.TransactionMessage({
|
|
351
473
|
payerKey: feePayerPubkey,
|
|
352
474
|
recentBlockhash: blockhash,
|
|
353
475
|
instructions
|
|
354
476
|
}).compileToV0Message();
|
|
355
|
-
const transaction = new import_web3.VersionedTransaction(
|
|
477
|
+
const transaction = new import_web3.VersionedTransaction(message2);
|
|
356
478
|
if (typeof wallet?.signTransaction !== "function") {
|
|
357
479
|
throw new Error("Connected wallet does not support signTransaction");
|
|
358
480
|
}
|
|
@@ -387,6 +509,7 @@ function getDefaultSolanaRpcUrl(network) {
|
|
|
387
509
|
}
|
|
388
510
|
|
|
389
511
|
// src/services/svm/payment-handler.ts
|
|
512
|
+
init_types();
|
|
390
513
|
async function handleSvmPayment(endpoint, config, requestInit) {
|
|
391
514
|
const { wallet, network, rpcUrl, maxPaymentAmount } = config;
|
|
392
515
|
const initialResponse = await fetch(endpoint, {
|
|
@@ -411,7 +534,8 @@ async function handleSvmPayment(endpoint, config, requestInit) {
|
|
|
411
534
|
"already_used": "This payment has already been used",
|
|
412
535
|
"network_mismatch": "Payment network does not match",
|
|
413
536
|
"invalid_payment": "Invalid payment data",
|
|
414
|
-
"verification_failed": "Payment verification failed"
|
|
537
|
+
"verification_failed": "Payment verification failed",
|
|
538
|
+
"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."
|
|
415
539
|
};
|
|
416
540
|
const errorMessage = ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
|
|
417
541
|
const error = new Error(errorMessage);
|
|
@@ -479,7 +603,8 @@ async function handleSvmPayment(endpoint, config, requestInit) {
|
|
|
479
603
|
"already_used": "This payment has already been used",
|
|
480
604
|
"network_mismatch": "Payment network does not match",
|
|
481
605
|
"invalid_payment": "Invalid payment data",
|
|
482
|
-
"verification_failed": "Payment verification failed"
|
|
606
|
+
"verification_failed": "Payment verification failed",
|
|
607
|
+
"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."
|
|
483
608
|
};
|
|
484
609
|
const errorMessage = ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
|
|
485
610
|
const error = new Error(errorMessage);
|
|
@@ -609,6 +734,7 @@ function getChainIdFromNetwork(network) {
|
|
|
609
734
|
}
|
|
610
735
|
|
|
611
736
|
// src/services/evm/payment-handler.ts
|
|
737
|
+
init_types();
|
|
612
738
|
async function handleEvmPayment(endpoint, config, requestInit) {
|
|
613
739
|
const { wallet, network, maxPaymentAmount } = config;
|
|
614
740
|
const initialResponse = await fetch(endpoint, {
|
|
@@ -779,6 +905,7 @@ async function handleEvmPayment(endpoint, config, requestInit) {
|
|
|
779
905
|
|
|
780
906
|
// src/utils/payment-helpers.ts
|
|
781
907
|
var import_ethers2 = require("ethers");
|
|
908
|
+
init_common();
|
|
782
909
|
function parsePaymentRequired(response) {
|
|
783
910
|
if (response && typeof response === "object") {
|
|
784
911
|
if ("x402Version" in response && "accepts" in response) {
|
|
@@ -802,9 +929,15 @@ function getSupportedNetworkTypes(paymentRequirements) {
|
|
|
802
929
|
});
|
|
803
930
|
return Array.from(networkTypes);
|
|
804
931
|
}
|
|
805
|
-
async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL) {
|
|
806
|
-
|
|
932
|
+
async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, additionalParams) {
|
|
933
|
+
const fullEndpoint = `${endpoint}/${merchantId}`;
|
|
807
934
|
let response;
|
|
935
|
+
const requestInit = additionalParams && Object.keys(additionalParams).length > 0 ? {
|
|
936
|
+
body: JSON.stringify(additionalParams),
|
|
937
|
+
headers: {
|
|
938
|
+
"Content-Type": "application/json"
|
|
939
|
+
}
|
|
940
|
+
} : {};
|
|
808
941
|
if (networkType === "solana" /* SOLANA */ || networkType === "svm" /* SVM */) {
|
|
809
942
|
const solana = window.solana;
|
|
810
943
|
if (!solana) {
|
|
@@ -813,11 +946,11 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL) {
|
|
|
813
946
|
if (!solana.isConnected) {
|
|
814
947
|
await solana.connect();
|
|
815
948
|
}
|
|
816
|
-
response = await handleSvmPayment(
|
|
949
|
+
response = await handleSvmPayment(fullEndpoint, {
|
|
817
950
|
wallet: solana,
|
|
818
951
|
network: "solana"
|
|
819
952
|
// Will use backend's network configuration
|
|
820
|
-
});
|
|
953
|
+
}, requestInit);
|
|
821
954
|
} else if (networkType === "evm" /* EVM */) {
|
|
822
955
|
if (!window.ethereum) {
|
|
823
956
|
throw new Error("\u8BF7\u5B89\u88C5 MetaMask \u94B1\u5305");
|
|
@@ -826,8 +959,8 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL) {
|
|
|
826
959
|
const signer = await provider.getSigner();
|
|
827
960
|
const wallet = {
|
|
828
961
|
address: await signer.getAddress(),
|
|
829
|
-
signTypedData: async (domain, types,
|
|
830
|
-
return await signer.signTypedData(domain, types,
|
|
962
|
+
signTypedData: async (domain, types, message2) => {
|
|
963
|
+
return await signer.signTypedData(domain, types, message2);
|
|
831
964
|
},
|
|
832
965
|
// Get current chain ID from wallet
|
|
833
966
|
getChainId: async () => {
|
|
@@ -842,35 +975,16 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL) {
|
|
|
842
975
|
});
|
|
843
976
|
}
|
|
844
977
|
};
|
|
845
|
-
response = await handleEvmPayment(
|
|
978
|
+
response = await handleEvmPayment(fullEndpoint, {
|
|
846
979
|
wallet,
|
|
847
980
|
network: "base"
|
|
848
981
|
// Will use backend's network configuration
|
|
849
|
-
});
|
|
982
|
+
}, requestInit);
|
|
850
983
|
} else {
|
|
851
984
|
throw new Error(`\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B: ${networkType}`);
|
|
852
985
|
}
|
|
853
986
|
return response;
|
|
854
987
|
}
|
|
855
|
-
async function handlePayment(endpoint, networkType, callbacks) {
|
|
856
|
-
try {
|
|
857
|
-
callbacks?.onStart?.();
|
|
858
|
-
const response = await makePayment(networkType, "", endpoint);
|
|
859
|
-
if (!response.ok) {
|
|
860
|
-
const errorText = await response.text();
|
|
861
|
-
throw new Error(`\u8BF7\u6C42\u5931\u8D25 (${response.status}): ${errorText}`);
|
|
862
|
-
}
|
|
863
|
-
const result = await response.json();
|
|
864
|
-
callbacks?.onSuccess?.(result);
|
|
865
|
-
return result;
|
|
866
|
-
} catch (err) {
|
|
867
|
-
const errorMessage = err.message || "\u652F\u4ED8\u5931\u8D25";
|
|
868
|
-
callbacks?.onError?.(errorMessage);
|
|
869
|
-
throw err;
|
|
870
|
-
} finally {
|
|
871
|
-
callbacks?.onFinish?.();
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
988
|
|
|
875
989
|
// src/utils/network.ts
|
|
876
990
|
var NETWORK_TYPE_MAP = {
|
|
@@ -894,6 +1008,7 @@ var NETWORK_TYPE_MAP = {
|
|
|
894
1008
|
};
|
|
895
1009
|
function getNetworkDisplayName(network) {
|
|
896
1010
|
const displayNames = {
|
|
1011
|
+
"evm": "EVM",
|
|
897
1012
|
"ethereum": "Ethereum",
|
|
898
1013
|
"sepolia": "Sepolia Testnet",
|
|
899
1014
|
"base": "Base",
|
|
@@ -1056,60 +1171,28 @@ var WalletStore = class {
|
|
|
1056
1171
|
init() {
|
|
1057
1172
|
if (this.initialized) return;
|
|
1058
1173
|
this.initialized = true;
|
|
1059
|
-
this.autoReconnect();
|
|
1060
1174
|
onAccountsChanged((accounts) => {
|
|
1061
|
-
|
|
1062
|
-
if (connectedType === "evm" /* EVM */) {
|
|
1175
|
+
if (this.state.networkType === "evm" /* EVM */) {
|
|
1063
1176
|
if (accounts.length === 0) {
|
|
1064
1177
|
this.setState({ address: null });
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
this.setState({ address: accounts[0] });
|
|
1069
|
-
console.log("\u{1F504} Account changed:", accounts[0]);
|
|
1070
|
-
}
|
|
1178
|
+
} else if (!isWalletManuallyDisconnected("evm" /* EVM */)) {
|
|
1179
|
+
this.setState({ address: accounts[0] });
|
|
1180
|
+
saveWalletAddress("evm" /* EVM */, accounts[0]);
|
|
1071
1181
|
}
|
|
1072
1182
|
}
|
|
1073
1183
|
});
|
|
1074
1184
|
onChainChanged(() => {
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
console.log("\u26A0\uFE0F Network changed detected - disconnecting wallet");
|
|
1078
|
-
disconnectWallet();
|
|
1079
|
-
this.setState({
|
|
1080
|
-
address: null,
|
|
1081
|
-
networkType: null,
|
|
1082
|
-
error: "Network changed. Please reconnect your wallet."
|
|
1083
|
-
});
|
|
1185
|
+
if (this.state.networkType === "evm" /* EVM */) {
|
|
1186
|
+
this.handleDisconnect("evm" /* EVM */, "Chain changed. Please reconnect your wallet.");
|
|
1084
1187
|
}
|
|
1085
1188
|
});
|
|
1086
1189
|
onWalletDisconnect(() => {
|
|
1087
|
-
const
|
|
1088
|
-
if (
|
|
1089
|
-
|
|
1090
|
-
disconnectWallet();
|
|
1091
|
-
this.setState({
|
|
1092
|
-
address: null,
|
|
1093
|
-
networkType: null
|
|
1094
|
-
});
|
|
1190
|
+
const svmTypes = ["solana" /* SOLANA */, "svm" /* SVM */];
|
|
1191
|
+
if (this.state.networkType && svmTypes.includes(this.state.networkType)) {
|
|
1192
|
+
this.handleDisconnect(this.state.networkType);
|
|
1095
1193
|
}
|
|
1096
1194
|
});
|
|
1097
1195
|
}
|
|
1098
|
-
async autoReconnect() {
|
|
1099
|
-
if (!isWalletManuallyDisconnected()) {
|
|
1100
|
-
const connectedType = getConnectedNetworkType();
|
|
1101
|
-
if (connectedType) {
|
|
1102
|
-
const currentAddress = await getCurrentWallet(connectedType);
|
|
1103
|
-
if (currentAddress) {
|
|
1104
|
-
this.setState({
|
|
1105
|
-
address: currentAddress,
|
|
1106
|
-
networkType: connectedType
|
|
1107
|
-
});
|
|
1108
|
-
console.log("\u{1F504} Auto-reconnected wallet:", currentAddress);
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
1196
|
// Get current state
|
|
1114
1197
|
getState() {
|
|
1115
1198
|
return this.state;
|
|
@@ -1130,18 +1213,32 @@ var WalletStore = class {
|
|
|
1130
1213
|
notifyListeners() {
|
|
1131
1214
|
this.listeners.forEach((listener) => listener());
|
|
1132
1215
|
}
|
|
1216
|
+
// Handle wallet disconnect (internal helper)
|
|
1217
|
+
handleDisconnect(networkType, error) {
|
|
1218
|
+
removeWalletAddress(networkType);
|
|
1219
|
+
markWalletDisconnected(networkType);
|
|
1220
|
+
if (typeof window !== "undefined") {
|
|
1221
|
+
localStorage.removeItem("connected_network_type");
|
|
1222
|
+
}
|
|
1223
|
+
this.setState({
|
|
1224
|
+
address: null,
|
|
1225
|
+
networkType: null,
|
|
1226
|
+
error: error || null
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1133
1229
|
// Connect wallet
|
|
1134
1230
|
async connect(type) {
|
|
1231
|
+
if (this.state.address && this.state.networkType && this.state.networkType !== type) {
|
|
1232
|
+
saveWalletAddress(this.state.networkType, this.state.address);
|
|
1233
|
+
}
|
|
1135
1234
|
this.setState({ isConnecting: true, error: null });
|
|
1136
1235
|
try {
|
|
1137
1236
|
const walletAddress = await connectWallet(type);
|
|
1138
|
-
console.log("\u2705 Wallet connected:", walletAddress, "Network:", type);
|
|
1139
1237
|
this.setState({
|
|
1140
1238
|
address: walletAddress,
|
|
1141
1239
|
networkType: type,
|
|
1142
1240
|
isConnecting: false
|
|
1143
1241
|
});
|
|
1144
|
-
console.log("\u{1F4DD} Store state updated");
|
|
1145
1242
|
} catch (err) {
|
|
1146
1243
|
this.setState({
|
|
1147
1244
|
error: err.message || "Failed to connect wallet",
|
|
@@ -1150,20 +1247,67 @@ var WalletStore = class {
|
|
|
1150
1247
|
throw err;
|
|
1151
1248
|
}
|
|
1152
1249
|
}
|
|
1250
|
+
// Switch network (use cached wallet if available)
|
|
1251
|
+
async switchNetwork(type) {
|
|
1252
|
+
if (this.state.address && this.state.networkType) {
|
|
1253
|
+
saveWalletAddress(this.state.networkType, this.state.address);
|
|
1254
|
+
}
|
|
1255
|
+
this.setState({ isConnecting: true, error: null });
|
|
1256
|
+
try {
|
|
1257
|
+
const address = await switchNetwork(type);
|
|
1258
|
+
if (address) {
|
|
1259
|
+
this.setState({
|
|
1260
|
+
address,
|
|
1261
|
+
networkType: type,
|
|
1262
|
+
isConnecting: false
|
|
1263
|
+
});
|
|
1264
|
+
} else {
|
|
1265
|
+
this.setState({
|
|
1266
|
+
address: null,
|
|
1267
|
+
networkType: type,
|
|
1268
|
+
isConnecting: true
|
|
1269
|
+
});
|
|
1270
|
+
await this.connect(type);
|
|
1271
|
+
}
|
|
1272
|
+
} catch (err) {
|
|
1273
|
+
this.setState({
|
|
1274
|
+
error: err.message || "Failed to switch network",
|
|
1275
|
+
isConnecting: false
|
|
1276
|
+
});
|
|
1277
|
+
throw err;
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1153
1280
|
// Disconnect wallet
|
|
1154
1281
|
disconnect() {
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1282
|
+
const currentNetwork = this.state.networkType;
|
|
1283
|
+
if (currentNetwork) {
|
|
1284
|
+
this.handleDisconnect(currentNetwork);
|
|
1285
|
+
} else {
|
|
1286
|
+
this.setState({
|
|
1287
|
+
address: null,
|
|
1288
|
+
networkType: null,
|
|
1289
|
+
error: null
|
|
1290
|
+
});
|
|
1291
|
+
}
|
|
1162
1292
|
}
|
|
1163
1293
|
// Clear error
|
|
1164
1294
|
clearError() {
|
|
1165
1295
|
this.setState({ error: null });
|
|
1166
1296
|
}
|
|
1297
|
+
// Ensure network matches expected type (for page-specific network requirements)
|
|
1298
|
+
async ensureNetwork(expectedNetwork) {
|
|
1299
|
+
if (isWalletManuallyDisconnected(expectedNetwork)) {
|
|
1300
|
+
return;
|
|
1301
|
+
}
|
|
1302
|
+
if (this.state.networkType === expectedNetwork && this.state.address) {
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
if (this.state.networkType !== expectedNetwork) {
|
|
1306
|
+
await this.switchNetwork(expectedNetwork);
|
|
1307
|
+
} else if (!this.state.address) {
|
|
1308
|
+
await this.connect(expectedNetwork);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1167
1311
|
};
|
|
1168
1312
|
var walletStore = new WalletStore();
|
|
1169
1313
|
if (typeof window !== "undefined") {
|
|
@@ -1181,24 +1325,43 @@ function useWallet() {
|
|
|
1181
1325
|
return {
|
|
1182
1326
|
...state,
|
|
1183
1327
|
connect: (type) => walletStore.connect(type),
|
|
1328
|
+
switchNetwork: (type) => walletStore.switchNetwork(type),
|
|
1329
|
+
ensureNetwork: (type) => walletStore.ensureNetwork(type),
|
|
1184
1330
|
disconnect: () => walletStore.disconnect(),
|
|
1185
1331
|
clearError: () => walletStore.clearError()
|
|
1186
1332
|
};
|
|
1187
1333
|
}
|
|
1188
1334
|
|
|
1189
|
-
// src/react/hooks/
|
|
1335
|
+
// src/react/hooks/usePageNetwork.ts
|
|
1190
1336
|
var import_react2 = require("react");
|
|
1337
|
+
function usePageNetwork(expectedNetwork, options = {}) {
|
|
1338
|
+
const {
|
|
1339
|
+
autoSwitch = true,
|
|
1340
|
+
switchOnMount = true
|
|
1341
|
+
} = options;
|
|
1342
|
+
const wallet = useWallet();
|
|
1343
|
+
(0, import_react2.useEffect)(() => {
|
|
1344
|
+
if (!autoSwitch || !switchOnMount) return;
|
|
1345
|
+
wallet.ensureNetwork(expectedNetwork).catch((err) => {
|
|
1346
|
+
console.error("Failed to ensure network:", err);
|
|
1347
|
+
});
|
|
1348
|
+
}, [expectedNetwork]);
|
|
1349
|
+
return wallet;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
// src/react/hooks/usePayment.ts
|
|
1353
|
+
var import_react3 = require("react");
|
|
1191
1354
|
function usePayment() {
|
|
1192
|
-
const [isProcessing, setIsProcessing] = (0,
|
|
1193
|
-
const [result, setResult] = (0,
|
|
1194
|
-
const [error, setError] = (0,
|
|
1195
|
-
const clearResult = (0,
|
|
1355
|
+
const [isProcessing, setIsProcessing] = (0, import_react3.useState)(false);
|
|
1356
|
+
const [result, setResult] = (0, import_react3.useState)(null);
|
|
1357
|
+
const [error, setError] = (0, import_react3.useState)(null);
|
|
1358
|
+
const clearResult = (0, import_react3.useCallback)(() => {
|
|
1196
1359
|
setResult(null);
|
|
1197
1360
|
}, []);
|
|
1198
|
-
const clearError = (0,
|
|
1361
|
+
const clearError = (0, import_react3.useCallback)(() => {
|
|
1199
1362
|
setError(null);
|
|
1200
1363
|
}, []);
|
|
1201
|
-
const reset = (0,
|
|
1364
|
+
const reset = (0, import_react3.useCallback)(() => {
|
|
1202
1365
|
setIsProcessing(false);
|
|
1203
1366
|
setResult(null);
|
|
1204
1367
|
setError(null);
|
|
@@ -1217,18 +1380,28 @@ function usePayment() {
|
|
|
1217
1380
|
}
|
|
1218
1381
|
|
|
1219
1382
|
// src/react/hooks/usePaymentInfo.ts
|
|
1220
|
-
var
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
const [
|
|
1224
|
-
const [
|
|
1225
|
-
const [
|
|
1383
|
+
var import_react4 = require("react");
|
|
1384
|
+
init_common();
|
|
1385
|
+
function usePaymentInfo(merchantId, endpoint = PROD_BACK_URL, additionalParams) {
|
|
1386
|
+
const [paymentInfo, setPaymentInfo] = (0, import_react4.useState)(null);
|
|
1387
|
+
const [supportedNetworks, setSupportedNetworks] = (0, import_react4.useState)([]);
|
|
1388
|
+
const [isLoading, setIsLoading] = (0, import_react4.useState)(true);
|
|
1389
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
1226
1390
|
const fetchPaymentInfo = async () => {
|
|
1227
1391
|
setIsLoading(true);
|
|
1228
1392
|
setError(null);
|
|
1229
1393
|
try {
|
|
1230
|
-
|
|
1231
|
-
const
|
|
1394
|
+
const fullEndpoint = `${endpoint}/${merchantId}`;
|
|
1395
|
+
const requestInit = {
|
|
1396
|
+
method: "POST",
|
|
1397
|
+
...additionalParams && Object.keys(additionalParams).length > 0 ? {
|
|
1398
|
+
body: JSON.stringify(additionalParams),
|
|
1399
|
+
headers: {
|
|
1400
|
+
"Content-Type": "application/json"
|
|
1401
|
+
}
|
|
1402
|
+
} : {}
|
|
1403
|
+
};
|
|
1404
|
+
const response = await fetch(fullEndpoint, requestInit);
|
|
1232
1405
|
if (response.status === 402) {
|
|
1233
1406
|
const body = await response.json();
|
|
1234
1407
|
const payment = parsePaymentRequired(body);
|
|
@@ -1247,9 +1420,9 @@ function usePaymentInfo(merchantId, endpoint = PROD_BACK_URL) {
|
|
|
1247
1420
|
setIsLoading(false);
|
|
1248
1421
|
}
|
|
1249
1422
|
};
|
|
1250
|
-
(0,
|
|
1423
|
+
(0, import_react4.useEffect)(() => {
|
|
1251
1424
|
fetchPaymentInfo();
|
|
1252
|
-
}, [endpoint]);
|
|
1425
|
+
}, [endpoint, merchantId]);
|
|
1253
1426
|
return {
|
|
1254
1427
|
paymentInfo,
|
|
1255
1428
|
supportedNetworks,
|
|
@@ -1260,7 +1433,7 @@ function usePaymentInfo(merchantId, endpoint = PROD_BACK_URL) {
|
|
|
1260
1433
|
}
|
|
1261
1434
|
|
|
1262
1435
|
// src/react/components/WalletConnect.tsx
|
|
1263
|
-
var
|
|
1436
|
+
var import_react5 = __toESM(require("react"));
|
|
1264
1437
|
|
|
1265
1438
|
// src/react/styles/inline-styles.ts
|
|
1266
1439
|
var isDarkMode = () => {
|
|
@@ -1352,12 +1525,21 @@ var baseButtonStyle = {
|
|
|
1352
1525
|
};
|
|
1353
1526
|
var getConnectButtonStyle = (isDisabled, isHovered) => {
|
|
1354
1527
|
const c = getColors();
|
|
1528
|
+
const darkMode = isDarkMode();
|
|
1529
|
+
if (isDisabled) {
|
|
1530
|
+
return {
|
|
1531
|
+
...baseButtonStyle,
|
|
1532
|
+
background: c.disabled,
|
|
1533
|
+
color: c.disabledText,
|
|
1534
|
+
cursor: "not-allowed",
|
|
1535
|
+
border: darkMode ? "1px solid #404040" : "1px solid #d4d4d4"
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1355
1538
|
return {
|
|
1356
1539
|
...baseButtonStyle,
|
|
1357
|
-
background:
|
|
1358
|
-
color:
|
|
1359
|
-
cursor:
|
|
1360
|
-
opacity: isDisabled ? 0.5 : 1
|
|
1540
|
+
background: isHovered ? c.primaryHover : c.primary,
|
|
1541
|
+
color: darkMode ? "#000000" : "#ffffff",
|
|
1542
|
+
cursor: "pointer"
|
|
1361
1543
|
};
|
|
1362
1544
|
};
|
|
1363
1545
|
var getDisconnectButtonStyle = (isHovered) => {
|
|
@@ -1368,17 +1550,6 @@ var getDisconnectButtonStyle = (isHovered) => {
|
|
|
1368
1550
|
color: "#ffffff"
|
|
1369
1551
|
};
|
|
1370
1552
|
};
|
|
1371
|
-
var getPayButtonStyle = (isDisabled, isHovered) => {
|
|
1372
|
-
const c = getColors();
|
|
1373
|
-
return {
|
|
1374
|
-
...baseButtonStyle,
|
|
1375
|
-
background: isDisabled ? c.disabled : isHovered ? c.successHover : c.success,
|
|
1376
|
-
color: "#ffffff",
|
|
1377
|
-
width: "100%",
|
|
1378
|
-
cursor: isDisabled ? "not-allowed" : "pointer",
|
|
1379
|
-
opacity: isDisabled ? 0.5 : 1
|
|
1380
|
-
};
|
|
1381
|
-
};
|
|
1382
1553
|
var getInstallLinkStyle = (isHovered) => {
|
|
1383
1554
|
const c = getColors();
|
|
1384
1555
|
return {
|
|
@@ -1451,8 +1622,8 @@ function WalletConnect({
|
|
|
1451
1622
|
onDisconnect
|
|
1452
1623
|
}) {
|
|
1453
1624
|
const { address, networkType, isConnecting, error, connect, disconnect } = useWallet();
|
|
1454
|
-
const [hoveredButton, setHoveredButton] = (0,
|
|
1455
|
-
const [hoveredLink, setHoveredLink] = (0,
|
|
1625
|
+
const [hoveredButton, setHoveredButton] = (0, import_react5.useState)(null);
|
|
1626
|
+
const [hoveredLink, setHoveredLink] = (0, import_react5.useState)(null);
|
|
1456
1627
|
const handleConnect = async (network) => {
|
|
1457
1628
|
try {
|
|
1458
1629
|
await connect(network);
|
|
@@ -1463,9 +1634,9 @@ function WalletConnect({
|
|
|
1463
1634
|
disconnect();
|
|
1464
1635
|
onDisconnect?.();
|
|
1465
1636
|
};
|
|
1466
|
-
return /* @__PURE__ */
|
|
1637
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { style: { ...containerStyle, ...className ? {} : {} }, className }, !address ? /* @__PURE__ */ import_react5.default.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ import_react5.default.createElement("h3", { style: getTitleStyle() }, "Connect Wallet"), supportedNetworks.length === 0 ? /* @__PURE__ */ import_react5.default.createElement("p", { style: getHintStyle() }, "Please install a supported wallet extension") : /* @__PURE__ */ import_react5.default.createElement("div", { style: buttonsContainerStyle }, supportedNetworks.map((network) => {
|
|
1467
1638
|
const installed = isWalletInstalled(network);
|
|
1468
|
-
return /* @__PURE__ */
|
|
1639
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { key: network, style: walletOptionStyle }, /* @__PURE__ */ import_react5.default.createElement(
|
|
1469
1640
|
"button",
|
|
1470
1641
|
{
|
|
1471
1642
|
style: getConnectButtonStyle(isConnecting || !installed, hoveredButton === network),
|
|
@@ -1475,7 +1646,7 @@ function WalletConnect({
|
|
|
1475
1646
|
onMouseLeave: () => setHoveredButton(null)
|
|
1476
1647
|
},
|
|
1477
1648
|
isConnecting ? "Connecting..." : getNetworkDisplayName(network)
|
|
1478
|
-
), !installed && /* @__PURE__ */
|
|
1649
|
+
), !installed && /* @__PURE__ */ import_react5.default.createElement(
|
|
1479
1650
|
"a",
|
|
1480
1651
|
{
|
|
1481
1652
|
href: getWalletInstallUrl(network),
|
|
@@ -1487,7 +1658,7 @@ function WalletConnect({
|
|
|
1487
1658
|
},
|
|
1488
1659
|
"Install Wallet"
|
|
1489
1660
|
));
|
|
1490
|
-
})), error && /* @__PURE__ */
|
|
1661
|
+
})), error && /* @__PURE__ */ import_react5.default.createElement("p", { style: getErrorStyle() }, error), /* @__PURE__ */ import_react5.default.createElement("p", { style: getHintStyle() }, "To switch accounts, please change it in your wallet extension")) : /* @__PURE__ */ import_react5.default.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ import_react5.default.createElement("div", { style: walletAddressStyle }, /* @__PURE__ */ import_react5.default.createElement("span", { style: getLabelStyle() }, "Connected ", networkType && `(${getNetworkDisplayName(networkType)})`), /* @__PURE__ */ import_react5.default.createElement("span", { style: getAddressStyle() }, formatAddress(address))), /* @__PURE__ */ import_react5.default.createElement("div", { style: walletActionsStyle }, /* @__PURE__ */ import_react5.default.createElement(
|
|
1491
1662
|
"button",
|
|
1492
1663
|
{
|
|
1493
1664
|
style: getDisconnectButtonStyle(hoveredButton === "disconnect"),
|
|
@@ -1496,65 +1667,568 @@ function WalletConnect({
|
|
|
1496
1667
|
onMouseLeave: () => setHoveredButton(null)
|
|
1497
1668
|
},
|
|
1498
1669
|
"Disconnect"
|
|
1499
|
-
)), /* @__PURE__ */
|
|
1670
|
+
)), /* @__PURE__ */ import_react5.default.createElement("p", { style: getHintStyle() }, "Switch account in your wallet to change address")));
|
|
1500
1671
|
}
|
|
1501
1672
|
|
|
1502
|
-
// src/react/components/
|
|
1503
|
-
var
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1673
|
+
// src/react/components/V402Checkout.tsx
|
|
1674
|
+
var import_react7 = __toESM(require("react"));
|
|
1675
|
+
var import_antd = require("antd");
|
|
1676
|
+
var import_icons = require("@ant-design/icons");
|
|
1677
|
+
init_common();
|
|
1678
|
+
|
|
1679
|
+
// src/react/utils/CryptoIcons.tsx
|
|
1680
|
+
var import_react6 = __toESM(require("react"));
|
|
1681
|
+
var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
|
|
1682
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
1683
|
+
"svg",
|
|
1684
|
+
{
|
|
1685
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1686
|
+
viewBox: "0 0 16 16",
|
|
1687
|
+
width,
|
|
1688
|
+
height,
|
|
1689
|
+
className,
|
|
1690
|
+
style
|
|
1691
|
+
},
|
|
1692
|
+
/* @__PURE__ */ import_react6.default.createElement("desc", null, "Solana SOL Fill Streamline Icon: https://streamlinehq.com"),
|
|
1693
|
+
/* @__PURE__ */ import_react6.default.createElement("g", { fill: "none", fillRule: "evenodd" }, /* @__PURE__ */ import_react6.default.createElement(
|
|
1694
|
+
"path",
|
|
1695
|
+
{
|
|
1696
|
+
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",
|
|
1697
|
+
strokeWidth: "0.6667"
|
|
1698
|
+
}
|
|
1699
|
+
), /* @__PURE__ */ import_react6.default.createElement(
|
|
1700
|
+
"path",
|
|
1701
|
+
{
|
|
1702
|
+
fill: "#000000",
|
|
1703
|
+
d: "M4.862 2.862A0.6666666666666666 0.6666666666666666 0 0 1 5.333333333333333 2.6666666666666665h8.666666666666666a0.6666666666666666 0.6666666666666666 0 0 1 0.47133333333333327 1.138l-2 2A0.6666666666666666 0.6666666666666666 0 0 1 12 6H3.333333333333333a0.6666666666666666 0.6666666666666666 0 0 1 -0.47133333333333327 -1.138l2 -2Zm-2.1166666666666663 4.156666666666666A0.6666666666666666 0.6666666666666666 0 0 1 3.333333333333333 6.666666666666666h8.666666666666666a0.6666666666666666 0.6666666666666666 0 0 1 0.5546666666666666 0.29666666666666663l1.3333333333333333 2A0.6666666666666666 0.6666666666666666 0 0 1 13.333333333333332 10H4.666666666666666a0.6666666666666666 0.6666666666666666 0 0 1 -0.5546666666666666 -0.29666666666666663l-1.3333333333333333 -2a0.6666666666666666 0.6666666666666666 0 0 1 -0.03333333333333333 -0.6846666666666665Zm1.4499999999999997 3.843333333333333A0.6666666666666666 0.6666666666666666 0 0 1 4.666666666666666 10.666666666666666h8.666666666666666a0.6666666666666666 0.6666666666666666 0 0 1 0.47133333333333327 1.138l-2 2A0.6666666666666666 0.6666666666666666 0 0 1 11.333333333333332 14H2.6666666666666665a0.6666666666666666 0.6666666666666666 0 0 1 -0.47133333333333327 -1.138l2 -2Z",
|
|
1704
|
+
strokeWidth: "0.6667"
|
|
1705
|
+
}
|
|
1706
|
+
))
|
|
1707
|
+
);
|
|
1708
|
+
};
|
|
1709
|
+
var BaseIcon = ({ width = 24, height = 24, className, style }) => {
|
|
1710
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
1711
|
+
"svg",
|
|
1712
|
+
{
|
|
1713
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1714
|
+
viewBox: "0 0 24 24",
|
|
1715
|
+
fill: "none",
|
|
1716
|
+
stroke: "#000000",
|
|
1717
|
+
strokeLinecap: "round",
|
|
1718
|
+
strokeLinejoin: "round",
|
|
1719
|
+
width,
|
|
1720
|
+
height,
|
|
1721
|
+
className,
|
|
1722
|
+
style
|
|
1723
|
+
},
|
|
1724
|
+
/* @__PURE__ */ import_react6.default.createElement("desc", null, "Brand Coinbase Streamline Icon: https://streamlinehq.com"),
|
|
1725
|
+
/* @__PURE__ */ import_react6.default.createElement(
|
|
1726
|
+
"path",
|
|
1727
|
+
{
|
|
1728
|
+
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",
|
|
1729
|
+
strokeWidth: "2"
|
|
1730
|
+
}
|
|
1731
|
+
)
|
|
1732
|
+
);
|
|
1733
|
+
};
|
|
1734
|
+
var getNetworkIcon = (network) => {
|
|
1735
|
+
const networkLower = network.toLowerCase();
|
|
1736
|
+
if (networkLower.includes("solana")) {
|
|
1737
|
+
return SolanaIcon;
|
|
1738
|
+
}
|
|
1739
|
+
if (networkLower.includes("base")) {
|
|
1740
|
+
return BaseIcon;
|
|
1741
|
+
}
|
|
1742
|
+
return BaseIcon;
|
|
1743
|
+
};
|
|
1744
|
+
|
|
1745
|
+
// src/react/components/V402Checkout.tsx
|
|
1746
|
+
var { Title, Text } = import_antd.Typography;
|
|
1747
|
+
var notify = {
|
|
1748
|
+
success: (title, msg) => {
|
|
1749
|
+
import_antd.message.success(`${title}: ${msg}`);
|
|
1750
|
+
},
|
|
1751
|
+
error: (title, msg) => {
|
|
1752
|
+
import_antd.message.error(`${title}: ${msg}`);
|
|
1753
|
+
},
|
|
1754
|
+
info: (title, msg) => {
|
|
1755
|
+
import_antd.message.info(`${title}: ${msg}`);
|
|
1756
|
+
}
|
|
1757
|
+
};
|
|
1758
|
+
function V402Checkout({
|
|
1759
|
+
merchantId,
|
|
1760
|
+
headerInfo = {},
|
|
1761
|
+
isModal = false,
|
|
1762
|
+
onPaymentComplete,
|
|
1763
|
+
additionalParams = {},
|
|
1764
|
+
expectedNetwork
|
|
1513
1765
|
}) {
|
|
1514
|
-
const {
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1766
|
+
const {
|
|
1767
|
+
title = "V402Pay - Make x402Pay Easier",
|
|
1768
|
+
subtitle = "onvoyage.ai",
|
|
1769
|
+
tooltipText = "V402Pay - Accept Crypto Payments Easier"
|
|
1770
|
+
} = headerInfo;
|
|
1771
|
+
let endpoint = DEV_BACK_URL;
|
|
1772
|
+
const {
|
|
1773
|
+
supportedNetworks,
|
|
1774
|
+
isLoading: fetchingPaymentInfo,
|
|
1775
|
+
paymentInfo
|
|
1776
|
+
} = usePaymentInfo(merchantId, endpoint, additionalParams);
|
|
1777
|
+
const targetNetwork = expectedNetwork || supportedNetworks[0];
|
|
1778
|
+
const { address, networkType, disconnect, ensureNetwork } = usePageNetwork(
|
|
1779
|
+
targetNetwork,
|
|
1780
|
+
{ autoSwitch: !!targetNetwork, switchOnMount: true }
|
|
1781
|
+
);
|
|
1782
|
+
const { isProcessing, setIsProcessing, result, setResult, error, setError } = usePayment();
|
|
1783
|
+
const [paymentDetails, setPaymentDetails] = (0, import_react7.useState)(null);
|
|
1784
|
+
const handleDisconnect = () => {
|
|
1785
|
+
disconnect();
|
|
1786
|
+
setResult(null);
|
|
1787
|
+
setError(null);
|
|
1788
|
+
notify.info("Wallet Disconnected", "Your wallet has been disconnected successfully.");
|
|
1789
|
+
};
|
|
1790
|
+
(0, import_react7.useEffect)(() => {
|
|
1791
|
+
if (paymentInfo && paymentInfo.length > 0) {
|
|
1792
|
+
const firstPayment = paymentInfo[0];
|
|
1793
|
+
const rawAmount = firstPayment.maxAmountRequired?.toString() || "0";
|
|
1794
|
+
const decimals = 6;
|
|
1795
|
+
const humanReadableAmount = (Number(rawAmount) / Math.pow(10, decimals)).toFixed(2);
|
|
1796
|
+
const network = firstPayment.network || "Unknown";
|
|
1797
|
+
const currency = "USDC";
|
|
1798
|
+
setPaymentDetails({
|
|
1799
|
+
amount: humanReadableAmount,
|
|
1800
|
+
currency,
|
|
1801
|
+
network
|
|
1802
|
+
});
|
|
1803
|
+
}
|
|
1804
|
+
}, [paymentInfo]);
|
|
1805
|
+
(0, import_react7.useEffect)(() => {
|
|
1806
|
+
if (targetNetwork && !fetchingPaymentInfo && ensureNetwork) {
|
|
1807
|
+
ensureNetwork(targetNetwork).catch((err) => {
|
|
1808
|
+
console.error("Failed to ensure network:", err);
|
|
1809
|
+
});
|
|
1810
|
+
}
|
|
1811
|
+
}, [targetNetwork, fetchingPaymentInfo]);
|
|
1812
|
+
const handlePayment = async () => {
|
|
1518
1813
|
if (!networkType) {
|
|
1519
|
-
|
|
1520
|
-
setError(errorMsg);
|
|
1521
|
-
onError?.(errorMsg);
|
|
1814
|
+
notify.error("Wallet Not Connected", "Please connect your wallet first.");
|
|
1522
1815
|
return;
|
|
1523
1816
|
}
|
|
1817
|
+
setResult(null);
|
|
1818
|
+
setError(null);
|
|
1819
|
+
setIsProcessing(true);
|
|
1524
1820
|
try {
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1821
|
+
const response = await makePayment(networkType, merchantId, endpoint, additionalParams);
|
|
1822
|
+
const data = await response.json();
|
|
1823
|
+
setResult(data);
|
|
1824
|
+
notify.success("Payment Successful!", "Your payment has been processed successfully.");
|
|
1825
|
+
if (onPaymentComplete) {
|
|
1826
|
+
onPaymentComplete(data);
|
|
1827
|
+
}
|
|
1531
1828
|
} catch (err) {
|
|
1532
|
-
const
|
|
1533
|
-
setError(
|
|
1534
|
-
|
|
1829
|
+
const errorMessage = err.message || "Payment failed";
|
|
1830
|
+
setError(errorMessage);
|
|
1831
|
+
notify.error("Payment Failed", errorMessage);
|
|
1535
1832
|
} finally {
|
|
1536
1833
|
setIsProcessing(false);
|
|
1537
|
-
onFinish?.();
|
|
1538
1834
|
}
|
|
1539
1835
|
};
|
|
1540
|
-
const
|
|
1541
|
-
|
|
1542
|
-
"
|
|
1836
|
+
const getNetworkColor = (network) => {
|
|
1837
|
+
if (network.toLowerCase().includes("solana")) return "#14F195";
|
|
1838
|
+
if (network.toLowerCase().includes("evm") || network.toLowerCase().includes("base")) return "#0052FF";
|
|
1839
|
+
return "#8c8c8c";
|
|
1840
|
+
};
|
|
1841
|
+
const NetworkIcon = paymentDetails ? getNetworkIcon(paymentDetails.network) : null;
|
|
1842
|
+
const networkColor = paymentDetails ? getNetworkColor(paymentDetails.network) : "#8c8c8c";
|
|
1843
|
+
const loadingColor = "#8c8c8c";
|
|
1844
|
+
const hasInvalidCheckoutId = !fetchingPaymentInfo && (!paymentInfo || paymentInfo.length === 0);
|
|
1845
|
+
return /* @__PURE__ */ import_react7.default.createElement(
|
|
1846
|
+
"div",
|
|
1543
1847
|
{
|
|
1544
|
-
|
|
1545
|
-
className,
|
|
1546
|
-
onClick: handleClick,
|
|
1547
|
-
disabled: isDisabled,
|
|
1548
|
-
onMouseEnter: () => setIsHovered(true),
|
|
1549
|
-
onMouseLeave: () => setIsHovered(false)
|
|
1848
|
+
className: isModal ? "bg-white" : "h-screen bg-white flex items-center justify-center p-4 overflow-hidden"
|
|
1550
1849
|
},
|
|
1551
|
-
|
|
1552
|
-
|
|
1850
|
+
/* @__PURE__ */ import_react7.default.createElement(
|
|
1851
|
+
"div",
|
|
1852
|
+
{
|
|
1853
|
+
className: "flex gap-4 items-center justify-center",
|
|
1854
|
+
style: {
|
|
1855
|
+
maxWidth: isProcessing || result || error ? "1200px" : "480px",
|
|
1856
|
+
transition: "max-width 0.4s ease-in-out",
|
|
1857
|
+
width: "100%"
|
|
1858
|
+
}
|
|
1859
|
+
},
|
|
1860
|
+
/* @__PURE__ */ import_react7.default.createElement(
|
|
1861
|
+
import_antd.Card,
|
|
1862
|
+
{
|
|
1863
|
+
className: "flex-shrink-0",
|
|
1864
|
+
style: {
|
|
1865
|
+
border: isModal ? "none" : "1px solid #e8e8e8",
|
|
1866
|
+
borderRadius: isModal ? "0" : "16px",
|
|
1867
|
+
boxShadow: isModal ? "none" : "0 4px 24px rgba(0, 0, 0, 0.06)",
|
|
1868
|
+
maxHeight: isModal ? "calc(100vh - 100px)" : "calc(100vh - 32px)",
|
|
1869
|
+
overflow: "auto",
|
|
1870
|
+
width: isModal ? "100%" : "480px",
|
|
1871
|
+
transition: "all 0.4s ease-in-out",
|
|
1872
|
+
transform: result || error ? "translateX(0)" : "translateX(0)"
|
|
1873
|
+
},
|
|
1874
|
+
styles: { body: { padding: isModal ? "0px" : "32px 24px" } }
|
|
1875
|
+
},
|
|
1876
|
+
/* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-3 mb-4" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
1877
|
+
"div",
|
|
1878
|
+
{
|
|
1879
|
+
className: "w-12 h-12 rounded-xl flex items-center justify-center",
|
|
1880
|
+
style: {
|
|
1881
|
+
background: hasInvalidCheckoutId ? "#ff4d4f" : paymentDetails ? networkColor : loadingColor,
|
|
1882
|
+
transition: "background 0.3s ease"
|
|
1883
|
+
}
|
|
1884
|
+
},
|
|
1885
|
+
hasInvalidCheckoutId ? /* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "20px", color: "white", fontWeight: "bold" } }, "\u2717") : paymentDetails && NetworkIcon ? /* @__PURE__ */ import_react7.default.createElement(NetworkIcon, { width: 24, height: 24 }) : /* @__PURE__ */ import_react7.default.createElement(import_icons.LoadingOutlined, { style: { fontSize: "20px", color: "white" }, spin: true })
|
|
1886
|
+
), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex-1" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react7.default.createElement(Title, { level: 4, style: { margin: 0, fontSize: "18px", fontWeight: 600 } }, title || "Echo Payment OnVoyage"), !hasInvalidCheckoutId && /* @__PURE__ */ import_react7.default.createElement(
|
|
1887
|
+
import_antd.Tooltip,
|
|
1888
|
+
{
|
|
1889
|
+
title: tooltipText,
|
|
1890
|
+
placement: "top"
|
|
1891
|
+
},
|
|
1892
|
+
/* @__PURE__ */ import_react7.default.createElement(
|
|
1893
|
+
import_icons.InfoCircleOutlined,
|
|
1894
|
+
{
|
|
1895
|
+
style: { fontSize: "14px", color: "#8c8c8c", cursor: "help" }
|
|
1896
|
+
}
|
|
1897
|
+
)
|
|
1898
|
+
)), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, subtitle))),
|
|
1899
|
+
/* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center mb-5" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "inline-flex items-center justify-center w-12 h-12 rounded-full bg-gray-50 mb-3" }, /* @__PURE__ */ import_react7.default.createElement(import_icons.LockOutlined, { style: { fontSize: "20px", color: "#595959" } })), /* @__PURE__ */ import_react7.default.createElement(Title, { level: 3, style: { margin: "0 0 6px 0", fontSize: "20px", fontWeight: 600 } }, "Payment Required"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Pay ", paymentDetails ? `$${paymentDetails.amount} ${paymentDetails.currency}` : "the required amount", " to access")),
|
|
1900
|
+
hasInvalidCheckoutId && /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
1901
|
+
"div",
|
|
1902
|
+
{
|
|
1903
|
+
className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
|
|
1904
|
+
style: {
|
|
1905
|
+
background: "linear-gradient(135deg, #ef4444 0%, #f87171 100%)",
|
|
1906
|
+
boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
|
|
1907
|
+
}
|
|
1908
|
+
},
|
|
1909
|
+
/* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "!")
|
|
1910
|
+
), /* @__PURE__ */ import_react7.default.createElement(
|
|
1911
|
+
Title,
|
|
1912
|
+
{
|
|
1913
|
+
level: 4,
|
|
1914
|
+
style: { margin: "0 0 12px 0", fontSize: "18px", fontWeight: 600, color: "#262626" }
|
|
1915
|
+
},
|
|
1916
|
+
"Invalid Checkout ID"
|
|
1917
|
+
), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", display: "block", marginBottom: "16px" } }, "The checkout ID you provided is invalid or has expired."), /* @__PURE__ */ import_react7.default.createElement(
|
|
1918
|
+
"div",
|
|
1919
|
+
{
|
|
1920
|
+
style: {
|
|
1921
|
+
background: "#fef2f2",
|
|
1922
|
+
padding: "16px",
|
|
1923
|
+
borderRadius: "12px",
|
|
1924
|
+
border: "1px solid #fee2e2",
|
|
1925
|
+
marginTop: "16px"
|
|
1926
|
+
}
|
|
1927
|
+
},
|
|
1928
|
+
/* @__PURE__ */ import_react7.default.createElement(Text, { style: {
|
|
1929
|
+
fontSize: "13px",
|
|
1930
|
+
color: "#dc2626",
|
|
1931
|
+
lineHeight: "1.6",
|
|
1932
|
+
fontWeight: 500
|
|
1933
|
+
} }, "Failed to load payment information. Please check your checkout ID.")
|
|
1934
|
+
)),
|
|
1935
|
+
!hasInvalidCheckoutId && fetchingPaymentInfo && /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { color: "#8c8c8c" } }, "Loading payment information...")),
|
|
1936
|
+
!hasInvalidCheckoutId && !fetchingPaymentInfo && !address && /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement(WalletConnect, { supportedNetworks })),
|
|
1937
|
+
!hasInvalidCheckoutId && address && /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement(
|
|
1938
|
+
"div",
|
|
1939
|
+
{
|
|
1940
|
+
className: "bg-gray-50 rounded-lg p-3 mb-4",
|
|
1941
|
+
style: { border: "1px solid #f0f0f0" }
|
|
1942
|
+
},
|
|
1943
|
+
/* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-3 flex-1" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
1944
|
+
"div",
|
|
1945
|
+
{
|
|
1946
|
+
className: "w-10 h-10 rounded-full bg-black flex items-center justify-center text-white text-sm font-semibold"
|
|
1947
|
+
},
|
|
1948
|
+
address.slice(0, 2).toUpperCase()
|
|
1949
|
+
), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: {
|
|
1950
|
+
display: "block",
|
|
1951
|
+
fontSize: "12px",
|
|
1952
|
+
color: "#8c8c8c",
|
|
1953
|
+
marginBottom: "2px"
|
|
1954
|
+
} }, "Connected Wallet"), /* @__PURE__ */ import_react7.default.createElement(
|
|
1955
|
+
Text,
|
|
1956
|
+
{
|
|
1957
|
+
style: {
|
|
1958
|
+
fontSize: "13px",
|
|
1959
|
+
fontWeight: 600,
|
|
1960
|
+
fontFamily: "Monaco, monospace"
|
|
1961
|
+
}
|
|
1962
|
+
},
|
|
1963
|
+
formatAddress(address)
|
|
1964
|
+
))), /* @__PURE__ */ import_react7.default.createElement(
|
|
1965
|
+
import_antd.Button,
|
|
1966
|
+
{
|
|
1967
|
+
type: "text",
|
|
1968
|
+
size: "small",
|
|
1969
|
+
icon: /* @__PURE__ */ import_react7.default.createElement(import_icons.DisconnectOutlined, null),
|
|
1970
|
+
onClick: handleDisconnect,
|
|
1971
|
+
style: { color: "#ff4d4f" }
|
|
1972
|
+
}
|
|
1973
|
+
))
|
|
1974
|
+
), paymentDetails && /* @__PURE__ */ import_react7.default.createElement("div", { className: "bg-gray-50 rounded-lg p-3 mb-4", style: { border: "1px solid #f0f0f0" } }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Payment Amount"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "18px", fontWeight: 600 } }, "$", paymentDetails.amount)), /* @__PURE__ */ import_react7.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Currency"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.currency)), /* @__PURE__ */ import_react7.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Network"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.network)), /* @__PURE__ */ import_react7.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Wallet Address"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: {
|
|
1975
|
+
fontSize: "11px",
|
|
1976
|
+
fontWeight: 500,
|
|
1977
|
+
fontFamily: "Monaco, monospace",
|
|
1978
|
+
wordBreak: "break-all",
|
|
1979
|
+
textAlign: "right",
|
|
1980
|
+
maxWidth: "60%",
|
|
1981
|
+
lineHeight: 1.4
|
|
1982
|
+
} }, address))), /* @__PURE__ */ import_react7.default.createElement(
|
|
1983
|
+
"div",
|
|
1984
|
+
{
|
|
1985
|
+
className: "flex items-center justify-center gap-2 mb-3 p-2 rounded-lg",
|
|
1986
|
+
style: { background: "#f6ffed", border: "1px solid #d9f7be" }
|
|
1987
|
+
},
|
|
1988
|
+
/* @__PURE__ */ import_react7.default.createElement(import_icons.SafetyOutlined, { style: { color: "#52c41a", fontSize: "13px" } }),
|
|
1989
|
+
/* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "12px", color: "#52c41a", fontWeight: 500 } }, "Secure payment powered by v402pay")
|
|
1990
|
+
), /* @__PURE__ */ import_react7.default.createElement(
|
|
1991
|
+
import_antd.Button,
|
|
1992
|
+
{
|
|
1993
|
+
type: "primary",
|
|
1994
|
+
size: "large",
|
|
1995
|
+
onClick: handlePayment,
|
|
1996
|
+
disabled: isProcessing || !paymentDetails,
|
|
1997
|
+
loading: isProcessing,
|
|
1998
|
+
block: true,
|
|
1999
|
+
style: {
|
|
2000
|
+
height: "44px",
|
|
2001
|
+
fontSize: "14px",
|
|
2002
|
+
fontWeight: 600,
|
|
2003
|
+
borderRadius: "8px",
|
|
2004
|
+
...!isProcessing && paymentDetails && {
|
|
2005
|
+
background: "#1a1a1a",
|
|
2006
|
+
borderColor: "#1a1a1a"
|
|
2007
|
+
},
|
|
2008
|
+
marginBottom: "10px"
|
|
2009
|
+
}
|
|
2010
|
+
},
|
|
2011
|
+
isProcessing ? "Processing..." : !paymentDetails ? "Loading..." : `Pay $${paymentDetails.amount} ${paymentDetails.currency}`
|
|
2012
|
+
), /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Don't have USDC?", " "), /* @__PURE__ */ import_react7.default.createElement(
|
|
2013
|
+
"a",
|
|
2014
|
+
{
|
|
2015
|
+
href: "https://faucet.circle.com/",
|
|
2016
|
+
target: "_blank",
|
|
2017
|
+
rel: "noopener noreferrer",
|
|
2018
|
+
className: "text-blue-600 hover:text-blue-700 text-sm font-medium inline-flex items-center gap-1"
|
|
2019
|
+
},
|
|
2020
|
+
"Get it here ",
|
|
2021
|
+
/* @__PURE__ */ import_react7.default.createElement(import_icons.LinkOutlined, { style: { fontSize: "12px" } })
|
|
2022
|
+
)), isModal && result && /* @__PURE__ */ import_react7.default.createElement(
|
|
2023
|
+
"div",
|
|
2024
|
+
{
|
|
2025
|
+
className: "mt-4 p-4 rounded-lg",
|
|
2026
|
+
style: { background: "#f6ffed", border: "1px solid #b7eb8f" }
|
|
2027
|
+
},
|
|
2028
|
+
/* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center" }, /* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "20px" } }, "\u2713"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: {
|
|
2029
|
+
fontSize: "14px",
|
|
2030
|
+
color: "#52c41a",
|
|
2031
|
+
fontWeight: 600,
|
|
2032
|
+
marginLeft: "8px"
|
|
2033
|
+
} }, "Payment Successful!"))
|
|
2034
|
+
), isModal && error && /* @__PURE__ */ import_react7.default.createElement(
|
|
2035
|
+
"div",
|
|
2036
|
+
{
|
|
2037
|
+
className: "mt-4 p-4 rounded-lg",
|
|
2038
|
+
style: { background: "#fff2f0", border: "1px solid #ffccc7" }
|
|
2039
|
+
},
|
|
2040
|
+
/* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center mb-3" }, /* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "20px" } }, "\u2717"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: {
|
|
2041
|
+
fontSize: "14px",
|
|
2042
|
+
color: "#ff4d4f",
|
|
2043
|
+
fontWeight: 600,
|
|
2044
|
+
marginLeft: "8px",
|
|
2045
|
+
display: "block",
|
|
2046
|
+
marginTop: "4px"
|
|
2047
|
+
} }, "Payment Failed")),
|
|
2048
|
+
/* @__PURE__ */ import_react7.default.createElement(Text, { style: {
|
|
2049
|
+
fontSize: "13px",
|
|
2050
|
+
color: "#ff4d4f",
|
|
2051
|
+
display: "block",
|
|
2052
|
+
textAlign: "center"
|
|
2053
|
+
} }, error)
|
|
2054
|
+
))
|
|
2055
|
+
),
|
|
2056
|
+
!isModal && (isProcessing || result || error) && /* @__PURE__ */ import_react7.default.createElement(
|
|
2057
|
+
import_antd.Card,
|
|
2058
|
+
{
|
|
2059
|
+
title: /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-2" }, isProcessing && !result && !error ? /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement(import_icons.LoadingOutlined, { style: { color: "#14b8a6", fontSize: "16px" } }), /* @__PURE__ */ import_react7.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Processing Payment")) : result ? /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement("span", { style: { color: "#52c41a", fontSize: "18px" } }, "\u2713"), /* @__PURE__ */ import_react7.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Successful")) : /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement("span", { style: { color: "#ff4d4f", fontSize: "18px" } }, "\u2717"), /* @__PURE__ */ import_react7.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Failed"))),
|
|
2060
|
+
extra: !isProcessing && /* @__PURE__ */ import_react7.default.createElement(
|
|
2061
|
+
import_antd.Button,
|
|
2062
|
+
{
|
|
2063
|
+
type: "text",
|
|
2064
|
+
size: "small",
|
|
2065
|
+
onClick: () => {
|
|
2066
|
+
setResult(null);
|
|
2067
|
+
setError(null);
|
|
2068
|
+
}
|
|
2069
|
+
},
|
|
2070
|
+
"Close"
|
|
2071
|
+
),
|
|
2072
|
+
style: {
|
|
2073
|
+
border: "1px solid #e8e8e8",
|
|
2074
|
+
borderRadius: "16px",
|
|
2075
|
+
boxShadow: "0 4px 24px rgba(0, 0, 0, 0.06)",
|
|
2076
|
+
maxHeight: "calc(100vh - 32px)",
|
|
2077
|
+
width: "480px",
|
|
2078
|
+
animation: "slideInRight 0.4s ease-out"
|
|
2079
|
+
},
|
|
2080
|
+
styles: {
|
|
2081
|
+
body: {
|
|
2082
|
+
padding: "24px",
|
|
2083
|
+
maxHeight: "calc(100vh - 120px)",
|
|
2084
|
+
overflow: "auto"
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
},
|
|
2088
|
+
isProcessing && !result && !error && /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center py-10" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "relative inline-block" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
2089
|
+
"div",
|
|
2090
|
+
{
|
|
2091
|
+
className: "absolute inset-0 rounded-full blur-xl opacity-40",
|
|
2092
|
+
style: {
|
|
2093
|
+
background: "linear-gradient(135deg, #14b8a6 0%, #06b6d4 100%)",
|
|
2094
|
+
animation: "pulse 2s ease-in-out infinite"
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
), /* @__PURE__ */ import_react7.default.createElement(
|
|
2098
|
+
import_antd.Spin,
|
|
2099
|
+
{
|
|
2100
|
+
indicator: /* @__PURE__ */ import_react7.default.createElement(import_icons.LoadingOutlined, { style: { fontSize: 56, color: "#14b8a6" } })
|
|
2101
|
+
}
|
|
2102
|
+
)), /* @__PURE__ */ import_react7.default.createElement("div", { className: "mt-6" }, /* @__PURE__ */ import_react7.default.createElement(Text, { strong: true, style: { fontSize: "18px", color: "#262626", letterSpacing: "-0.02em" } }, "Verifying Payment")), /* @__PURE__ */ import_react7.default.createElement("div", { className: "mt-2 mb-6" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", lineHeight: "1.6" } }, "Please wait while we confirm your transaction")), /* @__PURE__ */ import_react7.default.createElement(
|
|
2103
|
+
"div",
|
|
2104
|
+
{
|
|
2105
|
+
className: "mt-4 p-4 rounded-xl",
|
|
2106
|
+
style: {
|
|
2107
|
+
background: "linear-gradient(135deg, #f0fdfa 0%, #ecfeff 100%)",
|
|
2108
|
+
border: "1px solid #ccfbf1"
|
|
2109
|
+
}
|
|
2110
|
+
},
|
|
2111
|
+
/* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center justify-center gap-2" }, /* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "16px" } }, "\u23F1\uFE0F"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#0f766e", fontWeight: 500 } }, "This may take a few moments"))
|
|
2112
|
+
)),
|
|
2113
|
+
result && /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
2114
|
+
"div",
|
|
2115
|
+
{
|
|
2116
|
+
className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
|
|
2117
|
+
style: {
|
|
2118
|
+
background: "linear-gradient(135deg, #10b981 0%, #34d399 100%)",
|
|
2119
|
+
boxShadow: "0 4px 20px rgba(16, 185, 129, 0.3)"
|
|
2120
|
+
}
|
|
2121
|
+
},
|
|
2122
|
+
/* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2713")
|
|
2123
|
+
), /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement(Text, { strong: true, style: {
|
|
2124
|
+
fontSize: "20px",
|
|
2125
|
+
color: "#262626",
|
|
2126
|
+
display: "block",
|
|
2127
|
+
marginBottom: "8px"
|
|
2128
|
+
} }, "Payment Successful!"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Your transaction has been confirmed"))), /* @__PURE__ */ import_react7.default.createElement(import_antd.Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "RESPONSE DATA")), /* @__PURE__ */ import_react7.default.createElement(
|
|
2129
|
+
"pre",
|
|
2130
|
+
{
|
|
2131
|
+
style: {
|
|
2132
|
+
background: "#fafafa",
|
|
2133
|
+
padding: "20px",
|
|
2134
|
+
borderRadius: "12px",
|
|
2135
|
+
fontSize: "12px",
|
|
2136
|
+
lineHeight: "1.8",
|
|
2137
|
+
overflow: "auto",
|
|
2138
|
+
margin: 0,
|
|
2139
|
+
fontFamily: "Monaco, Courier New, monospace",
|
|
2140
|
+
whiteSpace: "pre-wrap",
|
|
2141
|
+
wordBreak: "break-word",
|
|
2142
|
+
border: "1px solid #e8e8e8",
|
|
2143
|
+
color: "#262626"
|
|
2144
|
+
}
|
|
2145
|
+
},
|
|
2146
|
+
JSON.stringify(result, null, 2)
|
|
2147
|
+
)),
|
|
2148
|
+
error && /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
2149
|
+
"div",
|
|
2150
|
+
{
|
|
2151
|
+
className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
|
|
2152
|
+
style: {
|
|
2153
|
+
background: "linear-gradient(135deg, #ef4444 0%, #f87171 100%)",
|
|
2154
|
+
boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
|
|
2155
|
+
}
|
|
2156
|
+
},
|
|
2157
|
+
/* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2717")
|
|
2158
|
+
), /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement(Text, { strong: true, style: {
|
|
2159
|
+
fontSize: "20px",
|
|
2160
|
+
color: "#262626",
|
|
2161
|
+
display: "block",
|
|
2162
|
+
marginBottom: "8px"
|
|
2163
|
+
} }, "Payment Failed"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Something went wrong with your transaction"))), /* @__PURE__ */ import_react7.default.createElement(import_antd.Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "ERROR DETAILS")), /* @__PURE__ */ import_react7.default.createElement(
|
|
2164
|
+
"div",
|
|
2165
|
+
{
|
|
2166
|
+
style: {
|
|
2167
|
+
background: "#fef2f2",
|
|
2168
|
+
padding: "20px",
|
|
2169
|
+
borderRadius: "12px",
|
|
2170
|
+
border: "1px solid #fee2e2"
|
|
2171
|
+
}
|
|
2172
|
+
},
|
|
2173
|
+
/* @__PURE__ */ import_react7.default.createElement(Text, { style: {
|
|
2174
|
+
fontSize: "14px",
|
|
2175
|
+
color: "#dc2626",
|
|
2176
|
+
lineHeight: "1.6",
|
|
2177
|
+
fontWeight: 500
|
|
2178
|
+
} }, error)
|
|
2179
|
+
), /* @__PURE__ */ import_react7.default.createElement("div", { className: "mt-4 text-center" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
2180
|
+
import_antd.Button,
|
|
2181
|
+
{
|
|
2182
|
+
size: "large",
|
|
2183
|
+
onClick: handlePayment,
|
|
2184
|
+
style: {
|
|
2185
|
+
height: "44px",
|
|
2186
|
+
fontSize: "14px",
|
|
2187
|
+
fontWeight: 600,
|
|
2188
|
+
borderRadius: "8px",
|
|
2189
|
+
background: "#1a1a1a",
|
|
2190
|
+
borderColor: "#1a1a1a",
|
|
2191
|
+
color: "white",
|
|
2192
|
+
paddingLeft: "32px",
|
|
2193
|
+
paddingRight: "32px"
|
|
2194
|
+
}
|
|
2195
|
+
},
|
|
2196
|
+
"Try Again"
|
|
2197
|
+
)))
|
|
2198
|
+
)
|
|
2199
|
+
),
|
|
2200
|
+
/* @__PURE__ */ import_react7.default.createElement("style", { dangerouslySetInnerHTML: {
|
|
2201
|
+
__html: `
|
|
2202
|
+
@keyframes slideInRight {
|
|
2203
|
+
from {
|
|
2204
|
+
opacity: 0;
|
|
2205
|
+
transform: translateX(100px);
|
|
2206
|
+
}
|
|
2207
|
+
to {
|
|
2208
|
+
opacity: 1;
|
|
2209
|
+
transform: translateX(0);
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
@keyframes pulse {
|
|
2214
|
+
0%, 100% {
|
|
2215
|
+
transform: scale(1);
|
|
2216
|
+
opacity: 0.4;
|
|
2217
|
+
}
|
|
2218
|
+
50% {
|
|
2219
|
+
transform: scale(1.1);
|
|
2220
|
+
opacity: 0.6;
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
`
|
|
2224
|
+
} })
|
|
2225
|
+
);
|
|
1553
2226
|
}
|
|
1554
2227
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1555
2228
|
0 && (module.exports = {
|
|
1556
|
-
|
|
2229
|
+
V402Checkout,
|
|
1557
2230
|
WalletConnect,
|
|
2231
|
+
usePageNetwork,
|
|
1558
2232
|
usePayment,
|
|
1559
2233
|
usePaymentInfo,
|
|
1560
2234
|
useWallet
|