def create_wallet(): global wallet_name if request.method == 'GET': return render_template('create-wallet.html') else: try: wallet_name = request.form['name'] m = int(request.form['m']) n = int(request.form['n']) MultisigWallet.create(wallet_name, m, n) flash_success('Wallet created') except JunctionError as e: flash_error(str(e)) return render_template('create-wallet.html') return redirect(url_for('wallet'))
def broadcast(): wallet = MultisigWallet.open(wallet_name) wallet.broadcast() wallet.remove_psbt() wallet.save() flash_success('transaction broadcasted successfully') return redirect(url_for('wallet'))
def sign_psbt(fingerprint): wallet = MultisigWallet.open(wallet_name) client, device = get_client_and_device(fingerprint) psbt = wallet.psbt raw_signed_psbt = client.sign_tx(wallet.psbt)['psbt'] new_psbt = serializations.PSBT() new_psbt.deserialize(raw_signed_psbt) wallet.psbt = new_psbt wallet.save() # FIXME: display the signer name here ... flash_success(f'{device["type"]} signed successfully') return redirect(url_for('wallet'))
def wallet(): wallet = MultisigWallet.open(wallet_name) devices = commands.enumerate() unconfirmed_balance, confirmed_balance = wallet.balances() # FIXME: ugly if wallet.psbt: psbt = wallet.decode_psbt() pprint(psbt) for signer in wallet.signers: signed = False # FIXME: this should check they've signed every input, not just one input for input in psbt['inputs']: for deriv in input['bip32_derivs']: fingerprint_match = deriv['master_fingerprint'] == signer[ 'fingerprint'] pubkey_match = deriv['pubkey'] in input.get( 'partial_signatures', []) if fingerprint_match and pubkey_match: signed = True signer['signed'] = signed else: psbt = None # FIXME: ugly for signer in wallet.signers: match = {'error': "Not found"} # note: "Not found" is used in UI for device in devices: if device.get('fingerprint') == signer['fingerprint']: match = device signer['device'] = match # FIXME: ugly signer_fingerprints = [signer['fingerprint'] for signer in wallet.signers] potential_signers = [ d for d in devices if 'fingerprint' not in d or d['fingerprint'] not in signer_fingerprints ] return render_template('wallet.html', devices=devices, wallet=wallet, psbt=psbt, unconfirmed_balance=unconfirmed_balance, confirmed_balance=confirmed_balance, potential_signers=potential_signers, btc_to_sat=btc_to_sat)
def add_signer(fingerprint): wallet = MultisigWallet.open(wallet_name) client, device = get_client_and_device(fingerprint) # Add a "signer" to the wallet account_path = "m/44h/1h/0h" base_key = client.get_pubkey_at_path(account_path)['xpub'] wallet.add_signer(device['type'], device['fingerprint'], base_key, account_path) # FIXME: only works when coldcard added last if device['type'] == 'coldcard': client.close() coldcard_enroll(wallet) msg = f"Signer \"{device['type']}\" has been added to your \"{wallet.name}\" wallet" flash_success(msg) return redirect(url_for('wallet'))
def create_psbt(): wallet = MultisigWallet.open(wallet_name) wallet.create_psbt(request.form['recipient'], int(request.form['satoshis'])) return redirect(url_for('wallet'))
def address(): wallet = MultisigWallet.open(wallet_name) address = wallet.address() return address, 200
def export(): wallet = MultisigWallet.open(wallet_name) wallet.export_watchonly() return redirect(url_for('wallet'))
devices = commands.enumerate() # prompt pins for device in devices: if device.get('needs_pin_sent'): global trezor_client trezor_client = trezor.TrezorClient(device['path']) trezor_client.prompt_pin() everything_unlocked = not any(['error' in device for device in devices]) return render_template('devices.html', devices=devices, everything_unlocked=everything_unlocked) if __name__ == '__main__': # FIXME: hack to prevent unloaded wallet try: wallet = MultisigWallet.open(wallet_name) wallet.ensure_watchonly() except: pass # Run flask, kill bitcoind on ctrl-c try: app.run(debug=True, threaded=False) except KeyboardInterrupt: process.terminate() print()