@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.mjs
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
2
|
+
var __esm = (fn, res) => function __init() {
|
|
3
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
// src/types/common.ts
|
|
7
|
+
var PROD_BACK_URL, DEV_BACK_URL;
|
|
8
|
+
var init_common = __esm({
|
|
9
|
+
"src/types/common.ts"() {
|
|
10
|
+
"use strict";
|
|
11
|
+
PROD_BACK_URL = "https://v402.onvoyage.ai/api/pay";
|
|
12
|
+
DEV_BACK_URL = "http://localhost:3000/api/pay";
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// src/types/svm.ts
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
import { ExactSvmPayloadSchema } from "x402/types";
|
|
19
|
+
var SolanaNetworkSchema, SolanaPaymentPayloadSchema;
|
|
20
|
+
var init_svm = __esm({
|
|
21
|
+
"src/types/svm.ts"() {
|
|
22
|
+
"use strict";
|
|
23
|
+
SolanaNetworkSchema = z.enum([
|
|
24
|
+
"solana-devnet",
|
|
25
|
+
"solana",
|
|
26
|
+
"solana-mainnet"
|
|
27
|
+
// Alias for mainnet
|
|
28
|
+
]);
|
|
29
|
+
SolanaPaymentPayloadSchema = z.object({
|
|
30
|
+
x402Version: z.literal(1),
|
|
31
|
+
scheme: z.literal("exact"),
|
|
32
|
+
network: SolanaNetworkSchema,
|
|
33
|
+
payload: ExactSvmPayloadSchema
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// src/types/evm.ts
|
|
39
|
+
import { z as z2 } from "zod";
|
|
40
|
+
import { ExactEvmPayloadSchema } from "x402/types";
|
|
41
|
+
var EvmNetworkSchema, EvmPaymentPayloadSchema;
|
|
42
|
+
var init_evm = __esm({
|
|
43
|
+
"src/types/evm.ts"() {
|
|
44
|
+
"use strict";
|
|
45
|
+
EvmNetworkSchema = z2.enum([
|
|
46
|
+
"ethereum",
|
|
47
|
+
"sepolia",
|
|
48
|
+
"base",
|
|
49
|
+
"base-sepolia",
|
|
50
|
+
"polygon",
|
|
51
|
+
"arbitrum",
|
|
52
|
+
"optimism"
|
|
53
|
+
]);
|
|
54
|
+
EvmPaymentPayloadSchema = z2.object({
|
|
55
|
+
x402Version: z2.literal(1),
|
|
56
|
+
scheme: z2.literal("exact"),
|
|
57
|
+
network: EvmNetworkSchema,
|
|
58
|
+
payload: ExactEvmPayloadSchema
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
});
|
|
3
62
|
|
|
4
63
|
// src/types/index.ts
|
|
5
64
|
import {
|
|
@@ -9,53 +68,18 @@ import {
|
|
|
9
68
|
SettleResponseSchema,
|
|
10
69
|
SupportedPaymentKindSchema,
|
|
11
70
|
SupportedPaymentKindsResponseSchema,
|
|
12
|
-
ExactSvmPayloadSchema as ExactSvmPayloadSchema2,
|
|
13
|
-
ExactEvmPayloadSchema as ExactEvmPayloadSchema2,
|
|
14
71
|
SupportedSVMNetworks,
|
|
15
72
|
SvmNetworkToChainId
|
|
16
73
|
} from "x402/types";
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
import { ExactSvmPayloadSchema } from "x402/types";
|
|
24
|
-
var SolanaNetworkSchema = z.enum([
|
|
25
|
-
"solana-devnet",
|
|
26
|
-
"solana",
|
|
27
|
-
"solana-mainnet"
|
|
28
|
-
// Alias for mainnet
|
|
29
|
-
]);
|
|
30
|
-
var SolanaPaymentPayloadSchema = z.object({
|
|
31
|
-
x402Version: z.literal(1),
|
|
32
|
-
scheme: z.literal("exact"),
|
|
33
|
-
network: SolanaNetworkSchema,
|
|
34
|
-
payload: ExactSvmPayloadSchema
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// src/types/evm.ts
|
|
38
|
-
import { z as z2 } from "zod";
|
|
39
|
-
import { ExactEvmPayloadSchema } from "x402/types";
|
|
40
|
-
var EvmNetworkSchema = z2.enum([
|
|
41
|
-
"ethereum",
|
|
42
|
-
"sepolia",
|
|
43
|
-
"base",
|
|
44
|
-
"base-sepolia",
|
|
45
|
-
"polygon",
|
|
46
|
-
"arbitrum",
|
|
47
|
-
"optimism"
|
|
48
|
-
]);
|
|
49
|
-
var EvmPaymentPayloadSchema = z2.object({
|
|
50
|
-
x402Version: z2.literal(1),
|
|
51
|
-
scheme: z2.literal("exact"),
|
|
52
|
-
network: EvmNetworkSchema,
|
|
53
|
-
payload: ExactEvmPayloadSchema
|
|
74
|
+
var init_types = __esm({
|
|
75
|
+
"src/types/index.ts"() {
|
|
76
|
+
"use strict";
|
|
77
|
+
init_svm();
|
|
78
|
+
init_evm();
|
|
79
|
+
}
|
|
54
80
|
});
|
|
55
81
|
|
|
56
82
|
// src/utils/wallet.ts
|
|
57
|
-
var WALLET_DISCONNECTED_KEY = "wallet_manually_disconnected";
|
|
58
|
-
var CONNECTED_NETWORK_TYPE_KEY = "connected_network_type";
|
|
59
83
|
function isWalletInstalled(networkType) {
|
|
60
84
|
if (typeof window === "undefined") {
|
|
61
85
|
return false;
|
|
@@ -76,22 +100,50 @@ function formatAddress(address) {
|
|
|
76
100
|
}
|
|
77
101
|
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
|
78
102
|
}
|
|
79
|
-
function
|
|
103
|
+
function getDisconnectedNetworks() {
|
|
104
|
+
if (typeof window === "undefined") {
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const cached = localStorage.getItem(WALLET_DISCONNECTED_NETWORKS_KEY);
|
|
109
|
+
return cached ? JSON.parse(cached) : {};
|
|
110
|
+
} catch (error) {
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function markWalletDisconnected(networkType) {
|
|
80
115
|
if (typeof window !== "undefined") {
|
|
81
|
-
|
|
82
|
-
|
|
116
|
+
if (networkType) {
|
|
117
|
+
const disconnected = getDisconnectedNetworks();
|
|
118
|
+
disconnected[networkType] = true;
|
|
119
|
+
localStorage.setItem(WALLET_DISCONNECTED_NETWORKS_KEY, JSON.stringify(disconnected));
|
|
120
|
+
} else {
|
|
121
|
+
localStorage.setItem(WALLET_DISCONNECTED_KEY, "true");
|
|
122
|
+
localStorage.removeItem(CONNECTED_NETWORK_TYPE_KEY);
|
|
123
|
+
}
|
|
83
124
|
}
|
|
84
125
|
}
|
|
85
|
-
function clearWalletDisconnection() {
|
|
126
|
+
function clearWalletDisconnection(networkType) {
|
|
86
127
|
if (typeof window !== "undefined") {
|
|
87
|
-
|
|
128
|
+
if (networkType) {
|
|
129
|
+
const disconnected = getDisconnectedNetworks();
|
|
130
|
+
delete disconnected[networkType];
|
|
131
|
+
localStorage.setItem(WALLET_DISCONNECTED_NETWORKS_KEY, JSON.stringify(disconnected));
|
|
132
|
+
} else {
|
|
133
|
+
localStorage.removeItem(WALLET_DISCONNECTED_KEY);
|
|
134
|
+
}
|
|
88
135
|
}
|
|
89
136
|
}
|
|
90
|
-
function isWalletManuallyDisconnected() {
|
|
137
|
+
function isWalletManuallyDisconnected(networkType) {
|
|
91
138
|
if (typeof window === "undefined") {
|
|
92
139
|
return false;
|
|
93
140
|
}
|
|
94
|
-
|
|
141
|
+
if (networkType) {
|
|
142
|
+
const disconnected = getDisconnectedNetworks();
|
|
143
|
+
return disconnected[networkType] === true;
|
|
144
|
+
} else {
|
|
145
|
+
return localStorage.getItem(WALLET_DISCONNECTED_KEY) === "true";
|
|
146
|
+
}
|
|
95
147
|
}
|
|
96
148
|
function saveConnectedNetworkType(networkType) {
|
|
97
149
|
if (typeof window !== "undefined") {
|
|
@@ -116,8 +168,60 @@ function getWalletInstallUrl(networkType) {
|
|
|
116
168
|
return "#";
|
|
117
169
|
}
|
|
118
170
|
}
|
|
171
|
+
function getAllWalletAddresses() {
|
|
172
|
+
if (typeof window === "undefined") {
|
|
173
|
+
return {};
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
const cached = localStorage.getItem(WALLET_ADDRESSES_KEY);
|
|
177
|
+
return cached ? JSON.parse(cached) : {};
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.error("Failed to parse wallet addresses cache:", error);
|
|
180
|
+
return {};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function saveWalletAddress(networkType, address) {
|
|
184
|
+
if (typeof window === "undefined") {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const addresses = getAllWalletAddresses();
|
|
188
|
+
addresses[networkType] = address;
|
|
189
|
+
localStorage.setItem(WALLET_ADDRESSES_KEY, JSON.stringify(addresses));
|
|
190
|
+
}
|
|
191
|
+
function getCachedWalletAddress(networkType) {
|
|
192
|
+
const addresses = getAllWalletAddresses();
|
|
193
|
+
return addresses[networkType] || null;
|
|
194
|
+
}
|
|
195
|
+
function removeWalletAddress(networkType) {
|
|
196
|
+
if (typeof window === "undefined") {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const addresses = getAllWalletAddresses();
|
|
200
|
+
delete addresses[networkType];
|
|
201
|
+
localStorage.setItem(WALLET_ADDRESSES_KEY, JSON.stringify(addresses));
|
|
202
|
+
}
|
|
203
|
+
var WALLET_DISCONNECTED_KEY, WALLET_DISCONNECTED_NETWORKS_KEY, CONNECTED_NETWORK_TYPE_KEY, WALLET_ADDRESSES_KEY;
|
|
204
|
+
var init_wallet = __esm({
|
|
205
|
+
"src/utils/wallet.ts"() {
|
|
206
|
+
"use strict";
|
|
207
|
+
WALLET_DISCONNECTED_KEY = "wallet_manually_disconnected";
|
|
208
|
+
WALLET_DISCONNECTED_NETWORKS_KEY = "wallet_disconnected_networks";
|
|
209
|
+
CONNECTED_NETWORK_TYPE_KEY = "connected_network_type";
|
|
210
|
+
WALLET_ADDRESSES_KEY = "wallet_addresses_cache";
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// src/react/index.ts
|
|
215
|
+
import "./styles.css";
|
|
216
|
+
|
|
217
|
+
// src/react/hooks/useWalletStore.ts
|
|
218
|
+
import { useSyncExternalStore } from "react";
|
|
219
|
+
|
|
220
|
+
// src/utils/index.ts
|
|
221
|
+
init_wallet();
|
|
119
222
|
|
|
120
223
|
// src/utils/wallet-connect.ts
|
|
224
|
+
init_wallet();
|
|
121
225
|
async function connectWallet(networkType) {
|
|
122
226
|
if (typeof window === "undefined") {
|
|
123
227
|
throw new Error("\u8BF7\u5728\u6D4F\u89C8\u5668\u73AF\u5883\u4E2D\u4F7F\u7528");
|
|
@@ -152,13 +256,11 @@ async function connectWallet(networkType) {
|
|
|
152
256
|
default:
|
|
153
257
|
throw new Error("\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B");
|
|
154
258
|
}
|
|
155
|
-
clearWalletDisconnection();
|
|
259
|
+
clearWalletDisconnection(networkType);
|
|
156
260
|
saveConnectedNetworkType(networkType);
|
|
261
|
+
saveWalletAddress(networkType, address);
|
|
157
262
|
return address;
|
|
158
263
|
}
|
|
159
|
-
function disconnectWallet() {
|
|
160
|
-
markWalletDisconnected();
|
|
161
|
-
}
|
|
162
264
|
async function getCurrentWallet(networkType) {
|
|
163
265
|
if (typeof window === "undefined") {
|
|
164
266
|
return null;
|
|
@@ -167,28 +269,36 @@ async function getCurrentWallet(networkType) {
|
|
|
167
269
|
if (!type) {
|
|
168
270
|
return null;
|
|
169
271
|
}
|
|
272
|
+
const cachedAddress = getCachedWalletAddress(type);
|
|
170
273
|
try {
|
|
274
|
+
let currentAddress = null;
|
|
171
275
|
switch (type) {
|
|
172
276
|
case "evm" /* EVM */: {
|
|
173
|
-
if (!window.ethereum) return
|
|
277
|
+
if (!window.ethereum) return cachedAddress;
|
|
174
278
|
const accounts = await window.ethereum.request({
|
|
175
279
|
method: "eth_accounts",
|
|
176
280
|
params: []
|
|
177
281
|
});
|
|
178
|
-
|
|
282
|
+
currentAddress = accounts && accounts.length > 0 ? accounts[0] : null;
|
|
283
|
+
break;
|
|
179
284
|
}
|
|
180
285
|
case "solana" /* SOLANA */:
|
|
181
286
|
case "svm" /* SVM */: {
|
|
182
287
|
const solana = window.solana;
|
|
183
|
-
if (!solana || !solana.isConnected) return
|
|
184
|
-
|
|
288
|
+
if (!solana || !solana.isConnected) return cachedAddress;
|
|
289
|
+
currentAddress = solana.publicKey?.toString() || null;
|
|
290
|
+
break;
|
|
185
291
|
}
|
|
186
292
|
default:
|
|
187
|
-
return
|
|
293
|
+
return cachedAddress;
|
|
294
|
+
}
|
|
295
|
+
if (currentAddress && currentAddress !== cachedAddress) {
|
|
296
|
+
saveWalletAddress(type, currentAddress);
|
|
188
297
|
}
|
|
298
|
+
return currentAddress || cachedAddress;
|
|
189
299
|
} catch (error) {
|
|
190
300
|
console.error("Failed to get current wallet:", error);
|
|
191
|
-
return
|
|
301
|
+
return cachedAddress;
|
|
192
302
|
}
|
|
193
303
|
}
|
|
194
304
|
function onAccountsChanged(callback) {
|
|
@@ -239,6 +349,18 @@ function onWalletDisconnect(callback) {
|
|
|
239
349
|
solana.removeListener?.("disconnect", handler);
|
|
240
350
|
};
|
|
241
351
|
}
|
|
352
|
+
async function switchNetwork(networkType) {
|
|
353
|
+
const cachedAddress = getCachedWalletAddress(networkType);
|
|
354
|
+
if (cachedAddress) {
|
|
355
|
+
saveConnectedNetworkType(networkType);
|
|
356
|
+
clearWalletDisconnection(networkType);
|
|
357
|
+
const currentAddress = await getCurrentWallet(networkType);
|
|
358
|
+
if (currentAddress) {
|
|
359
|
+
return currentAddress;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
242
364
|
|
|
243
365
|
// src/services/svm/payment-header.ts
|
|
244
366
|
import {
|
|
@@ -330,12 +452,12 @@ async function createSvmPaymentHeader(params) {
|
|
|
330
452
|
)
|
|
331
453
|
);
|
|
332
454
|
const { blockhash } = await connection.getLatestBlockhash("confirmed");
|
|
333
|
-
const
|
|
455
|
+
const message2 = new TransactionMessage({
|
|
334
456
|
payerKey: feePayerPubkey,
|
|
335
457
|
recentBlockhash: blockhash,
|
|
336
458
|
instructions
|
|
337
459
|
}).compileToV0Message();
|
|
338
|
-
const transaction = new VersionedTransaction(
|
|
460
|
+
const transaction = new VersionedTransaction(message2);
|
|
339
461
|
if (typeof wallet?.signTransaction !== "function") {
|
|
340
462
|
throw new Error("Connected wallet does not support signTransaction");
|
|
341
463
|
}
|
|
@@ -370,6 +492,7 @@ function getDefaultSolanaRpcUrl(network) {
|
|
|
370
492
|
}
|
|
371
493
|
|
|
372
494
|
// src/services/svm/payment-handler.ts
|
|
495
|
+
init_types();
|
|
373
496
|
async function handleSvmPayment(endpoint, config, requestInit) {
|
|
374
497
|
const { wallet, network, rpcUrl, maxPaymentAmount } = config;
|
|
375
498
|
const initialResponse = await fetch(endpoint, {
|
|
@@ -394,7 +517,8 @@ async function handleSvmPayment(endpoint, config, requestInit) {
|
|
|
394
517
|
"already_used": "This payment has already been used",
|
|
395
518
|
"network_mismatch": "Payment network does not match",
|
|
396
519
|
"invalid_payment": "Invalid payment data",
|
|
397
|
-
"verification_failed": "Payment verification failed"
|
|
520
|
+
"verification_failed": "Payment verification failed",
|
|
521
|
+
"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."
|
|
398
522
|
};
|
|
399
523
|
const errorMessage = ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
|
|
400
524
|
const error = new Error(errorMessage);
|
|
@@ -462,7 +586,8 @@ async function handleSvmPayment(endpoint, config, requestInit) {
|
|
|
462
586
|
"already_used": "This payment has already been used",
|
|
463
587
|
"network_mismatch": "Payment network does not match",
|
|
464
588
|
"invalid_payment": "Invalid payment data",
|
|
465
|
-
"verification_failed": "Payment verification failed"
|
|
589
|
+
"verification_failed": "Payment verification failed",
|
|
590
|
+
"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."
|
|
466
591
|
};
|
|
467
592
|
const errorMessage = ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
|
|
468
593
|
const error = new Error(errorMessage);
|
|
@@ -592,6 +717,7 @@ function getChainIdFromNetwork(network) {
|
|
|
592
717
|
}
|
|
593
718
|
|
|
594
719
|
// src/services/evm/payment-handler.ts
|
|
720
|
+
init_types();
|
|
595
721
|
async function handleEvmPayment(endpoint, config, requestInit) {
|
|
596
722
|
const { wallet, network, maxPaymentAmount } = config;
|
|
597
723
|
const initialResponse = await fetch(endpoint, {
|
|
@@ -761,6 +887,7 @@ async function handleEvmPayment(endpoint, config, requestInit) {
|
|
|
761
887
|
}
|
|
762
888
|
|
|
763
889
|
// src/utils/payment-helpers.ts
|
|
890
|
+
init_common();
|
|
764
891
|
import { ethers as ethers2 } from "ethers";
|
|
765
892
|
function parsePaymentRequired(response) {
|
|
766
893
|
if (response && typeof response === "object") {
|
|
@@ -785,9 +912,15 @@ function getSupportedNetworkTypes(paymentRequirements) {
|
|
|
785
912
|
});
|
|
786
913
|
return Array.from(networkTypes);
|
|
787
914
|
}
|
|
788
|
-
async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL) {
|
|
789
|
-
|
|
915
|
+
async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, additionalParams) {
|
|
916
|
+
const fullEndpoint = `${endpoint}/${merchantId}`;
|
|
790
917
|
let response;
|
|
918
|
+
const requestInit = additionalParams && Object.keys(additionalParams).length > 0 ? {
|
|
919
|
+
body: JSON.stringify(additionalParams),
|
|
920
|
+
headers: {
|
|
921
|
+
"Content-Type": "application/json"
|
|
922
|
+
}
|
|
923
|
+
} : {};
|
|
791
924
|
if (networkType === "solana" /* SOLANA */ || networkType === "svm" /* SVM */) {
|
|
792
925
|
const solana = window.solana;
|
|
793
926
|
if (!solana) {
|
|
@@ -796,11 +929,11 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL) {
|
|
|
796
929
|
if (!solana.isConnected) {
|
|
797
930
|
await solana.connect();
|
|
798
931
|
}
|
|
799
|
-
response = await handleSvmPayment(
|
|
932
|
+
response = await handleSvmPayment(fullEndpoint, {
|
|
800
933
|
wallet: solana,
|
|
801
934
|
network: "solana"
|
|
802
935
|
// Will use backend's network configuration
|
|
803
|
-
});
|
|
936
|
+
}, requestInit);
|
|
804
937
|
} else if (networkType === "evm" /* EVM */) {
|
|
805
938
|
if (!window.ethereum) {
|
|
806
939
|
throw new Error("\u8BF7\u5B89\u88C5 MetaMask \u94B1\u5305");
|
|
@@ -809,8 +942,8 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL) {
|
|
|
809
942
|
const signer = await provider.getSigner();
|
|
810
943
|
const wallet = {
|
|
811
944
|
address: await signer.getAddress(),
|
|
812
|
-
signTypedData: async (domain, types,
|
|
813
|
-
return await signer.signTypedData(domain, types,
|
|
945
|
+
signTypedData: async (domain, types, message2) => {
|
|
946
|
+
return await signer.signTypedData(domain, types, message2);
|
|
814
947
|
},
|
|
815
948
|
// Get current chain ID from wallet
|
|
816
949
|
getChainId: async () => {
|
|
@@ -825,35 +958,16 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL) {
|
|
|
825
958
|
});
|
|
826
959
|
}
|
|
827
960
|
};
|
|
828
|
-
response = await handleEvmPayment(
|
|
961
|
+
response = await handleEvmPayment(fullEndpoint, {
|
|
829
962
|
wallet,
|
|
830
963
|
network: "base"
|
|
831
964
|
// Will use backend's network configuration
|
|
832
|
-
});
|
|
965
|
+
}, requestInit);
|
|
833
966
|
} else {
|
|
834
967
|
throw new Error(`\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B: ${networkType}`);
|
|
835
968
|
}
|
|
836
969
|
return response;
|
|
837
970
|
}
|
|
838
|
-
async function handlePayment(endpoint, networkType, callbacks) {
|
|
839
|
-
try {
|
|
840
|
-
callbacks?.onStart?.();
|
|
841
|
-
const response = await makePayment(networkType, "", endpoint);
|
|
842
|
-
if (!response.ok) {
|
|
843
|
-
const errorText = await response.text();
|
|
844
|
-
throw new Error(`\u8BF7\u6C42\u5931\u8D25 (${response.status}): ${errorText}`);
|
|
845
|
-
}
|
|
846
|
-
const result = await response.json();
|
|
847
|
-
callbacks?.onSuccess?.(result);
|
|
848
|
-
return result;
|
|
849
|
-
} catch (err) {
|
|
850
|
-
const errorMessage = err.message || "\u652F\u4ED8\u5931\u8D25";
|
|
851
|
-
callbacks?.onError?.(errorMessage);
|
|
852
|
-
throw err;
|
|
853
|
-
} finally {
|
|
854
|
-
callbacks?.onFinish?.();
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
971
|
|
|
858
972
|
// src/utils/network.ts
|
|
859
973
|
var NETWORK_TYPE_MAP = {
|
|
@@ -877,6 +991,7 @@ var NETWORK_TYPE_MAP = {
|
|
|
877
991
|
};
|
|
878
992
|
function getNetworkDisplayName(network) {
|
|
879
993
|
const displayNames = {
|
|
994
|
+
"evm": "EVM",
|
|
880
995
|
"ethereum": "Ethereum",
|
|
881
996
|
"sepolia": "Sepolia Testnet",
|
|
882
997
|
"base": "Base",
|
|
@@ -1039,60 +1154,28 @@ var WalletStore = class {
|
|
|
1039
1154
|
init() {
|
|
1040
1155
|
if (this.initialized) return;
|
|
1041
1156
|
this.initialized = true;
|
|
1042
|
-
this.autoReconnect();
|
|
1043
1157
|
onAccountsChanged((accounts) => {
|
|
1044
|
-
|
|
1045
|
-
if (connectedType === "evm" /* EVM */) {
|
|
1158
|
+
if (this.state.networkType === "evm" /* EVM */) {
|
|
1046
1159
|
if (accounts.length === 0) {
|
|
1047
1160
|
this.setState({ address: null });
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
this.setState({ address: accounts[0] });
|
|
1052
|
-
console.log("\u{1F504} Account changed:", accounts[0]);
|
|
1053
|
-
}
|
|
1161
|
+
} else if (!isWalletManuallyDisconnected("evm" /* EVM */)) {
|
|
1162
|
+
this.setState({ address: accounts[0] });
|
|
1163
|
+
saveWalletAddress("evm" /* EVM */, accounts[0]);
|
|
1054
1164
|
}
|
|
1055
1165
|
}
|
|
1056
1166
|
});
|
|
1057
1167
|
onChainChanged(() => {
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
console.log("\u26A0\uFE0F Network changed detected - disconnecting wallet");
|
|
1061
|
-
disconnectWallet();
|
|
1062
|
-
this.setState({
|
|
1063
|
-
address: null,
|
|
1064
|
-
networkType: null,
|
|
1065
|
-
error: "Network changed. Please reconnect your wallet."
|
|
1066
|
-
});
|
|
1168
|
+
if (this.state.networkType === "evm" /* EVM */) {
|
|
1169
|
+
this.handleDisconnect("evm" /* EVM */, "Chain changed. Please reconnect your wallet.");
|
|
1067
1170
|
}
|
|
1068
1171
|
});
|
|
1069
1172
|
onWalletDisconnect(() => {
|
|
1070
|
-
const
|
|
1071
|
-
if (
|
|
1072
|
-
|
|
1073
|
-
disconnectWallet();
|
|
1074
|
-
this.setState({
|
|
1075
|
-
address: null,
|
|
1076
|
-
networkType: null
|
|
1077
|
-
});
|
|
1173
|
+
const svmTypes = ["solana" /* SOLANA */, "svm" /* SVM */];
|
|
1174
|
+
if (this.state.networkType && svmTypes.includes(this.state.networkType)) {
|
|
1175
|
+
this.handleDisconnect(this.state.networkType);
|
|
1078
1176
|
}
|
|
1079
1177
|
});
|
|
1080
1178
|
}
|
|
1081
|
-
async autoReconnect() {
|
|
1082
|
-
if (!isWalletManuallyDisconnected()) {
|
|
1083
|
-
const connectedType = getConnectedNetworkType();
|
|
1084
|
-
if (connectedType) {
|
|
1085
|
-
const currentAddress = await getCurrentWallet(connectedType);
|
|
1086
|
-
if (currentAddress) {
|
|
1087
|
-
this.setState({
|
|
1088
|
-
address: currentAddress,
|
|
1089
|
-
networkType: connectedType
|
|
1090
|
-
});
|
|
1091
|
-
console.log("\u{1F504} Auto-reconnected wallet:", currentAddress);
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
1179
|
// Get current state
|
|
1097
1180
|
getState() {
|
|
1098
1181
|
return this.state;
|
|
@@ -1113,18 +1196,32 @@ var WalletStore = class {
|
|
|
1113
1196
|
notifyListeners() {
|
|
1114
1197
|
this.listeners.forEach((listener) => listener());
|
|
1115
1198
|
}
|
|
1199
|
+
// Handle wallet disconnect (internal helper)
|
|
1200
|
+
handleDisconnect(networkType, error) {
|
|
1201
|
+
removeWalletAddress(networkType);
|
|
1202
|
+
markWalletDisconnected(networkType);
|
|
1203
|
+
if (typeof window !== "undefined") {
|
|
1204
|
+
localStorage.removeItem("connected_network_type");
|
|
1205
|
+
}
|
|
1206
|
+
this.setState({
|
|
1207
|
+
address: null,
|
|
1208
|
+
networkType: null,
|
|
1209
|
+
error: error || null
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1116
1212
|
// Connect wallet
|
|
1117
1213
|
async connect(type) {
|
|
1214
|
+
if (this.state.address && this.state.networkType && this.state.networkType !== type) {
|
|
1215
|
+
saveWalletAddress(this.state.networkType, this.state.address);
|
|
1216
|
+
}
|
|
1118
1217
|
this.setState({ isConnecting: true, error: null });
|
|
1119
1218
|
try {
|
|
1120
1219
|
const walletAddress = await connectWallet(type);
|
|
1121
|
-
console.log("\u2705 Wallet connected:", walletAddress, "Network:", type);
|
|
1122
1220
|
this.setState({
|
|
1123
1221
|
address: walletAddress,
|
|
1124
1222
|
networkType: type,
|
|
1125
1223
|
isConnecting: false
|
|
1126
1224
|
});
|
|
1127
|
-
console.log("\u{1F4DD} Store state updated");
|
|
1128
1225
|
} catch (err) {
|
|
1129
1226
|
this.setState({
|
|
1130
1227
|
error: err.message || "Failed to connect wallet",
|
|
@@ -1133,20 +1230,67 @@ var WalletStore = class {
|
|
|
1133
1230
|
throw err;
|
|
1134
1231
|
}
|
|
1135
1232
|
}
|
|
1233
|
+
// Switch network (use cached wallet if available)
|
|
1234
|
+
async switchNetwork(type) {
|
|
1235
|
+
if (this.state.address && this.state.networkType) {
|
|
1236
|
+
saveWalletAddress(this.state.networkType, this.state.address);
|
|
1237
|
+
}
|
|
1238
|
+
this.setState({ isConnecting: true, error: null });
|
|
1239
|
+
try {
|
|
1240
|
+
const address = await switchNetwork(type);
|
|
1241
|
+
if (address) {
|
|
1242
|
+
this.setState({
|
|
1243
|
+
address,
|
|
1244
|
+
networkType: type,
|
|
1245
|
+
isConnecting: false
|
|
1246
|
+
});
|
|
1247
|
+
} else {
|
|
1248
|
+
this.setState({
|
|
1249
|
+
address: null,
|
|
1250
|
+
networkType: type,
|
|
1251
|
+
isConnecting: true
|
|
1252
|
+
});
|
|
1253
|
+
await this.connect(type);
|
|
1254
|
+
}
|
|
1255
|
+
} catch (err) {
|
|
1256
|
+
this.setState({
|
|
1257
|
+
error: err.message || "Failed to switch network",
|
|
1258
|
+
isConnecting: false
|
|
1259
|
+
});
|
|
1260
|
+
throw err;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1136
1263
|
// Disconnect wallet
|
|
1137
1264
|
disconnect() {
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1265
|
+
const currentNetwork = this.state.networkType;
|
|
1266
|
+
if (currentNetwork) {
|
|
1267
|
+
this.handleDisconnect(currentNetwork);
|
|
1268
|
+
} else {
|
|
1269
|
+
this.setState({
|
|
1270
|
+
address: null,
|
|
1271
|
+
networkType: null,
|
|
1272
|
+
error: null
|
|
1273
|
+
});
|
|
1274
|
+
}
|
|
1145
1275
|
}
|
|
1146
1276
|
// Clear error
|
|
1147
1277
|
clearError() {
|
|
1148
1278
|
this.setState({ error: null });
|
|
1149
1279
|
}
|
|
1280
|
+
// Ensure network matches expected type (for page-specific network requirements)
|
|
1281
|
+
async ensureNetwork(expectedNetwork) {
|
|
1282
|
+
if (isWalletManuallyDisconnected(expectedNetwork)) {
|
|
1283
|
+
return;
|
|
1284
|
+
}
|
|
1285
|
+
if (this.state.networkType === expectedNetwork && this.state.address) {
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1288
|
+
if (this.state.networkType !== expectedNetwork) {
|
|
1289
|
+
await this.switchNetwork(expectedNetwork);
|
|
1290
|
+
} else if (!this.state.address) {
|
|
1291
|
+
await this.connect(expectedNetwork);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1150
1294
|
};
|
|
1151
1295
|
var walletStore = new WalletStore();
|
|
1152
1296
|
if (typeof window !== "undefined") {
|
|
@@ -1164,11 +1308,30 @@ function useWallet() {
|
|
|
1164
1308
|
return {
|
|
1165
1309
|
...state,
|
|
1166
1310
|
connect: (type) => walletStore.connect(type),
|
|
1311
|
+
switchNetwork: (type) => walletStore.switchNetwork(type),
|
|
1312
|
+
ensureNetwork: (type) => walletStore.ensureNetwork(type),
|
|
1167
1313
|
disconnect: () => walletStore.disconnect(),
|
|
1168
1314
|
clearError: () => walletStore.clearError()
|
|
1169
1315
|
};
|
|
1170
1316
|
}
|
|
1171
1317
|
|
|
1318
|
+
// src/react/hooks/usePageNetwork.ts
|
|
1319
|
+
import { useEffect } from "react";
|
|
1320
|
+
function usePageNetwork(expectedNetwork, options = {}) {
|
|
1321
|
+
const {
|
|
1322
|
+
autoSwitch = true,
|
|
1323
|
+
switchOnMount = true
|
|
1324
|
+
} = options;
|
|
1325
|
+
const wallet = useWallet();
|
|
1326
|
+
useEffect(() => {
|
|
1327
|
+
if (!autoSwitch || !switchOnMount) return;
|
|
1328
|
+
wallet.ensureNetwork(expectedNetwork).catch((err) => {
|
|
1329
|
+
console.error("Failed to ensure network:", err);
|
|
1330
|
+
});
|
|
1331
|
+
}, [expectedNetwork]);
|
|
1332
|
+
return wallet;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1172
1335
|
// src/react/hooks/usePayment.ts
|
|
1173
1336
|
import { useCallback, useState } from "react";
|
|
1174
1337
|
function usePayment() {
|
|
@@ -1200,8 +1363,9 @@ function usePayment() {
|
|
|
1200
1363
|
}
|
|
1201
1364
|
|
|
1202
1365
|
// src/react/hooks/usePaymentInfo.ts
|
|
1203
|
-
import { useEffect, useState as useState2 } from "react";
|
|
1204
|
-
|
|
1366
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
1367
|
+
init_common();
|
|
1368
|
+
function usePaymentInfo(merchantId, endpoint = PROD_BACK_URL, additionalParams) {
|
|
1205
1369
|
const [paymentInfo, setPaymentInfo] = useState2(null);
|
|
1206
1370
|
const [supportedNetworks, setSupportedNetworks] = useState2([]);
|
|
1207
1371
|
const [isLoading, setIsLoading] = useState2(true);
|
|
@@ -1210,8 +1374,17 @@ function usePaymentInfo(merchantId, endpoint = PROD_BACK_URL) {
|
|
|
1210
1374
|
setIsLoading(true);
|
|
1211
1375
|
setError(null);
|
|
1212
1376
|
try {
|
|
1213
|
-
|
|
1214
|
-
const
|
|
1377
|
+
const fullEndpoint = `${endpoint}/${merchantId}`;
|
|
1378
|
+
const requestInit = {
|
|
1379
|
+
method: "POST",
|
|
1380
|
+
...additionalParams && Object.keys(additionalParams).length > 0 ? {
|
|
1381
|
+
body: JSON.stringify(additionalParams),
|
|
1382
|
+
headers: {
|
|
1383
|
+
"Content-Type": "application/json"
|
|
1384
|
+
}
|
|
1385
|
+
} : {}
|
|
1386
|
+
};
|
|
1387
|
+
const response = await fetch(fullEndpoint, requestInit);
|
|
1215
1388
|
if (response.status === 402) {
|
|
1216
1389
|
const body = await response.json();
|
|
1217
1390
|
const payment = parsePaymentRequired(body);
|
|
@@ -1230,9 +1403,9 @@ function usePaymentInfo(merchantId, endpoint = PROD_BACK_URL) {
|
|
|
1230
1403
|
setIsLoading(false);
|
|
1231
1404
|
}
|
|
1232
1405
|
};
|
|
1233
|
-
|
|
1406
|
+
useEffect2(() => {
|
|
1234
1407
|
fetchPaymentInfo();
|
|
1235
|
-
}, [endpoint]);
|
|
1408
|
+
}, [endpoint, merchantId]);
|
|
1236
1409
|
return {
|
|
1237
1410
|
paymentInfo,
|
|
1238
1411
|
supportedNetworks,
|
|
@@ -1335,12 +1508,21 @@ var baseButtonStyle = {
|
|
|
1335
1508
|
};
|
|
1336
1509
|
var getConnectButtonStyle = (isDisabled, isHovered) => {
|
|
1337
1510
|
const c = getColors();
|
|
1511
|
+
const darkMode = isDarkMode();
|
|
1512
|
+
if (isDisabled) {
|
|
1513
|
+
return {
|
|
1514
|
+
...baseButtonStyle,
|
|
1515
|
+
background: c.disabled,
|
|
1516
|
+
color: c.disabledText,
|
|
1517
|
+
cursor: "not-allowed",
|
|
1518
|
+
border: darkMode ? "1px solid #404040" : "1px solid #d4d4d4"
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1338
1521
|
return {
|
|
1339
1522
|
...baseButtonStyle,
|
|
1340
|
-
background:
|
|
1341
|
-
color:
|
|
1342
|
-
cursor:
|
|
1343
|
-
opacity: isDisabled ? 0.5 : 1
|
|
1523
|
+
background: isHovered ? c.primaryHover : c.primary,
|
|
1524
|
+
color: darkMode ? "#000000" : "#ffffff",
|
|
1525
|
+
cursor: "pointer"
|
|
1344
1526
|
};
|
|
1345
1527
|
};
|
|
1346
1528
|
var getDisconnectButtonStyle = (isHovered) => {
|
|
@@ -1351,17 +1533,6 @@ var getDisconnectButtonStyle = (isHovered) => {
|
|
|
1351
1533
|
color: "#ffffff"
|
|
1352
1534
|
};
|
|
1353
1535
|
};
|
|
1354
|
-
var getPayButtonStyle = (isDisabled, isHovered) => {
|
|
1355
|
-
const c = getColors();
|
|
1356
|
-
return {
|
|
1357
|
-
...baseButtonStyle,
|
|
1358
|
-
background: isDisabled ? c.disabled : isHovered ? c.successHover : c.success,
|
|
1359
|
-
color: "#ffffff",
|
|
1360
|
-
width: "100%",
|
|
1361
|
-
cursor: isDisabled ? "not-allowed" : "pointer",
|
|
1362
|
-
opacity: isDisabled ? 0.5 : 1
|
|
1363
|
-
};
|
|
1364
|
-
};
|
|
1365
1536
|
var getInstallLinkStyle = (isHovered) => {
|
|
1366
1537
|
const c = getColors();
|
|
1367
1538
|
return {
|
|
@@ -1446,7 +1617,7 @@ function WalletConnect({
|
|
|
1446
1617
|
disconnect();
|
|
1447
1618
|
onDisconnect?.();
|
|
1448
1619
|
};
|
|
1449
|
-
return /* @__PURE__ */ React.createElement("div", { style: { ...containerStyle, ...className ? {} : {} }, className }, !address ? /* @__PURE__ */ React.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ React.createElement("h3", { style: getTitleStyle() }, "Connect Wallet"), supportedNetworks.length === 0 ? /* @__PURE__ */ React.createElement("p", { style: getHintStyle() }, "
|
|
1620
|
+
return /* @__PURE__ */ React.createElement("div", { style: { ...containerStyle, ...className ? {} : {} }, className }, !address ? /* @__PURE__ */ React.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ React.createElement("h3", { style: getTitleStyle() }, "Connect Wallet"), supportedNetworks.length === 0 ? /* @__PURE__ */ React.createElement("p", { style: getHintStyle() }, "Please install a supported wallet extension") : /* @__PURE__ */ React.createElement("div", { style: buttonsContainerStyle }, supportedNetworks.map((network) => {
|
|
1450
1621
|
const installed = isWalletInstalled(network);
|
|
1451
1622
|
return /* @__PURE__ */ React.createElement("div", { key: network, style: walletOptionStyle }, /* @__PURE__ */ React.createElement(
|
|
1452
1623
|
"button",
|
|
@@ -1482,61 +1653,571 @@ function WalletConnect({
|
|
|
1482
1653
|
)), /* @__PURE__ */ React.createElement("p", { style: getHintStyle() }, "Switch account in your wallet to change address")));
|
|
1483
1654
|
}
|
|
1484
1655
|
|
|
1485
|
-
// src/react/components/
|
|
1486
|
-
import
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1656
|
+
// src/react/components/V402Checkout.tsx
|
|
1657
|
+
import React3, { useEffect as useEffect3, useState as useState4 } from "react";
|
|
1658
|
+
import { Button, Card, Divider, message, Spin, Tooltip, Typography } from "antd";
|
|
1659
|
+
import {
|
|
1660
|
+
DisconnectOutlined,
|
|
1661
|
+
InfoCircleOutlined,
|
|
1662
|
+
LinkOutlined,
|
|
1663
|
+
LoadingOutlined,
|
|
1664
|
+
LockOutlined,
|
|
1665
|
+
SafetyOutlined
|
|
1666
|
+
} from "@ant-design/icons";
|
|
1667
|
+
init_common();
|
|
1668
|
+
|
|
1669
|
+
// src/react/utils/CryptoIcons.tsx
|
|
1670
|
+
import React2 from "react";
|
|
1671
|
+
var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
|
|
1672
|
+
return /* @__PURE__ */ React2.createElement(
|
|
1673
|
+
"svg",
|
|
1674
|
+
{
|
|
1675
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1676
|
+
viewBox: "0 0 16 16",
|
|
1677
|
+
width,
|
|
1678
|
+
height,
|
|
1679
|
+
className,
|
|
1680
|
+
style
|
|
1681
|
+
},
|
|
1682
|
+
/* @__PURE__ */ React2.createElement("desc", null, "Solana SOL Fill Streamline Icon: https://streamlinehq.com"),
|
|
1683
|
+
/* @__PURE__ */ React2.createElement("g", { fill: "none", fillRule: "evenodd" }, /* @__PURE__ */ React2.createElement(
|
|
1684
|
+
"path",
|
|
1685
|
+
{
|
|
1686
|
+
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",
|
|
1687
|
+
strokeWidth: "0.6667"
|
|
1688
|
+
}
|
|
1689
|
+
), /* @__PURE__ */ React2.createElement(
|
|
1690
|
+
"path",
|
|
1691
|
+
{
|
|
1692
|
+
fill: "#000000",
|
|
1693
|
+
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",
|
|
1694
|
+
strokeWidth: "0.6667"
|
|
1695
|
+
}
|
|
1696
|
+
))
|
|
1697
|
+
);
|
|
1698
|
+
};
|
|
1699
|
+
var BaseIcon = ({ width = 24, height = 24, className, style }) => {
|
|
1700
|
+
return /* @__PURE__ */ React2.createElement(
|
|
1701
|
+
"svg",
|
|
1702
|
+
{
|
|
1703
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1704
|
+
viewBox: "0 0 24 24",
|
|
1705
|
+
fill: "none",
|
|
1706
|
+
stroke: "#000000",
|
|
1707
|
+
strokeLinecap: "round",
|
|
1708
|
+
strokeLinejoin: "round",
|
|
1709
|
+
width,
|
|
1710
|
+
height,
|
|
1711
|
+
className,
|
|
1712
|
+
style
|
|
1713
|
+
},
|
|
1714
|
+
/* @__PURE__ */ React2.createElement("desc", null, "Brand Coinbase Streamline Icon: https://streamlinehq.com"),
|
|
1715
|
+
/* @__PURE__ */ React2.createElement(
|
|
1716
|
+
"path",
|
|
1717
|
+
{
|
|
1718
|
+
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",
|
|
1719
|
+
strokeWidth: "2"
|
|
1720
|
+
}
|
|
1721
|
+
)
|
|
1722
|
+
);
|
|
1723
|
+
};
|
|
1724
|
+
var getNetworkIcon = (network) => {
|
|
1725
|
+
const networkLower = network.toLowerCase();
|
|
1726
|
+
if (networkLower.includes("solana")) {
|
|
1727
|
+
return SolanaIcon;
|
|
1728
|
+
}
|
|
1729
|
+
if (networkLower.includes("base")) {
|
|
1730
|
+
return BaseIcon;
|
|
1731
|
+
}
|
|
1732
|
+
return BaseIcon;
|
|
1733
|
+
};
|
|
1734
|
+
|
|
1735
|
+
// src/react/components/V402Checkout.tsx
|
|
1736
|
+
var { Title, Text } = Typography;
|
|
1737
|
+
var notify = {
|
|
1738
|
+
success: (title, msg) => {
|
|
1739
|
+
message.success(`${title}: ${msg}`);
|
|
1740
|
+
},
|
|
1741
|
+
error: (title, msg) => {
|
|
1742
|
+
message.error(`${title}: ${msg}`);
|
|
1743
|
+
},
|
|
1744
|
+
info: (title, msg) => {
|
|
1745
|
+
message.info(`${title}: ${msg}`);
|
|
1746
|
+
}
|
|
1747
|
+
};
|
|
1748
|
+
function V402Checkout({
|
|
1749
|
+
merchantId,
|
|
1750
|
+
headerInfo = {},
|
|
1751
|
+
isModal = false,
|
|
1752
|
+
onPaymentComplete,
|
|
1753
|
+
additionalParams = {},
|
|
1754
|
+
expectedNetwork
|
|
1496
1755
|
}) {
|
|
1497
|
-
const {
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1756
|
+
const {
|
|
1757
|
+
title = "V402Pay - Make x402Pay Easier",
|
|
1758
|
+
subtitle = "onvoyage.ai",
|
|
1759
|
+
tooltipText = "V402Pay - Accept Crypto Payments Easier"
|
|
1760
|
+
} = headerInfo;
|
|
1761
|
+
let endpoint = DEV_BACK_URL;
|
|
1762
|
+
const {
|
|
1763
|
+
supportedNetworks,
|
|
1764
|
+
isLoading: fetchingPaymentInfo,
|
|
1765
|
+
paymentInfo
|
|
1766
|
+
} = usePaymentInfo(merchantId, endpoint, additionalParams);
|
|
1767
|
+
const targetNetwork = expectedNetwork || supportedNetworks[0];
|
|
1768
|
+
const { address, networkType, disconnect, ensureNetwork } = usePageNetwork(
|
|
1769
|
+
targetNetwork,
|
|
1770
|
+
{ autoSwitch: !!targetNetwork, switchOnMount: true }
|
|
1771
|
+
);
|
|
1772
|
+
const { isProcessing, setIsProcessing, result, setResult, error, setError } = usePayment();
|
|
1773
|
+
const [paymentDetails, setPaymentDetails] = useState4(null);
|
|
1774
|
+
const handleDisconnect = () => {
|
|
1775
|
+
disconnect();
|
|
1776
|
+
setResult(null);
|
|
1777
|
+
setError(null);
|
|
1778
|
+
notify.info("Wallet Disconnected", "Your wallet has been disconnected successfully.");
|
|
1779
|
+
};
|
|
1780
|
+
useEffect3(() => {
|
|
1781
|
+
if (paymentInfo && paymentInfo.length > 0) {
|
|
1782
|
+
const firstPayment = paymentInfo[0];
|
|
1783
|
+
const rawAmount = firstPayment.maxAmountRequired?.toString() || "0";
|
|
1784
|
+
const decimals = 6;
|
|
1785
|
+
const humanReadableAmount = (Number(rawAmount) / Math.pow(10, decimals)).toFixed(2);
|
|
1786
|
+
const network = firstPayment.network || "Unknown";
|
|
1787
|
+
const currency = "USDC";
|
|
1788
|
+
setPaymentDetails({
|
|
1789
|
+
amount: humanReadableAmount,
|
|
1790
|
+
currency,
|
|
1791
|
+
network
|
|
1792
|
+
});
|
|
1793
|
+
}
|
|
1794
|
+
}, [paymentInfo]);
|
|
1795
|
+
useEffect3(() => {
|
|
1796
|
+
if (targetNetwork && !fetchingPaymentInfo && ensureNetwork) {
|
|
1797
|
+
ensureNetwork(targetNetwork).catch((err) => {
|
|
1798
|
+
console.error("Failed to ensure network:", err);
|
|
1799
|
+
});
|
|
1800
|
+
}
|
|
1801
|
+
}, [targetNetwork, fetchingPaymentInfo]);
|
|
1802
|
+
const handlePayment = async () => {
|
|
1501
1803
|
if (!networkType) {
|
|
1502
|
-
|
|
1503
|
-
setError(errorMsg);
|
|
1504
|
-
onError?.(errorMsg);
|
|
1804
|
+
notify.error("Wallet Not Connected", "Please connect your wallet first.");
|
|
1505
1805
|
return;
|
|
1506
1806
|
}
|
|
1807
|
+
setResult(null);
|
|
1808
|
+
setError(null);
|
|
1809
|
+
setIsProcessing(true);
|
|
1507
1810
|
try {
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1811
|
+
const response = await makePayment(networkType, merchantId, endpoint, additionalParams);
|
|
1812
|
+
const data = await response.json();
|
|
1813
|
+
setResult(data);
|
|
1814
|
+
notify.success("Payment Successful!", "Your payment has been processed successfully.");
|
|
1815
|
+
if (onPaymentComplete) {
|
|
1816
|
+
onPaymentComplete(data);
|
|
1817
|
+
}
|
|
1514
1818
|
} catch (err) {
|
|
1515
|
-
const
|
|
1516
|
-
setError(
|
|
1517
|
-
|
|
1819
|
+
const errorMessage = err.message || "Payment failed";
|
|
1820
|
+
setError(errorMessage);
|
|
1821
|
+
notify.error("Payment Failed", errorMessage);
|
|
1518
1822
|
} finally {
|
|
1519
1823
|
setIsProcessing(false);
|
|
1520
|
-
onFinish?.();
|
|
1521
1824
|
}
|
|
1522
1825
|
};
|
|
1523
|
-
const
|
|
1524
|
-
|
|
1525
|
-
"
|
|
1826
|
+
const getNetworkColor = (network) => {
|
|
1827
|
+
if (network.toLowerCase().includes("solana")) return "#14F195";
|
|
1828
|
+
if (network.toLowerCase().includes("evm") || network.toLowerCase().includes("base")) return "#0052FF";
|
|
1829
|
+
return "#8c8c8c";
|
|
1830
|
+
};
|
|
1831
|
+
const NetworkIcon = paymentDetails ? getNetworkIcon(paymentDetails.network) : null;
|
|
1832
|
+
const networkColor = paymentDetails ? getNetworkColor(paymentDetails.network) : "#8c8c8c";
|
|
1833
|
+
const loadingColor = "#8c8c8c";
|
|
1834
|
+
const hasInvalidCheckoutId = !fetchingPaymentInfo && (!paymentInfo || paymentInfo.length === 0);
|
|
1835
|
+
return /* @__PURE__ */ React3.createElement(
|
|
1836
|
+
"div",
|
|
1526
1837
|
{
|
|
1527
|
-
|
|
1528
|
-
className,
|
|
1529
|
-
onClick: handleClick,
|
|
1530
|
-
disabled: isDisabled,
|
|
1531
|
-
onMouseEnter: () => setIsHovered(true),
|
|
1532
|
-
onMouseLeave: () => setIsHovered(false)
|
|
1838
|
+
className: isModal ? "bg-white" : "h-screen bg-white flex items-center justify-center p-4 overflow-hidden"
|
|
1533
1839
|
},
|
|
1534
|
-
|
|
1535
|
-
|
|
1840
|
+
/* @__PURE__ */ React3.createElement(
|
|
1841
|
+
"div",
|
|
1842
|
+
{
|
|
1843
|
+
className: "flex gap-4 items-center justify-center",
|
|
1844
|
+
style: {
|
|
1845
|
+
maxWidth: isProcessing || result || error ? "1200px" : "480px",
|
|
1846
|
+
transition: "max-width 0.4s ease-in-out",
|
|
1847
|
+
width: "100%"
|
|
1848
|
+
}
|
|
1849
|
+
},
|
|
1850
|
+
/* @__PURE__ */ React3.createElement(
|
|
1851
|
+
Card,
|
|
1852
|
+
{
|
|
1853
|
+
className: "flex-shrink-0",
|
|
1854
|
+
style: {
|
|
1855
|
+
border: isModal ? "none" : "1px solid #e8e8e8",
|
|
1856
|
+
borderRadius: isModal ? "0" : "16px",
|
|
1857
|
+
boxShadow: isModal ? "none" : "0 4px 24px rgba(0, 0, 0, 0.06)",
|
|
1858
|
+
maxHeight: isModal ? "calc(100vh - 100px)" : "calc(100vh - 32px)",
|
|
1859
|
+
overflow: "auto",
|
|
1860
|
+
width: isModal ? "100%" : "480px",
|
|
1861
|
+
transition: "all 0.4s ease-in-out",
|
|
1862
|
+
transform: result || error ? "translateX(0)" : "translateX(0)"
|
|
1863
|
+
},
|
|
1864
|
+
styles: { body: { padding: isModal ? "0px" : "32px 24px" } }
|
|
1865
|
+
},
|
|
1866
|
+
/* @__PURE__ */ React3.createElement("div", { className: "flex items-center gap-3 mb-4" }, /* @__PURE__ */ React3.createElement(
|
|
1867
|
+
"div",
|
|
1868
|
+
{
|
|
1869
|
+
className: "w-12 h-12 rounded-xl flex items-center justify-center",
|
|
1870
|
+
style: {
|
|
1871
|
+
background: hasInvalidCheckoutId ? "#ff4d4f" : paymentDetails ? networkColor : loadingColor,
|
|
1872
|
+
transition: "background 0.3s ease"
|
|
1873
|
+
}
|
|
1874
|
+
},
|
|
1875
|
+
hasInvalidCheckoutId ? /* @__PURE__ */ React3.createElement("span", { style: { fontSize: "20px", color: "white", fontWeight: "bold" } }, "\u2717") : paymentDetails && NetworkIcon ? /* @__PURE__ */ React3.createElement(NetworkIcon, { width: 24, height: 24 }) : /* @__PURE__ */ React3.createElement(LoadingOutlined, { style: { fontSize: "20px", color: "white" }, spin: true })
|
|
1876
|
+
), /* @__PURE__ */ React3.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React3.createElement(Title, { level: 4, style: { margin: 0, fontSize: "18px", fontWeight: 600 } }, title || "Echo Payment OnVoyage"), !hasInvalidCheckoutId && /* @__PURE__ */ React3.createElement(
|
|
1877
|
+
Tooltip,
|
|
1878
|
+
{
|
|
1879
|
+
title: tooltipText,
|
|
1880
|
+
placement: "top"
|
|
1881
|
+
},
|
|
1882
|
+
/* @__PURE__ */ React3.createElement(
|
|
1883
|
+
InfoCircleOutlined,
|
|
1884
|
+
{
|
|
1885
|
+
style: { fontSize: "14px", color: "#8c8c8c", cursor: "help" }
|
|
1886
|
+
}
|
|
1887
|
+
)
|
|
1888
|
+
)), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, subtitle))),
|
|
1889
|
+
/* @__PURE__ */ React3.createElement("div", { className: "text-center mb-5" }, /* @__PURE__ */ React3.createElement("div", { className: "inline-flex items-center justify-center w-12 h-12 rounded-full bg-gray-50 mb-3" }, /* @__PURE__ */ React3.createElement(LockOutlined, { style: { fontSize: "20px", color: "#595959" } })), /* @__PURE__ */ React3.createElement(Title, { level: 3, style: { margin: "0 0 6px 0", fontSize: "20px", fontWeight: 600 } }, "Payment Required"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Pay ", paymentDetails ? `$${paymentDetails.amount} ${paymentDetails.currency}` : "the required amount", " to access")),
|
|
1890
|
+
hasInvalidCheckoutId && /* @__PURE__ */ React3.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ React3.createElement(
|
|
1891
|
+
"div",
|
|
1892
|
+
{
|
|
1893
|
+
className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
|
|
1894
|
+
style: {
|
|
1895
|
+
background: "linear-gradient(135deg, #ef4444 0%, #f87171 100%)",
|
|
1896
|
+
boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
|
|
1897
|
+
}
|
|
1898
|
+
},
|
|
1899
|
+
/* @__PURE__ */ React3.createElement("span", { style: { fontSize: "32px", color: "white" } }, "!")
|
|
1900
|
+
), /* @__PURE__ */ React3.createElement(
|
|
1901
|
+
Title,
|
|
1902
|
+
{
|
|
1903
|
+
level: 4,
|
|
1904
|
+
style: { margin: "0 0 12px 0", fontSize: "18px", fontWeight: 600, color: "#262626" }
|
|
1905
|
+
},
|
|
1906
|
+
"Invalid Checkout ID"
|
|
1907
|
+
), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", display: "block", marginBottom: "16px" } }, "The checkout ID you provided is invalid or has expired."), /* @__PURE__ */ React3.createElement(
|
|
1908
|
+
"div",
|
|
1909
|
+
{
|
|
1910
|
+
style: {
|
|
1911
|
+
background: "#fef2f2",
|
|
1912
|
+
padding: "16px",
|
|
1913
|
+
borderRadius: "12px",
|
|
1914
|
+
border: "1px solid #fee2e2",
|
|
1915
|
+
marginTop: "16px"
|
|
1916
|
+
}
|
|
1917
|
+
},
|
|
1918
|
+
/* @__PURE__ */ React3.createElement(Text, { style: {
|
|
1919
|
+
fontSize: "13px",
|
|
1920
|
+
color: "#dc2626",
|
|
1921
|
+
lineHeight: "1.6",
|
|
1922
|
+
fontWeight: 500
|
|
1923
|
+
} }, "Failed to load payment information. Please check your checkout ID.")
|
|
1924
|
+
)),
|
|
1925
|
+
!hasInvalidCheckoutId && fetchingPaymentInfo && /* @__PURE__ */ React3.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ React3.createElement(Text, { style: { color: "#8c8c8c" } }, "Loading payment information...")),
|
|
1926
|
+
!hasInvalidCheckoutId && !fetchingPaymentInfo && !address && /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement(WalletConnect, { supportedNetworks })),
|
|
1927
|
+
!hasInvalidCheckoutId && address && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
|
|
1928
|
+
"div",
|
|
1929
|
+
{
|
|
1930
|
+
className: "bg-gray-50 rounded-lg p-3 mb-4",
|
|
1931
|
+
style: { border: "1px solid #f0f0f0" }
|
|
1932
|
+
},
|
|
1933
|
+
/* @__PURE__ */ React3.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center gap-3 flex-1" }, /* @__PURE__ */ React3.createElement(
|
|
1934
|
+
"div",
|
|
1935
|
+
{
|
|
1936
|
+
className: "w-10 h-10 rounded-full bg-black flex items-center justify-center text-white text-sm font-semibold"
|
|
1937
|
+
},
|
|
1938
|
+
address.slice(0, 2).toUpperCase()
|
|
1939
|
+
), /* @__PURE__ */ React3.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React3.createElement(Text, { style: {
|
|
1940
|
+
display: "block",
|
|
1941
|
+
fontSize: "12px",
|
|
1942
|
+
color: "#8c8c8c",
|
|
1943
|
+
marginBottom: "2px"
|
|
1944
|
+
} }, "Connected Wallet"), /* @__PURE__ */ React3.createElement(
|
|
1945
|
+
Text,
|
|
1946
|
+
{
|
|
1947
|
+
style: {
|
|
1948
|
+
fontSize: "13px",
|
|
1949
|
+
fontWeight: 600,
|
|
1950
|
+
fontFamily: "Monaco, monospace"
|
|
1951
|
+
}
|
|
1952
|
+
},
|
|
1953
|
+
formatAddress(address)
|
|
1954
|
+
))), /* @__PURE__ */ React3.createElement(
|
|
1955
|
+
Button,
|
|
1956
|
+
{
|
|
1957
|
+
type: "text",
|
|
1958
|
+
size: "small",
|
|
1959
|
+
icon: /* @__PURE__ */ React3.createElement(DisconnectOutlined, null),
|
|
1960
|
+
onClick: handleDisconnect,
|
|
1961
|
+
style: { color: "#ff4d4f" }
|
|
1962
|
+
}
|
|
1963
|
+
))
|
|
1964
|
+
), paymentDetails && /* @__PURE__ */ React3.createElement("div", { className: "bg-gray-50 rounded-lg p-3 mb-4", style: { border: "1px solid #f0f0f0" } }, /* @__PURE__ */ React3.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Payment Amount"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "18px", fontWeight: 600 } }, "$", paymentDetails.amount)), /* @__PURE__ */ React3.createElement(Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ React3.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Currency"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.currency)), /* @__PURE__ */ React3.createElement(Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ React3.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Network"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.network)), /* @__PURE__ */ React3.createElement(Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ React3.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Wallet Address"), /* @__PURE__ */ React3.createElement(Text, { style: {
|
|
1965
|
+
fontSize: "11px",
|
|
1966
|
+
fontWeight: 500,
|
|
1967
|
+
fontFamily: "Monaco, monospace",
|
|
1968
|
+
wordBreak: "break-all",
|
|
1969
|
+
textAlign: "right",
|
|
1970
|
+
maxWidth: "60%",
|
|
1971
|
+
lineHeight: 1.4
|
|
1972
|
+
} }, address))), /* @__PURE__ */ React3.createElement(
|
|
1973
|
+
"div",
|
|
1974
|
+
{
|
|
1975
|
+
className: "flex items-center justify-center gap-2 mb-3 p-2 rounded-lg",
|
|
1976
|
+
style: { background: "#f6ffed", border: "1px solid #d9f7be" }
|
|
1977
|
+
},
|
|
1978
|
+
/* @__PURE__ */ React3.createElement(SafetyOutlined, { style: { color: "#52c41a", fontSize: "13px" } }),
|
|
1979
|
+
/* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "12px", color: "#52c41a", fontWeight: 500 } }, "Secure payment powered by v402pay")
|
|
1980
|
+
), /* @__PURE__ */ React3.createElement(
|
|
1981
|
+
Button,
|
|
1982
|
+
{
|
|
1983
|
+
type: "primary",
|
|
1984
|
+
size: "large",
|
|
1985
|
+
onClick: handlePayment,
|
|
1986
|
+
disabled: isProcessing || !paymentDetails,
|
|
1987
|
+
loading: isProcessing,
|
|
1988
|
+
block: true,
|
|
1989
|
+
style: {
|
|
1990
|
+
height: "44px",
|
|
1991
|
+
fontSize: "14px",
|
|
1992
|
+
fontWeight: 600,
|
|
1993
|
+
borderRadius: "8px",
|
|
1994
|
+
...!isProcessing && paymentDetails && {
|
|
1995
|
+
background: "#1a1a1a",
|
|
1996
|
+
borderColor: "#1a1a1a"
|
|
1997
|
+
},
|
|
1998
|
+
marginBottom: "10px"
|
|
1999
|
+
}
|
|
2000
|
+
},
|
|
2001
|
+
isProcessing ? "Processing..." : !paymentDetails ? "Loading..." : `Pay $${paymentDetails.amount} ${paymentDetails.currency}`
|
|
2002
|
+
), /* @__PURE__ */ React3.createElement("div", { className: "text-center" }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Don't have USDC?", " "), /* @__PURE__ */ React3.createElement(
|
|
2003
|
+
"a",
|
|
2004
|
+
{
|
|
2005
|
+
href: "https://faucet.circle.com/",
|
|
2006
|
+
target: "_blank",
|
|
2007
|
+
rel: "noopener noreferrer",
|
|
2008
|
+
className: "text-blue-600 hover:text-blue-700 text-sm font-medium inline-flex items-center gap-1"
|
|
2009
|
+
},
|
|
2010
|
+
"Get it here ",
|
|
2011
|
+
/* @__PURE__ */ React3.createElement(LinkOutlined, { style: { fontSize: "12px" } })
|
|
2012
|
+
)), isModal && result && /* @__PURE__ */ React3.createElement(
|
|
2013
|
+
"div",
|
|
2014
|
+
{
|
|
2015
|
+
className: "mt-4 p-4 rounded-lg",
|
|
2016
|
+
style: { background: "#f6ffed", border: "1px solid #b7eb8f" }
|
|
2017
|
+
},
|
|
2018
|
+
/* @__PURE__ */ React3.createElement("div", { className: "text-center" }, /* @__PURE__ */ React3.createElement("span", { style: { fontSize: "20px" } }, "\u2713"), /* @__PURE__ */ React3.createElement(Text, { style: {
|
|
2019
|
+
fontSize: "14px",
|
|
2020
|
+
color: "#52c41a",
|
|
2021
|
+
fontWeight: 600,
|
|
2022
|
+
marginLeft: "8px"
|
|
2023
|
+
} }, "Payment Successful!"))
|
|
2024
|
+
), isModal && error && /* @__PURE__ */ React3.createElement(
|
|
2025
|
+
"div",
|
|
2026
|
+
{
|
|
2027
|
+
className: "mt-4 p-4 rounded-lg",
|
|
2028
|
+
style: { background: "#fff2f0", border: "1px solid #ffccc7" }
|
|
2029
|
+
},
|
|
2030
|
+
/* @__PURE__ */ React3.createElement("div", { className: "text-center mb-3" }, /* @__PURE__ */ React3.createElement("span", { style: { fontSize: "20px" } }, "\u2717"), /* @__PURE__ */ React3.createElement(Text, { style: {
|
|
2031
|
+
fontSize: "14px",
|
|
2032
|
+
color: "#ff4d4f",
|
|
2033
|
+
fontWeight: 600,
|
|
2034
|
+
marginLeft: "8px",
|
|
2035
|
+
display: "block",
|
|
2036
|
+
marginTop: "4px"
|
|
2037
|
+
} }, "Payment Failed")),
|
|
2038
|
+
/* @__PURE__ */ React3.createElement(Text, { style: {
|
|
2039
|
+
fontSize: "13px",
|
|
2040
|
+
color: "#ff4d4f",
|
|
2041
|
+
display: "block",
|
|
2042
|
+
textAlign: "center"
|
|
2043
|
+
} }, error)
|
|
2044
|
+
))
|
|
2045
|
+
),
|
|
2046
|
+
!isModal && (isProcessing || result || error) && /* @__PURE__ */ React3.createElement(
|
|
2047
|
+
Card,
|
|
2048
|
+
{
|
|
2049
|
+
title: /* @__PURE__ */ React3.createElement("div", { className: "flex items-center gap-2" }, isProcessing && !result && !error ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(LoadingOutlined, { style: { color: "#14b8a6", fontSize: "16px" } }), /* @__PURE__ */ React3.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Processing Payment")) : result ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", { style: { color: "#52c41a", fontSize: "18px" } }, "\u2713"), /* @__PURE__ */ React3.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Successful")) : /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", { style: { color: "#ff4d4f", fontSize: "18px" } }, "\u2717"), /* @__PURE__ */ React3.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Failed"))),
|
|
2050
|
+
extra: !isProcessing && /* @__PURE__ */ React3.createElement(
|
|
2051
|
+
Button,
|
|
2052
|
+
{
|
|
2053
|
+
type: "text",
|
|
2054
|
+
size: "small",
|
|
2055
|
+
onClick: () => {
|
|
2056
|
+
setResult(null);
|
|
2057
|
+
setError(null);
|
|
2058
|
+
}
|
|
2059
|
+
},
|
|
2060
|
+
"Close"
|
|
2061
|
+
),
|
|
2062
|
+
style: {
|
|
2063
|
+
border: "1px solid #e8e8e8",
|
|
2064
|
+
borderRadius: "16px",
|
|
2065
|
+
boxShadow: "0 4px 24px rgba(0, 0, 0, 0.06)",
|
|
2066
|
+
maxHeight: "calc(100vh - 32px)",
|
|
2067
|
+
width: "480px",
|
|
2068
|
+
animation: "slideInRight 0.4s ease-out"
|
|
2069
|
+
},
|
|
2070
|
+
styles: {
|
|
2071
|
+
body: {
|
|
2072
|
+
padding: "24px",
|
|
2073
|
+
maxHeight: "calc(100vh - 120px)",
|
|
2074
|
+
overflow: "auto"
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
},
|
|
2078
|
+
isProcessing && !result && !error && /* @__PURE__ */ React3.createElement("div", { className: "text-center py-10" }, /* @__PURE__ */ React3.createElement("div", { className: "relative inline-block" }, /* @__PURE__ */ React3.createElement(
|
|
2079
|
+
"div",
|
|
2080
|
+
{
|
|
2081
|
+
className: "absolute inset-0 rounded-full blur-xl opacity-40",
|
|
2082
|
+
style: {
|
|
2083
|
+
background: "linear-gradient(135deg, #14b8a6 0%, #06b6d4 100%)",
|
|
2084
|
+
animation: "pulse 2s ease-in-out infinite"
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
), /* @__PURE__ */ React3.createElement(
|
|
2088
|
+
Spin,
|
|
2089
|
+
{
|
|
2090
|
+
indicator: /* @__PURE__ */ React3.createElement(LoadingOutlined, { style: { fontSize: 56, color: "#14b8a6" } })
|
|
2091
|
+
}
|
|
2092
|
+
)), /* @__PURE__ */ React3.createElement("div", { className: "mt-6" }, /* @__PURE__ */ React3.createElement(Text, { strong: true, style: { fontSize: "18px", color: "#262626", letterSpacing: "-0.02em" } }, "Verifying Payment")), /* @__PURE__ */ React3.createElement("div", { className: "mt-2 mb-6" }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", lineHeight: "1.6" } }, "Please wait while we confirm your transaction")), /* @__PURE__ */ React3.createElement(
|
|
2093
|
+
"div",
|
|
2094
|
+
{
|
|
2095
|
+
className: "mt-4 p-4 rounded-xl",
|
|
2096
|
+
style: {
|
|
2097
|
+
background: "linear-gradient(135deg, #f0fdfa 0%, #ecfeff 100%)",
|
|
2098
|
+
border: "1px solid #ccfbf1"
|
|
2099
|
+
}
|
|
2100
|
+
},
|
|
2101
|
+
/* @__PURE__ */ React3.createElement("div", { className: "flex items-center justify-center gap-2" }, /* @__PURE__ */ React3.createElement("span", { style: { fontSize: "16px" } }, "\u23F1\uFE0F"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#0f766e", fontWeight: 500 } }, "This may take a few moments"))
|
|
2102
|
+
)),
|
|
2103
|
+
result && /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ React3.createElement(
|
|
2104
|
+
"div",
|
|
2105
|
+
{
|
|
2106
|
+
className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
|
|
2107
|
+
style: {
|
|
2108
|
+
background: "linear-gradient(135deg, #10b981 0%, #34d399 100%)",
|
|
2109
|
+
boxShadow: "0 4px 20px rgba(16, 185, 129, 0.3)"
|
|
2110
|
+
}
|
|
2111
|
+
},
|
|
2112
|
+
/* @__PURE__ */ React3.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2713")
|
|
2113
|
+
), /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement(Text, { strong: true, style: {
|
|
2114
|
+
fontSize: "20px",
|
|
2115
|
+
color: "#262626",
|
|
2116
|
+
display: "block",
|
|
2117
|
+
marginBottom: "8px"
|
|
2118
|
+
} }, "Payment Successful!"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Your transaction has been confirmed"))), /* @__PURE__ */ React3.createElement(Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "RESPONSE DATA")), /* @__PURE__ */ React3.createElement(
|
|
2119
|
+
"pre",
|
|
2120
|
+
{
|
|
2121
|
+
style: {
|
|
2122
|
+
background: "#fafafa",
|
|
2123
|
+
padding: "20px",
|
|
2124
|
+
borderRadius: "12px",
|
|
2125
|
+
fontSize: "12px",
|
|
2126
|
+
lineHeight: "1.8",
|
|
2127
|
+
overflow: "auto",
|
|
2128
|
+
margin: 0,
|
|
2129
|
+
fontFamily: "Monaco, Courier New, monospace",
|
|
2130
|
+
whiteSpace: "pre-wrap",
|
|
2131
|
+
wordBreak: "break-word",
|
|
2132
|
+
border: "1px solid #e8e8e8",
|
|
2133
|
+
color: "#262626"
|
|
2134
|
+
}
|
|
2135
|
+
},
|
|
2136
|
+
JSON.stringify(result, null, 2)
|
|
2137
|
+
)),
|
|
2138
|
+
error && /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ React3.createElement(
|
|
2139
|
+
"div",
|
|
2140
|
+
{
|
|
2141
|
+
className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
|
|
2142
|
+
style: {
|
|
2143
|
+
background: "linear-gradient(135deg, #ef4444 0%, #f87171 100%)",
|
|
2144
|
+
boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
|
|
2145
|
+
}
|
|
2146
|
+
},
|
|
2147
|
+
/* @__PURE__ */ React3.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2717")
|
|
2148
|
+
), /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement(Text, { strong: true, style: {
|
|
2149
|
+
fontSize: "20px",
|
|
2150
|
+
color: "#262626",
|
|
2151
|
+
display: "block",
|
|
2152
|
+
marginBottom: "8px"
|
|
2153
|
+
} }, "Payment Failed"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Something went wrong with your transaction"))), /* @__PURE__ */ React3.createElement(Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "ERROR DETAILS")), /* @__PURE__ */ React3.createElement(
|
|
2154
|
+
"div",
|
|
2155
|
+
{
|
|
2156
|
+
style: {
|
|
2157
|
+
background: "#fef2f2",
|
|
2158
|
+
padding: "20px",
|
|
2159
|
+
borderRadius: "12px",
|
|
2160
|
+
border: "1px solid #fee2e2"
|
|
2161
|
+
}
|
|
2162
|
+
},
|
|
2163
|
+
/* @__PURE__ */ React3.createElement(Text, { style: {
|
|
2164
|
+
fontSize: "14px",
|
|
2165
|
+
color: "#dc2626",
|
|
2166
|
+
lineHeight: "1.6",
|
|
2167
|
+
fontWeight: 500
|
|
2168
|
+
} }, error)
|
|
2169
|
+
), /* @__PURE__ */ React3.createElement("div", { className: "mt-4 text-center" }, /* @__PURE__ */ React3.createElement(
|
|
2170
|
+
Button,
|
|
2171
|
+
{
|
|
2172
|
+
size: "large",
|
|
2173
|
+
onClick: handlePayment,
|
|
2174
|
+
style: {
|
|
2175
|
+
height: "44px",
|
|
2176
|
+
fontSize: "14px",
|
|
2177
|
+
fontWeight: 600,
|
|
2178
|
+
borderRadius: "8px",
|
|
2179
|
+
background: "#1a1a1a",
|
|
2180
|
+
borderColor: "#1a1a1a",
|
|
2181
|
+
color: "white",
|
|
2182
|
+
paddingLeft: "32px",
|
|
2183
|
+
paddingRight: "32px"
|
|
2184
|
+
}
|
|
2185
|
+
},
|
|
2186
|
+
"Try Again"
|
|
2187
|
+
)))
|
|
2188
|
+
)
|
|
2189
|
+
),
|
|
2190
|
+
/* @__PURE__ */ React3.createElement("style", { dangerouslySetInnerHTML: {
|
|
2191
|
+
__html: `
|
|
2192
|
+
@keyframes slideInRight {
|
|
2193
|
+
from {
|
|
2194
|
+
opacity: 0;
|
|
2195
|
+
transform: translateX(100px);
|
|
2196
|
+
}
|
|
2197
|
+
to {
|
|
2198
|
+
opacity: 1;
|
|
2199
|
+
transform: translateX(0);
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
@keyframes pulse {
|
|
2204
|
+
0%, 100% {
|
|
2205
|
+
transform: scale(1);
|
|
2206
|
+
opacity: 0.4;
|
|
2207
|
+
}
|
|
2208
|
+
50% {
|
|
2209
|
+
transform: scale(1.1);
|
|
2210
|
+
opacity: 0.6;
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
`
|
|
2214
|
+
} })
|
|
2215
|
+
);
|
|
1536
2216
|
}
|
|
1537
2217
|
export {
|
|
1538
|
-
|
|
2218
|
+
V402Checkout,
|
|
1539
2219
|
WalletConnect,
|
|
2220
|
+
usePageNetwork,
|
|
1540
2221
|
usePayment,
|
|
1541
2222
|
usePaymentInfo,
|
|
1542
2223
|
useWallet
|