@agentlayer.tech/wallet 0.1.30 → 0.1.33
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 -2
- package/.openclaw/extensions/agent-wallet/dist/index.js +6 -340
- package/.openclaw/extensions/agent-wallet/index.ts +6 -340
- package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +0 -43
- package/.openclaw/extensions/agent-wallet/package.json +1 -1
- package/.openclaw/extensions/agent-wallet/skills/wallet-operator/SKILL.md +1 -3
- package/CHANGELOG.md +60 -0
- package/README.md +0 -5
- package/agent-wallet/.env.example +0 -12
- package/agent-wallet/README.md +0 -35
- package/agent-wallet/agent_wallet/btc_user_wallets.py +32 -1
- package/agent-wallet/agent_wallet/config.py +11 -7
- package/agent-wallet/agent_wallet/evm_user_wallets.py +2 -0
- package/agent-wallet/agent_wallet/openclaw_adapter.py +1 -655
- package/agent-wallet/agent_wallet/openclaw_cli.py +0 -7
- package/agent-wallet/agent_wallet/providers/evm_portfolio.py +18 -42
- package/agent-wallet/agent_wallet/providers/jupiter.py +1 -307
- package/agent-wallet/agent_wallet/providers/wdk_btc_local.py +31 -3
- package/agent-wallet/agent_wallet/providers/wdk_evm_local.py +37 -3
- package/agent-wallet/agent_wallet/transaction_policy.py +0 -262
- package/agent-wallet/agent_wallet/wallet_layer/base.py +0 -100
- package/agent-wallet/agent_wallet/wallet_layer/solana.py +1 -1118
- package/agent-wallet/openclaw.plugin.json +0 -4
- package/agent-wallet/pyproject.toml +1 -1
- package/agent-wallet/scripts/install_agent_wallet.py +113 -6
- package/agent-wallet/scripts/install_openclaw_local_config.py +7 -5
- package/agent-wallet/skills/wallet-operator/SKILL.md +1 -5
- package/bin/openclaw-agent-wallet.mjs +434 -68
- package/claude-code/plugins/agent-wallet/scripts/run_mcp.sh +21 -3
- package/codex/plugins/agent-wallet/scripts/run_mcp.sh +18 -0
- package/codex/plugins/agent-wallet/server.py +2 -118
- package/hermes/plugins/agent_wallet/tools.py +1 -1
- package/package.json +1 -1
- package/wdk-btc-wallet/src/local_vault.js +45 -68
- package/wdk-btc-wallet/src/server.js +1 -0
- package/wdk-evm-wallet/README.md +4 -3
- package/wdk-evm-wallet/src/config.js +15 -0
- package/wdk-evm-wallet/src/local_vault.js +45 -68
- package/wdk-evm-wallet/src/server.js +1 -0
- package/agent-wallet/agent_wallet/providers/houdini.py +0 -539
|
@@ -117,10 +117,6 @@
|
|
|
117
117
|
"type": "string",
|
|
118
118
|
"description": "Optional Jupiter Portfolio API base URL for Jupiter-specific positions and staking data."
|
|
119
119
|
},
|
|
120
|
-
"jupiterLendBaseUrl": {
|
|
121
|
-
"type": "string",
|
|
122
|
-
"description": "Optional Jupiter Lend API base URL for Earn read and deposit/withdraw flows."
|
|
123
|
-
},
|
|
124
120
|
"jupiterApiKey": {
|
|
125
121
|
"type": "string",
|
|
126
122
|
"description": "Optional Jupiter API key if your deployment uses a keyed endpoint."
|
|
@@ -182,6 +182,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
182
182
|
parser.add_argument("--extension-path", default=str(_extension_path()))
|
|
183
183
|
parser.add_argument("--wdk-btc-root", default=str(_default_wdk_btc_root()))
|
|
184
184
|
parser.add_argument("--wdk-evm-root", default=str(_default_wdk_evm_root()))
|
|
185
|
+
parser.add_argument("--wdk-evm-service-url", default=EVM_DEFAULT_SERVICE_URL)
|
|
185
186
|
parser.add_argument("--runtime-root", default=str(_default_runtime_root()))
|
|
186
187
|
parser.add_argument("--npm-bin", default=_default_npm_bin())
|
|
187
188
|
parser.add_argument("--plugin-id", default="agent-wallet")
|
|
@@ -665,6 +666,9 @@ def _build_next_steps(
|
|
|
665
666
|
command.extend(["--extension-path", str(effective_extension_path)])
|
|
666
667
|
command.extend(["--package-root", str(effective_package_root)])
|
|
667
668
|
command.extend(["--python-bin", str(python_bin)])
|
|
669
|
+
if _is_evm_backend(args.backend):
|
|
670
|
+
service_url = str(getattr(args, "wdk_evm_service_url", "") or EVM_DEFAULT_SERVICE_URL).strip()
|
|
671
|
+
command.extend(["--wdk-evm-service-url", service_url or EVM_DEFAULT_SERVICE_URL])
|
|
668
672
|
return command
|
|
669
673
|
|
|
670
674
|
|
|
@@ -672,18 +676,51 @@ def _is_solana_backend(backend: str) -> bool:
|
|
|
672
676
|
return backend.strip().lower() in {"solana", "solana_local", "solana-local"}
|
|
673
677
|
|
|
674
678
|
|
|
679
|
+
def _is_evm_backend(backend: str) -> bool:
|
|
680
|
+
return backend.strip().lower() in {
|
|
681
|
+
"wdk_evm_local",
|
|
682
|
+
"wdk-evm-local",
|
|
683
|
+
"evm_local",
|
|
684
|
+
"evm-local",
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
EVM_DEFAULT_SERVICE_URL = "http://127.0.0.1:8081"
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
def _build_evm_onboard_config(args: argparse.Namespace) -> dict[str, object]:
|
|
692
|
+
# The EVM wallet is provisioned on every install (best-effort). Seed creation
|
|
693
|
+
# with a valid EVM network; ensure_user_evm_wallet_ready binds BOTH base and
|
|
694
|
+
# ethereum (one address), so the active --network only matters when EVM is the
|
|
695
|
+
# active backend.
|
|
696
|
+
network = args.network.strip().lower() if _is_evm_backend(args.backend) else "base"
|
|
697
|
+
if network not in {"base", "ethereum"}:
|
|
698
|
+
network = "base"
|
|
699
|
+
service_url = str(getattr(args, "wdk_evm_service_url", "") or EVM_DEFAULT_SERVICE_URL).strip()
|
|
700
|
+
return {
|
|
701
|
+
"backend": "wdk_evm_local",
|
|
702
|
+
"network": network,
|
|
703
|
+
"signOnly": bool(args.sign_only),
|
|
704
|
+
"wdkEvmServiceUrl": service_url or EVM_DEFAULT_SERVICE_URL,
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
|
|
675
708
|
def _build_solana_onboard_config(args: argparse.Namespace) -> dict[str, object]:
|
|
709
|
+
# Solana is provisioned on every install (both wallets are created), so force
|
|
710
|
+
# the Solana backend/network here -- this must work even when the active
|
|
711
|
+
# backend chosen by the user is EVM or BTC.
|
|
712
|
+
solana_active = _is_solana_backend(args.backend)
|
|
676
713
|
config: dict[str, object] = {
|
|
677
|
-
"backend":
|
|
678
|
-
"network":
|
|
714
|
+
"backend": "solana_local",
|
|
715
|
+
"network": "mainnet",
|
|
679
716
|
"signOnly": bool(args.sign_only),
|
|
680
717
|
"encryptUserWallets": True,
|
|
681
718
|
"migratePlaintextUserWallets": True,
|
|
682
719
|
"refuseMainnetWalletRecreation": True,
|
|
683
720
|
}
|
|
684
|
-
if args.rpc_url.strip():
|
|
721
|
+
if solana_active and args.rpc_url.strip():
|
|
685
722
|
config["rpcUrl"] = args.rpc_url.strip()
|
|
686
|
-
if args.rpc_urls.strip():
|
|
723
|
+
if solana_active and args.rpc_urls.strip():
|
|
687
724
|
config["rpcUrls"] = [item.strip() for item in args.rpc_urls.split(",") if item.strip()]
|
|
688
725
|
return config
|
|
689
726
|
|
|
@@ -708,8 +745,6 @@ def _bootstrap_solana_wallet(
|
|
|
708
745
|
package_root: Path,
|
|
709
746
|
args: argparse.Namespace,
|
|
710
747
|
) -> dict[str, object] | None:
|
|
711
|
-
if not _is_solana_backend(args.backend):
|
|
712
|
-
return None
|
|
713
748
|
result = subprocess.run(
|
|
714
749
|
[
|
|
715
750
|
str(python_bin),
|
|
@@ -741,6 +776,60 @@ def _bootstrap_solana_wallet(
|
|
|
741
776
|
}
|
|
742
777
|
|
|
743
778
|
|
|
779
|
+
def _bootstrap_evm_wallet(
|
|
780
|
+
python_bin: Path,
|
|
781
|
+
package_root: Path,
|
|
782
|
+
args: argparse.Namespace,
|
|
783
|
+
wdk_evm_root: Path,
|
|
784
|
+
) -> dict[str, object]:
|
|
785
|
+
"""Provision the local EVM wallet (best-effort).
|
|
786
|
+
|
|
787
|
+
Mirrors _bootstrap_solana_wallet but for wdk_evm_local. Runs the onboard CLI,
|
|
788
|
+
which calls ensure_user_evm_wallet_ready: auto-starts the local Node service,
|
|
789
|
+
creates and seals the wallet password, and binds both base and ethereum.
|
|
790
|
+
Failures here never abort the install -- the lazy runtime path (ensure_ready on
|
|
791
|
+
first EVM use) remains the safety net.
|
|
792
|
+
"""
|
|
793
|
+
env = _runtime_env_for_onboard(package_root)
|
|
794
|
+
env["OPENCLAW_EVM_WDK_WALLET_ROOT"] = str(wdk_evm_root)
|
|
795
|
+
try:
|
|
796
|
+
result = subprocess.run(
|
|
797
|
+
[
|
|
798
|
+
str(python_bin),
|
|
799
|
+
"-m",
|
|
800
|
+
"agent_wallet.openclaw_cli",
|
|
801
|
+
"onboard",
|
|
802
|
+
"--user-id",
|
|
803
|
+
args.user_id,
|
|
804
|
+
"--config-json",
|
|
805
|
+
json.dumps(_build_evm_onboard_config(args)),
|
|
806
|
+
],
|
|
807
|
+
cwd=package_root,
|
|
808
|
+
capture_output=True,
|
|
809
|
+
text=True,
|
|
810
|
+
check=True,
|
|
811
|
+
env=env,
|
|
812
|
+
)
|
|
813
|
+
except subprocess.CalledProcessError as exc:
|
|
814
|
+
detail = (exc.stderr or exc.stdout or str(exc)).strip()
|
|
815
|
+
return {"ok": False, "error": detail[-2000:]}
|
|
816
|
+
try:
|
|
817
|
+
payload = json.loads(result.stdout)
|
|
818
|
+
except json.JSONDecodeError:
|
|
819
|
+
return {"ok": False, "error": "EVM onboard returned non-JSON output."}
|
|
820
|
+
session = dict(payload.get("session") or {})
|
|
821
|
+
wallet_path = str(session.get("wallet_path") or "")
|
|
822
|
+
wallet_id = wallet_path.split("walletId=", 1)[-1] if "walletId=" in wallet_path else None
|
|
823
|
+
return {
|
|
824
|
+
"ok": True,
|
|
825
|
+
"user_id": session.get("user_id") or args.user_id,
|
|
826
|
+
"address": session.get("address"),
|
|
827
|
+
"wallet_id": wallet_id,
|
|
828
|
+
"networks": ["base", "ethereum"],
|
|
829
|
+
"backend": session.get("backend"),
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
|
|
744
833
|
def main() -> None:
|
|
745
834
|
args = build_parser().parse_args()
|
|
746
835
|
source_package_root = Path(args.package_root).expanduser().resolve()
|
|
@@ -873,6 +962,7 @@ def main() -> None:
|
|
|
873
962
|
configured = False
|
|
874
963
|
configure_stdout = ""
|
|
875
964
|
solana_onboard_result: dict[str, object] | None = None
|
|
965
|
+
evm_onboard_result: dict[str, object] | None = None
|
|
876
966
|
if backend_enabled and not pending_env and not args.dry_run:
|
|
877
967
|
result = subprocess.run(
|
|
878
968
|
_build_next_steps(
|
|
@@ -893,6 +983,22 @@ def main() -> None:
|
|
|
893
983
|
package_root,
|
|
894
984
|
args,
|
|
895
985
|
)
|
|
986
|
+
# Both wallets are provisioned on every install. EVM provisioning is
|
|
987
|
+
# best-effort: a failure here must not abort the install, since the lazy
|
|
988
|
+
# runtime path will create the wallet on first EVM use.
|
|
989
|
+
evm_onboard_result = _bootstrap_evm_wallet(
|
|
990
|
+
python_bin,
|
|
991
|
+
package_root,
|
|
992
|
+
args,
|
|
993
|
+
wdk_evm_root,
|
|
994
|
+
)
|
|
995
|
+
if isinstance(evm_onboard_result, dict) and not evm_onboard_result.get("ok"):
|
|
996
|
+
print(
|
|
997
|
+
"warning: the EVM wallet was not provisioned during install; it will "
|
|
998
|
+
"be created automatically on first EVM use. Details: "
|
|
999
|
+
+ str(evm_onboard_result.get("error") or "unknown"),
|
|
1000
|
+
file=sys.stderr,
|
|
1001
|
+
)
|
|
896
1002
|
|
|
897
1003
|
print(
|
|
898
1004
|
json.dumps(
|
|
@@ -918,6 +1024,7 @@ def main() -> None:
|
|
|
918
1024
|
"configured": configured,
|
|
919
1025
|
"pending_env": pending_env,
|
|
920
1026
|
"solana_wallet": solana_onboard_result,
|
|
1027
|
+
"evm_wallet": evm_onboard_result,
|
|
921
1028
|
"next_configure_command": _build_next_steps(
|
|
922
1029
|
python_bin,
|
|
923
1030
|
install_config_script,
|
|
@@ -13,7 +13,11 @@ from pathlib import Path
|
|
|
13
13
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
14
14
|
|
|
15
15
|
from agent_wallet.file_ops import atomic_write_text, chmod_if_exists
|
|
16
|
-
from agent_wallet.config import
|
|
16
|
+
from agent_wallet.config import (
|
|
17
|
+
normalize_btc_network,
|
|
18
|
+
normalize_evm_network,
|
|
19
|
+
normalize_solana_network,
|
|
20
|
+
)
|
|
17
21
|
from agent_wallet.sealed_keys import resolve_sealed_keys_path, seal_keys, unseal_keys
|
|
18
22
|
from security_utils import write_redacted_backup
|
|
19
23
|
|
|
@@ -25,10 +29,6 @@ LEGACY_ALLOWLIST_TOOLS = [
|
|
|
25
29
|
"set_wallet_backend",
|
|
26
30
|
"get_wallet_portfolio",
|
|
27
31
|
"get_solana_token_prices",
|
|
28
|
-
"swap_solana_privately",
|
|
29
|
-
"continue_solana_private_swap",
|
|
30
|
-
"list_pending_solana_private_swaps",
|
|
31
|
-
"get_solana_private_swap_status",
|
|
32
32
|
"get_kamino_lend_markets",
|
|
33
33
|
"get_kamino_lend_market_reserves",
|
|
34
34
|
"get_kamino_lend_user_obligations",
|
|
@@ -182,6 +182,8 @@ def _normalize_network(backend: str, network: str) -> str:
|
|
|
182
182
|
normalized = network.strip().lower()
|
|
183
183
|
if backend_name in {"wdk_btc_local", "wdk-btc-local", "btc_local", "btc-local"}:
|
|
184
184
|
return normalize_btc_network(normalized or "bitcoin")
|
|
185
|
+
if backend_name in {"wdk_evm_local", "wdk-evm-local", "evm_local", "evm-local"}:
|
|
186
|
+
return normalize_evm_network(normalized or "ethereum")
|
|
185
187
|
return normalize_solana_network(normalized or "mainnet")
|
|
186
188
|
|
|
187
189
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wallet-operator
|
|
3
|
-
description: Use when operating OpenClaw wallet tools: balances, transfers, swaps, LI.FI cross-chain swaps, Jupiter swaps, Velora EVM swaps, BTC transfers, staking,
|
|
3
|
+
description: Use when operating OpenClaw wallet tools: balances, transfers, swaps, LI.FI cross-chain swaps, Jupiter swaps, Velora EVM swaps, BTC transfers, staking, Kamino lending, Bags claims/launches, and wallet execution safety.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Wallet Operator
|
|
@@ -29,7 +29,6 @@ Use this skill before calling OpenClaw wallet tools. It is the routing guide for
|
|
|
29
29
|
- EVM transfers: `transfer_evm_native`, `transfer_evm_token`.
|
|
30
30
|
- BTC transfer: `transfer_btc`.
|
|
31
31
|
- Solana staking: `stake_sol_native`, `deactivate_solana_stake`, `withdraw_solana_stake`.
|
|
32
|
-
- Jupiter Earn: `jupiter_earn_deposit`, `jupiter_earn_withdraw`.
|
|
33
32
|
- Kamino: `kamino_lend_deposit`, `kamino_lend_withdraw`, `kamino_lend_borrow`, `kamino_lend_repay`.
|
|
34
33
|
- Bags: `claim_bags_fees`, `launch_bags_token`.
|
|
35
34
|
|
|
@@ -107,9 +106,6 @@ Use this skill before calling OpenClaw wallet tools. It is the routing guide for
|
|
|
107
106
|
- `stake_sol_native`: `vote_account`, `amount` in SOL, `mode`, `purpose`.
|
|
108
107
|
- `deactivate_solana_stake`: `stake_account`, `mode`, `purpose`.
|
|
109
108
|
- `withdraw_solana_stake`: `stake_account`, `amount` in SOL, optional `recipient`, `mode`, `purpose`.
|
|
110
|
-
- Before Jupiter Earn writes, use `get_jupiter_earn_tokens`, `get_jupiter_earn_positions`, and `get_jupiter_earn_earnings`.
|
|
111
|
-
- `jupiter_earn_deposit`: `asset` mint, `amount_raw`, `mode`, `purpose`.
|
|
112
|
-
- `jupiter_earn_withdraw`: `asset` mint, `amount_raw`, `mode`, `purpose`.
|
|
113
109
|
- Before Kamino writes, use `get_kamino_lend_markets`, `get_kamino_lend_market_reserves`, `get_kamino_lend_user_obligations`, and `get_kamino_lend_user_rewards`.
|
|
114
110
|
- Kamino write params: `market`, `reserve`, `amount_ui` decimal string, `mode`, `purpose`.
|
|
115
111
|
- Bags reads: `get_bags_claimable_positions`, `get_bags_fee_analytics`.
|