Skip to main content
Stablecoin gas fees: Tempo has no native gas token. Transaction fees are paid in TIP-20 stablecoins (like pathUSD). When developing on testnet, get stablecoins from the faucet. On mainnet, acquire stablecoins from issuers or ecosystem partners.

MetaMask

On node access details, click Connect wallet to inject your Chainstack endpoint automatically. If you need to add the network manually, use: Mainnet:
  • Network name: Tempo Mainnet
  • RPC URL: your Chainstack HTTPS endpoint
  • Chain ID: 4217
  • Currency symbol: USD
  • Block explorer URL: https://explore.mainnet.tempo.xyz
Testnet:
  • Network name: Tempo Testnet (Moderato)
  • RPC URL: your Chainstack HTTPS endpoint
  • Chain ID: 42431
  • Currency symbol: USD
  • Block explorer URL: https://explore.tempo.xyz
Chainstack provides both HTTPS and WSS endpoints for Tempo. Use HTTPS for MetaMask and general RPC calls. Use WSS for real-time subscriptions in your applications. Refer to node access details for your endpoint URL format and credentials.
MetaMask may show an unusually high balance for the native token. This is expected—Tempo has no native gas token, and wallets see a placeholder value. Fees are paid in TIP-20 stablecoins denominated in USD. Check your stablecoin balances by adding the token addresses to MetaMask.

Stablecoin addresses

These addresses are the same on both mainnet and testnet:
TokenAddress
pathUSD0x20c0000000000000000000000000000000000000
AlphaUSD0x20c0000000000000000000000000000000000001
BetaUSD0x20c0000000000000000000000000000000000002
ThetaUSD0x20c0000000000000000000000000000000000003

web3.py

Build DApps using web3.py and Tempo nodes deployed with Chainstack.
  1. Install web3.py.
  2. Connect over HTTP or WebSocket.

HTTP

Use the HTTPProvider to connect to your node endpoint and get the latest block number.
from web3 import Web3

web3 = Web3(Web3.HTTPProvider('YOUR_CHAINSTACK_ENDPOINT'))
print(web3.eth.block_number)

WebSocket

Use the WebSocketProvider to connect over WebSocket. WebSocket connections enable subscriptions for real-time events like new blocks and pending transactions.
from web3 import Web3

web3 = Web3(Web3.WebSocketProvider('YOUR_CHAINSTACK_WSS_ENDPOINT'))
print(web3.eth.block_number)
where
  • YOUR_CHAINSTACK_ENDPOINT — your node HTTPS endpoint protected either with the key or password
  • YOUR_CHAINSTACK_WSS_ENDPOINT — your node WSS endpoint protected either with the key or password
  • USERNAME — the username to your node if you use a password-protected endpoint
  • PASSWORD — the password to your node if you use a password-protected endpoint
  • HOSTNAME — the host name of your node
Tempo network IDs:
  • Mainnet: 4217
  • Moderato Testnet: 42431
See also node access details.
web3.py works for basic JSON-RPC operations but does not support Tempo’s native feeToken parameter. For full Tempo Transaction support in Python, use pytempo instead. For TypeScript, use Viem.

ethers.js

Build DApps using ethers.js and Tempo nodes deployed with Chainstack.
  1. Install ethers.js.
  2. Connect over HTTP or WebSocket.

HTTP

Use the JsonRpcProvider object to connect to your node endpoint and get the latest block number:
const { ethers } = require("ethers");

const provider = new ethers.JsonRpcProvider("YOUR_CHAINSTACK_ENDPOINT", {
  chainId: 4217,
  name: "tempo"
});

provider.getBlockNumber().then(console.log);

WebSocket

Use the WebSocketProvider to connect over WebSocket. WebSocket connections enable subscriptions for real-time events like new blocks and pending transactions.
const { ethers } = require("ethers");

const provider = new ethers.WebSocketProvider("YOUR_CHAINSTACK_WSS_ENDPOINT", {
  chainId: 4217,
  name: "tempo"
});

// Get block number
provider.getBlockNumber().then(console.log);

// Subscribe to new blocks
provider.on("block", (blockNumber) => {
  console.log("New block:", blockNumber);
});
where
  • YOUR_CHAINSTACK_ENDPOINT — your node HTTPS endpoint protected either with the key or password
  • YOUR_CHAINSTACK_WSS_ENDPOINT — your node WSS endpoint protected either with the key or password
See also node access details.
ethers.js works for basic JSON-RPC operations but does not support Tempo’s native feeToken parameter. For transactions, Tempo uses a cascading fee algorithm that defaults to pathUSD for non-TIP20 contract interactions. For full Tempo Transaction support (fee token selection, fee sponsorship, batch transactions), use Viem instead.

Viem

Viem is the recommended TypeScript library for Tempo development. Starting from viem@2.43.0, Viem has native Tempo support with full access to Tempo Transaction features.
  1. Install Viem:
npm install viem
  1. Create a client configured for Tempo:
import { createPublicClient, createWalletClient, http } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { tempo as tempoChain } from 'viem/chains'
import { tempo } from 'viem/tempo'

// Public client for read operations
const publicClient = createPublicClient({
  chain: tempoChain,
  transport: http('YOUR_CHAINSTACK_ENDPOINT'),
}).extend(tempo())

// Wallet client for transactions
const walletClient = createWalletClient({
  account: privateKeyToAccount('YOUR_PRIVATE_KEY'),
  chain: tempoChain,
  transport: http('YOUR_CHAINSTACK_ENDPOINT'),
}).extend(tempo())

// Get block number
const blockNumber = await publicClient.getBlockNumber()
console.log(blockNumber)
where
  • YOUR_CHAINSTACK_ENDPOINT — your node HTTPS endpoint protected either with the key or password
  • YOUR_PRIVATE_KEY — the private key of your account (with 0x prefix)
Use tempoModerato for the active testnet (chain ID 42431). The tempoTestnet export points to the deprecated Andantino testnet (chain ID 42429).

WebSocket

Use the webSocket transport for real-time subscriptions:
import { createPublicClient, webSocket } from 'viem'
import { tempo as tempoChain } from 'viem/chains'
import { tempo } from 'viem/tempo'

const publicClient = createPublicClient({
  chain: tempoChain,
  transport: webSocket('YOUR_CHAINSTACK_WSS_ENDPOINT'),
}).extend(tempo())

// Subscribe to new blocks
const unwatch = publicClient.watchBlocks({
  onBlock: (block) => {
    console.log('New block:', block.number)
  },
})
where YOUR_CHAINSTACK_WSS_ENDPOINT is your node WSS endpoint protected either with the key or password.

Send transactions with fee token

Viem’s Tempo extension supports the feeToken parameter to specify which stablecoin pays the transaction fee:
import { parseUnits } from 'viem'

const alphaUsd = '0x20c0000000000000000000000000000000000001'
const betaUsd = '0x20c0000000000000000000000000000000000002'

// Transfer AlphaUSD, pay fees in BetaUSD
const receipt = await walletClient.token.transferSync({
  amount: parseUnits('100', 6),
  to: '0xRecipientAddress',
  token: alphaUsd,
  feeToken: betaUsd,
})

console.log('Transaction hash:', receipt.transactionHash)

Get token balance

const balance = await publicClient.token.getBalance({
  account: '0xYourAddress',
  token: '0x20c0000000000000000000000000000000000001', // AlphaUSD
})

console.log('Balance:', balance)
See also Viem Tempo documentation.

Wagmi

Wagmi provides React Hooks for Tempo development. Starting from wagmi@3.2.0, Wagmi has native Tempo support.
  1. Install Wagmi:
npm install wagmi viem @tanstack/react-query
  1. Configure Wagmi with Tempo:
import { http, createConfig } from 'wagmi'
import { tempo } from 'wagmi/chains'

export const config = createConfig({
  chains: [tempo],
  transports: {
    [tempo.id]: http('YOUR_CHAINSTACK_ENDPOINT'),
  },
})
where
  • YOUR_CHAINSTACK_ENDPOINT — your node HTTPS endpoint protected either with the key or password
  • YOUR_CHAINSTACK_WSS_ENDPOINT — your node WSS endpoint for real-time subscriptions
  1. Use Tempo hooks in your React components:
import { Hooks } from 'wagmi/tempo'
import { parseUnits } from 'viem'

const alphaUsd = '0x20c0000000000000000000000000000000000001'
const betaUsd = '0x20c0000000000000000000000000000000000002'

function SendPayment() {
  const sendPayment = Hooks.token.useTransferSync()

  const handleSend = () => {
    sendPayment.mutate({
      amount: parseUnits('100', 6),
      to: '0xRecipientAddress',
      token: alphaUsd,
      feeToken: betaUsd,
    })
  }

  return (
    <button onClick={handleSend} disabled={sendPayment.isPending}>
      Send Payment
    </button>
  )
}
See also Wagmi Tempo documentation.

Hardhat

Configure Hardhat to deploy contracts and interact through your Tempo nodes.
  1. Install Hardhat and create a project.
  2. Create a new environment in hardhat.config.js:
    require("@nomicfoundation/hardhat-ethers");
    ...
    module.exports = {
      solidity: "0.8.26",
      networks: {
        tempo: {
          url: "YOUR_CHAINSTACK_ENDPOINT",
          chainId: 4217,
          accounts: ["YOUR_PRIVATE_KEY"]
        },
        tempoTestnet: {
          url: "YOUR_CHAINSTACK_ENDPOINT",
          chainId: 42431,
          accounts: ["YOUR_PRIVATE_KEY"]
        }
      }
    };
    
    where
    • YOUR_CHAINSTACK_ENDPOINT — your node HTTPS endpoint protected either with the key or password. See node access details.
    • YOUR_PRIVATE_KEY — the private key of the account that you use to deploy the contract
  3. Run npx hardhat run scripts/deploy.js --network tempo (or --network tempoTestnet for testnet) and Hardhat will deploy using Chainstack.
Hardhat’s default gas estimation may not work correctly with Tempo’s stablecoin fee model. For contract deployments, consider using tempo-foundry instead, which has native support for stablecoin gas payments.

Remix IDE

To make Remix IDE interact with the network through a Chainstack node:
  1. Get MetaMask and set it to interact through a Chainstack node. See MetaMask.
  2. In Remix IDE, navigate to the Deploy & run transactions tab. Select Injected Provider - MetaMask in Environment.
This will engage MetaMask and make Remix IDE interact with the network through a Chainstack node.
Remix IDE uses standard EVM transactions and does not support Tempo’s feeToken parameter. Transactions default to pathUSD for gas fees when interacting with non-TIP20 contracts. Ensure your wallet has pathUSD balance. For smart contract deployment with fee token control, use tempo-foundry instead.

tempo-foundry

Tempo has a custom Foundry fork with native support for Tempo Transactions, including stablecoin gas fees via the --tempo.fee-token flag.

Installation

Install tempo-foundry using the standard foundryup installer with the -n tempo flag:
foundryup -n tempo
This installs the latest nightly release of all precompiled binaries: forge, cast, anvil, and chisel. Verify the installation:
forge -V
You should see version information including -tempo, indicating you are using the Tempo fork:
# forge <version>-tempo (<commit> <timestamp>)

Create a new project

Initialize a new project with Tempo support:
forge init -n tempo my-project && cd my-project
Each new project is configured for Tempo out of the box with tempo-std, the Tempo standard library, which contains helpers for Tempo’s protocol-level features.

Forge

Use forge to develop, test, and deploy your smart contracts. To deploy a contract:
forge create src/MyContract.sol:MyContract \
  --rpc-url YOUR_CHAINSTACK_ENDPOINT \
  --interactive \
  --broadcast \
  --verify
To deploy with a specific fee token:
forge create src/MyContract.sol:MyContract \
  --tempo.fee-token 0x20c0000000000000000000000000000000000001 \
  --rpc-url YOUR_CHAINSTACK_ENDPOINT \
  --interactive \
  --broadcast \
  --verify
where
  • src/MyContract.sol:MyContract — path to your contract file and the contract name
  • YOUR_CHAINSTACK_ENDPOINT — your node HTTPS endpoint protected either with the key or password
  • --tempo.fee-token — the TIP-20 token address to pay gas fees (AlphaUSD in this example)
  • --interactive — prompts for your private key instead of passing it on the command line
  • --broadcast — broadcasts the transaction to the network
  • --verify — verifies the contract on contracts.tempo.xyz (Sourcify-compatible)

Cast

Use cast to interact with the network and the deployed contracts. To get the latest block number:
cast block-number --rpc-url YOUR_CHAINSTACK_ENDPOINT
To send a transaction with a fee token:
cast send CONTRACT_ADDRESS \
  "functionName(args)" \
  --private-key YOUR_PRIVATE_KEY \
  --rpc-url YOUR_CHAINSTACK_ENDPOINT \
  --tempo.fee-token 0x20c0000000000000000000000000000000000001
where YOUR_CHAINSTACK_ENDPOINT is your node HTTPS endpoint protected either with the key or password.

Solidity integration with tempo-std

Import protocol interfaces from tempo-std in your Solidity contracts:
forge install tempoxyz/tempo-std
import {IStablecoinExchange} from "tempo-std/interfaces/IStablecoinExchange.sol";

IStablecoinExchange constant DEX = IStablecoinExchange(0xDEc0000000000000000000000000000000000000);

// Approve first, then:
uint128 amountOut = DEX.swapExactAmountIn(tokenIn, tokenOut, amountIn, minAmountOut);
See also Foundry for Tempo documentation.

pytempo

pytempo is Tempo’s native Python SDK, built as a web3.py extension. It adds support for Tempo Transactions, including call batching, fee token selection, fee sponsorship, and access key management.

Installation

pip install pytempo
Requires Python 3.9 or higher and web3.py 7.0+.

Connect to Tempo

from web3 import Web3

w3 = Web3(Web3.HTTPProvider("YOUR_CHAINSTACK_ENDPOINT"))
print(f"Connected to Tempo at block {w3.eth.block_number}")

Send a Tempo Transaction

Build and send a transaction using the TempoTransaction class:
import os
from web3 import Web3
from pytempo import Call, TempoTransaction

w3 = Web3(Web3.HTTPProvider("YOUR_CHAINSTACK_ENDPOINT"))
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()}")

Pay fees in a stablecoin

Specify a fee token so users pay gas in any supported stablecoin:
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),
    fee_token="0x20c0000000000000000000000000000000000001",  # AlphaUSD
    calls=(
        Call.create(to="0x70997970C51812dc3A010C7d01b50e0d17dc79C8"),
    ),
)

Batch multiple calls

Execute multiple operations atomically in a single transaction:
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.create(to=token_a.address, data=transfer_data_a),
        Call.create(to=token_b.address, data=transfer_data_b),
    ),
)
See also pytempo documentation.

tempo-go

tempo-go is Tempo’s Go SDK for building application clients. It provides packages for RPC communication, transaction signing, and key management.

Installation

go get github.com/tempoxyz/tempo-go@latest
Requires Go 1.21 or higher.

Connect to Tempo

package main

import (
    "context"
    "fmt"
    "github.com/tempoxyz/tempo-go/pkg/client"
)

func main() {
    c := client.New("YOUR_CHAINSTACK_ENDPOINT")
    ctx := context.Background()

    blockNum, _ := c.GetBlockNumber(ctx)
    fmt.Printf("Connected to Tempo at block %d\n", blockNum)
}

Send a Tempo Transaction

Build and send a transaction using the builder pattern:
package main

import (
    "context"
    "log"
    "math/big"
    "github.com/ethereum/go-ethereum/common"
    "github.com/tempoxyz/tempo-go/pkg/client"
    "github.com/tempoxyz/tempo-go/pkg/signer"
    "github.com/tempoxyz/tempo-go/pkg/transaction"
)

func main() {
    c := client.New("YOUR_CHAINSTACK_ENDPOINT")
    s, _ := signer.NewSigner("YOUR_PRIVATE_KEY")
    ctx := context.Background()

    nonce, _ := c.GetTransactionCount(ctx, s.Address().Hex())
    recipient := common.HexToAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8")

    tx := transaction.NewBuilder(big.NewInt(4217)). // Tempo mainnet
        SetNonce(nonce).
        SetGas(100000).
        SetMaxFeePerGas(big.NewInt(20000000000)).
        SetMaxPriorityFeePerGas(big.NewInt(1000000000)).
        AddCall(recipient, big.NewInt(0), []byte{}).
        Build()

    transaction.SignTransaction(tx, s)
    serialized, _ := transaction.Serialize(tx, nil)
    hash, _ := c.SendRawTransaction(ctx, serialized)
    log.Printf("Transaction hash: %s", hash)
}
See also tempo-go documentation.

tempo-alloy (Rust)

tempo-alloy is Tempo’s Rust SDK in the form of an Alloy crate. Alloy is a popular Rust crate for interacting with EVM-compatible blockchains.

Installation

cargo add alloy --features providers,transport-http,network tokio --features full
cargo add tempo-alloy --git https://github.com/tempoxyz/tempo --tag v1.4.2
Requires Rust 1.93.0 or higher.

Connect to Tempo

Create a provider using the TempoNetwork type to enable Tempo-specific features:
use alloy::providers::ProviderBuilder;
use tempo_alloy::TempoNetwork;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let provider = ProviderBuilder::new_with_network::<TempoNetwork>()
        .connect(&std::env::var("RPC_URL").expect("No RPC URL set"))
        .await?;

    println!("Provider connected successfully");
    Ok(())
}

Read chain data

use alloy::providers::{Provider, ProviderBuilder};
use tempo_alloy::TempoNetwork;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let provider = ProviderBuilder::new_with_network::<TempoNetwork>()
        .connect(&std::env::var("RPC_URL").expect("No RPC URL set"))
        .await?;

    println!("{}", provider.get_block_number().await?);
    Ok(())
}
See also Alloy documentation and tempo-alloy documentation.

Get testnet tokens

The faucet is only available on Tempo testnet. On mainnet, acquire stablecoins from issuers or ecosystem partners.
Fund your wallet using the tempo_fundAddress RPC method on the public Tempo RPC:
cast rpc tempo_fundAddress YOUR_ADDRESS --rpc-url https://rpc.moderato.tempo.xyz
The faucet sends 1M of each testnet stablecoin (pathUSD, AlphaUSD, BetaUSD, ThetaUSD) to the specified address. After receiving tokens, use your Chainstack endpoint for all other operations. See also tempo_fundAddress API reference.

See also

Last modified on March 19, 2026