[CHIA-3604] Port easy CAT endpoints to @marshal (#19992)

* Port `spend_clawback_coins` to `@marshal`

* fix tests

* fix test again

* how do I keep missing these?

* Port `select_coins` to `@marshal`

* fix tests

* fix test

* Port `get_spendable_coins`

* Port `get_coin_records_by_names`

* Port `send_notifications` to `@marshal`

* Fixing the thing that is always broken

* Remove accidental import

* Port `get_default_cat_list`

* Port `cat_set_name`

* Port `cat_get_name`

* Port `get_stray_cats`

* Port `cat_get_asset_id`

* Port `cat_asset_id_to_name`

* Port `check_offer_validity`

* Port `get_offers_count`
This commit is contained in:
Matt Hauff
2025-09-23 12:48:40 -07:00
committed by GitHub
parent 6099c7c5f4
commit b45f67765f
9 changed files with 248 additions and 133 deletions
+12 -8
View File
@@ -33,6 +33,10 @@ from chia.wallet.util.transaction_type import TransactionType
from chia.wallet.util.tx_config import TXConfig
from chia.wallet.util.wallet_types import WalletType
from chia.wallet.wallet_request_types import (
CATAssetIDToName,
CATAssetIDToNameResponse,
CATGetName,
CATGetNameResponse,
GetSyncStatusResponse,
GetTransaction,
GetTransactionResponse,
@@ -146,9 +150,9 @@ class TestWalletRpcClient(TestRpcClient):
bytes32([2] * 32),
)
async def get_cat_name(self, wallet_id: int) -> str:
self.add_to_log("get_cat_name", (wallet_id,))
return "test" + str(wallet_id)
async def get_cat_name(self, request: CATGetName) -> CATGetNameResponse:
self.add_to_log("get_cat_name", (request.wallet_id,))
return CATGetNameResponse(request.wallet_id, "test" + str(request.wallet_id))
async def sign_message_by_address(self, request: SignMessageByAddress) -> SignMessageByAddressResponse:
self.add_to_log("sign_message_by_address", (request.address, request.message))
@@ -182,15 +186,15 @@ class TestWalletRpcClient(TestRpcClient):
signing_mode = SigningMode.CHIP_0002.value
return SignMessageByIDResponse(pubkey, signature, bytes32.zeros, signing_mode)
async def cat_asset_id_to_name(self, asset_id: bytes32) -> Optional[tuple[Optional[uint32], str]]:
async def cat_asset_id_to_name(self, request: CATAssetIDToName) -> CATAssetIDToNameResponse:
"""
if bytes32([1] * 32), return (uint32(2), "test1"), if bytes32([1] * 32), return (uint32(3), "test2")
"""
self.add_to_log("cat_asset_id_to_name", (asset_id,))
self.add_to_log("cat_asset_id_to_name", (request.asset_id,))
for i in range(256):
if asset_id == get_bytes32(i):
return uint32(i + 1), "test" + str(i)
return None
if request.asset_id == get_bytes32(i):
return CATAssetIDToNameResponse(uint32(i + 1), "test" + str(i))
return CATAssetIDToNameResponse(wallet_id=None, name=None)
async def get_nft_info(self, request: NFTGetInfo) -> NFTGetInfoResponse:
self.add_to_log("get_nft_info", (request.coin_id, request.latest))
+14 -9
View File
@@ -43,6 +43,10 @@ from chia.wallet.wallet_coin_store import GetCoinRecords
from chia.wallet.wallet_request_types import (
BalanceResponse,
CancelOfferResponse,
CATAssetIDToName,
CATAssetIDToNameResponse,
CATSetName,
CATSetNameResponse,
CATSpendResponse,
ClawbackPuzzleDecoratorOverride,
CreateOfferForIDsResponse,
@@ -683,8 +687,9 @@ def test_add_token(capsys: object, get_test_cli_clients: tuple[TestRpcClients, P
self.add_to_log("create_wallet_for_existing_cat", (asset_id,))
return {"wallet_id": 3}
async def set_cat_name(self, wallet_id: int, name: str) -> None:
self.add_to_log("set_cat_name", (wallet_id, name))
async def set_cat_name(self, request: CATSetName) -> CATSetNameResponse:
self.add_to_log("set_cat_name", (request.wallet_id, request.name))
return CATSetNameResponse(wallet_id=request.wallet_id)
inst_rpc_client = AddTokenRpcClient()
test_rpc_clients.wallet_rpc_client = inst_rpc_client
@@ -1051,14 +1056,14 @@ def test_take_offer(capsys: object, get_test_cli_clients: tuple[TestRpcClients,
),
)
async def cat_asset_id_to_name(self, asset_id: bytes32) -> Optional[tuple[Optional[uint32], str]]:
self.add_to_log("cat_asset_id_to_name", (asset_id,))
if asset_id == cat_offered_id:
return uint32(2), "offered cat"
elif asset_id == cat_requested_id:
return uint32(3), "requested cat"
async def cat_asset_id_to_name(self, request: CATAssetIDToName) -> CATAssetIDToNameResponse:
self.add_to_log("cat_asset_id_to_name", (request.asset_id,))
if request.asset_id == cat_offered_id:
return CATAssetIDToNameResponse(uint32(2), "offered cat")
elif request.asset_id == cat_requested_id:
return CATAssetIDToNameResponse(uint32(3), "requested cat")
else:
return None
return CATAssetIDToNameResponse(wallet_id=None, name=None)
inst_rpc_client = TakeOfferRpcClient()
test_rpc_clients.wallet_rpc_client = inst_rpc_client
+4 -3
View File
@@ -1,12 +1,13 @@
from __future__ import annotations
from typing import Any, Optional
from typing import Any
import pytest
from chia_rs.sized_bytes import bytes32
from chia_rs.sized_ints import uint32
from chia.cmds.wallet_funcs import print_offer_summary
from chia.wallet.wallet_request_types import CATAssetIDToName, CATAssetIDToNameResponse
TEST_DUCKSAUCE_ASSET_ID = "1000000000000000000000000000000000000000000000000000000000000001"
TEST_CRUNCHBERRIES_ASSET_ID = "1000000000000000000000000000000000000000000000000000000000000002"
@@ -19,8 +20,8 @@ TEST_ASSET_ID_NAME_MAPPING: dict[bytes32, tuple[uint32, str]] = {
}
async def cat_name_resolver(asset_id: bytes32) -> Optional[tuple[Optional[uint32], str]]:
return TEST_ASSET_ID_NAME_MAPPING.get(asset_id)
async def cat_name_resolver(request: CATAssetIDToName) -> CATAssetIDToNameResponse:
return CATAssetIDToNameResponse(*TEST_ASSET_ID_NAME_MAPPING.get(request.asset_id, (None, None)))
@pytest.mark.anyio
+8 -4
View File
@@ -73,7 +73,7 @@ from chia.wallet.transaction_record import TransactionRecord
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
from chia.wallet.wallet import Wallet
from chia.wallet.wallet_node import WalletNode
from chia.wallet.wallet_request_types import DLLatestSingleton
from chia.wallet.wallet_request_types import CheckOfferValidity, DLLatestSingleton
from chia.wallet.wallet_rpc_api import WalletRpcApi
from chia.wallet.wallet_service import WalletService
@@ -222,7 +222,9 @@ async def check_singleton_confirmed(dl: DataLayer, store_id: bytes32) -> bool:
async def process_block_and_check_offer_validity(offer: TradingOffer, offer_setup: OfferSetup) -> bool:
await offer_setup.full_node_api.farm_blocks_to_puzzlehash(count=1, guarantee_transaction_blocks=True)
return (await offer_setup.maker.data_layer.wallet_rpc.check_offer_validity(offer=offer))[1]
return (
await offer_setup.maker.data_layer.wallet_rpc.check_offer_validity(CheckOfferValidity(offer=offer.to_bech32()))
).valid
async def run_cli_cmd(*args: str, root_path: Path) -> asyncio.subprocess.Process:
@@ -1825,9 +1827,11 @@ async def test_make_and_cancel_offer(offer_setup: OfferSetup, reference: MakeAnd
for _ in range(10):
if not (
await offer_setup.maker.data_layer.wallet_rpc.check_offer_validity(
offer=TradingOffer.from_bytes(hexstr_to_bytes(maker_response["offer"]["offer"])),
CheckOfferValidity(
offer=TradingOffer.from_bytes(hexstr_to_bytes(maker_response["offer"]["offer"])).to_bech32()
),
)
)[1]:
).valid:
break
await offer_setup.full_node_api.farm_blocks_to_puzzlehash(count=1, guarantee_transaction_blocks=True)
await asyncio.sleep(0.5)
+26 -22
View File
@@ -104,7 +104,12 @@ from chia.wallet.wallet_node import WalletNode
from chia.wallet.wallet_protocol import WalletProtocol
from chia.wallet.wallet_request_types import (
AddKey,
CATAssetIDToName,
CATGetAssetID,
CATGetName,
CATSetName,
CheckDeleteKey,
CheckOfferValidity,
ClawbackPuzzleDecoratorOverride,
CombineCoins,
DefaultCAT,
@@ -1203,25 +1208,23 @@ async def test_cat_endpoints(wallet_environments: WalletTestFramework, wallet_ty
env_0.wallet_states[uint32(env_0.wallet_aliases["cat0"])].balance.to_json_dict().items()
<= (await env_0.rpc_client.get_wallet_balance(GetWalletBalance(cat_0_id))).wallet_balance.to_json_dict().items()
)
asset_id = await env_0.rpc_client.get_cat_asset_id(cat_0_id)
assert (await env_0.rpc_client.get_cat_name(cat_0_id)) == wallet_type.default_wallet_name_for_unknown_cat(
asset_id.hex()
)
await env_0.rpc_client.set_cat_name(cat_0_id, "My cat")
assert (await env_0.rpc_client.get_cat_name(cat_0_id)) == "My cat"
result = await env_0.rpc_client.cat_asset_id_to_name(asset_id)
assert result is not None
wid, name = result
assert wid == cat_0_id
assert name == "My cat"
result = await env_0.rpc_client.cat_asset_id_to_name(bytes32.zeros)
assert result is None
asset_id = (await env_0.rpc_client.get_cat_asset_id(CATGetAssetID(cat_0_id))).asset_id
assert (
await env_0.rpc_client.get_cat_name(CATGetName(cat_0_id))
).name == wallet_type.default_wallet_name_for_unknown_cat(asset_id.hex())
await env_0.rpc_client.set_cat_name(CATSetName(cat_0_id, "My cat"))
assert (await env_0.rpc_client.get_cat_name(CATGetName(cat_0_id))).name == "My cat"
asset_to_name_response = await env_0.rpc_client.cat_asset_id_to_name(CATAssetIDToName(asset_id))
assert asset_to_name_response.wallet_id == cat_0_id
assert asset_to_name_response.name == "My cat"
asset_to_name_response = await env_0.rpc_client.cat_asset_id_to_name(CATAssetIDToName(bytes32.zeros))
assert asset_to_name_response.name is None
verified_asset_id = next(iter(DEFAULT_CATS.items()))[1]["asset_id"]
result = await env_0.rpc_client.cat_asset_id_to_name(bytes32.from_hexstr(verified_asset_id))
assert result is not None
should_be_none, name = result
assert should_be_none is None
assert name == next(iter(DEFAULT_CATS.items()))[1]["name"]
asset_to_name_response = await env_0.rpc_client.cat_asset_id_to_name(
CATAssetIDToName(bytes32.from_hexstr(verified_asset_id))
)
assert asset_to_name_response.wallet_id is None
assert asset_to_name_response.name == next(iter(DEFAULT_CATS.items()))[1]["name"]
# Creates a second wallet with the same CAT
res = await env_1.rpc_client.create_wallet_for_existing_cat(asset_id)
@@ -1395,8 +1398,8 @@ async def test_cat_endpoints(wallet_environments: WalletTestFramework, wallet_ty
await env_0.wallet_state_manager.interested_store.add_unacknowledged_token(
asset_id, "Unknown", uint32(10000), bytes32(b"\00" * 32)
)
cats = await env_0.rpc_client.get_stray_cats()
assert len(cats) == 1
stray_cats_response = await env_0.rpc_client.get_stray_cats()
assert len(stray_cats_response.stray_cats) == 1
# Test CAT coin selection
select_coins_response = await env_0.rpc_client.select_coins(
@@ -1564,8 +1567,9 @@ async def test_offer_endpoints(wallet_environments: WalletTestFramework, wallet_
}
assert advanced_summary == summary
id, _valid = await env_1.rpc_client.check_offer_validity(offer)
assert id == offer.name()
offer_validity_response = await env_1.rpc_client.check_offer_validity(CheckOfferValidity(offer.to_bech32()))
assert offer_validity_response.id == offer.name()
assert offer_validity_response.valid
all_offers = await env_1.rpc_client.get_all_offers(file_contents=True)
assert len(all_offers) == 1
+25 -23
View File
@@ -45,6 +45,10 @@ from chia.wallet.util.wallet_types import WalletType
from chia.wallet.vc_wallet.vc_store import VCProofs
from chia.wallet.wallet_coin_store import GetCoinRecords
from chia.wallet.wallet_request_types import (
CATAssetIDToName,
CATAssetIDToNameResponse,
CATGetName,
CATSetName,
CATSpendResponse,
ClawbackPuzzleDecoratorOverride,
DeleteNotifications,
@@ -92,7 +96,7 @@ from chia.wallet.wallet_request_types import (
)
from chia.wallet.wallet_rpc_client import WalletRpcClient
CATNameResolver = Callable[[bytes32], Awaitable[Optional[tuple[Optional[uint32], str]]]]
CATNameResolver = Callable[[CATAssetIDToName], Awaitable[CATAssetIDToNameResponse]]
transaction_type_descriptions = {
TransactionType.INCOMING_TX: "received",
@@ -184,7 +188,7 @@ async def get_unit_name_for_wallet_id(
}:
name: str = config["network_overrides"]["config"][config["selected_network"]]["address_prefix"].upper()
elif wallet_type in {WalletType.CAT, WalletType.CRCAT, WalletType.RCAT}:
name = await wallet_client.get_cat_name(wallet_id=wallet_id)
name = (await wallet_client.get_cat_name(CATGetName(wallet_id=uint32(wallet_id)))).name
else:
raise LookupError(f"Operation is not supported for Wallet type {wallet_type.name}")
@@ -469,21 +473,19 @@ async def add_token(
root_path: pathlib.Path, wallet_rpc_port: Optional[int], fp: Optional[int], asset_id: bytes32, token_name: str
) -> None:
async with get_wallet_client(root_path, wallet_rpc_port, fp) as (wallet_client, fingerprint, _):
existing_info: Optional[tuple[Optional[uint32], str]] = await wallet_client.cat_asset_id_to_name(asset_id)
if existing_info is None:
wallet_id = None
old_name = None
else:
wallet_id, old_name = existing_info
existing_info = await wallet_client.cat_asset_id_to_name(CATAssetIDToName(asset_id))
if wallet_id is None:
if existing_info.wallet_id is None:
response = await wallet_client.create_wallet_for_existing_cat(asset_id)
wallet_id = response["wallet_id"]
await wallet_client.set_cat_name(wallet_id, token_name)
await wallet_client.set_cat_name(CATSetName(wallet_id, token_name))
print(f"Successfully added {token_name} with wallet id {wallet_id} on key {fingerprint}")
else:
await wallet_client.set_cat_name(wallet_id, token_name)
print(f"Successfully renamed {old_name} with wallet_id {wallet_id} on key {fingerprint} to {token_name}")
await wallet_client.set_cat_name(CATSetName(existing_info.wallet_id, token_name))
print(
f"Successfully renamed {existing_info.name} with wallet_id {existing_info.wallet_id}"
f" on key {fingerprint} to {token_name}"
)
async def make_offer(
@@ -512,9 +514,9 @@ async def make_offer(
try:
b32_id = bytes32.from_hexstr(name)
id: Union[uint32, str] = b32_id.hex()
result = await wallet_client.cat_asset_id_to_name(b32_id)
if result is not None:
name = result[1]
result = await wallet_client.cat_asset_id_to_name(CATAssetIDToName(b32_id))
if result.name is not None:
name = result.name
else:
name = "Unknown CAT"
unit = units["cat"]
@@ -570,7 +572,7 @@ async def make_offer(
name = "XCH"
unit = units["chia"]
else:
name = await wallet_client.get_cat_name(id)
name = (await wallet_client.get_cat_name(CATGetName(id))).name
unit = units["cat"]
if item in offers:
fungible_assets.append(FungibleAsset(name, uint64(abs(int(Decimal(amount) * unit)))))
@@ -678,10 +680,10 @@ async def print_offer_summary(
description = " [Typically represents change returned from the included fee]"
else:
unit = units["cat"]
result = await cat_name_resolver(bytes32.from_hexstr(asset_id))
if result is not None:
wid = str(result[0])
name = result[1]
result = await cat_name_resolver(CATAssetIDToName(bytes32.from_hexstr(asset_id)))
if result.name is not None:
wid = str(result.wallet_id)
name = result.name
output: str = f" - {name}"
mojo_str: str = f"{mojo_amount} {'mojo' if mojo_amount == 1 else 'mojos'}"
if len(wid) > 0:
@@ -844,9 +846,9 @@ async def take_offer(
if fungible_asset_id is None:
nft_royalty_currency = network_xch
else:
result = await wallet_client.cat_asset_id_to_name(fungible_asset_id)
if result is not None:
nft_royalty_currency = result[1]
result = await wallet_client.cat_asset_id_to_name(CATAssetIDToName(fungible_asset_id))
if result.name is not None:
nft_royalty_currency = result.name
fungible_assets.append(
FungibleAsset(nft_royalty_currency, uint64(requested[fungible_asset_id_str]))
)
+80
View File
@@ -594,6 +594,86 @@ class GetCATListResponse(Streamable):
cat_list: list[DefaultCAT]
@streamable
@dataclass(frozen=True)
class CATSetName(Streamable):
wallet_id: uint32
name: str
@streamable
@dataclass(frozen=True)
class CATSetNameResponse(Streamable):
wallet_id: uint32
@streamable
@dataclass(frozen=True)
class CATGetName(Streamable):
wallet_id: uint32
@streamable
@dataclass(frozen=True)
class CATGetNameResponse(Streamable):
wallet_id: uint32
name: str
@streamable
@dataclass(frozen=True)
class StrayCAT(Streamable):
asset_id: bytes32
name: str
first_seen_height: uint32
sender_puzzle_hash: bytes32
@streamable
@dataclass(frozen=True)
class GetStrayCATsResponse(Streamable):
stray_cats: list[StrayCAT]
@streamable
@dataclass(frozen=True)
class CATGetAssetID(Streamable):
wallet_id: uint32
@streamable
@dataclass(frozen=True)
class CATGetAssetIDResponse(Streamable):
wallet_id: uint32
asset_id: bytes32
@streamable
@dataclass(frozen=True)
class CATAssetIDToName(Streamable):
asset_id: bytes32
@streamable
@dataclass(frozen=True)
class CATAssetIDToNameResponse(Streamable):
wallet_id: Optional[uint32]
name: Optional[str]
@streamable
@dataclass(frozen=True)
class CheckOfferValidity(Streamable):
offer: str
@streamable
@dataclass(frozen=True)
class CheckOfferValidityResponse(Streamable):
valid: bool
id: bytes32
@streamable
@dataclass(frozen=True)
class DIDSetWalletName(Streamable):
+53 -33
View File
@@ -112,12 +112,23 @@ from chia.wallet.wallet_request_types import (
ApplySignatures,
ApplySignaturesResponse,
BalanceResponse,
CATAssetIDToName,
CATAssetIDToNameResponse,
CATGetAssetID,
CATGetAssetIDResponse,
CATGetName,
CATGetNameResponse,
CATSetName,
CATSetNameResponse,
CheckDeleteKey,
CheckDeleteKeyResponse,
CheckOfferValidity,
CheckOfferValidityResponse,
CombineCoins,
CombineCoinsResponse,
CreateNewDL,
CreateNewDLResponse,
DefaultCAT,
DeleteKey,
DeleteNotifications,
DeleteUnconfirmedTransactions,
@@ -172,6 +183,7 @@ from chia.wallet.wallet_request_types import (
GatherSigningInfo,
GatherSigningInfoResponse,
GenerateMnemonicResponse,
GetCATListResponse,
GetCoinRecordsByNames,
GetCoinRecordsByNamesResponse,
GetCurrentDerivationIndexResponse,
@@ -181,12 +193,14 @@ from chia.wallet.wallet_request_types import (
GetNextAddressResponse,
GetNotifications,
GetNotificationsResponse,
GetOffersCountResponse,
GetPrivateKey,
GetPrivateKeyFormat,
GetPrivateKeyResponse,
GetPublicKeysResponse,
GetSpendableCoins,
GetSpendableCoinsResponse,
GetStrayCATsResponse,
GetSyncStatusResponse,
GetTimestampForHeight,
GetTimestampForHeightResponse,
@@ -261,6 +275,7 @@ from chia.wallet.wallet_request_types import (
SpendClawbackCoinsResponse,
SplitCoins,
SplitCoinsResponse,
StrayCAT,
SubmitTransactions,
SubmitTransactionsResponse,
TransactionRecordWithMetadata,
@@ -2095,29 +2110,31 @@ class WalletRpcApi:
# CATs and Trading
##########################################################################################
async def get_cat_list(self, request: dict[str, Any]) -> EndpointResult:
return {"cat_list": list(DEFAULT_CATS.values())}
@marshal
async def get_cat_list(self, request: Empty) -> GetCATListResponse:
return GetCATListResponse([DefaultCAT.from_json_dict(default_cat) for default_cat in DEFAULT_CATS.values()])
async def cat_set_name(self, request: dict[str, Any]) -> EndpointResult:
wallet_id = uint32(request["wallet_id"])
wallet = self.service.wallet_state_manager.get_wallet(id=wallet_id, required_type=CATWallet)
await wallet.set_name(str(request["name"]))
return {"wallet_id": wallet_id}
@marshal
async def cat_set_name(self, request: CATSetName) -> CATSetNameResponse:
wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=CATWallet)
await wallet.set_name(request.name)
return CATSetNameResponse(wallet_id=request.wallet_id)
async def cat_get_name(self, request: dict[str, Any]) -> EndpointResult:
wallet_id = uint32(request["wallet_id"])
wallet = self.service.wallet_state_manager.get_wallet(id=wallet_id, required_type=CATWallet)
@marshal
async def cat_get_name(self, request: CATGetName) -> CATGetNameResponse:
wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=CATWallet)
name: str = wallet.get_name()
return {"wallet_id": wallet_id, "name": name}
return CATGetNameResponse(wallet_id=request.wallet_id, name=name)
async def get_stray_cats(self, request: dict[str, Any]) -> EndpointResult:
@marshal
async def get_stray_cats(self, request: Empty) -> GetStrayCATsResponse:
"""
Get a list of all unacknowledged CATs
:param request: RPC request
:return: A list of unacknowledged CATs
"""
cats = await self.service.wallet_state_manager.interested_store.get_unacknowledged_tokens()
return {"stray_cats": cats}
return GetStrayCATsResponse(stray_cats=[StrayCAT.from_json_dict(cat) for cat in cats])
@tx_endpoint(push=True)
async def cat_spend(
@@ -2208,21 +2225,22 @@ class WalletRpcApi:
"transaction_id": None, # tx_endpoint wrapper will take care of this
}
async def cat_get_asset_id(self, request: dict[str, Any]) -> EndpointResult:
wallet_id = uint32(request["wallet_id"])
wallet = self.service.wallet_state_manager.get_wallet(id=wallet_id, required_type=CATWallet)
@marshal
async def cat_get_asset_id(self, request: CATGetAssetID) -> CATGetAssetIDResponse:
wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=CATWallet)
asset_id: str = wallet.get_asset_id()
return {"asset_id": asset_id, "wallet_id": wallet_id}
return CATGetAssetIDResponse(asset_id=bytes32.from_hexstr(asset_id), wallet_id=request.wallet_id)
async def cat_asset_id_to_name(self, request: dict[str, Any]) -> EndpointResult:
wallet = await self.service.wallet_state_manager.get_wallet_for_asset_id(request["asset_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.hex())
if wallet is None:
if request["asset_id"] in DEFAULT_CATS:
return {"wallet_id": None, "name": DEFAULT_CATS[request["asset_id"]]["name"]}
if request.asset_id.hex() in DEFAULT_CATS:
return CATAssetIDToNameResponse(wallet_id=None, name=DEFAULT_CATS[request.asset_id.hex()]["name"])
else:
raise ValueError("The asset ID specified does not belong to a wallet")
return CATAssetIDToNameResponse(wallet_id=None, name=None)
else:
return {"wallet_id": wallet.id(), "name": (wallet.get_name())}
return CATAssetIDToNameResponse(wallet_id=wallet.id(), name=wallet.get_name())
@tx_endpoint(push=False)
async def create_offer_for_ids(
@@ -2346,15 +2364,14 @@ class WalletRpcApi:
},
}
async def check_offer_validity(self, request: dict[str, Any]) -> EndpointResult:
offer_hex: str = request["offer"]
offer = Offer.from_bech32(offer_hex)
@marshal
async def check_offer_validity(self, request: CheckOfferValidity) -> CheckOfferValidityResponse:
offer = Offer.from_bech32(request.offer)
peer = self.service.get_full_node_peer()
return {
"valid": (await self.service.wallet_state_manager.trade_manager.check_offer_validity(offer, peer)),
"id": offer.name(),
}
return CheckOfferValidityResponse(
valid=(await self.service.wallet_state_manager.trade_manager.check_offer_validity(offer, peer)),
id=offer.name(),
)
@tx_endpoint(push=True)
async def take_offer(
@@ -2440,12 +2457,15 @@ class WalletRpcApi:
return {"trade_records": result, "offers": offer_values}
async def get_offers_count(self, request: dict[str, Any]) -> EndpointResult:
@marshal
async def get_offers_count(self, request: Empty) -> GetOffersCountResponse:
trade_mgr = self.service.wallet_state_manager.trade_manager
(total, my_offers_count, taken_offers_count) = await trade_mgr.trade_store.get_trades_count()
return {"total": total, "my_offers_count": my_offers_count, "taken_offers_count": taken_offers_count}
return GetOffersCountResponse(
total=uint16(total), my_offers_count=uint16(my_offers_count), taken_offers_count=uint16(taken_offers_count)
)
@tx_endpoint(push=True)
async def cancel_offer(
+26 -31
View File
@@ -1,6 +1,6 @@
from __future__ import annotations
from typing import Any, Optional, Union, cast
from typing import Any, Optional, Union
from chia_rs.sized_bytes import bytes32
from chia_rs.sized_ints import uint32, uint64
@@ -24,9 +24,19 @@ from chia.wallet.wallet_request_types import (
ApplySignaturesResponse,
CancelOfferResponse,
CancelOffersResponse,
CATAssetIDToName,
CATAssetIDToNameResponse,
CATGetAssetID,
CATGetAssetIDResponse,
CATGetName,
CATGetNameResponse,
CATSetName,
CATSetNameResponse,
CATSpendResponse,
CheckDeleteKey,
CheckDeleteKeyResponse,
CheckOfferValidity,
CheckOfferValidityResponse,
CombineCoins,
CombineCoinsResponse,
CreateNewDL,
@@ -102,6 +112,7 @@ from chia.wallet.wallet_request_types import (
GetPublicKeysResponse,
GetSpendableCoins,
GetSpendableCoinsResponse,
GetStrayCATsResponse,
GetSyncStatusResponse,
GetTimestampForHeight,
GetTimestampForHeightResponse,
@@ -624,37 +635,20 @@ class WalletRpcClient(RpcClient):
request = {"wallet_type": "cat_wallet", "asset_id": asset_id.hex(), "mode": "existing"}
return await self.fetch("create_new_wallet", request)
async def get_cat_asset_id(self, wallet_id: int) -> bytes32:
request = {"wallet_id": wallet_id}
return bytes32.from_hexstr((await self.fetch("cat_get_asset_id", request))["asset_id"])
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) -> list[dict[str, Any]]:
response = await self.fetch("get_stray_cats", {})
# TODO: casting due to lack of type checked deserialization
return cast(list[dict[str, Any]], response["stray_cats"])
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, asset_id: bytes32) -> Optional[tuple[Optional[uint32], str]]:
request = {"asset_id": asset_id.hex()}
try:
res = await self.fetch("cat_asset_id_to_name", request)
except ValueError: # This happens if the asset_id is unknown
return None
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()))
wallet_id: Optional[uint32] = None if res["wallet_id"] is None else uint32(res["wallet_id"])
return wallet_id, res["name"]
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 get_cat_name(self, wallet_id: int) -> str:
request = {"wallet_id": wallet_id}
response = await self.fetch("cat_get_name", request)
# TODO: casting due to lack of type checked deserialization
return cast(str, response["name"])
async def set_cat_name(self, wallet_id: int, name: str) -> None:
request: dict[str, Any] = {
"wallet_id": wallet_id,
"name": name,
}
await self.fetch("cat_set_name", request)
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,
@@ -736,9 +730,10 @@ class WalletRpcClient(RpcClient):
res = await self.fetch("get_offer_summary", {"offer": offer.to_bech32(), "advanced": advanced})
return bytes32.from_hexstr(res["id"]), res["summary"]
async def check_offer_validity(self, offer: Offer) -> tuple[bytes32, bool]:
res = await self.fetch("check_offer_validity", {"offer": offer.to_bech32()})
return bytes32.from_hexstr(res["id"]), res["valid"]
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,