mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2024-09-20 16:08:51 +03:00
Fix transaction record issue & migrate update_metadata to generate_signed_tx
This commit is contained in:
parent
0f49e5d048
commit
15206f9e45
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user