viem
Version:
130 lines • 5.6 kB
JavaScript
// TODO: Find opportunities to make this file less duplicated + more simplified with Viem v3.
import * as Hex from 'ox/Hex';
import { Transaction as ox_Transaction, TransactionRequest as ox_TransactionRequest, } from 'ox/tempo';
import { parseAccount } from '../accounts/utils/parseAccount.js';
import { formatTransaction as viem_formatTransaction } from '../utils/formatters/transaction.js';
import { formatTransactionReceipt as viem_formatTransactionReceipt } from '../utils/formatters/transactionReceipt.js';
import { formatTransactionRequest as viem_formatTransactionRequest } from '../utils/formatters/transactionRequest.js';
import { isTempo, } from './Transaction.js';
export function formatTransaction(transaction) {
if (!isTempo(transaction))
return viem_formatTransaction(transaction);
// TODO: upstream `blockTimestamp` formatting into `ox`.
const blockTimestamp = transaction.blockTimestamp == null
? undefined
: BigInt(transaction.blockTimestamp);
const { feePayerSignature, gasPrice: _, nonce, ...tx } = ox_Transaction.fromRpc(transaction);
return {
...tx,
accessList: tx.accessList,
...(typeof blockTimestamp !== 'undefined' && { blockTimestamp }),
feePayerSignature: feePayerSignature
? {
r: Hex.fromNumber(feePayerSignature.r, { size: 32 }),
s: Hex.fromNumber(feePayerSignature.s, { size: 32 }),
v: BigInt(feePayerSignature.v ?? 27),
yParity: feePayerSignature.yParity,
}
: undefined,
nonce: Number(nonce),
typeHex: ox_Transaction.toRpcType[tx.type],
type: tx.type,
};
}
export function formatTransactionReceipt(receipt) {
return viem_formatTransactionReceipt(receipt);
}
export function formatTransactionRequest(r, action) {
const request = r;
const account = request.account
? parseAccount(request.account)
: undefined;
// If the request is not a Tempo transaction, route to Viem formatter.
if (!isTempo(request))
return viem_formatTransactionRequest(r, action);
if (action)
request.calls = request.calls ?? [
{
to: r.to ||
(!r.data || r.data === '0x'
? '0x0000000000000000000000000000000000000000'
: undefined),
value: r.value,
data: r.data,
},
];
// If we have marked the transaction as intended to be paid by a fee
// payer (feePayer: true), we strip the fee token from the sender's
// sign payload — per TIP-76 the sender does not commit to it; the fee
// payer chooses and commits to the token via its own signature.
//
// Once the fee payer has signed (`feePayerSignature` is populated),
// the relay has chosen a token and signed over it. The broadcast
// envelope must therefore include `feeToken` so the chain can verify
// the fee payer's signature and identify which token to charge.
if (request.feePayer === true && !request.feePayerSignature)
delete request.feeToken;
const rpc = ox_TransactionRequest.toRpc({
...request,
type: 'tempo',
});
if (action === 'estimateGas') {
rpc.maxFeePerGas = undefined;
rpc.maxPriorityFeePerGas = undefined;
}
rpc.to = undefined;
rpc.data = undefined;
rpc.value = undefined;
const [keyType, keyData] = (() => {
const type = account && 'keyType' in account ? account.keyType : account?.source;
if (!type)
return [request.keyType, shimKeyData(request.keyData)];
if (type === 'webAuthn')
// Send a 2-byte big-endian length hint (1400 = 0x0578) instead of a
// 1400-byte dummy blob. The node's gas estimator expects key_data to
// be 1, 2, or 4 bytes encoding the desired WebAuthn signature size;
// anything else falls back to the 800-byte default.
return ['webAuthn', '0x0578'];
if (['p256', 'secp256k1'].includes(type))
return [type, undefined];
return [request.keyType, shimKeyData(request.keyData)];
})();
const keyId = account && 'accessKeyAddress' in account
? account.accessKeyAddress
: request.keyId;
if (account)
rpc.from = account.address;
return {
...rpc,
...(request.capabilities ? { capabilities: request.capabilities } : {}),
...(keyData ? { keyData } : {}),
...(keyId ? { keyId } : {}),
...(keyType ? { keyType } : {}),
...(typeof request.feePayer !== 'undefined'
? {
feePayer: typeof request.feePayer === 'object'
? parseAccount(request.feePayer)
: request.feePayer,
}
: {}),
...('feePayerSignature' in request &&
request.feePayerSignature !== undefined
? { feePayerSignature: request.feePayerSignature }
: {}),
};
}
/**
* Auto-shim user-provided keyData that is longer than 4 bytes into a
* 2-byte big-endian length hint. The node gas estimator only accepts
* 1, 2, or 4-byte key_data as a size hint; anything else silently falls
* back to the 800-byte default.
*/
function shimKeyData(data) {
if (!data)
return data;
const byteLength = (data.length - 2) / 2; // subtract "0x" prefix
if (byteLength <= 4)
return data;
return Hex.fromNumber(byteLength, { size: 2 });
}
//# sourceMappingURL=Formatters.js.map