diff --git a/.gitignore b/.gitignore index 15b5df4a..04eee297 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ service-configs/* !service-configs/.gitkeep +**/node_modules/ +__pycache__ +*.pyc +*.o diff --git a/apps/cic-cache/cic_cache/runnable/daemons/filters/erc20.py b/apps/cic-cache/cic_cache/runnable/daemons/filters/erc20.py index e2312a71..0ff88852 100644 --- a/apps/cic-cache/cic_cache/runnable/daemons/filters/erc20.py +++ b/apps/cic-cache/cic_cache/runnable/daemons/filters/erc20.py @@ -67,6 +67,7 @@ class ERC20TransferFilter(SyncFilter): tx.status == Status.SUCCESS, block.timestamp, ) - db_session.flush() + #db_session.flush() + db_session.commit() return True diff --git a/apps/cic-cache/cic_cache/runnable/daemons/tracker.py b/apps/cic-cache/cic_cache/runnable/daemons/tracker.py index bd03528a..270e1f6a 100644 --- a/apps/cic-cache/cic_cache/runnable/daemons/tracker.py +++ b/apps/cic-cache/cic_cache/runnable/daemons/tracker.py @@ -77,7 +77,7 @@ def main(): if len(syncer_backends) == 0: logg.info('found no backends to resume') - syncers.append(SQLBackend.initial(chain_spec, block_offset)) + syncer_backends.append(SQLBackend.initial(chain_spec, block_offset)) else: for syncer_backend in syncer_backends: logg.info('resuming sync session {}'.format(syncer_backend)) diff --git a/apps/cic-cache/docker/Dockerfile b/apps/cic-cache/docker/Dockerfile index 16752f45..ed01fd54 100644 --- a/apps/cic-cache/docker/Dockerfile +++ b/apps/cic-cache/docker/Dockerfile @@ -17,7 +17,7 @@ RUN apt-get update && \ # Copy shared requirements from top of mono-repo RUN echo "copying root req file ${root_requirement_file}" -RUN pip install $pip_extra_index_url_flag cic-base[full_graph]==0.1.2a58 +RUN pip install $pip_extra_index_url_flag cic-base[full_graph]==0.1.2a76 COPY cic-cache/requirements.txt ./ COPY cic-cache/setup.cfg \ diff --git a/apps/cic-eth/cic_eth/eth/meta.py b/apps/cic-eth/cic_eth/eth/meta.py index e6f446d3..21ab8295 100644 --- a/apps/cic-eth/cic_eth/eth/meta.py +++ b/apps/cic-eth/cic_eth/eth/meta.py @@ -1,6 +1,10 @@ -# extended imports +# external imports from chainlib.eth.constant import ZERO_ADDRESS from chainlib.status import Status as TxStatus +from cic_eth_registry.erc20 import ERC20Token + +# local imports +from cic_eth.ext.address import translate_address class ExtendedTx: @@ -27,12 +31,12 @@ class ExtendedTx: self.status_code = TxStatus.PENDING.value - def set_actors(self, sender, recipient, trusted_declarator_addresses=None): + def set_actors(self, sender, recipient, trusted_declarator_addresses=None, caller_address=ZERO_ADDRESS): self.sender = sender self.recipient = recipient if trusted_declarator_addresses != None: - self.sender_label = translate_address(sender, trusted_declarator_addresses, self.chain_spec) - self.recipient_label = translate_address(recipient, trusted_declarator_addresses, self.chain_spec) + self.sender_label = translate_address(sender, trusted_declarator_addresses, self.chain_spec, sender_address=caller_address) + self.recipient_label = translate_address(recipient, trusted_declarator_addresses, self.chain_spec, sender_address=caller_address) def set_tokens(self, source, source_value, destination=None, destination_value=None): @@ -40,8 +44,8 @@ class ExtendedTx: destination = source if destination_value == None: destination_value = source_value - st = ERC20Token(self.rpc, source) - dt = ERC20Token(self.rpc, destination) + st = ERC20Token(self.chain_spec, self.rpc, source) + dt = ERC20Token(self.chain_spec, self.rpc, destination) self.source_token = source self.source_token_symbol = st.symbol self.source_token_name = st.name @@ -62,10 +66,10 @@ class ExtendedTx: self.status_code = n - def to_dict(self): + def asdict(self): o = {} for attr in dir(self): - if attr[0] == '_' or attr in ['set_actors', 'set_tokens', 'set_status', 'to_dict']: + if attr[0] == '_' or attr in ['set_actors', 'set_tokens', 'set_status', 'asdict', 'rpc']: continue o[attr] = getattr(self, attr) return o diff --git a/apps/cic-eth/cic_eth/runnable/daemons/filters/callback.py b/apps/cic-eth/cic_eth/runnable/daemons/filters/callback.py index 4155a007..dd1a587b 100644 --- a/apps/cic-eth/cic_eth/runnable/daemons/filters/callback.py +++ b/apps/cic-eth/cic_eth/runnable/daemons/filters/callback.py @@ -1,7 +1,7 @@ # standard imports import logging -# third-party imports +# external imports import celery from cic_eth_registry.error import UnknownContractError from chainlib.status import Status as TxStatus @@ -9,7 +9,13 @@ from chainlib.eth.address import to_checksum_address from chainlib.eth.error import RequestMismatchException from chainlib.eth.constant import ZERO_ADDRESS from chainlib.eth.erc20 import ERC20 -from hexathon import strip_0x +from hexathon import ( + strip_0x, + add_0x, + ) +# TODO: use sarafu_Faucet for both when inheritance has been implemented +from erc20_single_shot_faucet import SingleShotFaucet +from sarafu_faucet import MinterFaucet as Faucet # local imports from .base import SyncFilter @@ -18,65 +24,73 @@ from cic_eth.eth.meta import ExtendedTx logg = logging.getLogger().getChild(__name__) -def parse_transfer(tx): - r = ERC20.parse_transfer_request(tx.payload) - transfer_data = {} - transfer_data['to'] = r[0] - transfer_data['value'] = r[1] - transfer_data['from'] = tx['from'] - transfer_data['token_address'] = tx['to'] - return ('transfer', transfer_data) - - -def parse_transferfrom(tx): - r = ERC20.parse_transfer_request(tx.payload) - transfer_data = unpack_transferfrom(tx.payload) - transfer_data['from'] = r[0] - transfer_data['to'] = r[1] - transfer_data['value'] = r[2] - transfer_data['token_address'] = tx['to'] - return ('transferfrom', transfer_data) - - -def parse_giftto(tx): - # TODO: broken - logg.error('broken') - return - transfer_data = unpack_gift(tx.payload) - transfer_data['from'] = tx.inputs[0] - transfer_data['value'] = 0 - transfer_data['token_address'] = ZERO_ADDRESS - # TODO: would be better to query the gift amount from the block state - for l in tx.logs: - topics = l['topics'] - logg.debug('topixx {}'.format(topics)) - if strip_0x(topics[0]) == '45c201a59ac545000ead84f30b2db67da23353aa1d58ac522c48505412143ffa': - #transfer_data['value'] = web3.Web3.toInt(hexstr=strip_0x(l['data'])) - transfer_data['value'] = int.from_bytes(bytes.fromhex(strip_0x(l_data))) - #token_address_bytes = topics[2][32-20:] - token_address = strip_0x(topics[2])[64-40:] - transfer_data['token_address'] = to_checksum_address(token_address) - return ('tokengift', transfer_data) - class CallbackFilter(SyncFilter): trusted_addresses = [] - def __init__(self, chain_spec, method, queue): + def __init__(self, chain_spec, method, queue, caller_address=ZERO_ADDRESS): self.queue = queue self.method = method self.chain_spec = chain_spec + self.caller_address = caller_address + + + def parse_transfer(self, tx, conn): + if not tx.payload: + return (None, None) + r = ERC20.parse_transfer_request(tx.payload) + transfer_data = {} + transfer_data['to'] = r[0] + transfer_data['value'] = r[1] + transfer_data['from'] = tx.outputs[0] + transfer_data['token_address'] = tx.inputs[0] + return ('transfer', transfer_data) + + + def parse_transferfrom(self, tx, conn): + if not tx.payload: + return (None, None) + r = ERC20.parse_transfer_from_request(tx.payload) + transfer_data = {} + transfer_data['from'] = r[0] + transfer_data['to'] = r[1] + transfer_data['value'] = r[2] + transfer_data['token_address'] = tx.inputs[0] + return ('transferfrom', transfer_data) + + + def parse_giftto(self, tx, conn): + if not tx.payload: + return (None, None) + r = Faucet.parse_give_to_request(tx.payload) + transfer_data = {} + transfer_data['to'] = r[0] + transfer_data['value'] = tx.value + transfer_data['from'] = tx.outputs[0] + #transfer_data['token_address'] = tx.inputs[0] + faucet_contract = tx.inputs[0] + + c = SingleShotFaucet(self.chain_spec) + o = c.token(faucet_contract, sender_address=self.caller_address) + r = conn.do(o) + transfer_data['token_address'] = add_0x(c.parse_token(r)) + + o = c.amount(faucet_contract, sender_address=self.caller_address) + r = conn.do(o) + transfer_data['value'] = c.parse_amount(r) + + return ('tokengift', transfer_data) def call_back(self, transfer_type, result): - logg.debug('result {}'.format(result)) + result['chain_spec'] = result['chain_spec'].asdict() s = celery.signature( self.method, [ result, transfer_type, - int(result['status_code'] == 0), + int(result['status_code'] != 0), ], queue=self.queue, ) @@ -92,26 +106,29 @@ class CallbackFilter(SyncFilter): # s_translate.link(s) # s_translate.apply_async() t = s.apply_async() - return s + return t - def parse_data(self, tx): + def parse_data(self, tx, conn): transfer_type = None transfer_data = None # TODO: what's with the mix of attributes and dict keys logg.debug('have payload {}'.format(tx.payload)) - method_signature = tx.payload[:8] logg.debug('tx status {}'.format(tx.status)) for parser in [ - parse_transfer, - parse_transferfrom, - parse_giftto, + self.parse_transfer, + self.parse_transferfrom, + self.parse_giftto, ]: try: - (transfer_type, transfer_data) = parser(tx) - break + if tx: + (transfer_type, transfer_data) = parser(tx, conn) + if transfer_type == None: + continue + else: + pass except RequestMismatchException: continue @@ -128,7 +145,7 @@ class CallbackFilter(SyncFilter): transfer_data = None transfer_type = None try: - (transfer_type, transfer_data) = self.parse_data(tx) + (transfer_type, transfer_data) = self.parse_data(tx, conn) except TypeError: logg.debug('invalid method data length for tx {}'.format(tx.hash)) return @@ -144,16 +161,17 @@ class CallbackFilter(SyncFilter): result = None try: tokentx = ExtendedTx(conn, tx.hash, self.chain_spec) - tokentx.set_actors(transfer_data['from'], transfer_data['to'], self.trusted_addresses) + tokentx.set_actors(transfer_data['from'], transfer_data['to'], self.trusted_addresses, caller_address=self.caller_address) tokentx.set_tokens(transfer_data['token_address'], transfer_data['value']) if transfer_data['status'] == 0: tokentx.set_status(1) else: tokentx.set_status(0) - t = self.call_back(transfer_type, tokentx.to_dict()) - logg.info('callback success task id {} tx {}'.format(t, tx.hash)) + result = tokentx.asdict() + t = self.call_back(transfer_type, result) + logg.info('callback success task id {} tx {} queue {}'.format(t, tx.hash, t.queue)) except UnknownContractError: - logg.debug('callback filter {}:{} skipping "transfer" method on unknown contract {} tx {}'.format(tc.queue, tc.method, transfer_data['to'], tx.hash)) + logg.debug('callback filter {}:{} skipping "transfer" method on unknown contract {} tx {}'.format(tx.queue, tx.method, transfer_data['to'], tx.hash)) def __str__(self): diff --git a/apps/cic-eth/cic_eth/runnable/daemons/tasker.py b/apps/cic-eth/cic_eth/runnable/daemons/tasker.py index 8a4a47f5..bfaf8ee1 100644 --- a/apps/cic-eth/cic_eth/runnable/daemons/tasker.py +++ b/apps/cic-eth/cic_eth/runnable/daemons/tasker.py @@ -39,6 +39,7 @@ from cic_eth.queue import ( from cic_eth.callbacks import ( Callback, http, + noop, #tcp, redis, ) diff --git a/apps/cic-eth/cic_eth/runnable/daemons/tracker.py b/apps/cic-eth/cic_eth/runnable/daemons/tracker.py index f25f28d7..d20dc338 100644 --- a/apps/cic-eth/cic_eth/runnable/daemons/tracker.py +++ b/apps/cic-eth/cic_eth/runnable/daemons/tracker.py @@ -15,7 +15,6 @@ import cic_base.config import cic_base.log import cic_base.argparse import cic_base.rpc -from cic_eth_registry import CICRegistry from cic_eth_registry.error import UnknownContractError from chainlib.chain import ChainSpec from chainlib.eth.constant import ZERO_ADDRESS @@ -43,6 +42,12 @@ from cic_eth.runnable.daemons.filters import ( TransferAuthFilter, ) from cic_eth.stat import init_chain_stat +from cic_eth.registry import ( + connect as connect_registry, + connect_declarator, + connect_token_registry, + ) + script_dir = os.path.realpath(os.path.dirname(__file__)) @@ -109,6 +114,8 @@ def main(): logg.info('Initializing HEAD syncer on backend {}'.format(syncer_backend)) syncers.append(HeadSyncer(syncer_backend)) + connect_registry(rpc, chain_spec, config.get('CIC_REGISTRY_ADDRESS')) + trusted_addresses_src = config.get('CIC_TRUST_ADDRESS') if trusted_addresses_src == None: logg.critical('At least one trusted address must be declared in CIC_TRUST_ADDRESS') @@ -116,6 +123,8 @@ def main(): trusted_addresses = trusted_addresses_src.split(',') for address in trusted_addresses: logg.info('using trusted address {}'.format(address)) + connect_declarator(rpc, chain_spec, trusted_addresses) + connect_token_registry(rpc, chain_spec) CallbackFilter.trusted_addresses = trusted_addresses callback_filters = [] diff --git a/apps/cic-eth/requirements.txt b/apps/cic-eth/requirements.txt index 3495b0d5..15e02448 100644 --- a/apps/cic-eth/requirements.txt +++ b/apps/cic-eth/requirements.txt @@ -1,25 +1,25 @@ -cic-base~=0.1.2a67 +cic-base~=0.1.2a76 celery==4.4.7 -crypto-dev-signer~=0.4.14b1 +crypto-dev-signer~=0.4.14b2 confini~=0.3.6rc3 -cic-eth-registry~=0.5.4a13 +cic-eth-registry~=0.5.4a16 #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.11a8 -erc20-transfer-authorization~=0.3.1a4 -#simple-rlp==0.1.2 +eth_accounts_index~=0.0.11a9 +erc20-transfer-authorization~=0.3.1a5 uWSGI==2.0.19.1 semver==2.13.0 websocket-client==0.57.0 moolb~=0.1.1b2 -eth-address-index~=0.1.1a8 -chainlib~=0.0.2a8 +eth-address-index~=0.1.1a9 +chainlib~=0.0.2a13 hexathon~=0.0.1a7 chainsyncer[sql]~=0.0.2a2 chainqueue~=0.0.1a7 pysha3==1.0.2 coincurve==15.0.0 -sarafu-faucet~=0.0.2a26 +sarafu-faucet==0.0.2a28 +potaahto~=0.0.1a1 diff --git a/apps/cic-eth/test_requirements.txt b/apps/cic-eth/test_requirements.txt index 05ab7cf6..6b61f67c 100644 --- a/apps/cic-eth/test_requirements.txt +++ b/apps/cic-eth/test_requirements.txt @@ -4,4 +4,4 @@ pytest-mock==3.3.1 pytest-cov==2.10.1 eth-tester==0.5.0b3 py-evm==0.3.0a20 -giftable-erc20-token==0.0.8a4 +giftable-erc20-token==0.0.8a9 diff --git a/apps/cic-eth/tests/filters/test_callback_filter.py b/apps/cic-eth/tests/filters/test_callback_filter.py new file mode 100644 index 00000000..952ff157 --- /dev/null +++ b/apps/cic-eth/tests/filters/test_callback_filter.py @@ -0,0 +1,223 @@ +# standard import +import logging +import datetime +import os + +# external imports +import pytest +from chainlib.connection import RPCConnection +from chainlib.eth.nonce import RPCNonceOracle +from chainlib.eth.gas import OverrideGasOracle +from chainlib.eth.tx import ( + receipt, + transaction, + Tx, + ) +from chainlib.eth.block import Block +from chainlib.eth.erc20 import ERC20 +from sarafu_faucet import MinterFaucet +from eth_accounts_index import AccountRegistry +from potaahto.symbols import snake_and_camel +from hexathon import add_0x + +# local imports +from cic_eth.runnable.daemons.filters.callback import CallbackFilter + +logg = logging.getLogger() + + +@pytest.mark.skip() +def test_transfer_tx( + default_chain_spec, + init_database, + eth_rpc, + eth_signer, + foo_token, + agent_roles, + token_roles, + contract_roles, + celery_session_worker, + ): + + rpc = RPCConnection.connect(default_chain_spec, 'default') + nonce_oracle = RPCNonceOracle(token_roles['FOO_TOKEN_OWNER'], rpc) + gas_oracle = OverrideGasOracle(conn=rpc, limit=200000) + + txf = ERC20(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle) + (tx_hash_hex, o) = txf.transfer(foo_token, token_roles['FOO_TOKEN_OWNER'], agent_roles['ALICE'], 1024) + r = rpc.do(o) + + o = transaction(tx_hash_hex) + r = rpc.do(o) + logg.debug(r) + tx_src = snake_and_camel(r) + tx = Tx(tx_src) + + o = receipt(tx_hash_hex) + r = rpc.do(o) + assert r['status'] == 1 + + rcpt = snake_and_camel(r) + tx.apply_receipt(rcpt) + + fltr = CallbackFilter(default_chain_spec, None, None, caller_address=contract_roles['CONTRACT_DEPLOYER']) + (transfer_type, transfer_data) = fltr.parse_transfer(tx, eth_rpc) + + assert transfer_type == 'transfer' + + +@pytest.mark.skip() +def test_transfer_from_tx( + default_chain_spec, + init_database, + eth_rpc, + eth_signer, + foo_token, + agent_roles, + token_roles, + contract_roles, + celery_session_worker, + ): + + rpc = RPCConnection.connect(default_chain_spec, 'default') + nonce_oracle = RPCNonceOracle(token_roles['FOO_TOKEN_OWNER'], rpc) + gas_oracle = OverrideGasOracle(conn=rpc, limit=200000) + + txf = ERC20(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle) + + (tx_hash_hex, o) = txf.approve(foo_token, token_roles['FOO_TOKEN_OWNER'], agent_roles['ALICE'], 1024) + r = rpc.do(o) + o = receipt(tx_hash_hex) + r = rpc.do(o) + assert r['status'] == 1 + + nonce_oracle = RPCNonceOracle(agent_roles['ALICE'], rpc) + txf = ERC20(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle) + (tx_hash_hex, o) = txf.transfer_from(foo_token, agent_roles['ALICE'], token_roles['FOO_TOKEN_OWNER'], agent_roles['BOB'], 1024) + r = rpc.do(o) + + o = transaction(tx_hash_hex) + r = rpc.do(o) + tx_src = snake_and_camel(r) + tx = Tx(tx_src) + + o = receipt(tx_hash_hex) + r = rpc.do(o) + assert r['status'] == 1 + + rcpt = snake_and_camel(r) + tx.apply_receipt(rcpt) + + fltr = CallbackFilter(default_chain_spec, None, None, caller_address=contract_roles['CONTRACT_DEPLOYER']) + (transfer_type, transfer_data) = fltr.parse_transferfrom(tx, eth_rpc) + + assert transfer_type == 'transferfrom' + + +def test_faucet_gift_to_tx( + default_chain_spec, + init_database, + eth_rpc, + eth_signer, + foo_token, + agent_roles, + contract_roles, + faucet, + account_registry, + celery_session_worker, + ): + + rpc = RPCConnection.connect(default_chain_spec, 'default') + gas_oracle = OverrideGasOracle(conn=rpc, limit=800000) + + nonce_oracle = RPCNonceOracle(contract_roles['ACCOUNT_REGISTRY_WRITER'], rpc) + txf = AccountRegistry(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle) + (tx_hash_hex, o) = txf.add(account_registry, contract_roles['ACCOUNT_REGISTRY_WRITER'], agent_roles['ALICE']) + r = rpc.do(o) + o = receipt(tx_hash_hex) + r = rpc.do(o) + assert r['status'] == 1 + + nonce_oracle = RPCNonceOracle(agent_roles['ALICE'], rpc) + txf = MinterFaucet(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle) + (tx_hash_hex, o) = txf.give_to(faucet, agent_roles['ALICE'], agent_roles['ALICE']) + r = rpc.do(o) + + o = transaction(tx_hash_hex) + r = rpc.do(o) + tx_src = snake_and_camel(r) + tx = Tx(tx_src) + + o = receipt(tx_hash_hex) + r = rpc.do(o) + assert r['status'] == 1 + + rcpt = snake_and_camel(r) + tx.apply_receipt(rcpt) + + fltr = CallbackFilter(default_chain_spec, None, None, caller_address=contract_roles['CONTRACT_DEPLOYER']) + (transfer_type, transfer_data) = fltr.parse_giftto(tx, eth_rpc) + + assert transfer_type == 'tokengift' + assert transfer_data['token_address'] == foo_token + + +def test_callback_filter( + default_chain_spec, + init_database, + eth_rpc, + eth_signer, + foo_token, + token_roles, + agent_roles, + contract_roles, + register_lookups, + ): + + rpc = RPCConnection.connect(default_chain_spec, 'default') + nonce_oracle = RPCNonceOracle(token_roles['FOO_TOKEN_OWNER'], rpc) + gas_oracle = OverrideGasOracle(conn=rpc, limit=200000) + + txf = ERC20(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle) + (tx_hash_hex, o) = txf.transfer(foo_token, token_roles['FOO_TOKEN_OWNER'], agent_roles['ALICE'], 1024) + r = rpc.do(o) + + o = transaction(tx_hash_hex) + r = rpc.do(o) + logg.debug(r) + + mockblock_src = { + 'hash': add_0x(os.urandom(32).hex()), + 'number': '0x2a', + 'transactions': [tx_hash_hex], + 'timestamp': datetime.datetime.utcnow().timestamp(), + } + mockblock = Block(mockblock_src) + + tx_src = snake_and_camel(r) + tx = Tx(tx_src, block=mockblock) + + o = receipt(tx_hash_hex) + r = rpc.do(o) + assert r['status'] == 1 + + rcpt = snake_and_camel(r) + tx.apply_receipt(rcpt) + + fltr = CallbackFilter(default_chain_spec, None, None, caller_address=contract_roles['CONTRACT_DEPLOYER']) + + class CallbackMock: + + def __init__(self): + self.results = {} + + def call_back(self, transfer_type, result): + self.results[transfer_type] = result + + mock = CallbackMock() + fltr.call_back = mock.call_back + + fltr.filter(eth_rpc, mockblock, tx, init_database) + + assert mock.results.get('transfer') != None + assert mock.results['transfer']['destination_token'] == foo_token diff --git a/apps/cic-notify/cic_notify/runnable/tasker.py b/apps/cic-notify/cic_notify/runnable/tasker.py index 286b68f4..453044f0 100644 --- a/apps/cic-notify/cic_notify/runnable/tasker.py +++ b/apps/cic-notify/cic_notify/runnable/tasker.py @@ -33,7 +33,9 @@ elif args.v: config = confini.Config(args.c, args.env_prefix) config.process() +config.add(args.q, '_CELERY_QUEUE', True) config.censor('PASSWORD', 'DATABASE') +logg.debug('config loaded from {}:\n{}'.format(args.c, config)) # connect to database dsn = dsn_from_config(config) diff --git a/apps/cic-notify/cic_notify/version.py b/apps/cic-notify/cic_notify/version.py index 97975986..a79e6140 100644 --- a/apps/cic-notify/cic_notify/version.py +++ b/apps/cic-notify/cic_notify/version.py @@ -6,11 +6,10 @@ import time import semver # local imports -from cic_notify.error import PleaseCommitFirstError logg = logging.getLogger() -version = (0, 4, 0, 'alpha.3') +version = (0, 4, 0, 'alpha.4') version_object = semver.VersionInfo( major=version[0], @@ -18,27 +17,4 @@ version_object = semver.VersionInfo( patch=version[2], prerelease=version[3], ) - version_string = str(version_object) - - -def git_hash(): - import subprocess - - git_hash = subprocess.run(['git', 'rev-parse', 'HEAD'], capture_output=True) - git_hash_brief = git_hash.stdout.decode('utf-8')[:8] - return git_hash_brief - - -try: - version_git = git_hash() - version_string += '+build.{}'.format(version_git) -except FileNotFoundError: - time_string_pair = str(time.time()).split('.') - version_string += '+build.{}{:<09d}'.format( - time_string_pair[0], - int(time_string_pair[1]), - ) -logg.info(f'Final version string will be {version_string}') - -__version_string__ = version_string diff --git a/apps/cic-notify/setup.cfg b/apps/cic-notify/setup.cfg index 9daf04a9..d4606598 100644 --- a/apps/cic-notify/setup.cfg +++ b/apps/cic-notify/setup.cfg @@ -1,6 +1,5 @@ [metadata] name = cic-notify -version= 0.4.0a3 description = CIC notifications service author = Louis Holbrook author_email = dev@holbrook.no diff --git a/apps/cic-notify/setup.py b/apps/cic-notify/setup.py index 848466f9..61363f56 100644 --- a/apps/cic-notify/setup.py +++ b/apps/cic-notify/setup.py @@ -1,9 +1,31 @@ # standard imports +import logging +import subprocess +import time from setuptools import setup -# third-party imports - # local imports +from cic_notify.version import version_string + +logg = logging.getLogger() + + +def git_hash(): + git_hash = subprocess.run(['git', 'rev-parse', 'HEAD'], capture_output=True) + git_hash_brief = git_hash.stdout.decode('utf-8')[:8] + return git_hash_brief + + +try: + version_git = git_hash() + version_string += '+build.{}'.format(version_git) +except FileNotFoundError: + time_string_pair = str(time.time()).split('.') + version_string += '+build.{}{:<09d}'.format( + time_string_pair[0], + int(time_string_pair[1]), + ) +logg.info(f'Final version string will be {version_string}') requirements = [] @@ -25,6 +47,6 @@ while True: test_requirements_file.close() setup( + version=version_string, install_requires=requirements, - tests_require=test_requirements, -) + tests_require=test_requirements) diff --git a/apps/cic-ussd/.config/redis.ini b/apps/cic-ussd/.config/redis.ini index 417481db..11335fe9 100644 --- a/apps/cic-ussd/.config/redis.ini +++ b/apps/cic-ussd/.config/redis.ini @@ -1,6 +1,6 @@ [celery] -BROKER_URL=redis://redis:6379 -RESULT_URL=redis://redis:6379 +BROKER_URL=redis:// +RESULT_URL=redis:// [redis] HOSTNAME=redis diff --git a/apps/cic-ussd/cic_ussd/account.py b/apps/cic-ussd/cic_ussd/account.py index 42e058b6..91fac0c3 100644 --- a/apps/cic-ussd/cic_ussd/account.py +++ b/apps/cic-ussd/cic_ussd/account.py @@ -8,12 +8,12 @@ from cic_types.processor import generate_metadata_pointer # local imports from cic_ussd.chain import Chain -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account from cic_ussd.metadata import blockchain_address_to_metadata_pointer from cic_ussd.redis import get_cached_data -def define_account_tx_metadata(user: User): +def define_account_tx_metadata(user: Account): # get sender metadata identifier = blockchain_address_to_metadata_pointer( blockchain_address=user.blockchain_address diff --git a/apps/cic-ussd/cic_ussd/db/migrations/default/versions/f289e8510444_.py b/apps/cic-ussd/cic_ussd/db/migrations/default/versions/f289e8510444_.py index 19fb28c1..29d1e470 100644 --- a/apps/cic-ussd/cic_ussd/db/migrations/default/versions/f289e8510444_.py +++ b/apps/cic-ussd/cic_ussd/db/migrations/default/versions/f289e8510444_.py @@ -1,4 +1,4 @@ -"""Create user table +"""Create account table Revision ID: f289e8510444 Revises: @@ -17,7 +17,7 @@ depends_on = None def upgrade(): - op.create_table('user', + op.create_table('account', sa.Column('id', sa.Integer(), nullable=False), sa.Column('blockchain_address', sa.String(), nullable=False), sa.Column('phone_number', sa.String(), nullable=False), @@ -29,11 +29,11 @@ def upgrade(): sa.Column('updated', sa.DateTime(), nullable=False), sa.PrimaryKeyConstraint('id') ) - op.create_index(op.f('ix_user_phone_number'), 'user', ['phone_number'], unique=True) - op.create_index(op.f('ix_user_blockchain_address'), 'user', ['blockchain_address'], unique=True) + op.create_index(op.f('ix_account_phone_number'), 'account', ['phone_number'], unique=True) + op.create_index(op.f('ix_account_blockchain_address'), 'account', ['blockchain_address'], unique=True) def downgrade(): - op.drop_index(op.f('ix_user_blockchain_address'), table_name='user') - op.drop_index(op.f('ix_user_phone_number'), table_name='user') - op.drop_table('user') + op.drop_index(op.f('ix_account_blockchain_address'), table_name='account') + op.drop_index(op.f('ix_account_phone_number'), table_name='account') + op.drop_table('account') diff --git a/apps/cic-ussd/cic_ussd/db/models/user.py b/apps/cic-ussd/cic_ussd/db/models/account.py similarity index 96% rename from apps/cic-ussd/cic_ussd/db/models/user.py rename to apps/cic-ussd/cic_ussd/db/models/account.py index 56826cf1..18f5e370 100644 --- a/apps/cic-ussd/cic_ussd/db/models/user.py +++ b/apps/cic-ussd/cic_ussd/db/models/account.py @@ -16,12 +16,12 @@ class AccountStatus(IntEnum): RESET = 4 -class User(SessionBase): +class Account(SessionBase): """ This class defines a user record along with functions responsible for hashing the user's corresponding password and subsequently verifying a password's validity given an input to compare against the persisted hash. """ - __tablename__ = 'user' + __tablename__ = 'account' blockchain_address = Column(String) phone_number = Column(String) @@ -38,7 +38,7 @@ class User(SessionBase): self.account_status = AccountStatus.PENDING.value def __repr__(self): - return f'' + return f'' def create_password(self, password): """This method takes a password value and hashes the value before assigning it to the corresponding diff --git a/apps/cic-ussd/cic_ussd/operations.py b/apps/cic-ussd/cic_ussd/operations.py index b7b7e0ef..5e7eeca5 100644 --- a/apps/cic-ussd/cic_ussd/operations.py +++ b/apps/cic-ussd/cic_ussd/operations.py @@ -10,7 +10,7 @@ from tinydb.table import Document from typing import Optional # local imports -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account from cic_ussd.db.models.ussd_session import UssdSession from cic_ussd.db.models.task_tracker import TaskTracker from cic_ussd.menu.ussd_menu import UssdMenu @@ -143,10 +143,10 @@ def get_account_status(phone_number) -> str: :return: The user account status. :rtype: str """ - user = User.session.query(User).filter_by(phone_number=phone_number).first() + user = Account.session.query(Account).filter_by(phone_number=phone_number).first() status = user.get_account_status() - User.session.add(user) - User.session.commit() + Account.session.add(user) + Account.session.commit() return status @@ -269,12 +269,12 @@ def cache_account_creation_task_id(phone_number: str, task_id: str): redis_cache.persist(name=task_id) -def process_current_menu(ussd_session: Optional[dict], user: User, user_input: str) -> Document: +def process_current_menu(ussd_session: Optional[dict], user: Account, user_input: str) -> Document: """This function checks user input and returns a corresponding ussd menu :param ussd_session: An in db ussd session object. :type ussd_session: UssdSession :param user: A user object. - :type user: User + :type user: Account :param user_input: The user's input. :type user_input: str :return: An in memory ussd menu object. @@ -324,7 +324,7 @@ def process_menu_interaction_requests(chain_str: str, else: # get user - user = User.session.query(User).filter_by(phone_number=phone_number).first() + user = Account.session.query(Account).filter_by(phone_number=phone_number).first() # find any existing ussd session existing_ussd_session = UssdSession.session.query(UssdSession).filter_by( @@ -390,10 +390,10 @@ def reset_pin(phone_number: str) -> str: :return: The status of the pin reset. :rtype: str """ - user = User.session.query(User).filter_by(phone_number=phone_number).first() + user = Account.session.query(Account).filter_by(phone_number=phone_number).first() user.reset_account_pin() - User.session.add(user) - User.session.commit() + Account.session.add(user) + Account.session.commit() response = f'Pin reset for user {phone_number} is successful!' return response diff --git a/apps/cic-ussd/cic_ussd/phone_number.py b/apps/cic-ussd/cic_ussd/phone_number.py index 0764ba8b..0a48b0d2 100644 --- a/apps/cic-ussd/cic_ussd/phone_number.py +++ b/apps/cic-ussd/cic_ussd/phone_number.py @@ -5,7 +5,7 @@ from typing import Optional import phonenumbers # local imports -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account def process_phone_number(phone_number: str, region: str): @@ -30,14 +30,14 @@ def process_phone_number(phone_number: str, region: str): return parsed_phone_number -def get_user_by_phone_number(phone_number: str) -> Optional[User]: +def get_user_by_phone_number(phone_number: str) -> Optional[Account]: """This function queries the database for a user based on the provided phone number. :param phone_number: A valid phone number. :type phone_number: str :return: A user object matching a given phone number - :rtype: User|None + :rtype: Account|None """ # consider adding region to user's metadata phone_number = process_phone_number(phone_number=phone_number, region='KE') - user = User.session.query(User).filter_by(phone_number=phone_number).first() + user = Account.session.query(Account).filter_by(phone_number=phone_number).first() return user diff --git a/apps/cic-ussd/cic_ussd/processor.py b/apps/cic-ussd/cic_ussd/processor.py index 061e9fbb..c977f77f 100644 --- a/apps/cic-ussd/cic_ussd/processor.py +++ b/apps/cic-ussd/cic_ussd/processor.py @@ -13,7 +13,7 @@ from tinydb.table import Document from cic_ussd.account import define_account_tx_metadata, retrieve_account_statement from cic_ussd.balance import BalanceManager, compute_operational_balance, get_cached_operational_balance from cic_ussd.chain import Chain -from cic_ussd.db.models.user import AccountStatus, User +from cic_ussd.db.models.account import AccountStatus, Account from cic_ussd.db.models.ussd_session import UssdSession from cic_ussd.error import MetadataNotFoundError from cic_ussd.menu.ussd_menu import UssdMenu @@ -28,13 +28,13 @@ from cic_types.models.person import generate_metadata_pointer, get_contact_data_ logg = logging.getLogger(__name__) -def process_pin_authorization(display_key: str, user: User, **kwargs) -> str: +def process_pin_authorization(display_key: str, user: Account, **kwargs) -> str: """ This method provides translation for all ussd menu entries that follow the pin authorization pattern. :param display_key: The path in the translation files defining an appropriate ussd response :type display_key: str :param user: The user in a running USSD session. - :type user: User + :type user: Account :param kwargs: Any additional information required by the text values in the internationalization files. :type kwargs :return: A string value corresponding the ussd menu's text value. @@ -55,13 +55,13 @@ def process_pin_authorization(display_key: str, user: User, **kwargs) -> str: ) -def process_exit_insufficient_balance(display_key: str, user: User, ussd_session: dict): +def process_exit_insufficient_balance(display_key: str, user: Account, ussd_session: dict): """This function processes the exit menu letting users their account balance is insufficient to perform a specific transaction. :param display_key: The path in the translation files defining an appropriate ussd response :type display_key: str :param user: The user requesting access to the ussd menu. - :type user: User + :type user: Account :param ussd_session: A JSON serialized in-memory ussd session object :type ussd_session: dict :return: Corresponding translation text response @@ -90,12 +90,12 @@ def process_exit_insufficient_balance(display_key: str, user: User, ussd_session ) -def process_exit_successful_transaction(display_key: str, user: User, ussd_session: dict): +def process_exit_successful_transaction(display_key: str, user: Account, ussd_session: dict): """This function processes the exit menu after a successful initiation for a transfer of tokens. :param display_key: The path in the translation files defining an appropriate ussd response :type display_key: str :param user: The user requesting access to the ussd menu. - :type user: User + :type user: Account :param ussd_session: A JSON serialized in-memory ussd session object :type ussd_session: dict :return: Corresponding translation text response @@ -118,11 +118,11 @@ def process_exit_successful_transaction(display_key: str, user: User, ussd_sessi ) -def process_transaction_pin_authorization(user: User, display_key: str, ussd_session: dict): +def process_transaction_pin_authorization(user: Account, display_key: str, ussd_session: dict): """This function processes pin authorization where making a transaction is concerned. It constructs a pre-transaction response menu that shows the details of the transaction. :param user: The user requesting access to the ussd menu. - :type user: User + :type user: Account :param display_key: The path in the translation files defining an appropriate ussd response :type display_key: str :param ussd_session: The USSD session determining what user data needs to be extracted and added to the menu's @@ -151,7 +151,7 @@ def process_transaction_pin_authorization(user: User, display_key: str, ussd_ses ) -def process_account_balances(user: User, display_key: str, ussd_session: dict): +def process_account_balances(user: Account, display_key: str, ussd_session: dict): """ :param user: :type user: @@ -205,7 +205,7 @@ def format_transactions(transactions: list, preferred_language: str): return formatted_transactions -def process_display_user_metadata(user: User, display_key: str): +def process_display_user_metadata(user: Account, display_key: str): """ :param user: :type user: @@ -238,7 +238,7 @@ def process_display_user_metadata(user: User, display_key: str): raise MetadataNotFoundError(f'Expected person metadata but found none in cache for key: {key}') -def process_account_statement(user: User, display_key: str, ussd_session: dict): +def process_account_statement(user: Account, display_key: str, ussd_session: dict): """ :param user: :type user: @@ -301,12 +301,12 @@ def process_account_statement(user: User, display_key: str, ussd_session: dict): ) -def process_start_menu(display_key: str, user: User): +def process_start_menu(display_key: str, user: Account): """This function gets data on an account's balance and token in order to append it to the start of the start menu's title. It passes said arguments to the translation function and returns the appropriate corresponding text from the translation files. :param user: The user requesting access to the ussd menu. - :type user: User + :type user: Account :param display_key: The path in the translation files defining an appropriate ussd response :type display_key: str :return: Corresponding translation text response @@ -361,13 +361,13 @@ def retrieve_most_recent_ussd_session(phone_number: str) -> UssdSession: return last_ussd_session -def process_request(user_input: str, user: User, ussd_session: Optional[dict] = None) -> Document: +def process_request(user_input: str, user: Account, ussd_session: Optional[dict] = None) -> Document: """This function assesses a request based on the user from the request comes, the session_id and the user's input. It determines whether the request translates to a return to an existing session by checking whether the provided session id exists in the database or whether the creation of a new ussd session object is warranted. It then returns the appropriate ussd menu text values. :param user: The user requesting access to the ussd menu. - :type user: User + :type user: Account :param user_input: The value a user enters in the ussd menu. :type user_input: str :param ussd_session: A JSON serialized in-memory ussd session object @@ -415,14 +415,14 @@ def process_request(user_input: str, user: User, ussd_session: Optional[dict] = return UssdMenu.find_by_name(name='initial_pin_entry') -def next_state(ussd_session: dict, user: User, user_input: str) -> str: +def next_state(ussd_session: dict, user: Account, user_input: str) -> str: """This function navigates the state machine based on the ussd session object and user inputs it receives. It checks the user input and provides the successive state in the state machine. It then updates the session's state attribute with the new state. :param ussd_session: A JSON serialized in-memory ussd session object :type ussd_session: dict :param user: The user requesting access to the ussd menu. - :type user: User + :type user: Account :param user_input: The value a user enters in the ussd menu. :type user_input: str :return: A string value corresponding the successive give a specific state in the state machine. @@ -438,7 +438,7 @@ def custom_display_text( display_key: str, menu_name: str, ussd_session: dict, - user: User) -> str: + user: Account) -> str: """This function extracts the appropriate session data based on the current menu name. It then inserts them as keywords in the i18n function. :param display_key: The path in the translation files defining an appropriate ussd response @@ -446,7 +446,7 @@ def custom_display_text( :param menu_name: The name by which a specific menu can be identified. :type menu_name: str :param user: The user in a running USSD session. - :type user: User + :type user: Account :param ussd_session: A JSON serialized in-memory ussd session object :type ussd_session: dict :return: A string value corresponding the ussd menu's text value. diff --git a/apps/cic-ussd/cic_ussd/requests.py b/apps/cic-ussd/cic_ussd/requests.py index 887dff30..8d436f45 100644 --- a/apps/cic-ussd/cic_ussd/requests.py +++ b/apps/cic-ussd/cic_ussd/requests.py @@ -10,7 +10,7 @@ from urllib.parse import urlparse, parse_qs from sqlalchemy import desc # local imports -from cic_ussd.db.models.user import AccountStatus, User +from cic_ussd.db.models.account import AccountStatus, Account from cic_ussd.operations import get_account_status, reset_pin from cic_ussd.validator import check_known_user @@ -123,9 +123,9 @@ def process_locked_accounts_requests(env: dict) -> tuple: else: limit = r[1] - locked_accounts = User.session.query(User.blockchain_address).filter( - User.account_status == AccountStatus.LOCKED.value, - User.failed_pin_attempts >= 3).order_by(desc(User.updated)).offset(offset).limit(limit).all() + locked_accounts = Account.session.query(Account.blockchain_address).filter( + Account.account_status == AccountStatus.LOCKED.value, + Account.failed_pin_attempts >= 3).order_by(desc(Account.updated)).offset(offset).limit(limit).all() # convert lists to scalar blockchain addresses locked_accounts = [blockchain_address for (blockchain_address, ) in locked_accounts] diff --git a/apps/cic-ussd/cic_ussd/runnable/server.py b/apps/cic-ussd/cic_ussd/runnable/server.py index e969d619..801da0f4 100644 --- a/apps/cic-ussd/cic_ussd/runnable/server.py +++ b/apps/cic-ussd/cic_ussd/runnable/server.py @@ -57,19 +57,17 @@ arg_parser.add_argument('--env-prefix', help='environment prefix for variables to overwrite configuration') args = arg_parser.parse_args() -# parse config -config = Config(config_dir=args.c, env_prefix=args.env_prefix) -config.process() -config.censor('PASSWORD', 'DATABASE') - # define log levels if args.vv: logging.getLogger().setLevel(logging.DEBUG) elif args.v: logging.getLogger().setLevel(logging.INFO) -# log config vars -logg.debug(config) +# parse config +config = Config(config_dir=args.c, env_prefix=args.env_prefix) +config.process() +config.censor('PASSWORD', 'DATABASE') +logg.debug('config loaded from {}:\n{}'.format(args.c, config)) # initialize elements # set up translations diff --git a/apps/cic-ussd/cic_ussd/runnable/tasker.py b/apps/cic-ussd/cic_ussd/runnable/tasker.py index ac39e06f..788f71b1 100644 --- a/apps/cic-ussd/cic_ussd/runnable/tasker.py +++ b/apps/cic-ussd/cic_ussd/runnable/tasker.py @@ -6,6 +6,7 @@ import tempfile # third party imports import celery +import i18n import redis from confini import Config @@ -33,18 +34,18 @@ arg_parser.add_argument('-vv', action='store_true', help='be more verbose') arg_parser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration') args = arg_parser.parse_args() -# parse config -config = Config(config_dir=args.c, env_prefix=args.env_prefix) -config.process() -config.censor('PASSWORD', 'DATABASE') - # define log levels if args.vv: logging.getLogger().setLevel(logging.DEBUG) elif args.v: logging.getLogger().setLevel(logging.INFO) -logg.debug(config) +# parse config +config = Config(args.c, args.env_prefix) +config.process() +config.add(args.q, '_CELERY_QUEUE', True) +config.censor('PASSWORD', 'DATABASE') +logg.debug('config loaded from {}:\n{}'.format(args.c, config)) # connect to database data_source_name = dsn_from_config(config) @@ -77,6 +78,10 @@ if key_file_path: validate_presence(path=key_file_path) Signer.key_file_path = key_file_path +# set up translations +i18n.load_path.append(config.get('APP_LOCALE_PATH')) +i18n.set('fallback', config.get('APP_LOCALE_FALLBACK')) + # set up celery current_app = celery.Celery(__name__) diff --git a/apps/cic-ussd/cic_ussd/state_machine/logic/balance.py b/apps/cic-ussd/cic_ussd/state_machine/logic/balance.py index 749841cc..899ff346 100644 --- a/apps/cic-ussd/cic_ussd/state_machine/logic/balance.py +++ b/apps/cic-ussd/cic_ussd/state_machine/logic/balance.py @@ -5,12 +5,12 @@ from typing import Tuple # third-party imports # local imports -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account logg = logging.getLogger(__file__) -def process_mini_statement_request(state_machine_data: Tuple[str, dict, User]): +def process_mini_statement_request(state_machine_data: Tuple[str, dict, Account]): """This function compiles a brief statement of a user's last three inbound and outbound transactions and send the same as a message on their selected avenue for notification. :param state_machine_data: A tuple containing user input, a ussd session and user object. diff --git a/apps/cic-ussd/cic_ussd/state_machine/logic/menu.py b/apps/cic-ussd/cic_ussd/state_machine/logic/menu.py index d8d4492a..c7239ab5 100644 --- a/apps/cic-ussd/cic_ussd/state_machine/logic/menu.py +++ b/apps/cic-ussd/cic_ussd/state_machine/logic/menu.py @@ -6,10 +6,10 @@ ussd menu facilitating the return of appropriate menu responses based on said us from typing import Tuple # local imports -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account -def menu_one_selected(state_machine_data: Tuple[str, dict, User]) -> bool: +def menu_one_selected(state_machine_data: Tuple[str, dict, Account]) -> bool: """This function checks that user input matches a string with value '1' :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: str @@ -20,7 +20,7 @@ def menu_one_selected(state_machine_data: Tuple[str, dict, User]) -> bool: return user_input == '1' -def menu_two_selected(state_machine_data: Tuple[str, dict, User]) -> bool: +def menu_two_selected(state_machine_data: Tuple[str, dict, Account]) -> bool: """This function checks that user input matches a string with value '2' :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple @@ -31,7 +31,7 @@ def menu_two_selected(state_machine_data: Tuple[str, dict, User]) -> bool: return user_input == '2' -def menu_three_selected(state_machine_data: Tuple[str, dict, User]) -> bool: +def menu_three_selected(state_machine_data: Tuple[str, dict, Account]) -> bool: """This function checks that user input matches a string with value '3' :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple @@ -42,7 +42,7 @@ def menu_three_selected(state_machine_data: Tuple[str, dict, User]) -> bool: return user_input == '3' -def menu_four_selected(state_machine_data: Tuple[str, dict, User]) -> bool: +def menu_four_selected(state_machine_data: Tuple[str, dict, Account]) -> bool: """ This function checks that user input matches a string with value '4' :param state_machine_data: A tuple containing user input, a ussd session and user object. @@ -54,7 +54,7 @@ def menu_four_selected(state_machine_data: Tuple[str, dict, User]) -> bool: return user_input == '4' -def menu_five_selected(state_machine_data: Tuple[str, dict, User]) -> bool: +def menu_five_selected(state_machine_data: Tuple[str, dict, Account]) -> bool: """ This function checks that user input matches a string with value '5' :param state_machine_data: A tuple containing user input, a ussd session and user object. @@ -66,7 +66,7 @@ def menu_five_selected(state_machine_data: Tuple[str, dict, User]) -> bool: return user_input == '5' -def menu_zero_zero_selected(state_machine_data: Tuple[str, dict, User]) -> bool: +def menu_zero_zero_selected(state_machine_data: Tuple[str, dict, Account]) -> bool: """ This function checks that user input matches a string with value '00' :param state_machine_data: A tuple containing user input, a ussd session and user object. @@ -78,7 +78,7 @@ def menu_zero_zero_selected(state_machine_data: Tuple[str, dict, User]) -> bool: return user_input == '00' -def menu_ninety_nine_selected(state_machine_data: Tuple[str, dict, User]) -> bool: +def menu_ninety_nine_selected(state_machine_data: Tuple[str, dict, Account]) -> bool: """ This function checks that user input matches a string with value '99' :param state_machine_data: A tuple containing user input, a ussd session and user object. diff --git a/apps/cic-ussd/cic_ussd/state_machine/logic/pin.py b/apps/cic-ussd/cic_ussd/state_machine/logic/pin.py index 98174b97..3577699d 100644 --- a/apps/cic-ussd/cic_ussd/state_machine/logic/pin.py +++ b/apps/cic-ussd/cic_ussd/state_machine/logic/pin.py @@ -12,7 +12,7 @@ from typing import Tuple import bcrypt # local imports -from cic_ussd.db.models.user import AccountStatus, User +from cic_ussd.db.models.account import AccountStatus, Account from cic_ussd.encoder import PasswordEncoder, create_password_hash from cic_ussd.operations import persist_session_to_db_task, create_or_update_session from cic_ussd.redis import InMemoryStore @@ -21,7 +21,7 @@ from cic_ussd.redis import InMemoryStore logg = logging.getLogger(__file__) -def is_valid_pin(state_machine_data: Tuple[str, dict, User]) -> bool: +def is_valid_pin(state_machine_data: Tuple[str, dict, Account]) -> bool: """This function checks a pin's validity by ensuring it has a length of for characters and the characters are numeric. :param state_machine_data: A tuple containing user input, a ussd session and user object. @@ -37,7 +37,7 @@ def is_valid_pin(state_machine_data: Tuple[str, dict, User]) -> bool: return pin_is_valid -def is_authorized_pin(state_machine_data: Tuple[str, dict, User]) -> bool: +def is_authorized_pin(state_machine_data: Tuple[str, dict, Account]) -> bool: """This function checks whether the user input confirming a specific pin matches the initial pin entered. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple @@ -48,7 +48,7 @@ def is_authorized_pin(state_machine_data: Tuple[str, dict, User]) -> bool: return user.verify_password(password=user_input) -def is_locked_account(state_machine_data: Tuple[str, dict, User]) -> bool: +def is_locked_account(state_machine_data: Tuple[str, dict, Account]) -> bool: """This function checks whether a user's account is locked due to too many failed attempts. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple @@ -59,7 +59,7 @@ def is_locked_account(state_machine_data: Tuple[str, dict, User]) -> bool: return user.get_account_status() == AccountStatus.LOCKED.name -def save_initial_pin_to_session_data(state_machine_data: Tuple[str, dict, User]): +def save_initial_pin_to_session_data(state_machine_data: Tuple[str, dict, Account]): """This function hashes a pin and stores it in session data. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple @@ -94,7 +94,7 @@ def save_initial_pin_to_session_data(state_machine_data: Tuple[str, dict, User]) persist_session_to_db_task(external_session_id=external_session_id, queue='cic-ussd') -def pins_match(state_machine_data: Tuple[str, dict, User]) -> bool: +def pins_match(state_machine_data: Tuple[str, dict, Account]) -> bool: """This function checks whether the user input confirming a specific pin matches the initial pin entered. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple @@ -108,7 +108,7 @@ def pins_match(state_machine_data: Tuple[str, dict, User]) -> bool: return bcrypt.checkpw(user_input.encode(), initial_pin) -def complete_pin_change(state_machine_data: Tuple[str, dict, User]): +def complete_pin_change(state_machine_data: Tuple[str, dict, Account]): """This function persists the user's pin to the database :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple @@ -116,11 +116,11 @@ def complete_pin_change(state_machine_data: Tuple[str, dict, User]): user_input, ussd_session, user = state_machine_data password_hash = ussd_session.get('session_data').get('initial_pin') user.password_hash = password_hash - User.session.add(user) - User.session.commit() + Account.session.add(user) + Account.session.commit() -def is_blocked_pin(state_machine_data: Tuple[str, dict, User]) -> bool: +def is_blocked_pin(state_machine_data: Tuple[str, dict, Account]) -> bool: """This function checks whether the user input confirming a specific pin matches the initial pin entered. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple @@ -131,7 +131,7 @@ def is_blocked_pin(state_machine_data: Tuple[str, dict, User]) -> bool: return user.get_account_status() == AccountStatus.LOCKED.name -def is_valid_new_pin(state_machine_data: Tuple[str, dict, User]) -> bool: +def is_valid_new_pin(state_machine_data: Tuple[str, dict, Account]) -> bool: """This function checks whether the user's new pin is a valid pin and that it isn't the same as the old one. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple diff --git a/apps/cic-ussd/cic_ussd/state_machine/logic/sms.py b/apps/cic-ussd/cic_ussd/state_machine/logic/sms.py index 84479583..517c09e9 100644 --- a/apps/cic-ussd/cic_ussd/state_machine/logic/sms.py +++ b/apps/cic-ussd/cic_ussd/state_machine/logic/sms.py @@ -3,21 +3,21 @@ import logging from typing import Tuple # local imports -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account logg = logging.getLogger() -def send_terms_to_user_if_required(state_machine_data: Tuple[str, dict, User]): +def send_terms_to_user_if_required(state_machine_data: Tuple[str, dict, Account]): user_input, ussd_session, user = state_machine_data logg.debug('Requires integration to cic-notify.') -def process_mini_statement_request(state_machine_data: Tuple[str, dict, User]): +def process_mini_statement_request(state_machine_data: Tuple[str, dict, Account]): user_input, ussd_session, user = state_machine_data logg.debug('Requires integration to cic-notify.') -def upsell_unregistered_recipient(state_machine_data: Tuple[str, dict, User]): +def upsell_unregistered_recipient(state_machine_data: Tuple[str, dict, Account]): user_input, ussd_session, user = state_machine_data logg.debug('Requires integration to cic-notify.') \ No newline at end of file diff --git a/apps/cic-ussd/cic_ussd/state_machine/logic/transaction.py b/apps/cic-ussd/cic_ussd/state_machine/logic/transaction.py index 7a006a78..ff563272 100644 --- a/apps/cic-ussd/cic_ussd/state_machine/logic/transaction.py +++ b/apps/cic-ussd/cic_ussd/state_machine/logic/transaction.py @@ -9,7 +9,7 @@ import celery # local imports from cic_ussd.balance import BalanceManager, compute_operational_balance from cic_ussd.chain import Chain -from cic_ussd.db.models.user import AccountStatus, User +from cic_ussd.db.models.account import AccountStatus, Account from cic_ussd.operations import save_to_in_memory_ussd_session_data from cic_ussd.phone_number import get_user_by_phone_number from cic_ussd.redis import create_cached_data_key, get_cached_data @@ -19,7 +19,7 @@ from cic_ussd.transactions import OutgoingTransactionProcessor logg = logging.getLogger(__file__) -def is_valid_recipient(state_machine_data: Tuple[str, dict, User]) -> bool: +def is_valid_recipient(state_machine_data: Tuple[str, dict, Account]) -> bool: """This function checks that a user exists, is not the initiator of the transaction, has an active account status and is authorized to perform standard transactions. :param state_machine_data: A tuple containing user input, a ussd session and user object. @@ -34,7 +34,7 @@ def is_valid_recipient(state_machine_data: Tuple[str, dict, User]) -> bool: return is_not_initiator and has_active_account_status and recipient is not None -def is_valid_transaction_amount(state_machine_data: Tuple[str, dict, User]) -> bool: +def is_valid_transaction_amount(state_machine_data: Tuple[str, dict, Account]) -> bool: """This function checks that the transaction amount provided is valid as per the criteria for the transaction being attempted. :param state_machine_data: A tuple containing user input, a ussd session and user object. @@ -49,7 +49,7 @@ def is_valid_transaction_amount(state_machine_data: Tuple[str, dict, User]) -> b return False -def has_sufficient_balance(state_machine_data: Tuple[str, dict, User]) -> bool: +def has_sufficient_balance(state_machine_data: Tuple[str, dict, Account]) -> bool: """This function checks that the transaction amount provided is valid as per the criteria for the transaction being attempted. :param state_machine_data: A tuple containing user input, a ussd session and user object. @@ -72,7 +72,7 @@ def has_sufficient_balance(state_machine_data: Tuple[str, dict, User]) -> bool: return int(user_input) <= operational_balance -def save_recipient_phone_to_session_data(state_machine_data: Tuple[str, dict, User]): +def save_recipient_phone_to_session_data(state_machine_data: Tuple[str, dict, Account]): """This function saves the phone number corresponding the intended recipients blockchain account. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: str @@ -85,7 +85,7 @@ def save_recipient_phone_to_session_data(state_machine_data: Tuple[str, dict, Us save_to_in_memory_ussd_session_data(queue='cic-ussd', session_data=session_data, ussd_session=ussd_session) -def retrieve_recipient_metadata(state_machine_data: Tuple[str, dict, User]): +def retrieve_recipient_metadata(state_machine_data: Tuple[str, dict, Account]): """ :param state_machine_data: :type state_machine_data: @@ -104,7 +104,7 @@ def retrieve_recipient_metadata(state_machine_data: Tuple[str, dict, User]): s_query_person_metadata.apply_async(queue='cic-ussd') -def save_transaction_amount_to_session_data(state_machine_data: Tuple[str, dict, User]): +def save_transaction_amount_to_session_data(state_machine_data: Tuple[str, dict, Account]): """This function saves the phone number corresponding the intended recipients blockchain account. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: str @@ -117,7 +117,7 @@ def save_transaction_amount_to_session_data(state_machine_data: Tuple[str, dict, save_to_in_memory_ussd_session_data(queue='cic-ussd', session_data=session_data, ussd_session=ussd_session) -def process_transaction_request(state_machine_data: Tuple[str, dict, User]): +def process_transaction_request(state_machine_data: Tuple[str, dict, Account]): """This function saves the phone number corresponding the intended recipients blockchain account. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: str diff --git a/apps/cic-ussd/cic_ussd/state_machine/logic/user.py b/apps/cic-ussd/cic_ussd/state_machine/logic/user.py index fd53904d..e8b8e44e 100644 --- a/apps/cic-ussd/cic_ussd/state_machine/logic/user.py +++ b/apps/cic-ussd/cic_ussd/state_machine/logic/user.py @@ -10,7 +10,7 @@ from cic_types.models.person import generate_vcard_from_contact_data, manage_ide # local imports from cic_ussd.chain import Chain -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account from cic_ussd.error import MetadataNotFoundError from cic_ussd.metadata import blockchain_address_to_metadata_pointer from cic_ussd.operations import save_to_in_memory_ussd_session_data @@ -19,40 +19,40 @@ from cic_ussd.redis import get_cached_data logg = logging.getLogger(__file__) -def change_preferred_language_to_en(state_machine_data: Tuple[str, dict, User]): +def change_preferred_language_to_en(state_machine_data: Tuple[str, dict, Account]): """This function changes the user's preferred language to english. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple """ user_input, ussd_session, user = state_machine_data user.preferred_language = 'en' - User.session.add(user) - User.session.commit() + Account.session.add(user) + Account.session.commit() -def change_preferred_language_to_sw(state_machine_data: Tuple[str, dict, User]): +def change_preferred_language_to_sw(state_machine_data: Tuple[str, dict, Account]): """This function changes the user's preferred language to swahili. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple """ user_input, ussd_session, user = state_machine_data user.preferred_language = 'sw' - User.session.add(user) - User.session.commit() + Account.session.add(user) + Account.session.commit() -def update_account_status_to_active(state_machine_data: Tuple[str, dict, User]): +def update_account_status_to_active(state_machine_data: Tuple[str, dict, Account]): """This function sets user's account to active. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple """ user_input, ussd_session, user = state_machine_data user.activate_account() - User.session.add(user) - User.session.commit() + Account.session.add(user) + Account.session.commit() -def process_gender_user_input(user: User, user_input: str): +def process_gender_user_input(user: Account, user_input: str): """ :param user: :type user: @@ -74,7 +74,7 @@ def process_gender_user_input(user: User, user_input: str): return gender -def save_metadata_attribute_to_session_data(state_machine_data: Tuple[str, dict, User]): +def save_metadata_attribute_to_session_data(state_machine_data: Tuple[str, dict, Account]): """This function saves first name data to the ussd session in the redis cache. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple @@ -109,7 +109,7 @@ def save_metadata_attribute_to_session_data(state_machine_data: Tuple[str, dict, save_to_in_memory_ussd_session_data(queue='cic-ussd', session_data=session_data, ussd_session=ussd_session) -def format_user_metadata(metadata: dict, user: User): +def format_user_metadata(metadata: dict, user: Account): """ :param metadata: :type metadata: @@ -150,7 +150,7 @@ def format_user_metadata(metadata: dict, user: User): } -def save_complete_user_metadata(state_machine_data: Tuple[str, dict, User]): +def save_complete_user_metadata(state_machine_data: Tuple[str, dict, Account]): """This function persists elements of the user metadata stored in session data :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: tuple @@ -171,7 +171,7 @@ def save_complete_user_metadata(state_machine_data: Tuple[str, dict, User]): s_create_person_metadata.apply_async(queue='cic-ussd') -def edit_user_metadata_attribute(state_machine_data: Tuple[str, dict, User]): +def edit_user_metadata_attribute(state_machine_data: Tuple[str, dict, Account]): user_input, ussd_session, user = state_machine_data blockchain_address = user.blockchain_address key = generate_metadata_pointer( @@ -218,7 +218,7 @@ def edit_user_metadata_attribute(state_machine_data: Tuple[str, dict, User]): s_edit_person_metadata.apply_async(queue='cic-ussd') -def get_user_metadata(state_machine_data: Tuple[str, dict, User]): +def get_user_metadata(state_machine_data: Tuple[str, dict, Account]): user_input, ussd_session, user = state_machine_data blockchain_address = user.blockchain_address s_get_user_metadata = celery.signature( diff --git a/apps/cic-ussd/cic_ussd/state_machine/logic/validator.py b/apps/cic-ussd/cic_ussd/state_machine/logic/validator.py index ffae027a..36cce59f 100644 --- a/apps/cic-ussd/cic_ussd/state_machine/logic/validator.py +++ b/apps/cic-ussd/cic_ussd/state_machine/logic/validator.py @@ -7,14 +7,14 @@ from typing import Tuple from cic_types.models.person import generate_metadata_pointer # local imports -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account from cic_ussd.metadata import blockchain_address_to_metadata_pointer from cic_ussd.redis import get_cached_data logg = logging.getLogger() -def has_cached_user_metadata(state_machine_data: Tuple[str, dict, User]): +def has_cached_user_metadata(state_machine_data: Tuple[str, dict, Account]): """This function checks whether the attributes of the user's metadata constituting a profile are filled out. :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: str @@ -29,7 +29,7 @@ def has_cached_user_metadata(state_machine_data: Tuple[str, dict, User]): return user_metadata is not None -def is_valid_name(state_machine_data: Tuple[str, dict, User]): +def is_valid_name(state_machine_data: Tuple[str, dict, Account]): """This function checks that a user provided name is valid :param state_machine_data: A tuple containing user input, a ussd session and user object. :type state_machine_data: str @@ -43,7 +43,7 @@ def is_valid_name(state_machine_data: Tuple[str, dict, User]): return False -def is_valid_gender_selection(state_machine_data: Tuple[str, dict, User]): +def is_valid_gender_selection(state_machine_data: Tuple[str, dict, Account]): """ :param state_machine_data: :type state_machine_data: diff --git a/apps/cic-ussd/cic_ussd/state_machine/state_machine.py b/apps/cic-ussd/cic_ussd/state_machine/state_machine.py index f5ba52e3..d8178047 100644 --- a/apps/cic-ussd/cic_ussd/state_machine/state_machine.py +++ b/apps/cic-ussd/cic_ussd/state_machine/state_machine.py @@ -13,7 +13,7 @@ class UssdStateMachine(Machine): """This class describes a finite state machine responsible for maintaining all the states that describe the ussd menu as well as providing a means for navigating through these states based on different user inputs. It defines different helper functions that co-ordinate with the stakeholder components of the ussd menu: i.e the - User, UssdSession, UssdMenu to facilitate user interaction with ussd menu. + Account, UssdSession, UssdMenu to facilitate user interaction with ussd menu. :cvar states: A list of pre-defined states. :type states: list :cvar transitions: A list of pre-defined transitions. diff --git a/apps/cic-ussd/cic_ussd/tasks/callback_handler.py b/apps/cic-ussd/cic_ussd/tasks/callback_handler.py index 286840b8..1766565a 100644 --- a/apps/cic-ussd/cic_ussd/tasks/callback_handler.py +++ b/apps/cic-ussd/cic_ussd/tasks/callback_handler.py @@ -9,7 +9,7 @@ import celery # local imports from cic_ussd.conversions import from_wei from cic_ussd.db.models.base import SessionBase -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account from cic_ussd.account import define_account_tx_metadata from cic_ussd.error import ActionDataNotFoundError from cic_ussd.redis import InMemoryStore, cache_data, create_cached_data_key @@ -49,7 +49,7 @@ def process_account_creation_callback(self, result: str, url: str, status_code: phone_number = account_creation_data.get('phone_number') # create user - user = User(blockchain_address=result, phone_number=phone_number) + user = Account(blockchain_address=result, phone_number=phone_number) session.add(user) session.commit() session.close() @@ -83,12 +83,12 @@ def process_incoming_transfer_callback(result: dict, param: str, status_code: in # collect result data recipient_blockchain_address = result.get('recipient') sender_blockchain_address = result.get('sender') - token_symbol = result.get('token_symbol') - value = result.get('destination_value') + token_symbol = result.get('destination_token_symbol') + value = result.get('destination_token_value') # try to find users in system - recipient_user = session.query(User).filter_by(blockchain_address=recipient_blockchain_address).first() - sender_user = session.query(User).filter_by(blockchain_address=sender_blockchain_address).first() + recipient_user = session.query(Account).filter_by(blockchain_address=recipient_blockchain_address).first() + sender_user = session.query(Account).filter_by(blockchain_address=sender_blockchain_address).first() # check whether recipient is in the system if not recipient_user: @@ -188,8 +188,8 @@ def process_statement_callback(result, param: str, status_code: int): processed_transaction = {} # check if sender is in the system - sender: User = session.query(User).filter_by(blockchain_address=sender_blockchain_address).first() - owner: User = session.query(User).filter_by(blockchain_address=param).first() + sender: Account = session.query(Account).filter_by(blockchain_address=sender_blockchain_address).first() + owner: Account = session.query(Account).filter_by(blockchain_address=param).first() if sender: processed_transaction['sender_phone_number'] = sender.phone_number @@ -205,7 +205,7 @@ def process_statement_callback(result, param: str, status_code: int): processed_transaction['sender_phone_number'] = 'GRASSROOTS ECONOMICS' # check if recipient is in the system - recipient: User = session.query(User).filter_by(blockchain_address=recipient_address).first() + recipient: Account = session.query(Account).filter_by(blockchain_address=recipient_address).first() if recipient: processed_transaction['recipient_phone_number'] = recipient.phone_number diff --git a/apps/cic-ussd/cic_ussd/translation.py b/apps/cic-ussd/cic_ussd/translation.py index b1746506..35fd1cd1 100644 --- a/apps/cic-ussd/cic_ussd/translation.py +++ b/apps/cic-ussd/cic_ussd/translation.py @@ -8,7 +8,7 @@ from typing import Optional def translation_for(key: str, preferred_language: Optional[str] = None, **kwargs) -> str: """ Translates text mapped to a specific YAML key into the user's set preferred language. - :param preferred_language: User's preferred language in which to view the ussd menu. + :param preferred_language: Account's preferred language in which to view the ussd menu. :type preferred_language str :param key: Key to a specific YAML test entry :type key: str diff --git a/apps/cic-ussd/cic_ussd/validator.py b/apps/cic-ussd/cic_ussd/validator.py index 1fc10065..89896955 100644 --- a/apps/cic-ussd/cic_ussd/validator.py +++ b/apps/cic-ussd/cic_ussd/validator.py @@ -8,7 +8,7 @@ import ipaddress from confini import Config # local imports -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account logg = logging.getLogger(__file__) @@ -68,7 +68,7 @@ def check_known_user(phone: str): :return: Is known phone number :rtype: boolean """ - user = User.session.query(User).filter_by(phone_number=phone).first() + user = Account.session.query(Account).filter_by(phone_number=phone).first() return user is not None diff --git a/apps/cic-ussd/cic_ussd/version.py b/apps/cic-ussd/cic_ussd/version.py index 5033279d..1dfeb772 100644 --- a/apps/cic-ussd/cic_ussd/version.py +++ b/apps/cic-ussd/cic_ussd/version.py @@ -1,7 +1,7 @@ # standard imports import semver -version = (0, 3, 0, 'alpha.8') +version = (0, 3, 0, 'alpha.9') version_object = semver.VersionInfo( major=version[0], diff --git a/apps/cic-ussd/requirements.txt b/apps/cic-ussd/requirements.txt index fe3e79e2..25578d59 100644 --- a/apps/cic-ussd/requirements.txt +++ b/apps/cic-ussd/requirements.txt @@ -1,4 +1,4 @@ cic_base[full_graph]~=0.1.2a68 cic-eth~=0.11.0b3 -cic-notify~=0.4.0a3 +cic-notify~=0.4.0a4 cic-types~=0.1.0a10 diff --git a/apps/cic-ussd/tests/cic_ussd/db/models/test_user.py b/apps/cic-ussd/tests/cic_ussd/db/models/test_user.py index f2173474..24f6fc99 100644 --- a/apps/cic-ussd/tests/cic_ussd/db/models/test_user.py +++ b/apps/cic-ussd/tests/cic_ussd/db/models/test_user.py @@ -4,19 +4,19 @@ import pytest # platform imports -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account def test_user(init_database, set_fernet_key): - user = User(blockchain_address='0x417f5962fc52dc33ff0689659b25848680dec6dcedc6785b03d1df60fc6d5c51', - phone_number='+254700000000') + user = Account(blockchain_address='0x417f5962fc52dc33ff0689659b25848680dec6dcedc6785b03d1df60fc6d5c51', + phone_number='+254700000000') user.create_password('0000') - session = User.session + session = Account.session session.add(user) session.commit() - queried_user = session.query(User).get(1) + queried_user = session.query(Account).get(1) assert queried_user.blockchain_address == '0x417f5962fc52dc33ff0689659b25848680dec6dcedc6785b03d1df60fc6d5c51' assert queried_user.phone_number == '+254700000000' assert queried_user.failed_pin_attempts == 0 @@ -25,7 +25,7 @@ def test_user(init_database, set_fernet_key): def test_user_state_transition(create_pending_user): user = create_pending_user - session = User.session + session = Account.session assert user.get_account_status() == 'PENDING' user.activate_account() diff --git a/apps/cic-ussd/tests/cic_ussd/tasks/test_callback_handler_tasks.py b/apps/cic-ussd/tests/cic_ussd/tasks/test_callback_handler_tasks.py index 184d2ffa..43df49cc 100644 --- a/apps/cic-ussd/tests/cic_ussd/tasks/test_callback_handler_tasks.py +++ b/apps/cic-ussd/tests/cic_ussd/tasks/test_callback_handler_tasks.py @@ -8,7 +8,7 @@ import celery import pytest # local imports -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account from cic_ussd.error import ActionDataNotFoundError from cic_ussd.conversions import from_wei @@ -29,7 +29,7 @@ def test_successful_process_account_creation_callback_task(account_creation_acti # WARNING: [THE SETTING OF THE ROOT ID IS A HACK AND SHOULD BE REVIEWED OR IMPROVED] mocked_task_request.root_id = task_id - user = init_database.query(User).filter_by(phone_number=phone_number).first() + user = init_database.query(Account).filter_by(phone_number=phone_number).first() assert user is None redis_cache = init_redis_cache @@ -48,7 +48,7 @@ def test_successful_process_account_creation_callback_task(account_creation_acti ) s_process_callback_request.apply_async().get() - user = init_database.query(User).filter_by(phone_number=phone_number).first() + user = init_database.query(Account).filter_by(phone_number=phone_number).first() assert user.blockchain_address == result action_data = redis_cache.get(task_id) diff --git a/apps/cic-ussd/tests/cic_ussd/test_requests.py b/apps/cic-ussd/tests/cic_ussd/test_requests.py index ffbd9aca..93c9e93e 100644 --- a/apps/cic-ussd/tests/cic_ussd/test_requests.py +++ b/apps/cic-ussd/tests/cic_ussd/test_requests.py @@ -2,7 +2,7 @@ import json # local imports -from cic_ussd.db.models.user import User +from cic_ussd.db.models.account import Account from cic_ussd.requests import (get_query_parameters, get_request_endpoint, get_request_method, @@ -58,8 +58,8 @@ def test_process_locked_accounts_requests(create_locked_accounts, valid_locked_a assert len(locked_account_addresses) == 10 # check that blockchain addresses are ordered by most recently accessed - user_1 = User.session.query(User).filter_by(blockchain_address=locked_account_addresses[2]).first() - user_2 = User.session.query(User).filter_by(blockchain_address=locked_account_addresses[7]).first() + user_1 = Account.session.query(Account).filter_by(blockchain_address=locked_account_addresses[2]).first() + user_2 = Account.session.query(Account).filter_by(blockchain_address=locked_account_addresses[7]).first() assert user_1.updated > user_2.updated diff --git a/apps/cic-ussd/tests/fixtures/user.py b/apps/cic-ussd/tests/fixtures/user.py index 162078e5..20dfbc28 100644 --- a/apps/cic-ussd/tests/fixtures/user.py +++ b/apps/cic-ussd/tests/fixtures/user.py @@ -9,7 +9,7 @@ from cic_types.models.person import generate_metadata_pointer from faker import Faker # local imports -from cic_ussd.db.models.user import AccountStatus, User +from cic_ussd.db.models.account import AccountStatus, Account from cic_ussd.redis import cache_data from cic_ussd.metadata import blockchain_address_to_metadata_pointer @@ -19,7 +19,7 @@ fake = Faker() @pytest.fixture(scope='function') def create_activated_user(init_database, set_fernet_key): - user = User( + user = Account( blockchain_address='0xFD9c5aD15C72C6F60f1a119A608931226674243f', phone_number='+25498765432' ) @@ -33,7 +33,7 @@ def create_activated_user(init_database, set_fernet_key): @pytest.fixture(scope='function') def create_valid_tx_recipient(init_database, set_fernet_key): - user = User( + user = Account( blockchain_address='0xd6204101012270Bf2558EDcFEd595938d1847bf0', phone_number='+25498765432' ) @@ -47,7 +47,7 @@ def create_valid_tx_recipient(init_database, set_fernet_key): @pytest.fixture(scope='function') def create_valid_tx_sender(init_database, set_fernet_key): - user = User( + user = Account( blockchain_address='0xd6204101012270Bf2558EDcFEd595938d1847bf1', phone_number='+25498765433' ) @@ -61,7 +61,7 @@ def create_valid_tx_sender(init_database, set_fernet_key): @pytest.fixture(scope='function') def create_pending_user(init_database, set_fernet_key): - user = User( + user = Account( blockchain_address='0x0ebdea8612c1b05d952c036859266c7f2cfcd6a29842d9c6cce3b9f1ba427588', phone_number='+25498765432' ) @@ -72,7 +72,7 @@ def create_pending_user(init_database, set_fernet_key): @pytest.fixture(scope='function') def create_pin_blocked_user(init_database, set_fernet_key): - user = User( + user = Account( blockchain_address='0x0ebdea8612c1b05d952c036859266c7f2cfcd6a29842d9c6cce3b9f1ba427588', phone_number='+25498765432' ) @@ -90,7 +90,7 @@ def create_locked_accounts(init_database, set_fernet_key): blockchain_address = str(uuid.uuid4()) phone_number = fake.phone_number() pin = f'{randint(1000, 9999)}' - user = User(phone_number=phone_number, blockchain_address=blockchain_address) + user = Account(phone_number=phone_number, blockchain_address=blockchain_address) user.create_password(password=pin) user.failed_pin_attempts = 3 user.account_status = AccountStatus.LOCKED.value diff --git a/apps/contract-migration/scripts/cic_eth/import_balance.py b/apps/contract-migration/scripts/cic_eth/import_balance.py index 6a8f6181..bad1d2bf 100644 --- a/apps/contract-migration/scripts/cic_eth/import_balance.py +++ b/apps/contract-migration/scripts/cic_eth/import_balance.py @@ -25,13 +25,13 @@ from chainlib.eth.block import ( block_by_number, Block, ) -from chainlib.eth.hash import keccak256_string_to_hex +from chainlib.hash import keccak256_string_to_hex from chainlib.eth.address import to_checksum_address from chainlib.eth.erc20 import ERC20 from chainlib.eth.gas import OverrideGasOracle from chainlib.eth.nonce import RPCNonceOracle from chainlib.eth.tx import TxFactory -from chainlib.eth.rpc import jsonrpc_template +from chainlib.jsonrpc import jsonrpc_template from chainlib.eth.error import EthException from chainlib.chain import ChainSpec from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer diff --git a/apps/contract-migration/scripts/eth/import_balance.py b/apps/contract-migration/scripts/eth/import_balance.py index 6a8f6181..bad1d2bf 100644 --- a/apps/contract-migration/scripts/eth/import_balance.py +++ b/apps/contract-migration/scripts/eth/import_balance.py @@ -25,13 +25,13 @@ from chainlib.eth.block import ( block_by_number, Block, ) -from chainlib.eth.hash import keccak256_string_to_hex +from chainlib.hash import keccak256_string_to_hex from chainlib.eth.address import to_checksum_address from chainlib.eth.erc20 import ERC20 from chainlib.eth.gas import OverrideGasOracle from chainlib.eth.nonce import RPCNonceOracle from chainlib.eth.tx import TxFactory -from chainlib.eth.rpc import jsonrpc_template +from chainlib.jsonrpc import jsonrpc_template from chainlib.eth.error import EthException from chainlib.chain import ChainSpec from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer diff --git a/apps/contract-migration/scripts/eth/import_users.py b/apps/contract-migration/scripts/eth/import_users.py index c5a5fb69..ed3659d6 100644 --- a/apps/contract-migration/scripts/eth/import_users.py +++ b/apps/contract-migration/scripts/eth/import_users.py @@ -24,7 +24,7 @@ from chainlib.eth.gas import RPCGasOracle from chainlib.eth.nonce import RPCNonceOracle from cic_types.processor import generate_metadata_pointer from eth_accounts_index import AccountRegistry -from contract_registry import Registry +from eth_contract_registry import Registry from crypto_dev_signer.keystore.dict import DictKeystore from crypto_dev_signer.eth.signer.defaultsigner import ReferenceSigner as EIP155Signer from crypto_dev_signer.keystore.keyfile import to_dict as to_keyfile_dict diff --git a/apps/contract-migration/scripts/package-lock.json b/apps/contract-migration/scripts/package-lock.json index 9737db2f..b99a4777 100644 --- a/apps/contract-migration/scripts/package-lock.json +++ b/apps/contract-migration/scripts/package-lock.json @@ -1,2118 +1,37 @@ { - "name": "scripts", - "lockfileVersion": 2, "requires": true, - "packages": { - "": { - "dependencies": { - "cic-client-meta": "^0.0.7-alpha.5", - "vcard-parser": "^1.0.0" - } - }, - "node_modules/@ethereumjs/common": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.0.0.tgz", - "integrity": "sha512-yL0zA7Xwgz8IFHKW0VoXGjdZDVxUJg8BQ/muMHvYPW7zHJNNC80gQmvLH+MpvIg1TCXZkFXxrpYRAyCElSm+aw==", - "dependencies": { - "crc-32": "^1.2.0" - } - }, - "node_modules/@ethereumjs/tx": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.0.2.tgz", - "integrity": "sha512-zmFCosjOdj1WoYEiQBdC4sCOAllBEwxdKuY85L9FgZ4zVDfZUVsQ4S9paczt4hVt65A7N8sJwgVEzDaQmrRaqw==", - "dependencies": { - "@ethereumjs/common": "^2.0.0", - "ethereumjs-util": "^7.0.8" - } - }, - "node_modules/@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==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "14.14.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.30.tgz", - "integrity": "sha512-gUWhy8s45fQp4PqqKecsnOkdW0kt1IaKjgOIR3HPokkzTmQj9ji2wWFID5THu1MKrtO+d4s2lVrlEhXUsPXSvg==" - }, - "node_modules/@types/pbkdf2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", - "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/secp256k1": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", - "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "node_modules/aes-js": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", - "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==" - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "optional": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "node_modules/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==", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/are-we-there-yet/node_modules/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==", - "dependencies": { - "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" - } - }, - "node_modules/are-we-there-yet/node_modules/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==" - }, - "node_modules/are-we-there-yet/node_modules/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==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "optional": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "optional": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "optional": true - }, - "node_modules/automerge": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/automerge/-/automerge-0.14.2.tgz", - "integrity": "sha512-shiwuJHCbNRI23WZyIECLV4Ovf3WiAFJ7P9BH4l5gON1In/UUbjcSJKRygtIirObw2UQumeYxp3F2XBdSvQHnA==", - "dependencies": { - "immutable": "^3.8.2", - "transit-immutable-js": "^0.7.0", - "transit-js": "^0.8.861", - "uuid": "^3.4.0" - } - }, - "node_modules/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, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "optional": true - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "node_modules/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==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/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, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/blakejs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", - "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" - }, - "node_modules/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, - "dependencies": { - "inherits": "~2.0.0" - }, - "engines": { - "node": "0.4 || >=0.5.8" - } - }, - "node_modules/bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dependencies": { - "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" - } - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/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==", - "engines": { - "node": ">=4" - } - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "optional": true - }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, - "node_modules/cic-client-meta": { - "version": "0.0.7-alpha.5", - "resolved": "https://registry.npmjs.org/cic-client-meta/-/cic-client-meta-0.0.7-alpha.5.tgz", - "integrity": "sha512-h+0wmAKZIgezppBNYDmG387w6tI91FSWqONMTZbMuaO1Ej76Gg0Mk2UcDyAF/dmY6doXz3kHAbWkWat7mTzXAQ==", - "dependencies": { - "@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" - }, - "engines": { - "node": "~15.3.0" - } - }, - "node_modules/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==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/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==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/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==" - }, - "node_modules/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, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/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=" - }, - "node_modules/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=" - }, - "node_modules/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==", - "dependencies": { - "exit-on-epipe": "~1.0.1", - "printj": "~1.1.0" - }, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/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==", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/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==", - "dependencies": { - "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" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "optional": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/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==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/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, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "optional": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dependencies": { - "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" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - }, - "node_modules/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==" - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/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==", - "dependencies": { - "@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" - } - }, - "node_modules/ethereumjs-util": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.8.tgz", - "integrity": "sha512-JJt7tDpCAmDPw/sGoFYeq0guOVqT3pTE9xlEbBmc/nlCij3JRCoS2c96SQ6kXVHOT3xWUNLDm5QCJLQaUnVAtQ==", - "dependencies": { - "@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" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/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==", - "dependencies": { - "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" - } - }, - "node_modules/ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dependencies": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/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==", - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/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==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "optional": true - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "engines": [ - "node >=0.6.0" - ], - "optional": true - }, - "node_modules/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 - }, - "node_modules/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 - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "optional": true, - "engines": { - "node": "*" - } - }, - "node_modules/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, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dependencies": { - "minipass": "^2.6.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dependencies": { - "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" - } - }, - "node_modules/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==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "optional": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dependencies": { - "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" - }, - "engines": { - "node": "*" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "optional": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "node_modules/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==", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "optional": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "dependencies": { - "minimatch": "^3.0.4" - } - }, - "node_modules/immutable": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", - "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/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=", - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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=", - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "optional": true - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "optional": true - }, - "node_modules/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 - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true - }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "optional": true - }, - "node_modules/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 - }, - "node_modules/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 - }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "engines": [ - "node >=0.6.0" - ], - "optional": true, - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "node_modules/keccak": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", - "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/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==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/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, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/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, - "dependencies": { - "mime-db": "1.46.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/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==" - }, - "node_modules/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=" - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dependencies": { - "minipass": "^2.9.0" - } - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/needle": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", - "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", - "dependencies": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" - } - }, - "node_modules/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_modules/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/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, - "dependencies": { - "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" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/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==", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/node-localstorage": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-localstorage/-/node-localstorage-1.3.1.tgz", - "integrity": "sha512-NMWCSWWc6JbHT5PyWlNT2i8r7PgGYXVntmKawY83k/M0UJScZ5jirb61TLnqKwd815DfBQu+lR3sRw08SPzIaQ==", - "dependencies": { - "write-file-atomic": "^1.1.4" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/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==", - "dependencies": { - "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" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/node-pre-gyp/node_modules/nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "dependencies": { - "abbrev": "1", - "osenv": "^0.1.4" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/node-pre-gyp/node_modules/tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "dependencies": { - "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" - }, - "engines": { - "node": ">=4.5" - } - }, - "node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "optional": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "dependencies": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "node_modules/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==" - }, - "node_modules/npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", - "dependencies": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "node_modules/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=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "engines": { - "node": "*" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/openpgp": { - "version": "4.10.10", - "resolved": "https://registry.npmjs.org/openpgp/-/openpgp-4.10.10.tgz", - "integrity": "sha512-Ub48OogGPjNsr0G/wnJ/SyAQzt/tfcXZTWVZdjKFpXCQV1Ca+upFdSPPkBlGG3lb9EQGOKZJ2tzYNH6ZyKMkDQ==", - "dependencies": { - "asn1.js": "^5.0.0", - "node-fetch": "^2.1.2", - "node-localstorage": "~1.3.0" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "node_modules/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==" - }, - "node_modules/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=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "optional": true - }, - "node_modules/pg": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz", - "integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==", - "dependencies": { - "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" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/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==" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-pool": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz", - "integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA==" - }, - "node_modules/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==" - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": { - "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" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz", - "integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==", - "dependencies": { - "split2": "^3.1.1" - } - }, - "node_modules/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==", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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==", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/printj": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", - "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", - "bin": { - "printj": "bin/printj.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/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==" - }, - "node_modules/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 - }, - "node_modules/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, - "engines": { - "node": ">=6" - } - }, - "node_modules/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, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/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==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "optional": true, - "dependencies": { - "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" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/rlp": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", - "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", - "dependencies": { - "bn.js": "^4.11.1" - }, - "bin": { - "rlp": "bin/rlp" - } - }, - "node_modules/rlp/node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - }, - "node_modules/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==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" - }, - "node_modules/secp256k1": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", - "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", - "dependencies": { - "elliptic": "^6.5.2", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" - }, - "node_modules/slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", - "engines": { - "node": "*" - } - }, - "node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/sqlite3": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.2.tgz", - "integrity": "sha512-1SdTNo+BVU211Xj1csWa8lV6KM0CtucDwRyA0VHl91wEH1Mgh7RxUpI4rVvG7OhHrzCSGaVyW5g8vKvlrk9DJA==", - "dependencies": { - "node-addon-api": "^3.0.0", - "node-pre-gyp": "^0.11.0" - }, - "optionalDependencies": { - "node-gyp": "3.x" - } - }, - "node_modules/sqlite3/node_modules/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==" - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "optional": true, - "dependencies": { - "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" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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=", - "dependencies": { - "is-hex-prefixed": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/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=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "optional": true, - "dependencies": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, - "node_modules/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, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/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=" - }, - "node_modules/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==", - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "optional": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "optional": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/vcard-parser": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vcard-parser/-/vcard-parser-1.0.0.tgz", - "integrity": "sha512-rSEjrjBK3of4VimMR5vBjLLcN5ZCSp9yuVzyx5i4Fwx74Yd0s+DnHtSit/wAAtj1a7/T/qQc0ykwXADoD0+fTQ==" - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "engines": [ - "node >=0.6.0" - ], - "optional": true, - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "optional": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/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==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/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==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/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=", - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "slide": "^1.1.5" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", - "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dependencies": { - "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" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/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==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/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==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - } - }, + "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==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.2.0.tgz", + "integrity": "sha512-PyQiTG00MJtBRkJmv46ChZL8u2XWxNBeAthznAUIUiefxPAXjbkuiCZOuncgJS34/XkMbNc9zMt/PlgKRBElig==", "requires": { - "crc-32": "^1.2.0" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.0.9" } }, "@ethereumjs/tx": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.0.2.tgz", - "integrity": "sha512-zmFCosjOdj1WoYEiQBdC4sCOAllBEwxdKuY85L9FgZ4zVDfZUVsQ4S9paczt4hVt65A7N8sJwgVEzDaQmrRaqw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.1.3.tgz", + "integrity": "sha512-DJBu6cbwYtiPTFeCUR8DF5p+PF0jxs+0rALJZiEcTz2tiRPIEkM72GEbrkGuqzENLCzBrJHT43O0DxSYTqeo+g==", "requires": { - "@ethereumjs/common": "^2.0.0", - "ethereumjs-util": "^7.0.8" + "@ethereumjs/common": "^2.2.0", + "ethereumjs-util": "^7.0.10" } }, "@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==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", + "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", "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==" + "version": "14.14.41", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.41.tgz", + "integrity": "sha512-dueRKfaJL4RTtSa7bWeTK1M+VH+Gns73oCgzvYfHZywRCoPSd8EkXBL0mZ9unPTveBn+D9phZBaxuzpwjWkW0g==" }, "@types/pbkdf2": { "version": "3.1.0", @@ -2123,9 +42,9 @@ } }, "@types/secp256k1": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", - "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-QMg+9v0bbNJ2peLuHRWxzmy0HRJIG6gFZNhaRSp7S3ggSbCCxiqQB2/ybvhXyhHOCequpNkrx7OavNhrWOsW0A==", "requires": { "@types/node": "*" } @@ -2229,9 +148,9 @@ }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" } } }, @@ -2271,9 +190,9 @@ "optional": true }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base-x": { "version": "3.0.8", @@ -2307,9 +226,9 @@ } }, "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" }, "brace-expansion": { "version": "1.1.11", @@ -2378,9 +297,9 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "cic-client-meta": { - "version": "0.0.7-alpha.5", - "resolved": "https://registry.npmjs.org/cic-client-meta/-/cic-client-meta-0.0.7-alpha.5.tgz", - "integrity": "sha512-h+0wmAKZIgezppBNYDmG387w6tI91FSWqONMTZbMuaO1Ej76Gg0Mk2UcDyAF/dmY6doXz3kHAbWkWat7mTzXAQ==", + "version": "0.0.7-alpha.6", + "resolved": "https://registry.npmjs.org/cic-client-meta/-/cic-client-meta-0.0.7-alpha.6.tgz", + "integrity": "sha512-oIN1aHkPHfsxJKDV6k4f1kX2tcppw3Q+D1b4BoPh0hYjNKNb7gImBMWnGsy8uiD9W6SNYE4sIXyrtct8mvrhsw==", "requires": { "@ethereumjs/tx": "^3.0.0-beta.1", "automerge": "^0.14.1", @@ -2422,9 +341,9 @@ "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==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -2580,9 +499,9 @@ }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" } } }, @@ -2619,11 +538,11 @@ } }, "ethereumjs-util": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.8.tgz", - "integrity": "sha512-JJt7tDpCAmDPw/sGoFYeq0guOVqT3pTE9xlEbBmc/nlCij3JRCoS2c96SQ6kXVHOT3xWUNLDm5QCJLQaUnVAtQ==", + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz", + "integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==", "requires": { - "@types/bn.js": "^4.11.3", + "@types/bn.js": "^5.1.0", "bn.js": "^5.1.2", "create-hash": "^1.1.2", "ethereum-cryptography": "^0.1.3", @@ -2980,18 +899,18 @@ } }, "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==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", "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==", + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", "optional": true, "requires": { - "mime-db": "1.46.0" + "mime-db": "1.47.0" } }, "minimalistic-assert": { @@ -3249,9 +1168,9 @@ "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==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", "requires": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -3267,23 +1186,23 @@ "optional": true }, "pg": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz", - "integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.6.0.tgz", + "integrity": "sha512-qNS9u61lqljTDFvmk/N66EeGq3n6Ujzj0FFyNMGQr6XuEv4tgNTXvJQTfJdcvGit5p5/DWPu+wj920hAJFI+QQ==", "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-connection-string": "^2.5.0", + "pg-pool": "^3.3.0", + "pg-protocol": "^1.5.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==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" }, "pg-int8": { "version": "1.0.1", @@ -3291,14 +1210,14 @@ "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==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.3.0.tgz", + "integrity": "sha512-0O5huCql8/D6PIRFAlmccjphLYWC+JIzvUhSzXSpGaf+tjTZc4nn+Lr7mLXBbFJfvwbP0ywDv73EiaBsxn7zdg==" }, "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==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", + "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" }, "pg-types": { "version": "2.2.0", @@ -3459,9 +1378,9 @@ }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" } } }, @@ -3571,14 +1490,6 @@ "tweetnacl": "~0.14.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" - } - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -3589,6 +1500,14 @@ "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", @@ -3734,9 +1653,9 @@ "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==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3774,9 +1693,9 @@ "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==" + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, "yallist": { "version": "3.1.1", @@ -3808,9 +1727,9 @@ "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==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3828,9 +1747,9 @@ } }, "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==" + "version": "20.2.7", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", + "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==" } } } diff --git a/apps/contract-migration/scripts/package.json b/apps/contract-migration/scripts/package.json index b5f273d2..0f61facd 100644 --- a/apps/contract-migration/scripts/package.json +++ b/apps/contract-migration/scripts/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "cic-client-meta": "^0.0.7-alpha.6", + "cic-client-meta": "0.0.7-alpha.6", "vcard-parser": "^1.0.0" } } diff --git a/apps/contract-migration/scripts/verify.py b/apps/contract-migration/scripts/verify.py index 14272ddd..f24a1148 100644 --- a/apps/contract-migration/scripts/verify.py +++ b/apps/contract-migration/scripts/verify.py @@ -22,7 +22,7 @@ from hexathon import ( strip_0x, add_0x, ) -from chainsyncer.backend import MemBackend +from chainsyncer.backend.memory import MemBackend from chainsyncer.driver import HeadSyncer from chainlib.chain import ChainSpec from chainlib.eth.connection import EthHTTPConnection @@ -32,7 +32,7 @@ from chainlib.eth.block import ( block_by_number, Block, ) -from chainlib.eth.hash import keccak256_string_to_hex +from chainlib.hash import keccak256_string_to_hex from chainlib.eth.address import to_checksum_address from chainlib.eth.erc20 import ERC20 from chainlib.eth.gas import ( @@ -40,7 +40,7 @@ from chainlib.eth.gas import ( balance, ) from chainlib.eth.tx import TxFactory -from chainlib.eth.rpc import jsonrpc_template +from chainlib.jsonrpc import jsonrpc_template from chainlib.eth.error import EthException from cic_types.models.person import ( Person, @@ -57,6 +57,7 @@ custodial_tests = [ 'local_key', 'gas', 'faucet', + 'ussd' ] metadata_tests = [ diff --git a/ci_templates/.cic-template.yml b/ci_templates/.cic-template.yml index 28eaf091..28148e93 100644 --- a/ci_templates/.cic-template.yml +++ b/ci_templates/.cic-template.yml @@ -24,7 +24,7 @@ variables: IMAGE_TAG_BASE: $CI_REGISTRY_IMAGE/$APP_NAME:$CI_COMMIT_BRANCH-$CI_COMMIT_SHORT_SHA LATEST_TAG: $CI_REGISTRY_IMAGE/$APP_NAME:latest script: - - export IMAGE_TAG="$IMAGE_TAG_BASE-$(date +%F.%H%M%S)" + - export IMAGE_TAG="$IMAGE_TAG_BASE-$(date +%s)" - mkdir -p /kaniko/.docker - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > "/kaniko/.docker/config.json" # - /kaniko/executor --context $CONTEXT --dockerfile $DOCKERFILE_PATH $KANIKO_CACHE_ARGS --destination $IMAGE_TAG diff --git a/docker-compose.yml b/docker-compose.yml index 3a74c5a0..69a9c318 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -450,7 +450,7 @@ services: deploy: restart_policy: condition: on-failure - command: "/root/start_tasker.sh -q cic-notify" + command: "/root/start_tasker.sh -q cic-notify -vv" cic-meta-server: @@ -498,6 +498,8 @@ services: DATABASE_NAME: cic_ussd DATABASE_ENGINE: postgresql DATABASE_DRIVER: psycopg2 + CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://redis} + CELERY_RESULT_URL: ${CELERY_BROKER_URL:-redis://redis} PGP_PASSPHRASE: merman SERVER_PORT: 9000 CIC_META_URL: ${CIC_META_URL:-http://meta:8000} diff --git a/scripts/initdb/create_db.sql b/scripts/initdb/create_db.sql index c1476495..46ccfc7f 100755 --- a/scripts/initdb/create_db.sql +++ b/scripts/initdb/create_db.sql @@ -5,6 +5,7 @@ CREATE DATABASE "cic_notify"; CREATE DATABASE "cic_meta"; CREATE DATABASE "cic_signer"; CREATE DATABASE "cic_ussd"; +CREATE DATABASE "chain_sync"; GRANT ALL PRIVILEGES -ON DATABASE "cic_cache", "cic_eth", "cic_notify", "cic_meta", "cic_signer", "cic_ussd" +ON DATABASE "cic_cache", "cic_eth", "cic_notify", "cic_meta", "cic_signer", "cic_ussd", "chain_sync" TO grassroots;