Resolved issues with script
This commit is contained in:
parent
d06ba7560c
commit
057c306df4
85
tx.py
85
tx.py
@ -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,26 +103,42 @@ 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}"
|
||||||
if method == 'GET':
|
print("🌐 API CALL:", method, url)
|
||||||
resp = requests.get(url)
|
if data:
|
||||||
else:
|
print("📨 Payload:", json.dumps(data, indent=2) if isinstance(data, dict) else data)
|
||||||
if isinstance(data, str) and endpoint.startswith("utils/"):
|
|
||||||
headers = {'Content-Type': 'text/plain'}
|
headers = {}
|
||||||
resp = requests.post(url, headers=headers, data=data)
|
resp = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
if method == 'GET':
|
||||||
|
resp = requests.get(url)
|
||||||
else:
|
else:
|
||||||
headers = {'Content-Type': 'application/json'}
|
if isinstance(data, str):
|
||||||
resp = requests.post(url, headers=headers, json=data)
|
headers['Content-Type'] = 'text/plain'
|
||||||
resp.raise_for_status()
|
resp = requests.post(url, headers=headers, data=data)
|
||||||
return resp.text.strip('"')
|
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 = {
|
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):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user