import asyncio from utilities.decorations import print_leaf, divider, prompt, start_list, close_list, selectable, informative from utilities.puzzle_utilities import puzzlehash_from_string from chiasim.hashable import Coin, Header, HeaderHash from chiasim.clients.ledger_sim import connect_to_ledger_sim from chiasim.wallet.deltas import additions_for_body, removals_for_body from chiasim.hashable.Body import Body from binascii import hexlify from authorised_payees import ap_wallet_a_functions from standard_wallet.wallet import Wallet try: import qrcode from PIL import Image from pyzbar.pyzbar import decode except ImportError: qrcode = None def view_funds(wallet): print(f"Current balance: {str(wallet.temp_balance)}") print(f"UTXOs: {[x.amount for x in wallet.temp_utxos]}") def print_my_details(wallet): print(f"{informative} Name: {wallet.name}") print(f"{informative} Pubkey: {hexlify(wallet.get_next_public_key().serialize()).decode('ascii')}") print(f"{informative} Puzzlehash: {wallet.get_new_puzzlehash()}") def make_QR(wallet): print(divider) qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=10, border=4, ) qr.add_data(f"{wallet.get_new_puzzlehash()}") qr.make(fit=True) img = qr.make_image() fn = input("Input file name: ") img.save(f"{fn}.jpg") print(f"QR code created in '{fn}.jpg'") def read_qr(wallet): amount = -1 if wallet.current_balance <= 0: print("You need some money first") return None print("Input filename of QR code: ") fn = input(prompt) decoded = decode(Image.open(fn)) puzzlehash = puzzlehash_from_string(decoded[0].data) while amount > wallet.temp_balance or amount <= 0: amount = input("Amount: ") if amount == "q": return if not amount.isdigit(): amount = -1 amount = int(amount) return wallet.generate_signed_transaction(amount, puzzlehash) def set_name(wallet): selection = input("Enter a new name: ") wallet.set_name(selection) async def make_payment(wallet, ledger_api): amount = -1 if wallet.current_balance <= 0: print("You need some money first") return None while amount > wallet.temp_balance or amount < 0: amount = input(f"{prompt} Enter amount to give recipient: ") if amount == "q": return if not amount.isdigit(): amount = -1 amount = int(amount) puzhashstring = input(f"{prompt} Enter puzzlehash: ") puzzlehash = puzzlehash_from_string(puzhashstring) tx = wallet.generate_signed_transaction(amount, puzzlehash) if tx is not None: await ledger_api.push_tx(tx=tx) async def initiate_ap(wallet, ledger_api): if wallet.temp_balance <= 0: print("You need some money first") return None # TODO: add a strict format checker to input here (and everywhere tbh) # Actual puzzle lockup/spend a_pubkey = wallet.get_next_public_key().serialize() b_pubkey = input("Enter recipient's pubkey: 0x") amount = -1 while amount > wallet.temp_balance or amount < 0: amount = input("Enter amount to give recipient: ") if amount == "q": return if not amount.isdigit(): amount = -1 amount = int(amount) APpuzzlehash = ap_wallet_a_functions.ap_get_new_puzzlehash( a_pubkey, b_pubkey) spend_bundle = wallet.generate_signed_transaction(amount, APpuzzlehash) await ledger_api.push_tx(tx=spend_bundle) print() print(f"{informative} AP Puzzlehash is: {str(APpuzzlehash)}") print(f"{informative} Pubkey used is: {hexlify(a_pubkey).decode('ascii')}") sig = str(ap_wallet_a_functions.ap_sign_output_newpuzzlehash( APpuzzlehash, wallet, a_pubkey).sig) print(f"{informative} Approved change signature is: {sig}") print() print("Give the AP wallet the following initialisation string -") print(f"{informative} Initialisation string: {str(APpuzzlehash)}:{hexlify(a_pubkey).decode('ascii')}:{sig}") print() print("The next step is to approve some contacts for the AP wallet to send to.") print("From another standard wallet press '4' to print out their puzzlehash for receiving money.") choice = "" while choice != "q": singlestr = input("Enter approved puzzlehash: ") if singlestr == "q": return puzzlehash = puzzlehash_from_string(singlestr) print() #print("Puzzle: " + str(puzzlehash)) sig = wallet.sign(puzzlehash, a_pubkey) #print("Signature: " + str(sig.sig)) name = input("Add a name for this puzzlehash: ") print("Give the following contact string to the AP wallet.") print(f"{informative} Contact string for AP Wallet: {name}:{str(puzzlehash)}:{str(sig.sig)}") choice = input("Press 'c' to continue, or 'q' to quit to menu: ") async def process_blocks(wallet, ledger_api, last_known_header, current_header_hash): r = await ledger_api.hash_preimage(hash=current_header_hash) header = Header.from_bytes(r) body = Body.from_bytes(await ledger_api.hash_preimage(hash=header.body_hash)) if header.previous_hash != last_known_header: await process_blocks(wallet, ledger_api, last_known_header, header.previous_hash) print(f'processing block {HeaderHash(header)}') additions = list(additions_for_body(body)) removals = removals_for_body(body) removals = [Coin.from_bytes(await ledger_api.hash_preimage(hash=x)) for x in removals] wallet.notify(additions, removals) async def farm_block(wallet, ledger_api, last_known_header): coinbase_puzzle_hash = wallet.get_new_puzzlehash() fees_puzzle_hash = wallet.get_new_puzzlehash() r = await ledger_api.next_block(coinbase_puzzle_hash=coinbase_puzzle_hash, fees_puzzle_hash=fees_puzzle_hash) header = r['header'] header_hash = HeaderHash(header) tip = await ledger_api.get_tip() await process_blocks(wallet, ledger_api, tip['genesis_hash'] if last_known_header is None else last_known_header, header_hash) return header_hash async def update_ledger(wallet, ledger_api, most_recent_header): r = await ledger_api.get_tip() if r['tip_hash'] != most_recent_header: await process_blocks(wallet, ledger_api, r['genesis_hash'] if most_recent_header is None else most_recent_header, r['tip_hash']) return r['tip_hash'] async def main_loop(): ledger_api = await connect_to_ledger_sim("localhost", 9868) selection = "" wallet = Wallet() print(divider) print_leaf() r = await ledger_api.get_tip() most_recent_header = r['genesis_hash'] while selection != "q": print(divider) view_funds(wallet) print(divider) print(start_list) print("Select a function:") print(f"{selectable} 1: Make Payment") print(f"{selectable} 2: Get Update") print(f"{selectable} 3: Farm Block") print(f"{selectable} 4: Print my details for somebody else") print(f"{selectable} 5: Set my wallet name") print(f"{selectable} 6: Initiate Authorised Payee") if qrcode: print(f"{selectable} 7: Make QR code") print(f"{selectable} 8: Payment to QR code") print(f"{selectable} q: Quit") print(close_list) selection = input(prompt) if selection == "1": r = await make_payment(wallet, ledger_api) elif selection == "2": most_recent_header = await update_ledger(wallet, ledger_api, most_recent_header) elif selection == "3": most_recent_header = await farm_block(wallet, ledger_api, most_recent_header) elif selection == "4": print_my_details(wallet) elif selection == "5": set_name(wallet) elif selection == "6": await initiate_ap(wallet, ledger_api) if qrcode: if selection == "7": make_QR(wallet) elif selection == "8": r = read_qr(wallet) if r is not None: await ledger_api.push_tx(tx=r) def main(): run = asyncio.get_event_loop().run_until_complete run(main_loop()) if __name__ == "__main__": main() """ Copyright 2018 Chia Network Inc Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """