@agentlayer.tech/wallet 0.1.25 → 0.1.27

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,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from abc import ABC, abstractmethod
6
+ import time
6
7
  from dataclasses import asdict, dataclass, field
7
8
  from typing import Any
8
9
 
@@ -524,6 +525,7 @@ class AgentWalletBackend(ABC):
524
525
  market: str,
525
526
  reserve: str,
526
527
  amount_ui: str,
528
+ obligation_address: str | None = None,
527
529
  ) -> dict[str, Any]:
528
530
  raise WalletBackendError(f"{self.name} does not support Kamino deposit previews.")
529
531
 
@@ -532,6 +534,8 @@ class AgentWalletBackend(ABC):
532
534
  market: str,
533
535
  reserve: str,
534
536
  amount_ui: str,
537
+ obligation_address: str | None = None,
538
+ approved_preview: dict[str, Any] | None = None,
535
539
  ) -> dict[str, Any]:
536
540
  raise WalletBackendError(f"{self.name} does not support Kamino deposit preparation.")
537
541
 
@@ -540,6 +544,8 @@ class AgentWalletBackend(ABC):
540
544
  market: str,
541
545
  reserve: str,
542
546
  amount_ui: str,
547
+ obligation_address: str | None = None,
548
+ approved_preview: dict[str, Any] | None = None,
543
549
  ) -> dict[str, Any]:
544
550
  raise WalletBackendError(f"{self.name} does not support Kamino deposits.")
545
551
 
@@ -548,6 +554,7 @@ class AgentWalletBackend(ABC):
548
554
  market: str,
549
555
  reserve: str,
550
556
  amount_ui: str,
557
+ obligation_address: str | None = None,
551
558
  ) -> dict[str, Any]:
552
559
  raise WalletBackendError(f"{self.name} does not support Kamino withdraw previews.")
553
560
 
@@ -556,6 +563,8 @@ class AgentWalletBackend(ABC):
556
563
  market: str,
557
564
  reserve: str,
558
565
  amount_ui: str,
566
+ obligation_address: str | None = None,
567
+ approved_preview: dict[str, Any] | None = None,
559
568
  ) -> dict[str, Any]:
560
569
  raise WalletBackendError(f"{self.name} does not support Kamino withdraw preparation.")
561
570
 
@@ -564,6 +573,8 @@ class AgentWalletBackend(ABC):
564
573
  market: str,
565
574
  reserve: str,
566
575
  amount_ui: str,
576
+ obligation_address: str | None = None,
577
+ approved_preview: dict[str, Any] | None = None,
567
578
  ) -> dict[str, Any]:
568
579
  raise WalletBackendError(f"{self.name} does not support Kamino withdraws.")
569
580
 
@@ -572,6 +583,7 @@ class AgentWalletBackend(ABC):
572
583
  market: str,
573
584
  reserve: str,
574
585
  amount_ui: str,
586
+ obligation_address: str | None = None,
575
587
  ) -> dict[str, Any]:
576
588
  raise WalletBackendError(f"{self.name} does not support Kamino borrow previews.")
577
589
 
@@ -580,6 +592,8 @@ class AgentWalletBackend(ABC):
580
592
  market: str,
581
593
  reserve: str,
582
594
  amount_ui: str,
595
+ obligation_address: str | None = None,
596
+ approved_preview: dict[str, Any] | None = None,
583
597
  ) -> dict[str, Any]:
584
598
  raise WalletBackendError(f"{self.name} does not support Kamino borrow preparation.")
585
599
 
@@ -588,6 +602,8 @@ class AgentWalletBackend(ABC):
588
602
  market: str,
589
603
  reserve: str,
590
604
  amount_ui: str,
605
+ obligation_address: str | None = None,
606
+ approved_preview: dict[str, Any] | None = None,
591
607
  ) -> dict[str, Any]:
592
608
  raise WalletBackendError(f"{self.name} does not support Kamino borrows.")
593
609
 
@@ -596,6 +612,7 @@ class AgentWalletBackend(ABC):
596
612
  market: str,
597
613
  reserve: str,
598
614
  amount_ui: str,
615
+ obligation_address: str | None = None,
599
616
  ) -> dict[str, Any]:
600
617
  raise WalletBackendError(f"{self.name} does not support Kamino repay previews.")
601
618
 
@@ -604,6 +621,8 @@ class AgentWalletBackend(ABC):
604
621
  market: str,
605
622
  reserve: str,
606
623
  amount_ui: str,
624
+ obligation_address: str | None = None,
625
+ approved_preview: dict[str, Any] | None = None,
607
626
  ) -> dict[str, Any]:
608
627
  raise WalletBackendError(f"{self.name} does not support Kamino repay preparation.")
609
628
 
@@ -612,6 +631,8 @@ class AgentWalletBackend(ABC):
612
631
  market: str,
613
632
  reserve: str,
614
633
  amount_ui: str,
634
+ obligation_address: str | None = None,
635
+ approved_preview: dict[str, Any] | None = None,
615
636
  ) -> dict[str, Any]:
616
637
  raise WalletBackendError(f"{self.name} does not support Kamino repays.")
617
638
 
@@ -731,16 +752,74 @@ class AgentWalletBackend(ABC):
731
752
  input_mint: str,
732
753
  output_mint: str,
733
754
  amount_ui: float,
734
- slippage_bps: int = 50,
755
+ slippage_bps: int = 300,
735
756
  ) -> dict[str, Any]:
736
757
  raise WalletBackendError(f"{self.name} does not support swap previews.")
737
758
 
759
+ async def preview_swap_intent(
760
+ self,
761
+ input_mint: str,
762
+ output_mint: str,
763
+ amount_ui: float,
764
+ slippage_bps: int = 300,
765
+ minimum_output_amount_raw: int | None = None,
766
+ max_fee_lamports: int | None = None,
767
+ valid_for_seconds: int = 30,
768
+ max_attempts: int = 2,
769
+ ) -> dict[str, Any]:
770
+ preview = await self.preview_swap(
771
+ input_mint=input_mint,
772
+ output_mint=output_mint,
773
+ amount_ui=amount_ui,
774
+ slippage_bps=slippage_bps,
775
+ )
776
+ fee_summary = preview.get("fee_summary") if isinstance(preview.get("fee_summary"), dict) else {}
777
+ network_fee_lamports = fee_summary.get("network_fee_lamports")
778
+ if max_fee_lamports is None and isinstance(network_fee_lamports, int):
779
+ max_fee_lamports = max(network_fee_lamports * 3, network_fee_lamports + 100_000)
780
+ resolved_min_raw = minimum_output_amount_raw
781
+ if resolved_min_raw is None and isinstance(preview.get("minimum_output_amount_raw"), int):
782
+ resolved_min_raw = int(preview["minimum_output_amount_raw"])
783
+ output_decimals = preview.get("output_decimals")
784
+ minimum_output_amount_ui = preview.get("minimum_output_amount_ui")
785
+ if resolved_min_raw is not None and isinstance(output_decimals, int):
786
+ minimum_output_amount_ui = int(resolved_min_raw) / (10**output_decimals)
787
+ return {
788
+ "chain": preview.get("chain", "solana"),
789
+ "network": preview.get("network", getattr(self, "network", "unknown")),
790
+ "mode": "intent_preview",
791
+ "asset_type": "solana-swap-intent",
792
+ "owner": preview.get("owner"),
793
+ "input_mint": preview.get("input_mint", input_mint),
794
+ "output_mint": preview.get("output_mint", output_mint),
795
+ "input_amount_ui": preview.get("input_amount_ui", amount_ui),
796
+ "input_amount_raw": preview.get("input_amount_raw"),
797
+ "minimum_output_amount_raw": resolved_min_raw,
798
+ "minimum_output_amount_ui": minimum_output_amount_ui,
799
+ "indicative_output_amount_ui": preview.get("estimated_output_amount_ui"),
800
+ "indicative_output_amount_raw": preview.get("estimated_output_amount_raw"),
801
+ "max_slippage_bps": slippage_bps,
802
+ "slippage_bps": slippage_bps,
803
+ "max_fee_lamports": max_fee_lamports,
804
+ "valid_for_seconds": valid_for_seconds,
805
+ "valid_until_epoch_seconds": int(time.time()) + valid_for_seconds,
806
+ "max_attempts": max_attempts,
807
+ "allowed_providers": ["jupiter-ultra", "jupiter-metis"],
808
+ "recipient_policy": "owner-only",
809
+ "spend_policy": "exact-input",
810
+ "indicative_swap_provider": preview.get("swap_provider"),
811
+ "indicative_fee_summary": fee_summary,
812
+ "can_send": preview.get("can_send"),
813
+ "sign_only": preview.get("sign_only"),
814
+ "source": "swap-intent",
815
+ }
816
+
738
817
  async def prepare_swap(
739
818
  self,
740
819
  input_mint: str,
741
820
  output_mint: str,
742
821
  amount_ui: float,
743
- slippage_bps: int = 50,
822
+ slippage_bps: int = 300,
744
823
  ) -> dict[str, Any]:
745
824
  raise WalletBackendError(f"{self.name} does not support swap preparation.")
746
825
 
@@ -752,7 +831,7 @@ class AgentWalletBackend(ABC):
752
831
  input_mint=str(preview["input_mint"]),
753
832
  output_mint=str(preview["output_mint"]),
754
833
  amount_ui=float(preview["input_amount_ui"]),
755
- slippage_bps=int(preview.get("slippage_bps") or 50),
834
+ slippage_bps=int(preview.get("slippage_bps") or 300),
756
835
  )
757
836
 
758
837
  async def execute_swap(
@@ -760,7 +839,7 @@ class AgentWalletBackend(ABC):
760
839
  input_mint: str,
761
840
  output_mint: str,
762
841
  amount_ui: float,
763
- slippage_bps: int = 50,
842
+ slippage_bps: int = 300,
764
843
  ) -> dict[str, Any]:
765
844
  raise WalletBackendError(f"{self.name} does not support swaps.")
766
845
 
@@ -772,8 +851,55 @@ class AgentWalletBackend(ABC):
772
851
  input_mint=str(preview["input_mint"]),
773
852
  output_mint=str(preview["output_mint"]),
774
853
  amount_ui=float(preview["input_amount_ui"]),
775
- slippage_bps=int(preview.get("slippage_bps") or 50),
854
+ slippage_bps=int(preview.get("slippage_bps") or 300),
855
+ )
856
+
857
+ async def execute_swap_intent(
858
+ self,
859
+ *,
860
+ input_mint: str,
861
+ output_mint: str,
862
+ amount_ui: float,
863
+ slippage_bps: int = 300,
864
+ minimum_output_amount_raw: int | None = None,
865
+ max_fee_lamports: int | None = None,
866
+ valid_until_epoch_seconds: int | None = None,
867
+ max_attempts: int = 2,
868
+ ) -> dict[str, Any]:
869
+ if valid_until_epoch_seconds is not None and int(time.time()) > int(valid_until_epoch_seconds):
870
+ raise WalletBackendError("Approved swap intent has expired. Create a fresh intent preview.")
871
+ preview = await self.preview_swap(
872
+ input_mint=input_mint,
873
+ output_mint=output_mint,
874
+ amount_ui=amount_ui,
875
+ slippage_bps=slippage_bps,
776
876
  )
877
+ output_raw = preview.get("estimated_output_amount_raw")
878
+ if (
879
+ minimum_output_amount_raw is not None
880
+ and isinstance(output_raw, int)
881
+ and output_raw < int(minimum_output_amount_raw)
882
+ ):
883
+ raise WalletBackendError(
884
+ "Fresh swap quote is below the approved minimum output. Funds were not moved."
885
+ )
886
+ fee_summary = preview.get("fee_summary") if isinstance(preview.get("fee_summary"), dict) else {}
887
+ network_fee_lamports = fee_summary.get("network_fee_lamports")
888
+ if (
889
+ max_fee_lamports is not None
890
+ and isinstance(network_fee_lamports, int)
891
+ and network_fee_lamports > int(max_fee_lamports)
892
+ ):
893
+ raise WalletBackendError("Fresh swap fee exceeds the approved fee limit. Funds were not moved.")
894
+ result = await self.execute_swap_from_preview(preview)
895
+ result["intent_execution"] = {
896
+ "approved_minimum_output_amount_raw": minimum_output_amount_raw,
897
+ "approved_max_fee_lamports": max_fee_lamports,
898
+ "fresh_quote_used": True,
899
+ "attempt_count": 1,
900
+ "max_attempts": max_attempts,
901
+ }
902
+ return result
777
903
 
778
904
  async def get_bags_claimable_positions(
779
905
  self,