예제 #1
0
def load_pool_config(root_path: Path) -> List[PoolWalletConfig]:
    config = load_config(root_path, "config.yaml")
    ret_list: List[PoolWalletConfig] = []
    if "pool_list" in config["pool"]:
        for pool_config_dict in config["pool"]["pool_list"]:
            try:
                pool_config = PoolWalletConfig(
                    bytes32.from_hexstr(pool_config_dict["launcher_id"]),
                    pool_config_dict["pool_url"],
                    pool_config_dict["payout_instructions"],
                    bytes32.from_hexstr(
                        pool_config_dict["target_puzzle_hash"]),
                    bytes32.from_hexstr(
                        pool_config_dict["p2_singleton_puzzle_hash"]),
                    G1Element.from_bytes(
                        hexstr_to_bytes(pool_config_dict["owner_public_key"])),
                    G1Element.from_bytes(
                        hexstr_to_bytes(
                            pool_config_dict["authentication_public_key"])),
                )
                ret_list.append(pool_config)
            except Exception as e:
                log.error(f"Exception loading config: {pool_config_dict} {e}")

    return ret_list
예제 #2
0
async def get_transaction(args: dict, wallet_client: WalletRpcClient, fingerprint: int) -> None:
    wallet_id = args["id"]
    transaction_id = bytes32.from_hexstr(args["tx_id"])
    config = load_config(DEFAULT_ROOT_PATH, "config.yaml", SERVICE_NAME)
    name = config["network_overrides"]["config"][config["selected_network"]]["address_prefix"]
    tx: TransactionRecord = await wallet_client.get_transaction(wallet_id, transaction_id=transaction_id)
    print_transaction(tx, verbose=(args["verbose"] > 0), name=name)
예제 #3
0
async def get_transaction(args: dict, wallet_client: WalletRpcClient,
                          fingerprint: int) -> None:
    transaction_id = bytes32.from_hexstr(args["tx_id"])
    config = load_config(DEFAULT_ROOT_PATH, "config.yaml", SERVICE_NAME)
    address_prefix = config["network_overrides"]["config"][
        config["selected_network"]]["address_prefix"]
    tx: TransactionRecord = await wallet_client.get_transaction(
        "this is unused", transaction_id=transaction_id)

    try:
        wallet_type = await get_wallet_type(wallet_id=tx.wallet_id,
                                            wallet_client=wallet_client)
        mojo_per_unit = get_mojo_per_unit(wallet_type=wallet_type)
        name = await get_name_for_wallet_id(
            config=config,
            wallet_type=wallet_type,
            wallet_id=tx.wallet_id,
            wallet_client=wallet_client,
        )
    except LookupError as e:
        print(e.args[0])
        return

    print_transaction(
        tx,
        verbose=(args["verbose"] > 0),
        name=name,
        address_prefix=address_prefix,
        mojo_per_unit=mojo_per_unit,
    )
예제 #4
0
async def add_token(args: dict, wallet_client: WalletRpcClient,
                    fingerprint: int) -> None:
    asset_id = args["asset_id"]
    token_name = args["token_name"]
    try:
        asset_id_bytes: bytes32 = bytes32.from_hexstr(asset_id)
        existing_info: Optional[Tuple[
            Optional[uint32],
            str]] = await wallet_client.cat_asset_id_to_name(asset_id_bytes)
        if existing_info is None or existing_info[0] is None:
            response = await wallet_client.create_wallet_for_existing_cat(
                asset_id_bytes)
            wallet_id = response["wallet_id"]
            await wallet_client.set_cat_name(wallet_id, token_name)
            print(
                f"Successfully added {token_name} with wallet id {wallet_id} on key {fingerprint}"
            )
        else:
            wallet_id, old_name = existing_info
            await wallet_client.set_cat_name(wallet_id, token_name)
            print(
                f"Successfully renamed {old_name} with wallet_id {wallet_id} on key {fingerprint} to {token_name}"
            )
    except ValueError as e:
        if "fromhex()" in str(e):
            print(f"{asset_id} is not a valid Asset ID")
        else:
            raise e
예제 #5
0
async def get_login_link(launcher_id_str: str) -> None:
    launcher_id: bytes32 = bytes32.from_hexstr(launcher_id_str)
    config = load_config(DEFAULT_ROOT_PATH, "config.yaml")
    self_hostname = config["self_hostname"]
    farmer_rpc_port = config["farmer"]["rpc_port"]
    farmer_client = await FarmerRpcClient.create(self_hostname,
                                                 uint16(farmer_rpc_port),
                                                 DEFAULT_ROOT_PATH, config)
    try:
        login_link: Optional[str] = await farmer_client.get_pool_login_link(
            launcher_id)
        if login_link is None:
            print("Was not able to get login link.")
        else:
            print(login_link)
    except Exception as e:
        if isinstance(e, aiohttp.ClientConnectorError):
            print(
                f"Connection error. Check if farmer is running at {farmer_rpc_port}."
                f" You can run the farmer by:\n    chia start farmer-only")
        else:
            print(f"Exception from 'farmer' {e}")
    finally:
        farmer_client.close()
        await farmer_client.await_closed()
예제 #6
0
    async def get_additions_and_removals(self,
                                         request: Dict) -> Optional[Dict]:
        if "header_hash" not in request:
            raise ValueError("No header_hash in request")
        header_hash = bytes32.from_hexstr(request["header_hash"])

        block: Optional[
            FullBlock] = await self.service.block_store.get_full_block(
                header_hash)
        if block is None:
            raise ValueError(f"Block {header_hash.hex()} not found")

        async with self.service._blockchain_lock_low_priority:
            if self.service.blockchain.height_to_hash(
                    block.height) != header_hash:
                raise ValueError(
                    f"Block at {header_hash.hex()} is no longer in the blockchain (it's in a fork)"
                )
            additions: List[
                CoinRecord] = await self.service.coin_store.get_coins_added_at_height(
                    block.height)
            removals: List[
                CoinRecord] = await self.service.coin_store.get_coins_removed_at_height(
                    block.height)

        return {"additions": additions, "removals": removals}
예제 #7
0
    async def get_puzzle_and_solution(self, request: Dict) -> Optional[Dict]:
        coin_name: bytes32 = bytes32.from_hexstr(request["coin_id"])
        height = request["height"]
        coin_record = await self.service.coin_store.get_coin_record(coin_name)
        if coin_record is None or not coin_record.spent or coin_record.spent_block_index != height:
            raise ValueError(
                f"Invalid height {height}. coin record {coin_record}")

        header_hash = self.service.blockchain.height_to_hash(height)
        assert header_hash is not None
        block: Optional[
            FullBlock] = await self.service.block_store.get_full_block(
                header_hash)

        if block is None or block.transactions_generator is None:
            raise ValueError("Invalid block or block generator")

        block_generator: Optional[
            BlockGenerator] = await self.service.blockchain.get_block_generator(
                block)
        assert block_generator is not None
        error, puzzle, solution = get_puzzle_and_solution_for_coin(
            block_generator, coin_name,
            self.service.constants.MAX_BLOCK_COST_CLVM)
        if error is not None:
            raise ValueError(f"Error: {error}")

        puzzle_ser: SerializedProgram = SerializedProgram.from_program(
            Program.to(puzzle))
        solution_ser: SerializedProgram = SerializedProgram.from_program(
            Program.to(solution))
        return {
            "coin_solution": CoinSpend(coin_record.coin, puzzle_ser,
                                       solution_ser)
        }
예제 #8
0
    async def get_mempool_item_by_tx_id(self, request: Dict) -> Optional[Dict]:
        if "tx_id" not in request:
            raise ValueError("No tx_id in request")
        tx_id: bytes32 = bytes32.from_hexstr(request["tx_id"])

        item = self.service.mempool_manager.get_mempool_item(tx_id)
        if item is None:
            raise ValueError(f"Tx id 0x{tx_id.hex()} not in the mempool")

        return {"mempool_item": item}
예제 #9
0
    async def get_block(self, request: Dict) -> Optional[Dict]:
        if "header_hash" not in request:
            raise ValueError("No header_hash in request")
        header_hash = bytes32.from_hexstr(request["header_hash"])

        block: Optional[
            FullBlock] = await self.service.block_store.get_full_block(
                header_hash)
        if block is None:
            raise ValueError(f"Block {header_hash.hex()} not found")

        return {"block": block}
예제 #10
0
    async def get_network_space(self, request: Dict) -> Optional[Dict]:
        """
        Retrieves an estimate of total space validating the chain
        between two block header hashes.
        """
        if "newer_block_header_hash" not in request or "older_block_header_hash" not in request:
            raise ValueError(
                "Invalid request. newer_block_header_hash and older_block_header_hash required"
            )
        newer_block_hex = request["newer_block_header_hash"]
        older_block_hex = request["older_block_header_hash"]

        if newer_block_hex == older_block_hex:
            raise ValueError("New and old must not be the same")

        newer_block_bytes = bytes32.from_hexstr(newer_block_hex)
        older_block_bytes = bytes32.from_hexstr(older_block_hex)

        newer_block = await self.service.block_store.get_block_record(
            newer_block_bytes)
        if newer_block is None:
            raise ValueError("Newer block not found")
        older_block = await self.service.block_store.get_block_record(
            older_block_bytes)
        if older_block is None:
            raise ValueError("Newer block not found")
        delta_weight = newer_block.weight - older_block.weight

        delta_iters = newer_block.total_iters - older_block.total_iters
        weight_div_iters = delta_weight / delta_iters
        additional_difficulty_constant = self.service.constants.DIFFICULTY_CONSTANT_FACTOR
        eligible_plots_filter_multiplier = 2**self.service.constants.NUMBER_ZERO_BITS_PLOT_FILTER
        network_space_bytes_estimate = (UI_ACTUAL_SPACE_CONSTANT_FACTOR *
                                        weight_div_iters *
                                        additional_difficulty_constant *
                                        eligible_plots_filter_multiplier)
        return {"space": uint128(int(network_space_bytes_estimate))}
예제 #11
0
    async def get_coin_record_by_name(self, request: Dict) -> Optional[Dict]:
        """
        Retrieves a coin record by it's name.
        """
        if "name" not in request:
            raise ValueError("Name not in request")
        name = bytes32.from_hexstr(request["name"])

        coin_record: Optional[
            CoinRecord] = await self.service.blockchain.coin_store.get_coin_record(
                name)
        if coin_record is None:
            raise ValueError(f"Coin record 0x{name.hex()} not found")

        return {"coin_record": coin_record}
예제 #12
0
async def get_offers(args: dict, wallet_client: WalletRpcClient,
                     fingerprint: int) -> None:
    id: Optional[str] = args.get("id", None)
    filepath: Optional[str] = args.get("filepath", None)
    exclude_my_offers: bool = args.get("exclude_my_offers", False)
    exclude_taken_offers: bool = args.get("exclude_taken_offers", False)
    include_completed: bool = args.get("include_completed", False)
    summaries: bool = args.get("summaries", False)
    reverse: bool = args.get("reverse", False)
    file_contents: bool = (filepath is not None) or summaries
    records: List[TradeRecord] = []
    if id is None:
        batch_size: int = 10
        start: int = 0
        end: int = start + batch_size

        # Traverse offers page by page
        while True:
            new_records: List[
                TradeRecord] = await wallet_client.get_all_offers(
                    start,
                    end,
                    reverse=reverse,
                    file_contents=file_contents,
                    exclude_my_offers=exclude_my_offers,
                    exclude_taken_offers=exclude_taken_offers,
                    include_completed=include_completed,
                )
            records.extend(new_records)

            # If fewer records were returned than requested, we're done
            if len(new_records) < batch_size:
                break

            start = end
            end += batch_size
    else:
        records = [
            await wallet_client.get_offer(bytes32.from_hexstr(id),
                                          file_contents)
        ]
        if filepath is not None:
            with open(pathlib.Path(filepath), "w") as file:
                file.write(Offer.from_bytes(records[0].offer).to_bech32())
                file.close()

    for record in records:
        await print_trade_record(record, wallet_client, summaries=summaries)
예제 #13
0
    async def get_block_record(self, request: Dict):
        if "header_hash" not in request:
            raise ValueError("header_hash not in request")
        header_hash_str = request["header_hash"]
        header_hash = bytes32.from_hexstr(header_hash_str)
        record: Optional[
            BlockRecord] = self.service.blockchain.try_block_record(
                header_hash)
        if record is None:
            # Fetch from DB
            record = await self.service.blockchain.block_store.get_block_record(
                header_hash)
        if record is None:
            raise ValueError(f"Block {header_hash.hex()} does not exist")

        return {"block_record": record}
예제 #14
0
async def print_offer_summary(wallet_client: WalletRpcClient, sum_dict: dict):
    for asset_id, amount in sum_dict.items():
        if asset_id == "xch":
            wid: str = "1"
            name: str = "XCH"
            unit: int = units["chia"]
        else:
            result = await wallet_client.cat_asset_id_to_name(
                bytes32.from_hexstr(asset_id))
            wid = "Unknown"
            name = asset_id
            unit = units["cat"]
            if result is not None:
                wid = str(result[0])
                name = result[1]
        print(
            f"    - {name} (Wallet ID: {wid}): {Decimal(int(amount)) / unit} ({int(Decimal(amount))} mojos)"
        )
예제 #15
0
async def cancel_offer(args: dict, wallet_client: WalletRpcClient,
                       fingerprint: int) -> None:
    id = bytes32.from_hexstr(args["id"])
    secure: bool = not args["insecure"]
    fee: int = int(Decimal(args["fee"]) * units["chia"])

    trade_record = await wallet_client.get_offer(id, file_contents=True)
    await print_trade_record(trade_record, wallet_client, summaries=True)

    confirmation = input(
        f"Are you sure you wish to cancel offer with ID: {trade_record.trade_id}? (y/n): "
    )
    if confirmation in ["y", "yes"]:
        await wallet_client.cancel_offer(id, secure=secure, fee=fee)
        print(f"Cancelled offer with ID {trade_record.trade_id}")
        if secure:
            print(
                f"Use chia wallet get_offers --id {trade_record.trade_id} -f {fingerprint} to view cancel status"
            )
예제 #16
0
    async def _messages_to_resend(self) -> List[Tuple[Message, Set[bytes32]]]:
        if self.wallet_state_manager is None or self.backup_initialized is False or self._shut_down:
            return []
        messages: List[Tuple[Message, Set[bytes32]]] = []

        records: List[
            TransactionRecord] = await self.wallet_state_manager.tx_store.get_not_sent(
            )

        for record in records:
            if record.spend_bundle is None:
                continue
            msg = make_msg(
                ProtocolMessageTypes.send_transaction,
                wallet_protocol.SendTransaction(record.spend_bundle),
            )
            already_sent = set()
            for peer, status, _ in record.sent_to:
                if status == MempoolInclusionStatus.SUCCESS.value:
                    already_sent.add(bytes32.from_hexstr(peer))
            messages.append((msg, already_sent))

        return messages
예제 #17
0
    async def get_puzzle_and_solution(self, request: Dict) -> Optional[Dict]:
        coin_name: bytes32 = bytes32.from_hexstr(request["coin_id"])
        height = request["height"]
        coin_record = await self.service.coin_store.get_coin_record(coin_name)
        if coin_record is None or not coin_record.spent or coin_record.spent_block_index != height:
            raise ValueError(
                f"Invalid height {height}. coin record {coin_record}")

        header_hash = self.service.blockchain.height_to_hash(height)
        # TODO: address hint error and remove ignore
        #       error: Argument 1 to "get_full_block" of "BlockStore" has incompatible type "Optional[bytes32]";
        #       expected "bytes32"  [arg-type]
        block: Optional[
            FullBlock] = await self.service.block_store.get_full_block(
                header_hash)  # type: ignore[arg-type]  # noqa: E501

        if block is None or block.transactions_generator is None:
            raise ValueError("Invalid block or block generator")

        block_generator: Optional[
            BlockGenerator] = await self.service.blockchain.get_block_generator(
                block)
        assert block_generator is not None
        error, puzzle, solution = get_puzzle_and_solution_for_coin(
            block_generator, coin_name,
            self.service.constants.MAX_BLOCK_COST_CLVM)
        if error is not None:
            raise ValueError(f"Error: {error}")

        puzzle_ser: SerializedProgram = SerializedProgram.from_program(
            Program.to(puzzle))
        solution_ser: SerializedProgram = SerializedProgram.from_program(
            Program.to(solution))
        return {
            "coin_solution": CoinSpend(coin_record.coin, puzzle_ser,
                                       solution_ser)
        }
예제 #18
0
async def show(args: dict, wallet_client: WalletRpcClient,
               fingerprint: int) -> None:

    config = load_config(DEFAULT_ROOT_PATH, "config.yaml")
    self_hostname = config["self_hostname"]
    farmer_rpc_port = config["farmer"]["rpc_port"]
    farmer_client = await FarmerRpcClient.create(self_hostname,
                                                 uint16(farmer_rpc_port),
                                                 DEFAULT_ROOT_PATH, config)
    address_prefix = config["network_overrides"]["config"][
        config["selected_network"]]["address_prefix"]
    summaries_response = await wallet_client.get_wallets()
    wallet_id_passed_in = args.get("id", None)
    plot_counts: Counter = Counter()
    try:
        pool_state_list: List = (await
                                 farmer_client.get_pool_state())["pool_state"]
        harvesters = await farmer_client.get_harvesters()
        for d in harvesters["harvesters"]:
            for plot in d["plots"]:
                if plot.get("pool_contract_puzzle_hash", None) is not None:
                    # Non pooled plots will have a None pool_contract_puzzle_hash
                    plot_counts[hexstr_to_bytes(
                        plot["pool_contract_puzzle_hash"])] += 1
    except Exception as e:
        if isinstance(e, aiohttp.ClientConnectorError):
            print(
                f"Connection error. Check if farmer is running at {farmer_rpc_port}."
                f" You can run the farmer by:\n    chia start farmer-only")
        else:
            print(f"Exception from 'wallet' {e}")
        farmer_client.close()
        await farmer_client.await_closed()
        return
    pool_state_dict: Dict[bytes32, Dict] = {
        bytes32.from_hexstr(pool_state_item["pool_config"]["launcher_id"]):
        pool_state_item
        for pool_state_item in pool_state_list
    }
    if wallet_id_passed_in is not None:
        for summary in summaries_response:
            typ = WalletType(int(summary["type"]))
            if summary[
                    "id"] == wallet_id_passed_in and typ != WalletType.POOLING_WALLET:
                print(
                    f"Wallet with id: {wallet_id_passed_in} is not a pooling wallet. Please provide a different id."
                )
                return
        pool_wallet_info, _ = await wallet_client.pw_status(wallet_id_passed_in
                                                            )
        await pprint_pool_wallet_state(
            wallet_client,
            wallet_id_passed_in,
            pool_wallet_info,
            address_prefix,
            pool_state_dict,
            plot_counts,
        )
    else:
        print(f"Wallet height: {await wallet_client.get_height_info()}")
        print(
            f"Sync status: {'Synced' if (await wallet_client.get_synced()) else 'Not synced'}"
        )
        for summary in summaries_response:
            wallet_id = summary["id"]
            typ = WalletType(int(summary["type"]))
            if typ == WalletType.POOLING_WALLET:
                print(f"Wallet id {wallet_id}: ")
                pool_wallet_info, _ = await wallet_client.pw_status(wallet_id)
                await pprint_pool_wallet_state(
                    wallet_client,
                    wallet_id,
                    pool_wallet_info,
                    address_prefix,
                    pool_state_dict,
                    plot_counts,
                )
                print("")
    farmer_client.close()
    await farmer_client.await_closed()
예제 #19
0
    async def get_recent_signage_point_or_eos(self, request: Dict):
        if "sp_hash" not in request:
            challenge_hash: bytes32 = bytes32.from_hexstr(
                request["challenge_hash"])
            # This is the case of getting an end of slot
            eos_tuple = self.service.full_node_store.recent_eos.get(
                challenge_hash)
            if not eos_tuple:
                raise ValueError(
                    f"Did not find eos {challenge_hash.hex()} in cache")
            eos, time_received = eos_tuple

            # If it's still in the full node store, it's not reverted
            if self.service.full_node_store.get_sub_slot(
                    eos.challenge_chain.get_hash()):
                return {
                    "eos": eos,
                    "time_received": time_received,
                    "reverted": False
                }

            # Otherwise we can backtrack from peak to find it in the blockchain
            curr: Optional[BlockRecord] = self.service.blockchain.get_peak()
            if curr is None:
                raise ValueError("No blocks in the chain")

            number_of_slots_searched = 0
            while number_of_slots_searched < 10:
                if curr.first_in_sub_slot:
                    assert curr.finished_challenge_slot_hashes is not None
                    if curr.finished_challenge_slot_hashes[
                            -1] == eos.challenge_chain.get_hash():
                        # Found this slot in the blockchain
                        return {
                            "eos": eos,
                            "time_received": time_received,
                            "reverted": False
                        }
                    number_of_slots_searched += len(
                        curr.finished_challenge_slot_hashes)
                curr = self.service.blockchain.try_block_record(curr.prev_hash)
                if curr is None:
                    # Got to the beginning of the blockchain without finding the slot
                    return {
                        "eos": eos,
                        "time_received": time_received,
                        "reverted": True
                    }

            # Backtracked through 10 slots but still did not find it
            return {
                "eos": eos,
                "time_received": time_received,
                "reverted": True
            }

        # Now we handle the case of getting a signage point
        sp_hash: bytes32 = bytes32.from_hexstr(request["sp_hash"])
        sp_tuple = self.service.full_node_store.recent_signage_points.get(
            sp_hash)
        if sp_tuple is None:
            raise ValueError(f"Did not find sp {sp_hash.hex()} in cache")

        sp, time_received = sp_tuple

        # If it's still in the full node store, it's not reverted
        if self.service.full_node_store.get_signage_point(sp_hash):
            return {
                "signage_point": sp,
                "time_received": time_received,
                "reverted": False
            }

        # Otherwise we can backtrack from peak to find it in the blockchain
        rc_challenge: bytes32 = sp.rc_vdf.challenge
        next_b: Optional[BlockRecord] = None
        curr_b_optional: Optional[
            BlockRecord] = self.service.blockchain.get_peak()
        assert curr_b_optional is not None
        curr_b: BlockRecord = curr_b_optional

        for _ in range(200):
            sp_total_iters = sp.cc_vdf.number_of_iterations + curr_b.ip_sub_slot_total_iters(
                self.service.constants)
            if curr_b.reward_infusion_new_challenge == rc_challenge:
                if next_b is None:
                    return {
                        "signage_point": sp,
                        "time_received": time_received,
                        "reverted": False
                    }
                next_b_total_iters = next_b.ip_sub_slot_total_iters(
                    self.service.constants) + next_b.ip_iters(
                        self.service.constants)

                return {
                    "signage_point": sp,
                    "time_received": time_received,
                    "reverted": sp_total_iters > next_b_total_iters,
                }
            if curr_b.finished_reward_slot_hashes is not None:
                assert curr_b.finished_challenge_slot_hashes is not None
                for eos_rc in curr_b.finished_challenge_slot_hashes:
                    if eos_rc == rc_challenge:
                        if next_b is None:
                            return {
                                "signage_point": sp,
                                "time_received": time_received,
                                "reverted": False
                            }
                        next_b_total_iters = next_b.ip_sub_slot_total_iters(
                            self.service.constants) + next_b.ip_iters(
                                self.service.constants)
                        return {
                            "signage_point": sp,
                            "time_received": time_received,
                            "reverted": sp_total_iters > next_b_total_iters,
                        }
            next_b = curr_b
            curr_b_optional = self.service.blockchain.try_block_record(
                curr_b.prev_hash)
            if curr_b_optional is None:
                break
            curr_b = curr_b_optional

        return {
            "signage_point": sp,
            "time_received": time_received,
            "reverted": True
        }
예제 #20
0
async def create(args: dict, wallet_client: WalletRpcClient,
                 fingerprint: int) -> None:
    state = args["state"]
    prompt = not args.get("yes", False)
    fee = Decimal(args.get("fee", 0))
    fee_mojos = uint64(int(fee * units["chia"]))
    target_puzzle_hash: Optional[bytes32]
    # Could use initial_pool_state_from_dict to simplify
    if state == "SELF_POOLING":
        pool_url: Optional[str] = None
        relative_lock_height = uint32(0)
        target_puzzle_hash = None  # wallet will fill this in
    elif state == "FARMING_TO_POOL":
        config = load_config(DEFAULT_ROOT_PATH, "config.yaml")
        enforce_https = config["full_node"]["selected_network"] == "mainnet"
        pool_url = str(args["pool_url"])
        if enforce_https and not pool_url.startswith("https://"):
            print(f"Pool URLs must be HTTPS on mainnet {pool_url}. Aborting.")
            return
        json_dict = await create_pool_args(pool_url)
        relative_lock_height = json_dict["relative_lock_height"]
        target_puzzle_hash = bytes32.from_hexstr(
            json_dict["target_puzzle_hash"])
    else:
        raise ValueError(
            "Plot NFT must be created in SELF_POOLING or FARMING_TO_POOL state."
        )

    pool_msg = f" and join pool: {pool_url}" if pool_url else ""
    print(f"Will create a plot NFT{pool_msg}.")
    if prompt:
        user_input: str = input("Confirm [n]/y: ")
    else:
        user_input = "yes"

    if user_input.lower() == "y" or user_input.lower() == "yes":
        try:
            tx_record: TransactionRecord = await wallet_client.create_new_pool_wallet(
                target_puzzle_hash,
                pool_url,
                relative_lock_height,
                "localhost:5000",
                "new",
                state,
                fee_mojos,
            )
            start = time.time()
            while time.time() - start < 10:
                await asyncio.sleep(0.1)
                tx = await wallet_client.get_transaction(
                    str(1), tx_record.name)
                if len(tx.sent_to) > 0:
                    print(f"Transaction submitted to nodes: {tx.sent_to}")
                    print(
                        f"Do chia wallet get_transaction -f {fingerprint} -tx 0x{tx_record.name} to get status"
                    )
                    return None
        except Exception as e:
            print(f"Error creating plot NFT: {e}")
        return
    print("Aborting.")
예제 #21
0
 async def set_payout_instructions(self, request: Dict) -> Dict:
     launcher_id: bytes32 = bytes32.from_hexstr(request["launcher_id"])
     await self.service.set_payout_instructions(
         launcher_id, request["payout_instructions"])
     return {}
예제 #22
0
    async def set_user_info(
        self,
        interval: uint64,
        limit: uint64,
        origin_parent_id: str,
        origin_puzzle_hash: str,
        origin_amount: uint64,
        admin_pubkey: str,
    ) -> None:
        admin_pubkey_bytes = hexstr_to_bytes(admin_pubkey)

        assert self.rl_info.user_pubkey is not None
        origin = Coin(
            bytes32.from_hexstr(origin_parent_id),
            bytes32.from_hexstr(origin_puzzle_hash),
            origin_amount,
        )
        rl_puzzle = rl_puzzle_for_pk(
            pubkey=self.rl_info.user_pubkey,
            rate_amount=limit,
            interval_time=interval,
            origin_id=origin.name(),
            clawback_pk=admin_pubkey_bytes,
        )

        rl_puzzle_hash = rl_puzzle.get_tree_hash()

        new_rl_info = RLInfo(
            "user",
            admin_pubkey_bytes,
            self.rl_info.user_pubkey,
            limit,
            interval,
            origin,
            origin.name(),
            rl_puzzle_hash,
            True,
        )
        rl_puzzle_hash = rl_puzzle.get_tree_hash()
        if await self.wallet_state_manager.puzzle_store.puzzle_hash_exists(
                rl_puzzle_hash):
            raise ValueError(
                "Cannot create multiple Rate Limited wallets under the same keys. This will change in a future release."
            )
        user_pubkey: G1Element = G1Element.from_bytes(self.rl_info.user_pubkey)
        index = await self.wallet_state_manager.puzzle_store.index_for_pubkey(
            user_pubkey)
        assert index is not None
        record = DerivationRecord(
            index,
            rl_puzzle_hash,
            user_pubkey,
            WalletType.RATE_LIMITED,
            self.id(),
        )

        aggregation_puzzlehash = self.rl_get_aggregation_puzzlehash(
            new_rl_info.rl_puzzle_hash)
        record2 = DerivationRecord(
            index + 1,
            aggregation_puzzlehash,
            user_pubkey,
            WalletType.RATE_LIMITED,
            self.id(),
        )
        await self.wallet_state_manager.puzzle_store.add_derivation_paths(
            [record, record2])
        self.wallet_state_manager.set_coin_with_puzzlehash_created_callback(
            aggregation_puzzlehash, self.aggregate_this_coin)

        data_str = json.dumps(new_rl_info.to_json_dict())
        new_wallet_info = WalletInfo(self.id(), self.wallet_info.name,
                                     self.type(), data_str)
        await self.wallet_state_manager.user_store.update_wallet(
            new_wallet_info, False)
        await self.wallet_state_manager.add_new_wallet(self, self.id())
        self.wallet_info = new_wallet_info
        self.rl_info = new_rl_info