def main(): url = "http://" + sys.argv[1] substrate = SubstrateInterface( url=url, type_registry_preset='default' ) keypair = Keypair.create_from_seed(sys.argv[2]) call = substrate.compose_call( call_module='Balances', call_function='transfer', call_params={ 'dest': sys.argv[3], 'value': int(sys.argv[4]) * 10**12 } ) extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair) try: result = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=False) print("Extrinsic '{}' sent".format(result['extrinsic_hash'])) except SubstrateRequestException as e: print("Failed to send: {}".format(e))
def register(domain, name, ip_addr, info, key): substrate = SubstrateInterface(url="http://127.0.0.1:9933", ss58_format=42, type_registry_preset='polkadot', type_registry={ "types": { "Certificate": { "type": "struct", "type_mapping": [["version_number", "i32"], ["owner_id", "AccountId"], ["name", "Vec<u8>"], ["info", "Vec<u8>"], ["key", "Vec<u8>"], ["ip_addr", "Vec<u8>"], ["domain", "Vec<u8>"]] } } }) keypair = Keypair.create_from_uri('//Alice') call = substrate.compose_call(call_module='SiipModule', call_function='register_certificate', call_params={ 'name': name, 'domain': domain, 'ip_addr': ip_addr, 'info': info, 'key': key, }) extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair) return substrate.submit_extrinsic(extrinsic)
async def nine_nine(ctx, arg): if (ctx.channel.type == "private"): # Forbid DM in discord await ctx.send("Hold on Capt'ain, you can't send me private messages !" ) else: substrate = SubstrateInterface( url=node_rpc, address_type=42, type_registry_preset='substrate-node-template') call = substrate.compose_call(call_module='Balances', call_function='transfer', call_params={ 'dest': arg, 'value': 100 * 10**12 }) reply = "" keypair = Keypair.create_from_mnemonic(faucet_mnemonic) extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair) reply = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=False) await ctx.send( ctx.author.mention + " Awesome, you just received 100 dPIRL, it has no real value it's only the testnet token :) " + reply['extrinsic_hash'] + str(ctx.channel.type))
def create_MnemonicKey(self): substrate = SubstrateInterface(url=self.url, address_type=42, type_registry_preset='polkadot') # keypair=Keypair.create_from_seed("0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a") #alice账号 file_name = open('account_info.csv', encoding='utf-8') csv_lines = csv.reader(file_name) data = [] for row in csv_lines: if csv_lines.line_num == 1: continue else: data.append(row) print("data", data) for info in data: print("info", info) account = info[0] keypair = Keypair.create_from_mnemonic(self.seed_secret) # keypair = Keypair.create_from_mnemonic(info[1]) amount = info[1] print("type", type(amount)) call = substrate.compose_call( call_module='Balances', call_function='transfer', call_params={ # 接收方 'dest': account, 'value': Decimal(amount) * 10**10 }) extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair) try: result = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True) print(result) print("Extrinsic '{}' sent and included in block '{}'".format( result['extrinsic_hash'], result['block_hash'])) except SubstrateRequestException as e: print(e) with open("faild_info.txt", "a") as f: f.write(account + "\n") time.sleep(5)
def withdraw(priv, pub, to_address, amount): substrate = SubstrateInterface(url='wss://rpc.polkadot.io', ss58_format=0, type_registry_preset='polkadot', use_remote_preset=True) call = substrate.compose_call( call_module='Balances', call_function='transfer', call_params={'dest': to_address, 'value': int(amount * 1e8)} ) from_address = public_key_to_address(pub) nonce = substrate.get_account_nonce(from_address) payload = substrate.generate_signature_payload(call, nonce=nonce).data signature = '0x' + eddsa_sign.eddsa_sign(priv, payload).hex() keypair = Keypair(ss58_address=from_address, ss58_format=0, crypto_type=KeypairType.ED25519) extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair, nonce=nonce, signature=signature) result=substrate.submit_extrinsic(extrinsic=extrinsic) print(result)
def sendPirl(mnemonic, destination, value): substrate = SubstrateInterface( url=node_rpc, address_type=42, type_registry_preset='substrate-node-template') call = substrate.compose_call( call_module='Balances', call_function='transfer', call_params={ 'dest': destination, # recipient address 'value': value * 10**12 # we send PIRLs and apply the 12 decimals }) keypair = Keypair.create_from_mnemonic(mnemonic) extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair) transaction = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True) print("extrinsic_hash: " + transaction['extrinsic_hash'], "block: " + transaction['block_hash'])
def run(): try: substrate = SubstrateInterface( url="wss://hk.listen.io/", address_type=42, type_registry_preset='default' ) import time time.sleep(1) keypair = Keypair.create_from_mnemonic("adult hunt thank force make satisfy saddle pumpkin reject very avoid goat") # print("Created address: {}".format(keypair.ss58_address)) mnemonic = Keypair.generate_mnemonic() # 接收方随机生成 keypair1 = Keypair.create_from_mnemonic(mnemonic, 2) # 可以直接调用自己定义的模块 不需要特殊处理 call = substrate.compose_call( call_module='Listen', call_function='air_drop', call_params={ # 接收方 # 'dest': '5GnGKSCitk1QPpMNugtTGX9t6TqzDGvL5BqKzLfHNsLSrwqN', 'des': keypair1.ss58_address, # 'value': 10 * 10**14 } ) extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair) try: result = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True) print("Extrinsic '{}' sent and included in block '{}'".format(result['extrinsic_hash'], result['block_hash'])) # substrate.s except SubstrateRequestException as e: print("Failed to send: {}".format(e)) except Exception as e: print(e)
def example_send_transaction(): """ similar to what is given in polkascan github README.md issue reported back to polkascan https://github.com/polkascan/py-substrate-interface/issues/14 """ # substrate = SubstrateInterface( url="ws://127.0.0.1:9944", address_type=42, type_registry_preset='kusama' ) # substrate = SubstrateInterface( url="ws://127.0.0.1:9944", address_type=2) substrate = SubstrateInterface(url="ws://127.0.0.1:9944") keypair = Keypair.create_from_mnemonic( 'episode together nose spoon dose oil faculty zoo ankle evoke admit walnut' ) # keypair = Keypair.create_from_private_key('//Alice') # keypair = Keypair.create_from_mnemonic('//Alice') keypair_printer(keypair) print("sending from:", keypair.ss58_address) BOB_ADDRESS = '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty' call = substrate.compose_call(call_module='Balances', call_function='transfer', call_params={ 'dest': BOB_ADDRESS, 'value': 1 * 10**12 }) extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair) try: result = substrate.send_extrinsic(extrinsic, wait_for_inclusion=True) print("Extrinsic '{}' sent and included in block '{}'".format( result['extrinsic_hash'], result['block_hash'])) except SubstrateRequestException as e: print("Failed to send: {} with args:".format(type(e))) print("{}".format(pformat(e.args[0])))
class JSONRPCResource(BaseResource): def __init__(self, cache_region): self.cache_region = cache_region # Check for custom types in Redis self.substrate = None custom_type_registry = self.cache_region.get('CUSTOM_TYPE_REGISTRY') self.init_type_registry(custom_type_registry) self.block_hash = None self.metadata_decoder = None self.runtime_version = None self.metadata_cache = {} self.methods = [ 'rpc_methods', 'runtime_decodeScale', 'runtime_encodeScale', 'runtime_getMetadata', 'runtime_getMetadataModules', 'runtime_getMetadataCallFunctions', 'runtime_getMetadataCallFunction', 'runtime_getMetadataEvents', 'runtime_getMetadataEvent', 'runtime_getMetadataConstants', 'runtime_getMetadataConstant', 'runtime_getMetadataStorageFunctions', 'runtime_getMetadataStorageFunction', 'runtime_getMetadataErrors', 'runtime_getMetadataError', 'runtime_getState', 'runtime_getTypeRegistry', 'runtime_getType', 'runtime_getCustomTypes', 'runtime_addCustomType', 'runtime_setCustomTypes', 'runtime_removeCustomType', 'runtime_resetCustomTypes', 'runtime_getBlock', 'runtime_createSignaturePayload', 'runtime_createExternalSignerPayload', 'runtime_createExtrinsic', 'runtime_submitExtrinsic', 'runtime_getPaymentInfo', 'keypair_create', 'keypair_inspect', 'keypair_sign', 'keypair_verify' ] def get_request_param(self, params): try: return params.pop(0) except IndexError: raise ValueError("Not enough parameters provided") def init_type_registry(self, custom_type_registry=None): if settings.TYPE_REGISTRY_FILE: type_registry = load_type_registry_file(settings.TYPE_REGISTRY_FILE) else: type_registry = {} if custom_type_registry: type_registry.update(custom_type_registry) self.substrate = SubstrateInterface( url=settings.SUBSTRATE_RPC_URL, ss58_format=settings.SUBSTRATE_ADDRESS_TYPE, type_registry_preset=settings.TYPE_REGISTRY, type_registry=custom_type_registry ) if settings.DEBUG: print('Custom types at init: ', custom_type_registry) self.substrate.debug = True def init_request(self, params=None): if params: self.block_hash = self.get_request_param(params) if type(self.block_hash) is int: self.block_hash = self.substrate.get_block_hash(self.block_hash) def on_post(self, req, resp): self.block_hash = None self.metadata_decoder = None self.runtime_version = None self.substrate.request_id = req.media.get('id') method = req.media.get('method') params = req.media.get('params', []) # Check request requirements if not req.media.get('jsonrpc'): resp.media = { "error": { "code": -32600, "message": "Unsupported JSON-RPC protocol version" }, "id": req.media.get('id') } elif not method: resp.media = { "error": { "code": -32601, "message": "Method not found" }, "id": req.media.get('id') } elif method not in self.methods: # Default pass through request to Substrate RPC resp.media = self.substrate.rpc_request(method, params) else: resp.status = falcon.HTTP_200 try: # Process methods if method == 'runtime_getBlock': self.init_request(params) block = self.substrate.get_block(block_hash=self.block_hash) if block: block['extrinsics'] = [extrinsic.value for extrinsic in block['extrinsics']] block['header']["digest"]["logs"] = [log.value for log in block['header']["digest"]["logs"]] response = { "jsonrpc": "2.0", "result": block, "id": req.media.get('id') } elif method == 'runtime_getState': # Init params storage_params = None # Process params module = self.get_request_param(params) storage_function = self.get_request_param(params) if params: storage_params = self.get_request_param(params) self.init_request(params) # Get response obj = self.substrate.query( module=module, storage_function=storage_function, params=storage_params, block_hash=self.block_hash ) response = {'result': obj.value if obj else None} elif method == 'runtime_getMetadata': # Process params self.init_request(params) # Get response response = self.substrate.get_runtime_metadata(block_hash=self.block_hash) elif method in ['runtime_createSignaturePayload', 'runtime_createExternalSignerPayload']: account = self.get_request_param(params) call_module = self.get_request_param(params) call_function = self.get_request_param(params) call_params = self.get_request_param(params) tip = self.get_request_param(params) or 0 era = self.get_request_param(params) self.init_request(params) try: # Create call call = self.substrate.compose_call( call_module=call_module, call_function=call_function, call_params=call_params, block_hash=self.block_hash ) nonce = self.substrate.get_account_nonce(account) or 0 if isinstance(era, dict) and 'current' not in era and 'phase' not in era: # Retrieve current block id era['current'] = self.substrate.get_block_number(self.substrate.get_chain_head()) if method == 'runtime_createExternalSignerPayload': include_call_length = True else: include_call_length = False # Generate signature payload signature_payload = self.substrate.generate_signature_payload( call=call, nonce=nonce, tip=tip, era=era, include_call_length=include_call_length ) response = { "jsonrpc": "2.0", "result": { 'signature_payload': str(signature_payload), 'nonce': nonce, 'era': era }, "id": req.media.get('id') } except ValueError as e: response = { "jsonrpc": "2.0", "error": { "code": -999, "message": str(e) }, "id": req.media.get('id') } elif method in ['runtime_submitExtrinsic', 'runtime_createExtrinsic']: account = self.get_request_param(params) call_module = self.get_request_param(params) call_function = self.get_request_param(params) call_params = self.get_request_param(params) tip = self.get_request_param(params) or 0 era = self.get_request_param(params) crypto_type = int(self.get_request_param(params) or 1) signature = self.get_request_param(params) self.init_request(params) try: # Create call call = self.substrate.compose_call( call_module=call_module, call_function=call_function, call_params=call_params, block_hash=self.block_hash ) nonce = self.substrate.get_account_nonce(account) or 0 # Create keypair with only public given given in request keypair = Keypair(ss58_address=account, crypto_type=crypto_type) if isinstance(era, dict) and 'current' in era: era['current'] = int(era['current']) # Create extrinsic extrinsic = self.substrate.create_signed_extrinsic( call=call, keypair=keypair, nonce=nonce, signature=signature, tip=tip, era=era ) if method == 'runtime_createExtrinsic': result = str(extrinsic.data) else: # Submit extrinsic to the node extrinsic_result = self.substrate.submit_extrinsic( extrinsic=extrinsic ) result = { "extrinsic_hash": extrinsic_result.extrinsic_hash, "block_hash": extrinsic_result.block_hash, "finalized": extrinsic_result.finalized, } response = { "jsonrpc": "2.0", "result": result, "id": req.media.get('id') } except ValueError as e: response = { "jsonrpc": "2.0", "error": { "code": -999, "message": str(e) }, "id": req.media.get('id') } except SubstrateRequestException as e: response = { "jsonrpc": "2.0", "error": e.args[0], "id": req.media.get('id') } elif method == 'runtime_getPaymentInfo': account = self.get_request_param(params) call_module = self.get_request_param(params) call_function = self.get_request_param(params) call_params = self.get_request_param(params) # Create call call = self.substrate.compose_call( call_module=call_module, call_function=call_function, call_params=call_params ) # Create keypair with only public given given in request keypair = Keypair(ss58_address=account) response = { "jsonrpc": "2.0", "result": self.substrate.get_payment_info(call=call, keypair=keypair), "id": req.media.get('id') } elif method == 'runtime_getMetadataModules': self.init_request(params) response = { "jsonrpc": "2.0", "result": self.substrate.get_metadata_modules(block_hash=self.block_hash), "id": req.media.get('id') } elif method == 'runtime_getMetadataCallFunctions': self.init_request(params) call_list = self.substrate.get_metadata_call_functions(block_hash=self.block_hash) response = { "jsonrpc": "2.0", "result": call_list, "id": req.media.get('id') } elif method == 'runtime_getMetadataCallFunction': param_call_module = self.get_request_param(params) param_call_module_function = self.get_request_param(params) self.init_request(params) result = self.substrate.get_metadata_call_function( module_name=param_call_module, call_function_name=param_call_module_function, block_hash=self.block_hash ) response = { "jsonrpc": "2.0", "result": result.value, "id": req.media.get('id') } elif method == 'runtime_getMetadataEvents': self.init_request(params) event_list = self.substrate.get_metadata_events(block_hash=self.block_hash) response = { "jsonrpc": "2.0", "result": event_list, "id": req.media.get('id') } elif method == 'runtime_getMetadataEvent': param_call_module = self.get_request_param(params) param_call_module_event = self.get_request_param(params) self.init_request(params) result = self.substrate.get_metadata_event( module_name=param_call_module, event_name=param_call_module_event, block_hash=self.block_hash ) response = { "jsonrpc": "2.0", "result": result, "id": req.media.get('id') } elif method == 'runtime_getMetadataConstants': self.init_request(params) constant_list = self.substrate.get_metadata_constants(block_hash=self.block_hash) response = { "jsonrpc": "2.0", "result": constant_list, "id": req.media.get('id') } elif method == 'runtime_getMetadataConstant': module_name = self.get_request_param(params) constant_name = self.get_request_param(params) self.init_request(params) result = self.substrate.get_metadata_constant( module_name=module_name, constant_name=constant_name, block_hash=self.block_hash ) response = { "jsonrpc": "2.0", "result": result, "id": req.media.get('id') } elif method == 'runtime_getMetadataStorageFunctions': self.init_request(params) storage_list = self.substrate.get_metadata_storage_functions(block_hash=self.block_hash) response = { "jsonrpc": "2.0", "result": storage_list, "id": req.media.get('id') } elif method == 'runtime_getMetadataStorageFunction': module_name = self.get_request_param(params) storage_name = self.get_request_param(params) self.init_request(params) result = self.substrate.get_metadata_storage_function( module_name=module_name, storage_name=storage_name, block_hash=self.block_hash ) response = { "jsonrpc": "2.0", "result": result.value, "id": req.media.get('id') } elif method == 'runtime_getMetadataErrors': self.init_request(params) error_list = self.substrate.get_metadata_errors(block_hash=self.block_hash) response = { "jsonrpc": "2.0", "result": error_list, "id": req.media.get('id') } elif method == 'runtime_getMetadataError': module_name = self.get_request_param(params) error_name = self.get_request_param(params) self.init_request(params) result = self.substrate.get_metadata_error( module_name=module_name, error_name=error_name, block_hash=self.block_hash ) response = { "jsonrpc": "2.0", "result": result, "id": req.media.get('id') } elif method == 'runtime_getTypeRegistry': self.init_request(params) result = self.substrate.get_type_registry(block_hash=self.block_hash) if result: result = list(result.values()) response = { "jsonrpc": "2.0", "result": result, "id": req.media.get('id') } elif method == 'runtime_getType': type_string = self.get_request_param(params) self.init_request(params) response = { "jsonrpc": "2.0", "result": self.substrate.get_type_definition(type_string, block_hash=self.block_hash), "id": req.media.get('id') } elif method == 'runtime_addCustomType': type_string = self.get_request_param(params) type_definition = self.get_request_param(params) # Retrieve current custom type registry custom_type_registry = self.cache_region.get('CUSTOM_TYPE_REGISTRY') if not custom_type_registry: custom_type_registry = { 'types': { } } custom_type_registry['types'][type_string] = type_definition # TODO Try to decode given type definition # Store updated custom type registry self.cache_region.set('CUSTOM_TYPE_REGISTRY', custom_type_registry) if settings.DEBUG: print('Custom types updated to: ', custom_type_registry) # Update runtime configuration RuntimeConfiguration().update_type_registry(custom_type_registry) response = { "jsonrpc": "2.0", "result": "Type registry updated", "id": req.media.get('id') } elif method == 'runtime_setCustomTypes': custom_types = self.get_request_param(params) if type(custom_types) is not dict: raise ValueError('custom types must be in format: {"type_string": "type_definition"}') custom_type_registry = { 'types': custom_types } # Store updated custom type registry self.cache_region.set('CUSTOM_TYPE_REGISTRY', custom_type_registry) # Reset runtime configuration RuntimeConfiguration().clear_type_registry() self.init_type_registry(custom_type_registry) if settings.DEBUG: print('Custom types updated to: ', custom_type_registry) response = { "jsonrpc": "2.0", "result": "Type registry updated", "id": req.media.get('id') } elif method == 'runtime_resetCustomTypes': custom_type_registry = None # Store updated custom type registry self.cache_region.set('CUSTOM_TYPE_REGISTRY', custom_type_registry) # Reset runtime configuration RuntimeConfiguration().clear_type_registry() self.init_type_registry() if settings.DEBUG: print('Custom types cleared') response = { "jsonrpc": "2.0", "result": "Custom types cleared", "id": req.media.get('id') } elif method == 'runtime_removeCustomType': type_string = self.get_request_param(params) # Retrieve current custom type registry custom_type_registry = self.cache_region.get('CUSTOM_TYPE_REGISTRY') if custom_type_registry and type_string in custom_type_registry.get('types', {}): del custom_type_registry['types'][type_string] # Store updated custom type registry self.cache_region.set('CUSTOM_TYPE_REGISTRY', custom_type_registry) # Reset runtime configuration RuntimeConfiguration().clear_type_registry() self.init_type_registry(custom_type_registry) result = '"{}" removed from custom type registry'.format(type_string) else: result = '"{}" not found in custom type registry'.format(type_string) response = { "jsonrpc": "2.0", "result": result, "id": req.media.get('id') } elif method == 'runtime_getCustomTypes': custom_type_registry = self.cache_region.get('CUSTOM_TYPE_REGISTRY') if custom_type_registry: result = custom_type_registry.get('types') else: result = {} response = { "jsonrpc": "2.0", "result": result, "id": req.media.get('id') } elif method == 'runtime_decodeScale': type_string = self.get_request_param(params) scale_hex_bytes = self.get_request_param(params) self.init_request(params) result = self.substrate.decode_scale( type_string=type_string, scale_bytes=scale_hex_bytes, block_hash=self.block_hash ) response = { "jsonrpc": "2.0", "result": result, "id": req.media.get('id') } elif method == 'runtime_encodeScale': type_string = self.get_request_param(params) value = self.get_request_param(params) self.init_request(params) result = self.substrate.encode_scale( type_string=type_string, value=value, block_hash=self.block_hash ) response = { "jsonrpc": "2.0", "result": result, "id": req.media.get('id') } elif method == 'keypair_create': word_count = self.get_request_param(params) or 0 crypto_type = int(self.get_request_param(params) or 1) mnemonic = Keypair.generate_mnemonic(word_count) keypair = Keypair.create_from_mnemonic( mnemonic=mnemonic, ss58_format=settings.SUBSTRATE_ADDRESS_TYPE, crypto_type=crypto_type ) response = { "jsonrpc": "2.0", "result": { 'ss58_address': keypair.ss58_address, 'public_key': keypair.public_key, 'private_key': keypair.private_key, 'mnemonic': keypair.mnemonic, }, "id": req.media.get('id') } elif method == 'keypair_inspect': mnemonic = self.get_request_param(params) crypto_type = int(self.get_request_param(params) or 1) keypair = Keypair.create_from_mnemonic( mnemonic=mnemonic, ss58_format=settings.SUBSTRATE_ADDRESS_TYPE, crypto_type=crypto_type ) response = { "jsonrpc": "2.0", "result": { 'ss58_address': keypair.ss58_address, 'public_key': keypair.public_key, 'private_key': keypair.private_key, 'mnemonic': keypair.mnemonic, }, "id": req.media.get('id') } elif method == 'keypair_sign': mnemonic = self.get_request_param(params) data = self.get_request_param(params) crypto_type = int(self.get_request_param(params) or 1) keypair = Keypair.create_from_mnemonic( mnemonic=mnemonic, ss58_format=settings.SUBSTRATE_ADDRESS_TYPE, crypto_type=crypto_type ) signature = keypair.sign(data) response = { "jsonrpc": "2.0", "result": {'signature': signature}, "id": req.media.get('id') } elif method == 'keypair_verify': account_address = self.get_request_param(params) data = self.get_request_param(params) signature = self.get_request_param(params) crypto_type = int(self.get_request_param(params) or 1) keypair = Keypair( ss58_address=account_address, ss58_format=settings.SUBSTRATE_ADDRESS_TYPE, crypto_type=crypto_type ) result = keypair.verify(data, signature) response = { "jsonrpc": "2.0", "result": {'verified': result}, "id": req.media.get('id') } elif method == 'rpc_methods': response = self.substrate.rpc_request(method, params) # Add additional implemented method response['result']['methods'] = sorted(response['result']['methods'] + self.methods) else: raise NotImplementedError('Method \'{}\' not implemented yet'.format(method)) except (ValueError, NotImplementedError) as e: response = { "error": { "code": -999, "message": str(e) }, "id": req.media.get('id') } except (InvalidScaleTypeValueException, RemainingScaleBytesNotEmptyException) as e: response = { "error": { "code": -998, "message": "Decoding error, given SCALE-value or type registry might be invalid " }, "id": req.media.get('id') } resp.media = response
keypair = Keypair.create_from_mnemonic('box change recall shift tent bus mad cherry aerobic engine ocean few') # keypair = Keypair.create_from_mnemonic('episode together nose spoon dose oil faculty zoo ankle evoke admit walnut') print(keypair.public_key) # 5CFPcUJgYgWryPaV1aYjSbTpbTLu42V32Ytw1L9rfoMAsfGh call = substrate.compose_call( call_module='Staking', call_function='bond', call_params={ 'controller': '5EPCUjPxiHAcNooYipQFWr9NmmXJKpNG5RhcntXwbtUySrgH', 'value': 0.000001, 'payee': {'Account':'5D5YAyW9o9Y8C39niHLNY623QsvuDtqkaWLDDNgpmYph6zgq'}, } ) extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair) try: receipt = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True) print("Extrinsic '{}' sent and included in block '{}'".format(receipt.extrinsic_hash, receipt.block_hash)) except SubstrateRequestException as e: print("Failed to send: {}".format(e)) keypair = Keypair.create_from_mnemonic('box change recall shift tent bus mad cherry aerobic engine ocean few') print(keypair.public_key) print(keypair.ss58_address) keypair = Keypair.create_from_mnemonic('cash quantum travel innocent cotton link seven inquiry dilemma renew hat space') print(keypair.public_key)
## current metadata s.get_runtime_metadata() ## send 100 tokens from Alice -> Bob from substrateinterface import Keypair alice = Keypair.create_from_uri('//Alice') bob = Keypair.create_from_uri('//Bob') call = s.compose_call(call_module='Balances', call_function='transfer', call_params={ 'dest': bob.ss58_address, 'value': 100 * 10**18 }) extrinsic = s.create_signed_extrinsic(call=call, keypair=alice) # tx dry run s.get_payment_info(call=call, keypair=alice) ## check tx metadata from substrateinterface import ExtrinsicReceipt receipt = ExtrinsicReceipt( substrate=s, extrinsic_hash= "0x1856aa746ed0cd0f5b01d4e2a5b68bf5a08a0c66b92aac1b3b3738f4a2d59ef6", block_hash= "0x3cdc5e4e145a25d0361c66669a062695d0e2a511cdd6d4868cfda80e66cf185c") receipt.is_success, receipt.weight, receipt.total_fee_amount ## find validators missing blocks
class Subtensor: """ Handles interactions with the subtensor chain. """ custom_type_registry = { "runtime_id": 2, "types": { "NeuronMetadataOf": { "type": "struct", "type_mapping": [["ip", "u128"], ["port", "u16"], ["ip_type", "u8"], ["uid", "u64"], ["modality", "u8"], ["hotkey", "AccountId"], ["coldkey", "AccountId"]] } } } def __init__(self, config: 'Munch' = None, network: str = None, chain_endpoint: str = None): r""" Initializes a subtensor chain interface. Args: config (:obj:`Munch`, `optional`): metagraph.Metagraph.config() network (default='akira', type=str) The subtensor network flag. The likely choices are: -- akira (testing network) -- kusanagi (main network) If this option is set it overloads subtensor.chain_endpoint with an entry point node from that network. chain_endpoint (default=None, type=str) The subtensor endpoint flag. If set, overrides the --network flag. """ if config == None: config = Subtensor.default_config() config.subtensor.network = network if network != None else config.subtensor.network config.subtensor.chain_endpoint = chain_endpoint if chain_endpoint != None else config.subtensor.chain_endpoint Subtensor.check_config(config) self.config = copy.deepcopy(config) chain_endpoint = "ws://subtensor.rawatech.com:9944" if not chain_endpoint else "ws://" + chain_endpoint # chain_endpoint = "ws://feynman.kusanagi.bittensor.com:9944" if not chain_endpoint else "ws://" + chain_endpoint self.substrate = SubstrateInterface( ss58_format=42, type_registry_preset='substrate-node-template', type_registry=self.custom_type_registry, url=chain_endpoint) @staticmethod def default_config() -> Munch: # Parses and returns a config Munch for this object. parser = argparse.ArgumentParser() Subtensor.add_args(parser) config = bittensor.config.Config.to_config(parser) return config @staticmethod def add_args(parser: argparse.ArgumentParser): try: parser.add_argument( '--subtensor.network', default='kusanagi', type=str, help='''The subtensor network flag. The likely choices are: -- akira (testing network) -- kusanagi (main network) If this option is set it overloads subtensor.chain_endpoint with an entry point node from that network. ''') parser.add_argument( '--subtensor.chain_endpoint', default=None, type=str, help= '''The subtensor endpoint flag. If set, overrides the --network flag. ''') except: pass @staticmethod def check_config(config: Munch): pass def endpoint_for_network(self, blacklist: List[str] = []) -> str: r""" Returns a chain endpoint based on config.subtensor.network. Returns None if there are no available endpoints. Raises: endpoint (str): Websocket endpoint or None if there are none available. """ # Chain endpoint overrides the --network flag. if self.config.subtensor.chain_endpoint != None: if self.config.subtensor.chain_endpoint in blacklist: return None else: return self.config.subtensor.chain_endpoint # Else defaults to networks. # TODO(const): this should probably make a DNS lookup. if self.config.subtensor.network == "akira": akira_available = [ item for item in bittensor.__akira_entrypoints__ if item not in blacklist ] if len(akira_available) == 0: return None return random.choice(akira_available) elif self.config.subtensor.network == "boltzmann": boltzmann_available = [ item for item in bittensor.__boltzmann_entrypoints__ if item not in blacklist ] if len(boltzmann_available) == 0: return None return random.choice(boltzmann_available) elif self.config.subtensor.network == "kusanagi": kusanagi_available = [ item for item in bittensor.__kusanagi_entrypoints__ if item not in blacklist ] if len(kusanagi_available) == 0: return None return random.choice(kusanagi_available) elif self.config.subtensor.network == "local": local_available = [ item for item in bittensor.__local_entrypoints__ if item not in blacklist ] if len(local_available) == 0: return None return random.choice(local_available) else: akira_available = [ item for item in bittensor.__akira_entrypoints__ if item not in blacklist ] if len(akira_available) == 0: return None return random.choice(akira_available) # def is_connected(self) -> bool: # r""" Returns true if the connection state as a boolean. # Raises: # success (bool): # True is the websocket is connected to the chain endpoint. # """ # loop = asyncio.get_event_loop() # loop.set_debug(enabled=True) # return loop.run_until_complete(self.async_is_connected()) # async def async_is_connected(self) -> bool: # r""" Returns the connection state as a boolean. # Raises: # success (bool): # True is the websocket is connected to the chain endpoint. # """ # return self.substrate.async_is_connected() # def check_connection(self) -> bool: # r""" Checks if substrate_old websocket backend is connected, connects if it is not. # """ # loop = asyncio.get_event_loop() # loop.set_debug(enabled=True) # return loop.run_until_complete(self.async_check_connection()) # async def async_check_connection(self) -> bool: # r""" Checks if substrate_old websocket backend is connected, connects if it is not. # """ # if not self.async_is_connected(): # return self.async_connect() # return True # def connect( self, timeout: int = 10, failure = True ) -> bool: # r""" Attempts to connect the substrate_old interface backend. # If the connection fails, attemps another endpoint until a timeout. # Args: # timeout (int): # Time to wait before subscription times out. # failure (bool): # This connection attempt raises an error an a failed attempt. # Returns: # success (bool): # True on success. # """ # loop = asyncio.get_event_loop() # loop.set_debug(enabled=True) # return loop.run_until_complete(self.async_connect(timeout, failure)) # async def async_connect( self, timeout: int = 10, failure = True ) -> bool: # r""" Attempts to connect the substrate_old interface backend. # If the connection fails, attemps another endpoint until a timeout. # Args: # timeout (int): # Time to wait before subscription times out. # failure (bool): # This connection attempt raises an error an a failed attempt. # Returns: # success (bool): # True on success. # """ # start_time = time.time() # attempted_endpoints = [] # while True: # def connection_error_message(): # print(''' # Check that your internet connection is working and the chain endpoints are available: <cyan>{}</cyan> # The subtensor.network should likely be one of the following choices: # -- local - (your locally running node) # -- akira - (testnet) # -- kusanagi - (mainnet) # Or you may set the endpoint manually using the --subtensor.chain_endpoint flag # To run a local node (See: docs/running_a_validator.md) \n # '''.format( attempted_endpoints) ) # # # ---- Get next endpoint ---- # ws_chain_endpoint = self.endpoint_for_network( blacklist = attempted_endpoints ) # if ws_chain_endpoint == None: # logger.error("No more endpoints available for subtensor.network: <cyan>{}</cyan>, attempted: <cyan>{}</cyan>".format(self.config.subtensor.network, attempted_endpoints)) # connection_error_message() # if failure: # logger.critical('Unable to connect to network:<cyan>{}</cyan>.\nMake sure your internet connection is stable and the network is properly set.'.format(self.config.subtensor.network)) # else: # return False # attempted_endpoints.append(ws_chain_endpoint) # # # --- Attempt connection ---- # if self.substrate.async_connect( ws_chain_endpoint, timeout = 5 ): # logger.success("Connected to network:<cyan>{}</cyan> at endpoint:<cyan>{}</cyan>".format(self.config.subtensor.network, ws_chain_endpoint)) # return True # # # ---- Timeout ---- # elif (time.time() - start_time) > timeout: # logger.error( "Error while connecting to network:<cyan>{}</cyan> at endpoint: <cyan>{}</cyan>".format(self.config.subtensor.network, ws_chain_endpoint)) # connection_error_message() # if failure: # raise RuntimeError('Unable to connect to network:<cyan>{}</cyan>.\nMake sure your internet connection is stable and the network is properly set.'.format(self.config.subtensor.network)) # else: # return False # async def _submit_and_check_extrinsic( # self, # extrinsic, # wait_for_inclusion:bool = False, # wait_for_finalization: bool = False, # timeout: int = bittensor.__blocktime__ * 3 # ) -> bool: # r""" Makes an extrinsic call to the chain, returns true if the extrinsic send was a success. # If wait_for_inclusion or wait_for_finalization are true, the call will return true iff the # extrinsic enters or finalizes in a block. # Args: # extrinsic (substrate_old extrinsic): # Extrinsic to send to the chain. # wait_for_inclusion (bool): # If set, waits for the extrinsic to enter a block before returning true, # or returns false if the extrinsic fails to enter the block within the timeout. # wait_for_finalization (bool): # If set, waits for the extrinsic to be finalized on the chain before returning true, # or returns false if the extrinsic fails to be finalized within the timeout. # timeout (int): # Time that this call waits for either finalization of inclusion. # Returns: # success (bool): # flag is true if extrinsic was finalized or uncluded in the block. # If we did not wait for finalization / inclusion, the response is true. # """ # # Send extrinsic # try: # response = self.substrate.submit_extrinsic( # extrinsic, # wait_for_inclusion = wait_for_inclusion, # wait_for_finalization = wait_for_finalization, # timeout = timeout # ) # except SubstrateRequestException as e: # logger.error('Extrinsic exception with error {}', e) # return False # except Exception as e: # logger.error('Error submitting extrinsic with error {}', e) # return False # # # Check timeout. # if response == None: # logger.error('Error in extrinsic: No response within timeout') # return False # # # Check result. # if not wait_for_inclusion and not wait_for_finalization: # return True # else: # if 'error' in response: # logger.error('Error in extrinsic: {}', response['error']) # elif 'finalized' in response and response['finalized'] == True: # return True # elif 'inBlock' in response and response['inBlock'] == True: # return True # else: # return False def is_subscribed(self, wallet: 'bittensor.wallet.Wallet', ip: str, port: int, modality: int) -> bool: r""" Returns true if the bittensor endpoint is already subscribed with the wallet and metadata. Args: wallet (bittensor.wallet.Wallet): bittensor wallet object. ip (str): endpoint host port i.e. 192.122.31.4 port (int): endpoint port number i.e. 9221 modality (int): int encoded endpoint modality i.e 0 for TEXT coldkeypub (str): string encoded coldekey pub. """ uid = self.get_uid_for_pubkey(wallet.hotkey.public_key) if uid is None: return False neuron = self.get_neuron_for_uid(uid) if neuron['ip'] == net.ip_to_int(ip) and neuron['port'] == port: return True else: return False def subscribe( self, wallet: 'bittensor.wallet.Wallet', ip: str, port: int, modality: int, wait_for_inclusion: bool = False, wait_for_finalization=True, timeout: int = 3 * bittensor.__blocktime__, ) -> bool: r""" Subscribes an bittensor endpoint to the substensor chain. Args: wallet (bittensor.wallet.Wallet): bittensor wallet object. ip (str): endpoint host port i.e. 192.122.31.4 port (int): endpoint port number i.e. 9221 modality (int): int encoded endpoint modality i.e 0 for TEXT wait_for_inclusion (bool): if set, waits for the extrinsic to enter a block before returning true, or returns false if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): if set, waits for the extrinsic to be finalized on the chain before returning true, or returns false if the extrinsic fails to be finalized within the timeout. timeout (int): time that this call waits for either finalization of inclusion. Returns: success (bool): flag is true if extrinsic was finalized or uncluded in the block. If we did not wait for finalization / inclusion, the response is true. """ if self.is_subscribed(wallet, ip, port, modality): logger.success( "Already subscribed with:\n<cyan>[\n ip: {},\n port: {},\n modality: {},\n hotkey: {},\n coldkey: {}\n]</cyan>" .format(ip, port, modality, wallet.hotkey.public_key, wallet.coldkeypub)) return True ip_as_int = net.ip_to_int(ip) params = { 'ip': ip_as_int, 'port': port, 'ip_type': 4, 'modality': modality, 'coldkey': wallet.coldkeypub, } call = self.substrate.compose_call(call_module='SubtensorModule', call_function='subscribe', call_params=params) # TODO (const): hotkey should be an argument here not assumed. Either that or the coldkey pub should also be assumed. extrinsic = self.substrate.create_signed_extrinsic( call=call, keypair=wallet.hotkey) result = self.substrate.submit_extrinsic( extrinsic, wait_for_inclusion, wait_for_finalization).is_success if result: logger.success( "Successfully subscribed with:\n<cyan>[\n ip: {},\n port: {},\n modality: {},\n hotkey: {},\n coldkey: {}\n]</cyan>" .format(ip, port, modality, wallet.hotkey.public_key, wallet.coldkeypub)) else: logger.error("Failed to subscribe") return result def add_stake( self, wallet: 'bittensor.wallet.Wallet', amount: Balance, hotkey_id: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, timeout: int = 3 * bittensor.__blocktime__, ) -> bool: r""" Adds the specified amount of stake to passed hotkey uid. Args: wallet (bittensor.wallet.Wallet): bittensor wallet object. amount (bittensor.utils.balance.Balance): amount to stake as bittensor balance hotkey_id (int): uid of hotkey to stake into. wait_for_inclusion (bool): if set, waits for the extrinsic to enter a block before returning true, or returns false if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): if set, waits for the extrinsic to be finalized on the chain before returning true, or returns false if the extrinsic fails to be finalized within the timeout. timeout (int): time that this call waits for either finalization of inclusion. Returns: success (bool): flag is true if extrinsic was finalized or uncluded in the block. If we did not wait for finalization / inclusion, the response is true. """ call = self.substrate.compose_call(call_module='SubtensorModule', call_function='add_stake', call_params={ 'hotkey': hotkey_id, 'ammount_staked': amount.rao }) extrinsic = self.substrate.create_signed_extrinsic( call=call, keypair=wallet.coldkey) return self.substrate.submit_extrinsic( extrinsic, wait_for_inclusion, wait_for_finalization).is_success def transfer( self, wallet: 'bittensor.wallet.Wallet', dest: str, amount: Balance, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, timeout: int = 3 * bittensor.__blocktime__, ) -> bool: r""" Transfers funds from this wallet to the destination public key address Args: wallet (bittensor.wallet.Wallet): bittensor wallet object. dest (str): destination public key address of reciever. amount (bittensor.utils.balance.Balance): amount to stake as bittensor balance wait_for_inclusion (bool): if set, waits for the extrinsic to enter a block before returning true, or returns false if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): if set, waits for the extrinsic to be finalized on the chain before returning true, or returns false if the extrinsic fails to be finalized within the timeout. timeout (int): time that this call waits for either finalization of inclusion. Returns: success (bool): flag is true if extrinsic was finalized or uncluded in the block. If we did not wait for finalization / inclusion, the response is true. """ call = self.substrate.compose_call(call_module='Balances', call_function='transfer', call_params={ 'dest': dest, 'value': amount.rao }) extrinsic = self.substrate.create_signed_extrinsic( call=call, keypair=wallet.coldkey) return self.substrate.submit_extrinsic( extrinsic, wait_for_inclusion, wait_for_finalization).is_success def unstake( self, wallet: 'bittensor.wallet.Wallet', amount: Balance, hotkey_id: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, timeout: int = 3 * bittensor.__blocktime__, ) -> bool: r""" Removes stake into the wallet coldkey from the specified hotkey uid. Args: wallet (bittensor.wallet.Wallet): bittensor wallet object. amount (bittensor.utils.balance.Balance): amount to stake as bittensor balance hotkey_id (int): uid of hotkey to unstake from. wait_for_inclusion (bool): if set, waits for the extrinsic to enter a block before returning true, or returns false if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): if set, waits for the extrinsic to be finalized on the chain before returning true, or returns false if the extrinsic fails to be finalized within the timeout. timeout (int): time that this call waits for either finalization of inclusion. Returns: success (bool): flag is true if extrinsic was finalized or uncluded in the block. If we did not wait for finalization / inclusion, the response is true. """ call = self.substrate.compose_call(call_module='SubtensorModule', call_function='remove_stake', call_params={ 'ammount_unstaked': amount.rao, 'hotkey': hotkey_id }) extrinsic = self.substrate.create_signed_extrinsic( call=call, keypair=wallet.coldkey) return self.substrate.submit_extrinsic( extrinsic, wait_for_inclusion, wait_for_finalization).is_success def set_weights(self, wallet: 'bittensor.wallet.Wallet', destinations, values, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, timeout: int = 3 * bittensor.__blocktime__) -> bool: r""" Sets the given weights and values on chain for wallet hotkey account. Args: wallet (bittensor.wallet.Wallet): bittensor wallet object. destinations (List[int]): uint64 uids of destination neurons. values (List[int]): u32 max encoded floating point weights. wait_for_inclusion (bool): if set, waits for the extrinsic to enter a block before returning true, or returns false if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): if set, waits for the extrinsic to be finalized on the chain before returning true, or returns false if the extrinsic fails to be finalized within the timeout. timeout (int): time that this call waits for either finalization of inclusion. Returns: success (bool): flag is true if extrinsic was finalized or uncluded in the block. If we did not wait for finalization / inclusion, the response is true. """ call = self.substrate.compose_call(call_module='SubtensorModule', call_function='set_weights', call_params={ 'dests': destinations, 'weights': values }) extrinsic = self.substrate.create_signed_extrinsic( call=call, keypair=wallet.hotkey) return self.substrate.submit_extrinsic( extrinsic, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization).is_success def get_balance(self, address: str) -> Balance: r""" Returns the token balance for the passed ss58_address address Args: address (Substrate address format, default = 42): ss58 chain address. Return: balance (bittensor.utils.balance.Balance): account balance """ result = self.substrate.get_runtime_state(module='System', storage_function='Account', params=[address], block_hash=None) balance_info = result.get('result') if not balance_info: return Balance(0) balance = balance_info['data']['free'] return Balance(balance) def get_current_block(self) -> int: r""" Returns the current block number on the chain. Returns: block_number (int): Current chain blocknumber. """ return self.substrate.get_block_number(None) def get_block_hash(self, block_nr): return self.substrate.get_block_hash(block_nr) def get_active(self) -> List[Tuple[str, int]]: r""" Returns a list of (public key, uid) pairs one for each active peer on chain. Returns: active (List[Tuple[str, int]]): List of active peers. """ result = self.substrate.iterate_map( module='SubtensorModule', storage_function='Active', ) return result def get_stake(self, hash=None) -> List[Tuple[int, int]]: r""" Returns a list of (uid, stake) pairs one for each active peer on chain. Returns: stake (List[Tuple[int, int]]): List of stake values. """ result = self.substrate.iterate_map(module='SubtensorModule', storage_function='Stake', block_hash=hash) return result def get_last_emit(self, hash=None) -> List[Tuple[int, int]]: r""" Returns a list of (uid, last emit) pairs for each active peer on chain. Returns: last_emit (List[Tuple[int, int]]): List of last emit values. """ result = self.substrate.iterate_map(module='SubtensorModule', storage_function='LastEmit', block_hash=hash) return result def get_weight_vals(self, hash=None) -> List[Tuple[int, List[int]]]: r""" Returns a list of (uid, weight vals) pairs for each active peer on chain. Returns: weight_vals (List[Tuple[int, List[int]]]): List of weight val pairs. """ result = self.substrate.iterate_map(module='SubtensorModule', storage_function='WeightVals', block_hash=hash) return result def get_weight_uids(self, hash=None) -> List[Tuple[int, int]]: r""" Returns a list of (uid, weight uids) pairs for each active peer on chain. Returns: weight_uids (List[Tuple[int, List[int]]]): List of weight uid pairs """ result = self.substrate.iterate_map(module='SubtensorModule', storage_function='WeightUids', block_hash=hash) return result def neurons(self, hash=None) -> List[Tuple[int, dict]]: r""" Returns a list of neuron from the chain. Returns: neuron (List[Tuple[int, dict]]): List of neuron objects. """ neurons = self.substrate.iterate_map(module='SubtensorModule', storage_function='Neurons', block_hash=hash) return neurons # def __convert_neuron(self, data) -> dict: # # return dict({ # 'coldkey': data['coldkey'], # 'hotkey': data['hotkey'], # 'ip_type': int(data['ip_type']), # 'ip': int(data['ip']), # 'port': int(data['port']), # 'modality': int(data['modality']), # 'uid': int(data['uid']) # }) def get_uid_for_pubkey(self, pubkey=str) -> Optional[int]: """ Returns the uid of the peer given passed public key string. Args: pubkey (str): String encoded public key. Returns: uid (int): uid of peer with hotkey equal to passed public key. """ result = self.substrate.get_runtime_state(module='SubtensorModule', storage_function='Active', params=[pubkey]) if result['result'] is None: return None return int(result['result']) def get_neuron_for_uid(self, uid) -> dict: """ Returns the neuron metadata of the peer with the passed uid. Args: uid (int): Uid to query for metadata. Returns: metadata (Dict): Dict in list form containing metadata of associated uid. """ result = self.substrate.get_runtime_state(module='SubtensorModule', storage_function='Neurons', params=[uid]) return result['result'] def get_stake_for_uid(self, uid) -> Balance: r""" Returns the staked token amount of the peer with the passed uid. Args: uid (int): Uid to query for metadata. Returns: stake (int): Amount of staked token. """ stake = self.substrate.get_runtime_state(module='SubtensorModule', storage_function='Stake', params=[uid]) result = stake['result'] if not result: return Balance(0) return Balance(result) def weight_uids_for_uid(self, uid) -> List[int]: r""" Returns the weight uids of the peer with the passed uid. Args: uid (int): Uid to query for metadata. Returns: weight_uids (List[int]): Weight uids for passed uid. """ result = self.substrate.get_runtime_state( module='SubtensorModule', storage_function='WeightUids', params=[uid]) return result['result'] def weight_vals_for_uid(self, uid) -> List[int]: r""" Returns the weight vals of the peer with the passed uid. Args: uid (int): Uid to query for metadata. Returns: weight_vals (List[int]): Weight vals for passed uid. """ result = self.substrate.get_runtime_state( module='SubtensorModule', storage_function='WeightVals', params=[uid]) return result['result'] def get_last_emit_data_for_uid(self, uid) -> int: r""" Returns the last emit of the peer with the passed uid. Args: uid (int): Uid to query for metadata. Returns: last_emit (int): Last emit block numebr """ result = self.substrate.get_runtime_state(module='SubtensorModule', storage_function='LastEmit', params=[uid]) return result['result']
call = substrate.compose_call( call_module='Balances', call_function='transfer', call_params={ 'dest': '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty', 'value': 1 * 10**15 }) # Get payment info payment_info = substrate.get_payment_info(call=call, keypair=keypair) print("Payment info: ", payment_info) extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair, era={'period': 64}) try: receipt = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True) print('Extrinsic "{}" included in block "{}"'.format( receipt.extrinsic_hash, receipt.block_hash)) if receipt.is_success: print('✅ Success, triggered events:') for event in receipt.triggered_events: print(f'* {event.value}') else: print('⚠️ Extrinsic Failed: ', receipt.error_message)
def cmd_pay(args, config): substrate = SubstrateInterface(url=get_config(args, config, 'rpcurl'), type_registry_preset=get_config( args, config, 'network')) active_era = substrate.query(module='Staking', storage_function='ActiveEra') active_era = active_era.value['index'] depth = get_config(args, config, 'deptheras') depth = int(depth) if depth is not None else 84 minEras = get_config(args, config, 'mineras') minEras = int(minEras) if minEras is not None else 5 start = active_era - depth end = active_era eras_payment_info = get_eras_payment_info_filtered( substrate, start, end, accounts=get_included_accounts(args, config), only_unclaimed=True) eras_payment_info = OrderedDict( sorted(eras_payment_info.items(), reverse=True)) if len(eras_payment_info.keys()) == 0: print(f"There are no rewards to claim in the last {depth} era(s)") return if len(eras_payment_info) < int(get_config(args, config, 'mineras')): max_age_unclaimed = int(get_config(args, config, 'maxageunclaimed')) if max_age_unclaimed is None: max_age_unclaimed = 84 if not old_unclaimed_exist(eras_payment_info, max_age_unclaimed, active_era): print( f"There are rewards to claim on {len(eras_payment_info.keys())} era(s), " + f"but those are not enough to reach the minimum threshold ({minEras})" ) return keypair = get_keypair(args, config) payout_calls = [] for era in eras_payment_info: for accountId in eras_payment_info[era]: payout_calls.append({ 'call_module': 'Staking', 'call_function': 'payout_stakers', 'call_args': { 'validator_stash': accountId, 'era': era, } }) call = substrate.compose_call(call_module='Utility', call_function='batch', call_params={'calls': payout_calls}) payment_info = substrate.get_payment_info(call=call, keypair=keypair) account_info = get_account_info(substrate, get_config(args, config, 'signingaccount')) expected_fees = payment_info['partialFee'] free_balance = account_info['data']['free'] existential_deposit = get_existential_deposit(substrate) if (free_balance - expected_fees) < existential_deposit: print( f"Account with not enough funds. Needed {existential_deposit + expected_fees}, but got {free_balance}" ) return signature_payload = substrate.generate_signature_payload( call=call, nonce=account_info['nonce']) signature = keypair.sign(signature_payload) extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair, nonce=account_info['nonce'], signature=signature) print("Submitting batch extrinsic to claim " + f"{len(payout_calls)} rewards (in {len(eras_payment_info)} eras)") extrinsic_receipt = substrate.submit_extrinsic(extrinsic=extrinsic, wait_for_inclusion=True) tweet_text = Twitter.generate_tweet_text(eras_payment_info) Twitter(config).update_status(tweet_text) fees = extrinsic_receipt.total_fee_amount print(f"\t Extrinsic hash: {extrinsic_receipt.extrinsic_hash}") print(f"\t Block hash: {extrinsic_receipt.block_hash}") print(f"\t Fee: {format_balance_to_symbol(substrate, fees)} ({fees})") print(f"\t Status: {'ok' if extrinsic_receipt.is_success else 'error'}") if not extrinsic_receipt.is_success: print( f"\t Error message: {extrinsic_receipt.error_message.get('docs')}")
class Kuka: def __init__(self): rospy.init_node('listener', anonymous=False) rospack = rospkg.RosPack() rospack.list() self.path = rospack.get_path('kuka_controller') with open(f"{self.path}/config/config", "r") as f: config = json.load(f) self.client = ipfshttpclient.connect() self.substrate = SubstrateInterface( url=config["node"], ss58_format=32, type_registry_preset="substrate-node-template", type_registry={ "types": { "Record": "Vec<u8>", "Parameter": "Bool", "LaunchParameter": "Bool", "<T as frame_system::Config>::AccountId": "AccountId", "RingBufferItem": { "type": "struct", "type_mapping": [ ["timestamp", "Compact<u64>"], ["payload", "Vec<u8>"], ], }, "RingBufferIndex": { "type": "struct", "type_mapping": [ ["start", "Compact<u64>"], ["end", "Compact<u64>"], ], } } }, ) mnemonic = config["kuka_mnemonic"] self.keypair = Keypair.create_from_mnemonic(mnemonic, ss58_format=32) # Call service move_arm def move_arm_client(self, desired_xyz, duration): rospy.wait_for_service('move_arm') try: move_arm = rospy.ServiceProxy('move_arm', MoveArm) resp = move_arm(desired_xyz, duration) return resp except rospy.ServiceException as e: rospy.loginfo("Service call failed: %s" % e) # Write data to a file def listener(self, data): if self.write: times_prev = self.times self.times = int(time.time()) if self.times != times_prev: #print('write') self.logs.write('\n') self.logs.write(str(data)) def write_datalog(self, data): call = self.substrate.compose_call(call_module="Datalog", call_function="record", call_params={'record': data}) extrinsic = self.substrate.create_signed_extrinsic( call=call, keypair=self.keypair) receipt = self.substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True) rospy.loginfo( f"Datalog created with extrinsic hash: {receipt.extrinsic_hash}") # Print circle def circle(self): rospy.loginfo("Work paid. Starting work...") t = 0 self.logs = open(f'{self.path}/data.txt', 'w') self.move_arm_client( [Float64(0.3), Float64(0.3), Float64(0.6)], Float64(2.0)) self.times = 0 self.write = True rospy.Subscriber('/manipulator/joint_states', JointState, self.listener) while t <= math.pi: x = 0.3 * math.cos(t) z = 0.3 * math.sin(t) + 0.6 t += 0.2 #print(x, z) self.move_arm_client( [Float64(x), Float64(0.3), Float64(z)], Float64(0.05)) self.write = False rospy.loginfo("Work done") self.logs.close() res = self.client.add(f'{self.path}/data.txt') rospy.loginfo(f"Data pinned to IPFS with hash {res['Hash']}") self.write_datalog(res['Hash']) rospy.loginfo(f"Wait for payment") def subscription_handler(self, obj, update_nr, subscription_id): ch = self.substrate.get_chain_head() chain_events = self.substrate.get_events(ch) for ce in chain_events: # if ce.value["event_id"] == "NewLaunch": # print(ce.params) if ce.value["event_id"] == "NewLaunch" and ce.params[1]["value"] == self.keypair.ss58_address \ and ce.params[2]["value"] is True: # yes/no print(f"\"ON\" launch command from employer.") self.circle() def spin(self): rospy.loginfo(f"Wait for payment") self.substrate.subscribe_block_headers(self.subscription_handler)
def main(path, wait_for_inclusion=False, nonce=0): with open(path) as json_file: test_adresses = json.load(json_file) custom_type_registry = load_type_registry_file("types.json") print(custom_type_registry) substrate = SubstrateInterface(url="ws://127.0.0.1:9944/", address_type=32, type_registry=TYPES, type_registry_preset='robonomics') # substrate = SubstrateInterface( # url="ws://127.0.0.1:9944/", # address_type=32, # type_registry=TYPES, # ) # Set block_hash to None for chaintip # block_hash = None # Retrieve extrinsics in block # result = substrate.get_runtime_block(block_hash=block_hash) # for extrinsic in result['block']['extrinsics']: # if 'account_id' in extrinsic: # signed_by_address = ss58_encode(address=extrinsic['account_id'], address_type=2) # else: # signed_by_address = None # print('\nModule: {}\nCall: {}\nSigned by: {}'.format( # extrinsic['call_module'], # extrinsic['call_function'], # signed_by_address # )) # for param in extrinsic['params']: # if param['type'] == 'Address': # param['value'] = ss58_encode(address=param['value'], address_type=2) # if param['type'] == 'Compact<Balance>': # param['value'] = '{} DOT'.format(param['value'] / 10**12) # print("Param '{}': {}".format(param['name'], param['value'])) # Storage call examples # print("\n\nCurrent Account info: {} DOT".format( # substrate.get_runtime_state( # module='System', # storage_function='Account', # params=['4GmqwyTi37bbwgWHiamoi7uCnebxuhj9Mmo2rCcjPgjF4Nag'] # ).get('result') # )) # print("Balance @ {}: {} DOT".format( # block_hash, # substrate.get_runtime_state( # module='Balances', # storage_function='FreeBalance', # params=['4GmqwyTi37bbwgWHiamoi7uCnebxuhj9Mmo2rCcjPgjF4Nag'], # block_hash=block_hash # ).get('result') # )) nonce = int(nonce) while True: for indx, row in enumerate(test_adresses['keys']): for address, mnemonic in row.items(): # Create, sign and submit extrinsic example # mnemonic = Keypair.generate_mnemonic() # mnemonic = "pave small hub weapon jewel dream net canvas mirror nurse delay they" keypair = Keypair.create_from_mnemonic(mnemonic, 32) # nonce = substrate.get_account_nonce(address) # nonce = substrate.get_account_nonce(address) print("Nonce: ", nonce) # keypair = Keypair( # ss58_address='4GQJvwgJwZ1U8j776kmawm5wccE9ZSRFCuH1GnxyCEuGWqL4', # public_key='0xba3f1ff4f7894070afc1dc88551f47c3d76e4b9a2847fbd045c571b998623c62', # address_type=32 # ) # keypair = Keypair.create_from_private_key( # '0x24dcd65948fe301e27eab1456df0c60ea6884f7eef9eb4e55b329a1a785eb43f', # public_key='0xba3f1ff4f7894070afc1dc88551f47c3d76e4b9a2847fbd045c571b998623c62', # ss58_address='4GQJvwgJwZ1U8j776kmawm5wccE9ZSRFCuH1GnxyCEuGWqL4', # address_type=32 # ) print("Created address: {}".format(keypair.ss58_address)) nonce = substrate.get_account_nonce(keypair.ss58_address) print(nonce) call = substrate.compose_call( 'Datalog', 'record', call_params={ 'record': '0x516d6178673336614b68345a41547342796f427133384b454b5a6743674366657934344b68746452426477764d41', }) # call = substrate.compose_call( # call_module='Launch', # call_function='launch', # call_params={ # # 'date': '0x01', # 'Parameter': False, # } # ) # call = substrate.compose_call( # call_module='Balances', # call_function='transfer', # call_params={ # 'dest': '4Ca9DE2ghDH4jQofEpRAhnQpdFejgVi3zVvkAo2QwsXFJvWA', # 'value': 5 * 10**3 # } # ) print('create extrinsic') extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair, nonce=nonce) # extrinsic = substrate.create_unsigned_extrinsic(call=call) try: print('try to send') result = substrate.submit_extrinsic( extrinsic, wait_for_inclusion=wait_for_inclusion) print('Extrinsic "{}" included in block "{}"'.format( result['extrinsic_hash'], result.get('block_hash'))) print(result) except SubstrateRequestException as e: print("Failed to send: {}".format(e)) nonce += 1