mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2026-09-05 02:24:21 -05:00
Merge pull request #12008 from Chia-Network/nft1_tx_fee
NFT/DID transaction related fix
This commit is contained in:
+19
-17
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user