commit e3badb6790fe44c9ed978a71e6417f95e6ed9c1a
parent b92ff308c387aa91f6ff404de97122b3fd552855
Author: lash <dev@holbrook.no>
Date: Tue, 31 Mar 2026 15:55:00 -0600
Consolidate arg parsing and context handling in cli
Diffstat:
11 files changed, 488 insertions(+), 439 deletions(-)
diff --git a/dummy/setup.cfg b/dummy/setup.cfg
@@ -38,4 +38,11 @@ packages =
[options.entry_points]
console_scripts =
usawad = usawa.runnable.server:main
- usawa = usawa.runnable.gui:main
+ usawa-gui = usawa.runnable.gui:main
+ usawa-create = usawa.runnable.create:main
+ usawa-add = usawa.runnable.add:main
+ usawa-entry = usawa.runnable.entry:main
+ usawa-wallet = usawa.runnable.wallet:main
+ usawa-view = usawa.runnable.view:main
+ usawa-import = usawa.runnable.import:main
+ usawa-export = usawa.runnable.export:main
diff --git a/dummy/usawa/gui/__init__.py b/dummy/usawa/gui/__init__.py
@@ -2,7 +2,7 @@ import logging
import signal
import gi
-from usawa.runnable.setup_wallet import setup_wallet
+from usawa.runnable.wallet import setup_wallet
gi.require_version("Gtk", "4.0")
gi.require_version("Adw", "1")
diff --git a/dummy/usawa/runnable/add.py b/dummy/usawa/runnable/add.py
@@ -120,46 +120,6 @@ def input_or_default(prompt, default=None, postfix=': ', validate_fn=None):
return v
-argp = argparse.ArgumentParser()
-argp.add_argument('-i', action='store_true', help='interactive edit')
-argp.add_argument('-r', type=str, help='external reference')
-argp.add_argument('-s', type=str, dest='src_account', default='general', help='source account')
-argp.add_argument('-t', type=str, dest='dst_account', default='general', help='destination account')
-argp.add_argument('-a', type=str, dest='amount', help='source and destination amount')
-argp.add_argument('-x', type=str, dest='attachment', default=[], action='append', help='add file attachment')
-argp.add_argument('-o', type=str, dest='output', help='output file for updated XML document')
-argp.add_argument('--src-type', dest='src_type', type=str, choices=CATEGORIES, default='expense', help='source type')
-argp.add_argument('--dst-type', dest='dst_type', type=str, choices=CATEGORIES, default='asset', help='dest type')
-argp.add_argument('-d', '--description', dest='description', type=str, help='interactive edit')
-# TODO: read default from xml if not defined
-argp.add_argument('-u', '--unit', type=str, default=UnitIndex.default_unit, help='Unit to use for transaction')
-argp.add_argument('-c', type=str, help='override config dir')
-argp.add_argument('--unit-precision', dest='unit_precision', type=int, default=UnitIndex.default_precision, help='Unit precision')
-argp.add_argument('--unit-rate', dest='unit_precision', type=float, default=1.0, help='Unit exchange rate')
-argp.add_argument('--valkey-host', dest='valkey_host', type=str, default='localhost', help='Valkey host')
-argp.add_argument('--valkey-port', dest='valkey_port', type=int, default=6379, help='Valkey port')
-
-argp.add_argument('ledger_xml_file', type=str, help='load ledger metadata from XML file')
-arg = argp.parse_args()
-ctx = Context.from_args(arg)
-
-ledger = None
-logg.warning('hardcoding unit index default sym, need unitindex xml parser')
-logg.warning('using default sym for all entries for now')
-ledger_tree = load(arg.ledger_xml_file)
-uidx = UnitIndex.from_tree(ledger_tree)
-ledger = Ledger.from_tree(ledger_tree)
-
-cfg = usawa.config.load_config(config_dir=arg.c)
-db = ValkeyStore('', host=ctx.valkey_host, port=ctx.valkey_port)
-store = LedgerStore(db, ledger)
-#pk = store.get_key()
-#wallet = DemoWallet(privatekey=pk)
-wallet = store.get_key(DemoWallet, passphrase=cfg.get('WALLET_KEY_PASSPHRASE'))
-ledger.set_wallet(wallet)
-dt = datetime.datetime.now()
-
-
def do_interactive(ctx):
v = input_or_default('Entry description', ctx.description)
ctx.description = v
@@ -186,24 +146,71 @@ def do_interactive(ctx):
output = input_or_default('Output file', ctx.output)
logg.debug('output {}'.format(output))
return ctx.open(output)
-
-
-if arg.i:
- ctx = do_interactive(ctx)
-
-ctx.validate()
-entry = Entry(ledger.next_serial(), dt, parent=ledger.current(), description=ctx.description, ref=ctx.ref, unitindex=ctx.uidx)
-entry.add_part(ctx.part[0], debit=True)
-entry.add_part(ctx.part[1])
-for o in ctx.attach:
- entry.attach(o)
- try:
- store.add_asset(o)
- except FileExistsError:
- logg.info('asset already in store: {}'.format(o))
-entry.sign(wallet)
-store.add_entry(entry, update_ledger=True)
-ledger.truncate()
-ledger.sign()
-ctx.f.write(ledger.to_string())
-ctx.close()
+
+
+def main():
+ argp = argparse.ArgumentParser()
+ argp.add_argument('-i', action='store_true', help='interactive edit')
+ argp.add_argument('-r', type=str, help='external reference')
+ argp.add_argument('-s', type=str, dest='src_account', default='general', help='source account')
+ argp.add_argument('-t', type=str, dest='dst_account', default='general', help='destination account')
+ argp.add_argument('-a', type=str, dest='amount', help='source and destination amount')
+ argp.add_argument('-x', type=str, dest='attachment', default=[], action='append', help='add file attachment')
+ argp.add_argument('-o', type=str, dest='output', help='output file for updated XML document')
+ argp.add_argument('--src-type', dest='src_type', type=str, choices=CATEGORIES, default='expense', help='source type')
+ argp.add_argument('--dst-type', dest='dst_type', type=str, choices=CATEGORIES, default='asset', help='dest type')
+ argp.add_argument('-d', '--description', dest='description', type=str, help='interactive edit')
+ # TODO: read default from xml if not defined
+ argp.add_argument('-u', '--unit', type=str, default=UnitIndex.default_unit, help='Unit to use for transaction')
+ argp.add_argument('-c', type=str, help='override config dir')
+ argp.add_argument('--unit-precision', dest='unit_precision', type=int, default=UnitIndex.default_precision, help='Unit precision')
+ argp.add_argument('--unit-rate', dest='unit_precision', type=float, default=1.0, help='Unit exchange rate')
+ argp.add_argument('--valkey-host', dest='valkey_host', type=str, default='localhost', help='Valkey host')
+ argp.add_argument('--valkey-port', dest='valkey_port', type=int, default=6379, help='Valkey port')
+
+ argp.add_argument('ledger_xml_file', type=str, help='load ledger metadata from XML file')
+ arg = argp.parse_args()
+ ctx = Context.from_args(arg)
+
+ ledger = None
+ logg.warning('hardcoding unit index default sym, need unitindex xml parser')
+ logg.warning('using default sym for all entries for now')
+ ledger_tree = load(arg.ledger_xml_file)
+ uidx = UnitIndex.from_tree(ledger_tree)
+ ledger = Ledger.from_tree(ledger_tree)
+
+ cfg = usawa.config.load_config(config_dir=arg.c)
+ db = ValkeyStore('', host=ctx.valkey_host, port=ctx.valkey_port)
+ store = LedgerStore(db, ledger)
+ #pk = store.get_key()
+ #wallet = DemoWallet(privatekey=pk)
+ wallet = store.get_key(DemoWallet, passphrase=cfg.get('WALLET_KEY_PASSPHRASE'))
+ ledger.set_wallet(wallet)
+ dt = datetime.datetime.now()
+
+
+
+
+ if arg.i:
+ ctx = do_interactive(ctx)
+
+ ctx.validate()
+ entry = Entry(ledger.next_serial(), dt, parent=ledger.current(), description=ctx.description, ref=ctx.ref, unitindex=ctx.uidx)
+ entry.add_part(ctx.part[0], debit=True)
+ entry.add_part(ctx.part[1])
+ for o in ctx.attach:
+ entry.attach(o)
+ try:
+ store.add_asset(o)
+ except FileExistsError:
+ logg.info('asset already in store: {}'.format(o))
+ entry.sign(wallet)
+ store.add_entry(entry, update_ledger=True)
+ ledger.truncate()
+ ledger.sign()
+ ctx.f.write(ledger.to_string())
+ ctx.close()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/dummy/usawa/runnable/create.py b/dummy/usawa/runnable/create.py
@@ -133,83 +133,88 @@ def input_or_default(prompt, default=None, postfix=': ', validate_fn=None):
return v
-argp = argparse.ArgumentParser()
-argp.add_argument('-i', action='store_true', help='interactive edit')
-argp.add_argument('-t', dest='topic', type=str, help='ledger topic')
-argp.add_argument('-v', type=str, choices=['info','debug','warning','error'], help='be verbose')
-argp.add_argument('-u', '--unit', type=str, action='append', default=[], help='Units to use for transaction')
-argp.add_argument('-p', action='store_true', help='Use passphrase to open wallet')
-argp.add_argument('-o', type=str, dest='output', help='output file for updated XML document')
-argp.add_argument('-l', type=str, dest='src_uri', help='URI for data source')
-argp.add_argument('-c', type=str, help='override config dir')
-arg = argp.parse_args()
-
-if arg.v:
- logg.setLevel(getattr(logging, arg.v.upper()))
-
-ctx = Context.from_args(arg)
-cfg = usawa.config.load_config(config_dir=arg.c)
-
-
-def do_interactive(ctx):
- logg.debug("Creating new ledger")
- v = input_or_default("Topic", ctx.topic)
-
- ctx.unit = input_or_default("Default unit", ctx.unit)
- ctx.unit_precision = input_or_default("Unit decimals", ctx.unit_precision)
- ctx.uri = input_or_default("Source URI", ctx.uri)
-
- input_or_default("XML output filename", ctx.output)
- return ctx
-
-
-if arg.i:
- ctx = do_interactive(ctx)
-ctx = ctx.open(ctx.output)
-ctx.validate()
-
-ledger = Ledger(ctx.uidx, topic=ctx.topic, src=ctx.uri)
-store_type = cfg.get('STORE_TYPE')
-db = None
-if store_type == 'valkey':
- db = ValkeyStore(
- "",
- host=cfg.get("VALKEY_HOST"),
- port=cfg.get("VALKEY_PORT"),
- )
-elif store_type == 'fs':
- db = FsStore(
- base=cfg.get('FSSTORE_BASE', xdg_data_home()),
- dbname='usawa',
- )
-else:
- raise ValueError('invalid store type: ' + store_type)
-store = LedgerStore(db, ledger)
-pk = None
-wallet = None
-dt = datetime.datetime.now()
-
-cfg = usawa.config.load_config(config_dir=arg.c)
-
-ops = int(cfg.get('WALLET_OPSLIMIT', 0))
-mem = int(cfg.get('WALLET_MEMLIMIT', 0))
-pw = cfg.get('WALLET_KEY_PASSPHRASE')
-if arg.p and pw == None:
- pw = getpass.getpass("passphrase: ")
-logg.debug('ops {}'.format(ops))
-try:
- wallet = store.get_key(DemoWallet, passphrase=pw, opslimit=ops, memlimit=mem)
-except FileNotFoundError:
- logg.info('no default key found')
- wallet = DemoWallet()
- store.add_key(wallet, passphrase=pw, opslimit=ops, memlimit=mem)
-if wallet == None:
- wallet = DemoWallet(privatekey=pk)
- logg.info('loaded existing key. {}'.format(wallet.pubkey().hex()))
-
-acl = ACL.from_wallet(wallet)
-#ledger.reset(topic=ctx.topic, src=ctx.uri, acl=acl, wallet=wallet)
-ledger = Ledger(ctx.uidx, topic=ctx.topic, src=ctx.uri, acl=acl, wallet=wallet)
-ledger.sign()
-ctx.f.write(ledger.to_string())
-ctx.close()
+def main():
+ argp = argparse.ArgumentParser()
+ argp.add_argument('-i', action='store_true', help='interactive edit')
+ argp.add_argument('-t', dest='topic', type=str, help='ledger topic')
+ argp.add_argument('-v', type=str, choices=['info','debug','warning','error'], help='be verbose')
+ argp.add_argument('-u', '--unit', type=str, action='append', default=[], help='Units to use for transaction')
+ argp.add_argument('-p', action='store_true', help='Use passphrase to open wallet')
+ argp.add_argument('-o', type=str, dest='output', help='output file for updated XML document')
+ argp.add_argument('-l', type=str, dest='src_uri', help='URI for data source')
+ argp.add_argument('-c', type=str, help='override config dir')
+ arg = argp.parse_args()
+
+ if arg.v:
+ logg.setLevel(getattr(logging, arg.v.upper()))
+
+ ctx = Context.from_args(arg)
+ cfg = usawa.config.load_config(config_dir=arg.c)
+
+
+ def do_interactive(ctx):
+ logg.debug("Creating new ledger")
+ v = input_or_default("Topic", ctx.topic)
+
+ ctx.unit = input_or_default("Default unit", ctx.unit)
+ ctx.unit_precision = input_or_default("Unit decimals", ctx.unit_precision)
+ ctx.uri = input_or_default("Source URI", ctx.uri)
+
+ input_or_default("XML output filename", ctx.output)
+ return ctx
+
+
+ if arg.i:
+ ctx = do_interactive(ctx)
+ ctx = ctx.open(ctx.output)
+ ctx.validate()
+
+ ledger = Ledger(ctx.uidx, topic=ctx.topic, src=ctx.uri)
+ store_type = cfg.get('STORE_TYPE')
+ db = None
+ if store_type == 'valkey':
+ db = ValkeyStore(
+ "",
+ host=cfg.get("VALKEY_HOST"),
+ port=cfg.get("VALKEY_PORT"),
+ )
+ elif store_type == 'fs':
+ db = FsStore(
+ base=cfg.get('FSSTORE_BASE', xdg_data_home()),
+ dbname='usawa',
+ )
+ else:
+ raise ValueError('invalid store type: ' + store_type)
+ store = LedgerStore(db, ledger)
+ pk = None
+ wallet = None
+ dt = datetime.datetime.now()
+
+ cfg = usawa.config.load_config(config_dir=arg.c)
+
+ ops = int(cfg.get('WALLET_OPSLIMIT', 0))
+ mem = int(cfg.get('WALLET_MEMLIMIT', 0))
+ pw = cfg.get('WALLET_KEY_PASSPHRASE')
+ if arg.p and pw == None:
+ pw = getpass.getpass("passphrase: ")
+ logg.debug('ops {}'.format(ops))
+ try:
+ wallet = store.get_key(DemoWallet, passphrase=pw, opslimit=ops, memlimit=mem)
+ except FileNotFoundError:
+ logg.info('no default key found')
+ wallet = DemoWallet()
+ store.add_key(wallet, passphrase=pw, opslimit=ops, memlimit=mem)
+ if wallet == None:
+ wallet = DemoWallet(privatekey=pk)
+ logg.info('loaded existing key. {}'.format(wallet.pubkey().hex()))
+
+ acl = ACL.from_wallet(wallet)
+ #ledger.reset(topic=ctx.topic, src=ctx.uri, acl=acl, wallet=wallet)
+ ledger = Ledger(ctx.uidx, topic=ctx.topic, src=ctx.uri, acl=acl, wallet=wallet)
+ ledger.sign()
+ ctx.f.write(ledger.to_string())
+ ctx.close()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/dummy/usawa/runnable/entry.py b/dummy/usawa/runnable/entry.py
@@ -5,6 +5,7 @@ import datetime
import signal
import sys
import shutil
+import getpass
from whee.valkey import ValkeyStore
from whee.fs import FsStore
@@ -19,6 +20,7 @@ logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger()
+
class Context:
def __init__(self, args):
@@ -79,7 +81,10 @@ class Context:
self.store = LedgerStore(self.db, self.ledger)
ops = int(self.cfg.get('WALLET_OPSLIMIT', 0))
mem = int(self.cfg.get('WALLET_MEMLIMIT', 0))
- self.wallet = self.store.get_key(DemoWallet, passphrase=self.cfg.get('WALLET_KEY_PASSPHRASE'), opslimit=ops, memlimit=mem)
+ pw = self.cfg.get('WALLET_KEY_PASSPHRASE')
+ if args.p and pw == None:
+ pw = getpass.getpass("passphrase: ")
+ self.wallet = self.store.get_key(DemoWallet, passphrase=pw, opslimit=ops, memlimit=mem)
self.ledger.set_wallet(self.wallet)
if args.e:
self.entry = self.store.get_draft(self.entry)
@@ -151,29 +156,6 @@ class Context:
return datetime.date.fromisoformat(v)
-argp = argparse.ArgumentParser()
-argp.add_argument('-e', type=str, help='unique reference of entry')
-argp.add_argument('-x', type=str, action='append', default=[], help='unique reference of attachment')
-argp.add_argument('-z', type=str, action='append', default=[], help='sum of attachment')
-argp.add_argument('-v', type=str, choices=['info','debug','warning','error'], help='be verbose')
-argp.add_argument('-c', type=str, help='override config dir')
-argp.add_argument('-d', type=str, help='transaction date or datetime')
-argp.add_argument('-o', type=str, help='output ledger state')
-argp.add_argument('--commit', action='store_true', dest='commit', help='commit to ledger')
-argp.add_argument('ledger_file', type=str, help='ledger file')
-args = argp.parse_args()
-
-if args.v:
- logg.setLevel(getattr(logging, args.v.upper()))
-
-ctx = Context(args)
-
-def croak(*args, **kwargs):
- sys.exit(1)
-
-signal.signal(signal.SIGINT, croak)
-signal.signal(signal.SIGTERM, croak)
-
def input_or_default(prompt, default=None, postfix=': ', validate_fn=None):
if default != None:
postfix = ' [{}]'.format(default) + postfix
@@ -243,49 +225,78 @@ def enter_part(ctx, entry):
return True
-entry = None
-if ctx.state == 0:
- do_interactive_one(ctx)
- entry = Entry.empty(ref=ctx.ref, unitindex=ctx.uidx, tx_date=ctx.txdate)
- entry = ctx.store.get_draft(entry)
- entry.description = ctx.description
- entry.dt = ctx.txdate
- do_interactive_two(ctx, entry)
-else:
- entry = ctx.entry
-
-
-for v in args.x:
- k = uuid.UUID(v)
- asset = Asset(ref=str(k))
- asset = ctx.store.get_asset_indexed(asset)
- entry.attach(asset)
-for v in args.z:
- k = bytes.fromhex(v)
- asset = Asset(digest=k)
- asset = ctx.store.get_asset(asset)
- entry.attach(asset)
-
-if ctx.commit:
- if entry.serial != -1:
- raise AttributeError('entry draft already marked as committed')
- entry.serial = ctx.ledger.next_serial()
-
-
-v = input_or_default('Commit? (type YES, any other input is no)', '')
-if v == 'YES':
- entry.parent = ctx.ledger.cur
- entry.sign(ctx.wallet)
- entry.serial = ctx.ledger.next_serial()
- ctx.store.add_entry(entry, update_ledger=True)
- ctx.ledger.truncate()
- ctx.ledger.sign()
- if ctx.fp_bak != None:
- shutil.copy(ctx.fp, ctx.fp_bak)
- f = open(ctx.fp, 'w')
- f.write(ctx.ledger.to_string())
- f.close()
-else:
- ctx.store.put_draft(entry)
-
-print(entry)
+def main():
+ def croak(*args, **kwargs):
+ sys.exit(1)
+
+ signal.signal(signal.SIGINT, croak)
+ signal.signal(signal.SIGTERM, croak)
+
+ argp = argparse.ArgumentParser()
+ argp.add_argument('-e', type=str, help='unique reference of entry')
+ argp.add_argument('-x', type=str, action='append', default=[], help='unique reference of attachment')
+ argp.add_argument('-z', type=str, action='append', default=[], help='sum of attachment')
+ argp.add_argument('-v', type=str, choices=['info','debug','warning','error'], help='be verbose')
+ argp.add_argument('-c', type=str, help='override config dir')
+ argp.add_argument('-d', type=str, help='transaction date or datetime')
+ argp.add_argument('-o', type=str, help='output ledger state')
+ argp.add_argument('-p', action='store_true', help='unlock wallet with password')
+ argp.add_argument('--commit', action='store_true', dest='commit', help='commit to ledger')
+ argp.add_argument('ledger_file', type=str, help='ledger file')
+ args = argp.parse_args()
+
+ if args.v:
+ logg.setLevel(getattr(logging, args.v.upper()))
+
+ ctx = Context(args)
+
+ entry = None
+ if ctx.state == 0:
+ do_interactive_one(ctx)
+ entry = Entry.empty(ref=ctx.ref, unitindex=ctx.uidx, tx_date=ctx.txdate)
+ entry = ctx.store.get_draft(entry)
+ entry.description = ctx.description
+ entry.dt = ctx.txdate
+ do_interactive_two(ctx, entry)
+ else:
+ entry = ctx.entry
+
+
+ for v in args.x:
+ k = uuid.UUID(v)
+ asset = Asset(ref=str(k))
+ asset = ctx.store.get_asset_indexed(asset)
+ entry.attach(asset)
+ for v in args.z:
+ k = bytes.fromhex(v)
+ asset = Asset(digest=k)
+ asset = ctx.store.get_asset(asset)
+ entry.attach(asset)
+
+ if ctx.commit:
+ if entry.serial != -1:
+ raise AttributeError('entry draft already marked as committed')
+ entry.serial = ctx.ledger.next_serial()
+
+
+ v = input_or_default('Commit? (type YES, any other input is no)', '')
+ if v == 'YES':
+ entry.parent = ctx.ledger.cur
+ entry.sign(ctx.wallet)
+ entry.serial = ctx.ledger.next_serial()
+ ctx.store.add_entry(entry, update_ledger=True)
+ ctx.ledger.truncate()
+ ctx.ledger.sign()
+ if ctx.fp_bak != None:
+ shutil.copy(ctx.fp, ctx.fp_bak)
+ f = open(ctx.fp, 'w')
+ f.write(ctx.ledger.to_string())
+ f.close()
+ else:
+ ctx.store.put_draft(entry)
+
+ print(entry)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/dummy/usawa/runnable/export.py b/dummy/usawa/runnable/export.py
@@ -57,47 +57,52 @@ class Context:
return ctx
-argp = argparse.ArgumentParser()
-argp.add_argument('-o', type=str, dest='output', help='output dir for resulting XML entry documents')
-argp.add_argument('-c', type=str, help='override config dir')
-argp.add_argument('--valkey-host', dest='valkey_host', type=str, default='localhost', help='Valkey host')
-argp.add_argument('--valkey-port', dest='valkey_port', type=int, default=6379, help='Valkey port')
-argp.add_argument('ledger_xml_file', type=str, help='load ledger metadata from XML file')
-arg = argp.parse_args()
-ctx = Context.from_args(arg)
-
-#ledger = None
-#ledger_tree = load(arg.ledger_xml_file)
-#uidx = UnitIndex.from_tree(ledger_tree)
-#ledger = Ledger.from_tree(ledger_tree)
-ledger = Ledger.from_file(arg.ledger_xml_file)
-
-cfg = usawa.config.load_config(config_dir=arg.c)
-store_type = cfg.get('STORE_TYPE')
-db = None
-if store_type == 'valkey':
- db = ValkeyStore(
- "",
- host=cfg.get("VALKEY_HOST"),
- port=cfg.get("VALKEY_PORT"),
- )
-elif store_type == 'fs':
- db = FsStore(
- base=cfg.get('FSSTORE_BASE', xdg_data_home()),
- dbname='usawa',
- )
-else:
- raise ValueError('invalid store type: ' + store_type)
-store = LedgerStore(db, ledger)
-#storedb = ValkeyStore('', host=ctx.valkey_host, port=ctx.valkey_port)
-#store = LedgerStore(storedb, ledger)
-#pk = store.get_key()
-#wallet = DemoWallet(privatekey=pk)
-#wallet = store.get_key(DemoWallet, passphrase=cfg.get('WALLET_KEY_PASSPHRASE'))
-wallet = store.get_default_key(DemoWallet)
-acl = ACL.from_wallet(wallet)
-store.load(acl=acl)
-resolve = FSResolver(ctx.output)
-
-for k in ledger.entries:
- r = resolve.put_entry(ledger.entries[k], lookup='sha512')
+def main():
+ argp = argparse.ArgumentParser()
+ argp.add_argument('-o', type=str, dest='output', help='output dir for resulting XML entry documents')
+ argp.add_argument('-c', type=str, help='override config dir')
+ argp.add_argument('--valkey-host', dest='valkey_host', type=str, default='localhost', help='Valkey host')
+ argp.add_argument('--valkey-port', dest='valkey_port', type=int, default=6379, help='Valkey port')
+ argp.add_argument('ledger_xml_file', type=str, help='load ledger metadata from XML file')
+ arg = argp.parse_args()
+ ctx = Context.from_args(arg)
+
+ #ledger = None
+ #ledger_tree = load(arg.ledger_xml_file)
+ #uidx = UnitIndex.from_tree(ledger_tree)
+ #ledger = Ledger.from_tree(ledger_tree)
+ ledger = Ledger.from_file(arg.ledger_xml_file)
+
+ cfg = usawa.config.load_config(config_dir=arg.c)
+ store_type = cfg.get('STORE_TYPE')
+ db = None
+ if store_type == 'valkey':
+ db = ValkeyStore(
+ "",
+ host=cfg.get("VALKEY_HOST"),
+ port=cfg.get("VALKEY_PORT"),
+ )
+ elif store_type == 'fs':
+ db = FsStore(
+ base=cfg.get('FSSTORE_BASE', xdg_data_home()),
+ dbname='usawa',
+ )
+ else:
+ raise ValueError('invalid store type: ' + store_type)
+ store = LedgerStore(db, ledger)
+ #storedb = ValkeyStore('', host=ctx.valkey_host, port=ctx.valkey_port)
+ #store = LedgerStore(storedb, ledger)
+ #pk = store.get_key()
+ #wallet = DemoWallet(privatekey=pk)
+ #wallet = store.get_key(DemoWallet, passphrase=cfg.get('WALLET_KEY_PASSPHRASE'))
+ wallet = store.get_default_key(DemoWallet)
+ acl = ACL.from_wallet(wallet)
+ store.load(acl=acl)
+ resolve = FSResolver(ctx.output)
+
+ for k in ledger.entries:
+ r = resolve.put_entry(ledger.entries[k], lookup='sha512')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/dummy/usawa/runnable/import.py b/dummy/usawa/runnable/import.py
@@ -54,22 +54,27 @@ class Context:
return ctx
-argp = argparse.ArgumentParser()
-argp.add_argument('-o', type=str, dest='output', help='output file for resulting XML document')
-argp.add_argument('--valkey-host', dest='valkey_host', type=str, default='localhost', help='Valkey host')
-argp.add_argument('--valkey-port', dest='valkey_port', type=int, default=6379, help='Valkey port')
-argp.add_argument('ledger_xml_file', type=str, help='load ledger metadata from XML file')
-arg = argp.parse_args()
-ctx = Context.from_args(arg)
-
-ledger = Ledger.from_file(arg.ledger_xml_file)
-
-cfg = usawa.config.load()
-storedb = ValkeyStore('', host=ctx.valkey_host, port=ctx.valkey_port)
-store = LedgerStore(storedb, ledger)
-#pk = store.get_key()
-#wallet = DemoWallet(privatekey=pk)
-#acl = ACL.from_wallet(wallet)
-#store.load(acl=acl)
-store.put_all(store_assets=True)
-sys.stdout.write(ledger.to_string())
+def main():
+ argp = argparse.ArgumentParser()
+ argp.add_argument('-o', type=str, dest='output', help='output file for resulting XML document')
+ argp.add_argument('--valkey-host', dest='valkey_host', type=str, default='localhost', help='Valkey host')
+ argp.add_argument('--valkey-port', dest='valkey_port', type=int, default=6379, help='Valkey port')
+ argp.add_argument('ledger_xml_file', type=str, help='load ledger metadata from XML file')
+ arg = argp.parse_args()
+ ctx = Context.from_args(arg)
+
+ ledger = Ledger.from_file(arg.ledger_xml_file)
+
+ cfg = usawa.config.load()
+ storedb = ValkeyStore('', host=ctx.valkey_host, port=ctx.valkey_port)
+ store = LedgerStore(storedb, ledger)
+ #pk = store.get_key()
+ #wallet = DemoWallet(privatekey=pk)
+ #acl = ACL.from_wallet(wallet)
+ #store.load(acl=acl)
+ store.put_all(store_assets=True)
+ sys.stdout.write(ledger.to_string())
+
+
+if __name__ == '__main__':
+ main()
diff --git a/dummy/usawa/runnable/server.py b/dummy/usawa/runnable/server.py
@@ -5,7 +5,7 @@ import signal
import usawa.config
from usawa import Ledger, Entry, EntryPart, DemoWallet, ACL, UnitIndex, load
-from usawa.context import Context
+from usawa.context import UsawaContext
from usawa.service import Handler, UnixServer
from whee.valkey import ValkeyStore
diff --git a/dummy/usawa/runnable/setup_wallet.py b/dummy/usawa/runnable/setup_wallet.py
@@ -1,111 +0,0 @@
-import argparse
-import getpass
-import logging
-import os
-from pathlib import Path
-from nacl.signing import SigningKey
-from nacl.secret import SecretBox
-from nacl.pwhash import argon2i
-from whee.valkey import ValkeyStore
-from whee.fs import FsStore
-from xdg_base_dirs import xdg_data_home
-
-from usawa.store import KeyStore
-from usawa.crypto import DemoWallet
-from usawa.config import load_config
-
-logging.basicConfig(level=logging.WARNING)
-logg = logging.getLogger()
-
-PRIVATEKEY_FILE = "privatekey.box"
-PUBLICKEY_FILE = "publickey.bin"
-
-# TODO: change to xdg_data_dir
-DEFAULT_WALLET_DIR = (
- Path(os.environ.get("XDG_DATA_HOME", Path.home() / ".local/share")) / "usawa"
-)
-
-
-def encrypt_seed(seed: bytes, passphrase: str) -> bytes:
- salt = os.urandom(argon2i.SALTBYTES)
- key = argon2i.kdf(
- SecretBox.KEY_SIZE,
- passphrase.encode(),
- salt,
- )
- box = SecretBox(key)
- encrypted = box.encrypt(seed)
-
- # Prepend salt so we can re-derive the key on decrypt
- return salt + encrypted
-
-
-def setup_wallet(cfg, wallet_dir=None):
- db = None
- store_type = cfg.get('STORE_TYPE')
- if store_type == 'valkey':
- db = ValkeyStore(
- "",
- host=cfg.get("VALKEY_HOST"),
- port=cfg.get("VALKEY_PORT"),
- )
- elif store_type == 'fs':
- db = FsStore(
- base=cfg.get('FSSTORE_BASE', xdg_data_home()),
- dbname='usawa',
- )
- else:
- raise ValueError('invalid store type: ' + store_type)
-
- store = KeyStore(db)
-
- wallet_dir = Path(wallet_dir) if wallet_dir else DEFAULT_WALLET_DIR
- wallet_dir.mkdir(parents=True, exist_ok=True)
- logg.info("wallet directory: %s", wallet_dir)
-
- privatekey_path = wallet_dir / PRIVATEKEY_FILE
- publickey_path = wallet_dir / PUBLICKEY_FILE
-
- passphrase = getpass.getpass("Enter wallet passphrase: ")
- passphrase_confirm = getpass.getpass("Confirm wallet passphrase: ")
- if passphrase != passphrase_confirm:
- logg.error("passphrases do not match")
- return 1
-
- random_bytes = os.urandom(32)
- logg.debug("generated 32-byte seed")
-
- encrypted = encrypt_seed(random_bytes, passphrase)
- with open(privatekey_path, "wb") as f:
- f.write(encrypted)
- logg.info("encrypted key material saved to: %s", privatekey_path)
-
- sk = SigningKey(random_bytes)
- pk = sk.verify_key
- with open(publickey_path, "wb") as f:
- f.write(pk.encode())
- logg.info("public key saved to: %s", publickey_path)
- ops = int(cfg.get('WALLET_OPSLIMIT', 0))
- mem = int(cfg.get('WALLET_MEMLIMIT', 0))
-
- wallet = DemoWallet(privatekey=random_bytes)
- store.add_key(wallet, passphrase=passphrase_confirm, opslimit=ops, memlimit=mem)
- logg.info("key written to store")
-
- logg.info("setup complete.")
- logg.info("your 32-byte public key (hex): %s", pk.encode().hex())
-
- return 0
-
-
-if __name__ == '__main__':
- argp = argparse.ArgumentParser()
- argp.add_argument('-c', type=str, help='override config dir')
- argp.add_argument('-v', type=str, choices=['info','debug','warning','error'], help='be verbose')
- args = argp.parse_args()
-
- if args.v:
- logg.setLevel(getattr(logging, args.v.upper()))
-
- cfg = load_config(config_dir=args.c)
- setup_wallet(cfg)
diff --git a/dummy/usawa/runnable/view.py b/dummy/usawa/runnable/view.py
@@ -57,54 +57,59 @@ class Context:
return ctx
-argp = argparse.ArgumentParser()
-argp.add_argument('-o', type=str, dest='output', help='output file for resulting XML document')
-#argp.add_argument('-p', action='store_true', help='prompt for password to open wallet')
-argp.add_argument('-c', type=str, help='override config dir')
-argp.add_argument('-v', type=str, choices=['info','debug','warning','error'], help='be verbose')
-argp.add_argument('--valkey-host', dest='valkey_host', type=str, default='localhost', help='Valkey host')
-argp.add_argument('--valkey-port', dest='valkey_port', type=int, default=6379, help='Valkey port')
-argp.add_argument('ledger_xml_file', type=str, help='load ledger metadata from XML file')
-arg = argp.parse_args()
-
-if arg.v:
- logg.setLevel(getattr(logging, arg.v.upper()))
-
-ctx = Context.from_args(arg)
-
-#ledger = None
-#ledger_tree = load(arg.ledger_xml_file)
-#uidx = UnitIndex.from_tree(ledger_tree)
-#ledger = Ledger.from_tree(ledger_tree)
-ledger = Ledger.from_file(arg.ledger_xml_file)
-
-cfg = usawa.config.load_config(config_dir=arg.c)
-store_type = cfg.get('STORE_TYPE')
-db = None
-if store_type == 'valkey':
- db = ValkeyStore(
- "",
- host=cfg.get("VALKEY_HOST"),
- port=cfg.get("VALKEY_PORT"),
- )
-elif store_type == 'fs':
- db = FsStore(
- base=cfg.get('FSSTORE_BASE', xdg_data_home()),
- dbname='usawa',
- )
-else:
- raise ValueError('invalid store type: ' + store_type)
-store = LedgerStore(db, ledger)
-#pk = store.get_key()
-#wallet = DemoWallet(privatekey=pk)
-#ops = int(cfg.get('WALLET_OPSLIMIT', 0))
-#mem = int(cfg.get('WALLET_MEMLIMIT', 0))
-#pw = cfg.get('WALLET_KEY_PASSPHRASE')
-#if arg.p and pw == None:
-# pw = getpass.getpass("passphrase: ")
-#logg.debug('ops {}'.format(ops))
-#wallet = store.get_key(DemoWallet, passphrase=pw, opslimit=ops, memlimit=mem)
-wallet = store.get_default_key(DemoWallet)
-acl = ACL.from_wallet(wallet)
-store.load(acl=acl)
-sys.stdout.write(ledger.to_string())
+def main():
+ argp = argparse.ArgumentParser()
+ argp.add_argument('-o', type=str, dest='output', help='output file for resulting XML document')
+ #argp.add_argument('-p', action='store_true', help='prompt for password to open wallet')
+ argp.add_argument('-c', type=str, help='override config dir')
+ argp.add_argument('-v', type=str, choices=['info','debug','warning','error'], help='be verbose')
+ argp.add_argument('--valkey-host', dest='valkey_host', type=str, default='localhost', help='Valkey host')
+ argp.add_argument('--valkey-port', dest='valkey_port', type=int, default=6379, help='Valkey port')
+ argp.add_argument('ledger_xml_file', type=str, help='load ledger metadata from XML file')
+ arg = argp.parse_args()
+
+ if arg.v:
+ logg.setLevel(getattr(logging, arg.v.upper()))
+
+ ctx = Context.from_args(arg)
+
+ #ledger = None
+ #ledger_tree = load(arg.ledger_xml_file)
+ #uidx = UnitIndex.from_tree(ledger_tree)
+ #ledger = Ledger.from_tree(ledger_tree)
+ ledger = Ledger.from_file(arg.ledger_xml_file)
+
+ cfg = usawa.config.load_config(config_dir=arg.c)
+ store_type = cfg.get('STORE_TYPE')
+ db = None
+ if store_type == 'valkey':
+ db = ValkeyStore(
+ "",
+ host=cfg.get("VALKEY_HOST"),
+ port=cfg.get("VALKEY_PORT"),
+ )
+ elif store_type == 'fs':
+ db = FsStore(
+ base=cfg.get('FSSTORE_BASE', xdg_data_home()),
+ dbname='usawa',
+ )
+ else:
+ raise ValueError('invalid store type: ' + store_type)
+ store = LedgerStore(db, ledger)
+ #pk = store.get_key()
+ #wallet = DemoWallet(privatekey=pk)
+ #ops = int(cfg.get('WALLET_OPSLIMIT', 0))
+ #mem = int(cfg.get('WALLET_MEMLIMIT', 0))
+ #pw = cfg.get('WALLET_KEY_PASSPHRASE')
+ #if arg.p and pw == None:
+ # pw = getpass.getpass("passphrase: ")
+ #logg.debug('ops {}'.format(ops))
+ #wallet = store.get_key(DemoWallet, passphrase=pw, opslimit=ops, memlimit=mem)
+ wallet = store.get_default_key(DemoWallet)
+ acl = ACL.from_wallet(wallet)
+ store.load(acl=acl)
+ sys.stdout.write(ledger.to_string())
+
+
+if __name__ == '__main__':
+ main()
diff --git a/dummy/usawa/runnable/wallet.py b/dummy/usawa/runnable/wallet.py
@@ -0,0 +1,115 @@
+import argparse
+import getpass
+import logging
+import os
+from pathlib import Path
+from nacl.signing import SigningKey
+from nacl.secret import SecretBox
+from nacl.pwhash import argon2i
+from whee.valkey import ValkeyStore
+from whee.fs import FsStore
+from xdg_base_dirs import xdg_data_home
+
+from usawa.store import KeyStore
+from usawa.crypto import DemoWallet
+from usawa.config import load_config
+
+logging.basicConfig(level=logging.WARNING)
+logg = logging.getLogger()
+
+PRIVATEKEY_FILE = "privatekey.box"
+PUBLICKEY_FILE = "publickey.bin"
+
+# TODO: change to xdg_data_dir
+DEFAULT_WALLET_DIR = (
+ Path(os.environ.get("XDG_DATA_HOME", Path.home() / ".local/share")) / "usawa"
+)
+
+
+def encrypt_seed(seed: bytes, passphrase: str) -> bytes:
+ salt = os.urandom(argon2i.SALTBYTES)
+ key = argon2i.kdf(
+ SecretBox.KEY_SIZE,
+ passphrase.encode(),
+ salt,
+ )
+ box = SecretBox(key)
+ encrypted = box.encrypt(seed)
+
+ # Prepend salt so we can re-derive the key on decrypt
+ return salt + encrypted
+
+
+def setup_wallet(cfg, wallet_dir=None):
+ db = None
+ store_type = cfg.get('STORE_TYPE')
+ if store_type == 'valkey':
+ db = ValkeyStore(
+ "",
+ host=cfg.get("VALKEY_HOST"),
+ port=cfg.get("VALKEY_PORT"),
+ )
+ elif store_type == 'fs':
+ db = FsStore(
+ base=cfg.get('FSSTORE_BASE', xdg_data_home()),
+ dbname='usawa',
+ )
+ else:
+ raise ValueError('invalid store type: ' + store_type)
+
+ store = KeyStore(db)
+
+ wallet_dir = Path(wallet_dir) if wallet_dir else DEFAULT_WALLET_DIR
+ wallet_dir.mkdir(parents=True, exist_ok=True)
+ logg.info("wallet directory: %s", wallet_dir)
+
+ privatekey_path = wallet_dir / PRIVATEKEY_FILE
+ publickey_path = wallet_dir / PUBLICKEY_FILE
+
+ passphrase = getpass.getpass("Enter wallet passphrase: ")
+ passphrase_confirm = getpass.getpass("Confirm wallet passphrase: ")
+ if passphrase != passphrase_confirm:
+ logg.error("passphrases do not match")
+ return 1
+
+ random_bytes = os.urandom(32)
+ logg.debug("generated 32-byte seed")
+
+ encrypted = encrypt_seed(random_bytes, passphrase)
+ with open(privatekey_path, "wb") as f:
+ f.write(encrypted)
+ logg.info("encrypted key material saved to: %s", privatekey_path)
+
+ sk = SigningKey(random_bytes)
+ pk = sk.verify_key
+ with open(publickey_path, "wb") as f:
+ f.write(pk.encode())
+ logg.info("public key saved to: %s", publickey_path)
+ ops = int(cfg.get('WALLET_OPSLIMIT', 0))
+ mem = int(cfg.get('WALLET_MEMLIMIT', 0))
+
+ wallet = DemoWallet(privatekey=random_bytes)
+ store.add_key(wallet, passphrase=passphrase_confirm, opslimit=ops, memlimit=mem)
+ logg.info("key written to store")
+
+ logg.info("setup complete.")
+ logg.info("your 32-byte public key (hex): %s", pk.encode().hex())
+
+ return 0
+
+
+def main():
+ argp = argparse.ArgumentParser()
+ argp.add_argument('-c', type=str, help='override config dir')
+ argp.add_argument('-v', type=str, choices=['info','debug','warning','error'], help='be verbose')
+ args = argp.parse_args()
+
+ if args.v:
+ logg.setLevel(getattr(logging, args.v.upper()))
+
+ cfg = load_config(config_dir=args.c)
+ setup_wallet(cfg)
+
+
+if __name__ == '__main__':
+ main()