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.
@@ -684,36 +684,113 @@ function uint8ArrayToBase64(bytes) {
684
684
  }
685
685
  var algosdk = null;
686
686
  var PeraWalletConnect = null;
687
+ var LuteConnect = null;
687
688
  async function loadAlgorandDeps() {
688
689
  if (!algosdk) {
689
690
  algosdk = await import('algosdk');
690
691
  }
692
+ }
693
+ async function loadPeraWallet() {
691
694
  if (!PeraWalletConnect) {
692
695
  const peraModule = await import('@perawallet/connect');
693
696
  PeraWalletConnect = peraModule.PeraWalletConnect;
694
697
  }
695
698
  }
699
+ async function loadLuteWallet() {
700
+ if (!LuteConnect) {
701
+ try {
702
+ const luteModule = await import('lute-connect');
703
+ LuteConnect = luteModule.default;
704
+ } catch {
705
+ LuteConnect = null;
706
+ }
707
+ }
708
+ }
709
+ function isLuteAvailable() {
710
+ if (typeof window === "undefined") return false;
711
+ const win = window;
712
+ return !!(win.algorand || win.lute);
713
+ }
696
714
  var AlgorandProvider = class {
697
- id = "pera";
698
- name = "Pera Wallet";
715
+ id = "algorand";
716
+ name = "Algorand Wallet";
699
717
  networkType = "algorand";
718
+ // Active wallet type
719
+ walletType = null;
720
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
721
+ luteWallet = null;
700
722
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
701
723
  peraWallet = null;
702
724
  address = null;
703
725
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
704
726
  algodClients = /* @__PURE__ */ new Map();
705
727
  /**
706
- * Check if Pera Wallet is available
707
- * Note: Pera works as a WalletConnect modal, so it's always "available"
728
+ * Check if any Algorand wallet is available
729
+ * Returns true if Lute extension is installed OR we can use Pera (always available via WalletConnect)
708
730
  */
709
731
  isAvailable() {
710
732
  return typeof window !== "undefined";
711
733
  }
712
734
  /**
713
- * Connect to Pera Wallet
735
+ * Get the name of the currently connected wallet
736
+ */
737
+ getWalletName() {
738
+ if (this.walletType === "lute") return "Lute Wallet";
739
+ if (this.walletType === "pera") return "Pera Wallet";
740
+ return "Algorand Wallet";
741
+ }
742
+ /**
743
+ * Connect to Algorand wallet
744
+ * Priority: Lute (desktop extension) > Pera (mobile via WalletConnect)
714
745
  */
715
746
  async connect(_chainName) {
716
747
  await loadAlgorandDeps();
748
+ if (isLuteAvailable()) {
749
+ try {
750
+ return await this.connectLute();
751
+ } catch (error) {
752
+ console.warn("Lute connection failed, falling back to Pera:", error);
753
+ }
754
+ }
755
+ return await this.connectPera();
756
+ }
757
+ /**
758
+ * Connect to Lute Wallet (desktop browser extension)
759
+ */
760
+ async connectLute() {
761
+ await loadLuteWallet();
762
+ if (!LuteConnect) {
763
+ throw new X402Error("Lute Wallet SDK not available", "WALLET_NOT_FOUND");
764
+ }
765
+ try {
766
+ this.luteWallet = new LuteConnect("402milly");
767
+ const genesisId = "mainnet-v1.0";
768
+ const accounts = await this.luteWallet.connect(genesisId);
769
+ if (!accounts || accounts.length === 0) {
770
+ throw new X402Error("No accounts returned from Lute Wallet", "WALLET_CONNECTION_REJECTED");
771
+ }
772
+ this.address = accounts[0];
773
+ this.walletType = "lute";
774
+ return accounts[0];
775
+ } catch (error) {
776
+ if (error instanceof X402Error) throw error;
777
+ if (error instanceof Error) {
778
+ if (error.message.includes("rejected") || error.message.includes("cancelled")) {
779
+ throw new X402Error("Connection rejected by user", "WALLET_CONNECTION_REJECTED");
780
+ }
781
+ }
782
+ throw new X402Error(
783
+ `Failed to connect Lute Wallet: ${error instanceof Error ? error.message : "Unknown error"}`,
784
+ "UNKNOWN_ERROR",
785
+ error
786
+ );
787
+ }
788
+ }
789
+ /**
790
+ * Connect to Pera Wallet (mobile via WalletConnect)
791
+ */
792
+ async connectPera() {
793
+ await loadPeraWallet();
717
794
  if (!PeraWalletConnect) {
718
795
  throw new X402Error("Failed to load Pera Wallet SDK", "WALLET_NOT_FOUND");
719
796
  }
@@ -722,6 +799,7 @@ var AlgorandProvider = class {
722
799
  const accounts = await this.peraWallet.reconnectSession();
723
800
  if (accounts.length > 0) {
724
801
  this.address = accounts[0];
802
+ this.walletType = "pera";
725
803
  return accounts[0];
726
804
  }
727
805
  const newAccounts = await this.peraWallet.connect();
@@ -729,8 +807,10 @@ var AlgorandProvider = class {
729
807
  throw new X402Error("No accounts returned from Pera Wallet", "WALLET_CONNECTION_REJECTED");
730
808
  }
731
809
  this.address = newAccounts[0];
810
+ this.walletType = "pera";
732
811
  this.peraWallet.connector?.on("disconnect", () => {
733
812
  this.address = null;
813
+ this.walletType = null;
734
814
  });
735
815
  return newAccounts[0];
736
816
  } catch (error) {
@@ -747,17 +827,21 @@ var AlgorandProvider = class {
747
827
  }
748
828
  }
749
829
  /**
750
- * Disconnect from Pera Wallet
830
+ * Disconnect from wallet
751
831
  */
752
832
  async disconnect() {
753
- if (this.peraWallet) {
833
+ if (this.walletType === "lute" && this.luteWallet) {
834
+ this.luteWallet = null;
835
+ }
836
+ if (this.walletType === "pera" && this.peraWallet) {
754
837
  try {
755
838
  await this.peraWallet.disconnect();
756
839
  } catch {
757
840
  }
841
+ this.peraWallet = null;
758
842
  }
759
- this.peraWallet = null;
760
843
  this.address = null;
844
+ this.walletType = null;
761
845
  this.algodClients.clear();
762
846
  }
763
847
  /**
@@ -801,7 +885,7 @@ var AlgorandProvider = class {
801
885
  */
802
886
  async signPayment(paymentInfo, chainConfig) {
803
887
  await loadAlgorandDeps();
804
- if (!this.peraWallet || !this.address) {
888
+ if (!this.address || !this.walletType) {
805
889
  throw new X402Error("Wallet not connected", "WALLET_NOT_CONNECTED");
806
890
  }
807
891
  if (!algosdk) {
@@ -821,11 +905,23 @@ var AlgorandProvider = class {
821
905
  suggestedParams,
822
906
  note: new TextEncoder().encode("x402 payment via uvd-x402-sdk")
823
907
  });
824
- const signedTxns = await this.peraWallet.signTransaction([[{ txn }]]);
825
- if (!signedTxns || signedTxns.length === 0) {
826
- throw new X402Error("No signed transaction returned", "SIGNATURE_REJECTED");
908
+ let signedTxn;
909
+ if (this.walletType === "lute" && this.luteWallet) {
910
+ const txnBase64 = uint8ArrayToBase64(txn.toByte());
911
+ const signedTxns = await this.luteWallet.signTxns([{ txn: txnBase64 }]);
912
+ if (!signedTxns || signedTxns.length === 0 || !signedTxns[0]) {
913
+ throw new X402Error("No signed transaction returned", "SIGNATURE_REJECTED");
914
+ }
915
+ signedTxn = Uint8Array.from(atob(signedTxns[0]), (c) => c.charCodeAt(0));
916
+ } else if (this.walletType === "pera" && this.peraWallet) {
917
+ const signedTxns = await this.peraWallet.signTransaction([[{ txn }]]);
918
+ if (!signedTxns || signedTxns.length === 0) {
919
+ throw new X402Error("No signed transaction returned", "SIGNATURE_REJECTED");
920
+ }
921
+ signedTxn = signedTxns[0];
922
+ } else {
923
+ throw new X402Error("No wallet available for signing", "WALLET_NOT_CONNECTED");
827
924
  }
828
- const signedTxn = signedTxns[0];
829
925
  const payload = {
830
926
  from: this.address,
831
927
  to: recipient,