From 057c306df48250fb9abfe7513061adf2d31edc89 Mon Sep 17 00:00:00 2001 From: crowetic Date: Sat, 19 Apr 2025 17:32:28 -0700 Subject: [PATCH] Resolved issues with script --- tx.py | 87 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/tx.py b/tx.py index 8e82f8b..e62888d 100755 --- a/tx.py +++ b/tx.py @@ -27,7 +27,7 @@ TRANSACTION_TYPES = { "update_group": {"url": "groups/update", "required": ["groupId", "newOwner", "newDescription", "newIsOpen", "newApprovalThreshold"], "key_name": "ownerPublicKey"}, "join_group": {"url": "groups/join", "required": ["groupId"], "key_name": "joinerPublicKey"}, "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"}, "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"}, @@ -78,23 +78,17 @@ def get_last_reference(address): 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): - num = int(hex_str, 16) - encode = "" - while num > 0: - num, rem = divmod(num, 58) - encode = BASE58_ALPHABET[rem] + encode - return encode + return api_call("utils/toBase58", hex_str) def decode_base58(b58_str): - num = 0 - for char in b58_str: - num *= 58 - num += BASE58_MAP[char] - hex_str = hex(num)[2:] - return hex_str.zfill(66) + return api_call("utils/fromBase58", b58_str) def get_group_owner_pubkey(group_id): try: @@ -109,26 +103,42 @@ def get_group_owner_pubkey(group_id): raise def pubkey_to_address(pubkey): - pubkey_bytes = bytes.fromhex(decode_base58(pubkey)) - 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) + return api_call(f"addresses/convert/{pubkey}", method='GET') + def api_call(endpoint, data=None, method='POST'): url = f"{BASE_URL}/{endpoint}" - if method == 'GET': - resp = requests.get(url) - else: - if isinstance(data, str) and endpoint.startswith("utils/"): - headers = {'Content-Type': 'text/plain'} - resp = requests.post(url, headers=headers, data=data) + 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': + resp = requests.get(url) else: - headers = {'Content-Type': 'application/json'} - resp = requests.post(url, headers=headers, json=data) - resp.raise_for_status() - return resp.text.strip('"') + if isinstance(data, str): + headers['Content-Type'] = 'text/plain' + resp = requests.post(url, headers=headers, data=data) + else: + headers['Content-Type'] = 'application/json' + resp = requests.post(url, headers=headers, json=data) + + 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('"') + + except requests.HTTPError as e: + print(f"โŒ API call failed: {e}") + try: + print("๐Ÿงพ Response:", resp.json()) + except: + print("๐Ÿงพ Raw response:", resp.text) + raise @@ -141,7 +151,6 @@ def build_raw(tx_type, priv_key, values): data = { "timestamp": int(time.time() * 1000), "fee": DEFAULT_FEE, - tx_info.get("key_name", "senderPublicKey"): pub_key, } if reference: data["reference"] = reference @@ -149,6 +158,12 @@ def build_raw(tx_type, priv_key, values): data.update(values) 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: for key in tx_info["remove"]: data.pop(key, None) @@ -158,6 +173,11 @@ def build_raw(tx_type, priv_key, values): if opt_key not in data: 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(json.dumps(data, indent=2)) @@ -166,8 +186,11 @@ def build_raw(tx_type, priv_key, values): if "pow_url" in tx_info: raw_tx = api_call(tx_info["pow_url"], raw_tx) - return raw_tx + print("๐Ÿงช Parsed input values:") + print(json.dumps(values, indent=2)) + return raw_tx + def sign_tx(privkey, raw_tx): data = { "privateKey": privkey,