From 1dd680e7ae7be6313266852bb7bf27570ebe3e12 Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 24 Nov 2020 07:26:02 +0100 Subject: [PATCH] Add complete history lib --- history.py | 29 ++++++++++++ libs/historylib.py | 108 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100755 history.py create mode 100644 libs/historylib.py diff --git a/history.py b/history.py new file mode 100755 index 0000000..4152d91 --- /dev/null +++ b/history.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +import sys, argparse, os +from os.path import join, dirname +from shutil import copyfile +from dotenv import load_dotenv +from libs.historylib import History + +# Get variables environment +if not os.path.isfile('.env'): + copyfile(".env.template", ".env") +dotenv_path = join(dirname(__file__), '.env') +load_dotenv(dotenv_path) + +dunikey = os.getenv('DUNIKEY') +node = os.getenv('NODE') +if not node: + sys.stderr.write("Please fill a Duniter node in .env file\n") + sys.exit(1) + +# Parse arguments +parser = argparse.ArgumentParser() +parser.add_argument('-p', '--pubkey', help="Clé publique du compte visé") +parser.add_argument('--mempool', action='store_true', help="Utilise les sources en Mempool") +args = parser.parse_args() + +# Create transaction and send it +hist = History(dunikey, node, args.pubkey, args.mempool) +result = hist.history() diff --git a/libs/historylib.py b/libs/historylib.py new file mode 100644 index 0000000..7270837 --- /dev/null +++ b/libs/historylib.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 + +import sys, re, os.path, json, ast +from datetime import datetime +from termcolor import colored +from natools import fmt, sign, get_privkey +from gql import gql, Client +from gql.transport.aiohttp import AIOHTTPTransport + +PUBKEY_REGEX = "(?![OIl])[1-9A-Za-z]{42,45}" + +class History: + + def __init__(self, dunikey, node, pubkey, useMempool=False): + self.dunikey = dunikey + self.pubkey = pubkey if pubkey else get_privkey(dunikey, "pubsec").pubkey + self.useMempool = useMempool + if not re.match(PUBKEY_REGEX, self.pubkey) or len(self.pubkey) > 45: + sys.stderr.write("La clé publique n'est pas au bon format.\n") + sys.exit(1) + + # Define Duniter GVA node + transport = AIOHTTPTransport(url=node) + self.client = Client(transport=transport, fetch_schema_from_transport=True) + + def sendDoc(self): + # Build TX generation document + queryBuild = gql( + """ + query ($pubkey: String!){ + transactionsHistory(pubkey: $pubkey) { + received { + writtenTime + issuers + outputs + comment + } + sent { + writtenTime + issuers + outputs + comment + } + } + } + """ + ) + paramsBuild = { + "pubkey": self.pubkey + } + + # Send TX document + try: + self.historyDoc = self.client.execute(queryBuild, variable_values=paramsBuild) + except Exception as e: + message = ast.literal_eval(str(e))["message"] + sys.stderr.write("Echec de récupération de l'historique:\n" + message + "\n") + sys.exit(1) + + + def parseHistory(self): + + res = self.historyDoc['transactionsHistory']['received'] + transIn=[[0 for x in range(0)] for y in range(len(res))] + for i, bloc in enumerate(res): + for output in bloc['outputs']: + if re.search(self.pubkey, output): + transIn[i].append("IN") + transIn[i].append(bloc['writtenTime']) + transIn[i].append(bloc['issuers'][0]) + transIn[i].append(int(output.split(':')[0])/100) + transIn[i].append(bloc['comment']) + + + res = self.historyDoc['transactionsHistory']['sent'] + transOut=[[0 for x in range(0)] for y in range(len(res))] + i = 0 + for bloc in res: + for output in bloc['outputs']: + if not re.search(self.pubkey, output): + transOut[i].append("OUT") + transOut[i].append(bloc['writtenTime']) + transOut[i].append(output.split("SIG(")[1].replace(')','')) + transOut[i].append(int(output.split(':')[0])/100) + transOut[i].append(bloc['comment']) + i += 1 + + trans = transIn + transOut + trans = list(filter(None, trans)) + trans.sort(key=lambda x: x[1]) + + # Get terminal size + rows = int(os.popen('stty size', 'r').read().split()[1]) + + print('-'.center(rows, '-')) + print("{: <20} | {: <45} | {: <7} | {: <30}".format(" Date"," De la part de (clé publique)","Montant","Commentaire")) + for i in trans: + color = "green" if i[0] == "IN" else "blue" + date = datetime.fromtimestamp(i[1]).strftime("%d/%m/%Y à %H:%M") + print('-'.center(rows, '-')) + print(colored("{: <20} | {: <45} | {: <7} | {: <30}".format(date, *i[2:]), color)) + # print(*i) + + + def history(self): + self.sendDoc() + self.parseHistory() +