Compare commits
5 Commits
main
...
quex.explo
Author | SHA1 | Date |
---|---|---|
Matt Hauff | b71466f427 | |
Matt Hauff | 2d94ae765d | |
Matt Hauff | f13eb468b3 | |
Matt Hauff | b849d4bf09 | |
Matt Hauff | dbcc201cf8 |
|
@ -1,13 +1,17 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import logging
|
||||
import traceback
|
||||
from contextlib import asynccontextmanager
|
||||
from decimal import Decimal
|
||||
from pathlib import Path
|
||||
from typing import Any, AsyncIterator, Awaitable, Callable, Dict, List, Optional, Tuple, Type, TypeVar
|
||||
|
||||
import click
|
||||
from aiohttp import ClientConnectorError
|
||||
|
||||
from chia.consensus.default_constants import DEFAULT_CONSTANTS
|
||||
from chia.daemon.keychain_proxy import KeychainProxy, connect_to_keychain_and_validate
|
||||
from chia.rpc.data_layer_rpc_client import DataLayerRpcClient
|
||||
from chia.rpc.farmer_rpc_client import FarmerRpcClient
|
||||
|
@ -20,9 +24,11 @@ from chia.types.blockchain_format.sized_bytes import bytes32
|
|||
from chia.types.mempool_submission_status import MempoolSubmissionStatus
|
||||
from chia.util.config import load_config
|
||||
from chia.util.default_root import DEFAULT_ROOT_PATH
|
||||
from chia.util.ints import uint16
|
||||
from chia.util.ints import uint16, uint64
|
||||
from chia.util.keychain import KeyData
|
||||
from chia.util.streamable import Streamable, streamable
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.tx_config import CoinSelectionConfig, CoinSelectionConfigLoader, TXConfig, TXConfigLoader
|
||||
|
||||
NODE_TYPES: Dict[str, Type[RpcClient]] = {
|
||||
"farmer": FarmerRpcClient,
|
||||
|
@ -222,3 +228,93 @@ async def execute_with_wallet(
|
|||
return
|
||||
|
||||
await function(extra_params, wallet_client, new_fp)
|
||||
|
||||
|
||||
def coin_selection_args(func: Callable[..., None]) -> Callable[..., None]:
|
||||
return click.option(
|
||||
"-ma",
|
||||
"--min-coin-amount",
|
||||
"--min-amount",
|
||||
help="Ignore coins worth less then this much XCH or CAT units",
|
||||
type=str,
|
||||
required=False,
|
||||
default=None,
|
||||
)(
|
||||
click.option(
|
||||
"-l",
|
||||
"--max-coin-amount",
|
||||
"--max-amount",
|
||||
help="Ignore coins worth more then this much XCH or CAT units",
|
||||
type=str,
|
||||
required=False,
|
||||
default=None,
|
||||
)(
|
||||
click.option(
|
||||
"--exclude-coin",
|
||||
"coins_to_exclude",
|
||||
multiple=True,
|
||||
help="Exclude this coin from being spent.",
|
||||
)(
|
||||
click.option(
|
||||
"--exclude-amount",
|
||||
"amounts_to_exclude",
|
||||
multiple=True,
|
||||
help="Exclude any coins with this XCH or CAT amount from being included.",
|
||||
)(func)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def tx_config_args(func: Callable[..., None]) -> Callable[..., None]:
|
||||
return click.option(
|
||||
"--reuse/--new-address",
|
||||
"--reuse-puzhash/--generate-new-puzhash",
|
||||
help="Reuse existing address for the change.",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
)(coin_selection_args(func))
|
||||
|
||||
|
||||
@streamable
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class CMDCoinSelectionConfigLoader(Streamable):
|
||||
min_coin_amount: Optional[str] = None
|
||||
max_coin_amount: Optional[str] = None
|
||||
excluded_coin_amounts: Optional[List[str]] = None
|
||||
excluded_coin_ids: Optional[List[bytes32]] = None
|
||||
|
||||
def to_coin_selection_config(self, mojo_per_unit: int) -> CoinSelectionConfig:
|
||||
return CoinSelectionConfigLoader(
|
||||
uint64(int(Decimal(self.min_coin_amount) * mojo_per_unit)) if self.min_coin_amount is not None else None,
|
||||
uint64(int(Decimal(self.max_coin_amount) * mojo_per_unit)) if self.max_coin_amount is not None else None,
|
||||
[uint64(int(Decimal(amount) * mojo_per_unit)) for amount in self.excluded_coin_amounts]
|
||||
if self.excluded_coin_amounts is not None
|
||||
else None,
|
||||
self.excluded_coin_ids,
|
||||
).autofill(DEFAULT_CONSTANTS)
|
||||
|
||||
|
||||
@streamable
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class CMDTXConfigLoader(Streamable):
|
||||
min_coin_amount: Optional[str] = None
|
||||
max_coin_amount: Optional[str] = None
|
||||
excluded_coin_amounts: Optional[List[str]] = None
|
||||
excluded_coin_ids: Optional[List[bytes32]] = None
|
||||
reuse_puzhash: Optional[bool] = None
|
||||
|
||||
def to_tx_config(self, mojo_per_unit: int, config: Dict[str, Any], fingerprint: int) -> TXConfig:
|
||||
return TXConfigLoader.from_json_dict(
|
||||
{
|
||||
"reuse_puzhash": self.reuse_puzhash,
|
||||
**CMDCoinSelectionConfigLoader(
|
||||
self.min_coin_amount,
|
||||
self.max_coin_amount,
|
||||
self.excluded_coin_amounts,
|
||||
self.excluded_coin_ids,
|
||||
)
|
||||
.to_coin_selection_config(mojo_per_unit)
|
||||
.to_json_dict(),
|
||||
}
|
||||
).autofill(config, fingerprint, DEFAULT_CONSTANTS)
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import sys
|
||||
from decimal import Decimal
|
||||
from typing import Any, Dict, List, Tuple, Union
|
||||
|
||||
from chia.cmds.cmd_utils import CMDCoinSelectionConfigLoader, CMDTXConfigLoader
|
||||
from chia.cmds.units import units
|
||||
from chia.cmds.wallet_funcs import get_mojo_per_unit, get_wallet_type, print_balance
|
||||
from chia.rpc.wallet_rpc_client import WalletRpcClient
|
||||
from chia.server.start_wallet import SERVICE_NAME
|
||||
from chia.types.blockchain_format.coin import Coin
|
||||
from chia.types.blockchain_format.sized_bytes import bytes32
|
||||
from chia.types.coin_record import CoinRecord
|
||||
from chia.util.bech32m import decode_puzzle_hash, encode_puzzle_hash
|
||||
from chia.util.config import load_config
|
||||
from chia.util.default_root import DEFAULT_ROOT_PATH
|
||||
from chia.util.ints import uint64, uint128
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
|
@ -18,10 +23,6 @@ from chia.wallet.util.wallet_types import WalletType
|
|||
|
||||
async def async_list(args: Dict[str, Any], wallet_client: WalletRpcClient, fingerprint: int) -> None:
|
||||
wallet_id: int = args["id"]
|
||||
min_coin_amount = Decimal(args["min_coin_amount"])
|
||||
max_coin_amount = Decimal(args["max_coin_amount"])
|
||||
excluded_coin_ids = args["excluded_coin_ids"]
|
||||
excluded_amounts = args["excluded_amounts"]
|
||||
addr_prefix = args["addr_prefix"]
|
||||
show_unconfirmed = args["show_unconfirmed"]
|
||||
paginate = args["paginate"]
|
||||
|
@ -36,15 +37,9 @@ async def async_list(args: Dict[str, Any], wallet_client: WalletRpcClient, finge
|
|||
if not await wallet_client.get_synced():
|
||||
print("Wallet not synced. Please wait.")
|
||||
return
|
||||
final_min_coin_amount: uint64 = uint64(int(min_coin_amount * mojo_per_unit))
|
||||
final_max_coin_amount: uint64 = uint64(int(max_coin_amount * mojo_per_unit))
|
||||
final_excluded_amounts: List[uint64] = [uint64(int(Decimal(amount) * mojo_per_unit)) for amount in excluded_amounts]
|
||||
conf_coins, unconfirmed_removals, unconfirmed_additions = await wallet_client.get_spendable_coins(
|
||||
wallet_id=wallet_id,
|
||||
max_coin_amount=final_max_coin_amount,
|
||||
min_coin_amount=final_min_coin_amount,
|
||||
excluded_amounts=final_excluded_amounts,
|
||||
excluded_coin_ids=excluded_coin_ids,
|
||||
coin_selection_config=CMDCoinSelectionConfigLoader.from_json_dict(args).to_coin_selection_config(mojo_per_unit),
|
||||
)
|
||||
print(f"There are a total of {len(conf_coins) + len(unconfirmed_additions)} coins in wallet {wallet_id}.")
|
||||
print(f"{len(conf_coins)} confirmed coins.")
|
||||
|
@ -107,10 +102,7 @@ def print_coins(
|
|||
|
||||
async def async_combine(args: Dict[str, Any], wallet_client: WalletRpcClient, fingerprint: int) -> None:
|
||||
wallet_id: int = args["id"]
|
||||
min_coin_amount = Decimal(args["min_coin_amount"])
|
||||
excluded_amounts = args["excluded_amounts"]
|
||||
number_of_coins = args["number_of_coins"]
|
||||
max_amount = Decimal(args["max_amount"])
|
||||
target_coin_amount = Decimal(args["target_coin_amount"])
|
||||
target_coin_ids: List[bytes32] = [bytes32.from_hexstr(coin_id) for coin_id in args["target_coin_ids"]]
|
||||
largest = bool(args["largest"])
|
||||
|
@ -127,24 +119,25 @@ async def async_combine(args: Dict[str, Any], wallet_client: WalletRpcClient, fi
|
|||
print("Wallet not synced. Please wait.")
|
||||
return
|
||||
is_xch: bool = wallet_type == WalletType.STANDARD_WALLET # this lets us know if we are directly combining Chia
|
||||
final_max_amount = uint64(int(max_amount * mojo_per_unit)) if not target_coin_ids else uint64(0)
|
||||
final_min_coin_amount: uint64 = uint64(int(min_coin_amount * mojo_per_unit))
|
||||
final_excluded_amounts: List[uint64] = [uint64(int(Decimal(amount) * mojo_per_unit)) for amount in excluded_amounts]
|
||||
final_target_coin_amount = uint64(int(target_coin_amount * mojo_per_unit))
|
||||
config = load_config(DEFAULT_ROOT_PATH, "config.yaml", SERVICE_NAME)
|
||||
loaded_tx_config = CMDTXConfigLoader.from_json_dict(args).to_tx_config(mojo_per_unit, config, fingerprint)
|
||||
if final_target_coin_amount != 0: # if we have a set target, just use standard coin selection.
|
||||
removals: List[Coin] = await wallet_client.select_coins(
|
||||
amount=(final_target_coin_amount + final_fee) if is_xch else final_target_coin_amount,
|
||||
wallet_id=wallet_id,
|
||||
max_coin_amount=final_max_amount,
|
||||
min_coin_amount=final_min_coin_amount,
|
||||
excluded_amounts=final_excluded_amounts + [final_target_coin_amount], # dont reuse coins of same amount.
|
||||
coin_selection_config=dataclasses.replace(
|
||||
loaded_tx_config.coin_selection_config,
|
||||
excluded_coin_amounts=[
|
||||
*loaded_tx_config.coin_selection_config.excluded_coin_amounts,
|
||||
final_target_coin_amount,
|
||||
],
|
||||
), # dont reuse coins of same amount.
|
||||
)
|
||||
else:
|
||||
conf_coins, _, _ = await wallet_client.get_spendable_coins(
|
||||
wallet_id=wallet_id,
|
||||
max_coin_amount=final_max_amount,
|
||||
min_coin_amount=final_min_coin_amount,
|
||||
excluded_amounts=final_excluded_amounts,
|
||||
coin_selection_config=loaded_tx_config.coin_selection_config,
|
||||
)
|
||||
if len(target_coin_ids) > 0:
|
||||
conf_coins = [cr for cr in conf_coins if cr.name in target_coin_ids]
|
||||
|
@ -171,7 +164,7 @@ async def async_combine(args: Dict[str, Any], wallet_client: WalletRpcClient, fi
|
|||
target_ph: bytes32 = decode_puzzle_hash(await wallet_client.get_next_address(wallet_id, False))
|
||||
additions = [{"amount": (total_amount - final_fee) if is_xch else total_amount, "puzzle_hash": target_ph}]
|
||||
transaction: TransactionRecord = await wallet_client.send_transaction_multi(
|
||||
wallet_id, additions, removals, final_fee
|
||||
wallet_id, additions, loaded_tx_config, removals, final_fee
|
||||
)
|
||||
tx_id = transaction.name.hex()
|
||||
print(f"Transaction sent: {tx_id}")
|
||||
|
@ -216,8 +209,10 @@ async def async_split(args: Dict[str, Any], wallet_client: WalletRpcClient, fing
|
|||
# we always use new addresses
|
||||
target_ph: bytes32 = decode_puzzle_hash(await wallet_client.get_next_address(wallet_id, new_address=True))
|
||||
additions.append({"amount": final_amount_per_coin, "puzzle_hash": target_ph})
|
||||
config = load_config(DEFAULT_ROOT_PATH, "config.yaml", SERVICE_NAME)
|
||||
loaded_tx_config = CMDTXConfigLoader.from_json_dict(args).to_tx_config(mojo_per_unit, config, fingerprint)
|
||||
transaction: TransactionRecord = await wallet_client.send_transaction_multi(
|
||||
wallet_id, additions, [removal_coin_record.coin], final_fee
|
||||
wallet_id, additions, loaded_tx_config, [removal_coin_record.coin], final_fee
|
||||
)
|
||||
tx_id = transaction.name.hex()
|
||||
print(f"Transaction sent: {tx_id}")
|
||||
|
|
|
@ -5,7 +5,7 @@ from typing import List, Optional
|
|||
|
||||
import click
|
||||
|
||||
from chia.cmds.cmds_util import execute_with_wallet
|
||||
from chia.cmds.cmds_util import coin_selection_args, execute_with_wallet, tx_config_args
|
||||
from chia.util.config import load_config, selected_network_address_prefix
|
||||
|
||||
|
||||
|
@ -26,35 +26,12 @@ def coins_cmd(ctx: click.Context) -> None:
|
|||
@click.option("-f", "--fingerprint", help="Set the fingerprint to specify which key to use", type=int)
|
||||
@click.option("-i", "--id", help="Id of the wallet to use", type=int, default=1, show_default=True, required=True)
|
||||
@click.option("-u", "--show-unconfirmed", help="Separately display unconfirmed coins.", is_flag=True)
|
||||
@click.option(
|
||||
"--min-amount",
|
||||
help="Ignore coins worth less then this much XCH or CAT units",
|
||||
type=str,
|
||||
default="0",
|
||||
)
|
||||
@click.option(
|
||||
"--max-amount",
|
||||
help="Ignore coins worth more then this much XCH or CAT units",
|
||||
type=str,
|
||||
default="0",
|
||||
)
|
||||
@click.option(
|
||||
"--exclude-coin",
|
||||
"coins_to_exclude",
|
||||
multiple=True,
|
||||
help="prevent this coin from being included.",
|
||||
)
|
||||
@click.option(
|
||||
"--exclude-amount",
|
||||
"amounts_to_exclude",
|
||||
multiple=True,
|
||||
help="Exclude any coins with this XCH or CAT amount from being included.",
|
||||
)
|
||||
@click.option(
|
||||
"--paginate/--no-paginate",
|
||||
default=None,
|
||||
help="Prompt for each page of data. Defaults to true for interactive consoles, otherwise false.",
|
||||
)
|
||||
@coin_selection_args
|
||||
@click.pass_context
|
||||
def list_cmd(
|
||||
ctx: click.Context,
|
||||
|
@ -62,8 +39,8 @@ def list_cmd(
|
|||
fingerprint: int,
|
||||
id: int,
|
||||
show_unconfirmed: bool,
|
||||
min_amount: str,
|
||||
max_amount: str,
|
||||
min_coin_amount: str,
|
||||
max_coin_amount: str,
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
paginate: Optional[bool],
|
||||
|
@ -72,8 +49,8 @@ def list_cmd(
|
|||
address_prefix = selected_network_address_prefix(config)
|
||||
extra_params = {
|
||||
"id": id,
|
||||
"max_coin_amount": max_amount,
|
||||
"min_coin_amount": min_amount,
|
||||
"max_coin_amount": max_coin_amount,
|
||||
"min_coin_amount": min_coin_amount,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
"addr_prefix": address_prefix,
|
||||
|
@ -103,18 +80,6 @@ def list_cmd(
|
|||
type=str,
|
||||
default="0",
|
||||
)
|
||||
@click.option(
|
||||
"--min-amount",
|
||||
help="Ignore coins worth less then this much XCH or CAT units",
|
||||
type=str,
|
||||
default="0",
|
||||
)
|
||||
@click.option(
|
||||
"--exclude-amount",
|
||||
"amounts_to_exclude",
|
||||
multiple=True,
|
||||
help="Exclude any coins with this XCH or CAT amount from being included.",
|
||||
)
|
||||
@click.option(
|
||||
"-n",
|
||||
"--number-of-coins",
|
||||
|
@ -123,12 +88,6 @@ def list_cmd(
|
|||
show_default=True,
|
||||
help="The number of coins we are combining.",
|
||||
)
|
||||
@click.option(
|
||||
"--max-amount",
|
||||
help="Ignore coins worth more then this much XCH or CAT units",
|
||||
type=str,
|
||||
default="0", # 0 means no limit
|
||||
)
|
||||
@click.option(
|
||||
"-m",
|
||||
"--fee",
|
||||
|
@ -150,29 +109,34 @@ def list_cmd(
|
|||
default=False,
|
||||
help="Sort coins from largest to smallest or smallest to largest.",
|
||||
)
|
||||
@tx_config_args
|
||||
def combine_cmd(
|
||||
wallet_rpc_port: Optional[int],
|
||||
fingerprint: int,
|
||||
id: int,
|
||||
target_amount: str,
|
||||
min_amount: str,
|
||||
amounts_to_exclude: List[int],
|
||||
number_of_coins: int,
|
||||
max_amount: str,
|
||||
fee: str,
|
||||
input_coins: List[str],
|
||||
largest_first: bool,
|
||||
reuse: bool,
|
||||
min_coin_amount: str,
|
||||
max_coin_amount: str,
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None:
|
||||
extra_params = {
|
||||
"id": id,
|
||||
"target_coin_amount": target_amount,
|
||||
"min_coin_amount": min_amount,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
"number_of_coins": number_of_coins,
|
||||
"max_amount": max_amount,
|
||||
"fee": fee,
|
||||
"target_coin_ids": list(input_coins),
|
||||
"largest": largest_first,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"max_coin_amount": max_coin_amount,
|
||||
"min_coin_amount": min_coin_amount,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
}
|
||||
from .coin_funcs import async_combine
|
||||
|
||||
|
@ -213,6 +177,7 @@ def combine_cmd(
|
|||
required=True,
|
||||
)
|
||||
@click.option("-t", "--target-coin-id", type=str, required=True, help="The coin id of the coin we are splitting.")
|
||||
@tx_config_args
|
||||
def split_cmd(
|
||||
wallet_rpc_port: Optional[int],
|
||||
fingerprint: int,
|
||||
|
@ -221,6 +186,11 @@ def split_cmd(
|
|||
fee: str,
|
||||
amount_per_coin: str,
|
||||
target_coin_id: str,
|
||||
reuse: bool,
|
||||
min_coin_amount: str,
|
||||
max_coin_amount: str,
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None:
|
||||
extra_params = {
|
||||
"id": id,
|
||||
|
@ -228,6 +198,11 @@ def split_cmd(
|
|||
"fee": fee,
|
||||
"amount_per_coin": amount_per_coin,
|
||||
"target_coin_id": target_coin_id,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"max_coin_amount": max_coin_amount,
|
||||
"min_coin_amount": min_coin_amount,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
}
|
||||
from .coin_funcs import async_split
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ from typing import Any, Dict, List, Optional, Tuple
|
|||
import click
|
||||
|
||||
from chia.cmds.check_wallet_db import help_text as check_help_text
|
||||
from chia.cmds.cmds_util import execute_with_wallet
|
||||
from chia.cmds.cmds_util import execute_with_wallet, tx_config_args
|
||||
from chia.cmds.coins import coins_cmd
|
||||
from chia.cmds.plotnft import validate_fee
|
||||
from chia.wallet.transaction_sorting import SortKey
|
||||
|
@ -165,34 +165,6 @@ def get_transactions_cmd(
|
|||
@click.option(
|
||||
"-o", "--override", help="Submits transaction without checking for unusual values", is_flag=True, default=False
|
||||
)
|
||||
@click.option(
|
||||
"-ma",
|
||||
"--min-coin-amount",
|
||||
help="Ignore coins worth less then this much XCH or CAT units",
|
||||
type=str,
|
||||
required=False,
|
||||
default="0",
|
||||
)
|
||||
@click.option(
|
||||
"-l",
|
||||
"--max-coin-amount",
|
||||
help="Ignore coins worth more then this much XCH or CAT units",
|
||||
type=str,
|
||||
required=False,
|
||||
default="0",
|
||||
)
|
||||
@click.option(
|
||||
"--exclude-coin",
|
||||
"coins_to_exclude",
|
||||
multiple=True,
|
||||
help="Exclude this coin from being spent.",
|
||||
)
|
||||
@click.option(
|
||||
"--reuse",
|
||||
help="Reuse existing address for the change.",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
)
|
||||
@click.option(
|
||||
"--clawback_time",
|
||||
help="The seconds that the recipient needs to wait to claim the fund."
|
||||
|
@ -200,6 +172,7 @@ def get_transactions_cmd(
|
|||
type=int,
|
||||
default=0,
|
||||
)
|
||||
@tx_config_args
|
||||
def send_cmd(
|
||||
wallet_rpc_port: Optional[int],
|
||||
fingerprint: int,
|
||||
|
@ -209,12 +182,13 @@ def send_cmd(
|
|||
fee: str,
|
||||
address: str,
|
||||
override: bool,
|
||||
min_coin_amount: str,
|
||||
max_coin_amount: str,
|
||||
coins_to_exclude: Tuple[str],
|
||||
reuse: bool,
|
||||
clawback_time: int,
|
||||
) -> None: # pragma: no cover
|
||||
reuse: bool,
|
||||
min_amount: Optional[str],
|
||||
max_amount: Optional[str],
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None:
|
||||
extra_params = {
|
||||
"id": id,
|
||||
"amount": amount,
|
||||
|
@ -222,11 +196,12 @@ def send_cmd(
|
|||
"fee": fee,
|
||||
"address": address,
|
||||
"override": override,
|
||||
"min_coin_amount": min_coin_amount,
|
||||
"max_coin_amount": max_coin_amount,
|
||||
"excluded_coin_ids": list(coins_to_exclude),
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"clawback_time": clawback_time,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"min_coin_amount": min_amount,
|
||||
"max_coin_amount": max_amount,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
}
|
||||
import asyncio
|
||||
|
||||
|
@ -467,12 +442,7 @@ def add_token_cmd(wallet_rpc_port: Optional[int], asset_id: str, token_name: str
|
|||
@click.option(
|
||||
"-m", "--fee", help="A fee to add to the offer when it gets taken, in XCH", default="0", show_default=True
|
||||
)
|
||||
@click.option(
|
||||
"--reuse",
|
||||
help="Reuse existing address for the offer.",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
)
|
||||
@tx_config_args
|
||||
def make_offer_cmd(
|
||||
wallet_rpc_port: Optional[int],
|
||||
fingerprint: int,
|
||||
|
@ -481,6 +451,10 @@ def make_offer_cmd(
|
|||
filepath: str,
|
||||
fee: str,
|
||||
reuse: bool,
|
||||
min_amount: Optional[str],
|
||||
max_amount: Optional[str],
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None:
|
||||
extra_params = {
|
||||
"offers": offer,
|
||||
|
@ -488,6 +462,10 @@ def make_offer_cmd(
|
|||
"filepath": filepath,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"min_coin_amount": min_amount,
|
||||
"max_coin_amount": max_amount,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
}
|
||||
import asyncio
|
||||
|
||||
|
@ -557,12 +535,7 @@ def get_offers_cmd(
|
|||
@click.option(
|
||||
"-m", "--fee", help="The fee to use when pushing the completed offer, in XCH", default="0", show_default=True
|
||||
)
|
||||
@click.option(
|
||||
"--reuse",
|
||||
help="Reuse existing address for the offer.",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
)
|
||||
@tx_config_args
|
||||
def take_offer_cmd(
|
||||
path_or_hex: str,
|
||||
wallet_rpc_port: Optional[int],
|
||||
|
@ -570,12 +543,20 @@ def take_offer_cmd(
|
|||
examine_only: bool,
|
||||
fee: str,
|
||||
reuse: bool,
|
||||
min_amount: Optional[str],
|
||||
max_amount: Optional[str],
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None:
|
||||
extra_params = {
|
||||
"file": path_or_hex,
|
||||
"examine_only": examine_only,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"min_coin_amount": min_amount,
|
||||
"max_coin_amount": max_amount,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
}
|
||||
import asyncio
|
||||
|
||||
|
@ -755,20 +736,31 @@ def did_get_details_cmd(wallet_rpc_port: Optional[int], fingerprint: int, coin_i
|
|||
@click.option("-f", "--fingerprint", help="Set the fingerprint to specify which key to use", type=int)
|
||||
@click.option("-i", "--id", help="Id of the DID wallet to use", type=int, required=True)
|
||||
@click.option("-d", "--metadata", help="The new whole metadata in json format", type=str, required=True)
|
||||
@click.option(
|
||||
"--reuse",
|
||||
help="Reuse existing address for the change.",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
)
|
||||
@tx_config_args
|
||||
def did_update_metadata_cmd(
|
||||
wallet_rpc_port: Optional[int], fingerprint: int, id: int, metadata: str, reuse: bool
|
||||
wallet_rpc_port: Optional[int],
|
||||
fingerprint: int,
|
||||
id: int,
|
||||
metadata: str,
|
||||
reuse: bool,
|
||||
min_amount: Optional[str],
|
||||
max_amount: Optional[str],
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None:
|
||||
import asyncio
|
||||
|
||||
from .wallet_funcs import update_did_metadata
|
||||
|
||||
extra_params = {"did_wallet_id": id, "metadata": metadata, "reuse_puzhash": reuse}
|
||||
extra_params = {
|
||||
"did_wallet_id": id,
|
||||
"metadata": metadata,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"min_coin_amount": min_amount,
|
||||
"max_coin_amount": max_amount,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
}
|
||||
asyncio.run(execute_with_wallet(wallet_rpc_port, fingerprint, extra_params, update_did_metadata))
|
||||
|
||||
|
||||
|
@ -901,12 +893,7 @@ def did_message_spend_cmd(
|
|||
show_default=True,
|
||||
callback=validate_fee,
|
||||
)
|
||||
@click.option(
|
||||
"--reuse",
|
||||
help="Reuse existing address for the change.",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
)
|
||||
@tx_config_args
|
||||
def did_transfer_did(
|
||||
wallet_rpc_port: Optional[int],
|
||||
fingerprint: int,
|
||||
|
@ -915,6 +902,10 @@ def did_transfer_did(
|
|||
reset_recovery: bool,
|
||||
fee: str,
|
||||
reuse: bool,
|
||||
min_amount: Optional[str],
|
||||
max_amount: Optional[str],
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None:
|
||||
import asyncio
|
||||
|
||||
|
@ -926,6 +917,10 @@ def did_transfer_did(
|
|||
"target_address": target_address,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"min_coin_amount": min_amount,
|
||||
"max_coin_amount": max_amount,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
}
|
||||
asyncio.run(execute_with_wallet(wallet_rpc_port, fingerprint, extra_params, transfer_did))
|
||||
|
||||
|
@ -1015,12 +1010,7 @@ def nft_sign_message(wallet_rpc_port: Optional[int], fingerprint: int, nft_id: s
|
|||
default=0,
|
||||
show_default=True,
|
||||
)
|
||||
@click.option(
|
||||
"--reuse",
|
||||
help="Reuse existing address for the change.",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
)
|
||||
@tx_config_args
|
||||
def nft_mint_cmd(
|
||||
wallet_rpc_port: Optional[int],
|
||||
fingerprint: int,
|
||||
|
@ -1039,6 +1029,10 @@ def nft_mint_cmd(
|
|||
fee: str,
|
||||
royalty_percentage_fraction: int,
|
||||
reuse: bool,
|
||||
min_amount: Optional[str],
|
||||
max_amount: Optional[str],
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None:
|
||||
import asyncio
|
||||
|
||||
|
@ -1070,6 +1064,10 @@ def nft_mint_cmd(
|
|||
"fee": fee,
|
||||
"royalty_percentage": royalty_percentage_fraction,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"min_coin_amount": min_amount,
|
||||
"max_coin_amount": max_amount,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
}
|
||||
asyncio.run(execute_with_wallet(wallet_rpc_port, fingerprint, extra_params, mint_nft))
|
||||
|
||||
|
@ -1097,12 +1095,7 @@ def nft_mint_cmd(
|
|||
show_default=True,
|
||||
callback=validate_fee,
|
||||
)
|
||||
@click.option(
|
||||
"--reuse",
|
||||
help="Reuse existing address for the change.",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
)
|
||||
@tx_config_args
|
||||
def nft_add_uri_cmd(
|
||||
wallet_rpc_port: Optional[int],
|
||||
fingerprint: int,
|
||||
|
@ -1113,6 +1106,10 @@ def nft_add_uri_cmd(
|
|||
license_uri: str,
|
||||
fee: str,
|
||||
reuse: bool,
|
||||
min_amount: Optional[str],
|
||||
max_amount: Optional[str],
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None:
|
||||
import asyncio
|
||||
|
||||
|
@ -1126,6 +1123,10 @@ def nft_add_uri_cmd(
|
|||
"license_uri": license_uri,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"min_coin_amount": min_amount,
|
||||
"max_coin_amount": max_amount,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
}
|
||||
asyncio.run(execute_with_wallet(wallet_rpc_port, fingerprint, extra_params, add_uri_to_nft))
|
||||
|
||||
|
@ -1151,12 +1152,7 @@ def nft_add_uri_cmd(
|
|||
show_default=True,
|
||||
callback=validate_fee,
|
||||
)
|
||||
@click.option(
|
||||
"--reuse",
|
||||
help="Reuse existing address for the change.",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
)
|
||||
@tx_config_args
|
||||
def nft_transfer_cmd(
|
||||
wallet_rpc_port: Optional[int],
|
||||
fingerprint: int,
|
||||
|
@ -1165,6 +1161,10 @@ def nft_transfer_cmd(
|
|||
target_address: str,
|
||||
fee: str,
|
||||
reuse: bool,
|
||||
min_amount: Optional[str],
|
||||
max_amount: Optional[str],
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None:
|
||||
import asyncio
|
||||
|
||||
|
@ -1176,6 +1176,10 @@ def nft_transfer_cmd(
|
|||
"target_address": target_address,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"min_coin_amount": min_amount,
|
||||
"max_coin_amount": max_amount,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
}
|
||||
asyncio.run(execute_with_wallet(wallet_rpc_port, fingerprint, extra_params, transfer_nft))
|
||||
|
||||
|
@ -1220,12 +1224,7 @@ def nft_list_cmd(wallet_rpc_port: Optional[int], fingerprint: int, id: int) -> N
|
|||
show_default=True,
|
||||
callback=validate_fee,
|
||||
)
|
||||
@click.option(
|
||||
"--reuse",
|
||||
help="Reuse existing address for the change.",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
)
|
||||
@tx_config_args
|
||||
def nft_set_did_cmd(
|
||||
wallet_rpc_port: Optional[int],
|
||||
fingerprint: int,
|
||||
|
@ -1234,6 +1233,10 @@ def nft_set_did_cmd(
|
|||
nft_coin_id: str,
|
||||
fee: str,
|
||||
reuse: bool,
|
||||
min_amount: Optional[str],
|
||||
max_amount: Optional[str],
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None:
|
||||
import asyncio
|
||||
|
||||
|
@ -1245,6 +1248,10 @@ def nft_set_did_cmd(
|
|||
"nft_coin_id": nft_coin_id,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"min_coin_amount": min_amount,
|
||||
"max_coin_amount": max_amount,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
}
|
||||
asyncio.run(execute_with_wallet(wallet_rpc_port, fingerprint, extra_params, set_nft_did))
|
||||
|
||||
|
@ -1481,12 +1488,7 @@ def _get_vcs(
|
|||
)
|
||||
@click.option("-p", "--new-proof-hash", help="The new proof hash to update the VC to", type=str, required=True)
|
||||
@click.option("-m", "--fee", help="Blockchain fee for update transaction, in XCH", type=str, required=False)
|
||||
@click.option(
|
||||
"--reuse-puzhash/--generate-new-puzhash",
|
||||
help="Send the VC back to the same puzzle hash it came from (ignored if --new-puzhash is specified)",
|
||||
default=False,
|
||||
show_default=True,
|
||||
)
|
||||
@tx_config_args
|
||||
def _spend_vc(
|
||||
wallet_rpc_port: Optional[int],
|
||||
fingerprint: int,
|
||||
|
@ -1494,7 +1496,11 @@ def _spend_vc(
|
|||
new_puzhash: Optional[str],
|
||||
new_proof_hash: str,
|
||||
fee: str,
|
||||
reuse_puzhash: bool,
|
||||
reuse: bool,
|
||||
min_amount: Optional[str],
|
||||
max_amount: Optional[str],
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None: # pragma: no cover
|
||||
import asyncio
|
||||
|
||||
|
@ -1507,7 +1513,11 @@ def _spend_vc(
|
|||
"new_puzhash": new_puzhash,
|
||||
"new_proof_hash": new_proof_hash,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"min_coin_amount": min_amount,
|
||||
"max_coin_amount": max_amount,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
}
|
||||
asyncio.run(execute_with_wallet(wallet_rpc_port, fingerprint, extra_params, spend_vc))
|
||||
|
||||
|
@ -1593,19 +1603,18 @@ def _get_proofs_for_root(
|
|||
required=False,
|
||||
)
|
||||
@click.option("-m", "--fee", help="Blockchain fee for revocation transaction, in XCH", type=str, required=False)
|
||||
@click.option(
|
||||
"--reuse-puzhash/--generate-new-puzhash",
|
||||
help="Send the VC back to the same puzzle hash it came from (ignored if --new-puzhash is specified)",
|
||||
default=False,
|
||||
show_default=True,
|
||||
)
|
||||
@tx_config_args
|
||||
def _revoke_vc(
|
||||
wallet_rpc_port: Optional[int],
|
||||
fingerprint: int,
|
||||
parent_coin_id: Optional[str],
|
||||
vc_id: Optional[str],
|
||||
fee: str,
|
||||
reuse_puzhash: bool,
|
||||
reuse: bool,
|
||||
min_amount: Optional[str],
|
||||
max_amount: Optional[str],
|
||||
coins_to_exclude: List[str],
|
||||
amounts_to_exclude: List[int],
|
||||
) -> None: # pragma: no cover
|
||||
import asyncio
|
||||
|
||||
|
@ -1617,6 +1626,10 @@ def _revoke_vc(
|
|||
"parent_coin_id": parent_coin_id,
|
||||
"vc_id": vc_id,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
"reuse_puzhash": True if reuse else None,
|
||||
"min_coin_amount": min_amount,
|
||||
"max_coin_amount": max_amount,
|
||||
"excluded_coin_ids": coins_to_exclude,
|
||||
"excluded_amounts": amounts_to_exclude,
|
||||
}
|
||||
asyncio.run(execute_with_wallet(wallet_rpc_port, fingerprint, extra_params, revoke_vc))
|
||||
|
|
|
@ -10,7 +10,7 @@ from datetime import datetime
|
|||
from decimal import Decimal
|
||||
from typing import Any, Awaitable, Callable, Dict, List, Optional, Tuple, Union
|
||||
|
||||
from chia.cmds.cmds_util import transaction_status_msg, transaction_submitted_msg
|
||||
from chia.cmds.cmds_util import CMDTXConfigLoader, transaction_status_msg, transaction_submitted_msg
|
||||
from chia.cmds.peer_funcs import print_connections
|
||||
from chia.cmds.units import units
|
||||
from chia.rpc.wallet_rpc_client import WalletRpcClient
|
||||
|
@ -245,12 +245,10 @@ async def send(args: dict, wallet_client: WalletRpcClient, fingerprint: int) ->
|
|||
fee = Decimal(args["fee"])
|
||||
address = args["address"]
|
||||
override = args["override"]
|
||||
min_coin_amount = Decimal(args["min_coin_amount"])
|
||||
max_coin_amount = Decimal(args["max_coin_amount"])
|
||||
excluded_coin_ids: List[str] = args["excluded_coin_ids"]
|
||||
memo = args["memo"]
|
||||
reuse_puzhash = args["reuse_puzhash"]
|
||||
clawback_time_lock = args["clawback_time"]
|
||||
config = load_config(DEFAULT_ROOT_PATH, "config.yaml")
|
||||
tx_config = CMDTXConfigLoader.from_json_dict(args).to_tx_config(units["chia"], config, fingerprint)
|
||||
if memo is None:
|
||||
memos = None
|
||||
else:
|
||||
|
@ -277,20 +275,15 @@ async def send(args: dict, wallet_client: WalletRpcClient, fingerprint: int) ->
|
|||
|
||||
final_fee: uint64 = uint64(int(fee * units["chia"])) # fees are always in XCH mojos
|
||||
final_amount: uint64 = uint64(int(amount * mojo_per_unit))
|
||||
final_min_coin_amount: uint64 = uint64(int(min_coin_amount * mojo_per_unit))
|
||||
final_max_coin_amount: uint64 = uint64(int(max_coin_amount * mojo_per_unit))
|
||||
if typ == WalletType.STANDARD_WALLET:
|
||||
print("Submitting transaction...")
|
||||
res = await wallet_client.send_transaction(
|
||||
wallet_id,
|
||||
final_amount,
|
||||
address,
|
||||
tx_config,
|
||||
final_fee,
|
||||
memos,
|
||||
final_min_coin_amount,
|
||||
final_max_coin_amount,
|
||||
excluded_coin_ids=excluded_coin_ids,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
puzzle_decorator_override=[
|
||||
{"decorator": PuzzleDecoratorType.CLAWBACK.name, "clawback_timelock": clawback_time_lock}
|
||||
]
|
||||
|
@ -301,14 +294,11 @@ async def send(args: dict, wallet_client: WalletRpcClient, fingerprint: int) ->
|
|||
print("Submitting transaction...")
|
||||
res = await wallet_client.cat_spend(
|
||||
wallet_id,
|
||||
tx_config,
|
||||
final_amount,
|
||||
address,
|
||||
final_fee,
|
||||
memos,
|
||||
final_min_coin_amount,
|
||||
final_max_coin_amount,
|
||||
excluded_coin_ids=excluded_coin_ids,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
else:
|
||||
print("Only standard wallet and CAT wallets are supported")
|
||||
|
@ -381,7 +371,6 @@ async def make_offer(args: dict, wallet_client: WalletRpcClient, fingerprint: in
|
|||
requests: List[str] = args["requests"]
|
||||
filepath: str = args["filepath"]
|
||||
fee: int = int(Decimal(args["fee"]) * units["chia"])
|
||||
reuse_puzhash: Optional[bool] = args["reuse_puzhash"]
|
||||
config = load_config(DEFAULT_ROOT_PATH, "config.yaml")
|
||||
|
||||
if [] in [offers, requests]:
|
||||
|
@ -522,7 +511,10 @@ async def make_offer(args: dict, wallet_client: WalletRpcClient, fingerprint: in
|
|||
else:
|
||||
with open(pathlib.Path(filepath), "w") as file:
|
||||
offer, trade_record = await wallet_client.create_offer_for_ids(
|
||||
offer_dict, driver_dict=driver_dict, fee=fee, reuse_puzhash=reuse_puzhash
|
||||
offer_dict,
|
||||
CMDTXConfigLoader.from_json_dict(args).to_tx_config(units["chia"], config, fingerprint),
|
||||
driver_dict=driver_dict,
|
||||
fee=fee,
|
||||
)
|
||||
if offer is not None:
|
||||
file.write(offer.to_bech32())
|
||||
|
@ -751,7 +743,9 @@ async def take_offer(args: dict, wallet_client: WalletRpcClient, fingerprint: in
|
|||
print()
|
||||
confirmation = input("Would you like to take this offer? (y/n): ")
|
||||
if confirmation in ["y", "yes"]:
|
||||
trade_record = await wallet_client.take_offer(offer, fee=fee)
|
||||
trade_record = await wallet_client.take_offer(
|
||||
offer, CMDTXConfigLoader.from_json_dict(args).to_tx_config(units["chia"], config, fingerprint), fee=fee
|
||||
)
|
||||
print(f"Accepted offer with ID {trade_record.trade_id}")
|
||||
print(f"Use chia wallet get_offers --id {trade_record.trade_id} -f {fingerprint} to view its status")
|
||||
|
||||
|
@ -1021,6 +1015,7 @@ async def mint_nft(args: Dict, wallet_client: WalletRpcClient, fingerprint: int)
|
|||
target_address,
|
||||
hash,
|
||||
uris,
|
||||
CMDTXConfigLoader.from_json_dict(args).to_tx_config(units["chia"], config, fingerprint),
|
||||
metadata_hash,
|
||||
metadata_uris,
|
||||
license_hash,
|
||||
|
@ -1030,7 +1025,6 @@ async def mint_nft(args: Dict, wallet_client: WalletRpcClient, fingerprint: int)
|
|||
fee,
|
||||
royalty_percentage,
|
||||
did_id,
|
||||
reuse_puzhash=args["reuse_puzhash"],
|
||||
)
|
||||
spend_bundle = response["spend_bundle"]
|
||||
print(f"NFT minted Successfully with spend bundle: {spend_bundle}")
|
||||
|
@ -1076,7 +1070,11 @@ async def transfer_nft(args: Dict, wallet_client: WalletRpcClient, fingerprint:
|
|||
target_address = ensure_valid_address(args["target_address"], allowed_types={AddressType.XCH}, config=config)
|
||||
fee: int = int(Decimal(args["fee"]) * units["chia"])
|
||||
response = await wallet_client.transfer_nft(
|
||||
wallet_id, nft_coin_id, target_address, fee, reuse_puzhash=args["reuse_puzhash"]
|
||||
wallet_id,
|
||||
nft_coin_id,
|
||||
target_address,
|
||||
fee,
|
||||
CMDTXConfigLoader.from_json_dict(args).to_tx_config(units["chia"], config, fingerprint),
|
||||
)
|
||||
spend_bundle = response["spend_bundle"]
|
||||
print(f"NFT transferred successfully with spend bundle: {spend_bundle}")
|
||||
|
@ -1143,8 +1141,13 @@ async def set_nft_did(args: Dict, wallet_client: WalletRpcClient, fingerprint: i
|
|||
nft_coin_id = args["nft_coin_id"]
|
||||
fee: int = int(Decimal(args["fee"]) * units["chia"])
|
||||
try:
|
||||
config = load_config(DEFAULT_ROOT_PATH, "config.yaml", SERVICE_NAME)
|
||||
response = await wallet_client.set_nft_did(
|
||||
wallet_id, did_id, nft_coin_id, fee, reuse_puzhash=args["reuse_puzhash"]
|
||||
wallet_id,
|
||||
did_id,
|
||||
nft_coin_id,
|
||||
fee,
|
||||
CMDTXConfigLoader.from_json_dict(args).to_tx_config(units["chia"], config, fingerprint),
|
||||
)
|
||||
spend_bundle = response["spend_bundle"]
|
||||
print(f"Transaction to set DID on NFT has been initiated with: {spend_bundle}")
|
||||
|
@ -1337,10 +1340,10 @@ async def spend_vc(args: Dict, wallet_client: WalletRpcClient, fingerprint: int)
|
|||
config = load_config(DEFAULT_ROOT_PATH, "config.yaml", SERVICE_NAME)
|
||||
txs = await wallet_client.vc_spend(
|
||||
bytes32.from_hexstr(args["vc_id"]),
|
||||
CMDTXConfigLoader.from_json_dict(args).to_tx_config(units["chia"], config, fingerprint),
|
||||
new_puzhash=None if args["new_puzhash"] is None else bytes32.from_hexstr(args["new_puzhash"]),
|
||||
new_proof_hash=bytes32.from_hexstr(args["new_proof_hash"]),
|
||||
fee=uint64(0) if args["fee"] is None else uint64(int(Decimal(args["fee"]) * units["chia"])),
|
||||
reuse_puzhash=args["reuse_puzhash"],
|
||||
)
|
||||
|
||||
print("Proofs successfully updated!")
|
||||
|
@ -1393,8 +1396,8 @@ async def revoke_vc(args: Dict, wallet_client: WalletRpcClient, fingerprint: int
|
|||
parent_id = bytes32.from_hexstr(args["parent_coin_id"])
|
||||
txs = await wallet_client.vc_revoke(
|
||||
parent_id,
|
||||
CMDTXConfigLoader.from_json_dict(args).to_tx_config(units["chia"], config, fingerprint),
|
||||
fee=uint64(0) if args["fee"] is None else uint64(int(Decimal(args["fee"]) * units["chia"])),
|
||||
reuse_puzhash=args["reuse_puzhash"],
|
||||
)
|
||||
|
||||
print("VC successfully revoked!")
|
||||
|
|
|
@ -47,6 +47,7 @@ from chia.util.path import path_from_root
|
|||
from chia.wallet.trade_record import TradeRecord
|
||||
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
|
||||
|
||||
|
||||
async def get_plugin_info(url: str) -> Tuple[str, Dict[str, Any]]:
|
||||
|
@ -754,6 +755,9 @@ class DataLayer:
|
|||
driver_dict={},
|
||||
fee=fee,
|
||||
validate_only=False,
|
||||
# TODO: probably shouldn't be default but due to peculiarities in the RPC, we're using a stop gap.
|
||||
# This is not a change in behavior, the default was already implicit.
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
)
|
||||
if wallet_offer is None:
|
||||
raise Exception("offer is None despite validate_only=False")
|
||||
|
@ -838,6 +842,9 @@ class DataLayer:
|
|||
offer=offer,
|
||||
solver=solver,
|
||||
fee=fee,
|
||||
# TODO: probably shouldn't be default but due to peculiarities in the RPC, we're using a stop gap.
|
||||
# This is not a change in behavior, the default was already implicit.
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
)
|
||||
|
||||
return trade_record
|
||||
|
|
|
@ -51,6 +51,7 @@ from chia.wallet.transaction_record import TransactionRecord
|
|||
from chia.wallet.util.compute_memos import compute_memos
|
||||
from chia.wallet.util.merkle_utils import _simplify_merkle_proof
|
||||
from chia.wallet.util.transaction_type import TransactionType
|
||||
from chia.wallet.util.tx_config import CoinSelectionConfig, TXConfig, TXConfigLoader
|
||||
from chia.wallet.util.wallet_sync_utils import fetch_coin_spend, fetch_coin_spend_for_coin_state
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet import Wallet
|
||||
|
@ -289,20 +290,21 @@ class DataLayerWallet:
|
|||
async def generate_new_reporter(
|
||||
self,
|
||||
initial_root: bytes32,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
) -> Tuple[TransactionRecord, TransactionRecord, bytes32]:
|
||||
"""
|
||||
Creates the initial singleton, which includes spending an origin coin, the launcher, and creating a singleton
|
||||
"""
|
||||
|
||||
coins: Set[Coin] = await self.standard_wallet.select_coins(uint64(fee + 1))
|
||||
coins: Set[Coin] = await self.standard_wallet.select_coins(uint64(fee + 1), tx_config.coin_selection_config)
|
||||
if coins is None:
|
||||
raise ValueError("Not enough coins to create new data layer singleton")
|
||||
|
||||
launcher_parent: Coin = list(coins)[0]
|
||||
launcher_coin: Coin = Coin(launcher_parent.name(), SINGLETON_LAUNCHER.get_tree_hash(), uint64(1))
|
||||
|
||||
inner_puzzle: Program = await self.standard_wallet.get_new_puzzle()
|
||||
inner_puzzle: Program = await self.standard_wallet.get_puzzle(new=not tx_config.reuse_puzhash)
|
||||
full_puzzle: Program = create_host_fullpuz(inner_puzzle, initial_root, launcher_coin.name())
|
||||
|
||||
genesis_launcher_solution: Program = Program.to(
|
||||
|
@ -313,6 +315,7 @@ class DataLayerWallet:
|
|||
create_launcher_tx_record: Optional[TransactionRecord] = await self.standard_wallet.generate_signed_transaction(
|
||||
amount=uint64(1),
|
||||
puzzle_hash=SINGLETON_LAUNCHER.get_tree_hash(),
|
||||
tx_config=tx_config,
|
||||
fee=fee,
|
||||
origin_id=launcher_parent.name(),
|
||||
coins=coins,
|
||||
|
@ -375,11 +378,13 @@ class DataLayerWallet:
|
|||
self,
|
||||
fee: uint64,
|
||||
announcement_to_assert: Announcement,
|
||||
tx_config: TXConfig,
|
||||
coin_announcement: bool = True,
|
||||
) -> TransactionRecord:
|
||||
chia_tx = await self.standard_wallet.generate_signed_transaction(
|
||||
amount=uint64(0),
|
||||
puzzle_hash=await self.standard_wallet.get_new_puzzlehash(),
|
||||
puzzle_hash=await self.standard_wallet.get_puzzle_hash(new=not tx_config.reuse_puzhash),
|
||||
tx_config=tx_config,
|
||||
fee=fee,
|
||||
negative_change_allowed=False,
|
||||
coin_announcements_to_consume={announcement_to_assert} if coin_announcement else None,
|
||||
|
@ -392,6 +397,7 @@ class DataLayerWallet:
|
|||
self,
|
||||
launcher_id: bytes32,
|
||||
root_hash: Optional[bytes32],
|
||||
tx_config: TXConfig,
|
||||
new_puz_hash: Optional[bytes32] = None,
|
||||
new_amount: Optional[uint64] = None,
|
||||
fee: uint64 = uint64(0),
|
||||
|
@ -416,7 +422,7 @@ class DataLayerWallet:
|
|||
|
||||
# Make the child's puzzles
|
||||
if new_puz_hash is None:
|
||||
new_puz_hash = (await self.standard_wallet.get_new_puzzle()).get_tree_hash()
|
||||
new_puz_hash = await self.standard_wallet.get_puzzle_hash(new=not tx_config.reuse_puzhash)
|
||||
assert new_puz_hash is not None
|
||||
next_full_puz_hash: bytes32 = create_host_fullpuz(new_puz_hash, root_hash, launcher_id).get_tree_hash_precalc(
|
||||
new_puz_hash
|
||||
|
@ -595,7 +601,7 @@ class DataLayerWallet:
|
|||
assert dl_tx.spend_bundle is not None
|
||||
if fee > 0:
|
||||
chia_tx = await self.create_tandem_xch_tx(
|
||||
fee, Announcement(current_coin.name(), b"$"), coin_announcement=True
|
||||
fee, Announcement(current_coin.name(), b"$"), tx_config, coin_announcement=True
|
||||
)
|
||||
assert chia_tx.spend_bundle is not None
|
||||
aggregate_bundle = SpendBundle.aggregate([dl_tx.spend_bundle, chia_tx.spend_bundle])
|
||||
|
@ -620,6 +626,7 @@ class DataLayerWallet:
|
|||
self,
|
||||
amounts: List[uint64],
|
||||
puzzle_hashes: List[bytes32],
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
coins: Set[Coin] = set(),
|
||||
memos: Optional[List[List[bytes]]] = None, # ignored
|
||||
|
@ -655,6 +662,7 @@ class DataLayerWallet:
|
|||
return await self.create_update_state_spend(
|
||||
launcher_id,
|
||||
new_root_hash,
|
||||
tx_config,
|
||||
puzzle_hashes[0],
|
||||
amounts[0],
|
||||
fee,
|
||||
|
@ -720,11 +728,12 @@ class DataLayerWallet:
|
|||
return collected
|
||||
|
||||
async def create_new_mirror(
|
||||
self, launcher_id: bytes32, amount: uint64, urls: List[bytes], fee: uint64 = uint64(0)
|
||||
self, launcher_id: bytes32, amount: uint64, urls: List[bytes], tx_config: TXConfig, fee: uint64 = uint64(0)
|
||||
) -> List[TransactionRecord]:
|
||||
create_mirror_tx_record: Optional[TransactionRecord] = await self.standard_wallet.generate_signed_transaction(
|
||||
amount=amount,
|
||||
puzzle_hash=create_mirror_puzzle().get_tree_hash(),
|
||||
tx_config=tx_config,
|
||||
fee=fee,
|
||||
primaries=[],
|
||||
memos=[launcher_id, *(url for url in urls)],
|
||||
|
@ -734,7 +743,7 @@ class DataLayerWallet:
|
|||
return [create_mirror_tx_record]
|
||||
|
||||
async def delete_mirror(
|
||||
self, mirror_id: bytes32, peer: WSChiaConnection, fee: uint64 = uint64(0)
|
||||
self, mirror_id: bytes32, peer: WSChiaConnection, tx_config: TXConfig, fee: uint64 = uint64(0)
|
||||
) -> List[TransactionRecord]:
|
||||
mirror: Mirror = await self.get_mirror(mirror_id)
|
||||
mirror_coin: Coin = (await self.wallet_state_manager.wallet_node.get_coin_state([mirror.coin_id], peer=peer))[
|
||||
|
@ -752,7 +761,7 @@ class DataLayerWallet:
|
|||
await self.standard_wallet.hack_populate_secret_key_for_puzzle_hash(parent_coin.puzzle_hash)
|
||||
|
||||
parent_inner_puzzle: Program = self.standard_wallet.puzzle_for_pk(inner_puzzle_derivation.pubkey)
|
||||
new_puzhash: bytes32 = await self.get_new_puzzlehash()
|
||||
new_puzhash: bytes32 = await self.standard_wallet.get_puzzle_hash(new=not tx_config.reuse_puzhash)
|
||||
excess_fee: int = fee - mirror_coin.amount
|
||||
inner_sol: Program = self.standard_wallet.make_solution(
|
||||
primaries=[Payment(new_puzhash, uint64(mirror_coin.amount - fee))] if excess_fee < 0 else [],
|
||||
|
@ -796,6 +805,7 @@ class DataLayerWallet:
|
|||
chia_tx: TransactionRecord = await self.wallet_state_manager.main_wallet.generate_signed_transaction(
|
||||
uint64(1),
|
||||
new_puzhash,
|
||||
tx_config,
|
||||
fee=uint64(excess_fee),
|
||||
coin_announcements_to_consume={Announcement(mirror_coin.name(), b"$")},
|
||||
)
|
||||
|
@ -975,10 +985,17 @@ class DataLayerWallet:
|
|||
else:
|
||||
fee = uint64(0)
|
||||
|
||||
assert self.wallet_state_manager.wallet_node.logged_in_fingerprint is not None
|
||||
|
||||
all_txs.extend(
|
||||
await self.create_update_state_spend(
|
||||
launcher_id,
|
||||
singleton.root,
|
||||
TXConfigLoader().autofill(
|
||||
self.wallet_state_manager.config,
|
||||
self.wallet_state_manager.wallet_node.logged_in_fingerprint,
|
||||
self.wallet_state_manager.constants,
|
||||
),
|
||||
fee=fee,
|
||||
)
|
||||
)
|
||||
|
@ -1126,6 +1143,7 @@ class DataLayerWallet:
|
|||
offer_dict: Dict[Optional[bytes32], int],
|
||||
driver_dict: Dict[bytes32, PuzzleInfo],
|
||||
solver: Solver,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
old: bool = False,
|
||||
) -> Offer:
|
||||
|
@ -1146,10 +1164,11 @@ class DataLayerWallet:
|
|||
except KeyError:
|
||||
this_solver = solver["0x" + launcher.hex()]
|
||||
new_root: bytes32 = this_solver["new_root"]
|
||||
new_ph: bytes32 = await wallet_state_manager.main_wallet.get_new_puzzlehash()
|
||||
new_ph: bytes32 = await wallet_state_manager.main_wallet.get_puzzle_hash(new=not tx_config.reuse_puzhash)
|
||||
txs: List[TransactionRecord] = await dl_wallet.generate_signed_transaction(
|
||||
[uint64(1)],
|
||||
[new_ph],
|
||||
tx_config,
|
||||
fee=fee_left_to_pay,
|
||||
launcher_id=launcher,
|
||||
new_root_hash=new_root,
|
||||
|
@ -1302,10 +1321,7 @@ class DataLayerWallet:
|
|||
async def select_coins(
|
||||
self,
|
||||
amount: uint64,
|
||||
exclude: Optional[List[Coin]] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
coin_selection_config: CoinSelectionConfig,
|
||||
) -> Set[Coin]:
|
||||
raise RuntimeError("DataLayerWallet does not support select_coins()")
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ from chia.wallet.derive_keys import find_owner_sk
|
|||
from chia.wallet.sign_coin_spends import sign_coin_spends
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.transaction_type import TransactionType
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG, CoinSelectionConfig, TXConfig
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet import Wallet
|
||||
from chia.wallet.wallet_coin_record import WalletCoinRecord
|
||||
|
@ -75,6 +76,7 @@ class PoolWallet:
|
|||
standard_wallet: Wallet
|
||||
wallet_id: int
|
||||
next_transaction_fee: uint64 = uint64(0)
|
||||
next_tx_config: TXConfig = DEFAULT_TX_CONFIG
|
||||
target_state: Optional[PoolState] = None
|
||||
_owner_sk_and_index: Optional[Tuple[PrivateKey, uint32]] = None
|
||||
|
||||
|
@ -296,6 +298,7 @@ class PoolWallet:
|
|||
if self.target_state == latest_state:
|
||||
self.target_state = None
|
||||
self.next_transaction_fee = uint64(0)
|
||||
self.next_tx_config = DEFAULT_TX_CONFIG
|
||||
break
|
||||
|
||||
await self.update_pool_config()
|
||||
|
@ -390,6 +393,7 @@ class PoolWallet:
|
|||
wallet_state_manager: Any,
|
||||
main_wallet: Wallet,
|
||||
initial_target_state: PoolState,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
p2_singleton_delay_time: Optional[uint64] = None,
|
||||
p2_singleton_delayed_ph: Optional[bytes32] = None,
|
||||
|
@ -429,6 +433,7 @@ class PoolWallet:
|
|||
wallet_state_manager.constants.GENESIS_CHALLENGE,
|
||||
p2_singleton_delay_time,
|
||||
p2_singleton_delayed_ph,
|
||||
tx_config,
|
||||
)
|
||||
|
||||
if spend_bundle is None:
|
||||
|
@ -491,11 +496,13 @@ class PoolWallet:
|
|||
async def generate_fee_transaction(
|
||||
self,
|
||||
fee: uint64,
|
||||
tx_config: TXConfig,
|
||||
coin_announcements: Optional[Set[Announcement]] = None,
|
||||
) -> TransactionRecord:
|
||||
fee_tx = await self.standard_wallet.generate_signed_transaction(
|
||||
uint64(0),
|
||||
(await self.standard_wallet.get_new_puzzlehash()),
|
||||
tx_config,
|
||||
fee=fee,
|
||||
origin_id=None,
|
||||
coins=None,
|
||||
|
@ -516,7 +523,9 @@ class PoolWallet:
|
|||
if fee_tx is not None:
|
||||
await self.wallet_state_manager.add_pending_transaction(dataclasses.replace(fee_tx, spend_bundle=None))
|
||||
|
||||
async def generate_travel_transactions(self, fee: uint64) -> Tuple[TransactionRecord, Optional[TransactionRecord]]:
|
||||
async def generate_travel_transactions(
|
||||
self, fee: uint64, tx_config: TXConfig
|
||||
) -> Tuple[TransactionRecord, Optional[TransactionRecord]]:
|
||||
# target_state is contained within pool_wallet_state
|
||||
pool_wallet_info: PoolWalletInfo = await self.get_current_state()
|
||||
|
||||
|
@ -594,7 +603,7 @@ class PoolWallet:
|
|||
assert signed_spend_bundle is not None
|
||||
fee_tx: Optional[TransactionRecord] = None
|
||||
if fee > 0:
|
||||
fee_tx = await self.generate_fee_transaction(fee)
|
||||
fee_tx = await self.generate_fee_transaction(fee, tx_config)
|
||||
assert fee_tx.spend_bundle is not None
|
||||
signed_spend_bundle = SpendBundle.aggregate([signed_spend_bundle, fee_tx.spend_bundle])
|
||||
|
||||
|
@ -629,12 +638,13 @@ class PoolWallet:
|
|||
genesis_challenge: bytes32,
|
||||
delay_time: uint64,
|
||||
delay_ph: bytes32,
|
||||
tx_config: TXConfig,
|
||||
) -> Tuple[SpendBundle, bytes32, bytes32]:
|
||||
"""
|
||||
Creates the initial singleton, which includes spending an origin coin, the launcher, and creating a singleton
|
||||
with the "pooling" inner state, which can be either self pooling or using a pool
|
||||
"""
|
||||
coins: Set[Coin] = await standard_wallet.select_coins(uint64(amount + fee))
|
||||
coins: Set[Coin] = await standard_wallet.select_coins(uint64(amount + fee), tx_config.coin_selection_config)
|
||||
if coins is None:
|
||||
raise ValueError("Not enough coins to create pool wallet")
|
||||
|
||||
|
@ -680,6 +690,7 @@ class PoolWallet:
|
|||
create_launcher_tx_record: Optional[TransactionRecord] = await standard_wallet.generate_signed_transaction(
|
||||
amount,
|
||||
genesis_launcher_puz.get_tree_hash(),
|
||||
tx_config,
|
||||
fee,
|
||||
coins,
|
||||
None,
|
||||
|
@ -703,7 +714,7 @@ class PoolWallet:
|
|||
return full_spend, puzzle_hash, launcher_coin.name()
|
||||
|
||||
async def join_pool(
|
||||
self, target_state: PoolState, fee: uint64
|
||||
self, target_state: PoolState, fee: uint64, tx_config: TXConfig
|
||||
) -> Tuple[uint64, TransactionRecord, Optional[TransactionRecord]]:
|
||||
if target_state.state != FARMING_TO_POOL.value:
|
||||
raise ValueError(f"join_pool must be called with target_state={FARMING_TO_POOL} (FARMING_TO_POOL)")
|
||||
|
@ -745,10 +756,13 @@ class PoolWallet:
|
|||
|
||||
self.target_state = target_state
|
||||
self.next_transaction_fee = fee
|
||||
travel_tx, fee_tx = await self.generate_travel_transactions(fee)
|
||||
self.next_tx_config = tx_config
|
||||
travel_tx, fee_tx = await self.generate_travel_transactions(fee, tx_config)
|
||||
return total_fee, travel_tx, fee_tx
|
||||
|
||||
async def self_pool(self, fee: uint64) -> Tuple[uint64, TransactionRecord, Optional[TransactionRecord]]:
|
||||
async def self_pool(
|
||||
self, fee: uint64, tx_config: TXConfig
|
||||
) -> Tuple[uint64, TransactionRecord, Optional[TransactionRecord]]:
|
||||
if await self.have_unconfirmed_transaction():
|
||||
raise ValueError(
|
||||
"Cannot self pool due to unconfirmed transaction. If this is stuck, delete the unconfirmed transaction."
|
||||
|
@ -782,11 +796,12 @@ class PoolWallet:
|
|||
SELF_POOLING, owner_puzzlehash, owner_pubkey, pool_url=None, relative_lock_height=uint32(0)
|
||||
)
|
||||
self.next_transaction_fee = fee
|
||||
travel_tx, fee_tx = await self.generate_travel_transactions(fee)
|
||||
self.next_tx_config = tx_config
|
||||
travel_tx, fee_tx = await self.generate_travel_transactions(fee, tx_config)
|
||||
return total_fee, travel_tx, fee_tx
|
||||
|
||||
async def claim_pool_rewards(
|
||||
self, fee: uint64, max_spends_in_tx: Optional[int]
|
||||
self, fee: uint64, max_spends_in_tx: Optional[int], tx_config: TXConfig
|
||||
) -> Tuple[TransactionRecord, Optional[TransactionRecord]]:
|
||||
# Search for p2_puzzle_hash coins, and spend them with the singleton
|
||||
if await self.have_unconfirmed_transaction():
|
||||
|
@ -864,7 +879,7 @@ class PoolWallet:
|
|||
if fee > 0:
|
||||
absorb_announce = Announcement(first_coin_record.coin.name(), b"$")
|
||||
assert absorb_announce is not None
|
||||
fee_tx = await self.generate_fee_transaction(fee, coin_announcements={absorb_announce})
|
||||
fee_tx = await self.generate_fee_transaction(fee, tx_config, coin_announcements={absorb_announce})
|
||||
assert fee_tx.spend_bundle is not None
|
||||
full_spend = SpendBundle.aggregate([fee_tx.spend_bundle, claim_spend])
|
||||
|
||||
|
@ -935,7 +950,7 @@ class PoolWallet:
|
|||
assert self.target_state.relative_lock_height >= self.MINIMUM_RELATIVE_LOCK_HEIGHT
|
||||
assert self.target_state.pool_url is not None
|
||||
|
||||
await self.generate_travel_transactions(self.next_transaction_fee)
|
||||
await self.generate_travel_transactions(self.next_transaction_fee, self.next_tx_config)
|
||||
|
||||
async def have_unconfirmed_transaction(self) -> bool:
|
||||
unconfirmed: List[TransactionRecord] = await self.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
|
||||
|
@ -969,14 +984,7 @@ class PoolWallet:
|
|||
async def coin_added(self, coin: Coin, height: uint32, peer: WSChiaConnection) -> None:
|
||||
pass
|
||||
|
||||
async def select_coins(
|
||||
self,
|
||||
amount: uint64,
|
||||
exclude: Optional[List[Coin]] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
) -> Set[Coin]:
|
||||
async def select_coins(self, amount: uint64, coin_selection_config: CoinSelectionConfig) -> Set[Coin]:
|
||||
raise RuntimeError("PoolWallet does not support select_coins()")
|
||||
|
||||
def require_derivation_paths(self) -> bool:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,6 +18,7 @@ from chia.wallet.trading.offer import Offer
|
|||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.transaction_sorting import SortKey
|
||||
from chia.wallet.util.query_filter import TransactionTypeFilter
|
||||
from chia.wallet.util.tx_config import CoinSelectionConfig, TXConfig
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.vc_wallet.vc_store import VCRecord
|
||||
from chia.wallet.wallet_coin_store import GetCoinRecords
|
||||
|
@ -184,14 +185,10 @@ class WalletRpcClient(RpcClient):
|
|||
wallet_id: int,
|
||||
amount: uint64,
|
||||
address: str,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
memos: Optional[List[str]] = None,
|
||||
min_coin_amount: uint64 = uint64(0),
|
||||
max_coin_amount: uint64 = uint64(0),
|
||||
excluded_amounts: Optional[List[uint64]] = None,
|
||||
excluded_coin_ids: Optional[List[str]] = None,
|
||||
puzzle_decorator_override: Optional[List[Dict[str, Union[str, int, bool]]]] = None,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> TransactionRecord:
|
||||
if memos is None:
|
||||
send_dict: Dict = {
|
||||
|
@ -199,12 +196,7 @@ class WalletRpcClient(RpcClient):
|
|||
"amount": amount,
|
||||
"address": address,
|
||||
"fee": fee,
|
||||
"min_coin_amount": min_coin_amount,
|
||||
"max_coin_amount": max_coin_amount,
|
||||
"excluded_coin_amounts": excluded_amounts,
|
||||
"excluded_coin_ids": excluded_coin_ids,
|
||||
"puzzle_decorator": puzzle_decorator_override,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
}
|
||||
else:
|
||||
send_dict = {
|
||||
|
@ -213,18 +205,19 @@ class WalletRpcClient(RpcClient):
|
|||
"address": address,
|
||||
"fee": fee,
|
||||
"memos": memos,
|
||||
"min_coin_amount": min_coin_amount,
|
||||
"max_coin_amount": max_coin_amount,
|
||||
"excluded_coin_amounts": excluded_amounts,
|
||||
"excluded_coin_ids": excluded_coin_ids,
|
||||
"puzzle_decorator": puzzle_decorator_override,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
}
|
||||
send_dict.update(tx_config.to_json_dict())
|
||||
res = await self.fetch("send_transaction", send_dict)
|
||||
return TransactionRecord.from_json_dict_convenience(res["transaction"])
|
||||
|
||||
async def send_transaction_multi(
|
||||
self, wallet_id: int, additions: List[Dict], coins: List[Coin] = None, fee: uint64 = uint64(0)
|
||||
self,
|
||||
wallet_id: int,
|
||||
additions: List[Dict],
|
||||
tx_config: TXConfig,
|
||||
coins: List[Coin] = None,
|
||||
fee: uint64 = uint64(0),
|
||||
) -> TransactionRecord:
|
||||
# Converts bytes to hex for puzzle hashes
|
||||
additions_hex = []
|
||||
|
@ -275,14 +268,11 @@ class WalletRpcClient(RpcClient):
|
|||
async def create_signed_transactions(
|
||||
self,
|
||||
additions: List[Dict],
|
||||
tx_config: TXConfig,
|
||||
coins: List[Coin] = None,
|
||||
fee: uint64 = uint64(0),
|
||||
coin_announcements: Optional[List[Announcement]] = None,
|
||||
puzzle_announcements: Optional[List[Announcement]] = None,
|
||||
min_coin_amount: uint64 = uint64(0),
|
||||
max_coin_amount: uint64 = uint64(0),
|
||||
excluded_coins: Optional[List[Coin]] = None,
|
||||
excluded_amounts: Optional[List[uint64]] = None,
|
||||
wallet_id: Optional[int] = None,
|
||||
) -> List[TransactionRecord]:
|
||||
# Converts bytes to hex for puzzle hashes
|
||||
|
@ -295,9 +285,7 @@ class WalletRpcClient(RpcClient):
|
|||
request: Dict[str, Any] = {
|
||||
"additions": additions_hex,
|
||||
"fee": fee,
|
||||
"min_coin_amount": min_coin_amount,
|
||||
"max_coin_amount": max_coin_amount,
|
||||
"excluded_coin_amounts": excluded_amounts,
|
||||
**tx_config.to_json_dict(),
|
||||
}
|
||||
|
||||
if coin_announcements is not None and len(coin_announcements) > 0:
|
||||
|
@ -324,10 +312,6 @@ class WalletRpcClient(RpcClient):
|
|||
coins_json = [c.to_json_dict() for c in coins]
|
||||
request["coins"] = coins_json
|
||||
|
||||
if excluded_coins is not None and len(excluded_coins) > 0:
|
||||
excluded_coins_json = [excluded_coin.to_json_dict() for excluded_coin in excluded_coins]
|
||||
request["excluded_coins"] = excluded_coins_json
|
||||
|
||||
if wallet_id:
|
||||
request["wallet_id"] = wallet_id
|
||||
|
||||
|
@ -337,24 +321,20 @@ class WalletRpcClient(RpcClient):
|
|||
async def create_signed_transaction(
|
||||
self,
|
||||
additions: List[Dict],
|
||||
tx_config: TXConfig,
|
||||
coins: List[Coin] = None,
|
||||
fee: uint64 = uint64(0),
|
||||
coin_announcements: Optional[List[Announcement]] = None,
|
||||
puzzle_announcements: Optional[List[Announcement]] = None,
|
||||
min_coin_amount: uint64 = uint64(0),
|
||||
excluded_coins: Optional[List[Coin]] = None,
|
||||
excluded_amounts: Optional[List[uint64]] = None,
|
||||
wallet_id: Optional[int] = None,
|
||||
) -> TransactionRecord:
|
||||
txs: List[TransactionRecord] = await self.create_signed_transactions(
|
||||
additions=additions,
|
||||
tx_config=tx_config,
|
||||
coins=coins,
|
||||
fee=fee,
|
||||
coin_announcements=coin_announcements,
|
||||
puzzle_announcements=puzzle_announcements,
|
||||
min_coin_amount=min_coin_amount,
|
||||
excluded_coins=excluded_coins,
|
||||
excluded_amounts=excluded_amounts,
|
||||
wallet_id=wallet_id,
|
||||
)
|
||||
if len(txs) == 0:
|
||||
|
@ -366,20 +346,12 @@ class WalletRpcClient(RpcClient):
|
|||
self,
|
||||
amount: int,
|
||||
wallet_id: int,
|
||||
excluded_coins: Optional[List[Coin]] = None,
|
||||
min_coin_amount: uint64 = uint64(0),
|
||||
max_coin_amount: uint64 = uint64(0),
|
||||
excluded_amounts: Optional[List[uint64]] = None,
|
||||
coin_selection_config: CoinSelectionConfig,
|
||||
) -> List[Coin]:
|
||||
if excluded_coins is None:
|
||||
excluded_coins = []
|
||||
request = {
|
||||
"amount": amount,
|
||||
"wallet_id": wallet_id,
|
||||
"min_coin_amount": min_coin_amount,
|
||||
"max_coin_amount": max_coin_amount,
|
||||
"excluded_coins": [excluded_coin.to_json_dict() for excluded_coin in excluded_coins],
|
||||
"excluded_coin_amounts": excluded_amounts,
|
||||
**coin_selection_config.to_json_dict(),
|
||||
}
|
||||
response: Dict[str, List[Dict]] = await self.fetch("select_coins", request)
|
||||
return [Coin.from_json_dict(coin) for coin in response["coins"]]
|
||||
|
@ -390,24 +362,14 @@ class WalletRpcClient(RpcClient):
|
|||
async def get_spendable_coins(
|
||||
self,
|
||||
wallet_id: int,
|
||||
excluded_coins: Optional[List[Coin]] = None,
|
||||
min_coin_amount: uint64 = uint64(0),
|
||||
max_coin_amount: uint64 = uint64(0),
|
||||
excluded_amounts: Optional[List[uint64]] = None,
|
||||
excluded_coin_ids: Optional[List[str]] = None,
|
||||
coin_selection_config: CoinSelectionConfig,
|
||||
) -> Tuple[List[CoinRecord], List[CoinRecord], List[Coin]]:
|
||||
"""
|
||||
We return a tuple containing: (confirmed records, unconfirmed removals, unconfirmed additions)
|
||||
"""
|
||||
if excluded_coins is None:
|
||||
excluded_coins = []
|
||||
request = {
|
||||
"wallet_id": wallet_id,
|
||||
"min_coin_amount": min_coin_amount,
|
||||
"max_coin_amount": max_coin_amount,
|
||||
"excluded_coins": [excluded_coin.to_json_dict() for excluded_coin in excluded_coins],
|
||||
"excluded_coin_amounts": excluded_amounts,
|
||||
"excluded_coin_ids": excluded_coin_ids,
|
||||
**coin_selection_config.to_json_dict(),
|
||||
}
|
||||
response: Dict[str, List[Dict]] = await self.fetch("get_spendable_coins", request)
|
||||
confirmed_wrs = [CoinRecord.from_json_dict(coin) for coin in response["confirmed_records"]]
|
||||
|
@ -481,13 +443,13 @@ class WalletRpcClient(RpcClient):
|
|||
wallet_id: int,
|
||||
recovery_list: List[str],
|
||||
num_verification: int,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
tx_config: TXConfig,
|
||||
) -> Dict:
|
||||
request: Dict[str, Any] = {
|
||||
"wallet_id": wallet_id,
|
||||
"new_list": recovery_list,
|
||||
"num_verifications_required": num_verification,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
**tx_config.to_json_dict(),
|
||||
}
|
||||
response = await self.fetch("did_update_recovery_ids", request)
|
||||
return response
|
||||
|
@ -514,12 +476,12 @@ class WalletRpcClient(RpcClient):
|
|||
self,
|
||||
wallet_id: int,
|
||||
metadata: Dict,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
tx_config: TXConfig,
|
||||
) -> Dict:
|
||||
request: Dict[str, Any] = {
|
||||
"wallet_id": wallet_id,
|
||||
"metadata": metadata,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
**tx_config.to_json_dict(),
|
||||
}
|
||||
response = await self.fetch("did_update_metadata", request)
|
||||
return response
|
||||
|
@ -582,14 +544,14 @@ class WalletRpcClient(RpcClient):
|
|||
address: str,
|
||||
fee: int,
|
||||
with_recovery: bool,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
tx_config: TXConfig,
|
||||
) -> Dict:
|
||||
request: Dict[str, Any] = {
|
||||
"wallet_id": wallet_id,
|
||||
"inner_address": address,
|
||||
"fee": fee,
|
||||
"with_recovery_info": with_recovery,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
**tx_config.to_json_dict(),
|
||||
}
|
||||
response = await self.fetch("did_transfer_did", request)
|
||||
return response
|
||||
|
@ -727,28 +689,20 @@ class WalletRpcClient(RpcClient):
|
|||
async def cat_spend(
|
||||
self,
|
||||
wallet_id: int,
|
||||
tx_config: TXConfig,
|
||||
amount: Optional[uint64] = None,
|
||||
inner_address: Optional[str] = None,
|
||||
fee: uint64 = uint64(0),
|
||||
memos: Optional[List[str]] = None,
|
||||
min_coin_amount: uint64 = uint64(0),
|
||||
max_coin_amount: uint64 = uint64(0),
|
||||
excluded_amounts: Optional[List[uint64]] = None,
|
||||
excluded_coin_ids: Optional[List[str]] = None,
|
||||
additions: Optional[List[Dict[str, Any]]] = None,
|
||||
removals: Optional[List[Coin]] = None,
|
||||
cat_discrepancy: Optional[Tuple[int, Program, Program]] = None, # (extra_delta, tail_reveal, tail_solution)
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> TransactionRecord:
|
||||
send_dict: Dict[str, Any] = {
|
||||
"wallet_id": wallet_id,
|
||||
"fee": fee,
|
||||
"memos": memos if memos else [],
|
||||
"min_coin_amount": min_coin_amount,
|
||||
"max_coin_amount": max_coin_amount,
|
||||
"excluded_coin_amounts": excluded_amounts,
|
||||
"excluded_coin_ids": excluded_coin_ids,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
**tx_config.to_json_dict(),
|
||||
}
|
||||
if amount is not None and inner_address is not None:
|
||||
send_dict["amount"] = amount
|
||||
|
@ -775,13 +729,11 @@ class WalletRpcClient(RpcClient):
|
|||
async def create_offer_for_ids(
|
||||
self,
|
||||
offer_dict: Dict[Union[uint32, str], int],
|
||||
tx_config: TXConfig,
|
||||
driver_dict: Dict[str, Any] = None,
|
||||
solver: Dict[str, Any] = None,
|
||||
fee=uint64(0),
|
||||
validate_only: bool = False,
|
||||
min_coin_amount: uint64 = uint64(0),
|
||||
max_coin_amount: uint64 = uint64(0),
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> Tuple[Optional[Offer], TradeRecord]:
|
||||
send_dict: Dict[str, int] = {str(key): value for key, value in offer_dict.items()}
|
||||
|
||||
|
@ -789,9 +741,7 @@ class WalletRpcClient(RpcClient):
|
|||
"offer": send_dict,
|
||||
"validate_only": validate_only,
|
||||
"fee": fee,
|
||||
"min_coin_amount": min_coin_amount,
|
||||
"max_coin_amount": max_coin_amount,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
**tx_config.to_json_dict(),
|
||||
}
|
||||
if driver_dict is not None:
|
||||
req["driver_dict"] = driver_dict
|
||||
|
@ -815,16 +765,14 @@ class WalletRpcClient(RpcClient):
|
|||
async def take_offer(
|
||||
self,
|
||||
offer: Offer,
|
||||
tx_config: TXConfig,
|
||||
solver: Dict[str, Any] = None,
|
||||
fee=uint64(0),
|
||||
min_coin_amount: uint64 = uint64(0),
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> TradeRecord:
|
||||
req = {
|
||||
"offer": offer.to_bech32(),
|
||||
"fee": fee,
|
||||
"min_coin_amount": min_coin_amount,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
**tx_config.to_json_dict(),
|
||||
}
|
||||
if solver is not None:
|
||||
req["solver"] = solver
|
||||
|
@ -891,6 +839,7 @@ class WalletRpcClient(RpcClient):
|
|||
target_address,
|
||||
hash,
|
||||
uris,
|
||||
tx_config: TXConfig,
|
||||
meta_hash="",
|
||||
meta_uris=[],
|
||||
license_hash="",
|
||||
|
@ -900,7 +849,6 @@ class WalletRpcClient(RpcClient):
|
|||
fee=0,
|
||||
royalty_percentage=0,
|
||||
did_id=None,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
):
|
||||
request: Dict[str, Any] = {
|
||||
"wallet_id": wallet_id,
|
||||
|
@ -917,7 +865,7 @@ class WalletRpcClient(RpcClient):
|
|||
"royalty_percentage": royalty_percentage,
|
||||
"did_id": did_id,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
**tx_config.to_json_dict(),
|
||||
}
|
||||
response = await self.fetch("nft_mint_nft", request)
|
||||
return response
|
||||
|
@ -929,7 +877,7 @@ class WalletRpcClient(RpcClient):
|
|||
key,
|
||||
uri,
|
||||
fee,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
tx_config: TXConfig,
|
||||
):
|
||||
request: Dict[str, Any] = {
|
||||
"wallet_id": wallet_id,
|
||||
|
@ -937,7 +885,7 @@ class WalletRpcClient(RpcClient):
|
|||
"uri": uri,
|
||||
"key": key,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
**tx_config.to_json_dict(),
|
||||
}
|
||||
response = await self.fetch("nft_add_uri", request)
|
||||
return response
|
||||
|
@ -969,14 +917,14 @@ class WalletRpcClient(RpcClient):
|
|||
nft_coin_id,
|
||||
target_address,
|
||||
fee,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
tx_config: TXConfig,
|
||||
):
|
||||
request: Dict[str, Any] = {
|
||||
"wallet_id": wallet_id,
|
||||
"nft_coin_id": nft_coin_id,
|
||||
"target_address": target_address,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
**tx_config.to_json_dict(),
|
||||
}
|
||||
response = await self.fetch("nft_transfer_nft", request)
|
||||
return response
|
||||
|
@ -997,14 +945,14 @@ class WalletRpcClient(RpcClient):
|
|||
did_id,
|
||||
nft_coin_id,
|
||||
fee,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
tx_config: TXConfig,
|
||||
):
|
||||
request: Dict[str, Any] = {
|
||||
"wallet_id": wallet_id,
|
||||
"did_id": did_id,
|
||||
"nft_coin_id": nft_coin_id,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
**tx_config.to_json_dict(),
|
||||
}
|
||||
response = await self.fetch("nft_set_nft_did", request)
|
||||
return response
|
||||
|
@ -1020,6 +968,7 @@ class WalletRpcClient(RpcClient):
|
|||
metadata_list: List[Dict[str, Any]],
|
||||
royalty_percentage: Optional[int],
|
||||
royalty_address: Optional[str],
|
||||
tx_config: TXConfig,
|
||||
target_list: Optional[List[str]] = None,
|
||||
mint_number_start: Optional[int] = 1,
|
||||
mint_total: Optional[int] = None,
|
||||
|
@ -1030,7 +979,6 @@ class WalletRpcClient(RpcClient):
|
|||
did_lineage_parent: Optional[str] = None,
|
||||
mint_from_did: Optional[bool] = False,
|
||||
fee: Optional[int] = 0,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> Dict:
|
||||
request = {
|
||||
"wallet_id": wallet_id,
|
||||
|
@ -1047,7 +995,7 @@ class WalletRpcClient(RpcClient):
|
|||
"did_lineage_parent": did_lineage_parent,
|
||||
"mint_from_did": mint_from_did,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
**tx_config.to_json_dict(),
|
||||
}
|
||||
response = await self.fetch("nft_mint_bulk", request)
|
||||
return response
|
||||
|
@ -1225,11 +1173,11 @@ class WalletRpcClient(RpcClient):
|
|||
async def vc_spend(
|
||||
self,
|
||||
vc_id: bytes32,
|
||||
tx_config: TXConfig,
|
||||
new_puzhash: Optional[bytes32] = None,
|
||||
new_proof_hash: Optional[bytes32] = None,
|
||||
provider_inner_puzhash: Optional[bytes32] = None,
|
||||
fee: uint64 = uint64(0),
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> List[TransactionRecord]:
|
||||
response = await self.fetch(
|
||||
"vc_spend",
|
||||
|
@ -1241,7 +1189,7 @@ class WalletRpcClient(RpcClient):
|
|||
if provider_inner_puzhash is not None
|
||||
else provider_inner_puzhash,
|
||||
"fee": fee,
|
||||
"reuse_puzhash": reuse_puzhash,
|
||||
**tx_config.to_json_dict(),
|
||||
},
|
||||
)
|
||||
return [TransactionRecord.from_json_dict_convenience(tx) for tx in response["transactions"]]
|
||||
|
@ -1256,10 +1204,10 @@ class WalletRpcClient(RpcClient):
|
|||
async def vc_revoke(
|
||||
self,
|
||||
vc_parent_id: bytes32,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> List[TransactionRecord]:
|
||||
response = await self.fetch(
|
||||
"vc_revoke", {"vc_parent_id": vc_parent_id.hex(), "fee": fee, "reuse_puzhash": reuse_puzhash}
|
||||
"vc_revoke", {"vc_parent_id": vc_parent_id.hex(), "fee": fee, **tx_config.to_json_dict()}
|
||||
)
|
||||
return [TransactionRecord.from_json_dict_convenience(tx) for tx in response["transactions"]]
|
||||
|
|
|
@ -27,6 +27,7 @@ from chia.util.config import lock_and_load_config, save_config
|
|||
from chia.util.ints import uint8, uint32, uint64, uint128
|
||||
from chia.wallet.payment import Payment
|
||||
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_state_manager import WalletStateManager
|
||||
|
@ -616,6 +617,7 @@ class FullNodeSimulator(FullNodeAPI):
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
amount=outputs_group[0].amount,
|
||||
puzzle_hash=outputs_group[0].puzzle_hash,
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
primaries=outputs_group[1:],
|
||||
)
|
||||
await wallet.push_transaction(tx=tx)
|
||||
|
|
|
@ -52,6 +52,7 @@ from chia.wallet.uncurried_puzzle import uncurry_puzzle
|
|||
from chia.wallet.util.compute_memos import compute_memos
|
||||
from chia.wallet.util.curry_and_treehash import calculate_hash_of_quoted_mod_hash, curry_and_treehash
|
||||
from chia.wallet.util.transaction_type import TransactionType
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG, CoinSelectionConfig, TXConfig
|
||||
from chia.wallet.util.wallet_sync_utils import fetch_coin_spend_for_coin_state
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet import Wallet
|
||||
|
@ -91,6 +92,7 @@ class CATWallet:
|
|||
wallet: Wallet,
|
||||
cat_tail_info: Dict[str, Any],
|
||||
amount: uint64,
|
||||
tx_config: TXConfig,
|
||||
name: Optional[str] = None,
|
||||
) -> "CATWallet":
|
||||
self = CATWallet()
|
||||
|
@ -122,6 +124,7 @@ class CATWallet:
|
|||
self,
|
||||
cat_tail_info,
|
||||
amount,
|
||||
tx_config,
|
||||
)
|
||||
assert self.cat_info.limitations_program_hash != empty_bytes
|
||||
except Exception:
|
||||
|
@ -305,7 +308,7 @@ class CATWallet:
|
|||
if self.cost_of_single_tx is None:
|
||||
coin = spendable[0].coin
|
||||
txs = await self.generate_signed_transaction(
|
||||
[uint64(coin.amount)], [coin.puzzle_hash], coins={coin}, ignore_max_send_amount=True
|
||||
[uint64(coin.amount)], [coin.puzzle_hash], DEFAULT_TX_CONFIG, coins={coin}, ignore_max_send_amount=True
|
||||
)
|
||||
assert txs[0].spend_bundle
|
||||
program: BlockGenerator = simple_solution_generator(txs[0].spend_bundle)
|
||||
|
@ -480,10 +483,7 @@ class CATWallet:
|
|||
async def select_coins(
|
||||
self,
|
||||
amount: uint64,
|
||||
exclude: Optional[List[Coin]] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
coin_selection_config: CoinSelectionConfig,
|
||||
) -> Set[Coin]:
|
||||
"""
|
||||
Returns a set of coins that can be used for generating a new transaction.
|
||||
|
@ -497,18 +497,13 @@ class CATWallet:
|
|||
unconfirmed_removals: Dict[bytes32, Coin] = await self.wallet_state_manager.unconfirmed_removals_for_wallet(
|
||||
self.id()
|
||||
)
|
||||
if max_coin_amount is None:
|
||||
max_coin_amount = uint64(self.wallet_state_manager.constants.MAX_COIN_AMOUNT)
|
||||
coins = await select_coins(
|
||||
spendable_amount,
|
||||
max_coin_amount,
|
||||
coin_selection_config,
|
||||
spendable_coins,
|
||||
unconfirmed_removals,
|
||||
self.log,
|
||||
uint128(amount),
|
||||
exclude,
|
||||
min_coin_amount,
|
||||
excluded_coin_amounts,
|
||||
)
|
||||
assert sum(c.amount for c in coins) >= amount
|
||||
return coins
|
||||
|
@ -565,11 +560,8 @@ class CATWallet:
|
|||
self,
|
||||
fee: uint64,
|
||||
amount_to_claim: uint64,
|
||||
tx_config: TXConfig,
|
||||
announcement_to_assert: Optional[Announcement] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> Tuple[TransactionRecord, Optional[Announcement]]:
|
||||
"""
|
||||
This function creates a non-CAT transaction to pay fees, contribute funds for issuance, and absorb melt value.
|
||||
|
@ -577,31 +569,21 @@ class CATWallet:
|
|||
wallet_state_manager lock
|
||||
"""
|
||||
announcement = None
|
||||
if reuse_puzhash is None:
|
||||
reuse_puzhash_config = self.wallet_state_manager.config.get("reuse_public_key_for_change", None)
|
||||
if reuse_puzhash_config is None:
|
||||
reuse_puzhash = False
|
||||
else:
|
||||
reuse_puzhash = reuse_puzhash_config.get(
|
||||
str(self.wallet_state_manager.wallet_node.logged_in_fingerprint), False
|
||||
)
|
||||
if fee > amount_to_claim:
|
||||
chia_coins = await self.standard_wallet.select_coins(
|
||||
fee,
|
||||
min_coin_amount=min_coin_amount,
|
||||
max_coin_amount=max_coin_amount,
|
||||
excluded_coin_amounts=excluded_coin_amounts,
|
||||
tx_config.coin_selection_config,
|
||||
)
|
||||
origin_id = list(chia_coins)[0].name()
|
||||
chia_tx = await self.standard_wallet.generate_signed_transaction(
|
||||
uint64(0),
|
||||
(await self.standard_wallet.get_puzzle_hash(not reuse_puzhash)),
|
||||
(await self.standard_wallet.get_puzzle_hash(not tx_config.reuse_puzhash)),
|
||||
tx_config,
|
||||
fee=uint64(fee - amount_to_claim),
|
||||
coins=chia_coins,
|
||||
origin_id=origin_id, # We specify this so that we know the coin that is making the announcement
|
||||
negative_change_allowed=False,
|
||||
coin_announcements_to_consume={announcement_to_assert} if announcement_to_assert is not None else None,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
assert chia_tx.spend_bundle is not None
|
||||
|
||||
|
@ -618,18 +600,16 @@ class CATWallet:
|
|||
else:
|
||||
chia_coins = await self.standard_wallet.select_coins(
|
||||
fee,
|
||||
min_coin_amount=min_coin_amount,
|
||||
max_coin_amount=max_coin_amount,
|
||||
excluded_coin_amounts=excluded_coin_amounts,
|
||||
tx_config.coin_selection_config,
|
||||
)
|
||||
selected_amount = sum([c.amount for c in chia_coins])
|
||||
chia_tx = await self.standard_wallet.generate_signed_transaction(
|
||||
uint64(selected_amount + amount_to_claim - fee),
|
||||
(await self.standard_wallet.get_puzzle_hash(not reuse_puzhash)),
|
||||
(await self.standard_wallet.get_puzzle_hash(not tx_config.reuse_puzhash)),
|
||||
tx_config,
|
||||
coins=chia_coins,
|
||||
negative_change_allowed=True,
|
||||
coin_announcements_to_consume={announcement_to_assert} if announcement_to_assert is not None else None,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
assert chia_tx.spend_bundle is not None
|
||||
|
||||
|
@ -638,16 +618,12 @@ class CATWallet:
|
|||
async def generate_unsigned_spendbundle(
|
||||
self,
|
||||
payments: List[Payment],
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
cat_discrepancy: Optional[Tuple[int, Program, Program]] = None, # (extra_delta, tail_reveal, tail_solution)
|
||||
coins: Optional[Set[Coin]] = None,
|
||||
coin_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
puzzle_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
excluded_coins: Optional[Set[Coin]] = None,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> Tuple[SpendBundle, Optional[TransactionRecord]]:
|
||||
if coin_announcements_to_consume is not None:
|
||||
coin_announcements_bytes: Optional[Set[bytes32]] = {a.name() for a in coin_announcements_to_consume}
|
||||
|
@ -665,26 +641,11 @@ class CATWallet:
|
|||
extra_delta, tail_reveal, tail_solution = 0, Program.to([]), Program.to([])
|
||||
payment_amount: int = sum([p.amount for p in payments])
|
||||
starting_amount: int = payment_amount - extra_delta
|
||||
if reuse_puzhash is None:
|
||||
reuse_puzhash_config = self.wallet_state_manager.config.get("reuse_public_key_for_change", None)
|
||||
if reuse_puzhash_config is None:
|
||||
reuse_puzhash = False
|
||||
else:
|
||||
reuse_puzhash = reuse_puzhash_config.get(
|
||||
str(self.wallet_state_manager.wallet_node.logged_in_fingerprint), False
|
||||
)
|
||||
if coins is None:
|
||||
if excluded_coins is None:
|
||||
excluded_coins = set()
|
||||
cat_coins = await self.select_coins(
|
||||
uint64(starting_amount),
|
||||
exclude=list(excluded_coins),
|
||||
min_coin_amount=min_coin_amount,
|
||||
max_coin_amount=max_coin_amount,
|
||||
excluded_coin_amounts=excluded_coin_amounts,
|
||||
tx_config.coin_selection_config,
|
||||
)
|
||||
elif excluded_coins is not None:
|
||||
raise ValueError("Can't exclude coins when also specifically including coins")
|
||||
else:
|
||||
cat_coins = coins
|
||||
|
||||
|
@ -708,7 +669,7 @@ class CATWallet:
|
|||
derivation_record = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash(
|
||||
list(cat_coins)[0].puzzle_hash
|
||||
)
|
||||
if derivation_record is not None and reuse_puzhash:
|
||||
if derivation_record is not None and tx_config.reuse_puzhash:
|
||||
change_puzhash = self.standard_wallet.puzzle_hash_for_pk(derivation_record.pubkey)
|
||||
for payment in payments:
|
||||
if change_puzhash == payment.puzzle_hash and change == payment.amount:
|
||||
|
@ -733,11 +694,8 @@ class CATWallet:
|
|||
chia_tx, _ = await self.create_tandem_xch_tx(
|
||||
fee,
|
||||
uint64(regular_chia_to_claim),
|
||||
tx_config,
|
||||
announcement_to_assert=announcement,
|
||||
min_coin_amount=min_coin_amount,
|
||||
max_coin_amount=max_coin_amount,
|
||||
excluded_coin_amounts=excluded_coin_amounts,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
innersol = self.standard_wallet.make_solution(
|
||||
primaries=primaries,
|
||||
|
@ -749,10 +707,7 @@ class CATWallet:
|
|||
chia_tx, _ = await self.create_tandem_xch_tx(
|
||||
fee,
|
||||
uint64(regular_chia_to_claim),
|
||||
min_coin_amount=min_coin_amount,
|
||||
max_coin_amount=max_coin_amount,
|
||||
excluded_coin_amounts=excluded_coin_amounts,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
tx_config,
|
||||
)
|
||||
innersol = self.standard_wallet.make_solution(
|
||||
primaries=primaries,
|
||||
|
@ -810,19 +765,15 @@ class CATWallet:
|
|||
self,
|
||||
amounts: List[uint64],
|
||||
puzzle_hashes: List[bytes32],
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
coins: Optional[Set[Coin]] = None,
|
||||
ignore_max_send_amount: bool = False,
|
||||
memos: Optional[List[List[bytes]]] = None,
|
||||
coin_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
puzzle_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
**kwargs: Unpack[GSTOptionalArgs],
|
||||
) -> List[TransactionRecord]:
|
||||
excluded_cat_coins: Optional[Set[Coin]] = kwargs.get("excluded_cat_coins", None)
|
||||
# (extra_delta, tail_reveal, tail_solution)
|
||||
cat_discrepancy: Optional[Tuple[int, Program, Program]] = kwargs.get("cat_discrepancy", None)
|
||||
if memos is None:
|
||||
|
@ -844,16 +795,12 @@ class CATWallet:
|
|||
raise ValueError(f"Can't send more than {max_send} mojos in a single transaction")
|
||||
unsigned_spend_bundle, chia_tx = await self.generate_unsigned_spendbundle(
|
||||
payments,
|
||||
tx_config,
|
||||
fee,
|
||||
cat_discrepancy=cat_discrepancy, # (extra_delta, tail_reveal, tail_solution)
|
||||
coins=coins,
|
||||
coin_announcements_to_consume=coin_announcements_to_consume,
|
||||
puzzle_announcements_to_consume=puzzle_announcements_to_consume,
|
||||
min_coin_amount=min_coin_amount,
|
||||
max_coin_amount=max_coin_amount,
|
||||
excluded_coin_amounts=excluded_coin_amounts,
|
||||
excluded_coins=excluded_cat_coins,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
spend_bundle = await self.sign(unsigned_spend_bundle)
|
||||
# TODO add support for array in stored records
|
||||
|
@ -937,10 +884,9 @@ class CATWallet:
|
|||
self,
|
||||
asset_id: Optional[bytes32],
|
||||
amount: uint64,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
coin_selection_config: CoinSelectionConfig,
|
||||
) -> Set[Coin]:
|
||||
balance = await self.get_confirmed_balance()
|
||||
if balance < amount:
|
||||
raise Exception(f"insufficient funds in wallet {self.id()}")
|
||||
return await self.select_coins(amount, min_coin_amount=min_coin_amount, max_coin_amount=max_coin_amount)
|
||||
return await self.select_coins(amount, coin_selection_config)
|
||||
|
|
|
@ -7,30 +7,21 @@ from typing import Dict, List, Optional, Set
|
|||
from chia.types.blockchain_format.coin import Coin
|
||||
from chia.types.blockchain_format.sized_bytes import bytes32
|
||||
from chia.util.ints import uint64, uint128
|
||||
from chia.wallet.util.tx_config import CoinSelectionConfig
|
||||
from chia.wallet.wallet_coin_record import WalletCoinRecord
|
||||
|
||||
|
||||
async def select_coins(
|
||||
spendable_amount: uint128,
|
||||
max_coin_amount: uint64,
|
||||
coin_selection_config: CoinSelectionConfig,
|
||||
spendable_coins: List[WalletCoinRecord],
|
||||
unconfirmed_removals: Dict[bytes32, Coin],
|
||||
log: logging.Logger,
|
||||
amount: uint128,
|
||||
exclude: Optional[List[Coin]] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
) -> Set[Coin]:
|
||||
"""
|
||||
Returns a set of coins that can be used for generating a new transaction.
|
||||
"""
|
||||
if exclude is None:
|
||||
exclude = []
|
||||
if min_coin_amount is None:
|
||||
min_coin_amount = uint64(0)
|
||||
if excluded_coin_amounts is None:
|
||||
excluded_coin_amounts = []
|
||||
|
||||
if amount > spendable_amount:
|
||||
error_msg = (
|
||||
f"Can't select amount higher than our spendable balance. Amount: {amount}, spendable: {spendable_amount}"
|
||||
|
@ -45,13 +36,17 @@ async def select_coins(
|
|||
valid_spendable_coins: List[Coin] = []
|
||||
|
||||
for coin_record in spendable_coins: # remove all the unconfirmed coins, excluded coins and dust.
|
||||
if coin_record.coin.name() in unconfirmed_removals:
|
||||
coin_name: bytes32 = coin_record.coin.name()
|
||||
if coin_name in unconfirmed_removals:
|
||||
continue
|
||||
if coin_record.coin in exclude:
|
||||
if coin_name in coin_selection_config.excluded_coin_ids:
|
||||
continue
|
||||
if coin_record.coin.amount < min_coin_amount or coin_record.coin.amount > max_coin_amount:
|
||||
if (
|
||||
coin_record.coin.amount < coin_selection_config.min_coin_amount
|
||||
or coin_record.coin.amount > coin_selection_config.max_coin_amount
|
||||
):
|
||||
continue
|
||||
if coin_record.coin.amount in excluded_coin_amounts:
|
||||
if coin_record.coin.amount in coin_selection_config.excluded_coin_amounts:
|
||||
continue
|
||||
valid_spendable_coins.append(coin_record.coin)
|
||||
sum_spendable_coins += coin_record.coin.amount
|
||||
|
@ -95,7 +90,9 @@ async def select_coins(
|
|||
log.debug(f"Selected closest greater coin: {smallest_coin.name()}")
|
||||
return {smallest_coin}
|
||||
elif smaller_coin_sum > amount:
|
||||
coin_set: Optional[Set[Coin]] = knapsack_coin_algorithm(smaller_coins, amount, max_coin_amount, max_num_coins)
|
||||
coin_set: Optional[Set[Coin]] = knapsack_coin_algorithm(
|
||||
smaller_coins, amount, coin_selection_config.max_coin_amount, max_num_coins
|
||||
)
|
||||
log.debug(f"Selected coins from knapsack algorithm: {coin_set}")
|
||||
if coin_set is None:
|
||||
coin_set = sum_largest_coins(amount, smaller_coins)
|
||||
|
|
|
@ -43,6 +43,7 @@ from chia.wallet.singleton import (
|
|||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.compute_memos import compute_memos
|
||||
from chia.wallet.util.transaction_type import TransactionType
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG, CoinSelectionConfig, TXConfig
|
||||
from chia.wallet.util.wallet_sync_utils import fetch_coin_spend, fetch_coin_spend_for_coin_state
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet import CHIP_0002_SIGN_MESSAGE_PREFIX, Wallet
|
||||
|
@ -123,7 +124,7 @@ class DIDWallet:
|
|||
raise ValueError("Not enough balance")
|
||||
|
||||
try:
|
||||
spend_bundle = await self.generate_new_decentralised_id(amount, fee)
|
||||
spend_bundle = await self.generate_new_decentralised_id(amount, DEFAULT_TX_CONFIG, fee)
|
||||
except Exception:
|
||||
await wallet_state_manager.user_store.delete_wallet(self.id())
|
||||
raise
|
||||
|
@ -323,10 +324,7 @@ class DIDWallet:
|
|||
async def select_coins(
|
||||
self,
|
||||
amount: uint64,
|
||||
exclude: Optional[List[Coin]] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
coin_selection_config: CoinSelectionConfig,
|
||||
) -> Set[Coin]:
|
||||
"""
|
||||
Returns a set of coins that can be used for generating a new transaction.
|
||||
|
@ -349,18 +347,13 @@ class DIDWallet:
|
|||
unconfirmed_removals: Dict[bytes32, Coin] = await self.wallet_state_manager.unconfirmed_removals_for_wallet(
|
||||
self.wallet_info.id
|
||||
)
|
||||
if max_coin_amount is None:
|
||||
max_coin_amount = uint64(self.wallet_state_manager.constants.MAX_COIN_AMOUNT)
|
||||
coins = await select_coins(
|
||||
spendable_amount,
|
||||
max_coin_amount,
|
||||
coin_selection_config,
|
||||
spendable_coins,
|
||||
unconfirmed_removals,
|
||||
self.log,
|
||||
uint128(amount),
|
||||
exclude,
|
||||
min_coin_amount,
|
||||
excluded_coin_amounts,
|
||||
)
|
||||
assert sum(c.amount for c in coins) >= amount
|
||||
return coins
|
||||
|
@ -566,10 +559,10 @@ class DIDWallet:
|
|||
def get_name(self):
|
||||
return self.wallet_info.name
|
||||
|
||||
async def create_update_spend(self, fee: uint64 = uint64(0), reuse_puzhash: Optional[bool] = None):
|
||||
async def create_update_spend(self, tx_config: TXConfig, fee: uint64 = uint64(0)):
|
||||
assert self.did_info.current_inner is not None
|
||||
assert self.did_info.origin_coin is not None
|
||||
coins = await self.select_coins(uint64(1))
|
||||
coins = await self.select_coins(uint64(1), tx_config.coin_selection_config)
|
||||
assert coins is not None
|
||||
coin = coins.pop()
|
||||
new_inner_puzzle = await self.get_new_did_innerpuz()
|
||||
|
@ -625,7 +618,7 @@ class DIDWallet:
|
|||
if fee > 0:
|
||||
announcement_to_make = coin.name()
|
||||
chia_tx = await self.standard_wallet.create_tandem_xch_tx(
|
||||
fee, Announcement(coin.name(), announcement_to_make), reuse_puzhash=reuse_puzhash
|
||||
fee, tx_config, Announcement(coin.name(), announcement_to_make)
|
||||
)
|
||||
else:
|
||||
announcement_to_make = None
|
||||
|
@ -661,7 +654,7 @@ class DIDWallet:
|
|||
new_puzhash: bytes32,
|
||||
fee: uint64,
|
||||
with_recovery: bool,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
tx_config: TXConfig,
|
||||
) -> TransactionRecord:
|
||||
"""
|
||||
Transfer the current DID to another owner
|
||||
|
@ -672,7 +665,7 @@ class DIDWallet:
|
|||
"""
|
||||
assert self.did_info.current_inner is not None
|
||||
assert self.did_info.origin_coin is not None
|
||||
coins = await self.select_coins(uint64(1))
|
||||
coins = await self.select_coins(uint64(1), tx_config.coin_selection_config)
|
||||
assert coins is not None
|
||||
coin = coins.pop()
|
||||
backup_ids = []
|
||||
|
@ -722,7 +715,7 @@ class DIDWallet:
|
|||
if fee > 0:
|
||||
announcement_to_make = coin.name()
|
||||
chia_tx = await self.standard_wallet.create_tandem_xch_tx(
|
||||
fee, Announcement(coin.name(), announcement_to_make), reuse_puzhash=reuse_puzhash
|
||||
fee, tx_config, Announcement(coin.name(), announcement_to_make)
|
||||
)
|
||||
else:
|
||||
chia_tx = None
|
||||
|
@ -754,6 +747,7 @@ class DIDWallet:
|
|||
# The message spend can tests\wallet\rpc\test_wallet_rpc.py send messages and also change your innerpuz
|
||||
async def create_message_spend(
|
||||
self,
|
||||
tx_config: TXConfig,
|
||||
coin_announcements: Optional[Set[bytes]] = None,
|
||||
puzzle_announcements: Optional[Set[bytes]] = None,
|
||||
coin_announcements_to_assert: Optional[Set[Announcement]] = None,
|
||||
|
@ -762,7 +756,7 @@ class DIDWallet:
|
|||
):
|
||||
assert self.did_info.current_inner is not None
|
||||
assert self.did_info.origin_coin is not None
|
||||
coins = await self.select_coins(uint64(1))
|
||||
coins = await self.select_coins(uint64(1), tx_config.coin_selection_config)
|
||||
assert coins is not None
|
||||
coin = coins.pop()
|
||||
innerpuz: Program = self.did_info.current_inner
|
||||
|
@ -809,10 +803,10 @@ class DIDWallet:
|
|||
return await self.sign(unsigned_spend_bundle)
|
||||
|
||||
# This is used to cash out, or update the id_list
|
||||
async def create_exit_spend(self, puzhash: bytes32):
|
||||
async def create_exit_spend(self, puzhash: bytes32, tx_config: TXConfig):
|
||||
assert self.did_info.current_inner is not None
|
||||
assert self.did_info.origin_coin is not None
|
||||
coins = await self.select_coins(uint64(1))
|
||||
coins = await self.select_coins(uint64(1), tx_config.coin_selection_config)
|
||||
assert coins is not None
|
||||
coin = coins.pop()
|
||||
message_puz = Program.to((1, [[51, puzhash, coin.amount - 1, [puzhash]], [51, 0x00, -113]]))
|
||||
|
@ -867,7 +861,7 @@ class DIDWallet:
|
|||
# Pushes a SpendBundle to create a message coin on the blockchain
|
||||
# Returns a SpendBundle for the recoverer to spend the message coin
|
||||
async def create_attestment(
|
||||
self, recovering_coin_name: bytes32, newpuz: bytes32, pubkey: G1Element
|
||||
self, recovering_coin_name: bytes32, newpuz: bytes32, pubkey: G1Element, tx_config: TXConfig
|
||||
) -> Tuple[SpendBundle, str]:
|
||||
"""
|
||||
Create an attestment
|
||||
|
@ -878,7 +872,7 @@ class DIDWallet:
|
|||
"""
|
||||
assert self.did_info.current_inner is not None
|
||||
assert self.did_info.origin_coin is not None
|
||||
coins = await self.select_coins(uint64(1))
|
||||
coins = await self.select_coins(uint64(1), tx_config.coin_selection_config)
|
||||
assert coins is not None and coins != set()
|
||||
coin = coins.pop()
|
||||
message = did_wallet_puzzles.create_recovery_message_puzzle(recovering_coin_name, newpuz, pubkey)
|
||||
|
@ -943,10 +937,12 @@ class DIDWallet:
|
|||
await self.wallet_state_manager.add_pending_transaction(did_record)
|
||||
return message_spend_bundle, attest_str
|
||||
|
||||
async def get_info_for_recovery(self) -> Optional[Tuple[bytes32, bytes32, uint64]]:
|
||||
async def get_info_for_recovery(
|
||||
self, coin_selection_config: CoinSelectionConfig
|
||||
) -> Optional[Tuple[bytes32, bytes32, uint64]]:
|
||||
assert self.did_info.current_inner is not None
|
||||
assert self.did_info.origin_coin is not None
|
||||
coins = await self.select_coins(uint64(1))
|
||||
coins = await self.select_coins(uint64(1), coin_selection_config)
|
||||
if coins is not None:
|
||||
coin = coins.pop()
|
||||
parent = coin.parent_coin_info
|
||||
|
@ -1213,12 +1209,14 @@ class DIDWallet:
|
|||
agg_sig = AugSchemeMPL.aggregate(sigs)
|
||||
return SpendBundle.aggregate([spend_bundle, SpendBundle([], agg_sig)])
|
||||
|
||||
async def generate_new_decentralised_id(self, amount: uint64, fee: uint64 = uint64(0)) -> Optional[SpendBundle]:
|
||||
async def generate_new_decentralised_id(
|
||||
self, amount: uint64, tx_config: TXConfig, fee: uint64 = uint64(0)
|
||||
) -> Optional[SpendBundle]:
|
||||
"""
|
||||
This must be called under the wallet state manager lock
|
||||
"""
|
||||
|
||||
coins = await self.standard_wallet.select_coins(uint64(amount + fee))
|
||||
coins = await self.standard_wallet.select_coins(uint64(amount + fee), tx_config.coin_selection_config)
|
||||
if coins is None:
|
||||
return None
|
||||
|
||||
|
@ -1238,6 +1236,7 @@ class DIDWallet:
|
|||
tx_record: Optional[TransactionRecord] = await self.standard_wallet.generate_signed_transaction(
|
||||
amount,
|
||||
genesis_launcher_puz.get_tree_hash(),
|
||||
tx_config,
|
||||
fee,
|
||||
coins,
|
||||
None,
|
||||
|
|
|
@ -51,6 +51,7 @@ from chia.wallet.transaction_record import TransactionRecord
|
|||
from chia.wallet.uncurried_puzzle import uncurry_puzzle
|
||||
from chia.wallet.util.compute_memos import compute_memos
|
||||
from chia.wallet.util.transaction_type import TransactionType
|
||||
from chia.wallet.util.tx_config import CoinSelectionConfig, TXConfig
|
||||
from chia.wallet.util.wallet_sync_utils import fetch_coin_spend
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet import CHIP_0002_SIGN_MESSAGE_PREFIX, Wallet
|
||||
|
@ -311,6 +312,7 @@ class NFTWallet:
|
|||
async def get_did_approval_info(
|
||||
self,
|
||||
nft_ids: List[bytes32],
|
||||
tx_config: TXConfig,
|
||||
did_id: Optional[bytes32] = None,
|
||||
) -> Tuple[bytes32, SpendBundle]:
|
||||
"""Get DID spend with announcement created we need to transfer NFT with did with current inner hash of DID
|
||||
|
@ -326,7 +328,7 @@ class NFTWallet:
|
|||
self.log.debug("Found a DID wallet, checking did: %r == %r", wallet.get_my_DID(), did_id)
|
||||
if bytes32.fromhex(wallet.get_my_DID()) == did_id:
|
||||
self.log.debug("Creating announcement from DID for nft_ids: %s", nft_ids)
|
||||
did_bundle = await wallet.create_message_spend(puzzle_announcements=nft_ids)
|
||||
did_bundle = await wallet.create_message_spend(tx_config, puzzle_announcements=nft_ids)
|
||||
self.log.debug("Sending DID announcement from puzzle: %s", did_bundle.removals())
|
||||
did_inner_hash = wallet.did_info.current_inner.get_tree_hash()
|
||||
break
|
||||
|
@ -337,13 +339,13 @@ class NFTWallet:
|
|||
async def generate_new_nft(
|
||||
self,
|
||||
metadata: Program,
|
||||
tx_config: TXConfig,
|
||||
target_puzzle_hash: Optional[bytes32] = None,
|
||||
royalty_puzzle_hash: Optional[bytes32] = None,
|
||||
percentage: uint16 = uint16(0),
|
||||
did_id: Optional[bytes] = None,
|
||||
fee: uint64 = uint64(0),
|
||||
push_tx: bool = True,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> Optional[SpendBundle]:
|
||||
"""
|
||||
This must be called under the wallet state manager lock
|
||||
|
@ -357,7 +359,7 @@ class NFTWallet:
|
|||
percentage = uint16(percentage)
|
||||
except ValueError:
|
||||
raise ValueError("Percentage must be lower than 655%")
|
||||
coins = await self.standard_wallet.select_coins(uint64(amount + fee))
|
||||
coins = await self.standard_wallet.select_coins(uint64(amount + fee), tx_config.coin_selection_config)
|
||||
if coins is None:
|
||||
return None
|
||||
origin = coins.copy().pop()
|
||||
|
@ -400,6 +402,7 @@ class NFTWallet:
|
|||
tx_record: Optional[TransactionRecord] = await self.standard_wallet.generate_signed_transaction(
|
||||
uint64(amount),
|
||||
nft_puzzles.LAUNCHER_PUZZLE_HASH,
|
||||
tx_config,
|
||||
fee,
|
||||
coins,
|
||||
None,
|
||||
|
@ -425,7 +428,7 @@ class NFTWallet:
|
|||
did_inner_hash = b""
|
||||
if did_id is not None:
|
||||
if did_id != b"":
|
||||
did_inner_hash, did_bundle = await self.get_did_approval_info([launcher_coin.name()])
|
||||
did_inner_hash, did_bundle = await self.get_did_approval_info([launcher_coin.name()], tx_config)
|
||||
bundles_to_agg.append(did_bundle)
|
||||
nft_coin = NFTCoinInfo(
|
||||
nft_id=launcher_coin.name(),
|
||||
|
@ -439,12 +442,12 @@ class NFTWallet:
|
|||
txs = await self.generate_signed_transaction(
|
||||
[uint64(eve_coin.amount)],
|
||||
[target_puzzle_hash],
|
||||
tx_config,
|
||||
nft_coin=nft_coin,
|
||||
new_owner=did_id,
|
||||
new_did_inner_hash=did_inner_hash,
|
||||
additional_bundles=bundles_to_agg,
|
||||
memos=[[target_puzzle_hash]],
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
txs.append(dataclasses.replace(tx_record, spend_bundle=None))
|
||||
if push_tx:
|
||||
|
@ -495,8 +498,8 @@ class NFTWallet:
|
|||
nft_coin_info: NFTCoinInfo,
|
||||
key: str,
|
||||
uri: str,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> Optional[SpendBundle]:
|
||||
uncurried_nft = UncurriedNFT.uncurry(*nft_coin_info.full_puzzle.uncurry())
|
||||
assert uncurried_nft is not None
|
||||
|
@ -510,10 +513,10 @@ class NFTWallet:
|
|||
txs = await self.generate_signed_transaction(
|
||||
[uint64(nft_coin_info.coin.amount)],
|
||||
[puzzle_hash],
|
||||
tx_config,
|
||||
fee,
|
||||
{nft_coin_info.coin},
|
||||
metadata_update=(key, uri),
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
for tx in txs:
|
||||
await self.wallet_state_manager.add_pending_transaction(tx)
|
||||
|
@ -618,13 +621,13 @@ class NFTWallet:
|
|||
self,
|
||||
amounts: List[uint64],
|
||||
puzzle_hashes: List[bytes32],
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
coins: Optional[Set[Coin]] = None,
|
||||
memos: Optional[List[List[bytes]]] = None,
|
||||
coin_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
puzzle_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
ignore_max_send_amount: bool = False,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
**kwargs: Unpack[GSTOptionalArgs],
|
||||
) -> List[TransactionRecord]:
|
||||
nft_coin: Optional[NFTCoinInfo] = kwargs.get("nft_coin", None)
|
||||
|
@ -648,6 +651,7 @@ class NFTWallet:
|
|||
payment_sum = sum([p.amount for p in payments])
|
||||
unsigned_spend_bundle, chia_tx = await self.generate_unsigned_spendbundle(
|
||||
payments,
|
||||
tx_config,
|
||||
fee,
|
||||
coins=coins,
|
||||
nft_coin=nft_coin,
|
||||
|
@ -657,7 +661,6 @@ class NFTWallet:
|
|||
new_did_inner_hash=new_did_inner_hash,
|
||||
trade_prices_list=trade_prices_list,
|
||||
metadata_update=metadata_update,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
spend_bundle = await self.sign(unsigned_spend_bundle)
|
||||
spend_bundle = SpendBundle.aggregate([spend_bundle] + additional_bundles)
|
||||
|
@ -694,6 +697,7 @@ class NFTWallet:
|
|||
async def generate_unsigned_spendbundle(
|
||||
self,
|
||||
payments: List[Payment],
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
coins: Optional[Set[Coin]] = None,
|
||||
coin_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
|
@ -703,7 +707,6 @@ class NFTWallet:
|
|||
trade_prices_list: Optional[Program] = None,
|
||||
metadata_update: Optional[Tuple[str, str]] = None,
|
||||
nft_coin: Optional[NFTCoinInfo] = None,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> Tuple[SpendBundle, Optional[TransactionRecord]]:
|
||||
if nft_coin is None:
|
||||
if coins is None or not len(coins) == 1:
|
||||
|
@ -727,7 +730,7 @@ class NFTWallet:
|
|||
if fee > 0:
|
||||
announcement_to_make = nft_coin.coin.name()
|
||||
chia_tx = await self.standard_wallet.create_tandem_xch_tx(
|
||||
fee, Announcement(nft_coin.coin.name(), announcement_to_make), reuse_puzhash=reuse_puzhash
|
||||
fee, tx_config, Announcement(nft_coin.coin.name(), announcement_to_make)
|
||||
)
|
||||
else:
|
||||
announcement_to_make = None
|
||||
|
@ -797,9 +800,8 @@ class NFTWallet:
|
|||
wallet_state_manager: Any,
|
||||
offer_dict: Dict[Optional[bytes32], int],
|
||||
driver_dict: Dict[bytes32, PuzzleInfo],
|
||||
tx_config: TXConfig,
|
||||
fee: uint64,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
old: bool = False,
|
||||
) -> Offer:
|
||||
DESIRED_OFFER_MOD = OFFER_MOD_OLD if old else OFFER_MOD
|
||||
|
@ -903,7 +905,7 @@ class NFTWallet:
|
|||
else:
|
||||
coin_amount_needed = abs(amount) + royalty_amount
|
||||
offered_coins: Set[Coin] = await wallet.get_coins_to_offer(
|
||||
asset, coin_amount_needed, min_coin_amount, max_coin_amount
|
||||
asset, coin_amount_needed, tx_config.coin_selection_config
|
||||
)
|
||||
if len(offered_coins) == 0:
|
||||
raise ValueError(f"Did not have asset ID {asset.hex() if asset is not None else 'XCH'} to offer")
|
||||
|
@ -950,6 +952,7 @@ class NFTWallet:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
abs(amount),
|
||||
DESIRED_OFFER_MOD_HASH,
|
||||
tx_config,
|
||||
primaries=[Payment(DESIRED_OFFER_MOD_HASH, uint64(payment_sum))]
|
||||
if payment_sum > 0 or old
|
||||
else [],
|
||||
|
@ -963,6 +966,7 @@ class NFTWallet:
|
|||
txs = await wallet.generate_signed_transaction(
|
||||
[abs(amount)],
|
||||
[DESIRED_OFFER_MOD_HASH],
|
||||
tx_config,
|
||||
fee=fee_left_to_pay,
|
||||
coins=offered_coins_by_asset[asset],
|
||||
puzzle_announcements_to_consume=announcements_to_assert,
|
||||
|
@ -977,6 +981,7 @@ class NFTWallet:
|
|||
txs = await wallet.generate_signed_transaction(
|
||||
[abs(amount), sum(p.amount for _, p in payments)],
|
||||
[DESIRED_OFFER_MOD_HASH, DESIRED_OFFER_MOD_HASH],
|
||||
tx_config,
|
||||
fee=fee_left_to_pay,
|
||||
coins=offered_coins_by_asset[asset],
|
||||
puzzle_announcements_to_consume=announcements_to_assert,
|
||||
|
@ -1097,9 +1102,9 @@ class NFTWallet:
|
|||
self,
|
||||
nft_list: List[NFTCoinInfo],
|
||||
did_id: bytes,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
announcement_ids: List[bytes32] = [],
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> List[TransactionRecord]:
|
||||
self.log.debug("Setting NFT DID with parameters: nft=%s did=%s", nft_list, did_id)
|
||||
did_inner_hash = b""
|
||||
|
@ -1110,7 +1115,7 @@ class NFTWallet:
|
|||
for nft_coin_info in nft_list:
|
||||
nft_ids.append(nft_coin_info.nft_id)
|
||||
if did_id != b"":
|
||||
did_inner_hash, did_bundle = await self.get_did_approval_info(announcement_ids, bytes32(did_id))
|
||||
did_inner_hash, did_bundle = await self.get_did_approval_info(announcement_ids, tx_config, bytes32(did_id))
|
||||
if len(announcement_ids) > 0:
|
||||
spend_bundles.append(did_bundle)
|
||||
|
||||
|
@ -1124,11 +1129,11 @@ class NFTWallet:
|
|||
await self.generate_signed_transaction(
|
||||
[uint64(nft_coin_info.coin.amount)],
|
||||
puzzle_hashes_to_sign,
|
||||
tx_config,
|
||||
fee,
|
||||
{nft_coin_info.coin},
|
||||
new_owner=did_id,
|
||||
new_did_inner_hash=did_inner_hash,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
)
|
||||
first = False
|
||||
|
@ -1149,8 +1154,8 @@ class NFTWallet:
|
|||
self,
|
||||
nft_list: List[NFTCoinInfo],
|
||||
puzzle_hash: bytes32,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> List[TransactionRecord]:
|
||||
self.log.debug("Transfer NFTs %s to %s", nft_list, puzzle_hash.hex())
|
||||
nft_tx_record = []
|
||||
|
@ -1164,11 +1169,11 @@ class NFTWallet:
|
|||
await self.generate_signed_transaction(
|
||||
[uint64(nft_coin_info.coin.amount)],
|
||||
[puzzle_hash],
|
||||
tx_config,
|
||||
coins={nft_coin_info.coin},
|
||||
fee=fee,
|
||||
new_owner=b"",
|
||||
new_did_inner_hash=b"",
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
)
|
||||
first = False
|
||||
|
@ -1188,8 +1193,8 @@ class NFTWallet:
|
|||
self,
|
||||
nft_coin_info: NFTCoinInfo,
|
||||
did_id: bytes,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> SpendBundle:
|
||||
self.log.debug("Setting NFT DID with parameters: nft=%s did=%s", nft_coin_info, did_id)
|
||||
unft = UncurriedNFT.uncurry(*nft_coin_info.full_puzzle.uncurry())
|
||||
|
@ -1199,18 +1204,18 @@ class NFTWallet:
|
|||
did_inner_hash = b""
|
||||
additional_bundles = []
|
||||
if did_id != b"":
|
||||
did_inner_hash, did_bundle = await self.get_did_approval_info([nft_id], bytes32(did_id))
|
||||
did_inner_hash, did_bundle = await self.get_did_approval_info([nft_id], tx_config, bytes32(did_id))
|
||||
additional_bundles.append(did_bundle)
|
||||
|
||||
nft_tx_record = await self.generate_signed_transaction(
|
||||
[uint64(nft_coin_info.coin.amount)],
|
||||
puzzle_hashes_to_sign,
|
||||
tx_config,
|
||||
fee,
|
||||
{nft_coin_info.coin},
|
||||
new_owner=did_id,
|
||||
new_did_inner_hash=did_inner_hash,
|
||||
additional_bundles=additional_bundles,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
spend_bundle = SpendBundle.aggregate([x.spend_bundle for x in nft_tx_record if x.spend_bundle is not None])
|
||||
if spend_bundle:
|
||||
|
@ -1225,6 +1230,7 @@ class NFTWallet:
|
|||
async def mint_from_did(
|
||||
self,
|
||||
metadata_list: List[Dict[str, Any]],
|
||||
tx_config: TXConfig,
|
||||
target_list: Optional[List[bytes32]] = [],
|
||||
mint_number_start: Optional[int] = 1,
|
||||
mint_total: Optional[int] = None,
|
||||
|
@ -1235,7 +1241,6 @@ class NFTWallet:
|
|||
did_coin: Optional[Coin] = None,
|
||||
did_lineage_parent: Optional[bytes32] = None,
|
||||
fee: Optional[uint64] = uint64(0),
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> SpendBundle:
|
||||
"""
|
||||
Minting NFTs from the DID linked wallet, also used for bulk minting NFTs.
|
||||
|
@ -1287,7 +1292,7 @@ class NFTWallet:
|
|||
|
||||
# Ensure we have a did coin and its next inner puzzle hash
|
||||
if did_coin is None:
|
||||
coins = await did_wallet.select_coins(uint64(1))
|
||||
coins = await did_wallet.select_coins(uint64(1), tx_config.coin_selection_config)
|
||||
assert coins is not None
|
||||
did_coin = coins.pop()
|
||||
innerpuz: Program = did_wallet.did_info.current_inner
|
||||
|
@ -1305,7 +1310,7 @@ class NFTWallet:
|
|||
assert isinstance(fee, uint64)
|
||||
total_amount = len(metadata_list) + fee
|
||||
if xch_coins is None:
|
||||
xch_coins = await self.standard_wallet.select_coins(uint64(total_amount))
|
||||
xch_coins = await self.standard_wallet.select_coins(uint64(total_amount), tx_config.coin_selection_config)
|
||||
assert len(xch_coins) > 0
|
||||
|
||||
# set the chunk size for the spend bundle we're going to create
|
||||
|
@ -1407,12 +1412,12 @@ class NFTWallet:
|
|||
eve_txs = await self.generate_signed_transaction(
|
||||
[uint64(eve_coin.amount)],
|
||||
[target_ph],
|
||||
tx_config,
|
||||
nft_coin=nft_coin,
|
||||
new_owner=b"",
|
||||
new_did_inner_hash=b"",
|
||||
additional_bundles=[],
|
||||
memos=[[target_ph]],
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
eve_sb = eve_txs[0].spend_bundle
|
||||
assert eve_sb is not None
|
||||
|
@ -1512,13 +1517,13 @@ class NFTWallet:
|
|||
async def mint_from_xch(
|
||||
self,
|
||||
metadata_list: List[Dict[str, Any]],
|
||||
tx_config: TXConfig,
|
||||
target_list: Optional[List[bytes32]] = [],
|
||||
mint_number_start: Optional[int] = 1,
|
||||
mint_total: Optional[int] = None,
|
||||
xch_coins: Optional[Set[Coin]] = None,
|
||||
xch_change_ph: Optional[bytes32] = None,
|
||||
fee: Optional[uint64] = uint64(0),
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> SpendBundle:
|
||||
"""
|
||||
Minting NFTs from a single XCH spend using intermediate launcher puzzle
|
||||
|
@ -1544,7 +1549,7 @@ class NFTWallet:
|
|||
assert isinstance(fee, uint64)
|
||||
total_amount = len(metadata_list) + fee
|
||||
if xch_coins is None:
|
||||
xch_coins = await self.standard_wallet.select_coins(uint64(total_amount))
|
||||
xch_coins = await self.standard_wallet.select_coins(uint64(total_amount), tx_config.coin_selection_config)
|
||||
assert len(xch_coins) > 0
|
||||
|
||||
funding_coin = xch_coins.copy().pop()
|
||||
|
@ -1644,12 +1649,12 @@ class NFTWallet:
|
|||
eve_txs = await self.generate_signed_transaction(
|
||||
[uint64(eve_coin.amount)],
|
||||
[target_ph],
|
||||
tx_config,
|
||||
nft_coin=nft_coin,
|
||||
new_owner=b"",
|
||||
new_did_inner_hash=b"",
|
||||
additional_bundles=[],
|
||||
memos=[[target_ph]],
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
eve_sb = eve_txs[0].spend_bundle
|
||||
assert eve_sb is not None
|
||||
|
@ -1712,10 +1717,7 @@ class NFTWallet:
|
|||
async def select_coins(
|
||||
self,
|
||||
amount: uint64,
|
||||
exclude: Optional[List[Coin]] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
coin_selection_config: CoinSelectionConfig,
|
||||
) -> Set[Coin]:
|
||||
raise RuntimeError("NFTWallet does not support select_coins()")
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ from chia.wallet.notification_store import Notification, NotificationStore
|
|||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.compute_memos import compute_memos_for_spend
|
||||
from chia.wallet.util.notifications import construct_notification
|
||||
from chia.wallet.util.tx_config import TXConfig
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
|
||||
|
||||
|
@ -82,9 +83,11 @@ class NotificationManager:
|
|||
return True
|
||||
|
||||
async def send_new_notification(
|
||||
self, target: bytes32, msg: bytes, amount: uint64, fee: uint64 = uint64(0)
|
||||
self, target: bytes32, msg: bytes, amount: uint64, tx_config: TXConfig, fee: uint64 = uint64(0)
|
||||
) -> TransactionRecord:
|
||||
coins: Set[Coin] = await self.wallet_state_manager.main_wallet.select_coins(uint64(amount + fee))
|
||||
coins: Set[Coin] = await self.wallet_state_manager.main_wallet.select_coins(
|
||||
uint64(amount + fee), tx_config.coin_selection_config
|
||||
)
|
||||
origin_coin: bytes32 = next(iter(coins)).name()
|
||||
notification_puzzle: Program = construct_notification(target, amount)
|
||||
notification_hash: bytes32 = notification_puzzle.get_tree_hash()
|
||||
|
@ -98,6 +101,7 @@ class NotificationManager:
|
|||
chia_tx = await self.wallet_state_manager.main_wallet.generate_signed_transaction(
|
||||
amount,
|
||||
notification_hash,
|
||||
tx_config,
|
||||
fee,
|
||||
coins=coins,
|
||||
origin_id=origin_coin,
|
||||
|
|
|
@ -19,6 +19,7 @@ from chia.wallet.lineage_proof import LineageProof
|
|||
from chia.wallet.payment import Payment
|
||||
from chia.wallet.puzzles.load_clvm import load_clvm_maybe_recompile
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.tx_config import TXConfig
|
||||
|
||||
GENESIS_BY_ID_MOD = load_clvm_maybe_recompile("genesis_by_coin_id.clsp")
|
||||
GENESIS_BY_PUZHASH_MOD = load_clvm_maybe_recompile("genesis_by_puzzle_hash.clsp")
|
||||
|
@ -41,7 +42,7 @@ class LimitationsProgram:
|
|||
|
||||
@classmethod
|
||||
async def generate_issuance_bundle(
|
||||
cls, wallet, cat_tail_info: Dict, amount: uint64
|
||||
cls, wallet, cat_tail_info: Dict, amount: uint64, tx_config: TXConfig
|
||||
) -> Tuple[TransactionRecord, SpendBundle]:
|
||||
raise NotImplementedError("Need to implement 'generate_issuance_bundle' on limitations programs")
|
||||
|
||||
|
@ -69,8 +70,10 @@ class GenesisById(LimitationsProgram):
|
|||
return Program.to([])
|
||||
|
||||
@classmethod
|
||||
async def generate_issuance_bundle(cls, wallet, _: Dict, amount: uint64) -> Tuple[TransactionRecord, SpendBundle]:
|
||||
coins = await wallet.standard_wallet.select_coins(amount)
|
||||
async def generate_issuance_bundle(
|
||||
cls, wallet, _: Dict, amount: uint64, tx_config: TXConfig
|
||||
) -> Tuple[TransactionRecord, SpendBundle]:
|
||||
coins = await wallet.standard_wallet.select_coins(amount, tx_config.coin_selection_config)
|
||||
|
||||
origin = coins.copy().pop()
|
||||
origin_id = origin.name()
|
||||
|
@ -86,7 +89,7 @@ class GenesisById(LimitationsProgram):
|
|||
minted_cat_puzzle_hash: bytes32 = construct_cat_puzzle(CAT_MOD, tail.get_tree_hash(), cat_inner).get_tree_hash()
|
||||
|
||||
tx_record: TransactionRecord = await wallet.standard_wallet.generate_signed_transaction(
|
||||
amount, minted_cat_puzzle_hash, uint64(0), coins, origin_id=origin_id
|
||||
amount, minted_cat_puzzle_hash, tx_config, uint64(0), coins, origin_id=origin_id
|
||||
)
|
||||
assert tx_record.spend_bundle is not None
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ from chia.wallet.trading.trade_store import TradeStore
|
|||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.query_filter import HashFilter
|
||||
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 import Wallet
|
||||
from chia.wallet.wallet_coin_record import WalletCoinRecord
|
||||
|
@ -221,7 +222,7 @@ class TradeManager:
|
|||
self.wallet_state_manager.state_changed("offer_failed")
|
||||
|
||||
async def cancel_pending_offer_safely(
|
||||
self, trade_id: bytes32, fee: uint64 = uint64(0)
|
||||
self, trade_id: bytes32, tx_config: TXConfig, fee: uint64 = uint64(0)
|
||||
) -> Optional[List[TransactionRecord]]:
|
||||
"""This will create a transaction that includes coins that were offered"""
|
||||
self.log.info(f"Secure-Cancel pending offer with id trade_id {trade_id.hex()}")
|
||||
|
@ -246,7 +247,10 @@ class TradeManager:
|
|||
if fee_to_pay > coin.amount:
|
||||
selected_coins: Set[Coin] = await wallet.select_coins(
|
||||
uint64(fee_to_pay - coin.amount),
|
||||
exclude=[coin],
|
||||
dataclasses.replace(
|
||||
tx_config.coin_selection_config,
|
||||
exculded_coin_ids=[*tx_config.coin_selection_config.excluded_coin_ids, coin.name()],
|
||||
),
|
||||
)
|
||||
selected_coins.add(coin)
|
||||
else:
|
||||
|
@ -254,6 +258,12 @@ class TradeManager:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(sum([c.amount for c in selected_coins]) - fee_to_pay),
|
||||
new_ph,
|
||||
dataclasses.replace(
|
||||
tx_config,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
tx_config.coin_selection_config, excluded_coin_ids=[]
|
||||
),
|
||||
),
|
||||
fee=fee_to_pay,
|
||||
coins=selected_coins,
|
||||
ignore_max_send_amount=True,
|
||||
|
@ -262,7 +272,17 @@ class TradeManager:
|
|||
else:
|
||||
# ATTENTION: new_wallets
|
||||
txs = await wallet.generate_signed_transaction(
|
||||
[coin.amount], [new_ph], fee=fee_to_pay, coins={coin}, ignore_max_send_amount=True
|
||||
[coin.amount],
|
||||
[new_ph],
|
||||
dataclasses.replace(
|
||||
tx_config,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
tx_config.coin_selection_config, excluded_coin_ids=[]
|
||||
),
|
||||
),
|
||||
fee=fee_to_pay,
|
||||
coins={coin},
|
||||
ignore_max_send_amount=True,
|
||||
)
|
||||
all_txs.extend(txs)
|
||||
fee_to_pay = uint64(0)
|
||||
|
@ -297,7 +317,7 @@ class TradeManager:
|
|||
return all_txs
|
||||
|
||||
async def cancel_pending_offers(
|
||||
self, trades: List[TradeRecord], fee: uint64 = uint64(0), secure: bool = True
|
||||
self, trades: List[TradeRecord], tx_config: TXConfig, fee: uint64 = uint64(0), secure: bool = True
|
||||
) -> Optional[List[TransactionRecord]]:
|
||||
"""This will create a transaction that includes coins that were offered"""
|
||||
|
||||
|
@ -325,7 +345,10 @@ class TradeManager:
|
|||
if fee_to_pay > coin.amount:
|
||||
selected_coins: Set[Coin] = await wallet.select_coins(
|
||||
uint64(fee_to_pay - coin.amount),
|
||||
exclude=[coin],
|
||||
dataclasses.replace(
|
||||
tx_config.coin_selection_config,
|
||||
exculded_coin_ids=[*tx_config.coin_selection_config.excluded_coin_ids, coin.name()],
|
||||
),
|
||||
)
|
||||
selected_coins.add(coin)
|
||||
else:
|
||||
|
@ -333,6 +356,12 @@ class TradeManager:
|
|||
tx: TransactionRecord = await wallet.generate_signed_transaction(
|
||||
uint64(sum([c.amount for c in selected_coins]) - fee_to_pay),
|
||||
new_ph,
|
||||
dataclasses.replace(
|
||||
tx_config,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
tx_config.coin_selection_config, excluded_coin_ids=[]
|
||||
),
|
||||
),
|
||||
fee=fee_to_pay,
|
||||
coins=selected_coins,
|
||||
ignore_max_send_amount=True,
|
||||
|
@ -343,7 +372,17 @@ class TradeManager:
|
|||
else:
|
||||
# ATTENTION: new_wallets
|
||||
txs = await wallet.generate_signed_transaction(
|
||||
[coin.amount], [new_ph], fee=fee_to_pay, coins={coin}, ignore_max_send_amount=True
|
||||
[coin.amount],
|
||||
[new_ph],
|
||||
dataclasses.replace(
|
||||
tx_config,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
tx_config.coin_selection_config, excluded_coin_ids=[]
|
||||
),
|
||||
),
|
||||
fee=fee_to_pay,
|
||||
coins={coin},
|
||||
ignore_max_send_amount=True,
|
||||
)
|
||||
for tx in txs:
|
||||
if tx is not None and tx.spend_bundle is not None:
|
||||
|
@ -406,13 +445,11 @@ class TradeManager:
|
|||
async def create_offer_for_ids(
|
||||
self,
|
||||
offer: Dict[Union[int, bytes32], int],
|
||||
tx_config: TXConfig,
|
||||
driver_dict: Optional[Dict[bytes32, PuzzleInfo]] = None,
|
||||
solver: Optional[Solver] = None,
|
||||
fee: uint64 = uint64(0),
|
||||
validate_only: bool = False,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> Union[Tuple[Literal[True], TradeRecord, None], Tuple[Literal[False], None, str]]:
|
||||
if driver_dict is None:
|
||||
driver_dict = {}
|
||||
|
@ -420,12 +457,10 @@ class TradeManager:
|
|||
solver = Solver({})
|
||||
result = await self._create_offer_for_ids(
|
||||
offer,
|
||||
tx_config,
|
||||
driver_dict,
|
||||
solver,
|
||||
fee=fee,
|
||||
min_coin_amount=min_coin_amount,
|
||||
max_coin_amount=max_coin_amount,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
if not result[0] or result[1] is None:
|
||||
raise Exception(f"Error creating offer: {result[2]}")
|
||||
|
@ -455,13 +490,11 @@ class TradeManager:
|
|||
async def _create_offer_for_ids(
|
||||
self,
|
||||
offer_dict: Dict[Union[int, bytes32], int],
|
||||
tx_config: TXConfig,
|
||||
driver_dict: Optional[Dict[bytes32, PuzzleInfo]] = None,
|
||||
solver: Optional[Solver] = None,
|
||||
fee: uint64 = uint64(0),
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
old: bool = False,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> Union[Tuple[Literal[True], Offer, None], Tuple[Literal[False], None, str]]:
|
||||
"""
|
||||
Offer is dictionary of wallet ids and amount
|
||||
|
@ -470,14 +503,6 @@ class TradeManager:
|
|||
driver_dict = {}
|
||||
if solver is None:
|
||||
solver = Solver({})
|
||||
if reuse_puzhash is None:
|
||||
reuse_puzhash_config = self.wallet_state_manager.config.get("reuse_public_key_for_change", None)
|
||||
if reuse_puzhash_config is None:
|
||||
reuse_puzhash = False
|
||||
else:
|
||||
reuse_puzhash = reuse_puzhash_config.get(
|
||||
str(self.wallet_state_manager.wallet_node.logged_in_fingerprint), False
|
||||
)
|
||||
try:
|
||||
coins_to_offer: Dict[Union[int, bytes32], List[Coin]] = {}
|
||||
requested_payments: Dict[Optional[bytes32], List[Payment]] = {}
|
||||
|
@ -492,7 +517,7 @@ class TradeManager:
|
|||
if isinstance(id, int):
|
||||
wallet_id = uint32(id)
|
||||
wallet = self.wallet_state_manager.wallets[wallet_id]
|
||||
p2_ph: bytes32 = await wallet.get_puzzle_hash(new=not reuse_puzhash)
|
||||
p2_ph: bytes32 = await wallet.get_puzzle_hash(new=not tx_config.reuse_puzhash)
|
||||
if wallet.type() != WalletType.STANDARD_WALLET:
|
||||
if callable(getattr(wallet, "get_asset_id", None)): # ATTENTION: new wallets
|
||||
asset_id = bytes32(bytes.fromhex(wallet.get_asset_id()))
|
||||
|
@ -502,7 +527,9 @@ class TradeManager:
|
|||
f"Cannot request assets from wallet id {wallet.id()} without more information"
|
||||
)
|
||||
else:
|
||||
p2_ph = await self.wallet_state_manager.main_wallet.get_puzzle_hash(new=not reuse_puzhash)
|
||||
p2_ph = await self.wallet_state_manager.main_wallet.get_puzzle_hash(
|
||||
new=not tx_config.reuse_puzhash
|
||||
)
|
||||
asset_id = id
|
||||
wallet = await self.wallet_state_manager.get_wallet_for_asset_id(asset_id.hex())
|
||||
memos = [p2_ph]
|
||||
|
@ -529,7 +556,7 @@ class TradeManager:
|
|||
if wallet.type() == WalletType.STANDARD_WALLET:
|
||||
amount_to_select += fee
|
||||
coins_to_offer[id] = await wallet.get_coins_to_offer(
|
||||
asset_id, uint64(amount_to_select), min_coin_amount, max_coin_amount
|
||||
asset_id, uint64(amount_to_select), tx_config.coin_selection_config
|
||||
)
|
||||
# Note: if we use check_for_special_offer_making, this is not used.
|
||||
elif amount == 0:
|
||||
|
@ -554,7 +581,7 @@ class TradeManager:
|
|||
raise ValueError(f"Wallet for asset id {asset_id} is not properly integrated with TradeManager")
|
||||
|
||||
potential_special_offer: Optional[Offer] = await self.check_for_special_offer_making(
|
||||
offer_dict_no_ints, driver_dict, solver, fee, min_coin_amount, max_coin_amount, old
|
||||
offer_dict_no_ints, driver_dict, tx_config, solver, fee, old
|
||||
)
|
||||
|
||||
if potential_special_offer is not None:
|
||||
|
@ -581,10 +608,10 @@ class TradeManager:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
abs(offer_dict[id]),
|
||||
OFFER_MOD_OLD_HASH if old else Offer.ph(),
|
||||
tx_config,
|
||||
fee=fee_left_to_pay,
|
||||
coins=set(selected_coins),
|
||||
puzzle_announcements_to_consume=announcements_to_assert,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
all_transactions.append(tx)
|
||||
elif wallet.type() == WalletType.NFT:
|
||||
|
@ -595,10 +622,10 @@ class TradeManager:
|
|||
# [abs(offer_dict[id])],
|
||||
amounts,
|
||||
[OFFER_MOD_OLD_HASH if old else Offer.ph()],
|
||||
tx_config,
|
||||
fee=fee_left_to_pay,
|
||||
coins=set(selected_coins),
|
||||
puzzle_announcements_to_consume=announcements_to_assert,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
all_transactions.extend(txs)
|
||||
else:
|
||||
|
@ -606,10 +633,10 @@ class TradeManager:
|
|||
txs = await wallet.generate_signed_transaction(
|
||||
[abs(offer_dict[id])],
|
||||
[OFFER_MOD_OLD_HASH if old else Offer.ph()],
|
||||
tx_config,
|
||||
fee=fee_left_to_pay,
|
||||
coins=set(selected_coins),
|
||||
puzzle_announcements_to_consume=announcements_to_assert,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
all_transactions.extend(txs)
|
||||
|
||||
|
@ -744,11 +771,9 @@ class TradeManager:
|
|||
self,
|
||||
offer: Offer,
|
||||
peer: WSChiaConnection,
|
||||
tx_config: TXConfig,
|
||||
solver: Optional[Solver] = None,
|
||||
fee: uint64 = uint64(0),
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> Tuple[TradeRecord, List[TransactionRecord]]:
|
||||
if solver is None:
|
||||
solver = Solver({})
|
||||
|
@ -776,13 +801,11 @@ class TradeManager:
|
|||
raise ValueError("This offer is no longer valid")
|
||||
result = await self._create_offer_for_ids(
|
||||
take_offer_dict,
|
||||
tx_config,
|
||||
offer.driver_dict,
|
||||
solver,
|
||||
fee=fee,
|
||||
min_coin_amount=min_coin_amount,
|
||||
max_coin_amount=max_coin_amount,
|
||||
old=offer.old,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
if not result[0] or result[1] is None:
|
||||
raise ValueError(result[2])
|
||||
|
@ -842,10 +865,9 @@ class TradeManager:
|
|||
self,
|
||||
offer_dict: Dict[Optional[bytes32], int],
|
||||
driver_dict: Dict[bytes32, PuzzleInfo],
|
||||
tx_config: TXConfig,
|
||||
solver: Solver,
|
||||
fee: uint64 = uint64(0),
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
old: bool = False,
|
||||
) -> Optional[Offer]:
|
||||
for puzzle_info in driver_dict.values():
|
||||
|
@ -856,7 +878,7 @@ class TradeManager:
|
|||
== AssetType.ROYALTY_TRANSFER_PROGRAM.value
|
||||
):
|
||||
return await NFTWallet.make_nft1_offer(
|
||||
self.wallet_state_manager, offer_dict, driver_dict, fee, min_coin_amount, max_coin_amount, old
|
||||
self.wallet_state_manager, offer_dict, driver_dict, tx_config, fee, old
|
||||
)
|
||||
elif (
|
||||
puzzle_info.check_type(
|
||||
|
@ -868,7 +890,7 @@ class TradeManager:
|
|||
and puzzle_info.also()["updater_hash"] == ACS_MU_PH # type: ignore
|
||||
):
|
||||
return await DataLayerWallet.make_update_offer(
|
||||
self.wallet_state_manager, offer_dict, driver_dict, solver, fee, old
|
||||
self.wallet_state_manager, offer_dict, driver_dict, solver, tx_config, fee, old
|
||||
)
|
||||
return None
|
||||
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
from typing import Any, Dict, List, Optional, Type, TypeVar
|
||||
|
||||
from chia.consensus.constants import ConsensusConstants
|
||||
from chia.consensus.default_constants import DEFAULT_CONSTANTS
|
||||
from chia.types.blockchain_format.coin import Coin
|
||||
from chia.types.blockchain_format.sized_bytes import bytes32
|
||||
from chia.util.ints import uint64
|
||||
from chia.util.streamable import Streamable, streamable
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class CoinSelectionConfig:
|
||||
min_coin_amount: uint64
|
||||
max_coin_amount: uint64
|
||||
excluded_coin_amounts: List[uint64]
|
||||
excluded_coin_ids: List[bytes32]
|
||||
|
||||
def to_json_dict(self) -> Dict[str, Any]:
|
||||
return CoinSelectionConfigLoader(
|
||||
self.min_coin_amount,
|
||||
self.max_coin_amount,
|
||||
self.excluded_coin_amounts,
|
||||
self.excluded_coin_ids,
|
||||
).to_json_dict()
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class TXConfig:
|
||||
coin_selection_config: CoinSelectionConfig
|
||||
reuse_puzhash: bool
|
||||
|
||||
def to_json_dict(self) -> Dict[str, Any]:
|
||||
return TXConfigLoader(
|
||||
self.coin_selection_config.min_coin_amount,
|
||||
self.coin_selection_config.max_coin_amount,
|
||||
self.coin_selection_config.excluded_coin_amounts,
|
||||
self.coin_selection_config.excluded_coin_ids,
|
||||
self.reuse_puzhash,
|
||||
).to_json_dict()
|
||||
|
||||
|
||||
_T_CoinSelectionConfigLoader = TypeVar("_T_CoinSelectionConfigLoader", bound="CoinSelectionConfigLoader")
|
||||
|
||||
|
||||
@streamable
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class CoinSelectionConfigLoader(Streamable):
|
||||
min_coin_amount: Optional[uint64] = None
|
||||
max_coin_amount: Optional[uint64] = None
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None
|
||||
excluded_coin_ids: Optional[List[bytes32]] = None
|
||||
|
||||
def autofill(
|
||||
self,
|
||||
constants: ConsensusConstants,
|
||||
) -> CoinSelectionConfig:
|
||||
return CoinSelectionConfig(
|
||||
min_coin_amount=uint64(0) if self.min_coin_amount is None else self.min_coin_amount,
|
||||
max_coin_amount=uint64(constants.MAX_COIN_AMOUNT) if self.max_coin_amount is None else self.max_coin_amount,
|
||||
excluded_coin_amounts=[] if self.excluded_coin_amounts is None else self.excluded_coin_amounts,
|
||||
excluded_coin_ids=[] if self.excluded_coin_ids is None else self.excluded_coin_ids,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_json_dict(
|
||||
cls: Type[_T_CoinSelectionConfigLoader], json_dict: Dict[str, Any]
|
||||
) -> _T_CoinSelectionConfigLoader:
|
||||
if "excluded_coins" in json_dict:
|
||||
excluded_coins: List[Coin] = [Coin.from_json_dict(c) for c in json_dict["excluded_coins"]]
|
||||
excluded_coin_ids: List[str] = [c.name().hex() for c in excluded_coins]
|
||||
if "excluded_coin_ids" in json_dict:
|
||||
json_dict["excluded_coin_ids"] = [*excluded_coin_ids, *json_dict["excluded_coin_ids"]]
|
||||
json_dict["excluded_coin_ids"] = excluded_coin_ids
|
||||
return super().from_json_dict(json_dict)
|
||||
|
||||
|
||||
@streamable
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class TXConfigLoader(Streamable):
|
||||
min_coin_amount: Optional[uint64] = None
|
||||
max_coin_amount: Optional[uint64] = None
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None
|
||||
excluded_coin_ids: Optional[List[bytes32]] = None
|
||||
reuse_puzhash: Optional[bool] = None
|
||||
|
||||
def autofill(
|
||||
self,
|
||||
config: Dict[str, Any],
|
||||
logged_in_fingerprint: int,
|
||||
constants: ConsensusConstants,
|
||||
) -> TXConfig:
|
||||
if self.reuse_puzhash is None:
|
||||
reuse_puzhash_config = config.get("reuse_public_key_for_change", None)
|
||||
if reuse_puzhash_config is None:
|
||||
reuse_puzhash = False
|
||||
else:
|
||||
reuse_puzhash = reuse_puzhash_config.get(str(logged_in_fingerprint), False)
|
||||
else:
|
||||
reuse_puzhash = self.reuse_puzhash
|
||||
|
||||
return TXConfig(
|
||||
CoinSelectionConfig(
|
||||
min_coin_amount=uint64(0) if self.min_coin_amount is None else self.min_coin_amount,
|
||||
max_coin_amount=uint64(constants.MAX_COIN_AMOUNT)
|
||||
if self.max_coin_amount is None
|
||||
else self.max_coin_amount,
|
||||
excluded_coin_amounts=[] if self.excluded_coin_amounts is None else self.excluded_coin_amounts,
|
||||
excluded_coin_ids=[] if self.excluded_coin_ids is None else self.excluded_coin_ids,
|
||||
),
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
|
||||
|
||||
DEFAULT_COIN_SELECTION_CONFIG = CoinSelectionConfig(uint64(0), uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT), [], [])
|
||||
DEFAULT_TX_CONFIG = TXConfig(
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
False,
|
||||
)
|
|
@ -24,6 +24,7 @@ from chia.wallet.sign_coin_spends import sign_coin_spends
|
|||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.compute_memos import compute_memos
|
||||
from chia.wallet.util.transaction_type import TransactionType
|
||||
from chia.wallet.util.tx_config import CoinSelectionConfig, TXConfig
|
||||
from chia.wallet.util.wallet_sync_utils import fetch_coin_spend_for_coin_state
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.vc_wallet.vc_drivers import VerifiedCredential
|
||||
|
@ -138,6 +139,7 @@ class VCWallet:
|
|||
async def launch_new_vc(
|
||||
self,
|
||||
provider_did: bytes32,
|
||||
tx_config: TXConfig,
|
||||
inner_puzzle_hash: Optional[bytes32] = None,
|
||||
fee: uint64 = uint64(0),
|
||||
) -> Tuple[VCRecord, List[TransactionRecord]]:
|
||||
|
@ -157,11 +159,11 @@ class VCWallet:
|
|||
if not found_did:
|
||||
raise ValueError(f"You don't own the DID {provider_did.hex()}") # pragma: no cover
|
||||
# Mint VC
|
||||
coins = await self.standard_wallet.select_coins(uint64(1 + fee), min_coin_amount=uint64(1 + fee))
|
||||
coins = await self.standard_wallet.select_coins(uint64(1 + fee), tx_config.coin_selection_config)
|
||||
if len(coins) == 0:
|
||||
raise ValueError("Cannot find a coin to mint the verified credential.") # pragma: no cover
|
||||
if inner_puzzle_hash is None:
|
||||
inner_puzzle_hash = await self.standard_wallet.get_puzzle_hash(new=False) # pragma: no cover
|
||||
if inner_puzzle_hash is None: # pragma: no cover
|
||||
inner_puzzle_hash = await self.standard_wallet.get_puzzle_hash(new=not tx_config.reuse_puzhash)
|
||||
original_coin = coins.pop()
|
||||
dpuz, coin_spends, vc = VerifiedCredential.launch(
|
||||
original_coin,
|
||||
|
@ -207,13 +209,13 @@ class VCWallet:
|
|||
async def generate_signed_transaction(
|
||||
self,
|
||||
vc_id: bytes32,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
new_inner_puzhash: Optional[bytes32] = None,
|
||||
coin_announcements: Optional[Set[bytes]] = None,
|
||||
puzzle_announcements: Optional[Set[bytes]] = None,
|
||||
coin_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
puzzle_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
**kwargs: Unpack[GSTOptionalArgs],
|
||||
) -> List[TransactionRecord]:
|
||||
new_proof_hash: Optional[bytes32] = kwargs.get(
|
||||
|
@ -257,7 +259,7 @@ class VCWallet:
|
|||
if fee > 0:
|
||||
announcement_to_make = vc_record.vc.coin.name()
|
||||
chia_tx = await self.wallet_state_manager.main_wallet.create_tandem_xch_tx(
|
||||
fee, Announcement(vc_record.vc.coin.name(), announcement_to_make), reuse_puzhash=reuse_puzhash
|
||||
fee, tx_config, Announcement(vc_record.vc.coin.name(), announcement_to_make)
|
||||
)
|
||||
if coin_announcements is None:
|
||||
coin_announcements = set((announcement_to_make,))
|
||||
|
@ -305,7 +307,9 @@ class VCWallet:
|
|||
assert isinstance(wallet, DIDWallet)
|
||||
if bytes32.fromhex(wallet.get_my_DID()) == vc_record.vc.proof_provider:
|
||||
self.log.debug("Creating announcement from DID for vc: %s", vc_id.hex())
|
||||
did_bundle = await wallet.create_message_spend(puzzle_announcements={bytes(did_announcement)})
|
||||
did_bundle = await wallet.create_message_spend(
|
||||
tx_config, puzzle_announcements={bytes(did_announcement)}
|
||||
)
|
||||
spend_bundles.append(did_bundle)
|
||||
break
|
||||
else:
|
||||
|
@ -343,7 +347,11 @@ class VCWallet:
|
|||
return tx_list
|
||||
|
||||
async def revoke_vc(
|
||||
self, parent_id: bytes32, peer: WSChiaConnection, fee: uint64 = uint64(0), reuse_puzhash: Optional[bool] = None
|
||||
self,
|
||||
parent_id: bytes32,
|
||||
peer: WSChiaConnection,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
) -> List[TransactionRecord]:
|
||||
vc_coin_states: List[CoinState] = await self.wallet_state_manager.wallet_node.get_coin_state(
|
||||
[parent_id], peer=peer
|
||||
|
@ -365,17 +373,19 @@ class VCWallet:
|
|||
else:
|
||||
raise ValueError(f"You don't own the DID {vc.proof_provider.hex()}") # pragma: no cover
|
||||
|
||||
recovery_info: Optional[Tuple[bytes32, bytes32, uint64]] = await did_wallet.get_info_for_recovery()
|
||||
recovery_info: Optional[Tuple[bytes32, bytes32, uint64]] = await did_wallet.get_info_for_recovery(
|
||||
tx_config.coin_selection_config
|
||||
)
|
||||
if recovery_info is None:
|
||||
raise RuntimeError("DID could not currently be accessed while trying to revoke VC") # pragma: no cover
|
||||
_, provider_inner_puzhash, _ = recovery_info
|
||||
|
||||
# Generate spend specific nonce
|
||||
coins = await did_wallet.select_coins(uint64(1))
|
||||
coins = await did_wallet.select_coins(uint64(1), tx_config.coin_selection_config)
|
||||
assert coins is not None
|
||||
coins.add(vc.coin)
|
||||
if fee > 0:
|
||||
coins.update(await self.standard_wallet.select_coins(fee))
|
||||
coins.update(await self.standard_wallet.select_coins(fee, tx_config.coin_selection_config))
|
||||
sorted_coins: List[Coin] = sorted(coins, key=Coin.name)
|
||||
sorted_coin_list: List[List[Union[bytes32, uint64]]] = [coin_as_list(c) for c in sorted_coins]
|
||||
nonce: bytes32 = Program.to(sorted_coin_list).get_tree_hash()
|
||||
|
@ -384,6 +394,7 @@ class VCWallet:
|
|||
# Assemble final bundle
|
||||
expected_did_announcement, vc_spend = vc.activate_backdoor(provider_inner_puzhash, announcement_nonce=nonce)
|
||||
did_spend: SpendBundle = await did_wallet.create_message_spend(
|
||||
tx_config,
|
||||
puzzle_announcements={expected_did_announcement},
|
||||
coin_announcements_to_assert={vc_announcement},
|
||||
)
|
||||
|
@ -408,7 +419,7 @@ class VCWallet:
|
|||
)
|
||||
if fee > 0:
|
||||
chia_tx: TransactionRecord = await self.wallet_state_manager.main_wallet.create_tandem_xch_tx(
|
||||
fee, vc_announcement, reuse_puzhash
|
||||
fee, tx_config, vc_announcement
|
||||
)
|
||||
assert tx.spend_bundle is not None
|
||||
assert chia_tx.spend_bundle is not None
|
||||
|
@ -421,10 +432,7 @@ class VCWallet:
|
|||
async def select_coins(
|
||||
self,
|
||||
amount: uint64,
|
||||
exclude: Optional[List[Coin]] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
coin_selection_config: CoinSelectionConfig,
|
||||
) -> Set[Coin]:
|
||||
raise RuntimeError("VCWallet does not support select_coins()") # pragma: no cover
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ from chia.wallet.transaction_record import TransactionRecord
|
|||
from chia.wallet.util.compute_memos import compute_memos
|
||||
from chia.wallet.util.puzzle_decorator import PuzzleDecoratorManager
|
||||
from chia.wallet.util.transaction_type import TransactionType
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG, CoinSelectionConfig, TXConfig
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet_coin_record import WalletCoinRecord
|
||||
from chia.wallet.wallet_info import WalletInfo
|
||||
|
@ -92,7 +93,11 @@ class Wallet:
|
|||
if self.cost_of_single_tx is None:
|
||||
coin = spendable[0].coin
|
||||
tx = await self.generate_signed_transaction(
|
||||
uint64(coin.amount), coin.puzzle_hash, coins={coin}, ignore_max_send_amount=True
|
||||
uint64(coin.amount),
|
||||
coin.puzzle_hash,
|
||||
DEFAULT_TX_CONFIG,
|
||||
coins={coin},
|
||||
ignore_max_send_amount=True,
|
||||
)
|
||||
assert tx.spend_bundle is not None
|
||||
program: BlockGenerator = simple_solution_generator(tx.spend_bundle)
|
||||
|
@ -204,6 +209,19 @@ class Wallet:
|
|||
await self.hack_populate_secret_key_for_puzzle_hash(puzzle.get_tree_hash())
|
||||
return puzzle
|
||||
|
||||
async def get_puzzle(self, new: bool) -> Program:
|
||||
if new:
|
||||
return await self.get_new_puzzle()
|
||||
else:
|
||||
record: Optional[
|
||||
DerivationRecord
|
||||
] = await self.wallet_state_manager.get_current_derivation_record_for_wallet(self.id())
|
||||
if record is None:
|
||||
return await self.get_new_puzzle()
|
||||
puzzle = puzzle_for_pk(record.pubkey)
|
||||
await self.hack_populate_secret_key_for_puzzle_hash(puzzle.get_tree_hash())
|
||||
return puzzle
|
||||
|
||||
async def get_puzzle_hash(self, new: bool) -> bytes32:
|
||||
if new:
|
||||
return await self.get_new_puzzlehash()
|
||||
|
@ -213,6 +231,7 @@ class Wallet:
|
|||
] = await self.wallet_state_manager.get_current_derivation_record_for_wallet(self.id())
|
||||
if record is None:
|
||||
return await self.get_new_puzzlehash()
|
||||
await self.hack_populate_secret_key_for_puzzle_hash(record.puzzle_hash)
|
||||
return record.puzzle_hash
|
||||
|
||||
async def get_new_puzzlehash(self) -> bytes32:
|
||||
|
@ -261,10 +280,7 @@ class Wallet:
|
|||
async def select_coins(
|
||||
self,
|
||||
amount: uint64,
|
||||
exclude: Optional[List[Coin]] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
coin_selection_config: CoinSelectionConfig,
|
||||
) -> Set[Coin]:
|
||||
"""
|
||||
Returns a set of coins that can be used for generating a new transaction.
|
||||
|
@ -280,18 +296,13 @@ class Wallet:
|
|||
unconfirmed_removals: Dict[bytes32, Coin] = await self.wallet_state_manager.unconfirmed_removals_for_wallet(
|
||||
self.id()
|
||||
)
|
||||
if max_coin_amount is None:
|
||||
max_coin_amount = uint64(self.wallet_state_manager.constants.MAX_COIN_AMOUNT)
|
||||
coins = await select_coins(
|
||||
spendable_amount,
|
||||
max_coin_amount,
|
||||
coin_selection_config,
|
||||
spendable_coins,
|
||||
unconfirmed_removals,
|
||||
self.log,
|
||||
uint128(amount),
|
||||
exclude,
|
||||
min_coin_amount,
|
||||
excluded_coin_amounts,
|
||||
)
|
||||
assert sum(c.amount for c in coins) >= amount
|
||||
return coins
|
||||
|
@ -300,6 +311,7 @@ class Wallet:
|
|||
self,
|
||||
amount: uint64,
|
||||
newpuzzlehash: bytes32,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
origin_id: Optional[bytes32] = None,
|
||||
coins: Optional[Set[Coin]] = None,
|
||||
|
@ -309,12 +321,7 @@ class Wallet:
|
|||
puzzle_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
memos: Optional[List[bytes]] = None,
|
||||
negative_change_allowed: bool = False,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
excluded_coins: Optional[Set[Coin]] = None,
|
||||
puzzle_decorator_override: Optional[List[Dict[str, Any]]] = None,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> List[CoinSpend]:
|
||||
"""
|
||||
Generates a unsigned transaction in form of List(Puzzle, Solutions)
|
||||
|
@ -329,15 +336,6 @@ class Wallet:
|
|||
primaries.extend(primaries_input)
|
||||
|
||||
total_amount = amount + sum(primary.amount for primary in primaries) + fee
|
||||
|
||||
if reuse_puzhash is None:
|
||||
reuse_puzhash_config = self.wallet_state_manager.config.get("reuse_public_key_for_change", None)
|
||||
if reuse_puzhash_config is None:
|
||||
reuse_puzhash = False
|
||||
else:
|
||||
reuse_puzhash = reuse_puzhash_config.get(
|
||||
str(self.wallet_state_manager.wallet_node.logged_in_fingerprint), False
|
||||
)
|
||||
total_balance = await self.get_spendable_balance()
|
||||
if not ignore_max_send_amount:
|
||||
max_send = await self.get_max_send_amount()
|
||||
|
@ -349,18 +347,10 @@ class Wallet:
|
|||
raise ValueError(
|
||||
f"Can't spend more than wallet balance: {total_balance} mojos, tried to spend: {total_amount} mojos"
|
||||
)
|
||||
excluded_coins_list: Optional[List[Coin]] = None
|
||||
if excluded_coins is not None:
|
||||
excluded_coins_list = list(excluded_coins)
|
||||
coins = await self.select_coins(
|
||||
uint64(total_amount),
|
||||
min_coin_amount=min_coin_amount,
|
||||
max_coin_amount=max_coin_amount,
|
||||
excluded_coin_amounts=excluded_coin_amounts,
|
||||
exclude=excluded_coins_list,
|
||||
tx_config.coin_selection_config,
|
||||
)
|
||||
elif excluded_coins is not None:
|
||||
raise ValueError("Can't exclude coins when also specifically including coins")
|
||||
|
||||
assert len(coins) > 0
|
||||
self.log.info(f"coins is not None {coins}")
|
||||
|
@ -406,7 +396,7 @@ class Wallet:
|
|||
target_primary.append(Payment(newpuzzlehash, amount, memos))
|
||||
|
||||
if change > 0:
|
||||
if reuse_puzhash:
|
||||
if tx_config.reuse_puzhash:
|
||||
change_puzzle_hash: bytes32 = coin.puzzle_hash
|
||||
for primary in primaries:
|
||||
if change_puzzle_hash == primary.puzzle_hash and change == primary.amount:
|
||||
|
@ -484,6 +474,7 @@ class Wallet:
|
|||
self,
|
||||
amount: uint64,
|
||||
puzzle_hash: bytes32,
|
||||
tx_config: TXConfig,
|
||||
fee: uint64 = uint64(0),
|
||||
coins: Optional[Set[Coin]] = None,
|
||||
primaries: Optional[List[Payment]] = None,
|
||||
|
@ -491,12 +482,7 @@ class Wallet:
|
|||
coin_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
puzzle_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
memos: Optional[List[bytes]] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
excluded_coins: Optional[Set[Coin]] = None,
|
||||
puzzle_decorator_override: Optional[List[Dict[str, Any]]] = None,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
**kwargs: Unpack[GSTOptionalArgs],
|
||||
) -> TransactionRecord:
|
||||
origin_id: Optional[bytes32] = kwargs.get("origin_id", None)
|
||||
|
@ -515,6 +501,7 @@ class Wallet:
|
|||
transaction = await self._generate_unsigned_transaction(
|
||||
amount,
|
||||
puzzle_hash,
|
||||
tx_config,
|
||||
fee,
|
||||
origin_id,
|
||||
coins,
|
||||
|
@ -524,12 +511,7 @@ class Wallet:
|
|||
puzzle_announcements_to_consume,
|
||||
memos,
|
||||
negative_change_allowed,
|
||||
min_coin_amount=min_coin_amount,
|
||||
max_coin_amount=max_coin_amount,
|
||||
excluded_coin_amounts=excluded_coin_amounts,
|
||||
excluded_coins=excluded_coins,
|
||||
puzzle_decorator_override=puzzle_decorator_override,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
assert len(transaction) > 0
|
||||
self.log.info("About to sign a transaction: %s", transaction)
|
||||
|
@ -574,25 +556,17 @@ class Wallet:
|
|||
async def create_tandem_xch_tx(
|
||||
self,
|
||||
fee: uint64,
|
||||
tx_config: TXConfig,
|
||||
announcement_to_assert: Optional[Announcement] = None,
|
||||
reuse_puzhash: Optional[bool] = None,
|
||||
) -> TransactionRecord:
|
||||
chia_coins = await self.select_coins(fee)
|
||||
if reuse_puzhash is None:
|
||||
reuse_puzhash_config = self.wallet_state_manager.config.get("reuse_public_key_for_change", None)
|
||||
if reuse_puzhash_config is None:
|
||||
reuse_puzhash = False
|
||||
else:
|
||||
reuse_puzhash = reuse_puzhash_config.get(
|
||||
str(self.wallet_state_manager.wallet_node.logged_in_fingerprint), False
|
||||
)
|
||||
chia_coins = await self.select_coins(fee, tx_config.coin_selection_config)
|
||||
chia_tx = await self.generate_signed_transaction(
|
||||
uint64(0),
|
||||
(await self.get_puzzle_hash(not reuse_puzhash)),
|
||||
(await self.get_puzzle_hash(not tx_config.reuse_puzhash)),
|
||||
tx_config,
|
||||
fee=fee,
|
||||
coins=chia_coins,
|
||||
coin_announcements_to_consume={announcement_to_assert} if announcement_to_assert is not None else None,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
assert chia_tx.spend_bundle is not None
|
||||
return chia_tx
|
||||
|
@ -606,15 +580,14 @@ class Wallet:
|
|||
self,
|
||||
asset_id: Optional[bytes32],
|
||||
amount: uint64,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
coin_selection_config: CoinSelectionConfig,
|
||||
) -> Set[Coin]:
|
||||
if asset_id is not None:
|
||||
raise ValueError(f"The standard wallet cannot offer coins with asset id {asset_id}")
|
||||
balance = await self.get_spendable_balance()
|
||||
if balance < amount:
|
||||
raise Exception(f"insufficient funds in wallet {self.id()}")
|
||||
return await self.select_coins(amount, min_coin_amount=min_coin_amount, max_coin_amount=max_coin_amount)
|
||||
return await self.select_coins(amount, coin_selection_config)
|
||||
|
||||
# WSChiaConnection is only imported for type checking
|
||||
async def coin_added(
|
||||
|
|
|
@ -12,6 +12,7 @@ from chia.types.blockchain_format.sized_bytes import bytes32
|
|||
from chia.types.spend_bundle import SpendBundle
|
||||
from chia.util.ints import uint32, uint64, uint128
|
||||
from chia.wallet.nft_wallet.nft_info import NFTCoinInfo
|
||||
from chia.wallet.util.tx_config import CoinSelectionConfig
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet_coin_record import WalletCoinRecord
|
||||
from chia.wallet.wallet_info import WalletInfo
|
||||
|
@ -34,10 +35,7 @@ class WalletProtocol(Protocol):
|
|||
async def select_coins(
|
||||
self,
|
||||
amount: uint64,
|
||||
exclude: Optional[List[Coin]] = None,
|
||||
min_coin_amount: Optional[uint64] = None,
|
||||
max_coin_amount: Optional[uint64] = None,
|
||||
excluded_coin_amounts: Optional[List[uint64]] = None,
|
||||
coin_selection_config: CoinSelectionConfig,
|
||||
) -> Set[Coin]:
|
||||
...
|
||||
|
||||
|
@ -81,7 +79,6 @@ class GSTOptionalArgs(TypedDict):
|
|||
add_pending_singleton: NotRequired[bool]
|
||||
announce_new_state: NotRequired[bool]
|
||||
# CATWallet
|
||||
excluded_cat_coins: NotRequired[Optional[Set[Coin]]]
|
||||
cat_discrepancy: NotRequired[Optional[Tuple[int, Program, Program]]]
|
||||
# NFTWallet
|
||||
nft_coin: NotRequired[Optional[NFTCoinInfo]]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import dataclasses
|
||||
import logging
|
||||
import multiprocessing.context
|
||||
import time
|
||||
|
@ -82,6 +83,7 @@ from chia.wallet.util.compute_memos import compute_memos
|
|||
from chia.wallet.util.puzzle_decorator import PuzzleDecoratorManager
|
||||
from chia.wallet.util.query_filter import HashFilter
|
||||
from chia.wallet.util.transaction_type import CLAWBACK_TRANSACTION_TYPES, TransactionType
|
||||
from chia.wallet.util.tx_config import TXConfig, TXConfigLoader
|
||||
from chia.wallet.util.wallet_sync_utils import (
|
||||
PeerRequestException,
|
||||
fetch_coin_spend_for_coin_state,
|
||||
|
@ -709,12 +711,26 @@ class WalletStateManager:
|
|||
current_timestamp = self.blockchain.get_latest_timestamp()
|
||||
clawback_coins: Dict[Coin, ClawbackMetadata] = {}
|
||||
tx_fee = uint64(self.config.get("auto_claim", {}).get("tx_fee", 0))
|
||||
min_amount = uint64(self.config.get("auto_claim", {}).get("min_amount", 0))
|
||||
assert self.wallet_node.logged_in_fingerprint is not None
|
||||
tx_config_loader: TXConfigLoader = TXConfigLoader.from_json_dict(self.config.get("auto_claim", {}))
|
||||
tx_config: TXConfig = tx_config_loader.autofill(
|
||||
self.config,
|
||||
self.wallet_node.logged_in_fingerprint,
|
||||
self.constants,
|
||||
)
|
||||
if tx_config_loader.min_coin_amount is None:
|
||||
tx_config_loader = dataclasses.replace(
|
||||
tx_config_loader,
|
||||
min_coin_amount=self.config.get("auto_claim", {}).get("min_amount"),
|
||||
)
|
||||
unspent_coins = await self.coin_store.get_coin_records(
|
||||
coin_type=CoinType.CLAWBACK,
|
||||
wallet_type=WalletType.STANDARD_WALLET,
|
||||
spent_range=UInt32Range(stop=uint32(0)),
|
||||
amount_range=UInt64Range(start=uint64(min_amount)),
|
||||
amount_range=UInt64Range(
|
||||
start=tx_config.coin_selection_config.min_coin_amount,
|
||||
stop=tx_config.coin_selection_config.max_coin_amount,
|
||||
),
|
||||
)
|
||||
for coin in unspent_coins.records:
|
||||
try:
|
||||
|
@ -724,14 +740,16 @@ class WalletStateManager:
|
|||
if current_timestamp - coin_timestamp >= metadata.time_lock:
|
||||
clawback_coins[coin.coin] = metadata
|
||||
if len(clawback_coins) >= self.config.get("auto_claim", {}).get("batch_size", 50):
|
||||
await self.spend_clawback_coins(clawback_coins, tx_fee)
|
||||
await self.spend_clawback_coins(clawback_coins, tx_fee, tx_config)
|
||||
clawback_coins = {}
|
||||
except Exception as e:
|
||||
self.log.error(f"Failed to claim clawback coin {coin.coin.name().hex()}: %s", e)
|
||||
if len(clawback_coins) > 0:
|
||||
await self.spend_clawback_coins(clawback_coins, tx_fee)
|
||||
await self.spend_clawback_coins(clawback_coins, tx_fee, tx_config)
|
||||
|
||||
async def spend_clawback_coins(self, clawback_coins: Dict[Coin, ClawbackMetadata], fee: uint64) -> List[bytes32]:
|
||||
async def spend_clawback_coins(
|
||||
self, clawback_coins: Dict[Coin, ClawbackMetadata], fee: uint64, tx_config: TXConfig
|
||||
) -> List[bytes32]:
|
||||
assert len(clawback_coins) > 0
|
||||
coin_spends: List[CoinSpend] = []
|
||||
message: bytes32 = std_hash(b"".join([c.name() for c in clawback_coins.keys()]))
|
||||
|
@ -783,7 +801,7 @@ class WalletStateManager:
|
|||
spend_bundle: SpendBundle = await self.main_wallet.sign_transaction(coin_spends)
|
||||
if fee > 0:
|
||||
chia_tx = await self.main_wallet.create_tandem_xch_tx(
|
||||
fee, Announcement(coin_spends[0].coin.name(), message)
|
||||
fee, tx_config, Announcement(coin_spends[0].coin.name(), message)
|
||||
)
|
||||
assert chia_tx.spend_bundle is not None
|
||||
spend_bundle = SpendBundle.aggregate([spend_bundle, chia_tx.spend_bundle])
|
||||
|
|
|
@ -53,6 +53,7 @@ from chia.util.limited_semaphore import LimitedSemaphore
|
|||
from chia.util.recursive_replace import recursive_replace
|
||||
from chia.util.vdf_prover import get_vdf_info_and_proof
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from tests.blockchain.blockchain_test_utils import _validate_and_add_block, _validate_and_add_block_no_error
|
||||
from tests.connection_utils import add_dummy_connection, connect_and_get_peer
|
||||
from tests.core.full_node.stores.test_coin_store import get_future_reward_coins
|
||||
|
@ -138,6 +139,7 @@ class TestFullNodeBlockCompression:
|
|||
tr: TransactionRecord = await wallet.generate_signed_transaction(
|
||||
tx_size,
|
||||
ph,
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
await wallet.push_transaction(tx=tr)
|
||||
await time_out_assert(
|
||||
|
@ -170,6 +172,7 @@ class TestFullNodeBlockCompression:
|
|||
tr: TransactionRecord = await wallet.generate_signed_transaction(
|
||||
20000,
|
||||
ph,
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
await wallet.push_transaction(tx=tr)
|
||||
await time_out_assert(
|
||||
|
@ -206,6 +209,7 @@ class TestFullNodeBlockCompression:
|
|||
tr: TransactionRecord = await wallet.generate_signed_transaction(
|
||||
30000,
|
||||
ph,
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
await wallet.push_transaction(tx=tr)
|
||||
await time_out_assert(
|
||||
|
@ -217,6 +221,7 @@ class TestFullNodeBlockCompression:
|
|||
tr: TransactionRecord = await wallet.generate_signed_transaction(
|
||||
40000,
|
||||
ph,
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
await wallet.push_transaction(tx=tr)
|
||||
await time_out_assert(
|
||||
|
@ -229,6 +234,7 @@ class TestFullNodeBlockCompression:
|
|||
tr: TransactionRecord = await wallet.generate_signed_transaction(
|
||||
50000,
|
||||
ph,
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
await wallet.push_transaction(tx=tr)
|
||||
await time_out_assert(
|
||||
|
@ -241,6 +247,7 @@ class TestFullNodeBlockCompression:
|
|||
tr: TransactionRecord = await wallet.generate_signed_transaction(
|
||||
3000000000000,
|
||||
ph,
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
await wallet.push_transaction(tx=tr)
|
||||
await time_out_assert(
|
||||
|
@ -269,6 +276,7 @@ class TestFullNodeBlockCompression:
|
|||
tr: TransactionRecord = await wallet.generate_signed_transaction(
|
||||
30000,
|
||||
Program.to(1).get_tree_hash(),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
extra_spend = SpendBundle(
|
||||
[
|
||||
|
@ -314,6 +322,7 @@ class TestFullNodeBlockCompression:
|
|||
tr: TransactionRecord = await wallet.generate_signed_transaction(
|
||||
30000,
|
||||
Program.to(1).get_tree_hash(),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
extra_spend = SpendBundle(
|
||||
[
|
||||
|
|
|
@ -13,6 +13,7 @@ from chia.simulator.simulator_protocol import FarmNewBlockProtocol
|
|||
from chia.simulator.time_out_assert import time_out_assert
|
||||
from chia.types.peer_info import PeerInfo
|
||||
from chia.util.ints import uint16, uint32
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
|
||||
|
||||
class TestTransactions:
|
||||
|
@ -81,7 +82,7 @@ class TestTransactions:
|
|||
await time_out_assert(20, peak_height, num_blocks, full_node_api_1)
|
||||
await time_out_assert(20, peak_height, num_blocks, full_node_api_2)
|
||||
|
||||
tx = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction(10, ph1, 0)
|
||||
tx = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction(10, ph1, DEFAULT_TX_CONFIG, 0)
|
||||
await wallet_0.wallet_state_manager.main_wallet.push_transaction(tx)
|
||||
|
||||
await time_out_assert(
|
||||
|
@ -153,7 +154,9 @@ class TestTransactions:
|
|||
)
|
||||
await time_out_assert(20, wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance, funds)
|
||||
|
||||
tx = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction(10, token_bytes(), 0)
|
||||
tx = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction(
|
||||
10, token_bytes(), DEFAULT_TX_CONFIG, 0
|
||||
)
|
||||
await wallet_0.wallet_state_manager.main_wallet.push_transaction(tx)
|
||||
|
||||
await time_out_assert(
|
||||
|
|
|
@ -44,6 +44,7 @@ from chia.types.spend_bundle_conditions import Spend, SpendBundleConditions
|
|||
from chia.util.errors import Err, ValidationError
|
||||
from chia.util.ints import uint16, uint32, uint64
|
||||
from chia.wallet.payment import Payment
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from chia.wallet.wallet import Wallet
|
||||
from chia.wallet.wallet_coin_record import WalletCoinRecord
|
||||
from chia.wallet.wallet_node import WalletNode
|
||||
|
@ -1443,7 +1444,9 @@ async def test_identical_spend_aggregation_e2e(simulator_and_wallet: SimulatorsA
|
|||
for _ in range(2):
|
||||
await farm_a_block(full_node_api, wallet_node, ph)
|
||||
other_recipients = [Payment(puzzle_hash=p, amount=uint64(200), memos=[]) for p in phs[1:]]
|
||||
tx = await wallet.generate_signed_transaction(uint64(200), phs[0], primaries=other_recipients)
|
||||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(200), phs[0], DEFAULT_TX_CONFIG, primaries=other_recipients
|
||||
)
|
||||
assert tx.spend_bundle is not None
|
||||
await send_to_mempool(full_node_api, tx.spend_bundle)
|
||||
await farm_a_block(full_node_api, wallet_node, ph)
|
||||
|
@ -1458,10 +1461,9 @@ async def test_identical_spend_aggregation_e2e(simulator_and_wallet: SimulatorsA
|
|||
wallet, coins, ph = await make_setup_and_coins(full_node_api, wallet_node)
|
||||
|
||||
# Make sure spending AB then BC would generate a conflict for the latter
|
||||
|
||||
tx_a = await wallet.generate_signed_transaction(uint64(30), ph, coins={coins[0].coin})
|
||||
tx_b = await wallet.generate_signed_transaction(uint64(30), ph, coins={coins[1].coin})
|
||||
tx_c = await wallet.generate_signed_transaction(uint64(30), ph, coins={coins[2].coin})
|
||||
tx_a = await wallet.generate_signed_transaction(uint64(30), ph, DEFAULT_TX_CONFIG, coins={coins[0].coin})
|
||||
tx_b = await wallet.generate_signed_transaction(uint64(30), ph, DEFAULT_TX_CONFIG, coins={coins[1].coin})
|
||||
tx_c = await wallet.generate_signed_transaction(uint64(30), ph, DEFAULT_TX_CONFIG, coins={coins[2].coin})
|
||||
assert tx_a.spend_bundle is not None
|
||||
assert tx_b.spend_bundle is not None
|
||||
assert tx_c.spend_bundle is not None
|
||||
|
@ -1475,7 +1477,9 @@ async def test_identical_spend_aggregation_e2e(simulator_and_wallet: SimulatorsA
|
|||
# Make sure DE and EF would aggregate on E when E is eligible for deduplication
|
||||
|
||||
# Create a coin with the identity puzzle hash
|
||||
tx = await wallet.generate_signed_transaction(uint64(200), IDENTITY_PUZZLE_HASH, coins={coins[3].coin})
|
||||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(200), IDENTITY_PUZZLE_HASH, DEFAULT_TX_CONFIG, coins={coins[3].coin}
|
||||
)
|
||||
assert tx.spend_bundle is not None
|
||||
await send_to_mempool(full_node_api, tx.spend_bundle)
|
||||
await farm_a_block(full_node_api, wallet_node, ph)
|
||||
|
@ -1498,10 +1502,20 @@ async def test_identical_spend_aggregation_e2e(simulator_and_wallet: SimulatorsA
|
|||
e_announcement = Announcement(e_coin_id, message)
|
||||
# Create transactions D and F that consume an announcement created by E
|
||||
tx_d = await wallet.generate_signed_transaction(
|
||||
uint64(100), ph, fee=uint64(0), coins={coins[4].coin}, coin_announcements_to_consume={e_announcement}
|
||||
uint64(100),
|
||||
ph,
|
||||
DEFAULT_TX_CONFIG,
|
||||
fee=uint64(0),
|
||||
coins={coins[4].coin},
|
||||
coin_announcements_to_consume={e_announcement},
|
||||
)
|
||||
tx_f = await wallet.generate_signed_transaction(
|
||||
uint64(150), ph, fee=uint64(0), coins={coins[5].coin}, coin_announcements_to_consume={e_announcement}
|
||||
uint64(150),
|
||||
ph,
|
||||
DEFAULT_TX_CONFIG,
|
||||
fee=uint64(0),
|
||||
coins={coins[5].coin},
|
||||
coin_announcements_to_consume={e_announcement},
|
||||
)
|
||||
assert tx_d.spend_bundle is not None
|
||||
assert tx_f.spend_bundle is not None
|
||||
|
@ -1529,7 +1543,7 @@ async def test_identical_spend_aggregation_e2e(simulator_and_wallet: SimulatorsA
|
|||
g_coin = coins[6].coin
|
||||
g_coin_id = g_coin.name()
|
||||
tx_g = await wallet.generate_signed_transaction(
|
||||
uint64(13), ph, coins={g_coin}, coin_announcements_to_consume={e_announcement}
|
||||
uint64(13), ph, DEFAULT_TX_CONFIG, coins={g_coin}, coin_announcements_to_consume={e_announcement}
|
||||
)
|
||||
assert tx_g.spend_bundle is not None
|
||||
sb_e2g = SpendBundle.aggregate([sb_e2, tx_g.spend_bundle])
|
||||
|
|
|
@ -34,6 +34,7 @@ from chia.util.config import load_config
|
|||
from chia.util.ints import uint16, uint32, uint64
|
||||
from chia.wallet.derive_keys import find_authentication_sk, find_owner_sk
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet_node import WalletNode
|
||||
from chia.wallet.wallet_node_api import WalletNodeAPI
|
||||
|
@ -469,7 +470,7 @@ class TestPoolWalletRpc:
|
|||
assert len(await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(2)) == 0
|
||||
|
||||
tr: TransactionRecord = await client.send_transaction(
|
||||
1, uint64(100), encode_puzzle_hash(status.p2_singleton_puzzle_hash, "txch")
|
||||
1, uint64(100), encode_puzzle_hash(status.p2_singleton_puzzle_hash, "txch"), DEFAULT_TX_CONFIG
|
||||
)
|
||||
|
||||
await full_node_api.wait_transaction_records_entered_mempool(records=[tr])
|
||||
|
|
|
@ -22,6 +22,7 @@ from chia.simulator.time_out_assert import time_out_assert
|
|||
from chia.types.blockchain_format.sized_bytes import bytes32
|
||||
from chia.types.peer_info import PeerInfo
|
||||
from chia.util.ints import uint16, uint32, uint64
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from chia.wallet.wallet_node import WalletNode
|
||||
|
||||
test_constants_modified = test_constants.replace(
|
||||
|
@ -166,6 +167,7 @@ class TestSimulation:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(10),
|
||||
await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash(),
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
)
|
||||
await wallet.push_transaction(tx)
|
||||
|
@ -339,6 +341,7 @@ class TestSimulation:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
amount=uint64(tx_amount),
|
||||
puzzle_hash=await wallet_node.wallet_state_manager.main_wallet.get_new_puzzlehash(),
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
coins={coin},
|
||||
)
|
||||
await wallet.push_transaction(tx)
|
||||
|
@ -384,6 +387,7 @@ class TestSimulation:
|
|||
await wallet.generate_signed_transaction(
|
||||
amount=uint64(tx_amount),
|
||||
puzzle_hash=await wallet_node.wallet_state_manager.main_wallet.get_new_puzzlehash(),
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
coins={coin},
|
||||
)
|
||||
for coin in coins
|
||||
|
|
|
@ -10,6 +10,7 @@ from chia.simulator.block_tools import BlockTools
|
|||
from chia.simulator.full_node_simulator import FullNodeSimulator, backoff_times
|
||||
from chia.types.peer_info import PeerInfo
|
||||
from chia.util.ints import uint16, uint64
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from chia.wallet.wallet_node import WalletNode
|
||||
|
||||
|
||||
|
@ -160,6 +161,7 @@ async def test_wait_transaction_records_entered_mempool(
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
amount=uint64(tx_amount),
|
||||
puzzle_hash=await wallet_node.wallet_state_manager.main_wallet.get_new_puzzlehash(),
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
coins={coin},
|
||||
)
|
||||
await wallet.push_transaction(tx)
|
||||
|
@ -194,6 +196,7 @@ async def test_process_transaction_records(
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
amount=uint64(tx_amount),
|
||||
puzzle_hash=await wallet_node.wallet_state_manager.main_wallet.get_new_puzzlehash(),
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
coins={coin},
|
||||
)
|
||||
await wallet.push_transaction(tx)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import dataclasses
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
@ -32,6 +33,7 @@ from chia.wallet.derive_keys import _derive_path_unhardened, master_sk_to_wallet
|
|||
from chia.wallet.lineage_proof import LineageProof
|
||||
from chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle import puzzle_hash_for_pk
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.tx_config import DEFAULT_COIN_SELECTION_CONFIG, DEFAULT_TX_CONFIG
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet_info import WalletInfo
|
||||
from chia.wallet.wallet_interested_store import WalletInterestedStore
|
||||
|
@ -74,7 +76,11 @@ class TestCATWallet:
|
|||
|
||||
async with wallet_node.wallet_state_manager.lock:
|
||||
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
||||
wallet_node.wallet_state_manager,
|
||||
wallet,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(100),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
# The next 2 lines are basically a noop, it just adds test coverage
|
||||
cat_wallet = await CATWallet.create(wallet_node.wallet_state_manager, wallet, cat_wallet.wallet_info)
|
||||
|
@ -136,10 +142,18 @@ class TestCATWallet:
|
|||
|
||||
async with wallet_node.wallet_state_manager.lock:
|
||||
cat_wallet_1: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
||||
wallet_node.wallet_state_manager,
|
||||
wallet,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(100),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
cat_wallet_2: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(200)
|
||||
wallet_node.wallet_state_manager,
|
||||
wallet,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(200),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
|
||||
proofs_1 = await cat_wallet_1.lineage_store.get_all_lineage_proofs()
|
||||
|
@ -189,7 +203,11 @@ class TestCATWallet:
|
|||
|
||||
async with wallet_node.wallet_state_manager.lock:
|
||||
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
||||
wallet_node.wallet_state_manager,
|
||||
wallet,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(100),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
tx_queue: List[TransactionRecord] = await wallet_node.wallet_state_manager.tx_store.get_not_sent()
|
||||
tx_record = tx_queue[0]
|
||||
|
@ -208,7 +226,9 @@ class TestCATWallet:
|
|||
assert cat_wallet.cat_info.limitations_program_hash == cat_wallet_2.cat_info.limitations_program_hash
|
||||
|
||||
cat_2_hash = await cat_wallet_2.get_new_inner_hash()
|
||||
tx_records = await cat_wallet.generate_signed_transaction([uint64(60)], [cat_2_hash], fee=uint64(1))
|
||||
tx_records = await cat_wallet.generate_signed_transaction(
|
||||
[uint64(60)], [cat_2_hash], DEFAULT_TX_CONFIG, fee=uint64(1)
|
||||
)
|
||||
tx_id = None
|
||||
for tx_record in tx_records:
|
||||
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
|
@ -233,7 +253,7 @@ class TestCATWallet:
|
|||
|
||||
await time_out_assert(30, cat_wallet_2.get_confirmed_balance, 60)
|
||||
await time_out_assert(30, cat_wallet_2.get_unconfirmed_balance, 60)
|
||||
coins = await cat_wallet_2.select_coins(uint64(60))
|
||||
coins = await cat_wallet_2.select_coins(uint64(60), DEFAULT_COIN_SELECTION_CONFIG)
|
||||
assert len(coins) == 1
|
||||
coin = coins.pop()
|
||||
tx_id = coin.name().hex()
|
||||
|
@ -241,7 +261,7 @@ class TestCATWallet:
|
|||
assert len(memos[tx_id]) == 2
|
||||
assert list(memos[tx_id].values())[0][0] == cat_2_hash.hex()
|
||||
cat_hash = await cat_wallet.get_new_inner_hash()
|
||||
tx_records = await cat_wallet_2.generate_signed_transaction([uint64(15)], [cat_hash])
|
||||
tx_records = await cat_wallet_2.generate_signed_transaction([uint64(15)], [cat_hash], DEFAULT_TX_CONFIG)
|
||||
for tx_record in tx_records:
|
||||
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
|
||||
|
@ -296,7 +316,11 @@ class TestCATWallet:
|
|||
|
||||
async with wallet_node.wallet_state_manager.lock:
|
||||
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
||||
wallet_node.wallet_state_manager,
|
||||
wallet,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(100),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
tx_queue: List[TransactionRecord] = await wallet_node.wallet_state_manager.tx_store.get_not_sent()
|
||||
tx_record = tx_queue[0]
|
||||
|
@ -316,7 +340,7 @@ class TestCATWallet:
|
|||
|
||||
cat_2_hash = await cat_wallet_2.get_new_inner_hash()
|
||||
tx_records = await cat_wallet.generate_signed_transaction(
|
||||
[uint64(60)], [cat_2_hash], fee=uint64(1), reuse_puzhash=True
|
||||
[uint64(60)], [cat_2_hash], dataclasses.replace(DEFAULT_TX_CONFIG, reuse_puzhash=True), fee=uint64(1)
|
||||
)
|
||||
for tx_record in tx_records:
|
||||
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
|
@ -345,7 +369,7 @@ class TestCATWallet:
|
|||
await time_out_assert(30, cat_wallet_2.get_unconfirmed_balance, 60)
|
||||
|
||||
cat_hash = await cat_wallet.get_new_inner_hash()
|
||||
tx_records = await cat_wallet_2.generate_signed_transaction([uint64(15)], [cat_hash])
|
||||
tx_records = await cat_wallet_2.generate_signed_transaction([uint64(15)], [cat_hash], DEFAULT_TX_CONFIG)
|
||||
for tx_record in tx_records:
|
||||
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
|
||||
|
@ -395,7 +419,11 @@ class TestCATWallet:
|
|||
|
||||
async with wallet_node.wallet_state_manager.lock:
|
||||
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
||||
wallet_node.wallet_state_manager,
|
||||
wallet,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(100),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
|
||||
for i in range(1, num_blocks):
|
||||
|
@ -453,7 +481,11 @@ class TestCATWallet:
|
|||
|
||||
async with wallet_node.wallet_state_manager.lock:
|
||||
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
||||
wallet_node.wallet_state_manager,
|
||||
wallet,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(100),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
tx_records: List[TransactionRecord] = await wallet_node.wallet_state_manager.tx_store.get_not_sent()
|
||||
await full_node_api.process_transaction_records(records=tx_records)
|
||||
|
@ -471,7 +503,9 @@ class TestCATWallet:
|
|||
assert cat_wallet.cat_info.limitations_program_hash == cat_wallet_2.cat_info.limitations_program_hash
|
||||
|
||||
cat_2_hash = await cat_wallet_2.get_new_inner_hash()
|
||||
tx_records = await cat_wallet.generate_signed_transaction([uint64(60)], [cat_2_hash], fee=uint64(1))
|
||||
tx_records = await cat_wallet.generate_signed_transaction(
|
||||
[uint64(60)], [cat_2_hash], DEFAULT_TX_CONFIG, fee=uint64(1)
|
||||
)
|
||||
for tx_record in tx_records:
|
||||
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
await full_node_api.process_transaction_records(records=tx_records)
|
||||
|
@ -486,7 +520,9 @@ class TestCATWallet:
|
|||
await time_out_assert(20, cat_wallet_2.get_unconfirmed_balance, 60)
|
||||
|
||||
cc2_ph = await cat_wallet_2.get_new_cat_puzzle_hash()
|
||||
tx_record = await wallet.wallet_state_manager.main_wallet.generate_signed_transaction(10, cc2_ph, 0)
|
||||
tx_record = await wallet.wallet_state_manager.main_wallet.generate_signed_transaction(
|
||||
10, cc2_ph, DEFAULT_TX_CONFIG, 0
|
||||
)
|
||||
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
await full_node_api.process_transaction_records(records=[tx_record])
|
||||
|
||||
|
@ -543,7 +579,11 @@ class TestCATWallet:
|
|||
|
||||
async with wallet_node_0.wallet_state_manager.lock:
|
||||
cat_wallet_0: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node_0.wallet_state_manager, wallet_0, {"identifier": "genesis_by_id"}, uint64(100)
|
||||
wallet_node_0.wallet_state_manager,
|
||||
wallet_0,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(100),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
tx_records: List[TransactionRecord] = await wallet_node_0.wallet_state_manager.tx_store.get_not_sent()
|
||||
await full_node_api.process_transaction_records(records=tx_records)
|
||||
|
@ -568,7 +608,9 @@ class TestCATWallet:
|
|||
cat_1_hash = await cat_wallet_1.get_new_inner_hash()
|
||||
cat_2_hash = await cat_wallet_2.get_new_inner_hash()
|
||||
|
||||
tx_records = await cat_wallet_0.generate_signed_transaction([uint64(60), uint64(20)], [cat_1_hash, cat_2_hash])
|
||||
tx_records = await cat_wallet_0.generate_signed_transaction(
|
||||
[uint64(60), uint64(20)], [cat_1_hash, cat_2_hash], DEFAULT_TX_CONFIG
|
||||
)
|
||||
for tx_record in tx_records:
|
||||
await wallet_0.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
await full_node_api.process_transaction_records(records=tx_records)
|
||||
|
@ -584,11 +626,11 @@ class TestCATWallet:
|
|||
|
||||
cat_hash = await cat_wallet_0.get_new_inner_hash()
|
||||
|
||||
tx_records = await cat_wallet_1.generate_signed_transaction([uint64(15)], [cat_hash])
|
||||
tx_records = await cat_wallet_1.generate_signed_transaction([uint64(15)], [cat_hash], DEFAULT_TX_CONFIG)
|
||||
for tx_record in tx_records:
|
||||
await wallet_1.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
|
||||
tx_records_2 = await cat_wallet_2.generate_signed_transaction([uint64(20)], [cat_hash])
|
||||
tx_records_2 = await cat_wallet_2.generate_signed_transaction([uint64(20)], [cat_hash], DEFAULT_TX_CONFIG)
|
||||
for tx_record in tx_records_2:
|
||||
await wallet_2.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
|
||||
|
@ -607,11 +649,11 @@ class TestCATWallet:
|
|||
print(len(txs))
|
||||
# Test with Memo
|
||||
tx_records_3: TransactionRecord = await cat_wallet_1.generate_signed_transaction(
|
||||
[uint64(30)], [cat_hash], memos=[[b"Markus Walburg"]]
|
||||
[uint64(30)], [cat_hash], DEFAULT_TX_CONFIG, memos=[[b"Markus Walburg"]]
|
||||
)
|
||||
with pytest.raises(ValueError):
|
||||
await cat_wallet_1.generate_signed_transaction(
|
||||
[uint64(30)], [cat_hash], memos=[[b"too"], [b"many"], [b"memos"]]
|
||||
[uint64(30)], [cat_hash], DEFAULT_TX_CONFIG, memos=[[b"too"], [b"many"], [b"memos"]]
|
||||
)
|
||||
|
||||
for tx_record in tx_records_3:
|
||||
|
@ -664,7 +706,11 @@ class TestCATWallet:
|
|||
|
||||
async with wallet_node.wallet_state_manager.lock:
|
||||
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100000)
|
||||
wallet_node.wallet_state_manager,
|
||||
wallet,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(100000),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
tx_records: List[TransactionRecord] = await wallet_node.wallet_state_manager.tx_store.get_not_sent()
|
||||
await full_node_api.process_transaction_records(records=tx_records)
|
||||
|
@ -682,7 +728,9 @@ class TestCATWallet:
|
|||
amounts.append(uint64(i))
|
||||
puzzle_hashes.append(cat_2_hash)
|
||||
spent_coint = (await cat_wallet.get_cat_spendable_coins())[0].coin
|
||||
tx_records = await cat_wallet.generate_signed_transaction(amounts, puzzle_hashes, coins={spent_coint})
|
||||
tx_records = await cat_wallet.generate_signed_transaction(
|
||||
amounts, puzzle_hashes, DEFAULT_TX_CONFIG, coins={spent_coint}
|
||||
)
|
||||
for tx_record in tx_records:
|
||||
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
await full_node_api.process_transaction_records(records=tx_records)
|
||||
|
@ -711,6 +759,7 @@ class TestCATWallet:
|
|||
[transaction_record] = await cat_wallet.generate_signed_transaction(
|
||||
[max_sent_amount - 1],
|
||||
[ph],
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
|
||||
assert transaction_record.amount == uint64(max_sent_amount - 1)
|
||||
|
@ -719,6 +768,7 @@ class TestCATWallet:
|
|||
[transaction_record] = await cat_wallet.generate_signed_transaction(
|
||||
[max_sent_amount],
|
||||
[ph],
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
|
||||
assert transaction_record.amount == uint64(max_sent_amount)
|
||||
|
@ -728,6 +778,7 @@ class TestCATWallet:
|
|||
await cat_wallet.generate_signed_transaction(
|
||||
[max_sent_amount + 1],
|
||||
[ph],
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -776,7 +827,11 @@ class TestCATWallet:
|
|||
|
||||
async with wallet_node.wallet_state_manager.lock:
|
||||
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
||||
wallet_node.wallet_state_manager,
|
||||
wallet,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(100),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
tx_records: List[TransactionRecord] = await wallet_node.wallet_state_manager.tx_store.get_not_sent()
|
||||
await full_node_api.process_transaction_records(records=tx_records)
|
||||
|
@ -786,7 +841,9 @@ class TestCATWallet:
|
|||
assert cat_wallet.cat_info.limitations_program_hash is not None
|
||||
|
||||
cat_2_hash = await wallet2.get_new_puzzlehash()
|
||||
tx_records = await cat_wallet.generate_signed_transaction([uint64(60)], [cat_2_hash], memos=[[cat_2_hash]])
|
||||
tx_records = await cat_wallet.generate_signed_transaction(
|
||||
[uint64(60)], [cat_2_hash], DEFAULT_TX_CONFIG, memos=[[cat_2_hash]]
|
||||
)
|
||||
|
||||
for tx_record in tx_records:
|
||||
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
|
@ -816,7 +873,9 @@ class TestCATWallet:
|
|||
}
|
||||
|
||||
# Then we send another transaction
|
||||
tx_records = await cat_wallet.generate_signed_transaction([uint64(10)], [cat_2_hash], memos=[[cat_2_hash]])
|
||||
tx_records = await cat_wallet.generate_signed_transaction(
|
||||
[uint64(10)], [cat_2_hash], DEFAULT_TX_CONFIG, memos=[[cat_2_hash]]
|
||||
)
|
||||
|
||||
for tx_record in tx_records:
|
||||
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
|
@ -835,7 +894,7 @@ class TestCATWallet:
|
|||
await time_out_assert(30, cat_wallet_2.get_unconfirmed_balance, 70)
|
||||
|
||||
cat_hash = await cat_wallet.get_new_inner_hash()
|
||||
tx_records = await cat_wallet_2.generate_signed_transaction([uint64(5)], [cat_hash])
|
||||
tx_records = await cat_wallet_2.generate_signed_transaction([uint64(5)], [cat_hash], DEFAULT_TX_CONFIG)
|
||||
for tx_record in tx_records:
|
||||
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
|
||||
|
@ -913,7 +972,7 @@ class TestCATWallet:
|
|||
cat_amount_0 = uint64(100)
|
||||
cat_amount_1 = uint64(5)
|
||||
|
||||
tx = await client_0.send_transaction(1, cat_amount_0, addr)
|
||||
tx = await client_0.send_transaction(1, cat_amount_0, addr, DEFAULT_TX_CONFIG)
|
||||
spend_bundle = tx.spend_bundle
|
||||
assert spend_bundle is not None
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ from chia.wallet.trading.offer import Offer
|
|||
from chia.wallet.trading.trade_status import TradeStatus
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.transaction_type import TransactionType
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG, TXConfig
|
||||
|
||||
buffer_blocks = 4
|
||||
|
||||
|
@ -75,16 +76,26 @@ class TestCATTrades:
|
|||
wallet_maker = wallet_node_maker.wallet_state_manager.main_wallet
|
||||
wallet_taker = wallet_node_taker.wallet_state_manager.main_wallet
|
||||
|
||||
tx_config: TXConfig = dataclasses.replace(DEFAULT_TX_CONFIG, reuse_puzhash=reuse_puzhash)
|
||||
|
||||
# Create two new CATs, one in each wallet
|
||||
async with wallet_node_maker.wallet_state_manager.lock:
|
||||
cat_wallet_maker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, uint64(100)
|
||||
wallet_node_maker.wallet_state_manager,
|
||||
wallet_maker,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(100),
|
||||
tx_config,
|
||||
)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
async with wallet_node_taker.wallet_state_manager.lock:
|
||||
new_cat_wallet_taker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node_taker.wallet_state_manager, wallet_taker, {"identifier": "genesis_by_id"}, uint64(100)
|
||||
wallet_node_taker.wallet_state_manager,
|
||||
wallet_taker,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(100),
|
||||
tx_config,
|
||||
)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
@ -176,7 +187,7 @@ class TestCATTrades:
|
|||
else:
|
||||
# chia_for_cat
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
chia_for_cat, fee=uint64(1), reuse_puzhash=reuse_puzhash
|
||||
chia_for_cat, tx_config, fee=uint64(1)
|
||||
)
|
||||
await asyncio.sleep(1)
|
||||
assert error is None
|
||||
|
@ -187,8 +198,8 @@ class TestCATTrades:
|
|||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
tx_config,
|
||||
fee=uint64(1),
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
assert trade_take is not None
|
||||
assert tx_records is not None
|
||||
|
@ -284,7 +295,7 @@ class TestCATTrades:
|
|||
)
|
||||
await trade_manager_maker.save_trade(*create_tr_for_offer(old_maker_offer))
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(cat_for_chia)
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(cat_for_chia, tx_config)
|
||||
assert error is None
|
||||
assert success is True
|
||||
assert trade_make is not None
|
||||
|
@ -292,6 +303,7 @@ class TestCATTrades:
|
|||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
tx_config,
|
||||
)
|
||||
assert trade_take is not None
|
||||
assert tx_records is not None
|
||||
|
@ -348,9 +360,7 @@ class TestCATTrades:
|
|||
)
|
||||
await trade_manager_maker.save_trade(*create_tr_for_offer(old_maker_offer))
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
cat_for_cat, reuse_puzhash=reuse_puzhash
|
||||
)
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(cat_for_cat, tx_config)
|
||||
await asyncio.sleep(1)
|
||||
assert error is None
|
||||
assert success is True
|
||||
|
@ -358,7 +368,7 @@ class TestCATTrades:
|
|||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
tx_config,
|
||||
)
|
||||
await time_out_assert(15, full_node.txs_in_mempool, True, tx_records)
|
||||
assert trade_take is not None
|
||||
|
@ -442,6 +452,7 @@ class TestCATTrades:
|
|||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
chia_for_multiple_cat,
|
||||
tx_config,
|
||||
driver_dict=driver_dict,
|
||||
)
|
||||
await asyncio.sleep(1)
|
||||
|
@ -452,6 +463,7 @@ class TestCATTrades:
|
|||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
tx_config,
|
||||
)
|
||||
await time_out_assert(15, full_node.txs_in_mempool, True, tx_records)
|
||||
assert trade_take is not None
|
||||
|
@ -501,7 +513,7 @@ class TestCATTrades:
|
|||
await trade_manager_maker.save_trade(*create_tr_for_offer(old_maker_offer))
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
multiple_cat_for_chia,
|
||||
multiple_cat_for_chia, tx_config
|
||||
)
|
||||
await asyncio.sleep(1)
|
||||
assert error is None
|
||||
|
@ -510,6 +522,7 @@ class TestCATTrades:
|
|||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
tx_config,
|
||||
)
|
||||
await time_out_assert(15, full_node.txs_in_mempool, True, tx_records)
|
||||
assert trade_take is not None
|
||||
|
@ -558,9 +571,7 @@ class TestCATTrades:
|
|||
)
|
||||
await trade_manager_maker.save_trade(*create_tr_for_offer(old_maker_offer))
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
chia_and_cat_for_cat,
|
||||
)
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(chia_and_cat_for_cat, tx_config)
|
||||
await asyncio.sleep(1)
|
||||
assert error is None
|
||||
assert success is True
|
||||
|
@ -569,6 +580,7 @@ class TestCATTrades:
|
|||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
tx_config,
|
||||
)
|
||||
await time_out_assert(15, full_node.txs_in_mempool, True, tx_records)
|
||||
assert trade_take is not None
|
||||
|
@ -624,7 +636,11 @@ class TestCATTrades:
|
|||
|
||||
async with wallet_node_maker.wallet_state_manager.lock:
|
||||
cat_wallet_maker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, xch_to_cat_amount
|
||||
wallet_node_maker.wallet_state_manager,
|
||||
wallet_maker,
|
||||
{"identifier": "genesis_by_id"},
|
||||
xch_to_cat_amount,
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
|
||||
tx_records: List[TransactionRecord] = await wallet_node_maker.wallet_state_manager.tx_store.get_not_sent()
|
||||
|
@ -653,7 +669,7 @@ class TestCATTrades:
|
|||
trade_rec = await trade_manager.get_trade_by_id(trade.trade_id)
|
||||
return TradeStatus(trade_rec.status)
|
||||
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(cat_for_chia)
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(cat_for_chia, DEFAULT_TX_CONFIG)
|
||||
await asyncio.sleep(1)
|
||||
assert error is None
|
||||
assert success is True
|
||||
|
@ -681,7 +697,7 @@ class TestCATTrades:
|
|||
|
||||
fee = uint64(2_000_000_000_000)
|
||||
|
||||
txs = await trade_manager_maker.cancel_pending_offer_safely(trade_make.trade_id, fee=fee)
|
||||
txs = await trade_manager_maker.cancel_pending_offer_safely(trade_make.trade_id, DEFAULT_TX_CONFIG, fee=fee)
|
||||
await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make)
|
||||
await full_node.process_transaction_records(records=txs)
|
||||
|
||||
|
@ -704,10 +720,10 @@ class TestCATTrades:
|
|||
|
||||
peer = wallet_node_taker.get_full_node_peer()
|
||||
with pytest.raises(ValueError, match="This offer is no longer valid"):
|
||||
await trade_manager_taker.respond_to_offer(Offer.from_bytes(trade_make.offer), peer)
|
||||
await trade_manager_taker.respond_to_offer(Offer.from_bytes(trade_make.offer), peer, DEFAULT_TX_CONFIG)
|
||||
|
||||
# Now we're going to create the other way around for test coverage sake
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(chia_for_cat)
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(chia_for_cat, DEFAULT_TX_CONFIG)
|
||||
assert error is None
|
||||
assert success is True
|
||||
assert trade_make is not None
|
||||
|
@ -717,9 +733,11 @@ class TestCATTrades:
|
|||
ValueError,
|
||||
match=f"Do not have a wallet for asset ID: {cat_wallet_maker.get_asset_id()} to fulfill offer",
|
||||
):
|
||||
await trade_manager_taker.respond_to_offer(Offer.from_bytes(trade_make.offer), peer)
|
||||
await trade_manager_taker.respond_to_offer(Offer.from_bytes(trade_make.offer), peer, DEFAULT_TX_CONFIG)
|
||||
|
||||
txs = await trade_manager_maker.cancel_pending_offer_safely(trade_make.trade_id, fee=uint64(0))
|
||||
txs = await trade_manager_maker.cancel_pending_offer_safely(
|
||||
trade_make.trade_id, DEFAULT_TX_CONFIG, fee=uint64(0)
|
||||
)
|
||||
await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make)
|
||||
await full_node.process_transaction_records(records=txs)
|
||||
|
||||
|
@ -738,7 +756,11 @@ class TestCATTrades:
|
|||
|
||||
async with wallet_node_maker.wallet_state_manager.lock:
|
||||
cat_wallet_maker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, xch_to_cat_amount
|
||||
wallet_node_maker.wallet_state_manager,
|
||||
wallet_maker,
|
||||
{"identifier": "genesis_by_id"},
|
||||
xch_to_cat_amount,
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
|
||||
tx_records: List[TransactionRecord] = await wallet_node_maker.wallet_state_manager.tx_store.get_not_sent()
|
||||
|
@ -761,12 +783,14 @@ class TestCATTrades:
|
|||
trade_rec = await trade_manager.get_trade_by_id(trade.trade_id)
|
||||
return TradeStatus(trade_rec.status)
|
||||
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(chia_for_cat)
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(chia_for_cat, DEFAULT_TX_CONFIG)
|
||||
await time_out_assert(10, get_trade_and_status, TradeStatus.PENDING_ACCEPT, trade_manager_maker, trade_make)
|
||||
assert error is None
|
||||
assert success is True
|
||||
assert trade_make is not None
|
||||
txs = await trade_manager_maker.cancel_pending_offer_safely(trade_make.trade_id, fee=uint64(0))
|
||||
txs = await trade_manager_maker.cancel_pending_offer_safely(
|
||||
trade_make.trade_id, DEFAULT_TX_CONFIG, fee=uint64(0)
|
||||
)
|
||||
await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make)
|
||||
await full_node.process_transaction_records(records=txs)
|
||||
|
||||
|
@ -785,7 +809,11 @@ class TestCATTrades:
|
|||
|
||||
async with wallet_node_maker.wallet_state_manager.lock:
|
||||
cat_wallet_maker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, xch_to_cat_amount
|
||||
wallet_node_maker.wallet_state_manager,
|
||||
wallet_maker,
|
||||
{"identifier": "genesis_by_id"},
|
||||
xch_to_cat_amount,
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
|
||||
tx_records: List[TransactionRecord] = await wallet_node_maker.wallet_state_manager.tx_store.get_not_sent()
|
||||
|
@ -812,20 +840,20 @@ class TestCATTrades:
|
|||
return TradeStatus(trade_rec.status)
|
||||
raise ValueError("Couldn't find the trade record")
|
||||
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(chia_for_cat)
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(chia_for_cat, DEFAULT_TX_CONFIG)
|
||||
await time_out_assert(10, get_trade_and_status, TradeStatus.PENDING_ACCEPT, trade_manager_maker, trade_make)
|
||||
assert error is None
|
||||
assert success is True
|
||||
assert trade_make is not None
|
||||
peer = wallet_node_taker.get_full_node_peer()
|
||||
offer = Offer.from_bytes(trade_make.offer)
|
||||
tr1, txs1 = await trade_manager_taker.respond_to_offer(offer, peer, fee=uint64(10))
|
||||
tr1, txs1 = await trade_manager_taker.respond_to_offer(offer, peer, DEFAULT_TX_CONFIG, fee=uint64(10))
|
||||
# we shouldn't be able to respond to a duplicate offer
|
||||
with pytest.raises(ValueError):
|
||||
await trade_manager_taker.respond_to_offer(offer, peer, fee=uint64(10))
|
||||
await trade_manager_taker.respond_to_offer(offer, peer, DEFAULT_TX_CONFIG, fee=uint64(10))
|
||||
await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CONFIRM, trade_manager_taker, tr1)
|
||||
# pushing into mempool while already in it should fail
|
||||
tr2, txs2 = await trade_manager_trader.respond_to_offer(offer, peer, fee=uint64(10))
|
||||
tr2, txs2 = await trade_manager_trader.respond_to_offer(offer, peer, DEFAULT_TX_CONFIG, fee=uint64(10))
|
||||
assert await trade_manager_trader.get_coins_of_interest()
|
||||
offer_tx_records: List[TransactionRecord] = await wallet_node_maker.wallet_state_manager.tx_store.get_not_sent()
|
||||
await full_node.process_transaction_records(records=offer_tx_records)
|
||||
|
@ -843,7 +871,11 @@ class TestCATTrades:
|
|||
|
||||
async with wallet_node_maker.wallet_state_manager.lock:
|
||||
cat_wallet_maker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, xch_to_cat_amount
|
||||
wallet_node_maker.wallet_state_manager,
|
||||
wallet_maker,
|
||||
{"identifier": "genesis_by_id"},
|
||||
xch_to_cat_amount,
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
|
||||
tx_records: List[TransactionRecord] = await wallet_node_maker.wallet_state_manager.tx_store.get_not_sent()
|
||||
|
@ -869,7 +901,7 @@ class TestCATTrades:
|
|||
return TradeStatus(trade_rec.status)
|
||||
raise ValueError("Couldn't find the trade record")
|
||||
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(chia_for_cat)
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(chia_for_cat, DEFAULT_TX_CONFIG)
|
||||
await time_out_assert(10, get_trade_and_status, TradeStatus.PENDING_ACCEPT, trade_manager_maker, trade_make)
|
||||
assert error is None
|
||||
assert success is True
|
||||
|
@ -878,7 +910,7 @@ class TestCATTrades:
|
|||
offer = Offer.from_bytes(trade_make.offer)
|
||||
bundle = dataclasses.replace(offer._bundle, aggregated_signature=G2Element())
|
||||
offer = dataclasses.replace(offer, _bundle=bundle)
|
||||
tr1, txs1 = await trade_manager_taker.respond_to_offer(offer, peer, fee=uint64(10))
|
||||
tr1, txs1 = await trade_manager_taker.respond_to_offer(offer, peer, DEFAULT_TX_CONFIG, fee=uint64(10))
|
||||
wallet_node_taker.wallet_tx_resend_timeout_secs = 0 # don't wait for resend
|
||||
await wallet_node_taker._resend_queue()
|
||||
await wallet_node_taker._resend_queue()
|
||||
|
@ -902,7 +934,11 @@ class TestCATTrades:
|
|||
|
||||
async with wallet_node_maker.wallet_state_manager.lock:
|
||||
cat_wallet_maker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, xch_to_cat_amount
|
||||
wallet_node_maker.wallet_state_manager,
|
||||
wallet_maker,
|
||||
{"identifier": "genesis_by_id"},
|
||||
xch_to_cat_amount,
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
|
||||
tx_records: List[TransactionRecord] = await wallet_node_maker.wallet_state_manager.tx_store.get_not_sent()
|
||||
|
@ -928,13 +964,15 @@ class TestCATTrades:
|
|||
return TradeStatus(trade_rec.status)
|
||||
raise ValueError("Couldn't find the trade record")
|
||||
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(chia_for_cat)
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(chia_for_cat, DEFAULT_TX_CONFIG)
|
||||
await time_out_assert(10, get_trade_and_status, TradeStatus.PENDING_ACCEPT, trade_manager_maker, trade_make)
|
||||
assert error is None
|
||||
assert success is True
|
||||
assert trade_make is not None
|
||||
peer = wallet_node_taker.get_full_node_peer()
|
||||
offer = Offer.from_bytes(trade_make.offer)
|
||||
tr1, txs1 = await trade_manager_taker.respond_to_offer(offer, peer, fee=uint64(1000000000000))
|
||||
tr1, txs1 = await trade_manager_taker.respond_to_offer(
|
||||
offer, peer, DEFAULT_TX_CONFIG, fee=uint64(1000000000000)
|
||||
)
|
||||
await full_node.process_transaction_records(records=txs1)
|
||||
await time_out_assert(15, get_trade_and_status, TradeStatus.CONFIRMED, trade_manager_taker, tr1)
|
||||
|
|
|
@ -14,6 +14,7 @@ from chia.wallet.trade_record import TradeRecord
|
|||
from chia.wallet.trading.offer import Offer
|
||||
from chia.wallet.trading.trade_status import TradeStatus
|
||||
from chia.wallet.util.merkle_utils import build_merkle_tree, simplify_merkle_proof
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
|
||||
|
||||
async def is_singleton_confirmed_and_root(dl_wallet: DataLayerWallet, lid: bytes32, root: bytes32) -> bool:
|
||||
|
@ -69,7 +70,9 @@ async def test_dl_offers(wallets_prefarm: Any, trusted: bool, forwards_compat: b
|
|||
|
||||
fee = uint64(1_999_999_999_999)
|
||||
|
||||
dl_record, std_record, launcher_id_maker = await dl_wallet_maker.generate_new_reporter(maker_root, fee=fee)
|
||||
dl_record, std_record, launcher_id_maker = await dl_wallet_maker.generate_new_reporter(
|
||||
maker_root, DEFAULT_TX_CONFIG, fee=fee
|
||||
)
|
||||
assert await dl_wallet_maker.get_latest_singleton(launcher_id_maker) is not None
|
||||
await wsm_maker.add_pending_transaction(dl_record)
|
||||
await wsm_maker.add_pending_transaction(std_record)
|
||||
|
@ -78,7 +81,9 @@ async def test_dl_offers(wallets_prefarm: Any, trusted: bool, forwards_compat: b
|
|||
maker_funds -= 1
|
||||
await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_maker, launcher_id_maker, maker_root)
|
||||
|
||||
dl_record, std_record, launcher_id_taker = await dl_wallet_taker.generate_new_reporter(taker_root, fee=fee)
|
||||
dl_record, std_record, launcher_id_taker = await dl_wallet_taker.generate_new_reporter(
|
||||
taker_root, DEFAULT_TX_CONFIG, fee=fee
|
||||
)
|
||||
assert await dl_wallet_taker.get_latest_singleton(launcher_id_taker) is not None
|
||||
await wsm_taker.add_pending_transaction(dl_record)
|
||||
await wsm_taker.add_pending_transaction(std_record)
|
||||
|
@ -123,6 +128,7 @@ async def test_dl_offers(wallets_prefarm: Any, trusted: bool, forwards_compat: b
|
|||
else:
|
||||
success, offer_maker, error = await trade_manager_maker.create_offer_for_ids(
|
||||
{launcher_id_maker: -1, launcher_id_taker: 1},
|
||||
DEFAULT_TX_CONFIG,
|
||||
solver=Solver(
|
||||
{
|
||||
launcher_id_maker.hex(): {
|
||||
|
@ -162,6 +168,7 @@ async def test_dl_offers(wallets_prefarm: Any, trusted: bool, forwards_compat: b
|
|||
offer_taker, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(offer_maker.offer),
|
||||
peer,
|
||||
DEFAULT_TX_CONFIG,
|
||||
solver=Solver(
|
||||
{
|
||||
launcher_id_taker.hex(): {
|
||||
|
@ -247,7 +254,7 @@ async def test_dl_offers(wallets_prefarm: Any, trusted: bool, forwards_compat: b
|
|||
|
||||
await time_out_assert(15, is_singleton_generation, True, dl_wallet_taker, launcher_id_taker, 2)
|
||||
|
||||
txs = await dl_wallet_taker.create_update_state_spend(launcher_id_taker, bytes32([2] * 32))
|
||||
txs = await dl_wallet_taker.create_update_state_spend(launcher_id_taker, bytes32([2] * 32), DEFAULT_TX_CONFIG)
|
||||
for tx in txs:
|
||||
await wallet_node_taker.wallet_state_manager.add_pending_transaction(tx)
|
||||
await full_node_api.process_transaction_records(records=txs)
|
||||
|
@ -269,13 +276,13 @@ async def test_dl_offer_cancellation(wallets_prefarm: Any, trusted: bool) -> Non
|
|||
ROWS = [bytes32([i] * 32) for i in range(0, 10)]
|
||||
root, _ = build_merkle_tree(ROWS)
|
||||
|
||||
dl_record, std_record, launcher_id = await dl_wallet.generate_new_reporter(root)
|
||||
dl_record, std_record, launcher_id = await dl_wallet.generate_new_reporter(root, DEFAULT_TX_CONFIG)
|
||||
assert await dl_wallet.get_latest_singleton(launcher_id) is not None
|
||||
await wsm.add_pending_transaction(dl_record)
|
||||
await wsm.add_pending_transaction(std_record)
|
||||
await full_node_api.process_transaction_records(records=[dl_record, std_record])
|
||||
await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet, launcher_id, root)
|
||||
dl_record_2, std_record_2, launcher_id_2 = await dl_wallet.generate_new_reporter(root)
|
||||
dl_record_2, std_record_2, launcher_id_2 = await dl_wallet.generate_new_reporter(root, DEFAULT_TX_CONFIG)
|
||||
await wsm.add_pending_transaction(dl_record_2)
|
||||
await wsm.add_pending_transaction(std_record_2)
|
||||
await full_node_api.process_transaction_records(records=[dl_record_2, std_record_2])
|
||||
|
@ -288,6 +295,7 @@ async def test_dl_offer_cancellation(wallets_prefarm: Any, trusted: bool) -> Non
|
|||
|
||||
success, offer, error = await trade_manager.create_offer_for_ids(
|
||||
{launcher_id: -1, launcher_id_2: 1},
|
||||
DEFAULT_TX_CONFIG,
|
||||
solver=Solver(
|
||||
{
|
||||
launcher_id.hex(): {
|
||||
|
@ -307,7 +315,9 @@ async def test_dl_offer_cancellation(wallets_prefarm: Any, trusted: bool) -> Non
|
|||
assert success is True
|
||||
assert offer is not None
|
||||
|
||||
cancellation_txs = await trade_manager.cancel_pending_offer_safely(offer.trade_id, fee=uint64(2_000_000_000_000))
|
||||
cancellation_txs = await trade_manager.cancel_pending_offer_safely(
|
||||
offer.trade_id, DEFAULT_TX_CONFIG, fee=uint64(2_000_000_000_000)
|
||||
)
|
||||
assert len(cancellation_txs) == 3
|
||||
await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager, offer)
|
||||
await full_node_api.process_transaction_records(records=cancellation_txs)
|
||||
|
@ -346,7 +356,9 @@ async def test_multiple_dl_offers(wallets_prefarm: Any, trusted: bool, forwards_
|
|||
|
||||
fee = uint64(1_999_999_999_999)
|
||||
|
||||
dl_record, std_record, launcher_id_maker_1 = await dl_wallet_maker.generate_new_reporter(maker_root, fee=fee)
|
||||
dl_record, std_record, launcher_id_maker_1 = await dl_wallet_maker.generate_new_reporter(
|
||||
maker_root, DEFAULT_TX_CONFIG, fee=fee
|
||||
)
|
||||
assert await dl_wallet_maker.get_latest_singleton(launcher_id_maker_1) is not None
|
||||
await wsm_maker.add_pending_transaction(dl_record)
|
||||
await wsm_maker.add_pending_transaction(std_record)
|
||||
|
@ -354,7 +366,9 @@ async def test_multiple_dl_offers(wallets_prefarm: Any, trusted: bool, forwards_
|
|||
maker_funds -= fee
|
||||
maker_funds -= 1
|
||||
await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_maker, launcher_id_maker_1, maker_root)
|
||||
dl_record, std_record, launcher_id_maker_2 = await dl_wallet_maker.generate_new_reporter(maker_root, fee=fee)
|
||||
dl_record, std_record, launcher_id_maker_2 = await dl_wallet_maker.generate_new_reporter(
|
||||
maker_root, DEFAULT_TX_CONFIG, fee=fee
|
||||
)
|
||||
assert await dl_wallet_maker.get_latest_singleton(launcher_id_maker_2) is not None
|
||||
await wsm_maker.add_pending_transaction(dl_record)
|
||||
await wsm_maker.add_pending_transaction(std_record)
|
||||
|
@ -363,7 +377,9 @@ async def test_multiple_dl_offers(wallets_prefarm: Any, trusted: bool, forwards_
|
|||
maker_funds -= 1
|
||||
await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_maker, launcher_id_maker_2, maker_root)
|
||||
|
||||
dl_record, std_record, launcher_id_taker_1 = await dl_wallet_taker.generate_new_reporter(taker_root, fee=fee)
|
||||
dl_record, std_record, launcher_id_taker_1 = await dl_wallet_taker.generate_new_reporter(
|
||||
taker_root, DEFAULT_TX_CONFIG, fee=fee
|
||||
)
|
||||
assert await dl_wallet_taker.get_latest_singleton(launcher_id_taker_1) is not None
|
||||
await wsm_taker.add_pending_transaction(dl_record)
|
||||
await wsm_taker.add_pending_transaction(std_record)
|
||||
|
@ -371,7 +387,9 @@ async def test_multiple_dl_offers(wallets_prefarm: Any, trusted: bool, forwards_
|
|||
taker_funds -= fee
|
||||
taker_funds -= 1
|
||||
await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_taker, launcher_id_taker_1, taker_root)
|
||||
dl_record, std_record, launcher_id_taker_2 = await dl_wallet_taker.generate_new_reporter(taker_root, fee=fee)
|
||||
dl_record, std_record, launcher_id_taker_2 = await dl_wallet_taker.generate_new_reporter(
|
||||
taker_root, DEFAULT_TX_CONFIG, fee=fee
|
||||
)
|
||||
assert await dl_wallet_taker.get_latest_singleton(launcher_id_taker_2) is not None
|
||||
await wsm_taker.add_pending_transaction(dl_record)
|
||||
await wsm_taker.add_pending_transaction(std_record)
|
||||
|
@ -420,6 +438,7 @@ async def test_multiple_dl_offers(wallets_prefarm: Any, trusted: bool, forwards_
|
|||
else:
|
||||
success, offer_maker, error = await trade_manager_maker.create_offer_for_ids(
|
||||
{launcher_id_maker_1: -1, launcher_id_taker_1: 1, launcher_id_maker_2: -1, launcher_id_taker_2: 1},
|
||||
DEFAULT_TX_CONFIG,
|
||||
solver=Solver(
|
||||
{
|
||||
launcher_id_maker_1.hex(): {
|
||||
|
@ -455,6 +474,7 @@ async def test_multiple_dl_offers(wallets_prefarm: Any, trusted: bool, forwards_
|
|||
offer_taker, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(offer_maker.offer),
|
||||
peer,
|
||||
DEFAULT_TX_CONFIG,
|
||||
solver=Solver(
|
||||
{
|
||||
launcher_id_taker_1.hex(): {
|
||||
|
|
|
@ -18,6 +18,7 @@ from chia.types.peer_info import PeerInfo
|
|||
from chia.util.ints import uint16, uint32, uint64
|
||||
from chia.wallet.db_wallet.db_wallet_puzzles import create_mirror_puzzle
|
||||
from chia.wallet.util.merkle_tree import MerkleTree
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
|
||||
pytestmark = pytest.mark.data_layer
|
||||
|
||||
|
@ -68,7 +69,7 @@ class TestDLWallet:
|
|||
|
||||
for i in range(0, 2):
|
||||
dl_record, std_record, launcher_id = await dl_wallet.generate_new_reporter(
|
||||
current_root, fee=uint64(1999999999999)
|
||||
current_root, DEFAULT_TX_CONFIG, fee=uint64(1999999999999)
|
||||
)
|
||||
|
||||
assert await dl_wallet.get_latest_singleton(launcher_id) is not None
|
||||
|
@ -120,7 +121,7 @@ class TestDLWallet:
|
|||
|
||||
for i in range(0, 2):
|
||||
dl_record, std_record, launcher_id = await dl_wallet.generate_new_reporter(
|
||||
current_root, fee=uint64(1999999999999)
|
||||
current_root, DEFAULT_TX_CONFIG, fee=uint64(1999999999999)
|
||||
)
|
||||
expected_launcher_ids.add(launcher_id)
|
||||
|
||||
|
@ -183,7 +184,7 @@ class TestDLWallet:
|
|||
current_tree = MerkleTree(nodes)
|
||||
current_root = current_tree.calculate_root()
|
||||
|
||||
dl_record, std_record, launcher_id = await dl_wallet_0.generate_new_reporter(current_root)
|
||||
dl_record, std_record, launcher_id = await dl_wallet_0.generate_new_reporter(current_root, DEFAULT_TX_CONFIG)
|
||||
|
||||
assert await dl_wallet_0.get_latest_singleton(launcher_id) is not None
|
||||
|
||||
|
@ -200,7 +201,7 @@ class TestDLWallet:
|
|||
|
||||
for i in range(0, 5):
|
||||
new_root = MerkleTree([Program.to("root").get_tree_hash()]).calculate_root()
|
||||
txs = await dl_wallet_0.create_update_state_spend(launcher_id, new_root)
|
||||
txs = await dl_wallet_0.create_update_state_spend(launcher_id, new_root, DEFAULT_TX_CONFIG)
|
||||
|
||||
for tx in txs:
|
||||
await wallet_node_0.wallet_state_manager.add_pending_transaction(tx)
|
||||
|
@ -255,7 +256,7 @@ class TestDLWallet:
|
|||
current_tree = MerkleTree(nodes)
|
||||
current_root = current_tree.calculate_root()
|
||||
|
||||
dl_record, std_record, launcher_id = await dl_wallet.generate_new_reporter(current_root)
|
||||
dl_record, std_record, launcher_id = await dl_wallet.generate_new_reporter(current_root, DEFAULT_TX_CONFIG)
|
||||
|
||||
assert await dl_wallet.get_latest_singleton(launcher_id) is not None
|
||||
|
||||
|
@ -275,6 +276,7 @@ class TestDLWallet:
|
|||
txs = await dl_wallet.generate_signed_transaction(
|
||||
[previous_record.lineage_proof.amount],
|
||||
[previous_record.inner_puzzle_hash],
|
||||
DEFAULT_TX_CONFIG,
|
||||
launcher_id=previous_record.launcher_id,
|
||||
new_root_hash=new_root,
|
||||
fee=uint64(1999999999999),
|
||||
|
@ -284,6 +286,7 @@ class TestDLWallet:
|
|||
await dl_wallet.generate_signed_transaction(
|
||||
[previous_record.lineage_proof.amount],
|
||||
[previous_record.inner_puzzle_hash],
|
||||
DEFAULT_TX_CONFIG,
|
||||
coins=set([txs[0].spend_bundle.removals()[0]]),
|
||||
fee=uint64(1999999999999),
|
||||
)
|
||||
|
@ -305,7 +308,7 @@ class TestDLWallet:
|
|||
previous_record = await dl_wallet.get_latest_singleton(launcher_id)
|
||||
|
||||
new_root = MerkleTree([Program.to("new root").get_tree_hash()]).calculate_root()
|
||||
txs = await dl_wallet.create_update_state_spend(launcher_id, new_root)
|
||||
txs = await dl_wallet.create_update_state_spend(launcher_id, new_root, DEFAULT_TX_CONFIG)
|
||||
new_record = await dl_wallet.get_latest_singleton(launcher_id)
|
||||
assert new_record is not None
|
||||
assert new_record != previous_record
|
||||
|
@ -367,7 +370,7 @@ class TestDLWallet:
|
|||
return False
|
||||
return latest_singleton.confirmed
|
||||
|
||||
dl_record, std_record, launcher_id = await dl_wallet_0.generate_new_reporter(current_root)
|
||||
dl_record, std_record, launcher_id = await dl_wallet_0.generate_new_reporter(current_root, DEFAULT_TX_CONFIG)
|
||||
|
||||
initial_record = await dl_wallet_0.get_latest_singleton(launcher_id)
|
||||
assert initial_record is not None
|
||||
|
@ -391,13 +394,13 @@ class TestDLWallet:
|
|||
|
||||
# Because these have the same fee, the one that gets pushed first will win
|
||||
report_txs = await dl_wallet_1.create_update_state_spend(
|
||||
launcher_id, current_record.root, fee=uint64(2000000000000)
|
||||
launcher_id, current_record.root, DEFAULT_TX_CONFIG, fee=uint64(2000000000000)
|
||||
)
|
||||
record_1 = await dl_wallet_1.get_latest_singleton(launcher_id)
|
||||
assert record_1 is not None
|
||||
assert current_record != record_1
|
||||
update_txs = await dl_wallet_0.create_update_state_spend(
|
||||
launcher_id, bytes32([0] * 32), fee=uint64(2000000000000)
|
||||
launcher_id, bytes32([0] * 32), DEFAULT_TX_CONFIG, fee=uint64(2000000000000)
|
||||
)
|
||||
record_0 = await dl_wallet_0.get_latest_singleton(launcher_id)
|
||||
assert record_0 is not None
|
||||
|
@ -454,7 +457,7 @@ class TestDLWallet:
|
|||
assert await dl_wallet_0.get_singleton_record(record_0.coin_id) is None
|
||||
|
||||
update_txs_1 = await dl_wallet_0.create_update_state_spend(
|
||||
launcher_id, bytes32([1] * 32), fee=uint64(2000000000000)
|
||||
launcher_id, bytes32([1] * 32), DEFAULT_TX_CONFIG, fee=uint64(2000000000000)
|
||||
)
|
||||
record_1 = await dl_wallet_0.get_latest_singleton(launcher_id)
|
||||
assert record_1 is not None
|
||||
|
@ -467,7 +470,7 @@ class TestDLWallet:
|
|||
for tx in update_txs_1:
|
||||
await wallet_node_0.wallet_state_manager.tx_store.delete_transaction_record(tx.name)
|
||||
|
||||
update_txs_0 = await dl_wallet_0.create_update_state_spend(launcher_id, bytes32([2] * 32))
|
||||
update_txs_0 = await dl_wallet_0.create_update_state_spend(launcher_id, bytes32([2] * 32), DEFAULT_TX_CONFIG)
|
||||
record_0 = await dl_wallet_0.get_latest_singleton(launcher_id)
|
||||
assert record_0 is not None
|
||||
assert record_0 != record_1
|
||||
|
@ -536,14 +539,14 @@ async def test_mirrors(wallets_prefarm: Any, trusted: bool) -> None:
|
|||
async with wsm_2.lock:
|
||||
dl_wallet_2 = await DataLayerWallet.create_new_dl_wallet(wsm_2)
|
||||
|
||||
dl_record, std_record, launcher_id_1 = await dl_wallet_1.generate_new_reporter(bytes32([0] * 32))
|
||||
dl_record, std_record, launcher_id_1 = await dl_wallet_1.generate_new_reporter(bytes32([0] * 32), DEFAULT_TX_CONFIG)
|
||||
assert await dl_wallet_1.get_latest_singleton(launcher_id_1) is not None
|
||||
await wsm_1.add_pending_transaction(dl_record)
|
||||
await wsm_1.add_pending_transaction(std_record)
|
||||
await full_node_api.process_transaction_records(records=[dl_record, std_record])
|
||||
await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_1, launcher_id_1, bytes32([0] * 32))
|
||||
|
||||
dl_record, std_record, launcher_id_2 = await dl_wallet_2.generate_new_reporter(bytes32([0] * 32))
|
||||
dl_record, std_record, launcher_id_2 = await dl_wallet_2.generate_new_reporter(bytes32([0] * 32), DEFAULT_TX_CONFIG)
|
||||
assert await dl_wallet_2.get_latest_singleton(launcher_id_2) is not None
|
||||
await wsm_2.add_pending_transaction(dl_record)
|
||||
await wsm_2.add_pending_transaction(std_record)
|
||||
|
@ -557,7 +560,9 @@ async def test_mirrors(wallets_prefarm: Any, trusted: bool) -> None:
|
|||
await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_1, launcher_id_2, bytes32([0] * 32))
|
||||
await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_2, launcher_id_1, bytes32([0] * 32))
|
||||
|
||||
txs = await dl_wallet_1.create_new_mirror(launcher_id_2, uint64(3), [b"foo", b"bar"], fee=uint64(1_999_999_999_999))
|
||||
txs = await dl_wallet_1.create_new_mirror(
|
||||
launcher_id_2, uint64(3), [b"foo", b"bar"], DEFAULT_TX_CONFIG, fee=uint64(1_999_999_999_999)
|
||||
)
|
||||
additions: List[Coin] = []
|
||||
for tx in txs:
|
||||
if tx.spend_bundle is not None:
|
||||
|
@ -574,7 +579,7 @@ async def test_mirrors(wallets_prefarm: Any, trusted: bool) -> None:
|
|||
15, dl_wallet_2.get_mirrors_for_launcher, [dataclasses.replace(mirror, ours=False)], launcher_id_2
|
||||
)
|
||||
|
||||
txs = await dl_wallet_1.delete_mirror(mirror.coin_id, peer_1, fee=uint64(2_000_000_000_000))
|
||||
txs = await dl_wallet_1.delete_mirror(mirror.coin_id, peer_1, DEFAULT_TX_CONFIG, fee=uint64(2_000_000_000_000))
|
||||
for tx in txs:
|
||||
await wsm_1.add_pending_transaction(tx)
|
||||
await full_node_api.process_transaction_records(records=txs)
|
||||
|
|
|
@ -21,6 +21,7 @@ from chia.util.ints import uint16, uint64
|
|||
from chia.wallet.did_wallet.did_wallet import DIDWallet
|
||||
from chia.wallet.singleton import create_singleton_puzzle
|
||||
from chia.wallet.util.address_type import AddressType
|
||||
from chia.wallet.util.tx_config import DEFAULT_COIN_SELECTION_CONFIG, DEFAULT_TX_CONFIG
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet import CHIP_0002_SIGN_MESSAGE_PREFIX
|
||||
|
||||
|
@ -195,7 +196,7 @@ class TestDIDWallet:
|
|||
did_wallet_2 = await DIDWallet.create_new_did_wallet_from_recovery(
|
||||
wallet_node_2.wallet_state_manager, wallet_2, backup_data
|
||||
)
|
||||
coins = await did_wallet_1.select_coins(1)
|
||||
coins = await did_wallet_1.select_coins(1, DEFAULT_COIN_SELECTION_CONFIG)
|
||||
coin = coins.copy().pop()
|
||||
assert did_wallet_2.did_info.temp_coin == coin
|
||||
newpuzhash = await did_wallet_2.get_new_did_inner_hash()
|
||||
|
@ -203,7 +204,7 @@ class TestDIDWallet:
|
|||
(await did_wallet_2.wallet_state_manager.get_unused_derivation_record(did_wallet_2.wallet_info.id)).pubkey
|
||||
)
|
||||
message_spend_bundle, attest_data = await did_wallet_0.create_attestment(
|
||||
did_wallet_2.did_info.temp_coin.name(), newpuzhash, pubkey
|
||||
did_wallet_2.did_info.temp_coin.name(), newpuzhash, pubkey, DEFAULT_TX_CONFIG
|
||||
)
|
||||
spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
|
||||
did_wallet_0.id()
|
||||
|
@ -239,7 +240,7 @@ class TestDIDWallet:
|
|||
assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet
|
||||
|
||||
some_ph = 32 * b"\2"
|
||||
await did_wallet_2.create_exit_spend(some_ph)
|
||||
await did_wallet_2.create_exit_spend(some_ph, DEFAULT_TX_CONFIG)
|
||||
|
||||
spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
|
||||
did_wallet_2.id()
|
||||
|
@ -347,7 +348,7 @@ class TestDIDWallet:
|
|||
assert did_wallet_3.did_info.backup_ids == recovery_list
|
||||
await time_out_assert(15, did_wallet_3.get_confirmed_balance, 201)
|
||||
await time_out_assert(15, did_wallet_3.get_unconfirmed_balance, 201)
|
||||
coins = await did_wallet_3.select_coins(1)
|
||||
coins = await did_wallet_3.select_coins(1, DEFAULT_COIN_SELECTION_CONFIG)
|
||||
coin = coins.pop()
|
||||
|
||||
backup_data = did_wallet_3.create_backup()
|
||||
|
@ -364,12 +365,16 @@ class TestDIDWallet:
|
|||
await did_wallet_4.wallet_state_manager.get_unused_derivation_record(did_wallet_2.wallet_info.id)
|
||||
).pubkey
|
||||
new_ph = did_wallet_4.did_info.temp_puzhash
|
||||
message_spend_bundle, attest1 = await did_wallet.create_attestment(coin.name(), new_ph, pubkey)
|
||||
message_spend_bundle, attest1 = await did_wallet.create_attestment(
|
||||
coin.name(), new_ph, pubkey, DEFAULT_TX_CONFIG
|
||||
)
|
||||
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id())
|
||||
|
||||
spend_bundle = spend_bundle_list[0].spend_bundle
|
||||
await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name())
|
||||
message_spend_bundle2, attest2 = await did_wallet_2.create_attestment(coin.name(), new_ph, pubkey)
|
||||
message_spend_bundle2, attest2 = await did_wallet_2.create_attestment(
|
||||
coin.name(), new_ph, pubkey, DEFAULT_TX_CONFIG
|
||||
)
|
||||
spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
|
||||
did_wallet_2.id()
|
||||
)
|
||||
|
@ -448,7 +453,7 @@ class TestDIDWallet:
|
|||
|
||||
await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
|
||||
await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
|
||||
coins = await did_wallet.select_coins(1)
|
||||
coins = await did_wallet.select_coins(1, DEFAULT_COIN_SELECTION_CONFIG)
|
||||
coin = coins.pop()
|
||||
info = Program.to([])
|
||||
pubkey = (await did_wallet.wallet_state_manager.get_unused_derivation_record(did_wallet.wallet_info.id)).pubkey
|
||||
|
@ -503,7 +508,7 @@ class TestDIDWallet:
|
|||
await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
|
||||
await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
|
||||
# Delete the coin and wallet
|
||||
coins = await did_wallet.select_coins(uint64(1))
|
||||
coins = await did_wallet.select_coins(uint64(1), DEFAULT_COIN_SELECTION_CONFIG)
|
||||
coin = coins.pop()
|
||||
await wallet_node.wallet_state_manager.coin_store.delete_coin_record(coin.name())
|
||||
await time_out_assert(15, did_wallet.get_confirmed_balance, 0)
|
||||
|
@ -526,7 +531,7 @@ class TestDIDWallet:
|
|||
recovery_list = [bytes32.fromhex(did_wallet.get_my_DID())]
|
||||
await did_wallet.update_recovery_list(recovery_list, uint64(1))
|
||||
assert did_wallet.did_info.backup_ids == recovery_list
|
||||
await did_wallet.create_update_spend()
|
||||
await did_wallet.create_update_spend(DEFAULT_TX_CONFIG)
|
||||
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id())
|
||||
spend_bundle = spend_bundle_list[0].spend_bundle
|
||||
await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name())
|
||||
|
@ -535,7 +540,7 @@ class TestDIDWallet:
|
|||
await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
|
||||
await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
|
||||
# Delete the coin and change inner puzzle
|
||||
coins = await did_wallet.select_coins(uint64(1))
|
||||
coins = await did_wallet.select_coins(uint64(1), DEFAULT_COIN_SELECTION_CONFIG)
|
||||
coin = coins.pop()
|
||||
await wallet_node.wallet_state_manager.coin_store.delete_coin_record(coin.name())
|
||||
await time_out_assert(15, did_wallet.get_confirmed_balance, 0)
|
||||
|
@ -607,7 +612,7 @@ class TestDIDWallet:
|
|||
recovery_list = [bytes.fromhex(did_wallet_2.get_my_DID())]
|
||||
await did_wallet.update_recovery_list(recovery_list, uint64(1))
|
||||
assert did_wallet.did_info.backup_ids == recovery_list
|
||||
await did_wallet.create_update_spend()
|
||||
await did_wallet.create_update_spend(DEFAULT_TX_CONFIG)
|
||||
|
||||
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id())
|
||||
|
||||
|
@ -629,13 +634,13 @@ class TestDIDWallet:
|
|||
backup_data,
|
||||
)
|
||||
new_ph = await did_wallet_3.get_new_did_inner_hash()
|
||||
coins = await did_wallet_2.select_coins(1)
|
||||
coins = await did_wallet_2.select_coins(1, DEFAULT_COIN_SELECTION_CONFIG)
|
||||
coin = coins.pop()
|
||||
pubkey = (
|
||||
await did_wallet_3.wallet_state_manager.get_unused_derivation_record(did_wallet_3.wallet_info.id)
|
||||
).pubkey
|
||||
await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
|
||||
attest_data = (await did_wallet.create_attestment(coin.name(), new_ph, pubkey))[1]
|
||||
attest_data = (await did_wallet.create_attestment(coin.name(), new_ph, pubkey, DEFAULT_TX_CONFIG))[1]
|
||||
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id())
|
||||
|
||||
spend_bundle = spend_bundle_list[0].spend_bundle
|
||||
|
@ -668,13 +673,13 @@ class TestDIDWallet:
|
|||
wallet2,
|
||||
backup_data,
|
||||
)
|
||||
coins = await did_wallet.select_coins(1)
|
||||
coins = await did_wallet.select_coins(1, DEFAULT_COIN_SELECTION_CONFIG)
|
||||
coin = coins.pop()
|
||||
new_ph = await did_wallet_4.get_new_did_inner_hash()
|
||||
pubkey = (
|
||||
await did_wallet_4.wallet_state_manager.get_unused_derivation_record(did_wallet_4.wallet_info.id)
|
||||
).pubkey
|
||||
attest1 = (await did_wallet_3.create_attestment(coin.name(), new_ph, pubkey))[1]
|
||||
attest1 = (await did_wallet_3.create_attestment(coin.name(), new_ph, pubkey, DEFAULT_TX_CONFIG))[1]
|
||||
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
|
||||
did_wallet_3.id()
|
||||
)
|
||||
|
@ -762,7 +767,7 @@ class TestDIDWallet:
|
|||
await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101)
|
||||
# Transfer DID
|
||||
new_puzhash = await wallet2.get_new_puzzlehash()
|
||||
await did_wallet_1.transfer_did(new_puzhash, fee, with_recovery)
|
||||
await did_wallet_1.transfer_did(new_puzhash, fee, with_recovery, DEFAULT_TX_CONFIG)
|
||||
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
|
||||
did_wallet_1.id()
|
||||
)
|
||||
|
@ -832,7 +837,7 @@ class TestDIDWallet:
|
|||
await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101)
|
||||
await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101)
|
||||
await did_wallet_1.update_recovery_list([bytes(ph)], 1)
|
||||
await did_wallet_1.create_update_spend()
|
||||
await did_wallet_1.create_update_spend(DEFAULT_TX_CONFIG)
|
||||
await full_node_api.farm_blocks_to_wallet(1, wallet)
|
||||
await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101)
|
||||
await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101)
|
||||
|
@ -890,26 +895,38 @@ class TestDIDWallet:
|
|||
did_wallet_1.did_info.current_inner, did_wallet_1.did_info.origin_coin.name()
|
||||
)
|
||||
assert response["metadata"]["twitter"] == "twitter"
|
||||
assert response["latest_coin"] == (await did_wallet_1.select_coins(uint64(1))).pop().name().hex()
|
||||
assert (
|
||||
response["latest_coin"]
|
||||
== (await did_wallet_1.select_coins(uint64(1), DEFAULT_COIN_SELECTION_CONFIG)).pop().name().hex()
|
||||
)
|
||||
assert response["num_verification"] == 0
|
||||
assert response["recovery_list_hash"] == Program(Program.to([])).get_tree_hash().hex()
|
||||
assert decode_puzzle_hash(response["p2_address"]).hex() == response["hints"][0]
|
||||
|
||||
# Test non-singleton coin
|
||||
coin = (await wallet.select_coins(uint64(1))).pop()
|
||||
coin = (await wallet.select_coins(uint64(1), DEFAULT_COIN_SELECTION_CONFIG)).pop()
|
||||
assert coin.amount % 2 == 1
|
||||
response = await api_0.did_get_info({"coin_id": coin.name().hex()})
|
||||
assert not response["success"]
|
||||
|
||||
# Test multiple odd coins
|
||||
odd_amount = uint64(1)
|
||||
coin_1 = (await wallet.select_coins(odd_amount, exclude=[coin])).pop()
|
||||
coin_1 = (
|
||||
await wallet.select_coins(
|
||||
odd_amount, dataclasses.replace(DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_ids=[coin.name()])
|
||||
)
|
||||
).pop()
|
||||
assert coin_1.amount % 2 == 0
|
||||
tx = await wallet.generate_signed_transaction(
|
||||
odd_amount,
|
||||
ph1,
|
||||
dataclasses.replace(
|
||||
DEFAULT_TX_CONFIG,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_ids=[coin.name()]
|
||||
),
|
||||
),
|
||||
fee,
|
||||
excluded_coins=set([coin]),
|
||||
)
|
||||
await wallet.push_transaction(tx)
|
||||
await full_node_api.process_transaction_records(records=[tx])
|
||||
|
@ -1032,7 +1049,7 @@ class TestDIDWallet:
|
|||
metadata = {}
|
||||
metadata["Twitter"] = "http://www.twitter.com"
|
||||
await did_wallet_1.update_metadata(metadata)
|
||||
await did_wallet_1.create_update_spend(fee)
|
||||
await did_wallet_1.create_update_spend(DEFAULT_TX_CONFIG, fee)
|
||||
transaction_records = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
|
||||
did_wallet_1.id()
|
||||
)
|
||||
|
|
|
@ -25,6 +25,7 @@ from chia.wallet.trading.offer import Offer
|
|||
from chia.wallet.trading.trade_status import TradeStatus
|
||||
from chia.wallet.uncurried_puzzle import uncurry_puzzle
|
||||
from chia.wallet.util.compute_memos import compute_memos
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from tests.wallet.cat_wallet.test_trades import create_tr_for_offer
|
||||
|
||||
# from clvm_tools.binutils import disassemble
|
||||
|
@ -137,6 +138,7 @@ async def test_nft_offer_sell_nft(
|
|||
|
||||
sb = await nft_wallet_maker.generate_new_nft(
|
||||
metadata,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_puzhash,
|
||||
royalty_puzhash,
|
||||
royalty_basis_pts,
|
||||
|
@ -188,7 +190,7 @@ async def test_nft_offer_sell_nft(
|
|||
)
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_did_nft_for_xch, {}, fee=maker_fee
|
||||
offer_did_nft_for_xch, DEFAULT_TX_CONFIG, {}, fee=maker_fee
|
||||
)
|
||||
assert success is True
|
||||
assert error is None
|
||||
|
@ -199,7 +201,10 @@ async def test_nft_offer_sell_nft(
|
|||
peer = wallet_node_taker.get_full_node_peer()
|
||||
|
||||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer), peer, fee=uint64(taker_fee)
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
DEFAULT_TX_CONFIG,
|
||||
fee=uint64(taker_fee),
|
||||
)
|
||||
|
||||
await time_out_assert(20, mempool_not_empty, True, full_node_api)
|
||||
|
@ -310,6 +315,7 @@ async def test_nft_offer_request_nft(
|
|||
|
||||
sb = await nft_wallet_taker.generate_new_nft(
|
||||
metadata,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_puzhash,
|
||||
royalty_puzhash,
|
||||
royalty_basis_pts,
|
||||
|
@ -364,7 +370,7 @@ async def test_nft_offer_request_nft(
|
|||
)
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_dict, driver_dict, fee=maker_fee
|
||||
offer_dict, DEFAULT_TX_CONFIG, driver_dict, fee=maker_fee
|
||||
)
|
||||
assert success is True
|
||||
assert error is None
|
||||
|
@ -374,7 +380,10 @@ async def test_nft_offer_request_nft(
|
|||
|
||||
peer = wallet_node_taker.get_full_node_peer()
|
||||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer), peer, fee=uint64(taker_fee)
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
DEFAULT_TX_CONFIG,
|
||||
fee=uint64(taker_fee),
|
||||
)
|
||||
await time_out_assert(20, mempool_not_empty, True, full_node_api)
|
||||
assert trade_take is not None
|
||||
|
@ -482,6 +491,7 @@ async def test_nft_offer_sell_did_to_did(
|
|||
|
||||
sb = await nft_wallet_maker.generate_new_nft(
|
||||
metadata,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_puzhash,
|
||||
royalty_puzhash,
|
||||
royalty_basis_pts,
|
||||
|
@ -551,7 +561,7 @@ async def test_nft_offer_sell_did_to_did(
|
|||
)
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_did_nft_for_xch, {}, fee=maker_fee
|
||||
offer_did_nft_for_xch, DEFAULT_TX_CONFIG, {}, fee=maker_fee
|
||||
)
|
||||
assert success is True
|
||||
assert error is None
|
||||
|
@ -561,7 +571,10 @@ async def test_nft_offer_sell_did_to_did(
|
|||
|
||||
peer = wallet_node_taker.get_full_node_peer()
|
||||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer), peer, fee=uint64(taker_fee)
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
DEFAULT_TX_CONFIG,
|
||||
fee=uint64(taker_fee),
|
||||
)
|
||||
await time_out_assert(20, mempool_not_empty, True, full_node_api)
|
||||
assert trade_take is not None
|
||||
|
@ -675,6 +688,7 @@ async def test_nft_offer_sell_nft_for_cat(
|
|||
|
||||
sb = await nft_wallet_maker.generate_new_nft(
|
||||
metadata,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_puzhash,
|
||||
royalty_puzhash,
|
||||
royalty_basis_pts,
|
||||
|
@ -711,7 +725,11 @@ async def test_nft_offer_sell_nft_for_cat(
|
|||
async with wallet_node_maker.wallet_state_manager.lock:
|
||||
full_node_api.full_node.log.warning(f"Mempool size: {full_node_api.full_node.mempool_manager.mempool.size()}")
|
||||
cat_wallet_maker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, uint64(cats_to_mint)
|
||||
wallet_node_maker.wallet_state_manager,
|
||||
wallet_maker,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(cats_to_mint),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
await time_out_assert(20, mempool_not_empty, True, full_node_api)
|
||||
|
||||
|
@ -728,7 +746,10 @@ async def test_nft_offer_sell_nft_for_cat(
|
|||
ph_taker_cat_1 = await wallet_taker.get_new_puzzlehash()
|
||||
ph_taker_cat_2 = await wallet_taker.get_new_puzzlehash()
|
||||
cat_tx_records = await cat_wallet_maker.generate_signed_transaction(
|
||||
[cats_to_trade, cats_to_trade], [ph_taker_cat_1, ph_taker_cat_2], memos=[[ph_taker_cat_1], [ph_taker_cat_2]]
|
||||
[cats_to_trade, cats_to_trade],
|
||||
[ph_taker_cat_1, ph_taker_cat_2],
|
||||
DEFAULT_TX_CONFIG,
|
||||
memos=[[ph_taker_cat_1], [ph_taker_cat_2]],
|
||||
)
|
||||
for tx_record in cat_tx_records:
|
||||
await wallet_maker.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
|
@ -762,7 +783,7 @@ async def test_nft_offer_sell_nft_for_cat(
|
|||
)
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_did_nft_for_xch, {}, fee=maker_fee
|
||||
offer_did_nft_for_xch, DEFAULT_TX_CONFIG, {}, fee=maker_fee
|
||||
)
|
||||
|
||||
assert success is True
|
||||
|
@ -773,7 +794,10 @@ async def test_nft_offer_sell_nft_for_cat(
|
|||
|
||||
peer = wallet_node_taker.get_full_node_peer()
|
||||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer), peer, fee=uint64(taker_fee)
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
DEFAULT_TX_CONFIG,
|
||||
fee=uint64(taker_fee),
|
||||
)
|
||||
await time_out_assert(20, mempool_not_empty, True, full_node_api)
|
||||
assert trade_take is not None
|
||||
|
@ -882,6 +906,7 @@ async def test_nft_offer_request_nft_for_cat(
|
|||
|
||||
sb = await nft_wallet_taker.generate_new_nft(
|
||||
metadata,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_puzhash,
|
||||
royalty_puzhash,
|
||||
royalty_basis_pts,
|
||||
|
@ -917,7 +942,11 @@ async def test_nft_offer_request_nft_for_cat(
|
|||
cats_to_trade = uint64(20000)
|
||||
async with wallet_node_maker.wallet_state_manager.lock:
|
||||
cat_wallet_maker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, uint64(cats_to_mint)
|
||||
wallet_node_maker.wallet_state_manager,
|
||||
wallet_maker,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(cats_to_mint),
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
await time_out_assert(20, mempool_not_empty, True, full_node_api)
|
||||
|
||||
|
@ -943,7 +972,7 @@ async def test_nft_offer_request_nft_for_cat(
|
|||
extra_change = cats_to_mint - (2 * cats_to_trade)
|
||||
amounts.append(uint64(extra_change))
|
||||
puzzle_hashes.append(ph_taker_cat_1)
|
||||
cat_tx_records = await cat_wallet_maker.generate_signed_transaction(amounts, puzzle_hashes)
|
||||
cat_tx_records = await cat_wallet_maker.generate_signed_transaction(amounts, puzzle_hashes, DEFAULT_TX_CONFIG)
|
||||
for tx_record in cat_tx_records:
|
||||
await wallet_maker.wallet_state_manager.add_pending_transaction(tx_record)
|
||||
await full_node_api.process_transaction_records(records=cat_tx_records)
|
||||
|
@ -984,7 +1013,7 @@ async def test_nft_offer_request_nft_for_cat(
|
|||
await trade_manager_maker.save_trade(*create_tr_for_offer(old_maker_offer))
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_dict, driver_dict, fee=maker_fee
|
||||
offer_dict, DEFAULT_TX_CONFIG, driver_dict, fee=maker_fee
|
||||
)
|
||||
assert success is True
|
||||
assert error is None
|
||||
|
@ -994,7 +1023,10 @@ async def test_nft_offer_request_nft_for_cat(
|
|||
|
||||
peer = wallet_node_taker.get_full_node_peer()
|
||||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer), peer, fee=uint64(taker_fee)
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
DEFAULT_TX_CONFIG,
|
||||
fee=uint64(taker_fee),
|
||||
)
|
||||
await time_out_assert(20, mempool_not_empty, True, full_node_api)
|
||||
assert trade_take is not None
|
||||
|
@ -1089,6 +1121,7 @@ async def test_nft_offer_sell_cancel(self_hostname: str, two_wallet_nodes: Any,
|
|||
|
||||
sb = await nft_wallet_maker.generate_new_nft(
|
||||
metadata,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_puzhash,
|
||||
royalty_puzhash,
|
||||
royalty_basis_pts,
|
||||
|
@ -1118,11 +1151,11 @@ async def test_nft_offer_sell_cancel(self_hostname: str, two_wallet_nodes: Any,
|
|||
offer_did_nft_for_xch = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested}
|
||||
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_did_nft_for_xch, {}, fee=maker_fee
|
||||
offer_did_nft_for_xch, DEFAULT_TX_CONFIG, {}, fee=maker_fee
|
||||
)
|
||||
|
||||
FEE = uint64(2000000000000)
|
||||
txs = await trade_manager_maker.cancel_pending_offer_safely(trade_make.trade_id, fee=FEE)
|
||||
txs = await trade_manager_maker.cancel_pending_offer_safely(trade_make.trade_id, DEFAULT_TX_CONFIG, fee=FEE)
|
||||
|
||||
async def get_trade_and_status(trade_manager: Any, trade: Any) -> TradeStatus:
|
||||
trade_rec = await trade_manager.get_trade_by_id(trade.trade_id)
|
||||
|
@ -1206,6 +1239,7 @@ async def test_nft_offer_sell_cancel_in_batch(self_hostname: str, two_wallet_nod
|
|||
|
||||
sb = await nft_wallet_maker.generate_new_nft(
|
||||
metadata,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_puzhash,
|
||||
royalty_puzhash,
|
||||
royalty_basis_pts,
|
||||
|
@ -1236,11 +1270,11 @@ async def test_nft_offer_sell_cancel_in_batch(self_hostname: str, two_wallet_nod
|
|||
offer_did_nft_for_xch = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested}
|
||||
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_did_nft_for_xch, {}, fee=maker_fee
|
||||
offer_did_nft_for_xch, DEFAULT_TX_CONFIG, {}, fee=maker_fee
|
||||
)
|
||||
|
||||
FEE = uint64(2000000000000)
|
||||
txs = await trade_manager_maker.cancel_pending_offers([trade_make], fee=FEE, secure=True)
|
||||
txs = await trade_manager_maker.cancel_pending_offers([trade_make], DEFAULT_TX_CONFIG, fee=FEE, secure=True)
|
||||
|
||||
async def get_trade_and_status(trade_manager: Any, trade: Any) -> TradeStatus:
|
||||
trade_rec = await trade_manager.get_trade_by_id(trade.trade_id)
|
||||
|
@ -1339,11 +1373,11 @@ async def test_complex_nft_offer(
|
|||
CAT_AMOUNT = uint64(100000000)
|
||||
async with wsm_maker.lock:
|
||||
cat_wallet_maker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wsm_maker, wallet_maker, {"identifier": "genesis_by_id"}, CAT_AMOUNT
|
||||
wsm_maker, wallet_maker, {"identifier": "genesis_by_id"}, CAT_AMOUNT, DEFAULT_TX_CONFIG
|
||||
)
|
||||
async with wsm_maker.lock:
|
||||
cat_wallet_taker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wsm_taker, wallet_taker, {"identifier": "genesis_by_id"}, CAT_AMOUNT
|
||||
wsm_taker, wallet_taker, {"identifier": "genesis_by_id"}, CAT_AMOUNT, DEFAULT_TX_CONFIG
|
||||
)
|
||||
cat_spend_bundle_maker = (
|
||||
await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet_maker.id())
|
||||
|
@ -1419,6 +1453,7 @@ async def test_complex_nft_offer(
|
|||
with pytest.raises(ValueError):
|
||||
await nft_wallet_maker.generate_new_nft(
|
||||
metadata,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_puzhash_maker,
|
||||
royalty_puzhash_maker,
|
||||
royalty_basis_pts_maker, # type: ignore
|
||||
|
@ -1428,6 +1463,7 @@ async def test_complex_nft_offer(
|
|||
else:
|
||||
sb_maker = await nft_wallet_maker.generate_new_nft(
|
||||
metadata,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_puzhash_maker,
|
||||
royalty_puzhash_maker,
|
||||
uint16(royalty_basis_pts_maker),
|
||||
|
@ -1436,6 +1472,7 @@ async def test_complex_nft_offer(
|
|||
|
||||
sb_taker_1 = await nft_wallet_taker.generate_new_nft(
|
||||
metadata,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_puzhash_taker,
|
||||
royalty_puzhash_taker,
|
||||
royalty_basis_pts_taker_1,
|
||||
|
@ -1460,6 +1497,7 @@ async def test_complex_nft_offer(
|
|||
# MAke one more NFT for the taker
|
||||
sb_taker_2 = await nft_wallet_taker.generate_new_nft(
|
||||
metadata,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_puzhash_taker,
|
||||
royalty_puzhash_taker,
|
||||
royalty_basis_pts_taker_2,
|
||||
|
@ -1526,7 +1564,7 @@ async def test_complex_nft_offer(
|
|||
)
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
complex_nft_offer, driver_dict=driver_dict, fee=FEE
|
||||
complex_nft_offer, DEFAULT_TX_CONFIG, driver_dict=driver_dict, fee=FEE
|
||||
)
|
||||
assert error is None
|
||||
assert success
|
||||
|
@ -1536,6 +1574,7 @@ async def test_complex_nft_offer(
|
|||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
wallet_node_taker.get_full_node_peer(),
|
||||
DEFAULT_TX_CONFIG,
|
||||
fee=FEE,
|
||||
)
|
||||
# all done for this test
|
||||
|
@ -1544,6 +1583,7 @@ async def test_complex_nft_offer(
|
|||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
wallet_node_taker.get_full_node_peer(),
|
||||
DEFAULT_TX_CONFIG,
|
||||
fee=FEE,
|
||||
)
|
||||
assert trade_take is not None
|
||||
|
@ -1648,7 +1688,7 @@ async def test_complex_nft_offer(
|
|||
)
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
complex_nft_offer, driver_dict=driver_dict, fee=uint64(0)
|
||||
complex_nft_offer, DEFAULT_TX_CONFIG, driver_dict=driver_dict, fee=uint64(0)
|
||||
)
|
||||
assert error is None
|
||||
assert success
|
||||
|
@ -1657,6 +1697,7 @@ async def test_complex_nft_offer(
|
|||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
wallet_node_taker.get_full_node_peer(),
|
||||
DEFAULT_TX_CONFIG,
|
||||
fee=uint64(0),
|
||||
)
|
||||
assert trade_take is not None
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
from secrets import token_bytes
|
||||
from typing import Any, Dict
|
||||
|
||||
|
@ -23,6 +24,7 @@ from chia.wallet.did_wallet.did_wallet import DIDWallet
|
|||
from chia.wallet.nft_wallet.nft_wallet import NFTWallet
|
||||
from chia.wallet.nft_wallet.uncurry_nft import UncurriedNFT
|
||||
from chia.wallet.util.address_type import AddressType
|
||||
from chia.wallet.util.tx_config import DEFAULT_COIN_SELECTION_CONFIG, DEFAULT_TX_CONFIG
|
||||
|
||||
|
||||
async def nft_count(wallet: NFTWallet) -> int:
|
||||
|
@ -110,7 +112,7 @@ async def test_nft_mint_from_did(self_hostname: str, two_wallet_nodes: Any, trus
|
|||
target_list = [(await wallet_1.get_new_puzzlehash()) for x in range(mint_total)]
|
||||
|
||||
sb = await nft_wallet_maker.mint_from_did(
|
||||
metadata_list, target_list=target_list, mint_number_start=1, mint_total=mint_total, fee=fee
|
||||
metadata_list, DEFAULT_TX_CONFIG, target_list=target_list, mint_number_start=1, mint_total=mint_total, fee=fee
|
||||
)
|
||||
|
||||
await api_0.push_tx({"spend_bundle": bytes(sb).hex()})
|
||||
|
@ -255,13 +257,17 @@ async def test_nft_mint_from_did_rpc(
|
|||
royalty_percentage = 300
|
||||
fee = 100
|
||||
required_amount = n + (fee * n)
|
||||
xch_coins = await client.select_coins(amount=required_amount, wallet_id=wallet_maker.id())
|
||||
xch_coins = await client.select_coins(
|
||||
amount=required_amount, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG, wallet_id=wallet_maker.id()
|
||||
)
|
||||
funding_coin = xch_coins[0]
|
||||
assert funding_coin.amount >= required_amount
|
||||
funding_coin_dict = xch_coins[0].to_json_dict()
|
||||
chunk = 5
|
||||
next_coin = funding_coin
|
||||
did_coin = (await client.select_coins(amount=1, wallet_id=2))[0]
|
||||
did_coin = (
|
||||
await client.select_coins(amount=1, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG, wallet_id=2)
|
||||
)[0]
|
||||
did_lineage_parent = None
|
||||
spends = []
|
||||
nft_ids = set([])
|
||||
|
@ -281,6 +287,7 @@ async def test_nft_mint_from_did_rpc(
|
|||
did_lineage_parent=did_lineage_parent,
|
||||
mint_from_did=True,
|
||||
fee=fee,
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
)
|
||||
assert resp["success"]
|
||||
sb: SpendBundle = SpendBundle.from_json_dict(resp["spend_bundle"])
|
||||
|
@ -439,13 +446,17 @@ async def test_nft_mint_from_did_rpc_no_royalties(
|
|||
royalty_address = None
|
||||
royalty_percentage = None
|
||||
required_amount = n
|
||||
xch_coins = await client.select_coins(amount=required_amount, wallet_id=wallet_maker.id())
|
||||
xch_coins = await client.select_coins(
|
||||
amount=required_amount, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG, wallet_id=wallet_maker.id()
|
||||
)
|
||||
funding_coin = xch_coins[0]
|
||||
assert funding_coin.amount >= required_amount
|
||||
funding_coin_dict = xch_coins[0].to_json_dict()
|
||||
chunk = 5
|
||||
next_coin = funding_coin
|
||||
did_coin = (await client.select_coins(amount=1, wallet_id=2))[0]
|
||||
did_coin = (
|
||||
await client.select_coins(amount=1, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG, wallet_id=2)
|
||||
)[0]
|
||||
did_lineage_parent = None
|
||||
spends = []
|
||||
|
||||
|
@ -464,6 +475,7 @@ async def test_nft_mint_from_did_rpc_no_royalties(
|
|||
did_coin=did_coin.to_json_dict(),
|
||||
did_lineage_parent=did_lineage_parent,
|
||||
mint_from_did=True,
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
)
|
||||
assert resp["success"]
|
||||
sb: SpendBundle = SpendBundle.from_json_dict(resp["spend_bundle"])
|
||||
|
@ -573,14 +585,20 @@ async def test_nft_mint_from_did_multiple_xch(self_hostname: str, two_wallet_nod
|
|||
]
|
||||
|
||||
# Grab two coins for testing that we can create a bulk minting with more than 1 xch coin
|
||||
xch_coins_1 = await wallet_maker.select_coins(amount=10000)
|
||||
xch_coins_2 = await wallet_maker.select_coins(amount=10000, exclude=xch_coins_1)
|
||||
xch_coins_1 = await wallet_maker.select_coins(amount=10000, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG)
|
||||
xch_coins_2 = await wallet_maker.select_coins(
|
||||
amount=10000,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_ids=[c.name() for c in xch_coins_1]
|
||||
),
|
||||
)
|
||||
xch_coins = xch_coins_1.union(xch_coins_2)
|
||||
|
||||
target_list = [ph_taker for x in range(mint_total)]
|
||||
|
||||
sb = await nft_wallet_maker.mint_from_did(
|
||||
metadata_list,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_list=target_list,
|
||||
mint_number_start=1,
|
||||
mint_total=mint_total,
|
||||
|
@ -682,7 +700,7 @@ async def test_nft_mint_from_xch(self_hostname: str, two_wallet_nodes: Any, trus
|
|||
target_list = [(await wallet_1.get_new_puzzlehash()) for x in range(mint_total)]
|
||||
|
||||
sb = await nft_wallet_maker.mint_from_xch(
|
||||
metadata_list, target_list=target_list, mint_number_start=1, mint_total=mint_total, fee=fee
|
||||
metadata_list, DEFAULT_TX_CONFIG, target_list=target_list, mint_number_start=1, mint_total=mint_total, fee=fee
|
||||
)
|
||||
|
||||
await api_0.push_tx({"spend_bundle": bytes(sb).hex()})
|
||||
|
@ -826,7 +844,9 @@ async def test_nft_mint_from_xch_rpc(
|
|||
royalty_percentage = 300
|
||||
fee = 100
|
||||
required_amount = n + (fee * n)
|
||||
xch_coins = await client.select_coins(amount=required_amount, wallet_id=wallet_maker.id())
|
||||
xch_coins = await client.select_coins(
|
||||
amount=required_amount, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG, wallet_id=wallet_maker.id()
|
||||
)
|
||||
funding_coin = xch_coins[0]
|
||||
assert funding_coin.amount >= required_amount
|
||||
funding_coin_dict = xch_coins[0].to_json_dict()
|
||||
|
@ -848,6 +868,7 @@ async def test_nft_mint_from_xch_rpc(
|
|||
xch_change_target=funding_coin_dict["puzzle_hash"],
|
||||
mint_from_did=False,
|
||||
fee=fee,
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
)
|
||||
assert resp["success"]
|
||||
sb: SpendBundle = SpendBundle.from_json_dict(resp["spend_bundle"])
|
||||
|
@ -971,14 +992,20 @@ async def test_nft_mint_from_xch_multiple_xch(self_hostname: str, two_wallet_nod
|
|||
]
|
||||
|
||||
# Grab two coins for testing that we can create a bulk minting with more than 1 xch coin
|
||||
xch_coins_1 = await wallet_maker.select_coins(amount=10000)
|
||||
xch_coins_2 = await wallet_maker.select_coins(amount=10000, exclude=xch_coins_1)
|
||||
xch_coins_1 = await wallet_maker.select_coins(amount=10000, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG)
|
||||
xch_coins_2 = await wallet_maker.select_coins(
|
||||
amount=10000,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_ids=[c.name() for c in xch_coins_1]
|
||||
),
|
||||
)
|
||||
xch_coins = xch_coins_1.union(xch_coins_2)
|
||||
|
||||
target_list = [ph_taker for x in range(mint_total)]
|
||||
|
||||
sb = await nft_wallet_maker.mint_from_xch(
|
||||
metadata_list,
|
||||
DEFAULT_TX_CONFIG,
|
||||
target_list=target_list,
|
||||
mint_number_start=1,
|
||||
mint_total=mint_total,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import sys
|
||||
from secrets import token_bytes
|
||||
from typing import Any, Dict, Optional
|
||||
|
@ -22,6 +23,7 @@ from chia.wallet.trading.offer import Offer
|
|||
from chia.wallet.trading.trade_status import TradeStatus
|
||||
from chia.wallet.uncurried_puzzle import uncurry_puzzle
|
||||
from chia.wallet.util.debug_spend_bundle import disassemble
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from tests.wallet.nft_wallet.test_nft_1_offers import mempool_not_empty
|
||||
|
||||
|
||||
|
@ -31,16 +33,14 @@ async def get_trade_and_status(trade_manager, trade) -> TradeStatus: # type: ig
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"trusted",
|
||||
[False],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"forwards_compat",
|
||||
[True, False],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"reuse_puzhash",
|
||||
[True, False],
|
||||
"trusted,forwards_compat,reuse_puzhash",
|
||||
[
|
||||
[True, True, False],
|
||||
[True, False, True],
|
||||
[True, False, False],
|
||||
[False, False, True],
|
||||
[False, False, False],
|
||||
],
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_nft_offer_with_fee(
|
||||
|
@ -54,6 +54,8 @@ async def test_nft_offer_with_fee(
|
|||
wallet_maker = wallet_node_0.wallet_state_manager.main_wallet
|
||||
wallet_taker = wallet_node_1.wallet_state_manager.main_wallet
|
||||
|
||||
tx_config = dataclasses.replace(DEFAULT_TX_CONFIG, reuse_puzhash=reuse_puzhash)
|
||||
|
||||
maker_ph = await wallet_maker.get_new_puzzlehash()
|
||||
taker_ph = await wallet_taker.get_new_puzzlehash()
|
||||
token_ph = bytes32(token_bytes())
|
||||
|
@ -103,7 +105,7 @@ async def test_nft_offer_with_fee(
|
|||
]
|
||||
)
|
||||
|
||||
sb = await nft_wallet_maker.generate_new_nft(metadata)
|
||||
sb = await nft_wallet_maker.generate_new_nft(metadata, tx_config)
|
||||
assert sb
|
||||
await time_out_assert_not_none(20, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name())
|
||||
|
||||
|
@ -147,7 +149,7 @@ async def test_nft_offer_with_fee(
|
|||
)
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_nft_for_xch, driver_dict, fee=maker_fee, reuse_puzhash=reuse_puzhash
|
||||
offer_nft_for_xch, tx_config, driver_dict, fee=maker_fee
|
||||
)
|
||||
assert success is True
|
||||
assert error is None
|
||||
|
@ -159,8 +161,8 @@ async def test_nft_offer_with_fee(
|
|||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
tx_config,
|
||||
fee=taker_fee,
|
||||
reuse_puzhash=reuse_puzhash and not forwards_compat,
|
||||
)
|
||||
assert trade_take is not None
|
||||
assert tx_records is not None
|
||||
|
@ -242,7 +244,7 @@ async def test_nft_offer_with_fee(
|
|||
)
|
||||
else:
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_xch_for_nft, driver_dict_to_buy, fee=maker_fee
|
||||
offer_xch_for_nft, tx_config, driver_dict_to_buy, fee=maker_fee
|
||||
)
|
||||
assert success is True
|
||||
assert error is None
|
||||
|
@ -251,7 +253,7 @@ async def test_nft_offer_with_fee(
|
|||
taker_fee = uint64(1)
|
||||
|
||||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer), peer, fee=taker_fee
|
||||
old_maker_offer if forwards_compat else Offer.from_bytes(trade_make.offer), peer, tx_config, fee=taker_fee
|
||||
)
|
||||
|
||||
assert trade_take is not None
|
||||
|
@ -332,7 +334,7 @@ async def test_nft_offer_cancellations(self_hostname: str, two_wallet_nodes: Any
|
|||
]
|
||||
)
|
||||
|
||||
sb = await nft_wallet_maker.generate_new_nft(metadata)
|
||||
sb = await nft_wallet_maker.generate_new_nft(metadata, DEFAULT_TX_CONFIG)
|
||||
assert sb
|
||||
await time_out_assert_not_none(20, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name())
|
||||
|
||||
|
@ -355,7 +357,7 @@ async def test_nft_offer_cancellations(self_hostname: str, two_wallet_nodes: Any
|
|||
offer_nft_for_xch = {wallet_maker.id(): xch_request, nft_asset_id: -1}
|
||||
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_nft_for_xch, driver_dict, fee=maker_fee
|
||||
offer_nft_for_xch, DEFAULT_TX_CONFIG, driver_dict, fee=maker_fee
|
||||
)
|
||||
assert success is True
|
||||
assert error is None
|
||||
|
@ -366,7 +368,7 @@ async def test_nft_offer_cancellations(self_hostname: str, two_wallet_nodes: Any
|
|||
|
||||
cancel_fee = uint64(10)
|
||||
|
||||
txs = await trade_manager_maker.cancel_pending_offer_safely(trade_make.trade_id, fee=cancel_fee)
|
||||
txs = await trade_manager_maker.cancel_pending_offer_safely(trade_make.trade_id, DEFAULT_TX_CONFIG, fee=cancel_fee)
|
||||
|
||||
await time_out_assert(20, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make)
|
||||
await full_node_api.process_transaction_records(records=txs)
|
||||
|
@ -445,7 +447,7 @@ async def test_nft_offer_with_metadata_update(self_hostname: str, two_wallet_nod
|
|||
]
|
||||
)
|
||||
|
||||
sb = await nft_wallet_maker.generate_new_nft(metadata)
|
||||
sb = await nft_wallet_maker.generate_new_nft(metadata, DEFAULT_TX_CONFIG)
|
||||
assert sb
|
||||
await time_out_assert_not_none(20, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name())
|
||||
|
||||
|
@ -460,7 +462,9 @@ async def test_nft_offer_with_metadata_update(self_hostname: str, two_wallet_nod
|
|||
url_to_add = "https://new_url.com"
|
||||
key = "mu"
|
||||
fee_for_update = uint64(10)
|
||||
update_sb = await nft_wallet_maker.update_metadata(nft_to_update, key, url_to_add, fee=fee_for_update)
|
||||
update_sb = await nft_wallet_maker.update_metadata(
|
||||
nft_to_update, key, url_to_add, DEFAULT_TX_CONFIG, fee=fee_for_update
|
||||
)
|
||||
mempool_mgr = full_node_api.full_node.mempool_manager
|
||||
await time_out_assert_not_none(20, mempool_mgr.get_spendbundle, update_sb.name()) # type: ignore
|
||||
|
||||
|
@ -487,7 +491,7 @@ async def test_nft_offer_with_metadata_update(self_hostname: str, two_wallet_nod
|
|||
offer_nft_for_xch = {wallet_maker.id(): xch_request, nft_asset_id: -1}
|
||||
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_nft_for_xch, driver_dict, fee=maker_fee
|
||||
offer_nft_for_xch, DEFAULT_TX_CONFIG, driver_dict, fee=maker_fee
|
||||
)
|
||||
assert success is True
|
||||
assert error is None
|
||||
|
@ -497,7 +501,7 @@ async def test_nft_offer_with_metadata_update(self_hostname: str, two_wallet_nod
|
|||
|
||||
peer = wallet_node_1.get_full_node_peer()
|
||||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
Offer.from_bytes(trade_make.offer), peer, fee=taker_fee
|
||||
Offer.from_bytes(trade_make.offer), peer, DEFAULT_TX_CONFIG, fee=taker_fee
|
||||
)
|
||||
|
||||
assert trade_take is not None
|
||||
|
@ -568,6 +572,8 @@ async def test_nft_offer_nft_for_cat(
|
|||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(token_ph))
|
||||
await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20)
|
||||
|
||||
tx_config = dataclasses.replace(DEFAULT_TX_CONFIG, reuse_puzhash=reuse_puzhash)
|
||||
|
||||
# Create NFT wallets and nfts for maker and taker
|
||||
nft_wallet_maker = await NFTWallet.create_new_nft_wallet(
|
||||
wallet_node_0.wallet_state_manager, wallet_maker, name="NFT WALLET 1"
|
||||
|
@ -587,7 +593,7 @@ async def test_nft_offer_nft_for_cat(
|
|||
]
|
||||
)
|
||||
|
||||
sb = await nft_wallet_maker.generate_new_nft(metadata)
|
||||
sb = await nft_wallet_maker.generate_new_nft(metadata, tx_config)
|
||||
assert sb
|
||||
await time_out_assert_not_none(20, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name())
|
||||
|
||||
|
@ -601,7 +607,11 @@ async def test_nft_offer_nft_for_cat(
|
|||
cats_to_mint = 10000
|
||||
async with wallet_node_0.wallet_state_manager.lock:
|
||||
cat_wallet_maker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node_0.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, uint64(cats_to_mint)
|
||||
wallet_node_0.wallet_state_manager,
|
||||
wallet_maker,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(cats_to_mint),
|
||||
tx_config,
|
||||
)
|
||||
await time_out_assert(20, mempool_not_empty, True, full_node_api)
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(token_ph))
|
||||
|
@ -609,7 +619,11 @@ async def test_nft_offer_nft_for_cat(
|
|||
|
||||
async with wallet_node_1.wallet_state_manager.lock:
|
||||
cat_wallet_taker: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node_1.wallet_state_manager, wallet_taker, {"identifier": "genesis_by_id"}, uint64(cats_to_mint)
|
||||
wallet_node_1.wallet_state_manager,
|
||||
wallet_taker,
|
||||
{"identifier": "genesis_by_id"},
|
||||
uint64(cats_to_mint),
|
||||
tx_config,
|
||||
)
|
||||
await time_out_assert(20, mempool_not_empty, True, full_node_api)
|
||||
|
||||
|
@ -652,7 +666,7 @@ async def test_nft_offer_nft_for_cat(
|
|||
).index
|
||||
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_nft_for_cat, driver_dict, fee=maker_fee, reuse_puzhash=reuse_puzhash
|
||||
offer_nft_for_cat, tx_config, driver_dict, fee=maker_fee
|
||||
)
|
||||
assert success is True
|
||||
assert error is None
|
||||
|
@ -664,8 +678,8 @@ async def test_nft_offer_nft_for_cat(
|
|||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
Offer.from_bytes(trade_make.offer),
|
||||
peer,
|
||||
tx_config,
|
||||
fee=taker_fee,
|
||||
reuse_puzhash=reuse_puzhash,
|
||||
)
|
||||
|
||||
assert trade_take is not None
|
||||
|
@ -736,7 +750,7 @@ async def test_nft_offer_nft_for_cat(
|
|||
}
|
||||
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_multi_cats_for_nft, driver_dict_to_buy, fee=maker_fee
|
||||
offer_multi_cats_for_nft, tx_config, driver_dict_to_buy, fee=maker_fee
|
||||
)
|
||||
assert success is True
|
||||
assert error is None
|
||||
|
@ -745,7 +759,7 @@ async def test_nft_offer_nft_for_cat(
|
|||
taker_fee = uint64(1)
|
||||
|
||||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
Offer.from_bytes(trade_make.offer), peer, fee=taker_fee
|
||||
Offer.from_bytes(trade_make.offer), peer, tx_config, fee=taker_fee
|
||||
)
|
||||
|
||||
assert trade_take is not None
|
||||
|
@ -833,7 +847,7 @@ async def test_nft_offer_nft_for_nft(self_hostname: str, two_wallet_nodes: Any,
|
|||
]
|
||||
)
|
||||
|
||||
sb = await nft_wallet_maker.generate_new_nft(metadata)
|
||||
sb = await nft_wallet_maker.generate_new_nft(metadata, DEFAULT_TX_CONFIG)
|
||||
assert sb
|
||||
await time_out_assert_not_none(20, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name())
|
||||
|
||||
|
@ -843,7 +857,7 @@ async def test_nft_offer_nft_for_nft(self_hostname: str, two_wallet_nodes: Any,
|
|||
("h", "0xD4584AD463139FA8C0D9F68F4B59F183"),
|
||||
]
|
||||
)
|
||||
sb_2 = await nft_wallet_taker.generate_new_nft(metadata_2)
|
||||
sb_2 = await nft_wallet_taker.generate_new_nft(metadata_2, DEFAULT_TX_CONFIG)
|
||||
assert sb_2
|
||||
await time_out_assert_not_none(20, full_node_api.full_node.mempool_manager.get_spendbundle, sb_2.name())
|
||||
|
||||
|
@ -875,7 +889,7 @@ async def test_nft_offer_nft_for_nft(self_hostname: str, two_wallet_nodes: Any,
|
|||
offer_nft_for_nft = {nft_to_take_asset_id: 1, nft_to_offer_asset_id: -1}
|
||||
|
||||
success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
|
||||
offer_nft_for_nft, driver_dict, fee=maker_fee
|
||||
offer_nft_for_nft, DEFAULT_TX_CONFIG, driver_dict, fee=maker_fee
|
||||
)
|
||||
assert success is True
|
||||
assert error is None
|
||||
|
@ -885,7 +899,7 @@ async def test_nft_offer_nft_for_nft(self_hostname: str, two_wallet_nodes: Any,
|
|||
|
||||
peer = wallet_node_1.get_full_node_peer()
|
||||
trade_take, tx_records = await trade_manager_taker.respond_to_offer(
|
||||
Offer.from_bytes(trade_make.offer), peer, fee=taker_fee
|
||||
Offer.from_bytes(trade_make.offer), peer, DEFAULT_TX_CONFIG, fee=taker_fee
|
||||
)
|
||||
|
||||
assert trade_take is not None
|
||||
|
|
|
@ -24,6 +24,7 @@ from chia.wallet.did_wallet.did_wallet import DIDWallet
|
|||
from chia.wallet.nft_wallet.nft_wallet import NFTWallet
|
||||
from chia.wallet.util.address_type import AddressType
|
||||
from chia.wallet.util.compute_memos import compute_memos
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet import CHIP_0002_SIGN_MESSAGE_PREFIX
|
||||
from chia.wallet.wallet_state_manager import WalletStateManager
|
||||
|
@ -132,7 +133,7 @@ async def test_nft_wallet_creation_automatically(self_hostname: str, two_wallet_
|
|||
]
|
||||
)
|
||||
|
||||
sb = await nft_wallet_0.generate_new_nft(metadata)
|
||||
sb = await nft_wallet_0.generate_new_nft(metadata, DEFAULT_TX_CONFIG)
|
||||
assert sb
|
||||
await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name())
|
||||
|
||||
|
@ -143,7 +144,9 @@ async def test_nft_wallet_creation_automatically(self_hostname: str, two_wallet_
|
|||
coins = await nft_wallet_0.get_current_nfts()
|
||||
assert len(coins) == 1, "nft not generated"
|
||||
|
||||
txs = await nft_wallet_0.generate_signed_transaction([uint64(coins[0].coin.amount)], [ph1], coins={coins[0].coin})
|
||||
txs = await nft_wallet_0.generate_signed_transaction(
|
||||
[uint64(coins[0].coin.amount)], [ph1], DEFAULT_TX_CONFIG, coins={coins[0].coin}
|
||||
)
|
||||
assert len(txs) == 1
|
||||
assert txs[0].spend_bundle is not None
|
||||
await wallet_node_0.wallet_state_manager.add_pending_transaction(txs[0])
|
||||
|
@ -227,7 +230,7 @@ async def test_nft_wallet_creation_and_transfer(self_hostname: str, two_wallet_n
|
|||
|
||||
await time_out_assert(30, wallet_0.get_unconfirmed_balance, 2000000000000)
|
||||
await time_out_assert(30, wallet_0.get_confirmed_balance, 2000000000000)
|
||||
sb = await nft_wallet_0.generate_new_nft(metadata)
|
||||
sb = await nft_wallet_0.generate_new_nft(metadata, DEFAULT_TX_CONFIG)
|
||||
assert sb
|
||||
# ensure hints are generated
|
||||
assert compute_memos(sb)
|
||||
|
@ -261,7 +264,7 @@ async def test_nft_wallet_creation_and_transfer(self_hostname: str, two_wallet_n
|
|||
await time_out_assert(10, wallet_0.get_unconfirmed_balance, 4000000000000 - 1)
|
||||
await time_out_assert(10, wallet_0.get_confirmed_balance, 4000000000000)
|
||||
|
||||
sb = await nft_wallet_0.generate_new_nft(metadata)
|
||||
sb = await nft_wallet_0.generate_new_nft(metadata, DEFAULT_TX_CONFIG)
|
||||
assert sb
|
||||
# ensure hints are generated
|
||||
assert compute_memos(sb)
|
||||
|
@ -278,7 +281,9 @@ async def test_nft_wallet_creation_and_transfer(self_hostname: str, two_wallet_n
|
|||
nft_wallet_1 = await NFTWallet.create_new_nft_wallet(
|
||||
wallet_node_1.wallet_state_manager, wallet_1, name="NFT WALLET 2"
|
||||
)
|
||||
txs = await nft_wallet_0.generate_signed_transaction([uint64(coins[1].coin.amount)], [ph1], coins={coins[1].coin})
|
||||
txs = await nft_wallet_0.generate_signed_transaction(
|
||||
[uint64(coins[1].coin.amount)], [ph1], DEFAULT_TX_CONFIG, coins={coins[1].coin}
|
||||
)
|
||||
assert len(txs) == 1
|
||||
assert txs[0].spend_bundle is not None
|
||||
await wallet_node_0.wallet_state_manager.add_pending_transaction(txs[0])
|
||||
|
@ -298,7 +303,9 @@ async def test_nft_wallet_creation_and_transfer(self_hostname: str, two_wallet_n
|
|||
await time_out_assert(30, wallet_1.get_pending_change_balance, 0)
|
||||
|
||||
# Send it back to original owner
|
||||
txs = await nft_wallet_1.generate_signed_transaction([uint64(coins[0].coin.amount)], [ph], coins={coins[0].coin})
|
||||
txs = await nft_wallet_1.generate_signed_transaction(
|
||||
[uint64(coins[0].coin.amount)], [ph], DEFAULT_TX_CONFIG, coins={coins[0].coin}
|
||||
)
|
||||
assert len(txs) == 1
|
||||
assert txs[0].spend_bundle is not None
|
||||
await wallet_node_1.wallet_state_manager.add_pending_transaction(txs[0])
|
||||
|
@ -988,7 +995,7 @@ async def test_nft_transfer_nft_with_did(self_hostname: str, two_wallet_nodes: A
|
|||
assert len(wallet_1.wallet_state_manager.wallets) == 1, "NFT wallet shouldn't exist yet"
|
||||
assert len(wallet_0.wallet_state_manager.wallets) == 3
|
||||
# transfer DID to the other wallet
|
||||
tx = await did_wallet.transfer_did(ph1, uint64(0), True)
|
||||
tx = await did_wallet.transfer_did(ph1, uint64(0), True, DEFAULT_TX_CONFIG)
|
||||
assert tx
|
||||
for i in range(1, num_blocks):
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph1))
|
||||
|
|
|
@ -53,6 +53,7 @@ from chia.wallet.util.address_type import AddressType
|
|||
from chia.wallet.util.compute_memos import compute_memos
|
||||
from chia.wallet.util.query_filter import AmountFilter, HashFilter, TransactionTypeFilter
|
||||
from chia.wallet.util.transaction_type import TransactionType
|
||||
from chia.wallet.util.tx_config import DEFAULT_COIN_SELECTION_CONFIG, DEFAULT_TX_CONFIG
|
||||
from chia.wallet.util.wallet_types import CoinType, WalletType
|
||||
from chia.wallet.wallet import Wallet
|
||||
from chia.wallet.wallet_coin_record import WalletCoinRecord
|
||||
|
@ -302,7 +303,7 @@ async def test_send_transaction(wallet_rpc_environment: WalletRpcTestEnvironment
|
|||
addr = encode_puzzle_hash(await wallet_2.get_new_puzzlehash(), "txch")
|
||||
tx_amount = uint64(15600000)
|
||||
with pytest.raises(ValueError):
|
||||
await client.send_transaction(1, uint64(100000000000000001), addr)
|
||||
await client.send_transaction(1, uint64(100000000000000001), addr, DEFAULT_TX_CONFIG)
|
||||
|
||||
# Tests sending a basic transaction
|
||||
tx = await client.send_transaction(
|
||||
|
@ -310,8 +311,14 @@ async def test_send_transaction(wallet_rpc_environment: WalletRpcTestEnvironment
|
|||
tx_amount,
|
||||
addr,
|
||||
memos=["this is a basic tx"],
|
||||
excluded_amounts=[uint64(250000000000)],
|
||||
excluded_coin_ids=[bytes32([0] * 32).hex()],
|
||||
tx_config=dataclasses.replace(
|
||||
DEFAULT_TX_CONFIG,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
excluded_coin_amounts=[uint64(250000000000)],
|
||||
excluded_coin_ids=[bytes32([0] * 32)],
|
||||
),
|
||||
),
|
||||
)
|
||||
transaction_id = tx.name
|
||||
|
||||
|
@ -348,6 +355,7 @@ async def test_push_transactions(wallet_rpc_environment: WalletRpcTestEnvironmen
|
|||
|
||||
tx = await client.create_signed_transaction(
|
||||
outputs,
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
fee=uint64(100),
|
||||
)
|
||||
|
||||
|
@ -371,7 +379,7 @@ async def test_get_balance(wallet_rpc_environment: WalletRpcTestEnvironment):
|
|||
await full_node_api.farm_blocks_to_wallet(2, wallet)
|
||||
async with wallet_node.wallet_state_manager.lock:
|
||||
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
||||
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
||||
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100), DEFAULT_TX_CONFIG
|
||||
)
|
||||
await assert_get_balance(wallet_rpc_client, wallet_node, wallet)
|
||||
await assert_get_balance(wallet_rpc_client, wallet_node, cat_wallet)
|
||||
|
@ -413,6 +421,7 @@ async def test_get_farmed_amount_with_fee(wallet_rpc_environment: WalletRpcTestE
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
amount=uint64(5),
|
||||
puzzle_hash=bytes32([0] * 32),
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
fee=uint64(fee_amount),
|
||||
)
|
||||
await wallet.push_transaction(tx)
|
||||
|
@ -498,7 +507,9 @@ async def test_create_signed_transaction(
|
|||
|
||||
selected_coin = None
|
||||
if select_coin:
|
||||
selected_coin = await wallet_1_rpc.select_coins(amount=amount_total, wallet_id=wallet_id)
|
||||
selected_coin = await wallet_1_rpc.select_coins(
|
||||
amount=amount_total, wallet_id=wallet_id, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG
|
||||
)
|
||||
assert len(selected_coin) == 1
|
||||
|
||||
tx = await wallet_1_rpc.create_signed_transaction(
|
||||
|
@ -507,7 +518,13 @@ async def test_create_signed_transaction(
|
|||
fee=amount_fee,
|
||||
wallet_id=wallet_id,
|
||||
# shouldn't actually block it
|
||||
excluded_amounts=[uint64(selected_coin[0].amount)] if selected_coin is not None else [],
|
||||
tx_config=dataclasses.replace(
|
||||
DEFAULT_TX_CONFIG,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
excluded_coin_amounts=[uint64(selected_coin[0].amount)] if selected_coin is not None else [],
|
||||
),
|
||||
),
|
||||
)
|
||||
change_expected = not selected_coin or selected_coin[0].amount - amount_total > 0
|
||||
assert_tx_amounts(tx, outputs, amount_fee=amount_fee, change_expected=change_expected, is_cat=is_cat)
|
||||
|
@ -563,7 +580,7 @@ async def test_create_signed_transaction_with_coin_announcement(wallet_rpc_envir
|
|||
]
|
||||
outputs = await create_tx_outputs(wallet_2, [(signed_tx_amount, None)])
|
||||
tx_res: TransactionRecord = await client.create_signed_transaction(
|
||||
outputs, coin_announcements=tx_coin_announcements
|
||||
outputs, tx_config=DEFAULT_TX_CONFIG, coin_announcements=tx_coin_announcements
|
||||
)
|
||||
assert_tx_amounts(tx_res, outputs, amount_fee=uint64(0), change_expected=True)
|
||||
await assert_push_tx_error(client_node, tx_res)
|
||||
|
@ -593,7 +610,9 @@ async def test_create_signed_transaction_with_puzzle_announcement(wallet_rpc_env
|
|||
),
|
||||
]
|
||||
outputs = await create_tx_outputs(wallet_2, [(signed_tx_amount, None)])
|
||||
tx_res = await client.create_signed_transaction(outputs, puzzle_announcements=tx_puzzle_announcements)
|
||||
tx_res = await client.create_signed_transaction(
|
||||
outputs, tx_config=DEFAULT_TX_CONFIG, puzzle_announcements=tx_puzzle_announcements
|
||||
)
|
||||
assert_tx_amounts(tx_res, outputs, amount_fee=uint64(0), change_expected=True)
|
||||
await assert_push_tx_error(client_node, tx_res)
|
||||
|
||||
|
@ -608,11 +627,21 @@ async def test_create_signed_transaction_with_excluded_coins(wallet_rpc_environm
|
|||
await generate_funds(full_node_api, env.wallet_1)
|
||||
|
||||
async def it_does_not_include_the_excluded_coins() -> None:
|
||||
selected_coins = await wallet_1_rpc.select_coins(amount=250000000000, wallet_id=1)
|
||||
selected_coins = await wallet_1_rpc.select_coins(
|
||||
amount=250000000000, wallet_id=1, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG
|
||||
)
|
||||
assert len(selected_coins) == 1
|
||||
outputs = await create_tx_outputs(wallet_1, [(uint64(250000000000), None)])
|
||||
|
||||
tx = await wallet_1_rpc.create_signed_transaction(outputs, excluded_coins=selected_coins)
|
||||
tx = await wallet_1_rpc.create_signed_transaction(
|
||||
outputs,
|
||||
dataclasses.replace(
|
||||
DEFAULT_TX_CONFIG,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_ids=[c.name() for c in selected_coins]
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
assert len(tx.removals) == 1
|
||||
assert tx.removals[0] != selected_coins[0]
|
||||
|
@ -620,12 +649,22 @@ async def test_create_signed_transaction_with_excluded_coins(wallet_rpc_environm
|
|||
await assert_push_tx_error(full_node_rpc, tx)
|
||||
|
||||
async def it_throws_an_error_when_all_spendable_coins_are_excluded() -> None:
|
||||
selected_coins = await wallet_1_rpc.select_coins(amount=1750000000000, wallet_id=1)
|
||||
selected_coins = await wallet_1_rpc.select_coins(
|
||||
amount=1750000000000, wallet_id=1, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG
|
||||
)
|
||||
assert len(selected_coins) == 1
|
||||
outputs = await create_tx_outputs(wallet_1, [(uint64(1750000000000), None)])
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
await wallet_1_rpc.create_signed_transaction(outputs, excluded_coins=selected_coins)
|
||||
await wallet_1_rpc.create_signed_transaction(
|
||||
outputs,
|
||||
dataclasses.replace(
|
||||
DEFAULT_TX_CONFIG,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_ids=[c.name() for c in selected_coins]
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
await it_does_not_include_the_excluded_coins()
|
||||
await it_throws_an_error_when_all_spendable_coins_are_excluded()
|
||||
|
@ -652,6 +691,7 @@ async def test_spend_clawback_coins(wallet_rpc_environment: WalletRpcTestEnviron
|
|||
wallet_id=1,
|
||||
amount=uint64(500),
|
||||
address=encode_puzzle_hash(wallet_2_puzhash, "txch"),
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
fee=uint64(0),
|
||||
puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 5}],
|
||||
)
|
||||
|
@ -662,6 +702,7 @@ async def test_spend_clawback_coins(wallet_rpc_environment: WalletRpcTestEnviron
|
|||
wallet_id=1,
|
||||
amount=uint64(500),
|
||||
address=encode_puzzle_hash(wallet_1_puzhash, "txch"),
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
fee=uint64(0),
|
||||
puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 5}],
|
||||
)
|
||||
|
@ -744,7 +785,9 @@ async def test_send_transaction_multi(wallet_rpc_environment: WalletRpcTestEnvir
|
|||
|
||||
generated_funds = await generate_funds(full_node_api, env.wallet_1)
|
||||
|
||||
removals = await client.select_coins(1750000000000, wallet_id=1) # we want a coin that won't be selected by default
|
||||
removals = await client.select_coins(
|
||||
1750000000000, wallet_id=1, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG
|
||||
) # we want a coin that won't be selected by default
|
||||
outputs = await create_tx_outputs(wallet_2, [(uint64(1), ["memo_1"]), (uint64(2), ["memo_2"])])
|
||||
amount_outputs = sum(output["amount"] for output in outputs)
|
||||
amount_fee = uint64(amount_outputs + 1)
|
||||
|
@ -752,6 +795,7 @@ async def test_send_transaction_multi(wallet_rpc_environment: WalletRpcTestEnvir
|
|||
send_tx_res: TransactionRecord = await client.send_transaction_multi(
|
||||
1,
|
||||
outputs,
|
||||
DEFAULT_TX_CONFIG,
|
||||
coins=removals,
|
||||
fee=amount_fee,
|
||||
)
|
||||
|
@ -806,7 +850,7 @@ async def test_get_transactions(wallet_rpc_environment: WalletRpcTestEnvironment
|
|||
|
||||
# Test RELEVANCE
|
||||
await client.send_transaction(
|
||||
1, uint64(1), encode_puzzle_hash(await wallet.get_new_puzzlehash(), "txch")
|
||||
1, uint64(1), encode_puzzle_hash(await wallet.get_new_puzzlehash(), "txch"), DEFAULT_TX_CONFIG
|
||||
) # Create a pending tx
|
||||
|
||||
all_transactions = await client.get_transactions(1, sort_key=SortKey.RELEVANCE)
|
||||
|
@ -823,7 +867,7 @@ async def test_get_transactions(wallet_rpc_environment: WalletRpcTestEnvironment
|
|||
|
||||
# Test get_transactions to address
|
||||
ph_by_addr = await wallet.get_new_puzzlehash()
|
||||
await client.send_transaction(1, uint64(1), encode_puzzle_hash(ph_by_addr, "txch"))
|
||||
await client.send_transaction(1, uint64(1), encode_puzzle_hash(ph_by_addr, "txch"), DEFAULT_TX_CONFIG)
|
||||
await client.farm_block(encode_puzzle_hash(ph_by_addr, "txch"))
|
||||
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20)
|
||||
tx_for_address = await client.get_transactions(1, to_address=encode_puzzle_hash(ph_by_addr, "txch"))
|
||||
|
@ -965,14 +1009,20 @@ async def test_cat_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment):
|
|||
with pytest.raises(ValueError):
|
||||
await client.cat_spend(
|
||||
cat_0_id,
|
||||
dataclasses.replace(
|
||||
DEFAULT_TX_CONFIG,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
excluded_coin_amounts=[uint64(20)],
|
||||
excluded_coin_ids=[bytes32([0] * 32)],
|
||||
),
|
||||
),
|
||||
uint64(4),
|
||||
addr_1,
|
||||
uint64(0),
|
||||
["the cat memo"],
|
||||
excluded_amounts=[uint64(20)],
|
||||
excluded_coin_ids=[bytes32([0] * 32).hex()],
|
||||
)
|
||||
tx_res = await client.cat_spend(cat_0_id, uint64(4), addr_1, uint64(0), ["the cat memo"])
|
||||
tx_res = await client.cat_spend(cat_0_id, DEFAULT_TX_CONFIG, uint64(4), addr_1, uint64(0), ["the cat memo"])
|
||||
assert tx_res.wallet_id == cat_0_id
|
||||
spend_bundle = tx_res.spend_bundle
|
||||
assert spend_bundle is not None
|
||||
|
@ -982,7 +1032,7 @@ async def test_cat_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment):
|
|||
await farm_transaction_block(full_node_api, wallet_node)
|
||||
|
||||
# Test CAT spend with a fee
|
||||
tx_res = await client.cat_spend(cat_0_id, uint64(1), addr_1, uint64(5_000_000), ["the cat memo"])
|
||||
tx_res = await client.cat_spend(cat_0_id, DEFAULT_TX_CONFIG, uint64(1), addr_1, uint64(5_000_000), ["the cat memo"])
|
||||
assert tx_res.wallet_id == cat_0_id
|
||||
spend_bundle = tx_res.spend_bundle
|
||||
assert spend_bundle is not None
|
||||
|
@ -990,8 +1040,12 @@ async def test_cat_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment):
|
|||
await farm_transaction(full_node_api, wallet_node, spend_bundle)
|
||||
|
||||
# Test CAT spend with a fee and pre-specified removals / coins
|
||||
removals = await client.select_coins(amount=uint64(2), wallet_id=cat_0_id)
|
||||
tx_res = await client.cat_spend(cat_0_id, uint64(1), addr_1, uint64(5_000_000), ["the cat memo"], removals=removals)
|
||||
removals = await client.select_coins(
|
||||
amount=uint64(2), wallet_id=cat_0_id, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG
|
||||
)
|
||||
tx_res = await client.cat_spend(
|
||||
cat_0_id, DEFAULT_TX_CONFIG, uint64(1), addr_1, uint64(5_000_000), ["the cat memo"], removals=removals
|
||||
)
|
||||
assert tx_res.wallet_id == cat_0_id
|
||||
spend_bundle = tx_res.spend_bundle
|
||||
assert spend_bundle is not None
|
||||
|
@ -1010,7 +1064,9 @@ async def test_cat_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment):
|
|||
await time_out_assert(20, get_confirmed_balance, 6, client_2, cat_1_id)
|
||||
|
||||
# Test CAT coin selection
|
||||
selected_coins = await client.select_coins(amount=1, wallet_id=cat_0_id)
|
||||
selected_coins = await client.select_coins(
|
||||
amount=1, wallet_id=cat_0_id, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG
|
||||
)
|
||||
assert len(selected_coins) > 0
|
||||
|
||||
|
||||
|
@ -1041,7 +1097,9 @@ async def test_offer_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment)
|
|||
await wallet_2_rpc.create_wallet_for_existing_cat(cat_asset_id)
|
||||
wallet_2_address = await wallet_2_rpc.get_next_address(cat_wallet_id, False)
|
||||
adds = [{"puzzle_hash": decode_puzzle_hash(wallet_2_address), "amount": uint64(4), "memos": ["the cat memo"]}]
|
||||
tx_res = await wallet_1_rpc.send_transaction_multi(cat_wallet_id, additions=adds, fee=uint64(0))
|
||||
tx_res = await wallet_1_rpc.send_transaction_multi(
|
||||
cat_wallet_id, additions=adds, tx_config=DEFAULT_TX_CONFIG, fee=uint64(0)
|
||||
)
|
||||
spend_bundle = tx_res.spend_bundle
|
||||
assert spend_bundle is not None
|
||||
await farm_transaction(full_node_api, wallet_node, spend_bundle)
|
||||
|
@ -1055,7 +1113,7 @@ async def test_offer_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment)
|
|||
await wallet_1_rpc.get_coin_records_by_names([a.name() for a in spend_bundle.additions() if a.amount == 4])
|
||||
# Create an offer of 5 chia for one CAT
|
||||
offer, trade_record = await wallet_1_rpc.create_offer_for_ids(
|
||||
{uint32(1): -5, cat_asset_id.hex(): 1}, validate_only=True
|
||||
{uint32(1): -5, cat_asset_id.hex(): 1}, DEFAULT_TX_CONFIG, validate_only=True
|
||||
)
|
||||
all_offers = await wallet_1_rpc.get_all_offers()
|
||||
assert len(all_offers) == 0
|
||||
|
@ -1065,6 +1123,7 @@ async def test_offer_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment)
|
|||
|
||||
offer, trade_record = await wallet_1_rpc.create_offer_for_ids(
|
||||
{uint32(1): -5, cat_asset_id.hex(): 1},
|
||||
DEFAULT_TX_CONFIG,
|
||||
driver_dict=driver_dict,
|
||||
fee=uint64(1),
|
||||
)
|
||||
|
@ -1085,7 +1144,7 @@ async def test_offer_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment)
|
|||
assert TradeStatus(all_offers[0].status) == TradeStatus.PENDING_ACCEPT
|
||||
assert all_offers[0].offer == bytes(offer)
|
||||
|
||||
trade_record = await wallet_2_rpc.take_offer(offer, fee=uint64(1))
|
||||
trade_record = await wallet_2_rpc.take_offer(offer, DEFAULT_TX_CONFIG, fee=uint64(1))
|
||||
assert TradeStatus(trade_record.status) == TradeStatus.PENDING_CONFIRM
|
||||
|
||||
await wallet_1_rpc.cancel_offer(offer.name(), secure=False)
|
||||
|
@ -1100,7 +1159,7 @@ async def test_offer_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment)
|
|||
assert TradeStatus(trade_record.status) == TradeStatus.PENDING_CANCEL
|
||||
|
||||
new_offer, new_trade_record = await wallet_1_rpc.create_offer_for_ids(
|
||||
{uint32(1): -5, cat_wallet_id: 1}, fee=uint64(1)
|
||||
{uint32(1): -5, cat_wallet_id: 1}, DEFAULT_TX_CONFIG, fee=uint64(1)
|
||||
)
|
||||
all_offers = await wallet_1_rpc.get_all_offers()
|
||||
assert len(all_offers) == 2
|
||||
|
@ -1172,7 +1231,7 @@ async def test_get_coin_records_by_names(wallet_rpc_environment: WalletRpcTestEn
|
|||
generated_funds = await generate_funds(full_node_api, env.wallet_1, 5)
|
||||
address = encode_puzzle_hash(await env.wallet_1.wallet.get_new_puzzlehash(), "txch")
|
||||
# Spend half of it back to the same wallet get some spent coins in the wallet
|
||||
tx = await client.send_transaction(1, uint64(generated_funds / 2), address)
|
||||
tx = await client.send_transaction(1, uint64(generated_funds / 2), address, DEFAULT_TX_CONFIG)
|
||||
assert tx.spend_bundle is not None
|
||||
await time_out_assert(20, tx_in_mempool, True, client, tx.name)
|
||||
await farm_transaction(full_node_api, wallet_node, tx.spend_bundle)
|
||||
|
@ -1261,7 +1320,7 @@ async def test_did_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment):
|
|||
await time_out_assert(5, check_mempool_spend_count, True, full_node_api, 1)
|
||||
await farm_transaction_block(full_node_api, wallet_1_node)
|
||||
# Update recovery list
|
||||
res = await wallet_1_rpc.update_did_recovery_list(did_wallet_id_0, [did_id_0], 1)
|
||||
res = await wallet_1_rpc.update_did_recovery_list(did_wallet_id_0, [did_id_0], 1, DEFAULT_TX_CONFIG)
|
||||
assert res["success"]
|
||||
res = await wallet_1_rpc.get_did_recovery_list(did_wallet_id_0)
|
||||
assert res["num_required"] == 1
|
||||
|
@ -1272,8 +1331,8 @@ async def test_did_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment):
|
|||
|
||||
# Update metadata
|
||||
with pytest.raises(ValueError, match="wallet id 1 is of type Wallet but type DIDWallet is required"):
|
||||
await wallet_1_rpc.update_did_metadata(wallet_1_id, {"Twitter": "Https://test"})
|
||||
res = await wallet_1_rpc.update_did_metadata(did_wallet_id_0, {"Twitter": "Https://test"})
|
||||
await wallet_1_rpc.update_did_metadata(wallet_1_id, {"Twitter": "Https://test"}, DEFAULT_TX_CONFIG)
|
||||
res = await wallet_1_rpc.update_did_metadata(did_wallet_id_0, {"Twitter": "Https://test"}, DEFAULT_TX_CONFIG)
|
||||
assert res["success"]
|
||||
|
||||
await farm_transaction_block(full_node_api, wallet_1_node)
|
||||
|
@ -1286,7 +1345,7 @@ async def test_did_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment):
|
|||
|
||||
# Transfer DID
|
||||
addr = encode_puzzle_hash(await wallet_2.get_new_puzzlehash(), "txch")
|
||||
res = await wallet_1_rpc.did_transfer_did(did_wallet_id_0, addr, 0, True)
|
||||
res = await wallet_1_rpc.did_transfer_did(did_wallet_id_0, addr, 0, True, DEFAULT_TX_CONFIG)
|
||||
assert res["success"]
|
||||
|
||||
await time_out_assert(5, check_mempool_spend_count, True, full_node_api, 1)
|
||||
|
@ -1333,6 +1392,7 @@ async def test_nft_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment):
|
|||
None,
|
||||
"0xD4584AD463139FA8C0D9F68F4B59F185",
|
||||
["https://www.chia.net/img/branding/chia-logo.svg"],
|
||||
DEFAULT_TX_CONFIG,
|
||||
)
|
||||
assert res["success"]
|
||||
|
||||
|
@ -1362,7 +1422,7 @@ async def test_nft_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment):
|
|||
assert nft_info["nft_coin_id"][2:] == (await nft_wallet.get_current_nfts())[0].coin.name().hex()
|
||||
|
||||
addr = encode_puzzle_hash(await wallet_2.get_new_puzzlehash(), "txch")
|
||||
res = await wallet_1_rpc.transfer_nft(nft_wallet_id, nft_id, addr, 0)
|
||||
res = await wallet_1_rpc.transfer_nft(nft_wallet_id, nft_id, addr, 0, DEFAULT_TX_CONFIG)
|
||||
assert res["success"]
|
||||
await time_out_assert(5, check_mempool_spend_count, True, full_node_api, 1)
|
||||
await farm_transaction_block(full_node_api, wallet_1_node)
|
||||
|
@ -1426,7 +1486,7 @@ async def test_key_and_address_endpoints(wallet_rpc_environment: WalletRpcTestEn
|
|||
addr = encode_puzzle_hash(ph, "txch")
|
||||
tx_amount = uint64(15600000)
|
||||
|
||||
created_tx = await client.send_transaction(1, tx_amount, addr)
|
||||
created_tx = await client.send_transaction(1, tx_amount, addr, DEFAULT_TX_CONFIG)
|
||||
|
||||
await time_out_assert(20, tx_in_mempool, True, client, created_tx.name)
|
||||
assert len(await wallet.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(1)) == 1
|
||||
|
@ -1522,7 +1582,7 @@ async def test_key_and_address_endpoints(wallet_rpc_environment: WalletRpcTestEn
|
|||
assert await get_unconfirmed_balance(client, int(wallets[0]["id"])) == 0
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
await client.send_transaction(wallets[0]["id"], uint64(100), addr)
|
||||
await client.send_transaction(wallets[0]["id"], uint64(100), addr, DEFAULT_TX_CONFIG)
|
||||
|
||||
# Delete all keys
|
||||
await client.delete_all_keys()
|
||||
|
@ -1547,7 +1607,7 @@ async def test_select_coins_rpc(wallet_rpc_environment: WalletRpcTestEnvironment
|
|||
for tx_amount in tx_amounts:
|
||||
funds -= tx_amount
|
||||
# create coins for tests
|
||||
tx = await client.send_transaction(1, tx_amount, addr)
|
||||
tx = await client.send_transaction(1, tx_amount, addr, DEFAULT_TX_CONFIG)
|
||||
spend_bundle = tx.spend_bundle
|
||||
assert spend_bundle is not None
|
||||
for coin in spend_bundle.additions():
|
||||
|
@ -1559,13 +1619,21 @@ async def test_select_coins_rpc(wallet_rpc_environment: WalletRpcTestEnvironment
|
|||
await time_out_assert(20, get_confirmed_balance, funds, client, 1)
|
||||
|
||||
# test min coin amount
|
||||
min_coins: List[Coin] = await client_2.select_coins(amount=1000, wallet_id=1, min_coin_amount=uint64(1001))
|
||||
min_coins: List[Coin] = await client_2.select_coins(
|
||||
amount=1000,
|
||||
wallet_id=1,
|
||||
coin_selection_config=dataclasses.replace(DEFAULT_COIN_SELECTION_CONFIG, min_coin_amount=uint64(1001)),
|
||||
)
|
||||
assert min_coins is not None
|
||||
assert len(min_coins) == 1 and min_coins[0].amount == uint64(10000)
|
||||
|
||||
# test max coin amount
|
||||
max_coins: List[Coin] = await client_2.select_coins(
|
||||
amount=2000, wallet_id=1, min_coin_amount=uint64(999), max_coin_amount=uint64(9999)
|
||||
amount=2000,
|
||||
wallet_id=1,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG, min_coin_amount=uint64(999), max_coin_amount=uint64(9999)
|
||||
),
|
||||
)
|
||||
assert max_coins is not None
|
||||
assert len(max_coins) == 2 and max_coins[0].amount == uint64(1000)
|
||||
|
@ -1573,7 +1641,9 @@ async def test_select_coins_rpc(wallet_rpc_environment: WalletRpcTestEnvironment
|
|||
# test excluded coin amounts
|
||||
non_1000_amt: int = sum(a for a in tx_amounts if a != 1000)
|
||||
excluded_amt_coins: List[Coin] = await client_2.select_coins(
|
||||
amount=non_1000_amt, wallet_id=1, excluded_amounts=[uint64(1000)]
|
||||
amount=non_1000_amt,
|
||||
wallet_id=1,
|
||||
coin_selection_config=dataclasses.replace(DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_amounts=[uint64(1000)]),
|
||||
)
|
||||
assert excluded_amt_coins is not None
|
||||
assert (
|
||||
|
@ -1583,23 +1653,47 @@ async def test_select_coins_rpc(wallet_rpc_environment: WalletRpcTestEnvironment
|
|||
|
||||
# test excluded coins
|
||||
with pytest.raises(ValueError):
|
||||
await client_2.select_coins(amount=5000, wallet_id=1, excluded_coins=min_coins)
|
||||
excluded_test = await client_2.select_coins(amount=1300, wallet_id=1, excluded_coins=coin_300)
|
||||
await client_2.select_coins(
|
||||
amount=5000,
|
||||
wallet_id=1,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_ids=[c.name() for c in min_coins]
|
||||
),
|
||||
)
|
||||
excluded_test = await client_2.select_coins(
|
||||
amount=1300,
|
||||
wallet_id=1,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_ids=[c.name() for c in coin_300]
|
||||
),
|
||||
)
|
||||
assert len(excluded_test) == 2
|
||||
for coin in excluded_test:
|
||||
assert coin != coin_300[0]
|
||||
|
||||
# test get coins
|
||||
all_coins, _, _ = await client_2.get_spendable_coins(
|
||||
wallet_id=1, excluded_coin_ids=[c.name().hex() for c in excluded_amt_coins]
|
||||
wallet_id=1,
|
||||
coin_selection_config=dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_ids=[c.name() for c in excluded_amt_coins]
|
||||
),
|
||||
)
|
||||
assert excluded_amt_coins not in all_coins
|
||||
all_coins, _, _ = await client_2.get_spendable_coins(wallet_id=1, excluded_amounts=[uint64(1000)])
|
||||
all_coins, _, _ = await client_2.get_spendable_coins(
|
||||
wallet_id=1,
|
||||
coin_selection_config=dataclasses.replace(DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_amounts=[uint64(1000)]),
|
||||
)
|
||||
assert excluded_amt_coins not in all_coins
|
||||
all_coins_2, _, _ = await client_2.get_spendable_coins(wallet_id=1, max_coin_amount=uint64(999))
|
||||
all_coins_2, _, _ = await client_2.get_spendable_coins(
|
||||
wallet_id=1,
|
||||
coin_selection_config=dataclasses.replace(DEFAULT_COIN_SELECTION_CONFIG, max_coin_amount=uint64(999)),
|
||||
)
|
||||
assert all_coins_2[0].coin == coin_300[0]
|
||||
with pytest.raises(ValueError): # validate fail on invalid coin id.
|
||||
await client_2.get_spendable_coins(wallet_id=1, excluded_coin_ids=["a"])
|
||||
await client_2.get_spendable_coins(
|
||||
wallet_id=1,
|
||||
coin_selection_config=dataclasses.replace(DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_ids=[b"a"]),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
@ -2005,7 +2099,12 @@ async def test_set_wallet_resync_on_startup(wallet_rpc_environment: WalletRpcTes
|
|||
nft_wallet_id = nft_wallet["wallet_id"]
|
||||
address = await wc.get_next_address(env.wallet_1.wallet.id(), True)
|
||||
await wc.mint_nft(
|
||||
nft_wallet_id, royalty_address=address, target_address=address, hash="deadbeef", uris=["http://test.nft"]
|
||||
nft_wallet_id,
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
royalty_address=address,
|
||||
target_address=address,
|
||||
hash="deadbeef",
|
||||
uris=["http://test.nft"],
|
||||
)
|
||||
await time_out_assert(5, check_mempool_spend_count, True, full_node_api, 1)
|
||||
await farm_transaction_block(full_node_api, env.wallet_1.node)
|
||||
|
@ -2140,7 +2239,7 @@ async def test_cat_spend_run_tail(wallet_rpc_environment: WalletRpcTestEnvironme
|
|||
)
|
||||
tx_amount = uint64(100)
|
||||
|
||||
tx = await client.send_transaction(1, tx_amount, addr)
|
||||
tx = await client.send_transaction(1, tx_amount, addr, DEFAULT_TX_CONFIG)
|
||||
transaction_id = tx.name
|
||||
spend_bundle = tx.spend_bundle
|
||||
assert spend_bundle is not None
|
||||
|
@ -2183,6 +2282,7 @@ async def test_cat_spend_run_tail(wallet_rpc_environment: WalletRpcTestEnvironme
|
|||
tx = await client.cat_spend(
|
||||
cat_wallet_id,
|
||||
amount=uint64(0),
|
||||
tx_config=DEFAULT_TX_CONFIG,
|
||||
inner_address=encode_puzzle_hash(our_ph, "txch"),
|
||||
cat_discrepancy=(tx_amount * -1, Program.to(None), Program.to(None)),
|
||||
)
|
||||
|
|
|
@ -25,6 +25,7 @@ from chia.types.condition_with_args import ConditionWithArgs
|
|||
from chia.types.peer_info import PeerInfo
|
||||
from chia.types.spend_bundle import SpendBundle
|
||||
from chia.util.ints import uint16, uint32, uint64
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from chia.wallet.wallet import Wallet
|
||||
from chia.wallet.wallet_state_manager import WalletStateManager
|
||||
from tests.connection_utils import add_dummy_connection
|
||||
|
@ -185,7 +186,7 @@ class TestSimpleSyncProtocol:
|
|||
|
||||
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20)
|
||||
|
||||
tx_record = await wallet.generate_signed_transaction(uint64(10), puzzle_hash, uint64(0))
|
||||
tx_record = await wallet.generate_signed_transaction(uint64(10), puzzle_hash, DEFAULT_TX_CONFIG, uint64(0))
|
||||
assert len(tx_record.spend_bundle.removals()) == 1
|
||||
spent_coin = tx_record.spend_bundle.removals()[0]
|
||||
assert spent_coin.puzzle_hash == puzzle_hash
|
||||
|
@ -199,7 +200,9 @@ class TestSimpleSyncProtocol:
|
|||
|
||||
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20)
|
||||
|
||||
tx_record = await wallet.generate_signed_transaction(uint64(10), SINGLETON_LAUNCHER_HASH, uint64(0))
|
||||
tx_record = await wallet.generate_signed_transaction(
|
||||
uint64(10), SINGLETON_LAUNCHER_HASH, DEFAULT_TX_CONFIG, uint64(0)
|
||||
)
|
||||
await wallet.push_transaction(tx_record)
|
||||
|
||||
await full_node_api.process_transaction_records(records=[tx_record])
|
||||
|
@ -207,7 +210,7 @@ class TestSimpleSyncProtocol:
|
|||
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20)
|
||||
|
||||
# Send a transaction to make sure the wallet is still running
|
||||
tx_record = await wallet.generate_signed_transaction(uint64(10), junk_ph, uint64(0))
|
||||
tx_record = await wallet.generate_signed_transaction(uint64(10), junk_ph, DEFAULT_TX_CONFIG, uint64(0))
|
||||
await wallet.push_transaction(tx_record)
|
||||
|
||||
await full_node_api.process_transaction_records(records=[tx_record])
|
||||
|
@ -267,7 +270,9 @@ class TestSimpleSyncProtocol:
|
|||
|
||||
coins = set()
|
||||
coins.add(coin_to_spend)
|
||||
tx_record = await standard_wallet.generate_signed_transaction(uint64(10), puzzle_hash, uint64(0), coins=coins)
|
||||
tx_record = await standard_wallet.generate_signed_transaction(
|
||||
uint64(10), puzzle_hash, DEFAULT_TX_CONFIG, uint64(0), coins=coins
|
||||
)
|
||||
await standard_wallet.push_transaction(tx_record)
|
||||
|
||||
await full_node_api.process_transaction_records(records=[tx_record])
|
||||
|
@ -287,7 +292,9 @@ class TestSimpleSyncProtocol:
|
|||
# Test getting notification for coin that is about to be created
|
||||
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20)
|
||||
|
||||
tx_record = await standard_wallet.generate_signed_transaction(uint64(10), puzzle_hash, uint64(0))
|
||||
tx_record = await standard_wallet.generate_signed_transaction(
|
||||
uint64(10), puzzle_hash, DEFAULT_TX_CONFIG, uint64(0)
|
||||
)
|
||||
|
||||
tx_record.spend_bundle.additions()
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ from chia.wallet.nft_wallet.nft_wallet import NFTWallet
|
|||
from chia.wallet.payment import Payment
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.compute_memos import compute_memos
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from chia.wallet.util.wallet_sync_utils import PeerRequestException
|
||||
from chia.wallet.wallet_coin_record import WalletCoinRecord
|
||||
from chia.wallet.wallet_weight_proof_handler import get_wp_fork_point
|
||||
|
@ -513,7 +514,9 @@ class TestWalletSync:
|
|||
payees.append(Payment(payee_ph, uint64(i + 100)))
|
||||
payees.append(Payment(payee_ph, uint64(i + 200)))
|
||||
|
||||
tx: TransactionRecord = await wallet.generate_signed_transaction(uint64(0), ph, primaries=payees)
|
||||
tx: TransactionRecord = await wallet.generate_signed_transaction(
|
||||
uint64(0), ph, DEFAULT_TX_CONFIG, primaries=payees
|
||||
)
|
||||
await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
|
||||
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
||||
|
@ -724,7 +727,9 @@ class TestWalletSync:
|
|||
payees.append(Payment(payee_ph, uint64(dust_value)))
|
||||
|
||||
# construct and send tx
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(uint64(0), ph, primaries=payees)
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(
|
||||
uint64(0), ph, DEFAULT_TX_CONFIG, primaries=payees
|
||||
)
|
||||
await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
|
||||
|
||||
# advance the chain and sync both wallets
|
||||
|
@ -784,7 +789,9 @@ class TestWalletSync:
|
|||
# This greatly speeds up the overall process
|
||||
if dust_remaining % 100 == 0 and dust_remaining != new_dust:
|
||||
# construct and send tx
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(uint64(0), ph, primaries=payees)
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(
|
||||
uint64(0), ph, DEFAULT_TX_CONFIG, primaries=payees
|
||||
)
|
||||
await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
||||
last_block: Optional[BlockRecord] = full_node_api.full_node.blockchain.get_peak()
|
||||
|
@ -797,7 +804,9 @@ class TestWalletSync:
|
|||
# Only need to create tx if there was new dust to be added
|
||||
if new_dust >= 1:
|
||||
# construct and send tx
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(uint64(0), ph, primaries=payees)
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(
|
||||
uint64(0), ph, DEFAULT_TX_CONFIG, primaries=payees
|
||||
)
|
||||
await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
|
||||
|
||||
# advance the chain and sync both wallets
|
||||
|
@ -844,7 +853,9 @@ class TestWalletSync:
|
|||
payees.append(Payment(payee_ph, uint64(xch_spam_amount)))
|
||||
|
||||
# construct and send tx
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(uint64(0), ph, primaries=payees)
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(
|
||||
uint64(0), ph, DEFAULT_TX_CONFIG, primaries=payees
|
||||
)
|
||||
await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
|
||||
|
||||
# advance the chain and sync both wallets
|
||||
|
@ -883,7 +894,9 @@ class TestWalletSync:
|
|||
payees.append(Payment(payee_ph, uint64(dust_value)))
|
||||
|
||||
# construct and send tx
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(uint64(0), ph, primaries=payees)
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(
|
||||
uint64(0), ph, DEFAULT_TX_CONFIG, primaries=payees
|
||||
)
|
||||
await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
|
||||
|
||||
# advance the chain and sync both wallets
|
||||
|
@ -942,7 +955,9 @@ class TestWalletSync:
|
|||
large_dust_balance += dust_value
|
||||
|
||||
# construct and send tx
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(uint64(0), ph, primaries=payees)
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(
|
||||
uint64(0), ph, DEFAULT_TX_CONFIG, primaries=payees
|
||||
)
|
||||
await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
|
||||
|
||||
# advance the chain and sync both wallets
|
||||
|
@ -978,7 +993,9 @@ class TestWalletSync:
|
|||
payees = [Payment(payee_ph, uint64(balance))]
|
||||
|
||||
# construct and send tx
|
||||
tx: TransactionRecord = await dust_wallet.generate_signed_transaction(uint64(0), ph, primaries=payees)
|
||||
tx: TransactionRecord = await dust_wallet.generate_signed_transaction(
|
||||
uint64(0), ph, DEFAULT_TX_CONFIG, primaries=payees
|
||||
)
|
||||
await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
|
||||
|
||||
# advance the chain and sync both wallets
|
||||
|
@ -1021,7 +1038,9 @@ class TestWalletSync:
|
|||
# This greatly speeds up the overall process
|
||||
if coins_remaining % 100 == 0 and coins_remaining != spam_filter_after_n_txs:
|
||||
# construct and send tx
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(uint64(0), ph, primaries=payees)
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(
|
||||
uint64(0), ph, DEFAULT_TX_CONFIG, primaries=payees
|
||||
)
|
||||
await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
||||
last_block: Optional[BlockRecord] = full_node_api.full_node.blockchain.get_peak()
|
||||
|
@ -1032,7 +1051,9 @@ class TestWalletSync:
|
|||
coins_remaining -= 1
|
||||
|
||||
# construct and send tx
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(uint64(0), ph, primaries=payees)
|
||||
tx: TransactionRecord = await farm_wallet.generate_signed_transaction(
|
||||
uint64(0), ph, DEFAULT_TX_CONFIG, primaries=payees
|
||||
)
|
||||
await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
|
||||
|
||||
# advance the chain and sync both wallets
|
||||
|
@ -1061,7 +1082,9 @@ class TestWalletSync:
|
|||
payees = [Payment(payee_ph, uint64(1))]
|
||||
|
||||
# construct and send tx
|
||||
tx: TransactionRecord = await dust_wallet.generate_signed_transaction(uint64(0), ph, primaries=payees)
|
||||
tx: TransactionRecord = await dust_wallet.generate_signed_transaction(
|
||||
uint64(0), ph, DEFAULT_TX_CONFIG, primaries=payees
|
||||
)
|
||||
await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
|
||||
|
||||
# advance the chain and sync both wallets
|
||||
|
@ -1137,6 +1160,7 @@ class TestWalletSync:
|
|||
txs = await farm_nft_wallet.generate_signed_transaction(
|
||||
[uint64(nft_coins[0].coin.amount)],
|
||||
[dust_ph],
|
||||
DEFAULT_TX_CONFIG,
|
||||
coins={nft_coins[0].coin},
|
||||
)
|
||||
assert len(txs) == 1
|
||||
|
@ -1273,7 +1297,9 @@ class TestWalletSync:
|
|||
|
||||
await time_out_assert(30, wallet.get_confirmed_balance, 2_000_000_000_000)
|
||||
|
||||
tx = await wallet.generate_signed_transaction(1_000_000_000_000, bytes32([0] * 32), memos=[ph])
|
||||
tx = await wallet.generate_signed_transaction(
|
||||
1_000_000_000_000, bytes32([0] * 32), DEFAULT_TX_CONFIG, memos=[ph]
|
||||
)
|
||||
await wallet_node.wallet_state_manager.add_pending_transaction(tx)
|
||||
|
||||
async def tx_in_mempool():
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import logging
|
||||
import time
|
||||
from random import randrange
|
||||
|
@ -19,6 +20,7 @@ from chia.wallet.coin_selection import (
|
|||
select_smallest_coin_over_target,
|
||||
sum_largest_coins,
|
||||
)
|
||||
from chia.wallet.util.tx_config import DEFAULT_COIN_SELECTION_CONFIG
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet_coin_record import WalletCoinRecord
|
||||
|
||||
|
@ -87,7 +89,7 @@ class TestCoinSelection:
|
|||
for target_amount in coin_amounts[:100]: # select the first 100 values
|
||||
result: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -116,7 +118,7 @@ class TestCoinSelection:
|
|||
print("Target amount: ", target_amount)
|
||||
result: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -136,7 +138,7 @@ class TestCoinSelection:
|
|||
for target_amount in [50000, 25000, 15000, 10000, 9000, 3000]: # select the first 100 values
|
||||
dusty_result: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -167,7 +169,7 @@ class TestCoinSelection:
|
|||
for target_amount in [20000, 15000, 10000, 5000]: # select the first 100 values
|
||||
dusty_below_target: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
new_coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -198,7 +200,7 @@ class TestCoinSelection:
|
|||
for target_amount in [50000, 10001, 10000, 9999]:
|
||||
dusty_below_target: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
new_coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -224,7 +226,7 @@ class TestCoinSelection:
|
|||
for target_amount in [10000, 9999]:
|
||||
await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -235,7 +237,7 @@ class TestCoinSelection:
|
|||
for target_amount in [10001, 20000]:
|
||||
await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -255,7 +257,7 @@ class TestCoinSelection:
|
|||
target_amount = uint128(40)
|
||||
exact_match_result: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -269,7 +271,7 @@ class TestCoinSelection:
|
|||
target_amount = uint128(153)
|
||||
match_2: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -282,7 +284,7 @@ class TestCoinSelection:
|
|||
target_amount = uint128(541)
|
||||
match_3: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -296,7 +298,7 @@ class TestCoinSelection:
|
|||
target_amount = spendable_amount
|
||||
match_all: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -316,7 +318,7 @@ class TestCoinSelection:
|
|||
target_amount = uint128(625)
|
||||
smallest_result: Set[Coin] = await select_coins(
|
||||
greater_spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
greater_coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -334,7 +336,7 @@ class TestCoinSelection:
|
|||
target_amount = uint128(50000)
|
||||
single_greater_result: Set[Coin] = await select_coins(
|
||||
single_greater_spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
single_greater_coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -354,7 +356,7 @@ class TestCoinSelection:
|
|||
target_amount = uint128(70000)
|
||||
multiple_greater_result: Set[Coin] = await select_coins(
|
||||
multiple_greater_spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
multiple_greater_coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -384,7 +386,7 @@ class TestCoinSelection:
|
|||
target_amount = spendable_amount - 1
|
||||
result: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -450,12 +452,11 @@ class TestCoinSelection:
|
|||
for min_coin_amount in [10, 100, 200, 300, 1000]:
|
||||
result: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
dataclasses.replace(DEFAULT_COIN_SELECTION_CONFIG, min_coin_amount=uint64(min_coin_amount)),
|
||||
coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
uint128(target_amount),
|
||||
min_coin_amount=uint64(min_coin_amount),
|
||||
)
|
||||
assert result is not None # this should never happen
|
||||
assert sum(coin.amount for coin in result) >= target_amount
|
||||
|
@ -483,12 +484,11 @@ class TestCoinSelection:
|
|||
# test that excluded coins are not included in the result
|
||||
selected_coins: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
dataclasses.replace(DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_ids=[c.name() for c in excluded_coins]),
|
||||
spendable_wallet_coin_records,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
amount=target_amount,
|
||||
exclude=excluded_coins,
|
||||
)
|
||||
|
||||
assert selected_coins is not None
|
||||
|
@ -501,12 +501,13 @@ class TestCoinSelection:
|
|||
with pytest.raises(ValueError):
|
||||
await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
dataclasses.replace(
|
||||
DEFAULT_COIN_SELECTION_CONFIG, excluded_coin_ids=[c.name() for c in excluded_all_coins]
|
||||
),
|
||||
spendable_wallet_coin_records,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
amount=target_amount,
|
||||
exclude=excluded_all_coins,
|
||||
)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
@ -522,7 +523,7 @@ class TestCoinSelection:
|
|||
target_amount = uint128(0)
|
||||
zero_amount_result: Set[Coin] = await select_coins(
|
||||
spendable_amount,
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
coin_list,
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
@ -535,7 +536,7 @@ class TestCoinSelection:
|
|||
with pytest.raises(ValueError):
|
||||
await select_coins(
|
||||
uint128(0),
|
||||
uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
|
||||
DEFAULT_COIN_SELECTION_CONFIG,
|
||||
[],
|
||||
{},
|
||||
logging.getLogger("test"),
|
||||
|
|
|
@ -16,6 +16,7 @@ from chia.types.peer_info import PeerInfo
|
|||
from chia.util.db_wrapper import DBWrapper2
|
||||
from chia.util.ints import uint16, uint32, uint64
|
||||
from chia.wallet.notification_store import NotificationStore
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
|
||||
|
||||
# For testing backwards compatibility with a DB change to add height
|
||||
|
@ -134,7 +135,7 @@ async def test_notifications(self_hostname: str, two_wallet_nodes: Any, trusted:
|
|||
allow_height = peak.height + 1
|
||||
if case == "allow_larger":
|
||||
allow_larger_height = peak.height + 1
|
||||
tx = await notification_manager_1.send_new_notification(ph_2, msg, AMOUNT, fee=FEE)
|
||||
tx = await notification_manager_1.send_new_notification(ph_2, msg, AMOUNT, DEFAULT_TX_CONFIG, fee=FEE)
|
||||
await wsm_1.add_pending_transaction(tx)
|
||||
await time_out_assert_not_none(
|
||||
5,
|
||||
|
|
|
@ -27,6 +27,7 @@ from chia.wallet.payment import Payment
|
|||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.compute_memos import compute_memos
|
||||
from chia.wallet.util.transaction_type import TransactionType
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from chia.wallet.util.wallet_types import CoinType
|
||||
from chia.wallet.wallet import CHIP_0002_SIGN_MESSAGE_PREFIX
|
||||
from chia.wallet.wallet_node import WalletNode, get_wallet_db_path
|
||||
|
@ -113,6 +114,7 @@ class TestWalletSimulator:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(tx_amount),
|
||||
await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash(),
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
)
|
||||
await wallet.push_transaction(tx)
|
||||
|
@ -160,8 +162,8 @@ class TestWalletSimulator:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(tx_amount),
|
||||
await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash(),
|
||||
dataclasses.replace(DEFAULT_TX_CONFIG, reuse_puzhash=True),
|
||||
uint64(0),
|
||||
reuse_puzhash=True,
|
||||
)
|
||||
assert tx.spend_bundle is not None
|
||||
assert len(tx.spend_bundle.coin_spends) == 1
|
||||
|
@ -217,6 +219,7 @@ class TestWalletSimulator:
|
|||
tx1 = await wallet.generate_signed_transaction(
|
||||
uint64(500),
|
||||
normal_puzhash,
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 10}],
|
||||
)
|
||||
|
@ -232,6 +235,7 @@ class TestWalletSimulator:
|
|||
tx2 = await wallet.generate_signed_transaction(
|
||||
uint64(500),
|
||||
await wallet_1.get_new_puzzlehash(),
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 10}],
|
||||
)
|
||||
|
@ -247,6 +251,7 @@ class TestWalletSimulator:
|
|||
tx3 = await wallet.generate_signed_transaction(
|
||||
uint64(500),
|
||||
normal_puzhash,
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 10}],
|
||||
)
|
||||
|
@ -324,6 +329,7 @@ class TestWalletSimulator:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(500),
|
||||
normal_puzhash,
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 500}],
|
||||
memos=[b"Test"],
|
||||
|
@ -449,6 +455,7 @@ class TestWalletSimulator:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(500),
|
||||
normal_puzhash,
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 5}],
|
||||
)
|
||||
|
@ -540,6 +547,7 @@ class TestWalletSimulator:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(500),
|
||||
normal_puzhash,
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 5}],
|
||||
)
|
||||
|
@ -637,6 +645,7 @@ class TestWalletSimulator:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(500),
|
||||
normal_puzhash,
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 500}],
|
||||
)
|
||||
|
@ -752,6 +761,7 @@ class TestWalletSimulator:
|
|||
tx = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction(
|
||||
uint64(10),
|
||||
bytes32(32 * b"0"),
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
)
|
||||
assert tx.spend_bundle is not None
|
||||
|
@ -808,6 +818,7 @@ class TestWalletSimulator:
|
|||
tx = await wallet_0.generate_signed_transaction(
|
||||
uint64(tx_amount),
|
||||
await wallet_node_1.wallet_state_manager.main_wallet.get_new_puzzlehash(),
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
)
|
||||
|
||||
|
@ -827,7 +838,7 @@ class TestWalletSimulator:
|
|||
|
||||
tx_amount = 5
|
||||
tx = await wallet_1.generate_signed_transaction(
|
||||
uint64(tx_amount), await wallet_0.get_new_puzzlehash(), uint64(0)
|
||||
uint64(tx_amount), await wallet_0.get_new_puzzlehash(), DEFAULT_TX_CONFIG, uint64(0)
|
||||
)
|
||||
await wallet_1.push_transaction(tx)
|
||||
await full_node_api_0.wait_transaction_records_entered_mempool(records=[tx])
|
||||
|
@ -920,6 +931,7 @@ class TestWalletSimulator:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(tx_amount),
|
||||
await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash(),
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(tx_fee),
|
||||
)
|
||||
assert tx.spend_bundle is not None
|
||||
|
@ -985,7 +997,9 @@ class TestWalletSimulator:
|
|||
tx_amount = 3200000000000
|
||||
tx_fee = 10
|
||||
ph_2 = await wallet_1.get_new_puzzlehash()
|
||||
tx = await wallet.generate_signed_transaction(uint64(tx_amount), ph_2, uint64(tx_fee), memos=[ph_2])
|
||||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(tx_amount), ph_2, DEFAULT_TX_CONFIG, uint64(tx_fee), memos=[ph_2]
|
||||
)
|
||||
tx_id = tx.name.hex()
|
||||
assert tx.spend_bundle is not None
|
||||
|
||||
|
@ -1049,7 +1063,9 @@ class TestWalletSimulator:
|
|||
await time_out_assert(20, wallet.get_confirmed_balance, expected_confirmed_balance)
|
||||
|
||||
primaries = [Payment(ph, uint64(1000000000 + i)) for i in range(60)]
|
||||
tx_split_coins = await wallet.generate_signed_transaction(uint64(1), ph, uint64(0), primaries=primaries)
|
||||
tx_split_coins = await wallet.generate_signed_transaction(
|
||||
uint64(1), ph, DEFAULT_TX_CONFIG, uint64(0), primaries=primaries
|
||||
)
|
||||
assert tx_split_coins.spend_bundle is not None
|
||||
|
||||
await wallet.push_transaction(tx_split_coins)
|
||||
|
@ -1062,6 +1078,7 @@ class TestWalletSimulator:
|
|||
transaction_record = await wallet.generate_signed_transaction(
|
||||
uint64(max_sent_amount - 1),
|
||||
ph,
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
)
|
||||
|
||||
|
@ -1071,6 +1088,7 @@ class TestWalletSimulator:
|
|||
transaction_record = await wallet.generate_signed_transaction(
|
||||
uint64(max_sent_amount),
|
||||
ph,
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
)
|
||||
|
||||
|
@ -1081,6 +1099,7 @@ class TestWalletSimulator:
|
|||
await wallet.generate_signed_transaction(
|
||||
uint64(max_sent_amount + 1),
|
||||
ph,
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
)
|
||||
|
||||
|
@ -1127,6 +1146,7 @@ class TestWalletSimulator:
|
|||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(tx_amount),
|
||||
await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash(),
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(tx_fee),
|
||||
)
|
||||
assert tx.spend_bundle is not None
|
||||
|
@ -1208,14 +1228,16 @@ class TestWalletSimulator:
|
|||
|
||||
# Ensure that we use a coin that we will not reorg out
|
||||
tx_amount = 1000
|
||||
coins = await wallet.select_coins(amount=uint64(tx_amount))
|
||||
coins = await wallet.select_coins(
|
||||
amount=uint64(tx_amount), coin_selection_config=DEFAULT_TX_CONFIG.coin_selection_config
|
||||
)
|
||||
coin = next(iter(coins))
|
||||
|
||||
reorg_height = full_node_api.full_node.blockchain.get_peak_height()
|
||||
assert reorg_height is not None
|
||||
reorg_funds = await full_node_api.farm_blocks_to_wallet(count=reorg_block_count, wallet=wallet)
|
||||
|
||||
tx = await wallet.generate_signed_transaction(uint64(tx_amount), ph2, coins={coin})
|
||||
tx = await wallet.generate_signed_transaction(uint64(tx_amount), ph2, DEFAULT_TX_CONFIG, coins={coin})
|
||||
assert tx.spend_bundle is not None
|
||||
await wallet.push_transaction(tx)
|
||||
await full_node_api.process_transaction_records(records=[tx])
|
||||
|
@ -1434,12 +1456,13 @@ class TestWalletSimulator:
|
|||
await time_out_assert(20, wallet.get_unconfirmed_balance, expected_confirmed_balance)
|
||||
|
||||
AMOUNT_TO_SEND = 4000000000000
|
||||
coins = await wallet.select_coins(uint64(AMOUNT_TO_SEND))
|
||||
coins = await wallet.select_coins(uint64(AMOUNT_TO_SEND), DEFAULT_TX_CONFIG.coin_selection_config)
|
||||
coin_list = list(coins)
|
||||
|
||||
tx = await wallet.generate_signed_transaction(
|
||||
uint64(AMOUNT_TO_SEND),
|
||||
await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash(),
|
||||
DEFAULT_TX_CONFIG,
|
||||
uint64(0),
|
||||
coins=coins,
|
||||
origin_id=coin_list[2].name(),
|
||||
|
|
|
@ -16,6 +16,7 @@ from chia.types.peer_info import PeerInfo
|
|||
from chia.types.spend_bundle import SpendBundle
|
||||
from chia.util.ints import uint16, uint64
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from chia.wallet.wallet_node import WalletNode
|
||||
|
||||
|
||||
|
@ -62,7 +63,9 @@ async def test_wallet_tx_retry(
|
|||
await farm_blocks(full_node_1, reward_ph, 2)
|
||||
await full_node_1.wait_for_wallet_synced(wallet_node=wallet_node_1, timeout=wait_secs)
|
||||
|
||||
transaction: TransactionRecord = await wallet_1.generate_signed_transaction(uint64(100), reward_ph)
|
||||
transaction: TransactionRecord = await wallet_1.generate_signed_transaction(
|
||||
uint64(100), reward_ph, DEFAULT_TX_CONFIG
|
||||
)
|
||||
sb1: Optional[SpendBundle] = transaction.spend_bundle
|
||||
assert sb1 is not None
|
||||
await wallet_1.push_transaction(transaction)
|
||||
|
|
|
@ -12,6 +12,7 @@ from chia.types.blockchain_format.sized_bytes import bytes32
|
|||
from chia.types.peer_info import PeerInfo
|
||||
from chia.util.ints import uint16, uint64
|
||||
from chia.wallet.did_wallet.did_wallet import DIDWallet
|
||||
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.vc_wallet.vc_store import VCProofs, VCRecord
|
||||
|
||||
|
@ -86,6 +87,7 @@ async def test_vc_lifecycle(self_hostname: str, two_wallet_nodes_services: Any,
|
|||
proof_root: bytes32 = proofs.root()
|
||||
txs = await client_0.vc_spend(
|
||||
vc_record.vc.launcher_id,
|
||||
DEFAULT_TX_CONFIG,
|
||||
new_proof_hash=proof_root,
|
||||
fee=uint64(100),
|
||||
)
|
||||
|
@ -99,7 +101,7 @@ async def test_vc_lifecycle(self_hostname: str, two_wallet_nodes_services: Any,
|
|||
assert vc_record_updated.vc.proof_hash == proof_root
|
||||
|
||||
# Do a mundane spend
|
||||
txs = await client_0.vc_spend(vc_record.vc.launcher_id)
|
||||
txs = await client_0.vc_spend(vc_record.vc.launcher_id, DEFAULT_TX_CONFIG)
|
||||
spend_bundle = next(tx.spend_bundle for tx in txs if tx.spend_bundle is not None)
|
||||
await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name())
|
||||
await full_node_api.farm_blocks_to_wallet(count=num_blocks, wallet=wallet_1)
|
||||
|
@ -128,7 +130,7 @@ async def test_vc_lifecycle(self_hostname: str, two_wallet_nodes_services: Any,
|
|||
assert fetched_proofs[proof_root.hex()] == proofs.key_value_pairs
|
||||
|
||||
# Revoke VC
|
||||
txs = await client_0.vc_revoke(vc_record_updated.vc.coin.parent_coin_info, uint64(1))
|
||||
txs = await client_0.vc_revoke(vc_record_updated.vc.coin.parent_coin_info, DEFAULT_TX_CONFIG, uint64(1))
|
||||
confirmed_balance -= 1
|
||||
spend_bundle = next(tx.spend_bundle for tx in txs if tx.spend_bundle is not None)
|
||||
await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name())
|
||||
|
|
Loading…
Reference in New Issue