Daimo Pay SDK
The best way to embed Daimo Pay into your app is via the @daimo/pay
SDK.
The SDK is open source. You can find it on NPM and GitHub. For installation instructions, see the Quickstart. For a live demo of common use-cases, see the Demo Page. For more details, see below.

DaimoPayButton Reference
Here are the three ways to use Daimo Pay when configuring it with your appId
Mode | Set | Result |
---|---|---|
Checkout | toAddress , toChain , toToken , toUnits | Shows a fixed amount. Funds settle to toAddress . |
Deposit | toAddress , toChain , toToken | User chooses amount. Funds settle to toAddress . |
Contract Call | toAddress , toChain , toToken , toUnits , toCallData | Converts to toToken , auto-approves toUnits , then calls the contract at toAddress with toCallData . |
- Name
appId
*- Type
- string
- Description
Your public app ID. Use
pay-demo
for prototyping only.
- Name
intent
- Type
- string
- Description
The intent verb, sets the modal title and the primary button label. Examples: "Pay", "Deposit", or "Add Money".
Purely visual. Does not change payment behavior.
- Name
toAddress
*- Type
- string
- Description
The destination address to transfer to, or contract to call.
Contract whitelist required
If thetoAddress
is a contract it must be whitelisted first. Email founders@daimo.com with:
Whitelist contract: 0xYourContractAddress
Chain: <chainId>
- Name
toChain
*- Type
- number
- Description
The destination chain ID
toAddress
is on.
- Name
toUnits
- Type
- string
- Description
Controls the exact amount to receive. Must be a precise decimal string (e.g. "1.00" for $1.00 USDC). Providing more decimals than the underlying token supports will result in an error.
When specified: User pays a fixed amount. You receive exactly this amount. Ideal for checkouts.
When omitted: User can input any amount to send. Ideal for deposits or top-ups into your app.
- Name
toToken
*- Type
- string
- Description
Token to receive on the destination chain. Provide an ERC20 address or use the zero address
0x000…0000
to receive the native token. Examples: ETH, CELO, POL.
IftoCallData
is set andtoToken
is an ERC-20, the amount is approved totoAddress
immediately before the call; otherwise the amount is transferred totoAddress
.Use constants from
@daimo/pay-common
to avoid typos and ensuretoToken
matchestoChain
.
- Name
refundAddress*
*- Type
- string
- Description
Required fallback refund address. Must be valid on all supported networks.
How refunds are routed- Wallet flow (user pays from a connected wallet):
If the payment bounces, the refund is automatically returned to that wallet. - Manual address flow (user copies an address/QR):
If the payment bounces or the user underpays/overpays, the refund is sent torefundAddress
.
We do this because we cannot reliably refund to exchange/custodial deposit addresses.
Choose an address you control on every supported network so refunds never get stuck.
- Wallet flow (user pays from a connected wallet):
- Name
toCallData
- Type
- string
- Description
Optional calldata to execute an arbitrary contract call if
toAddress
is a contract. If specified, we'll automatically make a token approval oftoUnits
to the contract before executing the call.Contract whitelist required To request whitelisting email us at founders@daimo.com with:
Whitelist contract: 0xYourContractAddress
Chain: <chainId>
- Name
paymentOptions
- Type
- string[]
- Description
Optional filter to display only a subset of payment options. By default, all payment options are enabled.
TheWallet
andManual Address
options are always enabled and cannot be disabled.
Lets you filter these options:AllExchanges
,Coinbase
,Binance
,Lemon
,AllPaymentApps
(desktop only),Venmo
,CashApp
,MercadoPago
,Revolut
,Wise
,Zelle
.
With these options, even users without a wallet can complete the flow.
- Name
preferredChains
- Type
- number[]
- Description
Optional preferred chain IDs. Assets on these chains will appear first.
- Name
preferredTokens
- Type
- object[]
- Description
Optional preferred tokens. Assets in these specific tokens will appear first, taking precedence over
preferredChains
. Each token has the format:{ chain: number, address: string }
.
- Name
metadata
- Type
- object
- Description
Optional. Attach key-value data to the payment object that persists across webhooks and API responses. For example, attach your system’s unique ID to simplify tracking, or store customer information with their payment.
You can specify up to 50 key-value pairs. Keys and values are stored as strings.
- Name
redirectReturnUrl
- Type
- string
- Description
Optional. Redirect URL to return to the app. After the user pays with
Coinbase
,Binance
, or one of thePayment Apps
, they will be redirected back to this URL.
- Name
defaultOpen
- Type
- boolean
- Description
Optional. If set, automatically open the modal on first render.
- Name
closeOnSuccess
- Type
- boolean
- Description
Optional. If set, automatically closes the modal after a successful payment.
- Name
resetOnSuccess
- Type
- boolean
- Description
Optional. If set, automatically resets the payment after a successful transaction, using the original props. This allows the user to initiate a new payment without refreshing the page.
import { encodeFunctionData, getAddress } from "viem";
import { optimismUSDC } from '@daimo/pay-common'
<DaimoPayButton
{/* Required props */}
appId="pay-demo"
toAddress="RECIPIENT_ADDRESS_HERE" or "CONTRACT_ADDRESS_HERE"
toChain={optimismUSDC.chainId} /* Optimism Chain ID*/
toToken={getAddress(optimismUSDC.token)} /* Optimism USDC */
{/* Optional props */}
intent="Checkout"
toUnits="1.00" /* 1 USDC */
toCallData={encodeFunctionData({ /* Example contract call */
abi: YOUR_CONTRACT_ABI,
functionName: "FUNCTION_NAME",
args: ["RECIPIENT_ADDRESS", quantity],
})}
paymentOptions={["Coinbase", "Binance"]}
preferredChains={[42161, 8453]} // Prefer Arbitrum, Base
preferredTokens={[ // Prefer Optimism USDC
{ chain: 10, address: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85" }
]},
metadata={{ mySystemId: "123", name: "John Doe" }}
defaultOpen() /* Automatically open the modal */
closeOnSuccess() /* Automatically close the modal after transaction*/
resetOnSuccess() /* Reset modal after a successful transaction */
{/* Event handlers */}
onPaymentStarted={(e) => console.log(e)}
onPaymentCompleted={(e) => console.log(e)}
onPaymentBounced={(e) => console.log(e)}
onOpen={() => console.log("Modal opened")}
onClose={() => console.log("Modal closed")}
/>
Alternatively, if you want to use Daimo Pay via the Payments API, you can initialize a payment by passing its payId
to DaimoPayButton
.
- Name
payId
*- Type
- string
- Description
Use
id
generated from your api call.
- Name
defaultOpen
- Type
- boolean
- Description
Optional. If set, automatically open the modal on first render.
- Name
closeOnSuccess
- Type
- boolean
- Description
Optional. If set, automatically closes the modal after a successful payment.
- Name
resetOnSuccess
- Type
- boolean
- Description
Optional. If set, automatically resets the payment after a successful transaction, using the original props. This allows the user to initiate a new payment without refreshing the page.
<DaimoPayButton
payId="EqxRaFwRHjtXHBJTJuvCxr8nmhNjrNZtVGcHLEDGgn1F"
defaultOpen() /* Automatically open the modal */
closeOnSuccess() /* Automatically close the modal after transaction*/
resetOnSuccess() /* Reset modal after a successful transaction */
/>
Modifying Payment Parameters
Once the DaimoPayButton
is rendered, its payment parameters are frozen to ensure a consistent and predictable user experience. This means that changes to props like toUnits
or toAddress
after initial render will not automatically update the current payment.
If your app needs to dynamically update the payment, such as when the user
changes the amount, selects a different token, or switches networks, you can
use the resetPayment
function provided by the useDaimoPayUI
hook.
Calling resetPayment
updates the current payment parameters. It accepts the
same parameters as DaimoPayButton
. You can pass only the props you wish to
change, any omitted fields will retain their previous values.
import { useDaimoPayUI } from "@daimo/pay";
const { resetPayment } = useDaimoPayUI();
// Example: user selects a new amount and token
function handleAmountChange(newAmount: string) {
resetPayment({
toChain: 8453, // Base
toUnits: newAmount, // updated amount
toToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // Base USDC
});
}
Themes and Customization
You can customize the look of both the button and the modal.
- Modal: Configure in
DaimoPayProvider
usingmode
,theme
, orcustomTheme
. - Button: Provide your own UI with
DaimoPayButton.Custom
.
- Name
mode
- Type
- string
- Description
Light, dark, or auto. Ignored if
theme
orcustomTheme
is set.
- Name
theme
- Type
- string
- Description
Named theme for the modal and wallet UI. One of:
auto
|web95
|retro
|soft
|midnight
|minimal
|rounded
|nouns
. Default:auto
. See the ConnectKit theming docs for previews.Note:
theme
(orcustomTheme
) overridesmode
. Usetheme="auto"
to follow the user’s system preference.
- Name
customTheme
- Type
- object
- Description
Custom theme overrides for the modal and wallet UI. Use this when
theme
is not enough.
Build and export themes with the ConnectKit theme builder
import { Roboto } from "next/font/google";
const roboto = Roboto({
variable: "--font-roboto",
subsets: ["latin"],
weight: ["300", "400", "500", "700", "900"],
});
// Only override the font
const robotoTheme = {
'--ck-font-family': 'var(--font-roboto)',
}
<DaimoPayProvider
mode="dark" /* will be override by customTheme */
{/* alternatively, theme="auto" */}
customTheme={robotoTheme}
/>
DaimoPayButton.Custom
In addition, you can replace the DaimoPayButton entirely with your own button using DaimoPayButton.Custom.
- Name
children
*- Type
- function
- Description
Custom renderer function that receives show/hide methods and returns React node.
<DaimoPayButton.Custom
appId="pay-demo"
toAddress="0x1234567890123456789012345678901234567890"
toChain={10} /* Optimism */
toUnits="1.23" /* $1.23 Optimism USDC */
toToken="0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85" /* Optimism USDC */
>
{({ show, hide }) => <button onClick={show}>Custom Pay Button</button>}
</DaimoPayButton.Custom>
Event Handlers
- Name
onPaymentStarted
- Type
- function
- Description
Called when the user sends payment and the transaction is seen on-chain.
- Name
onPaymentCompleted
- Type
- function
- Description
Called when the destination transfer or call completes successfully.
- Name
onPaymentBounced
- Type
- function
- Description
Called when the destination call reverts and funds are refunded.
- Name
onOpen
- Type
- function
- Description
Called when the payment modal opens. Useful for analytics or UI transitions.
- Name
onClose
- Type
- function
- Description
Called when the payment modal closes, whether from user dismissal or after a completed payment.
The events passed to the onPayment...
handlers match the events passed to
webhooks. You can use them for immediate feedback, while using
webhooks for things like backend order status tracking. This ensures robust
tracking even if the user loses network during payment.
const [latest, setLatest] = useState<DaimoPayEvent>();
return (<>
<DaimoPayButton
{/* For existing payments created via API, use payId. */}
payId="72hebvwpDJDA9qNubzb2jYjAbdDgjH4uD53rBnh8BR3A"
{/* Either way, the onPayment... handlers always work. */}
onPaymentStarted={setLatest}
onPaymentCompleted={setLatest}
onPaymentBounced={setLatest}
onOpen={() => console.log("Modal opened")}
onClose={() => console.log("Modal closed")}
/>
{latest.type === 'payment_started' && <Spinner />}
{latest.type === 'payment_completed' && <SuccessLink txHash={latest.txHash} />}
{latest.type === 'payment_bounced' && <RevertLink txHash={latest.txHash} />}
</>);
Configuration Reference
The @daimo/pay
SDK uses a configuration object to set up providers for your
application. This configuration is essential for initializing the SDK and
ensuring compatibility with the supported chains and transports. Below is a
detailed reference to the configuration options available in defaultConfig
.
defaultConfig
Parameters
- Name
appName
*- Type
- string
- Description
Required name of your application. This is displayed to users during wallet connections and other interactions.
- Name
appIcon
- Type
- string
- Description
Optional URL pointing to the app's icon. Used in wallet connection UIs.
- Name
appDescription
- Type
- string
- Description
Optional description of your app. Shown to users in wallet connection prompts.
- Name
appUrl
- Type
- string
- Description
Optional URL of your app. Used in wallet connection interfaces.
- Name
ssr
- Type
- boolean
- Description
Indicates whether the app uses server-side rendering (SSR). Set to
true
for SSR-enabled projects. Default isfalse
.
- Name
connectors
- Type
- function[]
- Description
Specifies wallet connectors. Defaults to Daimo's recommended connectors and configurations. Will override all default connectors and
additionalConnectors
.
- Name
additionalConnectors
- Type
- function[]
- Description
Optional additional wallet connectors to use in the configuration. Extend the list of default connectors with custom wallet connectors.
- Name
transports
- Type
- object
- Description
Defines the network transport (e.g., HTTP) for each supported chain. If not provided, default wagmi HTTP transports are used.
import { getDefaultConfig } from "@daimo/pay";
import { createConfig, http } from "wagmi";
import { mainnet, optimism } from "wagmi/chains";
// Define your configuration
const config = createConfig(
getDefaultConfig({
appName: "My Ethereum App",
appIcon: "https://example.com/icon.png",
appDescription: "An app for seamless crypto payments",
appUrl: "https://example.com",
additionalConnectors: [], // Add custom wallet connectors here
transports: {
[mainnet.id]: http("https://eth.llamarpc.com"),
[optimism.id]: http("https://optimism-rpc.publicnode.com"),
},
}),
);