Esempio n. 1
0
    async def _do_get_actor(self, market_oid, actor_adr):
        is_member = await self.call('network.xbr.console.is_member', actor_adr)
        if is_member:
            actor = await self.call('network.xbr.console.get_member_by_wallet', actor_adr)
            actor_oid = uuid.UUID(bytes=actor['oid'])
            actor_adr = web3.Web3.toChecksumAddress(actor['address'])
            actor_level = actor['level']
            actor_balance_eth = web3.Web3.fromWei(unpack_uint256(actor['balance']['eth']), 'ether')
            actor_balance_xbr = web3.Web3.fromWei(unpack_uint256(actor['balance']['xbr']), 'ether')
            self.log.info('Found member with address {member_adr} (member level {member_level}, balances: {member_balance_eth} ETH, {member_balance_xbr} XBR)',
                          member_adr=hlid(actor_adr),
                          member_level=hlval(actor_level),
                          member_balance_eth=hlval(actor_balance_eth),
                          member_balance_xbr=hlval(actor_balance_xbr))

            if market_oid:
                market_oids = [market_oid.bytes]
            else:
                market_oids = await self.call('network.xbr.console.get_markets_by_actor', actor_oid.bytes)

            if market_oids:
                for market_oid in market_oids:
                    # market = await self.call('network.xbr.console.get_market', market_oid)
                    result = await self.call('network.xbr.console.get_actor_in_market', market_oid, actor['address'])
                    for actor in result:
                        actor['actor'] = web3.Web3.toChecksumAddress(actor['actor'])
                        actor['timestamp'] = np.datetime64(actor['timestamp'], 'ns')
                        actor['joined'] = unpack_uint256(actor['joined']) if actor['joined'] else None
                        actor['market'] = uuid.UUID(bytes=actor['market'])
                        actor['security'] = web3.Web3.fromWei(unpack_uint256(actor['security']), 'ether') if actor['security'] else None
                        actor['signature'] = '0x' + binascii.b2a_hex(actor['signature']).decode() if actor['signature'] else None
                        actor['tid'] = '0x' + binascii.b2a_hex(actor['tid']).decode() if actor['tid'] else None

                        actor_type = actor['actor_type']
                        ACTOR_TYPE_TO_STR = {
                            # Actor is a XBR Provider.
                            1: 'PROVIDER',
                            # Actor is a XBR Consumer.
                            2: 'CONSUMER',
                            # Actor is both a XBR Provider and XBR Consumer.
                            3: 'PROVIDER_CONSUMER',
                        }
                        actor['actor_type'] = ACTOR_TYPE_TO_STR.get(actor_type, None)

                        self.log.info('Actor is joined to market {market_oid}:\n\n{actor}\n',
                                      market_oid=hlid(uuid.UUID(bytes=market_oid)), actor=pformat(actor))
            else:
                self.log.info('Member is not yet actor in any market!')
        else:
            self.log.warn('Address 0x{member_adr} is not a member in the XBR network',
                          member_adr=binascii.b2a_hex(actor_adr).decode())
Esempio n. 2
0
    def get_member(self, ethadr_raw):
        if self.is_attached():
            is_member = yield self.call('xbr.network.is_member', ethadr_raw)
            if is_member:
                member_data = yield self.call(
                    'xbr.network.get_member_by_wallet', ethadr_raw)

                member_data['address'] = web3.Web3.toChecksumAddress(
                    member_data['address'])
                member_data['oid'] = uuid.UUID(bytes=member_data['oid'])
                member_data['balance']['eth'] = web3.Web3.fromWei(
                    unpack_uint256(member_data['balance']['eth']), 'ether')
                member_data['balance']['xbr'] = web3.Web3.fromWei(
                    unpack_uint256(member_data['balance']['xbr']), 'ether')
                member_data['created'] = np.datetime64(member_data['created'],
                                                       'ns')

                member_level = member_data['level']
                member_data['level'] = {
                    # Member is active.
                    1: 'ACTIVE',
                    # Member is active and verified.
                    2: 'VERIFIED',
                    # Member is retired.
                    3: 'RETIRED',
                    # Member is subject to a temporary penalty.
                    4: 'PENALTY',
                    # Member is currently blocked and cannot current actively participate in the market.
                    5: 'BLOCKED',
                }.get(member_level, None)

                self.log.info(
                    'Member {member_oid} found for address 0x{member_adr} - current member level {member_level}',
                    member_level=hlval(member_data['level']),
                    member_oid=hlid(member_data['oid']),
                    member_adr=hlval(member_data['address']))

                return member_data
            else:
                self.log.warn(
                    'Address {output_ethadr} is not a member in the XBR network',
                    output_ethadr=ethadr_raw)
        else:
            self.log.warn(
                'not connected: could not retrieve member data for address {output_ethadr}',
                output_ethadr=ethadr_raw)
Esempio n. 3
0
    def onLeave(self, details):
        self.log.info('Client left realm (reason="{reason}")', reason=hlval(details.reason))
        self._running = False

        if details.reason == 'wamp.close.normal':
            # user initiated leave => end the program
            self.config.runner.stop()
            self.disconnect()
Esempio n. 4
0
    def _send_Allowance(self, from_adr, to_adr, amount):
        # FIXME: estimate gas required for call
        gas = self._default_gas
        gasPrice = self._w3.toWei('10', 'gwei')

        from_adr = self._ethadr

        # each submitted transaction must contain a nonce, which is obtained by the on-chain transaction number
        # for this account, including pending transactions (I think ..;) ..
        nonce = self._w3.eth.getTransactionCount(from_adr, block_identifier='pending')
        self.log.info('{func}::[1/4] - Ethereum transaction nonce: nonce={nonce}',
                      func=hltype(self._send_Allowance),
                      nonce=nonce)

        # serialize transaction raw data from contract call and transaction settings
        raw_transaction = xbr.xbrtoken.functions.approve(to_adr, amount).buildTransaction({
            'from': from_adr,
            'gas': gas,
            'gasPrice': gasPrice,
            'chainId': self._chain_id,  # https://stackoverflow.com/a/57901206/884770
            'nonce': nonce,
        })
        self.log.info(
            '{func}::[2/4] - Ethereum transaction created: raw_transaction=\n{raw_transaction}\n',
            func=hltype(self._send_Allowance),
            raw_transaction=raw_transaction)

        # compute signed transaction from above serialized raw transaction
        signed_txn = self._w3.eth.account.sign_transaction(raw_transaction, private_key=self._ethkey_raw)
        self.log.info(
            '{func}::[3/4] - Ethereum transaction signed: signed_txn=\n{signed_txn}\n',
            func=hltype(self._send_Allowance),
            signed_txn=hlval(binascii.b2a_hex(signed_txn.rawTransaction).decode()))

        # now send the pre-signed transaction to the blockchain via the gateway ..
        # https://web3py.readthedocs.io/en/stable/web3.eth.html  # web3.eth.Eth.sendRawTransaction
        txn_hash = self._w3.eth.sendRawTransaction(signed_txn.rawTransaction)
        txn_hash = bytes(txn_hash)
        self.log.info(
            '{func}::[4/4] - Ethereum transaction submitted: txn_hash=0x{txn_hash}',
            func=hltype(self._send_Allowance),
            txn_hash=hlval(binascii.b2a_hex(txn_hash).decode()))

        return txn_hash
Esempio n. 5
0
    def __init__(self, config_path):
        self._config_path = os.path.abspath(config_path)

        config = configparser.ConfigParser()
        config.read(config_path)

        self.config = config

        profiles = {}
        for profile_name in config.sections():
            profile = Profile.parse(config_path, profile_name,
                                    config.items(profile_name))
            profiles[profile_name] = profile

        self.profiles = profiles

        self.log.debug('profiles loaded: {profiles}',
                       func=hltype(self.__init__),
                       profiles=', '.join(
                           hlval(x) for x in sorted(self.profiles.keys())))
Esempio n. 6
0
def _main():
    parser = argparse.ArgumentParser()

    parser.add_argument('command',
                        type=str,
                        choices=_COMMANDS,
                        const='noop',
                        nargs='?',
                        help='Command to run')

    parser.add_argument('-d',
                        '--debug',
                        action='store_true',
                        help='Enable debug output.')

    parser.add_argument('--url',
                        dest='url',
                        type=str,
                        default='wss://planet.xbr.network/ws',
                        help='The router URL (default: "wss://planet.xbr.network/ws").')

    parser.add_argument('--realm',
                        dest='realm',
                        type=str,
                        default='xbrnetwork',
                        help='The realm to join (default: "xbrnetwork").')

    parser.add_argument('--ethkey',
                        dest='ethkey',
                        type=str,
                        help='Private Ethereum key (32 bytes as HEX encoded string)')

    parser.add_argument('--cskey',
                        dest='cskey',
                        type=str,
                        help='Private WAMP-cryptosign authentication key (32 bytes as HEX encoded string)')

    parser.add_argument('--username',
                        dest='username',
                        type=str,
                        default=None,
                        help='For on-boarding, the new member username.')

    parser.add_argument('--email',
                        dest='email',
                        type=str,
                        default=None,
                        help='For on-boarding, the new member email address.')

    parser.add_argument('--market',
                        dest='market',
                        type=str,
                        default=None,
                        help='For creating new markets, the market UUID.')

    parser.add_argument('--market_title',
                        dest='market_title',
                        type=str,
                        default=None,
                        help='For creating new markets, the market title.')

    parser.add_argument('--market_label',
                        dest='market_label',
                        type=str,
                        default=None,
                        help='For creating new markets, the market label.')

    parser.add_argument('--market_homepage',
                        dest='market_homepage',
                        type=str,
                        default=None,
                        help='For creating new markets, the market homepage.')

    parser.add_argument('--provider_security',
                        dest='provider_security',
                        type=int,
                        default=None,
                        help='')

    parser.add_argument('--consumer_security',
                        dest='consumer_security',
                        type=int,
                        default=None,
                        help='')

    parser.add_argument('--market_fee',
                        dest='market_fee',
                        type=int,
                        default=None,
                        help='')

    parser.add_argument('--marketmaker',
                        dest='marketmaker',
                        type=str,
                        default=None,
                        help='For creating new markets, the market maker address.')

    parser.add_argument('--actor_type',
                        dest='actor_type',
                        type=int,
                        choices=sorted([ActorType.CONSUMER, ActorType.PROVIDER, ActorType.PROVIDER_CONSUMER]),
                        default=None,
                        help='Actor type: PROVIDER = 1, CONSUMER = 2, PROVIDER_CONSUMER (both) = 3')

    parser.add_argument('--vcode',
                        dest='vcode',
                        type=str,
                        default=None,
                        help='For verifications of actions, the verification UUID.')

    parser.add_argument('--vaction',
                        dest='vaction',
                        type=str,
                        default=None,
                        help='For verifications of actions (on-board, create-market, ..), the verification code.')

    parser.add_argument('--channel',
                        dest='channel',
                        type=str,
                        default=None,
                        help='For creating new channel, the channel UUID.')

    parser.add_argument('--channel_type',
                        dest='channel_type',
                        type=int,
                        choices=sorted([ChannelType.PAYING, ChannelType.PAYMENT]),
                        default=None,
                        help='Channel type: Seller (PAYING) = 1, Buyer (PAYMENT) = 2')

    parser.add_argument('--delegate',
                        dest='delegate',
                        type=str,
                        default=None,
                        help='For creating new channel, the delegate address.')

    parser.add_argument('--amount',
                        dest='amount',
                        type=int,
                        default=None,
                        help='Amount to open the channel with. In tokens of the market coin type, used as means of payment in the market of the channel.')

    args = parser.parse_args()

    if args.command == 'version':
        print('')
        print(' XBR CLI v{}\n'.format(__version__))
        print('   XBRToken   contract address: {} [source: {}]'.format(hlid(XBR_DEBUG_TOKEN_ADDR), XBR_DEBUG_TOKEN_ADDR_SRC))
        print('   XBRNetwork contract address: {} [source: {}]'.format(hlid(XBR_DEBUG_NETWORK_ADDR), XBR_DEBUG_NETWORK_ADDR_SRC))
        print('   XBRMarket  contract address: {} [source: {}]'.format(hlid(XBR_DEBUG_MARKET_ADDR), XBR_DEBUG_MARKET_ADDR_SRC))
        print('   XBRCatalog contract address: {} [source: {}]'.format(hlid(XBR_DEBUG_CATALOG_ADDR), XBR_DEBUG_CATALOG_ADDR_SRC))
        print('   XBRChannel contract address: {} [source: {}]'.format(hlid(XBR_DEBUG_CHANNEL_ADDR), XBR_DEBUG_CHANNEL_ADDR_SRC))
        print('')
    else:
        if args.command is None or args.command == 'noop':
            print('no command given. select from: {}'.format(', '.join(_COMMANDS)))
            sys.exit(0)

        # read or create a user profile
        profile = load_or_create_profile()

        # only start txaio logging after above, which runs click (interactively)
        if args.debug:
            txaio.start_logging(level='debug')
        else:
            txaio.start_logging(level='info')

        log = txaio.make_logger()

        log.info('XBR CLI {version}', version=hlid('v' + __version__))
        log.info('Profile {profile} loaded from {path}', profile=hlval(profile.name), path=hlval(profile.path))

        extra = {
            # user profile and defaults
            'profile': profile,

            # allow to override, and add more arguments from the command line
            'command': args.command,
            'ethkey': binascii.a2b_hex(args.ethkey[2:]) if args.ethkey else None,
            'cskey': binascii.a2b_hex(args.cskey[2:]) if args.cskey else None,
            'username': args.username,
            'email': args.email,
            'market': uuid.UUID(args.market) if args.market else None,
            'market_title': args.market_title,
            'market_label': args.market_label,
            'market_homepage': args.market_homepage,
            'market_provider_security': args.provider_security or 0,
            'market_consumer_security': args.consumer_security or 0,
            'market_fee': args.market_fee or 0,
            'marketmaker': binascii.a2b_hex(args.marketmaker[2:]) if args.marketmaker else None,
            'actor_type': args.actor_type,
            'vcode': args.vcode,
            'vaction': uuid.UUID(args.vaction) if args.vaction else None,
            'channel': uuid.UUID(args.channel) if args.channel else None,
            'channel_type': args.channel_type,
            'delegate': binascii.a2b_hex(args.delegate[2:]) if args.delegate else None,
            'amount': args.amount or 0,
        }
        runner = ApplicationRunner(url=args.url, realm=args.realm, extra=extra, serializers=[CBORSerializer()])

        try:
            log.info('Connecting to "{url}" {realm} ..',
                     url=hlval(args.url), realm=('at realm "' + hlval(args.realm) + '"' if args.realm else ''))
            runner.run(Client, auto_reconnect=False)
        except Exception as e:
            print(e)
            sys.exit(1)
        else:
            sys.exit(0)