def populate(message: Message, signatures: List[bytes]) -> Transaction: """Populate Transaction object from message and signatures. Example: >>> raw_message = bytes.fromhex( ... '0200030500000000000000000000000000000000000000000000' ... '0000000000000000000100000000000000000000000000000000' ... '0000000000000000000000000000000200000000000000000000' ... '0000000000000000000000000000000000000000000300000000' ... '0000000000000000000000000000000000000000000000000000' ... '0004000000000000000000000000000000000000000000000000' ... '0000000000000005c49ae77603782054f17a9decea43b444eba0' ... 'edb12c6f1d31c6e0e4a84bf052eb010403010203050909090909' ... ) >>> from based58 import b58encode >>> from solana.message import Message >>> msg = Message.deserialize(raw_message) >>> signatures = [b58encode(bytes([1] * SIG_LENGTH)), b58encode(bytes([2] * SIG_LENGTH))] >>> type(Transaction.populate(msg, signatures)) <class 'solana.transaction.Transaction'> Returns: The populated transaction. """ transaction = Transaction(recent_blockhash=message.recent_blockhash) for idx, sig in enumerate(signatures): signature = None if sig == b58encode( Transaction.__DEFAULT_SIG) else b58decode(sig) transaction.signatures.append( SigPubkeyPair(pubkey=message.account_keys[idx], signature=signature)) for instr in message.instructions: account_metas: List[AccountMeta] = [] for acc_idx in instr.accounts: pubkey = message.account_keys[acc_idx] is_signer = any((pubkey == sigkeypair.pubkey for sigkeypair in transaction.signatures)) account_metas.append( AccountMeta( pubkey=pubkey, is_signer=is_signer, is_writable=message.is_account_writable(acc_idx))) program_id = message.account_keys[instr.program_id_index] transaction.instructions.append( TransactionInstruction(keys=account_metas, program_id=program_id, data=b58decode(instr.data))) return transaction
def test_decode_nonce_account_data(): b64_data = ( "AAAAAAEAAADbpRzeSWD3B/Ei2SfSmwM6qTDlK5pCxRlx3Vsnr3+v14Bbu3aJmuW0cG" "J2BVvh7C9g5qNUM+I200HP5eSQ8MHBiBMAAAAAAAA=") raw_data = b64decode(b64_data) parsed = VERSIONS_LAYOUT.parse(raw_data) assert parsed.state.data.authority == b58decode( b"FnQK7qe8rkD3x2GrA8ERptTd7bp7KwqouvaQYtr1uuaE") assert parsed.state.data.blockhash == b58decode( b"9e4KCe4NTbA87aUVugjo6Yb1EVittdxy1RQu6AELCTL4") assert parsed.state.data.fee_calculator.lamports_per_signature == 5000
def __encode_instruction( instruction: "CompiledInstruction", ) -> bytes: # TODO: Replace this with a construct struct. InstructionFormat = NamedTuple( "InstructionFormat", [ ("program_idx", bytes), ("accounts_length", bytes), ("accounts", bytes), ("data_length", bytes), ("data", bytes), ], ) data = b58decode(instruction.data) data_length = shortvec.encode_length(len(data)) return b"".join( InstructionFormat( program_idx=helpers.to_uint8_bytes( instruction.program_id_index), accounts_length=shortvec.encode_length( len(instruction.accounts)), accounts=bytes(instruction.accounts), data_length=data_length, data=data, ))
def __encode_message( self) -> bytes: # TODO: Replace this with a construct struct. MessageFormat = NamedTuple( "MessageFormat", [ ("num_required_signatures", bytes), ("num_readonly_signed_accounts", bytes), ("num_readonly_unsigned_accounts", bytes), ("pubkeys_length", bytes), ("pubkeys", bytes), ("recent_blockhash", bytes), ], ) return b"".join( MessageFormat( num_required_signatures=helpers.to_uint8_bytes( self.header.num_required_signatures), num_readonly_signed_accounts=helpers.to_uint8_bytes( self.header.num_readonly_signed_accounts), num_readonly_unsigned_accounts=helpers.to_uint8_bytes( self.header.num_readonly_unsigned_accounts), pubkeys_length=shortvec.encode_length(len(self.account_keys)), pubkeys=b"".join( [bytes(pubkey) for pubkey in self.account_keys]), recent_blockhash=b58decode( self.recent_blockhash.encode("ascii")), ))
def test_account_keypair(): """Validate account keypair against account's private and public key.""" expected_account = Account() keypair = expected_account.keypair() decoded_keypair = b58decode(keypair) actual_account = Account(decoded_keypair[:32]) assert expected_account.public_key() == actual_account.public_key() assert expected_account.secret_key() == actual_account.secret_key()
def decode_byte_string(byte_string: str, encoding: str = "base64") -> bytes: """Decode an encoded string from an RPC Response.""" b_str = str.encode(byte_string) if encoding == "base64": return b64decode(b_str) if encoding == "base58": return b58decode(b_str) raise NotImplementedError(f"{encoding} decoding not currently supported.")
def _get_signature_statuses_args( signatures: List[Union[str, bytes]], search_transaction_history: bool ) -> Tuple[types.RPCMethod, List[str], Dict[str, bool]]: base58_sigs: List[str] = [] for sig in signatures: if isinstance(sig, str): base58_sigs.append( b58encode(b58decode(sig.encode("ascii"))).decode("utf-8")) else: base58_sigs.append(b58encode(sig).decode("utf-8")) return ( types.RPCMethod("getSignatureStatuses"), base58_sigs, { "searchTransactionHistory": search_transaction_history }, )
def __init__(self, value: Union[bytearray, bytes, int, str, List[int], VerifyKey]): """Init PublicKey object.""" self._key: Optional[bytes] = None if isinstance(value, str): try: self._key = b58decode(value.encode("ascii")) except ValueError as err: raise ValueError("invalid public key input:", value) from err if len(self._key) != self.LENGTH: raise ValueError("invalid public key input:", value) elif isinstance(value, int): self._key = bytes([value]) else: self._key = bytes(value) if len(self._key) > self.LENGTH: raise ValueError("invalid public key input:", value)