Merge pull request #12008 from Chia-Network/nft1_tx_fee

NFT/DID transaction related fix
This commit is contained in:
Amine Khaldi
2022-06-23 19:35:27 +01:00
committed by GitHub
7 changed files with 226 additions and 222 deletions
+19 -17
View File
@@ -1128,7 +1128,7 @@ class WalletRpcApi:
async def did_set_wallet_name(self, request):
assert self.service.wallet_state_manager is not None
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
if wallet.type() == WalletType.DECENTRALIZED_ID:
await wallet.set_name(str(request["name"]))
@@ -1138,13 +1138,13 @@ class WalletRpcApi:
async def did_get_wallet_name(self, request):
assert self.service.wallet_state_manager is not None
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
name: str = await wallet.get_name()
return {"success": True, "wallet_id": wallet_id, "name": name}
async def did_update_recovery_ids(self, request):
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
recovery_list = []
success: bool = False
@@ -1164,7 +1164,7 @@ class WalletRpcApi:
return {"success": success}
async def did_update_metadata(self, request):
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
if wallet.type() != WalletType.DECENTRALIZED_ID.value:
return {"success": False, "error": f"Wallet with id {wallet_id} is not a DID one"}
@@ -1175,7 +1175,7 @@ class WalletRpcApi:
update_success = await wallet.update_metadata(metadata)
# Update coin with new ID info
if update_success:
spend_bundle = await wallet.create_update_spend()
spend_bundle = await wallet.create_update_spend(uint64(request.get("fee", 0)))
if spend_bundle is not None:
return {"wallet_id": wallet_id, "success": True, "spend_bundle": spend_bundle}
else:
@@ -1184,7 +1184,7 @@ class WalletRpcApi:
return {"success": False, "error": f"Couldn't update metadata with input: {metadata}"}
async def did_get_did(self, request):
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
my_did: str = encode_puzzle_hash(bytes32.fromhex(wallet.get_my_DID()), DID_HRP)
async with self.service.wallet_state_manager.lock:
@@ -1196,7 +1196,7 @@ class WalletRpcApi:
return {"success": True, "wallet_id": wallet_id, "my_did": my_did, "coin_id": coin.name()}
async def did_get_recovery_list(self, request):
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
recovery_list = wallet.did_info.backup_ids
recovery_dids = []
@@ -1210,7 +1210,7 @@ class WalletRpcApi:
}
async def did_get_metadata(self, request):
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
metadata = json.loads(wallet.did_info.metadata)
return {
@@ -1220,7 +1220,7 @@ class WalletRpcApi:
}
async def did_recovery_spend(self, request):
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
if len(request["attest_data"]) < wallet.did_info.num_of_backup_ids_needed:
return {"success": False, "reason": "insufficient messages"}
@@ -1253,21 +1253,21 @@ class WalletRpcApi:
return {"success": success}
async def did_get_pubkey(self, request):
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
pubkey = bytes((await wallet.wallet_state_manager.get_unused_derivation_record(wallet_id)).pubkey).hex()
return {"success": True, "pubkey": pubkey}
async def did_create_attest(self, request):
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
async with self.service.wallet_state_manager.lock:
info = await wallet.get_info_for_recovery()
coin = hexstr_to_bytes(request["coin_name"])
coin = bytes32.from_hexstr(request["coin_name"])
pubkey = G1Element.from_bytes(hexstr_to_bytes(request["pubkey"]))
spend_bundle, attest_data = await wallet.create_attestment(
coin,
hexstr_to_bytes(request["puzhash"]),
bytes32.from_hexstr(request["puzhash"]),
pubkey,
)
if info is not None and spend_bundle is not None:
@@ -1281,7 +1281,7 @@ class WalletRpcApi:
return {"success": False}
async def did_get_information_needed_for_recovery(self, request):
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
did_wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
my_did = encode_puzzle_hash(bytes32.from_hexstr(did_wallet.get_my_DID()), DID_HRP)
coin_name = did_wallet.did_info.temp_coin.name().hex()
@@ -1296,7 +1296,7 @@ class WalletRpcApi:
}
async def did_get_current_coin_info(self, request):
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
did_wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
my_did = encode_puzzle_hash(bytes32.from_hexstr(did_wallet.get_my_DID()), DID_HRP)
did_coin_threeple = await did_wallet.get_info_for_recovery()
@@ -1312,7 +1312,7 @@ class WalletRpcApi:
}
async def did_create_backup_file(self, request):
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
did_wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
return {"wallet_id": wallet_id, "success": True, "backup_data": did_wallet.create_backup()}
@@ -1320,7 +1320,7 @@ class WalletRpcApi:
assert self.service.wallet_state_manager is not None
if await self.service.wallet_state_manager.synced() is False:
raise ValueError("Wallet needs to be fully synced.")
wallet_id = int(request["wallet_id"])
wallet_id = uint32(request["wallet_id"])
did_wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
puzzle_hash: bytes32 = decode_puzzle_hash(request["inner_address"])
async with self.service.wallet_state_manager.lock:
@@ -1513,6 +1513,8 @@ class WalletRpcApi:
[puzzle_hash],
coins={nft_coin_info.coin},
fee=fee,
new_owner=b"",
new_did_inner_hash=b"",
)
spend_bundle: Optional[SpendBundle] = None
for tx in txs:
+77 -58
View File
@@ -1,3 +1,4 @@
import dataclasses
import logging
import time
import json
@@ -105,7 +106,7 @@ class DIDWallet:
raise ValueError("Not enough balance")
try:
spend_bundle = await self.generate_new_decentralised_id(uint64(amount))
spend_bundle = await self.generate_new_decentralised_id(amount, fee)
except Exception:
await wallet_state_manager.user_store.delete_wallet(self.id(), False)
raise
@@ -114,50 +115,7 @@ class DIDWallet:
await wallet_state_manager.user_store.delete_wallet(self.id(), False)
raise ValueError("Failed to create spend.")
await self.wallet_state_manager.add_new_wallet(self, self.wallet_info.id)
assert self.did_info.origin_coin is not None
assert self.did_info.current_inner is not None
did_puzzle_hash = did_wallet_puzzles.create_fullpuz(
self.did_info.current_inner, self.did_info.origin_coin.name()
).get_tree_hash()
did_record = TransactionRecord(
confirmed_at_height=uint32(0),
created_at_time=uint64(int(time.time())),
to_puzzle_hash=did_puzzle_hash,
amount=uint64(amount),
fee_amount=fee,
confirmed=False,
sent=uint32(10),
spend_bundle=None,
additions=spend_bundle.additions(),
removals=spend_bundle.removals(),
wallet_id=self.id(),
sent_to=[],
trade_id=None,
type=uint32(TransactionType.INCOMING_TX.value),
name=bytes32(token_bytes()),
memos=[],
)
regular_record = TransactionRecord(
confirmed_at_height=uint32(0),
created_at_time=uint64(int(time.time())),
to_puzzle_hash=did_puzzle_hash,
amount=uint64(amount),
fee_amount=fee,
confirmed=False,
sent=uint32(0),
spend_bundle=spend_bundle,
additions=spend_bundle.additions(),
removals=spend_bundle.removals(),
wallet_id=self.wallet_state_manager.main_wallet.id(),
sent_to=[],
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=bytes32(token_bytes()),
memos=list(compute_memos(spend_bundle).items()),
)
await self.standard_wallet.push_transaction(regular_record)
await self.standard_wallet.push_transaction(did_record)
return self
@staticmethod
@@ -300,7 +258,7 @@ class DIDWallet:
def type(cls) -> uint8:
return uint8(WalletType.DECENTRALIZED_ID)
def id(self):
def id(self) -> uint32:
return self.wallet_info.id
async def get_confirmed_balance(self, record_list=None) -> uint128:
@@ -521,6 +479,20 @@ class DIDWallet:
await self.add_parent(coin.parent_coin_info, parent_info, True)
assert parent_info is not None
async def create_tandem_xch_tx(
self, fee: uint64, announcement_to_assert: Optional[Announcement] = None
) -> TransactionRecord:
chia_coins = await self.standard_wallet.select_coins(fee)
chia_tx = await self.standard_wallet.generate_signed_transaction(
uint64(0),
(await self.standard_wallet.get_new_puzzlehash()),
fee=fee,
coins=chia_coins,
coin_announcements_to_consume={announcement_to_assert} if announcement_to_assert is not None else None,
)
assert chia_tx.spend_bundle is not None
return chia_tx
def puzzle_for_pk(self, pubkey: G1Element) -> Program:
if self.did_info.origin_coin is not None:
innerpuz = did_wallet_puzzles.create_innerpuz(
@@ -556,7 +528,7 @@ class DIDWallet:
async def get_name(self):
return self.wallet_info.name
async def create_update_spend(self):
async def create_update_spend(self, 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(1)
@@ -565,7 +537,8 @@ class DIDWallet:
new_puzhash = await self.get_new_did_inner_hash()
# innerpuz solution is (mode, p2_solution)
p2_solution = self.standard_wallet.make_solution(
primaries=[{"puzzlehash": new_puzhash, "amount": uint64(coin.amount), "memos": [new_puzhash]}]
primaries=[{"puzzlehash": new_puzhash, "amount": uint64(coin.amount), "memos": [new_puzhash]}],
coin_announcements={coin.name()},
)
innersol: Program = Program.to([1, p2_solution])
# full solution is (corehash parent_info my_amount innerpuz_reveal solution)
@@ -591,7 +564,16 @@ class DIDWallet:
list_of_coinspends = [CoinSpend(coin, full_puzzle, fullsol)]
unsigned_spend_bundle = SpendBundle(list_of_coinspends, G2Element())
spend_bundle = await self.sign(unsigned_spend_bundle)
if fee > 0:
announcement_to_make = coin.name()
chia_tx = await self.create_tandem_xch_tx(fee, Announcement(coin.name(), announcement_to_make))
else:
announcement_to_make = None
chia_tx = None
if chia_tx is not None and chia_tx.spend_bundle is not None:
spend_bundle = SpendBundle.aggregate([spend_bundle, chia_tx.spend_bundle])
chia_tx = dataclasses.replace(chia_tx, spend_bundle=None)
await self.wallet_state_manager.add_pending_transaction(chia_tx)
did_record = TransactionRecord(
confirmed_at_height=uint32(0),
created_at_time=uint64(int(time.time())),
@@ -610,7 +592,8 @@ class DIDWallet:
name=bytes32(token_bytes()),
memos=list(compute_memos(spend_bundle).items()),
)
await self.standard_wallet.push_transaction(did_record)
await self.wallet_state_manager.add_pending_transaction(did_record)
return spend_bundle
async def transfer_did(self, new_puzhash: bytes32, fee: uint64, with_recovery: bool) -> TransactionRecord:
@@ -645,7 +628,8 @@ class DIDWallet:
"amount": uint64(coin.amount),
"memos": [new_puzhash],
}
]
],
coin_announcements={coin.name()},
)
# Need to include backup list reveal here, even we are don't recover
# innerpuz solution is
@@ -675,7 +659,15 @@ class DIDWallet:
list_of_coinspends = [CoinSpend(coin, full_puzzle, fullsol)]
unsigned_spend_bundle = SpendBundle(list_of_coinspends, G2Element())
spend_bundle = await self.sign(unsigned_spend_bundle)
if fee > 0:
announcement_to_make = coin.name()
chia_tx = await self.create_tandem_xch_tx(fee, Announcement(coin.name(), announcement_to_make))
else:
chia_tx = None
if chia_tx is not None and chia_tx.spend_bundle is not None:
spend_bundle = SpendBundle.aggregate([spend_bundle, chia_tx.spend_bundle])
chia_tx = dataclasses.replace(chia_tx, spend_bundle=None)
await self.wallet_state_manager.add_pending_transaction(chia_tx)
did_record = TransactionRecord(
confirmed_at_height=uint32(0),
created_at_time=uint64(int(time.time())),
@@ -694,7 +686,7 @@ class DIDWallet:
name=bytes32(token_bytes()),
memos=list(compute_memos(spend_bundle).items()),
)
await self.standard_wallet.push_transaction(did_record)
await self.wallet_state_manager.add_pending_transaction(did_record)
return did_record
# The message spend can tests\wallet\rpc\test_wallet_rpc.py send messages and also change your innerpuz
@@ -797,7 +789,7 @@ class DIDWallet:
name=bytes32(token_bytes()),
memos=list(compute_memos(spend_bundle).items()),
)
await self.standard_wallet.push_transaction(did_record)
await self.wallet_state_manager.add_pending_transaction(did_record)
return spend_bundle
# Pushes a SpendBundle to create a message coin on the blockchain
@@ -873,7 +865,7 @@ class DIDWallet:
)
attest_str: str = f"{self.get_my_DID()}:{bytes(message_spend_bundle).hex()}:{coin.parent_coin_info.hex()}:"
attest_str += f"{self.did_info.current_inner.get_tree_hash().hex()}:{coin.amount}"
await self.standard_wallet.push_transaction(did_record)
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]]:
@@ -999,7 +991,7 @@ class DIDWallet:
name=bytes32(token_bytes()),
memos=list(compute_memos(spend_bundle).items()),
)
await self.standard_wallet.push_transaction(did_record)
await self.wallet_state_manager.add_pending_transaction(did_record)
new_did_info = DIDInfo(
self.did_info.origin_coin,
self.did_info.backup_ids,
@@ -1116,12 +1108,12 @@ class DIDWallet:
agg_sig = AugSchemeMPL.aggregate(sigs)
return SpendBundle.aggregate([spend_bundle, SpendBundle([], agg_sig)])
async def generate_new_decentralised_id(self, amount: uint64) -> Optional[SpendBundle]:
async def generate_new_decentralised_id(self, amount: uint64, fee: uint64 = uint64(0)) -> Optional[SpendBundle]:
"""
This must be called under the wallet state manager lock
"""
coins = await self.standard_wallet.select_coins(amount)
coins = await self.standard_wallet.select_coins(uint64(amount + fee))
if coins is None:
return None
@@ -1139,7 +1131,7 @@ class DIDWallet:
announcement_set.add(Announcement(launcher_coin.name(), announcement_message))
tx_record: Optional[TransactionRecord] = await self.standard_wallet.generate_signed_transaction(
amount, genesis_launcher_puz.get_tree_hash(), uint64(0), origin.name(), coins, None, False, announcement_set
amount, genesis_launcher_puz.get_tree_hash(), fee, origin.name(), coins, None, False, announcement_set
)
genesis_launcher_solution = Program.to([did_puzzle_hash, amount, bytes(0x80)])
@@ -1179,6 +1171,33 @@ class DIDWallet:
await self.save_info(did_info, False)
eve_spend = await self.generate_eve_spend(eve_coin, did_full_puz, did_inner)
full_spend = SpendBundle.aggregate([tx_record.spend_bundle, eve_spend, launcher_sb])
assert self.did_info.origin_coin is not None
assert self.did_info.current_inner is not None
did_puzzle_hash = did_wallet_puzzles.create_fullpuz(
self.did_info.current_inner, self.did_info.origin_coin.name()
).get_tree_hash()
did_record = TransactionRecord(
confirmed_at_height=uint32(0),
created_at_time=uint64(int(time.time())),
to_puzzle_hash=did_puzzle_hash,
amount=uint64(amount),
fee_amount=fee,
confirmed=False,
sent=uint32(10),
spend_bundle=full_spend,
additions=full_spend.additions(),
removals=full_spend.removals(),
wallet_id=self.id(),
sent_to=[],
trade_id=None,
type=uint32(TransactionType.INCOMING_TX.value),
name=bytes32(token_bytes()),
memos=[],
)
regular_record = dataclasses.replace(tx_record, spend_bundle=None)
await self.wallet_state_manager.add_pending_transaction(regular_record)
await self.wallet_state_manager.add_pending_transaction(did_record)
return full_spend
async def generate_eve_spend(self, coin: Coin, full_puzzle: Program, innerpuz: Program):
+30 -93
View File
@@ -2,7 +2,6 @@ import dataclasses
import json
import logging
import time
from secrets import token_bytes
from typing import Any, Dict, List, Optional, Set, Tuple, Type, TypeVar
from blspy import AugSchemeMPL, G1Element, G2Element
@@ -36,7 +35,6 @@ from chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle import (
DEFAULT_HIDDEN_PUZZLE_HASH,
calculate_synthetic_secret_key,
puzzle_for_pk,
solution_for_conditions,
)
from chia.wallet.trading.offer import OFFER_MOD, NotarizedPayment, Offer
from chia.wallet.transaction_record import TransactionRecord
@@ -351,7 +349,7 @@ class NFTWallet:
# For a DID enabled NFT wallet it cannot mint NFT0. Mint NFT1 instead.
did_id = self.did_id
amount = uint64(1)
coins = await self.standard_wallet.select_coins(amount)
coins = await self.standard_wallet.select_coins(uint64(amount + fee))
if coins is None:
return None
origin = coins.copy().pop()
@@ -400,7 +398,6 @@ class NFTWallet:
False,
announcement_set,
)
genesis_launcher_solution = Program.to([eve_fullpuz.get_tree_hash(), amount, []])
# launcher spend to generate the singleton
@@ -428,16 +425,17 @@ class NFTWallet:
full_puzzle=eve_fullpuz,
mint_height=uint32(0),
)
# Don't set fee, it is covered in the tx_record
txs = await self.generate_signed_transaction(
[eve_coin.amount],
[target_puzzle_hash],
nft_coin=nft_coin,
fee=fee,
new_owner=did_id,
new_did_inner_hash=did_inner_hash,
additional_bundles=bundles_to_agg,
memos=[[target_puzzle_hash]],
)
txs.append(dataclasses.replace(tx_record, spend_bundle=None))
if push_tx:
for tx in txs:
await self.wallet_state_manager.add_pending_transaction(tx)
@@ -487,91 +485,25 @@ class NFTWallet:
agg_sig = AugSchemeMPL.aggregate(sigs)
return SpendBundle.aggregate([spend_bundle, SpendBundle([], agg_sig)])
async def _make_nft_transaction(
self,
nft_coin_info: NFTCoinInfo,
inner_solution: Program,
puzzle_hashes_to_sign: List[bytes32],
fee: uint64 = uint64(0),
additional_bundles: List[SpendBundle] = [],
) -> TransactionRecord:
# Update NFT status
coin = nft_coin_info.coin
amount = coin.amount
if not additional_bundles:
additional_bundles = []
full_puzzle = nft_coin_info.full_puzzle
lineage_proof = nft_coin_info.lineage_proof
assert lineage_proof is not None
full_solution = Program.to(
[
[lineage_proof.parent_name, lineage_proof.inner_puzzle_hash, lineage_proof.amount],
coin.amount,
inner_solution,
]
)
list_of_coinspends = [CoinSpend(coin, full_puzzle.to_serialized_program(), full_solution)]
self.log.debug(
"Going to run a new NFT transaction: \nPuzzle:\n%s\n=================================\nSolution:\n%s",
disassemble(full_puzzle),
disassemble(full_solution),
)
spend_bundle = SpendBundle(list_of_coinspends, AugSchemeMPL.aggregate([]))
spend_bundle = await self.sign(spend_bundle, puzzle_hashes_to_sign)
full_spend = SpendBundle.aggregate([spend_bundle] + additional_bundles)
self.log.debug("Memos are: %r", list(compute_memos(full_spend).items()))
nft_record = TransactionRecord(
confirmed_at_height=uint32(0),
created_at_time=uint64(int(time.time())),
to_puzzle_hash=full_puzzle.get_tree_hash(),
amount=uint64(amount),
fee_amount=fee,
confirmed=False,
sent=uint32(0),
spend_bundle=full_spend,
additions=full_spend.additions(),
removals=full_spend.removals(),
wallet_id=self.wallet_info.id,
sent_to=[],
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=bytes32(token_bytes()),
memos=list(compute_memos(full_spend).items()),
)
return nft_record
async def update_metadata(
self, nft_coin_info: NFTCoinInfo, key: str, uri: str, fee: uint64 = uint64(0)
) -> Optional[SpendBundle]:
coin = nft_coin_info.coin
uncurried_nft = UncurriedNFT.uncurry(nft_coin_info.full_puzzle)
puzzle_hash = uncurried_nft.p2_puzzle.get_tree_hash()
if uncurried_nft.supports_did:
condition_list = [
[51, puzzle_hash, coin.amount, [puzzle_hash]],
[-24, NFT_METADATA_UPDATER, (key, uri)],
]
inner_solution = Program.to([[solution_for_conditions(condition_list)]])
else:
condition_list = [
[51, puzzle_hash, coin.amount, [puzzle_hash]],
[-24, NFT_METADATA_UPDATER, (key, uri)],
]
inner_solution = Program.to([solution_for_conditions(condition_list)])
self.log.info(
"Attempting to add urls to NFT coin %s in the metadata: %s",
nft_coin_info.coin.name(),
uncurried_nft.metadata,
)
nft_tx_record = await self._make_nft_transaction(nft_coin_info, inner_solution, [puzzle_hash], fee)
await self.standard_wallet.push_transaction(nft_tx_record)
txs = await self.generate_signed_transaction(
[uint64(nft_coin_info.coin.amount)], [puzzle_hash], fee, {nft_coin_info.coin}, metadata_update=(key, uri)
)
for tx in txs:
await self.wallet_state_manager.add_pending_transaction(tx)
await self.update_coin_status(nft_coin_info.coin.name(), True)
self.wallet_state_manager.state_changed("nft_coin_updated", self.wallet_info.id)
return nft_tx_record.spend_bundle
return SpendBundle.aggregate([x.spend_bundle for x in txs if x.spend_bundle is not None])
def get_current_nfts(self) -> List[NFTCoinInfo]:
return self.my_nft_coins
@@ -694,6 +626,7 @@ class NFTWallet:
new_did_inner_hash: Optional[bytes] = None,
trade_prices_list: Optional[Program] = None,
additional_bundles: List[SpendBundle] = [],
metadata_update: Tuple[str, str] = None,
) -> List[TransactionRecord]:
if memos is None:
memos = [[] for _ in range(len(puzzle_hashes))]
@@ -719,6 +652,7 @@ class NFTWallet:
new_owner=new_owner,
new_did_inner_hash=new_did_inner_hash,
trade_prices_list=trade_prices_list,
metadata_update=metadata_update,
)
spend_bundle = await self.sign(unsigned_spend_bundle)
spend_bundle = SpendBundle.aggregate([spend_bundle] + additional_bundles)
@@ -762,6 +696,7 @@ class NFTWallet:
new_owner: Optional[bytes] = None,
new_did_inner_hash: Optional[bytes] = None,
trade_prices_list: Optional[Program] = None,
metadata_update: Tuple[str, str] = None,
nft_coin: Optional[NFTCoinInfo] = None,
) -> Tuple[SpendBundle, Optional[TransactionRecord]]:
if nft_coin is None:
@@ -801,8 +736,9 @@ class NFTWallet:
puzzle_announcements_to_assert=puzzle_announcements_bytes,
)
uncurried_nft = UncurriedNFT.uncurry(nft_coin.full_puzzle)
if uncurried_nft.supports_did:
unft = UncurriedNFT.uncurry(nft_coin.full_puzzle)
magic_condition = None
if unft.supports_did:
if new_owner is None:
# If no new owner was specified and we're sending this to ourselves, let's not reset the DID
derivation_record: Optional[
@@ -811,11 +747,16 @@ class NFTWallet:
payments[0].puzzle_hash
)
if derivation_record is not None:
new_owner = uncurried_nft.owner_did
new_owner = unft.owner_did
magic_condition = Program.to([-10, new_owner, trade_prices_list, new_did_inner_hash])
if metadata_update:
# We don't support update metadata while changing the ownership
magic_condition = Program.to([-24, NFT_METADATA_UPDATER, metadata_update])
if magic_condition:
# TODO: This line is a hack, make_solution should allow us to pass extra conditions to it
w_added_magic_condition = Program.to([[], (1, magic_condition.cons(innersol.at("rfr"))), []])
innersol = Program.to([w_added_magic_condition])
innersol = Program.to([[], (1, magic_condition.cons(innersol.at("rfr"))), []])
if unft.supports_did:
innersol = Program.to([innersol])
nft_layer_solution = Program.to([innersol])
assert isinstance(nft_coin.lineage_proof, LineageProof)
@@ -824,7 +765,7 @@ class NFTWallet:
nft_spend_bundle = SpendBundle([coin_spend], G2Element())
return (nft_spend_bundle, chia_tx)
return nft_spend_bundle, chia_tx
@staticmethod
async def make_nft1_offer(
@@ -885,7 +826,7 @@ class NFTWallet:
[offered_amount],
[Offer.ph()],
fee=fee,
coins=set([offered_coin]),
coins={offered_coin},
puzzle_announcements_to_consume=set(announcements),
trade_prices_list=trade_prices,
)
@@ -1019,16 +960,12 @@ class NFTWallet:
new_did_inner_hash=did_inner_hash,
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 = spend_bundle.aggregate([spend_bundle, tx.spend_bundle])
await self.standard_wallet.push_transaction(tx)
await self.update_coin_status(nft_coin_info.coin.name(), True)
self.wallet_state_manager.state_changed("nft_coin_did_set", self.wallet_info.id)
spend_bundle = SpendBundle.aggregate([x.spend_bundle for x in nft_tx_record if x.spend_bundle is not None])
if spend_bundle:
for tx in nft_tx_record:
await self.wallet_state_manager.add_pending_transaction(tx)
await self.update_coin_status(nft_coin_info.coin.name(), True)
self.wallet_state_manager.state_changed("nft_coin_did_set", self.wallet_info.id)
return spend_bundle
else:
raise ValueError("Couldn't set DID on given NFT")
+6 -4
View File
@@ -405,6 +405,7 @@ class TradeManager:
driver_dict,
fee,
)
if potential_special_offer is not None:
return True, potential_special_offer, None
@@ -457,8 +458,10 @@ class TradeManager:
fee_left_to_pay = uint64(0)
transaction_bundles: List[Optional[SpendBundle]] = [tx.spend_bundle for tx in all_transactions]
total_spend_bundle = SpendBundle.aggregate(list(filter(lambda b: b is not None, transaction_bundles)))
total_spend_bundle = SpendBundle.aggregate(
[x.spend_bundle for x in all_transactions if x.spend_bundle is not None]
)
offer = Offer(notarized_payments, total_spend_bundle, driver_dict)
return True, offer, None
@@ -582,6 +585,7 @@ class TradeManager:
async def respond_to_offer(self, offer: Offer, fee=uint64(0)) -> Tuple[bool, Optional[TradeRecord], Optional[str]]:
take_offer_dict: Dict[Union[bytes32, int], int] = {}
arbitrage: Dict[Optional[bytes32], int] = offer.arbitrage()
for asset_id, amount in arbitrage.items():
if asset_id is None:
wallet = self.wallet_state_manager.main_wallet
@@ -601,7 +605,6 @@ class TradeManager:
valid: bool = await self.check_offer_validity(offer)
if not valid:
return False, None, "This offer is no longer valid"
success, take_offer, error = await self._create_offer_for_ids(take_offer_dict, offer.driver_dict, fee=fee)
if not success or take_offer is None:
return False, None, error
@@ -610,7 +613,6 @@ class TradeManager:
assert complete_offer.is_valid()
final_spend_bundle: SpendBundle = complete_offer.to_valid_spend()
await self.maybe_create_wallets_for_offer(complete_offer)
tx_records: List[TransactionRecord] = await self.calculate_tx_records_for_offer(complete_offer, True)
+55 -27
View File
@@ -84,7 +84,9 @@ class TestDIDWallet:
wallet_node_0.wallet_state_manager, wallet_0, uint64(101)
)
spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet_0.id())
spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
did_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())
@@ -103,7 +105,9 @@ class TestDIDWallet:
wallet_node_1.wallet_state_manager, wallet_1, uint64(201), backup_ids
)
spend_bundle_list = await wallet_node_1.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet_1.id())
spend_bundle_list = await wallet_node_1.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
did_wallet_1.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())
@@ -235,7 +239,7 @@ class TestDIDWallet:
wallet_node.wallet_state_manager, wallet, uint64(101)
)
assert did_wallet.wallet_info.name == "Profile 1"
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet.id())
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())
@@ -254,7 +258,9 @@ class TestDIDWallet:
wallet_node_2.wallet_state_manager, wallet2, uint64(101), recovery_list
)
spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet2.id())
spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
did_wallet_2.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())
@@ -274,7 +280,9 @@ class TestDIDWallet:
wallet_node_2.wallet_state_manager, wallet2, uint64(201), recovery_list
)
spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet2.id())
spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
did_wallet_3.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())
@@ -386,7 +394,7 @@ class TestDIDWallet:
wallet_node.wallet_state_manager, wallet, uint64(101)
)
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet.id())
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())
@@ -454,7 +462,7 @@ class TestDIDWallet:
did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet(
wallet_node.wallet_state_manager, wallet, uint64(101)
)
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet.id())
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())
@@ -470,7 +478,9 @@ class TestDIDWallet:
did_wallet_2: DIDWallet = await DIDWallet.create_new_did_wallet(
wallet_node_2.wallet_state_manager, wallet2, uint64(101), recovery_list
)
spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet2.id())
spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
did_wallet_2.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())
@@ -597,6 +607,7 @@ class TestDIDWallet:
@pytest.mark.asyncio
async def test_did_transfer(self, two_wallet_nodes, with_recovery, trusted):
num_blocks = 5
fee = uint64(1000)
full_nodes, wallets = two_wallet_nodes
full_node_api = full_nodes[0]
server_1 = full_node_api.server
@@ -639,19 +650,9 @@ class TestDIDWallet:
[bytes(ph)],
uint64(1),
{"Twitter": "Test", "GitHub": "测试"},
fee=fee,
)
assert did_wallet_1.wallet_info.name == "Profile 1"
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(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())
ph2 = await wallet2.get_new_puzzlehash()
for i in range(1, num_blocks):
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph2))
await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101)
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, uint64(0), with_recovery)
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
did_wallet_1.id()
)
@@ -660,6 +661,23 @@ class TestDIDWallet:
ph2 = await wallet2.get_new_puzzlehash()
for i in range(1, num_blocks):
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph2))
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 time_out_assert(15, wallet.get_confirmed_balance, 7999999998899)
await time_out_assert(15, wallet.get_unconfirmed_balance, 7999999998899)
# Transfer DID
new_puzhash = await wallet2.get_new_puzzlehash()
await did_wallet_1.transfer_did(new_puzhash, fee, with_recovery)
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
did_wallet_1.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())
ph2 = await wallet2.get_new_puzzlehash()
for i in range(1, num_blocks):
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph2))
await time_out_assert(15, wallet.get_confirmed_balance, 7999999997899)
await time_out_assert(15, wallet.get_unconfirmed_balance, 7999999997899)
# Check if the DID wallet is created in the wallet2
await time_out_assert(30, len, 2, wallet_node_2.wallet_state_manager.wallets)
# Get the new DID wallet
@@ -722,7 +740,9 @@ class TestDIDWallet:
did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
wallet_node.wallet_state_manager, wallet, uint64(101), []
)
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet.id())
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
did_wallet_1.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())
ph2 = await wallet.get_new_puzzlehash()
@@ -747,13 +767,16 @@ class TestDIDWallet:
@pytest.mark.asyncio
async def test_update_metadata(self, two_wallet_nodes, trusted):
num_blocks = 5
fee = uint64(1000)
full_nodes, wallets = two_wallet_nodes
full_node_api = full_nodes[0]
server_1 = full_node_api.server
wallet_node, server_2 = wallets[0]
wallet_node_2, server_3 = wallets[1]
wallet = wallet_node.wallet_state_manager.main_wallet
wallet1 = wallet_node_2.wallet_state_manager.main_wallet
ph = await wallet.get_new_puzzlehash()
ph1 = await wallet1.get_new_puzzlehash()
if trusted:
wallet_node.config["trusted_peers"] = {
full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
@@ -781,23 +804,28 @@ class TestDIDWallet:
async with wallet_node.wallet_state_manager.lock:
did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
wallet_node.wallet_state_manager, wallet, uint64(101), []
wallet_node.wallet_state_manager, wallet, uint64(101), [], fee=fee
)
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet.id())
spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
did_wallet_1.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())
ph2 = await wallet.get_new_puzzlehash()
for i in range(1, num_blocks):
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph2))
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph1))
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 time_out_assert(15, wallet.get_confirmed_balance, 7999999998899)
await time_out_assert(15, wallet.get_unconfirmed_balance, 7999999998899)
metadata = {}
metadata["Twitter"] = "http://www.twitter.com"
await did_wallet_1.update_metadata(metadata)
await did_wallet_1.create_update_spend()
ph2 = await wallet.get_new_puzzlehash()
await did_wallet_1.create_update_spend(fee)
for i in range(1, num_blocks):
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph2))
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph1))
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 time_out_assert(15, wallet.get_confirmed_balance, 7999999997899)
await time_out_assert(15, wallet.get_unconfirmed_balance, 7999999997899)
assert did_wallet_1.did_info.metadata.find("Twitter") > 0
+7 -7
View File
@@ -95,7 +95,7 @@ async def test_nft_offer_sell_nft(two_wallet_nodes: Any, trusted: Any) -> None:
wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1)
)
spend_bundle_list = await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
wallet_maker.id()
did_wallet_maker.id()
)
spend_bundle = spend_bundle_list[0].spend_bundle
@@ -247,7 +247,7 @@ async def test_nft_offer_request_nft(two_wallet_nodes: Any, trusted: Any) -> Non
wallet_node_taker.wallet_state_manager, wallet_taker, uint64(1)
)
spend_bundle_list = await wallet_node_taker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
wallet_taker.id()
did_wallet_taker.id()
)
spend_bundle = spend_bundle_list[0].spend_bundle
@@ -400,7 +400,7 @@ async def test_nft_offer_sell_did_to_did(two_wallet_nodes: Any, trusted: Any) ->
wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1)
)
spend_bundle_list = await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
wallet_maker.id()
did_wallet_maker.id()
)
spend_bundle = spend_bundle_list[0].spend_bundle
@@ -452,7 +452,7 @@ async def test_nft_offer_sell_did_to_did(two_wallet_nodes: Any, trusted: Any) ->
wallet_node_taker.wallet_state_manager, wallet_taker, uint64(1)
)
spend_bundle_list_taker = await wallet_node_taker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
wallet_taker.id()
did_wallet_taker.id()
)
spend_bundle_taker = spend_bundle_list_taker[0].spend_bundle
@@ -575,7 +575,7 @@ async def test_nft_offer_sell_nft_for_cat(two_wallet_nodes: Any, trusted: Any) -
wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1)
)
spend_bundle_list = await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
wallet_maker.id()
did_wallet_maker.id()
)
spend_bundle = spend_bundle_list[0].spend_bundle
@@ -769,7 +769,7 @@ async def test_nft_offer_request_nft_for_cat(two_wallet_nodes: Any, trusted: Any
wallet_node_taker.wallet_state_manager, wallet_taker, uint64(1)
)
spend_bundle_list = await wallet_node_taker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
wallet_taker.id()
did_wallet_taker.id()
)
spend_bundle = spend_bundle_list[0].spend_bundle
@@ -952,7 +952,7 @@ async def test_nft_offer_sell_cancel(two_wallet_nodes: Any, trusted: Any) -> Non
wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1)
)
spend_bundle_list = await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
wallet_maker.id()
did_wallet_maker.id()
)
spend_bundle = spend_bundle_list[0].spend_bundle
+32 -16
View File
@@ -575,7 +575,7 @@ async def test_nft_with_did_wallet_creation(two_wallet_nodes: Any, trusted: Any)
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_list = await wallet_node_0.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())
@@ -740,7 +740,7 @@ async def test_nft_rpc_mint(two_wallet_nodes: Any, trusted: Any) -> None:
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_list = await wallet_node_0.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())
@@ -818,6 +818,7 @@ async def test_nft_rpc_mint(two_wallet_nodes: Any, trusted: Any) -> None:
@pytest.mark.asyncio
async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) -> None:
num_blocks = 3
fee = 100
full_nodes, wallets = two_wallet_nodes
full_node_api: FullNodeSimulator = full_nodes[0]
full_node_server = full_node_api.server
@@ -857,7 +858,7 @@ async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) ->
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_list = await wallet_node_0.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())
@@ -873,7 +874,8 @@ async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) ->
assert res.get("success")
nft_wallet_0_id = res["wallet_id"]
await time_out_assert(5, did_wallet.get_confirmed_balance, 1)
await time_out_assert(15, did_wallet.get_confirmed_balance, 1)
await time_out_assert(15, did_wallet.get_unconfirmed_balance, 1)
# Create a NFT with DID
resp = await api_0.nft_mint_nft(
@@ -881,6 +883,7 @@ async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) ->
"wallet_id": nft_wallet_0_id,
"hash": "0xD4584AD463139FA8C0D9F68F4B59F185",
"uris": ["https://www.chia.net/img/branding/chia-logo.svg"],
"fee": fee,
}
)
assert resp.get("success")
@@ -891,12 +894,14 @@ async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) ->
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))
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph1))
# Check DID NFT
coins_response = await wait_rpc_state_condition(
5, api_0.nft_get_nfts, [dict(wallet_id=nft_wallet_0_id)], lambda x: x["nft_list"]
)
await time_out_assert(10, wallet_0.get_unconfirmed_balance, 7999999999898)
await time_out_assert(10, wallet_0.get_confirmed_balance, 7999999999898)
coins = coins_response["nft_list"]
assert len(coins) == 1
assert coins[0].owner_did.hex() == hex_did_id
@@ -907,6 +912,7 @@ async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) ->
wallet_id=nft_wallet_0_id,
target_address=encode_puzzle_hash(ph1, "xch"),
nft_coin_id=coins[0].nft_coin_id.hex(),
fee=fee,
)
)
# transfer DID to the other wallet
@@ -923,7 +929,8 @@ async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) ->
await wait_rpc_state_condition(
5, api_0.nft_get_nfts, [dict(wallet_id=nft_wallet_0_id)], lambda x: not x["nft_list"]
)
await time_out_assert(10, wallet_0.get_unconfirmed_balance, 7999999999798)
await time_out_assert(10, wallet_0.get_confirmed_balance, 7999999999798)
# wait for all wallets to be created
await time_out_assert(10, len, 3, wallet_1.wallet_state_manager.wallets)
did_wallet_1 = wallet_1.wallet_state_manager.wallets[3]
@@ -943,17 +950,18 @@ async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) ->
# Set DID
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())
dict(wallet_id=nft_wallet_id_1, did_id=hmr_did_id, nft_coin_id=nft_coin_id.hex(), fee=fee)
)
assert resp.get("success")
for i in range(1, num_blocks):
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph1))
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
coins_response = await wait_rpc_state_condition(
5, api_1.nft_get_by_did, [dict(did_id=hmr_did_id)], lambda x: x.get("wallet_id", 0) > 0
)
print(wallet_1.wallet_state_manager.wallets)
await time_out_assert(10, wallet_1.get_unconfirmed_balance, 12000000000100)
await time_out_assert(10, wallet_1.get_confirmed_balance, 12000000000100)
nft_wallet_1_id = coins_response.get("wallet_id")
assert nft_wallet_1_id
# Check NFT DID is set now
@@ -981,8 +989,10 @@ async def test_update_metadata_for_nft_did(two_wallet_nodes: Any, trusted: Any)
wallet_node_0, server_0 = wallets[0]
wallet_node_1, server_1 = wallets[1]
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)
ph = await wallet_0.get_new_puzzlehash()
ph1 = await wallet_1.get_new_puzzlehash()
if trusted:
wallet_node_0.config["trusted_peers"] = {
@@ -1010,7 +1020,7 @@ async def test_update_metadata_for_nft_did(two_wallet_nodes: Any, trusted: Any)
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_list = await wallet_node_0.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())
@@ -1058,9 +1068,14 @@ async def test_update_metadata_for_nft_did(two_wallet_nodes: Any, trusted: Any)
# add another URI
tr1 = await api_0.nft_add_uri(
{"wallet_id": nft_wallet_0_id, "nft_coin_id": nft_coin_id.hex(), "uri": "http://metadata", "key": "mu"}
{
"wallet_id": nft_wallet_0_id,
"nft_coin_id": nft_coin_id.hex(),
"uri": "http://metadata",
"key": "mu",
"fee": 100,
}
)
assert isinstance(tr1, dict)
assert tr1.get("success")
coins_response = await api_0.nft_get_nfts(dict(wallet_id=nft_wallet_0_id))
@@ -1068,9 +1083,10 @@ async def test_update_metadata_for_nft_did(two_wallet_nodes: Any, trusted: Any)
sb = tr1["spend_bundle"]
await time_out_assert_not_none(15, 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))
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph1))
# check that new URI was added
await time_out_assert(10, wallet_0.get_unconfirmed_balance, 11999999999898)
await time_out_assert(10, wallet_0.get_confirmed_balance, 11999999999898)
coins_response = await wait_rpc_state_condition(
5,
api_0.nft_get_nfts,
@@ -1132,7 +1148,7 @@ async def test_nft_set_did(two_wallet_nodes: Any, trusted: Any) -> None:
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_list = await wallet_node_0.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())
@@ -1176,7 +1192,7 @@ async def test_nft_set_did(two_wallet_nodes: Any, trusted: Any) -> None:
did_wallet1: 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_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet1.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())