Skip to content
Snippets Groups Projects

#134: Add ability to pass a file containing the tx recipients and amounts

Merged #134: Add ability to pass a file containing the tx recipients and amounts
Merged Moul requested to merge 134_tx_file_parsing into dev
3 files
+ 164
22
Compare changes
  • Side-by-side
  • Inline
Files
3
+ 79
16
@@ -13,8 +13,12 @@
# You should have received a copy of the GNU Affero General Public License
# along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
import math
import shlex
import sys
from re import compile, search
from typing import List
import click
from duniterpy.api.bma.tx import process
@@ -60,7 +64,7 @@ NBR_ISSUERS = 1
type=click.FloatRange(MINIMAL_ABSOLUTE_TX_AMOUNT),
help=f"Quantitative amount(s):\n-a <amount>\nMinimum amount is {MINIMAL_ABSOLUTE_TX_AMOUNT}.",
cls=cli_tools.MutuallyExclusiveOption,
mutually_exclusive=["amountsud", "allsources"],
mutually_exclusive=["amountsud", "allsources", "file_path"],
)
@click.option(
"amountsud",
@@ -70,25 +74,34 @@ NBR_ISSUERS = 1
type=click.FloatRange(MINIMAL_RELATIVE_TX_AMOUNT),
help=f"Relative amount(s):\n-d <amount_UD>\nMinimum amount is {MINIMAL_RELATIVE_TX_AMOUNT}",
cls=cli_tools.MutuallyExclusiveOption,
mutually_exclusive=["amounts", "allsources"],
mutually_exclusive=["amounts", "allsources", "file_path"],
)
@click.option(
"--allSources",
is_flag=True,
help="Send all sources to one recipient",
cls=cli_tools.MutuallyExclusiveOption,
mutually_exclusive=["amounts", "amountsud"],
mutually_exclusive=["amounts", "amountsud", "file_path"],
)
@click.option(
"recipients",
"--recipient",
"-r",
multiple=True,
required=True,
help="Pubkey(s)’ recipients + optional checksum:\n-r <pubkey>[:checksum]\n\
Sending to many recipients is possible:\n\
* With one amount, all will receive the amount\n\
* With many amounts (one per recipient)",
cls=cli_tools.MutuallyExclusiveOption,
mutually_exclusive=["file_path"],
)
@click.option(
"file_path",
"--file",
"-f",
help="File’s path containing a list of amounts in absolute or relative reference and recipients’ pubkeys",
cls=cli_tools.MutuallyExclusiveOption,
mutually_exclusive=["recipients", "amounts", "amountsUD", "allsources"],
)
@click.option("--comment", "-c", default="", help="Comment")
@click.option(
@@ -103,22 +116,25 @@ def send_transaction(
amountsud,
allsources,
recipients,
file_path,
comment,
outputbackchange,
yes,
):
"""
Main function
"""
if not (amounts or amountsud or allsources):
tools.message_exit("Error: amount, amountUD or allSources is not set.")
if allsources and len(recipients) > 1:
tools.message_exit(
"Error: the --allSources option can only be used with one recipient."
)
# compute amounts and amountsud
if not allsources:
tx_amounts = transaction_amount(amounts, amountsud, recipients)
if file_path:
tx_amounts, recipients = parse_file_containing_amounts_recipients(file_path)
else:
if not (amounts or amountsud or allsources):
tools.message_exit("Error: amount, amountUD or allSources is not set.")
if not recipients:
tools.message_exit("Error: A recipient should be passed")
if allsources and len(recipients) > 1:
tools.message_exit(
"Error: the --allSources option can only be used with one recipient."
)
# compute amounts and amountsud
if not allsources:
tx_amounts = transaction_amount(amounts, amountsud, recipients)
key = auth.auth_method()
issuer_pubkey = key.pubkey
@@ -167,6 +183,53 @@ def send_transaction(
)
def parse_file_containing_amounts_recipients(file_path: str) -> List:
"""
Parse file in a specific format
Comments are ignored
Format should be:
```txt
[ABSOLUTE/RELATIVE]
# comment1
amount1 recipient1’s pubkey
# comment2
amount2 recipient2’s pubkey
```
"""
reference = ""
amounts, recipients = [], []
with open(file_path) as file:
for n, line in enumerate(file):
line = shlex.split(line, True)
if line:
if n == 0:
reference = line[0]
else:
try:
amounts.append(float(line[0]))
recipients.append(line[1])
except (ValueError, IndexError):
tools.message_exit(f"Syntax error at line {n + 1}")
if not reference or (reference != "ABSOLUTE" and reference != "RELATIVE"):
tools.message_exit(
f"{file_path} must contain at first line 'ABSOLUTE' or 'RELATIVE' header"
)
if not amounts or not recipients:
tools.message_exit("No amounts or recipients specified")
# Compute amount depending on the reference
if reference == "ABSOLUTE":
reference_mult = CENT_MULT_TO_UNIT
else:
reference_mult = money.UDValue().ud_value
tx_amounts = compute_amounts(amounts, reference_mult)
return tx_amounts, recipients
def transaction_amount(amounts, UDs_amounts, outputAddresses):
"""
Check that the number of passed amounts(UD) and recipients are the same
Loading