@agentlayer.tech/wallet 0.1.12 → 0.1.14
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/AGENTS.md +10 -1
- package/.openclaw/extensions/agent-wallet/index.ts +454 -18
- package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +96 -0
- package/.openclaw/extensions/agent-wallet/skills/wallet-operator/SKILL.md +2 -0
- package/.openclaw/extensions/pay-bridge/README.md +32 -0
- package/.openclaw/extensions/pay-bridge/core.mjs +287 -0
- package/.openclaw/extensions/pay-bridge/index.ts +196 -0
- package/.openclaw/extensions/pay-bridge/openclaw.plugin.json +34 -0
- package/.openclaw/extensions/pay-bridge/package.json +11 -0
- package/.openclaw/extensions/pay-bridge/skills/pay-operator/SKILL.md +20 -0
- package/.openclaw/extensions/pay-bridge/smoke_pay_bridge.mjs +38 -0
- package/CHANGELOG.md +10 -0
- package/README.md +16 -2
- package/agent-wallet/.env.example +11 -0
- package/agent-wallet/README.md +29 -0
- package/agent-wallet/agent_wallet/approval.py +4 -0
- package/agent-wallet/agent_wallet/config.py +6 -0
- package/agent-wallet/agent_wallet/exceptions.py +2 -1
- package/agent-wallet/agent_wallet/openclaw_adapter.py +361 -2
- package/agent-wallet/agent_wallet/openclaw_cli.py +13 -1
- package/agent-wallet/agent_wallet/openclaw_runtime.py +2 -5
- package/agent-wallet/agent_wallet/providers/houdini.py +539 -0
- package/agent-wallet/agent_wallet/transaction_policy.py +251 -0
- package/agent-wallet/agent_wallet/user_wallets.py +83 -0
- package/agent-wallet/agent_wallet/wallet_layer/base.py +40 -0
- package/agent-wallet/agent_wallet/wallet_layer/solana.py +885 -16
- package/agent-wallet/pyproject.toml +1 -1
- package/agent-wallet/scripts/install_agent_wallet.py +54 -2
- package/agent-wallet/scripts/install_openclaw_local_config.py +128 -6
- package/hermes/plugins/agent_wallet/tools.py +93 -9
- package/package.json +2 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import struct
|
|
5
6
|
from typing import Any
|
|
6
7
|
|
|
7
8
|
from agent_wallet.wallet_layer.base import WalletBackendError
|
|
@@ -88,6 +89,32 @@ def _program_ids(message: Any, loaded_addresses: list[str] | None = None) -> lis
|
|
|
88
89
|
return values
|
|
89
90
|
|
|
90
91
|
|
|
92
|
+
def _instruction_account_keys(
|
|
93
|
+
message: Any,
|
|
94
|
+
instruction: Any,
|
|
95
|
+
*,
|
|
96
|
+
loaded_addresses: list[str] | None = None,
|
|
97
|
+
) -> list[str]:
|
|
98
|
+
keys = _account_keys(message, loaded_addresses)
|
|
99
|
+
values: list[str] = []
|
|
100
|
+
for raw_index in list(getattr(instruction, "accounts", []) or []):
|
|
101
|
+
index = int(raw_index)
|
|
102
|
+
if index < 0 or index >= len(keys):
|
|
103
|
+
raise WalletBackendError("Provider transaction contains an invalid account index.")
|
|
104
|
+
values.append(keys[index])
|
|
105
|
+
return values
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _instruction_data_bytes(instruction: Any) -> bytes:
|
|
109
|
+
raw = getattr(instruction, "data", b"")
|
|
110
|
+
if isinstance(raw, bytes):
|
|
111
|
+
return raw
|
|
112
|
+
try:
|
|
113
|
+
return bytes(raw)
|
|
114
|
+
except Exception as exc: # pragma: no cover - defensive bridge for solders internals
|
|
115
|
+
raise WalletBackendError("Provider transaction instruction data could not be decoded.") from exc
|
|
116
|
+
|
|
117
|
+
|
|
91
118
|
def _assert_program_allowlist(
|
|
92
119
|
program_ids: list[str],
|
|
93
120
|
*,
|
|
@@ -379,6 +406,230 @@ def verify_provider_swap_simulation_result(
|
|
|
379
406
|
}
|
|
380
407
|
|
|
381
408
|
|
|
409
|
+
def verify_provider_houdini_transaction(
|
|
410
|
+
message: Any,
|
|
411
|
+
*,
|
|
412
|
+
wallet_address: str,
|
|
413
|
+
deposit_address: str,
|
|
414
|
+
amount_raw: int,
|
|
415
|
+
is_native_input: bool,
|
|
416
|
+
token_mint: str | None = None,
|
|
417
|
+
loaded_addresses: list[str] | None = None,
|
|
418
|
+
) -> dict[str, Any]:
|
|
419
|
+
binding = _assert_basic_wallet_binding(
|
|
420
|
+
message,
|
|
421
|
+
wallet_address=wallet_address,
|
|
422
|
+
loaded_addresses=loaded_addresses,
|
|
423
|
+
)
|
|
424
|
+
keys = binding["account_keys"]
|
|
425
|
+
program_ids = _program_ids(message, loaded_addresses)
|
|
426
|
+
unknown_program_ids = _assert_program_allowlist(
|
|
427
|
+
program_ids,
|
|
428
|
+
allowed_programs=CORE_PROGRAM_IDS,
|
|
429
|
+
label="Houdini private swap funding",
|
|
430
|
+
reject_unknown=False,
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
matched_native_lamports = 0
|
|
434
|
+
matched_token_amount = 0
|
|
435
|
+
parsed_transfers: list[dict[str, Any]] = []
|
|
436
|
+
|
|
437
|
+
for instruction in _compiled_instructions(message):
|
|
438
|
+
instruction_accounts = _instruction_account_keys(
|
|
439
|
+
message,
|
|
440
|
+
instruction,
|
|
441
|
+
loaded_addresses=loaded_addresses,
|
|
442
|
+
)
|
|
443
|
+
data = _instruction_data_bytes(instruction)
|
|
444
|
+
program_id_index = int(getattr(instruction, "program_id_index", -1))
|
|
445
|
+
if program_id_index < 0 or program_id_index >= len(keys):
|
|
446
|
+
raise WalletBackendError("Provider transaction contains an invalid program id index.")
|
|
447
|
+
program_id = _account_keys(message, loaded_addresses)[program_id_index]
|
|
448
|
+
|
|
449
|
+
if (
|
|
450
|
+
is_native_input
|
|
451
|
+
and program_id == SYSTEM_PROGRAM_ID
|
|
452
|
+
and len(data) >= 12
|
|
453
|
+
and len(instruction_accounts) >= 2
|
|
454
|
+
):
|
|
455
|
+
instruction_type = struct.unpack_from("<I", data, 0)[0]
|
|
456
|
+
if instruction_type == 2:
|
|
457
|
+
lamports = struct.unpack_from("<Q", data, 4)[0]
|
|
458
|
+
recipient = instruction_accounts[1]
|
|
459
|
+
parsed_transfers.append(
|
|
460
|
+
{
|
|
461
|
+
"program_id": program_id,
|
|
462
|
+
"recipient": recipient,
|
|
463
|
+
"amount_raw": str(lamports),
|
|
464
|
+
"kind": "system-transfer",
|
|
465
|
+
}
|
|
466
|
+
)
|
|
467
|
+
if recipient == deposit_address:
|
|
468
|
+
matched_native_lamports += lamports
|
|
469
|
+
continue
|
|
470
|
+
|
|
471
|
+
if program_id not in {TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID} or len(instruction_accounts) < 2:
|
|
472
|
+
continue
|
|
473
|
+
|
|
474
|
+
if not data:
|
|
475
|
+
continue
|
|
476
|
+
instruction_tag = data[0]
|
|
477
|
+
if instruction_tag == 3 and len(data) >= 9 and len(instruction_accounts) >= 2:
|
|
478
|
+
token_amount = struct.unpack_from("<Q", data, 1)[0]
|
|
479
|
+
recipient = instruction_accounts[1]
|
|
480
|
+
parsed_transfers.append(
|
|
481
|
+
{
|
|
482
|
+
"program_id": program_id,
|
|
483
|
+
"recipient": recipient,
|
|
484
|
+
"amount_raw": str(token_amount),
|
|
485
|
+
"kind": "spl-transfer",
|
|
486
|
+
"mint": None,
|
|
487
|
+
}
|
|
488
|
+
)
|
|
489
|
+
if not is_native_input and recipient == deposit_address:
|
|
490
|
+
matched_token_amount += token_amount
|
|
491
|
+
continue
|
|
492
|
+
|
|
493
|
+
if instruction_tag == 12 and len(data) >= 10 and len(instruction_accounts) >= 3:
|
|
494
|
+
token_amount = struct.unpack_from("<Q", data, 1)[0]
|
|
495
|
+
mint = instruction_accounts[1]
|
|
496
|
+
recipient = instruction_accounts[2]
|
|
497
|
+
parsed_transfers.append(
|
|
498
|
+
{
|
|
499
|
+
"program_id": program_id,
|
|
500
|
+
"recipient": recipient,
|
|
501
|
+
"amount_raw": str(token_amount),
|
|
502
|
+
"kind": "spl-transfer-checked",
|
|
503
|
+
"mint": mint,
|
|
504
|
+
}
|
|
505
|
+
)
|
|
506
|
+
if (
|
|
507
|
+
not is_native_input
|
|
508
|
+
and recipient == deposit_address
|
|
509
|
+
and (token_mint is None or mint == token_mint)
|
|
510
|
+
):
|
|
511
|
+
matched_token_amount += token_amount
|
|
512
|
+
|
|
513
|
+
if is_native_input:
|
|
514
|
+
if matched_native_lamports != amount_raw:
|
|
515
|
+
raise WalletBackendError(
|
|
516
|
+
"Houdini funding transaction does not transfer the approved native SOL amount to the expected deposit address."
|
|
517
|
+
)
|
|
518
|
+
else:
|
|
519
|
+
if matched_token_amount != amount_raw:
|
|
520
|
+
raise WalletBackendError(
|
|
521
|
+
"Houdini funding transaction does not transfer the approved SPL token amount to the expected deposit address."
|
|
522
|
+
)
|
|
523
|
+
|
|
524
|
+
return {
|
|
525
|
+
"wallet_address": wallet_address,
|
|
526
|
+
"fee_payer": binding["fee_payer"],
|
|
527
|
+
"required_signer_keys": binding["required_signer_keys"],
|
|
528
|
+
"required_signature_count": binding["required_signature_count"],
|
|
529
|
+
"wallet_signer_index": binding["wallet_signer_index"],
|
|
530
|
+
"sponsored_fee_payer": binding["sponsored_fee_payer"],
|
|
531
|
+
"program_ids": program_ids,
|
|
532
|
+
"unknown_program_ids": unknown_program_ids,
|
|
533
|
+
"non_core_program_ids": [pid for pid in program_ids if pid not in CORE_PROGRAM_IDS],
|
|
534
|
+
"account_key_count": len(keys),
|
|
535
|
+
"instruction_count": len(_compiled_instructions(message)),
|
|
536
|
+
"deposit_address": deposit_address,
|
|
537
|
+
"amount_raw": str(amount_raw),
|
|
538
|
+
"is_native_input": is_native_input,
|
|
539
|
+
"token_mint": token_mint,
|
|
540
|
+
"parsed_transfers": parsed_transfers,
|
|
541
|
+
"verified": True,
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
def verify_provider_houdini_simulation_result(
|
|
546
|
+
simulation_value: dict[str, Any],
|
|
547
|
+
*,
|
|
548
|
+
wallet_address: str,
|
|
549
|
+
wallet_account_index: int | None,
|
|
550
|
+
is_native_input: bool,
|
|
551
|
+
token_mint: str | None,
|
|
552
|
+
amount_raw: int,
|
|
553
|
+
native_sol_extra_spend_allowance_lamports: int = (
|
|
554
|
+
DEFAULT_NATIVE_SOL_EXTRA_SPEND_ALLOWANCE_LAMPORTS
|
|
555
|
+
),
|
|
556
|
+
) -> dict[str, Any]:
|
|
557
|
+
if not isinstance(simulation_value, dict):
|
|
558
|
+
raise WalletBackendError(
|
|
559
|
+
"Houdini funding transaction simulation returned an unexpected payload.",
|
|
560
|
+
code="transaction_simulation_invalid",
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
if simulation_value.get("err") is not None:
|
|
564
|
+
raise WalletBackendError(
|
|
565
|
+
"Houdini funding transaction simulation failed.",
|
|
566
|
+
code="transaction_simulation_failed",
|
|
567
|
+
details={"simulation": simulation_value},
|
|
568
|
+
)
|
|
569
|
+
|
|
570
|
+
token_deltas = _wallet_token_deltas_by_mint(
|
|
571
|
+
simulation_value,
|
|
572
|
+
wallet_address=wallet_address,
|
|
573
|
+
)
|
|
574
|
+
native_delta = _native_lamport_delta(
|
|
575
|
+
simulation_value,
|
|
576
|
+
wallet_account_index=wallet_account_index,
|
|
577
|
+
)
|
|
578
|
+
warnings: list[str] = []
|
|
579
|
+
enforced_checks: list[str] = ["simulation_err_is_none"]
|
|
580
|
+
|
|
581
|
+
if is_native_input:
|
|
582
|
+
if native_delta is None:
|
|
583
|
+
warnings.append("native_input_delta_unavailable")
|
|
584
|
+
else:
|
|
585
|
+
max_spend = max(amount_raw, 0) + max(native_sol_extra_spend_allowance_lamports, 0)
|
|
586
|
+
if -native_delta > max_spend:
|
|
587
|
+
raise WalletBackendError(
|
|
588
|
+
"Houdini funding transaction simulation spends more native SOL than approved.",
|
|
589
|
+
code="houdini_simulation_overspend",
|
|
590
|
+
details={
|
|
591
|
+
"approved_input_amount_raw": str(amount_raw),
|
|
592
|
+
"native_delta_lamports": str(native_delta),
|
|
593
|
+
"allowed_extra_lamports": str(
|
|
594
|
+
native_sol_extra_spend_allowance_lamports
|
|
595
|
+
),
|
|
596
|
+
},
|
|
597
|
+
)
|
|
598
|
+
enforced_checks.append("native_input_spend_within_approved_amount")
|
|
599
|
+
else:
|
|
600
|
+
if not token_mint:
|
|
601
|
+
raise WalletBackendError("token_mint is required for SPL Houdini simulation checks.")
|
|
602
|
+
input_delta = token_deltas.get(token_mint)
|
|
603
|
+
if input_delta is None:
|
|
604
|
+
warnings.append("token_input_delta_unavailable")
|
|
605
|
+
elif -input_delta > amount_raw:
|
|
606
|
+
raise WalletBackendError(
|
|
607
|
+
"Houdini funding transaction simulation spends more SPL token than approved.",
|
|
608
|
+
code="houdini_simulation_overspend",
|
|
609
|
+
details={
|
|
610
|
+
"token_mint": token_mint,
|
|
611
|
+
"approved_input_amount_raw": str(amount_raw),
|
|
612
|
+
"input_delta_raw": str(input_delta),
|
|
613
|
+
},
|
|
614
|
+
)
|
|
615
|
+
else:
|
|
616
|
+
enforced_checks.append("token_input_spend_within_approved_amount")
|
|
617
|
+
|
|
618
|
+
return {
|
|
619
|
+
"verified": True,
|
|
620
|
+
"simulation_err": None,
|
|
621
|
+
"wallet_address": wallet_address,
|
|
622
|
+
"wallet_account_index": wallet_account_index,
|
|
623
|
+
"token_mint": token_mint,
|
|
624
|
+
"amount_raw": str(amount_raw),
|
|
625
|
+
"is_native_input": is_native_input,
|
|
626
|
+
"token_deltas": {mint: str(delta) for mint, delta in sorted(token_deltas.items())},
|
|
627
|
+
"native_delta_lamports": str(native_delta) if native_delta is not None else None,
|
|
628
|
+
"enforced_checks": enforced_checks,
|
|
629
|
+
"warnings": warnings,
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
|
|
382
633
|
def verify_provider_bags_transaction(
|
|
383
634
|
message: Any,
|
|
384
635
|
*,
|
|
@@ -17,6 +17,7 @@ from agent_wallet.config import (
|
|
|
17
17
|
resolve_openclaw_home,
|
|
18
18
|
resolve_runtime_solana_rpc_config,
|
|
19
19
|
resolve_runtime_solana_swap_config,
|
|
20
|
+
resolve_solana_private_key,
|
|
20
21
|
resolve_wallet_master_key,
|
|
21
22
|
settings,
|
|
22
23
|
use_per_user_key_derivation,
|
|
@@ -26,6 +27,7 @@ from agent_wallet.encrypted_storage import (
|
|
|
26
27
|
decrypt_secret_material,
|
|
27
28
|
encrypt_secret_material,
|
|
28
29
|
is_encrypted_wallet_payload,
|
|
30
|
+
load_wallet_secret_material,
|
|
29
31
|
write_encrypted_wallet_file,
|
|
30
32
|
)
|
|
31
33
|
from agent_wallet.wallet_layer.base import WalletBackendError
|
|
@@ -353,3 +355,84 @@ def create_wallet_backend_for_user(
|
|
|
353
355
|
swap_provider=str(swap_config["provider"]),
|
|
354
356
|
swap_transport=str(swap_config["transport"]),
|
|
355
357
|
)
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def create_openclaw_solana_backend(
|
|
361
|
+
user_id: str,
|
|
362
|
+
*,
|
|
363
|
+
sign_only: bool | None = None,
|
|
364
|
+
network: str | None = None,
|
|
365
|
+
rpc_url: str | None = None,
|
|
366
|
+
) -> tuple[SolanaWalletBackend, dict[str, str], bool]:
|
|
367
|
+
"""Create a Solana backend for OpenClaw, preferring explicit signer config over per-user wallets."""
|
|
368
|
+
effective_network = _resolve_effective_network(network)
|
|
369
|
+
configured_public_key = settings.solana_agent_public_key.strip()
|
|
370
|
+
configured_keypair_path = settings.solana_agent_keypair_path.strip()
|
|
371
|
+
configured_secret = resolve_solana_private_key().strip()
|
|
372
|
+
|
|
373
|
+
signer: SolanaLocalKeypairSigner | None = None
|
|
374
|
+
storage_format = ""
|
|
375
|
+
wallet_path = ""
|
|
376
|
+
key_scope = ""
|
|
377
|
+
|
|
378
|
+
if configured_secret:
|
|
379
|
+
signer = SolanaLocalKeypairSigner.from_secret_material(configured_secret)
|
|
380
|
+
storage_format = "sealed_runtime_secret"
|
|
381
|
+
wallet_path = f"{resolve_openclaw_home() / 'sealed_keys.json'}#private_key"
|
|
382
|
+
key_scope = "sealed-runtime"
|
|
383
|
+
elif configured_keypair_path:
|
|
384
|
+
path = Path(configured_keypair_path).expanduser()
|
|
385
|
+
if not path.exists():
|
|
386
|
+
raise WalletBackendError(f"Configured Solana keypair path does not exist: {path}")
|
|
387
|
+
secret_material, loaded_format = load_wallet_secret_material(path)
|
|
388
|
+
signer = SolanaLocalKeypairSigner.from_secret_material(secret_material)
|
|
389
|
+
storage_format = loaded_format
|
|
390
|
+
wallet_path = str(path)
|
|
391
|
+
key_scope = "configured-keypair"
|
|
392
|
+
|
|
393
|
+
resolved_address = configured_public_key or (signer.address if signer else "")
|
|
394
|
+
if configured_public_key and signer and configured_public_key != signer.address:
|
|
395
|
+
raise WalletBackendError(
|
|
396
|
+
"Configured Solana publicKey does not match the signer derived from keypairPath/runtime secret."
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
rpc_config = resolve_runtime_solana_rpc_config(
|
|
400
|
+
effective_network,
|
|
401
|
+
rpc_url or settings.solana_rpc_url,
|
|
402
|
+
settings.solana_rpc_urls,
|
|
403
|
+
)
|
|
404
|
+
swap_config = resolve_runtime_solana_swap_config(effective_network)
|
|
405
|
+
|
|
406
|
+
if signer is not None or configured_public_key:
|
|
407
|
+
backend = SolanaWalletBackend(
|
|
408
|
+
rpc_url=rpc_config["rpc_urls"],
|
|
409
|
+
commitment=settings.solana_commitment,
|
|
410
|
+
network=effective_network,
|
|
411
|
+
signer=signer,
|
|
412
|
+
address=resolved_address or None,
|
|
413
|
+
sign_only=settings.agent_wallet_sign_only if sign_only is None else sign_only,
|
|
414
|
+
rpc_provider_mode=str(rpc_config["mode"]),
|
|
415
|
+
rpc_provider=str(rpc_config["provider"]),
|
|
416
|
+
rpc_transport=str(rpc_config["transport"]),
|
|
417
|
+
swap_provider=str(swap_config["provider"]),
|
|
418
|
+
swap_transport=str(swap_config["transport"]),
|
|
419
|
+
)
|
|
420
|
+
wallet_info = {
|
|
421
|
+
"user_id": user_id,
|
|
422
|
+
"address": resolved_address,
|
|
423
|
+
"path": wallet_path or "<configured-public-key>",
|
|
424
|
+
"storage_format": storage_format or "configured_public_key",
|
|
425
|
+
"key_scope": key_scope or ("configured-public-key" if configured_public_key else "host-managed"),
|
|
426
|
+
}
|
|
427
|
+
return backend, wallet_info, False
|
|
428
|
+
|
|
429
|
+
wallet_path = resolve_user_wallet_path(user_id, network=effective_network)
|
|
430
|
+
created_now = not wallet_path.exists()
|
|
431
|
+
backend = create_wallet_backend_for_user(
|
|
432
|
+
user_id,
|
|
433
|
+
sign_only=sign_only,
|
|
434
|
+
network=effective_network,
|
|
435
|
+
rpc_url=rpc_url,
|
|
436
|
+
)
|
|
437
|
+
wallet_info = ensure_user_solana_wallet(user_id, network=effective_network)
|
|
438
|
+
return backend, wallet_info, created_now
|
|
@@ -327,6 +327,46 @@ class AgentWalletBackend(ABC):
|
|
|
327
327
|
) -> dict[str, Any]:
|
|
328
328
|
raise WalletBackendError(f"{self.name} does not support Solana-origin LI.FI swap previews.")
|
|
329
329
|
|
|
330
|
+
async def preview_solana_private_swap(
|
|
331
|
+
self,
|
|
332
|
+
*,
|
|
333
|
+
input_token: str,
|
|
334
|
+
output_token: str,
|
|
335
|
+
destination_address: str,
|
|
336
|
+
amount_ui: float,
|
|
337
|
+
use_xmr: bool = False,
|
|
338
|
+
) -> dict[str, Any]:
|
|
339
|
+
raise WalletBackendError(f"{self.name} does not support Solana private swap previews.")
|
|
340
|
+
|
|
341
|
+
async def execute_solana_private_swap(
|
|
342
|
+
self,
|
|
343
|
+
*,
|
|
344
|
+
input_token: str,
|
|
345
|
+
output_token: str,
|
|
346
|
+
destination_address: str,
|
|
347
|
+
amount_ui: float,
|
|
348
|
+
use_xmr: bool = False,
|
|
349
|
+
approved_preview: dict[str, Any] | None = None,
|
|
350
|
+
existing_order: dict[str, Any] | None = None,
|
|
351
|
+
) -> dict[str, Any]:
|
|
352
|
+
raise WalletBackendError(f"{self.name} does not support Solana private swaps.")
|
|
353
|
+
|
|
354
|
+
async def get_solana_private_swap_status(
|
|
355
|
+
self,
|
|
356
|
+
*,
|
|
357
|
+
multi_id: str | None = None,
|
|
358
|
+
houdini_id: str | None = None,
|
|
359
|
+
) -> dict[str, Any]:
|
|
360
|
+
raise WalletBackendError(f"{self.name} does not support Solana private swap status lookup.")
|
|
361
|
+
|
|
362
|
+
async def continue_solana_private_swap(
|
|
363
|
+
self,
|
|
364
|
+
*,
|
|
365
|
+
approved_preview: dict[str, Any],
|
|
366
|
+
existing_order: dict[str, Any],
|
|
367
|
+
) -> dict[str, Any]:
|
|
368
|
+
raise WalletBackendError(f"{self.name} does not support continuing Solana private swaps.")
|
|
369
|
+
|
|
330
370
|
async def execute_solana_lifi_cross_chain_swap(
|
|
331
371
|
self,
|
|
332
372
|
*,
|