Resolved issues with script

This commit is contained in:
crowetic 2025-04-19 17:32:28 -07:00
parent d06ba7560c
commit 057c306df4

71
tx.py
View File

@ -27,7 +27,7 @@ TRANSACTION_TYPES = {
"update_group": {"url": "groups/update", "required": ["groupId", "newOwner", "newDescription", "newIsOpen", "newApprovalThreshold"], "key_name": "ownerPublicKey"}, "update_group": {"url": "groups/update", "required": ["groupId", "newOwner", "newDescription", "newIsOpen", "newApprovalThreshold"], "key_name": "ownerPublicKey"},
"join_group": {"url": "groups/join", "required": ["groupId"], "key_name": "joinerPublicKey"}, "join_group": {"url": "groups/join", "required": ["groupId"], "key_name": "joinerPublicKey"},
"leave_group": {"url": "groups/leave", "required": ["groupId"], "key_name": "leaverPublicKey"}, "leave_group": {"url": "groups/leave", "required": ["groupId"], "key_name": "leaverPublicKey"},
"group_invite": {"url": "groups/invite", "required": ["groupId", "invitee"], "key_name": "adminPublicKey"}, "group_invite": {"url": "groups/invite", "required": ["groupId", "txGroupId", "invitee"], "key_name": "adminPublicKey"},
"group_kick": {"url": "groups/kick", "required": ["groupId", "member", "reason"], "key_name": "adminPublicKey"}, "group_kick": {"url": "groups/kick", "required": ["groupId", "member", "reason"], "key_name": "adminPublicKey"},
"add_group_admin": {"url": "groups/addadmin", "required": ["groupId", "txGroupId", "member"], "key_name": "ownerPublicKey"}, "add_group_admin": {"url": "groups/addadmin", "required": ["groupId", "txGroupId", "member"], "key_name": "ownerPublicKey"},
"remove_group_admin": {"url": "groups/removeadmin", "required": ["groupId", "txGroupId", "admin"], "key_name": "ownerPublicKey"}, "remove_group_admin": {"url": "groups/removeadmin", "required": ["groupId", "txGroupId", "admin"], "key_name": "ownerPublicKey"},
@ -78,23 +78,17 @@ def get_last_reference(address):
def get_pub_key(privkey): def get_pub_key(privkey):
return api_call("utils/publickey", privkey) pubkey = api_call("utils/publickey", privkey)
if not pubkey or pubkey.strip().lower() == "none":
raise ValueError("❌ Invalid public key returned. Is the private key correct?")
return pubkey.strip()
def encode_base58(hex_str): def encode_base58(hex_str):
num = int(hex_str, 16) return api_call("utils/toBase58", hex_str)
encode = ""
while num > 0:
num, rem = divmod(num, 58)
encode = BASE58_ALPHABET[rem] + encode
return encode
def decode_base58(b58_str): def decode_base58(b58_str):
num = 0 return api_call("utils/fromBase58", b58_str)
for char in b58_str:
num *= 58
num += BASE58_MAP[char]
hex_str = hex(num)[2:]
return hex_str.zfill(66)
def get_group_owner_pubkey(group_id): def get_group_owner_pubkey(group_id):
try: try:
@ -109,27 +103,43 @@ def get_group_owner_pubkey(group_id):
raise raise
def pubkey_to_address(pubkey): def pubkey_to_address(pubkey):
pubkey_bytes = bytes.fromhex(decode_base58(pubkey)) return api_call(f"addresses/convert/{pubkey}", method='GET')
pkh = RIPEMD.new(sha256(pubkey_bytes).digest()).hexdigest()
raw = bytes.fromhex("3a" + pkh)
checksum = sha256(sha256(raw).digest()).hexdigest()[:8]
address_hex = "3a" + pkh + checksum
return encode_base58(address_hex)
def api_call(endpoint, data=None, method='POST'): def api_call(endpoint, data=None, method='POST'):
url = f"{BASE_URL}/{endpoint}" url = f"{BASE_URL}/{endpoint}"
print("🌐 API CALL:", method, url)
if data:
print("📨 Payload:", json.dumps(data, indent=2) if isinstance(data, dict) else data)
headers = {}
resp = None
try:
if method == 'GET': if method == 'GET':
resp = requests.get(url) resp = requests.get(url)
else: else:
if isinstance(data, str) and endpoint.startswith("utils/"): if isinstance(data, str):
headers = {'Content-Type': 'text/plain'} headers['Content-Type'] = 'text/plain'
resp = requests.post(url, headers=headers, data=data) resp = requests.post(url, headers=headers, data=data)
else: else:
headers = {'Content-Type': 'application/json'} headers['Content-Type'] = 'application/json'
resp = requests.post(url, headers=headers, json=data) resp = requests.post(url, headers=headers, json=data)
resp.raise_for_status() resp.raise_for_status()
content_type = resp.headers.get('Content-Type', '')
if 'application/json' in content_type:
return json.dumps(resp.json())
return resp.text.strip('"') return resp.text.strip('"')
except requests.HTTPError as e:
print(f"❌ API call failed: {e}")
try:
print("🧾 Response:", resp.json())
except:
print("🧾 Raw response:", resp.text)
raise
def build_raw(tx_type, priv_key, values): def build_raw(tx_type, priv_key, values):
@ -141,7 +151,6 @@ def build_raw(tx_type, priv_key, values):
data = { data = {
"timestamp": int(time.time() * 1000), "timestamp": int(time.time() * 1000),
"fee": DEFAULT_FEE, "fee": DEFAULT_FEE,
tx_info.get("key_name", "senderPublicKey"): pub_key,
} }
if reference: if reference:
data["reference"] = reference data["reference"] = reference
@ -149,6 +158,12 @@ def build_raw(tx_type, priv_key, values):
data.update(values) data.update(values)
data.update(tx_info.get("defaults", {})) data.update(tx_info.get("defaults", {}))
# Always use the signer's pubkey for txGroupId-based approval-required transactions
if "txGroupId" in data and str(data["txGroupId"]) != "0" and "key_name" in tx_info:
data[tx_info["key_name"]] = pub_key
elif "key_name" in tx_info:
data[tx_info["key_name"]] = pub_key
if "remove" in tx_info: if "remove" in tx_info:
for key in tx_info["remove"]: for key in tx_info["remove"]:
data.pop(key, None) data.pop(key, None)
@ -158,6 +173,11 @@ def build_raw(tx_type, priv_key, values):
if opt_key not in data: if opt_key not in data:
data[opt_key] = tx_info.get("defaults", {}).get(opt_key, None) data[opt_key] = tx_info.get("defaults", {}).get(opt_key, None)
# Auto-convert numeric-looking strings to int
for key in list(data.keys()):
if isinstance(data[key], str) and data[key].isdigit():
data[key] = int(data[key])
print("📦 Final JSON Payload:") print("📦 Final JSON Payload:")
print(json.dumps(data, indent=2)) print(json.dumps(data, indent=2))
@ -166,6 +186,9 @@ def build_raw(tx_type, priv_key, values):
if "pow_url" in tx_info: if "pow_url" in tx_info:
raw_tx = api_call(tx_info["pow_url"], raw_tx) raw_tx = api_call(tx_info["pow_url"], raw_tx)
print("🧪 Parsed input values:")
print(json.dumps(values, indent=2))
return raw_tx return raw_tx
def sign_tx(privkey, raw_tx): def sign_tx(privkey, raw_tx):