@voyage_ai/v402-web-ts 0.3.0 → 1.0.2

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 CHANGED
@@ -443,6 +443,7 @@ declare function getWalletDisplayName(networkType: NetworkType): string;
443
443
  * @param networkType - Network type (from useWallet)
444
444
  * @param merchantId - @see our website to apply
445
445
  * @param additionalParams - Optional additional parameters to send with the request (default: {})
446
+ * @param expectedAddress - Optional expected wallet address for validation
446
447
  * @returns Response from the payment
447
448
  *
448
449
  * @example
@@ -453,16 +454,17 @@ declare function getWalletDisplayName(networkType: NetworkType): string;
453
454
  *
454
455
  * @example
455
456
  * ```tsx
456
- * // With additional parameters
457
+ * // With additional parameters and address validation
457
458
  * const response = await makePayment(
458
459
  * '/api/endpoint',
459
460
  * networkType,
460
461
  * merchantId,
461
- * { userId: '123', customField: 'value' }
462
+ * { userId: '123', customField: 'value' },
463
+ * walletAddress // Pass the expected address for validation
462
464
  * );
463
465
  * ```
464
466
  */
465
- declare function makePayment(networkType: NetworkType, merchantId: string, endpoint?: string, additionalParams?: Record<string, any>): Promise<Response>;
467
+ declare function makePayment(networkType: NetworkType, merchantId: string, endpoint?: string, additionalParams?: Record<string, any>, expectedAddress?: string): Promise<Response>;
466
468
 
467
469
  /**
468
470
  * Network utilities
package/dist/index.d.ts CHANGED
@@ -443,6 +443,7 @@ declare function getWalletDisplayName(networkType: NetworkType): string;
443
443
  * @param networkType - Network type (from useWallet)
444
444
  * @param merchantId - @see our website to apply
445
445
  * @param additionalParams - Optional additional parameters to send with the request (default: {})
446
+ * @param expectedAddress - Optional expected wallet address for validation
446
447
  * @returns Response from the payment
447
448
  *
448
449
  * @example
@@ -453,16 +454,17 @@ declare function getWalletDisplayName(networkType: NetworkType): string;
453
454
  *
454
455
  * @example
455
456
  * ```tsx
456
- * // With additional parameters
457
+ * // With additional parameters and address validation
457
458
  * const response = await makePayment(
458
459
  * '/api/endpoint',
459
460
  * networkType,
460
461
  * merchantId,
461
- * { userId: '123', customField: 'value' }
462
+ * { userId: '123', customField: 'value' },
463
+ * walletAddress // Pass the expected address for validation
462
464
  * );
463
465
  * ```
464
466
  */
465
- declare function makePayment(networkType: NetworkType, merchantId: string, endpoint?: string, additionalParams?: Record<string, any>): Promise<Response>;
467
+ declare function makePayment(networkType: NetworkType, merchantId: string, endpoint?: string, additionalParams?: Record<string, any>, expectedAddress?: string): Promise<Response>;
466
468
 
467
469
  /**
468
470
  * Network utilities
package/dist/index.js CHANGED
@@ -182,9 +182,52 @@ function getWalletDisplayName(networkType) {
182
182
  return "Unknown Wallet";
183
183
  }
184
184
  }
185
+ function getAllWalletAddresses() {
186
+ if (typeof window === "undefined") {
187
+ return {};
188
+ }
189
+ try {
190
+ const cached = localStorage.getItem(WALLET_ADDRESSES_KEY);
191
+ return cached ? JSON.parse(cached) : {};
192
+ } catch (error) {
193
+ console.error("Failed to parse wallet addresses cache:", error);
194
+ return {};
195
+ }
196
+ }
197
+ function saveWalletAddress(networkType, address) {
198
+ if (typeof window === "undefined") {
199
+ return;
200
+ }
201
+ const addresses = getAllWalletAddresses();
202
+ addresses[networkType] = address;
203
+ localStorage.setItem(WALLET_ADDRESSES_KEY, JSON.stringify(addresses));
204
+ }
205
+ function getCachedWalletAddress(networkType) {
206
+ const addresses = getAllWalletAddresses();
207
+ return addresses[networkType] || null;
208
+ }
209
+ function getAllConnectedWalletIds() {
210
+ if (typeof window === "undefined") {
211
+ return {};
212
+ }
213
+ try {
214
+ const cached = localStorage.getItem(CONNECTED_WALLET_IDS_KEY);
215
+ return cached ? JSON.parse(cached) : {};
216
+ } catch (error) {
217
+ console.error("Failed to parse connected wallet IDs:", error);
218
+ return {};
219
+ }
220
+ }
221
+ function getConnectedWalletId(networkType) {
222
+ const walletIds = getAllConnectedWalletIds();
223
+ return walletIds[networkType] || null;
224
+ }
225
+ var WALLET_ADDRESSES_KEY, CONNECTED_WALLET_IDS_KEY;
185
226
  var init_wallet = __esm({
186
227
  "src/utils/wallet.ts"() {
187
228
  "use strict";
229
+ WALLET_ADDRESSES_KEY = "wallet_addresses_cache";
230
+ CONNECTED_WALLET_IDS_KEY = "connected_wallet_ids";
188
231
  }
189
232
  });
190
233
 
@@ -232,6 +275,51 @@ var import_spl_token = require("@solana/spl-token");
232
275
  init_wallet();
233
276
 
234
277
  // src/utils/wallet-discovery.ts
278
+ init_wallet();
279
+ var SOLANA_WALLETS = [
280
+ {
281
+ id: "phantom",
282
+ name: "Phantom",
283
+ // Phantom official icon
284
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZD0iTTExMC41IDY0QzExMC41IDg5Ljk1NjggODkuMjAxIDExMSA2My41IDExMUg0MS41QzM2LjI1MzMgMTExIDMyIDEwNi43NDcgMzIgMTAxLjVWNTQuNUMzMiAzMS4wMjggNTEuMDI4IDEyIDc0LjUgMTJDOTcuOTcyIDEyIDExNyAzMS4wMjggMTE3IDU0LjVWNTUuNUMxMTcgNTguNTM3NiAxMTQuNTM4IDYxIDExMS41IDYxSDEwOS41QzEwNi40NjIgNjEgMTA0IDYzLjQ2MjQgMTA0IDY2LjVWNjhDMTA0IDcxLjg2NiAxMDcuMTM0IDc1IDExMSA3NUgxMTEuNUMxMTQuNTM4IDc1IDExNyA3Mi41Mzc2IDExNyA2OS41VjY0SDExMC41WiIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzEyOF8xMjgpIi8+CjxwYXRoIGQ9Ik00OC41IDY3QzUxLjUzNzYgNjcgNTQgNjQuNTM3NiA1NCA2MS41QzU0IDU4LjQ2MjQgNTEuNTM3NiA1NiA0OC41IDU2QzQ1LjQ2MjQgNTYgNDMgNTguNDYyNCA0MyA2MS41QzQzIDY0LjUzNzYgNDUuNDYyNCA2NyA0OC41IDY3WiIgZmlsbD0iIzFCMUIxQiIvPgo8cGF0aCBkPSJNNzMuNSA2N0M3Ni41Mzc2IDY3IDc5IDY0LjUzNzYgNzkgNjEuNUM3OSA1OC40NjI0IDc2LjUzNzYgNTYgNzMuNSA1NkM3MC40NjI0IDU2IDY4IDU4LjQ2MjQgNjggNjEuNUM2OCA2NC41Mzc2IDcwLjQ2MjQgNjcgNzMuNSA2N1oiIGZpbGw9IiMxQjFCMUIiLz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl8xMjhfMTI4IiB4MT0iMTE3IiB5MT0iMTIiIHgyPSIxMTciIHkyPSIxMTEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRkZGRiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRkZGRkYiIHN0b3Atb3BhY2l0eT0iMC44MiIvPgo8L2xpbmVhckdyYWRpZW50Pgo8L2RlZnM+Cjwvc3ZnPg==",
285
+ detect: () => window.phantom?.solana
286
+ },
287
+ {
288
+ id: "solflare",
289
+ name: "Solflare",
290
+ // Solflare icon
291
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNGQzZEMDEiLz4KPHBhdGggZD0iTTk2IDY0TDY0IDMyTDMyIDY0TDY0IDk2TDk2IDY0WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+",
292
+ detect: () => window.solflare
293
+ },
294
+ {
295
+ id: "backpack",
296
+ name: "Backpack",
297
+ // Backpack icon (red coral color)
298
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNFMzM0MzAiLz4KPHBhdGggZD0iTTQwIDQ4SDg4VjgwQzg4IDg4LjgzNjYgODAuODM2NiA5NiA3MiA5Nkg1NkM0Ny4xNjM0IDk2IDQwIDg4LjgzNjYgNDAgODBWNDhaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNTIgMzJINzZWNDhINTJWMzJaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
299
+ detect: () => window.backpack
300
+ },
301
+ {
302
+ id: "okx-solana",
303
+ name: "OKX Wallet",
304
+ // OKX icon
305
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9ImJsYWNrIi8+CjxyZWN0IHg9IjI0IiB5PSIyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iNTIiIHk9IjI0IiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSI4MCIgeT0iMjQiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjI0IiB5PSI1MiIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjUyIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSIyNCIgeT0iODAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjUyIiB5PSI4MCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjgwIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
306
+ detect: () => window.okxwallet?.solana
307
+ },
308
+ {
309
+ id: "coinbase-solana",
310
+ name: "Coinbase Wallet",
311
+ // Coinbase icon (blue)
312
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwMDUyRkYiLz4KPGNpcmNsZSBjeD0iNjQiIGN5PSI2NCIgcj0iMzYiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjQ4IiB5PSI1NiIgd2lkdGg9IjMyIiBoZWlnaHQ9IjE2IiByeD0iNCIgZmlsbD0iIzAwNTJGRiIvPgo8L3N2Zz4=",
313
+ detect: () => window.coinbaseSolana
314
+ },
315
+ {
316
+ id: "trust-solana",
317
+ name: "Trust Wallet",
318
+ // Trust Wallet icon
319
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwNTAwRkYiLz4KPHBhdGggZD0iTTY0IDI0QzY0IDI0IDk2IDQwIDk2IDY0Qzk2IDg4IDY0IDEwNCA2NCAxMDRDNjQgMTA0IDMyIDg4IDMyIDY0QzMyIDQwIDY0IDI0IDY0IDI0WiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSI2IiBmaWxsPSJub25lIi8+Cjwvc3ZnPg==",
320
+ detect: () => window.trustwallet?.solana
321
+ }
322
+ ];
235
323
  var evmWallets = /* @__PURE__ */ new Map();
236
324
  var evmDiscoveryListeners = /* @__PURE__ */ new Set();
237
325
  var evmDiscoveryInitialized = false;
@@ -246,10 +334,118 @@ function initEVMWalletDiscovery() {
246
334
  }));
247
335
  window.dispatchEvent(new Event("eip6963:requestProvider"));
248
336
  }
337
+ function getEVMWallets() {
338
+ const wallets = [];
339
+ const detectedNames = /* @__PURE__ */ new Set();
340
+ evmWallets.forEach((detail, uuid) => {
341
+ if (!detectedNames.has(detail.info.name)) {
342
+ wallets.push({
343
+ id: uuid,
344
+ name: detail.info.name,
345
+ icon: detail.info.icon,
346
+ networkType: "evm" /* EVM */,
347
+ provider: detail.provider,
348
+ installed: true
349
+ });
350
+ detectedNames.add(detail.info.name);
351
+ }
352
+ });
353
+ if (wallets.length === 0 && typeof window !== "undefined" && window.ethereum) {
354
+ const ethereum = window.ethereum;
355
+ const walletName = ethereum.isMetaMask ? "MetaMask" : ethereum.isCoinbaseWallet ? "Coinbase Wallet" : ethereum.isOkxWallet ? "OKX Wallet" : "Browser Wallet";
356
+ if (!detectedNames.has(walletName)) {
357
+ wallets.push({
358
+ id: "injected",
359
+ name: walletName,
360
+ icon: "",
361
+ // Will use first letter as avatar
362
+ networkType: "evm" /* EVM */,
363
+ provider: ethereum,
364
+ installed: true
365
+ });
366
+ }
367
+ }
368
+ return wallets;
369
+ }
370
+ function getSolanaWallets() {
371
+ if (typeof window === "undefined") return [];
372
+ const wallets = [];
373
+ const detectedProviders = /* @__PURE__ */ new Set();
374
+ const detectedNames = /* @__PURE__ */ new Set();
375
+ for (const wallet of SOLANA_WALLETS) {
376
+ const provider = wallet.detect();
377
+ if (provider && !detectedNames.has(wallet.name)) {
378
+ wallets.push({
379
+ id: wallet.id,
380
+ name: wallet.name,
381
+ icon: wallet.icon,
382
+ networkType: "solana" /* SOLANA */,
383
+ provider,
384
+ installed: true
385
+ });
386
+ detectedProviders.add(provider);
387
+ detectedNames.add(wallet.name);
388
+ }
389
+ }
390
+ const windowSolana = window.solana;
391
+ if (windowSolana && !detectedProviders.has(windowSolana)) {
392
+ const walletName = windowSolana.isPhantom ? "Phantom" : windowSolana.isSolflare ? "Solflare" : windowSolana.isBackpack ? "Backpack" : windowSolana.walletName || "Solana Wallet";
393
+ if (!detectedNames.has(walletName)) {
394
+ wallets.push({
395
+ id: "solana-unknown",
396
+ name: walletName,
397
+ icon: "",
398
+ // Will use first letter as avatar
399
+ networkType: "solana" /* SOLANA */,
400
+ provider: windowSolana,
401
+ installed: true
402
+ });
403
+ }
404
+ }
405
+ return wallets;
406
+ }
407
+ function getWalletsForNetwork(networkType) {
408
+ switch (networkType) {
409
+ case "evm" /* EVM */:
410
+ return getEVMWallets();
411
+ case "solana" /* SOLANA */:
412
+ case "svm" /* SVM */:
413
+ return getSolanaWallets();
414
+ default:
415
+ return [];
416
+ }
417
+ }
418
+ function getWalletByName(name, networkType) {
419
+ const wallets = getWalletsForNetwork(networkType);
420
+ return wallets.find((w) => w.name === name) || null;
421
+ }
422
+ function restoreConnectedWallet(networkType) {
423
+ const savedWalletName = getConnectedWalletId(networkType);
424
+ if (!savedWalletName) {
425
+ return null;
426
+ }
427
+ const wallet = getWalletByName(savedWalletName, networkType);
428
+ if (wallet) {
429
+ currentConnectedWallet = wallet;
430
+ if ((networkType === "solana" /* SOLANA */ || networkType === "svm" /* SVM */) && wallet.provider) {
431
+ const providerPublicKey = wallet.provider.publicKey?.toString();
432
+ const cachedAddress = getCachedWalletAddress(networkType);
433
+ if (providerPublicKey && cachedAddress && providerPublicKey !== cachedAddress) {
434
+ saveWalletAddress(networkType, providerPublicKey);
435
+ }
436
+ }
437
+ return wallet;
438
+ }
439
+ return null;
440
+ }
249
441
  function getWalletProviderForPayment(networkType) {
250
442
  if (currentConnectedWallet && currentConnectedWallet.networkType === networkType) {
251
443
  return currentConnectedWallet.provider;
252
444
  }
445
+ const restoredWallet = restoreConnectedWallet(networkType);
446
+ if (restoredWallet) {
447
+ return restoredWallet.provider;
448
+ }
253
449
  if (typeof window === "undefined") return null;
254
450
  switch (networkType) {
255
451
  case "evm" /* EVM */:
@@ -527,7 +723,7 @@ function createEvmPaymentFetch(config) {
527
723
  // src/utils/payment-helpers.ts
528
724
  var import_ethers2 = require("ethers");
529
725
  init_common();
530
- async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, additionalParams) {
726
+ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, additionalParams, expectedAddress) {
531
727
  const fullEndpoint = `${endpoint}/${merchantId}`;
532
728
  let response;
533
729
  const requestInit = additionalParams && Object.keys(additionalParams).length > 0 ? {
@@ -539,11 +735,19 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
539
735
  if (networkType === "solana" /* SOLANA */ || networkType === "svm" /* SVM */) {
540
736
  const solana = getWalletProviderForPayment(networkType);
541
737
  if (!solana) {
542
- throw new Error("\u8BF7\u5148\u8FDE\u63A5 Solana \u94B1\u5305");
738
+ throw new Error("Please connect your Solana wallet first.");
543
739
  }
544
740
  if (!solana.isConnected) {
545
741
  await solana.connect();
546
742
  }
743
+ const currentAddress = solana.publicKey?.toString();
744
+ if (expectedAddress && currentAddress) {
745
+ if (currentAddress !== expectedAddress) {
746
+ throw new Error(
747
+ `Wallet account mismatch: the current wallet account is ${currentAddress.slice(0, 8)}...\uFF0CBut the desired account is ${expectedAddress.slice(0, 8)}.... Please switch to the correct account in your wallet.`
748
+ );
749
+ }
750
+ }
547
751
  response = await handleSvmPayment(fullEndpoint, {
548
752
  wallet: solana,
549
753
  network: "solana"
@@ -552,12 +756,18 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
552
756
  } else if (networkType === "evm" /* EVM */) {
553
757
  const ethereum = getWalletProviderForPayment(networkType);
554
758
  if (!ethereum) {
555
- throw new Error("\u8BF7\u5148\u8FDE\u63A5 EVM \u94B1\u5305");
759
+ throw new Error("Please connect the EVM wallet first");
556
760
  }
557
761
  const provider = new import_ethers2.ethers.BrowserProvider(ethereum);
558
762
  const signer = await provider.getSigner();
763
+ const currentAddress = await signer.getAddress();
764
+ if (expectedAddress && currentAddress.toLowerCase() !== expectedAddress.toLowerCase()) {
765
+ throw new Error(
766
+ `Wallet account mismatch: the current wallet account is ${currentAddress.slice(0, 8)}...\uFF0CBut the desired account is ${expectedAddress.slice(0, 8)}.... Please switch to the correct account in your wallet.`
767
+ );
768
+ }
559
769
  const wallet = {
560
- address: await signer.getAddress(),
770
+ address: currentAddress,
561
771
  signTypedData: async (domain, types, message) => {
562
772
  return await signer.signTypedData(domain, types, message);
563
773
  },
@@ -580,7 +790,7 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
580
790
  // Will use backend's network configuration
581
791
  }, requestInit);
582
792
  } else {
583
- throw new Error(`\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B: ${networkType}`);
793
+ throw new Error(`Unsupported network types: ${networkType}`);
584
794
  }
585
795
  return response;
586
796
  }