import json
import sys
import time
import os
import green_gdk as gdk
def main():
valid_environments = ['dev', 'test', 'amp']
environment = 'dev' verbose = False
original_stderr = None
args = sys.argv[1:]
if '-v' in args or '--verbose' in args:
verbose = True
args = [arg for arg in args if arg not in ['-v', '--verbose']]
if len(args) > 0:
environment = args[0].lower()
if environment not in valid_environments:
print(f"Error: Invalid environment '{environment}'")
print(f"Valid environments are: {', '.join(valid_environments)}")
sys.exit(1)
if verbose:
print(f"Using environment: {environment}")
if not verbose:
original_stderr = sys.stderr
sys.stderr = open(os.devnull, 'w')
try:
gdk.init({
'datadir': '.', 'log_level': 'none' if not verbose else 'warn'
})
except:
gdk.init({
'datadir': '.',
'log_level': 'warn'
})
mnemonics = {
'dev': "vote ball voice juice visit license music off paddle hold suffer beach someone hover wheat boring protect broccoli issue opinion uniform media update arrange",
'test': "hood novel finish couch rack pistol march army gun bring universe unknown hurry famous vote enact inspire whisper violin blur chief into engage cigar",
'amp': "perfect grit monkey disorder cliff exhibit meat giant dream secret liberty walnut later caught snow wasp bulb bind feature couple vault flower credit bundle"
}
mnemonic = mnemonics[environment]
if not gdk.validate_mnemonic(mnemonic):
raise Exception("Invalid mnemonic")
session = gdk.Session({'name': 'testnet-liquid'})
credentials = {'mnemonic': mnemonic}
def login_with_retry(session, credentials, verbose, max_retries=3):
for attempt in range(max_retries):
try:
try:
if verbose:
print("Attempting to login to existing wallet...")
session.login_user({}, credentials).resolve()
if verbose:
print("Successfully logged in to existing wallet")
return session
except RuntimeError as e:
if 'id_login_failed' in str(e):
if verbose:
print("Wallet doesn't exist, registering new wallet...")
session.register_user({}, credentials).resolve()
session.login_user({}, credentials).resolve()
if verbose:
print("Successfully registered and logged in")
return session
else:
raise
except RuntimeError as e:
if 'reconnect required' in str(e) and attempt < max_retries - 1:
if verbose:
print(f"Connection error, retrying... (attempt {attempt + 2}/{max_retries})")
time.sleep(2)
session = gdk.Session({'name': 'testnet-liquid'})
else:
raise
return session
session = login_with_retry(session, credentials, verbose)
subaccounts_result = session.get_subaccounts().resolve()
existing_subaccounts = {}
for subaccount in subaccounts_result['subaccounts']:
if subaccount['type'] == '2of2_no_recovery':
existing_subaccounts[subaccount['name']] = subaccount
gaids = []
if verbose:
print("\nCreating/retrieving 20 subaccounts...")
for i in range(1, 21):
account_name = f"GAID {environment.upper()} Account {i:02d}"
if account_name in existing_subaccounts:
subaccount = existing_subaccounts[account_name]
pointer = subaccount['pointer']
gaid = subaccount['receiving_id']
if verbose:
print(f" Found existing subaccount {i:2d}: {account_name}")
else:
if verbose:
print(f" Creating new subaccount {i:2d}: {account_name}")
create_details = {
'name': account_name,
'type': '2of2_no_recovery'
}
max_retries = 3
for attempt in range(max_retries):
try:
result = session.create_subaccount(create_details).resolve()
pointer = result['pointer']
subaccount_details = session.get_subaccount(pointer).resolve()
gaid = subaccount_details['receiving_id']
break
except RuntimeError as e:
if 'reconnect required' in str(e) and attempt < max_retries - 1:
if verbose:
print(f" Connection error, retrying... (attempt {attempt + 2}/{max_retries})")
time.sleep(2)
try:
session.login_user({}, credentials).resolve()
except:
session = gdk.Session({'name': 'testnet-liquid'})
session.login_user({}, credentials).resolve()
else:
raise
user_privkey = 'N/A'
user_pubkey = 'N/A'
service_pubkey = 'N/A'
try:
addr_details = session.get_receive_address({'subaccount': pointer}).resolve()
script = addr_details.get('script', '')
try:
try:
addr_with_priv = session.get_receive_address({
'subaccount': pointer,
'show_priv_key': True }).resolve()
if 'priv_key' in addr_with_priv:
user_privkey = addr_with_priv['priv_key']
elif 'private_key' in addr_with_priv:
user_privkey = addr_with_priv['private_key']
except:
pass
if user_privkey == 'N/A':
try:
prev_addrs = session.get_previous_addresses({
'subaccount': pointer,
'last_pointer': 10 }).resolve()
if 'list' in prev_addrs:
for addr_info in prev_addrs['list']:
if 'private_key' in addr_info:
user_privkey = addr_info['private_key']
break
elif 'priv_key' in addr_info:
user_privkey = addr_info['priv_key']
break
except:
pass
if user_privkey == 'N/A':
try:
root_path = session.get_subaccount_root_path(pointer).resolve()
except:
pass
except Exception as e:
if verbose:
print(f" Note: Could not extract private key for account {i}")
if script and len(script) > 140: try:
if script[:4] == '5221':
user_pubkey = script[4:4+66] if script[70:72] == '21':
service_pubkey = script[72:72+66]
except Exception as e:
if verbose:
print(f" Warning: Could not parse script for account {i}: {e}")
except Exception as e:
pass
gaids.append({
'index': i,
'name': account_name,
'pointer': pointer,
'gaid': gaid,
'user_privkey': user_privkey,
'user_pubkey': user_pubkey,
'service_pubkey': service_pubkey
})
if verbose:
print("\n" + "=" * 100)
print(f"20 Subaccounts with their GAIDs and Public Keys (Environment: {environment.upper()}):")
print("=" * 100)
for account in gaids:
print(f"{account['index']:2d}. {account['name']:<25} GAID: {account['gaid']}")
print(f" User PrivKey: {account['user_privkey']}")
print(f" User PubKey: {account['user_pubkey']}")
print(f" Service PubKey: {account['service_pubkey']}")
print()
print("=" * 100)
print(f"Total subaccounts: {len(gaids)}")
print("=" * 100)
print("\n" + "=" * 100)
print("JSON Output:")
print("=" * 100)
gaid_list = [account['gaid'] for account in gaids]
json_output = {
'gaids': gaid_list
}
print(json.dumps(json_output, indent=2))
if verbose:
print("=" * 100)
if not verbose and original_stderr is not None:
sys.stderr.close()
sys.stderr = original_stderr
return gaids
if __name__ == "__main__":
verbose = '-v' in sys.argv or '--verbose' in sys.argv
try:
gaids = main()
if verbose:
print(f"\nSuccessfully processed {len(gaids)} subaccounts!")
except Exception as e:
if verbose:
print(f"Error: {e}", file=sys.stderr)
import traceback
traceback.print_exc()
else:
print(json.dumps({"error": str(e)}), file=sys.stderr)
sys.exit(1)