Python SDK
Tempo distributes a Python SDK as a web3.py extension. The SDK adds native support for Tempo Transactions, including call batching, fee sponsorship, and access key management.
The Tempo Python SDK can be used to perform common operations with the chain, such as: sending Tempo Transactions, batching multiple calls, fee sponsorship, and more.
Create a Python client
To interact with Tempo, create a web3.py client connected to a Tempo node:
from web3 import Web3
w3 = Web3(Web3.HTTPProvider("https://rpc.tempo.xyz"))
block_number = w3.eth.block_number
print(f"Connected to Tempo at block {block_number}")Send a Tempo transaction with Python
Build and send a transaction using the TempoTransaction class:
import os
from web3 import Web3
from pytempo import Call, TempoTransaction
w3 = Web3(Web3.HTTPProvider("https://rpc.tempo.xyz"))
private_key = os.environ["PRIVATE_KEY"]
account = w3.eth.account.from_key(private_key)
tx = TempoTransaction.create(
chain_id=w3.eth.chain_id,
gas_limit=100_000,
max_fee_per_gas=w3.eth.gas_price * 2,
max_priority_fee_per_gas=w3.eth.gas_price,
nonce=w3.eth.get_transaction_count(account.address),
calls=(
Call.create(to="0x70997970C51812dc3A010C7d01b50e0d17dc79C8"),
),
)
signed_tx = tx.sign(private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.encode())
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Transaction hash: {tx_hash.hex()}")Python SDK examples
Send a token transfer with Python
Send a TIP-20 token transfer using pytempo's typed contract helpers:
from pytempo import TempoTransaction
from pytempo.contracts import TIP20, ALPHA_USD
tx = TempoTransaction.create(
chain_id=4217,
gas_limit=100_000,
max_fee_per_gas=10_000_000_000,
max_priority_fee_per_gas=1_000_000_000,
nonce=w3.eth.get_transaction_count(account.address),
calls=(
TIP20(ALPHA_USD).transfer(
to="0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
amount=100_000_000, # 100 tokens (6 decimals)
),
),
)Pay fees in a stablecoin with Python
Use a TIP-20 token to pay for transaction fees instead of the native token:
from pytempo import TempoTransaction, Call
from pytempo.contracts import ALPHA_USD
tx = TempoTransaction.create(
chain_id=4217,
gas_limit=100_000,
max_fee_per_gas=10_000_000_000,
max_priority_fee_per_gas=1_000_000_000,
nonce=w3.eth.get_transaction_count(account.address),
fee_token=ALPHA_USD,
calls=(
Call.create(to="0x70997970C51812dc3A010C7d01b50e0d17dc79C8"),
),
)Batch multiple calls with Python
Execute multiple operations atomically in a single transaction:
from pytempo import TempoTransaction
from pytempo.contracts import TIP20, ALPHA_USD
token = TIP20(ALPHA_USD)
tx = TempoTransaction.create(
chain_id=4217,
gas_limit=300_000,
max_fee_per_gas=10_000_000_000,
max_priority_fee_per_gas=1_000_000_000,
nonce=w3.eth.get_transaction_count(account.address),
calls=(
token.transfer(to="0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb", amount=100_000_000),
token.transfer(to="0x70997970C51812dc3A010C7d01b50e0d17dc79C8", amount=50_000_000),
token.transfer(to="0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", amount=25_000_000),
),
)
signed_tx = tx.sign(private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.encode())Parallel Transactions (2D Nonces)
Send multiple transactions concurrently using different nonce keys:
tx1 = TempoTransaction.create(
chain_id=4217,
gas_limit=100_000,
max_fee_per_gas=10_000_000_000,
max_priority_fee_per_gas=1_000_000_000,
nonce_key=1, # Sequence A
nonce=0,
calls=(Call.create(to=recipient1, data=data1),),
)
tx2 = TempoTransaction.create(
chain_id=4217,
gas_limit=100_000,
max_fee_per_gas=10_000_000_000,
max_priority_fee_per_gas=1_000_000_000,
nonce_key=2, # Sequence B (parallel)
nonce=0,
calls=(Call.create(to=recipient2, data=data2),),
)
# Sign and send both in parallel
signed_tx1 = tx1.sign(private_key)
signed_tx2 = tx2.sign(private_key)
w3.eth.send_raw_transaction(signed_tx1.encode())
w3.eth.send_raw_transaction(signed_tx2.encode())Fee sponsorship with Python
Have another account pay for transaction fees:
# User creates and signs a transaction marked for fee sponsorship
tx = TempoTransaction.create(
chain_id=4217,
gas_limit=100_000,
max_fee_per_gas=10_000_000_000,
max_priority_fee_per_gas=1_000_000_000,
awaiting_fee_payer=True,
calls=(Call.create(to=recipient, data=data),),
)
signed_by_user = tx.sign(user_private_key)
final_tx = signed_by_user.sign(fee_payer_private_key, for_fee_payer=True)
w3.eth.send_raw_transaction(final_tx.encode())Transaction validity windows in Python
Set a time window during which the transaction is valid:
import time
now = int(time.time())
tx = TempoTransaction.create(
chain_id=4217,
gas_limit=100_000,
max_fee_per_gas=10_000_000_000,
max_priority_fee_per_gas=1_000_000_000,
nonce=nonce,
valid_after=now,
valid_before=now + 3600, # 1 hour from now
calls=(Call.create(to=recipient, data=data),),
)Account Keychain in the Python SDK
The AccountKeychain class provides typed helpers for Tempo's Account Keychain precompile, enabling access key management directly from Python.
from pytempo import (
TempoTransaction, Call,
KeyRestrictions, SignatureType, TokenLimit, CallScope,
)
from pytempo.contracts import AccountKeychain, ALPHA_USD
from web3 import Web3
w3 = Web3(Web3.HTTPProvider("https://rpc.tempo.xyz"))
# Authorize a new access key (secp256k1, no expiry):
call = AccountKeychain.authorize_key(
key_id="<ACCESS_KEY_ADDRESS>",
signature_type=SignatureType.SECP256K1,
restrictions=KeyRestrictions(expiry=0),
)
tx = TempoTransaction.create(
chain_id=w3.eth.chain_id,
gas_limit=200_000,
max_fee_per_gas=w3.eth.gas_price * 2,
max_priority_fee_per_gas=w3.eth.gas_price,
nonce=w3.eth.get_transaction_count(account.address),
calls=(call,),
)
# Authorize with a spending limit:
call = AccountKeychain.authorize_key(
key_id="<ACCESS_KEY_ADDRESS>",
signature_type=SignatureType.SECP256K1,
restrictions=KeyRestrictions(
expiry=0,
limits=[TokenLimit(token=ALPHA_USD, limit=1_000_000)],
),
)
# Authorize with call scopes (restrict to specific contracts/functions):
call = AccountKeychain.authorize_key(
key_id="<ACCESS_KEY_ADDRESS>",
signature_type=SignatureType.SECP256K1,
restrictions=KeyRestrictions(
expiry=0,
allowed_calls=[
CallScope.transfer(target=ALPHA_USD),
CallScope.approve(target=ALPHA_USD),
],
),
)
# Full example: 24h expiry + spending limit + call scope:
import time
expiry = int(time.time()) + 86400
call = AccountKeychain.authorize_key(
key_id="<ACCESS_KEY_ADDRESS>",
signature_type=SignatureType.SECP256K1,
restrictions=KeyRestrictions(
expiry=expiry,
limits=[TokenLimit(token=ALPHA_USD, limit=1_000_000)],
allowed_calls=[CallScope.transfer(target=ALPHA_USD)],
),
)
# Revoke an access key (permanent, cannot be re-authorized):
call = AccountKeychain.revoke_key(key_id="<ACCESS_KEY_ADDRESS>")
# Update spending limit for a key-token pair:
call = AccountKeychain.update_spending_limit(
key_id="<ACCESS_KEY_ADDRESS>",
token=str(ALPHA_USD),
new_limit=2_000_000,
)
# Replace all call scopes for a key:
call = AccountKeychain.set_allowed_calls(
key_id="<ACCESS_KEY_ADDRESS>",
scopes=[
CallScope.transfer(target=ALPHA_USD),
CallScope.unrestricted(target="<CONTRACT_ADDRESS>"),
],
)
# Remove a target contract from allowed call list:
call = AccountKeychain.remove_allowed_calls(
key_id="<ACCESS_KEY_ADDRESS>",
target="<TARGET_ADDRESS>",
)
# Query key info (read-only):
key_info = AccountKeychain.get_key(
w3,
account_address="<ACCOUNT_ADDRESS>",
key_id="<ACCESS_KEY_ADDRESS>",
)
print(key_info)
# {'signature_type': 0, 'key_id': '0x...', 'expiry': 1893456000, ...}
# Query remaining spending limit:
remaining = AccountKeychain.get_remaining_limit(
w3,
account_address="<ACCOUNT_ADDRESS>",
key_id="<ACCESS_KEY_ADDRESS>",
token_address=str(ALPHA_USD),
)
print(f"Remaining: {remaining}")Sign with an access key in Python
Use sign_access_key to sign a transaction as an access key holder:
from pytempo import TempoTransaction, Call
tx = TempoTransaction.create(
chain_id=w3.eth.chain_id,
gas_limit=100_000,
max_fee_per_gas=w3.eth.gas_price * 2,
max_priority_fee_per_gas=w3.eth.gas_price,
nonce=w3.eth.get_transaction_count(root_account_address),
calls=(Call.create(to="<CONTRACT_ADDRESS>"),),
)
signed_tx = tx.sign_access_key(
access_key_private_key="<ACCESS_KEY_PRIVATE_KEY>",
root_account="<ROOT_ACCOUNT_ADDRESS>",
)
tx_hash = w3.eth.send_raw_transaction(signed_tx.encode())Next steps for the Python SDK
After setting up the Python SDK, you can:
- Follow a guide on how to make payments, issue stablecoins, exchange stablecoins, and more.
- View the source on GitHub
- View the package on PyPI
Was this helpful?