> loading_
# ---------------------------------------------------------
# Walkthrough: Exploring TIP-1011 enhanced access key permissions
# and TIP20 virtual address precompiles on Tempo
# ---------------------------------------------------------
# 1. TIP-1011 — Creating a scoped access key
# The new permission model lets you attach granular
# capabilities when adding an access key to an account.
from tempo_sdk import Account, AccessKey, Permission
# Connect to a Tempo RPC endpoint (testnet recommended)
account = Account.from_private_key("YOUR_PRIVATE_KEY", rpc="https://rpc.testnet.tempo.xyz")
# Define a scoped permission:
# - Can only call the "swap" method on a specific DEX contract
# - Allowance capped at 50 TEMPO for gas
scoped_permission = Permission.function_call(
receiver_id="dex.pool.tempo",
method_names=["swap"], # restrict to specific methods
allowance=50_000_000_000_000, # 50 TEMPO in smallest unit
)
# Generate a new key pair for the session key
session_key = AccessKey.generate()
# Add the scoped access key on-chain
tx = account.add_access_key(
public_key=session_key.public_key,
permission=scoped_permission,
)
print(f"Access key added in tx: {tx.hash}")
# The session key can now ONLY call dex.pool.tempo#swap
# and will stop working once 50 TEMPO of gas is spent.
# ---------------------------------------------------------
# 2. TIP20 Virtual Address Precompile
# Resolve a TIP20 virtual address to its underlying
# contract address using the new precompile (no Solidity needed).
# ---------------------------------------------------------
from tempo_sdk.evm import call_precompile
# The TIP20 virtual address precompile lives at a fixed address
TIP20_PRECOMPILE = "0x00000000000000000000000000000000000020Aa"
# Encode the virtual address you want to resolve
virtual_address = "tempo:tip20:USDT"
result = call_precompile(
rpc="https://rpc.testnet.tempo.xyz",
to=TIP20_PRECOMPILE,
data=virtual_address.encode().hex(), # precompile expects hex-encoded name
)
# The precompile returns the canonical contract address
resolved_contract = "0x" + result[-40:] # last 20 bytes = address
print(f"USDT TIP20 contract resolved to: {resolved_contract}")
# You can now call transfer / balanceOf directly on resolved_contract
# without routing through a registry contract — lower gas, simpler code.
# ---------------------------------------------------------
# 3. Consensus change — Validating block construction
# If you run a custom block builder, verify system tx ordering.
# ---------------------------------------------------------
# Pseudocode for block-builder validation before submitting:
#
# def validate_block(transactions):
# system_tx_seen = False
# for tx in transactions:
# if tx.is_system():
# system_tx_seen = True
# elif system_tx_seen:
# # A non-system tx appeared AFTER a system tx → invalid
# raise BlockValidationError(
# "System transactions must be at the end of the block. "
# "Reorder before submitting or the block will be rejected."
# )
# return True
#
# This mirrors the new consensus rule. Test against the latest
# testnet node to confirm your builder passes validation.