Skip to content

Commit c03c0b9

Browse files
committed
Port create_offer_for_ids to @marshal
1 parent dfceb28 commit c03c0b9

File tree

9 files changed

+177
-140
lines changed

9 files changed

+177
-140
lines changed

chia/_tests/wallet/rpc/test_wallet_rpc.py

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
from chia.wallet.derive_keys import master_sk_to_wallet_sk, master_sk_to_wallet_sk_unhardened
8181
from chia.wallet.did_wallet.did_wallet import DIDWallet
8282
from chia.wallet.nft_wallet.nft_wallet import NFTWallet
83+
from chia.wallet.puzzle_drivers import PuzzleInfo
8384
from chia.wallet.puzzles.clawback.metadata import AutoClaimSettings
8485
from chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle import puzzle_hash_for_pk
8586
from chia.wallet.signer_protocol import UnsignedTransaction
@@ -113,6 +114,7 @@
113114
CheckOfferValidity,
114115
ClawbackPuzzleDecoratorOverride,
115116
CombineCoins,
117+
CreateOfferForIDs,
116118
DefaultCAT,
117119
DeleteKey,
118120
DeleteNotifications,
@@ -1546,28 +1548,29 @@ async def test_offer_endpoints(wallet_environments: WalletTestFramework, wallet_
15461548
)
15471549
# Create an offer of 5 chia for one CAT
15481550
await env_1.rpc_client.create_offer_for_ids(
1549-
{uint32(1): -5, cat_asset_id.hex(): 1}, wallet_environments.tx_config, validate_only=True
1551+
CreateOfferForIDs(offer={str(1): "-5", cat_asset_id.hex(): "1"}, validate_only=True),
1552+
tx_config=wallet_environments.tx_config,
15501553
)
15511554
all_offers = await env_1.rpc_client.get_all_offers()
15521555
assert len(all_offers) == 0
15531556

1554-
driver_dict: dict[str, Any] = {
1555-
cat_asset_id.hex(): {
1556-
"type": "CAT",
1557-
"tail": "0x" + cat_asset_id.hex(),
1558-
**(
1559-
{}
1560-
if wallet_type is CATWallet
1561-
else {"also": {"type": "revocation layer", "hidden_puzzle_hash": "0x" + bytes32.zeros.hex()}}
1562-
),
1563-
}
1557+
driver_dict = {
1558+
cat_asset_id: PuzzleInfo(
1559+
{
1560+
"type": "CAT",
1561+
"tail": "0x" + cat_asset_id.hex(),
1562+
**(
1563+
{}
1564+
if wallet_type is CATWallet
1565+
else {"also": {"type": "revocation layer", "hidden_puzzle_hash": "0x" + bytes32.zeros.hex()}}
1566+
),
1567+
}
1568+
)
15641569
}
15651570

15661571
create_res = await env_1.rpc_client.create_offer_for_ids(
1567-
{uint32(1): -5, cat_asset_id.hex(): 1},
1568-
wallet_environments.tx_config,
1569-
driver_dict=driver_dict,
1570-
fee=uint64(1),
1572+
CreateOfferForIDs(offer={str(1): "-5", cat_asset_id.hex(): "1"}, driver_dict=driver_dict, fee=uint64(1)),
1573+
tx_config=wallet_environments.tx_config,
15711574
)
15721575
offer = create_res.offer
15731576

@@ -1578,7 +1581,7 @@ async def test_offer_endpoints(wallet_environments: WalletTestFramework, wallet_
15781581
assert summary == {
15791582
"offered": {"xch": 5},
15801583
"requested": {cat_asset_id.hex(): 1},
1581-
"infos": driver_dict,
1584+
"infos": {key.hex(): info.info for key, info in driver_dict.items()},
15821585
"fees": 1,
15831586
"additions": [c.name().hex() for c in offer.additions()],
15841587
"removals": [c.name().hex() for c in offer.removals()],
@@ -1622,7 +1625,8 @@ async def test_offer_endpoints(wallet_environments: WalletTestFramework, wallet_
16221625
assert TradeStatus(trade_record.status) == TradeStatus.PENDING_CANCEL
16231626

16241627
create_res = await env_1.rpc_client.create_offer_for_ids(
1625-
{uint32(1): -5, cat_wallet_id: 1}, wallet_environments.tx_config, fee=uint64(1)
1628+
CreateOfferForIDs(offer={str(1): "-5", str(cat_wallet_id): "1"}, fee=uint64(1)),
1629+
tx_config=wallet_environments.tx_config,
16261630
)
16271631
all_offers = await env_1.rpc_client.get_all_offers()
16281632
assert len(all_offers) == 2
@@ -1736,9 +1740,8 @@ def only_ids(trades: list[TradeRecord]) -> list[bytes32]:
17361740
assert len(all_offers) == 2
17371741

17381742
await env_1.rpc_client.create_offer_for_ids(
1739-
{uint32(1): -5, cat_asset_id.hex(): 1},
1740-
wallet_environments.tx_config,
1741-
driver_dict=driver_dict,
1743+
CreateOfferForIDs(offer={str(1): "-5", cat_asset_id.hex(): "1"}, driver_dict=driver_dict),
1744+
tx_config=wallet_environments.tx_config,
17421745
)
17431746
assert (
17441747
len([o for o in await env_1.rpc_client.get_all_offers() if o.status == TradeStatus.PENDING_ACCEPT.value]) == 2
@@ -1774,14 +1777,12 @@ def only_ids(trades: list[TradeRecord]) -> list[bytes32]:
17741777
)
17751778

17761779
await env_1.rpc_client.create_offer_for_ids(
1777-
{uint32(1): -5, cat_asset_id.hex(): 1},
1778-
wallet_environments.tx_config,
1779-
driver_dict=driver_dict,
1780+
CreateOfferForIDs(offer={str(1): "-5", cat_asset_id.hex(): "1"}, driver_dict=driver_dict),
1781+
tx_config=wallet_environments.tx_config,
17801782
)
17811783
await env_1.rpc_client.create_offer_for_ids(
1782-
{uint32(1): 5, cat_asset_id.hex(): -1},
1783-
wallet_environments.tx_config,
1784-
driver_dict=driver_dict,
1784+
CreateOfferForIDs(offer={str(1): "5", cat_asset_id.hex(): "-1"}, driver_dict=driver_dict),
1785+
tx_config=wallet_environments.tx_config,
17851786
)
17861787
assert (
17871788
len([o for o in await env_1.rpc_client.get_all_offers() if o.status == TradeStatus.PENDING_ACCEPT.value]) == 2
@@ -1828,9 +1829,8 @@ def only_ids(trades: list[TradeRecord]) -> list[bytes32]:
18281829
)
18291830

18301831
await env_1.rpc_client.create_offer_for_ids(
1831-
{uint32(1): 5, cat_asset_id.hex(): -1},
1832-
wallet_environments.tx_config,
1833-
driver_dict=driver_dict,
1832+
CreateOfferForIDs(offer={str(1): "5", cat_asset_id.hex(): "-1"}, driver_dict=driver_dict),
1833+
tx_config=wallet_environments.tx_config,
18341834
)
18351835
assert (
18361836
len([o for o in await env_1.rpc_client.get_all_offers() if o.status == TradeStatus.PENDING_ACCEPT.value]) == 1
@@ -1846,9 +1846,11 @@ def only_ids(trades: list[TradeRecord]) -> list[bytes32]:
18461846

18471847
with pytest.raises(ValueError, match="not currently supported"):
18481848
await env_1.rpc_client.create_offer_for_ids(
1849-
{uint32(1): -5, cat_asset_id.hex(): 1},
1849+
CreateOfferForIDs(
1850+
offer={str(1): "-5", cat_asset_id.hex(): "1"},
1851+
driver_dict=driver_dict,
1852+
),
18501853
wallet_environments.tx_config,
1851-
driver_dict=driver_dict,
18521854
timelock_info=ConditionValidTimes(min_secs_since_created=uint64(1)),
18531855
)
18541856

chia/cmds/wallet_funcs.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
CATSpend,
5353
CATSpendResponse,
5454
ClawbackPuzzleDecoratorOverride,
55+
CreateOfferForIDs,
5556
DeleteNotifications,
5657
DeleteUnconfirmedTransactions,
5758
DIDFindLostDID,
@@ -507,16 +508,16 @@ async def make_offer(
507508
if offers == [] or requests == []:
508509
print("Not creating offer: Must be offering and requesting at least one asset")
509510
else:
510-
offer_dict: dict[Union[uint32, str], int] = {}
511-
driver_dict: dict[str, Any] = {}
511+
offer_dict: dict[str, str] = {}
512+
driver_dict: dict[bytes32, PuzzleInfo] = {}
512513
printable_dict: dict[str, tuple[str, int, int]] = {} # dict[asset_name, tuple[amount, unit, multiplier]]
513514
royalty_assets: list[RoyaltyAsset] = []
514515
fungible_assets: list[FungibleAsset] = []
515516
for item in [*offers, *requests]:
516517
name, amount = tuple(item.split(":")[0:2])
517518
try:
518519
b32_id = bytes32.from_hexstr(name)
519-
id: Union[uint32, str] = b32_id.hex()
520+
id: str = b32_id.hex()
520521
result = await wallet_client.cat_asset_id_to_name(CATAssetIDToName(b32_id))
521522
if result.name is not None:
522523
name = result.name
@@ -535,7 +536,7 @@ async def make_offer(
535536
id = info.launcher_id.hex()
536537
assert isinstance(id, str)
537538
if item in requests:
538-
driver_dict[id] = {
539+
puzzle_info_dict: dict[str, Any] = {
539540
"type": "singleton",
540541
"launcher_id": "0x" + id,
541542
"launcher_ph": "0x" + info.launcher_puzhash.hex(),
@@ -548,7 +549,7 @@ async def make_offer(
548549
if info.supports_did:
549550
assert info.royalty_puzzle_hash is not None
550551
assert info.royalty_percentage is not None
551-
driver_dict[id]["also"]["also"] = {
552+
puzzle_info_dict["also"]["also"] = {
552553
"type": "ownership",
553554
"owner": "()",
554555
"transfer_program": {
@@ -565,17 +566,18 @@ async def make_offer(
565566
info.royalty_percentage,
566567
)
567568
)
569+
driver_dict[info.launcher_id] = PuzzleInfo(puzzle_info_dict)
568570
else:
569571
id = decode_puzzle_hash(name).hex()
570572
assert hrp is not None
571573
unit = units[hrp]
572574
except ValueError:
573-
id = uint32(name)
574-
if id == 1:
575+
id = str(uint32(name))
576+
if id == "1":
575577
name = "XCH"
576578
unit = units["chia"]
577579
else:
578-
name = (await wallet_client.get_cat_name(CATGetName(id))).name
580+
name = (await wallet_client.get_cat_name(CATGetName(uint32(name)))).name
579581
unit = units["cat"]
580582
if item in offers:
581583
fungible_assets.append(FungibleAsset(name, uint64(abs(int(Decimal(amount) * unit)))))
@@ -585,7 +587,7 @@ async def make_offer(
585587
print("Not creating offer: Cannot offer and request the same asset in a trade")
586588
break
587589
else:
588-
offer_dict[id] = int(Decimal(amount) * unit) * multiplier
590+
offer_dict[id] = str(int(Decimal(amount) * unit) * multiplier)
589591
else:
590592
print("Creating Offer")
591593
print("--------------")
@@ -642,9 +644,11 @@ async def make_offer(
642644

643645
with filepath.open(mode="w") as file:
644646
res = await wallet_client.create_offer_for_ids(
645-
offer_dict,
646-
driver_dict=driver_dict,
647-
fee=fee,
647+
CreateOfferForIDs(
648+
offer=offer_dict,
649+
driver_dict=driver_dict,
650+
fee=fee,
651+
),
648652
tx_config=CMDTXConfigLoader(
649653
reuse_puzhash=reuse_puzhash,
650654
).to_tx_config(units["chia"], config, fingerprint),

chia/data_layer/data_layer.py

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,14 @@
6363
from chia.util.async_pool import Job, QueuedAsyncPool
6464
from chia.util.path import path_from_root
6565
from chia.util.task_referencer import create_referenced_task
66+
from chia.wallet.puzzle_drivers import Solver
6667
from chia.wallet.trade_record import TradeRecord
6768
from chia.wallet.trading.offer import Offer as TradingOffer
6869
from chia.wallet.transaction_record import TransactionRecord
6970
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
7071
from chia.wallet.wallet_request_types import (
7172
CreateNewDL,
73+
CreateOfferForIDs,
7274
DLDeleteMirror,
7375
DLGetMirrors,
7476
DLHistory,
@@ -1137,34 +1139,38 @@ async def make_offer(
11371139
async with self.data_store.transaction():
11381140
our_store_proofs = await self.process_offered_stores(offer_stores=maker)
11391141

1140-
offer_dict: dict[Union[uint32, str], int] = {
1141-
**{offer_store.store_id.hex(): -1 for offer_store in maker},
1142-
**{offer_store.store_id.hex(): 1 for offer_store in taker},
1142+
offer_dict: dict[str, str] = {
1143+
**{offer_store.store_id.hex(): "-1" for offer_store in maker},
1144+
**{offer_store.store_id.hex(): "1" for offer_store in taker},
11431145
}
11441146

1145-
solver: dict[str, Any] = {
1146-
"0x" + our_offer_store.store_id.hex(): {
1147-
"new_root": "0x" + our_store_proofs[our_offer_store.store_id].proofs[0].root().hex(),
1148-
"dependencies": [
1149-
{
1150-
"launcher_id": "0x" + their_offer_store.store_id.hex(),
1151-
"values_to_prove": [
1152-
"0x" + leaf_hash(key=entry.key, value=entry.value).hex()
1153-
for entry in their_offer_store.inclusions
1154-
],
1155-
}
1156-
for their_offer_store in taker
1157-
],
1147+
solver = Solver(
1148+
{
1149+
"0x" + our_offer_store.store_id.hex(): {
1150+
"new_root": "0x" + our_store_proofs[our_offer_store.store_id].proofs[0].root().hex(),
1151+
"dependencies": [
1152+
{
1153+
"launcher_id": "0x" + their_offer_store.store_id.hex(),
1154+
"values_to_prove": [
1155+
"0x" + leaf_hash(key=entry.key, value=entry.value).hex()
1156+
for entry in their_offer_store.inclusions
1157+
],
1158+
}
1159+
for their_offer_store in taker
1160+
],
1161+
}
1162+
for our_offer_store in maker
11581163
}
1159-
for our_offer_store in maker
1160-
}
1164+
)
11611165

11621166
res = await self.wallet_rpc.create_offer_for_ids(
1163-
offer_dict=offer_dict,
1164-
solver=solver,
1165-
driver_dict={},
1166-
fee=fee,
1167-
validate_only=False,
1167+
CreateOfferForIDs(
1168+
offer=offer_dict,
1169+
solver=solver,
1170+
driver_dict={},
1171+
fee=fee,
1172+
validate_only=False,
1173+
),
11681174
# TODO: probably shouldn't be default but due to peculiarities in the RPC, we're using a stop gap.
11691175
# This is not a change in behavior, the default was already implicit.
11701176
tx_config=DEFAULT_TX_CONFIG,

chia/util/streamable.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ def recurse_jsonify(
288288
"""
289289
if next_recursion_step is None:
290290
next_recursion_step = recurse_jsonify
291+
if getattr(d, "json_serialization_override", None) is not None:
292+
return d.json_serialization_override(d)
291293
if dataclasses.is_dataclass(d):
292294
new_dict = {}
293295
for field in dataclasses.fields(d):

chia/wallet/puzzle_drivers.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from __future__ import annotations
22

3-
from dataclasses import dataclass
4-
from typing import Any, Optional
3+
from typing import Any, Optional, Self
54

65
from clvm.SExp import SExp
76
from clvm_tools.binutils import assemble, type_for_atom
@@ -17,7 +16,6 @@
1716
"""
1817

1918

20-
@dataclass(frozen=True)
2119
class PuzzleInfo:
2220
"""
2321
There are two 'magic' keys in a PuzzleInfo object:
@@ -27,6 +25,10 @@ class PuzzleInfo:
2725

2826
info: dict[str, Any]
2927

28+
def __init__(self, info: dict[str, Any]) -> None:
29+
self.info = info
30+
self.__post_init__()
31+
3032
def __post_init__(self) -> None:
3133
if "type" not in self.info:
3234
raise ValueError("A type is required to initialize a puzzle driver")
@@ -74,11 +76,25 @@ def check_type(self, types: list[str]) -> bool:
7476
else:
7577
return False
7678

79+
# Methods to make this a valid Streamable member
80+
# Should not be being serialized as bytes
81+
stream = None
82+
parse = None
83+
84+
def to_json_dict(self) -> dict[str, Any]:
85+
return self.info
86+
87+
@classmethod
88+
def from_json_dict(cls, json_dict: dict[str, Any]) -> Self:
89+
return cls(json_dict)
90+
7791

78-
@dataclass(frozen=True)
7992
class Solver:
8093
info: dict[str, Any]
8194

95+
def __init__(self, info: dict[str, Any]) -> None:
96+
self.info = info
97+
8298
def __getitem__(self, item: str) -> Any:
8399
value = self.info[item]
84100
return decode_info_value(Solver, value)
@@ -92,6 +108,17 @@ def __eq__(self, other: object) -> bool:
92108
return False
93109
return True
94110

111+
# Methods to make this a valid Streamable member
112+
stream = None
113+
parse = None
114+
115+
def to_json_dict(self) -> dict[str, Any]:
116+
return self.info
117+
118+
@classmethod
119+
def from_json_dict(cls, json_dict: dict[str, Any]) -> Self:
120+
return cls(json_dict)
121+
95122

96123
def decode_info_value(cls: Any, value: Any) -> Any:
97124
if isinstance(value, dict):

chia/wallet/trade_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ async def create_offer_for_ids(
429429
validate_only: bool = False,
430430
extra_conditions: tuple[Condition, ...] = tuple(),
431431
taking: bool = False,
432-
) -> Union[tuple[Literal[True], TradeRecord, None], tuple[Literal[False], None, str]]:
432+
) -> tuple[Literal[True], TradeRecord, None]:
433433
if driver_dict is None:
434434
driver_dict = {}
435435
if solver is None:

0 commit comments

Comments
 (0)