mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2026-09-05 02:24:21 -05:00
Merge pull request #11918 from Chia-Network/nft1_claim
Add set_nft_did API
This commit is contained in:
@@ -137,6 +137,7 @@ class WalletRpcApi:
|
||||
"/nft_mint_nft": self.nft_mint_nft,
|
||||
"/nft_get_nfts": self.nft_get_nfts,
|
||||
"/nft_get_by_did": self.nft_get_by_did,
|
||||
"/nft_set_nft_did": self.nft_set_nft_did,
|
||||
"/nft_get_wallet_did": self.nft_get_wallet_did,
|
||||
"/nft_get_wallets_with_dids": self.nft_get_wallets_with_dids,
|
||||
"/nft_get_info": self.nft_get_info,
|
||||
@@ -1399,6 +1400,22 @@ class WalletRpcApi:
|
||||
nft_info_list.append(nft_puzzles.get_nft_info_from_puzzle(nft))
|
||||
return {"wallet_id": wallet_id, "success": True, "nft_list": nft_info_list}
|
||||
|
||||
async def nft_set_nft_did(self, request):
|
||||
try:
|
||||
assert self.service.wallet_state_manager is not None
|
||||
wallet_id = uint32(request["wallet_id"])
|
||||
nft_wallet: NFTWallet = self.service.wallet_state_manager.wallets[wallet_id]
|
||||
did_id: Optional[bytes32] = None
|
||||
if "did_id" in request:
|
||||
did_id = decode_puzzle_hash(request["did_id"])
|
||||
nft_coin_info = nft_wallet.get_nft_coin_by_id(bytes32.from_hexstr(request["nft_coin_id"]))
|
||||
fee = uint64(request.get("fee", 0))
|
||||
spend_bundle = await nft_wallet.set_nft_did(nft_coin_info, did_id, fee=fee)
|
||||
return {"wallet_id": wallet_id, "success": True, "spend_bundle": spend_bundle}
|
||||
except Exception as e:
|
||||
log.exception(f"Failed to set DID on NFT: {e}")
|
||||
return {"success": False, "error": f"Failed to set DID on NFT: {e}"}
|
||||
|
||||
async def nft_get_by_did(self, request) -> Dict:
|
||||
did_id: Optional[bytes32] = None
|
||||
if "did_id" in request:
|
||||
@@ -1469,7 +1486,7 @@ class WalletRpcApi:
|
||||
txs = await nft_wallet.generate_signed_transaction(
|
||||
[nft_coin_info.coin.amount],
|
||||
[puzzle_hash],
|
||||
coins=[nft_coin_info.coin],
|
||||
coins={nft_coin_info.coin},
|
||||
fee=fee,
|
||||
)
|
||||
spend_bundle: Optional[SpendBundle] = None
|
||||
|
||||
@@ -226,7 +226,7 @@ def create_ownership_layer_puzzle(
|
||||
|
||||
def create_ownership_layer_transfer_solution(
|
||||
new_did: bytes,
|
||||
new_did_inner_hash: bytes32,
|
||||
new_did_inner_hash: bytes,
|
||||
trade_prices_list: List[List[int]],
|
||||
new_puzhash: bytes32,
|
||||
) -> Program:
|
||||
@@ -256,7 +256,7 @@ def create_ownership_layer_transfer_solution(
|
||||
return solution
|
||||
|
||||
|
||||
def get_metadata_and_phs(unft: UncurriedNFT, puzzle: Program, solution: SerializedProgram) -> Tuple[Program, bytes32]:
|
||||
def get_metadata_and_phs(unft: UncurriedNFT, solution: SerializedProgram) -> Tuple[Program, bytes32]:
|
||||
conditions = unft.p2_puzzle.run(unft.get_innermost_solution(solution.to_program()))
|
||||
metadata = unft.metadata
|
||||
puzhash_for_derivation: Optional[bytes32] = None
|
||||
@@ -285,7 +285,7 @@ def get_metadata_and_phs(unft: UncurriedNFT, puzzle: Program, solution: Serializ
|
||||
def recurry_nft_puzzle(unft: UncurriedNFT, solution: Program, sp2_puzzle: Program) -> Program:
|
||||
log.debug("Generating NFT puzzle with ownership support: %s", disassemble(solution))
|
||||
conditions = solution.at("frfr").as_iter()
|
||||
new_did_id = None
|
||||
new_did_id = unft.owner_did
|
||||
new_puzhash = None
|
||||
for condition in conditions:
|
||||
if condition.first().as_int() == -10:
|
||||
@@ -298,3 +298,13 @@ def recurry_nft_puzzle(unft: UncurriedNFT, solution: Program, sp2_puzzle: Progra
|
||||
assert unft.transfer_program
|
||||
inner_puzzle = construct_ownership_layer(new_did_id, unft.transfer_program, sp2_puzzle)
|
||||
return inner_puzzle
|
||||
|
||||
|
||||
def get_new_owner_did(solution: Program) -> Optional[bytes32]:
|
||||
conditions = solution.at("rrfffrfr").as_iter()
|
||||
new_did_id = None
|
||||
for condition in conditions:
|
||||
if condition.first().as_int() == -10:
|
||||
# this is the change owner magic condition
|
||||
new_did_id = condition.at("rf").atom
|
||||
return new_did_id
|
||||
|
||||
@@ -192,7 +192,7 @@ class NFTWallet:
|
||||
self.log.debug("Puzzle solution received to wallet: %s", self.wallet_info)
|
||||
coin_name = coin_spend.coin.name()
|
||||
puzzle: Program = Program.from_bytes(bytes(coin_spend.puzzle_reveal))
|
||||
delegated_puz_solution: Program = Program.from_bytes(bytes(coin_spend.solution)).rest().rest().first().first()
|
||||
delegated_puz_solution: Program = coin_spend.solution.to_program().rest().rest().first().first()
|
||||
# At this point, the puzzle must be a NFT puzzle.
|
||||
# This method will be called only when the wallet state manager uncurried this coin as a NFT puzzle.
|
||||
|
||||
@@ -202,7 +202,7 @@ class NFTWallet:
|
||||
)
|
||||
singleton_id = uncurried_nft.singleton_launcher_id
|
||||
parent_inner_puzhash = uncurried_nft.nft_state_layer.get_tree_hash()
|
||||
metadata, p2_puzzle_hash = get_metadata_and_phs(uncurried_nft, puzzle, coin_spend.solution)
|
||||
metadata, p2_puzzle_hash = get_metadata_and_phs(uncurried_nft, coin_spend.solution)
|
||||
self.log.debug("Got back puzhash from solution: %s", p2_puzzle_hash)
|
||||
self.log.debug("Got back updated metadata: %s", metadata)
|
||||
derivation_record: Optional[
|
||||
@@ -314,24 +314,27 @@ class NFTWallet:
|
||||
async def get_did_approval_info(
|
||||
self,
|
||||
nft_id: bytes32,
|
||||
did_id: bytes32 = None,
|
||||
) -> Tuple[bytes32, SpendBundle]:
|
||||
"""Get DID spend with announcement created we need to transfer NFT with did with current inner hash of DID
|
||||
|
||||
We also store `did_id` and then iterate to find the did wallet as we'd otherwise have to subscribe to
|
||||
any changes to DID wallet and storing wallet_id is not guaranteed to be consistent on wallet crash/reset.
|
||||
"""
|
||||
if did_id is None:
|
||||
did_id = self.did_id
|
||||
for _, wallet in self.wallet_state_manager.wallets.items():
|
||||
self.log.debug("Checking wallet type %s", wallet.type())
|
||||
if wallet.type() == WalletType.DISTRIBUTED_ID:
|
||||
self.log.debug("Found a DID wallet, checking did: %r == %r", wallet.get_my_DID(), self.did_id)
|
||||
if bytes32.fromhex(wallet.get_my_DID()) == self.did_id:
|
||||
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_id: %s", nft_id)
|
||||
did_bundle = await wallet.create_message_spend(puzzle_announcements=[nft_id])
|
||||
self.log.debug("Sending DID announcement from puzzle: %s", did_bundle.removals())
|
||||
did_inner_hash = wallet.did_info.current_inner.get_tree_hash()
|
||||
break
|
||||
else:
|
||||
raise ValueError(f"Missing DID Wallet for did_id: {self.did_id}")
|
||||
raise ValueError(f"Missing DID Wallet for did_id: {did_id}")
|
||||
return did_inner_hash, did_bundle
|
||||
|
||||
async def generate_new_nft(
|
||||
@@ -412,10 +415,11 @@ class NFTWallet:
|
||||
record: Optional[DerivationRecord] = None
|
||||
# Create inner solution for eve spend
|
||||
if did_id is not None:
|
||||
did_inner_hash, did_bundle = await self.get_did_approval_info(launcher_coin.name())
|
||||
did_inner_hash = b""
|
||||
if did_id != b"":
|
||||
did_inner_hash, did_bundle = await self.get_did_approval_info(launcher_coin.name())
|
||||
bundles_to_agg.append(did_bundle)
|
||||
innersol = create_ownership_layer_transfer_solution(did_id, did_inner_hash, [], target_puzzle_hash)
|
||||
bundles_to_agg.append(did_bundle)
|
||||
|
||||
self.log.debug("Created an inner DID NFT solution: %s", disassemble(innersol))
|
||||
else:
|
||||
condition_list = [make_create_coin_condition(target_puzzle_hash, amount, [target_puzzle_hash])]
|
||||
@@ -567,7 +571,6 @@ class NFTWallet:
|
||||
condition_list = [
|
||||
[51, puzzle_hash, coin.amount, [puzzle_hash]],
|
||||
[-24, NFT_METADATA_UPDATER, (key, uri)],
|
||||
[-10, [], [], []],
|
||||
]
|
||||
inner_solution = Program.to([[solution_for_conditions(condition_list)]])
|
||||
else:
|
||||
@@ -703,9 +706,10 @@ class NFTWallet:
|
||||
coin_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
puzzle_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
ignore_max_send_amount: bool = False,
|
||||
new_owner: Optional[bytes32] = None,
|
||||
new_did_inner_hash: Optional[bytes32] = None,
|
||||
new_owner: Optional[bytes] = None,
|
||||
new_did_inner_hash: Optional[bytes] = None,
|
||||
trade_prices_list: Optional[Program] = None,
|
||||
additional_bundles: List[SpendBundle] = [],
|
||||
) -> List[TransactionRecord]:
|
||||
if memos is None:
|
||||
memos = [[] for _ in range(len(puzzle_hashes))]
|
||||
@@ -727,9 +731,13 @@ class NFTWallet:
|
||||
coins=coins,
|
||||
coin_announcements_to_consume=coin_announcements_to_consume,
|
||||
puzzle_announcements_to_consume=puzzle_announcements_to_consume,
|
||||
new_owner=new_owner,
|
||||
new_did_inner_hash=new_did_inner_hash,
|
||||
trade_prices_list=trade_prices_list,
|
||||
)
|
||||
spend_bundle = await self.sign(unsigned_spend_bundle)
|
||||
|
||||
spend_bundle = await self.sign(unsigned_spend_bundle)
|
||||
spend_bundle = SpendBundle.aggregate([spend_bundle] + additional_bundles)
|
||||
tx_list = [
|
||||
TransactionRecord(
|
||||
confirmed_at_height=uint32(0),
|
||||
@@ -782,8 +790,8 @@ class NFTWallet:
|
||||
coins: Set[Coin] = None,
|
||||
coin_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
puzzle_announcements_to_consume: Optional[Set[Announcement]] = None,
|
||||
new_owner: Optional[bytes32] = None,
|
||||
new_did_inner_hash: Optional[bytes32] = None,
|
||||
new_owner: Optional[bytes] = None,
|
||||
new_did_inner_hash: Optional[bytes] = None,
|
||||
trade_prices_list: Optional[Program] = None,
|
||||
) -> Tuple[SpendBundle, Optional[TransactionRecord]]:
|
||||
if coins is None or len(coins) > 1:
|
||||
@@ -840,4 +848,39 @@ class NFTWallet:
|
||||
|
||||
unsigned_spend_bundle = SpendBundle.aggregate([nft_spend_bundle, chia_spend_bundle])
|
||||
|
||||
return (unsigned_spend_bundle, chia_tx)
|
||||
return unsigned_spend_bundle, chia_tx
|
||||
|
||||
async def set_nft_did(
|
||||
self, nft_coin_info: NFTCoinInfo, did_id: Optional[bytes32], fee: uint64 = uint64(0)
|
||||
) -> 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)
|
||||
nft_id = unft.singleton_launcher_id
|
||||
puzzle_hashes_to_sign = [unft.p2_puzzle.get_tree_hash()]
|
||||
if did_id:
|
||||
did_inner_hash, did_bundle = await self.get_did_approval_info(nft_id, did_id)
|
||||
additional_bundles = [did_bundle]
|
||||
else:
|
||||
did_inner_hash = None
|
||||
additional_bundles = []
|
||||
nft_tx_record = await self.generate_signed_transaction(
|
||||
[nft_coin_info.coin.amount],
|
||||
puzzle_hashes_to_sign,
|
||||
fee,
|
||||
{nft_coin_info.coin},
|
||||
new_owner=did_id if did_id else b"",
|
||||
new_did_inner_hash=did_inner_hash if did_inner_hash else b"",
|
||||
additional_bundles=additional_bundles,
|
||||
)
|
||||
spend_bundle: Optional[SpendBundle] = None
|
||||
for tx in nft_tx_record:
|
||||
if spend_bundle is None:
|
||||
spend_bundle = tx.spend_bundle
|
||||
else:
|
||||
spend_bundle.aggregate([tx.spend_bundle])
|
||||
await self.standard_wallet.push_transaction(tx)
|
||||
self.wallet_state_manager.state_changed("nft_coin_did_set", self.wallet_info.id)
|
||||
if spend_bundle:
|
||||
return spend_bundle
|
||||
else:
|
||||
raise ValueError("Couldn't set DID on given NFT")
|
||||
|
||||
@@ -42,7 +42,7 @@ from chia.wallet.did_wallet.did_wallet import DIDWallet
|
||||
from chia.wallet.did_wallet.did_wallet_puzzles import DID_INNERPUZ_MOD, create_fullpuz, match_did_puzzle
|
||||
from chia.wallet.key_val_store import KeyValStore
|
||||
from chia.wallet.nft_wallet.nft_info import NFTWalletInfo
|
||||
from chia.wallet.nft_wallet.nft_puzzles import get_metadata_and_phs
|
||||
from chia.wallet.nft_wallet.nft_puzzles import get_metadata_and_phs, get_new_owner_did
|
||||
from chia.wallet.nft_wallet.nft_wallet import NFTWallet
|
||||
from chia.wallet.nft_wallet.uncurry_nft import UncurriedNFT
|
||||
from chia.wallet.outer_puzzles import AssetType
|
||||
@@ -721,7 +721,16 @@ class WalletStateManager:
|
||||
"""
|
||||
wallet_id = None
|
||||
wallet_type = None
|
||||
did_id = uncurried_nft.owner_did
|
||||
did_id = None
|
||||
if uncurried_nft.supports_did:
|
||||
# Try to get the latest owner DID
|
||||
did_id = get_new_owner_did(coin_spend.solution.to_program())
|
||||
if did_id is None:
|
||||
# No DID owner update, use the original DID
|
||||
did_id = uncurried_nft.owner_did
|
||||
if did_id == b"":
|
||||
# Owner DID is updated to None
|
||||
did_id = None
|
||||
self.log.debug("Handling NFT: %s, DID: %s", coin_spend, did_id)
|
||||
for wallet_info in await self.get_all_wallet_info_entries(wallet_type=WalletType.NFT):
|
||||
nft_wallet_info: NFTWalletInfo = NFTWalletInfo.from_json_dict(json.loads(wallet_info.data))
|
||||
@@ -750,7 +759,6 @@ class WalletStateManager:
|
||||
)
|
||||
metadata, p2_puzzle_hash = get_metadata_and_phs(
|
||||
uncurried_nft,
|
||||
Program.from_bytes(bytes(coin_spend.puzzle_reveal)),
|
||||
coin_spend.solution,
|
||||
)
|
||||
derivation_record: Optional[
|
||||
|
||||
@@ -853,6 +853,7 @@ async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) ->
|
||||
wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
|
||||
wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
|
||||
api_0 = WalletRpcApi(wallet_node_0)
|
||||
api_1 = WalletRpcApi(wallet_node_1)
|
||||
ph = await wallet_0.get_new_puzzlehash()
|
||||
ph1 = await wallet_1.get_new_puzzlehash()
|
||||
|
||||
@@ -931,6 +932,7 @@ async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) ->
|
||||
assert coins_response.get("success")
|
||||
coins = coins_response["nft_list"]
|
||||
assert len(coins) == 1
|
||||
assert coins[0].owner_did.hex() == hex_did_id
|
||||
|
||||
try:
|
||||
wallet_1.wallet_state_manager.wallets[2]
|
||||
@@ -945,6 +947,8 @@ async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) ->
|
||||
nft_coin_id=coins[0].nft_coin_id.hex(),
|
||||
)
|
||||
)
|
||||
tx = await did_wallet.transfer_did(ph1, uint64(0), True)
|
||||
assert tx
|
||||
assert resp.get("success")
|
||||
sb = resp["spend_bundle"]
|
||||
assert compute_memos(sb)
|
||||
@@ -961,9 +965,53 @@ async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) ->
|
||||
time_left -= 0.5
|
||||
else:
|
||||
raise AssertionError("NFT not transferred")
|
||||
# Check if the NFT owner DID is reset
|
||||
resp = await api_1.nft_get_by_did(dict())
|
||||
assert resp.get("success")
|
||||
nft_wallet_id_1 = resp.get("wallet_id")
|
||||
time_left = 10.0
|
||||
while time_left > 0:
|
||||
coins_response = await api_1.nft_get_nfts(dict(wallet_id=nft_wallet_id_1))
|
||||
if len(coins_response["nft_list"]) == 0:
|
||||
break
|
||||
await asyncio.sleep(0.5)
|
||||
time_left -= 0.5
|
||||
assert coins_response.get("success")
|
||||
assert len(coins_response["nft_list"]) == 1
|
||||
assert coins_response["nft_list"][0].owner_did is None
|
||||
nft_coin_id = coins_response["nft_list"][0].nft_coin_id
|
||||
# Set DID
|
||||
|
||||
nft_wallet_1 = wallet_1.wallet_state_manager.wallets[2]
|
||||
await time_out_assert(15, len, 1, nft_wallet_1.my_nft_coins)
|
||||
resp = await api_1.nft_set_nft_did(
|
||||
dict(wallet_id=nft_wallet_id_1, did_id=hmr_did_id, nft_coin_id=nft_coin_id.hex())
|
||||
)
|
||||
assert resp.get("success")
|
||||
|
||||
for i in range(1, num_blocks):
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph1))
|
||||
|
||||
time_left = 5.0
|
||||
coins_response = {}
|
||||
while time_left > 0:
|
||||
coins_response = await api_1.nft_get_by_did(dict(did_id=hmr_did_id))
|
||||
if coins_response.get("wallet_id"):
|
||||
break
|
||||
await asyncio.sleep(0.5)
|
||||
time_left -= 0.5
|
||||
nft_wallet_1_id = coins_response.get("wallet_id")
|
||||
assert nft_wallet_1_id
|
||||
# Check NFT DID
|
||||
time_left = 15.0
|
||||
while time_left > 0:
|
||||
resp = await api_1.nft_get_nfts(dict(wallet_id=nft_wallet_1_id))
|
||||
if coins_response.get("nft_list"):
|
||||
break
|
||||
await asyncio.sleep(0.5)
|
||||
time_left -= 0.5
|
||||
assert resp.get("success")
|
||||
coins = resp["nft_list"]
|
||||
assert len(coins) == 1
|
||||
assert coins[0].owner_did.hex() == hex_did_id
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -1074,7 +1122,7 @@ async def test_update_metadata_for_nft_did(two_wallet_nodes: Any, trusted: Any)
|
||||
for i in range(1, num_blocks):
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
||||
# check that new URI was added
|
||||
time_left = 5.0
|
||||
time_left = 10.0
|
||||
while time_left > 0:
|
||||
coins_response = await api_0.nft_get_nfts(dict(wallet_id=nft_wallet_0_id))
|
||||
try:
|
||||
@@ -1095,3 +1143,185 @@ async def test_update_metadata_for_nft_did(two_wallet_nodes: Any, trusted: Any)
|
||||
raise
|
||||
await asyncio.sleep(0.5)
|
||||
time_left -= 0.5
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"trusted",
|
||||
[True, False],
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_nft_set_did(two_wallet_nodes: Any, trusted: Any) -> None:
|
||||
num_blocks = 5
|
||||
full_nodes, wallets = two_wallet_nodes
|
||||
full_node_api: FullNodeSimulator = full_nodes[0]
|
||||
full_node_server = full_node_api.server
|
||||
wallet_node_0, server_0 = wallets[0]
|
||||
wallet_node_1, server_1 = wallets[1]
|
||||
wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
|
||||
api_0 = WalletRpcApi(wallet_node_0)
|
||||
ph = await wallet_0.get_new_puzzlehash()
|
||||
|
||||
if trusted:
|
||||
wallet_node_0.config["trusted_peers"] = {
|
||||
full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
|
||||
}
|
||||
wallet_node_1.config["trusted_peers"] = {
|
||||
full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
|
||||
}
|
||||
else:
|
||||
wallet_node_0.config["trusted_peers"] = {}
|
||||
wallet_node_1.config["trusted_peers"] = {}
|
||||
|
||||
await server_0.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None)
|
||||
await server_1.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None)
|
||||
|
||||
for _ in range(1, num_blocks):
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
||||
|
||||
funds = sum(
|
||||
[calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks - 1)]
|
||||
)
|
||||
|
||||
await time_out_assert(10, wallet_0.get_unconfirmed_balance, funds)
|
||||
await time_out_assert(10, wallet_0.get_confirmed_balance, funds)
|
||||
did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet(
|
||||
wallet_node_0.wallet_state_manager, wallet_0, uint64(1)
|
||||
)
|
||||
spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet_0.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())
|
||||
|
||||
for _ in range(1, num_blocks):
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
||||
await time_out_assert(15, wallet_0.get_pending_change_balance, 0)
|
||||
hex_did_id = did_wallet.get_my_DID()
|
||||
hmr_did_id = encode_puzzle_hash(bytes32.from_hexstr(hex_did_id), DID_HRP)
|
||||
|
||||
res = await api_0.create_new_wallet(dict(wallet_type="nft_wallet", name="NFT WALLET 1"))
|
||||
assert isinstance(res, dict)
|
||||
assert res.get("success")
|
||||
nft_wallet_0_id = res["wallet_id"]
|
||||
|
||||
await time_out_assert(5, did_wallet.get_confirmed_balance, 1)
|
||||
|
||||
# Create a NFT with DID
|
||||
resp = await api_0.nft_mint_nft(
|
||||
{
|
||||
"wallet_id": nft_wallet_0_id,
|
||||
"hash": "0xD4584AD463139FA8C0D9F68F4B59F185",
|
||||
"uris": ["https://www.chia.net/img/branding/chia-logo.svg"],
|
||||
"mu": ["https://www.chia.net/img/branding/chia-logo.svg"],
|
||||
"did_id": "",
|
||||
}
|
||||
)
|
||||
assert resp.get("success")
|
||||
sb = resp["spend_bundle"]
|
||||
|
||||
# ensure hints are generated
|
||||
assert compute_memos(sb)
|
||||
await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name())
|
||||
|
||||
for i in range(1, num_blocks):
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
||||
|
||||
# Check DID NFT
|
||||
time_left = 5.0
|
||||
coins_response = {}
|
||||
while time_left > 0:
|
||||
coins_response = await api_0.nft_get_nfts(dict(wallet_id=nft_wallet_0_id))
|
||||
if coins_response.get("nft_list"):
|
||||
break
|
||||
await asyncio.sleep(0.5)
|
||||
time_left -= 0.5
|
||||
assert coins_response["nft_list"], isinstance(coins_response, dict)
|
||||
assert coins_response.get("success")
|
||||
coins = coins_response["nft_list"]
|
||||
assert len(coins) == 1
|
||||
assert coins[0].owner_did is None
|
||||
nft_coin_id = coins[0].nft_coin_id
|
||||
# Test set None -> DID1
|
||||
did_wallet1: DIDWallet = await DIDWallet.create_new_did_wallet(
|
||||
wallet_node_0.wallet_state_manager, wallet_0, uint64(1)
|
||||
)
|
||||
resp = await api_0.nft_set_nft_did(
|
||||
dict(wallet_id=nft_wallet_0_id, did_id=hmr_did_id, nft_coin_id=nft_coin_id.hex())
|
||||
)
|
||||
assert resp.get("success")
|
||||
for i in range(1, num_blocks):
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
||||
|
||||
time_left = 5.0
|
||||
coins_response = {}
|
||||
while time_left > 0:
|
||||
coins_response = await api_0.nft_get_by_did(dict(did_id=hmr_did_id))
|
||||
if coins_response.get("wallet_id"):
|
||||
break
|
||||
await asyncio.sleep(0.5)
|
||||
time_left -= 0.5
|
||||
nft_wallet_1_id = coins_response.get("wallet_id")
|
||||
assert nft_wallet_1_id
|
||||
# Check NFT DID
|
||||
time_left = 10.0
|
||||
while time_left > 0:
|
||||
resp = await api_0.nft_get_nfts(dict(wallet_id=nft_wallet_1_id))
|
||||
if resp.get("nft_list"):
|
||||
break
|
||||
await asyncio.sleep(0.5)
|
||||
time_left -= 0.5
|
||||
assert resp.get("success")
|
||||
coins = resp["nft_list"]
|
||||
assert len(coins) == 1
|
||||
assert coins[0].owner_did.hex() == hex_did_id
|
||||
nft_coin_id = coins[0].nft_coin_id
|
||||
# Test set DID1 -> DID2
|
||||
hex_did_id = did_wallet1.get_my_DID()
|
||||
hmr_did_id = encode_puzzle_hash(bytes32.from_hexstr(hex_did_id), DID_HRP)
|
||||
resp = await api_0.nft_set_nft_did(
|
||||
dict(wallet_id=nft_wallet_1_id, did_id=hmr_did_id, nft_coin_id=nft_coin_id.hex())
|
||||
)
|
||||
assert resp.get("success")
|
||||
for i in range(1, num_blocks):
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
||||
|
||||
time_left = 5.0
|
||||
coins_response = {}
|
||||
while time_left > 0:
|
||||
coins_response = await api_0.nft_get_by_did(dict(did_id=hmr_did_id))
|
||||
if coins_response.get("wallet_id"):
|
||||
break
|
||||
await asyncio.sleep(0.5)
|
||||
time_left -= 0.5
|
||||
nft_wallet_2_id = coins_response.get("wallet_id")
|
||||
assert nft_wallet_2_id
|
||||
# Check NFT DID
|
||||
time_left = 10.0
|
||||
while time_left > 0:
|
||||
resp = await api_0.nft_get_nfts(dict(wallet_id=nft_wallet_2_id))
|
||||
if resp.get("nft_list"):
|
||||
break
|
||||
await asyncio.sleep(0.5)
|
||||
time_left -= 0.5
|
||||
assert resp.get("success")
|
||||
coins = resp["nft_list"]
|
||||
assert len(coins) == 1
|
||||
assert coins[0].owner_did.hex() == hex_did_id
|
||||
nft_coin_id = coins[0].nft_coin_id
|
||||
# Test set DID2 -> None
|
||||
resp = await api_0.nft_set_nft_did(dict(wallet_id=nft_wallet_2_id, nft_coin_id=nft_coin_id.hex()))
|
||||
assert resp.get("success")
|
||||
for i in range(1, num_blocks):
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
||||
|
||||
# Check NFT DID
|
||||
time_left = 10.0
|
||||
while time_left > 0:
|
||||
resp = await api_0.nft_get_nfts(dict(wallet_id=nft_wallet_0_id))
|
||||
if resp.get("nft_list"):
|
||||
break
|
||||
await asyncio.sleep(0.5)
|
||||
time_left -= 0.5
|
||||
assert resp.get("success")
|
||||
coins = resp["nft_list"]
|
||||
assert len(coins) == 1
|
||||
assert coins[0].owner_did is None
|
||||
|
||||
Reference in New Issue
Block a user