This guide shows you how to send a transaction from the connected wallet on an EVM chain such as DogeOS Chikyū Testnet: a DOGE transfer or a contract call. The SDK has no send method of its own; you send through the wallet’s provider. If your app uses Wagmi, use Wagmi’s useSendTransaction and useWriteContract instead; see Use the SDK With Wagmi.
The examples use viem to encode values and wait for the receipt. If your app doesn’t import viem yet, add it:
pnpm add viemSend DOGE#
- Make sure the wallet is on the right network. If
chainIdisn’t Chikyū’s,0x5fdaf3, switch it first. Inside MyDoge, a transaction whosechainIddoesn’t match the active network is rejected. - Send
eth_sendTransactionthroughcurrentProvider, with thechainIdyou expect. It resolves with the transaction hash once the user approves. - Wait for the receipt through the network’s RPC.
"use client"
import { useState } from "react"
import { createPublicClient, http, parseEther, toHex, type Hash } from "viem"
import { isWalletError, useAccount, WalletErrorCode } from "@dogeos/dogeos-sdk"
const chikyu = createPublicClient({ transport: http("https://rpc.testnet.dogeos.com/") })
export function SendDogeButton({ to }: { to: `0x${string}` }) {
const { address, chainId, currentProvider } = useAccount()
const [status, setStatus] = useState("")
async function onSend() {
if (!address || !currentProvider) return
if (chainId !== "0x5fdaf3") {
setStatus("Switch to DogeOS Chikyū Testnet first.")
return
}
try {
setStatus("Waiting for approval…")
const hash = (await currentProvider.request({
method: "eth_sendTransaction",
params: [{ from: address, to, value: toHex(parseEther("0.01")), chainId: "0x5fdaf3" }],
})) as Hash
setStatus("Waiting for confirmation…")
const receipt = await chikyu.waitForTransactionReceipt({ hash })
setStatus(receipt.status === "success" ? "Sent." : "The transaction failed.")
} catch (error) {
if (isWalletError(error, WalletErrorCode.UserRejected)) {
setStatus("")
return
}
setStatus(isWalletError(error) || error instanceof Error ? error.message : "Sending failed.")
}
}
return (
<div>
<button type="button" onClick={onSend}>
Send 0.01 DOGE
</button>
{status ? <p role="status">{status}</p> : null}
</div>
)
}value is in wei, as a hexadecimal string; parseEther converts DOGE amounts, since native DOGE has 18 decimals on DogeOS.
Call a Contract#
Encode the call with viem’s encodeFunctionData, and send it as the transaction’s data:
import { encodeFunctionData, parseAbi } from "viem"
const data = encodeFunctionData({
abi: parseAbi(["function transfer(address to, uint256 amount) returns (bool)"]),
functionName: "transfer",
args: [recipient, 1_000_000_000_000_000_000n],
})
const hash = await currentProvider.request({
method: "eth_sendTransaction",
params: [{ from: address, to: tokenAddress, data, chainId: "0x5fdaf3" }],
})Wait for the receipt the same way. To pay with DOGE in a contract, use native DOGE’s ERC-20 interface rather than wrapped DOGE; see Native DOGE as an ERC-20.
Handle Failures#
| What happens | Error | What to do |
|---|---|---|
| The user rejects the transaction | 4001 | Leave your UI as it was |
| The transaction is for another network (MyDoge) | -32602 | Switch networks, then send again |
| Sending fails after approval (MyDoge 3.1.1 and later) | -32603 | Show the message and offer a retry |
| The transaction reverts on chain | The receipt’s status is "reverted" | Show that it failed; the network fee is still paid |
On MyDoge 3.1.0, a transaction that fails after the user approves it is reported as 4001, the same as a rejection, so your app can’t tell the two apart there.
The Errors reference lists every code.