> Feedback: If these docs are stale, missing, or confusing, post sanitized feedback to `https://docs.tempo.xyz/api/feedback` with `source: "mcp"`, a short `message`, and any relevant `toolName`, `relatedResource`, or `client`.
# Accept a Payment

Accept stablecoin payments in your application. Learn how to receive payments, verify transactions, and reconcile payments using memos.

## Receiving Payments

Payments are automatically credited to the recipient's address when a transfer is executed. You don't need to do anything special to "accept" a payment, it happens automatically onchain.

In this basic receiving demo you can see the balances update after you add funds to your account, using the `getBalance` and `watchEvent` calls documented below.

<Demo.Container name="Receive a Payment" footerVariant="balances" tokens={[Token.alphaUsd, Token.betaUsd, Token.thetaUsd]} src="tempoxyz/examples/tree/main/examples/payments">
  <Connect stepNumber={1} />

  <AddFunds stepNumber={2} last />
</Demo.Container>

## Verifying Payments

Check if a payment has been received by querying the token balance or listening for transfer events:

### Check Balance

<Tabs stateKey="library">
  <Tab title="Viem">
    :::code-group

    ```ts [example.ts]
    import { client } from './viem.config'

    const balance = await client.token.getBalance({
      token: '0x20c0000000000000000000000000000000000001', // AlphaUSD
      address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
    })

    console.log('Balance:', balance)
    ```

    ```ts [viem.config.ts]
    // [!include ~/snippets/viem.config.ts:setup]
    ```

    :::
  </Tab>

  <Tab title="Rust">
    :::code-group

    ```rust [example.rs]
    use alloy::{primitives::address, providers::ProviderBuilder};
    use tempo_alloy::{TempoNetwork, contracts::precompiles::ITIP20};

    #[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?;

        let balance = ITIP20::new( // [!code focus]
            address!("0x20c0000000000000000000000000000000000001"), // AlphaUSD // [!code focus]
            &provider, // [!code focus]
        ) // [!code focus]
        .balanceOf(address!("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb")) // [!code focus]
        .call() // [!code focus]
        .await?; // [!code focus]

        println!("Balance: {balance:?}"); // [!code focus]

        Ok(())
    }
    ```

    ```rust [provider.rs]
    // [!include ~/snippets/rust-provider.rs:setup]
    ```

    :::
  </Tab>

  <Tab title="Python">
    :::code-group

    ```python [example.py]
    from web3 import Web3
    from eth_abi import encode
    from provider import w3

    token_address = "0x20c0000000000000000000000000000000000001"  # AlphaUSD
    account_address = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb"

    # balanceOf(address) selector: 0x70a08231
    calldata = "0x70a08231" + encode(["address"], [account_address]).hex() # [!code hl]
    result = w3.eth.call({"to": token_address, "data": calldata}) # [!code hl]
    balance = int.from_bytes(result, "big") # [!code hl]

    print(f"Balance: {balance}")
    ```

    ```python [provider.py]
    from web3 import Web3

    w3 = Web3(Web3.HTTPProvider("https://rpc.tempo.xyz"))
    ```

    :::
  </Tab>

  <Tab title="Go">
    :::code-group

    ```go [main.go]
    package main

    import (
    	"context"
    	"fmt"
    	"log"
    	"math/big"
    	"strings"
    )

    func main() {
    	c := newClient()
    	ctx := context.Background()

    	token := "0x20c0000000000000000000000000000000000001"
    	account := "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb"

    	// balanceOf(address) — ABI-encoded eth_call // [!code hl]
    	calldata := "0x70a08231" + fmt.Sprintf("%064s", strings.TrimPrefix(account, "0x")) // [!code hl]

    	resp, err := c.SendRequest(ctx, "eth_call", map[string]interface{}{ // [!code hl]
    		"to":   token, // [!code hl]
    		"data": calldata, // [!code hl]
    	}, "latest") // [!code hl]
    	if err != nil {
    		log.Fatal(err)
    	}

    	balance := new(big.Int) // [!code hl]
    	balance.SetString(strings.TrimPrefix(resp.Result.(string), "0x"), 16) // [!code hl]
    	fmt.Printf("Balance: %s\n", balance)
    }
    ```

    ```go [provider.go]
    // [!include ~/snippets/go-provider.go:setup]
    ```

    :::
  </Tab>

  <Tab title="Cast">
    ```bash
    $ cast call 0x20c0000000000000000000000000000000000001 \
      "balanceOf(address)(uint256)" \
      0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb \
      --rpc-url $TEMPO_RPC_URL
    ```
  </Tab>
</Tabs>

### Listen for Transfer Events

<Tabs stateKey="library">
  <Tab title="Viem">
    :::code-group

    ```ts [example.ts]
    import { client } from './viem.config'

    // Watch for incoming transfers
    const unwatch = client.watchEvent({
      address: '0x20c0000000000000000000000000000000000001',
      event: {
        type: 'event',
        name: 'Transfer',
        inputs: [
          { name: 'from', type: 'address', indexed: true },
          { name: 'to', type: 'address', indexed: true },
          { name: 'value', type: 'uint256' },
        ],
      },
      onLogs: (logs) => { // [!code focus]
        logs.forEach((log) => { // [!code focus]
          console.log('Received payment:', { // [!code focus]
            from: log.args.from, // [!code focus]
            amount: log.args.value, // [!code focus]
          }) // [!code focus]
        }) // [!code focus]
      }, // [!code focus]
    })
    ```

    ```ts [viem.config.ts]
    // [!include ~/snippets/viem.config.ts:setup]
    ```

    :::
  </Tab>

  <Tab title="Rust">
    :::code-group

    ```rust [example.rs]
    use alloy::{primitives::address, providers::ProviderBuilder};
    use futures::StreamExt;
    use tempo_alloy::{TempoNetwork, contracts::precompiles::ITIP20};

    #[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?;

        // Watch for incoming transfers // [!code focus]
        let mut transfers = ITIP20::new( // [!code focus]
            address!("0x20c0000000000000000000000000000000000001"), // [!code focus]
            &provider, // [!code focus]
        ) // [!code focus]
        .Transfer_filter() // [!code focus]
        .watch() // [!code focus]
        .await? // [!code focus]
        .into_stream(); // [!code focus]

        while let Some(Ok((payment, _))) = transfers.next().await { // [!code focus]
            println!("Received payment: {payment:?}") // [!code focus]
        } // [!code focus]

        Ok(())
    }
    ```

    ```rust [provider.rs]
    // [!include ~/snippets/rust-provider.rs:setup]
    ```

    :::
  </Tab>

  <Tab title="Python">
    :::code-group

    ```python [example.py]
    import json
    from web3 import Web3
    from provider import w3

    token_address = "0x20c0000000000000000000000000000000000001"  # AlphaUSD

    transfer_event_abi = { # [!code focus]
        "anonymous": False, # [!code focus]
        "name": "Transfer", # [!code focus]
        "type": "event", # [!code focus]
        "inputs": [ # [!code focus]
            {"indexed": True, "name": "from", "type": "address"}, # [!code focus]
            {"indexed": True, "name": "to", "type": "address"}, # [!code focus]
            {"indexed": False, "name": "value", "type": "uint256"}, # [!code focus]
        ], # [!code focus]
    } # [!code focus]

    contract = w3.eth.contract( # [!code focus]
        address=Web3.to_checksum_address(token_address), # [!code focus]
        abi=[transfer_event_abi], # [!code focus]
    ) # [!code focus]

    # Get historical Transfer events # [!code focus]
    events = contract.events.Transfer().get_logs(from_block="latest") # [!code focus]
    for event in events: # [!code focus]
        print(f"Transfer: {event.args['from']} -> {event.args['to']}: {event.args['value']}") # [!code focus]
    ```

    ```python [provider.py]
    from web3 import Web3

    w3 = Web3(Web3.HTTPProvider("https://rpc.tempo.xyz"))
    ```

    :::
  </Tab>

  <Tab title="Go">
    :::code-group

    ```go [main.go]
    package main

    import (
    	"context"
    	"fmt"
    	"log"

    	"github.com/ethereum/go-ethereum/crypto"
    )

    func main() {
    	c := newClient()
    	ctx := context.Background()

    	token := "0x20c0000000000000000000000000000000000001"

    	// Transfer(address,address,uint256) event topic // [!code focus]
    	transferTopic := crypto.Keccak256Hash([]byte("Transfer(address,address,uint256)")) // [!code focus]

    	resp, err := c.SendRequest(ctx, "eth_getLogs", map[string]interface{}{ // [!code focus]
    		"fromBlock": "0x0", // [!code focus]
    		"toBlock":   "latest", // [!code focus]
    		"address":   token, // [!code focus]
    		"topics":    []interface{}{transferTopic.Hex()}, // [!code focus]
    	}) // [!code focus]
    	if err != nil {
    		log.Fatal(err)
    	}

    	logs, _ := resp.Result.([]interface{}) // [!code focus]
    	for _, entry := range logs { // [!code focus]
    		l := entry.(map[string]interface{}) // [!code focus]
    		topics := l["topics"].([]interface{}) // [!code focus]
    		fmt.Printf("Transfer: %s -> %s (data: %s)\n", topics[1], topics[2], l["data"]) // [!code focus]
    	} // [!code focus]
    }
    ```

    ```go [provider.go]
    // [!include ~/snippets/go-provider.go:setup]
    ```

    :::
  </Tab>

  <Tab title="Cast">
    ```bash
    $ cast logs \
      --address 0x20c0000000000000000000000000000000000001 \
      "Transfer(address indexed, address indexed, uint256)" \
      --rpc-url $TEMPO_RPC_URL
    ```
  </Tab>
</Tabs>

## Payment Reconciliation with Memos

If payments include memos (invoice IDs, order numbers, etc.), you can reconcile them automatically:

<Tabs stateKey="library">
  <Tab title="Viem">
    :::code-group

    ```ts [example.ts]
    import { client } from './viem.config'

    // Watch for TransferWithMemo events
    const unwatch = client.watchEvent({
      address: '0x20c0000000000000000000000000000000000001',
      event: {
        type: 'event',
        name: 'TransferWithMemo',
        inputs: [
          { name: 'from', type: 'address', indexed: true },
          { name: 'to', type: 'address', indexed: true },
          { name: 'value', type: 'uint256' },
          { name: 'memo', type: 'bytes32', indexed: true },
        ],
      },
      onLogs: (logs) => { // [!code focus]
        logs.forEach((log) => { // [!code focus]
          const invoiceId = log.args.memo // [!code focus]
          // Mark invoice as paid in your database // [!code focus]
          markInvoiceAsPaid(invoiceId, log.args.value) // [!code focus]
        }) // [!code focus]
      }, // [!code focus]
    })
    ```

    ```ts [viem.config.ts]
    // [!include ~/snippets/viem.config.ts:setup]
    ```

    :::
  </Tab>

  <Tab title="Rust">
    :::code-group

    ```rust [example.rs]
    use alloy::{primitives::address, providers::ProviderBuilder};
    use futures::StreamExt;
    use tempo_alloy::{TempoNetwork, contracts::precompiles::ITIP20};

    #[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?;

        let mut transfers = ITIP20::new( // [!code focus]
            address!("0x20c0000000000000000000000000000000000001"), // [!code focus]
            &provider, // [!code focus]
        ) // [!code focus]
        .TransferWithMemo_filter() // [!code focus]
        .watch() // [!code focus]
        .await? // [!code focus]
        .into_stream(); // [!code focus]

        while let Some(Ok((transfer, _))) = transfers.next().await { // [!code focus]
            let invoice_id = transfer.memo; // [!code focus]
            println!("Transfer received with memo: {invoice_id:?}"); // [!code focus]
        } // [!code focus]

        Ok(())
    }
    ```

    ```rust [provider.rs]
    // [!include ~/snippets/rust-provider.rs:setup]
    ```

    :::
  </Tab>

  <Tab title="Python">
    :::code-group

    ```python [example.py]
    from web3 import Web3
    from provider import w3

    token_address = "0x20c0000000000000000000000000000000000001"  # AlphaUSD

    transfer_memo_abi = { # [!code focus]
        "anonymous": False, # [!code focus]
        "name": "TransferWithMemo", # [!code focus]
        "type": "event", # [!code focus]
        "inputs": [ # [!code focus]
            {"indexed": True, "name": "from", "type": "address"}, # [!code focus]
            {"indexed": True, "name": "to", "type": "address"}, # [!code focus]
            {"indexed": False, "name": "value", "type": "uint256"}, # [!code focus]
            {"indexed": True, "name": "memo", "type": "bytes32"}, # [!code focus]
        ], # [!code focus]
    } # [!code focus]

    contract = w3.eth.contract( # [!code focus]
        address=Web3.to_checksum_address(token_address), # [!code focus]
        abi=[transfer_memo_abi], # [!code focus]
    ) # [!code focus]

    events = contract.events.TransferWithMemo().get_logs(from_block="latest") # [!code focus]
    for event in events: # [!code focus]
        invoice_id = event.args["memo"] # [!code focus]
        print(f"Transfer with memo {invoice_id.hex()}: {event.args['value']}") # [!code focus]
    ```

    ```python [provider.py]
    from web3 import Web3

    w3 = Web3(Web3.HTTPProvider("https://rpc.tempo.xyz"))
    ```

    :::
  </Tab>

  <Tab title="Go">
    :::code-group

    ```go [main.go]
    package main

    import (
    	"context"
    	"fmt"
    	"log"

    	"github.com/ethereum/go-ethereum/crypto"
    )

    func main() {
    	c := newClient()
    	ctx := context.Background()

    	token := "0x20c0000000000000000000000000000000000001"

    	// TransferWithMemo(address,address,uint256,bytes32) event topic // [!code focus]
    	memoTopic := crypto.Keccak256Hash( // [!code focus]
    		[]byte("TransferWithMemo(address,address,uint256,bytes32)"), // [!code focus]
    	) // [!code focus]

    	resp, err := c.SendRequest(ctx, "eth_getLogs", map[string]interface{}{ // [!code focus]
    		"fromBlock": "0x0", // [!code focus]
    		"toBlock":   "latest", // [!code focus]
    		"address":   token, // [!code focus]
    		"topics":    []interface{}{memoTopic.Hex()}, // [!code focus]
    	}) // [!code focus]
    	if err != nil {
    		log.Fatal(err)
    	}

    	logs, _ := resp.Result.([]interface{}) // [!code focus]
    	for _, entry := range logs { // [!code focus]
    		l := entry.(map[string]interface{}) // [!code focus]
    		topics := l["topics"].([]interface{}) // [!code focus]
    		fmt.Printf("Transfer: %s -> %s (memo: %s, data: %s)\n", // [!code focus]
    			topics[1], topics[2], topics[3], l["data"]) // [!code focus]
    	} // [!code focus]
    }
    ```

    ```go [provider.go]
    // [!include ~/snippets/go-provider.go:setup]
    ```

    :::
  </Tab>

  <Tab title="Cast">
    ```bash
    $ cast logs \
      --address 0x20c0000000000000000000000000000000000001 \
      "TransferWithMemo(address indexed, address indexed, uint256, bytes32 indexed)" \
      --rpc-url $TEMPO_RPC_URL
    ```
  </Tab>
</Tabs>

## Smart Contract Integration

If you're building a smart contract that accepts payments:

```solidity
contract PaymentReceiver {
    ITIP20 public token;
    mapping(bytes32 => bool) public paidInvoices;
    
    event PaymentReceived(
        address indexed payer,
        uint256 amount,
        bytes32 indexed invoiceId
    );
    
    function receivePayment(
        address payer,
        uint256 amount,
        bytes32 invoiceId
    ) external {
        require(!paidInvoices[invoiceId], "Invoice already paid");
        
        // Transfer tokens from payer to this contract
        token.transferFrom(payer, address(this), amount);
        
        paidInvoices[invoiceId] = true;
        emit PaymentReceived(payer, amount, invoiceId);
    }
}
```

## Payment Verification Best Practices

1. **Verify onchain**: Always verify payments onchain before marking orders as paid
2. **Use memos**: Request memos from payers to link payments to invoices or orders
3. **Check confirmations**: Wait for transaction finality (~1 second on Tempo) before processing
4. **Handle edge cases**: Account for partial payments, refunds, and failed transactions

## Cross-Stablecoin Payments

If you need to accept payments in a specific stablecoin but receive a different one, use the exchange to swap:

```ts
// User sends USDG, but you need USDT
// Swap USDG to USDT using the exchange
const { receipt } = await client.dex.sellSync({
  tokenIn: usdgAddress,
  tokenOut: usdtAddress,
  amountIn: receivedAmount,
  minAmountOut: receivedAmount * 99n / 100n, // 1% slippage
})
```

## Next Steps

* **[Send a payment](/docs/guide/payments/send-a-payment)** to learn how to send payments
* Learn more about [Exchange](/docs/guide/stablecoin-dex) for cross-stablecoin payments
