> ## Documentation Index
> Fetch the complete documentation index at: https://docs.privy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Using Tempo with Privy

[Tempo](https://tempo.xyz) is a low-cost, high-throughput EVM-compatible blockchain optimized for payments. Just like with other [chains](/wallets/overview/chains), your app can use Privy to create wallets for users to send and receive payments on Tempo.

This guide demonstrates how to create an embedded wallet and send transactions on Tempo.

## Prerequisites

Before implementing Tempo support, ensure the following:

* A Privy app configured with the application
* Basic familiarity with [sending transactions](/wallets/using-wallets/ethereum/send-a-transaction)
* (Optional) [Gas sponsorship enabled](/wallets/gas-and-asset-management/gas/setup) to sponsor transaction fees

## 1. Create an embedded wallet

Privy embedded wallets support Tempo by default. To create an embedded wallet for a user on Tempo, use the same "Ethereum" `chain_type` as any other EVM-compatible chain.

This recipe includes examples of creating an EVM-compatible wallet in React, Node, or via the REST API. See [Create a wallet](/wallets/wallets/create/create-a-wallet) for more guidance across all SDKs.

<View title="NodeJS" icon="node-js">
  ```typescript theme={"system"}
  import {PrivyClient} from '@privy-io/node';

  const privy = new PrivyClient({
    appId: process.env.PRIVY_APP_ID,
    appSecret: process.env.PRIVY_APP_SECRET
  });

  async function createTempoWallet(userId: string) {
    const wallet = await privy.wallets().create({
      chain_type: 'ethereum'
    });

    console.log('Created wallet:', wallet.address);
    return wallet;
  }
  ```
</View>

<View title="React" icon="react">
  ```tsx theme={"system"}
  import {useCreateWallet} from '@privy-io/react-auth';

  function CreateWallet() {
    const {createWallet} = useCreateWallet();

    const handleCreateWallet = async () => {
      const wallet = await createWallet(); // creates an Ethereum-type wallet for the logged-in user
      console.log('Created wallet:', wallet.address);
    };

    return <button onClick={handleCreateWallet}>Create Tempo wallet</button>;
  }
  ```
</View>

Once created, the wallet address receives payments on Tempo.

## 2. Transfer tokens on Tempo

The [`/transfer`](/wallets/actions/transfer/usage) endpoint provides the simplest integration path for sending tokens on Tempo. Privy handles Tempo transaction construction, token decimal precision, and gas sponsorship automatically.

<View title="NodeJS" icon="node-js">
  ```typescript {skip-check} theme={"system"}
  import {PrivyClient} from '@privy-io/node';

  const privy = new PrivyClient({
    appId: process.env.PRIVY_APP_ID,
    appSecret: process.env.PRIVY_APP_SECRET
  });

  const response = await privy.wallets().transfer('insert-wallet-id', {
    source: {
      asset: 'usdc',
      amount: '10.0',
      chain: 'tempo'
    },
    destination: {
      address: '0xRecipientAddress'
    }
  });

  console.log('Transfer action:', response.id, response.status);
  ```
</View>

<View title="REST API" icon="terminal">
  ```bash theme={"system"}
  curl -X POST https://api.privy.io/v1/wallets/{wallet_id}/transfer \
    -u "<your-privy-app-id>:<your-privy-app-secret>" \
    -H "privy-app-id: <your-privy-app-id>" \
    -H "Content-Type: application/json" \
    -d '{
      "source": {
        "asset": "usdc",
        "amount": "10.0",
        "chain": "tempo"
      },
      "destination": {
        "address": "0xRecipientAddress"
      }
    }'
  ```

  ```json Example response theme={"system"}
  {
    "id": "action-id",
    "status": "pending",
    "wallet_id": "wallet-id",
    "created_at": "2026-04-14T20:09:11.929Z",
    "type": "transfer",
    "source_asset": "usdc",
    "source_amount": "10.0",
    "source_chain": "tempo",
    "destination_address": "0xRecipientAddress"
  }
  ```
</View>

<Tip>
  If [gas sponsorship](/wallets/gas-and-asset-management/gas/setup) is enabled in the Privy
  Dashboard, the `/transfer` endpoint sponsors gas automatically. No additional parameters are
  needed.
</Tip>

The `/transfer` endpoint also supports [cross-chain bridging](/wallets/actions/transfer/bridging) to and from Tempo. See the [transfer API reference](/wallets/actions/transfer/usage) for full parameter documentation.

## 3. Send custom transactions on Tempo

For use cases beyond simple transfers — such as batched calls, custom contract interactions, specifying fee tokens, or using viem directly — use the low-level transaction APIs.

To send transactions on Tempo mainnet, specify the CAIP-2 identifier `eip155:4217` when making transaction requests. This routes transactions to the Tempo network.

<Info>
  To send transactions on Tempo Moderato (testnet), specify the CAIP-2 identifier `eip155:42431`.
</Info>

<Info>
  If no transaction type is specified, Privy sends a standard EIP-1559 transaction. Use Tempo
  transaction type `118` to access Tempo-native features like specifying the fee token.
</Info>

<Info>
  Tempo has no native gas token. To pay fees directly, set `feeToken` or `fee_token` to a supported
  TIP-20 token. If omitted, Tempo's [fee-token preference
  rules](https://docs.tempo.xyz/protocol/fees/spec-fee#fee-lifecycle) apply.
</Info>

<Accordion title="Using Privy SDK or REST API">
  Privy SDKs and REST API support Tempo transactions natively. Specify `type: 118` in the transaction
  params to access Tempo-native features like fee token control and gas sponsorship.

  <View title="NodeJS" icon="node-js">
    ```typescript {skip-check} theme={"system"}
    import {PrivyClient} from '@privy-io/node';
    import {encodeFunctionData, parseAbi} from 'viem';

    const privy = new PrivyClient({
      appId: process.env.PRIVY_APP_ID,
      appSecret: process.env.PRIVY_APP_SECRET
    });

    const walletId = 'insert-wallet-id';
    const USDC_E = '0x20c000000000000000000000b9537d11c60e8b50';

    const data = encodeFunctionData({
      abi: parseAbi(['function transfer(address to, uint256 amount) public returns (bool)']),
      functionName: 'transfer',
      args: ['0xRecipientAddress', 1_000_000n] // 1 USDC (6 decimals)
    });

    const {hash} = await privy
      .wallets()
      .ethereum()
      .sendTransaction(walletId, {
        caip2: 'eip155:4217', // use 'eip155:42431' for Tempo Moderato (testnet)
        params: {
          transaction: {
            type: 118,
            fee_token: USDC_E, // pay Tempo fees in USDC
            calls: [
              {
                to: USDC_E,
                data
              }
            ]
          }
        }
      });

    console.log('Transaction hash:', hash);
    ```
  </View>

  <View title="React" icon="react">
    ```tsx {skip-check} theme={"system"}
    import {useWallets} from '@privy-io/react-auth';
    import {useSendTransaction} from '@privy-io/react-auth/tempo';
    import {encodeFunctionData, parseAbi} from 'viem';

    const usdc = '0x20c000000000000000000000b9537d11c60e8b50';

    function SendTempoToken() {
      const {wallets} = useWallets();
      const {sendTransaction} = useSendTransaction();

      const handleSend = async () => {
        const wallet = wallets[0];

        const {hash} = await sendTransaction({
          transaction: {
            type: 118,
            chainId: 4217, // use 42431 for Tempo Moderato (testnet)
            feeToken: usdc, // pay Tempo fees in USDC
            calls: [
              {
                to: usdc,
                data: encodeFunctionData({
                  abi: parseAbi([
                    'function transfer(address to, uint256 amount) public returns (bool)'
                  ]),
                  functionName: 'transfer',
                  args: ['0xRecipientAddress', 1_000_000n] // 1 USDC (6 decimals)
                })
              }
            ]
          },
          wallet
        });
        console.log('Transaction hash:', hash);
      };

      return <button onClick={handleSend}>Send token</button>;
    }
    ```
  </View>

  <View title="REST API" icon="code">
    ```bash theme={"system"}
    curl --request POST \
      --url https://api.privy.io/v1/wallets/{wallet_id}/rpc \
      --header 'Authorization: Basic <encoded-credentials>' \
      --header 'Content-Type: application/json' \
      --header 'privy-app-id: <privy-app-id>' \
      --data '{
        "method": "eth_sendTransaction",
        "caip2": "eip155:4217",
        "params": {
          "transaction": {
            "type": 118,
            "fee_token": "0x20c000000000000000000000b9537d11c60e8b50",
            "calls": [
              {
                "to": "0x20c000000000000000000000b9537d11c60e8b50",
                "data": "<encoded transfer calldata>"
              }
            ]
          }
        }
      }'
    ```
  </View>
</Accordion>

<Accordion title="Using viem tempoActions">
  This approach uses viem's `tempoActions` extension to send native Tempo transactions. Use
  this path when building with viem directly, particularly for React embedded wallets.

  <View title="NodeJS" icon="node-js">
    ```typescript {skip-check} theme={"system"}
    import {PrivyClient} from '@privy-io/node';
    import {createViemAccount} from '@privy-io/node/viem';
    import {createWalletClient, http, padHex, stringToHex} from 'viem';
    import {tempo} from 'viem/chains';
    import {tempoActions} from 'viem/tempo';

    const privy = new PrivyClient({
      appId: process.env.PRIVY_APP_ID,
      appSecret: process.env.PRIVY_APP_SECRET
    });

    const account = createViemAccount(privy, {
      walletId: 'insert-wallet-id',
      address: 'insert-wallet-address'
    });

    const walletClient = createWalletClient({
      account,
      chain: tempo,
      transport: http()
    }).extend(tempoActions());

    const usdc = '0x20c000000000000000000000b9537d11c60e8b50';

    const receipt = await walletClient.token.transferSync({
      to: '0xRecipientAddress',
      amount: 1_000_000n, // 1 USDC (6 decimals)
      token: usdc,
      memo: padHex(stringToHex('Hello, world!'), {size: 32}),
      feeToken: usdc // pay Tempo fees in USDC
    });
    console.log(receipt);
    ```
  </View>

  <View title="React" icon="react">
    ```tsx {skip-check} theme={"system"}
    import {useWallets, toViemAccount} from '@privy-io/react-auth';
    import {createWalletClient, http, padHex, stringToHex} from 'viem';
    import {tempo} from 'viem/chains';
    import {tempoActions} from 'viem/tempo';

    const usdc = '0x20c000000000000000000000b9537d11c60e8b50';

    function SendTempoToken() {
      const {wallets} = useWallets();

      const handleSend = async () => {
        const account = await toViemAccount({wallet: wallets[0]});

        const walletClient = createWalletClient({
          account,
          chain: tempo, // use tempoModerato from 'viem/chains' for testnet
          transport: http()
        }).extend(tempoActions());

        const hash = await walletClient.token.transfer({
          to: '0xRecipientAddress',
          amount: 1_000_000n, // 1 USDC (6 decimals)
          token: usdc,
          memo: padHex(stringToHex('Hello, world!'), {size: 32}),
          feeToken: usdc // pay gas fees in USDC
        });
        console.log('Transaction hash:', hash);
      };

      return <button onClick={handleSend}>Send token</button>;
    }
    ```
  </View>

  <View title="REST API" icon="terminal">
    ```bash theme={"system"}
    curl --request POST \
      --url https://api.privy.io/v1/wallets/{wallet_id}/rpc \
      --header 'Authorization: Basic <encoded-credentials>' \
      --header 'Content-Type: application/json' \
      --header 'privy-app-id: <privy-app-id>' \
      --data '{
        "method": "eth_sendTransaction",
        "caip2": "eip155:4217",
        "params": {
          "transaction": {
            "type": 118,
            "fee_token": "0x20c000000000000000000000b9537d11c60e8b50",
            "calls": [
              {
                "to": "0x20c000000000000000000000b9537d11c60e8b50",
                "data": "<encoded transfer calldata>"
              }
            ]
          }
        }
      }'
    ```
  </View>
</Accordion>

<Accordion title="Using gas sponsorship">
  This approach sends a Tempo transaction with Privy paying the gas fee. [Gas
  sponsorship](/wallets/gas-and-asset-management/gas/setup) must be enabled in the Privy Dashboard
  before use, and requires TEE execution. Privy adds the Tempo fee payer signature before broadcasting
  the transaction.

  <View title="NodeJS" icon="node-js">
    ```typescript {skip-check} theme={"system"}
    import {PrivyClient} from '@privy-io/node';
    import {encodeFunctionData, parseAbi} from 'viem';

    const privy = new PrivyClient({
      appId: process.env.PRIVY_APP_ID,
      appSecret: process.env.PRIVY_APP_SECRET
    });

    const USDC_E = '0x20c000000000000000000000b9537d11c60e8b50';

    const data = encodeFunctionData({
      abi: parseAbi(['function transfer(address to, uint256 amount) public returns (bool)']),
      functionName: 'transfer',
      args: ['0xRecipientAddress', 1_000_000n] // 1 USDC (6 decimals)
    });

    const {hash} = await privy
      .wallets()
      .ethereum()
      .sendTransaction('insert-wallet-id', {
        caip2: 'eip155:4217', // use 'eip155:42431' for Tempo Moderato (testnet)
        params: {
          transaction: {
            type: 118,
            calls: [
              {
                to: USDC_E,
                data
              }
            ]
          }
        },
        sponsor: true
      });

    console.log('Transaction hash:', hash);
    ```
  </View>

  <View title="React" icon="react">
    ```tsx {skip-check} theme={"system"}
    import {useWallets} from '@privy-io/react-auth';
    import {useSendTransaction} from '@privy-io/react-auth/tempo';
    import {encodeFunctionData, parseAbi} from 'viem';

    const usdc = '0x20c000000000000000000000b9537d11c60e8b50';

    function SendSponsoredTempoTransaction() {
      const {wallets} = useWallets();
      const {sendTransaction} = useSendTransaction();

      const handleSend = async () => {
        const {hash} = await sendTransaction(
          {
            transaction: {
              type: 118,
              chainId: 4217, // use 42431 for Tempo Moderato (testnet)
              calls: [
                {
                  to: usdc,
                  data: encodeFunctionData({
                    abi: parseAbi([
                      'function transfer(address to, uint256 amount) public returns (bool)'
                    ]),
                    functionName: 'transfer',
                    args: ['0xRecipientAddress', 1_000_000n] // 1 USDC (6 decimals)
                  })
                }
              ]
            },
            wallet: wallets[0]
          },
          {sponsor: true}
        );
        console.log('Transaction hash:', hash);
      };

      return <button onClick={handleSend}>Send sponsored transaction</button>;
    }
    ```
  </View>

  <View title="REST API" icon="terminal">
    ```bash theme={"system"}
    curl --request POST https://api.privy.io/v1/wallets/<wallet_id>/rpc \
      -u "<app-id>:<app-secret>" \
      -H "privy-app-id: <app-id>" \
      -H "privy-authorization-signature: <authorization-signature>" \
      -H "Content-Type: application/json" \
      -d '{
        "method": "eth_sendTransaction",
        "caip2": "eip155:4217",
        "sponsor": true,
        "params": {
          "transaction": {
            "type": 118,
            "calls": [
              {
                "to": "0x20c000000000000000000000b9537d11c60e8b50",
                "data": "<encoded transfer calldata>"
              }
            ]
          }
        }
      }'
    ```
  </View>
</Accordion>

## Controlling transactions with policies

Privy's policy engine supports Tempo-specific transaction fields via the `tempo_transaction` field source. Your app can require a specific fee token, enforce or block transaction sponsorship, and time-bound validity windows, all without affecting standard EVM policy rules.

See [Tempo policy examples](/controls/policies/example-policies/tempo) for ready-to-use policy configurations.

## Related resources

<CardGroup cols={2}>
  <Card title="Send a transaction" icon="paper-plane" href="/wallets/using-wallets/ethereum/send-a-transaction">
    Complete guide to sending transactions with Privy
  </Card>

  <Card title="Gas sponsorship overview" icon="gas-pump" href="/wallets/gas-and-asset-management/gas/overview">
    Learn about Privy's gas sponsorship engine
  </Card>

  <Card title="Balance webhooks" icon="wallet" href="/wallets/gas-and-asset-management/assets/balance-event-webhooks">
    {' '}

    Subscribe to deposit and withdrawal events.{' '}
  </Card>

  <Card title="Create a wallet" icon="wallet" href="/wallets/wallets/create/create-a-wallet">
    Learn more about creating embedded wallets
  </Card>

  <Card title="Tempo policy examples" icon="shield-check" href="/controls/policies/example-policies/tempo">
    Configure policies for fee tokens, sponsorship, and time windows on Tempo
  </Card>
</CardGroup>
