Exemplo n.º 1
0
    def send_transaction(
        self, txn: Transaction, *signers: Account, opts: types.TxOpts = types.TxOpts()
    ) -> types.RPCResponse:
        """Send a transaction.

        :param txn: Transaction object.
        :param signers: Signers to sign the transaction.
        :param opts: (optional) Transaction options.

        >>> from solana.account import Account
        >>> from solana.system_program import TransferParams, transfer
        >>> from solana.transaction import Transaction
        >>> sender, reciever = Account(1), Account(2)
        >>> txn = Transaction().add(transfer(TransferParams(
        ...     from_pubkey=sender.public_key(), to_pubkey=reciever.public_key(), lamports=1000)))
        >>> solana_client = Client("http://localhost:8899")
        >>> solana_client.send_transaction(txn, sender) # doctest: +SKIP
        {'jsonrpc': '2.0',
         'result': '236zSA5w4NaVuLXXHK1mqiBuBxkNBu84X6cfLBh1v6zjPrLfyECz4zdedofBaZFhs4gdwzSmij9VkaSo2tR5LTgG',
         'id': 12}
        """
        try:
            # TODO: Cache recent blockhash
            blockhash_resp = self.get_recent_blockhash()
            if not blockhash_resp["result"]:
                raise RuntimeError("failed to get recent blockhash")
            txn.recent_blockhash = Blockhash(blockhash_resp["result"]["value"]["blockhash"])
        except Exception as err:
            raise RuntimeError("failed to get recent blockhash") from err

        txn.sign(*signers)
        return self.send_raw_transaction(txn.serialize(), opts=opts)
Exemplo n.º 2
0
    def send_transaction(self, txn: Transaction,
                         *signers: Account) -> RPCResponse:
        """Send a transaction.

        :param txn: Transaction object.
        :param signers: Signers to sign the transaction

        >>> from solana.account import Account
        >>> from solana.system_program import TransferParams, transfer
        >>> sender, reciever = Account(1), Account(2)
        >>> tx = transfer(TransferParams(
        ...     from_pubkey=sender.public_key(), to_pubkey=reciever.public_key(), lamports=1000))
        >>> solana_client = Client("http://localhost:8899")
        >>> solana_client.send_transaction(tx, sender) # doctest: +SKIP
        {'jsonrpc': '2.0',
         'result': '236zSA5w4NaVuLXXHK1mqiBuBxkNBu84X6cfLBh1v6zjPrLfyECz4zdedofBaZFhs4gdwzSmij9VkaSo2tR5LTgG',
         'id': 12}
        """
        try:
            # TODO: Cache recent blockhash
            blockhash_resp = self.get_recent_blockhash()
            if not blockhash_resp["result"]:
                raise RuntimeError("failed to get recent blockhash")
            txn.recent_blockhash = Blockhash(
                blockhash_resp["result"]["value"]["blockhash"])
        except Exception as err:
            raise RuntimeError("failed to get recent blockhash") from err

        txn.sign(*signers)
        wire_format = b58encode(txn.serialize()).decode("utf-8")
        return self._provider.make_request(RPCMethod("sendTransaction"),
                                           wire_format)
    def _validate_txsize(self) -> bool:
        tx = self.build_tx()

        # Predefined blockhash is used only to check transaction size, this transaction won't be send to network
        tx.recent_blockhash = Blockhash(
            '4NCYB3kRT8sCNodPNuCZo8VUh4xqpBQxsxed2wd9xaD4')
        tx.sign(self.s.resource.signer)
        try:
            tx.serialize()
            return True
        except Exception as err:
            if check_if_big_transaction(err):
                self.error = 'Too big transaction size'
                return False
            self.error = str(err)
            raise
Exemplo n.º 4
0
    def deserialize(raw_message: bytes) -> Message:
        """Deserialize raw message bytes.

        >>> raw_message = bytes.fromhex(
        ...     '0200030500000000000000000000000000000000000000000000'
        ...     '0000000000000000000100000000000000000000000000000000'
        ...     '0000000000000000000000000000000200000000000000000000'
        ...     '0000000000000000000000000000000000000000000300000000'
        ...     '0000000000000000000000000000000000000000000000000000'
        ...     '0004000000000000000000000000000000000000000000000000'
        ...     '0000000000000005c49ae77603782054f17a9decea43b444eba0'
        ...     'edb12c6f1d31c6e0e4a84bf052eb010403010203050909090909'
        ... )
        >>> type(Message.deserialize(raw_message))
        <class 'solana.message.Message'>
        """
        HEADER_OFFSET = 3  # pylint: disable=invalid-name
        if len(raw_message) < HEADER_OFFSET:
            raise ValueError("byte representation of message is missing message header")
        num_required_signatures = raw_message[0]
        num_readonly_signed_accounts = raw_message[1]
        num_readonly_unsigned_accounts = raw_message[2]
        header = MessageHeader(
            num_required_signatures=num_required_signatures,
            num_readonly_signed_accounts=num_readonly_signed_accounts,
            num_readonly_unsigned_accounts=num_readonly_unsigned_accounts,
        )
        raw_message = raw_message[HEADER_OFFSET:]

        account_keys = []
        accounts_length, accounts_offset = shortvec.decode_length(raw_message)
        for _ in range(accounts_length):
            key_bytes = raw_message[accounts_offset : accounts_offset + PublicKey.LENGTH]  # noqa: E203
            account_keys.append(str(PublicKey(key_bytes)))
            accounts_offset += PublicKey.LENGTH
        raw_message = raw_message[accounts_offset:]

        recent_blockhash = Blockhash(b58encode(raw_message[: PublicKey.LENGTH]).decode("utf-8"))
        raw_message = raw_message[PublicKey.LENGTH :]  # noqa: E203

        instructions = []
        instruction_count, offset = shortvec.decode_length(raw_message)
        raw_message = raw_message[offset:]
        for _ in range(instruction_count):
            program_id_index = raw_message[0]
            raw_message = raw_message[1:]

            accounts_length, offset = shortvec.decode_length(raw_message)
            raw_message = raw_message[offset:]
            accounts = raw_message[:accounts_length]
            raw_message = raw_message[accounts_length:]

            data_length, offset = shortvec.decode_length(raw_message)
            raw_message = raw_message[offset:]
            data = b58encode(raw_message[:data_length])
            raw_message = raw_message[data_length:]

            instructions.append(CompiledInstruction(program_id_index=program_id_index, accounts=accounts, data=data))

        return Message(
            MessageArgs(
                header=header,
                account_keys=account_keys,
                recent_blockhash=recent_blockhash,
                instructions=instructions,
            )
        )
Exemplo n.º 5
0
 def parse_recent_blockhash(blockhash_resp: types.RPCResponse) -> Blockhash:
     """Extract blockhash from JSON RPC result."""
     if not blockhash_resp.get("result"):
         raise RuntimeError("failed to get recent blockhash")
     return Blockhash(blockhash_resp["result"]["value"]["blockhash"])
Exemplo n.º 6
0
def stubbed_blockhash() -> Blockhash:
    """Arbitrary block hash."""
    return Blockhash("EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k")