uvd-x402-sdk 2.10.1 → 2.11.1

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.
@@ -3,9 +3,14 @@ import { c as WalletAdapter, C as ChainConfig, P as PaymentInfo, l as X402Versio
3
3
  /**
4
4
  * uvd-x402-sdk - Algorand Provider
5
5
  *
6
- * Provides wallet connection and payment creation for Algorand via Pera Wallet.
6
+ * Provides wallet connection and payment creation for Algorand.
7
+ * Supports both Lute Wallet (desktop browser extension) and Pera Wallet (mobile).
7
8
  * Uses ASA (Algorand Standard Assets) transfers for USDC payments.
8
9
  *
10
+ * Wallet Priority:
11
+ * 1. Lute Wallet - Desktop browser extension (preferred for desktop)
12
+ * 2. Pera Wallet - Mobile via WalletConnect (fallback/mobile)
13
+ *
9
14
  * USDC ASA IDs:
10
15
  * - Mainnet: 31566704
11
16
  * - Testnet: 10458941
@@ -17,7 +22,7 @@ import { c as WalletAdapter, C as ChainConfig, P as PaymentInfo, l as X402Versio
17
22
  *
18
23
  * const algorand = new AlgorandProvider();
19
24
  *
20
- * // Connect to Pera Wallet
25
+ * // Connect to Lute (desktop) or Pera (mobile) automatically
21
26
  * const address = await algorand.connect();
22
27
  *
23
28
  * // Create Algorand payment
@@ -28,28 +33,44 @@ import { c as WalletAdapter, C as ChainConfig, P as PaymentInfo, l as X402Versio
28
33
  */
29
34
 
30
35
  /**
31
- * AlgorandProvider - Wallet adapter for Algorand via Pera Wallet
36
+ * AlgorandProvider - Wallet adapter for Algorand
32
37
  *
33
- * Supports both mainnet and testnet through chain configuration.
38
+ * Supports Lute Wallet (desktop) and Pera Wallet (mobile).
39
+ * Automatically detects and uses the best available wallet.
34
40
  */
35
41
  declare class AlgorandProvider implements WalletAdapter {
36
- readonly id = "pera";
37
- readonly name = "Pera Wallet";
42
+ readonly id = "algorand";
43
+ readonly name = "Algorand Wallet";
38
44
  readonly networkType: "algorand";
45
+ private walletType;
46
+ private luteWallet;
39
47
  private peraWallet;
40
48
  private address;
41
49
  private algodClients;
42
50
  /**
43
- * Check if Pera Wallet is available
44
- * Note: Pera works as a WalletConnect modal, so it's always "available"
51
+ * Check if any Algorand wallet is available
52
+ * Returns true if Lute extension is installed OR we can use Pera (always available via WalletConnect)
45
53
  */
46
54
  isAvailable(): boolean;
47
55
  /**
48
- * Connect to Pera Wallet
56
+ * Get the name of the currently connected wallet
57
+ */
58
+ getWalletName(): string;
59
+ /**
60
+ * Connect to Algorand wallet
61
+ * Priority: Lute (desktop extension) > Pera (mobile via WalletConnect)
49
62
  */
50
63
  connect(_chainName?: string): Promise<string>;
51
64
  /**
52
- * Disconnect from Pera Wallet
65
+ * Connect to Lute Wallet (desktop browser extension)
66
+ */
67
+ private connectLute;
68
+ /**
69
+ * Connect to Pera Wallet (mobile via WalletConnect)
70
+ */
71
+ private connectPera;
72
+ /**
73
+ * Disconnect from wallet
53
74
  */
54
75
  disconnect(): Promise<void>;
55
76
  /**
@@ -3,9 +3,14 @@ import { c as WalletAdapter, C as ChainConfig, P as PaymentInfo, l as X402Versio
3
3
  /**
4
4
  * uvd-x402-sdk - Algorand Provider
5
5
  *
6
- * Provides wallet connection and payment creation for Algorand via Pera Wallet.
6
+ * Provides wallet connection and payment creation for Algorand.
7
+ * Supports both Lute Wallet (desktop browser extension) and Pera Wallet (mobile).
7
8
  * Uses ASA (Algorand Standard Assets) transfers for USDC payments.
8
9
  *
10
+ * Wallet Priority:
11
+ * 1. Lute Wallet - Desktop browser extension (preferred for desktop)
12
+ * 2. Pera Wallet - Mobile via WalletConnect (fallback/mobile)
13
+ *
9
14
  * USDC ASA IDs:
10
15
  * - Mainnet: 31566704
11
16
  * - Testnet: 10458941
@@ -17,7 +22,7 @@ import { c as WalletAdapter, C as ChainConfig, P as PaymentInfo, l as X402Versio
17
22
  *
18
23
  * const algorand = new AlgorandProvider();
19
24
  *
20
- * // Connect to Pera Wallet
25
+ * // Connect to Lute (desktop) or Pera (mobile) automatically
21
26
  * const address = await algorand.connect();
22
27
  *
23
28
  * // Create Algorand payment
@@ -28,28 +33,44 @@ import { c as WalletAdapter, C as ChainConfig, P as PaymentInfo, l as X402Versio
28
33
  */
29
34
 
30
35
  /**
31
- * AlgorandProvider - Wallet adapter for Algorand via Pera Wallet
36
+ * AlgorandProvider - Wallet adapter for Algorand
32
37
  *
33
- * Supports both mainnet and testnet through chain configuration.
38
+ * Supports Lute Wallet (desktop) and Pera Wallet (mobile).
39
+ * Automatically detects and uses the best available wallet.
34
40
  */
35
41
  declare class AlgorandProvider implements WalletAdapter {
36
- readonly id = "pera";
37
- readonly name = "Pera Wallet";
42
+ readonly id = "algorand";
43
+ readonly name = "Algorand Wallet";
38
44
  readonly networkType: "algorand";
45
+ private walletType;
46
+ private luteWallet;
39
47
  private peraWallet;
40
48
  private address;
41
49
  private algodClients;
42
50
  /**
43
- * Check if Pera Wallet is available
44
- * Note: Pera works as a WalletConnect modal, so it's always "available"
51
+ * Check if any Algorand wallet is available
52
+ * Returns true if Lute extension is installed OR we can use Pera (always available via WalletConnect)
45
53
  */
46
54
  isAvailable(): boolean;
47
55
  /**
48
- * Connect to Pera Wallet
56
+ * Get the name of the currently connected wallet
57
+ */
58
+ getWalletName(): string;
59
+ /**
60
+ * Connect to Algorand wallet
61
+ * Priority: Lute (desktop extension) > Pera (mobile via WalletConnect)
49
62
  */
50
63
  connect(_chainName?: string): Promise<string>;
51
64
  /**
52
- * Disconnect from Pera Wallet
65
+ * Connect to Lute Wallet (desktop browser extension)
66
+ */
67
+ private connectLute;
68
+ /**
69
+ * Connect to Pera Wallet (mobile via WalletConnect)
70
+ */
71
+ private connectPera;
72
+ /**
73
+ * Disconnect from wallet
53
74
  */
54
75
  disconnect(): Promise<void>;
55
76
  /**
@@ -688,36 +688,113 @@ function uint8ArrayToBase64(bytes) {
688
688
  }
689
689
  var algosdk = null;
690
690
  var PeraWalletConnect = null;
691
+ var LuteConnect = null;
691
692
  async function loadAlgorandDeps() {
692
693
  if (!algosdk) {
693
694
  algosdk = await import('algosdk');
694
695
  }
696
+ }
697
+ async function loadPeraWallet() {
695
698
  if (!PeraWalletConnect) {
696
699
  const peraModule = await import('@perawallet/connect');
697
700
  PeraWalletConnect = peraModule.PeraWalletConnect;
698
701
  }
699
702
  }
703
+ async function loadLuteWallet() {
704
+ if (!LuteConnect) {
705
+ try {
706
+ const luteModule = await import('lute-connect');
707
+ LuteConnect = luteModule.default;
708
+ } catch {
709
+ LuteConnect = null;
710
+ }
711
+ }
712
+ }
713
+ function isLuteAvailable() {
714
+ if (typeof window === "undefined") return false;
715
+ const win = window;
716
+ return !!(win.algorand || win.lute);
717
+ }
700
718
  var AlgorandProvider = class {
701
- id = "pera";
702
- name = "Pera Wallet";
719
+ id = "algorand";
720
+ name = "Algorand Wallet";
703
721
  networkType = "algorand";
722
+ // Active wallet type
723
+ walletType = null;
724
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
725
+ luteWallet = null;
704
726
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
705
727
  peraWallet = null;
706
728
  address = null;
707
729
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
708
730
  algodClients = /* @__PURE__ */ new Map();
709
731
  /**
710
- * Check if Pera Wallet is available
711
- * Note: Pera works as a WalletConnect modal, so it's always "available"
732
+ * Check if any Algorand wallet is available
733
+ * Returns true if Lute extension is installed OR we can use Pera (always available via WalletConnect)
712
734
  */
713
735
  isAvailable() {
714
736
  return typeof window !== "undefined";
715
737
  }
716
738
  /**
717
- * Connect to Pera Wallet
739
+ * Get the name of the currently connected wallet
740
+ */
741
+ getWalletName() {
742
+ if (this.walletType === "lute") return "Lute Wallet";
743
+ if (this.walletType === "pera") return "Pera Wallet";
744
+ return "Algorand Wallet";
745
+ }
746
+ /**
747
+ * Connect to Algorand wallet
748
+ * Priority: Lute (desktop extension) > Pera (mobile via WalletConnect)
718
749
  */
719
750
  async connect(_chainName) {
720
751
  await loadAlgorandDeps();
752
+ if (isLuteAvailable()) {
753
+ try {
754
+ return await this.connectLute();
755
+ } catch (error) {
756
+ console.warn("Lute connection failed, falling back to Pera:", error);
757
+ }
758
+ }
759
+ return await this.connectPera();
760
+ }
761
+ /**
762
+ * Connect to Lute Wallet (desktop browser extension)
763
+ */
764
+ async connectLute() {
765
+ await loadLuteWallet();
766
+ if (!LuteConnect) {
767
+ throw new X402Error("Lute Wallet SDK not available", "WALLET_NOT_FOUND");
768
+ }
769
+ try {
770
+ this.luteWallet = new LuteConnect("402milly");
771
+ const genesisId = "mainnet-v1.0";
772
+ const accounts = await this.luteWallet.connect(genesisId);
773
+ if (!accounts || accounts.length === 0) {
774
+ throw new X402Error("No accounts returned from Lute Wallet", "WALLET_CONNECTION_REJECTED");
775
+ }
776
+ this.address = accounts[0];
777
+ this.walletType = "lute";
778
+ return accounts[0];
779
+ } catch (error) {
780
+ if (error instanceof X402Error) throw error;
781
+ if (error instanceof Error) {
782
+ if (error.message.includes("rejected") || error.message.includes("cancelled")) {
783
+ throw new X402Error("Connection rejected by user", "WALLET_CONNECTION_REJECTED");
784
+ }
785
+ }
786
+ throw new X402Error(
787
+ `Failed to connect Lute Wallet: ${error instanceof Error ? error.message : "Unknown error"}`,
788
+ "UNKNOWN_ERROR",
789
+ error
790
+ );
791
+ }
792
+ }
793
+ /**
794
+ * Connect to Pera Wallet (mobile via WalletConnect)
795
+ */
796
+ async connectPera() {
797
+ await loadPeraWallet();
721
798
  if (!PeraWalletConnect) {
722
799
  throw new X402Error("Failed to load Pera Wallet SDK", "WALLET_NOT_FOUND");
723
800
  }
@@ -726,6 +803,7 @@ var AlgorandProvider = class {
726
803
  const accounts = await this.peraWallet.reconnectSession();
727
804
  if (accounts.length > 0) {
728
805
  this.address = accounts[0];
806
+ this.walletType = "pera";
729
807
  return accounts[0];
730
808
  }
731
809
  const newAccounts = await this.peraWallet.connect();
@@ -733,8 +811,10 @@ var AlgorandProvider = class {
733
811
  throw new X402Error("No accounts returned from Pera Wallet", "WALLET_CONNECTION_REJECTED");
734
812
  }
735
813
  this.address = newAccounts[0];
814
+ this.walletType = "pera";
736
815
  this.peraWallet.connector?.on("disconnect", () => {
737
816
  this.address = null;
817
+ this.walletType = null;
738
818
  });
739
819
  return newAccounts[0];
740
820
  } catch (error) {
@@ -751,17 +831,21 @@ var AlgorandProvider = class {
751
831
  }
752
832
  }
753
833
  /**
754
- * Disconnect from Pera Wallet
834
+ * Disconnect from wallet
755
835
  */
756
836
  async disconnect() {
757
- if (this.peraWallet) {
837
+ if (this.walletType === "lute" && this.luteWallet) {
838
+ this.luteWallet = null;
839
+ }
840
+ if (this.walletType === "pera" && this.peraWallet) {
758
841
  try {
759
842
  await this.peraWallet.disconnect();
760
843
  } catch {
761
844
  }
845
+ this.peraWallet = null;
762
846
  }
763
- this.peraWallet = null;
764
847
  this.address = null;
848
+ this.walletType = null;
765
849
  this.algodClients.clear();
766
850
  }
767
851
  /**
@@ -805,7 +889,7 @@ var AlgorandProvider = class {
805
889
  */
806
890
  async signPayment(paymentInfo, chainConfig) {
807
891
  await loadAlgorandDeps();
808
- if (!this.peraWallet || !this.address) {
892
+ if (!this.address || !this.walletType) {
809
893
  throw new X402Error("Wallet not connected", "WALLET_NOT_CONNECTED");
810
894
  }
811
895
  if (!algosdk) {
@@ -825,11 +909,23 @@ var AlgorandProvider = class {
825
909
  suggestedParams,
826
910
  note: new TextEncoder().encode("x402 payment via uvd-x402-sdk")
827
911
  });
828
- const signedTxns = await this.peraWallet.signTransaction([[{ txn }]]);
829
- if (!signedTxns || signedTxns.length === 0) {
830
- throw new X402Error("No signed transaction returned", "SIGNATURE_REJECTED");
912
+ let signedTxn;
913
+ if (this.walletType === "lute" && this.luteWallet) {
914
+ const txnBase64 = uint8ArrayToBase64(txn.toByte());
915
+ const signedTxns = await this.luteWallet.signTxns([{ txn: txnBase64 }]);
916
+ if (!signedTxns || signedTxns.length === 0 || !signedTxns[0]) {
917
+ throw new X402Error("No signed transaction returned", "SIGNATURE_REJECTED");
918
+ }
919
+ signedTxn = Uint8Array.from(atob(signedTxns[0]), (c) => c.charCodeAt(0));
920
+ } else if (this.walletType === "pera" && this.peraWallet) {
921
+ const signedTxns = await this.peraWallet.signTransaction([[{ txn }]]);
922
+ if (!signedTxns || signedTxns.length === 0) {
923
+ throw new X402Error("No signed transaction returned", "SIGNATURE_REJECTED");
924
+ }
925
+ signedTxn = signedTxns[0];
926
+ } else {
927
+ throw new X402Error("No wallet available for signing", "WALLET_NOT_CONNECTED");
831
928
  }
832
- const signedTxn = signedTxns[0];
833
929
  const payload = {
834
930
  from: this.address,
835
931
  to: recipient,