From 96b4ad4a7213f4c327303ca25e1a6586e23629d2 Mon Sep 17 00:00:00 2001 From: Louis Holbrook Date: Sun, 21 Feb 2021 15:41:37 +0000 Subject: [PATCH] Refactor import scripts --- apps/cic-eth/cic_eth/api/api_task.py | 7 +- apps/cic-eth/cic_eth/callbacks/redis.py | 8 +- apps/cic-eth/cic_eth/db/models/base.py | 1 + apps/cic-eth/cic_eth/db/models/role.py | 70 +- apps/cic-eth/cic_eth/eth/gas.py | 5 +- apps/cic-eth/cic_eth/eth/tx.py | 2 +- apps/cic-eth/cic_eth/runnable/create.py | 5 +- .../cic_eth/runnable/daemons/dispatcher.py | 7 +- .../cic_eth/runnable/daemons/filters/gas.py | 5 +- .../runnable/daemons/filters/register.py | 6 +- .../cic_eth/runnable/daemons/manager.py | 2 +- .../cic_eth/runnable/daemons/tasker.py | 5 +- apps/cic-eth/cic_eth/sync/history.py | 2 +- apps/cic-eth/cic_eth/sync/mined.py | 7 +- apps/cic-eth/cic_eth/version.py | 2 +- apps/cic-eth/config/cic.ini | 2 +- apps/cic-eth/config/docker/bancor.ini | 2 + apps/cic-eth/config/docker/celery.ini | 3 + apps/cic-eth/config/docker/cic.ini | 4 + apps/cic-eth/config/docker/custody.ini | 2 + apps/cic-eth/config/docker/database.ini | 9 + apps/cic-eth/config/docker/dispatcer.ini | 2 + apps/cic-eth/config/docker/eth.ini | 8 + apps/cic-eth/config/docker/redis.ini | 4 + apps/cic-eth/config/docker/signer.ini | 5 + apps/cic-eth/config/docker/ssl.ini | 6 + apps/cic-eth/config/docker/syncer.ini | 2 + apps/cic-eth/config/docker/tasks.ini | 3 + apps/cic-eth/requirements.txt | 6 +- apps/cic-meta/CHANGELOG | 3 + apps/cic-meta/package.json | 10 +- apps/cic-meta/scripts/server/server.ts | 5 +- apps/cic-meta/src/index.ts | 1 + apps/contract-migration/dev/balance.py | 58 - apps/contract-migration/dev/create.py | 47 - apps/contract-migration/dev/decode.py | 48 - apps/contract-migration/dev/env.sh | 24 - apps/contract-migration/dev/gas.py | 105 - .../dev/js/register_users.js | 101 - apps/contract-migration/dev/keys.sh | 26 - .../dev/python/scripts/setup.py | 4 - .../dev/python/scripts/tx_driver.py | 150 -- .../dev/python/scripts/tx_seed.py | 51 - .../dev/python/scripts/users.py | 212 -- apps/contract-migration/dev/python/setup.cfg | 40 - apps/contract-migration/dev/python/setup.py | 4 - apps/contract-migration/dev/requirements.txt | 10 - .../dev/sarafu_declaration.json | 18 - apps/contract-migration/dev/sarafu_logo.png | Bin 7214 -> 0 bytes apps/contract-migration/dev/setup.sh | 138 -- apps/contract-migration/dev/tests/create.py | 31 - apps/contract-migration/dev/transfer.py | 105 - apps/contract-migration/docker/Dockerfile | 35 +- apps/contract-migration/{dev => }/nvm.sh | 0 apps/contract-migration/scripts/README | 72 + .../scripts/cmd/__init__.py | 0 .../contract-migration/scripts/cmd/traffic.py | 417 ++++ .../scripts/common/__init__.py | 8 + .../scripts/common/argparse.py | 73 + .../scripts/common/config.py | 39 + apps/contract-migration/scripts/common/log.py | 18 + .../scripts/common/registry.py | 86 + apps/contract-migration/scripts/common/rpc.py | 18 + .../scripts/common/signer.py | 23 + .../scripts/config/celery.ini | 3 + .../contract-migration/scripts/config/cic.ini | 9 + .../scripts/config/database.ini | 5 + .../contract-migration/scripts/config/eth.ini | 8 + .../scripts/config/meta.ini | 2 + .../contract-migration/scripts/config/pgp.ini | 5 + .../scripts/config/redis.ini | 4 + .../scripts/config/traffic.ini | 4 + .../scripts/create_import_users.py | 216 ++ .../_logs/2021-02-12T18_59_21_680Z-debug.log | 1383 +++++++++++++ .../scripts/false/anonymous-cli-metrics.json | 1 + .../scripts/import_balance.py | 295 +++ .../scripts/import_balance.sh | 1 + .../contract-migration/scripts/import_meta.js | 120 ++ .../scripts/import_users.py | 177 ++ .../scripts/import_users.sh | 1 + .../scripts/local/account.py | 37 + .../scripts/local/noop_traffic.py | 37 + .../scripts/local/transfer.py | 51 + .../scripts/package-lock.json | 1749 +++++++++++++++++ .../scripts/requirements.txt | 12 + apps/contract-migration/scripts/traffic.py | 101 + apps/contract-migration/scripts/verify.py | 306 +++ apps/contract-migration/seed_cic_eth.sh | 16 +- .../testdata/pgp/privatekeys_meta.asc | 241 +++ .../testdata/pgp/publickeys_meta.asc | 151 ++ docker-compose.yml | 26 +- 91 files changed, 5872 insertions(+), 1261 deletions(-) create mode 100644 apps/cic-eth/config/docker/bancor.ini create mode 100644 apps/cic-eth/config/docker/celery.ini create mode 100644 apps/cic-eth/config/docker/cic.ini create mode 100644 apps/cic-eth/config/docker/custody.ini create mode 100644 apps/cic-eth/config/docker/database.ini create mode 100644 apps/cic-eth/config/docker/dispatcer.ini create mode 100644 apps/cic-eth/config/docker/eth.ini create mode 100644 apps/cic-eth/config/docker/redis.ini create mode 100644 apps/cic-eth/config/docker/signer.ini create mode 100644 apps/cic-eth/config/docker/ssl.ini create mode 100644 apps/cic-eth/config/docker/syncer.ini create mode 100644 apps/cic-eth/config/docker/tasks.ini delete mode 100644 apps/contract-migration/dev/balance.py delete mode 100644 apps/contract-migration/dev/create.py delete mode 100644 apps/contract-migration/dev/decode.py delete mode 100644 apps/contract-migration/dev/env.sh delete mode 100644 apps/contract-migration/dev/gas.py delete mode 100644 apps/contract-migration/dev/js/register_users.js delete mode 100644 apps/contract-migration/dev/keys.sh delete mode 100644 apps/contract-migration/dev/python/scripts/setup.py delete mode 100644 apps/contract-migration/dev/python/scripts/tx_driver.py delete mode 100644 apps/contract-migration/dev/python/scripts/tx_seed.py delete mode 100644 apps/contract-migration/dev/python/scripts/users.py delete mode 100644 apps/contract-migration/dev/python/setup.cfg delete mode 100644 apps/contract-migration/dev/python/setup.py delete mode 100644 apps/contract-migration/dev/requirements.txt delete mode 100644 apps/contract-migration/dev/sarafu_declaration.json delete mode 100644 apps/contract-migration/dev/sarafu_logo.png delete mode 100644 apps/contract-migration/dev/setup.sh delete mode 100644 apps/contract-migration/dev/tests/create.py delete mode 100644 apps/contract-migration/dev/transfer.py rename apps/contract-migration/{dev => }/nvm.sh (100%) create mode 100644 apps/contract-migration/scripts/README create mode 100644 apps/contract-migration/scripts/cmd/__init__.py create mode 100644 apps/contract-migration/scripts/cmd/traffic.py create mode 100644 apps/contract-migration/scripts/common/__init__.py create mode 100644 apps/contract-migration/scripts/common/argparse.py create mode 100644 apps/contract-migration/scripts/common/config.py create mode 100644 apps/contract-migration/scripts/common/log.py create mode 100644 apps/contract-migration/scripts/common/registry.py create mode 100644 apps/contract-migration/scripts/common/rpc.py create mode 100644 apps/contract-migration/scripts/common/signer.py create mode 100644 apps/contract-migration/scripts/config/celery.ini create mode 100644 apps/contract-migration/scripts/config/cic.ini create mode 100644 apps/contract-migration/scripts/config/database.ini create mode 100644 apps/contract-migration/scripts/config/eth.ini create mode 100644 apps/contract-migration/scripts/config/meta.ini create mode 100644 apps/contract-migration/scripts/config/pgp.ini create mode 100644 apps/contract-migration/scripts/config/redis.ini create mode 100644 apps/contract-migration/scripts/config/traffic.ini create mode 100644 apps/contract-migration/scripts/create_import_users.py create mode 100644 apps/contract-migration/scripts/false/_logs/2021-02-12T18_59_21_680Z-debug.log create mode 100644 apps/contract-migration/scripts/false/anonymous-cli-metrics.json create mode 100644 apps/contract-migration/scripts/import_balance.py create mode 100644 apps/contract-migration/scripts/import_balance.sh create mode 100644 apps/contract-migration/scripts/import_meta.js create mode 100644 apps/contract-migration/scripts/import_users.py create mode 100644 apps/contract-migration/scripts/import_users.sh create mode 100644 apps/contract-migration/scripts/local/account.py create mode 100644 apps/contract-migration/scripts/local/noop_traffic.py create mode 100644 apps/contract-migration/scripts/local/transfer.py create mode 100644 apps/contract-migration/scripts/package-lock.json create mode 100644 apps/contract-migration/scripts/requirements.txt create mode 100644 apps/contract-migration/scripts/traffic.py create mode 100644 apps/contract-migration/scripts/verify.py create mode 100644 apps/contract-migration/testdata/pgp/privatekeys_meta.asc create mode 100644 apps/contract-migration/testdata/pgp/publickeys_meta.asc diff --git a/apps/cic-eth/cic_eth/api/api_task.py b/apps/cic-eth/cic_eth/api/api_task.py index a92bd50..8522ffb 100644 --- a/apps/cic-eth/cic_eth/api/api_task.py +++ b/apps/cic-eth/cic_eth/api/api_task.py @@ -6,10 +6,13 @@ # standard imports import logging -# third-party imports +# external imports import celery -from cic_registry.chain import ChainSpec +#from cic_registry.chain import ChainSpec from cic_registry import CICRegistry +from chainlib.chain import ChainSpec + +# local imports from cic_eth.eth.factory import TxFactory from cic_eth.db.enum import LockEnum diff --git a/apps/cic-eth/cic_eth/callbacks/redis.py b/apps/cic-eth/cic_eth/callbacks/redis.py index 648edab..745f9f8 100644 --- a/apps/cic-eth/cic_eth/callbacks/redis.py +++ b/apps/cic-eth/cic_eth/callbacks/redis.py @@ -18,7 +18,11 @@ logg = celery_app.log.get_default_logger() def redis(self, result, destination, status_code): (host, port, db, channel) = destination.split(':') r = redis_interface.Redis(host=host, port=port, db=db) - s = json.dumps(result) + data = { + 'root_id': self.request.root_id, + 'status': status_code, + 'result': result, + } logg.debug('redis callback on host {} port {} db {} channel {}'.format(host, port, db, channel)) - r.publish(channel, s) + r.publish(channel, json.dumps(data)) r.close() diff --git a/apps/cic-eth/cic_eth/db/models/base.py b/apps/cic-eth/cic_eth/db/models/base.py index 353c67c..db570df 100644 --- a/apps/cic-eth/cic_eth/db/models/base.py +++ b/apps/cic-eth/cic_eth/db/models/base.py @@ -114,6 +114,7 @@ class SessionBase(Model): @staticmethod def release_session(session=None): + session.flush() session_key = str(id(session)) if SessionBase.localsessions.get(session_key) != None: logg.debug('destroying session {}'.format(session_key)) diff --git a/apps/cic-eth/cic_eth/db/models/role.py b/apps/cic-eth/cic_eth/db/models/role.py index e2d4824..d632b0a 100644 --- a/apps/cic-eth/cic_eth/db/models/role.py +++ b/apps/cic-eth/cic_eth/db/models/role.py @@ -24,9 +24,10 @@ class AccountRole(SessionBase): tag = Column(Text) address_hex = Column(String(42)) - + + # TODO: @staticmethod - def get_address(tag): + def get_address(tag, session): """Get Ethereum address matching the given tag :param tag: Tag @@ -34,14 +35,24 @@ class AccountRole(SessionBase): :returns: Ethereum address, or zero-address if tag does not exist :rtype: str, 0x-hex """ - role = AccountRole.get_role(tag) - if role == None: - return zero_address - return role.address_hex + if session == None: + raise ValueError('nested bind session calls will not succeed as the first call to release_session in the stack will leave the db object detached further down the stack. We will need additional reference count.') + + session = SessionBase.bind_session(session) + + role = AccountRole.get_role(tag, session) + + r = zero_address + if role != None: + r = role.address_hex + + SessionBase.release_session(session) + + return r @staticmethod - def get_role(tag): + def get_role(tag, session=None): """Get AccountRole model object matching the given tag :param tag: Tag @@ -49,20 +60,26 @@ class AccountRole(SessionBase): :returns: Role object, if found :rtype: cic_eth.db.models.role.AccountRole """ - session = AccountRole.create_session() - role = AccountRole.__get_role(session, tag) - session.close() - #return role.address_hex + session = SessionBase.bind_session(session) + + role = AccountRole.__get_role(tag, session) + + SessionBase.release_session(session) + return role @staticmethod - def __get_role(session, tag): - return session.query(AccountRole).filter(AccountRole.tag==tag).first() + def __get_role(tag, session): + q = session.query(AccountRole) + q = q.filter(AccountRole.tag==tag) + r = q.first() + session.flush() + return r @staticmethod - def set(tag, address_hex): + def set(tag, address_hex, session=None): """Persist a tag to Ethereum address association. This will silently overwrite the existing value. @@ -74,16 +91,16 @@ class AccountRole(SessionBase): :returns: Role object :rtype: cic_eth.db.models.role.AccountRole """ - #session = AccountRole.create_session() - #role = AccountRole.__get(session, tag) - role = AccountRole.get_role(tag) #session, tag) + session = SessionBase.bind_session(session) + + role = AccountRole.get_role(tag, session) if role == None: role = AccountRole(tag) role.address_hex = address_hex - #session.add(role) - #session.commit() - #session.close() - return role #address_hex + + SessionBase.release_session(session) + + return role @staticmethod @@ -95,20 +112,17 @@ class AccountRole(SessionBase): :returns: Role tag, or None if no match :rtype: str or None """ - localsession = session - if localsession == None: - localsession = SessionBase.create_session() + session = SessionBase.bind_session(session) - q = localsession.query(AccountRole) + q = session.query(AccountRole) q = q.filter(AccountRole.address_hex==address) role = q.first() tag = None if role != None: tag = role.tag - if session == None: - localsession.close() - + SessionBase.release_session(session) + return tag diff --git a/apps/cic-eth/cic_eth/eth/gas.py b/apps/cic-eth/cic_eth/eth/gas.py index 5bbd13d..8cf9905 100644 --- a/apps/cic-eth/cic_eth/eth/gas.py +++ b/apps/cic-eth/cic_eth/eth/gas.py @@ -52,7 +52,10 @@ class GasOracle(): :returns: Etheerum account address :rtype: str, 0x-hex """ - return AccountRole.get_address('GAS_GIFTER') + session = SessionBase.create_session() + a = AccountRole.get_address('GAS_GIFTER', session) + session.close() + return a def gas_price(self, category='safe'): diff --git a/apps/cic-eth/cic_eth/eth/tx.py b/apps/cic-eth/cic_eth/eth/tx.py index ce16145..a091696 100644 --- a/apps/cic-eth/cic_eth/eth/tx.py +++ b/apps/cic-eth/cic_eth/eth/tx.py @@ -399,7 +399,7 @@ def refill_gas(self, recipient_address, chain_str): q = session.query(Otx.tx_hash) q = q.join(TxCache) q = q.filter(Otx.status.op('&')(StatusBits.FINAL.value)==0) - q = q.filter(TxCache.from_value!='0x00') + q = q.filter(TxCache.from_value!=0) q = q.filter(TxCache.recipient==recipient_address) c = q.count() session.close() diff --git a/apps/cic-eth/cic_eth/runnable/create.py b/apps/cic-eth/cic_eth/runnable/create.py index 5514abc..8371b0e 100644 --- a/apps/cic-eth/cic_eth/runnable/create.py +++ b/apps/cic-eth/cic_eth/runnable/create.py @@ -76,8 +76,9 @@ def main(): t = api.create_account(register=register) ps.get_message() - m = ps.get_message(timeout=args.timeout) - print(json.loads(m['data'])) + o = ps.get_message(timeout=args.timeout) + m = json.loads(o['data']) + print(m['result']) if __name__ == '__main__': diff --git a/apps/cic-eth/cic_eth/runnable/daemons/dispatcher.py b/apps/cic-eth/cic_eth/runnable/daemons/dispatcher.py index dfcbdf5..9837585 100644 --- a/apps/cic-eth/cic_eth/runnable/daemons/dispatcher.py +++ b/apps/cic-eth/cic_eth/runnable/daemons/dispatcher.py @@ -91,6 +91,8 @@ run = True class DispatchSyncer: + yield_delay = 0.005 + def __init__(self, chain_spec): self.chain_spec = chain_spec self.chain_id = chain_spec.chain_id() @@ -138,7 +140,10 @@ class DispatchSyncer: txs[k] = utxs[k] self.process(w3, txs) - time.sleep(interval) + if len(utxs) > 0: + time.sleep(self.yield_delay) + else: + time.sleep(interval) def main(): diff --git a/apps/cic-eth/cic_eth/runnable/daemons/filters/gas.py b/apps/cic-eth/cic_eth/runnable/daemons/filters/gas.py index 4b31237..485f955 100644 --- a/apps/cic-eth/cic_eth/runnable/daemons/filters/gas.py +++ b/apps/cic-eth/cic_eth/runnable/daemons/filters/gas.py @@ -5,9 +5,10 @@ import logging from cic_registry.chain import ChainSpec # local imports +from cic_eth.db.enum import StatusBits from cic_eth.db.models.base import SessionBase from cic_eth.db.models.tx import TxCache -from cic_eth.db import Otx +from cic_eth.db.models.otx import Otx from cic_eth.queue.tx import get_paused_txs from cic_eth.eth.task import create_check_gas_and_send_task from .base import SyncFilter @@ -39,7 +40,7 @@ class GasFilter(SyncFilter): return chain_spec = ChainSpec.from_chain_str(chain_str) - txs = get_paused_txs(StatusEnum.WAITFORGAS, r[0], chain_spec.chain_id(), session=session) + txs = get_paused_txs(StatusBits.GAS_ISSUES, r[0], chain_spec.chain_id(), session=session) SessionBase.release_session(session) diff --git a/apps/cic-eth/cic_eth/runnable/daemons/filters/register.py b/apps/cic-eth/cic_eth/runnable/daemons/filters/register.py index 3c003d3..f753d57 100644 --- a/apps/cic-eth/cic_eth/runnable/daemons/filters/register.py +++ b/apps/cic-eth/cic_eth/runnable/daemons/filters/register.py @@ -15,6 +15,10 @@ account_registry_add_log_hash = '0x5ed3bdd47b9af629827a8d129aa39c870b10c03f0153f class RegistrationFilter(SyncFilter): + def __init__(self, queue): + self.queue = queue + + def filter(self, w3, tx, rcpt, chain_spec, session=None): logg.debug('applying registration filter') registered_address = None @@ -30,6 +34,6 @@ class RegistrationFilter(SyncFilter): address, str(chain_spec), ], - queue=queue, + queue=self.queue, ) s.apply_async() diff --git a/apps/cic-eth/cic_eth/runnable/daemons/manager.py b/apps/cic-eth/cic_eth/runnable/daemons/manager.py index db83460..068f0a4 100644 --- a/apps/cic-eth/cic_eth/runnable/daemons/manager.py +++ b/apps/cic-eth/cic_eth/runnable/daemons/manager.py @@ -178,7 +178,7 @@ def main(): tx_filter = TxFilter(queue) - registration_filter = RegistrationFilter() + registration_filter = RegistrationFilter(queue) gas_filter = GasFilter(c.gas_provider(), queue) diff --git a/apps/cic-eth/cic_eth/runnable/daemons/tasker.py b/apps/cic-eth/cic_eth/runnable/daemons/tasker.py index 6b9c4bf..9a4bb2c 100644 --- a/apps/cic-eth/cic_eth/runnable/daemons/tasker.py +++ b/apps/cic-eth/cic_eth/runnable/daemons/tasker.py @@ -32,6 +32,7 @@ from cic_eth.admin import ctrl from cic_eth.eth.rpc import RpcClient from cic_eth.eth.rpc import GasOracle from cic_eth.queue import tx +from cic_eth.queue import balance from cic_eth.callbacks import Callback from cic_eth.callbacks import http from cic_eth.callbacks import tcp @@ -49,6 +50,7 @@ argparser = argparse.ArgumentParser() argparser.add_argument('-p', '--provider', dest='p', type=str, help='web3 provider') argparser.add_argument('-c', type=str, default=config_dir, help='config file') argparser.add_argument('-q', type=str, default='cic-eth', help='queue name for worker tasks') +argparser.add_argument('-r', type=str, help='CIC registry address') argparser.add_argument('--abi-dir', dest='abi_dir', type=str, help='Directory containing bytecode and abi') argparser.add_argument('--trace-queue-status', default=None, dest='trace_queue_status', action='store_true', help='set to perist all queue entry status changes to storage') argparser.add_argument('-i', '--chain-spec', dest='i', type=str, help='chain spec') @@ -68,6 +70,7 @@ config.process() args_override = { 'ETH_ABI_DIR': getattr(args, 'abi_dir'), 'CIC_CHAIN_SPEC': getattr(args, 'i'), + 'CIC_REGISTRY_ADDRESS': getattr(args, 'r'), 'ETH_PROVIDER': getattr(args, 'p'), 'TASKS_TRACE_QUEUE_STATUS': getattr(args, 'trace_queue_status'), } @@ -228,7 +231,7 @@ def main(): for address in trusted_addresses: logg.info('using trusted address {}'.format(address)) oracle = DeclaratorOracleAdapter(declarator.contract, trusted_addresses) - chain_registry.add_oracle('naive_erc20_oracle', oracle) + chain_registry.add_oracle(oracle, 'naive_erc20_oracle') #chain_spec = CICRegistry.default_chain_spec diff --git a/apps/cic-eth/cic_eth/sync/history.py b/apps/cic-eth/cic_eth/sync/history.py index c75602b..6a500fd 100644 --- a/apps/cic-eth/cic_eth/sync/history.py +++ b/apps/cic-eth/cic_eth/sync/history.py @@ -21,7 +21,7 @@ class HistorySyncer(MinedSyncer): :param mx: Maximum number of blocks to return in one call :type mx: int """ - def __init__(self, bc_cache, mx=20): + def __init__(self, bc_cache, mx=500): super(HistorySyncer, self).__init__(bc_cache) self.max = mx diff --git a/apps/cic-eth/cic_eth/sync/mined.py b/apps/cic-eth/cic_eth/sync/mined.py index 4481bb2..62b5567 100644 --- a/apps/cic-eth/cic_eth/sync/mined.py +++ b/apps/cic-eth/cic_eth/sync/mined.py @@ -23,6 +23,8 @@ class MinedSyncer(Syncer): :type bc_cache: Object implementing methods from cic_eth.sync.SyncerBackend """ + yield_delay = 0.005 + def __init__(self, bc_cache): super(MinedSyncer, self).__init__(bc_cache) self.block_offset = 0 @@ -100,5 +102,8 @@ class MinedSyncer(Syncer): block_number = self.process(c.w3, block.hex()) logg.info('processed block {} {}'.format(block_number, block.hex())) self.bc_cache.disconnect() - time.sleep(interval) + if len(e) > 0: + time.sleep(self.yield_delay) + else: + time.sleep(interval) logg.info("Syncer no longer set to run, gracefully exiting") diff --git a/apps/cic-eth/cic_eth/version.py b/apps/cic-eth/cic_eth/version.py index f782394..9b5feb4 100644 --- a/apps/cic-eth/cic_eth/version.py +++ b/apps/cic-eth/cic_eth/version.py @@ -10,7 +10,7 @@ version = ( 0, 10, 0, - 'alpha.27', + 'alpha.30', ) version_object = semver.VersionInfo( diff --git a/apps/cic-eth/config/cic.ini b/apps/cic-eth/config/cic.ini index bb167d6..73cc99c 100644 --- a/apps/cic-eth/config/cic.ini +++ b/apps/cic-eth/config/cic.ini @@ -2,4 +2,4 @@ registry_address = chain_spec = tx_retry_delay = -trust_address = +trust_address = diff --git a/apps/cic-eth/config/docker/bancor.ini b/apps/cic-eth/config/docker/bancor.ini new file mode 100644 index 0000000..443924f --- /dev/null +++ b/apps/cic-eth/config/docker/bancor.ini @@ -0,0 +1,2 @@ +[bancor] +dir = /usr/local/share/cic/bancor diff --git a/apps/cic-eth/config/docker/celery.ini b/apps/cic-eth/config/docker/celery.ini new file mode 100644 index 0000000..98c5012 --- /dev/null +++ b/apps/cic-eth/config/docker/celery.ini @@ -0,0 +1,3 @@ +[celery] +broker_url = redis://localhost:63379 +result_url = redis://localhost:63379 diff --git a/apps/cic-eth/config/docker/cic.ini b/apps/cic-eth/config/docker/cic.ini new file mode 100644 index 0000000..251a6be --- /dev/null +++ b/apps/cic-eth/config/docker/cic.ini @@ -0,0 +1,4 @@ +[cic] +registry_address = +chain_spec = evm:bloxberg:8996 +trust_address = 0xEb3907eCad74a0013c259D5874AE7f22DcBcC95C diff --git a/apps/cic-eth/config/docker/custody.ini b/apps/cic-eth/config/docker/custody.ini new file mode 100644 index 0000000..8523f03 --- /dev/null +++ b/apps/cic-eth/config/docker/custody.ini @@ -0,0 +1,2 @@ +[custody] +account_index_address = diff --git a/apps/cic-eth/config/docker/database.ini b/apps/cic-eth/config/docker/database.ini new file mode 100644 index 0000000..2b29289 --- /dev/null +++ b/apps/cic-eth/config/docker/database.ini @@ -0,0 +1,9 @@ +[database] +NAME=cic_eth +USER=postgres +PASSWORD=tralala +HOST=localhost +PORT=63432 +ENGINE=postgresql +DRIVER=psycopg2 +DEBUG=1 diff --git a/apps/cic-eth/config/docker/dispatcer.ini b/apps/cic-eth/config/docker/dispatcer.ini new file mode 100644 index 0000000..85dea83 --- /dev/null +++ b/apps/cic-eth/config/docker/dispatcer.ini @@ -0,0 +1,2 @@ +[dispatcher] +loop_interval = 0.9 diff --git a/apps/cic-eth/config/docker/eth.ini b/apps/cic-eth/config/docker/eth.ini new file mode 100644 index 0000000..d162a5e --- /dev/null +++ b/apps/cic-eth/config/docker/eth.ini @@ -0,0 +1,8 @@ +[eth] +#ws_provider = ws://localhost:8546 +#ttp_provider = http://localhost:8545 +provider = http://localhost:63545 +gas_provider_address = +#chain_id = +abi_dir = /home/lash/src/ext/cic/grassrootseconomics/cic-contracts/abis +account_accounts_index_writer = diff --git a/apps/cic-eth/config/docker/redis.ini b/apps/cic-eth/config/docker/redis.ini new file mode 100644 index 0000000..ea32137 --- /dev/null +++ b/apps/cic-eth/config/docker/redis.ini @@ -0,0 +1,4 @@ +[redis] +host = localhost +port = 63379 +db = 0 diff --git a/apps/cic-eth/config/docker/signer.ini b/apps/cic-eth/config/docker/signer.ini new file mode 100644 index 0000000..69df88d --- /dev/null +++ b/apps/cic-eth/config/docker/signer.ini @@ -0,0 +1,5 @@ +[signer] +socket_path = /tmp/crypto-dev-signer/jsonrpc.ipc +secret = deedbeef +database_name = signer_test +dev_keys_path = diff --git a/apps/cic-eth/config/docker/ssl.ini b/apps/cic-eth/config/docker/ssl.ini new file mode 100644 index 0000000..bd49472 --- /dev/null +++ b/apps/cic-eth/config/docker/ssl.ini @@ -0,0 +1,6 @@ +[SSL] +enable_client = false +cert_file = +key_file = +password = +ca_file = diff --git a/apps/cic-eth/config/docker/syncer.ini b/apps/cic-eth/config/docker/syncer.ini new file mode 100644 index 0000000..9723674 --- /dev/null +++ b/apps/cic-eth/config/docker/syncer.ini @@ -0,0 +1,2 @@ +[SYNCER] +loop_interval = 1 diff --git a/apps/cic-eth/config/docker/tasks.ini b/apps/cic-eth/config/docker/tasks.ini new file mode 100644 index 0000000..732d797 --- /dev/null +++ b/apps/cic-eth/config/docker/tasks.ini @@ -0,0 +1,3 @@ +[tasks] +transfer_callbacks = taskcall:cic_eth.callbacks.noop.noop +trace_queue_status = 1 diff --git a/apps/cic-eth/requirements.txt b/apps/cic-eth/requirements.txt index 5962543..4d9dc2e 100644 --- a/apps/cic-eth/requirements.txt +++ b/apps/cic-eth/requirements.txt @@ -2,13 +2,13 @@ web3==5.12.2 celery==4.4.7 crypto-dev-signer~=0.4.13rc2 confini~=0.3.6b1 -cic-registry~=0.5.3a18 +cic-registry~=0.5.3a20 cic-bancor~=0.0.6 redis==3.5.3 alembic==1.4.2 websockets==8.1 requests~=2.24.0 -eth_accounts_index~=0.0.10a7 +eth_accounts_index~=0.0.10a10 erc20-approval-escrow~=0.3.0a5 erc20-single-shot-faucet~=0.2.0a6 rlp==2.0.1 @@ -18,5 +18,5 @@ eth-gas-proxy==0.0.1a4 websocket-client==0.57.0 moolb~=0.1.1b2 eth-address-index~=0.1.0a8 -chainlib~=0.0.1a12 +chainlib~=0.0.1a16 hexathon~=0.0.1a3 diff --git a/apps/cic-meta/CHANGELOG b/apps/cic-meta/CHANGELOG index 7db215c..1181250 100644 --- a/apps/cic-meta/CHANGELOG +++ b/apps/cic-meta/CHANGELOG @@ -1,3 +1,6 @@ +* 0.0.7-pending + - Add immutable content + - Add db lock on server * 0.0.6 - Add server build * 0.0.5 diff --git a/apps/cic-meta/package.json b/apps/cic-meta/package.json index 70bed03..28475bd 100644 --- a/apps/cic-meta/package.json +++ b/apps/cic-meta/package.json @@ -1,18 +1,16 @@ { "name": "cic-client-meta", - "version": "0.0.6", + "version": "0.0.7-alpha.2", "description": "Signed CRDT metadata graphs for the CIC network", "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { "test": "mocha -r node_modules/node-localstorage/register -r ts-node/register tests/*.ts", - "build": "node_modules/typescript/bin/tsc -d --outDir dist", + "build": "node_modules/typescript/bin/tsc -d --outDir dist && npm run build-server", "build-server": "tsc -d --outDir dist-server scripts/server/*.ts", "pack": "node_modules/typescript/bin/tsc -d --outDir dist && webpack", - "clean": "rm -rf dist" - }, - "bin": { - "cic-meta-server": "./dist-server/scripts/server/server.js" + "clean": "rm -rf dist", + "prepare": "npm run build && npm run build-server" }, "dependencies": { "@ethereumjs/tx": "^3.0.0-beta.1", diff --git a/apps/cic-meta/scripts/server/server.ts b/apps/cic-meta/scripts/server/server.ts index ed4faaf..5840f0f 100755 --- a/apps/cic-meta/scripts/server/server.ts +++ b/apps/cic-meta/scripts/server/server.ts @@ -137,6 +137,7 @@ async function processRequest(req, res) { console.debug('mode', mod); let content = ''; let contentType = 'application/json'; + console.debug('handling data', data); let r:any = undefined; try { switch (mod) { @@ -192,14 +193,16 @@ async function processRequest(req, res) { } if (content === undefined) { + console.error('empty onctent', data); res.writeHead(400, {"Content-Type": "text/plain"}); res.end(); return; } + const responseContentLength = (new TextEncoder().encode(content)).length; res.writeHead(200, { "Content-Type": contentType, - "Content-Length": content.length, + "Content-Length": responseContentLength, }); res.write(content); res.end(); diff --git a/apps/cic-meta/src/index.ts b/apps/cic-meta/src/index.ts index d892711..4ab9250 100644 --- a/apps/cic-meta/src/index.ts +++ b/apps/cic-meta/src/index.ts @@ -2,3 +2,4 @@ export { PGPSigner, PGPKeyStore } from './auth'; export { Envelope, Syncable } from './sync'; export { User } from './assets/user'; export { Phone } from './assets/phone'; +export { Config } from './config'; diff --git a/apps/contract-migration/dev/balance.py b/apps/contract-migration/dev/balance.py deleted file mode 100644 index 4fa6ba5..0000000 --- a/apps/contract-migration/dev/balance.py +++ /dev/null @@ -1,58 +0,0 @@ -#!python3 - -"""Gas transfer script - -.. moduleauthor:: Louis Holbrook -.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 - -""" - -# SPDX-License-Identifier: GPL-3.0-or-later - -# standard imports -import os -import json -import argparse -import logging - -# third-party imports -import web3 - -logging.basicConfig(level=logging.WARNING) -logg = logging.getLogger() - -logging.getLogger('web3').setLevel(logging.WARNING) -logging.getLogger('urllib3').setLevel(logging.WARNING) - -default_abi_dir = os.environ.get('ETH_ABI_DIR', '/usr/share/local/cic/solidity/abi') -default_eth_provider = os.environ.get('ETH_PROVIDER', 'http://localhost:8545') - -argparser = argparse.ArgumentParser() -argparser.add_argument('-p', '--provider', dest='p', default=default_eth_provider, type=str, help='Web3 provider url (http only)') -argparser.add_argument('-t', '--token-address', dest='t', type=str, help='Token address. If not set, will return gas balance') -argparser.add_argument('--abi-dir', dest='abi_dir', type=str, default=default_abi_dir, help='Directory containing bytecode and abi (default {})'.format(default_abi_dir)) -argparser.add_argument('-v', action='store_true', help='Be verbose') -argparser.add_argument('account', type=str, help='Account address') -args = argparser.parse_args() - - -if args.v: - logg.setLevel(logging.DEBUG) - -def main(): - w3 = web3.Web3(web3.Web3.HTTPProvider(args.p)) - - balance = None - if args.t != None: - f = open(os.path.join(args.abi_dir, 'ERC20.json')) - abi = json.load(f) - f.close() - c = w3.eth.contract(abi=abi, address=args.t) - balance = c.functions.balanceOf(args.account).call() - else: - balance =w3.eth.getBalance(args.account) - - print(balance) - -if __name__ == '__main__': - main() diff --git a/apps/contract-migration/dev/create.py b/apps/contract-migration/dev/create.py deleted file mode 100644 index 11851ce..0000000 --- a/apps/contract-migration/dev/create.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/python -import sys -import os -import logging - -import celery -from cic_eth.api import Api -import confini -import argparse - -logging.basicConfig(level=logging.WARNING) -logg = logging.getLogger('create_account_script') -logging.getLogger('confini').setLevel(logging.WARNING) -logging.getLogger('gnupg').setLevel(logging.WARNING) - -config_dir = os.environ.get('CONFINI_DIR', '/usr/local/etc/cic') - -argparser = argparse.ArgumentParser() -argparser.add_argument('--no-register', dest='no_register', action='store_true', help='Do not register new account in on-chain accounts index') -argparser.add_argument('-v', action='store_true', help='Be verbose') -argparser.add_argument('-vv', action='store_true', help='Be more verbose') -args = argparser.parse_args() - -if args.vv: - logg.setLevel(logging.DEBUG) -if args.v: - logg.setLevel(logging.INFO) - -config = confini.Config(config_dir, os.environ.get('CONFINI_ENV_PREFIX')) -config.process() - -celery_app = celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=config.get('CELERY_RESULT_URL')) - -api = Api(config.get('CIC_CHAIN_SPEC')) - -registration_account = None -#t = api.create_account(registration_account=registration_account) -if len(sys.argv) > 1: - registration_account = config.get('DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER', None) - -logg.debug('accounts index writer NOT USED {}'.format(registration_account)) - -register = not args.no_register -logg.debug('register {}'.format(register)) -t = api.create_account(register=register) - -print(t.get()) diff --git a/apps/contract-migration/dev/decode.py b/apps/contract-migration/dev/decode.py deleted file mode 100644 index 58b7766..0000000 --- a/apps/contract-migration/dev/decode.py +++ /dev/null @@ -1,48 +0,0 @@ -#!python3 - -"""Decode raw transaction - -.. moduleauthor:: Louis Holbrook -.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 - -""" - -# SPDX-License-Identifier: GPL-3.0-or-later - -# standard imports -import os -import json -import argparse -import logging - -# third-party imports -from cic_eth.eth.util import unpack_signed_raw_tx - -logging.basicConfig(level=logging.WARNING) -logg = logging.getLogger() - -default_abi_dir = os.environ.get('ETH_ABI_DIR', '/usr/share/local/cic/solidity/abi') -default_eth_provider = os.environ.get('ETH_PROVIDER', 'http://localhost:8545') - -argparser = argparse.ArgumentParser() -argparser.add_argument('-v', action='store_true', help='Be verbose') -argparser.add_argument('-i', '--chain-id', dest='i', type=int, help='Numeric network id') -argparser.add_argument('tx', type=str, help='hex-encoded signed raw transaction') -args = argparser.parse_args() - - -if args.v: - logg.setLevel(logging.DEBUG) - -def main(): - tx_raw = args.tx - if tx_raw[:2] == '0x': - tx_raw = tx_raw[2:] - tx_raw_bytes = bytes.fromhex(tx_raw) - tx = unpack_signed_raw_tx(tx_raw_bytes, args.i) - for k in tx.keys(): - print('{}: {}'.format(k, tx[k])) - - -if __name__ == '__main__': - main() diff --git a/apps/contract-migration/dev/env.sh b/apps/contract-migration/dev/env.sh deleted file mode 100644 index 55fe450..0000000 --- a/apps/contract-migration/dev/env.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -cic_data_dir=${CIC_DATA_DIR:-/tmp/cic} -t=${1:-$(mktemp)} -prefix='' -if [ ! -z $2 ]; then - prefix="${2}_" -fi - -echo "#!/bin/bash" > $t -echo "set +a" >> $t -cat $cic_data_dir/.env | sed -e "s/^\([A-Z]\)/export ${prefix}\1/g" >> $t - -#if [ -f $cic_data_dir/.env ]; then -#cat $cic_data_dir/.env | sed -e "s/^\([A-Z]\)/export ${prefix}\1/g" >> $t -#fi -echo "export CONFINI_DIR=$(dirname $(realpath .))/config_template" >> $t -source $t -echo "export CELERY_BROKER_URL=redis://localhost:${HTTP_PORT_REDIS}" >> $t -echo "export CELERY_RESULT_URL=redis://localhost:${HTTP_PORT_REDIS}" >> $t -echo "export ETH_PROVIDER=http://localhost:${HTTP_PORT_ETH}" >> $t -echo "export META_PROVIDER=http://localhost:${HTTP_PORT_CIC_META}" >> $t -echo "set -a" >> $t -echo $t diff --git a/apps/contract-migration/dev/gas.py b/apps/contract-migration/dev/gas.py deleted file mode 100644 index 42c5cc4..0000000 --- a/apps/contract-migration/dev/gas.py +++ /dev/null @@ -1,105 +0,0 @@ -#!python3 - -"""Gas transfer script - -.. moduleauthor:: Louis Holbrook -.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 - -""" - -# SPDX-License-Identifier: GPL-3.0-or-later - -# standard imports -import os -import json -import argparse -import logging - -# third-party imports -import web3 -from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer -from crypto_dev_signer.keystore import DictKeystore -from crypto_dev_signer.eth.helper import EthTxExecutor - -logging.basicConfig(level=logging.WARNING) -logg = logging.getLogger() - -logging.getLogger('web3').setLevel(logging.WARNING) -logging.getLogger('urllib3').setLevel(logging.WARNING) - -default_abi_dir = '/usr/share/local/cic/solidity/abi' -argparser = argparse.ArgumentParser() -argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)') -argparser.add_argument('-w', action='store_true', help='Wait for the last transaction to be confirmed') -argparser.add_argument('-ww', action='store_true', help='Wait for every transaction to be confirmed') -argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='Ethereum:1', help='Chain specification string') -argparser.add_argument('-a', '--signer-address', dest='a', type=str, help='Signing address') -argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing') -argparser.add_argument('-v', action='store_true', help='Be verbose') -argparser.add_argument('-vv', action='store_true', help='Be more verbose') -argparser.add_argument('recipient', type=str, help='Ethereum address of recipient') -argparser.add_argument('amount', type=int, help='Amount of tokens to mint and gift') -args = argparser.parse_args() - - -if args.vv: - logg.setLevel(logging.DEBUG) -elif args.v: - logg.setLevel(logging.INFO) - -block_last = args.w -block_all = args.ww - -w3 = web3.Web3(web3.Web3.HTTPProvider(args.p)) - -signer_address = None -keystore = DictKeystore() -if args.y != None: - logg.debug('loading keystore file {}'.format(args.y)) - signer_address = keystore.import_keystore_file(args.y) - logg.debug('now have key for signer address {}'.format(signer_address)) -signer = EIP155Signer(keystore) - -chain_pair = args.i.split(':') -chain_id = int(chain_pair[1]) - -helper = EthTxExecutor( - w3, - signer_address, - signer, - chain_id, - block=args.ww, - ) - - -def build_gas_transaction(recipient, value): - def builder(tx): - tx['to'] = recipient - tx['value'] = value - tx['data'] = '0x' - return tx - return builder - - -def main(): - recipient = args.recipient - value = args.amount - - logg.debug('sender {} balance before: {}'.format(signer_address, w3.eth.getBalance(signer_address))) - logg.debug('recipient {} balance before: {}'.format(recipient, w3.eth.getBalance(recipient))) - (tx_hash, rcpt) = helper.sign_and_send( - [ - build_gas_transaction(recipient, value), - ], - ) - logg.debug('sender {} balance after: {}'.format(signer_address, w3.eth.getBalance(signer_address))) - logg.debug('recipient {} balance after: {}'.format(recipient, w3.eth.getBalance(recipient))) - - if block_last: - helper.wait_for() - - print(tx_hash) - - -if __name__ == '__main__': - main() diff --git a/apps/contract-migration/dev/js/register_users.js b/apps/contract-migration/dev/js/register_users.js deleted file mode 100644 index 60b0f3a..0000000 --- a/apps/contract-migration/dev/js/register_users.js +++ /dev/null @@ -1,101 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const cic = require('cic-client-meta'); -const http = require('http'); -const confini = require('confini'); - -console.debug('sorry this script doesnt read cli flags, set all in env vars'); - -let config_data_dir = process.env.CONFINI_DIR; -if (config_data_dir === undefined) { - config_data_dir = '/usr/local/etc/cic'; -} -const config = new confini.Config(config_data_dir, process.env.CONFINI_ENV_PREFIX); -config.process(); -Object.keys(config.store).forEach((k) => { - console.debug(k, config.get(k)); -}); - -// flatten file list from directories recursively -// cheekily though gratefully stolen from https://coderrocketfuel.com/article/recursively-list-all-the-files-in-a-directory-using-node-js -const getAllFiles = function(dirPath, arrayOfFiles) { - files = fs.readdirSync(dirPath) - - arrayOfFiles = arrayOfFiles || [] - - files.forEach(function(file) { - if (fs.statSync(dirPath + "/" + file).isDirectory()) { - arrayOfFiles = getAllFiles(dirPath + "/" + file, arrayOfFiles) - } else { - arrayOfFiles.push(path.join(dirPath, "/", file)) - } - }) - - return arrayOfFiles -} - -async function sendit(uid, envelope) { - const d = envelope.toJSON(); - - const opts = { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - 'Content-Length': d.length, - 'X-CIC-AUTOMERGE': 'client', - - }, - }; - let url = config.get('META_PROVIDER'); //['archiveUrl']; - url = url.replace(new RegExp('^(.+://[^/]+)/*$'), '$1/'); - const req = http.request(url + uid, opts, (res) => { - res.on('data', process.stdout.write); - res.on('end', () => { - console.log('result', res.statusCode, res.headers); - }); - }); - - req.write(d); - req.end(); -} - -function doit(keystore) { - dataDir = 'data'; - if (process.argv.length > 2) { - dataDir = process.argv[2]; - } - console.log('argv', process.argv); - console.log('datadir', path.join(dataDir, 'person')); - getAllFiles(path.join(dataDir, 'person')).forEach((filename) => { - console.debug('person file', filename); - const signer = new cic.PGPSigner(keystore); - const parts = filename.split('.'); - const uid = path.basename(parts[0]); - - const d = fs.readFileSync(filename, 'utf-8'); - const o = JSON.parse(d); - - const s = new cic.Syncable(uid, o); - console.log(s); - s.setSigner(signer); - s.onwrap = (env) => { - console.log('env', env); - //console.log('sign', s.m.signature.digest); - sendit(uid, env); - }; - s.sign(); - }); -} - -pk = fs.readFileSync(path.join(config.get('PGP_EXPORTS_DIR'), config.get('PGP_PRIVATEKEY_FILE'))); -pubk = fs.readFileSync(path.join(config.get('PGP_EXPORTS_DIR'), config.get('DEV_PGP_PUBLICKEYS_ACTIVE_FILE'))); - -new cic.PGPKeyStore( - process.env['PGP_PASSPHRASE'], - pk, - pubk, - undefined, - undefined, - doit, -); - diff --git a/apps/contract-migration/dev/keys.sh b/apps/contract-migration/dev/keys.sh deleted file mode 100644 index 6424258..0000000 --- a/apps/contract-migration/dev/keys.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -mkdir -vp .tmp -echo -n '' > .tmp/.env_accounts -account_labels=( - DEV_ETH_ACCOUNT_BANCOR_DEPLOYER - DEV_ETH_ACCOUNT_GAS_PROVIDER - DEV_ETH_ACCOUNT_RESERVE_OWNER - DEV_ETH_ACCOUNT_RESERVE_MINTER - DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_OWNER - DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER - DEV_ETH_ACCOUNT_SARAFU_OWNER - DEV_ETH_ACCOUNT_SARAFU_GIFTER - DEV_ETH_ACCOUNT_APPROVAL_ESCROW_OWNER - DEV_ETH_ACCOUNT_SINGLE_SHOT_FAUCET_OWNER -) -bip39gen -n ${#account_labels[@]} "$DEV_MNEMONIC" -i=0 -for a in `bip39gen -n ${#account_labels[@]} "$DEV_MNEMONIC" | jq -r .address[]`; do - exportline=${account_labels[$i]}=$a - export $exportline - echo $exportline >> .tmp/.env_accounts - echo exportline $exportline - i=$(($i+1)) -done - diff --git a/apps/contract-migration/dev/python/scripts/setup.py b/apps/contract-migration/dev/python/scripts/setup.py deleted file mode 100644 index bd1da75..0000000 --- a/apps/contract-migration/dev/python/scripts/setup.py +++ /dev/null @@ -1,4 +0,0 @@ -from setuptools import setup - -setup( - ) diff --git a/apps/contract-migration/dev/python/scripts/tx_driver.py b/apps/contract-migration/dev/python/scripts/tx_driver.py deleted file mode 100644 index c2a79ae..0000000 --- a/apps/contract-migration/dev/python/scripts/tx_driver.py +++ /dev/null @@ -1,150 +0,0 @@ -# standard imports -import os -import logging -import argparse -import re -import json -import signal -import random -import time - -# third-party imports -import confini -import web3 -from cic_registry.chain import ChainSpec -from cic_registry.chain import ChainRegistry -from cic_registry import CICRegistry -from eth_token_index import TokenUniqueSymbolIndex as TokenIndex -from eth_accounts_index import AccountRegistry - -from cic_eth.api import Api - - -logging.basicConfig(level=logging.WARNING) -logg = logging.getLogger() -logging.getLogger('websockets.protocol').setLevel(logging.CRITICAL) -logging.getLogger('web3.RequestManager').setLevel(logging.CRITICAL) -logging.getLogger('web3.providers.WebsocketProvider').setLevel(logging.CRITICAL) -logging.getLogger('web3.providers.HTTPProvider').setLevel(logging.CRITICAL) - -default_data_dir = '/usr/local/share/cic/solidity/abi' - -argparser = argparse.ArgumentParser() -argparser.add_argument('-c', type=str, default='./config', help='config file') -argparser.add_argument('-i', '--chain-spec', dest='i', type=str, help='chain spec') -argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration') -argparser.add_argument('--abi-dir', dest='abi_dir', type=str, default=default_data_dir, help='Directory containing bytecode and abi (default: {})'.format(default_data_dir)) -argparser.add_argument('-v', action='store_true', help='be verbose') -argparser.add_argument('-vv', action='store_true', help='be more verbose') -argparser.add_argument('--wait-max', dest='wait_max', default=2.0, type=float, help='maximum time in decimal seconds to wait between transactions') -argparser.add_argument('--account-index-address', dest='account_index', type=str, help='Contract address of accounts index') -argparser.add_argument('--token-index-address', dest='token_index', type=str, help='Contract address of token index') -argparser.add_argument('--approval-escrow-address', dest='approval_escrow', type=str, help='Contract address for transfer approvals') -argparser.add_argument('--declarator-address', dest='declarator', type=str, help='Address of declarations contract to perform lookup against') -argparser.add_argument('-a', '--accounts-index-writer', dest='a', type=str, help='Address of account with access to add to accounts index') - -args = argparser.parse_args() - -if args.vv: - logging.getLogger().setLevel(logging.DEBUG) -elif args.v: - logging.getLogger().setLevel(logging.INFO) - -config = confini.Config(args.c, args.env_prefix) -config.process() -args_override = { - 'ETH_ABI_DIR': getattr(args, 'abi_dir'), - 'CIC_CHAIN_SPEC': getattr(args, 'i'), - 'DEV_ETH_ACCOUNTS_INDEX_ADDRESS': getattr(args, 'account_index'), - 'DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER': getattr(args, 'a'), - 'DEV_ETH_ERC20_APPROVAL_ESCROW_ADDRESS': getattr(args, 'approval_escrow'), - 'DEV_ETH_TOKEN_INDEX_ADDRESS': getattr(args, 'token_index'), - } -config.dict_override(args_override, 'cli flag') -config.validate() -config.censor('PASSWORD', 'DATABASE') -config.censor('PASSWORD', 'SSL') -logg.debug('config:\n{}'.format(config)) - -re_websocket = r'^wss?:' -re_http = r'^https?:' -blockchain_provider = None -if re.match(re_websocket, config.get('ETH_PROVIDER')): - blockchain_provider = web3.Web3.WebsocketProvider(config.get('ETH_PROVIDER')) -elif re.match(re_http, config.get('ETH_PROVIDER')): - blockchain_provider = web3.Web3.HTTPProvider(config.get('ETH_PROVIDER')) -w3 = web3.Web3(blockchain_provider) - - -chain_spec = ChainSpec.from_chain_str(config.get('CIC_CHAIN_SPEC')) -CICRegistry.init(w3, config.get('CIC_REGISTRY_ADDRESS'), chain_spec) -CICRegistry.add_path(config.get('ETH_ABI_DIR')) - -chain_registry = ChainRegistry(chain_spec) -CICRegistry.add_chain_registry(chain_registry, True) - -run = True - -def inthandler(name, frame): - logg.warning('got {}, stopping'.format(name)) - global run - run = False - -signal.signal(signal.SIGTERM, inthandler) -signal.signal(signal.SIGINT, inthandler) - -api = Api(str(chain_spec)) - -f = open(os.path.join(config.get('ETH_ABI_DIR'), 'ERC20.json')) -erc20_abi = json.load(f) -f.close() - -def get_tokens(): - tokens = [] - token_index = TokenIndex(w3, config.get('CIC_TOKEN_INDEX_ADDRESS')) - token_count = token_index.count() - for i in range(token_count): - tokens.append(token_index.get_index(i)) - logg.debug('tokens {}'.format(tokens)) - return tokens - -def get_addresses(): - address_index = AccountRegistry(w3, config.get('CIC_ACCOUNTS_INDEX_ADDRESS')) - address_count = address_index.count() - addresses = address_index.last(address_count-1) - logg.debug('addresses {} {}'.format(address_count, addresses)) - return addresses - -random.seed() - -while run: - n = random.randint(0, 255) - - # some of the time do other things than transfers - if n & 0xf8 == 0xf8: - t = api.create_account() - logg.info('create account {}'.format(t)) - - else: - tokens = get_tokens() - addresses = get_addresses() - address_pair = random.choices(addresses, k=2) - sender = address_pair[0] - recipient = address_pair[1] - token = random.choice(tokens) - - c = w3.eth.contract(abi=erc20_abi, address=token) - sender_balance = c.functions.balanceOf(sender).call() - token_symbol = c.functions.symbol().call() - amount = int(random.random() * (sender_balance / 2)) - - n = random.randint(0, 255) - - if n & 0xc0 == 0xc0: - t = api.transfer_request(sender, recipient, config.get('CIC_APPROVAL_ESCROW_ADDRESS'), amount, token_symbol) - logg.info('transfer REQUEST {} {} from {} to {} => {}'.format(amount, token_symbol, sender, recipient, t)) - else: - t = api.transfer(sender, recipient, amount, token_symbol) - logg.info('transfer {} {} from {} to {} => {}'.format(amount, token_symbol, sender, recipient, t)) - - time.sleep(random.random() * args.wait_max) diff --git a/apps/contract-migration/dev/python/scripts/tx_seed.py b/apps/contract-migration/dev/python/scripts/tx_seed.py deleted file mode 100644 index aacb9fa..0000000 --- a/apps/contract-migration/dev/python/scripts/tx_seed.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/python - -import csv -import logging -import argparse -import os -import re - -import web3 -import confini - -from cic_registry import CICRegistry -from cic_eth.api import Api - -logging.basicConfig(level=logging.INFO) -logg = logging.getLogger() - -confini_default_dir = os.environ.get('CONFINI_DIR', '/usr/local/etc/cic') - - -argparser = argparse.ArgumentParser() -argparser.add_argument('-c', type=str, default=confini_default_dir, help='config data dir') -argparser.add_argument('-a', '--token-gifter-address', dest='a', type=str, help='Token gifter address') -argparser.add_argument('-i', '--chain-spec', dest='i', type=str, help='chain spec') -argparser.add_argument('-s', '--token-symbol', dest='s', type=str, help='Token symbol') -argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration') -argparser.add_argument('-v', action='store_true', help='be verbose') -argparser.add_argument('-vv', action='store_true', help='be more verbose') -args = argparser.parse_args() - -if args.vv: - logging.getLogger().setLevel(logging.DEBUG) -elif args.v: - logging.getLogger().setLevel(logging.INFO) - -config = confini.Config(args.c, args.env_prefix) -config.process() -args_override = { - 'CIC_CHAIN_SPEC': getattr(args, 'i'), - } -cic_eth_api = Api(config.get('CIC_CHAIN_SPEC')) - -token_gifter_address = args.a - -if __name__ == '__main__': - f = open('./data/amounts', 'r') - cr = csv.reader(f) - for r in cr: - logg.info('sending {} {} from {} to {}'.format(r[1], args.s, token_gifter_address, r[0])) - cic_eth_api.transfer(token_gifter_address, r[0], int(r[1]), args.s) - f.close() diff --git a/apps/contract-migration/dev/python/scripts/users.py b/apps/contract-migration/dev/python/scripts/users.py deleted file mode 100644 index 035806b..0000000 --- a/apps/contract-migration/dev/python/scripts/users.py +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/python - -import json -import time -import datetime -import random -import logging -import os -import base64 -import hashlib -import sys - -import vobject - -import celery -import web3 -from faker import Faker -import cic_registry -import confini -from cic_eth.api import Api - -logging.basicConfig(level=logging.DEBUG) -logg = logging.getLogger() - -fake = Faker(['sl', 'en_US', 'no', 'de', 'ro']) - -#f = open('cic.conf', 'r') -#config = json.load(f) -#f.close() -# - -config_dir = os.environ.get('CONFINI_DIR', '/usr/local/etc/cic') - -config = confini.Config(config_dir, os.environ.get('CONFINI_ENV_PREFIX')) -config.process() -logg.info('loaded config\n{}'.format(config)) - - -w3s = None -w3s = web3.Web3(web3.Web3.IPCProvider(config.get('SIGNER_SOCKET_PATH'))) -#w3s = web3.Web3(web3.Web3.IPCProvider(config['signer']['provider'])) -#w3 = web3.Web3(web3.Web3.WebsocketProvider(config['eth']['provider'])) - -dt_now = datetime.datetime.utcnow() -dt_then = dt_now - datetime.timedelta(weeks=150) -ts_now = int(dt_now.timestamp()) -ts_then = int(dt_then.timestamp()) - -celery_app = celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=config.get('CELERY_RESULT_URL')) - -api = Api(config.get('CIC_CHAIN_SPEC')) - -gift_max = 10000 -gift_factor = (10**9) - -categories = [ - "food/water", - "fuel/energy", - "education", - "health", - "shop", - "environment", - "transport", - "farming/labor", - "savingsgroup", - ] - -phone_idx = [] - - -def genPhoneIndex(phone): - h = hashlib.new('sha256') - h.update(phone.encode('utf-8')) - h.update(b'cic.msisdn') - return h.digest().hex() - - -def genId(addr, typ): - h = hashlib.new('sha256') - h.update(bytes.fromhex(addr[2:])) - h.update(typ.encode('utf-8')) - return h.digest().hex() - - -def genDate(): - - logg.info(ts_then) - ts = random.randint(ts_then, ts_now) - return datetime.datetime.fromtimestamp(ts).timestamp() - - -def genPhone(): - return fake.msisdn() - - -def genPersonal(phone): - fn = fake.first_name() - ln = fake.last_name() - e = fake.email() - - v = vobject.vCard() - first_name = fake.first_name() - last_name = fake.last_name() - v.add('n') - v.n.value = vobject.vcard.Name(family=last_name, given=first_name) - v.add('fn') - v.fn.value = '{} {}'.format(first_name, last_name) - v.add('tel') - v.tel.typ_param = 'CELL' - v.tel.value = phone - v.add('email') - v.email.value = fake.email() - - vcard_serialized = v.serialize() - vcard_base64 = base64.b64encode(vcard_serialized.encode('utf-8')) - - return vcard_base64.decode('utf-8') - - -def genCats(): - i = random.randint(0, 3) - return random.choices(categories, k=i) - - -def genAmount(): - return random.randint(0, gift_max) * gift_factor - - -def gen(): - old_blockchain_address = '0x' + os.urandom(20).hex() - accounts_index_account = config.get('DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER') - if not accounts_index_account: - accounts_index_account = None - logg.debug('accounts indexwriter {}'.format(accounts_index_account)) - t = api.create_account() - new_blockchain_address = t.get() - gender = random.choice(['female', 'male', 'other']) - phone = genPhone() - v = genPersonal(phone) - o = { - 'date_registered': genDate(), - 'vcard': v, - 'gender': gender, - 'key': { - 'ethereum': [ - old_blockchain_address, - new_blockchain_address, - ], - }, - 'location': { - 'latitude': str(fake.latitude()), - 'longitude': str(fake.longitude()), - 'external': { # add osm lookup - } - }, - 'selling': genCats(), - } - uid = genId(new_blockchain_address, 'cic.person') - - #logg.info('gifting {} to {}'.format(amount, new_blockchain_address)) - - return (uid, phone, o) - - -def prepareLocalFilePath(datadir, address): - parts = [ - address[:2], - address[2:4], - ] - dirs = '{}/{}/{}'.format( - datadir, - parts[0], - parts[1], - ) - os.makedirs(dirs, exist_ok=True) - return dirs - - -if __name__ == '__main__': - - os.makedirs('data/person', exist_ok=True) - os.makedirs('data/phone', exist_ok=True) - - fa = open('./data/amounts', 'w') - fb = open('./data/addresses', 'w') - - #for i in range(10): - for i in range(int(sys.argv[1])): - - (uid, phone, o) = gen() - eth = o['key']['ethereum'][1] - - print(o) - - d = prepareLocalFilePath('./data/person', uid) - f = open('{}/{}'.format(d, uid), 'w') - json.dump(o, f) - f.close() - - pidx = genPhoneIndex(phone) - d = prepareLocalFilePath('./data/phone', uid) - f = open('{}/{}'.format(d, pidx), 'w') - f.write(eth) - f.close() - - amount = genAmount() - fa.write('{},{}\n'.format(eth,amount)) - fb.write('{}\n'.format(eth)) - logg.debug('pidx {}, uid {}, eth {}, amount {}'.format(pidx, uid, eth, amount)) - - fb.close() - fa.close() diff --git a/apps/contract-migration/dev/python/setup.cfg b/apps/contract-migration/dev/python/setup.cfg deleted file mode 100644 index a62eb41..0000000 --- a/apps/contract-migration/dev/python/setup.cfg +++ /dev/null @@ -1,40 +0,0 @@ -[metadata] -name = cic-dev-fake -version = 0.0.1 -description = Fake data generator tools -author = Louis Holbrook -author_email = dev@holbrook.no -url = https://gitlab.com/nolash/simple-multisig -keywords = - ethereum -classifiers = - Programming Language :: Python :: 3 - Operating System :: OS Independent - Development Status :: 3 - Alpha - Environment :: No Input/Output (Daemon) - Intended Audience :: Developers - License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) - Topic :: Internet - #Topic :: Blockchain :: EVM -license = GPL3 -licence_files = - LICENSE - -[options] -python_requires = >= 3.6 -install_requires = - web3==5.12.2 - vobject==0.9.6.1 - faker==4.17.1 -tests_require = - eth-tester==0.5.0b2 - py-evm==0.3.0a20 -scripts = - scripts/users.py - scripts/tx_generator.py - scripts/tx_seed.py - -[options.extras_require] -testing = - eth-tester==0.5.0b2 - py-evm==0.3.0a20 diff --git a/apps/contract-migration/dev/python/setup.py b/apps/contract-migration/dev/python/setup.py deleted file mode 100644 index bd1da75..0000000 --- a/apps/contract-migration/dev/python/setup.py +++ /dev/null @@ -1,4 +0,0 @@ -from setuptools import setup - -setup( - ) diff --git a/apps/contract-migration/dev/requirements.txt b/apps/contract-migration/dev/requirements.txt deleted file mode 100644 index 72c938f..0000000 --- a/apps/contract-migration/dev/requirements.txt +++ /dev/null @@ -1,10 +0,0 @@ -cryptocurrency-cli-tools~=0.0.4 -giftable-erc20-token~=0.0.7b1 -eth-accounts-index~=0.0.10a2 -erc20-single-shot-faucet~=0.2.0a1 -erc20-approval-escrow~=0.3.0a1 -cic-eth==0.10.0a5 -vobject==0.9.6.1 -faker==4.17.1 -eth-address-index~=0.1.0a1 -crypto-dev-signer~=0.4.13b9 diff --git a/apps/contract-migration/dev/sarafu_declaration.json b/apps/contract-migration/dev/sarafu_declaration.json deleted file mode 100644 index ff0745d..0000000 --- a/apps/contract-migration/dev/sarafu_declaration.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "objectType": "ERC20", - "content": { - { - "tokenlists": { - "logoURI": "data:image/svg+xml;base64,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", - "tags": [ - "cic", - "bancor" - ] - }, - "logo": { - "sha256": "6d36122bf05c4ebe483a1be281b5b524e4d2d6df4607fe31e80ccdc430ea981d", - "bzz": "7fa223e40ebdc1691253775abdf96d2289e6fc8ef8f0775e318071744b691e87" - } - } - } -} diff --git a/apps/contract-migration/dev/sarafu_logo.png b/apps/contract-migration/dev/sarafu_logo.png deleted file mode 100644 index 5b9c746b44f94cc2a6ee711bf7fef1b32a420a18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7214 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 diff --git a/apps/contract-migration/dev/setup.sh b/apps/contract-migration/dev/setup.sh deleted file mode 100644 index 2c65a8a..0000000 --- a/apps/contract-migration/dev/setup.sh +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/bash - -# Debug flag -#debug='-v' -keystore_file=../keystore/UTC--2021-01-08T17-18-44.521011372Z--eb3907ecad74a0013c259d5874ae7f22dcbcc95c - -debug='' -abi_dir=${ETH_ABI_DIR:-/usr/local/share/cic/solidity/abi} - -# Determine token amount -token_amount=${DEV_ETH_RESERVE_AMOUNT:0:-1} - -# Determine gas amount -#gas_amount=20000000000000000000 -gas_amount=2000000000000000000 - -export DATABASE_NAME=$DATABASE_NAME_CIC_ETH -export DATABASE_PORT=$HTTP_PORT_POSTGRES -export DATABASE_HOST=localhost - -set -e -set -a - -old_gas_provider=$DEV_ETH_ACCOUNT_GAS_PROVIDER -DEV_ETH_ACCOUNT_GAS_GIFTER=`python ./create.py --no-register` -echo DEV_ETH_ACCOUNT_GAS_GIFTER=$DEV_ETH_ACCOUNT_GAS_GIFTER -export DEV_ETH_ACCOUNT_GAS_GIFTER=$DEV_ETH_ACCOUNT_GAS_GIFTER -cic-eth-tag GAS_GIFTER $DEV_ETH_ACCOUNT_GAS_GIFTER - -DEV_ETH_ACCOUNT_SARAFU_GIFTER=`python ./create.py --no-register` -echo DEV_ETH_ACCOUNT_SARAFU_GIFTER=$DEV_ETH_ACCOUNT_SARAFU_GIFTER -export DEV_ETH_ACCOUNT_SARAFU_GIFTER=$DEV_ETH_ACCOUNT_SARAFU_GIFTER -cic-eth-tag SARAFU_GIFTER $DEV_ETH_ACCOUNT_SARAFU_GIFTER - - -DEV_ETH_ACCOUNT_APPROVAL_ESCROW_OWNER=`python ./create.py --no-register` -echo DEV_ETH_ACCOUNT_APPROVAL_ESCROW_OWNER=$DEV_ETH_ACCOUNT_APPROVAL_ESCROW_OWNER -export DEV_ETH_ACCOUNT_APPROVAL_ESCROW_OWNER=$DEV_ETH_ACCOUNT_APPROVAL_ESCROW_OWNER -cic-eth-tag TRANSFER_APPROVAL_OWNER $DEV_ETH_ACCOUNT_APPROVAL_ESCROW_OWNER - - -DEV_ETH_ACCOUNT_SINGLE_SHOT_FAUCET_OWNER=`python ./create.py --no-register` -echo DEV_ETH_ACCOUNT_SINGLE_SHOT_FAUCET_OWNER=$DEV_ETH_ACCOUNT_SINGLE_SHOT_FAUCET_OWNER -export DEV_ETH_ACCOUNT_SINGLE_SHOT_FAUCET_OWNER=$DEV_ETH_ACCOUNT_SINGLE_SHOT_FAUCET_OWNER -cic-eth-tag FAUCET_OWNER $DEV_ETH_ACCOUNT_SINGLE_SHOT_FAUCET_OWNER - - -DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER=`python ./create.py --no-register` -echo DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER=$DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER -export DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER=$DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER -cic-eth-tag ACCOUNTS_INDEX_WRITER $DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER - - -# Transfer gas to custodial gas provider adddress -#echo $old_gas_provider ->&2 echo gift gas to gas gifter ->&2 echo "python gas.py -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_ACCOUNT_GAS_GIFTER $gas_amount" ->&2 python gas.py -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_ACCOUNT_GAS_GIFTER $gas_amount - ->&2 echo gift gas to sarafu token owner ->&2 echo "python gas.py -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_ACCOUNT_SARAFU_OWNER $gas_amount" ->&2 python gas.py -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_ACCOUNT_SARAFU_OWNER $gas_amount - ->&2 echo gift gas to account index owner ->&2 echo "python gas.py -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_OWNER $gas_amount" ->&2 python gas.py -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_OWNER $gas_amount - - -# Send reserve to token creator ->&2 giftable-token-gift -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -a $DEV_ETH_RESERVE_ADDRESS --recipient $DEV_ETH_ACCOUNT_SARAFU_OWNER -w $debug $token_amount - - -# Create token -#DEV_ETH_SARAFU_TOKEN_ADDRESS=`cic-bancor-token -p $ETH_PROVIDER -r $CIC_REGISTRY_ADDRESS -z $DEV_ETH_RESERVE_ADDRESS -o $DEV_ETH_ACCOUNT_SARAFU_OWNER -n $DEV_ETH_SARAFU_TOKEN_NAME -s $DEV_ETH_SARAFU_TOKEN_SYMBOL -d $DEV_ETH_SARAFU_TOKEN_DECIMALS -i $CIC_CHAIN_SPEC $debug $token_amount` -DEV_ETH_SARAFU_TOKEN_ADDRESS=$DEV_ETH_RESERVE_ADDRESS -echo DEV_ETH_SARAFU_TOKEN_ADDRESS=$DEV_ETH_SARAFU_TOKEN_ADDRESS -export DEV_ETH_SARAFU_TOKEN_ADDRESS=$DEV_ETH_SARAFU_TOKEN_ADDRESS - - -# Transfer tokens to gifter address ->&2 python transfer.py -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER --token-address $DEV_ETH_SARAFU_TOKEN_ADDRESS --abi-dir $abi_dir -w $debug $DEV_ETH_ACCOUNT_SARAFU_GIFTER ${token_amount:0:-1} - -# Deploy transfer approval contract -CIC_APPROVAL_ESCROW_ADDRESS=`erc20-approval-escrow-deploy -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER --approver $DEV_ETH_ACCOUNT_APPROVAL_ESCROW_OWNER -w $debug` -echo CIC_APPROVAL_ESCROW_ADDRESS=$CIC_APPROVAL_ESCROW_ADDRESS -export CIC_APPROVAL_ESCROW_ADDRESS=$CIC_APPROVAL_ESCROW_ADDRESS - -# Register transfer approval contract ->&2 cic-registry-set -y $keystore_file -r $CIC_REGISTRY_ADDRESS -k TransferApproval -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $CIC_APPROVAL_ESCROW_ADDRESS - -# Deploy one-time token faucet for newly created token -DEV_ETH_SARAFU_FAUCET_ADDRESS=`erc20-single-shot-faucet-deploy -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER --token-address $DEV_ETH_SARAFU_TOKEN_ADDRESS --editor $DEV_ETH_ACCOUNT_SINGLE_SHOT_FAUCET_OWNER --set-amount 1048576 -w $debug` -echo DEV_ETH_SARAFU_FAUCET_ADDRESS=$DEV_ETH_SARAFU_FAUCET_ADDRESS -export DEV_ETH_SARAFU_FAUCET_ADDRESS=$DEV_ETH_SARAFU_FAUCET_ADDRESS - -# Transfer tokens to faucet contract ->&2 python transfer.py -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER --token-address $DEV_ETH_SARAFU_TOKEN_ADDRESS --abi-dir $abi_dir -w $debug $DEV_ETH_SARAFU_FAUCET_ADDRESS ${token_amount:0:-1} - -# Registry faucet entry ->&2 cic-registry-set -y $keystore_file -r $CIC_REGISTRY_ADDRESS -k Faucet -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_SARAFU_FAUCET_ADDRESS - -# Deploy token endorser registry -#DEV_ETH_TOKEN_ENDORSER_ADDRESS=`eth-token-endorser-deploy -p $ETH_PROVIDER -o $DEV_ETH_ACCOUNT_SARAFU_OWNER $debug` -#echo DEV_ETH_TOKEN_ENDORSER_ADDRESS=$DEV_ETH_TOKEN_ENDORSER_ADDRESS -#export DEV_ETH_TOKEN_ENDORSER_ADDRESS=$DEV_ETH_TOKEN_ENDORSER_ADDRESS -#ENDORSEMENT_MSG=`echo -n 'very cool token' | sha256sum | awk '{print $1;}'` -#>&2 eth-token-endorser-add -p $ETH_PROVIDER -a $DEV_ETH_TOKEN_ENDORSER_ADDRESS -t $DEV_ETH_SARAFU_TOKEN_ADDRESS -o $DEV_ETH_ACCOUNT_SARAFU_OWNER $debug $ENDORSEMENT_MSG -CIC_TOKEN_INDEX_ADDRESS=`eth-token-index-deploy -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug` -echo CIC_TOKEN_INDEX_ADDRESS=$CIC_TOKEN_INDEX_ADDRESS -export CIC_TOKEN_INDEX_ADDRESS=$CIC_TOKEN_INDEX_ADDRESS ->&2 eth-token-index-add -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -r $CIC_TOKEN_INDEX_ADDRESS -w $debug $DEV_ETH_SARAFU_TOKEN_ADDRESS - -# Register token registry ->&2 cic-registry-set -y $keystore_file -r $CIC_REGISTRY_ADDRESS -k TokenRegistry -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER $CIC_TOKEN_INDEX_ADDRESS - -# Deploy address declarator registry -declarator_description=0x546869732069732074686520434943206e6574776f726b000000000000000000 -CIC_DECLARATOR_ADDRESS=`eth-address-declarator-deploy -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $declarator_description` -echo CIC_DECLARATOR_ADDRESS=$CIC_DECLARATOR_ADDRESS -export CIC_DECLARATOR_ADDRESS=$CIC_DECLARATOR_ADDRESS -token_description_one=`sha256sum sarafu_declaration.json | awk '{ print $1; }'` -token_description_two=0x54686973206973207468652053617261667520746f6b656e0000000000000000 ->&2 eth-address-declarator-add -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -r $CIC_DECLARATOR_ADDRESS -w $debug $DEV_ETH_SARAFU_TOKEN_ADDRESS $token_description_one ->&2 eth-address-declarator-add -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -r $CIC_DECLARATOR_ADDRESS -w $debug $DEV_ETH_SARAFU_TOKEN_ADDRESS $token_description_two - - -# Register address declarator ->&2 cic-registry-set -y $keystore_file -r $CIC_REGISTRY_ADDRESS -k AddressDeclarator -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER $CIC_DECLARATOR_ADDRESS - -# We're done with the registry at this point, seal it off ->&2 cic-registry-seal -y $keystore_file -i $CIC_CHAIN_SPEC -r $CIC_REGISTRY_ADDRESS -p $ETH_PROVIDER - - -# Add accounts index writer with key from keystore ->&2 eth-accounts-index-add -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -r $CIC_ACCOUNTS_INDEX_ADDRESS --writer $DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER -w $debug - -set +a -set +e diff --git a/apps/contract-migration/dev/tests/create.py b/apps/contract-migration/dev/tests/create.py deleted file mode 100644 index 7b5f020..0000000 --- a/apps/contract-migration/dev/tests/create.py +++ /dev/null @@ -1,31 +0,0 @@ -#!python3 - -# Author: Louis Holbrook 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 -# SPDX-License-Identifier: GPL-3.0-or-later -# File-version: 1 -# Description: Smoke test for cic-eth create account api - -# standard imports -import os -import logging - -# third-party imports -import celery -import confini - -# platform imports -from cic_eth import Api - -script_dir = os.path.dirname(__file__) - -logging.basicConfig(level=logging.DEBUG) -logg = logging.getLogger() - -config_dir = os.environ.get('CONFINI_DIR', '/usr/local/etc/cic/') - -config = confini.Config(config_dir) -config.process() - -a = Api() -t = a.create_account() -logg.debug('create account task uuid {}'.format(t)) diff --git a/apps/contract-migration/dev/transfer.py b/apps/contract-migration/dev/transfer.py deleted file mode 100644 index c8ef8fd..0000000 --- a/apps/contract-migration/dev/transfer.py +++ /dev/null @@ -1,105 +0,0 @@ -#!python3 - -"""Token transfer script - -.. moduleauthor:: Louis Holbrook -.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 - -""" - -# SPDX-License-Identifier: GPL-3.0-or-later - -# standard imports -import os -import json -import argparse -import logging - -# third-party imports -import web3 -from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer -from crypto_dev_signer.keystore import DictKeystore -from crypto_dev_signer.eth.helper import EthTxExecutor - -logging.basicConfig(level=logging.WARNING) -logg = logging.getLogger() - -logging.getLogger('web3').setLevel(logging.WARNING) -logging.getLogger('urllib3').setLevel(logging.WARNING) - -default_abi_dir = '/usr/share/local/cic/solidity/abi' -argparser = argparse.ArgumentParser() -argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)') -argparser.add_argument('-w', action='store_true', help='Wait for the last transaction to be confirmed') -argparser.add_argument('-ww', action='store_true', help='Wait for every transaction to be confirmed') -argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='Ethereum:1', help='Chain specification string') -argparser.add_argument('--token-address', required='True', dest='t', type=str, help='Token address') -argparser.add_argument('-a', '--sender-address', dest='s', type=str, help='Sender account address') -argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing') -argparser.add_argument('--abi-dir', dest='abi_dir', type=str, default=default_abi_dir, help='Directory containing bytecode and abi (default {})'.format(default_abi_dir)) -argparser.add_argument('-v', action='store_true', help='Be verbose') -argparser.add_argument('-vv', action='store_true', help='Be more verbose') -argparser.add_argument('recipient', type=str, help='Recipient account address') -argparser.add_argument('amount', type=int, help='Amount of tokens to mint and gift') -args = argparser.parse_args() - - -if args.vv: - logg.setLevel(logging.DEBUG) -elif args.v: - logg.setLevel(logging.INFO) - -block_last = args.w -block_all = args.ww - -w3 = web3.Web3(web3.Web3.HTTPProvider(args.p)) - -signer_address = None -keystore = DictKeystore() -if args.y != None: - logg.debug('loading keystore file {}'.format(args.y)) - signer_address = keystore.import_keystore_file(args.y) - logg.debug('now have key for signer address {}'.format(signer_address)) -signer = EIP155Signer(keystore) - -chain_pair = args.i.split(':') -chain_id = int(chain_pair[1]) - -helper = EthTxExecutor( - w3, - signer_address, - signer, - chain_id, - block=args.ww, - ) - - -def main(): - # TODO: Add pure ERC20 abi to collection - f = open(os.path.join(args.abi_dir, 'ERC20.json'), 'r') - abi = json.load(f) - f.close() - - c = w3.eth.contract(abi=abi, address=args.t) - - recipient = args.recipient - value = args.amount - - logg.debug('sender {} balance before: {}'.format(signer_address, c.functions.balanceOf(signer_address).call())) - logg.debug('recipient {} balance before: {}'.format(recipient, c.functions.balanceOf(recipient).call())) - (tx_hash, rcpt) = helper.sign_and_send( - [ - c.functions.transfer(recipient, value).buildTransaction, - ], - ) - logg.debug('sender {} balance after: {}'.format(signer_address, c.functions.balanceOf(signer_address).call())) - logg.debug('recipient {} balance after: {}'.format(recipient, c.functions.balanceOf(recipient).call())) - - if block_last: - helper.wait_for() - - print(tx_hash) - - -if __name__ == '__main__': - main() diff --git a/apps/contract-migration/docker/Dockerfile b/apps/contract-migration/docker/Dockerfile index 6dc271d..1b893de 100644 --- a/apps/contract-migration/docker/Dockerfile +++ b/apps/contract-migration/docker/Dockerfile @@ -53,7 +53,7 @@ RUN apt-get update && \ RUN echo installing nodejs tooling -COPY contract-migration/dev/nvm.sh /root/ +COPY contract-migration/nvm.sh /root/ # Install nvm with node and npm # https://stackoverflow.com/questions/25899912/how-to-install-nvm-in-docker @@ -106,7 +106,7 @@ RUN cd cic-bancor/python && \ pip install --extra-index-url $pip_extra_index_url . RUN echo installing common python tooling -ARG cic_python_commit=beecee783ceac2ea0fa711f888ce4c82f1a81490 +ARG cic_python_commit=9bd1d5319aad8791ebf353707eabbb7b3e7ab5d0 ARG cic_python_url=https://gitlab.com/grassrootseconomics/cic-python.git/ RUN echo Install sum of python dependencies across all components && \ git clone --depth 1 $cic_python_url cic-python && \ @@ -120,39 +120,48 @@ ARG cryptocurrency_cli_tools_version=0.0.4 RUN pip install --extra-index-url $pip_extra_index_url cryptocurrency-cli-tools==$cryptocurrency_cli_tools_version RUN echo Install smart contract interface implementations, least frequently changed first -ARG giftable_erc20_token_version=0.0.7b10 +ARG giftable_erc20_token_version=0.0.7b12 RUN pip install --extra-index-url $pip_extra_index_url giftable-erc20-token==$giftable_erc20_token_version -ARG eth_accounts_index_version=0.0.10a6 +ARG eth_accounts_index_version=0.0.10a9 RUN pip install --extra-index-url $pip_extra_index_url eth-accounts-index==$eth_accounts_index_version -ARG erc20_approval_escrow_version=0.3.0a4 -RUN pip install --extra-index-url $pip_extra_index_url erc20-approval-escrow==$erc20_approval_escrow_version +#ARG erc20_approval_escrow_version=0.3.0a4 +#RUN pip install --extra-index-url $pip_extra_index_url erc20-approval-escrow==$erc20_approval_escrow_version +ARG erc20_transfer_authorization_version=0.3.0a9 +RUN pip install --extra-index-url $pip_extra_index_url erc20-transfer-authorization==$erc20_transfer_authorization_version #ARG erc20_single_shot_faucet_version=0.2.0a5 #RUN pip install --extra-index-url $pip_extra_index_url erc20-single-shot-faucet==$erc20_single_shot_faucet_version -ARG sarafu_faucet_version==0.0.1a10 +ARG sarafu_faucet_version=0.0.1a11 RUN pip install --extra-index-url $pip_extra_index_url sarafu-faucet==$sarafu_faucet_version -ARG eth_address_index_version==0.1.0a8 +ARG eth_address_index_version=0.1.0a10 RUN pip install --extra-index-url $pip_extra_index_url eth-address-index==$eth_address_index_version RUN echo Install cic specific python packages -ARG cic_registry_version=0.5.3a18 -RUN pip install --extra-index-url $pip_extra_index_url cic-registry==$cic_registry_version +ARG cic_registry_version=0.5.3a20+build.30d0026c +RUN pip install --extra-index-url $pip_extra_index_url cic-registry==$cic_registry_version RUN echo Install misc helpers -ARG crypto_dev_signer_version==0.4.13rc2 +ARG crypto_dev_signer_version=0.4.13rc2 RUN pip install --extra-index-url $pip_extra_index_url crypto-dev-signer==$crypto_dev_signer_version -ARG eth_gas_proxy_version==0.0.1a4 +ARG eth_gas_proxy_version=0.0.1a4 RUN pip install --extra-index-url $pip_extra_index_url eth-gas-proxy==$eth_gas_proxy_version -ARG cic_contracts_version==0.0.2a2 +ARG cic_contracts_version=0.0.2a2 RUN pip install --extra-index-url $pip_extra_index_url cic-contracts==$cic_contracts_version +ARG chainlib_version=0.0.1a16 +RUN pip install --extra-index-url $pip_extra_index_url chainlib==$chainlib_version + +ARG chainsyncer_version=0.0.1a8 +RUN pip install --extra-index-url $pip_extra_index_url chainsyncer==$chainsyncer_version + + WORKDIR /root COPY contract-migration/testdata/pgp testdata/pgp diff --git a/apps/contract-migration/dev/nvm.sh b/apps/contract-migration/nvm.sh similarity index 100% rename from apps/contract-migration/dev/nvm.sh rename to apps/contract-migration/nvm.sh diff --git a/apps/contract-migration/scripts/README b/apps/contract-migration/scripts/README new file mode 100644 index 0000000..00dbac2 --- /dev/null +++ b/apps/contract-migration/scripts/README @@ -0,0 +1,72 @@ +# DATA GENERATION TOOLS + +This folder contains tools to generate and import test data. + +## DATA CREATION + +Does not need the cluster to run. + +Vanilla: + +`python create_import_users.py [--dir ] ` + +If you want to use the `import_balance.py` script to add to the user's balance from an external address, add: + +`python create_import_users.py --gift-threshold [--dir ] ` + + +## IMPORT + +Make sure the following is running in the cluster: + * eth + * postgres + * redis + * cic-eth-tasker + * cic-eth-dispatcher + * cic-eth-manager-head + + +You will want to run these in sequence: + + +## 1. Metadata + +`node import_meta.js ` + +Monitors a folder for output from the `import_users.py` script, adding the metadata found to the `cic-meta` service. + + +## 2. Balances + +(Only if you used the `--gift-threshold` option above) + +`python -c config -i -r -p --head -y ../keystore/UTC--2021-01-08T17-18-44.521011372Z--eb3907ecad74a0013c259d5874ae7f22dcbcc95c ` + +This will monitor new mined blocks and send balances to the newly created accounts. + + +### 3. Users + +Without any modifications to the cluster and config files: + +`python -c config --redis-host-callback redis ` + +** A note on the The callback**: The script uses a redis callback to retrieve the newly generated custodial address. This is the redis server _from the perspective of the cic-eth component_. + + +## VERIFY + +`python verify.py -c config -i -r -p ` + +Checks + * Private key is in cic-eth keystore + * Address is in accounts index + * Address has balance matching the gift threshold + * Metadata can be retrieved and has exact match + +Should exit with code 0 if all input data is found in the respective services. + + +## KNOWN ISSUES + +If the faucet disbursement is set to a non-zero amount, the balances will be off. The verify script needs to be improved to check the faucet amount. diff --git a/apps/contract-migration/scripts/cmd/__init__.py b/apps/contract-migration/scripts/cmd/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/contract-migration/scripts/cmd/traffic.py b/apps/contract-migration/scripts/cmd/traffic.py new file mode 100644 index 0000000..1e5f58c --- /dev/null +++ b/apps/contract-migration/scripts/cmd/traffic.py @@ -0,0 +1,417 @@ +# standard imports +import logging +import json +import uuid +import importlib +import random +import copy +from argparse import RawTextHelpFormatter + +# external imports +import redis +from cic_eth.api.api_task import Api + +logg = logging.getLogger(__name__) + + +def add_args(argparser): + """Parse script specific command line arguments + + :param argparser: Top-level argument parser + :type argparser: argparse.ArgumentParser + """ + argparser.formatter_class = formatter_class=RawTextHelpFormatter + argparser.add_argument('--redis-host-callback', dest='redis_host_callback', default='localhost', type=str, help='redis host to use for callback') + argparser.add_argument('--redis-port-callback', dest='redis_port_callback', default=6379, type=int, help='redis port to use for callback') + argparser.add_argument('--batch-size', dest='batch_size', default=10, type=int, help='number of events to process simultaneously') + argparser.description = """Generates traffic on the cic network using dynamically loaded modules as event sources + +""" + return argparser + + +class TrafficItem: + """Represents a single item of traffic meta that will be processed by a traffic generation method + + The traffic generation module passed in the argument must implement a method "do" with interface conforming to local.noop_traffic.do. + + :param item: Traffic generation module. + :type item: function + """ + def __init__(self, item): + self.method = item.do + self.uuid = uuid.uuid4() + self.ext = None + self.result = None + self.sender = None + self.recipient = None + self.source_token = None + self.destination_token = None + self.source_value = 0 + + + def __str__(self): + return 'traffic item method {} uuid {}'.format(self.method, self.uuid) + + +class TrafficRouter: + """Holds and selects from the collection of traffic generator modules that will be used for the execution. + + :params batch_size: Amount of simultaneous traffic items that can simultanously be in flight. + :type batch_size: number + :raises ValueError: If batch size is zero of negative + """ + def __init__(self, batch_size=1): + if batch_size < 1: + raise ValueError('batch size cannot be 0') + self.items = [] + self.weights = [] + self.total_weights = 0 + self.batch_size = batch_size + self.reserved = {} + self.reserved_count = 0 + self.traffic = {} + + + def add(self, item, weight): + """Add a traffic generator module to the list of modules to choose between for traffic item exectuion. + + The probability that a module will be chosen for any single item is the ratio between the weight parameter and the accumulated weights for all items. + + See local.noop for which criteria the generator module must fulfill. + + :param item: Qualified class path to traffic generator module. Will be dynamically loaded. + :type item: str + :param weight: Selection probability weight + :type weight: number + :raises ModuleNotFound: Invalid item argument + """ + self.weights.append(self.total_weights) + self.total_weights += weight + m = importlib.import_module(item) + self.items.append(m) + + + def reserve(self): + """Selects the module to be used to execute the next traffic item, using the provided weights. + + If the current number of calls to "reserve" without corresponding calls to "release" equals the set batch size limit, None will be returned. The calling code should allow a short grace period before trying the call again. + :raises ValueError: No items have been added + :returns: A traffic item with the selected module method as the method property. + :rtype: TrafficItem|None + """ + if len(self.items) == 0: + raise ValueError('Add at least one item first') + + if len(self.reserved) == self.batch_size: + return None + + n = random.randint(0, self.total_weights) + item = self.items[0] + for i in range(len(self.weights)): + if n <= self.weights[i]: + item = self.items[i] + break + + ti = TrafficItem(item) + self.reserved[ti.uuid] = ti + return ti + + + def release(self, traffic_item): + """Releases the traffic item from the list of simultaneous traffic items in flight. + + :param traffic_item: Traffic item + :type traffic_item: TrafficItem + """ + del self.reserved[traffic_item.uuid] + + + def apply_import_dict(self, keys, dct): + """Convenience method to add traffic generator modules from a dictionary. + + :param keys: Keys in dictionary to add + :type keys: list of str + :param dct: Dictionary to choose module strings from + :type dct: dict + :raises ModuleNotFoundError: If one of the module strings refer to an invalid module. + """ + # parse traffic items + for k in keys: + if len(k) > 8 and k[:8] == 'TRAFFIC_': + v = int(dct.get(k)) + self.add(k[8:].lower(), v) + logg.debug('found traffic item {} weight {}'.format(k, v)) + + +# TODO: This will not work well with big networks. The provisioner should use lazy loading and LRU instead. +class TrafficProvisioner: + """Loads metadata necessary for traffic item execution. + + Instantiation will by default trigger retrieval of accounts and tokens on the network. + + It will also populate the aux property of the instance with the values from the static aux parameter template. + """ + + oracles = { + 'account': None, + 'token': None, + } + """Data oracles to be used for traffic item generation""" + default_aux = { + } + """Aux parameter template to be passed to the traffic generator module""" + + + def __init__(self): + self.tokens = self.oracles['token'].get_tokens() + self.accounts = self.oracles['account'].get_accounts() + self.aux = copy.copy(self.default_aux) + self.__balances = {} + for a in self.accounts: + self.__balances[a] = {} + + + # Caches a single address' balance of a single token + def __cache_balance(self, holder_address, token, value): + if self.__balances.get(holder_address) == None: + self.__balances[holder_address] = {} + self.__balances[holder_address][token] = value + logg.debug('setting cached balance of {} token {} to {}'.format(holder_address, token, value)) + + + def add_aux(self, k, v): + """Add a key-value pair to the aux parameter list. + + Does not protect existing entries from being overwritten. + + :param k: Key + :type k: str + :param v: Value + :type v: any + """ + logg.debug('added {} = {} to traffictasker'.format(k, v)) + self.aux[k] = v + + + # TODO: Balance list type should perhaps be a class (provided by cic-eth package) due to its complexity. + def balances(self, refresh_accounts=None): + """Retrieves all token balances for the given account list. + + If refresh_accounts is not None, the balance values for the given accounts will be retrieved from upstream. If the argument is an empty list, the balances will be updated for all tokens of all ccounts. If there are many accounts and/or tokens, this may be a VERY EXPENSIVE OPERATION. The "balance" method can be used instead to update individual account/token pair balances. + + :param accounts: List of accounts to refresh balances for. + :type accounts: list of str, 0x-hex + :returns: Dict of dict of dicts; v[accounts][token] = {balance_types} + :rtype: dict + """ + if refresh_accounts != None: + accounts = refresh_accounts + if len(accounts) == 0: + accounts = self.accounts + for account in accounts: + for token in self.tokens: + value = self.balance(account, token) + self.__cache_balance(account, token.symbol(), value) + logg.debug('balance sender {} token {} = {}'.format(account, token, value)) + else: + logg.debug('returning cached balances') + + return self.__balances + + + # TODO: use proper redis callback + def balance(self, account, token): + """Update balance for a single token of a single account from upstream. + + The balance will be the spendable balance at the time of the call. This value may be less than the balance reported by the consensus network, if a previous outgoing transaction is still pending in the network or the custodial system queue. + + :param account: Account to update + :type account: str, 0x-hex + :param token: Token to update balance for + :type token: cic_registry.token.Token + :returns: Updated balance + :rtype: complex balance dict + """ + api = Api( + str(self.aux['chain_spec']), + queue=self.aux['api_queue'], + #callback_param='{}:{}:{}:{}'.format(aux['redis_host_callback'], aux['redis_port_callback'], aux['redis_db'], aux['redis_channel']), + #callback_task='cic_eth.callbacks.redis.redis', + #callback_queue=queue, + ) + t = api.balance(account, token.symbol()) + r = t.get() + for c in t.collect(): + r = c[1] + assert t.successful() + #return r[0]['balance_network'] - r[0]['balance_outgoing'] + return r[0] + + + def update_balance(self, account, token, value): + """Manually set a token balance for an account. + + :param account: Account to update + :type account: str, 0x-hex + :param token: Token to update balance for + :type token: cic_registry.token.Token + :param value: Balance value to set + :type value: number + :returns: Balance value (unchanged) + :rtype: complex balance dict + """ + self.__cache_balance(account, token.symbol(), value) + return value + + +# TODO: Abstract redis with a generic pubsub adapter +class TrafficSyncHandler: + """Encapsulates callback methods required by the chain syncer. + + This implementation uses a redis subscription as backend to retrieve results from asynchronously executed tasks. + + :param config: Configuration of current top-level execution + :type config: object with dict get interface + :param traffic_router: Traffic router instance to use for the syncer session. + :type traffic_router: TrafficRouter + :raises Exception: Any Exception redis may raise on connection attempt. + """ + def __init__(self, config, traffic_router): + self.traffic_router = traffic_router + self.redis_channel = str(uuid.uuid4()) + self.pubsub = self.__connect_redis(self.redis_channel, config) + self.traffic_items = {} + self.config = config + self.init = False + + + # connects to redis + def __connect_redis(self, redis_channel, config): + r = redis.Redis(config.get('REDIS_HOST'), config.get('REDIS_PORT'), config.get('REDIS_DB')) + redis_pubsub = r.pubsub() + redis_pubsub.subscribe(redis_channel) + logg.debug('redis connected on channel {}'.format(redis_channel)) + return redis_pubsub + + + # TODO: This method is too long, split up + # TODO: This method will not yet cache balances for newly created accounts + def refresh(self, block_number, tx_index): + """Traffic method and item execution driver to be called on every loop execution of the chain syncer. + + Implements the signature required by callbacks called from chainsyncer.driver.loop. + + :param block_number: Syncer block height at time of call. + :type block_number: number + :param tx_index: Syncer block transaction index at time of call. + :type tx_index: number + """ + traffic_provisioner = TrafficProvisioner() + traffic_provisioner.add_aux('redis_channel', self.redis_channel) + + refresh_accounts = None + # Note! This call may be very expensive if there are a lot of accounts and/or tokens on the network + if not self.init: + refresh_accounts = traffic_provisioner.accounts + balances = traffic_provisioner.balances(refresh_accounts=refresh_accounts) + self.init = True + + if len(traffic_provisioner.tokens) == 0: + logg.error('patiently waiting for at least one registered token...') + return + + logg.debug('executing handler refresh with accounts {}'.format(traffic_provisioner.accounts)) + logg.debug('executing handler refresh with tokens {}'.format(traffic_provisioner.tokens)) + + sender_indices = [*range(0, len(traffic_provisioner.accounts))] + # TODO: only get balances for the selection that we will be generating for + + while True: + traffic_item = self.traffic_router.reserve() + if traffic_item == None: + logg.debug('no traffic_items left to reserve {}'.format(traffic_item)) + break + + # TODO: temporary selection + token_pair = ( + traffic_provisioner.tokens[0], + traffic_provisioner.tokens[0], + ) + sender_index_index = random.randint(0, len(sender_indices)-1) + sender_index = sender_indices[sender_index_index] + sender = traffic_provisioner.accounts[sender_index] + #balance_full = balances[sender][token_pair[0].symbol()] + if len(sender_indices) == 1: + sender_indices[m] = sender_sender_indices[len(senders)-1] + sender_indices = sender_indices[:len(sender_indices)-1] + + balance_full = traffic_provisioner.balance(sender, token_pair[0]) + + recipient_index = random.randint(0, len(traffic_provisioner.accounts)-1) + recipient = traffic_provisioner.accounts[recipient_index] + + logg.debug('trigger item {} tokens {} sender {} recipient {} balance {}') + (e, t, balance_result,) = traffic_item.method( + token_pair, + sender, + recipient, + balance_full, + traffic_provisioner.aux, + block_number, + tx_index, + ) + traffic_provisioner.update_balance(sender, token_pair[0], balance_result) + sender_indices.append(recipient_index) + + if e != None: + logg.info('failed {}: {}'.format(str(traffic_item), e)) + self.traffic_router.release(traffic_item) + continue + + if t == None: + logg.info('traffic method {} completed immediately') + self.traffic_router.release(traffic_item) + traffic_item.ext = t + self.traffic_items[traffic_item.ext] = traffic_item + + + while True: + m = self.pubsub.get_message(timeout=0.1) + if m == None: + break + logg.debug('redis message {}'.format(m)) + if m['type'] == 'message': + message_data = json.loads(m['data']) + uu = message_data['root_id'] + match_item = self.traffic_items[uu] + self.traffic_router.release(match_item) + logg.debug('>>>>>>>>>>>>>>>>>>> match item {} {} {}'.format(match_item, match_item.result, dir(match_item))) + if message_data['status'] != 0: + logg.error('task item {} failed with error code {}'.format(match_item, message_data['status'])) + else: + match_item.result = message_data['result'] + logg.debug('got callback result: {}'.format(match_item)) + + + def name(self): + """Returns the common name for the syncer callback implementation. Required by the chain syncer. + """ + return 'traffic_item_handler' + + + def filter(self, conn, block, tx, db_session): + """Callback for every transaction found in a block. Required by the chain syncer. + + Currently performs no operation. + + :param conn: A HTTPConnection object to the chain rpc provider. + :type conn: chainlib.eth.rpc.HTTPConnection + :param block: The block object of current transaction + :type block: chainlib.eth.block.Block + :param tx: The block transaction object + :type tx: chainlib.eth.tx.Tx + :param db_session: Syncer backend database session + :type db_session: SQLAlchemy.Session + """ + logg.debug('handler get {}'.format(tx)) diff --git a/apps/contract-migration/scripts/common/__init__.py b/apps/contract-migration/scripts/common/__init__.py new file mode 100644 index 0000000..4337b66 --- /dev/null +++ b/apps/contract-migration/scripts/common/__init__.py @@ -0,0 +1,8 @@ +from . import ( + log, + argparse, + config, + signer, + rpc, + registry, + ) diff --git a/apps/contract-migration/scripts/common/argparse.py b/apps/contract-migration/scripts/common/argparse.py new file mode 100644 index 0000000..b4edebf --- /dev/null +++ b/apps/contract-migration/scripts/common/argparse.py @@ -0,0 +1,73 @@ +# standard imports +import logging +import argparse +import os +import sys + +default_config_dir = os.environ.get('CONFINI_DIR') +full_template = { + # (long arg and key name, short var, type, default, help,) + 'provider': ('p', str, None, 'RPC provider url',), + 'registry_address': ('r', str, None, 'CIC registry address',), + 'keystore_file': ('y', str, None, 'Keystore file',), + 'config_dir': ('c', str, default_config_dir, 'Configuration directory',), + 'queue': ('q', str, 'cic-eth', 'Celery task queue',), + 'chain_spec': ('i', str, None, 'Chain spec string',), + 'abi_dir': (None, str, None, 'Smart contract ABI search path',), + 'env_prefix': (None, str, os.environ.get('CONFINI_ENV_PREFIX'), 'Environment prefix for variables to overwrite configuration',), + } +default_include_args = [ + 'config_dir', + 'provider', + 'env_prefix', + ] + +sub = None + +def create(caller_dir, include_args=default_include_args): + + argparser = argparse.ArgumentParser() + + for k in include_args: + a = full_template[k] + long_flag = '--' + k.replace('_', '-') + short_flag = None + dest = None + if a[0] != None: + short_flag = '-' + a[0] + dest = a[0] + else: + dest = k + default = a[2] + if default == None and k == 'config_dir': + default = os.path.join(caller_dir, 'config') + + if short_flag == None: + argparser.add_argument(long_flag, dest=dest, type=a[1], default=default, help=a[3]) + else: + argparser.add_argument(short_flag, long_flag, dest=dest, type=a[1], default=default, help=a[3]) + + argparser.add_argument('-v', action='store_true', help='Be verbose') + argparser.add_argument('-vv', action='store_true', help='Be more verbose') + + return argparser + + +def add(argparser, processor, name, description=None): + processor(argparser) + + return argparser + + +def parse(argparser, logger=None): + + args = argparser.parse_args(sys.argv[1:]) + + # handle logging input + if logger != None: + if args.vv: + logger.setLevel(logging.DEBUG) + elif args.v: + logger.setLevel(logging.INFO) + + return args diff --git a/apps/contract-migration/scripts/common/config.py b/apps/contract-migration/scripts/common/config.py new file mode 100644 index 0000000..565136d --- /dev/null +++ b/apps/contract-migration/scripts/common/config.py @@ -0,0 +1,39 @@ +# external imports +import logging +import confini + +logg = logging.getLogger(__name__) + +default_arg_overrides = { + 'abi_dir': 'ETH_ABI_DIR', + 'p': 'ETH_PROVIDER', + 'i': 'CIC_CHAIN_SPEC', + 'r': 'CIC_REGISTRY_ADDRESS', + } + + +def override(config, override_dict, label): + config.dict_override(override_dict, label) + config.validate() + return config + + +def create(config_dir, args, env_prefix=None, arg_overrides=default_arg_overrides): + # handle config input + config = confini.Config(config_dir, env_prefix) + config.process() + if arg_overrides != None and args != None: + override_dict = {} + for k in arg_overrides: + v = getattr(args, k) + if v != None: + override_dict[arg_overrides[k]] = v + config = override(config, override_dict, 'args') + else: + config.validate() + + return config + + +def log(config): + logg.debug('config loaded:\n{}'.format(config)) diff --git a/apps/contract-migration/scripts/common/log.py b/apps/contract-migration/scripts/common/log.py new file mode 100644 index 0000000..a4a0508 --- /dev/null +++ b/apps/contract-migration/scripts/common/log.py @@ -0,0 +1,18 @@ +# standard imports +import logging + +logging.basicConfig(level=logging.WARNING) + +default_mutelist = [ + 'urllib3', + 'websockets.protocol', + 'web3.RequestManager', + 'web3.providers.WebsocketProvider', + 'web3.providers.HTTPProvider', + ] + +def create(name=None, mutelist=default_mutelist): + logg = logging.getLogger(name) + for m in mutelist: + logging.getLogger(m).setLevel(logging.CRITICAL) + return logg diff --git a/apps/contract-migration/scripts/common/registry.py b/apps/contract-migration/scripts/common/registry.py new file mode 100644 index 0000000..83bbf02 --- /dev/null +++ b/apps/contract-migration/scripts/common/registry.py @@ -0,0 +1,86 @@ +# standard imports +import logging +import copy + +# external imports +from cic_registry import CICRegistry +from eth_token_index import TokenUniqueSymbolIndex +from eth_accounts_index import AccountRegistry +from chainlib.chain import ChainSpec +from cic_registry.chain import ChainRegistry +from cic_registry.helper.declarator import DeclaratorOracleAdapter + +logg = logging.getLogger(__name__) + + +class TokenOracle: + + def __init__(self, conn, chain_spec, registry): + self.tokens = [] + self.chain_spec = chain_spec + self.registry = registry + + token_registry_contract = CICRegistry.get_contract(chain_spec, 'TokenRegistry', 'Registry') + self.getter = TokenUniqueSymbolIndex(conn, token_registry_contract.address()) + + + def get_tokens(self): + token_count = self.getter.count() + if token_count == len(self.tokens): + return self.tokens + + for i in range(len(self.tokens), token_count): + token_address = self.getter.get_index(i) + t = self.registry.get_address(self.chain_spec, token_address) + token_symbol = t.symbol() + self.tokens.append(t) + + logg.debug('adding token idx {} symbol {} address {}'.format(i, token_symbol, token_address)) + + return copy.copy(self.tokens) + + +class AccountsOracle: + + def __init__(self, conn, chain_spec, registry): + self.accounts = [] + self.chain_spec = chain_spec + self.registry = registry + + accounts_registry_contract = CICRegistry.get_contract(chain_spec, 'AccountRegistry', 'Registry') + self.getter = AccountRegistry(conn, accounts_registry_contract.address()) + + + def get_accounts(self): + accounts_count = self.getter.count() + if accounts_count == len(self.accounts): + return self.accounts + + for i in range(len(self.accounts), accounts_count): + account = self.getter.get_index(i) + self.accounts.append(account) + logg.debug('adding account {}'.format(account)) + + return copy.copy(self.accounts) + + +def init_legacy(config, w3): + chain_spec = ChainSpec.from_chain_str(config.get('CIC_CHAIN_SPEC')) + CICRegistry.init(w3, config.get('CIC_REGISTRY_ADDRESS'), chain_spec) + CICRegistry.add_path(config.get('ETH_ABI_DIR')) + + chain_registry = ChainRegistry(chain_spec) + CICRegistry.add_chain_registry(chain_registry, True) + + declarator = CICRegistry.get_contract(chain_spec, 'AddressDeclarator', interface='Declarator') + trusted_addresses_src = config.get('CIC_TRUST_ADDRESS') + if trusted_addresses_src == None: + raise ValueError('At least one trusted address must be declared in CIC_TRUST_ADDRESS') + trusted_addresses = trusted_addresses_src.split(',') + for address in trusted_addresses: + logg.info('using trusted address {}'.format(address)) + + oracle = DeclaratorOracleAdapter(declarator.contract, trusted_addresses) + chain_registry.add_oracle(oracle, 'naive_erc20_oracle') + + return CICRegistry diff --git a/apps/contract-migration/scripts/common/rpc.py b/apps/contract-migration/scripts/common/rpc.py new file mode 100644 index 0000000..b8f8b20 --- /dev/null +++ b/apps/contract-migration/scripts/common/rpc.py @@ -0,0 +1,18 @@ +# standard imports +import re + +# external imports +import web3 + +def create(url): + # web3 input + # TODO: Replace with chainlib + re_websocket = r'^wss?:' + re_http = r'^https?:' + blockchain_provider = None + if re.match(re_websocket, url): + blockchain_provider = web3.Web3.WebsocketProvider(url) + elif re.match(re_http, url): + blockchain_provider = web3.Web3.HTTPProvider(url) + w3 = web3.Web3(blockchain_provider) + return w3 diff --git a/apps/contract-migration/scripts/common/signer.py b/apps/contract-migration/scripts/common/signer.py new file mode 100644 index 0000000..3493513 --- /dev/null +++ b/apps/contract-migration/scripts/common/signer.py @@ -0,0 +1,23 @@ +# standard imports +import logging + +# external imports +from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer +from crypto_dev_signer.keystore import DictKeystore + +logg = logging.getLogger(__name__) + +keystore = DictKeystore() + +def from_keystore(keyfile): + global keystore + + # signer + if keyfile == None: + raise ValueError('please specify signer keystore file') + + logg.debug('loading keystore file {}'.format(keyfile)) + address = keystore.import_keystore_file(keyfile) + + signer = EIP155Signer(keystore) + return (address, signer,) diff --git a/apps/contract-migration/scripts/config/celery.ini b/apps/contract-migration/scripts/config/celery.ini new file mode 100644 index 0000000..98c5012 --- /dev/null +++ b/apps/contract-migration/scripts/config/celery.ini @@ -0,0 +1,3 @@ +[celery] +broker_url = redis://localhost:63379 +result_url = redis://localhost:63379 diff --git a/apps/contract-migration/scripts/config/cic.ini b/apps/contract-migration/scripts/config/cic.ini new file mode 100644 index 0000000..b2e0b80 --- /dev/null +++ b/apps/contract-migration/scripts/config/cic.ini @@ -0,0 +1,9 @@ +[cic] +registry_address = 0x32E860c2A0645d1B7B005273696905F5D6DC5D05 +token_index_address = +accounts_index_address = +declarator_address = +approval_escrow_address = +chain_spec = evm:bloxberg:8996 +tx_retry_delay = +trust_address = 0xEb3907eCad74a0013c259D5874AE7f22DcBcC95C diff --git a/apps/contract-migration/scripts/config/database.ini b/apps/contract-migration/scripts/config/database.ini new file mode 100644 index 0000000..e5b8926 --- /dev/null +++ b/apps/contract-migration/scripts/config/database.ini @@ -0,0 +1,5 @@ +[database] +name = sempo +host = localhost +port = 5432 +user = postgres diff --git a/apps/contract-migration/scripts/config/eth.ini b/apps/contract-migration/scripts/config/eth.ini new file mode 100644 index 0000000..54eed6a --- /dev/null +++ b/apps/contract-migration/scripts/config/eth.ini @@ -0,0 +1,8 @@ +[eth] +#ws_provider = ws://localhost:8546 +#ttp_provider = http://localhost:8545 +provider = http://localhost:63545 +gas_provider_address = +#chain_id = +abi_dir = /usr/local/share/cic/solidity/abi +account_accounts_index_writer = diff --git a/apps/contract-migration/scripts/config/meta.ini b/apps/contract-migration/scripts/config/meta.ini new file mode 100644 index 0000000..0d16ee2 --- /dev/null +++ b/apps/contract-migration/scripts/config/meta.ini @@ -0,0 +1,2 @@ +[meta] +url = http://localhost:63380 diff --git a/apps/contract-migration/scripts/config/pgp.ini b/apps/contract-migration/scripts/config/pgp.ini new file mode 100644 index 0000000..b97b0c8 --- /dev/null +++ b/apps/contract-migration/scripts/config/pgp.ini @@ -0,0 +1,5 @@ +[pgp] +exports_dir = ../testdata/pgp +private_key_file = privatekeys_meta.asc +public_key_file = publickeys_meta.asc +passphrase = merman diff --git a/apps/contract-migration/scripts/config/redis.ini b/apps/contract-migration/scripts/config/redis.ini new file mode 100644 index 0000000..ea32137 --- /dev/null +++ b/apps/contract-migration/scripts/config/redis.ini @@ -0,0 +1,4 @@ +[redis] +host = localhost +port = 63379 +db = 0 diff --git a/apps/contract-migration/scripts/config/traffic.ini b/apps/contract-migration/scripts/config/traffic.ini new file mode 100644 index 0000000..99b572c --- /dev/null +++ b/apps/contract-migration/scripts/config/traffic.ini @@ -0,0 +1,4 @@ +[traffic] +#local.noop_traffic = 2 +local.account = 2 +local.transfer = 2 diff --git a/apps/contract-migration/scripts/create_import_users.py b/apps/contract-migration/scripts/create_import_users.py new file mode 100644 index 0000000..0ef540b --- /dev/null +++ b/apps/contract-migration/scripts/create_import_users.py @@ -0,0 +1,216 @@ +#!/usr/bin/python + +# standard imports +import json +import time +import datetime +import random +import logging +import os +import base64 +import hashlib +import sys +import argparse +import random + +# external imports +import vobject +import celery +import web3 +from faker import Faker +import cic_registry +import confini +from cic_eth.api import Api +from cic_types.models.person import ( + Person, + generate_vcard_from_contact_data, + get_contact_data_from_vcard, + ) +from chainlib.eth.address import to_checksum + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +fake = Faker(['sl', 'en_US', 'no', 'de', 'ro']) + +script_dir = os.path.realpath(os.path.dirname(__file__)) +#config_dir = os.environ.get('CONFINI_DIR', '/usr/local/etc/cic') +config_dir = os.environ.get('CONFINI_DIR', os.path.join(script_dir, 'config')) + +argparser = argparse.ArgumentParser() +argparser.add_argument('-c', type=str, default=config_dir, help='Config dir') +argparser.add_argument('--gift-threshold', type=int, help='If set, users will be funded with additional random balance (in token integer units)') +argparser.add_argument('-v', action='store_true', help='Be verbose') +argparser.add_argument('-vv', action='store_true', help='Be more verbose') +argparser.add_argument('--dir', default='out', type=str, help='path to users export dir tree') +argparser.add_argument('user_count', type=int, help='amount of users to generate') +args = argparser.parse_args() + +if args.v: + logg.setLevel(logging.INFO) +elif args.vv: + logg.setLevel(logging.DEBUG) + +config = confini.Config(args.c, os.environ.get('CONFINI_ENV_PREFIX')) +config.process() +logg.info('loaded config\n{}'.format(config)) + + +dt_now = datetime.datetime.utcnow() +dt_then = dt_now - datetime.timedelta(weeks=150) +ts_now = int(dt_now.timestamp()) +ts_then = int(dt_then.timestamp()) + +celery_app = celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=config.get('CELERY_RESULT_URL')) + +api = Api(config.get('CIC_CHAIN_SPEC')) + +gift_max = args.gift_threshold or 0 +gift_factor = (10**6) + +categories = [ + "food/water", + "fuel/energy", + "education", + "health", + "shop", + "environment", + "transport", + "farming/labor", + "savingsgroup", + ] + +phone_idx = [] + +user_dir = args.dir +user_count = args.user_count + +def genPhoneIndex(phone): + h = hashlib.new('sha256') + h.update(phone.encode('utf-8')) + h.update(b'cic.msisdn') + return h.digest().hex() + + +def genId(addr, typ): + h = hashlib.new('sha256') + h.update(bytes.fromhex(addr[2:])) + h.update(typ.encode('utf-8')) + return h.digest().hex() + + +def genDate(): + + logg.info(ts_then) + ts = random.randint(ts_then, ts_now) + return datetime.datetime.fromtimestamp(ts).timestamp() + + +def genPhone(): + return fake.msisdn() + + +def genPersonal(phone): + fn = fake.first_name() + ln = fake.last_name() + e = fake.email() + + return generate_vcard_from_contact_data(ln, fn, phone, e) + + +def genCats(): + i = random.randint(0, 3) + return random.choices(categories, k=i) + + +def genAmount(): + return random.randint(0, gift_max) * gift_factor + +def genDob(): + dob_src = fake.date_of_birth(minimum_age=15) + dob = {} + + if random.random() < 0.5: + dob['year'] = dob_src.year + + if random.random() > 0.5: + dob['month'] = dob_src.month + dob['day'] = dob_src.day + + return dob + + +def gen(): + old_blockchain_address = '0x' + os.urandom(20).hex() + old_blockchain_checksum_address = to_checksum(old_blockchain_address) + gender = random.choice(['female', 'male', 'other']) + phone = genPhone() + city = fake.city_name() + v = genPersonal(phone) + + contact_data = get_contact_data_from_vcard(v) + p = Person() + p.load_vcard(contact_data) + + p.date_registered = genDate() + p.date_of_birth = genDob() + p.gender = gender + p.identities = { + 'evm': { + 'oldchain:1': [ + old_blockchain_checksum_address, + ], + }, + } + p.location['area_name'] = city + if random.randint(0, 1): + p.identities['latitude'] = (random.random() + 180) - 90 #fake.local_latitude() + p.identities['longitude'] = (random.random() + 360) - 180 #fake.local_latitude() + + return (old_blockchain_checksum_address, phone, p) + + +def prepareLocalFilePath(datadir, address): + parts = [ + address[:2], + address[2:4], + ] + dirs = '{}/{}/{}'.format( + datadir, + parts[0], + parts[1], + ) + os.makedirs(dirs, exist_ok=True) + return dirs + + +if __name__ == '__main__': + + base_dir = os.path.join(user_dir, 'old') + os.makedirs(base_dir, exist_ok=True) + + fa = open(os.path.join(user_dir, 'balances.csv'), 'w') + + for i in range(user_count): + + (eth, phone, o) = gen() + uid = eth[2:].upper() + + print(o) + + d = prepareLocalFilePath(base_dir, uid) + f = open('{}/{}'.format(d, uid + '.json'), 'w') + json.dump(o.serialize(), f) + f.close() + + pidx = genPhoneIndex(phone) + d = prepareLocalFilePath(os.path.join(user_dir, 'phone'), uid) + f = open('{}/{}'.format(d, pidx), 'w') + f.write(eth) + f.close() + + amount = genAmount() + fa.write('{},{}\n'.format(eth,amount)) + logg.debug('pidx {}, uid {}, eth {}, amount {}'.format(pidx, uid, eth, amount)) + + fa.close() diff --git a/apps/contract-migration/scripts/false/_logs/2021-02-12T18_59_21_680Z-debug.log b/apps/contract-migration/scripts/false/_logs/2021-02-12T18_59_21_680Z-debug.log new file mode 100644 index 0000000..011bfd8 --- /dev/null +++ b/apps/contract-migration/scripts/false/_logs/2021-02-12T18_59_21_680Z-debug.log @@ -0,0 +1,1383 @@ +0 info it worked if it ends with ok +1 verbose cli [ +1 verbose cli '/usr/bin/node', +1 verbose cli '/usr/bin/npm', +1 verbose cli 'install', +1 verbose cli '--no-cache', +1 verbose cli '../../../apps/cic-meta' +1 verbose cli ] +2 info using npm@6.14.11 +3 info using node@v15.6.0 +4 verbose npm-session 64ba63e9b9f4a63f +5 silly install loadCurrentTree +6 silly install readLocalPackageData +7 silly pacote directory manifest for undefined@file:../../cic-meta fetched in 4ms +8 timing stage:loadCurrentTree Completed in 473ms +9 silly install loadIdealTree +10 silly install cloneCurrentTreeToIdealTree +11 timing stage:loadIdealTree:cloneCurrentTree Completed in 3ms +12 silly install loadShrinkwrap +13 timing stage:loadIdealTree:loadShrinkwrap Completed in 57ms +14 silly install loadAllDepsIntoIdealTree +15 silly resolveWithNewModule cic-client-meta@0.0.7-alpha.1 checking installable status +16 silly removeObsoleteDep removing cic-client-meta@0.0.7-alpha.1 from the tree as its been replaced by a newer version or is no longer required +17 silly removeObsoleteDep removing @ethereumjs/tx@3.0.0-beta.1 from the tree as its been replaced by a newer version or is no longer required +18 silly removeObsoleteDep removing @ethereumjs/common@2.0.0-beta.1 from the tree as its been replaced by a newer version or is no longer required +19 silly removeObsoleteDep removing crc-32@1.2.0 from the tree as its been replaced by a newer version or is no longer required +20 silly removeObsoleteDep removing exit-on-epipe@1.0.1 from the tree as its been replaced by a newer version or is no longer required +21 silly removeObsoleteDep removing printj@1.1.2 from the tree as its been replaced by a newer version or is no longer required +22 silly removeObsoleteDep removing automerge@0.14.1 from the tree as its been replaced by a newer version or is no longer required +23 silly removeObsoleteDep removing immutable@3.8.2 from the tree as its been replaced by a newer version or is no longer required +24 silly removeObsoleteDep removing transit-immutable-js@0.7.0 from the tree as its been replaced by a newer version or is no longer required +25 silly removeObsoleteDep removing transit-js@0.8.867 from the tree as its been replaced by a newer version or is no longer required +26 silly removeObsoleteDep removing ethereumjs-wallet@1.0.1 from the tree as its been replaced by a newer version or is no longer required +27 silly removeObsoleteDep removing aes-js@3.1.2 from the tree as its been replaced by a newer version or is no longer required +28 silly removeObsoleteDep removing bs58check@2.1.2 from the tree as its been replaced by a newer version or is no longer required +29 silly removeObsoleteDep removing bs58@4.0.1 from the tree as its been replaced by a newer version or is no longer required +30 silly removeObsoleteDep removing base-x@3.0.8 from the tree as its been replaced by a newer version or is no longer required +31 silly removeObsoleteDep removing create-hash@1.2.0 from the tree as its been replaced by a newer version or is no longer required +32 silly removeObsoleteDep removing cipher-base@1.0.4 from the tree as its been replaced by a newer version or is no longer required +33 silly removeObsoleteDep removing md5.js@1.3.5 from the tree as its been replaced by a newer version or is no longer required +34 silly removeObsoleteDep removing hash-base@3.1.0 from the tree as its been replaced by a newer version or is no longer required +35 silly removeObsoleteDep removing ripemd160@2.0.2 from the tree as its been replaced by a newer version or is no longer required +36 silly removeObsoleteDep removing sha.js@2.4.11 from the tree as its been replaced by a newer version or is no longer required +37 silly removeObsoleteDep removing ethereum-cryptography@0.1.3 from the tree as its been replaced by a newer version or is no longer required +38 silly removeObsoleteDep removing @types/pbkdf2@3.1.0 from the tree as its been replaced by a newer version or is no longer required +39 silly removeObsoleteDep removing @types/node@14.14.6 from the tree as its been replaced by a newer version or is no longer required +40 silly removeObsoleteDep removing @types/secp256k1@4.0.1 from the tree as its been replaced by a newer version or is no longer required +41 silly removeObsoleteDep removing blakejs@1.1.0 from the tree as its been replaced by a newer version or is no longer required +42 silly removeObsoleteDep removing browserify-aes@1.2.0 from the tree as its been replaced by a newer version or is no longer required +43 silly removeObsoleteDep removing buffer-xor@1.0.3 from the tree as its been replaced by a newer version or is no longer required +44 silly removeObsoleteDep removing evp_bytestokey@1.0.3 from the tree as its been replaced by a newer version or is no longer required +45 silly removeObsoleteDep removing create-hmac@1.1.7 from the tree as its been replaced by a newer version or is no longer required +46 silly removeObsoleteDep removing hash.js@1.1.7 from the tree as its been replaced by a newer version or is no longer required +47 silly removeObsoleteDep removing keccak@3.0.1 from the tree as its been replaced by a newer version or is no longer required +48 silly removeObsoleteDep removing node-gyp-build@4.2.3 from the tree as its been replaced by a newer version or is no longer required +49 silly removeObsoleteDep removing pbkdf2@3.1.1 from the tree as its been replaced by a newer version or is no longer required +50 silly removeObsoleteDep removing randombytes@2.1.0 from the tree as its been replaced by a newer version or is no longer required +51 silly removeObsoleteDep removing scrypt-js@3.0.1 from the tree as its been replaced by a newer version or is no longer required +52 silly removeObsoleteDep removing secp256k1@4.0.2 from the tree as its been replaced by a newer version or is no longer required +53 silly removeObsoleteDep removing elliptic@6.5.3 from the tree as its been replaced by a newer version or is no longer required +54 silly removeObsoleteDep removing brorand@1.1.0 from the tree as its been replaced by a newer version or is no longer required +55 silly removeObsoleteDep removing hmac-drbg@1.0.1 from the tree as its been replaced by a newer version or is no longer required +56 silly removeObsoleteDep removing minimalistic-crypto-utils@1.0.1 from the tree as its been replaced by a newer version or is no longer required +57 silly removeObsoleteDep removing setimmediate@1.0.5 from the tree as its been replaced by a newer version or is no longer required +58 silly removeObsoleteDep removing ethereumjs-util@7.0.7 from the tree as its been replaced by a newer version or is no longer required +59 silly removeObsoleteDep removing @types/bn.js@4.11.6 from the tree as its been replaced by a newer version or is no longer required +60 silly removeObsoleteDep removing bn.js@5.1.3 from the tree as its been replaced by a newer version or is no longer required +61 silly removeObsoleteDep removing ethjs-util@0.1.6 from the tree as its been replaced by a newer version or is no longer required +62 silly removeObsoleteDep removing is-hex-prefixed@1.0.0 from the tree as its been replaced by a newer version or is no longer required +63 silly removeObsoleteDep removing strip-hex-prefix@1.0.0 from the tree as its been replaced by a newer version or is no longer required +64 silly removeObsoleteDep removing rlp@2.2.6 from the tree as its been replaced by a newer version or is no longer required +65 silly removeObsoleteDep removing utf8@3.0.0 from the tree as its been replaced by a newer version or is no longer required +66 silly removeObsoleteDep removing openpgp@4.10.8 from the tree as its been replaced by a newer version or is no longer required +67 silly removeObsoleteDep removing asn1.js@5.4.1 from the tree as its been replaced by a newer version or is no longer required +68 silly removeObsoleteDep removing bn.js@4.11.9 from the tree as its been replaced by a newer version or is no longer required +69 silly removeObsoleteDep removing minimalistic-assert@1.0.1 from the tree as its been replaced by a newer version or is no longer required +70 silly removeObsoleteDep removing node-fetch@2.6.1 from the tree as its been replaced by a newer version or is no longer required +71 silly removeObsoleteDep removing node-localstorage@1.3.1 from the tree as its been replaced by a newer version or is no longer required +72 silly removeObsoleteDep removing write-file-atomic@1.3.4 from the tree as its been replaced by a newer version or is no longer required +73 silly removeObsoleteDep removing imurmurhash@0.1.4 from the tree as its been replaced by a newer version or is no longer required +74 silly removeObsoleteDep removing slide@1.1.6 from the tree as its been replaced by a newer version or is no longer required +75 silly removeObsoleteDep removing pg@8.4.2 from the tree as its been replaced by a newer version or is no longer required +76 silly removeObsoleteDep removing buffer-writer@2.0.0 from the tree as its been replaced by a newer version or is no longer required +77 silly removeObsoleteDep removing packet-reader@1.0.0 from the tree as its been replaced by a newer version or is no longer required +78 silly removeObsoleteDep removing pg-connection-string@2.4.0 from the tree as its been replaced by a newer version or is no longer required +79 silly removeObsoleteDep removing pg-pool@3.2.2 from the tree as its been replaced by a newer version or is no longer required +80 silly removeObsoleteDep removing pg-protocol@1.3.0 from the tree as its been replaced by a newer version or is no longer required +81 silly removeObsoleteDep removing pg-types@2.2.0 from the tree as its been replaced by a newer version or is no longer required +82 silly removeObsoleteDep removing pg-int8@1.0.1 from the tree as its been replaced by a newer version or is no longer required +83 silly removeObsoleteDep removing postgres-array@2.0.0 from the tree as its been replaced by a newer version or is no longer required +84 silly removeObsoleteDep removing postgres-bytea@1.0.0 from the tree as its been replaced by a newer version or is no longer required +85 silly removeObsoleteDep removing postgres-date@1.0.7 from the tree as its been replaced by a newer version or is no longer required +86 silly removeObsoleteDep removing postgres-interval@1.2.0 from the tree as its been replaced by a newer version or is no longer required +87 silly removeObsoleteDep removing xtend@4.0.2 from the tree as its been replaced by a newer version or is no longer required +88 silly removeObsoleteDep removing pgpass@1.0.4 from the tree as its been replaced by a newer version or is no longer required +89 silly removeObsoleteDep removing split2@3.2.2 from the tree as its been replaced by a newer version or is no longer required +90 silly removeObsoleteDep removing readable-stream@3.6.0 from the tree as its been replaced by a newer version or is no longer required +91 silly removeObsoleteDep removing string_decoder@1.3.0 from the tree as its been replaced by a newer version or is no longer required +92 silly removeObsoleteDep removing sqlite3@5.0.0 from the tree as its been replaced by a newer version or is no longer required +93 silly removeObsoleteDep removing node-addon-api@2.0.0 from the tree as its been replaced by a newer version or is no longer required +94 silly removeObsoleteDep removing node-gyp@3.8.0 from the tree as its been replaced by a newer version or is no longer required +95 silly removeObsoleteDep removing fstream@1.0.12 from the tree as its been replaced by a newer version or is no longer required +96 silly removeObsoleteDep removing graceful-fs@4.2.4 from the tree as its been replaced by a newer version or is no longer required +97 silly removeObsoleteDep removing inherits@2.0.4 from the tree as its been replaced by a newer version or is no longer required +98 silly removeObsoleteDep removing mkdirp@0.5.5 from the tree as its been replaced by a newer version or is no longer required +99 silly removeObsoleteDep removing minimist@1.2.5 from the tree as its been replaced by a newer version or is no longer required +100 silly removeObsoleteDep removing rimraf@2.7.1 from the tree as its been replaced by a newer version or is no longer required +101 silly removeObsoleteDep removing glob@7.1.6 from the tree as its been replaced by a newer version or is no longer required +102 silly removeObsoleteDep removing fs.realpath@1.0.0 from the tree as its been replaced by a newer version or is no longer required +103 silly removeObsoleteDep removing inflight@1.0.6 from the tree as its been replaced by a newer version or is no longer required +104 silly removeObsoleteDep removing once@1.4.0 from the tree as its been replaced by a newer version or is no longer required +105 silly removeObsoleteDep removing wrappy@1.0.2 from the tree as its been replaced by a newer version or is no longer required +106 silly removeObsoleteDep removing minimatch@3.0.4 from the tree as its been replaced by a newer version or is no longer required +107 silly removeObsoleteDep removing brace-expansion@1.1.11 from the tree as its been replaced by a newer version or is no longer required +108 silly removeObsoleteDep removing balanced-match@1.0.0 from the tree as its been replaced by a newer version or is no longer required +109 silly removeObsoleteDep removing concat-map@0.0.1 from the tree as its been replaced by a newer version or is no longer required +110 silly removeObsoleteDep removing path-is-absolute@1.0.1 from the tree as its been replaced by a newer version or is no longer required +111 silly removeObsoleteDep removing nopt@3.0.6 from the tree as its been replaced by a newer version or is no longer required +112 silly removeObsoleteDep removing abbrev@1.1.1 from the tree as its been replaced by a newer version or is no longer required +113 silly removeObsoleteDep removing npmlog@4.1.2 from the tree as its been replaced by a newer version or is no longer required +114 silly removeObsoleteDep removing are-we-there-yet@1.1.5 from the tree as its been replaced by a newer version or is no longer required +115 silly removeObsoleteDep removing delegates@1.0.0 from the tree as its been replaced by a newer version or is no longer required +116 silly removeObsoleteDep removing readable-stream@2.3.7 from the tree as its been replaced by a newer version or is no longer required +117 silly removeObsoleteDep removing core-util-is@1.0.2 from the tree as its been replaced by a newer version or is no longer required +118 silly removeObsoleteDep removing isarray@1.0.0 from the tree as its been replaced by a newer version or is no longer required +119 silly removeObsoleteDep removing process-nextick-args@2.0.1 from the tree as its been replaced by a newer version or is no longer required +120 silly removeObsoleteDep removing safe-buffer@5.1.2 from the tree as its been replaced by a newer version or is no longer required +121 silly removeObsoleteDep removing string_decoder@1.1.1 from the tree as its been replaced by a newer version or is no longer required +122 silly removeObsoleteDep removing util-deprecate@1.0.2 from the tree as its been replaced by a newer version or is no longer required +123 silly removeObsoleteDep removing console-control-strings@1.1.0 from the tree as its been replaced by a newer version or is no longer required +124 silly removeObsoleteDep removing gauge@2.7.4 from the tree as its been replaced by a newer version or is no longer required +125 silly removeObsoleteDep removing aproba@1.2.0 from the tree as its been replaced by a newer version or is no longer required +126 silly removeObsoleteDep removing has-unicode@2.0.1 from the tree as its been replaced by a newer version or is no longer required +127 silly removeObsoleteDep removing object-assign@4.1.1 from the tree as its been replaced by a newer version or is no longer required +128 silly removeObsoleteDep removing signal-exit@3.0.3 from the tree as its been replaced by a newer version or is no longer required +129 silly removeObsoleteDep removing string-width@1.0.2 from the tree as its been replaced by a newer version or is no longer required +130 silly removeObsoleteDep removing code-point-at@1.1.0 from the tree as its been replaced by a newer version or is no longer required +131 silly removeObsoleteDep removing is-fullwidth-code-point@1.0.0 from the tree as its been replaced by a newer version or is no longer required +132 silly removeObsoleteDep removing number-is-nan@1.0.1 from the tree as its been replaced by a newer version or is no longer required +133 silly removeObsoleteDep removing strip-ansi@3.0.1 from the tree as its been replaced by a newer version or is no longer required +134 silly removeObsoleteDep removing ansi-regex@2.1.1 from the tree as its been replaced by a newer version or is no longer required +135 silly removeObsoleteDep removing wide-align@1.1.3 from the tree as its been replaced by a newer version or is no longer required +136 silly removeObsoleteDep removing set-blocking@2.0.0 from the tree as its been replaced by a newer version or is no longer required +137 silly removeObsoleteDep removing osenv@0.1.5 from the tree as its been replaced by a newer version or is no longer required +138 silly removeObsoleteDep removing os-homedir@1.0.2 from the tree as its been replaced by a newer version or is no longer required +139 silly removeObsoleteDep removing os-tmpdir@1.0.2 from the tree as its been replaced by a newer version or is no longer required +140 silly removeObsoleteDep removing request@2.88.2 from the tree as its been replaced by a newer version or is no longer required +141 silly removeObsoleteDep removing aws-sign2@0.7.0 from the tree as its been replaced by a newer version or is no longer required +142 silly removeObsoleteDep removing aws4@1.11.0 from the tree as its been replaced by a newer version or is no longer required +143 silly removeObsoleteDep removing caseless@0.12.0 from the tree as its been replaced by a newer version or is no longer required +144 silly removeObsoleteDep removing combined-stream@1.0.8 from the tree as its been replaced by a newer version or is no longer required +145 silly removeObsoleteDep removing delayed-stream@1.0.0 from the tree as its been replaced by a newer version or is no longer required +146 silly removeObsoleteDep removing extend@3.0.2 from the tree as its been replaced by a newer version or is no longer required +147 silly removeObsoleteDep removing forever-agent@0.6.1 from the tree as its been replaced by a newer version or is no longer required +148 silly removeObsoleteDep removing form-data@2.3.3 from the tree as its been replaced by a newer version or is no longer required +149 silly removeObsoleteDep removing asynckit@0.4.0 from the tree as its been replaced by a newer version or is no longer required +150 silly removeObsoleteDep removing mime-types@2.1.27 from the tree as its been replaced by a newer version or is no longer required +151 silly removeObsoleteDep removing mime-db@1.44.0 from the tree as its been replaced by a newer version or is no longer required +152 silly removeObsoleteDep removing har-validator@5.1.5 from the tree as its been replaced by a newer version or is no longer required +153 silly removeObsoleteDep removing ajv@6.12.6 from the tree as its been replaced by a newer version or is no longer required +154 silly removeObsoleteDep removing fast-deep-equal@3.1.3 from the tree as its been replaced by a newer version or is no longer required +155 silly removeObsoleteDep removing fast-json-stable-stringify@2.1.0 from the tree as its been replaced by a newer version or is no longer required +156 silly removeObsoleteDep removing json-schema-traverse@0.4.1 from the tree as its been replaced by a newer version or is no longer required +157 silly removeObsoleteDep removing uri-js@4.4.0 from the tree as its been replaced by a newer version or is no longer required +158 silly removeObsoleteDep removing punycode@2.1.1 from the tree as its been replaced by a newer version or is no longer required +159 silly removeObsoleteDep removing har-schema@2.0.0 from the tree as its been replaced by a newer version or is no longer required +160 silly removeObsoleteDep removing http-signature@1.2.0 from the tree as its been replaced by a newer version or is no longer required +161 silly removeObsoleteDep removing assert-plus@1.0.0 from the tree as its been replaced by a newer version or is no longer required +162 silly removeObsoleteDep removing jsprim@1.4.1 from the tree as its been replaced by a newer version or is no longer required +163 silly removeObsoleteDep removing extsprintf@1.3.0 from the tree as its been replaced by a newer version or is no longer required +164 silly removeObsoleteDep removing json-schema@0.2.3 from the tree as its been replaced by a newer version or is no longer required +165 silly removeObsoleteDep removing verror@1.10.0 from the tree as its been replaced by a newer version or is no longer required +166 silly removeObsoleteDep removing sshpk@1.16.1 from the tree as its been replaced by a newer version or is no longer required +167 silly removeObsoleteDep removing asn1@0.2.4 from the tree as its been replaced by a newer version or is no longer required +168 silly removeObsoleteDep removing safer-buffer@2.1.2 from the tree as its been replaced by a newer version or is no longer required +169 silly removeObsoleteDep removing bcrypt-pbkdf@1.0.2 from the tree as its been replaced by a newer version or is no longer required +170 silly removeObsoleteDep removing tweetnacl@0.14.5 from the tree as its been replaced by a newer version or is no longer required +171 silly removeObsoleteDep removing dashdash@1.14.1 from the tree as its been replaced by a newer version or is no longer required +172 silly removeObsoleteDep removing ecc-jsbn@0.1.2 from the tree as its been replaced by a newer version or is no longer required +173 silly removeObsoleteDep removing jsbn@0.1.1 from the tree as its been replaced by a newer version or is no longer required +174 silly removeObsoleteDep removing getpass@0.1.7 from the tree as its been replaced by a newer version or is no longer required +175 silly removeObsoleteDep removing is-typedarray@1.0.0 from the tree as its been replaced by a newer version or is no longer required +176 silly removeObsoleteDep removing isstream@0.1.2 from the tree as its been replaced by a newer version or is no longer required +177 silly removeObsoleteDep removing json-stringify-safe@5.0.1 from the tree as its been replaced by a newer version or is no longer required +178 silly removeObsoleteDep removing oauth-sign@0.9.0 from the tree as its been replaced by a newer version or is no longer required +179 silly removeObsoleteDep removing performance-now@2.1.0 from the tree as its been replaced by a newer version or is no longer required +180 silly removeObsoleteDep removing qs@6.5.2 from the tree as its been replaced by a newer version or is no longer required +181 silly removeObsoleteDep removing safe-buffer@5.2.1 from the tree as its been replaced by a newer version or is no longer required +182 silly removeObsoleteDep removing tough-cookie@2.5.0 from the tree as its been replaced by a newer version or is no longer required +183 silly removeObsoleteDep removing psl@1.8.0 from the tree as its been replaced by a newer version or is no longer required +184 silly removeObsoleteDep removing tunnel-agent@0.6.0 from the tree as its been replaced by a newer version or is no longer required +185 silly removeObsoleteDep removing uuid@3.4.0 from the tree as its been replaced by a newer version or is no longer required +186 silly removeObsoleteDep removing semver@5.3.0 from the tree as its been replaced by a newer version or is no longer required +187 silly removeObsoleteDep removing tar@2.2.2 from the tree as its been replaced by a newer version or is no longer required +188 silly removeObsoleteDep removing block-stream@0.0.9 from the tree as its been replaced by a newer version or is no longer required +189 silly removeObsoleteDep removing which@1.3.1 from the tree as its been replaced by a newer version or is no longer required +190 silly removeObsoleteDep removing isexe@2.0.0 from the tree as its been replaced by a newer version or is no longer required +191 silly removeObsoleteDep removing node-pre-gyp@0.11.0 from the tree as its been replaced by a newer version or is no longer required +192 silly removeObsoleteDep removing detect-libc@1.0.3 from the tree as its been replaced by a newer version or is no longer required +193 silly removeObsoleteDep removing needle@2.5.2 from the tree as its been replaced by a newer version or is no longer required +194 silly removeObsoleteDep removing debug@3.2.6 from the tree as its been replaced by a newer version or is no longer required +195 silly removeObsoleteDep removing ms@2.1.2 from the tree as its been replaced by a newer version or is no longer required +196 silly removeObsoleteDep removing iconv-lite@0.4.24 from the tree as its been replaced by a newer version or is no longer required +197 silly removeObsoleteDep removing sax@1.2.4 from the tree as its been replaced by a newer version or is no longer required +198 silly removeObsoleteDep removing nopt@4.0.3 from the tree as its been replaced by a newer version or is no longer required +199 silly removeObsoleteDep removing npm-packlist@1.4.8 from the tree as its been replaced by a newer version or is no longer required +200 silly removeObsoleteDep removing ignore-walk@3.0.3 from the tree as its been replaced by a newer version or is no longer required +201 silly removeObsoleteDep removing npm-bundled@1.1.1 from the tree as its been replaced by a newer version or is no longer required +202 silly removeObsoleteDep removing npm-normalize-package-bin@1.0.1 from the tree as its been replaced by a newer version or is no longer required +203 silly removeObsoleteDep removing rc@1.2.8 from the tree as its been replaced by a newer version or is no longer required +204 silly removeObsoleteDep removing deep-extend@0.6.0 from the tree as its been replaced by a newer version or is no longer required +205 silly removeObsoleteDep removing ini@1.3.5 from the tree as its been replaced by a newer version or is no longer required +206 silly removeObsoleteDep removing strip-json-comments@2.0.1 from the tree as its been replaced by a newer version or is no longer required +207 silly removeObsoleteDep removing tar@4.4.13 from the tree as its been replaced by a newer version or is no longer required +208 silly removeObsoleteDep removing chownr@1.1.4 from the tree as its been replaced by a newer version or is no longer required +209 silly removeObsoleteDep removing fs-minipass@1.2.7 from the tree as its been replaced by a newer version or is no longer required +210 silly removeObsoleteDep removing minipass@2.9.0 from the tree as its been replaced by a newer version or is no longer required +211 silly removeObsoleteDep removing yallist@3.1.1 from the tree as its been replaced by a newer version or is no longer required +212 silly removeObsoleteDep removing minizlib@1.3.3 from the tree as its been replaced by a newer version or is no longer required +213 silly removeObsoleteDep removing yargs@16.1.0 from the tree as its been replaced by a newer version or is no longer required +214 silly removeObsoleteDep removing cliui@7.0.3 from the tree as its been replaced by a newer version or is no longer required +215 silly removeObsoleteDep removing string-width@4.2.0 from the tree as its been replaced by a newer version or is no longer required +216 silly removeObsoleteDep removing emoji-regex@8.0.0 from the tree as its been replaced by a newer version or is no longer required +217 silly removeObsoleteDep removing is-fullwidth-code-point@3.0.0 from the tree as its been replaced by a newer version or is no longer required +218 silly removeObsoleteDep removing strip-ansi@6.0.0 from the tree as its been replaced by a newer version or is no longer required +219 silly removeObsoleteDep removing ansi-regex@5.0.0 from the tree as its been replaced by a newer version or is no longer required +220 silly removeObsoleteDep removing wrap-ansi@7.0.0 from the tree as its been replaced by a newer version or is no longer required +221 silly removeObsoleteDep removing ansi-styles@4.3.0 from the tree as its been replaced by a newer version or is no longer required +222 silly removeObsoleteDep removing color-convert@2.0.1 from the tree as its been replaced by a newer version or is no longer required +223 silly removeObsoleteDep removing color-name@1.1.4 from the tree as its been replaced by a newer version or is no longer required +224 silly removeObsoleteDep removing string-width@4.2.0 from the tree as its been replaced by a newer version or is no longer required +225 silly removeObsoleteDep removing is-fullwidth-code-point@3.0.0 from the tree as its been replaced by a newer version or is no longer required +226 silly removeObsoleteDep removing strip-ansi@6.0.0 from the tree as its been replaced by a newer version or is no longer required +227 silly removeObsoleteDep removing ansi-regex@5.0.0 from the tree as its been replaced by a newer version or is no longer required +228 silly removeObsoleteDep removing escalade@3.1.1 from the tree as its been replaced by a newer version or is no longer required +229 silly removeObsoleteDep removing get-caller-file@2.0.5 from the tree as its been replaced by a newer version or is no longer required +230 silly removeObsoleteDep removing require-directory@2.1.1 from the tree as its been replaced by a newer version or is no longer required +231 silly removeObsoleteDep removing string-width@4.2.0 from the tree as its been replaced by a newer version or is no longer required +232 silly removeObsoleteDep removing is-fullwidth-code-point@3.0.0 from the tree as its been replaced by a newer version or is no longer required +233 silly removeObsoleteDep removing strip-ansi@6.0.0 from the tree as its been replaced by a newer version or is no longer required +234 silly removeObsoleteDep removing ansi-regex@5.0.0 from the tree as its been replaced by a newer version or is no longer required +235 silly removeObsoleteDep removing y18n@5.0.5 from the tree as its been replaced by a newer version or is no longer required +236 silly removeObsoleteDep removing yargs-parser@20.2.3 from the tree as its been replaced by a newer version or is no longer required +237 timing stage:loadIdealTree:loadAllDepsIntoIdealTree Completed in 339ms +238 timing stage:loadIdealTree Completed in 441ms +239 silly currentTree scripts +239 silly currentTree └─┬ cic-client-meta@0.0.7-alpha.1 +239 silly currentTree ├── @ethereumjs/common@2.0.0-beta.1 +239 silly currentTree ├── @ethereumjs/tx@3.0.0-beta.1 +239 silly currentTree ├── @types/bn.js@4.11.6 +239 silly currentTree ├── @types/eslint-scope@3.7.0 +239 silly currentTree ├── @types/eslint@7.2.4 +239 silly currentTree ├── @types/estree@0.0.45 +239 silly currentTree ├── @types/json-schema@7.0.6 +239 silly currentTree ├── @types/mocha@8.0.3 +239 silly currentTree ├── @types/node@14.14.6 +239 silly currentTree ├── @types/pbkdf2@3.1.0 +239 silly currentTree ├── @types/secp256k1@4.0.1 +239 silly currentTree ├── @ungap/promise-all-settled@1.1.2 +239 silly currentTree ├── @webassemblyjs/ast@1.9.0 +239 silly currentTree ├── @webassemblyjs/floating-point-hex-parser@1.9.0 +239 silly currentTree ├── @webassemblyjs/helper-api-error@1.9.0 +239 silly currentTree ├── @webassemblyjs/helper-buffer@1.9.0 +239 silly currentTree ├── @webassemblyjs/helper-code-frame@1.9.0 +239 silly currentTree ├── @webassemblyjs/helper-fsm@1.9.0 +239 silly currentTree ├── @webassemblyjs/helper-module-context@1.9.0 +239 silly currentTree ├── @webassemblyjs/helper-wasm-bytecode@1.9.0 +239 silly currentTree ├── @webassemblyjs/helper-wasm-section@1.9.0 +239 silly currentTree ├── @webassemblyjs/ieee754@1.9.0 +239 silly currentTree ├── @webassemblyjs/leb128@1.9.0 +239 silly currentTree ├── @webassemblyjs/utf8@1.9.0 +239 silly currentTree ├── @webassemblyjs/wasm-edit@1.9.0 +239 silly currentTree ├── @webassemblyjs/wasm-gen@1.9.0 +239 silly currentTree ├── @webassemblyjs/wasm-opt@1.9.0 +239 silly currentTree ├── @webassemblyjs/wasm-parser@1.9.0 +239 silly currentTree ├── @webassemblyjs/wast-parser@1.9.0 +239 silly currentTree ├── @webassemblyjs/wast-printer@1.9.0 +239 silly currentTree ├── @webpack-cli/info@1.1.0 +239 silly currentTree ├── @webpack-cli/serve@1.1.0 +239 silly currentTree ├── @xtuc/ieee754@1.2.0 +239 silly currentTree ├── @xtuc/long@4.2.2 +239 silly currentTree ├── abbrev@1.1.1 +239 silly currentTree ├── acorn@8.0.4 +239 silly currentTree ├── aes-js@3.1.2 +239 silly currentTree ├── ajv-keywords@3.5.2 +239 silly currentTree ├── ajv@6.12.6 +239 silly currentTree ├── ansi-colors@4.1.1 +239 silly currentTree ├── ansi-regex@2.1.1 +239 silly currentTree ├── ansi-styles@4.3.0 +239 silly currentTree ├── anymatch@3.1.1 +239 silly currentTree ├── aproba@1.2.0 +239 silly currentTree ├─┬ are-we-there-yet@1.1.5 +239 silly currentTree │ ├── readable-stream@2.3.7 +239 silly currentTree │ ├── safe-buffer@5.1.2 +239 silly currentTree │ └── string_decoder@1.1.1 +239 silly currentTree ├── arg@4.1.3 +239 silly currentTree ├── argparse@1.0.10 +239 silly currentTree ├── array-back@4.0.1 +239 silly currentTree ├── asn1.js@5.4.1 +239 silly currentTree ├── asn1@0.2.4 +239 silly currentTree ├── assert-plus@1.0.0 +239 silly currentTree ├── asynckit@0.4.0 +239 silly currentTree ├── automerge@0.14.1 +239 silly currentTree ├── aws-sign2@0.7.0 +239 silly currentTree ├── aws4@1.11.0 +239 silly currentTree ├── balanced-match@1.0.0 +239 silly currentTree ├── base-x@3.0.8 +239 silly currentTree ├── bcrypt-pbkdf@1.0.2 +239 silly currentTree ├── binary-extensions@2.1.0 +239 silly currentTree ├── blakejs@1.1.0 +239 silly currentTree ├── block-stream@0.0.9 +239 silly currentTree ├── bn.js@4.11.9 +239 silly currentTree ├── brace-expansion@1.1.11 +239 silly currentTree ├── braces@3.0.2 +239 silly currentTree ├── brorand@1.1.0 +239 silly currentTree ├── browser-stdout@1.3.1 +239 silly currentTree ├── browserify-aes@1.2.0 +239 silly currentTree ├── browserslist@4.14.6 +239 silly currentTree ├── bs58@4.0.1 +239 silly currentTree ├── bs58check@2.1.2 +239 silly currentTree ├── buffer-from@1.1.1 +239 silly currentTree ├── buffer-writer@2.0.0 +239 silly currentTree ├── buffer-xor@1.0.3 +239 silly currentTree ├── camelcase@5.3.1 +239 silly currentTree ├── caniuse-lite@1.0.30001156 +239 silly currentTree ├── caseless@0.12.0 +239 silly currentTree ├── chalk@4.1.0 +239 silly currentTree ├── chokidar@3.4.3 +239 silly currentTree ├── chownr@1.1.4 +239 silly currentTree ├── chrome-trace-event@1.0.2 +239 silly currentTree ├── cipher-base@1.0.4 +239 silly currentTree ├─┬ cliui@7.0.3 +239 silly currentTree │ ├── ansi-regex@5.0.0 +239 silly currentTree │ ├── is-fullwidth-code-point@3.0.0 +239 silly currentTree │ ├── string-width@4.2.0 +239 silly currentTree │ └── strip-ansi@6.0.0 +239 silly currentTree ├── code-point-at@1.1.0 +239 silly currentTree ├── color-convert@2.0.1 +239 silly currentTree ├── color-name@1.1.4 +239 silly currentTree ├── colorette@1.2.1 +239 silly currentTree ├── combined-stream@1.0.8 +239 silly currentTree ├─┬ command-line-usage@6.1.0 +239 silly currentTree │ ├── ansi-styles@3.2.1 +239 silly currentTree │ ├── chalk@2.4.2 +239 silly currentTree │ ├── color-convert@1.9.3 +239 silly currentTree │ ├── color-name@1.1.3 +239 silly currentTree │ ├── escape-string-regexp@1.0.5 +239 silly currentTree │ ├── has-flag@3.0.0 +239 silly currentTree │ └── supports-color@5.5.0 +239 silly currentTree ├── commander@2.20.3 +239 silly currentTree ├── concat-map@0.0.1 +239 silly currentTree ├── console-control-strings@1.1.0 +239 silly currentTree ├── core-util-is@1.0.2 +239 silly currentTree ├── crc-32@1.2.0 +239 silly currentTree ├── create-hash@1.2.0 +239 silly currentTree ├── create-hmac@1.1.7 +239 silly currentTree ├─┬ cross-spawn@7.0.3 +239 silly currentTree │ └── which@2.0.2 +239 silly currentTree ├── dashdash@1.14.1 +239 silly currentTree ├── debug@3.2.6 +239 silly currentTree ├── decamelize@1.2.0 +239 silly currentTree ├── deep-extend@0.6.0 +239 silly currentTree ├── delayed-stream@1.0.0 +239 silly currentTree ├── delegates@1.0.0 +239 silly currentTree ├── detect-libc@1.0.3 +239 silly currentTree ├── diff@4.0.2 +239 silly currentTree ├── ecc-jsbn@0.1.2 +239 silly currentTree ├── electron-to-chromium@1.3.591 +239 silly currentTree ├── elliptic@6.5.3 +239 silly currentTree ├── emoji-regex@8.0.0 +239 silly currentTree ├── end-of-stream@1.4.4 +239 silly currentTree ├── enhanced-resolve@5.3.1 +239 silly currentTree ├── enquirer@2.3.6 +239 silly currentTree ├── envinfo@7.7.3 +239 silly currentTree ├── escalade@3.1.1 +239 silly currentTree ├── escape-string-regexp@4.0.0 +239 silly currentTree ├── eslint-scope@5.1.1 +239 silly currentTree ├── esprima@4.0.1 +239 silly currentTree ├─┬ esrecurse@4.3.0 +239 silly currentTree │ └── estraverse@5.2.0 +239 silly currentTree ├── estraverse@4.3.0 +239 silly currentTree ├── ethereum-cryptography@0.1.3 +239 silly currentTree ├─┬ ethereumjs-util@7.0.7 +239 silly currentTree │ └── bn.js@5.1.3 +239 silly currentTree ├── ethereumjs-wallet@1.0.1 +239 silly currentTree ├── ethjs-util@0.1.6 +239 silly currentTree ├── events@3.2.0 +239 silly currentTree ├── evp_bytestokey@1.0.3 +239 silly currentTree ├── execa@4.1.0 +239 silly currentTree ├── exit-on-epipe@1.0.1 +239 silly currentTree ├── extend@3.0.2 +239 silly currentTree ├── extsprintf@1.3.0 +239 silly currentTree ├── fast-deep-equal@3.1.3 +239 silly currentTree ├── fast-json-stable-stringify@2.1.0 +239 silly currentTree ├── fill-range@7.0.1 +239 silly currentTree ├── find-up@5.0.0 +239 silly currentTree ├── flat@5.0.2 +239 silly currentTree ├── forever-agent@0.6.1 +239 silly currentTree ├── form-data@2.3.3 +239 silly currentTree ├── fs-minipass@1.2.7 +239 silly currentTree ├── fs.realpath@1.0.0 +239 silly currentTree ├── fstream@1.0.12 +239 silly currentTree ├── function-bind@1.1.1 +239 silly currentTree ├── gauge@2.7.4 +239 silly currentTree ├── get-caller-file@2.0.5 +239 silly currentTree ├── get-stream@5.2.0 +239 silly currentTree ├── getpass@0.1.7 +239 silly currentTree ├── glob-parent@5.1.1 +239 silly currentTree ├── glob-to-regexp@0.4.1 +239 silly currentTree ├── glob@7.1.6 +239 silly currentTree ├── graceful-fs@4.2.4 +239 silly currentTree ├── growl@1.10.5 +239 silly currentTree ├── har-schema@2.0.0 +239 silly currentTree ├── har-validator@5.1.5 +239 silly currentTree ├── has-flag@4.0.0 +239 silly currentTree ├── has-unicode@2.0.1 +239 silly currentTree ├── has@1.0.3 +239 silly currentTree ├── hash-base@3.1.0 +239 silly currentTree ├── hash.js@1.1.7 +239 silly currentTree ├── he@1.2.0 +239 silly currentTree ├── hmac-drbg@1.0.1 +239 silly currentTree ├── http-signature@1.2.0 +239 silly currentTree ├── human-signals@1.1.1 +239 silly currentTree ├── iconv-lite@0.4.24 +239 silly currentTree ├── ignore-walk@3.0.3 +239 silly currentTree ├── immutable@3.8.2 +239 silly currentTree ├── import-local@3.0.2 +239 silly currentTree ├── imurmurhash@0.1.4 +239 silly currentTree ├── inflight@1.0.6 +239 silly currentTree ├── inherits@2.0.4 +239 silly currentTree ├── ini@1.3.5 +239 silly currentTree ├── interpret@2.2.0 +239 silly currentTree ├── is-binary-path@2.1.0 +239 silly currentTree ├── is-core-module@2.1.0 +239 silly currentTree ├── is-extglob@2.1.1 +239 silly currentTree ├── is-fullwidth-code-point@1.0.0 +239 silly currentTree ├── is-glob@4.0.1 +239 silly currentTree ├── is-hex-prefixed@1.0.0 +239 silly currentTree ├── is-number@7.0.0 +239 silly currentTree ├── is-plain-obj@2.1.0 +239 silly currentTree ├── is-stream@2.0.0 +239 silly currentTree ├── is-typedarray@1.0.0 +239 silly currentTree ├── isarray@1.0.0 +239 silly currentTree ├── isexe@2.0.0 +239 silly currentTree ├── isstream@0.1.2 +239 silly currentTree ├── jest-worker@26.6.2 +239 silly currentTree ├── js-yaml@3.14.0 +239 silly currentTree ├── jsbn@0.1.1 +239 silly currentTree ├── json-parse-better-errors@1.0.2 +239 silly currentTree ├── json-schema-traverse@0.4.1 +239 silly currentTree ├── json-schema@0.2.3 +239 silly currentTree ├── json-stringify-safe@5.0.1 +239 silly currentTree ├── jsprim@1.4.1 +239 silly currentTree ├── keccak@3.0.1 +239 silly currentTree ├── leven@3.1.0 +239 silly currentTree ├── loader-runner@4.1.0 +239 silly currentTree ├── locate-path@6.0.0 +239 silly currentTree ├── lodash@4.17.20 +239 silly currentTree ├── log-symbols@4.0.0 +239 silly currentTree ├── make-error@1.3.6 +239 silly currentTree ├── md5.js@1.3.5 +239 silly currentTree ├── merge-stream@2.0.0 +239 silly currentTree ├── mime-db@1.44.0 +239 silly currentTree ├── mime-types@2.1.27 +239 silly currentTree ├── mimic-fn@2.1.0 +239 silly currentTree ├── minimalistic-assert@1.0.1 +239 silly currentTree ├── minimalistic-crypto-utils@1.0.1 +239 silly currentTree ├── minimatch@3.0.4 +239 silly currentTree ├── minimist@1.2.5 +239 silly currentTree ├── minipass@2.9.0 +239 silly currentTree ├── minizlib@1.3.3 +239 silly currentTree ├── mkdirp@0.5.5 +239 silly currentTree ├─┬ mocha@8.2.1 +239 silly currentTree │ ├── ansi-regex@4.1.0 +239 silly currentTree │ ├── ansi-styles@3.2.1 +239 silly currentTree │ ├── cliui@5.0.0 +239 silly currentTree │ ├── color-convert@1.9.3 +239 silly currentTree │ ├── color-name@1.1.3 +239 silly currentTree │ ├── debug@4.2.0 +239 silly currentTree │ ├── emoji-regex@7.0.3 +239 silly currentTree │ ├── is-fullwidth-code-point@2.0.0 +239 silly currentTree │ ├── locate-path@3.0.0 +239 silly currentTree │ ├── p-limit@2.3.0 +239 silly currentTree │ ├── p-locate@3.0.0 +239 silly currentTree │ ├── path-exists@3.0.0 +239 silly currentTree │ ├── string-width@3.1.0 +239 silly currentTree │ ├── strip-ansi@5.2.0 +239 silly currentTree │ ├── strip-json-comments@3.1.1 +239 silly currentTree │ ├── which@2.0.2 +239 silly currentTree │ ├── wrap-ansi@5.1.0 +239 silly currentTree │ ├── y18n@4.0.0 +239 silly currentTree │ ├── yargs-parser@13.1.2 +239 silly currentTree │ └─┬ yargs@13.3.2 +239 silly currentTree │ └── find-up@3.0.0 +239 silly currentTree ├── ms@2.1.2 +239 silly currentTree ├── nanoid@3.1.12 +239 silly currentTree ├── needle@2.5.2 +239 silly currentTree ├── neo-async@2.6.2 +239 silly currentTree ├── node-addon-api@2.0.0 +239 silly currentTree ├── node-fetch@2.6.1 +239 silly currentTree ├── node-gyp-build@4.2.3 +239 silly currentTree ├── node-gyp@3.8.0 +239 silly currentTree ├── node-localstorage@2.1.6 +239 silly currentTree ├─┬ node-pre-gyp@0.11.0 +239 silly currentTree │ ├── nopt@4.0.3 +239 silly currentTree │ └── tar@4.4.13 +239 silly currentTree ├── node-releases@1.1.66 +239 silly currentTree ├── nopt@3.0.6 +239 silly currentTree ├── normalize-path@3.0.0 +239 silly currentTree ├── npm-bundled@1.1.1 +239 silly currentTree ├── npm-normalize-package-bin@1.0.1 +239 silly currentTree ├── npm-packlist@1.4.8 +239 silly currentTree ├── npm-run-path@4.0.1 +239 silly currentTree ├── npmlog@4.1.2 +239 silly currentTree ├── number-is-nan@1.0.1 +239 silly currentTree ├── oauth-sign@0.9.0 +239 silly currentTree ├── object-assign@4.1.1 +239 silly currentTree ├── once@1.4.0 +239 silly currentTree ├── onetime@5.1.2 +239 silly currentTree ├─┬ openpgp@4.10.8 +239 silly currentTree │ └── node-localstorage@1.3.1 +239 silly currentTree ├── os-homedir@1.0.2 +239 silly currentTree ├── os-tmpdir@1.0.2 +239 silly currentTree ├── osenv@0.1.5 +239 silly currentTree ├── p-limit@3.0.2 +239 silly currentTree ├── p-locate@5.0.0 +239 silly currentTree ├── p-try@2.2.0 +239 silly currentTree ├── packet-reader@1.0.0 +239 silly currentTree ├── path-exists@4.0.0 +239 silly currentTree ├── path-is-absolute@1.0.1 +239 silly currentTree ├── path-key@3.1.1 +239 silly currentTree ├── path-parse@1.0.6 +239 silly currentTree ├── pbkdf2@3.1.1 +239 silly currentTree ├── performance-now@2.1.0 +239 silly currentTree ├── pg-connection-string@2.4.0 +239 silly currentTree ├── pg-int8@1.0.1 +239 silly currentTree ├── pg-pool@3.2.2 +239 silly currentTree ├── pg-protocol@1.3.0 +239 silly currentTree ├── pg-types@2.2.0 +239 silly currentTree ├── pg@8.4.2 +239 silly currentTree ├── pgpass@1.0.4 +239 silly currentTree ├── picomatch@2.2.2 +239 silly currentTree ├─┬ pkg-dir@4.2.0 +239 silly currentTree │ ├── find-up@4.1.0 +239 silly currentTree │ ├── locate-path@5.0.0 +239 silly currentTree │ ├── p-limit@2.3.0 +239 silly currentTree │ └── p-locate@4.1.0 +239 silly currentTree ├── postgres-array@2.0.0 +239 silly currentTree ├── postgres-bytea@1.0.0 +239 silly currentTree ├── postgres-date@1.0.7 +239 silly currentTree ├── postgres-interval@1.2.0 +239 silly currentTree ├── printj@1.1.2 +239 silly currentTree ├── process-nextick-args@2.0.1 +239 silly currentTree ├── psl@1.8.0 +239 silly currentTree ├── pump@3.0.0 +239 silly currentTree ├── punycode@2.1.1 +239 silly currentTree ├── qs@6.5.2 +239 silly currentTree ├── randombytes@2.1.0 +239 silly currentTree ├── rc@1.2.8 +239 silly currentTree ├── readable-stream@3.6.0 +239 silly currentTree ├── readdirp@3.5.0 +239 silly currentTree ├── rechoir@0.7.0 +239 silly currentTree ├── reduce-flatten@2.0.0 +239 silly currentTree ├── request@2.88.2 +239 silly currentTree ├── require-directory@2.1.1 +239 silly currentTree ├── require-main-filename@2.0.0 +239 silly currentTree ├── resolve-cwd@3.0.0 +239 silly currentTree ├── resolve-from@5.0.0 +239 silly currentTree ├── resolve@1.18.1 +239 silly currentTree ├── rimraf@2.7.1 +239 silly currentTree ├── ripemd160@2.0.2 +239 silly currentTree ├── rlp@2.2.6 +239 silly currentTree ├── safe-buffer@5.2.1 +239 silly currentTree ├── safer-buffer@2.1.2 +239 silly currentTree ├── sax@1.2.4 +239 silly currentTree ├── schema-utils@3.0.0 +239 silly currentTree ├── scrypt-js@3.0.1 +239 silly currentTree ├── secp256k1@4.0.2 +239 silly currentTree ├── semver@5.3.0 +239 silly currentTree ├── serialize-javascript@5.0.1 +239 silly currentTree ├── set-blocking@2.0.0 +239 silly currentTree ├── setimmediate@1.0.5 +239 silly currentTree ├── sha.js@2.4.11 +239 silly currentTree ├── shebang-command@2.0.0 +239 silly currentTree ├── shebang-regex@3.0.0 +239 silly currentTree ├── signal-exit@3.0.3 +239 silly currentTree ├── slide@1.1.6 +239 silly currentTree ├── source-list-map@2.0.1 +239 silly currentTree ├── source-map-support@0.5.19 +239 silly currentTree ├── source-map@0.6.1 +239 silly currentTree ├── split2@3.2.2 +239 silly currentTree ├── sprintf-js@1.0.3 +239 silly currentTree ├── sqlite3@5.0.0 +239 silly currentTree ├── sshpk@1.16.1 +239 silly currentTree ├── string_decoder@1.3.0 +239 silly currentTree ├── string-width@1.0.2 +239 silly currentTree ├── strip-ansi@3.0.1 +239 silly currentTree ├── strip-final-newline@2.0.0 +239 silly currentTree ├── strip-hex-prefix@1.0.0 +239 silly currentTree ├── strip-json-comments@2.0.1 +239 silly currentTree ├── supports-color@7.2.0 +239 silly currentTree ├── table-layout@1.0.1 +239 silly currentTree ├── tapable@2.0.0 +239 silly currentTree ├── tar@2.2.2 +239 silly currentTree ├── terser-webpack-plugin@5.0.3 +239 silly currentTree ├─┬ terser@5.3.8 +239 silly currentTree │ └── source-map@0.7.3 +239 silly currentTree ├── to-regex-range@5.0.1 +239 silly currentTree ├── tough-cookie@2.5.0 +239 silly currentTree ├── transit-immutable-js@0.7.0 +239 silly currentTree ├── transit-js@0.8.867 +239 silly currentTree ├── ts-node@9.0.0 +239 silly currentTree ├── tslib@1.14.1 +239 silly currentTree ├── tunnel-agent@0.6.0 +239 silly currentTree ├── tweetnacl@0.14.5 +239 silly currentTree ├── typescript@4.0.5 +239 silly currentTree ├── typical@5.2.0 +239 silly currentTree ├── uri-js@4.4.0 +239 silly currentTree ├── utf8@3.0.0 +239 silly currentTree ├── util-deprecate@1.0.2 +239 silly currentTree ├── uuid@3.4.0 +239 silly currentTree ├── v8-compile-cache@2.2.0 +239 silly currentTree ├── verror@1.10.0 +239 silly currentTree ├── watchpack@2.0.1 +239 silly currentTree ├─┬ webpack-cli@4.2.0 +239 silly currentTree │ └── commander@6.2.0 +239 silly currentTree ├── webpack-merge@4.2.2 +239 silly currentTree ├── webpack-sources@2.2.0 +239 silly currentTree ├── webpack@5.4.0 +239 silly currentTree ├── which-module@2.0.0 +239 silly currentTree ├── which@1.3.1 +239 silly currentTree ├── wide-align@1.1.3 +239 silly currentTree ├── wordwrapjs@4.0.0 +239 silly currentTree ├── workerpool@6.0.2 +239 silly currentTree ├─┬ wrap-ansi@7.0.0 +239 silly currentTree │ ├── ansi-regex@5.0.0 +239 silly currentTree │ ├── is-fullwidth-code-point@3.0.0 +239 silly currentTree │ ├── string-width@4.2.0 +239 silly currentTree │ └── strip-ansi@6.0.0 +239 silly currentTree ├── wrappy@1.0.2 +239 silly currentTree ├── write-file-atomic@1.3.4 +239 silly currentTree ├── xtend@4.0.2 +239 silly currentTree ├── y18n@5.0.5 +239 silly currentTree ├── yallist@3.1.1 +239 silly currentTree ├── yargs-parser@20.2.3 +239 silly currentTree ├─┬ yargs-unparser@2.0.0 +239 silly currentTree │ ├── camelcase@6.2.0 +239 silly currentTree │ └── decamelize@4.0.0 +239 silly currentTree ├─┬ yargs@16.1.0 +239 silly currentTree │ ├── ansi-regex@5.0.0 +239 silly currentTree │ ├── is-fullwidth-code-point@3.0.0 +239 silly currentTree │ ├── string-width@4.2.0 +239 silly currentTree │ └── strip-ansi@6.0.0 +239 silly currentTree └── yn@3.1.1 +240 silly idealTree scripts +240 silly idealTree └─┬ cic-client-meta@0.0.7-alpha.1 +240 silly idealTree ├── @ethereumjs/common@2.0.0-beta.1 +240 silly idealTree ├── @ethereumjs/tx@3.0.0-beta.1 +240 silly idealTree ├── @types/bn.js@4.11.6 +240 silly idealTree ├── @types/eslint-scope@3.7.0 +240 silly idealTree ├── @types/eslint@7.2.4 +240 silly idealTree ├── @types/estree@0.0.45 +240 silly idealTree ├── @types/json-schema@7.0.6 +240 silly idealTree ├── @types/mocha@8.0.3 +240 silly idealTree ├── @types/node@14.14.6 +240 silly idealTree ├── @types/pbkdf2@3.1.0 +240 silly idealTree ├── @types/secp256k1@4.0.1 +240 silly idealTree ├── @ungap/promise-all-settled@1.1.2 +240 silly idealTree ├── @webassemblyjs/ast@1.9.0 +240 silly idealTree ├── @webassemblyjs/floating-point-hex-parser@1.9.0 +240 silly idealTree ├── @webassemblyjs/helper-api-error@1.9.0 +240 silly idealTree ├── @webassemblyjs/helper-buffer@1.9.0 +240 silly idealTree ├── @webassemblyjs/helper-code-frame@1.9.0 +240 silly idealTree ├── @webassemblyjs/helper-fsm@1.9.0 +240 silly idealTree ├── @webassemblyjs/helper-module-context@1.9.0 +240 silly idealTree ├── @webassemblyjs/helper-wasm-bytecode@1.9.0 +240 silly idealTree ├── @webassemblyjs/helper-wasm-section@1.9.0 +240 silly idealTree ├── @webassemblyjs/ieee754@1.9.0 +240 silly idealTree ├── @webassemblyjs/leb128@1.9.0 +240 silly idealTree ├── @webassemblyjs/utf8@1.9.0 +240 silly idealTree ├── @webassemblyjs/wasm-edit@1.9.0 +240 silly idealTree ├── @webassemblyjs/wasm-gen@1.9.0 +240 silly idealTree ├── @webassemblyjs/wasm-opt@1.9.0 +240 silly idealTree ├── @webassemblyjs/wasm-parser@1.9.0 +240 silly idealTree ├── @webassemblyjs/wast-parser@1.9.0 +240 silly idealTree ├── @webassemblyjs/wast-printer@1.9.0 +240 silly idealTree ├── @webpack-cli/info@1.1.0 +240 silly idealTree ├── @webpack-cli/serve@1.1.0 +240 silly idealTree ├── @xtuc/ieee754@1.2.0 +240 silly idealTree ├── @xtuc/long@4.2.2 +240 silly idealTree ├── abbrev@1.1.1 +240 silly idealTree ├── acorn@8.0.4 +240 silly idealTree ├── aes-js@3.1.2 +240 silly idealTree ├── ajv-keywords@3.5.2 +240 silly idealTree ├── ajv@6.12.6 +240 silly idealTree ├── ansi-colors@4.1.1 +240 silly idealTree ├── ansi-regex@2.1.1 +240 silly idealTree ├── ansi-styles@4.3.0 +240 silly idealTree ├── anymatch@3.1.1 +240 silly idealTree ├── aproba@1.2.0 +240 silly idealTree ├─┬ are-we-there-yet@1.1.5 +240 silly idealTree │ ├── readable-stream@2.3.7 +240 silly idealTree │ ├── safe-buffer@5.1.2 +240 silly idealTree │ └── string_decoder@1.1.1 +240 silly idealTree ├── arg@4.1.3 +240 silly idealTree ├── argparse@1.0.10 +240 silly idealTree ├── array-back@4.0.1 +240 silly idealTree ├── asn1.js@5.4.1 +240 silly idealTree ├── asn1@0.2.4 +240 silly idealTree ├── assert-plus@1.0.0 +240 silly idealTree ├── asynckit@0.4.0 +240 silly idealTree ├── automerge@0.14.1 +240 silly idealTree ├── aws-sign2@0.7.0 +240 silly idealTree ├── aws4@1.11.0 +240 silly idealTree ├── balanced-match@1.0.0 +240 silly idealTree ├── base-x@3.0.8 +240 silly idealTree ├── bcrypt-pbkdf@1.0.2 +240 silly idealTree ├── binary-extensions@2.1.0 +240 silly idealTree ├── blakejs@1.1.0 +240 silly idealTree ├── block-stream@0.0.9 +240 silly idealTree ├── bn.js@4.11.9 +240 silly idealTree ├── brace-expansion@1.1.11 +240 silly idealTree ├── braces@3.0.2 +240 silly idealTree ├── brorand@1.1.0 +240 silly idealTree ├── browser-stdout@1.3.1 +240 silly idealTree ├── browserify-aes@1.2.0 +240 silly idealTree ├── browserslist@4.14.6 +240 silly idealTree ├── bs58@4.0.1 +240 silly idealTree ├── bs58check@2.1.2 +240 silly idealTree ├── buffer-from@1.1.1 +240 silly idealTree ├── buffer-writer@2.0.0 +240 silly idealTree ├── buffer-xor@1.0.3 +240 silly idealTree ├── camelcase@5.3.1 +240 silly idealTree ├── caniuse-lite@1.0.30001156 +240 silly idealTree ├── caseless@0.12.0 +240 silly idealTree ├── chalk@4.1.0 +240 silly idealTree ├── chokidar@3.4.3 +240 silly idealTree ├── chownr@1.1.4 +240 silly idealTree ├── chrome-trace-event@1.0.2 +240 silly idealTree ├── cipher-base@1.0.4 +240 silly idealTree ├─┬ cliui@7.0.3 +240 silly idealTree │ ├── ansi-regex@5.0.0 +240 silly idealTree │ ├── is-fullwidth-code-point@3.0.0 +240 silly idealTree │ ├── string-width@4.2.0 +240 silly idealTree │ └── strip-ansi@6.0.0 +240 silly idealTree ├── code-point-at@1.1.0 +240 silly idealTree ├── color-convert@2.0.1 +240 silly idealTree ├── color-name@1.1.4 +240 silly idealTree ├── colorette@1.2.1 +240 silly idealTree ├── combined-stream@1.0.8 +240 silly idealTree ├─┬ command-line-usage@6.1.0 +240 silly idealTree │ ├── ansi-styles@3.2.1 +240 silly idealTree │ ├── chalk@2.4.2 +240 silly idealTree │ ├── color-convert@1.9.3 +240 silly idealTree │ ├── color-name@1.1.3 +240 silly idealTree │ ├── escape-string-regexp@1.0.5 +240 silly idealTree │ ├── has-flag@3.0.0 +240 silly idealTree │ └── supports-color@5.5.0 +240 silly idealTree ├── commander@2.20.3 +240 silly idealTree ├── concat-map@0.0.1 +240 silly idealTree ├── console-control-strings@1.1.0 +240 silly idealTree ├── core-util-is@1.0.2 +240 silly idealTree ├── crc-32@1.2.0 +240 silly idealTree ├── create-hash@1.2.0 +240 silly idealTree ├── create-hmac@1.1.7 +240 silly idealTree ├─┬ cross-spawn@7.0.3 +240 silly idealTree │ └── which@2.0.2 +240 silly idealTree ├── dashdash@1.14.1 +240 silly idealTree ├── debug@3.2.6 +240 silly idealTree ├── decamelize@1.2.0 +240 silly idealTree ├── deep-extend@0.6.0 +240 silly idealTree ├── delayed-stream@1.0.0 +240 silly idealTree ├── delegates@1.0.0 +240 silly idealTree ├── detect-libc@1.0.3 +240 silly idealTree ├── diff@4.0.2 +240 silly idealTree ├── ecc-jsbn@0.1.2 +240 silly idealTree ├── electron-to-chromium@1.3.591 +240 silly idealTree ├── elliptic@6.5.3 +240 silly idealTree ├── emoji-regex@8.0.0 +240 silly idealTree ├── end-of-stream@1.4.4 +240 silly idealTree ├── enhanced-resolve@5.3.1 +240 silly idealTree ├── enquirer@2.3.6 +240 silly idealTree ├── envinfo@7.7.3 +240 silly idealTree ├── escalade@3.1.1 +240 silly idealTree ├── escape-string-regexp@4.0.0 +240 silly idealTree ├── eslint-scope@5.1.1 +240 silly idealTree ├── esprima@4.0.1 +240 silly idealTree ├─┬ esrecurse@4.3.0 +240 silly idealTree │ └── estraverse@5.2.0 +240 silly idealTree ├── estraverse@4.3.0 +240 silly idealTree ├── ethereum-cryptography@0.1.3 +240 silly idealTree ├─┬ ethereumjs-util@7.0.7 +240 silly idealTree │ └── bn.js@5.1.3 +240 silly idealTree ├── ethereumjs-wallet@1.0.1 +240 silly idealTree ├── ethjs-util@0.1.6 +240 silly idealTree ├── events@3.2.0 +240 silly idealTree ├── evp_bytestokey@1.0.3 +240 silly idealTree ├── execa@4.1.0 +240 silly idealTree ├── exit-on-epipe@1.0.1 +240 silly idealTree ├── extend@3.0.2 +240 silly idealTree ├── extsprintf@1.3.0 +240 silly idealTree ├── fast-deep-equal@3.1.3 +240 silly idealTree ├── fast-json-stable-stringify@2.1.0 +240 silly idealTree ├── fill-range@7.0.1 +240 silly idealTree ├── find-up@5.0.0 +240 silly idealTree ├── flat@5.0.2 +240 silly idealTree ├── forever-agent@0.6.1 +240 silly idealTree ├── form-data@2.3.3 +240 silly idealTree ├── fs-minipass@1.2.7 +240 silly idealTree ├── fs.realpath@1.0.0 +240 silly idealTree ├── fstream@1.0.12 +240 silly idealTree ├── function-bind@1.1.1 +240 silly idealTree ├── gauge@2.7.4 +240 silly idealTree ├── get-caller-file@2.0.5 +240 silly idealTree ├── get-stream@5.2.0 +240 silly idealTree ├── getpass@0.1.7 +240 silly idealTree ├── glob-parent@5.1.1 +240 silly idealTree ├── glob-to-regexp@0.4.1 +240 silly idealTree ├── glob@7.1.6 +240 silly idealTree ├── graceful-fs@4.2.4 +240 silly idealTree ├── growl@1.10.5 +240 silly idealTree ├── har-schema@2.0.0 +240 silly idealTree ├── har-validator@5.1.5 +240 silly idealTree ├── has-flag@4.0.0 +240 silly idealTree ├── has-unicode@2.0.1 +240 silly idealTree ├── has@1.0.3 +240 silly idealTree ├── hash-base@3.1.0 +240 silly idealTree ├── hash.js@1.1.7 +240 silly idealTree ├── he@1.2.0 +240 silly idealTree ├── hmac-drbg@1.0.1 +240 silly idealTree ├── http-signature@1.2.0 +240 silly idealTree ├── human-signals@1.1.1 +240 silly idealTree ├── iconv-lite@0.4.24 +240 silly idealTree ├── ignore-walk@3.0.3 +240 silly idealTree ├── immutable@3.8.2 +240 silly idealTree ├── import-local@3.0.2 +240 silly idealTree ├── imurmurhash@0.1.4 +240 silly idealTree ├── inflight@1.0.6 +240 silly idealTree ├── inherits@2.0.4 +240 silly idealTree ├── ini@1.3.5 +240 silly idealTree ├── interpret@2.2.0 +240 silly idealTree ├── is-binary-path@2.1.0 +240 silly idealTree ├── is-core-module@2.1.0 +240 silly idealTree ├── is-extglob@2.1.1 +240 silly idealTree ├── is-fullwidth-code-point@1.0.0 +240 silly idealTree ├── is-glob@4.0.1 +240 silly idealTree ├── is-hex-prefixed@1.0.0 +240 silly idealTree ├── is-number@7.0.0 +240 silly idealTree ├── is-plain-obj@2.1.0 +240 silly idealTree ├── is-stream@2.0.0 +240 silly idealTree ├── is-typedarray@1.0.0 +240 silly idealTree ├── isarray@1.0.0 +240 silly idealTree ├── isexe@2.0.0 +240 silly idealTree ├── isstream@0.1.2 +240 silly idealTree ├── jest-worker@26.6.2 +240 silly idealTree ├── js-yaml@3.14.0 +240 silly idealTree ├── jsbn@0.1.1 +240 silly idealTree ├── json-parse-better-errors@1.0.2 +240 silly idealTree ├── json-schema-traverse@0.4.1 +240 silly idealTree ├── json-schema@0.2.3 +240 silly idealTree ├── json-stringify-safe@5.0.1 +240 silly idealTree ├── jsprim@1.4.1 +240 silly idealTree ├── keccak@3.0.1 +240 silly idealTree ├── leven@3.1.0 +240 silly idealTree ├── loader-runner@4.1.0 +240 silly idealTree ├── locate-path@6.0.0 +240 silly idealTree ├── lodash@4.17.20 +240 silly idealTree ├── log-symbols@4.0.0 +240 silly idealTree ├── make-error@1.3.6 +240 silly idealTree ├── md5.js@1.3.5 +240 silly idealTree ├── merge-stream@2.0.0 +240 silly idealTree ├── mime-db@1.44.0 +240 silly idealTree ├── mime-types@2.1.27 +240 silly idealTree ├── mimic-fn@2.1.0 +240 silly idealTree ├── minimalistic-assert@1.0.1 +240 silly idealTree ├── minimalistic-crypto-utils@1.0.1 +240 silly idealTree ├── minimatch@3.0.4 +240 silly idealTree ├── minimist@1.2.5 +240 silly idealTree ├── minipass@2.9.0 +240 silly idealTree ├── minizlib@1.3.3 +240 silly idealTree ├── mkdirp@0.5.5 +240 silly idealTree ├─┬ mocha@8.2.1 +240 silly idealTree │ ├── ansi-regex@4.1.0 +240 silly idealTree │ ├── ansi-styles@3.2.1 +240 silly idealTree │ ├── cliui@5.0.0 +240 silly idealTree │ ├── color-convert@1.9.3 +240 silly idealTree │ ├── color-name@1.1.3 +240 silly idealTree │ ├── debug@4.2.0 +240 silly idealTree │ ├── emoji-regex@7.0.3 +240 silly idealTree │ ├── is-fullwidth-code-point@2.0.0 +240 silly idealTree │ ├── locate-path@3.0.0 +240 silly idealTree │ ├── p-limit@2.3.0 +240 silly idealTree │ ├── p-locate@3.0.0 +240 silly idealTree │ ├── path-exists@3.0.0 +240 silly idealTree │ ├── string-width@3.1.0 +240 silly idealTree │ ├── strip-ansi@5.2.0 +240 silly idealTree │ ├── strip-json-comments@3.1.1 +240 silly idealTree │ ├── which@2.0.2 +240 silly idealTree │ ├── wrap-ansi@5.1.0 +240 silly idealTree │ ├── y18n@4.0.0 +240 silly idealTree │ ├── yargs-parser@13.1.2 +240 silly idealTree │ └─┬ yargs@13.3.2 +240 silly idealTree │ └── find-up@3.0.0 +240 silly idealTree ├── ms@2.1.2 +240 silly idealTree ├── nanoid@3.1.12 +240 silly idealTree ├── needle@2.5.2 +240 silly idealTree ├── neo-async@2.6.2 +240 silly idealTree ├── node-addon-api@2.0.0 +240 silly idealTree ├── node-fetch@2.6.1 +240 silly idealTree ├── node-gyp-build@4.2.3 +240 silly idealTree ├── node-gyp@3.8.0 +240 silly idealTree ├── node-localstorage@2.1.6 +240 silly idealTree ├─┬ node-pre-gyp@0.11.0 +240 silly idealTree │ ├── nopt@4.0.3 +240 silly idealTree │ └── tar@4.4.13 +240 silly idealTree ├── node-releases@1.1.66 +240 silly idealTree ├── nopt@3.0.6 +240 silly idealTree ├── normalize-path@3.0.0 +240 silly idealTree ├── npm-bundled@1.1.1 +240 silly idealTree ├── npm-normalize-package-bin@1.0.1 +240 silly idealTree ├── npm-packlist@1.4.8 +240 silly idealTree ├── npm-run-path@4.0.1 +240 silly idealTree ├── npmlog@4.1.2 +240 silly idealTree ├── number-is-nan@1.0.1 +240 silly idealTree ├── oauth-sign@0.9.0 +240 silly idealTree ├── object-assign@4.1.1 +240 silly idealTree ├── once@1.4.0 +240 silly idealTree ├── onetime@5.1.2 +240 silly idealTree ├─┬ openpgp@4.10.8 +240 silly idealTree │ └── node-localstorage@1.3.1 +240 silly idealTree ├── os-homedir@1.0.2 +240 silly idealTree ├── os-tmpdir@1.0.2 +240 silly idealTree ├── osenv@0.1.5 +240 silly idealTree ├── p-limit@3.0.2 +240 silly idealTree ├── p-locate@5.0.0 +240 silly idealTree ├── p-try@2.2.0 +240 silly idealTree ├── packet-reader@1.0.0 +240 silly idealTree ├── path-exists@4.0.0 +240 silly idealTree ├── path-is-absolute@1.0.1 +240 silly idealTree ├── path-key@3.1.1 +240 silly idealTree ├── path-parse@1.0.6 +240 silly idealTree ├── pbkdf2@3.1.1 +240 silly idealTree ├── performance-now@2.1.0 +240 silly idealTree ├── pg-connection-string@2.4.0 +240 silly idealTree ├── pg-int8@1.0.1 +240 silly idealTree ├── pg-pool@3.2.2 +240 silly idealTree ├── pg-protocol@1.3.0 +240 silly idealTree ├── pg-types@2.2.0 +240 silly idealTree ├── pg@8.4.2 +240 silly idealTree ├── pgpass@1.0.4 +240 silly idealTree ├── picomatch@2.2.2 +240 silly idealTree ├─┬ pkg-dir@4.2.0 +240 silly idealTree │ ├── find-up@4.1.0 +240 silly idealTree │ ├── locate-path@5.0.0 +240 silly idealTree │ ├── p-limit@2.3.0 +240 silly idealTree │ └── p-locate@4.1.0 +240 silly idealTree ├── postgres-array@2.0.0 +240 silly idealTree ├── postgres-bytea@1.0.0 +240 silly idealTree ├── postgres-date@1.0.7 +240 silly idealTree ├── postgres-interval@1.2.0 +240 silly idealTree ├── printj@1.1.2 +240 silly idealTree ├── process-nextick-args@2.0.1 +240 silly idealTree ├── psl@1.8.0 +240 silly idealTree ├── pump@3.0.0 +240 silly idealTree ├── punycode@2.1.1 +240 silly idealTree ├── qs@6.5.2 +240 silly idealTree ├── randombytes@2.1.0 +240 silly idealTree ├── rc@1.2.8 +240 silly idealTree ├── readable-stream@3.6.0 +240 silly idealTree ├── readdirp@3.5.0 +240 silly idealTree ├── rechoir@0.7.0 +240 silly idealTree ├── reduce-flatten@2.0.0 +240 silly idealTree ├── request@2.88.2 +240 silly idealTree ├── require-directory@2.1.1 +240 silly idealTree ├── require-main-filename@2.0.0 +240 silly idealTree ├── resolve-cwd@3.0.0 +240 silly idealTree ├── resolve-from@5.0.0 +240 silly idealTree ├── resolve@1.18.1 +240 silly idealTree ├── rimraf@2.7.1 +240 silly idealTree ├── ripemd160@2.0.2 +240 silly idealTree ├── rlp@2.2.6 +240 silly idealTree ├── safe-buffer@5.2.1 +240 silly idealTree ├── safer-buffer@2.1.2 +240 silly idealTree ├── sax@1.2.4 +240 silly idealTree ├── schema-utils@3.0.0 +240 silly idealTree ├── scrypt-js@3.0.1 +240 silly idealTree ├── secp256k1@4.0.2 +240 silly idealTree ├── semver@5.3.0 +240 silly idealTree ├── serialize-javascript@5.0.1 +240 silly idealTree ├── set-blocking@2.0.0 +240 silly idealTree ├── setimmediate@1.0.5 +240 silly idealTree ├── sha.js@2.4.11 +240 silly idealTree ├── shebang-command@2.0.0 +240 silly idealTree ├── shebang-regex@3.0.0 +240 silly idealTree ├── signal-exit@3.0.3 +240 silly idealTree ├── slide@1.1.6 +240 silly idealTree ├── source-list-map@2.0.1 +240 silly idealTree ├── source-map-support@0.5.19 +240 silly idealTree ├── source-map@0.6.1 +240 silly idealTree ├── split2@3.2.2 +240 silly idealTree ├── sprintf-js@1.0.3 +240 silly idealTree ├── sqlite3@5.0.0 +240 silly idealTree ├── sshpk@1.16.1 +240 silly idealTree ├── string_decoder@1.3.0 +240 silly idealTree ├── string-width@1.0.2 +240 silly idealTree ├── strip-ansi@3.0.1 +240 silly idealTree ├── strip-final-newline@2.0.0 +240 silly idealTree ├── strip-hex-prefix@1.0.0 +240 silly idealTree ├── strip-json-comments@2.0.1 +240 silly idealTree ├── supports-color@7.2.0 +240 silly idealTree ├── table-layout@1.0.1 +240 silly idealTree ├── tapable@2.0.0 +240 silly idealTree ├── tar@2.2.2 +240 silly idealTree ├── terser-webpack-plugin@5.0.3 +240 silly idealTree ├─┬ terser@5.3.8 +240 silly idealTree │ └── source-map@0.7.3 +240 silly idealTree ├── to-regex-range@5.0.1 +240 silly idealTree ├── tough-cookie@2.5.0 +240 silly idealTree ├── transit-immutable-js@0.7.0 +240 silly idealTree ├── transit-js@0.8.867 +240 silly idealTree ├── ts-node@9.0.0 +240 silly idealTree ├── tslib@1.14.1 +240 silly idealTree ├── tunnel-agent@0.6.0 +240 silly idealTree ├── tweetnacl@0.14.5 +240 silly idealTree ├── typescript@4.0.5 +240 silly idealTree ├── typical@5.2.0 +240 silly idealTree ├── uri-js@4.4.0 +240 silly idealTree ├── utf8@3.0.0 +240 silly idealTree ├── util-deprecate@1.0.2 +240 silly idealTree ├── uuid@3.4.0 +240 silly idealTree ├── v8-compile-cache@2.2.0 +240 silly idealTree ├── verror@1.10.0 +240 silly idealTree ├── watchpack@2.0.1 +240 silly idealTree ├─┬ webpack-cli@4.2.0 +240 silly idealTree │ └── commander@6.2.0 +240 silly idealTree ├── webpack-merge@4.2.2 +240 silly idealTree ├── webpack-sources@2.2.0 +240 silly idealTree ├── webpack@5.4.0 +240 silly idealTree ├── which-module@2.0.0 +240 silly idealTree ├── which@1.3.1 +240 silly idealTree ├── wide-align@1.1.3 +240 silly idealTree ├── wordwrapjs@4.0.0 +240 silly idealTree ├── workerpool@6.0.2 +240 silly idealTree ├─┬ wrap-ansi@7.0.0 +240 silly idealTree │ ├── ansi-regex@5.0.0 +240 silly idealTree │ ├── is-fullwidth-code-point@3.0.0 +240 silly idealTree │ ├── string-width@4.2.0 +240 silly idealTree │ └── strip-ansi@6.0.0 +240 silly idealTree ├── wrappy@1.0.2 +240 silly idealTree ├── write-file-atomic@1.3.4 +240 silly idealTree ├── xtend@4.0.2 +240 silly idealTree ├── y18n@5.0.5 +240 silly idealTree ├── yallist@3.1.1 +240 silly idealTree ├── yargs-parser@20.2.3 +240 silly idealTree ├─┬ yargs-unparser@2.0.0 +240 silly idealTree │ ├── camelcase@6.2.0 +240 silly idealTree │ └── decamelize@4.0.0 +240 silly idealTree ├─┬ yargs@16.1.0 +240 silly idealTree │ ├── ansi-regex@5.0.0 +240 silly idealTree │ ├── is-fullwidth-code-point@3.0.0 +240 silly idealTree │ ├── string-width@4.2.0 +240 silly idealTree │ └── strip-ansi@6.0.0 +240 silly idealTree └── yn@3.1.1 +241 silly install generateActionsToTake +242 timing stage:generateActionsToTake Completed in 13ms +243 silly diffTrees action count 1 +244 silly diffTrees update cic-client-meta@0.0.7-alpha.1 +245 silly decomposeActions action count 8 +246 silly decomposeActions unbuild cic-client-meta@0.0.7-alpha.1 +247 silly decomposeActions remove cic-client-meta@0.0.7-alpha.1 +248 silly decomposeActions preinstall cic-client-meta@0.0.7-alpha.1 +249 silly decomposeActions build cic-client-meta@0.0.7-alpha.1 +250 silly decomposeActions install cic-client-meta@0.0.7-alpha.1 +251 silly decomposeActions postinstall cic-client-meta@0.0.7-alpha.1 +252 silly decomposeActions finalize cic-client-meta@0.0.7-alpha.1 +253 silly decomposeActions refresh-package-json cic-client-meta@0.0.7-alpha.1 +254 silly install executeActions +255 silly doSerial global-install 8 +256 verbose correctMkdir /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/false/_locks correctMkdir not in flight; initializing +257 verbose lock using /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/false/_locks/staging-5da34164c06d3d08.lock for /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/node_modules/.staging +258 silly doParallel extract 0 +259 silly doReverseSerial unbuild 8 +260 silly unbuild cic-client-meta@0.0.7-alpha.1 +261 info lifecycle cic-client-meta@0.0.7-alpha.1~preuninstall: cic-client-meta@0.0.7-alpha.1 +262 info lifecycle cic-client-meta@0.0.7-alpha.1~uninstall: cic-client-meta@0.0.7-alpha.1 +263 verbose unbuild rmStuff cic-client-meta@0.0.7-alpha.1 from /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/node_modules +264 silly isEverInside /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/node_modules/cic-client-meta is not inside /usr +265 silly isEverInside /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/cic-meta is not inside /usr +266 silly isEverInside /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/node_modules/cic-client-meta is not inside /usr/bin +267 silly isEverInside /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/cic-meta is not inside /usr/bin +268 silly isEverInside /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/node_modules/cic-client-meta is not inside /usr/lib/node_modules +269 silly isEverInside /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/cic-meta is not inside /usr/lib/node_modules +270 info lifecycle cic-client-meta@0.0.7-alpha.1~postuninstall: cic-client-meta@0.0.7-alpha.1 +271 timing action:unbuild Completed in 5ms +272 silly doSerial remove 8 +273 silly remove /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/node_modules/cic-client-meta +274 timing action:remove Completed in 1ms +275 silly doSerial move 8 +276 silly doSerial finalize 8 +277 silly finalize /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/cic-meta +278 timing action:finalize Completed in 0ms +279 silly doParallel refresh-package-json 1 +280 silly refresh-package-json /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/cic-meta +281 timing action:refresh-package-json Completed in 2ms +282 silly doParallel preinstall 1 +283 silly preinstall cic-client-meta@0.0.7-alpha.1 +284 info lifecycle cic-client-meta@0.0.7-alpha.1~preinstall: cic-client-meta@0.0.7-alpha.1 +285 timing action:preinstall Completed in 0ms +286 silly doSerial build 8 +287 silly build cic-client-meta@0.0.7-alpha.1 +288 info linkStuff cic-client-meta@0.0.7-alpha.1 +289 silly linkStuff cic-client-meta@0.0.7-alpha.1 has /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/node_modules as its parent node_modules +290 verbose linkBins [ +290 verbose linkBins { 'cic-meta-server': 'dist-server/scripts/server/server.js' }, +290 verbose linkBins '/home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/node_modules/.bin', +290 verbose linkBins false +290 verbose linkBins ] +291 timing action:build Completed in 2ms +292 verbose unlock done using /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/false/_locks/staging-5da34164c06d3d08.lock for /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/node_modules/.staging +293 timing stage:rollbackFailedOptional Completed in 0ms +294 timing stage:runTopLevelLifecycles Completed in 1000ms +295 silly saveTree scripts +295 silly saveTree └─┬ cic-client-meta@0.0.7-alpha.1 +295 silly saveTree ├─┬ @ethereumjs/tx@3.0.0-beta.1 +295 silly saveTree │ ├─┬ @ethereumjs/common@2.0.0-beta.1 +295 silly saveTree │ │ └─┬ crc-32@1.2.0 +295 silly saveTree │ │ ├── exit-on-epipe@1.0.1 +295 silly saveTree │ │ └── printj@1.1.2 +295 silly saveTree │ └─┬ ethereumjs-util@7.0.7 +295 silly saveTree │ ├─┬ @types/bn.js@4.11.6 +295 silly saveTree │ │ └── @types/node@14.14.6 +295 silly saveTree │ ├── bn.js@5.1.3 +295 silly saveTree │ ├─┬ create-hash@1.2.0 +295 silly saveTree │ │ ├─┬ cipher-base@1.0.4 +295 silly saveTree │ │ │ ├── inherits@2.0.4 +295 silly saveTree │ │ │ └── safe-buffer@5.2.1 +295 silly saveTree │ │ ├── inherits@2.0.4 +295 silly saveTree │ │ ├─┬ md5.js@1.3.5 +295 silly saveTree │ │ │ └─┬ hash-base@3.1.0 +295 silly saveTree │ │ │ └─┬ readable-stream@3.6.0 +295 silly saveTree │ │ │ ├── string_decoder@1.3.0 +295 silly saveTree │ │ │ └── util-deprecate@1.0.2 +295 silly saveTree │ │ ├── ripemd160@2.0.2 +295 silly saveTree │ │ └── sha.js@2.4.11 +295 silly saveTree │ ├─┬ ethereum-cryptography@0.1.3 +295 silly saveTree │ │ ├── @types/pbkdf2@3.1.0 +295 silly saveTree │ │ ├── @types/secp256k1@4.0.1 +295 silly saveTree │ │ ├── blakejs@1.1.0 +295 silly saveTree │ │ ├─┬ browserify-aes@1.2.0 +295 silly saveTree │ │ │ ├── buffer-xor@1.0.3 +295 silly saveTree │ │ │ └── evp_bytestokey@1.0.3 +295 silly saveTree │ │ ├─┬ bs58check@2.1.2 +295 silly saveTree │ │ │ └─┬ bs58@4.0.1 +295 silly saveTree │ │ │ └── base-x@3.0.8 +295 silly saveTree │ │ ├── create-hmac@1.1.7 +295 silly saveTree │ │ ├─┬ hash.js@1.1.7 +295 silly saveTree │ │ │ └── minimalistic-assert@1.0.1 +295 silly saveTree │ │ ├─┬ keccak@3.0.1 +295 silly saveTree │ │ │ ├── node-addon-api@2.0.0 +295 silly saveTree │ │ │ └── node-gyp-build@4.2.3 +295 silly saveTree │ │ ├── pbkdf2@3.1.1 +295 silly saveTree │ │ ├── randombytes@2.1.0 +295 silly saveTree │ │ ├── scrypt-js@3.0.1 +295 silly saveTree │ │ ├─┬ secp256k1@4.0.2 +295 silly saveTree │ │ │ └─┬ elliptic@6.5.3 +295 silly saveTree │ │ │ ├── bn.js@4.11.9 +295 silly saveTree │ │ │ ├── brorand@1.1.0 +295 silly saveTree │ │ │ ├─┬ hmac-drbg@1.0.1 +295 silly saveTree │ │ │ │ └── minimalistic-crypto-utils@1.0.1 +295 silly saveTree │ │ │ └── minimalistic-crypto-utils@1.0.1 +295 silly saveTree │ │ └── setimmediate@1.0.5 +295 silly saveTree │ ├─┬ ethjs-util@0.1.6 +295 silly saveTree │ │ ├── is-hex-prefixed@1.0.0 +295 silly saveTree │ │ └── strip-hex-prefix@1.0.0 +295 silly saveTree │ └── rlp@2.2.6 +295 silly saveTree ├─┬ automerge@0.14.1 +295 silly saveTree │ ├── immutable@3.8.2 +295 silly saveTree │ ├── transit-immutable-js@0.7.0 +295 silly saveTree │ ├── transit-js@0.8.867 +295 silly saveTree │ └── uuid@3.4.0 +295 silly saveTree ├─┬ ethereumjs-wallet@1.0.1 +295 silly saveTree │ ├── aes-js@3.1.2 +295 silly saveTree │ └── utf8@3.0.0 +295 silly saveTree ├── ini@1.3.5 +295 silly saveTree ├─┬ openpgp@4.10.8 +295 silly saveTree │ ├─┬ asn1.js@5.4.1 +295 silly saveTree │ │ └── safer-buffer@2.1.2 +295 silly saveTree │ ├── node-fetch@2.6.1 +295 silly saveTree │ └─┬ node-localstorage@1.3.1 +295 silly saveTree │ └─┬ write-file-atomic@1.3.4 +295 silly saveTree │ ├── graceful-fs@4.2.4 +295 silly saveTree │ ├── imurmurhash@0.1.4 +295 silly saveTree │ └── slide@1.1.6 +295 silly saveTree ├─┬ pg@8.4.2 +295 silly saveTree │ ├── buffer-writer@2.0.0 +295 silly saveTree │ ├── packet-reader@1.0.0 +295 silly saveTree │ ├── pg-connection-string@2.4.0 +295 silly saveTree │ ├── pg-pool@3.2.2 +295 silly saveTree │ ├── pg-protocol@1.3.0 +295 silly saveTree │ ├─┬ pg-types@2.2.0 +295 silly saveTree │ │ ├── pg-int8@1.0.1 +295 silly saveTree │ │ ├── postgres-array@2.0.0 +295 silly saveTree │ │ ├── postgres-bytea@1.0.0 +295 silly saveTree │ │ ├── postgres-date@1.0.7 +295 silly saveTree │ │ └─┬ postgres-interval@1.2.0 +295 silly saveTree │ │ └── xtend@4.0.2 +295 silly saveTree │ └─┬ pgpass@1.0.4 +295 silly saveTree │ └── split2@3.2.2 +295 silly saveTree ├─┬ sqlite3@5.0.0 +295 silly saveTree │ ├─┬ node-gyp@3.8.0 +295 silly saveTree │ │ ├─┬ fstream@1.0.12 +295 silly saveTree │ │ │ ├─┬ mkdirp@0.5.5 +295 silly saveTree │ │ │ │ └── minimist@1.2.5 +295 silly saveTree │ │ │ └─┬ rimraf@2.7.1 +295 silly saveTree │ │ │ └─┬ glob@7.1.6 +295 silly saveTree │ │ │ ├── fs.realpath@1.0.0 +295 silly saveTree │ │ │ ├─┬ inflight@1.0.6 +295 silly saveTree │ │ │ │ ├─┬ once@1.4.0 +295 silly saveTree │ │ │ │ │ └── wrappy@1.0.2 +295 silly saveTree │ │ │ │ └── wrappy@1.0.2 +295 silly saveTree │ │ │ ├─┬ minimatch@3.0.4 +295 silly saveTree │ │ │ │ └─┬ brace-expansion@1.1.11 +295 silly saveTree │ │ │ │ ├── balanced-match@1.0.0 +295 silly saveTree │ │ │ │ └── concat-map@0.0.1 +295 silly saveTree │ │ │ ├── once@1.4.0 +295 silly saveTree │ │ │ └── path-is-absolute@1.0.1 +295 silly saveTree │ │ ├── glob@7.1.6 +295 silly saveTree │ │ ├── mkdirp@0.5.5 +295 silly saveTree │ │ ├─┬ nopt@3.0.6 +295 silly saveTree │ │ │ └── abbrev@1.1.1 +295 silly saveTree │ │ ├─┬ npmlog@4.1.2 +295 silly saveTree │ │ │ ├─┬ are-we-there-yet@1.1.5 +295 silly saveTree │ │ │ │ ├── delegates@1.0.0 +295 silly saveTree │ │ │ │ └─┬ readable-stream@2.3.7 +295 silly saveTree │ │ │ │ ├── core-util-is@1.0.2 +295 silly saveTree │ │ │ │ ├── isarray@1.0.0 +295 silly saveTree │ │ │ │ ├── process-nextick-args@2.0.1 +295 silly saveTree │ │ │ │ ├── safe-buffer@5.1.2 +295 silly saveTree │ │ │ │ └── string_decoder@1.1.1 +295 silly saveTree │ │ │ ├── console-control-strings@1.1.0 +295 silly saveTree │ │ │ ├─┬ gauge@2.7.4 +295 silly saveTree │ │ │ │ ├── aproba@1.2.0 +295 silly saveTree │ │ │ │ ├── has-unicode@2.0.1 +295 silly saveTree │ │ │ │ ├── object-assign@4.1.1 +295 silly saveTree │ │ │ │ ├── signal-exit@3.0.3 +295 silly saveTree │ │ │ │ ├─┬ string-width@1.0.2 +295 silly saveTree │ │ │ │ │ ├── code-point-at@1.1.0 +295 silly saveTree │ │ │ │ │ ├─┬ is-fullwidth-code-point@1.0.0 +295 silly saveTree │ │ │ │ │ │ └── number-is-nan@1.0.1 +295 silly saveTree │ │ │ │ │ └─┬ strip-ansi@3.0.1 +295 silly saveTree │ │ │ │ │ └── ansi-regex@2.1.1 +295 silly saveTree │ │ │ │ ├── strip-ansi@3.0.1 +295 silly saveTree │ │ │ │ └── wide-align@1.1.3 +295 silly saveTree │ │ │ └── set-blocking@2.0.0 +295 silly saveTree │ │ ├─┬ osenv@0.1.5 +295 silly saveTree │ │ │ ├── os-homedir@1.0.2 +295 silly saveTree │ │ │ └── os-tmpdir@1.0.2 +295 silly saveTree │ │ ├─┬ request@2.88.2 +295 silly saveTree │ │ │ ├── aws-sign2@0.7.0 +295 silly saveTree │ │ │ ├── aws4@1.11.0 +295 silly saveTree │ │ │ ├── caseless@0.12.0 +295 silly saveTree │ │ │ ├─┬ combined-stream@1.0.8 +295 silly saveTree │ │ │ │ └── delayed-stream@1.0.0 +295 silly saveTree │ │ │ ├── extend@3.0.2 +295 silly saveTree │ │ │ ├── forever-agent@0.6.1 +295 silly saveTree │ │ │ ├─┬ form-data@2.3.3 +295 silly saveTree │ │ │ │ ├── asynckit@0.4.0 +295 silly saveTree │ │ │ │ └─┬ mime-types@2.1.27 +295 silly saveTree │ │ │ │ └── mime-db@1.44.0 +295 silly saveTree │ │ │ ├─┬ har-validator@5.1.5 +295 silly saveTree │ │ │ │ ├─┬ ajv@6.12.6 +295 silly saveTree │ │ │ │ │ ├── fast-deep-equal@3.1.3 +295 silly saveTree │ │ │ │ │ ├── fast-json-stable-stringify@2.1.0 +295 silly saveTree │ │ │ │ │ ├── json-schema-traverse@0.4.1 +295 silly saveTree │ │ │ │ │ └─┬ uri-js@4.4.0 +295 silly saveTree │ │ │ │ │ └── punycode@2.1.1 +295 silly saveTree │ │ │ │ └── har-schema@2.0.0 +295 silly saveTree │ │ │ ├─┬ http-signature@1.2.0 +295 silly saveTree │ │ │ │ ├── assert-plus@1.0.0 +295 silly saveTree │ │ │ │ ├─┬ jsprim@1.4.1 +295 silly saveTree │ │ │ │ │ ├── extsprintf@1.3.0 +295 silly saveTree │ │ │ │ │ ├── json-schema@0.2.3 +295 silly saveTree │ │ │ │ │ └── verror@1.10.0 +295 silly saveTree │ │ │ │ └─┬ sshpk@1.16.1 +295 silly saveTree │ │ │ │ ├── asn1@0.2.4 +295 silly saveTree │ │ │ │ ├─┬ bcrypt-pbkdf@1.0.2 +295 silly saveTree │ │ │ │ │ └── tweetnacl@0.14.5 +295 silly saveTree │ │ │ │ ├── dashdash@1.14.1 +295 silly saveTree │ │ │ │ ├─┬ ecc-jsbn@0.1.2 +295 silly saveTree │ │ │ │ │ └── jsbn@0.1.1 +295 silly saveTree │ │ │ │ ├── getpass@0.1.7 +295 silly saveTree │ │ │ │ ├── jsbn@0.1.1 +295 silly saveTree │ │ │ │ └── tweetnacl@0.14.5 +295 silly saveTree │ │ │ ├── is-typedarray@1.0.0 +295 silly saveTree │ │ │ ├── isstream@0.1.2 +295 silly saveTree │ │ │ ├── json-stringify-safe@5.0.1 +295 silly saveTree │ │ │ ├── mime-types@2.1.27 +295 silly saveTree │ │ │ ├── oauth-sign@0.9.0 +295 silly saveTree │ │ │ ├── performance-now@2.1.0 +295 silly saveTree │ │ │ ├── qs@6.5.2 +295 silly saveTree │ │ │ ├─┬ tough-cookie@2.5.0 +295 silly saveTree │ │ │ │ └── psl@1.8.0 +295 silly saveTree │ │ │ └── tunnel-agent@0.6.0 +295 silly saveTree │ │ ├── rimraf@2.7.1 +295 silly saveTree │ │ ├── semver@5.3.0 +295 silly saveTree │ │ ├─┬ tar@2.2.2 +295 silly saveTree │ │ │ └── block-stream@0.0.9 +295 silly saveTree │ │ └─┬ which@1.3.1 +295 silly saveTree │ │ └── isexe@2.0.0 +295 silly saveTree │ └─┬ node-pre-gyp@0.11.0 +295 silly saveTree │ ├── detect-libc@1.0.3 +295 silly saveTree │ ├─┬ needle@2.5.2 +295 silly saveTree │ │ ├─┬ debug@3.2.6 +295 silly saveTree │ │ │ └── ms@2.1.2 +295 silly saveTree │ │ ├── iconv-lite@0.4.24 +295 silly saveTree │ │ └── sax@1.2.4 +295 silly saveTree │ ├── nopt@4.0.3 +295 silly saveTree │ ├─┬ npm-packlist@1.4.8 +295 silly saveTree │ │ ├── ignore-walk@3.0.3 +295 silly saveTree │ │ ├─┬ npm-bundled@1.1.1 +295 silly saveTree │ │ │ └── npm-normalize-package-bin@1.0.1 +295 silly saveTree │ │ └── npm-normalize-package-bin@1.0.1 +295 silly saveTree │ ├─┬ rc@1.2.8 +295 silly saveTree │ │ ├── deep-extend@0.6.0 +295 silly saveTree │ │ └── strip-json-comments@2.0.1 +295 silly saveTree │ └─┬ tar@4.4.13 +295 silly saveTree │ ├── chownr@1.1.4 +295 silly saveTree │ ├─┬ fs-minipass@1.2.7 +295 silly saveTree │ │ └─┬ minipass@2.9.0 +295 silly saveTree │ │ └── yallist@3.1.1 +295 silly saveTree │ ├── minipass@2.9.0 +295 silly saveTree │ ├── minizlib@1.3.3 +295 silly saveTree │ └── yallist@3.1.1 +295 silly saveTree └─┬ yargs@16.1.0 +295 silly saveTree ├─┬ cliui@7.0.3 +295 silly saveTree │ ├─┬ string-width@4.2.0 +295 silly saveTree │ │ ├── emoji-regex@8.0.0 +295 silly saveTree │ │ ├── is-fullwidth-code-point@3.0.0 +295 silly saveTree │ │ └─┬ strip-ansi@6.0.0 +295 silly saveTree │ │ └── ansi-regex@5.0.0 +295 silly saveTree │ ├── strip-ansi@6.0.0 +295 silly saveTree │ └─┬ wrap-ansi@7.0.0 +295 silly saveTree │ ├─┬ ansi-styles@4.3.0 +295 silly saveTree │ │ └─┬ color-convert@2.0.1 +295 silly saveTree │ │ └── color-name@1.1.4 +295 silly saveTree │ ├─┬ string-width@4.2.0 +295 silly saveTree │ │ ├── is-fullwidth-code-point@3.0.0 +295 silly saveTree │ │ └─┬ strip-ansi@6.0.0 +295 silly saveTree │ │ └── ansi-regex@5.0.0 +295 silly saveTree │ └── strip-ansi@6.0.0 +295 silly saveTree ├── escalade@3.1.1 +295 silly saveTree ├── get-caller-file@2.0.5 +295 silly saveTree ├── require-directory@2.1.1 +295 silly saveTree ├─┬ string-width@4.2.0 +295 silly saveTree │ ├── is-fullwidth-code-point@3.0.0 +295 silly saveTree │ └─┬ strip-ansi@6.0.0 +295 silly saveTree │ └── ansi-regex@5.0.0 +295 silly saveTree ├── y18n@5.0.5 +295 silly saveTree └── yargs-parser@20.2.3 +296 warn notsup Unsupported engine for cic-client-meta@0.0.7-alpha.1: wanted: {"node":"~15.3.0"} (current: {"node":"15.6.0","npm":"6.14.11"}) +297 warn notsup Not compatible with your version of node/npm: cic-client-meta@0.0.7-alpha.1 +298 verbose notsup Not compatible with your version of node/npm: cic-client-meta@0.0.7-alpha.1 +298 verbose notsup Required: {"node":"~15.3.0"} +298 verbose notsup Actual: {"npm":"6.14.11","node":"15.6.0"} +299 warn enoent ENOENT: no such file or directory, open '/home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/package.json' +300 verbose enoent This is related to npm not being able to find a file. +301 warn scripts No description +302 warn scripts No repository field. +303 warn scripts No README data +304 warn scripts No license field. +305 verbose stack Error: ENOENT: no such file or directory, chmod '/home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/node_modules/cic-client-meta/dist-server/scripts/server/server.js' +306 verbose cwd /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts +307 verbose Linux 5.10.8-arch1-1 +308 verbose argv "/usr/bin/node" "/usr/bin/npm" "install" "--no-cache" "../../../apps/cic-meta" +309 verbose node v15.6.0 +310 verbose npm v6.14.11 +311 error code ENOENT +312 error syscall chmod +313 error path /home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/node_modules/cic-client-meta/dist-server/scripts/server/server.js +314 error errno -2 +315 error enoent ENOENT: no such file or directory, chmod '/home/lash/src/ext/cic/grassrootseconomics/cic-internal-integration/apps/contract-migration/scripts/node_modules/cic-client-meta/dist-server/scripts/server/server.js' +316 error enoent This is related to npm not being able to find a file. +317 verbose exit [ -2, true ] diff --git a/apps/contract-migration/scripts/false/anonymous-cli-metrics.json b/apps/contract-migration/scripts/false/anonymous-cli-metrics.json new file mode 100644 index 0000000..bd2344c --- /dev/null +++ b/apps/contract-migration/scripts/false/anonymous-cli-metrics.json @@ -0,0 +1 @@ +{"metricId":"ea11447f-da1c-49e6-b0a2-8a988a99e3ce","metrics":{"from":"2021-02-12T18:59:21.666Z","to":"2021-02-12T18:59:21.666Z","successfulInstalls":0,"failedInstalls":1}} \ No newline at end of file diff --git a/apps/contract-migration/scripts/import_balance.py b/apps/contract-migration/scripts/import_balance.py new file mode 100644 index 0000000..427fc9f --- /dev/null +++ b/apps/contract-migration/scripts/import_balance.py @@ -0,0 +1,295 @@ +# standard imports +import os +import sys +import logging +import time +import argparse +import sys +import re +import hashlib +import csv +import json + +# third-party impotts +import eth_abi +import confini +from hexathon import ( + strip_0x, + add_0x, + ) +from chainsyncer.backend import MemBackend +from chainsyncer.driver import HeadSyncer +from chainlib.eth.connection import HTTPConnection +from chainlib.eth.block import ( + block_latest, + block_by_number, + Block, + ) +from chainlib.eth.hash import keccak256_string_to_hex +from chainlib.eth.address import to_checksum +from chainlib.eth.erc20 import ERC20TxFactory +from chainlib.eth.gas import DefaultGasOracle +from chainlib.eth.nonce import DefaultNonceOracle +from chainlib.eth.tx import TxFactory +from chainlib.eth.rpc import jsonrpc_template +from chainlib.eth.error import EthException +from chainlib.chain import ChainSpec +from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer +from crypto_dev_signer.keystore import DictKeystore +from cic_types.models.person import Person + + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +config_dir = '/usr/local/etc/cic-syncer' + +argparser = argparse.ArgumentParser(description='daemon that monitors transactions in new blocks') +argparser.add_argument('-p', '--provider', dest='p', type=str, help='chain rpc provider address') +argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing') +argparser.add_argument('-c', type=str, default=config_dir, help='config root to use') +argparser.add_argument('--old-chain-spec', type=str, dest='old_chain_spec', default='oldchain:1', help='chain spec') +argparser.add_argument('-i', '--chain-spec', type=str, dest='i', help='chain spec') +argparser.add_argument('-r', '--registry-address', type=str, dest='r', help='CIC Registry address') +argparser.add_argument('--token-symbol', default='SRF', type=str, dest='token_symbol', help='Token symbol to use for trnsactions') +argparser.add_argument('--head', action='store_true', help='start at current block height (overrides --offset)') +argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration') +argparser.add_argument('-q', type=str, default='cic-eth', help='celery queue to submit transaction tasks to') +argparser.add_argument('--offset', type=int, default=0, help='block offset to start syncer from') +argparser.add_argument('-v', help='be verbose', action='store_true') +argparser.add_argument('-vv', help='be more verbose', action='store_true') +argparser.add_argument('user_dir', type=str, help='user export directory') +args = argparser.parse_args(sys.argv[1:]) + +if args.v == True: + logging.getLogger().setLevel(logging.INFO) +elif args.vv == True: + logging.getLogger().setLevel(logging.DEBUG) + +config_dir = os.path.join(args.c) +os.makedirs(config_dir, 0o777, True) +config = confini.Config(config_dir, args.env_prefix) +config.process() +# override args +args_override = { + 'CIC_CHAIN_SPEC': getattr(args, 'i'), + 'ETH_PROVIDER': getattr(args, 'p'), + 'CIC_REGISTRY_ADDRESS': getattr(args, 'r'), + } +config.dict_override(args_override, 'cli flag') +config.censor('PASSWORD', 'DATABASE') +config.censor('PASSWORD', 'SSL') +logg.debug('config loaded from {}:\n{}'.format(config_dir, config)) + +#app = celery.Celery(backend=config.get('CELERY_RESULT_URL'), broker=config.get('CELERY_BROKER_URL')) + +signer_address = None +keystore = DictKeystore() +if args.y != None: + logg.debug('loading keystore file {}'.format(args.y)) + signer_address = keystore.import_keystore_file(args.y) + logg.debug('now have key for signer address {}'.format(signer_address)) +signer = EIP155Signer(keystore) + +queue = args.q +chain_str = config.get('CIC_CHAIN_SPEC') +block_offset = 0 +if args.head: + block_offset = -1 +else: + block_offset = args.offset + +chain_spec = ChainSpec.from_chain_str(chain_str) +old_chain_spec_str = args.old_chain_spec + +user_dir = args.user_dir # user_out_dir from import_users.py + +token_symbol = args.token_symbol + + +class Handler: + + account_index_add_signature = keccak256_string_to_hex('add(address)')[:8] + + def __init__(self, conn, chain_spec, user_dir, balances, token_address, signer, gas_oracle, nonce_oracle): + self.token_address = token_address + self.user_dir = user_dir + self.balances = balances + self.chain_spec = chain_spec + self.tx_factory = ERC20TxFactory(signer, gas_oracle, nonce_oracle, chain_spec.network_id()) + + + def name(self): + return 'balance_handler' + + + def filter(self, conn, block, tx, db_session): + if tx.payload == None or len(tx.payload) == 0: + logg.debug('no payload, skipping {}'.format(tx)) + return + + if tx.payload[:8] == self.account_index_add_signature: + recipient = eth_abi.decode_single('address', bytes.fromhex(tx.payload[-64:])) + #original_address = to_checksum(self.addresses[to_checksum(recipient)]) + user_file = 'new/{}/{}/{}.json'.format( + recipient[2:4].upper(), + recipient[4:6].upper(), + recipient[2:].upper(), + ) + filepath = os.path.join(self.user_dir, user_file) + o = None + try: + f = open(filepath, 'r') + o = json.load(f) + f.close() + except FileNotFoundError: + logg.error('no import record of address {}'.format(recipient)) + return + u = Person.deserialize(o) + original_address = u.identities['evm'][old_chain_spec_str][0] + balance = self.balances[original_address] + + # TODO: store token object in handler ,get decimals from there + multiplier = 10**6 + balance_full = balance * multiplier + logg.info('registered {} originally {} ({}) tx hash {} balance {}'.format(recipient, original_address, u, tx.hash, balance_full)) + + (tx_hash_hex, o) = self.tx_factory.erc20_transfer(self.token_address, signer_address, recipient, balance_full) + logg.info('submitting erc20 transfer tx {} for recipient {}'.format(tx_hash_hex, recipient)) + r = conn.do(o) +# except TypeError as e: +# logg.warning('typerror {}'.format(e)) +# pass +# except IndexError as e: +# logg.warning('indexerror {}'.format(e)) +# pass +# except EthException as e: +# logg.error('send error {}'.format(e).ljust(200)) + #except KeyError as e: + # logg.error('key record not found in imports: {}'.format(e).ljust(200)) + + +class BlockGetter: + + def __init__(self, conn, gas_oracle, nonce_oracle, chain_id): + self.conn = conn + self.tx_factory = ERC20TxFactory(signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle, chain_id=chain_id) + + + def get(self, n): + o = block_by_number(n) + r = self.conn.do(o) + b = None + try: + b = Block(r) + except TypeError as e: + if r == None: + logg.debug('block not found {}'.format(n)) + else: + logg.error('block retrieve error {}'.format(e)) + return b + + +def progress_callback(block_number, tx_index, s): + sys.stdout.write(s.ljust(200) + "\n") + + + +def main(): + global chain_str, block_offset, user_dir + + conn = HTTPConnection(config.get('ETH_PROVIDER')) + gas_oracle = DefaultGasOracle(conn) + nonce_oracle = DefaultNonceOracle(signer_address, conn) + + # Get Token registry address + txf = TxFactory(signer=signer, gas_oracle=gas_oracle, nonce_oracle=None, chain_id=chain_spec.network_id()) + tx = txf.template(signer_address, config.get('CIC_REGISTRY_ADDRESS')) + + registry_addressof_method = keccak256_string_to_hex('addressOf(bytes32)')[:8] + data = add_0x(registry_addressof_method) + data += eth_abi.encode_single('bytes32', b'TokenRegistry').hex() + txf.set_code(tx, data) + + o = jsonrpc_template() + o['method'] = 'eth_call' + o['params'].append(txf.normalize(tx)) + o['params'].append('latest') + r = conn.do(o) + token_index_address = to_checksum(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) + logg.info('found token index address {}'.format(token_index_address)) + + + # Get Sarafu token address + tx = txf.template(signer_address, token_index_address) + data = add_0x(registry_addressof_method) + h = hashlib.new('sha256') + h.update(token_symbol.encode('utf-8')) + z = h.digest() + data += eth_abi.encode_single('bytes32', z).hex() + txf.set_code(tx, data) + o = jsonrpc_template() + o['method'] = 'eth_call' + o['params'].append(txf.normalize(tx)) + o['params'].append('latest') + r = conn.do(o) + try: + sarafu_token_address = to_checksum(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) + except ValueError as e: + logg.critical('lookup failed for token {}: {}'.format(token_symbol, e)) + sys.exit(1) + logg.info('found token address {}'.format(sarafu_token_address)) + + syncer_backend = MemBackend(chain_str, 0) + + if block_offset == -1: + o = block_latest() + r = conn.do(o) + block_offset = int(strip_0x(r), 16) + 1 +# +# addresses = {} +# f = open('{}/addresses.csv'.format(user_dir, 'r')) +# while True: +# l = f.readline() +# if l == None: +# break +# r = l.split(',') +# try: +# k = r[0] +# v = r[1].rstrip() +# addresses[k] = v +# sys.stdout.write('loading address mapping {} -> {}'.format(k, v).ljust(200) + "\r") +# except IndexError as e: +# break +# f.close() + + # TODO get decimals from token + balances = {} + f = open('{}/balances.csv'.format(user_dir, 'r')) + remove_zeros = 10**6 + i = 0 + while True: + l = f.readline() + if l == None: + break + r = l.split(',') + try: + address = to_checksum(r[0]) + sys.stdout.write('loading balance {} {} {}'.format(i, address, r[1]).ljust(200) + "\r") + except ValueError: + break + balance = int(int(r[1].rstrip()) / remove_zeros) + balances[address] = balance + i += 1 + + f.close() + + syncer_backend.set(block_offset, 0) + syncer = HeadSyncer(syncer_backend, progress_callback=progress_callback) + handler = Handler(conn, chain_spec, user_dir, balances, sarafu_token_address, signer, gas_oracle, nonce_oracle) + syncer.add_filter(handler) + syncer.loop(1, conn) + + +if __name__ == '__main__': + main() diff --git a/apps/contract-migration/scripts/import_balance.sh b/apps/contract-migration/scripts/import_balance.sh new file mode 100644 index 0000000..8db2632 --- /dev/null +++ b/apps/contract-migration/scripts/import_balance.sh @@ -0,0 +1 @@ +python import_balance.py -c config -i evm:bloxberg:8996 -y /home/lash/tmp/d/keystore/UTC--2021-02-07T09-58-35.341813355Z--eb3907ecad74a0013c259d5874ae7f22dcbcc95c -v $@ diff --git a/apps/contract-migration/scripts/import_meta.js b/apps/contract-migration/scripts/import_meta.js new file mode 100644 index 0000000..3ea82e9 --- /dev/null +++ b/apps/contract-migration/scripts/import_meta.js @@ -0,0 +1,120 @@ +const fs = require('fs'); +const path = require('path'); +const http = require('http'); + +const cic = require('cic-client-meta'); + +//const conf = JSON.parse(fs.readFileSync('./cic.conf')); + +const config = new cic.Config('./config'); +config.process(); +console.log(config); + + +function sendit(uid, envelope) { + const d = envelope.toJSON(); + + const contentLength = (new TextEncoder().encode(d)).length; + const opts = { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'Content-Length': contentLength, + 'X-CIC-AUTOMERGE': 'client', + + }, + }; + let url = config.get('META_URL'); + url = url.replace(new RegExp('^(.+://[^/]+)/*$'), '$1/'); + console.log('posting to url: ' + url + uid); + const req = http.request(url + uid, opts, (res) => { + res.on('data', process.stdout.write); + res.on('end', () => { + console.log('result', res.statusCode, res.headers); + }); + }); + if (!req.write(d)) { + console.error('foo', d); + process.exit(1); + } + req.end(); +} + +function doOne(keystore, filePath) { + const signer = new cic.PGPSigner(keystore); + const parts = path.basename(filePath).split('.'); + const ethereum_address = path.basename(parts[0]); + + cic.User.toKey('0x' + ethereum_address).then((uid) => { + const d = fs.readFileSync(filePath, 'utf-8'); + const o = JSON.parse(d); + //console.log(o); + fs.unlinkSync(filePath); + + const s = new cic.Syncable(uid, o); + s.setSigner(signer); + s.onwrap = (env) => { + sendit(uid, env); + }; + s.sign(); + }); +} + +const privateKeyPath = path.join(config.get('PGP_EXPORTS_DIR'), config.get('PGP_PRIVATE_KEY_FILE')); +const publicKeyPath = path.join(config.get('PGP_EXPORTS_DIR'), config.get('PGP_PRIVATE_KEY_FILE')); +pk = fs.readFileSync(privateKeyPath); +pubk = fs.readFileSync(publicKeyPath); + +new cic.PGPKeyStore( + config.get('PGP_PASSPHRASE'), + pk, + pubk, + undefined, + undefined, + importMeta, +); + +const batchSize = 50; +const batchDelay = 1000; +const total = parseInt(process.argv[3]); +const workDir = path.join(process.argv[2], 'meta'); +let count = 0; +let batchCount = 0; + + +function importMeta(keystore) { + let err; + let files; + + try { + err, files = fs.readdirSync(workDir); + } catch { + console.error('source directory not yet ready', workDir); + setTimeout(importMeta, batchDelay, keystore); + return; + } + let limit = batchSize; + if (files.length < limit) { + limit = files.length; + } + for (let i = 0; i < limit; i++) { + const file = files[i]; + if (file.substr(-5) != '.json') { + console.debug('skipping file', file); + } + const filePath = path.join(workDir, file); + doOne(keystore, filePath); + count++; + batchCount++; + if (batchCount == batchSize) { + console.debug('reached batch size, breathing'); + batchCount=0; + setTimeout(importMeta, batchDelay, keystore); + return; + } + } + if (count == total) { + return; + } + setTimeout(importMeta, 100, keystore); +} diff --git a/apps/contract-migration/scripts/import_users.py b/apps/contract-migration/scripts/import_users.py new file mode 100644 index 0000000..675d36c --- /dev/null +++ b/apps/contract-migration/scripts/import_users.py @@ -0,0 +1,177 @@ +# standard imports +import os +import sys +import json +import logging +import argparse +import uuid +import datetime +import time +from glob import glob + +# third-party imports +import redis +import confini +import celery +from hexathon import ( + add_0x, + strip_0x, + ) +from chainlib.eth.address import to_checksum +from cic_types.models.person import Person +from cic_eth.api.api_task import Api +from cic_registry.chain import ChainSpec +from cic_types.processor import generate_metadata_pointer + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +default_config_dir = '/usr/local/etc/cic' + +argparser = argparse.ArgumentParser() +argparser.add_argument('-c', type=str, default=default_config_dir, help='config file') +argparser.add_argument('-i', '--chain-spec', dest='i', type=str, help='Chain specification string') +argparser.add_argument('--redis-host', dest='redis_host', type=str, help='redis host to use for task submission') +argparser.add_argument('--redis-port', dest='redis_port', type=int, help='redis host to use for task submission') +argparser.add_argument('--redis-db', dest='redis_db', type=int, help='redis db to use for task submission and callback') +argparser.add_argument('--redis-host-callback', dest='redis_host_callback', default='localhost', type=str, help='redis host to use for callback') +argparser.add_argument('--redis-port-callback', dest='redis_port_callback', default=6379, type=int, help='redis port to use for callback') +argparser.add_argument('--batch-size', dest='batch_size', default=50, type=int, help='burst size of sending transactions to node') +argparser.add_argument('--batch-delay', dest='batch_delay', default=2, type=int, help='seconds delay between batches') +argparser.add_argument('--timeout', default=20.0, type=float, help='Callback timeout') +argparser.add_argument('-q', type=str, default='cic-eth', help='Task queue') +argparser.add_argument('-v', action='store_true', help='Be verbose') +argparser.add_argument('-vv', action='store_true', help='Be more verbose') +argparser.add_argument('user_dir', type=str, help='path to users export dir tree') +args = argparser.parse_args() + +if args.v: + logg.setLevel(logging.INFO) +elif args.vv: + logg.setLevel(logging.DEBUG) + +config_dir = args.c +config = confini.Config(config_dir, os.environ.get('CONFINI_ENV_PREFIX')) +config.process() +args_override = { + 'CIC_CHAIN_SPEC': getattr(args, 'i'), + 'REDIS_HOST': getattr(args, 'redis_host'), + 'REDIS_PORT': getattr(args, 'redis_port'), + 'REDIS_DB': getattr(args, 'redis_db'), + } +config.dict_override(args_override, 'cli') +celery_app = celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=config.get('CELERY_RESULT_URL')) + +redis_host = config.get('REDIS_HOST') +redis_port = config.get('REDIS_PORT') +redis_db = config.get('REDIS_DB') +r = redis.Redis(redis_host, redis_port, redis_db) + +ps = r.pubsub() + +user_new_dir = os.path.join(args.user_dir, 'new') +os.makedirs(user_new_dir) + +meta_dir = os.path.join(args.user_dir, 'meta') +os.makedirs(meta_dir) + +user_old_dir = os.path.join(args.user_dir, 'old') +os.stat(user_old_dir) + +chain_spec = ChainSpec.from_chain_str(config.get('CIC_CHAIN_SPEC')) +chain_str = str(chain_spec) + +batch_size = args.batch_size +batch_delay = args.batch_delay + + +def register_eth(i, u): + redis_channel = str(uuid.uuid4()) + ps.subscribe(redis_channel) + ps.get_message() + api = Api( + config.get('CIC_CHAIN_SPEC'), + queue=args.q, + callback_param='{}:{}:{}:{}'.format(args.redis_host_callback, args.redis_port_callback, redis_db, redis_channel), + callback_task='cic_eth.callbacks.redis.redis', + callback_queue=args.q, + ) + t = api.create_account(register=True) + + ps.get_message() + m = ps.get_message(timeout=args.timeout) + try: + r = json.loads(m['data']) + address = r['result'] + except TypeError as e: + if m == None: + logg.critical('empty response from redis callback (did the service crash?)') + else: + logg.critical('unexpected response from redis callback: {}'.format(m)) + sys.exit(1) + logg.debug('[{}] register eth {} {}'.format(i, u, address)) + + return address + + +def register_ussd(u): + pass + + +if __name__ == '__main__': + + #fi = open(os.path.join(user_out_dir, 'addresses.csv'), 'a') + + i = 0 + j = 0 + for x in os.walk(user_old_dir): + for y in x[2]: + if y[len(y)-5:] != '.json': + continue + filepath = os.path.join(x[0], y) + f = open(filepath, 'r') + try: + o = json.load(f) + except json.decoder.JSONDecodeError as e: + f.close() + logg.error('load error for {}: {}'.format(y, e)) + continue + f.close() + u = Person.deserialize(o) + + new_address = register_eth(i, u) + if u.identities.get('evm') == None: + u.identities['evm'] = {} + u.identities['evm'][chain_str] = [new_address] + + register_ussd(u) + + new_address_clean = strip_0x(new_address) + filepath = os.path.join( + user_new_dir, + new_address_clean[:2].upper(), + new_address_clean[2:4].upper(), + new_address_clean.upper() + '.json', + ) + os.makedirs(os.path.dirname(filepath), exist_ok=True) + + o = u.serialize() + f = open(filepath, 'w') + f.write(json.dumps(o)) + f.close() + + #old_address = to_checksum(add_0x(y[:len(y)-5])) + #fi.write('{},{}\n'.format(new_address, old_address)) + meta_key = generate_metadata_pointer(bytes.fromhex(new_address_clean), 'cic.person') + meta_filepath = os.path.join(meta_dir, '{}.json'.format(new_address_clean.upper())) + os.symlink(os.path.realpath(filepath), meta_filepath) + + i += 1 + sys.stdout.write('imported {} {}'.format(i, u).ljust(200) + "\r") + + j += 1 + if j == batch_size: + time.sleep(batch_delay) + j = 0 + + #fi.close() diff --git a/apps/contract-migration/scripts/import_users.sh b/apps/contract-migration/scripts/import_users.sh new file mode 100644 index 0000000..38507b7 --- /dev/null +++ b/apps/contract-migration/scripts/import_users.sh @@ -0,0 +1 @@ +python import_users.py -c config --redis-host-callback redis -vv $@ diff --git a/apps/contract-migration/scripts/local/account.py b/apps/contract-migration/scripts/local/account.py new file mode 100644 index 0000000..35666a0 --- /dev/null +++ b/apps/contract-migration/scripts/local/account.py @@ -0,0 +1,37 @@ +# standard imports +import logging + +# external imports +from cic_eth.api.api_task import Api + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +queue = 'cic-eth' +name = 'account' + + +def do(token_pair, sender, recipient, sender_balance, aux, block_number, tx_index): + """Triggers creation and registration of new account through the custodial cic-eth component. + + It expects the following aux parameters to exist: + - redis_host_callback: Redis host name exposed to cic-eth, for callback + - redis_port_callback: Redis port exposed to cic-eth, for callback + - redis_db: Redis db, for callback + - redis_channel: Redis channel, for callback + - chain_spec: Chain specification for the chain to execute the transfer on + + See local.noop.do for details on parameters and return values. + """ + logg.debug('running {} {} {}'.format(__name__, token_pair, sender, recipient)) + api = Api( + str(aux['chain_spec']), + queue=queue, + callback_param='{}:{}:{}:{}'.format(aux['redis_host_callback'], aux['redis_port_callback'], aux['redis_db'], aux['redis_channel']), + callback_task='cic_eth.callbacks.redis.redis', + callback_queue=queue, + ) + + t = api.create_account(register=True) + + return (None, t, sender_balance, ) diff --git a/apps/contract-migration/scripts/local/noop_traffic.py b/apps/contract-migration/scripts/local/noop_traffic.py new file mode 100644 index 0000000..85f7cf2 --- /dev/null +++ b/apps/contract-migration/scripts/local/noop_traffic.py @@ -0,0 +1,37 @@ +# standard imports +import logging + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + + +def do(token_pair, sender, recipient, sender_balance, aux, block_number, tx_index): + """Defines the function signature for a traffic generator. The method itself only logs the input parameters. + + If the error position in the return tuple is not None, the calling code should consider the generation as failed, and not count it towards the limit of simultaneous traffic items that can be simultaneously in flight. + + If the task_id position in the return tuple is None, the calling code should interpret the traffic item to have been synchronously completed, and not count it towards the limit of simultaneous traffic items that can be simultaneously in flight. + + The balance element of the result is the balance dict passed as argument, with fields updated according to the expected delta as a result of the operation. However, in the event that the generator module dispatches an asynchronous event then there is no guarantee that this balance will actually be the correct result. The caller should take care to periodically re-sync balance from the upstream. + + :param token_pair: Source and destination tokens for the traffic item. + :type token_pair: 2-element tuple with cic_registry.token.Token + :param sender: Sender address + :type sender: str, 0x-hex + :param recipient: Recipient address + :type recipient: str, 0x-hex + :param sender_balance: Sender balance in full decimal resolution + :type sender_balance: complex balance dict + :param aux: Custom parameters defined by traffic generation client code + :type aux: dict + :param block_number: Syncer block number position at time of method call + :type block_number: number + :param tx_index: Syncer block transaction index position at time of method call + :type tx_index: number + :raises KeyError: Missing required aux element + :returns: Exception|None, task_id|None and adjusted_sender_balance respectively + :rtype: tuple + """ + logg.debug('running {} {} {} {} {} {} {} {}'.format(__name__, token_pair, sender, recipient, sender_balance, aux, block_number, tx_index)) + + return (None, None, sender_balance, ) diff --git a/apps/contract-migration/scripts/local/transfer.py b/apps/contract-migration/scripts/local/transfer.py new file mode 100644 index 0000000..e6a6e74 --- /dev/null +++ b/apps/contract-migration/scripts/local/transfer.py @@ -0,0 +1,51 @@ +# standard imports +import logging +import random + +# external imports +from cic_eth.api.api_task import Api + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +queue = 'cic-eth' +name = 'erc20_transfer' + + +def do(token_pair, sender, recipient, sender_balance, aux, block_number, tx_index): + """Triggers an ERC20 token transfer through the custodial cic-eth component, with a randomly chosen amount in integer resolution. + + It expects the following aux parameters to exist: + - redis_host_callback: Redis host name exposed to cic-eth, for callback + - redis_port_callback: Redis port exposed to cic-eth, for callback + - redis_db: Redis db, for callback + - redis_channel: Redis channel, for callback + - chain_spec: Chain specification for the chain to execute the transfer on + + See local.noop.do for details on parameters and return values. + """ + logg.debug('running {} {} {} {}'.format(__name__, token_pair, sender, recipient)) + + decimals = token_pair[0].decimals() + + sender_balance_value = sender_balance['balance_network'] - sender_balance['balance_outgoing'] + + balance_units = int(sender_balance_value / decimals) + + if balance_units <= 0: + return (AttributeError('sender {} has zero balance'), None, 0,) + + spend_units = random.randint(1, balance_units) + spend_value = spend_units * decimals + + api = Api( + str(aux['chain_spec']), + queue=queue, + callback_param='{}:{}:{}:{}'.format(aux['redis_host_callback'], aux['redis_port_callback'], aux['redis_db'], aux['redis_channel']), + callback_task='cic_eth.callbacks.redis.redis', + callback_queue=queue, + ) + t = api.transfer(sender, recipient, spend_value, token_pair[0].symbol()) + + sender_balance['balance_outgoing'] += spend_value + return (None, t, sender_balance,) diff --git a/apps/contract-migration/scripts/package-lock.json b/apps/contract-migration/scripts/package-lock.json new file mode 100644 index 0000000..d2d7ed3 --- /dev/null +++ b/apps/contract-migration/scripts/package-lock.json @@ -0,0 +1,1749 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@ethereumjs/common": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.0.0.tgz", + "integrity": "sha512-yL0zA7Xwgz8IFHKW0VoXGjdZDVxUJg8BQ/muMHvYPW7zHJNNC80gQmvLH+MpvIg1TCXZkFXxrpYRAyCElSm+aw==", + "requires": { + "crc-32": "^1.2.0" + } + }, + "@ethereumjs/tx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.0.2.tgz", + "integrity": "sha512-zmFCosjOdj1WoYEiQBdC4sCOAllBEwxdKuY85L9FgZ4zVDfZUVsQ4S9paczt4hVt65A7N8sJwgVEzDaQmrRaqw==", + "requires": { + "@ethereumjs/common": "^2.0.0", + "ethereumjs-util": "^7.0.8" + } + }, + "@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "14.14.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.30.tgz", + "integrity": "sha512-gUWhy8s45fQp4PqqKecsnOkdW0kt1IaKjgOIR3HPokkzTmQj9ji2wWFID5THu1MKrtO+d4s2lVrlEhXUsPXSvg==" + }, + "@types/pbkdf2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", + "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/secp256k1": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", + "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", + "requires": { + "@types/node": "*" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "aes-js": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", + "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==" + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "optional": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "optional": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "optional": true + }, + "automerge": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/automerge/-/automerge-0.14.2.tgz", + "integrity": "sha512-shiwuJHCbNRI23WZyIECLV4Ovf3WiAFJ7P9BH4l5gON1In/UUbjcSJKRygtIirObw2UQumeYxp3F2XBdSvQHnA==", + "requires": { + "immutable": "^3.8.2", + "transit-immutable-js": "^0.7.0", + "transit-js": "^0.8.861", + "uuid": "^3.4.0" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "optional": true + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "optional": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base-x": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", + "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "blakejs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", + "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "optional": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "requires": { + "base-x": "^3.0.2" + } + }, + "bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "requires": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "optional": true + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "cic-client-meta": { + "version": "0.0.7-alpha.2", + "resolved": "https://registry.npmjs.org/cic-client-meta/-/cic-client-meta-0.0.7-alpha.2.tgz", + "integrity": "sha512-q7Ifz/THPIp9XvjUEK+WFM/UFk1R0VbGJXopQd/3gW3zRpxEPj5V1JfcTts7EkyS5eYaLA0/+E4u6j4ddgmsfg==", + "requires": { + "@ethereumjs/tx": "^3.0.0-beta.1", + "automerge": "^0.14.1", + "ethereumjs-wallet": "^1.0.1", + "ini": "^1.3.5", + "openpgp": "^4.10.8", + "pg": "^8.4.2", + "sqlite3": "^5.0.0", + "yargs": "^16.1.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "optional": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "optional": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "optional": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "requires": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "ethereumjs-util": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.8.tgz", + "integrity": "sha512-JJt7tDpCAmDPw/sGoFYeq0guOVqT3pTE9xlEbBmc/nlCij3JRCoS2c96SQ6kXVHOT3xWUNLDm5QCJLQaUnVAtQ==", + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.4" + } + }, + "ethereumjs-wallet": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-1.0.1.tgz", + "integrity": "sha512-3Z5g1hG1das0JWU6cQ9HWWTY2nt9nXCcwj7eXVNAHKbo00XAZO8+NHlwdgXDWrL0SXVQMvTWN8Q/82DRH/JhPw==", + "requires": { + "aes-js": "^3.1.1", + "bs58check": "^2.1.2", + "ethereum-cryptography": "^0.1.3", + "ethereumjs-util": "^7.0.2", + "randombytes": "^2.0.6", + "scrypt-js": "^3.0.1", + "utf8": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "optional": true + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "optional": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "optional": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "optional": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "optional": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "optional": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "optional": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "optional": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "requires": { + "minimatch": "^3.0.4" + } + }, + "immutable": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", + "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "optional": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "optional": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "optional": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "optional": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "optional": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "optional": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "keccak": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", + "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", + "requires": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mime-db": { + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", + "optional": true + }, + "mime-types": { + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "optional": true, + "requires": { + "mime-db": "1.46.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "needle": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", + "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "optional": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + } + }, + "node-gyp-build": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" + }, + "node-localstorage": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-localstorage/-/node-localstorage-1.3.1.tgz", + "integrity": "sha512-NMWCSWWc6JbHT5PyWlNT2i8r7PgGYXVntmKawY83k/M0UJScZ5jirb61TLnqKwd815DfBQu+lR3sRw08SPzIaQ==", + "requires": { + "write-file-atomic": "^1.1.4" + } + }, + "node-pre-gyp": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", + "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + }, + "dependencies": { + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "optional": true, + "requires": { + "abbrev": "1" + } + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "openpgp": { + "version": "4.10.10", + "resolved": "https://registry.npmjs.org/openpgp/-/openpgp-4.10.10.tgz", + "integrity": "sha512-Ub48OogGPjNsr0G/wnJ/SyAQzt/tfcXZTWVZdjKFpXCQV1Ca+upFdSPPkBlGG3lb9EQGOKZJ2tzYNH6ZyKMkDQ==", + "requires": { + "asn1.js": "^5.0.0", + "node-fetch": "^2.1.2", + "node-localstorage": "~1.3.0" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "optional": true + }, + "pg": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz", + "integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.4.0", + "pg-pool": "^3.2.2", + "pg-protocol": "^1.4.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + } + }, + "pg-connection-string": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz", + "integrity": "sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ==" + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz", + "integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA==" + }, + "pg-protocol": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.4.0.tgz", + "integrity": "sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA==" + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz", + "integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==", + "requires": { + "split2": "^3.1.1" + } + }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" + }, + "postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "requires": { + "xtend": "^4.0.0" + } + }, + "printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "optional": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "optional": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "optional": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "optional": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rlp": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", + "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", + "requires": { + "bn.js": "^4.11.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" + }, + "secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "requires": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + } + }, + "sqlite3": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.2.tgz", + "integrity": "sha512-1SdTNo+BVU211Xj1csWa8lV6KM0CtucDwRyA0VHl91wEH1Mgh7RxUpI4rVvG7OhHrzCSGaVyW5g8vKvlrk9DJA==", + "requires": { + "node-addon-api": "^3.0.0", + "node-gyp": "3.x", + "node-pre-gyp": "^0.11.0" + }, + "dependencies": { + "node-addon-api": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz", + "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==" + } + } + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "optional": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "optional": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "optional": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "transit-immutable-js": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/transit-immutable-js/-/transit-immutable-js-0.7.0.tgz", + "integrity": "sha1-mT4lCJtjEf9AIUD1VidtbSUwBdk=" + }, + "transit-js": { + "version": "0.8.867", + "resolved": "https://registry.npmjs.org/transit-js/-/transit-js-0.8.867.tgz", + "integrity": "sha512-rOwB4K0z/WZ+E2bV42iN9UV3mvGzmwSv/IpMOKdnFpawPAZT0d1L7f91Y+tZQF7lXSDGk+oln4XyIQXo+pyTGA==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "optional": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "optional": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "optional": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "slide": "^1.1.5" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "yargs-parser": { + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.5.tgz", + "integrity": "sha512-jYRGS3zWy20NtDtK2kBgo/TlAoy5YUuhD9/LZ7z7W4j1Fdw2cqD0xEEclf8fxc8xjD6X5Qr+qQQwCEsP8iRiYg==" + } + } +} diff --git a/apps/contract-migration/scripts/requirements.txt b/apps/contract-migration/scripts/requirements.txt new file mode 100644 index 0000000..3f04974 --- /dev/null +++ b/apps/contract-migration/scripts/requirements.txt @@ -0,0 +1,12 @@ +psycopg2==2.8.6 +chainlib~=0.0.1a15 +chainsyncer~=0.0.1a10 +cic-eth==0.10.0a30+build.fdb16130 +cic-registry~=0.5.3a19 +confini~=0.3.6rc3 +celery==4.4.7 +redis==3.5.3 +hexathon~=0.0.1a3 +faker==4.17.1 +cic-types==0.1.0a7+build.1c254367 +eth-accounts-index~=0.0.10a10 diff --git a/apps/contract-migration/scripts/traffic.py b/apps/contract-migration/scripts/traffic.py new file mode 100644 index 0000000..8dc4ba3 --- /dev/null +++ b/apps/contract-migration/scripts/traffic.py @@ -0,0 +1,101 @@ +# standard imports +import os +import logging +import re +import sys +import json + +# external imports +import redis +import celery +from chainsyncer.backend import MemBackend +from chainsyncer.driver import HeadSyncer +from chainlib.eth.connection import HTTPConnection +from chainlib.eth.gas import DefaultGasOracle +from chainlib.eth.nonce import DefaultNonceOracle +from chainlib.eth.block import block_latest +from hexathon import strip_0x + +# local imports +import common +from cmd.traffic import ( + TrafficItem, + TrafficRouter, + TrafficProvisioner, + TrafficSyncHandler, + ) +from cmd.traffic import add_args as add_traffic_args + + +# common basics +script_dir = os.path.realpath(os.path.dirname(__file__)) +logg = common.log.create() +argparser = common.argparse.create(script_dir, common.argparse.full_template) +argparser = common.argparse.add(argparser, add_traffic_args, 'traffic') +args = common.argparse.parse(argparser, logg) +config = common.config.create(args.c, args, args.env_prefix) + +# map custom args to local config entries +batchsize = args.batch_size +if batchsize < 1: + batchsize = 1 +logg.info('batch size {}'.format(batchsize)) +config.add(batchsize, '_BATCH_SIZE', True) + +config.add(args.redis_host_callback, '_REDIS_HOST_CALLBACK', True) +config.add(args.redis_port_callback, '_REDIS_PORT_CALLBACK', True) + +config.add(args.y, '_KEYSTORE_FILE', True) + +config.add(args.q, '_CELERY_QUEUE', True) + +common.config.log(config) + + +def main(): + # create signer (not currently in use, but needs to be accessible for custom traffic item generators) + (signer_address, signer) = common.signer.from_keystore(config.get('_KEYSTORE_FILE')) + + # connect to celery + celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=config.get('CELERY_RESULT_URL')) + + # set up registry + w3 = common.rpc.create(config.get('ETH_PROVIDER')) # replace with HTTPConnection when registry has been so refactored + registry = common.registry.init_legacy(config, w3) + + # Connect to blockchain with chainlib + conn = HTTPConnection(config.get('ETH_PROVIDER')) + gas_oracle = DefaultGasOracle(conn) + nonce_oracle = DefaultNonceOracle(signer_address, conn) + + # Set up magic traffic handler + traffic_router = TrafficRouter() + traffic_router.apply_import_dict(config.all(), config) + handler = TrafficSyncHandler(config, traffic_router) + + # Set up syncer + syncer_backend = MemBackend(config.get('CIC_CHAIN_SPEC'), 0) + o = block_latest() + r = conn.do(o) + block_offset = int(strip_0x(r), 16) + 1 + syncer_backend.set(block_offset, 0) + + # Set up provisioner for common task input data + TrafficProvisioner.oracles['token']= common.registry.TokenOracle(w3, config.get('CIC_CHAIN_SPEC'), registry) + TrafficProvisioner.oracles['account'] = common.registry.AccountsOracle(w3, config.get('CIC_CHAIN_SPEC'), registry) + TrafficProvisioner.default_aux = { + 'chain_spec': config.get('CIC_CHAIN_SPEC'), + 'registry': registry, + 'redis_host_callback': config.get('_REDIS_HOST_CALLBACK'), + 'redis_port_callback': config.get('_REDIS_PORT_CALLBACK'), + 'redis_db': config.get('REDIS_DB'), + 'api_queue': config.get('_CELERY_QUEUE'), + } + + syncer = HeadSyncer(syncer_backend, loop_callback=handler.refresh) + syncer.add_filter(handler) + syncer.loop(1, conn) + + +if __name__ == '__main__': + main() diff --git a/apps/contract-migration/scripts/verify.py b/apps/contract-migration/scripts/verify.py new file mode 100644 index 0000000..0b9ae20 --- /dev/null +++ b/apps/contract-migration/scripts/verify.py @@ -0,0 +1,306 @@ +# standard imports +import os +import sys +import logging +import time +import argparse +import sys +import re +import hashlib +import csv +import json +import urllib + +# external impotts +import celery +import eth_abi +import confini +from hexathon import ( + strip_0x, + add_0x, + ) +from cic_registry.chain import ChainSpec +from chainsyncer.backend import MemBackend +from chainsyncer.driver import HeadSyncer +from chainlib.eth.connection import HTTPConnection +from chainlib.eth.constant import ZERO_ADDRESS +from chainlib.eth.block import ( + block_latest, + block_by_number, + Block, + ) +from chainlib.eth.hash import keccak256_string_to_hex +from chainlib.eth.address import to_checksum +from chainlib.eth.erc20 import ERC20TxFactory +from chainlib.eth.gas import DefaultGasOracle +from chainlib.eth.nonce import DefaultNonceOracle +from chainlib.eth.tx import TxFactory +from chainlib.eth.rpc import jsonrpc_template +from chainlib.eth.error import EthException +from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer +from crypto_dev_signer.keystore import DictKeystore +from cic_eth.api.api_admin import AdminApi +from cic_types.models.person import ( + Person, + generate_metadata_pointer, + ) + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +config_dir = '/usr/local/etc/cic-syncer' + +argparser = argparse.ArgumentParser(description='daemon that monitors transactions in new blocks') +argparser.add_argument('-p', '--provider', dest='p', type=str, help='chain rpc provider address') +argparser.add_argument('-c', type=str, default=config_dir, help='config root to use') +argparser.add_argument('--old-chain-spec', type=str, dest='old_chain_spec', default='oldchain:1', help='chain spec') +argparser.add_argument('-i', '--chain-spec', type=str, dest='i', help='chain spec') +argparser.add_argument('--meta-provider', type=str, dest='meta_provider', default='http://localhost:63380', help='cic-meta url') +argparser.add_argument('-r', '--registry-address', type=str, dest='r', help='CIC Registry address') +argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration') +argparser.add_argument('-v', help='be verbose', action='store_true') +argparser.add_argument('-vv', help='be more verbose', action='store_true') +argparser.add_argument('user_dir', type=str, help='user export directory') +args = argparser.parse_args(sys.argv[1:]) + +if args.v == True: + logging.getLogger().setLevel(logging.INFO) +elif args.vv == True: + logging.getLogger().setLevel(logging.DEBUG) + +config_dir = os.path.join(args.c) +os.makedirs(config_dir, 0o777, True) +config = confini.Config(config_dir, args.env_prefix) +config.process() +# override args +args_override = { + 'CIC_CHAIN_SPEC': getattr(args, 'i'), + 'ETH_PROVIDER': getattr(args, 'p'), + 'CIC_REGISTRY_ADDRESS': getattr(args, 'r'), + } +config.dict_override(args_override, 'cli flag') +config.censor('PASSWORD', 'DATABASE') +config.censor('PASSWORD', 'SSL') +logg.debug('config loaded from {}:\n{}'.format(config_dir, config)) + +celery_app = celery.Celery(backend=config.get('CELERY_RESULT_URL'), broker=config.get('CELERY_BROKER_URL')) + +chain_spec = ChainSpec.from_chain_str(config.get('CIC_CHAIN_SPEC')) +chain_str = str(chain_spec) +old_chain_spec = ChainSpec.from_chain_str(args.old_chain_spec) +old_chain_str = str(old_chain_spec) +user_dir = args.user_dir # user_out_dir from import_users.py +meta_url = args.meta_provider + + +class VerifierError(Exception): + + def __init__(self, e, c): + super(VerifierError, self).__init__(e) + self.c = c + + + def __str__(self): + super_error = super(VerifierError, self).__str__() + return '[{}] {}'.format(self.c, super_error) + + +class Verifier: + + def __init__(self, conn, cic_eth_api, gas_oracle, chain_spec, index_address, token_address, data_dir): + self.conn = conn + self.gas_oracle = gas_oracle + self.chain_spec = chain_spec + self.index_address = index_address + self.token_address = token_address + self.erc20_tx_factory = ERC20TxFactory(chain_id=chain_spec.chain_id(), gas_oracle=gas_oracle) + self.tx_factory = TxFactory(chain_id=chain_spec.chain_id(), gas_oracle=gas_oracle) + self.api = cic_eth_api + self.data_dir = data_dir + + + def verify_accounts_index(self, address): + tx = self.tx_factory.template(ZERO_ADDRESS, self.index_address) + data = keccak256_string_to_hex('have(address)')[:8] + data += eth_abi.encode_single('address', address).hex() + tx = self.tx_factory.set_code(tx, data) + tx = self.tx_factory.normalize(tx) + o = jsonrpc_template() + o['method'] = 'eth_call' + o['params'].append(tx) + r = self.conn.do(o) + logg.debug('index check for {}: {}'.format(address, r)) + n = eth_abi.decode_single('uint256', bytes.fromhex(strip_0x(r))) + if n != 1: + raise VerifierError(n, 'accounts index') + + + def verify_balance(self, address, balance): + o = self.erc20_tx_factory.erc20_balance(self.token_address, address) + r = self.conn.do(o) + actual_balance = int(strip_0x(r), 16) + logg.debug('balance for {}: {}'.format(address, balance)) + if balance != actual_balance: + raise VerifierError((actual_balance, balance), 'balance') + + + def verify_local_key(self, address): + r = self.api.have_account(address, str(self.chain_spec)) + logg.debug('verify local key result {}'.format(r)) + if r != address: + raise VerifierError((address, r), 'local key') + + + def verify_metadata(self, address): + k = generate_metadata_pointer(bytes.fromhex(strip_0x(address)), ':cic.person') + url = os.path.join(meta_url, k) + logg.debug('verify metadata url {}'.format(url)) + try: + res = urllib.request.urlopen(url) + except urllib.error.HTTPError as e: + raise VerifierError( + '({}) {}'.format(url, e), + 'metadata (person)', + ) + b = res.read() + o_retrieved = json.loads(b.decode('utf-8')) + + upper_address = strip_0x(address).upper() + f = open(os.path.join( + self.data_dir, + 'new', + upper_address[:2], + upper_address[2:4], + upper_address + '.json', + ), 'r' + ) + o_original = json.load(f) + f.close() + + if o_original != o_retrieved: + raise VerifierError(o_retrieved, 'metadata (person)') + + + def verify(self, address, balance): + logg.debug('verify {} {}'.format(address, balance)) + + try: + self.verify_local_key(address) + self.verify_accounts_index(address) + self.verify_balance(address, balance) + self.verify_metadata(address) + except VerifierError as e: + logg.critical('verification failed: {}'.format(e)) + sys.exit(1) + + +class MockClient: + + w3 = None + +def main(): + global chain_str, block_offset, user_dir + + conn = HTTPConnection(config.get('ETH_PROVIDER')) + gas_oracle = DefaultGasOracle(conn) + + # Get Token registry address + txf = TxFactory(signer=None, gas_oracle=gas_oracle, nonce_oracle=None, chain_id=chain_spec.chain_id()) + tx = txf.template(ZERO_ADDRESS, config.get('CIC_REGISTRY_ADDRESS')) + + registry_addressof_method = keccak256_string_to_hex('addressOf(bytes32)')[:8] + data = add_0x(registry_addressof_method) + data += eth_abi.encode_single('bytes32', b'TokenRegistry').hex() + txf.set_code(tx, data) + + o = jsonrpc_template() + o['method'] = 'eth_call' + o['params'].append(txf.normalize(tx)) + o['params'].append('latest') + r = conn.do(o) + print('r {}'.format(r)) + token_index_address = to_checksum(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) + logg.info('found token index address {}'.format(token_index_address)) + + data = add_0x(registry_addressof_method) + data += eth_abi.encode_single('bytes32', b'AccountRegistry').hex() + txf.set_code(tx, data) + + o = jsonrpc_template() + o['method'] = 'eth_call' + o['params'].append(txf.normalize(tx)) + o['params'].append('latest') + r = conn.do(o) + account_index_address = to_checksum(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) + logg.info('found account index address {}'.format(account_index_address)) + + + # Get Sarafu token address + tx = txf.template(ZERO_ADDRESS, token_index_address) + data = add_0x(registry_addressof_method) + h = hashlib.new('sha256') + h.update(b'SRF') + z = h.digest() + data += eth_abi.encode_single('bytes32', z).hex() + txf.set_code(tx, data) + o = jsonrpc_template() + o['method'] = 'eth_call' + o['params'].append(txf.normalize(tx)) + o['params'].append('latest') + r = conn.do(o) + print('r {}'.format(r)) + sarafu_token_address = to_checksum(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) + logg.info('found token address {}'.format(sarafu_token_address)) + + balances = {} + f = open('{}/balances.csv'.format(user_dir, 'r')) + remove_zeros = 10**12 + i = 0 + while True: + l = f.readline() + if l == None: + break + r = l.split(',') + try: + address = to_checksum(r[0]) + sys.stdout.write('loading balance {} {}'.format(i, address).ljust(200) + "\r") + except ValueError: + break + balance = int(int(r[1].rstrip()) / remove_zeros) + balances[address] = balance + i += 1 + + f.close() + + api = AdminApi(MockClient()) + + verifier = Verifier(conn, api, gas_oracle, chain_spec, account_index_address, sarafu_token_address, user_dir) + + user_new_dir = os.path.join(user_dir, 'new') + for x in os.walk(user_new_dir): + for y in x[2]: + if y[len(y)-5:] != '.json': + continue + filepath = os.path.join(x[0], y) + f = open(filepath, 'r') + try: + o = json.load(f) + except json.decoder.JSONDecodeError as e: + f.close() + logg.error('load error for {}: {}'.format(y, e)) + continue + f.close() + + u = Person.deserialize(o) + logg.debug('data {}'.format(u.identities['evm'])) + + new_address = u.identities['evm'][chain_str][0] + old_address = u.identities['evm'][old_chain_str][0] + balance = balances[old_address] + logg.debug('checking {} -> {} = {}'.format(old_address, new_address, balance)) + + verifier.verify(new_address, balance) + + +if __name__ == '__main__': + main() diff --git a/apps/contract-migration/seed_cic_eth.sh b/apps/contract-migration/seed_cic_eth.sh index 39b5f64..14e4e88 100644 --- a/apps/contract-migration/seed_cic_eth.sh +++ b/apps/contract-migration/seed_cic_eth.sh @@ -20,7 +20,8 @@ debug='-vv' abi_dir=${ETH_ABI_DIR:-/usr/local/share/cic/solidity/abi} gas_amount=100000000000000000000000 token_amount=${gas_amount} -faucet_amount=1000000000 +#faucet_amount=1000000000 +faucet_amount=0 env_out_file=${CIC_DATA_DIR}/.env_seed init_level_file=${CIC_DATA_DIR}/.init truncate $env_out_file -s 0 @@ -29,7 +30,8 @@ truncate $env_out_file -s 0 set -e set -a -pip install --extra-index-url $DEV_PIP_EXTRA_INDEX_URL cic-eth==0.10.0a25 chainlib==0.0.1a11 +# We need to not install these here... +pip install --extra-index-url $DEV_PIP_EXTRA_INDEX_URL cic-eth==0.10.0a30+build.fdb16130 chainlib==0.0.1a16 >&2 echo "create account for gas gifter" old_gas_provider=$DEV_ETH_ACCOUNT_GAS_PROVIDER @@ -87,13 +89,13 @@ export DEV_ETH_SARAFU_TOKEN_ADDRESS=$DEV_ETH_RESERVE_ADDRESS >&2 echo "deploy transfer authorization contract" -CIC_TRANSFER_AUTHORIZATION_ADDRESS=`erc20-approval-escrow-deploy -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER --approver $DEV_ETH_ACCOUNT_TRANSFER_AUTHORIZATION_OWNER -w $debug` -echo CIC_APPROVAL_ESCROW_ADDRESS=$CIC_TRANSFER_AUTHORIZATION_ADDRESS >> $env_out_file -export CIC_TRANSFER_AUTHORIZATION_ADDRESS=$CIC_TRANSFER_AUTHORIZATION_ADDRESS +#CIC_TRANSFER_AUTHORIZATION_ADDRESS=`erc20-approval-escrow-deploy -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER --approver $DEV_ETH_ACCOUNT_TRANSFER_AUTHORIZATION_OWNER -w $debug` +#echo CIC_APPROVAL_ESCROW_ADDRESS=$CIC_TRANSFER_AUTHORIZATION_ADDRESS >> $env_out_file +#export CIC_TRANSFER_AUTHORIZATION_ADDRESS=$CIC_TRANSFER_AUTHORIZATION_ADDRESS # Register transfer approval contract ->&2 echo "add transfer approval request contract to registry" ->&2 cic-registry-set -y $keystore_file -r $CIC_REGISTRY_ADDRESS -k TransferApproval -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $CIC_TRANSFER_AUTHORIZATION_ADDRESS +#>&2 echo "add transfer approval request contract to registry" +#>&2 cic-registry-set -y $keystore_file -r $CIC_REGISTRY_ADDRESS -k TransferApproval -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $CIC_TRANSFER_AUTHORIZATION_ADDRESS # Deploy one-time token faucet for newly created token diff --git a/apps/contract-migration/testdata/pgp/privatekeys_meta.asc b/apps/contract-migration/testdata/pgp/privatekeys_meta.asc new file mode 100644 index 0000000..3b2fd80 --- /dev/null +++ b/apps/contract-migration/testdata/pgp/privatekeys_meta.asc @@ -0,0 +1,241 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +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 +1VrzRbOS5ymseDJcjejtMxuCOuSTN9R5KuQ= +=VqO+ +-----END PGP PRIVATE KEY BLOCK----- diff --git a/apps/contract-migration/testdata/pgp/publickeys_meta.asc b/apps/contract-migration/testdata/pgp/publickeys_meta.asc new file mode 100644 index 0000000..a7dd871 --- /dev/null +++ b/apps/contract-migration/testdata/pgp/publickeys_meta.asc @@ -0,0 +1,151 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +KuNFGWsKI1qTd1aEMRQzT4s+JJM= +=8257 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/docker-compose.yml b/docker-compose.yml index 2c54eae..ac85dea 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -84,7 +84,7 @@ services: # And these two are for wait-for-it (could parse this) ETH_PROVIDER_HOST: eth ETH_PROVIDER_PORT: 8545 - CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-Bloxberg:8996} + CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-evm:bloxberg:8996} CIC_DATA_DIR: ${CIC_DATA_DIR:-/tmp/cic/config} command: ["./reset.sh"] depends_on: @@ -102,7 +102,7 @@ services: # And these two are for wait-for-it (could parse this) ETH_PROVIDER_HOST: eth ETH_PROVIDER_PORT: 8545 - CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-Bloxberg:8996} + CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-evm:bloxberg:8996} CIC_DATA_DIR: ${CIC_DATA_DIR:-/tmp/cic/config} DATABASE_HOST: ${DATABASE_HOST:-postgres} DATABASE_PORT: ${DATABASE_PORT:-5432} @@ -146,7 +146,7 @@ services: DATABASE_DEBUG: 1 ETH_ABI_DIR: ${ETH_ABI_DIR:-/usr/local/share/cic/solidity/abi} CIC_TRUST_ADDRESS: ${DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER:-0xEb3907eCad74a0013c259D5874AE7f22DcBcC95C} - CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-Bloxberg:8996} + CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-evm:bloxberg:8996} CELERY_BROKER_URL: redis://redis:6379 CELERY_RESULT_URL: redis://redis:6379 deploy: @@ -214,7 +214,7 @@ services: DATABASE_DRIVER: ${DATABASE_DRIVER:-psycopg2} DATABASE_DEBUG: ${DATABASE_DEBUG:-0} PGPASSWORD: ${DATABASE_PASSWORD:-tralala} - CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-Bloxberg:8996} + CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-evm:bloxberg:8996} BANCOR_DIR: ${BANCOR_DIR:-/usr/local/share/cic/bancor} CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://redis} CELERY_RESULT_URL: ${CELERY_RESULT_URL:-redis://redis} @@ -253,9 +253,8 @@ services: DATABASE_PORT: ${DATABASE_PORT:-5432} DATABASE_ENGINE: ${DATABASE_ENGINE:-postgres} DATABASE_DRIVER: ${DATABASE_DRIVER:-psycopg2} - #DATABASE_DEBUG: ${DATABASE_DEBUG:-0} DATABASE_DEBUG: 1 - CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-Bloxberg:8996} + CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-evm:bloxberg:8996} CIC_REGISTRY_ADDRESS: $CIC_REGISTRY_ADDRESS #BANCOR_DIR: $BANCOR_DIR CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://redis} @@ -275,7 +274,7 @@ services: - -c - | if [[ -f /tmp/cic/config/.env ]]; then source /tmp/cic/config/.env; fi - ./start_manager.sh head -vv + ./start_manager.sh head -v # command: "/root/start_manager.sh head -vv" cic-eth-manager-history: @@ -292,7 +291,7 @@ services: DATABASE_ENGINE: ${DATABASE_ENGINE:-postgres} DATABASE_DRIVER: ${DATABASE_DRIVER:-psycopg2} DATABASE_DEBUG: ${DATABASE_DEBUG:-0} - CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-Bloxberg:8996} + CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-evm:bloxberg:8996} CIC_REGISTRY_ADDRESS: $CIC_REGISTRY_ADDRESS #BANCOR_DIR: $BANCOR_DIR CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://redis} @@ -312,7 +311,7 @@ services: - -c - | if [[ -f /tmp/cic/config/.env ]]; then source /tmp/cic/config/.env; fi - ./start_manager.sh history -vv + ./start_manager.sh history -v # command: "/root/start_manager.sh history -vv" cic-eth-dispatcher: @@ -329,7 +328,7 @@ services: DATABASE_ENGINE: ${DATABASE_ENGINE:-postgres} DATABASE_DRIVER: ${DATABASE_DRIVER:-psycopg2} DATABASE_DEBUG: ${DATABASE_DEBUG:-0} - CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-Bloxberg:8996} + CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-evm:bloxberg:8996} CIC_REGISTRY_ADDRESS: $CIC_REGISTRY_ADDRESS #BANCOR_DIR: $BANCOR_DIR CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://redis} @@ -351,7 +350,7 @@ services: - -c - | if [[ -f /tmp/cic/config/.env ]]; then source /tmp/cic/config/.env; fi - ./start_dispatcher.sh -q cic-eth -vv + ./start_dispatcher.sh -q cic-eth -v # command: "/root/start_dispatcher.sh -q cic-eth -vv" @@ -368,7 +367,8 @@ services: DATABASE_PORT: ${DATABASE_PORT:-5432} DATABASE_ENGINE: ${DATABASE_ENGINE:-postgres} DATABASE_DRIVER: ${DATABASE_DRIVER:-psycopg2} - CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-Bloxberg:8996} + DATABASE_DEBUG: ${DATABASE_DEBUG:-0} + CIC_CHAIN_SPEC: ${CIC_CHAIN_SPEC:-evm:bloxberg:8996} CIC_REGISTRY_ADDRESS: $CIC_REGISTRY_ADDRESS #BANCOR_DIR: $BANCOR_DIR CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://redis} @@ -389,7 +389,7 @@ services: - -c - | if [[ -f /tmp/cic/config/.env ]]; then source /tmp/cic/config/.env; fi - ./start_retry.sh -vv + ./start_retry.sh -v # command: "/root/start_retry.sh -q cic-eth -vv"