Skip to content

python ​

Send a transaction over UDP from Python using the standard library socket module. No extra dependencies beyond what you already use to sign Solana transactions.

Minimal Example ​

python
import socket

ENDPOINT = ("fra.blocksprint.io", 5000)
API_KEY = b"YOUR_API_KEY"

def send_udp(tx_bytes: bytes) -> None:
    """Fire-and-forget UDP submission. tx_bytes must be the serialized Solana transaction."""
    pkt = bytes([len(API_KEY)]) + API_KEY + tx_bytes
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.sendto(pkt, ENDPOINT)
    sock.close()

Full Example: Sign + Send with solders ​

python
import socket
from solders.hash import Hash
from solders.keypair import Keypair
from solders.message import Message
from solders.pubkey import Pubkey
from solders.system_program import TransferParams, transfer
from solders.transaction import VersionedTransaction

ENDPOINT = ("fra.blocksprint.io", 5000)
API_KEY = b"YOUR_API_KEY"

# One of your tip recipient addresses — see the Tipping doc for the full list
TIP_ADDRESS = Pubkey.from_string("YOUR_TIP_ADDRESS")
TIP_LAMPORTS = 1_000_000  # 0.001 SOL (minimum)


def build_and_send(payer: Keypair, recipient: Pubkey, amount_lamports: int, recent_blockhash: Hash) -> str:
    instructions = [
        # Your transfer
        transfer(TransferParams(
            from_pubkey=payer.pubkey(),
            to_pubkey=recipient,
            lamports=amount_lamports,
        )),
        # Tip
        transfer(TransferParams(
            from_pubkey=payer.pubkey(),
            to_pubkey=TIP_ADDRESS,
            lamports=TIP_LAMPORTS,
        )),
    ]

    message = Message.new_with_blockhash(instructions, payer.pubkey(), recent_blockhash)
    tx = VersionedTransaction(message, [payer])

    tx_bytes = bytes(tx)  # Solana wire bytes
    pkt = bytes([len(API_KEY)]) + API_KEY + tx_bytes

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.sendto(pkt, ENDPOINT)
    sock.close()

    return str(tx.signatures[0])


# Usage
payer = Keypair()  # your wallet keypair
recent_blockhash = Hash.from_string("RECENT_BLOCKHASH")  # from getLatestBlockhash on your own Solana RPC
signature = build_and_send(payer, Pubkey.from_string("RECIPIENT_ADDRESS"), 1_000_000, recent_blockhash)
print(f"Sent signature: {signature}")

Reusing the Socket (High Throughput) ​

For bots submitting many transactions, create the socket once and reuse it:

python
import socket

class UdpSender:
    def __init__(self, host: str, port: int, api_key: str):
        self.endpoint = (host, port)
        self.api_key = api_key.encode("ascii")
        self.key_prefix = bytes([len(self.api_key)]) + self.api_key
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    def send(self, tx_bytes: bytes) -> None:
        self.sock.sendto(self.key_prefix + tx_bytes, self.endpoint)

    def close(self) -> None:
        self.sock.close()


# Usage
sender = UdpSender("fra.blocksprint.io", 5000, "YOUR_API_KEY")
try:
    for tx_bytes in pending_transactions:
        sender.send(tx_bytes)
finally:
    sender.close()

Async Version ​

python
import asyncio
import socket

class AsyncUdpSender:
    def __init__(self, host: str, port: int, api_key: str):
        self.endpoint = (host, port)
        self.api_key = api_key.encode("ascii")
        self.key_prefix = bytes([len(self.api_key)]) + self.api_key
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.setblocking(False)

    async def send(self, tx_bytes: bytes) -> None:
        loop = asyncio.get_running_loop()
        await loop.sock_sendto(self.sock, self.key_prefix + tx_bytes, self.endpoint)


async def main():
    sender = AsyncUdpSender("fra.blocksprint.io", 5000, "YOUR_API_KEY")
    await sender.send(tx_bytes)


asyncio.run(main())

Notes ​

  • No response. sendto returns once the OS has accepted the packet — there is no acknowledgement from BlockSprint. Record the signature client-side and poll status yourself.
  • Silent drops. Invalid keys, missing tips or tips below 0.001 SOL, and rate-limit hits all cause silent drops with no error returned.
  • MTU. Keep the total packet under ~1300 bytes (1 + key_len + ≤ 1232 tx bytes).
  • Transaction V1. Build it with solders 0.29 or later (MessageV1 with a TransactionConfig that sets the compute-unit limit and the loaded-accounts data size limit). bytes(tx) then gives the V1 wire bytes. Keep V1 datagrams within about 1,400 bytes, and send larger V1 transactions (up to 4,096 bytes) via QUIC or sendTransaction.
  • Encoding. API_KEY must be plain ASCII bytes — do not base64-encode or hash it.