@agentlayer.tech/wallet 0.1.66 → 0.1.67
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/index.ts +82 -0
- package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +7 -1
- package/.openclaw/extensions/agent-wallet/package.json +1 -1
- package/VERSION +1 -1
- package/agent-wallet/README.md +6 -0
- package/agent-wallet/agent_wallet/__init__.py +1 -1
- package/agent-wallet/agent_wallet/openclaw_adapter.py +481 -4
- package/agent-wallet/agent_wallet/providers/kamino.py +169 -3
- package/agent-wallet/agent_wallet/transaction_policy.py +60 -0
- package/agent-wallet/agent_wallet/wallet_layer/base.py +124 -0
- package/agent-wallet/agent_wallet/wallet_layer/solana.py +563 -0
- package/agent-wallet/agent_wallet/wallet_layer/wdk_evm.py +16 -0
- package/agent-wallet/openclaw.plugin.json +2 -2
- package/agent-wallet/pyproject.toml +1 -1
- package/agent-wallet/scripts/install_openclaw_local_config.py +6 -0
- package/agent-wallet/skills/wallet-operator/SKILL.md +5 -3
- package/claude-code/plugins/agent-wallet/.claude-plugin/plugin.json +1 -1
- package/codex/plugins/agent-wallet/.codex-plugin/plugin.json +1 -1
- package/hermes/plugins/agent_wallet/plugin.yaml +1 -1
- package/package.json +1 -1
- package/wdk-btc-wallet/package.json +1 -1
- package/wdk-evm-wallet/package.json +1 -1
- package/wdk-evm-wallet/src/wdk_evm_wallet.js +126 -19
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import json
|
|
6
|
+
import time
|
|
5
7
|
from typing import Any
|
|
6
8
|
|
|
7
9
|
from agent_wallet.config import normalize_solana_network, settings
|
|
@@ -9,6 +11,41 @@ from agent_wallet.exceptions import ProviderError
|
|
|
9
11
|
from agent_wallet.http_client import get_client
|
|
10
12
|
|
|
11
13
|
KAMINO_BUILD_TIMEOUT_SECONDS = 20.0
|
|
14
|
+
# Discovery data only (market/vault catalogs and rate metrics) — never
|
|
15
|
+
# user-specific data such as obligations, positions, rewards, or portfolios.
|
|
16
|
+
# Catalogs change when Kamino ships a market/vault (days); rate metrics drift
|
|
17
|
+
# slower than the API's own aggregation window over these TTLs. The cache is
|
|
18
|
+
# long-lived only inside the resident read worker; cold CLI runs start empty.
|
|
19
|
+
MARKETS_CACHE_TTL_SECONDS = 600.0
|
|
20
|
+
RESERVES_CACHE_TTL_SECONDS = 180.0
|
|
21
|
+
EARN_VAULTS_CACHE_TTL_SECONDS = 600.0
|
|
22
|
+
EARN_VAULT_METRICS_CACHE_TTL_SECONDS = 180.0
|
|
23
|
+
_DISCOVERY_CACHE_MAX_ENTRIES = 128
|
|
24
|
+
_discovery_cache: dict[str, tuple[float, str]] = {}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _discovery_cache_get(cache_key: str) -> Any | None:
|
|
28
|
+
entry = _discovery_cache.get(cache_key)
|
|
29
|
+
if entry is None:
|
|
30
|
+
return None
|
|
31
|
+
expires_at, payload_text = entry
|
|
32
|
+
if expires_at <= time.monotonic():
|
|
33
|
+
_discovery_cache.pop(cache_key, None)
|
|
34
|
+
return None
|
|
35
|
+
return json.loads(payload_text)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _discovery_cache_set(cache_key: str, payload: Any, ttl_seconds: float) -> None:
|
|
39
|
+
try:
|
|
40
|
+
payload_text = json.dumps(payload)
|
|
41
|
+
except (TypeError, ValueError):
|
|
42
|
+
return
|
|
43
|
+
if len(_discovery_cache) >= _DISCOVERY_CACHE_MAX_ENTRIES:
|
|
44
|
+
for stale_key in sorted(_discovery_cache, key=lambda key: _discovery_cache[key][0])[
|
|
45
|
+
: len(_discovery_cache) - _DISCOVERY_CACHE_MAX_ENTRIES + 1
|
|
46
|
+
]:
|
|
47
|
+
_discovery_cache.pop(stale_key, None)
|
|
48
|
+
_discovery_cache[cache_key] = (time.monotonic() + ttl_seconds, payload_text)
|
|
12
49
|
|
|
13
50
|
|
|
14
51
|
def _normalized_api_base() -> str:
|
|
@@ -48,6 +85,10 @@ def _env_name(network: str) -> str:
|
|
|
48
85
|
|
|
49
86
|
async def fetch_lend_markets() -> dict[str, Any]:
|
|
50
87
|
"""Fetch Kamino lending markets for the configured program id."""
|
|
88
|
+
cache_key = f"markets:{settings.kamino_program_id}"
|
|
89
|
+
cached = _discovery_cache_get(cache_key)
|
|
90
|
+
if cached is not None:
|
|
91
|
+
return cached
|
|
51
92
|
client = get_client()
|
|
52
93
|
response = await client.get(
|
|
53
94
|
f"{_normalized_api_base()}/v2/kamino-market",
|
|
@@ -55,11 +96,85 @@ async def fetch_lend_markets() -> dict[str, Any]:
|
|
|
55
96
|
)
|
|
56
97
|
if response.status_code != 200:
|
|
57
98
|
raise ProviderError("kamino", f"HTTP {response.status_code}: {response.text[:300]}")
|
|
58
|
-
|
|
99
|
+
result = _normalize_named_list_response(
|
|
59
100
|
response.json(),
|
|
60
101
|
key="markets",
|
|
61
102
|
provider_name="kamino",
|
|
62
103
|
)
|
|
104
|
+
_discovery_cache_set(cache_key, result, MARKETS_CACHE_TTL_SECONDS)
|
|
105
|
+
return result
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
async def fetch_portfolio(*, user: str) -> dict[str, Any]:
|
|
109
|
+
"""Fetch the unified Kamino product portfolio for one wallet."""
|
|
110
|
+
client = get_client()
|
|
111
|
+
response = await client.get(f"{_normalized_api_base()}/portfolio/{user}")
|
|
112
|
+
if response.status_code != 200:
|
|
113
|
+
raise ProviderError("kamino", f"HTTP {response.status_code}: {response.text[:300]}")
|
|
114
|
+
data = response.json()
|
|
115
|
+
if not isinstance(data, dict):
|
|
116
|
+
raise ProviderError("kamino", "Unexpected portfolio response from Kamino.")
|
|
117
|
+
return data
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
async def fetch_earn_vaults() -> dict[str, Any]:
|
|
121
|
+
"""Fetch the list of Kamino Earn vaults."""
|
|
122
|
+
cache_key = "earn_vaults"
|
|
123
|
+
cached = _discovery_cache_get(cache_key)
|
|
124
|
+
if cached is not None:
|
|
125
|
+
return cached
|
|
126
|
+
client = get_client()
|
|
127
|
+
response = await client.get(f"{_normalized_api_base()}/kvaults/vaults")
|
|
128
|
+
if response.status_code != 200:
|
|
129
|
+
raise ProviderError("kamino", f"HTTP {response.status_code}: {response.text[:300]}")
|
|
130
|
+
result = _normalize_named_list_response(
|
|
131
|
+
response.json(),
|
|
132
|
+
key="vaults",
|
|
133
|
+
provider_name="kamino",
|
|
134
|
+
)
|
|
135
|
+
_discovery_cache_set(cache_key, result, EARN_VAULTS_CACHE_TTL_SECONDS)
|
|
136
|
+
return result
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
async def fetch_earn_vault_metrics(*, vault: str, network: str) -> dict[str, Any]:
|
|
140
|
+
"""Fetch APY/TVL metrics for one Kamino Earn vault."""
|
|
141
|
+
env = _env_name(network)
|
|
142
|
+
cache_key = f"earn_vault_metrics:{vault}:{env}"
|
|
143
|
+
cached = _discovery_cache_get(cache_key)
|
|
144
|
+
if cached is not None:
|
|
145
|
+
return cached
|
|
146
|
+
client = get_client()
|
|
147
|
+
response = await client.get(
|
|
148
|
+
f"{_normalized_api_base()}/kvaults/{vault}/metrics",
|
|
149
|
+
params={"env": env},
|
|
150
|
+
)
|
|
151
|
+
if response.status_code != 200:
|
|
152
|
+
raise ProviderError("kamino", f"HTTP {response.status_code}: {response.text[:300]}")
|
|
153
|
+
data = response.json()
|
|
154
|
+
if not isinstance(data, dict):
|
|
155
|
+
raise ProviderError("kamino", "Unexpected vault metrics response from Kamino.")
|
|
156
|
+
_discovery_cache_set(cache_key, data, EARN_VAULT_METRICS_CACHE_TTL_SECONDS)
|
|
157
|
+
return data
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
async def fetch_earn_user_positions(
|
|
161
|
+
*,
|
|
162
|
+
user: str,
|
|
163
|
+
network: str,
|
|
164
|
+
) -> dict[str, Any]:
|
|
165
|
+
"""Fetch all Kamino Earn vault positions for a wallet."""
|
|
166
|
+
client = get_client()
|
|
167
|
+
response = await client.get(
|
|
168
|
+
f"{_normalized_api_base()}/kvaults/users/{user}/positions",
|
|
169
|
+
params={"env": _env_name(network)},
|
|
170
|
+
)
|
|
171
|
+
if response.status_code != 200:
|
|
172
|
+
raise ProviderError("kamino", f"HTTP {response.status_code}: {response.text[:300]}")
|
|
173
|
+
return _normalize_named_list_response(
|
|
174
|
+
response.json(),
|
|
175
|
+
key="positions",
|
|
176
|
+
provider_name="kamino",
|
|
177
|
+
)
|
|
63
178
|
|
|
64
179
|
|
|
65
180
|
async def fetch_lend_market_reserves(
|
|
@@ -68,18 +183,25 @@ async def fetch_lend_market_reserves(
|
|
|
68
183
|
network: str,
|
|
69
184
|
) -> dict[str, Any]:
|
|
70
185
|
"""Fetch reserve metrics for one Kamino lending market."""
|
|
186
|
+
env = _env_name(network)
|
|
187
|
+
cache_key = f"reserves:{market}:{env}"
|
|
188
|
+
cached = _discovery_cache_get(cache_key)
|
|
189
|
+
if cached is not None:
|
|
190
|
+
return cached
|
|
71
191
|
client = get_client()
|
|
72
192
|
response = await client.get(
|
|
73
193
|
f"{_normalized_api_base()}/kamino-market/{market}/reserves/metrics",
|
|
74
|
-
params={"env":
|
|
194
|
+
params={"env": env},
|
|
75
195
|
)
|
|
76
196
|
if response.status_code != 200:
|
|
77
197
|
raise ProviderError("kamino", f"HTTP {response.status_code}: {response.text[:300]}")
|
|
78
|
-
|
|
198
|
+
result = _normalize_named_list_response(
|
|
79
199
|
response.json(),
|
|
80
200
|
key="reserves",
|
|
81
201
|
provider_name="kamino",
|
|
82
202
|
)
|
|
203
|
+
_discovery_cache_set(cache_key, result, RESERVES_CACHE_TTL_SECONDS)
|
|
204
|
+
return result
|
|
83
205
|
|
|
84
206
|
|
|
85
207
|
async def fetch_lend_user_obligations(
|
|
@@ -236,3 +358,47 @@ async def build_lend_repay_transaction(
|
|
|
236
358
|
if response.status_code != 200:
|
|
237
359
|
raise ProviderError("kamino", f"HTTP {response.status_code}: {response.text[:300]}")
|
|
238
360
|
return _normalized_tx_response(response.json(), provider_name="kamino")
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
async def build_earn_deposit_transaction(
|
|
364
|
+
*,
|
|
365
|
+
wallet: str,
|
|
366
|
+
kvault: str,
|
|
367
|
+
amount_ui: str,
|
|
368
|
+
) -> dict[str, Any]:
|
|
369
|
+
"""Build an unsigned Kamino Earn deposit transaction."""
|
|
370
|
+
client = get_client()
|
|
371
|
+
response = await client.post(
|
|
372
|
+
f"{_normalized_api_base()}/ktx/kvault/deposit",
|
|
373
|
+
json={
|
|
374
|
+
"wallet": wallet,
|
|
375
|
+
"kvault": kvault,
|
|
376
|
+
"amount": amount_ui,
|
|
377
|
+
},
|
|
378
|
+
timeout=KAMINO_BUILD_TIMEOUT_SECONDS,
|
|
379
|
+
)
|
|
380
|
+
if response.status_code != 200:
|
|
381
|
+
raise ProviderError("kamino", f"HTTP {response.status_code}: {response.text[:300]}")
|
|
382
|
+
return _normalized_tx_response(response.json(), provider_name="kamino")
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
async def build_earn_withdraw_transaction(
|
|
386
|
+
*,
|
|
387
|
+
wallet: str,
|
|
388
|
+
kvault: str,
|
|
389
|
+
amount_ui: str,
|
|
390
|
+
) -> dict[str, Any]:
|
|
391
|
+
"""Build an unsigned Kamino Earn withdraw transaction."""
|
|
392
|
+
client = get_client()
|
|
393
|
+
response = await client.post(
|
|
394
|
+
f"{_normalized_api_base()}/ktx/kvault/withdraw",
|
|
395
|
+
json={
|
|
396
|
+
"wallet": wallet,
|
|
397
|
+
"kvault": kvault,
|
|
398
|
+
"amount": amount_ui,
|
|
399
|
+
},
|
|
400
|
+
timeout=KAMINO_BUILD_TIMEOUT_SECONDS,
|
|
401
|
+
)
|
|
402
|
+
if response.status_code != 200:
|
|
403
|
+
raise ProviderError("kamino", f"HTTP {response.status_code}: {response.text[:300]}")
|
|
404
|
+
return _normalized_tx_response(response.json(), provider_name="kamino")
|
|
@@ -18,6 +18,7 @@ JUPITER_V6_PROGRAM_ID = "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5Nt7NQYjN"
|
|
|
18
18
|
JUPITER_ULTRA_EXACT_OUT_PROGRAM_ID = "j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X"
|
|
19
19
|
JUPITER_DCA_PROGRAM_ID = "DCA265Vj8a7wYymQG8LqM3m7A4QeV9hiC7VYh4S6Jsa"
|
|
20
20
|
KAMINO_LEND_PROGRAM_ID = "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"
|
|
21
|
+
KAMINO_EARN_PROGRAM_ID = "KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd"
|
|
21
22
|
NATIVE_SOL_MINT = "So11111111111111111111111111111111111111112"
|
|
22
23
|
DEFAULT_NATIVE_SOL_EXTRA_SPEND_ALLOWANCE_LAMPORTS = 10_000_000
|
|
23
24
|
|
|
@@ -45,6 +46,7 @@ FORBIDDEN_PROGRAMS = {
|
|
|
45
46
|
}
|
|
46
47
|
KAMINO_ALLOWED_PROGRAMS = CORE_PROGRAM_IDS | {
|
|
47
48
|
KAMINO_LEND_PROGRAM_ID,
|
|
49
|
+
KAMINO_EARN_PROGRAM_ID,
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
|
|
@@ -513,6 +515,64 @@ def verify_provider_kamino_lend_transaction(
|
|
|
513
515
|
}
|
|
514
516
|
|
|
515
517
|
|
|
518
|
+
def verify_provider_kamino_earn_transaction(
|
|
519
|
+
message: Any,
|
|
520
|
+
*,
|
|
521
|
+
wallet_address: str,
|
|
522
|
+
vault_address: str,
|
|
523
|
+
action: str,
|
|
524
|
+
vault_token_mint: str | None = None,
|
|
525
|
+
loaded_addresses: list[str] | None = None,
|
|
526
|
+
) -> dict[str, Any]:
|
|
527
|
+
binding = _assert_basic_wallet_binding(
|
|
528
|
+
message,
|
|
529
|
+
wallet_address=wallet_address,
|
|
530
|
+
loaded_addresses=loaded_addresses,
|
|
531
|
+
)
|
|
532
|
+
keys = binding["account_keys"]
|
|
533
|
+
if vault_address not in keys:
|
|
534
|
+
raise WalletBackendError(
|
|
535
|
+
f"{action} transaction does not reference the expected Kamino Earn vault."
|
|
536
|
+
)
|
|
537
|
+
if vault_token_mint and vault_token_mint not in keys:
|
|
538
|
+
raise WalletBackendError(
|
|
539
|
+
f"{action} transaction does not reference the expected Kamino Earn vault token mint."
|
|
540
|
+
)
|
|
541
|
+
program_ids = _program_ids(message, loaded_addresses)
|
|
542
|
+
unknown_program_ids = _assert_program_allowlist(
|
|
543
|
+
program_ids,
|
|
544
|
+
allowed_programs=KAMINO_ALLOWED_PROGRAMS,
|
|
545
|
+
label=action,
|
|
546
|
+
reject_unknown=False,
|
|
547
|
+
)
|
|
548
|
+
recognized_kamino_program_ids = [
|
|
549
|
+
pid for pid in program_ids if pid == KAMINO_EARN_PROGRAM_ID
|
|
550
|
+
]
|
|
551
|
+
if not recognized_kamino_program_ids:
|
|
552
|
+
raise WalletBackendError(
|
|
553
|
+
f"{action} transaction does not include the expected Kamino Earn program."
|
|
554
|
+
)
|
|
555
|
+
return {
|
|
556
|
+
"wallet_address": wallet_address,
|
|
557
|
+
"fee_payer": binding["fee_payer"],
|
|
558
|
+
"required_signer_keys": binding["required_signer_keys"],
|
|
559
|
+
"required_signature_count": binding["required_signature_count"],
|
|
560
|
+
"wallet_signer_index": binding["wallet_signer_index"],
|
|
561
|
+
"sponsored_fee_payer": binding["sponsored_fee_payer"],
|
|
562
|
+
"program_ids": program_ids,
|
|
563
|
+
"unknown_program_ids": unknown_program_ids,
|
|
564
|
+
"recognized_kamino_program_ids": recognized_kamino_program_ids,
|
|
565
|
+
"has_recognized_kamino_program": True,
|
|
566
|
+
"non_core_program_ids": [pid for pid in program_ids if pid not in CORE_PROGRAM_IDS],
|
|
567
|
+
"account_key_count": len(keys),
|
|
568
|
+
"instruction_count": len(_compiled_instructions(message)),
|
|
569
|
+
"vault_address": vault_address,
|
|
570
|
+
"vault_token_mint": vault_token_mint,
|
|
571
|
+
"action": action,
|
|
572
|
+
"verified": True,
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
|
|
516
576
|
def verify_provider_flash_transaction(
|
|
517
577
|
message: Any,
|
|
518
578
|
*,
|
|
@@ -549,6 +549,24 @@ class AgentWalletBackend(ABC):
|
|
|
549
549
|
async def get_kamino_lend_markets(self) -> dict[str, Any]:
|
|
550
550
|
raise WalletBackendError(f"{self.name} does not support Kamino market lookup.")
|
|
551
551
|
|
|
552
|
+
async def get_kamino_portfolio(self, user: str | None = None) -> dict[str, Any]:
|
|
553
|
+
raise WalletBackendError(f"{self.name} does not support Kamino portfolio lookup.")
|
|
554
|
+
|
|
555
|
+
async def get_kamino_vaults(
|
|
556
|
+
self,
|
|
557
|
+
vault_address: str | None = None,
|
|
558
|
+
token_mint: str | None = None,
|
|
559
|
+
include_metrics: bool = False,
|
|
560
|
+
limit: int | None = None,
|
|
561
|
+
) -> dict[str, Any]:
|
|
562
|
+
raise WalletBackendError(f"{self.name} does not support Kamino vault lookup.")
|
|
563
|
+
|
|
564
|
+
async def get_kamino_earn_positions(self, user: str | None = None) -> dict[str, Any]:
|
|
565
|
+
raise WalletBackendError(f"{self.name} does not support Kamino Earn position lookup.")
|
|
566
|
+
|
|
567
|
+
async def get_kamino_liquidity_positions(self, user: str | None = None) -> dict[str, Any]:
|
|
568
|
+
raise WalletBackendError(f"{self.name} does not support Kamino liquidity position lookup.")
|
|
569
|
+
|
|
552
570
|
async def get_kamino_lend_market_reserves(self, market: str) -> dict[str, Any]:
|
|
553
571
|
raise WalletBackendError(f"{self.name} does not support Kamino reserve lookup.")
|
|
554
572
|
|
|
@@ -791,6 +809,112 @@ class AgentWalletBackend(ABC):
|
|
|
791
809
|
) -> dict[str, Any]:
|
|
792
810
|
raise WalletBackendError(f"{self.name} does not support Kamino repays.")
|
|
793
811
|
|
|
812
|
+
async def preview_kamino_earn_deposit(
|
|
813
|
+
self,
|
|
814
|
+
kvault: str,
|
|
815
|
+
amount_ui: str,
|
|
816
|
+
) -> dict[str, Any]:
|
|
817
|
+
raise WalletBackendError(f"{self.name} does not support Kamino Earn deposit previews.")
|
|
818
|
+
|
|
819
|
+
def _build_kamino_earn_intent_preview(
|
|
820
|
+
self,
|
|
821
|
+
base_preview: dict[str, Any],
|
|
822
|
+
*,
|
|
823
|
+
valid_for_seconds: int,
|
|
824
|
+
) -> dict[str, Any]:
|
|
825
|
+
if valid_for_seconds <= 0 or valid_for_seconds > 300:
|
|
826
|
+
raise WalletBackendError("valid_for_seconds must be between 1 and 300.")
|
|
827
|
+
try:
|
|
828
|
+
can_send = bool(self.get_capabilities().can_send_transaction)
|
|
829
|
+
except Exception:
|
|
830
|
+
can_send = bool(base_preview.get("can_send"))
|
|
831
|
+
return {
|
|
832
|
+
"chain": "solana",
|
|
833
|
+
"network": getattr(self, "network", "mainnet"),
|
|
834
|
+
"mode": "intent_preview",
|
|
835
|
+
"asset_type": "kamino-earn-intent",
|
|
836
|
+
"kamino_operation": base_preview["asset_type"],
|
|
837
|
+
"owner": base_preview["owner"],
|
|
838
|
+
"kvault": base_preview["kvault"],
|
|
839
|
+
"amount_ui": base_preview["amount_ui"],
|
|
840
|
+
"vault_info": base_preview.get("vault_info"),
|
|
841
|
+
"position_info": base_preview.get("position_info"),
|
|
842
|
+
"recipient_policy": "owner-only",
|
|
843
|
+
"spend_policy": "exact-amount",
|
|
844
|
+
"valid_for_seconds": valid_for_seconds,
|
|
845
|
+
"valid_until_epoch_seconds": int(time.time()) + valid_for_seconds,
|
|
846
|
+
"intent_note": (
|
|
847
|
+
"This is an intent approval preview. Execute re-derives the Kamino "
|
|
848
|
+
"Earn transaction and only signs/sends if it remains within these approved parameters."
|
|
849
|
+
),
|
|
850
|
+
"can_send": can_send,
|
|
851
|
+
"sign_only": bool(getattr(self, "sign_only", False)),
|
|
852
|
+
"source": "kamino-intent",
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
async def preview_kamino_earn_deposit_intent(
|
|
856
|
+
self,
|
|
857
|
+
kvault: str,
|
|
858
|
+
amount_ui: str,
|
|
859
|
+
valid_for_seconds: int = 120,
|
|
860
|
+
) -> dict[str, Any]:
|
|
861
|
+
base = await self.preview_kamino_earn_deposit(
|
|
862
|
+
kvault=kvault,
|
|
863
|
+
amount_ui=amount_ui,
|
|
864
|
+
)
|
|
865
|
+
return self._build_kamino_earn_intent_preview(base, valid_for_seconds=valid_for_seconds)
|
|
866
|
+
|
|
867
|
+
async def prepare_kamino_earn_deposit(
|
|
868
|
+
self,
|
|
869
|
+
kvault: str,
|
|
870
|
+
amount_ui: str,
|
|
871
|
+
approved_preview: dict[str, Any] | None = None,
|
|
872
|
+
) -> dict[str, Any]:
|
|
873
|
+
raise WalletBackendError(f"{self.name} does not support Kamino Earn deposit preparation.")
|
|
874
|
+
|
|
875
|
+
async def execute_kamino_earn_deposit(
|
|
876
|
+
self,
|
|
877
|
+
kvault: str,
|
|
878
|
+
amount_ui: str,
|
|
879
|
+
approved_preview: dict[str, Any] | None = None,
|
|
880
|
+
) -> dict[str, Any]:
|
|
881
|
+
raise WalletBackendError(f"{self.name} does not support Kamino Earn deposits.")
|
|
882
|
+
|
|
883
|
+
async def preview_kamino_earn_withdraw(
|
|
884
|
+
self,
|
|
885
|
+
kvault: str,
|
|
886
|
+
amount_ui: str,
|
|
887
|
+
) -> dict[str, Any]:
|
|
888
|
+
raise WalletBackendError(f"{self.name} does not support Kamino Earn withdraw previews.")
|
|
889
|
+
|
|
890
|
+
async def preview_kamino_earn_withdraw_intent(
|
|
891
|
+
self,
|
|
892
|
+
kvault: str,
|
|
893
|
+
amount_ui: str,
|
|
894
|
+
valid_for_seconds: int = 120,
|
|
895
|
+
) -> dict[str, Any]:
|
|
896
|
+
base = await self.preview_kamino_earn_withdraw(
|
|
897
|
+
kvault=kvault,
|
|
898
|
+
amount_ui=amount_ui,
|
|
899
|
+
)
|
|
900
|
+
return self._build_kamino_earn_intent_preview(base, valid_for_seconds=valid_for_seconds)
|
|
901
|
+
|
|
902
|
+
async def prepare_kamino_earn_withdraw(
|
|
903
|
+
self,
|
|
904
|
+
kvault: str,
|
|
905
|
+
amount_ui: str,
|
|
906
|
+
approved_preview: dict[str, Any] | None = None,
|
|
907
|
+
) -> dict[str, Any]:
|
|
908
|
+
raise WalletBackendError(f"{self.name} does not support Kamino Earn withdraw preparation.")
|
|
909
|
+
|
|
910
|
+
async def execute_kamino_earn_withdraw(
|
|
911
|
+
self,
|
|
912
|
+
kvault: str,
|
|
913
|
+
amount_ui: str,
|
|
914
|
+
approved_preview: dict[str, Any] | None = None,
|
|
915
|
+
) -> dict[str, Any]:
|
|
916
|
+
raise WalletBackendError(f"{self.name} does not support Kamino Earn withdraws.")
|
|
917
|
+
|
|
794
918
|
async def preview_close_empty_token_accounts(
|
|
795
919
|
self,
|
|
796
920
|
limit: int = 8,
|