diff --git a/chaind_eth/cli/process.py b/chaind_eth/cli/process.py index 1ba16f3..0344bee 100644 --- a/chaind_eth/cli/process.py +++ b/chaind_eth/cli/process.py @@ -24,6 +24,7 @@ class Processor: self.source = source self.processor = [] self.content = [] + self.token = [] self.token_resolver = resolver self.cursor = 0 self.gas_oracle = gas_oracle @@ -54,7 +55,8 @@ class Processor: # 0: recipient # 1: amount - # 2: token identifier + # 2: token identifier (optional, when not specified network gas token will be used) + # 3: gas amount (optional) def process(self): txs = [] for i, r in enumerate(self.content): @@ -68,10 +70,11 @@ class Processor: self.content[i][1] = int(strip_0x(r[1]), 16) native_token_value = 0 if self.token_resolver == None: - self.content[i][2] = None + self.token.append(None) else: - k = r[2] - self.content[i][2] = self.token_resolver.lookup(k) + #self.content[i][2] = self.token_resolver.lookup(k) + token = self.token_resolver.lookup(r[2]) + self.token.append(token) if len(self.content[i]) == 3: self.content[i].append(native_token_value) @@ -94,27 +97,53 @@ class Processor: token_factory = None r = self.content[self.cursor] - logg.debug('rrrr {} '.format(r)) - if r[2] == None: + token = self.token[self.cursor] + if token == None: token_factory = Gas(self.chain_spec, signer=self.signer, gas_oracle=self.gas_oracle, nonce_oracle=self.nonce_oracle) else: token_factory = ERC20(self.chain_spec, signer=self.signer, gas_oracle=self.gas_oracle, nonce_oracle=self.nonce_oracle) value = 0 + gas_value = 0 data = '0x' + debug_destination = (r[2], token) + if debug_destination[1] == None: + debug_destination = (None, 'network gas token') if isinstance(token_factory, ERC20): - (tx_hash_hex, o) = token_factory.transfer(r[2], self.sender, r[0], r[1]) + (tx_hash_hex, o) = token_factory.transfer(token, self.sender, r[0], r[1]) logg.debug('tx {}'.format(o)) - # TODO: allow chainlib to return args only + # TODO: allow chainlib to return data args only (TxFormat) tx = unpack(bytes.fromhex(strip_0x(o['params'][0])), self.chain_spec) data = tx['data'] + try: + value = int(r[1]) + except ValueError: + value = int(strip_0x(r[1]), 16) + try: + gas_value = int(r[3]) + except: + gas_value = int(strip_0x(r[3]), 16) else: - value = r[1] + try: + value = int(r[1]) + except ValueError: + value = int(strip_0x(r[1]), 16) + gas_value = value + + logg.debug('token factory {} resolved sender {} recipient {} gas value {} token value {} token {}'.format( + str(token_factory), + self.sender, + r[0], + gas_value, + value, + debug_destination, + ) + ) tx = { 'from': self.sender, 'to': r[0], - 'value': value, + 'value': gas_value, 'data': data, 'nonce': nonce, 'gasPrice': self.gas_price_start, diff --git a/chaind_eth/cli/resolver.py b/chaind_eth/cli/resolver.py index ca91f8b..618ee2e 100644 --- a/chaind_eth/cli/resolver.py +++ b/chaind_eth/cli/resolver.py @@ -24,13 +24,13 @@ class DefaultResolver: def lookup(self, k): + if k == '' or k == None: + return None for i, lookup in enumerate(self.lookups): address = self.lookup_pointers[i] o = lookup.address_of(address, k, sender_address=self.sender_address) r = self.rpc.do(o) address = lookup.parse_address_of(r) - if address == ZERO_ADDRESS: - address = None - return address - + if address != ZERO_ADDRESS: + return address raise FileNotFoundError(k) diff --git a/chaind_eth/runnable/send.py b/chaind_eth/runnable/send.py index 3fc876f..a88d556 100644 --- a/chaind_eth/runnable/send.py +++ b/chaind_eth/runnable/send.py @@ -6,6 +6,7 @@ import datetime import enum import re import stat +import socket # external imports import chainlib.eth.cli @@ -53,12 +54,14 @@ conn = rpc.connect_by_config(config) chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC')) class OpMode(enum.Enum): - STDOUT = 'standard output' - UNIX = 'unix socket' + STDOUT = 'standard_output' + UNIX = 'unix_socket' mode = OpMode.STDOUT -re_unix = r'^ipc:///.+' -if re.match(re_unix, config.get('_SOCKET', '')): +re_unix = r'^ipc://(/.+)' +m = re.match(re_unix, config.get('_SOCKET', '')) +if m != None: + config.add(m.group(1), '_SOCKET', exists_ok=True) r = 0 try: stat_info = os.stat(config.get('_SOCKET')) @@ -70,7 +73,7 @@ if re.match(re_unix, config.get('_SOCKET', '')): if r > 0: sys.stderr.write('{} is not a socket\n'.format(config.get('_SOCKET'))) sys.exit(1) - + mode = OpMode.UNIX logg.info('using mode {}'.format(mode.value)) @@ -92,9 +95,31 @@ class TokenIndexLookupAdapter(TokenUniqueSymbolIndex): return self.address_of(self.index_address, v, sender_address=sender) +class Outputter: + + def __init__(self, mode): + self.out = getattr(self, 'do_' + mode.value) + + + def do(self, hx): + self.out(hx) + + + def do_standard_output(self, hx): + sys.stdout.write(hx + '\n') + + + def do_unix_socket(self, hx): + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.connect(config.get('_SOCKET')) + s.send(hx.encode('utf-8')) + s.close() + + def main(): signer = rpc.get_signer() + # TODO: make resolvers pluggable token_resolver = DefaultResolver(chain_spec, conn, sender_address=rpc.get_sender_address()) token_index_lookup = TokenUniqueSymbolIndex(chain_spec, signer=signer, gas_oracle=rpc.get_gas_oracle(), nonce_oracle=rpc.get_nonce_oracle()) token_resolver.add_lookup(token_index_lookup, config.get('_TOKEN_INDEX')) @@ -111,13 +136,15 @@ def main(): tx_iter = iter(processor) + out = Outputter(mode) while True: tx = None try: tx_bytes = next(tx_iter) except StopIteration: break - print(tx_bytes.hex()) + tx_hex = tx_bytes.hex() + out.do(tx_hex) if __name__ == '__main__':