diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 766b50c015..259cff120b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,6 +13,13 @@ repos: entry: ./activated.py python chia/_tests/build-init-files.py -v --root . language: system pass_filenames: false + - repo: local + hooks: + - id: generate_wallet_rpc_client_stubs + name: Generate wallet RPC client stubs + entry: ./activated.py python tools/generate_wallet_rpc_client_stub.py + language: system + pass_filenames: false - repo: local hooks: - id: ruff_format diff --git a/chia/_tests/core/data_layer/test_data_rpc.py b/chia/_tests/core/data_layer/test_data_rpc.py index 3e554dc85f..b378a6bce0 100644 --- a/chia/_tests/core/data_layer/test_data_rpc.py +++ b/chia/_tests/core/data_layer/test_data_rpc.py @@ -16,7 +16,7 @@ from copy import deepcopy from dataclasses import dataclass from enum import IntEnum from pathlib import Path -from typing import Any, cast +from typing import Any from unittest.mock import AsyncMock, MagicMock import aiohttp @@ -78,7 +78,6 @@ from chia.util.task_referencer import create_referenced_task from chia.util.timing import adjusted_timeout, backoff_times from chia.wallet.lineage_proof import LineageProof from chia.wallet.trading.offer import Offer as TradingOffer -from chia.wallet.transaction_record import TransactionRecord from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG from chia.wallet.wallet_node import WalletNode from chia.wallet.wallet_request_types import ( @@ -88,6 +87,9 @@ from chia.wallet.wallet_request_types import ( DLOwnedSingletonsResponse, DLStopTracking, DLTrackNew, + Empty, + GetTransaction, + LogIn, ) from chia.wallet.wallet_rpc_api import WalletRpcApi from chia.wallet.wallet_service import WalletService @@ -202,11 +204,11 @@ async def farm_block_check_singleton( async def is_transaction_confirmed(api: WalletRpcApi, tx_id: bytes32) -> bool: try: - val = await api.get_transaction({"transaction_id": tx_id.hex()}) + val = await api.get_transaction(GetTransaction(transaction_id=tx_id)) except ValueError: # pragma: no cover return False - return True if TransactionRecord.from_json_dict(val["transaction"]).confirmed else False # mypy + return val.transaction.confirmed async def check_mempool_spend_count_or_fail( @@ -214,9 +216,8 @@ async def check_mempool_spend_count_or_fail( ) -> bool: """Poll mempool count but raise immediately if the transaction was rejected.""" try: - val = await wallet_rpc_api.get_transaction({"transaction_id": tx_id.hex()}) - tx_record = TransactionRecord.from_json_dict(val["transaction"]) - for _, status, error in tx_record.sent_to: + val = await wallet_rpc_api.get_transaction(GetTransaction(transaction_id=tx_id)) + for _, status, error in val.transaction.sent_to: if status == MempoolInclusionStatus.FAILED.value: raise RuntimeError(f"Transaction {tx_id} rejected by mempool: {error}") # pragma: no cover except ValueError: # pragma: no cover @@ -2449,16 +2450,17 @@ async def test_wallet_log_in_changes_active_fingerprint( wallet_rpc_api, _full_node_api, wallet_rpc_port, _ph, bt = await init_wallet_and_node( self_hostname, one_wallet_and_one_simulator_services ) - primary_fingerprint = cast(int, (await wallet_rpc_api.get_logged_in_fingerprint(request={}))["fingerprint"]) + primary_fingerprint = (await wallet_rpc_api.get_logged_in_fingerprint(Empty())).fingerprint + assert primary_fingerprint is not None mnemonic = create_mnemonic() assert wallet_rpc_api.service.local_keychain is not None private_key = wallet_rpc_api.service.local_keychain.add_key(mnemonic_or_pk=mnemonic) secondary_fingerprint: int = private_key.get_g1().get_fingerprint() - await wallet_rpc_api.log_in(request={"fingerprint": primary_fingerprint}) + await wallet_rpc_api.log_in(LogIn(fingerprint=primary_fingerprint)) - active_fingerprint = cast(int, (await wallet_rpc_api.get_logged_in_fingerprint(request={}))["fingerprint"]) + active_fingerprint = (await wallet_rpc_api.get_logged_in_fingerprint(Empty())).fingerprint assert active_fingerprint == primary_fingerprint async with init_data_layer_service(wallet_rpc_port=wallet_rpc_port, bt=bt) as data_layer_service: @@ -2496,7 +2498,7 @@ async def test_wallet_log_in_changes_active_fingerprint( else: # pragma: no cover assert False, "unhandled parametrization" - active_fingerprint = cast(int, (await wallet_rpc_api.get_logged_in_fingerprint(request={}))["fingerprint"]) + active_fingerprint = (await wallet_rpc_api.get_logged_in_fingerprint(Empty())).fingerprint assert active_fingerprint == secondary_fingerprint diff --git a/chia/_tests/wallet/did_wallet/test_did.py b/chia/_tests/wallet/did_wallet/test_did.py index 956fcee1b9..3b245311a3 100644 --- a/chia/_tests/wallet/did_wallet/test_did.py +++ b/chia/_tests/wallet/did_wallet/test_did.py @@ -57,9 +57,12 @@ from chia.wallet.wallet_node import WalletNode from chia.wallet.wallet_request_types import ( CreateNewWallet, CreateNewWalletType, + DIDFindLostDID, DIDGetCurrentCoinInfo, DIDGetInfo, DIDType, + SetWalletResyncOnStartup, + SignMessageByID, ) from chia.wallet.wallet_rpc_api import WalletRpcApi from chia.wallet.wallet_spend_bundle import WalletSpendBundle @@ -695,7 +698,7 @@ async def test_did_auto_transfer_limit( backup_data, ) assert did_wallet_10.did_info.origin_coin is not None - await api_1.did_find_lost_did({"coin_id": did_wallet_10.did_info.origin_coin.name().hex()}) + await api_1.did_find_lost_did(DIDFindLostDID(coin_id=did_wallet_10.did_info.origin_coin.name().hex())) await time_out_assert(15, did_wallet_10.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_10.get_unconfirmed_balance, 101) @@ -718,7 +721,7 @@ async def test_did_auto_transfer_limit( # Try and find lost coin assert did_wallet_9.did_info.origin_coin is not None - await api_1.did_find_lost_did({"coin_id": did_wallet_9.did_info.origin_coin.name().hex()}) + await api_1.did_find_lost_did(DIDFindLostDID(coin_id=did_wallet_9.did_info.origin_coin.name().hex())) did_wallets = list( filter( lambda w: w.type == WalletType.DECENTRALIZED_ID.value, @@ -1103,44 +1106,71 @@ async def test_did_sign_message(wallet_environments: WalletTestFramework, capsys await DidSignMessageCMD( rpc_info=wallet_environments.cmd_tx_endpoint_args(env)["rpc_info"], did_id=CliAddress(did_wallet_1.did_info.origin_coin.name(), did_id, AddressType.DID), - hex_message=message.encode().hex(), + hex_message=message, ).run() output = capsys.readouterr().out - assert f"Message: {message.encode().hex()}" in output + assert f"Message: {message}" in output assert "Public Key:" in output assert "Signature:" in output - response = await api_0.sign_message_by_id({"id": did_id, "message": message}) + pubkey = G1Element.from_bytes(bytes.fromhex(output.split("Public Key:")[1].split("\n")[0].strip())) + signature = G2Element.from_bytes(bytes.fromhex(output.split("Signature:")[1].split("\n")[0].strip())) + puzzle: Program = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, message)) assert AugSchemeMPL.verify( - G1Element.from_bytes(hexstr_to_bytes(response["pubkey"])), + pubkey, puzzle.get_tree_hash(), - G2Element.from_bytes(hexstr_to_bytes(response["signature"])), + signature, ) - + # Test hex string message = "0123456789ABCDEF" - response = await api_0.sign_message_by_id({"id": did_id, "message": message, "is_hex": True}) + response = await api_0.sign_message_by_id( + SignMessageByID( + id=encode_puzzle_hash(did_wallet_1.did_info.origin_coin.name(), AddressType.DID.value), + message=message, + is_hex=True, + ) + ) + puzzle = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, bytes.fromhex(message))) puzzle = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, bytes.fromhex(message))) assert AugSchemeMPL.verify( - G1Element.from_bytes(hexstr_to_bytes(response["pubkey"])), + response.pubkey, puzzle.get_tree_hash(), - G2Element.from_bytes(hexstr_to_bytes(response["signature"])), + response.signature, ) message = "Hello World" - response = await api_0.sign_message_by_id({"id": did_id, "message": message, "is_hex": False, "safe_mode": False}) - assert AugSchemeMPL.verify( - G1Element.from_bytes(hexstr_to_bytes(response["pubkey"])), - bytes(message, "utf-8"), - G2Element.from_bytes(hexstr_to_bytes(response["signature"])), + assert did_wallet_1.did_info.origin_coin is not None + response = await api_0.sign_message_by_id( + SignMessageByID( + id=encode_puzzle_hash(did_wallet_1.did_info.origin_coin.name(), AddressType.DID.value), + message=message, + is_hex=False, + safe_mode=False, + ) ) - message = "0123456789ABCDEF" - response = await api_0.sign_message_by_id({"id": did_id, "message": message, "is_hex": True, "safe_mode": False}) assert AugSchemeMPL.verify( - G1Element.from_bytes(hexstr_to_bytes(response["pubkey"])), + response.pubkey, + bytes(message, "utf-8"), + response.signature, + ) + # Test BLS sign hex + message = "0123456789ABCDEF" + assert did_wallet_1.did_info.origin_coin is not None + response = await api_0.sign_message_by_id( + SignMessageByID( + id=encode_puzzle_hash(did_wallet_1.did_info.origin_coin.name(), AddressType.DID.value), + message=message, + is_hex=True, + safe_mode=False, + ) + ) + + assert AugSchemeMPL.verify( + response.pubkey, hexstr_to_bytes(message), - G2Element.from_bytes(hexstr_to_bytes(response["signature"])), + response.signature, ) @@ -1414,9 +1444,9 @@ async def test_did_resync( did_wallet_2 = wallet_node_2.wallet_state_manager.get_wallet(uint32(2), DIDWallet) did_info = did_wallet_2.did_info # set flag to reset wallet sync data on start - await wallet_api_1.set_wallet_resync_on_startup({"enable": True}) + await wallet_api_1.set_wallet_resync_on_startup(SetWalletResyncOnStartup(enable=True)) fingerprint_1 = wallet_node_1.logged_in_fingerprint - await wallet_api_2.set_wallet_resync_on_startup({"enable": True}) + await wallet_api_2.set_wallet_resync_on_startup(SetWalletResyncOnStartup(enable=True)) fingerprint_2 = wallet_node_2.logged_in_fingerprint # 2 reward coins assert len(await wallet_node_1.wallet_state_manager.coin_store.get_all_unspent_coins()) == 2 diff --git a/chia/_tests/wallet/rpc/test_dl_wallet_rpc.py b/chia/_tests/wallet/rpc/test_dl_wallet_rpc.py index 2dd90bc654..1513e80285 100644 --- a/chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +++ b/chia/_tests/wallet/rpc/test_dl_wallet_rpc.py @@ -401,7 +401,7 @@ class TestWalletRpc: wallet_service.config, ) as client: with pytest.raises(ValueError, match="No peer connected"): - await wallet_service.rpc_server.rpc_api.dl_verify_proof(fake_gpr.to_json_dict()) + await wallet_service.rpc_server.rpc_api.dl_verify_proof(fake_gpr) await wallet_node.server.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None) await validate_get_routes(client, wallet_service.rpc_server.rpc_api) diff --git a/chia/_tests/wallet/rpc/test_wallet_rpc.py b/chia/_tests/wallet/rpc/test_wallet_rpc.py index 160815d8bb..4e611ee4e6 100644 --- a/chia/_tests/wallet/rpc/test_wallet_rpc.py +++ b/chia/_tests/wallet/rpc/test_wallet_rpc.py @@ -7,7 +7,7 @@ import logging import re from operator import attrgetter from types import SimpleNamespace -from typing import Any +from typing import Any, cast from unittest.mock import AsyncMock, MagicMock, patch import aiosqlite @@ -65,6 +65,7 @@ from chia.util.bech32m import decode_puzzle_hash, encode_puzzle_hash from chia.util.config import load_config, lock_and_load_config, save_config from chia.util.db_wrapper import DBWrapper2 from chia.util.hash import std_hash +from chia.util.streamable import Streamable, streamable from chia.wallet.cat_wallet.cat_constants import DEFAULT_CATS from chia.wallet.cat_wallet.cat_utils import CAT_MOD, construct_cat_puzzle from chia.wallet.cat_wallet.cat_wallet import CATWallet @@ -180,6 +181,8 @@ from chia.wallet.wallet_request_types import ( SpendClawbackCoins, SplitCoins, TakeOffer, + TransactionEndpointRequest, + TransactionEndpointResponse, VCSpend, VerifySignature, VerifySignatureResponse, @@ -188,6 +191,7 @@ from chia.wallet.wallet_request_types import ( ) from chia.wallet.wallet_rpc_api import WalletRpcApi from chia.wallet.wallet_rpc_client import WalletRpcClient +from chia.wallet.wallet_rpc_metadata import WalletRpcMetadata from chia.wallet.wallet_spend_bundle import WalletSpendBundle from chia.wallet.wallet_state_manager import SyncStatus @@ -2667,7 +2671,7 @@ async def test_get_height_info_response_variants( api_self = SimpleNamespace( service=SimpleNamespace(wallet_state_manager=SimpleNamespace(blockchain=mock_blockchain)) ) - response = GetHeightInfoResponse.from_json_dict(await WalletRpcApi.get_height_info(api_self, {})) + response = await WalletRpcApi.get_height_info(cast(WalletRpcApi, api_self), GetHeightInfo()) assert isinstance(response, GetHeightInfoResponse) assert response.height == sync_height assert response.is_transaction_block == expected_is_tx @@ -5135,3 +5139,29 @@ def test_miscellaneous_wallet_rpc_errors() -> None: spent_height=uint32(0), coinbase=False, ) + + @streamable + @dataclasses.dataclass(frozen=True) + class NotATXRequest(Streamable): + pass + + @streamable + @dataclasses.dataclass(frozen=True) + class NotATXResponse(Streamable): + pass + + class YesATXRequest(TransactionEndpointRequest): + pass + + class YesATXResponse(TransactionEndpointResponse): + pass + + with pytest.raises(TypeError, match="tx_endpoint request type must subclass TransactionEndpointRequest"): + WalletRpcMetadata( + endpoint_name="foo", tx_endpoint=True, request_type=NotATXRequest, response_type=YesATXResponse + ) + + with pytest.raises(TypeError, match="tx_endpoint response type must subclass TransactionEndpointResponse"): + WalletRpcMetadata( + endpoint_name="foo", tx_endpoint=True, request_type=YesATXRequest, response_type=NotATXResponse + ) diff --git a/chia/_tests/wallet/test_wallet.py b/chia/_tests/wallet/test_wallet.py index 9281d2dbea..002ec14fc1 100644 --- a/chia/_tests/wallet/test_wallet.py +++ b/chia/_tests/wallet/test_wallet.py @@ -5,7 +5,7 @@ from pathlib import Path from typing import Any import pytest -from chia_rs import AugSchemeMPL, Coin, CoinSpend, G1Element, G2Element +from chia_rs import AugSchemeMPL, Coin, CoinSpend from chia_rs.sized_bytes import bytes32 from chia_rs.sized_ints import uint8, uint16, uint32, uint64 @@ -37,6 +37,7 @@ from chia.wallet.wallet_request_types import ( GetTransactionMemo, GetTransactions, SendTransaction, + SignMessageByAddress, SpendClawbackCoins, ) @@ -2153,59 +2154,61 @@ class TestWalletSimulator: async with env.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: ph = await action_scope.get_puzzle_hash(env.wallet_state_manager) - response = await api_0.sign_message_by_address({"address": encode_puzzle_hash(ph, "xch"), "message": message}) + response = await api_0.sign_message_by_address( + SignMessageByAddress(address=encode_puzzle_hash(ph, "xch"), message=message) + ) puzzle: Program = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, message)) assert AugSchemeMPL.verify( - G1Element.from_bytes(hexstr_to_bytes(response["pubkey"])), + response.pubkey, puzzle.get_tree_hash(), - G2Element.from_bytes(hexstr_to_bytes(response["signature"])), + response.signature, ) # Test hex string message = "0123456789ABCDEF" response = await api_0.sign_message_by_address( - {"address": encode_puzzle_hash(ph, "xch"), "message": message, "is_hex": True} + SignMessageByAddress(address=encode_puzzle_hash(ph, "xch"), message=message, is_hex=True) ) puzzle = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, bytes.fromhex(message))) assert AugSchemeMPL.verify( - G1Element.from_bytes(hexstr_to_bytes(response["pubkey"])), + response.pubkey, puzzle.get_tree_hash(), - G2Element.from_bytes(hexstr_to_bytes(response["signature"])), + response.signature, ) # Test informal input message = "0123456789ABCDEF" response = await api_0.sign_message_by_address( - {"address": encode_puzzle_hash(ph, "xch"), "message": message, "is_hex": "true", "safe_mode": "true"} + SignMessageByAddress(address=encode_puzzle_hash(ph, "xch"), message=message, is_hex=True, safe_mode=True) ) puzzle = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, bytes.fromhex(message))) assert AugSchemeMPL.verify( - G1Element.from_bytes(hexstr_to_bytes(response["pubkey"])), + response.pubkey, puzzle.get_tree_hash(), - G2Element.from_bytes(hexstr_to_bytes(response["signature"])), + response.signature, ) # Test BLS sign string message = "Hello World" response = await api_0.sign_message_by_address( - {"address": encode_puzzle_hash(ph, "xch"), "message": message, "is_hex": False, "safe_mode": False} + SignMessageByAddress(address=encode_puzzle_hash(ph, "xch"), message=message, is_hex=False, safe_mode=False) ) assert AugSchemeMPL.verify( - G1Element.from_bytes(hexstr_to_bytes(response["pubkey"])), + response.pubkey, bytes(message, "utf-8"), - G2Element.from_bytes(hexstr_to_bytes(response["signature"])), + response.signature, ) # Test BLS sign hex message = "0123456789ABCDEF" response = await api_0.sign_message_by_address( - {"address": encode_puzzle_hash(ph, "xch"), "message": message, "is_hex": True, "safe_mode": False} + SignMessageByAddress(address=encode_puzzle_hash(ph, "xch"), message=message, is_hex=True, safe_mode=False) ) assert AugSchemeMPL.verify( - G1Element.from_bytes(hexstr_to_bytes(response["pubkey"])), + response.pubkey, hexstr_to_bytes(message), - G2Element.from_bytes(hexstr_to_bytes(response["signature"])), + response.signature, ) @pytest.mark.parametrize( diff --git a/chia/rpc/rpc_server.py b/chia/rpc/rpc_server.py index 49e36f18c8..ac77ab4cb9 100644 --- a/chia/rpc/rpc_server.py +++ b/chia/rpc/rpc_server.py @@ -149,6 +149,7 @@ class RpcServer(Generic[_T_RpcApiProtocol]): """ rpc_api: _T_RpcApiProtocol + rpc_api_routes: dict[str, Endpoint] stop_cb: Callable[[], None] service_name: str ssl_context: SSLContext @@ -183,6 +184,7 @@ class RpcServer(Generic[_T_RpcApiProtocol]): ssl_client_context = ssl_context_for_client(ca_cert_path, ca_key_path, crt_path, key_path, log=log) return cls( rpc_api, + rpc_api.get_routes(), stop_cb, service_name, ssl_context, @@ -261,7 +263,7 @@ class RpcServer(Generic[_T_RpcApiProtocol]): def _get_routes(self) -> dict[str, Endpoint]: return { - **self.rpc_api.get_routes(), + **self.rpc_api_routes, **{path: MethodType(handler, self) for path, handler in self._routes.items()}, } @@ -381,7 +383,7 @@ class RpcServer(Generic[_T_RpcApiProtocol]): f_internal: Endpoint | None = getattr(self, command, None) if f_internal is not None: return await f_internal(data) - f_rpc_api: Endpoint | None = getattr(self.rpc_api, command, None) + f_rpc_api: Endpoint | None = self.rpc_api_routes.get("/" + command) if f_rpc_api is not None: return await f_rpc_api(data) diff --git a/chia/wallet/wallet_rpc_api.py b/chia/wallet/wallet_rpc_api.py index 27985df9f3..78b5c308fe 100644 --- a/chia/wallet/wallet_rpc_api.py +++ b/chia/wallet/wallet_rpc_api.py @@ -7,6 +7,7 @@ from collections.abc import Callable from datetime import datetime, timezone from itertools import count from pathlib import Path +from types import MethodType from typing import TYPE_CHECKING, Any, ClassVar, cast from chia_rs import AugSchemeMPL, Coin, CoinRecord, CoinSpend, CoinState, G1Element, G2Element, PrivateKey @@ -28,7 +29,7 @@ from chia.pools.pool_wallet_info import ( ) from chia.protocols.outbound_message import NodeType from chia.rpc.rpc_server import Endpoint, EndpointResult, RpcServiceProtocol, default_get_connections -from chia.rpc.util import ALL_TRANSLATION_LAYERS, RpcEndpoint, marshal +from chia.rpc.util import ALL_TRANSLATION_LAYERS, MarshallableRpcEndpoint, RpcEndpoint, marshal from chia.types.blockchain_format.program import Program from chia.util.bech32m import decode_puzzle_hash, encode_puzzle_hash from chia.util.config import load_config @@ -88,7 +89,7 @@ from chia.wallet.vc_wallet.vc_wallet import VCWallet from chia.wallet.wallet import Wallet from chia.wallet.wallet_action_scope import WalletActionScope from chia.wallet.wallet_coin_record import WalletCoinRecord, WalletCoinRecordMetadataParsingError -from chia.wallet.wallet_coin_store import CoinRecordOrder, GetCoinRecords, unspent_range +from chia.wallet.wallet_coin_store import CoinRecordOrder, unspent_range from chia.wallet.wallet_info import WalletInfo from chia.wallet.wallet_node import WalletNode, get_wallet_db_path from chia.wallet.wallet_request_types import ( @@ -188,6 +189,7 @@ from chia.wallet.wallet_request_types import ( GetAllOffers, GetAllOffersResponse, GetCATListResponse, + GetCoinRecords, GetCoinRecordsByNames, GetCoinRecordsByNamesResponse, GetCoinRecordsResponse, @@ -322,6 +324,7 @@ from chia.wallet.wallet_request_types import ( WalletCreationMode, WalletInfoResponse, ) +from chia.wallet.wallet_rpc_metadata import WALLET_RPC_ENDPOINT_METADATA, WalletRpcMetadata from chia.wallet.wallet_spend_bundle import WalletSpendBundle from chia.wallet.wallet_state_manager import SyncStatus @@ -587,143 +590,17 @@ class WalletRpcApi: self.service_name = "chia_wallet" def get_routes(self) -> dict[str, Endpoint]: + def apply_wrappers(endpoint_func: MarshallableRpcEndpoint, endpoint: WalletRpcMetadata) -> Endpoint: + marshalled_func = marshal(endpoint_func) + if endpoint.tx_endpoint: + marshalled_func = tx_endpoint(push=endpoint.auto_push, merge_spends=endpoint.auto_merge_spends)( + marshalled_func + ) + return MethodType(marshalled_func, self) + return { - # Key management - "/log_in": self.log_in, - "/get_logged_in_fingerprint": self.get_logged_in_fingerprint, - "/get_public_keys": self.get_public_keys, - "/get_private_key": self.get_private_key, - "/generate_mnemonic": self.generate_mnemonic, - "/add_key": self.add_key, - "/delete_key": self.delete_key, - "/check_delete_key": self.check_delete_key, - "/delete_all_keys": self.delete_all_keys, - # Wallet node - "/set_wallet_resync_on_startup": self.set_wallet_resync_on_startup, - "/get_sync_status": self.get_sync_status, - "/get_full_node_peer_count": self.get_full_node_peer_count, - "/get_height_info": self.get_height_info, - "/push_tx": self.push_tx, - "/push_transactions": self.push_transactions, - "/get_timestamp_for_height": self.get_timestamp_for_height, - "/get_fee_estimate": self.get_fee_estimate, - "/set_auto_claim": self.set_auto_claim, - "/get_auto_claim": self.get_auto_claim, - # Wallet management - "/get_wallets": self.get_wallets, - "/create_new_wallet": self.create_new_wallet, - # Wallet - "/get_wallet_balance": self.get_wallet_balance, - "/get_wallet_balances": self.get_wallet_balances, - "/get_transaction": self.get_transaction, - "/get_transactions": self.get_transactions, - "/get_transaction_count": self.get_transaction_count, - "/get_next_address": self.get_next_address, - "/send_transaction": self.send_transaction, - "/send_transaction_multi": self.send_transaction_multi, - "/spend_clawback_coins": self.spend_clawback_coins, - "/get_coin_records": self.get_coin_records, - "/get_farmed_amount": self.get_farmed_amount, - "/create_signed_transaction": self.create_signed_transaction, - "/delete_unconfirmed_transactions": self.delete_unconfirmed_transactions, - "/select_coins": self.select_coins, - "/get_spendable_coins": self.get_spendable_coins, - "/get_coin_records_by_names": self.get_coin_records_by_names, - "/get_puzzle_and_solution": self.get_puzzle_and_solution, - "/get_current_derivation_index": self.get_current_derivation_index, - "/extend_derivation_index": self.extend_derivation_index, - "/get_notifications": self.get_notifications, - "/delete_notifications": self.delete_notifications, - "/send_notification": self.send_notification, - "/sign_message_by_address": self.sign_message_by_address, - "/sign_message_by_id": self.sign_message_by_id, - "/verify_signature": self.verify_signature, - "/get_transaction_memo": self.get_transaction_memo, - "/split_coins": self.split_coins, - "/combine_coins": self.combine_coins, - # CATs and trading - "/cat_set_name": self.cat_set_name, - "/cat_asset_id_to_name": self.cat_asset_id_to_name, - "/cat_get_name": self.cat_get_name, - "/get_stray_cats": self.get_stray_cats, - "/cat_spend": self.cat_spend, - "/cat_get_asset_id": self.cat_get_asset_id, - "/create_offer_for_ids": self.create_offer_for_ids, - "/get_offer_summary": self.get_offer_summary, - "/check_offer_validity": self.check_offer_validity, - "/take_offer": self.take_offer, - "/get_offer": self.get_offer, - "/get_all_offers": self.get_all_offers, - "/get_offers_count": self.get_offers_count, - "/cancel_offer": self.cancel_offer, - "/cancel_offers": self.cancel_offers, - "/get_cat_list": self.get_cat_list, - # DID Wallet - "/did_set_wallet_name": self.did_set_wallet_name, - "/did_get_wallet_name": self.did_get_wallet_name, - "/did_update_metadata": self.did_update_metadata, - "/did_get_pubkey": self.did_get_pubkey, - "/did_get_did": self.did_get_did, - "/did_get_metadata": self.did_get_metadata, - "/did_get_current_coin_info": self.did_get_current_coin_info, - "/did_create_backup_file": self.did_create_backup_file, - "/did_transfer_did": self.did_transfer_did, - "/did_message_spend": self.did_message_spend, - "/did_get_info": self.did_get_info, - "/did_find_lost_did": self.did_find_lost_did, - # NFT Wallet - "/nft_mint_nft": self.nft_mint_nft, - "/nft_count_nfts": self.nft_count_nfts, - "/nft_get_nfts": self.nft_get_nfts, - "/nft_get_by_did": self.nft_get_by_did, - "/nft_set_nft_did": self.nft_set_nft_did, - "/nft_set_nft_status": self.nft_set_nft_status, - "/nft_get_wallet_did": self.nft_get_wallet_did, - "/nft_get_wallets_with_dids": self.nft_get_wallets_with_dids, - "/nft_get_info": self.nft_get_info, - "/nft_transfer_nft": self.nft_transfer_nft, - "/nft_add_uri": self.nft_add_uri, - "/nft_calculate_royalties": self.nft_calculate_royalties, - "/nft_mint_bulk": self.nft_mint_bulk, - "/nft_set_did_bulk": self.nft_set_did_bulk, - "/nft_transfer_bulk": self.nft_transfer_bulk, - # Remote Wallet - "/register_remote_coins": self.register_remote_coins, - # Pool Wallet - "/pw_join_pool": self.pw_join_pool, - "/pw_self_pool": self.pw_self_pool, - "/pw_absorb_rewards": self.pw_absorb_rewards, - "/pw_status": self.pw_status, - # DL Wallet - "/create_new_dl": self.create_new_dl, - "/dl_track_new": self.dl_track_new, - "/dl_stop_tracking": self.dl_stop_tracking, - "/dl_latest_singleton": self.dl_latest_singleton, - "/dl_singletons_by_root": self.dl_singletons_by_root, - "/dl_update_root": self.dl_update_root, - "/dl_update_multiple": self.dl_update_multiple, - "/dl_history": self.dl_history, - "/dl_owned_singletons": self.dl_owned_singletons, - "/dl_get_mirrors": self.dl_get_mirrors, - "/dl_new_mirror": self.dl_new_mirror, - "/dl_delete_mirror": self.dl_delete_mirror, - "/dl_verify_proof": self.dl_verify_proof, - # Verified Credential - "/vc_mint": self.vc_mint, - "/vc_get": self.vc_get, - "/vc_get_list": self.vc_get_list, - "/vc_spend": self.vc_spend, - "/vc_add_proofs": self.vc_add_proofs, - "/vc_get_proofs_for_root": self.vc_get_proofs_for_root, - "/vc_revoke": self.vc_revoke, - # CR-CATs - "/crcat_approve_pending": self.crcat_approve_pending, - # Signer Protocol - "/gather_signing_info": self.gather_signing_info, - "/apply_signatures": self.apply_signatures, - "/submit_transactions": self.submit_transactions, - # Not technically Signer Protocol but related - "/execute_signing_instructions": self.execute_signing_instructions, + "/" + endpoint.endpoint_name: apply_wrappers(getattr(WalletRpcApi, endpoint.endpoint_name), endpoint) + for endpoint in WALLET_RPC_ENDPOINT_METADATA } def get_connections(self, request_node_type: NodeType | None) -> list[dict[str, Any]]: @@ -764,7 +641,6 @@ class WalletRpcApi: # Key management ########################################################################################## - @marshal async def log_in(self, request: LogIn) -> LogInResponse: """ Logs in the wallet with a specific key. @@ -780,11 +656,9 @@ class WalletRpcApi: raise ValueError(f"fingerprint {request.fingerprint} not found in keychain or keychain is empty") - @marshal async def get_logged_in_fingerprint(self, request: Empty) -> GetLoggedInFingerprintResponse: return GetLoggedInFingerprintResponse(fingerprint=uint32.construct_optional(self.service.logged_in_fingerprint)) - @marshal async def get_public_keys(self, request: Empty) -> GetPublicKeysResponse: try: fingerprints = [key_data.fingerprint for key_data in await self.service.keychain_proxy.get_keys()] @@ -808,7 +682,6 @@ class WalletRpcApi: log.error(f"Failed to get private key by fingerprint: {e}") return None, None - @marshal async def get_private_key(self, request: GetPrivateKey) -> GetPrivateKeyResponse: sk, seed = await self._get_private_key(request.fingerprint) if sk is not None: @@ -826,11 +699,9 @@ class WalletRpcApi: raise ValueError(f"Could not get a private key for fingerprint {request.fingerprint}") - @marshal async def generate_mnemonic(self, request: Empty) -> GenerateMnemonicResponse: return GenerateMnemonicResponse(mnemonic=generate_mnemonic().split(" ")) - @marshal async def add_key(self, request: AddKey) -> AddKeyResponse: # Adding a key from 24 word mnemonic try: @@ -852,7 +723,6 @@ class WalletRpcApi: return AddKeyResponse(fingerprint=fingerprint) raise ValueError("Failed to start") - @marshal async def delete_key(self, request: DeleteKey) -> Empty: await self._stop_wallet() try: @@ -910,7 +780,6 @@ class WalletRpcApi: return found_farmer, found_pool - @marshal async def check_delete_key(self, request: CheckDeleteKey) -> CheckDeleteKeyResponse: """Check the key use prior to possible deletion checks whether key is used for either farm or pool rewards @@ -948,7 +817,6 @@ class WalletRpcApi: wallet_balance=wallet_balance, ) - @marshal async def delete_all_keys(self, request: Empty) -> Empty: await self._stop_wallet() all_key_datas = await self.service.keychain_proxy.get_keys() @@ -970,7 +838,6 @@ class WalletRpcApi: ########################################################################################## # Wallet Node ########################################################################################## - @marshal async def set_wallet_resync_on_startup(self, request: SetWalletResyncOnStartup) -> Empty: """ Resync the current logged in wallet. The transaction and offer records will be kept. @@ -981,7 +848,6 @@ class WalletRpcApi: self.service.set_resync_on_startup(self.service.logged_in_fingerprint, request.enable) return Empty() - @marshal async def get_sync_status(self, request: Empty) -> GetSyncStatusResponse: sync_mode = self.service.wallet_state_manager.sync_mode has_pending_queue_items = self.service.new_peak_queue.has_pending_data_process_items() @@ -989,13 +855,11 @@ class WalletRpcApi: synced = await self.service.wallet_state_manager.synced() return GetSyncStatusResponse(synced=synced, syncing=syncing) - @marshal async def get_full_node_peer_count(self, request: Empty) -> GetFullNodePeerCountResponse: return GetFullNodePeerCountResponse( peer_count=uint64(len(self.service.wallet_state_manager.wallet_node.get_full_node_peers_in_order())) ) - @marshal async def get_height_info(self, request: GetHeightInfo) -> GetHeightInfoResponse: """ Returns height info for the current wallet. @@ -1032,7 +896,6 @@ class WalletRpcApi: prev_transaction_block_height=prev_transaction_block_height, ) - @marshal async def push_tx(self, request: PushTX) -> Empty: nodes = self.service.server.get_connections(NodeType.FULL_NODE) if len(nodes) == 0: @@ -1042,8 +905,6 @@ class WalletRpcApi: return Empty() - @tx_endpoint(push=True) - @marshal async def push_transactions( self, request: PushTransactions, @@ -1070,11 +931,9 @@ class WalletRpcApi: return PushTransactionsResponse(unsigned_transactions=[], transactions=[]) # tx_endpoint takes care of this - @marshal async def get_timestamp_for_height(self, request: GetTimestampForHeight) -> GetTimestampForHeightResponse: return GetTimestampForHeightResponse(timestamp=await self.service.get_timestamp_for_height(request.height)) - @marshal async def get_fee_estimate(self, request: Empty) -> GetFeeEstimateResponse: """ Fetch fee estimates from a connected full node peer via the wallet <-> full node protocol. @@ -1102,7 +961,6 @@ class WalletRpcApi: fee_per_cost = estimate.estimated_fee_rate.mojos_per_clvm_cost return GetFeeEstimateResponse(fee_per_cost=fee_per_cost) - @marshal async def set_auto_claim(self, request: AutoClaimSettings) -> AutoClaimSettings: """ Set auto claim merkle coins config @@ -1111,7 +969,6 @@ class WalletRpcApi: """ return AutoClaimSettings.from_json_dict(self.service.set_auto_claim(request)) - @marshal async def get_auto_claim(self, request: Empty) -> AutoClaimSettings: """ Get auto claim merkle coins config @@ -1124,7 +981,6 @@ class WalletRpcApi: # Wallet Management ########################################################################################## - @marshal async def get_wallets(self, request: GetWallets) -> GetWalletsResponse: wallet_type: WalletType | None = None if request.type is not None: @@ -1161,8 +1017,6 @@ class WalletRpcApi: wallets=wallet_infos, fingerprint=uint32.construct_optional(self.service.logged_in_fingerprint) ) - @tx_endpoint(push=True) - @marshal async def create_new_wallet( self, request: CreateNewWallet, @@ -1403,11 +1257,9 @@ class WalletRpcApi: return BalanceResponse.from_json_dict(wallet_balance) - @marshal async def get_wallet_balance(self, request: GetWalletBalance) -> GetWalletBalanceResponse: return GetWalletBalanceResponse(wallet_balance=await self._get_wallet_balance(request.wallet_id)) - @marshal async def get_wallet_balances(self, request: GetWalletBalances) -> GetWalletBalancesResponse: if request.wallet_ids is not None: wallet_ids = request.wallet_ids @@ -1417,7 +1269,6 @@ class WalletRpcApi: wallet_balances={wallet_id: await self._get_wallet_balance(wallet_id) for wallet_id in wallet_ids} ) - @marshal async def get_transaction(self, request: GetTransaction) -> GetTransactionResponse: tr: TransactionRecord | None = await self.service.wallet_state_manager.get_transaction(request.transaction_id) if tr is None: @@ -1428,7 +1279,6 @@ class WalletRpcApi: transaction_id=tr.name, ) - @marshal async def get_transaction_memo(self, request: GetTransactionMemo) -> GetTransactionMemoResponse: transaction_id: bytes32 = request.transaction_id tr: TransactionRecord | None = await self.service.wallet_state_manager.get_transaction(transaction_id) @@ -1451,8 +1301,6 @@ class WalletRpcApi: spend_bundle = tr.spend_bundle return GetTransactionMemoResponse(transaction_memos={transaction_id: compute_memos(spend_bundle)}) - @tx_endpoint(push=False) - @marshal async def split_coins( self, request: SplitCoins, action_scope: WalletActionScope, extra_conditions: tuple[Condition, ...] = tuple() ) -> SplitCoinsResponse: @@ -1469,8 +1317,6 @@ class WalletRpcApi: # tx_endpoint will take care to fill this out return SplitCoinsResponse(unsigned_transactions=[], transactions=[]) - @tx_endpoint(push=False) - @marshal async def combine_coins( self, request: CombineCoins, action_scope: WalletActionScope, extra_conditions: tuple[Condition, ...] = tuple() ) -> CombineCoinsResponse: @@ -1488,7 +1334,6 @@ class WalletRpcApi: # tx_endpoint will take care to fill this out return CombineCoinsResponse(unsigned_transactions=[], transactions=[]) - @marshal async def get_transactions(self, request: GetTransactions) -> GetTransactionsResponse: to_puzzle_hash: bytes32 | None = None if request.to_address is not None: @@ -1530,7 +1375,6 @@ class WalletRpcApi: wallet_id=request.wallet_id, ) - @marshal async def get_transaction_count(self, request: GetTransactionCount) -> GetTransactionCountResponse: return GetTransactionCountResponse( wallet_id=request.wallet_id, @@ -1541,7 +1385,6 @@ class WalletRpcApi: ), ) - @marshal async def get_next_address(self, request: GetNextAddress) -> GetNextAddressResponse: """ Returns a new address @@ -1563,8 +1406,6 @@ class WalletRpcApi: address=address, ) - @tx_endpoint(push=True) - @marshal async def send_transaction( self, request: SendTransaction, @@ -1589,9 +1430,10 @@ class WalletRpcApi: wallet_id=request.wallet_id, fee=request.fee, puzzle_decorator=request.puzzle_decorator, - ).json_serialize_for_transport(action_scope.config.tx_config, extra_conditions, ConditionValidTimes()), + ), + action_scope=action_scope, + extra_conditions=extra_conditions, hold_lock=False, - action_scope_override=action_scope, ) # Transaction may not have been included in the mempool yet. Use get_transaction to check. @@ -1603,8 +1445,6 @@ class WalletRpcApi: transaction_id=bytes32.zeros, ) - @tx_endpoint(push=True) - @marshal async def send_transaction_multi( self, request: SendTransactionMulti, @@ -1616,19 +1456,17 @@ class WalletRpcApi: async with self.service.wallet_state_manager.lock: if issubclass(type(wallet), CATWallet): await self.cat_spend( - request.convert_to_proxy(CATSpend).json_serialize_for_transport( - action_scope.config.tx_config, extra_conditions, ConditionValidTimes() - ), + request.convert_to_proxy(CATSpend), + action_scope=action_scope, + extra_conditions=extra_conditions, hold_lock=False, - action_scope_override=action_scope, ) else: await self.create_signed_transaction( - request.convert_to_proxy(CreateSignedTransaction).json_serialize_for_transport( - action_scope.config.tx_config, extra_conditions, ConditionValidTimes() - ), + request.convert_to_proxy(CreateSignedTransaction), + action_scope=action_scope, + extra_conditions=extra_conditions, hold_lock=False, - action_scope_override=action_scope, ) # tx_endpoint will take care of these values @@ -1639,8 +1477,6 @@ class WalletRpcApi: transaction_id=bytes32.zeros, ) - @tx_endpoint(push=True, merge_spends=False) - @marshal async def spend_clawback_coins( self, request: SpendClawbackCoins, @@ -1687,7 +1523,6 @@ class WalletRpcApi: # tx_endpoint will fill in the default values here return SpendClawbackCoinsResponse(unsigned_transactions=[], transactions=[], transaction_ids=[]) - @marshal async def delete_unconfirmed_transactions(self, request: DeleteUnconfirmedTransactions) -> Empty: if request.wallet_id not in self.service.wallet_state_manager.wallets: raise ValueError(f"Wallet id {request.wallet_id} does not exist") @@ -1702,7 +1537,6 @@ class WalletRpcApi: wallet.target_state = None return Empty() - @marshal async def select_coins( self, request: SelectCoins, @@ -1742,7 +1576,6 @@ class WalletRpcApi: return SelectCoinsResponse(coins=list(selected_coins)) - @marshal async def get_spendable_coins(self, request: GetSpendableCoins) -> GetSpendableCoinsResponse: sync_status = await self.service.wallet_state_manager.get_sync_status() if sync_status == SyncStatus.DISCONNECTED: @@ -1790,7 +1623,6 @@ class WalletRpcApi: unconfirmed_additions=list(unconfirmed_additions), ) - @marshal async def get_coin_records_by_names(self, request: GetCoinRecordsByNames) -> GetCoinRecordsByNamesResponse: sync_status = await self.service.wallet_state_manager.get_sync_status() if sync_status == SyncStatus.DISCONNECTED: @@ -1831,7 +1663,6 @@ class WalletRpcApi: return GetCoinRecordsByNamesResponse(coin_records=coin_records) - @marshal async def get_puzzle_and_solution(self, request: GetPuzzleAndSolution) -> GetPuzzleAndSolutionResponse: coin_record = await self.service.wallet_state_manager.coin_store.get_coin_record(request.coin_name) if coin_record is None or not coin_record.spent: @@ -1843,7 +1674,6 @@ class WalletRpcApi: solution=bytes(coin_spend.solution).hex(), ) - @marshal async def get_current_derivation_index(self, request: Empty) -> GetCurrentDerivationIndexResponse: assert self.service.wallet_state_manager is not None @@ -1851,7 +1681,6 @@ class WalletRpcApi: return GetCurrentDerivationIndexResponse(index=index) - @marshal async def extend_derivation_index(self, request: ExtendDerivationIndex) -> ExtendDerivationIndexResponse: assert self.service.wallet_state_manager is not None @@ -1888,7 +1717,6 @@ class WalletRpcApi: return ExtendDerivationIndexResponse(index=updated_index) - @marshal async def get_notifications(self, request: GetNotifications) -> GetNotificationsResponse: return GetNotificationsResponse( notifications=( @@ -1898,7 +1726,6 @@ class WalletRpcApi: ) ) - @marshal async def delete_notifications(self, request: DeleteNotifications) -> Empty: await self.service.wallet_state_manager.notification_manager.notification_store.delete_notifications( coin_ids=request.ids @@ -1906,8 +1733,6 @@ class WalletRpcApi: return Empty() - @tx_endpoint(push=True) - @marshal async def send_notification( self, request: SendNotification, @@ -1926,7 +1751,6 @@ class WalletRpcApi: # tx_endpoint will take care of these default values return SendNotificationResponse(unsigned_transactions=[], transactions=[], tx=REPLACEABLE_TRANSACTION_RECORD) - @marshal async def verify_signature(self, request: VerifySignature) -> VerifySignatureResponse: return verify_signature( signing_mode=request.signing_mode_enum, @@ -1936,7 +1760,6 @@ class WalletRpcApi: address=request.address, ) - @marshal async def sign_message_by_address(self, request: SignMessageByAddress) -> SignMessageByAddressResponse: """ Given a derived P2 address, sign the message by its private key. @@ -1957,7 +1780,6 @@ class WalletRpcApi: signing_mode=request.signing_mode_enum.value, ) - @marshal async def sign_message_by_id(self, request: SignMessageByID) -> SignMessageByIDResponse: """ Given a NFT/DID ID, sign the message by the P2 private key. @@ -2030,27 +1852,23 @@ class WalletRpcApi: # CATs and Trading ########################################################################################## - @marshal async def get_cat_list(self, request: Empty) -> GetCATListResponse: return GetCATListResponse( cat_list=[DefaultCAT.from_json_dict(default_cat) for default_cat in DEFAULT_CATS.values()] ) - @marshal async def cat_set_name(self, request: CATSetName) -> CATSetNameResponse: await self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=CATWallet).set_name( request.name ) return CATSetNameResponse(wallet_id=request.wallet_id) - @marshal async def cat_get_name(self, request: CATGetName) -> CATGetNameResponse: return CATGetNameResponse( wallet_id=request.wallet_id, name=self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=CATWallet).get_name(), ) - @marshal async def get_stray_cats(self, request: Empty) -> GetStrayCATsResponse: """ Get a list of all unacknowledged CATs @@ -2064,8 +1882,6 @@ class WalletRpcApi: ] ) - @tx_endpoint(push=True) - @marshal async def cat_spend( self, request: CATSpend, @@ -2099,9 +1915,10 @@ class WalletRpcApi: extra_delta=request.extra_delta, tail_reveal=request.tail_reveal, tail_solution=request.tail_solution, - ).json_serialize_for_transport(action_scope.config.tx_config, extra_conditions, ConditionValidTimes()), + ), + action_scope=action_scope, + extra_conditions=extra_conditions, hold_lock=hold_lock, - action_scope_override=action_scope, ) # tx_endpoint will fill in these default values @@ -2112,7 +1929,6 @@ class WalletRpcApi: transaction_id=bytes32.zeros, ) - @marshal async def cat_get_asset_id(self, request: CATGetAssetID) -> CATGetAssetIDResponse: return CATGetAssetIDResponse( asset_id=self.service.wallet_state_manager.get_wallet( @@ -2121,7 +1937,6 @@ class WalletRpcApi: wallet_id=request.wallet_id, ) - @marshal async def cat_asset_id_to_name(self, request: CATAssetIDToName) -> CATAssetIDToNameResponse: wallet = await self.service.wallet_state_manager.get_wallet_for_asset_id(request.asset_id) if wallet is None: @@ -2132,8 +1947,6 @@ class WalletRpcApi: else: return CATAssetIDToNameResponse(wallet_id=wallet.id(), name=wallet.get_name()) - @tx_endpoint(push=False) - @marshal async def create_offer_for_ids( self, request: CreateOfferForIDs, @@ -2170,7 +1983,6 @@ class WalletRpcApi: _trade_record=result[1], ) - @marshal async def get_offer_summary(self, request: GetOfferSummary) -> GetOfferSummaryResponse: dl_summary = None if not request.advanced: @@ -2226,7 +2038,6 @@ class WalletRpcApi: else None, ) - @marshal async def check_offer_validity(self, request: CheckOfferValidity) -> CheckOfferValidityResponse: offer = Offer.from_bech32(request.offer) peer = self.service.get_full_node_peer() @@ -2235,8 +2046,6 @@ class WalletRpcApi: id=offer.name(), ) - @tx_endpoint(push=True) - @marshal async def take_offer( self, request: TakeOffer, @@ -2266,7 +2075,6 @@ class WalletRpcApi: _trade_record=trade_record, ) - @marshal async def get_offer(self, request: GetOffer) -> GetOfferResponse: trade_record: TradeRecord | None = await self.service.wallet_state_manager.trade_manager.get_trade_by_id( request.trade_id @@ -2281,7 +2089,6 @@ class WalletRpcApi: trade_record=trade_record, ) - @marshal async def get_all_offers(self, request: GetAllOffers) -> GetAllOffersResponse: all_trades = await self.service.wallet_state_manager.trade_manager.trade_store.get_trades_between( request.start, @@ -2306,7 +2113,6 @@ class WalletRpcApi: offers=offer_values, ) - @marshal async def get_offers_count(self, request: Empty) -> GetOffersCountResponse: ( total, @@ -2318,8 +2124,6 @@ class WalletRpcApi: total=uint32(total), my_offers_count=uint32(my_offers_count), taken_offers_count=uint32(taken_offers_count) ) - @tx_endpoint(push=True) - @marshal async def cancel_offer( self, request: CancelOffer, @@ -2338,8 +2142,6 @@ class WalletRpcApi: # tx_endpoint will fill in default values here return CancelOfferResponse(unsigned_transactions=[], transactions=[]) - @tx_endpoint(push=True, merge_spends=False) - @marshal async def cancel_offers( self, request: CancelOffers, @@ -2386,22 +2188,18 @@ class WalletRpcApi: # Distributed Identities ########################################################################################## - @marshal async def did_set_wallet_name(self, request: DIDSetWalletName) -> DIDSetWalletNameResponse: await self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet).set_name( request.name ) return DIDSetWalletNameResponse(wallet_id=request.wallet_id) - @marshal async def did_get_wallet_name(self, request: DIDGetWalletName) -> DIDGetWalletNameResponse: return DIDGetWalletNameResponse( wallet_id=request.wallet_id, name=self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet).get_name(), ) - @tx_endpoint(push=False) - @marshal async def did_message_spend( self, request: DIDMessageSpend, @@ -2424,7 +2222,6 @@ class WalletRpcApi: unsigned_transactions=[], transactions=[], spend_bundle=WalletSpendBundle([], G2Element()) ) - @marshal async def did_get_info(self, request: DIDGetInfo) -> DIDGetInfoResponse: if request.coin_id.startswith(AddressType.DID.hrp(self.service.config)): coin_id = decode_puzzle_hash(request.coin_id) @@ -2447,7 +2244,6 @@ class WalletRpcApi: hints=search_results.hints, ) - @marshal async def did_find_lost_did(self, request: DIDFindLostDID) -> DIDFindLostDIDResponse: """ Recover a missing or unspendable DID wallet by a coin id of the DID @@ -2470,8 +2266,6 @@ class WalletRpcApi: return DIDFindLostDIDResponse(latest_coin_id=coin_id) - @tx_endpoint(push=True) - @marshal async def did_update_metadata( self, request: DIDUpdateMetadata, @@ -2491,7 +2285,6 @@ class WalletRpcApi: spend_bundle=WalletSpendBundle([], G2Element()), ) - @marshal async def did_get_did(self, request: DIDGetDID) -> DIDGetDIDResponse: wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet) my_did: str = encode_puzzle_hash(bytes32.fromhex(wallet.get_my_DID()), AddressType.DID.hrp(self.service.config)) @@ -2502,7 +2295,6 @@ class WalletRpcApi: except RuntimeError: return DIDGetDIDResponse(wallet_id=request.wallet_id, my_did=my_did) - @marshal async def did_get_metadata(self, request: DIDGetMetadata) -> DIDGetMetadataResponse: wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet) metadata = json.loads(wallet.did_info.metadata) @@ -2511,7 +2303,6 @@ class WalletRpcApi: metadata=metadata, ) - @marshal async def did_get_pubkey(self, request: DIDGetPubkey) -> DIDGetPubkeyResponse: # opportunity to raise self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet) @@ -2519,7 +2310,6 @@ class WalletRpcApi: pubkey=(await self.service.wallet_state_manager.get_unused_derivation_record(request.wallet_id)).pubkey ) - @marshal async def did_get_current_coin_info(self, request: DIDGetCurrentCoinInfo) -> DIDGetCurrentCoinInfoResponse: did_wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet) my_did = encode_puzzle_hash( @@ -2537,7 +2327,6 @@ class WalletRpcApi: did_amount=parent_coin.amount, ) - @marshal async def did_create_backup_file(self, request: DIDCreateBackupFile) -> DIDCreateBackupFileResponse: return DIDCreateBackupFileResponse( wallet_id=request.wallet_id, @@ -2546,8 +2335,6 @@ class WalletRpcApi: ).create_backup(), ) - @tx_endpoint(push=True) - @marshal async def did_transfer_did( self, request: DIDTransferDID, @@ -2576,8 +2363,6 @@ class WalletRpcApi: ########################################################################################## # NFT Wallet ########################################################################################## - @tx_endpoint(push=True) - @marshal async def nft_mint_nft( self, request: NFTMintNFTRequest, @@ -2637,7 +2422,6 @@ class WalletRpcApi: nft_id=nft_id_bech32, ) - @marshal async def nft_count_nfts(self, request: NFTCountNFTs) -> NFTCountNFTsResponse: count = 0 if request.wallet_id is not None: @@ -2648,7 +2432,6 @@ class WalletRpcApi: count = await self.service.wallet_state_manager.nft_store.count() return NFTCountNFTsResponse(wallet_id=request.wallet_id, count=uint64(count)) - @marshal async def nft_get_nfts(self, request: NFTGetNFTs) -> NFTGetNFTsResponse: nfts: list[NFTCoinInfo] = [] if request.wallet_id is not None: @@ -2667,8 +2450,6 @@ class WalletRpcApi: nft_info_list.append(nft_info) return NFTGetNFTsResponse(wallet_id=request.wallet_id, nft_list=nft_info_list) - @tx_endpoint(push=True) - @marshal async def nft_set_nft_did( self, request: NFTSetNFTDID, @@ -2701,8 +2482,6 @@ class WalletRpcApi: spend_bundle=WalletSpendBundle([], G2Element()), ) - @tx_endpoint(push=True) - @marshal async def nft_set_did_bulk( self, request: NFTSetDIDBulk, @@ -2773,8 +2552,6 @@ class WalletRpcApi: tx_num=uint32(len(interface.side_effects.transactions)), ) - @tx_endpoint(push=True) - @marshal async def nft_transfer_bulk( self, request: NFTTransferBulk, @@ -2838,7 +2615,6 @@ class WalletRpcApi: tx_num=uint32(len(interface.side_effects.transactions)), ) - @marshal async def nft_get_by_did(self, request: NFTGetByDID) -> NFTGetByDIDResponse: did_id: bytes32 | None = None if request.did_id is not None: @@ -2848,7 +2624,6 @@ class WalletRpcApi: return NFTGetByDIDResponse(wallet_id=uint32(wallet.wallet_id)) raise ValueError(f"Cannot find a NFT wallet DID = {did_id}") - @marshal async def nft_get_wallet_did(self, request: NFTGetWalletDID) -> NFTGetWalletDIDResponse: nft_wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=NFTWallet) did_bytes: bytes32 | None = nft_wallet.get_did() @@ -2857,7 +2632,6 @@ class WalletRpcApi: did_id = encode_puzzle_hash(did_bytes, AddressType.DID.hrp(self.service.config)) return NFTGetWalletDIDResponse(did_id=None if len(did_id) == 0 else did_id) - @marshal async def nft_get_wallets_with_dids(self, request: Empty) -> NFTGetWalletsWithDIDsResponse: all_wallets = self.service.wallet_state_manager.wallets.values() did_wallets_by_did_id: dict[bytes32, uint32] = {} @@ -2886,15 +2660,12 @@ class WalletRpcApi: ) return NFTGetWalletsWithDIDsResponse(nft_wallets=did_nft_wallets) - @marshal async def nft_set_nft_status(self, request: NFTSetNFTStatus) -> Empty: assert self.service.wallet_state_manager is not None nft_wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=NFTWallet) await nft_wallet.update_coin_status(request.coin_id, request.in_transaction) return Empty() - @tx_endpoint(push=True) - @marshal async def nft_transfer_nft( self, request: NFTTransferNFT, @@ -2929,7 +2700,6 @@ class WalletRpcApi: spend_bundle=WalletSpendBundle([], G2Element()), ) - @marshal async def nft_get_info(self, request: NFTGetInfo) -> NFTGetInfoResponse: if request.coin_id.startswith(AddressType.NFT.hrp(self.service.config)): coin_id = decode_puzzle_hash(request.coin_id) @@ -2942,8 +2712,6 @@ class WalletRpcApi: nft_info = dataclasses.replace(search_results.nft_info, p2_address=search_results.next_p2_puzzle_hash) return NFTGetInfoResponse(nft_info=nft_info) - @tx_endpoint(push=True) - @marshal async def nft_add_uri( self, request: NFTAddURI, @@ -2970,7 +2738,6 @@ class WalletRpcApi: spend_bundle=WalletSpendBundle([], G2Element()), ) - @marshal async def nft_calculate_royalties(self, request: NFTCalculateRoyalties) -> NFTCalculateRoyaltiesResponse: return NFTCalculateRoyaltiesResponse.from_json_dict( NFTWallet.royalty_calculation( @@ -2982,8 +2749,6 @@ class WalletRpcApi: ) ) - @tx_endpoint(push=False) - @marshal async def nft_mint_bulk( self, request: NFTMintBulk, @@ -3074,13 +2839,11 @@ class WalletRpcApi: nft_id_list=nft_id_list, ) - @marshal async def register_remote_coins(self, request: RegisterRemoteCoins) -> Empty: remote_wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=RemoteWallet) await remote_wallet.register_remote_coins(request.coin_ids) return Empty() - @marshal async def get_coin_records(self, request: GetCoinRecords) -> GetCoinRecordsResponse: if request.limit != uint32.MAXIMUM and request.limit > self.max_get_coin_records_limit: @@ -3142,7 +2905,6 @@ class WalletRpcApi: total_count=result.total_count, ) - @marshal async def get_farmed_amount(self, request: GetFarmedAmount) -> GetFarmedAmountResponse: tx_records: list[TransactionRecord] = await self.service.wallet_state_manager.tx_store.get_farming_rewards() amount = 0 @@ -3191,8 +2953,6 @@ class WalletRpcApi: blocks_won=uint32(blocks_won), ) - @tx_endpoint(push=False) - @marshal async def create_signed_transaction( self, request: CreateSignedTransaction, @@ -3261,8 +3021,6 @@ class WalletRpcApi: ########################################################################################## # Pool Wallet ########################################################################################## - @tx_endpoint(push=True) - @marshal async def pw_join_pool( self, request: PWJoinPool, @@ -3314,8 +3072,6 @@ class WalletRpcApi: fee_transaction=REPLACEABLE_TRANSACTION_RECORD, ) - @tx_endpoint(push=True) - @marshal async def pw_self_pool( self, request: PWSelfPool, @@ -3350,8 +3106,6 @@ class WalletRpcApi: fee_transaction=REPLACEABLE_TRANSACTION_RECORD, ) - @tx_endpoint(push=True) - @marshal async def pw_absorb_rewards( self, request: PWAbsorbRewards, @@ -3379,7 +3133,6 @@ class WalletRpcApi: fee_transaction=REPLACEABLE_TRANSACTION_RECORD, ) - @marshal async def pw_status(self, request: PWStatus) -> PWStatusResponse: """Return the complete state of the Pool wallet with id `request["wallet_id"]`""" wallet = self.service.wallet_state_manager.wallets[request.wallet_id] @@ -3399,8 +3152,6 @@ class WalletRpcApi: ########################################################################################## # DataLayer Wallet ########################################################################################## - @tx_endpoint(push=True) - @marshal async def create_new_dl( self, request: CreateNewDL, @@ -3424,7 +3175,6 @@ class WalletRpcApi: # tx_endpoint will take care of these default values return CreateNewDLResponse(unsigned_transactions=[], transactions=[], launcher_id=launcher_id) - @marshal async def dl_track_new(self, request: DLTrackNew) -> Empty: """Initialize the DataLayer Wallet (only one can exist)""" if self.service.wallet_state_manager is None: @@ -3436,7 +3186,6 @@ class WalletRpcApi: return Empty() - @marshal async def dl_stop_tracking(self, request: DLStopTracking) -> Empty: """Initialize the DataLayer Wallet (only one can exist)""" if self.service.wallet_state_manager is None: @@ -3446,7 +3195,6 @@ class WalletRpcApi: await dl_wallet.stop_tracking_singleton(request.launcher_id) return Empty() - @marshal async def dl_latest_singleton(self, request: DLLatestSingleton) -> DLLatestSingletonResponse: """Get the singleton record for the latest singleton of a launcher ID""" if self.service.wallet_state_manager is None: @@ -3456,7 +3204,6 @@ class WalletRpcApi: record = await wallet.get_latest_singleton(request.launcher_id, request.only_confirmed) return DLLatestSingletonResponse(singleton=record) - @marshal async def dl_singletons_by_root(self, request: DLSingletonsByRoot) -> DLSingletonsByRootResponse: """Get the singleton records that contain the specified root""" if self.service.wallet_state_manager is None: @@ -3466,8 +3213,6 @@ class WalletRpcApi: records = await wallet.get_singletons_by_root(request.launcher_id, request.root) return DLSingletonsByRootResponse(singletons=records) - @tx_endpoint(push=True) - @marshal async def dl_update_root( self, request: DLUpdateRoot, @@ -3491,8 +3236,6 @@ class WalletRpcApi: # tx_endpoint will take care of default values here return DLUpdateRootResponse(unsigned_transactions=[], transactions=[], tx_record=REPLACEABLE_TRANSACTION_RECORD) - @tx_endpoint(push=True) - @marshal async def dl_update_multiple( self, request: DLUpdateMultiple, @@ -3521,7 +3264,6 @@ class WalletRpcApi: # tx_endpoint will take care of default values here return DLUpdateMultipleResponse(unsigned_transactions=[], transactions=[]) - @marshal async def dl_history(self, request: DLHistory) -> DLHistoryResponse: """Get the singleton record for the latest singleton of a launcher ID""" if self.service.wallet_state_manager is None: @@ -3540,7 +3282,6 @@ class WalletRpcApi: history = await wallet.get_history(request.launcher_id, **additional_kwargs) return DLHistoryResponse(history=history, count=uint32(len(history))) - @marshal async def dl_owned_singletons(self, request: Empty) -> DLOwnedSingletonsResponse: """Get all owned singleton records""" if self.service.wallet_state_manager is None: @@ -3551,7 +3292,6 @@ class WalletRpcApi: return DLOwnedSingletonsResponse(singletons=singletons, count=uint32(len(singletons))) - @marshal async def dl_get_mirrors(self, request: DLGetMirrors) -> DLGetMirrorsResponse: """Get all of the mirrors for a specific singleton""" if self.service.wallet_state_manager is None: @@ -3560,8 +3300,6 @@ class WalletRpcApi: wallet = await self.service.wallet_state_manager.get_dl_wallet() return DLGetMirrorsResponse(mirrors=await wallet.get_mirrors_for_launcher(request.launcher_id)) - @tx_endpoint(push=True) - @marshal async def dl_new_mirror( self, request: DLNewMirror, @@ -3586,8 +3324,6 @@ class WalletRpcApi: # tx_endpoint will take care of default values here return DLNewMirrorResponse(unsigned_transactions=[], transactions=[]) - @tx_endpoint(push=True) - @marshal async def dl_delete_mirror( self, request: DLDeleteMirror, @@ -3611,7 +3347,6 @@ class WalletRpcApi: # tx_endpoint will take care of default values here return DLDeleteMirrorResponse(unsigned_transactions=[], transactions=[]) - @marshal async def dl_verify_proof( self, request: DLProof, @@ -3628,8 +3363,6 @@ class WalletRpcApi: ########################################################################################## # Verified Credential ########################################################################################## - @tx_endpoint(push=True) - @marshal async def vc_mint( self, request: VCMint, @@ -3654,7 +3387,6 @@ class WalletRpcApi: ) return VCMintResponse(unsigned_transactions=[], transactions=[], vc_record=vc_record) - @marshal async def vc_get(self, request: VCGet) -> VCGetResponse: """ Given a launcher ID get the verified credential @@ -3664,7 +3396,6 @@ class WalletRpcApi: vc_record = await self.service.wallet_state_manager.vc_store.get_vc_record(request.vc_id) return VCGetResponse(vc_record=vc_record) - @marshal async def vc_get_list(self, request: VCGetList) -> VCGetListResponse: """ Get a list of verified credentials @@ -3688,8 +3419,6 @@ class WalletRpcApi: ], ) - @tx_endpoint(push=True) - @marshal async def vc_spend( self, request: VCSpend, @@ -3723,7 +3452,6 @@ class WalletRpcApi: return VCSpendResponse(unsigned_transactions=[], transactions=[]) # tx_endpoint takes care of filling this out - @marshal async def vc_add_proofs(self, request: VCAddProofs) -> Empty: """ Add a set of proofs to the DB that can be used when spending a VC. VCs are near useless until their proofs have @@ -3737,7 +3465,6 @@ class WalletRpcApi: return Empty() - @marshal async def vc_get_proofs_for_root(self, request: VCGetProofsForRoot) -> VCGetProofsForRootResponse: """ Given a specified vc root, get any proofs associated with that root. @@ -3752,8 +3479,6 @@ class WalletRpcApi: raise ValueError("no proofs found for specified root") # pragma: no cover return VCGetProofsForRootResponse.from_vc_proofs(vc_proofs) - @tx_endpoint(push=True) - @marshal async def vc_revoke( self, request: VCRevoke, @@ -3778,8 +3503,6 @@ class WalletRpcApi: return VCRevokeResponse(unsigned_transactions=[], transactions=[]) # tx_endpoint takes care of filling this out - @tx_endpoint(push=True) - @marshal async def crcat_approve_pending( self, request: CRCATApprovePending, @@ -3807,7 +3530,6 @@ class WalletRpcApi: # tx_endpoint will take care of default values here return CRCATApprovePendingResponse(unsigned_transactions=[], transactions=[]) - @marshal async def gather_signing_info( self, request: GatherSigningInfo, @@ -3816,7 +3538,6 @@ class WalletRpcApi: signing_instructions=await self.service.wallet_state_manager.gather_signing_info(request.spends) ) - @marshal async def apply_signatures( self, request: ApplySignatures, @@ -3827,7 +3548,6 @@ class WalletRpcApi: ] ) - @marshal async def submit_transactions( self, request: SubmitTransactions, @@ -3836,7 +3556,6 @@ class WalletRpcApi: mempool_ids=await self.service.wallet_state_manager.submit_transactions(request.signed_transactions) ) - @marshal async def execute_signing_instructions( self, request: ExecuteSigningInstructions, diff --git a/chia/wallet/wallet_rpc_client.py b/chia/wallet/wallet_rpc_client.py index 5293555df6..d3fbed79bb 100644 --- a/chia/wallet/wallet_rpc_client.py +++ b/chia/wallet/wallet_rpc_client.py @@ -1,1048 +1,129 @@ from __future__ import annotations -from typing import Any +from collections.abc import Awaitable, Callable -from chia.data_layer.data_layer_util import DLProof, VerifyProofResponse from chia.rpc.rpc_client import RpcClient +from chia.util.streamable import Streamable from chia.wallet.conditions import Condition, ConditionValidTimes -from chia.wallet.puzzles.clawback.metadata import AutoClaimSettings -from chia.wallet.transaction_record import TransactionRecord from chia.wallet.util.clvm_streamable import json_deserialize_with_clvm_streamable from chia.wallet.util.tx_config import TXConfig -from chia.wallet.wallet_coin_store import GetCoinRecords -from chia.wallet.wallet_request_types import ( - AddKey, - AddKeyResponse, - ApplySignatures, - ApplySignaturesResponse, - CancelOffer, - CancelOfferResponse, - CancelOffers, - CancelOffersResponse, - CATAssetIDToName, - CATAssetIDToNameResponse, - CATGetAssetID, - CATGetAssetIDResponse, - CATGetName, - CATGetNameResponse, - CATSetName, - CATSetNameResponse, - CATSpend, - CATSpendResponse, - CheckDeleteKey, - CheckDeleteKeyResponse, - CheckOfferValidity, - CheckOfferValidityResponse, - CombineCoins, - CombineCoinsResponse, - CRCATApprovePending, - CRCATApprovePendingResponse, - CreateNewDL, - CreateNewDLResponse, - CreateNewWallet, - CreateNewWalletResponse, - CreateOfferForIDs, - CreateOfferForIDsResponse, - CreateSignedTransaction, - CreateSignedTransactionsResponse, - DeleteKey, - DeleteNotifications, - DeleteUnconfirmedTransactions, - DIDCreateBackupFile, - DIDCreateBackupFileResponse, - DIDFindLostDID, - DIDFindLostDIDResponse, - DIDGetCurrentCoinInfo, - DIDGetCurrentCoinInfoResponse, - DIDGetDID, - DIDGetDIDResponse, - DIDGetInfo, - DIDGetInfoResponse, - DIDGetMetadata, - DIDGetMetadataResponse, - DIDGetPubkey, - DIDGetPubkeyResponse, - DIDGetWalletName, - DIDGetWalletNameResponse, - DIDMessageSpend, - DIDMessageSpendResponse, - DIDSetWalletName, - DIDSetWalletNameResponse, - DIDTransferDID, - DIDTransferDIDResponse, - DIDUpdateMetadata, - DIDUpdateMetadataResponse, - DLDeleteMirror, - DLDeleteMirrorResponse, - DLGetMirrors, - DLGetMirrorsResponse, - DLHistory, - DLHistoryResponse, - DLLatestSingleton, - DLLatestSingletonResponse, - DLNewMirror, - DLNewMirrorResponse, - DLOwnedSingletonsResponse, - DLSingletonsByRoot, - DLSingletonsByRootResponse, - DLStopTracking, - DLTrackNew, - DLUpdateMultiple, - DLUpdateMultipleResponse, - DLUpdateRoot, - DLUpdateRootResponse, - ExecuteSigningInstructions, - ExecuteSigningInstructionsResponse, - ExtendDerivationIndex, - ExtendDerivationIndexResponse, - GatherSigningInfo, - GatherSigningInfoResponse, - GenerateMnemonicResponse, - GetAllOffers, - GetAllOffersResponse, - GetCATListResponse, - GetCoinRecordsByNames, - GetCoinRecordsByNamesResponse, - GetCoinRecordsResponse, - GetCurrentDerivationIndexResponse, - GetFarmedAmount, - GetFarmedAmountResponse, - GetFeeEstimateResponse, - GetFullNodePeerCountResponse, - GetHeightInfo, - GetHeightInfoResponse, - GetLoggedInFingerprintResponse, - GetNextAddress, - GetNextAddressResponse, - GetNotifications, - GetNotificationsResponse, - GetOffer, - GetOfferResponse, - GetOffersCountResponse, - GetOfferSummary, - GetOfferSummaryResponse, - GetPrivateKey, - GetPrivateKeyResponse, - GetPublicKeysResponse, - GetSpendableCoins, - GetSpendableCoinsResponse, - GetStrayCATsResponse, - GetSyncStatusResponse, - GetTimestampForHeight, - GetTimestampForHeightResponse, - GetTransaction, - GetTransactionCount, - GetTransactionCountResponse, - GetTransactionMemo, - GetTransactionMemoResponse, - GetTransactionResponse, - GetTransactions, - GetTransactionsResponse, - GetWalletBalance, - GetWalletBalanceResponse, - GetWalletBalances, - GetWalletBalancesResponse, - GetWallets, - GetWalletsResponse, - LogIn, - LogInResponse, - NFTAddURI, - NFTAddURIResponse, - NFTCalculateRoyalties, - NFTCalculateRoyaltiesResponse, - NFTCountNFTs, - NFTCountNFTsResponse, - NFTGetByDID, - NFTGetByDIDResponse, - NFTGetInfo, - NFTGetInfoResponse, - NFTGetNFTs, - NFTGetNFTsResponse, - NFTGetWalletDID, - NFTGetWalletDIDResponse, - NFTGetWalletsWithDIDsResponse, - NFTMintBulk, - NFTMintBulkResponse, - NFTMintNFTRequest, - NFTMintNFTResponse, - NFTSetDIDBulk, - NFTSetDIDBulkResponse, - NFTSetNFTDID, - NFTSetNFTDIDResponse, - NFTSetNFTStatus, - NFTTransferBulk, - NFTTransferBulkResponse, - NFTTransferNFT, - NFTTransferNFTResponse, - PushTransactions, - PushTransactionsResponse, - PushTX, - PWAbsorbRewards, - PWAbsorbRewardsResponse, - PWJoinPool, - PWJoinPoolResponse, - PWSelfPool, - PWSelfPoolResponse, - PWStatus, - PWStatusResponse, - RegisterRemoteCoins, - SelectCoins, - SelectCoinsResponse, - SendNotification, - SendNotificationResponse, - SendTransaction, - SendTransactionMulti, - SendTransactionMultiResponse, - SendTransactionResponse, - SetWalletResyncOnStartup, - SignMessageByAddress, - SignMessageByAddressResponse, - SignMessageByID, - SignMessageByIDResponse, - SpendClawbackCoins, - SpendClawbackCoinsResponse, - SplitCoins, - SplitCoinsResponse, - SubmitTransactions, - SubmitTransactionsResponse, - TakeOffer, - TakeOfferResponse, - VCAddProofs, - VCGet, - VCGetList, - VCGetListResponse, - VCGetProofsForRoot, - VCGetProofsForRootResponse, - VCGetResponse, - VCMint, - VCMintResponse, - VCRevoke, - VCRevokeResponse, - VCSpend, - VCSpendResponse, - VerifySignature, - VerifySignatureResponse, +from chia.wallet.wallet_request_types import Empty +from chia.wallet.wallet_rpc_metadata import WALLET_RPC_ENDPOINT_METADATA, WalletRpcMetadata + +# Client method names that differ from the RPC endpoint path (historical CLI/test API). +# TODO: change these to match +CLIENT_METHOD_NAME_OVERRIDES: dict[str, str] = { + "create_signed_transaction": "create_signed_transactions", + "did_get_did": "get_did_id", + "did_get_info": "get_did_info", + "did_create_backup_file": "create_did_backup_file", + "did_update_metadata": "update_did_metadata", + "did_get_pubkey": "get_did_pubkey", + "did_get_metadata": "get_did_metadata", + "did_find_lost_did": "find_lost_did", + "cat_get_asset_id": "get_cat_asset_id", + "cat_get_name": "get_cat_name", + "cat_set_name": "set_cat_name", + "nft_mint_nft": "mint_nft", + "nft_add_uri": "add_uri_to_nft", + "nft_get_info": "get_nft_info", + "nft_transfer_nft": "transfer_nft", + "nft_count_nfts": "count_nfts", + "nft_get_nfts": "list_nfts", + "nft_get_by_did": "get_nft_wallet_by_did", + "nft_set_nft_did": "set_nft_did", + "nft_set_nft_status": "set_nft_status", + "nft_get_wallet_did": "get_nft_wallet_did", + "nft_get_wallets_with_dids": "get_nft_wallets_with_dids", + "nft_set_did_bulk": "set_nft_did_bulk", + "nft_transfer_bulk": "transfer_nft_bulk", +} + + +EndpointMethod = ( + Callable[ + ["WalletRpcClient", Streamable, TXConfig, tuple[Condition, ...], ConditionValidTimes], + Awaitable[Streamable | None], + ] + | Callable[["WalletRpcClient", Streamable], Awaitable[Streamable | None]] + | Callable[["WalletRpcClient"], Awaitable[Streamable | None]] ) -def parse_result_transactions(result: dict[str, Any]) -> dict[str, Any]: - result["transaction"] = TransactionRecord.from_json_dict(result["transaction"]) - result["transactions"] = [TransactionRecord.from_json_dict(tx) for tx in result["transactions"]] - if result["fee_transaction"]: - result["fee_transaction"] = TransactionRecord.from_json_dict(result["fee_transaction"]) - return result +def client_method_name(endpoint_name: str) -> str: + return CLIENT_METHOD_NAME_OVERRIDES.get(endpoint_name, endpoint_name) + + +def _make_endpoint_method(meta: WalletRpcMetadata) -> EndpointMethod: + endpoint_name = meta.endpoint_name + request_type = meta.request_type + response_type = meta.response_type + empty_request = request_type is Empty + empty_response = response_type is Empty + + if meta.tx_endpoint: + + async def tx_method( + self: WalletRpcClient, + request: Streamable, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = tuple(), + timelock_info: ConditionValidTimes = ConditionValidTimes(), + ) -> Streamable: + payload = request.json_serialize_for_transport( # type: ignore[attr-defined] + tx_config, extra_conditions, timelock_info + ) + result = await self.fetch(meta.endpoint_name, payload) + return json_deserialize_with_clvm_streamable(result, response_type) + + tx_method.__name__ = client_method_name(endpoint_name) + tx_method.__qualname__ = f"WalletRpcClient.{tx_method.__name__}" + return tx_method + + if empty_request: + + async def no_arg_method( + self: WalletRpcClient, + ) -> Streamable | None: + result = await self.fetch(meta.endpoint_name, {}) + if empty_response: + return None + return meta.response_type.from_json_dict(result) + + no_arg_method.__name__ = client_method_name(endpoint_name) + no_arg_method.__qualname__ = f"WalletRpcClient.{no_arg_method.__name__}" + return no_arg_method + + async def request_method( + self: WalletRpcClient, + request: Streamable, + ) -> Streamable | None: + result = await self.fetch(meta.endpoint_name, request.to_json_dict()) + if empty_response: + return None + return meta.response_type.from_json_dict(result) + + request_method.__name__ = client_method_name(endpoint_name) + request_method.__qualname__ = f"WalletRpcClient.{request_method.__name__}" + return request_method class WalletRpcClient(RpcClient): """ Client to Chia RPC, connects to a local wallet. Uses HTTP/JSON, and converts back from JSON into native python objects before returning. All api calls use POST requests. - Note that this is not the same as the peer protocol, or wallet protocol (which run Chia's - protocol on top of TCP), it's a separate protocol on top of HTTP that provides easy access - to the full node. + + Methods are generated at import time from WALLET_RPC_ENDPOINT_METADATA. See + wallet_rpc_client.pyi for the typed surface used by editors / type checkers. """ - # Key Management APIs - async def log_in(self, request: LogIn) -> LogInResponse: - return LogInResponse.from_json_dict(await self.fetch("log_in", request.to_json_dict())) - async def get_logged_in_fingerprint(self) -> GetLoggedInFingerprintResponse: - return GetLoggedInFingerprintResponse.from_json_dict(await self.fetch("get_logged_in_fingerprint", {})) +for _meta in WALLET_RPC_ENDPOINT_METADATA: + setattr(WalletRpcClient, client_method_name(_meta.endpoint_name), _make_endpoint_method(_meta)) - async def get_public_keys(self) -> GetPublicKeysResponse: - return GetPublicKeysResponse.from_json_dict(await self.fetch("get_public_keys", {})) - async def get_private_key(self, request: GetPrivateKey) -> GetPrivateKeyResponse: - return GetPrivateKeyResponse.from_json_dict(await self.fetch("get_private_key", request.to_json_dict())) - - async def generate_mnemonic(self) -> GenerateMnemonicResponse: - return GenerateMnemonicResponse.from_json_dict(await self.fetch("generate_mnemonic", {})) - - async def add_key(self, request: AddKey) -> AddKeyResponse: - return AddKeyResponse.from_json_dict(await self.fetch("add_key", request.to_json_dict())) - - async def delete_key(self, request: DeleteKey) -> None: - await self.fetch("delete_key", request.to_json_dict()) - - async def check_delete_key(self, request: CheckDeleteKey) -> CheckDeleteKeyResponse: - return CheckDeleteKeyResponse.from_json_dict(await self.fetch("check_delete_key", request.to_json_dict())) - - async def delete_all_keys(self) -> None: - await self.fetch("delete_all_keys", {}) - - # Wallet Node APIs - async def set_wallet_resync_on_startup(self, request: SetWalletResyncOnStartup) -> None: - await self.fetch("set_wallet_resync_on_startup", request.to_json_dict()) - - async def get_sync_status(self) -> GetSyncStatusResponse: - return GetSyncStatusResponse.from_json_dict(await self.fetch("get_sync_status", {})) - - async def get_height_info(self, request: GetHeightInfo) -> GetHeightInfoResponse: - return GetHeightInfoResponse.from_json_dict(await self.fetch("get_height_info", request.to_json_dict())) - - async def get_fee_estimate(self) -> GetFeeEstimateResponse: - return GetFeeEstimateResponse.from_json_dict(await self.fetch("get_fee_estimate", {})) - - async def get_full_node_peer_count(self) -> GetFullNodePeerCountResponse: - return GetFullNodePeerCountResponse.from_json_dict(await self.fetch("get_full_node_peer_count", {})) - - async def push_tx(self, request: PushTX) -> None: - await self.fetch("push_tx", request.to_json_dict()) - - async def push_transactions( - self, - request: PushTransactions, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> PushTransactionsResponse: - return PushTransactionsResponse.from_json_dict( - await self.fetch( - "push_transactions", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def get_timestamp_for_height(self, request: GetTimestampForHeight) -> GetTimestampForHeightResponse: - return GetTimestampForHeightResponse.from_json_dict( - await self.fetch("get_timestamp_for_height", request.to_json_dict()) - ) - - async def set_auto_claim(self, request: AutoClaimSettings) -> AutoClaimSettings: - return AutoClaimSettings.from_json_dict(await self.fetch("set_auto_claim", {**request.to_json_dict()})) - - async def get_auto_claim(self) -> AutoClaimSettings: - return AutoClaimSettings.from_json_dict(await self.fetch("get_auto_claim", {})) - - # Remote Wallet APIs - async def register_remote_coins(self, request: RegisterRemoteCoins) -> None: - await self.fetch("register_remote_coins", request.to_json_dict()) - - # Wallet Management APIs - async def get_wallets(self, request: GetWallets) -> GetWalletsResponse: - return GetWalletsResponse.from_json_dict(await self.fetch("get_wallets", request.to_json_dict())) - - # Wallet APIs - async def get_wallet_balance(self, request: GetWalletBalance) -> GetWalletBalanceResponse: - return GetWalletBalanceResponse.from_json_dict(await self.fetch("get_wallet_balance", request.to_json_dict())) - - async def get_wallet_balances(self, request: GetWalletBalances) -> GetWalletBalancesResponse: - return GetWalletBalancesResponse.from_json_dict(await self.fetch("get_wallet_balances", request.to_json_dict())) - - async def get_transaction(self, request: GetTransaction) -> GetTransactionResponse: - return GetTransactionResponse.from_json_dict(await self.fetch("get_transaction", request.to_json_dict())) - - async def get_transactions(self, request: GetTransactions) -> GetTransactionsResponse: - return GetTransactionsResponse.from_json_dict(await self.fetch("get_transactions", request.to_json_dict())) - - async def get_transaction_count(self, request: GetTransactionCount) -> GetTransactionCountResponse: - return GetTransactionCountResponse.from_json_dict( - await self.fetch("get_transaction_count", request.to_json_dict()) - ) - - async def get_next_address(self, request: GetNextAddress) -> GetNextAddressResponse: - return GetNextAddressResponse.from_json_dict(await self.fetch("get_next_address", request.to_json_dict())) - - async def create_new_wallet( - self, - request: CreateNewWallet, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> CreateNewWalletResponse: - return CreateNewWalletResponse.from_json_dict( - await self.fetch( - "create_new_wallet", - request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info), - ) - ) - - async def send_transaction( - self, - request: SendTransaction, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> SendTransactionResponse: - return SendTransactionResponse.from_json_dict( - await self.fetch( - "send_transaction", - request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info), - ) - ) - - async def send_transaction_multi( - self, - request: SendTransactionMulti, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> SendTransactionMultiResponse: - return SendTransactionMultiResponse.from_json_dict( - await self.fetch( - "send_transaction_multi", - request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info), - ) - ) - - async def spend_clawback_coins( - self, - request: SpendClawbackCoins, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> SpendClawbackCoinsResponse: - return SpendClawbackCoinsResponse.from_json_dict( - await self.fetch( - "spend_clawback_coins", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def delete_unconfirmed_transactions(self, request: DeleteUnconfirmedTransactions) -> None: - await self.fetch("delete_unconfirmed_transactions", request.to_json_dict()) - - async def get_current_derivation_index(self) -> GetCurrentDerivationIndexResponse: - return GetCurrentDerivationIndexResponse.from_json_dict(await self.fetch("get_current_derivation_index", {})) - - async def extend_derivation_index(self, request: ExtendDerivationIndex) -> ExtendDerivationIndexResponse: - return ExtendDerivationIndexResponse.from_json_dict( - await self.fetch("extend_derivation_index", request.to_json_dict()) - ) - - async def get_farmed_amount(self, request: GetFarmedAmount) -> GetFarmedAmountResponse: - return GetFarmedAmountResponse.from_json_dict(await self.fetch("get_farmed_amount", request.to_json_dict())) - - async def create_signed_transactions( - self, - request: CreateSignedTransaction, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> CreateSignedTransactionsResponse: - return CreateSignedTransactionsResponse.from_json_dict( - await self.fetch( - "create_signed_transaction", - request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info), - ) - ) - - async def select_coins(self, request: SelectCoins) -> SelectCoinsResponse: - return SelectCoinsResponse.from_json_dict(await self.fetch("select_coins", request.to_json_dict())) - - async def get_coin_records(self, request: GetCoinRecords) -> GetCoinRecordsResponse: - return GetCoinRecordsResponse.from_json_dict(await self.fetch("get_coin_records", request.to_json_dict())) - - async def get_spendable_coins(self, request: GetSpendableCoins) -> GetSpendableCoinsResponse: - return GetSpendableCoinsResponse.from_json_dict(await self.fetch("get_spendable_coins", request.to_json_dict())) - - async def get_coin_records_by_names(self, request: GetCoinRecordsByNames) -> GetCoinRecordsByNamesResponse: - return GetCoinRecordsByNamesResponse.from_json_dict( - await self.fetch("get_coin_records_by_names", request.to_json_dict()) - ) - - # DID wallet - async def get_did_id(self, request: DIDGetDID) -> DIDGetDIDResponse: - return DIDGetDIDResponse.from_json_dict(await self.fetch("did_get_did", request.to_json_dict())) - - async def get_did_info(self, request: DIDGetInfo) -> DIDGetInfoResponse: - return DIDGetInfoResponse.from_json_dict(await self.fetch("did_get_info", request.to_json_dict())) - - async def create_did_backup_file(self, request: DIDCreateBackupFile) -> DIDCreateBackupFileResponse: - return DIDCreateBackupFileResponse.from_json_dict( - await self.fetch("did_create_backup_file", request.to_json_dict()) - ) - - async def did_message_spend( - self, - request: DIDMessageSpend, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> DIDMessageSpendResponse: - return DIDMessageSpendResponse.from_json_dict( - await self.fetch( - "did_message_spend", - request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info), - ) - ) - - async def update_did_metadata( - self, - request: DIDUpdateMetadata, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> DIDUpdateMetadataResponse: - return DIDUpdateMetadataResponse.from_json_dict( - await self.fetch( - "did_update_metadata", - request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info), - ) - ) - - async def get_did_pubkey(self, request: DIDGetPubkey) -> DIDGetPubkeyResponse: - return DIDGetPubkeyResponse.from_json_dict(await self.fetch("did_get_pubkey", request.to_json_dict())) - - async def get_did_metadata(self, request: DIDGetMetadata) -> DIDGetMetadataResponse: - return DIDGetMetadataResponse.from_json_dict(await self.fetch("did_get_metadata", request.to_json_dict())) - - async def find_lost_did(self, request: DIDFindLostDID) -> DIDFindLostDIDResponse: - return DIDFindLostDIDResponse.from_json_dict(await self.fetch("did_find_lost_did", request.to_json_dict())) - - async def create_new_did_wallet_from_recovery(self, filename: str) -> dict[str, Any]: - request = {"wallet_type": "did_wallet", "did_type": "recovery", "filename": filename} - response = await self.fetch("create_new_wallet", request) - return response - - async def did_get_current_coin_info(self, request: DIDGetCurrentCoinInfo) -> DIDGetCurrentCoinInfoResponse: - return DIDGetCurrentCoinInfoResponse.from_json_dict( - await self.fetch("did_get_current_coin_info", request.to_json_dict()) - ) - - async def did_transfer_did( - self, - request: DIDTransferDID, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> DIDTransferDIDResponse: - return DIDTransferDIDResponse.from_json_dict( - await self.fetch( - "did_transfer_did", - request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info), - ) - ) - - async def did_set_wallet_name(self, request: DIDSetWalletName) -> DIDSetWalletNameResponse: - return DIDSetWalletNameResponse.from_json_dict(await self.fetch("did_set_wallet_name", request.to_json_dict())) - - async def did_get_wallet_name(self, request: DIDGetWalletName) -> DIDGetWalletNameResponse: - return DIDGetWalletNameResponse.from_json_dict(await self.fetch("did_get_wallet_name", request.to_json_dict())) - - async def pw_self_pool( - self, - request: PWSelfPool, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> PWSelfPoolResponse: - return PWSelfPoolResponse.from_json_dict( - await self.fetch( - "pw_self_pool", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def pw_join_pool( - self, - request: PWJoinPool, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> PWJoinPoolResponse: - return PWJoinPoolResponse.from_json_dict( - await self.fetch( - "pw_join_pool", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def pw_absorb_rewards( - self, - request: PWAbsorbRewards, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> PWAbsorbRewardsResponse: - return PWAbsorbRewardsResponse.from_json_dict( - await self.fetch( - "pw_absorb_rewards", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def pw_status(self, request: PWStatus) -> PWStatusResponse: - return PWStatusResponse.from_json_dict(await self.fetch("pw_status", request.to_json_dict())) - - # CATS - async def get_cat_asset_id(self, request: CATGetAssetID) -> CATGetAssetIDResponse: - return CATGetAssetIDResponse.from_json_dict(await self.fetch("cat_get_asset_id", request.to_json_dict())) - - async def get_stray_cats(self) -> GetStrayCATsResponse: - return GetStrayCATsResponse.from_json_dict(await self.fetch("get_stray_cats", {})) - - async def cat_asset_id_to_name(self, request: CATAssetIDToName) -> CATAssetIDToNameResponse: - return CATAssetIDToNameResponse.from_json_dict(await self.fetch("cat_asset_id_to_name", request.to_json_dict())) - - async def get_cat_name(self, request: CATGetName) -> CATGetNameResponse: - return CATGetNameResponse.from_json_dict(await self.fetch("cat_get_name", request.to_json_dict())) - - async def set_cat_name(self, request: CATSetName) -> CATSetNameResponse: - return CATSetNameResponse.from_json_dict(await self.fetch("cat_set_name", request.to_json_dict())) - - async def cat_spend( - self, - request: CATSpend, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> CATSpendResponse: - return CATSpendResponse.from_json_dict( - await self.fetch( - "cat_spend", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - # Offers - async def create_offer_for_ids( - self, - request: CreateOfferForIDs, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> CreateOfferForIDsResponse: - response = await self.fetch( - "create_offer_for_ids", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - return CreateOfferForIDsResponse.from_json_dict(response) - - async def get_offer_summary(self, request: GetOfferSummary) -> GetOfferSummaryResponse: - return GetOfferSummaryResponse.from_json_dict(await self.fetch("get_offer_summary", request.to_json_dict())) - - async def check_offer_validity(self, request: CheckOfferValidity) -> CheckOfferValidityResponse: - return CheckOfferValidityResponse.from_json_dict( - await self.fetch("check_offer_validity", request.to_json_dict()) - ) - - async def take_offer( - self, - request: TakeOffer, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> TakeOfferResponse: - return TakeOfferResponse.from_json_dict( - await self.fetch( - "take_offer", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def get_offer(self, request: GetOffer) -> GetOfferResponse: - return GetOfferResponse.from_json_dict(await self.fetch("get_offer", request.to_json_dict())) - - async def get_all_offers(self, request: GetAllOffers) -> GetAllOffersResponse: - return GetAllOffersResponse.from_json_dict(await self.fetch("get_all_offers", request.to_json_dict())) - - async def get_offers_count(self) -> GetOffersCountResponse: - return GetOffersCountResponse.from_json_dict(await self.fetch("get_offers_count", {})) - - async def cancel_offer( - self, - request: CancelOffer, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> CancelOfferResponse: - return CancelOfferResponse.from_json_dict( - await self.fetch( - "cancel_offer", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def cancel_offers( - self, - request: CancelOffers, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> CancelOffersResponse: - return CancelOffersResponse.from_json_dict( - await self.fetch( - "cancel_offers", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def get_cat_list(self) -> GetCATListResponse: - return GetCATListResponse.from_json_dict(await self.fetch("get_cat_list", {})) - - # NFT wallet - async def mint_nft( - self, - request: NFTMintNFTRequest, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> NFTMintNFTResponse: - return NFTMintNFTResponse.from_json_dict( - await self.fetch( - "nft_mint_nft", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def add_uri_to_nft( - self, - request: NFTAddURI, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> NFTAddURIResponse: - return NFTAddURIResponse.from_json_dict( - await self.fetch( - "nft_add_uri", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def nft_calculate_royalties( - self, - request: NFTCalculateRoyalties, - ) -> NFTCalculateRoyaltiesResponse: - return NFTCalculateRoyaltiesResponse.from_json_dict( - await self.fetch("nft_calculate_royalties", request.to_json_dict()) - ) - - async def get_nft_info(self, request: NFTGetInfo) -> NFTGetInfoResponse: - return NFTGetInfoResponse.from_json_dict(await self.fetch("nft_get_info", request.to_json_dict())) - - async def transfer_nft( - self, - request: NFTTransferNFT, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> NFTTransferNFTResponse: - return NFTTransferNFTResponse.from_json_dict( - await self.fetch( - "nft_transfer_nft", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def count_nfts(self, request: NFTCountNFTs) -> NFTCountNFTsResponse: - return NFTCountNFTsResponse.from_json_dict(await self.fetch("nft_count_nfts", request.to_json_dict())) - - async def list_nfts(self, request: NFTGetNFTs) -> NFTGetNFTsResponse: - return NFTGetNFTsResponse.from_json_dict(await self.fetch("nft_get_nfts", request.to_json_dict())) - - async def get_nft_wallet_by_did(self, request: NFTGetByDID) -> NFTGetByDIDResponse: - return NFTGetByDIDResponse.from_json_dict(await self.fetch("nft_get_by_did", request.to_json_dict())) - - async def set_nft_did( - self, - request: NFTSetNFTDID, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> NFTSetNFTDIDResponse: - return NFTSetNFTDIDResponse.from_json_dict( - await self.fetch( - "nft_set_nft_did", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def set_nft_status(self, request: NFTSetNFTStatus) -> None: - await self.fetch("nft_set_nft_status", request.to_json_dict()) - - async def get_nft_wallet_did(self, request: NFTGetWalletDID) -> NFTGetWalletDIDResponse: - return NFTGetWalletDIDResponse.from_json_dict(await self.fetch("nft_get_wallet_did", request.to_json_dict())) - - async def get_nft_wallets_with_dids(self) -> NFTGetWalletsWithDIDsResponse: - return NFTGetWalletsWithDIDsResponse.from_json_dict(await self.fetch("nft_get_wallets_with_dids", {})) - - async def nft_mint_bulk( - self, - request: NFTMintBulk, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> NFTMintBulkResponse: - return NFTMintBulkResponse.from_json_dict( - await self.fetch( - "nft_mint_bulk", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def set_nft_did_bulk( - self, - request: NFTSetDIDBulk, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> NFTSetDIDBulkResponse: - return NFTSetDIDBulkResponse.from_json_dict( - await self.fetch( - "nft_set_did_bulk", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def transfer_nft_bulk( - self, - request: NFTTransferBulk, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> NFTTransferBulkResponse: - return NFTTransferBulkResponse.from_json_dict( - await self.fetch( - "nft_transfer_bulk", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - # DataLayer - async def create_new_dl( - self, - request: CreateNewDL, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> CreateNewDLResponse: - return CreateNewDLResponse.from_json_dict( - await self.fetch( - "create_new_dl", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def dl_track_new(self, request: DLTrackNew) -> None: - await self.fetch("dl_track_new", request.to_json_dict()) - - async def dl_stop_tracking(self, request: DLStopTracking) -> None: - await self.fetch("dl_stop_tracking", request.to_json_dict()) - - async def dl_latest_singleton(self, request: DLLatestSingleton) -> DLLatestSingletonResponse: - return DLLatestSingletonResponse.from_json_dict(await self.fetch("dl_latest_singleton", request.to_json_dict())) - - async def dl_singletons_by_root(self, request: DLSingletonsByRoot) -> DLSingletonsByRootResponse: - return DLSingletonsByRootResponse.from_json_dict( - await self.fetch("dl_singletons_by_root", request.to_json_dict()) - ) - - async def dl_update_root( - self, - request: DLUpdateRoot, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> DLUpdateRootResponse: - return DLUpdateRootResponse.from_json_dict( - await self.fetch( - "dl_update_root", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def dl_update_multiple( - self, - request: DLUpdateMultiple, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> DLUpdateMultipleResponse: - return DLUpdateMultipleResponse.from_json_dict( - await self.fetch( - "dl_update_multiple", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def dl_history(self, request: DLHistory) -> DLHistoryResponse: - return DLHistoryResponse.from_json_dict(await self.fetch("dl_history", request.to_json_dict())) - - async def dl_owned_singletons(self) -> DLOwnedSingletonsResponse: - return DLOwnedSingletonsResponse.from_json_dict(await self.fetch("dl_owned_singletons", {})) - - async def dl_get_mirrors(self, request: DLGetMirrors) -> DLGetMirrorsResponse: - return DLGetMirrorsResponse.from_json_dict(await self.fetch("dl_get_mirrors", request.to_json_dict())) - - async def dl_new_mirror( - self, - request: DLNewMirror, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> DLNewMirrorResponse: - return DLNewMirrorResponse.from_json_dict( - await self.fetch( - "dl_new_mirror", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def dl_delete_mirror( - self, - request: DLDeleteMirror, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> DLDeleteMirrorResponse: - return DLDeleteMirrorResponse.from_json_dict( - await self.fetch( - "dl_delete_mirror", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def dl_verify_proof(self, request: DLProof) -> VerifyProofResponse: - return VerifyProofResponse.from_json_dict(await self.fetch("dl_verify_proof", request.to_json_dict())) - - async def get_notifications(self, request: GetNotifications) -> GetNotificationsResponse: - response = await self.fetch("get_notifications", request.to_json_dict()) - return json_deserialize_with_clvm_streamable(response, GetNotificationsResponse) - - async def delete_notifications(self, request: DeleteNotifications) -> None: - await self.fetch("delete_notifications", request.to_json_dict()) - - async def send_notification( - self, - request: SendNotification, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> SendNotificationResponse: - return SendNotificationResponse.from_json_dict( - await self.fetch( - "send_notification", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def sign_message_by_address(self, request: SignMessageByAddress) -> SignMessageByAddressResponse: - return SignMessageByAddressResponse.from_json_dict( - await self.fetch("sign_message_by_address", request.to_json_dict()) - ) - - async def sign_message_by_id(self, request: SignMessageByID) -> SignMessageByIDResponse: - return SignMessageByIDResponse.from_json_dict(await self.fetch("sign_message_by_id", request.to_json_dict())) - - async def verify_signature(self, request: VerifySignature) -> VerifySignatureResponse: - return VerifySignatureResponse.from_json_dict(await self.fetch("verify_signature", {**request.to_json_dict()})) - - async def get_transaction_memo(self, request: GetTransactionMemo) -> GetTransactionMemoResponse: - return GetTransactionMemoResponse.from_json_dict( - await self.fetch("get_transaction_memo", {**request.to_json_dict()}) - ) - - async def vc_mint( - self, - request: VCMint, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> VCMintResponse: - return VCMintResponse.from_json_dict( - await self.fetch( - "vc_mint", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def vc_get(self, request: VCGet) -> VCGetResponse: - return VCGetResponse.from_json_dict(await self.fetch("vc_get", request.to_json_dict())) - - async def vc_get_list(self, request: VCGetList) -> VCGetListResponse: - return VCGetListResponse.from_json_dict(await self.fetch("vc_get_list", request.to_json_dict())) - - async def vc_spend( - self, - request: VCSpend, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> VCSpendResponse: - return VCSpendResponse.from_json_dict( - await self.fetch( - "vc_spend", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def vc_add_proofs(self, request: VCAddProofs) -> None: - await self.fetch("vc_add_proofs", request.to_json_dict()) - - async def vc_get_proofs_for_root(self, request: VCGetProofsForRoot) -> VCGetProofsForRootResponse: - return VCGetProofsForRootResponse.from_json_dict( - await self.fetch("vc_get_proofs_for_root", request.to_json_dict()) - ) - - async def vc_revoke( - self, - request: VCRevoke, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> VCRevokeResponse: - return VCRevokeResponse.from_json_dict( - await self.fetch( - "vc_revoke", request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def crcat_approve_pending( - self, - request: CRCATApprovePending, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> CRCATApprovePendingResponse: - return CRCATApprovePendingResponse.from_json_dict( - await self.fetch( - "crcat_approve_pending", - request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info), - ) - ) - - async def gather_signing_info( - self, - args: GatherSigningInfo, - ) -> GatherSigningInfoResponse: - return json_deserialize_with_clvm_streamable( - await self.fetch( - "gather_signing_info", - args.to_json_dict(), - ), - GatherSigningInfoResponse, - ) - - async def apply_signatures( - self, - args: ApplySignatures, - ) -> ApplySignaturesResponse: - return json_deserialize_with_clvm_streamable( - await self.fetch( - "apply_signatures", - args.to_json_dict(), - ), - ApplySignaturesResponse, - ) - - async def submit_transactions( - self, - args: SubmitTransactions, - ) -> SubmitTransactionsResponse: - return json_deserialize_with_clvm_streamable( - await self.fetch( - "submit_transactions", - args.to_json_dict(), - ), - SubmitTransactionsResponse, - ) - - async def execute_signing_instructions( - self, - args: ExecuteSigningInstructions, - ) -> ExecuteSigningInstructionsResponse: - return ExecuteSigningInstructionsResponse.from_json_dict( - await self.fetch("execute_signing_instructions", args.to_json_dict()) - ) - - async def split_coins( - self, - args: SplitCoins, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> SplitCoinsResponse: - return SplitCoinsResponse.from_json_dict( - await self.fetch( - "split_coins", args.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) - - async def combine_coins( - self, - args: CombineCoins, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> CombineCoinsResponse: - return CombineCoinsResponse.from_json_dict( - await self.fetch( - "combine_coins", args.json_serialize_for_transport(tx_config, extra_conditions, timelock_info) - ) - ) +__all__ = [ + "CLIENT_METHOD_NAME_OVERRIDES", + "WalletRpcClient", + "client_method_name", +] diff --git a/chia/wallet/wallet_rpc_client.pyi b/chia/wallet/wallet_rpc_client.pyi new file mode 100644 index 0000000000..30b0782d96 --- /dev/null +++ b/chia/wallet/wallet_rpc_client.pyi @@ -0,0 +1,565 @@ +# This file is generated by tools/generate_wallet_rpc_client_stub.py +from chia.data_layer.data_layer_util import DLProof, VerifyProofResponse +from chia.rpc.rpc_client import RpcClient +from chia.wallet import wallet_request_types +from chia.wallet.conditions import Condition, ConditionValidTimes +from chia.wallet.puzzles.clawback.metadata import AutoClaimSettings +from chia.wallet.util.tx_config import TXConfig + +def client_method_name(endpoint_name: str) -> str: ... + +class WalletRpcClient(RpcClient): + async def log_in( + self, + request: wallet_request_types.LogIn, + ) -> wallet_request_types.LogInResponse: ... + async def get_logged_in_fingerprint(self) -> wallet_request_types.GetLoggedInFingerprintResponse: ... + async def get_public_keys(self) -> wallet_request_types.GetPublicKeysResponse: ... + async def get_private_key( + self, + request: wallet_request_types.GetPrivateKey, + ) -> wallet_request_types.GetPrivateKeyResponse: ... + async def generate_mnemonic(self) -> wallet_request_types.GenerateMnemonicResponse: ... + async def add_key( + self, + request: wallet_request_types.AddKey, + ) -> wallet_request_types.AddKeyResponse: ... + async def delete_key( + self, + request: wallet_request_types.DeleteKey, + ) -> None: ... + async def check_delete_key( + self, + request: wallet_request_types.CheckDeleteKey, + ) -> wallet_request_types.CheckDeleteKeyResponse: ... + async def delete_all_keys(self) -> None: ... + async def set_wallet_resync_on_startup( + self, + request: wallet_request_types.SetWalletResyncOnStartup, + ) -> None: ... + async def get_sync_status(self) -> wallet_request_types.GetSyncStatusResponse: ... + async def get_full_node_peer_count(self) -> wallet_request_types.GetFullNodePeerCountResponse: ... + async def get_height_info( + self, + request: wallet_request_types.GetHeightInfo, + ) -> wallet_request_types.GetHeightInfoResponse: ... + async def push_tx( + self, + request: wallet_request_types.PushTX, + ) -> None: ... + async def push_transactions( + self, + request: wallet_request_types.PushTransactions, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.PushTransactionsResponse: ... + async def get_timestamp_for_height( + self, + request: wallet_request_types.GetTimestampForHeight, + ) -> wallet_request_types.GetTimestampForHeightResponse: ... + async def get_fee_estimate(self) -> wallet_request_types.GetFeeEstimateResponse: ... + async def set_auto_claim( + self, + request: AutoClaimSettings, + ) -> AutoClaimSettings: ... + async def get_auto_claim(self) -> AutoClaimSettings: ... + async def get_wallets( + self, + request: wallet_request_types.GetWallets, + ) -> wallet_request_types.GetWalletsResponse: ... + async def create_new_wallet( + self, + request: wallet_request_types.CreateNewWallet, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.CreateNewWalletResponse: ... + async def get_wallet_balance( + self, + request: wallet_request_types.GetWalletBalance, + ) -> wallet_request_types.GetWalletBalanceResponse: ... + async def get_wallet_balances( + self, + request: wallet_request_types.GetWalletBalances, + ) -> wallet_request_types.GetWalletBalancesResponse: ... + async def get_transaction( + self, + request: wallet_request_types.GetTransaction, + ) -> wallet_request_types.GetTransactionResponse: ... + async def get_transactions( + self, + request: wallet_request_types.GetTransactions, + ) -> wallet_request_types.GetTransactionsResponse: ... + async def get_transaction_count( + self, + request: wallet_request_types.GetTransactionCount, + ) -> wallet_request_types.GetTransactionCountResponse: ... + async def get_next_address( + self, + request: wallet_request_types.GetNextAddress, + ) -> wallet_request_types.GetNextAddressResponse: ... + async def send_transaction( + self, + request: wallet_request_types.SendTransaction, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.SendTransactionResponse: ... + async def send_transaction_multi( + self, + request: wallet_request_types.SendTransactionMulti, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.SendTransactionMultiResponse: ... + async def spend_clawback_coins( + self, + request: wallet_request_types.SpendClawbackCoins, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.SpendClawbackCoinsResponse: ... + async def get_farmed_amount( + self, + request: wallet_request_types.GetFarmedAmount, + ) -> wallet_request_types.GetFarmedAmountResponse: ... + async def create_signed_transactions( + self, + request: wallet_request_types.CreateSignedTransaction, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.CreateSignedTransactionsResponse: ... + async def delete_unconfirmed_transactions( + self, + request: wallet_request_types.DeleteUnconfirmedTransactions, + ) -> None: ... + async def select_coins( + self, + request: wallet_request_types.SelectCoins, + ) -> wallet_request_types.SelectCoinsResponse: ... + async def get_spendable_coins( + self, + request: wallet_request_types.GetSpendableCoins, + ) -> wallet_request_types.GetSpendableCoinsResponse: ... + async def get_coin_records_by_names( + self, + request: wallet_request_types.GetCoinRecordsByNames, + ) -> wallet_request_types.GetCoinRecordsByNamesResponse: ... + async def get_puzzle_and_solution( + self, + request: wallet_request_types.GetPuzzleAndSolution, + ) -> wallet_request_types.GetPuzzleAndSolutionResponse: ... + async def get_current_derivation_index(self) -> wallet_request_types.GetCurrentDerivationIndexResponse: ... + async def extend_derivation_index( + self, + request: wallet_request_types.ExtendDerivationIndex, + ) -> wallet_request_types.ExtendDerivationIndexResponse: ... + async def get_notifications( + self, + request: wallet_request_types.GetNotifications, + ) -> wallet_request_types.GetNotificationsResponse: ... + async def delete_notifications( + self, + request: wallet_request_types.DeleteNotifications, + ) -> None: ... + async def send_notification( + self, + request: wallet_request_types.SendNotification, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.SendNotificationResponse: ... + async def sign_message_by_address( + self, + request: wallet_request_types.SignMessageByAddress, + ) -> wallet_request_types.SignMessageByAddressResponse: ... + async def sign_message_by_id( + self, + request: wallet_request_types.SignMessageByID, + ) -> wallet_request_types.SignMessageByIDResponse: ... + async def verify_signature( + self, + request: wallet_request_types.VerifySignature, + ) -> wallet_request_types.VerifySignatureResponse: ... + async def get_transaction_memo( + self, + request: wallet_request_types.GetTransactionMemo, + ) -> wallet_request_types.GetTransactionMemoResponse: ... + async def split_coins( + self, + request: wallet_request_types.SplitCoins, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.SplitCoinsResponse: ... + async def combine_coins( + self, + request: wallet_request_types.CombineCoins, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.CombineCoinsResponse: ... + async def set_cat_name( + self, + request: wallet_request_types.CATSetName, + ) -> wallet_request_types.CATSetNameResponse: ... + async def cat_asset_id_to_name( + self, + request: wallet_request_types.CATAssetIDToName, + ) -> wallet_request_types.CATAssetIDToNameResponse: ... + async def get_cat_name( + self, + request: wallet_request_types.CATGetName, + ) -> wallet_request_types.CATGetNameResponse: ... + async def get_stray_cats(self) -> wallet_request_types.GetStrayCATsResponse: ... + async def cat_spend( + self, + request: wallet_request_types.CATSpend, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.CATSpendResponse: ... + async def get_cat_asset_id( + self, + request: wallet_request_types.CATGetAssetID, + ) -> wallet_request_types.CATGetAssetIDResponse: ... + async def create_offer_for_ids( + self, + request: wallet_request_types.CreateOfferForIDs, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.CreateOfferForIDsResponse: ... + async def get_offer_summary( + self, + request: wallet_request_types.GetOfferSummary, + ) -> wallet_request_types.GetOfferSummaryResponse: ... + async def check_offer_validity( + self, + request: wallet_request_types.CheckOfferValidity, + ) -> wallet_request_types.CheckOfferValidityResponse: ... + async def take_offer( + self, + request: wallet_request_types.TakeOffer, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.TakeOfferResponse: ... + async def get_offer( + self, + request: wallet_request_types.GetOffer, + ) -> wallet_request_types.GetOfferResponse: ... + async def get_all_offers( + self, + request: wallet_request_types.GetAllOffers, + ) -> wallet_request_types.GetAllOffersResponse: ... + async def get_offers_count(self) -> wallet_request_types.GetOffersCountResponse: ... + async def cancel_offer( + self, + request: wallet_request_types.CancelOffer, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.CancelOfferResponse: ... + async def cancel_offers( + self, + request: wallet_request_types.CancelOffers, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.CancelOffersResponse: ... + async def get_cat_list(self) -> wallet_request_types.GetCATListResponse: ... + async def did_set_wallet_name( + self, + request: wallet_request_types.DIDSetWalletName, + ) -> wallet_request_types.DIDSetWalletNameResponse: ... + async def did_get_wallet_name( + self, + request: wallet_request_types.DIDGetWalletName, + ) -> wallet_request_types.DIDGetWalletNameResponse: ... + async def update_did_metadata( + self, + request: wallet_request_types.DIDUpdateMetadata, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.DIDUpdateMetadataResponse: ... + async def get_did_pubkey( + self, + request: wallet_request_types.DIDGetPubkey, + ) -> wallet_request_types.DIDGetPubkeyResponse: ... + async def get_did_id( + self, + request: wallet_request_types.DIDGetDID, + ) -> wallet_request_types.DIDGetDIDResponse: ... + async def get_did_metadata( + self, + request: wallet_request_types.DIDGetMetadata, + ) -> wallet_request_types.DIDGetMetadataResponse: ... + async def did_get_current_coin_info( + self, + request: wallet_request_types.DIDGetCurrentCoinInfo, + ) -> wallet_request_types.DIDGetCurrentCoinInfoResponse: ... + async def create_did_backup_file( + self, + request: wallet_request_types.DIDCreateBackupFile, + ) -> wallet_request_types.DIDCreateBackupFileResponse: ... + async def did_transfer_did( + self, + request: wallet_request_types.DIDTransferDID, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.DIDTransferDIDResponse: ... + async def did_message_spend( + self, + request: wallet_request_types.DIDMessageSpend, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.DIDMessageSpendResponse: ... + async def get_did_info( + self, + request: wallet_request_types.DIDGetInfo, + ) -> wallet_request_types.DIDGetInfoResponse: ... + async def find_lost_did( + self, + request: wallet_request_types.DIDFindLostDID, + ) -> wallet_request_types.DIDFindLostDIDResponse: ... + async def mint_nft( + self, + request: wallet_request_types.NFTMintNFTRequest, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.NFTMintNFTResponse: ... + async def count_nfts( + self, + request: wallet_request_types.NFTCountNFTs, + ) -> wallet_request_types.NFTCountNFTsResponse: ... + async def list_nfts( + self, + request: wallet_request_types.NFTGetNFTs, + ) -> wallet_request_types.NFTGetNFTsResponse: ... + async def get_nft_wallet_by_did( + self, + request: wallet_request_types.NFTGetByDID, + ) -> wallet_request_types.NFTGetByDIDResponse: ... + async def set_nft_did( + self, + request: wallet_request_types.NFTSetNFTDID, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.NFTSetNFTDIDResponse: ... + async def set_nft_status( + self, + request: wallet_request_types.NFTSetNFTStatus, + ) -> None: ... + async def get_nft_wallet_did( + self, + request: wallet_request_types.NFTGetWalletDID, + ) -> wallet_request_types.NFTGetWalletDIDResponse: ... + async def get_nft_wallets_with_dids(self) -> wallet_request_types.NFTGetWalletsWithDIDsResponse: ... + async def get_nft_info( + self, + request: wallet_request_types.NFTGetInfo, + ) -> wallet_request_types.NFTGetInfoResponse: ... + async def transfer_nft( + self, + request: wallet_request_types.NFTTransferNFT, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.NFTTransferNFTResponse: ... + async def add_uri_to_nft( + self, + request: wallet_request_types.NFTAddURI, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.NFTAddURIResponse: ... + async def nft_calculate_royalties( + self, + request: wallet_request_types.NFTCalculateRoyalties, + ) -> wallet_request_types.NFTCalculateRoyaltiesResponse: ... + async def nft_mint_bulk( + self, + request: wallet_request_types.NFTMintBulk, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.NFTMintBulkResponse: ... + async def set_nft_did_bulk( + self, + request: wallet_request_types.NFTSetDIDBulk, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.NFTSetDIDBulkResponse: ... + async def transfer_nft_bulk( + self, + request: wallet_request_types.NFTTransferBulk, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.NFTTransferBulkResponse: ... + async def register_remote_coins( + self, + request: wallet_request_types.RegisterRemoteCoins, + ) -> None: ... + async def get_coin_records( + self, + request: wallet_request_types.GetCoinRecords, + ) -> wallet_request_types.GetCoinRecordsResponse: ... + async def pw_join_pool( + self, + request: wallet_request_types.PWJoinPool, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.PWJoinPoolResponse: ... + async def pw_self_pool( + self, + request: wallet_request_types.PWSelfPool, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.PWSelfPoolResponse: ... + async def pw_absorb_rewards( + self, + request: wallet_request_types.PWAbsorbRewards, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.PWAbsorbRewardsResponse: ... + async def pw_status( + self, + request: wallet_request_types.PWStatus, + ) -> wallet_request_types.PWStatusResponse: ... + async def create_new_dl( + self, + request: wallet_request_types.CreateNewDL, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.CreateNewDLResponse: ... + async def dl_track_new( + self, + request: wallet_request_types.DLTrackNew, + ) -> None: ... + async def dl_stop_tracking( + self, + request: wallet_request_types.DLStopTracking, + ) -> None: ... + async def dl_latest_singleton( + self, + request: wallet_request_types.DLLatestSingleton, + ) -> wallet_request_types.DLLatestSingletonResponse: ... + async def dl_singletons_by_root( + self, + request: wallet_request_types.DLSingletonsByRoot, + ) -> wallet_request_types.DLSingletonsByRootResponse: ... + async def dl_update_root( + self, + request: wallet_request_types.DLUpdateRoot, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.DLUpdateRootResponse: ... + async def dl_update_multiple( + self, + request: wallet_request_types.DLUpdateMultiple, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.DLUpdateMultipleResponse: ... + async def dl_history( + self, + request: wallet_request_types.DLHistory, + ) -> wallet_request_types.DLHistoryResponse: ... + async def dl_owned_singletons(self) -> wallet_request_types.DLOwnedSingletonsResponse: ... + async def dl_get_mirrors( + self, + request: wallet_request_types.DLGetMirrors, + ) -> wallet_request_types.DLGetMirrorsResponse: ... + async def dl_new_mirror( + self, + request: wallet_request_types.DLNewMirror, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.DLNewMirrorResponse: ... + async def dl_delete_mirror( + self, + request: wallet_request_types.DLDeleteMirror, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.DLDeleteMirrorResponse: ... + async def dl_verify_proof( + self, + request: DLProof, + ) -> VerifyProofResponse: ... + async def vc_mint( + self, + request: wallet_request_types.VCMint, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.VCMintResponse: ... + async def vc_get( + self, + request: wallet_request_types.VCGet, + ) -> wallet_request_types.VCGetResponse: ... + async def vc_get_list( + self, + request: wallet_request_types.VCGetList, + ) -> wallet_request_types.VCGetListResponse: ... + async def vc_spend( + self, + request: wallet_request_types.VCSpend, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.VCSpendResponse: ... + async def vc_add_proofs( + self, + request: wallet_request_types.VCAddProofs, + ) -> None: ... + async def vc_get_proofs_for_root( + self, + request: wallet_request_types.VCGetProofsForRoot, + ) -> wallet_request_types.VCGetProofsForRootResponse: ... + async def vc_revoke( + self, + request: wallet_request_types.VCRevoke, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.VCRevokeResponse: ... + async def crcat_approve_pending( + self, + request: wallet_request_types.CRCATApprovePending, + tx_config: TXConfig, + extra_conditions: tuple[Condition, ...] = ..., + timelock_info: ConditionValidTimes = ..., + ) -> wallet_request_types.CRCATApprovePendingResponse: ... + async def gather_signing_info( + self, + request: wallet_request_types.GatherSigningInfo, + ) -> wallet_request_types.GatherSigningInfoResponse: ... + async def apply_signatures( + self, + request: wallet_request_types.ApplySignatures, + ) -> wallet_request_types.ApplySignaturesResponse: ... + async def submit_transactions( + self, + request: wallet_request_types.SubmitTransactions, + ) -> wallet_request_types.SubmitTransactionsResponse: ... + async def execute_signing_instructions( + self, + request: wallet_request_types.ExecuteSigningInstructions, + ) -> wallet_request_types.ExecuteSigningInstructionsResponse: ... diff --git a/chia/wallet/wallet_rpc_metadata.py b/chia/wallet/wallet_rpc_metadata.py new file mode 100644 index 0000000000..376977f2f1 --- /dev/null +++ b/chia/wallet/wallet_rpc_metadata.py @@ -0,0 +1,724 @@ +from __future__ import annotations + +from dataclasses import dataclass + +from chia.data_layer.data_layer_util import DLProof, VerifyProofResponse +from chia.util.streamable import Streamable +from chia.wallet import wallet_request_types +from chia.wallet.puzzles.clawback.metadata import AutoClaimSettings + + +@dataclass(frozen=True, kw_only=True) +class RpcMetadata: + endpoint_name: str + request_type: type[Streamable] + response_type: type[Streamable] + + +@dataclass(frozen=True, kw_only=True) +class WalletRpcMetadata(RpcMetadata): + tx_endpoint: bool = False + auto_push: bool = False + auto_merge_spends: bool = True + + def __post_init__(self) -> None: + if self.tx_endpoint and not issubclass(self.request_type, wallet_request_types.TransactionEndpointRequest): + raise TypeError("tx_endpoint request type must subclass TransactionEndpointRequest") + if self.tx_endpoint and not issubclass(self.response_type, wallet_request_types.TransactionEndpointResponse): + raise TypeError("tx_endpoint response type must subclass TransactionEndpointResponse") + + +WALLET_RPC_ENDPOINT_METADATA: list[WalletRpcMetadata] = [ + # Key management + WalletRpcMetadata( + endpoint_name="log_in", + request_type=wallet_request_types.LogIn, + response_type=wallet_request_types.LogInResponse, + ), + WalletRpcMetadata( + endpoint_name="get_logged_in_fingerprint", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.GetLoggedInFingerprintResponse, + ), + WalletRpcMetadata( + endpoint_name="get_public_keys", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.GetPublicKeysResponse, + ), + WalletRpcMetadata( + endpoint_name="get_private_key", + request_type=wallet_request_types.GetPrivateKey, + response_type=wallet_request_types.GetPrivateKeyResponse, + ), + WalletRpcMetadata( + endpoint_name="generate_mnemonic", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.GenerateMnemonicResponse, + ), + WalletRpcMetadata( + endpoint_name="add_key", + request_type=wallet_request_types.AddKey, + response_type=wallet_request_types.AddKeyResponse, + ), + WalletRpcMetadata( + endpoint_name="delete_key", + request_type=wallet_request_types.DeleteKey, + response_type=wallet_request_types.Empty, + ), + WalletRpcMetadata( + endpoint_name="check_delete_key", + request_type=wallet_request_types.CheckDeleteKey, + response_type=wallet_request_types.CheckDeleteKeyResponse, + ), + WalletRpcMetadata( + endpoint_name="delete_all_keys", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.Empty, + ), + # Wallet node + WalletRpcMetadata( + endpoint_name="set_wallet_resync_on_startup", + request_type=wallet_request_types.SetWalletResyncOnStartup, + response_type=wallet_request_types.Empty, + ), + WalletRpcMetadata( + endpoint_name="get_sync_status", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.GetSyncStatusResponse, + ), + WalletRpcMetadata( + endpoint_name="get_full_node_peer_count", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.GetFullNodePeerCountResponse, + ), + WalletRpcMetadata( + endpoint_name="get_height_info", + request_type=wallet_request_types.GetHeightInfo, + response_type=wallet_request_types.GetHeightInfoResponse, + ), + WalletRpcMetadata( + endpoint_name="push_tx", + request_type=wallet_request_types.PushTX, + response_type=wallet_request_types.Empty, + ), + WalletRpcMetadata( + endpoint_name="push_transactions", + request_type=wallet_request_types.PushTransactions, + response_type=wallet_request_types.PushTransactionsResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="get_timestamp_for_height", + request_type=wallet_request_types.GetTimestampForHeight, + response_type=wallet_request_types.GetTimestampForHeightResponse, + ), + WalletRpcMetadata( + endpoint_name="get_fee_estimate", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.GetFeeEstimateResponse, + ), + WalletRpcMetadata( + endpoint_name="set_auto_claim", + request_type=AutoClaimSettings, + response_type=AutoClaimSettings, + ), + WalletRpcMetadata( + endpoint_name="get_auto_claim", + request_type=wallet_request_types.Empty, + response_type=AutoClaimSettings, + ), + # Wallet management + WalletRpcMetadata( + endpoint_name="get_wallets", + request_type=wallet_request_types.GetWallets, + response_type=wallet_request_types.GetWalletsResponse, + ), + WalletRpcMetadata( + endpoint_name="create_new_wallet", + request_type=wallet_request_types.CreateNewWallet, + response_type=wallet_request_types.CreateNewWalletResponse, + tx_endpoint=True, + auto_push=True, + ), + # Wallet + WalletRpcMetadata( + endpoint_name="get_wallet_balance", + request_type=wallet_request_types.GetWalletBalance, + response_type=wallet_request_types.GetWalletBalanceResponse, + ), + WalletRpcMetadata( + endpoint_name="get_wallet_balances", + request_type=wallet_request_types.GetWalletBalances, + response_type=wallet_request_types.GetWalletBalancesResponse, + ), + WalletRpcMetadata( + endpoint_name="get_transaction", + request_type=wallet_request_types.GetTransaction, + response_type=wallet_request_types.GetTransactionResponse, + ), + WalletRpcMetadata( + endpoint_name="get_transactions", + request_type=wallet_request_types.GetTransactions, + response_type=wallet_request_types.GetTransactionsResponse, + ), + WalletRpcMetadata( + endpoint_name="get_transaction_count", + request_type=wallet_request_types.GetTransactionCount, + response_type=wallet_request_types.GetTransactionCountResponse, + ), + WalletRpcMetadata( + endpoint_name="get_next_address", + request_type=wallet_request_types.GetNextAddress, + response_type=wallet_request_types.GetNextAddressResponse, + ), + WalletRpcMetadata( + endpoint_name="send_transaction", + request_type=wallet_request_types.SendTransaction, + response_type=wallet_request_types.SendTransactionResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="send_transaction_multi", + request_type=wallet_request_types.SendTransactionMulti, + response_type=wallet_request_types.SendTransactionMultiResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="spend_clawback_coins", + request_type=wallet_request_types.SpendClawbackCoins, + response_type=wallet_request_types.SpendClawbackCoinsResponse, + tx_endpoint=True, + auto_push=True, + auto_merge_spends=False, + ), + # get_coin_records remains a legacy untyped endpoint. + WalletRpcMetadata( + endpoint_name="get_farmed_amount", + request_type=wallet_request_types.GetFarmedAmount, + response_type=wallet_request_types.GetFarmedAmountResponse, + ), + WalletRpcMetadata( + endpoint_name="create_signed_transaction", + request_type=wallet_request_types.CreateSignedTransaction, + response_type=wallet_request_types.CreateSignedTransactionsResponse, + tx_endpoint=True, + ), + WalletRpcMetadata( + endpoint_name="delete_unconfirmed_transactions", + request_type=wallet_request_types.DeleteUnconfirmedTransactions, + response_type=wallet_request_types.Empty, + ), + WalletRpcMetadata( + endpoint_name="select_coins", + request_type=wallet_request_types.SelectCoins, + response_type=wallet_request_types.SelectCoinsResponse, + ), + WalletRpcMetadata( + endpoint_name="get_spendable_coins", + request_type=wallet_request_types.GetSpendableCoins, + response_type=wallet_request_types.GetSpendableCoinsResponse, + ), + WalletRpcMetadata( + endpoint_name="get_coin_records_by_names", + request_type=wallet_request_types.GetCoinRecordsByNames, + response_type=wallet_request_types.GetCoinRecordsByNamesResponse, + ), + WalletRpcMetadata( + endpoint_name="get_puzzle_and_solution", + request_type=wallet_request_types.GetPuzzleAndSolution, + response_type=wallet_request_types.GetPuzzleAndSolutionResponse, + ), + WalletRpcMetadata( + endpoint_name="get_current_derivation_index", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.GetCurrentDerivationIndexResponse, + ), + WalletRpcMetadata( + endpoint_name="extend_derivation_index", + request_type=wallet_request_types.ExtendDerivationIndex, + response_type=wallet_request_types.ExtendDerivationIndexResponse, + ), + WalletRpcMetadata( + endpoint_name="get_notifications", + request_type=wallet_request_types.GetNotifications, + response_type=wallet_request_types.GetNotificationsResponse, + ), + WalletRpcMetadata( + endpoint_name="delete_notifications", + request_type=wallet_request_types.DeleteNotifications, + response_type=wallet_request_types.Empty, + ), + WalletRpcMetadata( + endpoint_name="send_notification", + request_type=wallet_request_types.SendNotification, + response_type=wallet_request_types.SendNotificationResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="sign_message_by_address", + request_type=wallet_request_types.SignMessageByAddress, + response_type=wallet_request_types.SignMessageByAddressResponse, + ), + WalletRpcMetadata( + endpoint_name="sign_message_by_id", + request_type=wallet_request_types.SignMessageByID, + response_type=wallet_request_types.SignMessageByIDResponse, + ), + WalletRpcMetadata( + endpoint_name="verify_signature", + request_type=wallet_request_types.VerifySignature, + response_type=wallet_request_types.VerifySignatureResponse, + ), + WalletRpcMetadata( + endpoint_name="get_transaction_memo", + request_type=wallet_request_types.GetTransactionMemo, + response_type=wallet_request_types.GetTransactionMemoResponse, + ), + WalletRpcMetadata( + endpoint_name="split_coins", + request_type=wallet_request_types.SplitCoins, + response_type=wallet_request_types.SplitCoinsResponse, + tx_endpoint=True, + ), + WalletRpcMetadata( + endpoint_name="combine_coins", + request_type=wallet_request_types.CombineCoins, + response_type=wallet_request_types.CombineCoinsResponse, + tx_endpoint=True, + ), + # CATs and trading + WalletRpcMetadata( + endpoint_name="cat_set_name", + request_type=wallet_request_types.CATSetName, + response_type=wallet_request_types.CATSetNameResponse, + ), + WalletRpcMetadata( + endpoint_name="cat_asset_id_to_name", + request_type=wallet_request_types.CATAssetIDToName, + response_type=wallet_request_types.CATAssetIDToNameResponse, + ), + WalletRpcMetadata( + endpoint_name="cat_get_name", + request_type=wallet_request_types.CATGetName, + response_type=wallet_request_types.CATGetNameResponse, + ), + WalletRpcMetadata( + endpoint_name="get_stray_cats", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.GetStrayCATsResponse, + ), + WalletRpcMetadata( + endpoint_name="cat_spend", + request_type=wallet_request_types.CATSpend, + response_type=wallet_request_types.CATSpendResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="cat_get_asset_id", + request_type=wallet_request_types.CATGetAssetID, + response_type=wallet_request_types.CATGetAssetIDResponse, + ), + WalletRpcMetadata( + endpoint_name="create_offer_for_ids", + request_type=wallet_request_types.CreateOfferForIDs, + response_type=wallet_request_types.CreateOfferForIDsResponse, + tx_endpoint=True, + ), + WalletRpcMetadata( + endpoint_name="get_offer_summary", + request_type=wallet_request_types.GetOfferSummary, + response_type=wallet_request_types.GetOfferSummaryResponse, + ), + WalletRpcMetadata( + endpoint_name="check_offer_validity", + request_type=wallet_request_types.CheckOfferValidity, + response_type=wallet_request_types.CheckOfferValidityResponse, + ), + WalletRpcMetadata( + endpoint_name="take_offer", + request_type=wallet_request_types.TakeOffer, + response_type=wallet_request_types.TakeOfferResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="get_offer", + request_type=wallet_request_types.GetOffer, + response_type=wallet_request_types.GetOfferResponse, + ), + WalletRpcMetadata( + endpoint_name="get_all_offers", + request_type=wallet_request_types.GetAllOffers, + response_type=wallet_request_types.GetAllOffersResponse, + ), + WalletRpcMetadata( + endpoint_name="get_offers_count", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.GetOffersCountResponse, + ), + WalletRpcMetadata( + endpoint_name="cancel_offer", + request_type=wallet_request_types.CancelOffer, + response_type=wallet_request_types.CancelOfferResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="cancel_offers", + request_type=wallet_request_types.CancelOffers, + response_type=wallet_request_types.CancelOffersResponse, + tx_endpoint=True, + auto_push=True, + auto_merge_spends=False, + ), + WalletRpcMetadata( + endpoint_name="get_cat_list", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.GetCATListResponse, + ), + # DID wallet + WalletRpcMetadata( + endpoint_name="did_set_wallet_name", + request_type=wallet_request_types.DIDSetWalletName, + response_type=wallet_request_types.DIDSetWalletNameResponse, + ), + WalletRpcMetadata( + endpoint_name="did_get_wallet_name", + request_type=wallet_request_types.DIDGetWalletName, + response_type=wallet_request_types.DIDGetWalletNameResponse, + ), + WalletRpcMetadata( + endpoint_name="did_update_metadata", + request_type=wallet_request_types.DIDUpdateMetadata, + response_type=wallet_request_types.DIDUpdateMetadataResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="did_get_pubkey", + request_type=wallet_request_types.DIDGetPubkey, + response_type=wallet_request_types.DIDGetPubkeyResponse, + ), + WalletRpcMetadata( + endpoint_name="did_get_did", + request_type=wallet_request_types.DIDGetDID, + response_type=wallet_request_types.DIDGetDIDResponse, + ), + WalletRpcMetadata( + endpoint_name="did_get_metadata", + request_type=wallet_request_types.DIDGetMetadata, + response_type=wallet_request_types.DIDGetMetadataResponse, + ), + WalletRpcMetadata( + endpoint_name="did_get_current_coin_info", + request_type=wallet_request_types.DIDGetCurrentCoinInfo, + response_type=wallet_request_types.DIDGetCurrentCoinInfoResponse, + ), + WalletRpcMetadata( + endpoint_name="did_create_backup_file", + request_type=wallet_request_types.DIDCreateBackupFile, + response_type=wallet_request_types.DIDCreateBackupFileResponse, + ), + WalletRpcMetadata( + endpoint_name="did_transfer_did", + request_type=wallet_request_types.DIDTransferDID, + response_type=wallet_request_types.DIDTransferDIDResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="did_message_spend", + request_type=wallet_request_types.DIDMessageSpend, + response_type=wallet_request_types.DIDMessageSpendResponse, + tx_endpoint=True, + ), + WalletRpcMetadata( + endpoint_name="did_get_info", + request_type=wallet_request_types.DIDGetInfo, + response_type=wallet_request_types.DIDGetInfoResponse, + ), + WalletRpcMetadata( + endpoint_name="did_find_lost_did", + request_type=wallet_request_types.DIDFindLostDID, + response_type=wallet_request_types.DIDFindLostDIDResponse, + ), + # NFT wallet + WalletRpcMetadata( + endpoint_name="nft_mint_nft", + request_type=wallet_request_types.NFTMintNFTRequest, + response_type=wallet_request_types.NFTMintNFTResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="nft_count_nfts", + request_type=wallet_request_types.NFTCountNFTs, + response_type=wallet_request_types.NFTCountNFTsResponse, + ), + WalletRpcMetadata( + endpoint_name="nft_get_nfts", + request_type=wallet_request_types.NFTGetNFTs, + response_type=wallet_request_types.NFTGetNFTsResponse, + ), + WalletRpcMetadata( + endpoint_name="nft_get_by_did", + request_type=wallet_request_types.NFTGetByDID, + response_type=wallet_request_types.NFTGetByDIDResponse, + ), + WalletRpcMetadata( + endpoint_name="nft_set_nft_did", + request_type=wallet_request_types.NFTSetNFTDID, + response_type=wallet_request_types.NFTSetNFTDIDResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="nft_set_nft_status", + request_type=wallet_request_types.NFTSetNFTStatus, + response_type=wallet_request_types.Empty, + ), + WalletRpcMetadata( + endpoint_name="nft_get_wallet_did", + request_type=wallet_request_types.NFTGetWalletDID, + response_type=wallet_request_types.NFTGetWalletDIDResponse, + ), + WalletRpcMetadata( + endpoint_name="nft_get_wallets_with_dids", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.NFTGetWalletsWithDIDsResponse, + ), + WalletRpcMetadata( + endpoint_name="nft_get_info", + request_type=wallet_request_types.NFTGetInfo, + response_type=wallet_request_types.NFTGetInfoResponse, + ), + WalletRpcMetadata( + endpoint_name="nft_transfer_nft", + request_type=wallet_request_types.NFTTransferNFT, + response_type=wallet_request_types.NFTTransferNFTResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="nft_add_uri", + request_type=wallet_request_types.NFTAddURI, + response_type=wallet_request_types.NFTAddURIResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="nft_calculate_royalties", + request_type=wallet_request_types.NFTCalculateRoyalties, + response_type=wallet_request_types.NFTCalculateRoyaltiesResponse, + ), + WalletRpcMetadata( + endpoint_name="nft_mint_bulk", + request_type=wallet_request_types.NFTMintBulk, + response_type=wallet_request_types.NFTMintBulkResponse, + tx_endpoint=True, + ), + WalletRpcMetadata( + endpoint_name="nft_set_did_bulk", + request_type=wallet_request_types.NFTSetDIDBulk, + response_type=wallet_request_types.NFTSetDIDBulkResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="nft_transfer_bulk", + request_type=wallet_request_types.NFTTransferBulk, + response_type=wallet_request_types.NFTTransferBulkResponse, + tx_endpoint=True, + auto_push=True, + ), + # Remote wallet + WalletRpcMetadata( + endpoint_name="register_remote_coins", + request_type=wallet_request_types.RegisterRemoteCoins, + response_type=wallet_request_types.Empty, + ), + WalletRpcMetadata( + endpoint_name="get_coin_records", + request_type=wallet_request_types.GetCoinRecords, + response_type=wallet_request_types.GetCoinRecordsResponse, + ), + # Pool wallet + WalletRpcMetadata( + endpoint_name="pw_join_pool", + request_type=wallet_request_types.PWJoinPool, + response_type=wallet_request_types.PWJoinPoolResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="pw_self_pool", + request_type=wallet_request_types.PWSelfPool, + response_type=wallet_request_types.PWSelfPoolResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="pw_absorb_rewards", + request_type=wallet_request_types.PWAbsorbRewards, + response_type=wallet_request_types.PWAbsorbRewardsResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="pw_status", + request_type=wallet_request_types.PWStatus, + response_type=wallet_request_types.PWStatusResponse, + ), + # Data layer wallet + WalletRpcMetadata( + endpoint_name="create_new_dl", + request_type=wallet_request_types.CreateNewDL, + response_type=wallet_request_types.CreateNewDLResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="dl_track_new", + request_type=wallet_request_types.DLTrackNew, + response_type=wallet_request_types.Empty, + ), + WalletRpcMetadata( + endpoint_name="dl_stop_tracking", + request_type=wallet_request_types.DLStopTracking, + response_type=wallet_request_types.Empty, + ), + WalletRpcMetadata( + endpoint_name="dl_latest_singleton", + request_type=wallet_request_types.DLLatestSingleton, + response_type=wallet_request_types.DLLatestSingletonResponse, + ), + WalletRpcMetadata( + endpoint_name="dl_singletons_by_root", + request_type=wallet_request_types.DLSingletonsByRoot, + response_type=wallet_request_types.DLSingletonsByRootResponse, + ), + WalletRpcMetadata( + endpoint_name="dl_update_root", + request_type=wallet_request_types.DLUpdateRoot, + response_type=wallet_request_types.DLUpdateRootResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="dl_update_multiple", + request_type=wallet_request_types.DLUpdateMultiple, + response_type=wallet_request_types.DLUpdateMultipleResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="dl_history", + request_type=wallet_request_types.DLHistory, + response_type=wallet_request_types.DLHistoryResponse, + ), + WalletRpcMetadata( + endpoint_name="dl_owned_singletons", + request_type=wallet_request_types.Empty, + response_type=wallet_request_types.DLOwnedSingletonsResponse, + ), + WalletRpcMetadata( + endpoint_name="dl_get_mirrors", + request_type=wallet_request_types.DLGetMirrors, + response_type=wallet_request_types.DLGetMirrorsResponse, + ), + WalletRpcMetadata( + endpoint_name="dl_new_mirror", + request_type=wallet_request_types.DLNewMirror, + response_type=wallet_request_types.DLNewMirrorResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="dl_delete_mirror", + request_type=wallet_request_types.DLDeleteMirror, + response_type=wallet_request_types.DLDeleteMirrorResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="dl_verify_proof", + request_type=DLProof, + response_type=VerifyProofResponse, + ), + # Verified credentials + WalletRpcMetadata( + endpoint_name="vc_mint", + request_type=wallet_request_types.VCMint, + response_type=wallet_request_types.VCMintResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="vc_get", + request_type=wallet_request_types.VCGet, + response_type=wallet_request_types.VCGetResponse, + ), + WalletRpcMetadata( + endpoint_name="vc_get_list", + request_type=wallet_request_types.VCGetList, + response_type=wallet_request_types.VCGetListResponse, + ), + WalletRpcMetadata( + endpoint_name="vc_spend", + request_type=wallet_request_types.VCSpend, + response_type=wallet_request_types.VCSpendResponse, + tx_endpoint=True, + auto_push=True, + ), + WalletRpcMetadata( + endpoint_name="vc_add_proofs", + request_type=wallet_request_types.VCAddProofs, + response_type=wallet_request_types.Empty, + ), + WalletRpcMetadata( + endpoint_name="vc_get_proofs_for_root", + request_type=wallet_request_types.VCGetProofsForRoot, + response_type=wallet_request_types.VCGetProofsForRootResponse, + ), + WalletRpcMetadata( + endpoint_name="vc_revoke", + request_type=wallet_request_types.VCRevoke, + response_type=wallet_request_types.VCRevokeResponse, + tx_endpoint=True, + auto_push=True, + ), + # CR-CATs + WalletRpcMetadata( + endpoint_name="crcat_approve_pending", + request_type=wallet_request_types.CRCATApprovePending, + response_type=wallet_request_types.CRCATApprovePendingResponse, + tx_endpoint=True, + auto_push=True, + ), + # Signer protocol + WalletRpcMetadata( + endpoint_name="gather_signing_info", + request_type=wallet_request_types.GatherSigningInfo, + response_type=wallet_request_types.GatherSigningInfoResponse, + ), + WalletRpcMetadata( + endpoint_name="apply_signatures", + request_type=wallet_request_types.ApplySignatures, + response_type=wallet_request_types.ApplySignaturesResponse, + ), + WalletRpcMetadata( + endpoint_name="submit_transactions", + request_type=wallet_request_types.SubmitTransactions, + response_type=wallet_request_types.SubmitTransactionsResponse, + ), + WalletRpcMetadata( + endpoint_name="execute_signing_instructions", + request_type=wallet_request_types.ExecuteSigningInstructions, + response_type=wallet_request_types.ExecuteSigningInstructionsResponse, + ), +] diff --git a/tools/generate_wallet_rpc_client_stub.py b/tools/generate_wallet_rpc_client_stub.py new file mode 100755 index 0000000000..1421417df0 --- /dev/null +++ b/tools/generate_wallet_rpc_client_stub.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +from pathlib import Path + +from chia.wallet import wallet_rpc_client +from chia.wallet.wallet_request_types import Empty +from chia.wallet.wallet_rpc_metadata import WALLET_RPC_ENDPOINT_METADATA + +REPO_ROOT = Path(__file__).resolve().parents[1] +OUTPUT_PATH = REPO_ROOT / "chia" / "wallet" / "wallet_rpc_client.pyi" + + +def _type_name(cls: type) -> str: + return cls.__name__ + + +def _import_name(cls: type) -> str: + return cls.__module__ + + +def generate() -> str: + + methods: list[str] = [] + + for meta in WALLET_RPC_ENDPOINT_METADATA: + method_name = wallet_rpc_client.client_method_name(meta.endpoint_name) + request_type = meta.request_type + response_type = meta.response_type + + if response_type is Empty: + response_ann = "None" + elif _import_name(response_type) == "chia.wallet.wallet_request_types": + response_ann = "wallet_request_types." + _type_name(response_type) + else: + response_ann = _type_name(response_type) + + if _import_name(request_type) == "chia.wallet.wallet_request_types": + request_ann = "wallet_request_types." + _type_name(request_type) + else: + request_ann = _type_name(request_type) + + if meta.tx_endpoint: + methods.append( + f" async def {method_name}(\n" + f" self,\n" + f" request: {request_ann},\n" + f" tx_config: TXConfig,\n" + f" extra_conditions: tuple[Condition, ...] = ...,\n" + f" timelock_info: ConditionValidTimes = ...,\n" + f" ) -> {response_ann}: ..." + ) + elif request_type is Empty: + methods.append(f" async def {method_name}(self) -> {response_ann}: ...") + else: + methods.append( + f" async def {method_name}(\n" + " self,\n" + f" request: {request_ann},\n" + f" ) -> {response_ann}: ..." + ) + + body = "\n".join( + [ + "# This file is generated by tools/generate_wallet_rpc_client_stub.py", + "from chia.data_layer.data_layer_util import DLProof, VerifyProofResponse", + "from chia.rpc.rpc_client import RpcClient", + "from chia.wallet import wallet_request_types", + "from chia.wallet.conditions import Condition, ConditionValidTimes", + "from chia.wallet.puzzles.clawback.metadata import AutoClaimSettings", + "from chia.wallet.util.tx_config import TXConfig", + "", + "def client_method_name(endpoint_name: str) -> str: ...", + "", + "class WalletRpcClient(RpcClient):", + *methods, + "", + ] + ) + return body + + +def main() -> None: + OUTPUT_PATH.write_text(generate(), encoding="utf-8", newline="\n") + print(f"Wrote {OUTPUT_PATH}") + + +if __name__ == "__main__": + main()