Appearance
Sign with policy
Every request names the subject that authorizes it and the chain it targets. Omitted, both resolve to the signed-in wallet and a configured chain; pass them explicitly when your product manages more than one wallet or chain at a time. No unlock step is required: every request opens the wallet confirmation, and the user approves that transaction with the wallet's auth method. The examples below use useWallet for buttons and the SeamsWeb client for standalone signing calls.
NEAR transaction
This example sends a set_greeting function call to a NEAR testnet account. Replace the receiver, action, and execution status with values from your app.
tsx
import { functionCall, logWalletEvents, TxExecutionStatus, useWallet } from '@seams/wallet/react';
export function SetGreetingButton() {
// `near` is null when nobody is signed in, and when the signed-in wallet has
// no NEAR account yet. One check covers both; read `status` to tell them apart.
const { near } = useWallet();
if (!near) return null;
const onSign = async (): Promise<void> => {
// Each request opens the wallet confirmation, where the user approves this
// transaction with the wallet's auth method.
await near.signAndSendTransaction({
receiverId: 'guest-book.testnet',
actions: [functionCall({ method: 'set_greeting', args: { greeting: 'Hello from Seams' } })],
options: {
waitUntil: TxExecutionStatus.EXECUTED_OPTIMISTIC,
onEvent: logWalletEvents(),
},
});
};
return <button onClick={() => void onSign()}>Sign transaction</button>;
}wallet.near is null until the wallet has a NEAR account, so the check next to the sign button is a type guard rather than a convention — a request cannot start without one. For an exact subject, call seams.near.signAndSendTransaction with walletSession and nearAccount built from walletSessionRefFromSession and nearAccountRefFromAccountId.
EVM-family transaction
seams.evm signs EIP-1559 transactions; seams.tempo signs Tempo's EIP-2718 typed transactions. The two mirror each other — signTransaction, executeTransaction, and an advanced group — and stay separate because the envelopes and the signed results differ: seams.evm yields txHashHex, seams.tempo yields senderHashHex.
Build the transaction with your EVM utilities, then name the chain: a configured network slug like 'ethereum-sepolia' resolves to exactly one configured chain, and a selector matching two throws and names both rather than picking one. seams.chainTarget(selector) resolves the same value up front, and an exact chain target is still accepted.
ts
import { logWalletEvents, type SeamsWeb } from '@seams/wallet';
// EIP-1559 on any configured EVM chain. `seams.tempo` mirrors this API for
// Tempo's EIP-2718 typed transactions; the two stay separate because the
// envelopes and the signed results differ.
export async function executeEvmTransaction(seams: SeamsWeb): Promise<string> {
const execution = await seams.evm.executeTransaction({
// A configured network slug. The RPC endpoint comes from that chain, and
// `tx.chainId` is filled in from it. Omitting `walletSession` targets the
// authenticated wallet.
chainTarget: 'ethereum-sepolia',
request: {
chain: 'evm',
kind: 'eip1559',
senderSignatureAlgorithm: 'secp256k1',
tx: {
maxPriorityFeePerGas: 1n,
maxFeePerGas: 1n,
gasLimit: 21_000n,
to: '0x1234567890abcdef1234567890abcdef12345678',
value: 0n,
data: '0x',
},
},
options: { onEvent: logWalletEvents() },
});
console.log('transaction hash', execution.txHash);
return execution.txHash;
}The example targets Tempo testnet and uses placeholder transaction values. Replace the chain, recipient, fees, and data before sending a real transaction. tx.chainId is filled in from the chain target, and the RPC endpoint comes from the chain you configured — neither is repeated on the call. A successful call returns the transaction hash.
Use signTransaction when your application broadcasts the payload itself; the post-broadcast reporting lives on seams.evm.advanced and seams.tempo.advanced.
Sign with less friction
Per-transaction approval is the right default while you integrate. When your product needs a burst of signatures without prompting for each one, provision a signing session with unlock: read wallet sessions and signing lanes.
Handle cancellation and retries
- Treat a cancelled confirmation or policy denial as the result of the current request and show a clear retry action.
- If broadcast status is uncertain, reconcile the transaction or nonce before submitting another request.
- Keep the
onEventcallback attached while you build progress UI or audit logs; each canonical example shows the same event shape.