def test_decode_reserved_ss58_formats(self): with self.assertRaises(ValueError) as cm: ss58_decode('MGP3U1wqNhFofseKXU7B6FcZuLbvQvJFyin1EvQM65mBcNsY8') self.assertEqual('46 is a reserved SS58 format', str(cm.exception)) with self.assertRaises(ValueError) as cm: ss58_decode('MhvaLBvSb5jhjrftHLQPAvJegnpXgyDTE1ZprRNzAcfQSRdbL') self.assertEqual('47 is a reserved SS58 format', str(cm.exception))
def _get_address_info(self, address: str) -> dict: """ Returns information associated with provided address """ # Storage key: # xxHash128(System) + xxHash128(Account) storage_key = ( "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9" ) account_id = ss58_decode(address, valid_ss58_format=self.address_type) hashed_address = f"{blake2b(bytes.fromhex(account_id), digest_size=16).digest().hex()}{account_id}" storage_hash = storage_key + hashed_address result = self.network.node_rpc_call("state_getStorageAt", [storage_hash, None])["result"] if not result: return { "nonce": 0, "refcount": 0, "data": { "free": 0, "reserved": 0, "miscFrozen": 0, "feeFrozen": 0 }, } return_decoder = ScaleDecoder.get_decoder_class( "AccountInfo<Index, AccountData>", ScaleBytes(result), metadata=self.metadata, runtime_config=self.runtime_config, ) return return_decoder.decode()
def get_prefix(escrow_address: str, address_type: int = 2) -> str: """ Returns prefix containing the account ID of the address provided """ module_prefix = xx128("Multisig") + xx128("Multisigs") account_id = ss58_decode(escrow_address, valid_ss58_format=address_type) storage_key = bytearray( xxhash.xxh64(bytes.fromhex(account_id), seed=0).digest()) storage_key.reverse() return f"{module_prefix}{storage_key.hex()}{account_id}"
def test_multiaddress_ss58_address_as_str(self): obj = ScaleDecoder.get_decoder_class('Multiaddress') ss58_address = "CdVuGwX71W4oRbXHsLuLQxNPns23rnSSiZwZPN4etWf6XYo" public_key = ss58_decode(ss58_address) data = obj.encode(ss58_address) decode_obj = ScaleDecoder.get_decoder_class('Multiaddress', data=data) self.assertEqual(decode_obj.decode(), f'0x{public_key}')
def test_multiaddress_ss58_address_as_str(self): obj = RuntimeConfiguration().create_scale_object('Multiaddress') ss58_address = "CdVuGwX71W4oRbXHsLuLQxNPns23rnSSiZwZPN4etWf6XYo" public_key = ss58_decode(ss58_address) data = obj.encode(ss58_address) decode_obj = RuntimeConfiguration().create_scale_object('MultiAddress', data=data) self.assertEqual(decode_obj.decode(), f'0x{public_key}')
def get_mempool_nonce(self, address: str) -> int: """ Returns the nonce of any pending extrinsics for a given address """ account_id = ss58_decode(address) pending_extrinsics = self.get_pending_extrinsics() nonce = -1 for idx, extrinsic in enumerate(pending_extrinsics): if extrinsic.get("account_id") == account_id: nonce = max(extrinsic.get("nonce", nonce), nonce) return nonce
def order_addresses(addresses: list, address_type: int = 0): bytearray_public_keys = [] ordered_addresses = [] # Convert address to public keys and then to byte array for address in addresses: public_key = ss58_decode(address, valid_ss58_format=address_type) public_key_bytearray = bytearray() public_key_bytearray.extend(map(ord, public_key)) bytearray_public_keys.append(public_key_bytearray) sorted_bytearray = sorted(bytearray_public_keys) # Convert back to addresses for byte_array in sorted_bytearray: ordered_addresses.append( ss58_encode(byte_array.decode(), ss58_format=address_type)) return ordered_addresses
def test_account_id_runtime_config(self): ss58_address = "CdVuGwX71W4oRbXHsLuLQxNPns23rnSSiZwZPN4etWf6XYo" public_key = '0x' + ss58_decode(ss58_address) runtime_config = RuntimeConfigurationObject(ss58_format=2) runtime_config.update_type_registry(load_type_registry_preset("default")) # Encode obj = RuntimeConfiguration().create_scale_object('AccountId', runtime_config=runtime_config) data = obj.encode(ss58_address) # Decode decode_obj = RuntimeConfiguration().create_scale_object('AccountId', data=data, runtime_config=runtime_config) decode_obj.decode() self.assertEqual(decode_obj.value, ss58_address) self.assertEqual(decode_obj.ss58_address, ss58_address) self.assertEqual(decode_obj.public_key, public_key)
def process_encode(self, value): if type(value) == str and value[0:2] != '0x': # Assume SS58 encoding address if len(value) >= 46: from scalecodec.utils.ss58 import ss58_decode value = '0x{}'.format(ss58_decode(value)) else: from scalecodec.utils.ss58 import ss58_decode_account_index index_obj = GenericAccountIndex() value = index_obj.encode(ss58_decode_account_index(value)) if type(value) == str and value[0:2] == '0x' and len(value) == 66: # value is AccountId return ScaleBytes('0x{}'.format(value[2:])) elif type(value) == int: # value is AccountIndex raise NotImplementedError('Encoding of AccountIndex Adresses not supported yet') else: raise ValueError('Value is in unsupported format, expected 32 bytes hex-string for AccountIds or int for AccountIndex')
def create_from_account_list(cls, accounts, threshold): from scalecodec.utils.ss58 import ss58_decode account_ids = [] for account in accounts: if account[0:2] != '0x': account = '0x{}'.format(ss58_decode(account)) account_ids.append(account) account_list_cls = cls.get_decoder_class('Vec<AccountId>') account_list_data = account_list_cls.encode(sorted(account_ids)) threshold_data = cls.get_decoder_class("u16").encode(threshold) multi_account_id = "0x{}".format(blake2b( b"modlpy/utilisuba" + bytes(account_list_data.data) + bytes(threshold_data.data), digest_size=32 ).digest().hex()) multi_account_obj = cls() multi_account_obj.encode(multi_account_id) return multi_account_obj
def test_decode_invalid_length(self): with self.assertRaises(ValueError) as cm: ss58_decode( '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQubsdhfjksdhfkj') self.assertEqual('Invalid address length', str(cm.exception))
def test_decode_invalid_length(self): with self.assertRaises(ValueError): ss58_decode( '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQubsdhfjksdhfkj')
def test_invalid_ss58_format_check(self): with self.assertRaises(ValueError) as cm: ss58_decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua', valid_ss58_format=2) self.assertEqual('Invalid SS58 format', str(cm.exception))
def test_decode_invalid_checksum(self): with self.assertRaises(ValueError) as cm: ss58_decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQub') self.assertEqual('Invalid checksum', str(cm.exception))
def test_decode_empty_string(self): with self.assertRaises(ValueError) as cm: ss58_decode('') self.assertEqual('Empty address provided', str(cm.exception))
def test_decode_public_key(self): self.assertEqual( '0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077', ss58_decode( '0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077' ))
def test_decode_subkey_generated_pairs(self): for subkey_pair in self.subkey_pairs: self.assertEqual( subkey_pair['public_key'], '0x' + ss58_decode(address=subkey_pair['address'], valid_ss58_format=subkey_pair['ss58_format']))
def test_decode_invalid_checksum(self): with self.assertRaises(ValueError): ss58_decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQub')
def process_encode(self, value): if value[0:2] != '0x': from scalecodec.utils.ss58 import ss58_decode self.ss58_address = value value = '0x{}'.format(ss58_decode(value)) return super().process_encode(value)
def test_encode_with_2_byte_prefix(self): public_key = ss58_decode( '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua') self.assertEqual('yGHU8YKprxHbHdEv7oUK4rzMZXtsdhcXVG2CAMyC9WhzhjH2k', ss58_encode(public_key, ss58_format=255))
def test_invalid_ss58_format_check(self): with self.assertRaises(ValueError): ss58_decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua', valid_ss58_format=2)