def green(debug, network, auth, config_dir, compact, watch_only, tor): """Command line interface for green gdk""" global context if context is not None: # Retain context over multiple commands in repl mode return if debug: logging.basicConfig(level=logging.DEBUG) config_dir = config_dir or os.path.expanduser( os.path.join('~', '.green-cli', network)) try: os.makedirs(config_dir) except FileExistsError: pass gdk.init({}) session = Session({'name': network, 'use_tor': tor}) atexit.register(session.destroy) if watch_only: auth = 'watch-only' authenticator = get_authenticator(auth, config_dir) context = Context(config_dir, session, network, TwoFactorResolver(), authenticator, compact)
def green(**options): """Command line interface for Blockstream Green.""" if context.configured: # In repl mode run configuration once only return if options['log_level']: py_log_level = { 'error': logging.ERROR, 'warning': logging.WARNING, 'info': logging.INFO, 'debug': logging.DEBUG, }[options['log_level']] logging.basicConfig(level=py_log_level) if options['config_dir'] is None: options['config_dir'] = _get_config_dir(options) os.makedirs(options['config_dir'], exist_ok=True) gdk.init({}) if options['watch_only']: options['auth'] = 'watchonly' authenticator = _get_authenticator(options) context.configure(authenticator, options)
def green(debug, network, auth, config_dir, compact): """Command line interface for green gdk""" global context if context is not None: # Retain context over multiple commands in repl mode return if debug: logging.basicConfig(level=logging.DEBUG) if network == 'mainnet': raise click.ClickException("This tool is not currently suitable for use on mainnet") config_dir = config_dir or os.path.expanduser(os.path.join('~', '.green-cli', network)) try: os.makedirs(config_dir) except FileExistsError: pass gdk.init({}) session = gdk.Session({'name': network}) atexit.register(session.destroy) authenticator = get_authenticator(auth, config_dir) context = Context(session, network, TwoFactorResolver(), authenticator, compact)
def download_file_gdk(hw_target, write_compressed, index_file, auto_select_fw): import greenaddress as gdk import base64 import json # We need to pass the relevant root certificate with open(FWSERVER_CERTIFICATE_FILE, 'r') as cf: root_cert = cf.read() gdk.init({}) session = gdk.Session({'name': 'mainnet'}) # GET the index file from the firmware server which lists the # available firmwares url = f'{FWSERVER_URL_ROOT}/{hw_target}/{index_file}' logger.info(f'Downloading firmware index file {url} using gdk') params = {'method': 'GET', 'root_certificates': [root_cert], 'urls': [url]} rslt = gdk.http_request(session.session_obj, json.dumps(params)) rslt = json.loads(rslt) assert 'body' in rslt, f'Cannot download index file {url}: {rslt.get("error")}' # Get the filename of the firmware to download fwname = get_fw_filename(rslt['body'], auto_select_fw) fwlen = get_expected_fw_length(fwname) # GET the selected firmware from the server in base64 encoding url = f'{FWSERVER_URL_ROOT}/{hw_target}/{fwname}' logger.info(f'Downloading firmware {url} using gdk') params['urls'] = [url] params['accept'] = 'base64' rslt = gdk.http_request(session.session_obj, json.dumps(params)) rslt = json.loads(rslt) assert 'body' in rslt, f'Cannot download firmware file {url}: {rslt.get("error")}' fw_b64 = rslt['body'] fwcmp = base64.b64decode(fw_b64) logger.info('Downloaded {len(fwcmp)} byte firmware') # If passed --write-compressed we write a copy of the compressed file if write_compressed: write_cmpfwfile(fwname, fwcmp) # Return return fwcmp, fwlen
def download_file_gdk(hw_target, write_compressed, release): import greenaddress as gdk import base64 gdk.init({}) session = gdk.Session({'name': 'mainnet'}) # GET the index file from the firmware server which lists the # available firmwares url = f'{FWSERVER_URL_ROOT}/{hw_target}/{FWSERVER_INDEX_FILE}' logger.info(f'Downloading firmware index file {url} using gdk') params = {'method': 'GET', 'urls': [url]} rslt = gdk.http_request(session.session_obj, json.dumps(params)) rslt = json.loads(rslt) assert 'body' in rslt, f'Cannot download index file {url}: {rslt.get("error")}' # Get the filename of the firmware to download release_data = json.loads(rslt['body'])[release] if not release_data: return None fwdata = get_fw_metadata(release_data) fwname = fwdata['filename'] # GET the selected firmware from the server in base64 encoding url = f'{FWSERVER_URL_ROOT}/{hw_target}/{fwname}' logger.info(f'Downloading firmware {url} using gdk') params = {'method': 'GET', 'urls': [url], 'accept': 'base64'} rslt = gdk.http_request(session.session_obj, json.dumps(params)) rslt = json.loads(rslt) assert 'body' in rslt, f'Cannot download firmware file {url}: {rslt.get("error")}' fw_b64 = rslt['body'] fwcmp = base64.b64decode(fw_b64) logger.info(f'Downloaded {len(fwcmp)} byte firmware') # If passed --write-compressed we write a copy of the compressed file if write_compressed: cmpfilename = f'{COMP_FW_DIR}/{fwname}' fwtools.write(fwcmp, cmpfilename) # Return return fwdata['fwsize'], fwdata.get('patch_size'), fwcmp
def green(**options): """Command line interface for Blockstream Green.""" if context.configured: # In repl mode run configuration once only return if options['log_level']: py_log_level = { 'error': logging.ERROR, 'warn': logging.WARNING, 'info': logging.INFO, 'debug': logging.DEBUG, }[options['log_level']] logging.basicConfig(level=py_log_level) if options['config_dir'] is None: options['config_dir'] = _get_config_dir(options) os.makedirs(options['config_dir'], exist_ok=True) if options['datadir'] is None: options['datadir'] = os.path.join(options['config_dir'], 'gdk_datadir') os.makedirs(options['datadir'], exist_ok=True) if options['tordir'] is None: options['tordir'] = os.path.join(options['config_dir'], 'gdk_tordir') os.makedirs(options['tordir'], exist_ok=True) gdk.init({ 'log_level': options['gdk_log'], 'datadir': options['datadir'], 'tordir': options['tordir'], }) if options['watch_only']: options['auth'] = 'watchonly' # Load additional config json file for the authenticator if required _normalise_auth_config(options) authenticator = _get_authenticator(options) context.configure(authenticator, options)
def green(**options): """Command line interface for green gdk""" global context if context is not None: # Retain context over multiple commands in repl mode return session_params = { 'name': options['network'], 'use_tor': options['tor'], 'log_level': options['gdk_log'], } if options['log_level']: py_log_level = { 'error': logging.ERROR, 'warning': logging.WARNING, 'info': logging.INFO, 'debug': logging.DEBUG, }[options['log_level']] logging.basicConfig(level=py_log_level) if options['config_dir'] is None: options['config_dir'] = _get_config_dir(options) try: os.makedirs(options['config_dir']) except FileExistsError: pass gdk.init({}) session = Session(session_params) atexit.register(session.destroy) if options['watch_only']: options['auth'] = 'watchonly' authenticator = get_authenticator(options) authenticator = get_authenticator(options) context = Context(session, TwoFactorResolver(), authenticator, options)
logger = logging.getLogger('jade') logger.setLevel(logging.DEBUG) logger.addHandler(jadehandler) logger = logging.getLogger('jade-device') logger.setLevel(logging.DEBUG) logger.addHandler(jadehandler) # We can test with the gdk http_request() function if we have the wheel installed http_request_fn = None if USE_GDK_HTTP_CLIENT: import json import greenaddress as gdk gdk.init({}) gdk_session = gdk.Session({'name': 'mainnet'}) def http_request_fn(params): reply = gdk.http_request(gdk_session.session_obj, json.dumps(params)) return json.loads(reply) if len(sys.argv) > 1 and sys.argv[1] == 'ble': print('Fetching jade version info over BLE') serial_number = sys.argv[2] if len(sys.argv) > 2 else None create_jade_fn = JadeAPI.create_ble kwargs = {'serial_number': serial_number} else: print('Fetching jade version info over serial') serial_device = sys.argv[2] if len(sys.argv) > 2 else None
def main(): # Our calls to GDK are wrapped in the gdk_wallet class, which should only be # created using either create_new_wallet, login_with_mnemonic or # login_with_pin methods. The example uses Bitcoin's testnet. # Initialize GDK. gdk.init({}) # Wallet creation and login using Mnemonic # ======================================== # To create a wallet with a Managed Assets account, pass a mnemonic # into the following. You can generate a 24 word mnemonic yourself or # have GDK generate it for you by leaving mnemonic as None. # You can choose to create a wallet that's covered by 2FA or not. # 2FA can be activated or deactivated at any point in time. """ wallet = gdk_wallet.create_new_wallet(create_with_2fa_enabled=False, mnemonic=None) print(f'\nMnemonic: {wallet.mnemonic}') """ # To login to an existing wallet you can either use the mnemonic or pin. # Later we'll see how to use a pin, for now we will use the mnemonic. mnemonic = 'your twenty four word mnemonic goes here with single spaced words' if not gdk.validate_mnemonic(mnemonic): raise Exception("Invalid mnemonic.") # Login to a GDK wallet session using the mnemonic. wallet = gdk_wallet.login_with_mnemonic(mnemonic) # We can now perform calls against the session, such as get balance for # the logged in wallet. balance = wallet.get_balance() print(f'\n{json.dumps(balance, indent=4)}') # Using a pin to encrypt the mnemonic and login # ============================================= # You can also login using a pin. Setting the pin for the wallet returns # encrypted data that is saved to file. When you login with the pin, the # server will give you the key to decrypt the mnemonic which it uses to # login. If the pin is entered incorrectly 3 times the server will delete # the key and you must use the mnemonic to login. """ # Before setting the pin, login with the wallet's mnemonic. wallet = gdk_wallet.login_with_mnemonic(mnemonic) # Then set the pin for the wallet, this saves encrypted data to file. # Don't use the example value below, set you own. pin = 123456 # You only need to set the pin data once. wallet.set_pin(mnemonic, pin) # After setting the pin you can then login using pin and do not have to # enter the mnemonic again. The pin is used to decrypt the local file. wallet.login_with_pin(pin) """ # Two factor authorization # ======================== # You can add Two Factor Authentication (2FA) to a wallet when you create # it or enable or disable 2FA at a later date. # Check the current 2FA status for the wallet. twofactor_status = wallet.get_current_2fa_status() print(f'\n{json.dumps(twofactor_status, indent=4)}') # The example below will enable 2FA on an existing wallet and uses email by # default, which you can amend if you want. """ try: wallet.twofactor_auth_enabled(False) except RuntimeError as e: # Will error if 2FA is already enabled print(f'\nError: {e}\n') """ # Getting notification data from GDK to obtain the last block height # ================================================================== # The fetch_block_height example shows how to handle notification events # from Green by processing the notifications queue. block_height = wallet.fetch_block_height() print(f'\nCurrent Bitcoin block height: {block_height}') # Getting a new address # ===================== address_info = wallet.get_new_address() print(f'Address: {address_info["address"]}') # Getting transaction data from Green using GDK # ============================================= txs = wallet.get_wallet_transactions() for tx in txs: print(f'TRANSACTION ID : {tx["txhash"]}') print(f'CONFIRMATION STATUS : {tx["confirmation_status"]}') print(f'BLOCK HEIGHT : {tx["block_height"]}') print(f'TYPE : {tx["type"]}') print(f'INPUT COUNT : {len(tx["inputs"])}') print(f'OUTPUT COUNT : {len(tx["outputs"])}\n') # Sending assets # ============== amount_sat = 1001 address = 'destination address here' txid = wallet.send_to_address(amount_sat, address) if txid: print(f'\nTransaction sent. Txid: {txid}') else: print(f'\nTransaction failed. See error logging.')
def main(): # Our calls to GDK are wrapped in the gdk_wallet class, which should only be # created using either create_new_wallet, login_with_mnemonic or # login_with_pin methods. The example uses the live Liquid network. # Initialize GDK. gdk.init({}) # Wallet creation and login using Mnemonic # ======================================== # To create a wallet with a Managed Assets account, pass a mnemonic # into the following. You can generate a 24 word mnemonic yourself or # have GDK generate it for you by leaving mnemonic as None. # You can choose to create a wallet that's covered by 2FA or not. # 2FA can be activated or deactivated at any point in time. """ wallet = gdk_wallet.create_new_wallet(create_with_2fa_enabled=False, mnemonic=None) print(f'\nMnemonic: {wallet.mnemonic}') """ # To login to an existing wallet you can either use the mnemonic or pin. # Later we'll see how to use a pin, for now we will use the mnemonic. mnemonic = 'your twenty four word mnemonic goes here with single spaced words' if not gdk.validate_mnemonic(mnemonic): raise Exception("Invalid mnemonic.") # Login to a GDK wallet session using the mnemonic. wallet = gdk_wallet.login_with_mnemonic(mnemonic) # We can now perform calls against the session, such as get balance for # the logged in Blockstream AMP Managed Assets account. balance = wallet.get_balance() print(f'\n{json.dumps(balance, indent=4)}') # Using a pin to encrypt the mnemonic and login # ============================================= # You can also login using a pin. Setting the pin for the wallet returns # encrypted data that is saved to file. When you login with the pin, the # server will give you the key to decrypt the mnemonic which it uses to # login. If the pin is entered incorrectly 3 times the server will delete # the key and you must use the mnemonic to login. """ # Before setting the pin, login with the wallet's mnemonic. wallet = gdk_wallet.login_with_mnemonic(mnemonic) # Then set the pin for the wallet, this saves encrypted data to file. # Don't use the example value below, set you own. pin = 123456 # You only need to set the pin data once. wallet.set_pin(mnemonic, pin) # After setting the pin you can then login using pin and do not have to # enter the mnemonic again. The pin is used to decrypt the local file. wallet.login_with_pin(pin) """ # Two factor authorization # ======================== # You can add Two Factor Authentication (2FA) to a wallet when you create # it or enable or disable 2FA at a later date. # Check the current 2FA status for the wallet. twofactor_status = wallet.get_current_2fa_status() print(f'\n{json.dumps(twofactor_status, indent=4)}') # The example below will enable 2FA on an existing wallet and uses email by # default, which you can amend if you want. """ try: wallet.twofactor_auth_enabled(False) except RuntimeError as e: # Will error if 2FA is already enabled print(f'\nError: {e}\n') """ # Getting notification data from GDK to obtain the last block height # ================================================================== # The fetch_block_height example shows how to handle notification events # from Green by processing the notifications queue. block_height = wallet.fetch_block_height() print(f'\nCurrent Liquid block height: {block_height}') # Getting a new address and understanding pointers # ================================================ # The new address returned will be confidential, whereas GDK transactions # will show the unconfidential address. For this reason, use the address # 'pointer' to identify it in transactions. The pointer plus sub account # index maps to a derivation path so you can use pointers within each # sub account to link confidential and unconfidential addresses. Be sure # to note that you must consider which sub account you are using when # using the pointer as an identifier like this. address_info = wallet.get_new_address() print(f'Address: {address_info["address"]}') print(f'Address pointer: {address_info["pointer"]}') # Each call creates a new address/pointer pair for the user. address_info = wallet.get_new_address() print(f'Address: {address_info["address"]}') print(f'Address pointer: {address_info["pointer"]}') # Getting transaction data from Green using GDK # ============================================= txs = wallet.get_wallet_transactions() for tx in txs: print(f'TRANSACTION ID : {tx["txhash"]}') print(f'CONFIRMATION STATUS : {tx["confirmation_status"]}') print(f'BLOCK HEIGHT : {tx["block_height"]}') print(f'TYPE : {tx["type"]}') print(f'INPUT COUNT : {len(tx["inputs"])}') print(f'OUTPUT COUNT : {len(tx["outputs"])}\n') # Sending assets # ============== # Please be aware that AMP issued assets are issued with a precision # that affects how the number of sats sent are converted to the number # of units of the asset itself. Please refer to the examples under # 'precision' on the following page for more details and examples: # https://docs.blockstream.com/blockstream-amp/api-tutorial.html#issuing-an-asset # If the asset is registered with the Liquid Assets Registry you can # check the precision using the following link, or check with the # asset's issuer: # https://blockstream.info/liquid/assets amount_sat = 1 asset_id = 'asset id here' address = 'destination address here' txid = wallet.send_to_address(amount_sat, asset_id, address) if txid: print(f'\nTransaction sent. Txid: {txid}') else: print(f'\nTransaction failed. See error logging.')
@app.route('/api/about', methods=['GET']) @limiter.exempt def api_about(): data = about() return jsonify(data) @app.route('/about', methods=['GET']) @limiter.exempt def url_about(): data = about() return render_template('about', **data) if __name__ == '__main__': init({}) s = Session({"name": "testnet-liquid", "log_level": "info"}) s.login_user({}, {'mnemonic': gdkMnemonic}).resolve() s.change_settings({"unit": "sats"}).resolve() subaccount = -1 subaccounts = s.get_subaccounts().resolve() for sub in subaccounts['subaccounts']: if sub['name'] == gdkSubaccount: if sub['type'] != '2of2_no_recovery': pass subaccount = sub['pointer'] break app.import_name = '.' app.run(host='0.0.0.0', port=8123)