Was this helpful?
Attach 32-byte references to TIP-20 transfers for payment reconciliation. Use memos to link onchain transactions to your internal records—customer IDs, invoice numbers, or any identifier that helps you match payments to your database.
As an exchange, use a single master hot wallet for all customer deposits. Customers include their customer ID as the memo, and you credit their account by parsing the event.
import { Actions } from 'viem/tempo'
import { parseUnits, stringToHex, pad } from 'viem'
// Customer deposits with their customer ID
await Actions.token.transferSync(walletClient, {
token: tokenAddress,
to: exchangeHotWallet,
amount: parseUnits('500', 6),
memo: pad(stringToHex
Batch multiple payments in a single Tempo transaction with employee IDs in each memo for clear accounting records.
import { Abis } from 'viem/tempo'
import { encodeFunctionData, parseUnits, stringToHex, pad } from 'viem'
const calls = employees.map(emp => ({
to: tokenAddress,
data: encodeFunctionData({
abi: Abis.TIP20,
functionName: 'transferWithMemo',
Include a refund address in the memo so the recipient knows where to send funds if a reversal is needed.
import { Actions } from 'viem/tempo'
import { parseUnits, stringToHex, pad } from 'viem'
const refundMemo = pad(stringToHex('REFUND 0x742d35Cc6634C0532925a3b8'), { size: 32 })
await Actions.token.transferSync(walletClient, {
token: tokenAddress,
to: merchantAddress,
amount:
Establish a naming convention for your memos (e.g., CUST-{id}, INV-{number}, REFUND-{id}) to make parsing and filtering reliable across your system.
Memos are bytes32 values. Use toHex(string, { size: 32 }) to convert strings—if your string exceeds 32 bytes, it will be truncated. For longer references, store the full data offchain and use a hash or short ID as the memo.
The TransferWithMemo event has memo as an indexed parameter. Use getLogs with the args filter to query transactions by memo without scanning all events.
import { parseAbiItem, stringToHex, pad } from 'viem'
const logs = await client.getLogs({
address: tokenAddress,
event: parseAbiItem('event TransferWithMemo(address indexed from, address indexed to, uint256 value, bytes32 indexed memo)'),
args: { memo: pad(stringToHex('INV-12345'), { size: 32 }) },
})Use transferWithMemo to attach a reference to your payment. The memo is a 32-byte value that gets emitted in the TransferWithMemo event.
import { } from 'wagmi/tempo'
import { , } from 'viem'
import { } from 'wagmi'
export function () {
const { } = ()
const = ..()
const = () => {
.({
: '0x20c0000000000000000000000000000000000001',
: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
: ('100', 6),
: ('INV-12345', { : 32 }),
})
}
return (
< ={} ={.
{. ? 'Sending...' : 'Send Payment'}
</>
)
}import { } from 'viem/chains'
import { , }
import { } from 'wagmi'
import { } from 'viem'
import { } from 'viem/tempo'
export function ({ }: { : `0x${string}` }) {
({
: '0x20c0000000000000000000000000000000000001',
: .TIP20,
: 'TransferWithMemo',
: () => {
for (const of ) {
if (.args.to === ) {
const = (.args.memo, 'string').
.(`Received ${.args.value} with memo: ${}`)
}
}
},
})
return <>Watching for deposits...</>
}import { } from 'viem/chains'
import { , }