Fix transaction record issue & migrate update_metadata to generate_signed_tx

This commit is contained in:
ytx1991 2022-06-21 19:39:10 -07:00
parent 0f49e5d048
commit 15206f9e45
No known key found for this signature in database
GPG Key ID: 1B767F8CA343E501
4 changed files with 38 additions and 86 deletions

View File

@ -1494,6 +1494,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:

View File

@ -156,8 +156,8 @@ class DIDWallet:
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)
await self.wallet_state_manager.add_pending_transaction(regular_record)
await self.wallet_state_manager.add_pending_transaction(did_record)
return self
@staticmethod
@ -610,7 +610,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
async def transfer_did(self, new_puzhash: bytes32, fee: uint64, with_recovery: bool) -> TransactionRecord:
@ -694,7 +694,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 +797,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 +873,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 +999,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,

View File

@ -458,7 +458,7 @@ class NFTWallet:
name=bytes32(token_bytes()),
memos=list(compute_memos(full_spend).items()),
)
await self.standard_wallet.push_transaction(nft_record)
await self.wallet_state_manager.add_pending_transaction(nft_record)
return nft_record.spend_bundle
async def sign(self, spend_bundle: SpendBundle, puzzle_hashes: List[bytes32] = None) -> SpendBundle:
@ -505,91 +505,30 @@ 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(
[nft_coin_info.coin.amount], [puzzle_hash], fee, {nft_coin_info.coin}, metadata_update=(key, uri)
)
spend_bundle: Optional[SpendBundle] = None
for tx in txs:
if tx.spend_bundle is not None:
spend_bundle = tx.spend_bundle
else:
spend_bundle = SpendBundle.aggregate([spend_bundle, tx.spend_bundle])
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 spend_bundle
def get_current_nfts(self) -> List[NFTCoinInfo]:
return self.my_nft_coins
@ -711,6 +650,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))]
@ -735,6 +675,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)
@ -794,6 +735,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,
) -> Tuple[SpendBundle, Optional[TransactionRecord]]:
if coins is None or len(coins) > 1:
# Make sure the user is specifying which specific NFT coin to use
@ -830,12 +772,18 @@ class NFTWallet:
coin_announcements_to_assert=coin_announcements_bytes,
puzzle_announcements_to_assert=puzzle_announcements_bytes,
)
if UncurriedNFT.uncurry(nft_coin.full_puzzle).supports_did:
unft = UncurriedNFT.uncurry(nft_coin.full_puzzle)
magic_condition = None
if new_owner is not None and new_did_inner_hash is not None and unft.supports_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)
@ -849,7 +797,7 @@ 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
@staticmethod
async def make_nft1_offer(
@ -1052,7 +1000,7 @@ class NFTWallet:
spend_bundle = tx.spend_bundle
else:
spend_bundle.aggregate([tx.spend_bundle])
await self.standard_wallet.push_transaction(tx)
await self.wallet_state_manager.add_pending_transaction(tx)
self.wallet_state_manager.state_changed("nft_coin_did_set", self.wallet_info.id)
if spend_bundle:
return spend_bundle

View File

@ -881,6 +881,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": 100,
}
)
assert resp.get("success")
@ -897,6 +898,7 @@ async def test_nft_transfer_nft_with_did(two_wallet_nodes: Any, trusted: Any) ->
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"]
)
coins = coins_response["nft_list"]
assert len(coins) == 1
assert coins[0].owner_did.hex() == hex_did_id