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())
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)
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()
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
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())))
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)