Commit e8daa47d authored by matograine's avatar matograine

* changes due to trials on the gui

* adds utils/constants and utils/utils
* checks the configuration
* manage a config file
parent f964633f
......@@ -15,18 +15,18 @@ import asyncio
import aiohttp
import async_timeout
if len(argv) > 1:
if argv[1] == "generate":
amount = float(argv[2])
pages = int(argv[3])
date = str(argv[4])
Creating (amount, date, pages).create()
if argv[1] == "generate":
amount = float(argv[2])
pages = int(argv[3])
date = str(argv[4])
Creating (amount, date, pages).create()
elif argv[1] == "retrieve":
file = argv[2]
elif argv[1] == "retrieve":
file = argv[2]
# pubkey = argv [3]
Retrieve().retrieve(file) #, pubkey)
Retrieve().retrieve(file) #, pubkey)
else :
print ("Use \"generate <amount> <pages number> <delay days>\" to generate G1pourboires.")
print ("Use \"retrieve <file> <your pubkey>\" to retrieve G1pourboires from a file")
print ("Use \"generate <amount> <pages number> <peremption_date_DD/MM/YYYY>\" to generate Ğ1Dons.")
print ("Use \"retrieve <file>\" to retrieve Ğ1Dons from a file")
from duniterpy.key import SigningKey, ascii_armor
import datetime
import re
import os
import json
from utils.generator import Generator
from utils.transfer import Transfer
from utils.constants import DEFAULT_FOLDER, WALLETS_FOLDER, BACKUP_FOLDER, CONF_FILE, MAX_PAGES
from utils.utils import CheckConfig, check_date
from utils.silkaj.tools import coroutine
from utils.silkaj.auth import auth_by_scrypt
from duniterpy.key import SigningKey, ascii_armor
import os
import json
MAX_PAGES_I_CAN_GENERATE = 10
def check_date(given_date):
infos_date = given_date.split("/")
if len(infos_date) != 3 or len(infos_date[2]) != 4:
print ("Erreur : le champs <date> doit être de forme JJ/MM/YYYY")
exit
return datetime.date(int(infos_date[2]), int(infos_date[1]), int(infos_date[0]))
# Generate and fill Tips
class Creating:
......@@ -26,37 +19,34 @@ class Creating:
def __init__(self, amount, given_date, pages=1): # Pour les tests, sur 15 min par defaut.
self.pages = pages
self.amount = amount
self.folder = os.path.expanduser("~/Documents/G1pourboire/")
self.wallets_folder = os.path.expanduser("~/Documents/G1pourboire/Recuperation_ne_pas_supprimer/")
self.backup_folder = os.path.expanduser("~/Documents/G1pourboire/.backup/")
conf = CheckConfig()
conf.check()
self.folder, self.wallets_folder, self.backup_folder = conf.folder, conf.wallets_folder, conf.backup_folder
self.output = datetime.datetime.now().strftime(
"G1pourboire_%Y-%m-%dT%Hh%M"
"Ğ1Don_%Y-%m-%dT%Hh%M"
)
self.key = auth_by_scrypt(None)
self.wallets = []
# Check date format
self.date = check_date(given_date)
# Create the folder
if not os.path.exists(self.folder):
os.makedirs(self.folder)
if not os.path.exists(self.wallets_folder):
os.makedirs(self.wallets_folder)
if not os.path.exists(self.backup_folder):
os.makedirs(self.backup_folder)
self.key = auth_by_scrypt(None)
def __call__(self):
return self
#@coroutine
def create(self):
""" Generating, filling wallets."""
if self.pages <= MAX_PAGES_I_CAN_GENERATE:
#self.transfer = False
if self.key and self.pages <= MAX_PAGES:
Generator(self.folder + self.output, self.wallets, self.amount, self.date, self.pages).generate()
transfer = Transfer(self.amount, self.pages, self.wallets, self.output, self.date)
self.save_json(self.key)
else:
print ("Sorry, Ğ1Pourboire can generate maximum 10 pages at once. For now !")
exit()
if self.amount > 0:
transfer.transfer(self.key)
transfer = Transfer(self.amount, self.pages, self.wallets, self.output, self.date)
self.save_json()
if self.amount > 0:
transfer.transfer(self.key)
def save_json(self, key):
def save_json(self): #, key):
"""
write wallets data in a json file.
"""
......@@ -70,17 +60,17 @@ class Creating:
for w in self.wallets
]
clear_json = json.dumps(wallet_data)
encrypted_wallets = ascii_armor.AsciiArmor.create(clear_json, key.pubkey)
encrypted_wallets = ascii_armor.AsciiArmor.create(clear_json, self.key.pubkey)
# add date and creator info
data = {
"creator_pubkey": key.pubkey,
"creator_pubkey": self.key.pubkey,
"peremption_date": self.date.isoformat(),
"wallets": encrypted_wallets,
}
data = json.dumps(data)
# sign the whole document
signed_data = ascii_armor.AsciiArmor.create(data, signing_keys=[key])
signed_data = ascii_armor.AsciiArmor.create(data, signing_keys=[self.key])
with open(
self.wallets_folder + self.output + ".json.signed", "a"
) as f:
......
SUGGESTED_AMOUNT = 10
MAX_AMOUNT = 1000000000
SUGGESTED_DEV_PERCENT = 5
DATE_FORMAT = "[0-9]{2}/[0-9]{2}/[0-9]{4}"
PUBKEY_FORMAT = "[1-9A-HJ-NP-Za-km-z]{43,44}"
DEFAULT_FOLDER = "~/Documents/G1pourboire/"
WALLETS_FOLDER = "Recuperation_ne_pas_supprimer/"
BACKUP_FOLDER = ".backup/"
CONF_FILE = ".config"
MAX_PAGES = 10
COMMENT = "G1Don"
......@@ -3,6 +3,7 @@ from reportlab.pdfgen import canvas
from reportlab.lib.units import cm
from duniterpy.key import SigningKey, ascii_armor
from utils.diceware import diceware
from utils.silkaj.constants import G1_SYMBOL
import os
import json
......@@ -43,16 +44,19 @@ class Generator:
self.make_pdf()
def new_wallet(self):
# Generating credetials
# Generating credentials
salt = diceware(3, separator="-", camelcase=False)
password = diceware(3, separator="-", camelcase=False)
# Generating public key from credentials
# Generating key from credentials
key = SigningKey.from_credentials(salt, password)
# Url to redirect to in the public QR code
account_url = "https://g1.duniter.fr/#/app/wot/tx/" + key.pubkey + "/"
# Generating wif data
key.save_wif_file("privatekey.wif")
wif_data = open("privatekey.wif").readlines()[-1].split(": ")[1]
#try add a \n after wif
wif_data.join(["\n"])
print (wif_data)
os.remove("privatekey.wif")
# Creating the QR codes
qr_pub = qrcode.make(account_url)
......@@ -68,7 +72,7 @@ class Generator:
# Writing amount
if self.amount > 0:
draw = ImageDraw.Draw(recto)
txt = "\n".join([str(self.amount) + " Ğ1"])
txt = "\n".join([str(self.amount) + G1_SYMBOL])
draw.text(
(1090, 150),
txt,
......@@ -135,19 +139,3 @@ class Generator:
for wallets in chunks(self.wallets, 6):
self.gen_page(wallets)
self.c.save()
"""
def encrypt_wallets(self, wallets, key):
data = [
{"pubkey": w["pubkey"], "salt": w["salt"], "password": w["password"]}
for w in self.wallets
]
clear_json = json.dumps(data)
encrypted_json = ascii_armor.AsciiArmor(clear_json, signing_keys=[key])
"""
def save_json(self): # Is this function still necessary ?
data = [
{"pubkey": w["pubkey"], "salt": w["salt"], "password": w["password"]}
for w in self.wallets
]
with open(self.output + ".json", "w") as f:
f.write(json.dumps(data, indent=4))
from duniterpy.key import SigningKey, ascii_armor
import os
import json
import re
from datetime import datetime
from time import sleep
from duniterpy.key import SigningKey, ascii_armor
from utils.constants import COMMENT
from utils.diceware import diceware
from utils.silkaj.money import get_amount_from_pubkey
from utils.silkaj.network_tools import ClientInstance
from utils.silkaj.tx_retrieve import handle_intermediaries_transactions, generate_and_send_transaction, get_list_input_for_transaction
from utils.silkaj.auth import auth_by_scrypt_with_IDs, auth_by_scrypt
from utils.silkaj.tools import coroutine
from utils.silkaj.constants import PUBKEY_PATTERN
import os
import json
import re
MAX_ISSUERS = 20
class Retrieve():
# def __init__(self):
# self.key = auth_by_scrypt(None)
def open_file(self, file):
with open(file) as wallets_json:
return json.load(wallets_json)
......@@ -51,10 +52,7 @@ class Retrieve():
signed_data = open(file, "r").read()
pubkey = re.search(re.compile(PUBKEY_PATTERN), signed_data).group()
key = self.get_pubkey(pubkey)
#print(signed_data)
data = ascii_armor.AsciiArmor.parse(signed_data, sender_pubkeys=[key.pubkey])
#print(data)
#print(data["message"]["content"])
content = json.loads(data["message"]["content"])
# check if date is passed
self.is_date_passed(content)
......@@ -92,7 +90,7 @@ class Retrieve():
amount,
total_listinput_and_amount,
[key.pubkey],
"G1Don",
COMMENT,
)
issuers, key_list, amount, listinput = list(), list(), 0, list()
# delete already used wallets
......
......@@ -135,22 +135,6 @@ def auth_by_scrypt(ctx):
message_exit(error)
def auth_by_scrypt_with_IDs(salt, password):
# salt = getpass("Please enter your Scrypt Salt (Secret identifier): ")
# password = getpass("Please enter your Scrypt password (masked): ")
# if ctx.obj["AUTH_SCRYPT_PARAMS"]:
# n, r, p = ctx.obj["AUTH_SCRYPT_PARAMS"].split(",")
# if n.isnumeric() and r.isnumeric() and p.isnumeric():
# n, r, p = int(n), int(r), int(p)
# if n <= 0 or n > 65536 or r <= 0 or r > 512 or p <= 0 or p > 32:
# message_exit("Error: the values of Scrypt parameters are not good")
# scrypt_params = ScryptParams(n, r, p)
# else:
# message_exit("one of n, r or p is not a number")
# else:
# scrypt_params = None
scrypt_params = None
try:
return SigningKey.from_credentials(salt, password, scrypt_params)
......
......@@ -19,7 +19,7 @@ SILKAJ_VERSION = "0.7.3"
G1_SYMBOL = "Ğ1"
GTEST_SYMBOL = "ĞTest"
#G1_DEFAULT_ENDPOINT = "duniter.moul.re", "443" #"g1.duniter.org", "443"
G1_DEFAULT_ENDPOINT = "g1-test.duniter.org", "443"
G1_DEFAULT_ENDPOINT = "g1-test.cgeek.fr", "443"
G1_TEST_DEFAULT_ENDPOINT = "ts.gt.librelois.fr", "443"
CONNECTION_TIMEOUT = 10
ASYNC_SLEEP = 0.1
......
......@@ -171,9 +171,8 @@ async def get_sources(pubkey):
for input in pending_sources:
if input in listinput:
listinput.remove(input)
return listinput, amount
class UDValue(object):
__instance = None
......
......@@ -32,6 +32,9 @@ from utils.silkaj.constants import (
ASYNC_SLEEP,
)
from utils.utils import CheckConfig
#from gui.parameters import ClientInstance
async def discover_peers(discover):
"""
......@@ -123,61 +126,22 @@ def singleton(class_):
return getinstance
##@singleton
class EndPoint(object):
# #@pass_context
@singleton
#class EndPoint(object):
class EndPoint():
# @pass_context
# def __init__(ctx, self):
def __init__(self):
ep = dict()
# peer = ctx.obj["PEER"]
# if peer:
# if ":" in peer:
# ep["domain"], ep["port"] = peer.rsplit(":", 1)
# else:
# ep["domain"], ep["port"] = peer, "443"
# else:
# ep["domain"], ep["port"] = (
# G1_TEST_DEFAULT_ENDPOINT if ctx.obj["GTEST"] else G1_DEFAULT_ENDPOINT
# )
ep["domain"], ep["port"] = (
G1_DEFAULT_ENDPOINT
)
# if ep["domain"].startswith("[") and ep["domain"].endswith("]"):
# ep["domain"] = ep["domain"][1:-1]
# self.ep = ep
ep = CheckConfig().get_conf()
api = "BMAS" if ep["port"] == "443" else "BASIC_MERKLED_API"
self.BMA_ENDPOINT = " ".join([api, ep["domain"], ep["port"]])
"""
class EndPoint(object):
#@pass_context
def __init__(ctx, self):
ep = dict()
peer = ctx.obj["PEER"]
if peer:
if ":" in peer:
ep["domain"], ep["port"] = peer.rsplit(":", 1)
else:
ep["domain"], ep["port"] = peer, "443"
else:
ep["domain"], ep["port"] = (
G1_TEST_DEFAULT_ENDPOINT if ctx.obj["GTEST"] else G1_DEFAULT_ENDPOINT
)
if ep["domain"].startswith("[") and ep["domain"].endswith("]"):
ep["domain"] = ep["domain"][1:-1]
self.ep = ep
api = "BMAS" if ep["port"] == "443" else "BASIC_MERKLED_API"
self.BMA_ENDPOINT = " ".join([api, ep["domain"], ep["port"]])
"""
@singleton
class ClientInstance(object):
def __init__(self):
# self.client = Client(EndPoint().BMA_ENDPOINT)
self.client = Client(EndPoint().BMA_ENDPOINT)
def parse_endpoint(rep):
"""
rep: raw endpoint, sep: split endpoint
......
......@@ -324,6 +324,7 @@ async def handle_intermediaries_transactions(
)
await client.close()
break
#return 0
async def handle_transactions_with_delay(
key,
......
import os
import json
import datetime
from duniterpy.key import SigningKey, ascii_armor
from time import sleep
from utils.diceware import diceware
from utils.silkaj.money import get_amount_from_pubkey
from utils.silkaj.network_tools import ClientInstance
from utils.silkaj.tx import handle_intermediaries_transactions, handle_transactions_with_delay
from utils.silkaj.auth import auth_by_scrypt
from utils.silkaj.tx import handle_intermediaries_transactions
from utils.silkaj.tools import coroutine
import os
import json
import datetime
from utils.constants import COMMENT
class Transfer:
"""Create a transfer wallet, send amount to tips"""
......@@ -19,81 +19,31 @@ class Transfer:
self.pages = pages
self.Tips_Amount = amount
self.date = peremption_date
# self.key = auth_by_scrypt(None)
@coroutine
async def transfer(self, key):
"""
Asks for authentification to send the tips.
sends tips.
"""
total_amount = int(100 * self.Tips_Amount * 6 * self.pages)
# key = auth_by_scrypt(None)
# create outputs list
outputAddresses = []
for w in self.wallets:
outputAddresses.append (w["pubkey"])
#print ("FALSE sending on key : ", w["pubkey"])
#delay = int(86400 * self.delay_days)
#print ("You will be able to recover the tips after ", self.delay_days, "days")
# send to tips
pubkey_amount = await get_amount_from_pubkey(key.pubkey)
if pubkey_amount[0] < total_amount:
print ("Not enough money on pubkey", key.pubkey)
else :
print ("Sending ", self.Tips_Amount, "on ", 6 * self.pages, "Tips, for a total of ", total_amount/100, "Ğ1.")
comment = "G1Pourboire"
outputbackchange = None
amount_tx = int (self.Tips_Amount * 100)
tx_amount = list()
tx_amount.append(amount_tx)
issuers = key.pubkey
# write the json before doing transactions
# self.save_json()
# Next few lines are commented, but are ready for when a client will implement CSV() unlock condition.
# await handle_transactions_with_delay(
await handle_intermediaries_transactions(
key,
issuers,
tx_amount,
total_amount,
outputAddresses,
# delay,
comment,
COMMENT,
outputbackchange,
)
def save_json(self, key):
"""
write wallets data in a json file.
"""
# create and encrypt wallet list
wallet_data = [
{
"pubkey": w["pubkey"],
"salt": w["salt"],
"password": w["password"],
}
for w in self.wallets
]
clear_json = json.dumps(wallet_data)
encrypted_wallets = ascii_armor.AsciiArmor.create(clear_json, key.pubkey)
# add date and creator info
data = {
"creator_pubkey": key.pubkey,
"peremption_date": self.date.isoformat(),
"wallets": encrypted_wallets,
}
data = json.dumps(data)
# sign the whole document
signed_data = ascii_armor.AsciiArmor.create(data, signing_keys=[key])
with open(
self.output + ".json.signed", "a"
) as f:
f.write(signed_data) #json.dumps(data, indent=4))
import datetime
import os
import json
from utils.constants import DEFAULT_FOLDER, WALLETS_FOLDER, BACKUP_FOLDER, CONF_FILE
def check_date(given_date):
infos_date = given_date.split("/")
if len(infos_date) != 3 or len(infos_date[2]) != 4 or len(infos_date[0]) != 2 or len(infos_date[1]) != 2:
print ("Erreur : le champs <date> doit être de forme JJ/MM/YYYY")
exit
return datetime.date(int(infos_date[2]), int(infos_date[1]), int(infos_date[0]))
class CheckConfig():
def __init__(self):
self.folder = os.path.expanduser(DEFAULT_FOLDER)
self.wallets_folder = os.path.expanduser(DEFAULT_FOLDER + WALLETS_FOLDER)
self.backup_folder = os.path.expanduser(DEFAULT_FOLDER + BACKUP_FOLDER)
self.config_file = os.path.expanduser(DEFAULT_FOLDER + CONF_FILE)
def __call__(self):
return self
def check(self):
if not os.path.exists(self.folder):
os.makedirs(self.folder)
if not os.path.exists(self.wallets_folder):
os.makedirs(self.wallets_folder)
if not os.path.exists(self.backup_folder):
os.makedirs(self.backup_folder)
if not os.path.exists(self.config_file):
node = dict()
node["domain"] = str(G1_DEFAULT_ENDPOINT[0])
node["port"] = int(G1_DEFAULT_ENDPOINT[1])
with open(self.config_file) as f:
f.write(json.dumps(node, 4))
def get_conf(self):
if not os.path.exists(self.config_file):
self.check()
with open(self.config_file, "r") as f:
return json.loads(f.read())
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment