UNPKG

ox

Version:

Ethereum Standard Library

357 lines 15.3 kB
import * as core_Hex from '../../core/Hex.js'; import * as z_AccessList from '../AccessList.js'; import * as z_Address from '../Address.js'; import * as z_Hex from '../Hex.js'; import * as z_TransactionRequest from '../TransactionRequest.js'; import { encodeNumberish, uintBigintNumberish, uintNumberNumberish, } from '../internal/Integer.js'; import * as z from 'zod/mini'; import * as z_AuthorizationTempo from './AuthorizationTempo.js'; import * as z_KeyAuthorization from './KeyAuthorization.js'; import * as z_SignatureEnvelope from './SignatureEnvelope.js'; const fromRpcType = { '0x76': 'tempo' }; const toRpcType = { tempo: '0x76' }; const KeyType = z.union([ z.literal('secp256k1'), z.literal('p256'), z.literal('webAuthn'), ]); const SignatureRpc = z.object({ r: z_Hex.Hex, s: z_Hex.Hex, v: z.optional(z_Hex.Hex), yParity: z_Hex.Hex, }); const SignatureDecoded = z.object({ r: z_Hex.Hex, s: z_Hex.Hex, v: z.optional(z.number()), yParity: z.number(), }); const CallRpc = z.object({ data: z.optional(z_Hex.Hex), to: z.optional(z_Address.Address), value: z.optional(z_Hex.Hex), }); const Call = z.object({ data: z.optional(z_Hex.Hex), to: z.optional(z_Address.Address), value: z.optional(z.bigint()), }); const CallToRpc = z.object({ data: z.optional(z_Hex.Hex), to: z.optional(z_Address.Address), value: z.optional(uintBigintNumberish()), }); const Capabilities = z.record(z.string(), z.unknown()); const MultisigInit = z.object({ salt: z_Hex.Hex, threshold: z.number(), owners: z.readonly(z.array(z.object({ owner: z_Address.Address, weight: z.number() }))), }); /** RPC tempo transaction request schema. */ export const Rpc = z.object({ accessList: z.optional(z_AccessList.AccessList), authorizationList: z.optional(z_AuthorizationTempo.ListRpc), blobVersionedHashes: z.optional(z.readonly(z.array(z_Hex.Hex))), blobs: z.optional(z.readonly(z.array(z_Hex.Hex))), calls: z.optional(z.readonly(z.array(CallRpc))), capabilities: z.optional(Capabilities), chainId: z.optional(z_Hex.Hex), data: z.optional(z_Hex.Hex), feePayer: z.optional(z.boolean()), feePayerSignature: z.optional(z.union([SignatureRpc, z.null()])), feeToken: z.optional(z_Hex.Hex), from: z.optional(z_Address.Address), gas: z.optional(z_Hex.Hex), gasPrice: z.optional(z_Hex.Hex), input: z.optional(z_Hex.Hex), keyAuthorization: z.optional(z_KeyAuthorization.Rpc), keyData: z.optional(z_Hex.Hex), keyId: z.optional(z_Address.Address), keyType: z.optional(KeyType), maxFeePerBlobGas: z.optional(z_Hex.Hex), maxFeePerGas: z.optional(z_Hex.Hex), maxPriorityFeePerGas: z.optional(z_Hex.Hex), multisigInit: z.optional(MultisigInit), multisigSignatureCount: z.optional(z.number()), nonce: z.optional(z_Hex.Hex), nonceKey: z.optional(z_Hex.Hex), r: z.optional(z_Hex.Hex), s: z.optional(z_Hex.Hex), signature: z.optional(z_SignatureEnvelope.Rpc), to: z.optional(z.union([z_Address.Address, z.null()])), type: z.optional(z.string()), v: z.optional(z_Hex.Hex), validAfter: z.optional(z_Hex.Hex), validBefore: z.optional(z_Hex.Hex), value: z.optional(z_Hex.Hex), yParity: z.optional(z_Hex.Hex), }); const AuthorizationSigned = z.object({ address: z_Address.Address, chainId: z.number(), nonce: z.bigint(), signature: z_SignatureEnvelope.Domain, }); const AuthorizationSignedToRpc = z.object({ address: z_Address.Address, chainId: uintNumberNumberish(), nonce: uintBigintNumberish(), signature: z_SignatureEnvelope.Domain, }); /** Decoded tempo transaction request schema. */ export const Domain = z.object({ accessList: z.optional(z_AccessList.AccessList), authorizationList: z.optional(z.readonly(z.array(AuthorizationSigned))), blobVersionedHashes: z.optional(z.readonly(z.array(z_Hex.Hex))), blobs: z.optional(z.readonly(z.array(z_Hex.Hex))), calls: z.optional(z.readonly(z.array(Call))), capabilities: z.optional(Capabilities), chainId: z.optional(z.number()), data: z.optional(z_Hex.Hex), feePayer: z.optional(z.boolean()), feePayerSignature: z.optional(z.union([SignatureDecoded, z.null()])), feeToken: z.optional(z_Address.Address), from: z.optional(z_Address.Address), gas: z.optional(z.bigint()), gasPrice: z.optional(z.bigint()), input: z.optional(z_Hex.Hex), keyAuthorization: z.optional(z_KeyAuthorization.Domain), keyData: z.optional(z_Hex.Hex), keyId: z.optional(z_Address.Address), keyType: z.optional(KeyType), maxFeePerBlobGas: z.optional(z.bigint()), maxFeePerGas: z.optional(z.bigint()), maxPriorityFeePerGas: z.optional(z.bigint()), multisigInit: z.optional(MultisigInit), multisigSignatureCount: z.optional(z.number()), nonce: z.optional(z.bigint()), nonceKey: z.optional(z.union([z.bigint(), z.literal('random')])), r: z.optional(z_Hex.Hex), s: z.optional(z_Hex.Hex), signature: z.optional(z_SignatureEnvelope.Domain), to: z.optional(z.union([z_Address.Address, z.null()])), type: z.optional(z.string()), v: z.optional(z.number()), validAfter: z.optional(z.number()), validBefore: z.optional(z.number()), value: z.optional(z.bigint()), yParity: z.optional(z.number()), }); /** Encode-only decoded tempo transaction request schema accepting numberish `toRpc` inputs. */ export const DomainToRpc = z.object({ accessList: z.optional(z_AccessList.AccessList), authorizationList: z.optional(z.readonly(z.array(AuthorizationSignedToRpc))), blobVersionedHashes: z.optional(z.readonly(z.array(z_Hex.Hex))), blobs: z.optional(z.readonly(z.array(z_Hex.Hex))), calls: z.optional(z.readonly(z.array(CallToRpc))), capabilities: z.optional(Capabilities), chainId: z.optional(uintNumberNumberish()), data: z.optional(z_Hex.Hex), feePayer: z.optional(z.boolean()), feePayerSignature: z.optional(z.union([SignatureDecoded, z.null()])), feeToken: z.optional(z_Address.Address), from: z.optional(z_Address.Address), gas: z.optional(uintBigintNumberish()), gasPrice: z.optional(uintBigintNumberish()), input: z.optional(z_Hex.Hex), keyAuthorization: z.optional(z_KeyAuthorization.DomainToRpc), keyData: z.optional(z_Hex.Hex), keyId: z.optional(z_Address.Address), keyType: z.optional(KeyType), maxFeePerBlobGas: z.optional(uintBigintNumberish()), maxFeePerGas: z.optional(uintBigintNumberish()), maxPriorityFeePerGas: z.optional(uintBigintNumberish()), multisigInit: z.optional(MultisigInit), multisigSignatureCount: z.optional(z.number()), nonce: z.optional(uintBigintNumberish()), nonceKey: z.optional(z.union([uintBigintNumberish(), z.literal('random')])), r: z.optional(z_Hex.Hex), s: z.optional(z_Hex.Hex), signature: z.optional(z_SignatureEnvelope.Domain), to: z.optional(z.union([z_Address.Address, z.null()])), type: z.optional(z.string()), v: z.optional(z.number()), validAfter: z.optional(uintNumberNumberish()), validBefore: z.optional(uintNumberNumberish()), value: z.optional(uintBigintNumberish()), yParity: z.optional(z.number()), }); /** Codec decoding an RPC tempo transaction request into a transaction request. */ export const TransactionRequest = z.codec(Rpc, Domain, { decode: (value) => fromRpc(value), encode: (value) => toRpc(value), }); /** Encode-only tempo transaction request codec accepting numberish `toRpc` inputs. */ export const TransactionRequestToRpc = z.codec(Rpc, DomainToRpc, { decode: (value) => fromRpc(value), encode: (value) => toRpc(value), }); /** Decodes an RPC tempo transaction request into a transaction request. */ function fromRpc(request) { const { authorizationList: _, ...rest } = request; const request_ = z.decode(z_TransactionRequest.TransactionRequest, rest); if (typeof request.type !== 'undefined') request_.type = fromRpcType[request.type] || request_.type; if (request.authorizationList) request_.authorizationList = z.decode(z_AuthorizationTempo.ListSigned, request.authorizationList); if (request.signature) request_.signature = z.decode(z_SignatureEnvelope.SignatureEnvelope, request.signature); if (request.feePayerSignature) request_.feePayerSignature = signatureFromRpc(request.feePayerSignature); if (request.calls) request_.calls = request.calls.map((call) => ({ to: call.to, data: call.data, ...(call.value && call.value !== '0x' ? { value: core_Hex.toBigInt(call.value) } : {}), })); if (typeof request.feeToken !== 'undefined') request_.feeToken = request.feeToken; if (request.keyAuthorization) request_.keyAuthorization = z.decode(z_KeyAuthorization.KeyAuthorization, request.keyAuthorization); if (typeof request.capabilities !== 'undefined') request_.capabilities = request.capabilities; if (typeof request.feePayer !== 'undefined') request_.feePayer = request.feePayer; if (typeof request.keyData !== 'undefined') request_.keyData = request.keyData; if (typeof request.keyId !== 'undefined') request_.keyId = request.keyId; if (typeof request.keyType !== 'undefined') request_.keyType = request.keyType; if (typeof request.multisigInit !== 'undefined') request_.multisigInit = request.multisigInit; if (typeof request.multisigSignatureCount !== 'undefined') request_.multisigSignatureCount = request.multisigSignatureCount; if (typeof request.validBefore !== 'undefined') request_.validBefore = core_Hex.toNumber(request.validBefore); if (typeof request.validAfter !== 'undefined') request_.validAfter = core_Hex.toNumber(request.validAfter); if (typeof request.nonceKey !== 'undefined') request_.nonceKey = core_Hex.toBigInt(request.nonceKey); return request_; } /** Encodes a transaction request into an RPC tempo transaction request. */ function toRpc(request) { const request_rpc = z.encode(z_TransactionRequest.TransactionRequestToRpc, { ...request, authorizationList: undefined, }); const tempo = typeof request.calls !== 'undefined' || typeof request.capabilities !== 'undefined' || typeof request.feePayer !== 'undefined' || typeof request.feeToken !== 'undefined' || typeof request.keyAuthorization !== 'undefined' || typeof request.keyData !== 'undefined' || typeof request.keyId !== 'undefined' || typeof request.keyType !== 'undefined' || typeof request.multisigInit !== 'undefined' || typeof request.multisigSignatureCount !== 'undefined' || typeof request.nonceKey !== 'undefined' || typeof request.validBefore !== 'undefined' || typeof request.validAfter !== 'undefined' || request.type === 'tempo'; if (request.authorizationList) request_rpc.authorizationList = z.encode(z_AuthorizationTempo.ListSignedToRpc, request.authorizationList); if (request.signature) request_rpc.signature = z.encode(z_SignatureEnvelope.SignatureEnvelope, request.signature); if (request.feePayerSignature) request_rpc.feePayerSignature = signatureToRpc(request.feePayerSignature); if (request.calls) request_rpc.calls = request.calls.map((call) => ({ to: call.to, value: call.value ? encodeNumberish(call.value) : '0x', data: call.data ?? '0x', })); else if (request.to || request.data || request.value || tempo) request_rpc.calls = [ { to: request.to || (tempo && (!request.data || request.data === '0x') ? '0x0000000000000000000000000000000000000000' : undefined), value: request.value ? encodeNumberish(request.value) : '0x', data: request.data ?? '0x', }, ]; if (typeof request.feeToken !== 'undefined' && !(request.feePayer === true && !request.feePayerSignature)) request_rpc.feeToken = request.feeToken; if (request.keyAuthorization) request_rpc.keyAuthorization = z.encode(z_KeyAuthorization.KeyAuthorizationToRpc, request.keyAuthorization); if (typeof request.capabilities !== 'undefined') request_rpc.capabilities = request.capabilities; if (typeof request.feePayer !== 'undefined') request_rpc.feePayer = request.feePayer; if (typeof request.keyData !== 'undefined') request_rpc.keyData = shimKeyData(request.keyData); if (typeof request.keyId !== 'undefined') request_rpc.keyId = request.keyId; if (typeof request.keyType !== 'undefined') request_rpc.keyType = request.keyType; if (typeof request.multisigInit !== 'undefined') request_rpc.multisigInit = request.multisigInit; if (typeof request.multisigSignatureCount !== 'undefined') request_rpc.multisigSignatureCount = request.multisigSignatureCount; if (typeof request.validBefore !== 'undefined') request_rpc.validBefore = encodeNumberish(request.validBefore); if (typeof request.validAfter !== 'undefined') request_rpc.validAfter = encodeNumberish(request.validAfter); const nonceKey = (() => { if (request.nonceKey === 'random') return core_Hex.random(24); if (typeof request.nonceKey !== 'undefined') return encodeNumberish(request.nonceKey); return undefined; })(); if (nonceKey) request_rpc.nonceKey = nonceKey; if (tempo) { request_rpc.type = toRpcType.tempo; delete request_rpc.data; delete request_rpc.input; delete request_rpc.to; delete request_rpc.value; } return request_rpc; } /** * Shims key data longer than 4 bytes into a 2-byte big-endian length hint * (the node's gas estimator only accepts 1, 2, or 4-byte key data). */ function shimKeyData(data) { const byteLength = core_Hex.size(data); if (byteLength <= 4) return data; return core_Hex.fromNumber(byteLength, { size: 2 }); } /** Decodes an RPC signature into a recovered signature. */ function signatureFromRpc(signature) { const v = signature.v ? Number(signature.v) : undefined; let yParity = signature.yParity ? Number(signature.yParity) : undefined; if (typeof v === 'number' && typeof yParity !== 'number') { if (v === 0 || v === 27) yParity = 0; else if (v === 1 || v === 28) yParity = 1; else if (v >= 35) yParity = v % 2 === 0 ? 1 : 0; } return { r: core_Hex.padLeft(signature.r, 32), s: core_Hex.padLeft(signature.s, 32), yParity: yParity, }; } /** Encodes a recovered signature into an RPC signature. */ function signatureToRpc(signature) { return { r: signature.r, s: signature.s, yParity: signature.yParity === 0 ? '0x0' : '0x1', }; } //# sourceMappingURL=TransactionRequest.js.map