diff --git a/pay-gui.py b/gui-tkinter.py similarity index 100% rename from pay-gui.py rename to gui-tkinter.py diff --git a/libs/paylib.py b/libs/paylib.py new file mode 100644 index 0000000..c135aa2 --- /dev/null +++ b/libs/paylib.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 + +import sys, re, os.path, json, ast +from shutil import copyfile +if not os.path.isfile("userEnv.py"): + copyfile("userEnv.py.template", "userEnv.py") +from termcolor import colored +from userEnv import dunikey, node +from natools import fmt, sign, get_privkey +from gql import gql, Client +from gql.transport.aiohttp import AIOHTTPTransport + +if not (dunikey): + print("Please set the path to your pubsec keychain in userEnv.py file.") + sys.exit(1) + +# Define Duniter GVA node +transport = AIOHTTPTransport(url=node) +client = Client(transport=transport, fetch_schema_from_transport=True) +issuer = get_privkey(dunikey, "pubsec").pubkey + +def sendGenDoc(recipient, amount, comment): + # TODO: Check args + + # Build TX generation document + queryBuild = gql( + """ + query ($recipient: String!, $issuer: String!, $amount: Int!, $comment: String!){ genTxs( + amount: $amount + comment: $comment + issuer: $issuer + recipient: $recipient + ) + } + """ + ) + paramsBuild = { + "recipient": recipient, + "issuer": issuer, + "amount": amount, + "comment": comment + } + + # Send TX document + try: + txDoc = str(client.execute(queryBuild, variable_values=paramsBuild))[13:-3].replace('\\n','\n') + return txDoc + except Exception as e: + message = ast.literal_eval(str(e))["message"] + sys.stderr.write("Echec de la génération du document:\n" + message + "\n") + sys.exit(1) + + +# Check document +def checkTXDoc(txDoc, recipient, amount, comment): + docList = txDoc.splitlines() + for i, line in enumerate(docList): + if re.search("Issuers:", line): + issuerRaw = docList[(i + 1) % len(docList)] + if re.search("Outputs:", line): + outputRaw = docList[(i + 1) % len(docList)].split(":") + outAmount = outputRaw[0] + outPubkey = outputRaw[2].split("SIG(")[1].replace(')','') + if re.search("Comment:", line): + commentRaw = line.split(': ', 1)[1] + + if issuerRaw != issuer or int(outAmount) != amount or outPubkey != recipient or commentRaw != comment: + sys.stderr.write(colored("Le document généré est corrompu !\nNe fait plus confiance au noeud " + node + "\n", 'red')) + sys.stderr.write(colored(issuerRaw + " envoi " + outAmount + " vers " + outPubkey + " with comment: " + commentRaw + "\n", "yellow")) + sys.exit(1) + else: + print("Le document généré est conforme.") + return True + + +def signDoc(txDoc): + # Sign TX document + signature = fmt["64"](sign(txDoc.encode(), get_privkey(dunikey, "pubsec"))[:-len(txDoc.encode())]) + signedDoc = txDoc + signature.decode() + + return signedDoc + + +def sendTXDoc(signedDoc): + # Build TX document + querySign = gql( + """ + mutation ($signedDoc: String!){ tx( + rawTx: $signedDoc + ) { + version + issuers + outputs + } + } + """ + ) + paramsSign = { + "signedDoc": signedDoc + } + + # Send TX Signed document + try: + client.execute(querySign, variable_values=paramsSign) + print(colored("Transaction effectué avec succès !", "green")) + except Exception as e: + message = ast.literal_eval(str(e))["message"] + sys.stderr.write("Echec de la transaction:\n" + message + "\n") + sys.exit(1) \ No newline at end of file diff --git a/pay.py b/pay.py index 37f3b6e..4da7fc8 100755 --- a/pay.py +++ b/pay.py @@ -1,24 +1,10 @@ #!/usr/bin/env python3 -import sys, re, os.path, json, ast -from shutil import copyfile -if not os.path.isfile("userEnv.py"): - copyfile("userEnv.py.template", "userEnv.py") -from termcolor import colored -from userEnv import dunikey, node -from natools import fmt, sign, get_privkey -from gql import gql, Client -from gql.transport.aiohttp import AIOHTTPTransport - -if not (dunikey): - print("Please set the path to your pubsec keychain in userEnv.py file.") - sys.exit(1) - -# Define Duniter GVA node -transport = AIOHTTPTransport(url=node) -client = Client(transport=transport, fetch_schema_from_transport=True) -issuer = get_privkey(dunikey, "pubsec").pubkey +import sys +sys.path.insert(1, 'libs') +from paylib import * +# Get args try: recipient = sys.argv[1] amount = int(sys.argv[2]) @@ -26,109 +12,17 @@ try: comment = sys.argv[3] else: comment = "" - graphic = False -except: - graphic = True - - -def sendGenDoc(recipient, amount, comment): - # TODO: Check args - - # Build TX generation document - queryBuild = gql( - """ - query ($recipient: String!, $issuer: String!, $amount: Int!, $comment: String!){ genTxs( - amount: $amount - comment: $comment - issuer: $issuer - recipient: $recipient - ) - } - """ - ) - paramsBuild = { - "recipient": recipient, - "issuer": issuer, - "amount": amount, - "comment": comment - } - - # Send TX document - try: - txDoc = str(client.execute(queryBuild, variable_values=paramsBuild))[13:-3].replace('\\n','\n') - return txDoc - except Exception as e: - message = ast.literal_eval(str(e))["message"] - sys.stderr.write("Echec de la génération du document:\n" + message + "\n") - sys.exit(1) - - -# Check document -def checkTXDoc(txDoc, recipient, amount, comment): - docList = txDoc.splitlines() - for i, line in enumerate(docList): - if re.search("Issuers:", line): - issuerRaw = docList[(i + 1) % len(docList)] - if re.search("Outputs:", line): - outputRaw = docList[(i + 1) % len(docList)].split(":") - outAmount = outputRaw[0] - outPubkey = outputRaw[2].split("SIG(")[1].replace(')','') - if re.search("Comment:", line): - commentRaw = line.split(': ', 1)[1] - - if issuerRaw != issuer or int(outAmount) != amount or outPubkey != recipient or commentRaw != comment: - sys.stderr.write(colored("Le document généré est corrompu !\nNe fait plus confiance au noeud " + node + "\n", 'red')) - sys.stderr.write(colored(issuerRaw + " envoi " + outAmount + " vers " + outPubkey + " with comment: " + commentRaw + "\n", "yellow")) - sys.exit(1) - else: - print("Le document généré est conforme.") - return True - - -def signDoc(txDoc): - # Sign TX document - signature = fmt["64"](sign(txDoc.encode(), get_privkey(dunikey, "pubsec"))[:-len(txDoc.encode())]) - signedDoc = txDoc + signature.decode() - - return signedDoc - - -def sendTXDoc(signedDoc): - # Build TX document - querySign = gql( - """ - mutation ($signedDoc: String!){ tx( - rawTx: $signedDoc - ) { - version - issuers - outputs - } - } - """ - ) - paramsSign = { - "signedDoc": signedDoc - } - - # Send TX Signed document - try: - client.execute(querySign, variable_values=paramsSign) - print(colored("Transaction effectué avec succès !", "green")) - except Exception as e: - message = ast.literal_eval(str(e))["message"] - sys.stderr.write("Echec de la transaction:\n" + message + "\n") - sys.exit(1) - +except Exception as e: + print(str(e)) + sys.exit(1) # Execute workflow -if not graphic: - returnGen = sendGenDoc(recipient, amount, comment) - docIsOK = checkTXDoc(returnGen, recipient, amount, comment) - if docIsOK: - returnSigned = signDoc(returnGen) - sendTXDoc(returnSigned) - -#print(sentTX) #For debug +## Generate TX document from server and check it +returnGen = sendGenDoc(recipient, amount, comment) +docIsOK = checkTXDoc(returnGen, recipient, amount, comment) +# Confirm TX document is ok, sign and send it +if docIsOK: + returnSigned = signDoc(returnGen) + sendTXDoc(returnSigned)