UNPKG

accounts

Version:

Tempo Accounts SDK

141 lines 5.72 kB
import { Hex, RpcRequest, RpcResponse } from 'ox'; import { KeyAuthorization, Transaction as core_Transaction, TxEnvelopeTempo } from 'ox/tempo'; import { BaseError } from 'viem'; import * as z from 'zod/mini'; export function resolveChainId(value) { if (typeof value === 'number') return value; if (typeof value === 'bigint') return Number(value); if (typeof value === 'string') { if (Hex.validate(value)) return Hex.toNumber(value); const n = Number(value); if (Number.isFinite(n)) return n; } return undefined; } export function formatFillTransactionRequest(client, value) { const format = client.chain?.formatters?.transactionRequest?.format; if (!format) return value; return format({ ...value }, 'fillTransaction'); } export function normalizeFillTransactionRequest(tx) { const { to, data, value, ...rest } = tx; const keyAuthorization = normalizeKeyAuthorization(tx.keyAuthorization); const withKeyAuthorization = keyAuthorization ? { keyAuthorization } : {}; if (Array.isArray(tx.calls) && tx.calls.length > 0) return { ...tx, ...withKeyAuthorization, calls: tx.calls.map((call) => ({ ...call, value: normalizeFillValue(call.value), })), }; const call = { ...(typeof to !== 'undefined' ? { to } : {}), ...(typeof data !== 'undefined' ? { data } : {}), ...(typeof value !== 'undefined' ? { value: normalizeFillValue(value) } : {}), }; return { ...rest, ...withKeyAuthorization, calls: [call] }; } /** * Forwards `keyAuthorization` to the chain in RPC shape. Pass-through * when already RPC; convert via `KeyAuthorization.toRpc` when internal. */ function normalizeKeyAuthorization(value) { if (!value || typeof value !== 'object') return undefined; const ka = value; const signature = ka.signature; if (!signature || typeof signature !== 'object') return undefined; const isInternal = typeof signature.signature === 'object' && signature.signature !== null; return isInternal ? KeyAuthorization.toRpc(value) : value; } function normalizeFillValue(value) { if (typeof value !== 'string' || !value.startsWith('0x')) return value; return BigInt(value === '0x' ? '0x0' : value); } /** Returns whether a raw transaction uses a Tempo sender or fee-payer wire prefix. */ export function isSerializedTempoTransaction(value) { if (typeof value !== 'string') return false; // `0x78` is Tempo's fee-payer handoff magic, not a separate EIP-2718 type. return (value.startsWith(TxEnvelopeTempo.serializedType) || value.startsWith(TxEnvelopeTempo.feePayerMagic)); } export function normalizeTempoTransaction(value) { if (!value) throw new Error('Expected `tx` in eth_fillTransaction response.'); return core_Transaction.fromRpc({ type: '0x76', ...value }); } /** Returns a raw JSON-RPC error response object (not wrapped in a `Response`). */ export function rpcErrorJson(request, error) { if (error instanceof RpcResponse.InvalidParamsError) return RpcResponse.from({ error }, { request }); if (error instanceof RpcResponse.MethodNotSupportedError) return RpcResponse.from({ error }, { request }); if (error.name === 'ZodError') return RpcResponse.from({ error: new RpcResponse.InvalidParamsError({ message: error.message, }), }, { request }); const inner = resolveError(error); if (inner.code === RpcResponse.InternalError.code && inner.message !== undefined && /^Revm error: transaction expired\.?$/.test(inner.message)) return RpcResponse.from({ error: { code: -32003, data: { code: 'transaction_expired' }, message: 'Transaction expired.', }, }, { request }); const message = inner.message ?? error.message; const code = inner.code ?? -32603; const data = inner.data; return RpcResponse.from({ error: { code, message, ...(data ? { data } : {}) }, }, { request }); } export function rpcError(request, error) { return Response.json(rpcErrorJson(request, error)); } export function rpcResult(request, result) { return Response.json(RpcResponse.from({ result }, { request })); } export const parseParams = z.readonly(z.tuple([z.record(z.string(), z.unknown())])); function resolveError(error) { if (!error || typeof error !== 'object') return {}; // Walk the `cause` chain to the deepest object that looks like an upstream // JSON-RPC error (`{ code, message }`). This unwraps viem's // `RpcRequestError`, whose own `message` is the verbose // "RPC Request failed.\nURL: …\nRequest body: …" formatting, and surfaces // the raw upstream error instead. let deepest; let current = error; const seen = new Set(); while (current && typeof current === 'object' && !seen.has(current)) { seen.add(current); const e = current; if (typeof e.code === 'number' && typeof e.message === 'string') deepest = { code: e.code, message: e.message, data: e.data }; current = e.cause; } if (deepest) return deepest; if (error instanceof BaseError) { const inner = error.walk((e) => typeof e.code === 'number'); if (inner && typeof inner.code === 'number' && typeof inner.message === 'string') return { message: inner.message, code: inner.code, data: inner.data }; } return {}; } //# sourceMappingURL=utils.js.map