Skip to content

Instantly share code, notes, and snippets.

@hussu010
Created January 5, 2022 10:49
Show Gist options
  • Save hussu010/b2947f319b6fd774a21a9f55b1b12bb3 to your computer and use it in GitHub Desktop.
Save hussu010/b2947f319b6fd774a21a9f55b1b12bb3 to your computer and use it in GitHub Desktop.
'''
Required third party libraries
- requests: python -m pip install requests
- PyNaCl: pip install pynacl
'''
import requests
import json
from nacl.encoding import HexEncoder
import nacl.signing
from operator import itemgetter
# Utils
def generate_block(balance_lock, transactions, signing_key):
account_number = signing_key.verify_key.encode(encoder=HexEncoder).decode('utf-8')
message = {
'balance_key': balance_lock,
'txs': sorted(transactions, key=itemgetter('recipient'))
}
signature = signing_key.sign(json.dumps(message, separators=(',', ':'), sort_keys=True).encode('utf-8')).signature.hex()
block = {
'account_number': account_number,
'message': message,
'signature': signature
}
return json.dumps(block)
# -------------------------------------------------------------------
def send_tnbc(*, bank_ip, signing_key, destination_account_number, amount, memo):
success = False
message = ""
# Check if signing key is valid hexadecimal
try:
int(signing_key, 16)
except ValueError as exception:
message = "{'error': 'Non-hexadecimal digit found'}"
return success, message
# Check if the length of the key is 64
if len(signing_key) != 64:
message = "{'error': 'Invalid length of the Singing Key'}"
return success, message
nacl_signing_key = nacl.signing.SigningKey(str.encode(signing_key), encoder=nacl.encoding.HexEncoder)
payment_account_number = nacl_signing_key.verify_key.encode(encoder=nacl.encoding.HexEncoder).decode('utf-8')
try:
bank_config_url = f'http://{bank_ip}/config?format=json'
bank_config = requests.get(bank_config_url).json()
balance_lock_url = f"{bank_config['primary_validator']['protocol']}://{bank_config['primary_validator']['ip_address']}:{bank_config['primary_validator']['port'] or 0}/accounts/{payment_account_number}/balance_lock?format=json"
balance_lock = requests.get(balance_lock_url).json()['balance_lock']
# Handling bank config and balance lock exceptions gracefully.
except requests.exceptions.Timeout:
message = "{'error': 'The request timed out while trying to retrieve bank config.'}"
return success, message
except requests.exceptions.ConnectionError:
message = "{'error': 'Connection error occurred while trying to retrieve bank config.'}"
return success, message
except requests.exceptions.HTTPError:
message = "{'error': 'An HTTP error occurred while trying to retrieve bank config.'}"
return success, message
except requests.exceptions.RequestException as exception:
message = "{'error': 'Error while trying to retrieve bank config: %s'}" % exception
return success, message
# Check if the signing key is initialized. If not, request the user to initialize by sending a tnbc.
if not balance_lock:
message = "{'error': 'Signing key not initialized. Please send a tnbc to %s to initialize.'}" % payment_account_number
return success, message
# Creating a transaction to generate a block.
txs = [
{
'amount': amount,
'memo': memo,
'recipient': destination_account_number,
},
{
'amount': int(bank_config['default_transaction_fee']),
'fee': 'BANK',
'recipient': bank_config['account_number'],
},
{
'amount': int(bank_config['primary_validator']['default_transaction_fee']),
'fee': 'PRIMARY_VALIDATOR',
'recipient': bank_config['primary_validator']['account_number'],
}
]
# generate a transaction block with transaction info.
data = generate_block(balance_lock, txs, nacl_signing_key)
headers = {
'Connection': 'keep-alive',
'Accept': 'application/json, text/plain, */*',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) TNBAccountManager/1.0.0-alpha.43 Chrome/83.0.4103.122 Electron/9.4.0 Safari/537.36',
'Content-Type': 'application/json',
}
try:
response = requests.post(f'http://{bank_ip}/blocks', headers=headers, data=data)
if response.status_code == 201:
success = True
message = response.json()
else:
message = response
# Handling block exceptions gracefully.
except requests.exceptions.Timeout:
message = "{'error': 'The request timed out while trying to create a block.'}"
return success, message
except requests.exceptions.ConnectionError:
message = "{'error': 'A Connection error occurred while trying to create a block.'}"
return success, message
except requests.exceptions.HTTPError:
message = "{'error': 'An HTTP error occurred while trying to create a block.'}"
return success, message
except requests.exceptions.RequestException as exception:
message = "{'error': 'Error while trying to create a block: %s'}" % exception
return success, message
return success, message
print(send_tnbc(bank_ip="BANK_IP", signing_key="SIGNING_KEY", destination_account_number="DESTINATION_MEMO", amount=1, memo="MEMO"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment