Browse Source

minor cleanups

The MMGen Project 2 years ago
parent
commit
3fd9c971bf
4 changed files with 86 additions and 56 deletions
  1. 16 7
      README.md
  2. 51 36
      mmgen_node_tools/Ticker.py
  3. 18 12
      mmgen_node_tools/main_ticker.py
  4. 1 1
      test/test_py_d/ts_misc.py

+ 16 - 7
README.md

@@ -12,10 +12,10 @@ First, install [MMGen][6].
 
 Then,
 
-    $ git clone https://github.com/mmgen/mmgen-node-tools
-    $ cd mmgen-node-tools
-    $ python3 -m build --no-isolation
-    $ python3 -m pip install --user dist/*.whl
+	$ git clone https://github.com/mmgen/mmgen-node-tools
+	$ cd mmgen-node-tools
+	$ python3 -m build --no-isolation
+	$ python3 -m pip install --user dist/*.whl
 
 Also make sure that `~/.local/bin` is in `PATH`.
 
@@ -24,9 +24,18 @@ Also make sure that `~/.local/bin` is in `PATH`.
 *NOTE: the tests require that the MMGen and MMGen Node Tools repositories be
 located in the same directory.*
 
-    $ test/init.sh
-    $ test/test-release.sh -A  # BTC-only testing
-    $ test/test-release.sh     # Full testing
+Initialize the test framework (must be run at least once after cloning, and
+possibly again after a pull if tests have been updated):
+
+	$ test/init.sh
+
+BTC-only testing:
+
+	$ test/test-release.sh -A
+
+Full testing:
+
+	$ test/test-release.sh
 
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 

+ 51 - 36
mmgen_node_tools/Ticker.py

@@ -87,11 +87,11 @@ def gen_data(data):
 	usr_wants = {
 		'id': (
 			{a.id for a in usr_assets if a.id} -
-			{a.id for a in usr_assets if a.amount and a.id} - {'usd-us-dollar'} )
+			{a.id for a in usr_assets if a.rate and a.id} - {'usd-us-dollar'} )
 		,
 		'symbol': (
 			{a.symbol for a in usr_assets if not a.id} -
-			{a.symbol for a in usr_assets if a.amount} - {'USD'} ),
+			{a.symbol for a in usr_assets if a.rate} - {'USD'} ),
 	}
 
 	found = { 'id': set(), 'symbol': set() }
@@ -114,7 +114,7 @@ def gen_data(data):
 			break
 
 	for asset in (cfg.usr_rows + cfg.usr_columns):
-		if asset.amount:
+		if asset.rate:
 			"""
 			User-supplied rate overrides rate from source data.
 			"""
@@ -122,8 +122,8 @@ def gen_data(data):
 			yield ( _id, {
 				'symbol': asset.symbol,
 				'id': _id,
-				'price_usd': str(Decimal(1/asset.amount)),
-				'price_btc': str(Decimal(1/asset.amount/btcusd)),
+				'price_usd': str(Decimal(1/asset.rate)),
+				'price_btc': str(Decimal(1/asset.rate/btcusd)),
 				'last_updated': int(now),
 			})
 
@@ -280,47 +280,62 @@ def main(cfg_parm,cfg_in_parm):
 def make_cfg(cmd_args,cfg_in):
 
 	def get_rows_from_cfg(add_data=None):
-		def create_row(e):
-			return asset_tuple(e.split('-')[0].upper(),e)
 		def gen():
 			for n,(k,v) in enumerate(cfg_in.cfg['assets'].items()):
 				yield(k)
 				if add_data and k in add_data:
 					v += tuple(add_data[k])
 				for e in v:
-					yield(create_row(e))
+					yield parse_asset_id(e,True)
 		return tuple(gen())
 
-	def parse_asset_tuple(s):
-		sym,id = (s.split('-')[0],s) if '-' in s else (s,None)
-		return asset_tuple( sym.upper(), id.lower() if id else None )
-
-	def parse_asset_triplet(s,reverse_ok=False):
-		ss = s.split(':')
-		return asset_triplet(
-			*parse_asset_tuple(s if len(ss) == 1 else ss[0]),
-			(
-				None if len(ss) == 1 else
-				1 / Decimal(ss[1][:-1]) if reverse_ok and ss[1].lower().endswith('r') else
-				Decimal(ss[1])
-			))
+	def parse_asset_id(s,require_label=False):
+		sym,label = (*s.split('-',1),None)[:2]
+		if require_label and not label:
+			die(1,f'{s!r}: asset label is missing')
+		return asset_tuple( sym.upper(), (s.lower() if label else None) )
 
 	def parse_usr_asset_arg(s):
-		return tuple(parse_asset_triplet(ss,reverse_ok=True) for ss in s.split(',')) if s else ()
+		"""
+		asset_id[:rate]
+		"""
+		def parse_parm(s):
+			ss = s.split(':')
+			assert len(ss) in (1,2), f'{s}: malformed argument'
+			asset_id,rate = (*ss,None)[:2]
+			parsed_id = parse_asset_id(asset_id)
+
+			return asset_data(
+				symbol = parsed_id.symbol,
+				id     = parsed_id.id,
+				amount = None,
+				rate   = (
+					None if rate is None else
+					1 / Decimal(rate[:-1]) if rate.lower().endswith('r') else
+					Decimal(rate) ))
+
+		return tuple(parse_parm(s2) for s2 in s.split(',')) if s else ()
 
 	def parse_query_arg(s):
+		"""
+		asset_id:amount[:to_asset_id[:to_amount]]
+		"""
+		def parse_query_asset(asset_id,amount):
+			parsed_id = parse_asset_id(asset_id)
+			return asset_data(
+				symbol = parsed_id.symbol,
+				id     = parsed_id.id,
+				amount = None if amount is None else Decimal(amount),
+				rate   = None )
+
 		ss = s.split(':')
-		if len(ss) == 2:
-			return query_tuple(
-				asset    = parse_asset_triplet(s),
-				to_asset = None )
-		elif len(ss) in (3,4):
-			return query_tuple(
-				asset    = parse_asset_triplet(':'.join(ss[:2])),
-				to_asset = parse_asset_triplet(':'.join(ss[2:])),
-			)
-		else:
-			die(1,f'{s}: malformed argument')
+		assert len(ss) in (2,3,4), f'{s}: malformed argument'
+		asset_id,amount,to_asset_id,to_amount = (*ss,None,None)[:4]
+
+		return query_tuple(
+			asset = parse_query_asset(asset_id,amount),
+			to_asset = parse_query_asset(to_asset_id,to_amount) if to_asset_id else None
+		)
 
 	def gen_uniq(obj_list,key,preload=None):
 		found = set([getattr(obj,key) for obj in preload if hasattr(obj,key)] if preload else ())
@@ -339,7 +354,7 @@ def make_cfg(cmd_args,cfg_in):
 
 	def get_portfolio_assets(ret=()):
 		if cfg_in.portfolio and opt.portfolio:
-			ret = tuple( asset_tuple(e.split('-')[0].upper(),e) for e in cfg_in.portfolio )
+			ret = (parse_asset_id(e,True) for e in cfg_in.portfolio)
 		return ( 'portfolio', tuple(e for e in ret if (not opt.btc) or e.symbol == 'BTC') )
 
 	def get_portfolio():
@@ -357,7 +372,7 @@ def make_cfg(cmd_args,cfg_in):
 	def create_rows():
 		rows = (
 			('trade_pair',) + query if (query and query.to_asset) else
-			('bitcoin',parse_asset_tuple('btc-bitcoin')) if opt.btc else
+			('bitcoin',parse_asset_id('btc-bitcoin')) if opt.btc else
 			get_rows_from_cfg( add_data={'fiat':['usd-us-dollar']} if opt.add_columns else None )
 		)
 
@@ -385,7 +400,7 @@ def make_cfg(cmd_args,cfg_in):
 		'portfolio' ])
 
 	query_tuple   = namedtuple('query',['asset','to_asset'])
-	asset_triplet = namedtuple('asset_triplet',['symbol','id','amount'])
+	asset_data    = namedtuple('asset_data',['symbol','id','amount','rate'])
 	asset_tuple   = namedtuple('asset_tuple',['symbol','id'])
 
 	usr_rows    = parse_usr_asset_arg(opt.add_rows)

+ 18 - 12
mmgen_node_tools/main_ticker.py

@@ -67,22 +67,28 @@ user’s portfolio, while trading mode displays the price of a given quantity
 of an asset in relation to other assets, optionally comparing an offered
 price to the spot price.
 
-ASSETS consist of either a symbol (e.g. ‘xmr’) or full ID consisting of
-symbol plus label (e.g. ‘xmr-monero’).  In cases where the symbol is
-ambiguous, the full ID must be used.  Examples:
+ASSETS consist of either a symbol (e.g. ‘xmr’) or full ID (see --list-ids)
+consisting of symbol plus label (e.g. ‘xmr-monero’).  In cases where the
+symbol is ambiguous, the full ID must be used.  Examples:
 
   chf                   - specify asset by symbol
   chf-swiss-franc-token - same as above, but use full ID instead of symbol
 
-ASSET SPECIFIERS consist of an ASSET followed by an optional colon and USD
-rate.  If the asset is not in the source data (see --list-ids), the label
-part of the ID may be arbitrarily chosen by the user.  When the letter ‘r’
-is appended to the USD rate, the rate is reversed, i.e. treated as ‘USD per
-asset’ instead of ‘asset per USD’.  Asset specifier examples:
+ASSET SPECIFIERS have the following format:
 
-  inr:79.5              - INR is not in the source data, so supply USD rate
-  inr-indian-rupee:79.5 - same as above, but add an arbitrary label
-  omr-omani-rial:2.59r  - OMR is pegged to USD with fixed value of 2.59 USD
+  ASSET[:RATE]
+
+If the asset referred to by ASSET is not in the source data (see --list-ids),
+an arbitrarily chosen label may be used.  RATE is the USD exchange rate of
+the asset.  When RATE is postfixed with the letter ‘r’, its meaning is
+reversed, i.e. interpreted as ‘ASSET/USD’ instead of ‘USD/ASSET’.  Asset
+specifier examples:
+
+  inr:79.5               - INR is not in the source data, so supply rate of
+                           79.5 INR to the Dollar (USD/INR)
+  inr:0.01257r           - same as above, but use reverse rate (INR/USD)
+  inr-indian-rupee:79.5  - same as first example, but add an arbitrary label
+  omr-omani-rial:2.59r   - Omani Rial is pegged to the Dollar at 2.59 USD
 
 A TRADE_SPECIFIER is a single argument in the format:
 
@@ -137,7 +143,7 @@ $ mmnode-ticker
 # Display BTC price only:
 $ mmnode-ticker --btc
 
-# Wide display, add EUR and OMR columns, OMRUSD rate, extra precision and
+# Wide display, add EUR and OMR columns, OMR/USD rate, extra precision and
 # proxy:
 $ mmnode-ticker -w -c eur,omr-omani-rial:2.59r -e2 -x http://vpnhost:8118
 

+ 1 - 1
test/test_py_d/ts_misc.py

@@ -280,6 +280,6 @@ class TestSuiteScripts(TestSuiteBase):
 				r'EUR \(EURO TOKEN\) = 1.0186 USD ' +
 				r'OMR \(OMANI RIAL\) = 2.5900 USD',
 				'USD EUR OMR BTC CHG_7d CHG_24h UPDATED',
-				'BITCOIN',
+				r'BITCOIN 23,250.77 22,826.6890 8,977.1328 1.00000000 \+11.15 \+0.89 10 minutes ago',
 				'OMANI RIAL 2.59 2.5428 1.0000 0.00011139 -- -- just now'
 			])