@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.
- package/.openclaw/extensions/agent-wallet/README.md +1 -1
- package/.openclaw/extensions/agent-wallet/dist/index.js +35 -9
- package/.openclaw/extensions/agent-wallet/index.ts +35 -9
- package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +4 -0
- package/.openclaw/extensions/agent-wallet/package.json +1 -1
- package/.openclaw/extensions/agent-wallet/skills/wallet-operator/SKILL.md +5 -1
- package/CHANGELOG.md +26 -0
- package/agent-wallet/README.md +1 -1
- package/agent-wallet/agent_wallet/config.py +1 -0
- package/agent-wallet/agent_wallet/openclaw_adapter.py +242 -15
- package/agent-wallet/agent_wallet/openclaw_cli.py +1 -0
- package/agent-wallet/agent_wallet/providers/jupiter.py +127 -14
- package/agent-wallet/agent_wallet/providers/kamino.py +6 -0
- package/agent-wallet/agent_wallet/transaction_policy.py +6 -0
- package/agent-wallet/agent_wallet/wallet_layer/base.py +131 -5
- package/agent-wallet/agent_wallet/wallet_layer/solana.py +528 -43
- package/agent-wallet/pyproject.toml +1 -1
- package/agent-wallet/skills/wallet-operator/SKILL.md +7 -2
- package/package.json +2 -2
|
@@ -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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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,
|