FRE-600: Fix code review blockers

- Consolidated duplicate UndoManagers to single instance
- Fixed connection promise to only resolve on 'connected' status
- Fixed WebSocketProvider import (WebsocketProvider)
- Added proper doc.destroy() cleanup
- Renamed isPresenceInitialized property to avoid conflict

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-04-25 00:08:01 -04:00
parent 65b552bb08
commit 7c684a42cc
48450 changed files with 5679671 additions and 383 deletions

390
node_modules/viem/utils/abi/decodeAbiParameters.ts generated vendored Normal file
View File

@@ -0,0 +1,390 @@
import type {
AbiParameter,
AbiParameterKind,
AbiParametersToPrimitiveTypes,
} from 'abitype'
import {
AbiDecodingDataSizeTooSmallError,
AbiDecodingZeroDataError,
InvalidAbiDecodingTypeError,
type InvalidAbiDecodingTypeErrorType,
} from '../../errors/abi.js'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import {
type ChecksumAddressErrorType,
checksumAddress,
} from '../address/getAddress.js'
import {
type CreateCursorErrorType,
type Cursor,
createCursor,
} from '../cursor.js'
import { type SizeErrorType, size } from '../data/size.js'
import { type SliceBytesErrorType, sliceBytes } from '../data/slice.js'
import { type TrimErrorType, trim } from '../data/trim.js'
import {
type BytesToBigIntErrorType,
type BytesToBoolErrorType,
type BytesToNumberErrorType,
type BytesToStringErrorType,
bytesToBigInt,
bytesToBool,
bytesToNumber,
bytesToString,
} from '../encoding/fromBytes.js'
import { type HexToBytesErrorType, hexToBytes } from '../encoding/toBytes.js'
import { type BytesToHexErrorType, bytesToHex } from '../encoding/toHex.js'
import { getArrayComponents } from './encodeAbiParameters.js'
export type DecodeAbiParametersReturnType<
params extends readonly AbiParameter[] = readonly AbiParameter[],
> = AbiParametersToPrimitiveTypes<
params extends readonly AbiParameter[] ? params : AbiParameter[],
AbiParameterKind,
true
>
export type DecodeAbiParametersErrorType =
| HexToBytesErrorType
| BytesToHexErrorType
| DecodeParameterErrorType
| SizeErrorType
| CreateCursorErrorType
| ErrorType
export function decodeAbiParameters<
const params extends readonly AbiParameter[],
>(
params: params,
data: ByteArray | Hex,
): DecodeAbiParametersReturnType<params> {
const bytes = typeof data === 'string' ? hexToBytes(data) : data
const cursor = createCursor(bytes)
if (size(bytes) === 0 && params.length > 0)
throw new AbiDecodingZeroDataError()
if (size(data) && size(data) < 32)
throw new AbiDecodingDataSizeTooSmallError({
data: typeof data === 'string' ? data : bytesToHex(data),
params: params as readonly AbiParameter[],
size: size(data),
})
let consumed = 0
const values = []
for (let i = 0; i < params.length; ++i) {
const param = params[i]
cursor.setPosition(consumed)
const [data, consumed_] = decodeParameter(cursor, param, {
staticPosition: 0,
})
consumed += consumed_
values.push(data)
}
return values as never
}
type DecodeParameterErrorType =
| DecodeArrayErrorType
| DecodeTupleErrorType
| DecodeAddressErrorType
| DecodeBoolErrorType
| DecodeBytesErrorType
| DecodeNumberErrorType
| DecodeStringErrorType
| InvalidAbiDecodingTypeErrorType
function decodeParameter(
cursor: Cursor,
param: AbiParameter,
{ staticPosition }: { staticPosition: number },
) {
const arrayComponents = getArrayComponents(param.type)
if (arrayComponents) {
const [length, type] = arrayComponents
return decodeArray(cursor, { ...param, type }, { length, staticPosition })
}
if (param.type === 'tuple')
return decodeTuple(cursor, param as TupleAbiParameter, { staticPosition })
if (param.type === 'address') return decodeAddress(cursor)
if (param.type === 'bool') return decodeBool(cursor)
if (param.type.startsWith('bytes'))
return decodeBytes(cursor, param, { staticPosition })
if (param.type.startsWith('uint') || param.type.startsWith('int'))
return decodeNumber(cursor, param)
if (param.type === 'string') return decodeString(cursor, { staticPosition })
throw new InvalidAbiDecodingTypeError(param.type, {
docsPath: '/docs/contract/decodeAbiParameters',
})
}
////////////////////////////////////////////////////////////////////
// Type Decoders
const sizeOfLength = 32
const sizeOfOffset = 32
type DecodeAddressErrorType =
| ChecksumAddressErrorType
| BytesToHexErrorType
| SliceBytesErrorType
| ErrorType
function decodeAddress(cursor: Cursor) {
const value = cursor.readBytes(32)
return [checksumAddress(bytesToHex(sliceBytes(value, -20))), 32]
}
type DecodeArrayErrorType = BytesToNumberErrorType | ErrorType
function decodeArray(
cursor: Cursor,
param: AbiParameter,
{ length, staticPosition }: { length: number | null; staticPosition: number },
) {
// If the length of the array is not known in advance (dynamic array),
// this means we will need to wonder off to the pointer and decode.
if (!length) {
// Dealing with a dynamic type, so get the offset of the array data.
const offset = bytesToNumber(cursor.readBytes(sizeOfOffset))
// Start is the static position of current slot + offset.
const start = staticPosition + offset
const startOfData = start + sizeOfLength
// Get the length of the array from the offset.
cursor.setPosition(start)
const length = bytesToNumber(cursor.readBytes(sizeOfLength))
// Check if the array has any dynamic children.
const dynamicChild = hasDynamicChild(param)
let consumed = 0
const value: unknown[] = []
for (let i = 0; i < length; ++i) {
// If any of the children is dynamic, then all elements will be offset pointer, thus size of one slot (32 bytes).
// Otherwise, elements will be the size of their encoding (consumed bytes).
cursor.setPosition(startOfData + (dynamicChild ? i * 32 : consumed))
const [data, consumed_] = decodeParameter(cursor, param, {
staticPosition: startOfData,
})
consumed += consumed_
value.push(data)
}
// As we have gone wondering, restore to the original position + next slot.
cursor.setPosition(staticPosition + 32)
return [value, 32]
}
// If the length of the array is known in advance,
// and the length of an element deeply nested in the array is not known,
// we need to decode the offset of the array data.
if (hasDynamicChild(param)) {
// Dealing with dynamic types, so get the offset of the array data.
const offset = bytesToNumber(cursor.readBytes(sizeOfOffset))
// Start is the static position of current slot + offset.
const start = staticPosition + offset
const value: unknown[] = []
for (let i = 0; i < length; ++i) {
// Move cursor along to the next slot (next offset pointer).
cursor.setPosition(start + i * 32)
const [data] = decodeParameter(cursor, param, {
staticPosition: start,
})
value.push(data)
}
// As we have gone wondering, restore to the original position + next slot.
cursor.setPosition(staticPosition + 32)
return [value, 32]
}
// If the length of the array is known in advance and the array is deeply static,
// then we can just decode each element in sequence.
let consumed = 0
const value: unknown[] = []
for (let i = 0; i < length; ++i) {
const [data, consumed_] = decodeParameter(cursor, param, {
staticPosition: staticPosition + consumed,
})
consumed += consumed_
value.push(data)
}
return [value, consumed]
}
type DecodeBoolErrorType = BytesToBoolErrorType | ErrorType
function decodeBool(cursor: Cursor) {
return [bytesToBool(cursor.readBytes(32), { size: 32 }), 32]
}
type DecodeBytesErrorType =
| BytesToNumberErrorType
| BytesToHexErrorType
| ErrorType
function decodeBytes(
cursor: Cursor,
param: AbiParameter,
{ staticPosition }: { staticPosition: number },
) {
const [_, size] = param.type.split('bytes')
if (!size) {
// Dealing with dynamic types, so get the offset of the bytes data.
const offset = bytesToNumber(cursor.readBytes(32))
// Set position of the cursor to start of bytes data.
cursor.setPosition(staticPosition + offset)
const length = bytesToNumber(cursor.readBytes(32))
// If there is no length, we have zero data.
if (length === 0) {
// As we have gone wondering, restore to the original position + next slot.
cursor.setPosition(staticPosition + 32)
return ['0x', 32]
}
const data = cursor.readBytes(length)
// As we have gone wondering, restore to the original position + next slot.
cursor.setPosition(staticPosition + 32)
return [bytesToHex(data), 32]
}
const value = bytesToHex(cursor.readBytes(Number.parseInt(size, 10), 32))
return [value, 32]
}
type DecodeNumberErrorType =
| BytesToNumberErrorType
| BytesToBigIntErrorType
| ErrorType
function decodeNumber(cursor: Cursor, param: AbiParameter) {
const signed = param.type.startsWith('int')
const size = Number.parseInt(param.type.split('int')[1] || '256', 10)
const value = cursor.readBytes(32)
return [
size > 48
? bytesToBigInt(value, { signed })
: bytesToNumber(value, { signed }),
32,
]
}
type TupleAbiParameter = AbiParameter & { components: readonly AbiParameter[] }
type DecodeTupleErrorType = BytesToNumberErrorType | ErrorType
function decodeTuple(
cursor: Cursor,
param: TupleAbiParameter,
{ staticPosition }: { staticPosition: number },
) {
// Tuples can have unnamed components (i.e. they are arrays), so we must
// determine whether the tuple is named or unnamed. In the case of a named
// tuple, the value will be an object where each property is the name of the
// component. In the case of an unnamed tuple, the value will be an array.
const hasUnnamedChild =
param.components.length === 0 || param.components.some(({ name }) => !name)
// Initialize the value to an object or an array, depending on whether the
// tuple is named or unnamed.
const value: any = hasUnnamedChild ? [] : {}
let consumed = 0
// If the tuple has a dynamic child, we must first decode the offset to the
// tuple data.
if (hasDynamicChild(param)) {
// Dealing with dynamic types, so get the offset of the tuple data.
const offset = bytesToNumber(cursor.readBytes(sizeOfOffset))
// Start is the static position of referencing slot + offset.
const start = staticPosition + offset
for (let i = 0; i < param.components.length; ++i) {
const component = param.components[i]
cursor.setPosition(start + consumed)
const [data, consumed_] = decodeParameter(cursor, component, {
staticPosition: start,
})
consumed += consumed_
value[hasUnnamedChild ? i : component?.name!] = data
}
// As we have gone wondering, restore to the original position + next slot.
cursor.setPosition(staticPosition + 32)
return [value, 32]
}
// If the tuple has static children, we can just decode each component
// in sequence.
for (let i = 0; i < param.components.length; ++i) {
const component = param.components[i]
const [data, consumed_] = decodeParameter(cursor, component, {
staticPosition,
})
value[hasUnnamedChild ? i : component?.name!] = data
consumed += consumed_
}
return [value, consumed]
}
type DecodeStringErrorType =
| BytesToNumberErrorType
| BytesToStringErrorType
| TrimErrorType
| ErrorType
function decodeString(
cursor: Cursor,
{ staticPosition }: { staticPosition: number },
) {
// Get offset to start of string data.
const offset = bytesToNumber(cursor.readBytes(32))
// Start is the static position of current slot + offset.
const start = staticPosition + offset
cursor.setPosition(start)
const length = bytesToNumber(cursor.readBytes(32))
// If there is no length, we have zero data (empty string).
if (length === 0) {
cursor.setPosition(staticPosition + 32)
return ['', 32]
}
const data = cursor.readBytes(length, 32)
const value = bytesToString(trim(data))
// As we have gone wondering, restore to the original position + next slot.
cursor.setPosition(staticPosition + 32)
return [value, 32]
}
function hasDynamicChild(param: AbiParameter) {
const { type } = param
if (type === 'string') return true
if (type === 'bytes') return true
if (type.endsWith('[]')) return true
if (type === 'tuple') return (param as any).components?.some(hasDynamicChild)
const arrayComponents = getArrayComponents(param.type)
if (
arrayComponents &&
hasDynamicChild({ ...param, type: arrayComponents[1] } as AbiParameter)
)
return true
return false
}

60
node_modules/viem/utils/abi/decodeDeployData.ts generated vendored Normal file
View File

@@ -0,0 +1,60 @@
import type { Abi } from 'abitype'
import {
AbiConstructorNotFoundError,
type AbiConstructorNotFoundErrorType,
AbiConstructorParamsNotFoundError,
type AbiConstructorParamsNotFoundErrorType,
} from '../../errors/abi.js'
import type { ErrorType } from '../../errors/utils.js'
import type { ContractConstructorArgs } from '../../types/contract.js'
import type { Hex } from '../../types/misc.js'
import {
type DecodeAbiParametersErrorType,
decodeAbiParameters,
} from './decodeAbiParameters.js'
const docsPath = '/docs/contract/decodeDeployData'
export type DecodeDeployDataParameters<
abi extends Abi | readonly unknown[] = Abi,
> = {
abi: abi
bytecode: Hex
data: Hex
}
export type DecodeDeployDataReturnType<
abi extends Abi | readonly unknown[] = Abi,
///
allArgs = ContractConstructorArgs<abi>,
> = {
bytecode: Hex
args: allArgs
}
export type DecodeDeployDataErrorType =
| AbiConstructorNotFoundErrorType
| AbiConstructorParamsNotFoundErrorType
| DecodeAbiParametersErrorType
| ErrorType
export function decodeDeployData<const abi extends Abi | readonly unknown[]>(
parameters: DecodeDeployDataParameters<abi>,
): DecodeDeployDataReturnType<abi> {
const { abi, bytecode, data } = parameters as DecodeDeployDataParameters
if (data === bytecode) return { bytecode } as DecodeDeployDataReturnType<abi>
const description = abi.find((x) => 'type' in x && x.type === 'constructor')
if (!description) throw new AbiConstructorNotFoundError({ docsPath })
if (!('inputs' in description))
throw new AbiConstructorParamsNotFoundError({ docsPath })
if (!description.inputs || description.inputs.length === 0)
throw new AbiConstructorParamsNotFoundError({ docsPath })
const args = decodeAbiParameters(
description.inputs,
`0x${data.replace(bytecode, '')}`,
)
return { args, bytecode } as unknown as DecodeDeployDataReturnType<abi>
}

92
node_modules/viem/utils/abi/decodeErrorResult.ts generated vendored Normal file
View File

@@ -0,0 +1,92 @@
import type { Abi, ExtractAbiError } from 'abitype'
import { solidityError, solidityPanic } from '../../constants/solidity.js'
import {
AbiDecodingZeroDataError,
type AbiDecodingZeroDataErrorType,
AbiErrorSignatureNotFoundError,
type AbiErrorSignatureNotFoundErrorType,
} from '../../errors/abi.js'
import type { BaseError } from '../../errors/base.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
AbiItem,
ContractErrorArgs,
ContractErrorName,
} from '../../types/contract.js'
import type { Hex } from '../../types/misc.js'
import type { IsNarrowable, UnionEvaluate } from '../../types/utils.js'
import { slice } from '../data/slice.js'
import {
type ToFunctionSelectorErrorType,
toFunctionSelector,
} from '../hash/toFunctionSelector.js'
import {
type DecodeAbiParametersErrorType,
decodeAbiParameters,
} from './decodeAbiParameters.js'
import { type FormatAbiItemErrorType, formatAbiItem } from './formatAbiItem.js'
export type DecodeErrorResultParameters<
abi extends Abi | readonly unknown[] = Abi,
> = { abi?: abi | undefined; data: Hex; cause?: BaseError | Error | undefined }
export type DecodeErrorResultReturnType<
abi extends Abi | readonly unknown[] = Abi,
///
allErrorNames extends ContractErrorName<abi> = ContractErrorName<abi>,
> = IsNarrowable<abi, Abi> extends true
? UnionEvaluate<
{
[errorName in allErrorNames]: {
abiItem: abi extends Abi
? Abi extends abi
? AbiItem
: ExtractAbiError<abi, errorName>
: AbiItem
args: ContractErrorArgs<abi, errorName>
errorName: errorName
}
}[allErrorNames]
>
: {
abiItem: AbiItem
args: readonly unknown[] | undefined
errorName: string
}
export type DecodeErrorResultErrorType =
| AbiDecodingZeroDataErrorType
| AbiErrorSignatureNotFoundErrorType
| DecodeAbiParametersErrorType
| FormatAbiItemErrorType
| ToFunctionSelectorErrorType
| ErrorType
export function decodeErrorResult<const abi extends Abi | readonly unknown[]>(
parameters: DecodeErrorResultParameters<abi>,
): DecodeErrorResultReturnType<abi> {
const { abi, data, cause } = parameters as DecodeErrorResultParameters
const signature = slice(data, 0, 4)
if (signature === '0x') throw new AbiDecodingZeroDataError({ cause })
const abi_ = [...(abi || []), solidityError, solidityPanic]
const abiItem = abi_.find(
(x) =>
x.type === 'error' && signature === toFunctionSelector(formatAbiItem(x)),
)
if (!abiItem)
throw new AbiErrorSignatureNotFoundError(signature, {
docsPath: '/docs/contract/decodeErrorResult',
cause,
})
return {
abiItem,
args:
'inputs' in abiItem && abiItem.inputs && abiItem.inputs.length > 0
? decodeAbiParameters(abiItem.inputs, slice(data, 4))
: undefined,
errorName: (abiItem as { name: string }).name,
} as DecodeErrorResultReturnType<abi>
}

232
node_modules/viem/utils/abi/decodeEventLog.ts generated vendored Normal file
View File

@@ -0,0 +1,232 @@
import type { Abi, AbiParameter } from 'abitype'
import {
AbiDecodingDataSizeTooSmallError,
type AbiDecodingDataSizeTooSmallErrorType,
AbiEventSignatureEmptyTopicsError,
type AbiEventSignatureEmptyTopicsErrorType,
AbiEventSignatureNotFoundError,
type AbiEventSignatureNotFoundErrorType,
DecodeLogDataMismatch,
type DecodeLogDataMismatchErrorType,
DecodeLogTopicsMismatch,
type DecodeLogTopicsMismatchErrorType,
} from '../../errors/abi.js'
import { PositionOutOfBoundsError } from '../../errors/cursor.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
ContractEventArgsFromTopics,
ContractEventName,
EventDefinition,
} from '../../types/contract.js'
import type { Hex } from '../../types/misc.js'
import type {
IsNarrowable,
Prettify,
UnionEvaluate,
} from '../../types/utils.js'
import { size } from '../data/size.js'
import {
type ToEventSelectorErrorType,
toEventSelector,
} from '../hash/toEventSelector.js'
import {
type DecodeAbiParametersErrorType,
decodeAbiParameters,
} from './decodeAbiParameters.js'
import { type FormatAbiItemErrorType, formatAbiItem } from './formatAbiItem.js'
export type DecodeEventLogParameters<
abi extends Abi | readonly unknown[] = Abi,
eventName extends ContractEventName<abi> | undefined = ContractEventName<abi>,
topics extends Hex[] = Hex[],
data extends Hex | undefined = undefined,
strict extends boolean = true,
> = {
abi: abi
data?: data | undefined
eventName?: eventName | ContractEventName<abi> | undefined
strict?: strict | boolean | undefined
topics: [signature: Hex, ...args: topics] | []
}
export type DecodeEventLogReturnType<
abi extends Abi | readonly unknown[] = Abi,
eventName extends ContractEventName<abi> | undefined = ContractEventName<abi>,
topics extends Hex[] = Hex[],
data extends Hex | undefined = undefined,
strict extends boolean = true,
///
allEventNames extends
ContractEventName<abi> = eventName extends ContractEventName<abi>
? eventName
: ContractEventName<abi>,
> = IsNarrowable<abi, Abi> extends true
? {
[name in allEventNames]: Prettify<
{
eventName: name
} & UnionEvaluate<
ContractEventArgsFromTopics<abi, name, strict> extends infer allArgs
? topics extends readonly []
? data extends undefined
? { args?: undefined }
: { args?: allArgs | undefined }
: { args: allArgs }
: never
>
>
}[allEventNames]
: {
eventName: eventName
args: readonly unknown[] | undefined
}
export type DecodeEventLogErrorType =
| AbiDecodingDataSizeTooSmallErrorType
| AbiEventSignatureEmptyTopicsErrorType
| AbiEventSignatureNotFoundErrorType
| DecodeAbiParametersErrorType
| DecodeLogTopicsMismatchErrorType
| DecodeLogDataMismatchErrorType
| FormatAbiItemErrorType
| ToEventSelectorErrorType
| ErrorType
const docsPath = '/docs/contract/decodeEventLog'
export function decodeEventLog<
const abi extends Abi | readonly unknown[],
eventName extends ContractEventName<abi> | undefined = undefined,
topics extends Hex[] = Hex[],
data extends Hex | undefined = undefined,
strict extends boolean = true,
>(
parameters: DecodeEventLogParameters<abi, eventName, topics, data, strict>,
): DecodeEventLogReturnType<abi, eventName, topics, data, strict> {
const {
abi,
data,
strict: strict_,
topics,
} = parameters as DecodeEventLogParameters
const strict = strict_ ?? true
const [signature, ...argTopics] = topics
if (!signature) throw new AbiEventSignatureEmptyTopicsError({ docsPath })
const abiItem = abi.find(
(x) =>
x.type === 'event' &&
signature === toEventSelector(formatAbiItem(x) as EventDefinition),
)
if (!(abiItem && 'name' in abiItem) || abiItem.type !== 'event')
throw new AbiEventSignatureNotFoundError(signature, { docsPath })
const { name, inputs } = abiItem
const isUnnamed = inputs?.some((x) => !('name' in x && x.name))
const args: any = isUnnamed ? [] : {}
// Decode topics (indexed args).
const indexedInputs = inputs
.map((x, i) => [x, i] as const)
.filter(([x]) => 'indexed' in x && x.indexed)
const missingIndexedInputs: [AbiParameter, number][] = []
for (let i = 0; i < indexedInputs.length; i++) {
const [param, argIndex] = indexedInputs[i]
const topic = argTopics[i]
if (!topic) {
if (strict)
throw new DecodeLogTopicsMismatch({
abiItem,
param: param as AbiParameter & { indexed: boolean },
})
// Track missing indexed inputs to decode from data when strict is false
missingIndexedInputs.push([param, argIndex])
continue
}
args[isUnnamed ? argIndex : param.name || argIndex] = decodeTopic({
param,
value: topic,
})
}
// Decode data (non-indexed args + missing indexed args when strict is false).
const nonIndexedInputs = inputs.filter((x) => !('indexed' in x && x.indexed))
// When strict is false, missing indexed inputs should be decoded from data
const inputsToDecode = strict
? nonIndexedInputs
: [...missingIndexedInputs.map(([param]) => param), ...nonIndexedInputs]
if (inputsToDecode.length > 0) {
if (data && data !== '0x') {
try {
const decodedData = decodeAbiParameters(
inputsToDecode,
data,
) as unknown[]
if (decodedData) {
let dataIndex = 0
// First, assign missing indexed parameters (when strict is false)
if (!strict) {
for (const [param, argIndex] of missingIndexedInputs) {
args[isUnnamed ? argIndex : param.name || argIndex] =
decodedData[dataIndex++]
}
}
// Then, assign non-indexed parameters
if (isUnnamed) {
for (let i = 0; i < inputs.length; i++)
if (args[i] === undefined && dataIndex < decodedData.length)
args[i] = decodedData[dataIndex++]
} else
for (let i = 0; i < nonIndexedInputs.length; i++)
args[nonIndexedInputs[i].name!] = decodedData[dataIndex++]
}
} catch (err) {
if (strict) {
if (
err instanceof AbiDecodingDataSizeTooSmallError ||
err instanceof PositionOutOfBoundsError
)
throw new DecodeLogDataMismatch({
abiItem,
data: data,
params: inputsToDecode,
size: size(data),
})
throw err
}
}
} else if (strict) {
throw new DecodeLogDataMismatch({
abiItem,
data: '0x',
params: inputsToDecode,
size: 0,
})
}
}
return {
eventName: name,
args: Object.values(args).length > 0 ? args : undefined,
} as unknown as DecodeEventLogReturnType<abi, eventName, topics, data, strict>
}
function decodeTopic({ param, value }: { param: AbiParameter; value: Hex }) {
if (
param.type === 'string' ||
param.type === 'bytes' ||
param.type === 'tuple' ||
param.type.match(/^(.*)\[(\d+)?\]$/)
)
return value
const decodedArg = decodeAbiParameters([param], value) || []
return decodedArg[0]
}

78
node_modules/viem/utils/abi/decodeFunctionData.ts generated vendored Normal file
View File

@@ -0,0 +1,78 @@
import type { Abi, AbiStateMutability } from 'abitype'
import { AbiFunctionSignatureNotFoundError } from '../../errors/abi.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
ContractFunctionArgs,
ContractFunctionName,
} from '../../types/contract.js'
import type { Hex } from '../../types/misc.js'
import type { IsNarrowable, UnionEvaluate } from '../../types/utils.js'
import { type SliceErrorType, slice } from '../data/slice.js'
import {
type ToFunctionSelectorErrorType,
toFunctionSelector,
} from '../hash/toFunctionSelector.js'
import {
type DecodeAbiParametersErrorType,
decodeAbiParameters,
} from './decodeAbiParameters.js'
import { type FormatAbiItemErrorType, formatAbiItem } from './formatAbiItem.js'
export type DecodeFunctionDataParameters<
abi extends Abi | readonly unknown[] = Abi,
> = {
abi: abi
data: Hex
}
export type DecodeFunctionDataReturnType<
abi extends Abi | readonly unknown[] = Abi,
///
allFunctionNames extends
ContractFunctionName<abi> = ContractFunctionName<abi>,
> = IsNarrowable<abi, Abi> extends true
? UnionEvaluate<
{
[functionName in allFunctionNames]: {
args: ContractFunctionArgs<abi, AbiStateMutability, functionName>
functionName: functionName
}
}[allFunctionNames]
>
: {
args: readonly unknown[] | undefined
functionName: string
}
export type DecodeFunctionDataErrorType =
| AbiFunctionSignatureNotFoundError
| DecodeAbiParametersErrorType
| FormatAbiItemErrorType
| ToFunctionSelectorErrorType
| SliceErrorType
| ErrorType
export function decodeFunctionData<const abi extends Abi | readonly unknown[]>(
parameters: DecodeFunctionDataParameters<abi>,
) {
const { abi, data } = parameters as DecodeFunctionDataParameters
const signature = slice(data, 0, 4)
const description = abi.find(
(x) =>
x.type === 'function' &&
signature === toFunctionSelector(formatAbiItem(x)),
)
if (!description)
throw new AbiFunctionSignatureNotFoundError(signature, {
docsPath: '/docs/contract/decodeFunctionData',
})
return {
functionName: (description as { name: string }).name,
args: ('inputs' in description &&
description.inputs &&
description.inputs.length > 0
? decodeAbiParameters(description.inputs, slice(data, 4))
: undefined) as readonly unknown[] | undefined,
} as DecodeFunctionDataReturnType<abi>
}

166
node_modules/viem/utils/abi/decodeFunctionResult.ts generated vendored Normal file
View File

@@ -0,0 +1,166 @@
import type { Abi, AbiStateMutability, ExtractAbiFunctions } from 'abitype'
import {
AbiFunctionNotFoundError,
type AbiFunctionNotFoundErrorType,
AbiFunctionOutputsNotFoundError,
type AbiFunctionOutputsNotFoundErrorType,
} from '../../errors/abi.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
ContractFunctionArgs,
ContractFunctionName,
ContractFunctionReturnType,
Widen,
} from '../../types/contract.js'
import type { Hex } from '../../types/misc.js'
import type { IsNarrowable, UnionEvaluate } from '../../types/utils.js'
import {
type DecodeAbiParametersErrorType,
decodeAbiParameters,
} from './decodeAbiParameters.js'
import { type GetAbiItemErrorType, getAbiItem } from './getAbiItem.js'
const docsPath = '/docs/contract/decodeFunctionResult'
export type DecodeFunctionResultParameters<
abi extends Abi | readonly unknown[] = Abi,
functionName extends
| ContractFunctionName<abi>
| undefined = ContractFunctionName<abi>,
args extends ContractFunctionArgs<
abi,
AbiStateMutability,
functionName extends ContractFunctionName<abi>
? functionName
: ContractFunctionName<abi>
> = ContractFunctionArgs<
abi,
AbiStateMutability,
functionName extends ContractFunctionName<abi>
? functionName
: ContractFunctionName<abi>
>,
///
hasFunctions = abi extends Abi
? Abi extends abi
? true
: [ExtractAbiFunctions<abi>] extends [never]
? false
: true
: true,
allArgs = ContractFunctionArgs<
abi,
AbiStateMutability,
functionName extends ContractFunctionName<abi>
? functionName
: ContractFunctionName<abi>
>,
allFunctionNames = ContractFunctionName<abi>,
> = {
abi: abi
data: Hex
} & UnionEvaluate<
IsNarrowable<abi, Abi> extends true
? abi['length'] extends 1
? { functionName?: functionName | allFunctionNames | undefined }
: { functionName: functionName | allFunctionNames }
: { functionName?: functionName | allFunctionNames | undefined }
> &
UnionEvaluate<
readonly [] extends allArgs
? {
args?:
| allArgs // show all options
// infer value, widen inferred value of `args` conditionally to match `allArgs`
| (abi extends Abi
? args extends allArgs
? Widen<args>
: never
: never)
| undefined
}
: {
args?:
| allArgs // show all options
| (Widen<args> & (args extends allArgs ? unknown : never)) // infer value, widen inferred value of `args` match `allArgs` (e.g. avoid union `args: readonly [123n] | readonly [bigint]`)
| undefined
}
> &
(hasFunctions extends true ? unknown : never)
export type DecodeFunctionResultReturnType<
abi extends Abi | readonly unknown[] = Abi,
functionName extends
| ContractFunctionName<abi>
| undefined = ContractFunctionName<abi>,
args extends ContractFunctionArgs<
abi,
AbiStateMutability,
functionName extends ContractFunctionName<abi>
? functionName
: ContractFunctionName<abi>
> = ContractFunctionArgs<
abi,
AbiStateMutability,
functionName extends ContractFunctionName<abi>
? functionName
: ContractFunctionName<abi>
>,
> = ContractFunctionReturnType<
abi,
AbiStateMutability,
functionName extends ContractFunctionName<abi>
? functionName
: ContractFunctionName<abi>,
args
>
export type DecodeFunctionResultErrorType =
| AbiFunctionNotFoundErrorType
| AbiFunctionOutputsNotFoundErrorType
| DecodeAbiParametersErrorType
| GetAbiItemErrorType
| ErrorType
export function decodeFunctionResult<
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName<abi> | undefined = undefined,
const args extends ContractFunctionArgs<
abi,
AbiStateMutability,
functionName extends ContractFunctionName<abi>
? functionName
: ContractFunctionName<abi>
> = ContractFunctionArgs<
abi,
AbiStateMutability,
functionName extends ContractFunctionName<abi>
? functionName
: ContractFunctionName<abi>
>,
>(
parameters: DecodeFunctionResultParameters<abi, functionName, args>,
): DecodeFunctionResultReturnType<abi, functionName, args> {
const { abi, args, functionName, data } =
parameters as DecodeFunctionResultParameters
let abiItem = abi[0]
if (functionName) {
const item = getAbiItem({ abi, args, name: functionName })
if (!item) throw new AbiFunctionNotFoundError(functionName, { docsPath })
abiItem = item
}
if (abiItem.type !== 'function')
throw new AbiFunctionNotFoundError(undefined, { docsPath })
if (!abiItem.outputs)
throw new AbiFunctionOutputsNotFoundError(abiItem.name, { docsPath })
const values = decodeAbiParameters(abiItem.outputs, data)
if (values && values.length > 1)
return values as DecodeFunctionResultReturnType<abi, functionName, args>
if (values && values.length === 1)
return values[0] as DecodeFunctionResultReturnType<abi, functionName, args>
return undefined as DecodeFunctionResultReturnType<abi, functionName, args>
}

430
node_modules/viem/utils/abi/encodeAbiParameters.ts generated vendored Normal file
View File

@@ -0,0 +1,430 @@
import type {
AbiParameter,
AbiParameterKind,
AbiParametersToPrimitiveTypes,
AbiParameterToPrimitiveType,
} from 'abitype'
import {
AbiEncodingArrayLengthMismatchError,
type AbiEncodingArrayLengthMismatchErrorType,
AbiEncodingBytesSizeMismatchError,
type AbiEncodingBytesSizeMismatchErrorType,
AbiEncodingLengthMismatchError,
type AbiEncodingLengthMismatchErrorType,
InvalidAbiEncodingTypeError,
type InvalidAbiEncodingTypeErrorType,
InvalidArrayError,
type InvalidArrayErrorType,
} from '../../errors/abi.js'
import {
InvalidAddressError,
type InvalidAddressErrorType,
} from '../../errors/address.js'
import { BaseError } from '../../errors/base.js'
import { IntegerOutOfRangeError } from '../../errors/encoding.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Hex } from '../../types/misc.js'
import { type IsAddressErrorType, isAddress } from '../address/isAddress.js'
import { type ConcatErrorType, concat } from '../data/concat.js'
import { type PadHexErrorType, padHex } from '../data/pad.js'
import { type SizeErrorType, size } from '../data/size.js'
import { type SliceErrorType, slice } from '../data/slice.js'
import {
type BoolToHexErrorType,
boolToHex,
type NumberToHexErrorType,
numberToHex,
type StringToHexErrorType,
stringToHex,
} from '../encoding/toHex.js'
import { integerRegex } from '../regex.js'
export type EncodeAbiParametersReturnType = Hex
export type EncodeAbiParametersErrorType =
| AbiEncodingLengthMismatchErrorType
| PrepareParamsErrorType
| EncodeParamsErrorType
| ErrorType
/**
* @description Encodes a list of primitive values into an ABI-encoded hex value.
*
* - Docs: https://viem.sh/docs/abi/encodeAbiParameters#encodeabiparameters
*
* Generates ABI encoded data using the [ABI specification](https://docs.soliditylang.org/en/latest/abi-spec), given a set of ABI parameters (inputs/outputs) and their corresponding values.
*
* @param params - a set of ABI Parameters (params), that can be in the shape of the inputs or outputs attribute of an ABI Item.
* @param values - a set of values (values) that correspond to the given params.
* @example
* ```typescript
* import { encodeAbiParameters } from 'viem'
*
* const encodedData = encodeAbiParameters(
* [
* { name: 'x', type: 'string' },
* { name: 'y', type: 'uint' },
* { name: 'z', type: 'bool' }
* ],
* ['wagmi', 420n, true]
* )
* ```
*
* You can also pass in Human Readable parameters with the parseAbiParameters utility.
*
* @example
* ```typescript
* import { encodeAbiParameters, parseAbiParameters } from 'viem'
*
* const encodedData = encodeAbiParameters(
* parseAbiParameters('string x, uint y, bool z'),
* ['wagmi', 420n, true]
* )
* ```
*/
export function encodeAbiParameters<
const params extends readonly AbiParameter[] | readonly unknown[],
>(
params: params,
values: params extends readonly AbiParameter[]
? AbiParametersToPrimitiveTypes<params, AbiParameterKind, true>
: never,
): EncodeAbiParametersReturnType {
if (params.length !== values.length)
throw new AbiEncodingLengthMismatchError({
expectedLength: params.length as number,
givenLength: values.length as any,
})
// Prepare the parameters to determine dynamic types to encode.
const preparedParams = prepareParams({
params: params as readonly AbiParameter[],
values: values as any,
})
const data = encodeParams(preparedParams)
if (data.length === 0) return '0x'
return data
}
/////////////////////////////////////////////////////////////////
type PreparedParam = { dynamic: boolean; encoded: Hex }
type TupleAbiParameter = AbiParameter & { components: readonly AbiParameter[] }
type Tuple = AbiParameterToPrimitiveType<TupleAbiParameter>
type PrepareParamsErrorType = PrepareParamErrorType | ErrorType
function prepareParams<const params extends readonly AbiParameter[]>({
params,
values,
}: {
params: params
values: AbiParametersToPrimitiveTypes<params>
}) {
const preparedParams: PreparedParam[] = []
for (let i = 0; i < params.length; i++) {
preparedParams.push(prepareParam({ param: params[i], value: values[i] }))
}
return preparedParams
}
type PrepareParamErrorType =
| EncodeAddressErrorType
| EncodeArrayErrorType
| EncodeBytesErrorType
| EncodeBoolErrorType
| EncodeNumberErrorType
| EncodeStringErrorType
| EncodeTupleErrorType
| GetArrayComponentsErrorType
| InvalidAbiEncodingTypeErrorType
| ErrorType
function prepareParam<const param extends AbiParameter>({
param,
value,
}: {
param: param
value: AbiParameterToPrimitiveType<param>
}): PreparedParam {
const arrayComponents = getArrayComponents(param.type)
if (arrayComponents) {
const [length, type] = arrayComponents
return encodeArray(value, { length, param: { ...param, type } })
}
if (param.type === 'tuple') {
return encodeTuple(value as unknown as Tuple, {
param: param as TupleAbiParameter,
})
}
if (param.type === 'address') {
return encodeAddress(value as unknown as Hex)
}
if (param.type === 'bool') {
return encodeBool(value as unknown as boolean)
}
if (param.type.startsWith('uint') || param.type.startsWith('int')) {
const signed = param.type.startsWith('int')
const [, , size = '256'] = integerRegex.exec(param.type) ?? []
return encodeNumber(value as unknown as number, {
signed,
size: Number(size),
})
}
if (param.type.startsWith('bytes')) {
return encodeBytes(value as unknown as Hex, { param })
}
if (param.type === 'string') {
return encodeString(value as unknown as string)
}
throw new InvalidAbiEncodingTypeError(param.type, {
docsPath: '/docs/contract/encodeAbiParameters',
})
}
/////////////////////////////////////////////////////////////////
type EncodeParamsErrorType = NumberToHexErrorType | SizeErrorType | ErrorType
function encodeParams(preparedParams: PreparedParam[]): Hex {
// 1. Compute the size of the static part of the parameters.
let staticSize = 0
for (let i = 0; i < preparedParams.length; i++) {
const { dynamic, encoded } = preparedParams[i]
if (dynamic) staticSize += 32
else staticSize += size(encoded)
}
// 2. Split the parameters into static and dynamic parts.
const staticParams: Hex[] = []
const dynamicParams: Hex[] = []
let dynamicSize = 0
for (let i = 0; i < preparedParams.length; i++) {
const { dynamic, encoded } = preparedParams[i]
if (dynamic) {
staticParams.push(numberToHex(staticSize + dynamicSize, { size: 32 }))
dynamicParams.push(encoded)
dynamicSize += size(encoded)
} else {
staticParams.push(encoded)
}
}
// 3. Concatenate static and dynamic parts.
return concat([...staticParams, ...dynamicParams])
}
/////////////////////////////////////////////////////////////////
type EncodeAddressErrorType =
| InvalidAddressErrorType
| IsAddressErrorType
| ErrorType
function encodeAddress(value: Hex): PreparedParam {
if (!isAddress(value)) throw new InvalidAddressError({ address: value })
return { dynamic: false, encoded: padHex(value.toLowerCase() as Hex) }
}
type EncodeArrayErrorType =
| AbiEncodingArrayLengthMismatchErrorType
| ConcatErrorType
| EncodeParamsErrorType
| InvalidArrayErrorType
| NumberToHexErrorType
// TODO: Add back once circular type reference is resolved
// | PrepareParamErrorType
| ErrorType
function encodeArray<const param extends AbiParameter>(
value: AbiParameterToPrimitiveType<param>,
{
length,
param,
}: {
length: number | null
param: param
},
): PreparedParam {
const dynamic = length === null
if (!Array.isArray(value)) throw new InvalidArrayError(value)
if (!dynamic && value.length !== length)
throw new AbiEncodingArrayLengthMismatchError({
expectedLength: length!,
givenLength: value.length,
type: `${param.type}[${length}]`,
})
let dynamicChild = false
const preparedParams: PreparedParam[] = []
for (let i = 0; i < value.length; i++) {
const preparedParam = prepareParam({ param, value: value[i] })
if (preparedParam.dynamic) dynamicChild = true
preparedParams.push(preparedParam)
}
if (dynamic || dynamicChild) {
const data = encodeParams(preparedParams)
if (dynamic) {
const length = numberToHex(preparedParams.length, { size: 32 })
return {
dynamic: true,
encoded: preparedParams.length > 0 ? concat([length, data]) : length,
}
}
if (dynamicChild) return { dynamic: true, encoded: data }
}
return {
dynamic: false,
encoded: concat(preparedParams.map(({ encoded }) => encoded)),
}
}
type EncodeBytesErrorType =
| AbiEncodingBytesSizeMismatchErrorType
| ConcatErrorType
| PadHexErrorType
| NumberToHexErrorType
| SizeErrorType
| ErrorType
function encodeBytes<const param extends AbiParameter>(
value: Hex,
{ param }: { param: param },
): PreparedParam {
const [, paramSize] = param.type.split('bytes')
const bytesSize = size(value)
if (!paramSize) {
let value_ = value
// If the size is not divisible by 32 bytes, pad the end
// with empty bytes to the ceiling 32 bytes.
if (bytesSize % 32 !== 0)
value_ = padHex(value_, {
dir: 'right',
size: Math.ceil((value.length - 2) / 2 / 32) * 32,
})
return {
dynamic: true,
encoded: concat([padHex(numberToHex(bytesSize, { size: 32 })), value_]),
}
}
if (bytesSize !== Number.parseInt(paramSize, 10))
throw new AbiEncodingBytesSizeMismatchError({
expectedSize: Number.parseInt(paramSize, 10),
value,
})
return { dynamic: false, encoded: padHex(value, { dir: 'right' }) }
}
type EncodeBoolErrorType = PadHexErrorType | BoolToHexErrorType | ErrorType
function encodeBool(value: boolean): PreparedParam {
if (typeof value !== 'boolean')
throw new BaseError(
`Invalid boolean value: "${value}" (type: ${typeof value}). Expected: \`true\` or \`false\`.`,
)
return { dynamic: false, encoded: padHex(boolToHex(value)) }
}
type EncodeNumberErrorType = NumberToHexErrorType | ErrorType
function encodeNumber(
value: number,
{ signed, size = 256 }: { signed: boolean; size?: number | undefined },
): PreparedParam {
if (typeof size === 'number') {
const max = 2n ** (BigInt(size) - (signed ? 1n : 0n)) - 1n
const min = signed ? -max - 1n : 0n
if (value > max || value < min)
throw new IntegerOutOfRangeError({
max: max.toString(),
min: min.toString(),
signed,
size: size / 8,
value: value.toString(),
})
}
return {
dynamic: false,
encoded: numberToHex(value, {
size: 32,
signed,
}),
}
}
type EncodeStringErrorType =
| ConcatErrorType
| NumberToHexErrorType
| PadHexErrorType
| SizeErrorType
| SliceErrorType
| StringToHexErrorType
| ErrorType
function encodeString(value: string): PreparedParam {
const hexValue = stringToHex(value)
const partsLength = Math.ceil(size(hexValue) / 32)
const parts: Hex[] = []
for (let i = 0; i < partsLength; i++) {
parts.push(
padHex(slice(hexValue, i * 32, (i + 1) * 32), {
dir: 'right',
}),
)
}
return {
dynamic: true,
encoded: concat([
padHex(numberToHex(size(hexValue), { size: 32 })),
...parts,
]),
}
}
type EncodeTupleErrorType =
| ConcatErrorType
| EncodeParamsErrorType
// TODO: Add back once circular type reference is resolved
// | PrepareParamErrorType
| ErrorType
function encodeTuple<
const param extends AbiParameter & { components: readonly AbiParameter[] },
>(
value: AbiParameterToPrimitiveType<param>,
{ param }: { param: param },
): PreparedParam {
let dynamic = false
const preparedParams: PreparedParam[] = []
for (let i = 0; i < param.components.length; i++) {
const param_ = param.components[i]
const index = Array.isArray(value) ? i : param_.name
const preparedParam = prepareParam({
param: param_,
value: (value as any)[index!] as readonly unknown[],
})
preparedParams.push(preparedParam)
if (preparedParam.dynamic) dynamic = true
}
return {
dynamic,
encoded: dynamic
? encodeParams(preparedParams)
: concat(preparedParams.map(({ encoded }) => encoded)),
}
}
type GetArrayComponentsErrorType = ErrorType
export function getArrayComponents(
type: string,
): [length: number | null, innerType: string] | undefined {
const matches = type.match(/^(.*)\[(\d+)?\]$/)
return matches
? // Return `null` if the array is dynamic.
[matches[2] ? Number(matches[2]) : null, matches[1]]
: undefined
}

65
node_modules/viem/utils/abi/encodeDeployData.ts generated vendored Normal file
View File

@@ -0,0 +1,65 @@
import type { Abi } from 'abitype'
import {
AbiConstructorNotFoundError,
type AbiConstructorNotFoundErrorType,
AbiConstructorParamsNotFoundError,
} from '../../errors/abi.js'
import type { ErrorType } from '../../errors/utils.js'
import type { ContractConstructorArgs } from '../../types/contract.js'
import type { Hex } from '../../types/misc.js'
import type { UnionEvaluate } from '../../types/utils.js'
import { type ConcatHexErrorType, concatHex } from '../data/concat.js'
import {
type EncodeAbiParametersErrorType,
encodeAbiParameters,
} from './encodeAbiParameters.js'
const docsPath = '/docs/contract/encodeDeployData'
export type EncodeDeployDataParameters<
abi extends Abi | readonly unknown[] = Abi,
///
hasConstructor = abi extends Abi
? Abi extends abi
? true
: [Extract<abi[number], { type: 'constructor' }>] extends [never]
? false
: true
: true,
allArgs = ContractConstructorArgs<abi>,
> = {
abi: abi
bytecode: Hex
} & UnionEvaluate<
hasConstructor extends false
? { args?: undefined }
: readonly [] extends allArgs
? { args?: allArgs | undefined }
: { args: allArgs }
>
export type EncodeDeployDataReturnType = Hex
export type EncodeDeployDataErrorType =
| AbiConstructorNotFoundErrorType
| ConcatHexErrorType
| EncodeAbiParametersErrorType
| ErrorType
export function encodeDeployData<const abi extends Abi | readonly unknown[]>(
parameters: EncodeDeployDataParameters<abi>,
): EncodeDeployDataReturnType {
const { abi, args, bytecode } = parameters as EncodeDeployDataParameters
if (!args || args.length === 0) return bytecode
const description = abi.find((x) => 'type' in x && x.type === 'constructor')
if (!description) throw new AbiConstructorNotFoundError({ docsPath })
if (!('inputs' in description))
throw new AbiConstructorParamsNotFoundError({ docsPath })
if (!description.inputs || description.inputs.length === 0)
throw new AbiConstructorParamsNotFoundError({ docsPath })
const data = encodeAbiParameters(description.inputs, args)
return concatHex([bytecode, data!])
}

96
node_modules/viem/utils/abi/encodeErrorResult.ts generated vendored Normal file
View File

@@ -0,0 +1,96 @@
import type { Abi, ExtractAbiErrors } from 'abitype'
import {
AbiErrorInputsNotFoundError,
AbiErrorNotFoundError,
} from '../../errors/abi.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
ContractErrorArgs,
ContractErrorName,
} from '../../types/contract.js'
import type { Hex } from '../../types/misc.js'
import type { IsNarrowable, UnionEvaluate } from '../../types/utils.js'
import { type ConcatHexErrorType, concatHex } from '../data/concat.js'
import {
type ToFunctionSelectorErrorType,
toFunctionSelector,
} from '../hash/toFunctionSelector.js'
import {
type EncodeAbiParametersErrorType,
encodeAbiParameters,
} from './encodeAbiParameters.js'
import { type FormatAbiItemErrorType, formatAbiItem } from './formatAbiItem.js'
import { type GetAbiItemErrorType, getAbiItem } from './getAbiItem.js'
const docsPath = '/docs/contract/encodeErrorResult'
export type EncodeErrorResultParameters<
abi extends Abi | readonly unknown[] = Abi,
errorName extends ContractErrorName<abi> | undefined = ContractErrorName<abi>,
///
hasErrors = abi extends Abi
? Abi extends abi
? true
: [ExtractAbiErrors<abi>] extends [never]
? false
: true
: true,
allArgs = ContractErrorArgs<
abi,
errorName extends ContractErrorName<abi>
? errorName
: ContractErrorName<abi>
>,
allErrorNames = ContractErrorName<abi>,
> = {
abi: abi
args?: allArgs | undefined
} & UnionEvaluate<
IsNarrowable<abi, Abi> extends true
? abi['length'] extends 1
? { errorName?: errorName | allErrorNames | undefined }
: { errorName: errorName | allErrorNames }
: { errorName?: errorName | allErrorNames | undefined }
> &
(hasErrors extends true ? unknown : never)
export type EncodeErrorResultReturnType = Hex
export type EncodeErrorResultErrorType =
| GetAbiItemErrorType
| FormatAbiItemErrorType
| ToFunctionSelectorErrorType
| EncodeAbiParametersErrorType
| ConcatHexErrorType
| ErrorType
export function encodeErrorResult<
const abi extends Abi | readonly unknown[],
errorName extends ContractErrorName<abi> | undefined = undefined,
>(
parameters: EncodeErrorResultParameters<abi, errorName>,
): EncodeErrorResultReturnType {
const { abi, errorName, args } = parameters as EncodeErrorResultParameters
let abiItem = abi[0]
if (errorName) {
const item = getAbiItem({ abi, args, name: errorName })
if (!item) throw new AbiErrorNotFoundError(errorName, { docsPath })
abiItem = item
}
if (abiItem.type !== 'error')
throw new AbiErrorNotFoundError(undefined, { docsPath })
const definition = formatAbiItem(abiItem)
const signature = toFunctionSelector(definition)
let data: Hex = '0x'
if (args && args.length > 0) {
if (!abiItem.inputs)
throw new AbiErrorInputsNotFoundError(abiItem.name, { docsPath })
data = encodeAbiParameters(abiItem.inputs, args)
}
return concatHex([signature, data])
}

146
node_modules/viem/utils/abi/encodeEventTopics.ts generated vendored Normal file
View File

@@ -0,0 +1,146 @@
import type {
Abi,
AbiParameter,
AbiParameterToPrimitiveType,
ExtractAbiEvents,
} from 'abitype'
import {
AbiEventNotFoundError,
type AbiEventNotFoundErrorType,
} from '../../errors/abi.js'
import {
FilterTypeNotSupportedError,
type FilterTypeNotSupportedErrorType,
} from '../../errors/log.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
ContractEventArgs,
ContractEventName,
EventDefinition,
} from '../../types/contract.js'
import type { Hex } from '../../types/misc.js'
import type { IsNarrowable, UnionEvaluate } from '../../types/utils.js'
import { type ToBytesErrorType, toBytes } from '../encoding/toBytes.js'
import { type Keccak256ErrorType, keccak256 } from '../hash/keccak256.js'
import {
type ToEventSelectorErrorType,
toEventSelector,
} from '../hash/toEventSelector.js'
import {
type EncodeAbiParametersErrorType,
encodeAbiParameters,
} from './encodeAbiParameters.js'
import { type FormatAbiItemErrorType, formatAbiItem } from './formatAbiItem.js'
import { type GetAbiItemErrorType, getAbiItem } from './getAbiItem.js'
const docsPath = '/docs/contract/encodeEventTopics'
export type EncodeEventTopicsParameters<
abi extends Abi | readonly unknown[] = Abi,
eventName extends ContractEventName<abi> | undefined = ContractEventName<abi>,
///
hasEvents = abi extends Abi
? Abi extends abi
? true
: [ExtractAbiEvents<abi>] extends [never]
? false
: true
: true,
allArgs = ContractEventArgs<
abi,
eventName extends ContractEventName<abi>
? eventName
: ContractEventName<abi>
>,
allErrorNames = ContractEventName<abi>,
> = {
abi: abi
args?: allArgs | undefined
} & UnionEvaluate<
IsNarrowable<abi, Abi> extends true
? abi['length'] extends 1
? { eventName?: eventName | allErrorNames | undefined }
: { eventName: eventName | allErrorNames }
: { eventName?: eventName | allErrorNames | undefined }
> &
(hasEvents extends true ? unknown : never)
export type EncodeEventTopicsReturnType = [Hex, ...(Hex | Hex[] | null)[]]
export type EncodeEventTopicsErrorType =
| AbiEventNotFoundErrorType
| EncodeArgErrorType
| FormatAbiItemErrorType
| GetAbiItemErrorType
| ToEventSelectorErrorType
| ErrorType
export function encodeEventTopics<
const abi extends Abi | readonly unknown[],
eventName extends ContractEventName<abi> | undefined = undefined,
>(
parameters: EncodeEventTopicsParameters<abi, eventName>,
): EncodeEventTopicsReturnType {
const { abi, eventName, args } = parameters as EncodeEventTopicsParameters
let abiItem = abi[0]
if (eventName) {
const item = getAbiItem({ abi, name: eventName })
if (!item) throw new AbiEventNotFoundError(eventName, { docsPath })
abiItem = item
}
if (abiItem.type !== 'event')
throw new AbiEventNotFoundError(undefined, { docsPath })
const definition = formatAbiItem(abiItem)
const signature = toEventSelector(definition as EventDefinition)
let topics: (Hex | Hex[] | null)[] = []
if (args && 'inputs' in abiItem) {
const indexedInputs = abiItem.inputs?.filter(
(param) => 'indexed' in param && param.indexed,
)
const args_ = Array.isArray(args)
? args
: Object.values(args).length > 0
? (indexedInputs?.map((x: any) => (args as any)[x.name]) ?? [])
: []
if (args_.length > 0) {
topics =
indexedInputs?.map((param, i) => {
if (Array.isArray(args_[i]))
return args_[i].map((_: any, j: number) =>
encodeArg({ param, value: args_[i][j] }),
)
return typeof args_[i] !== 'undefined' && args_[i] !== null
? encodeArg({ param, value: args_[i] })
: null
}) ?? []
}
}
return [signature, ...topics]
}
export type EncodeArgErrorType =
| Keccak256ErrorType
| ToBytesErrorType
| EncodeAbiParametersErrorType
| FilterTypeNotSupportedErrorType
| ErrorType
function encodeArg({
param,
value,
}: {
param: AbiParameter
value: AbiParameterToPrimitiveType<AbiParameter>
}) {
if (param.type === 'string' || param.type === 'bytes')
return keccak256(toBytes(value as string))
if (param.type === 'tuple' || param.type.match(/^(.*)\[(\d+)?\]$/))
throw new FilterTypeNotSupportedError(param.type)
return encodeAbiParameters([param], [value])
}

95
node_modules/viem/utils/abi/encodeFunctionData.ts generated vendored Normal file
View File

@@ -0,0 +1,95 @@
import type { Abi, AbiStateMutability, ExtractAbiFunctions } from 'abitype'
import type { AbiFunctionNotFoundErrorType } from '../../errors/abi.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
ContractFunctionArgs,
ContractFunctionName,
} from '../../types/contract.js'
import type { Hex } from '../../types/misc.js'
import type { IsNarrowable, UnionEvaluate } from '../../types/utils.js'
import { type ConcatHexErrorType, concatHex } from '../data/concat.js'
import type { ToFunctionSelectorErrorType } from '../hash/toFunctionSelector.js'
import {
type EncodeAbiParametersErrorType,
encodeAbiParameters,
} from './encodeAbiParameters.js'
import type { FormatAbiItemErrorType } from './formatAbiItem.js'
import type { GetAbiItemErrorType } from './getAbiItem.js'
import { prepareEncodeFunctionData } from './prepareEncodeFunctionData.js'
export type EncodeFunctionDataParameters<
abi extends Abi | readonly unknown[] = Abi,
functionName extends
| ContractFunctionName<abi>
| Hex
| undefined = ContractFunctionName<abi>,
///
hasFunctions = abi extends Abi
? Abi extends abi
? true
: [ExtractAbiFunctions<abi>] extends [never]
? false
: true
: true,
allArgs = ContractFunctionArgs<
abi,
AbiStateMutability,
functionName extends ContractFunctionName<abi>
? functionName
: ContractFunctionName<abi>
>,
allFunctionNames = ContractFunctionName<abi>,
> = {
abi: abi
} & UnionEvaluate<
IsNarrowable<abi, Abi> extends true
? abi['length'] extends 1
? { functionName?: functionName | allFunctionNames | Hex | undefined }
: { functionName: functionName | allFunctionNames | Hex }
: { functionName?: functionName | allFunctionNames | Hex | undefined }
> &
UnionEvaluate<
readonly [] extends allArgs
? { args?: allArgs | undefined }
: { args: allArgs }
> &
(hasFunctions extends true ? unknown : never)
export type EncodeFunctionDataReturnType = Hex
export type EncodeFunctionDataErrorType =
| AbiFunctionNotFoundErrorType
| ConcatHexErrorType
| EncodeAbiParametersErrorType
| FormatAbiItemErrorType
| GetAbiItemErrorType
| ToFunctionSelectorErrorType
| ErrorType
export function encodeFunctionData<
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName<abi> | undefined = undefined,
>(
parameters: EncodeFunctionDataParameters<abi, functionName>,
): EncodeFunctionDataReturnType {
const { args } = parameters as EncodeFunctionDataParameters
const { abi, functionName } = (() => {
if (
parameters.abi.length === 1 &&
parameters.functionName?.startsWith('0x')
)
return parameters as { abi: Abi; functionName: Hex }
return prepareEncodeFunctionData(parameters)
})()
const abiItem = abi[0]
const signature = functionName
const data =
'inputs' in abiItem && abiItem.inputs
? encodeAbiParameters(abiItem.inputs, args ?? [])
: undefined
return concatHex([signature, data ?? '0x'])
}

97
node_modules/viem/utils/abi/encodeFunctionResult.ts generated vendored Normal file
View File

@@ -0,0 +1,97 @@
import type { Abi, AbiStateMutability, ExtractAbiFunctions } from 'abitype'
import {
AbiFunctionNotFoundError,
AbiFunctionOutputsNotFoundError,
InvalidArrayError,
} from '../../errors/abi.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
ContractFunctionName,
ContractFunctionReturnType,
} from '../../types/contract.js'
import type { Hex } from '../../types/misc.js'
import type { IsNarrowable, UnionEvaluate } from '../../types/utils.js'
import {
type EncodeAbiParametersErrorType,
encodeAbiParameters,
} from './encodeAbiParameters.js'
import { type GetAbiItemErrorType, getAbiItem } from './getAbiItem.js'
const docsPath = '/docs/contract/encodeFunctionResult'
export type EncodeFunctionResultParameters<
abi extends Abi | readonly unknown[] = Abi,
functionName extends
| ContractFunctionName<abi>
| undefined = ContractFunctionName<abi>,
///
hasFunctions = abi extends Abi
? Abi extends abi
? true
: [ExtractAbiFunctions<abi>] extends [never]
? false
: true
: true,
allFunctionNames = ContractFunctionName<abi>,
> = {
abi: abi
result?:
| ContractFunctionReturnType<
abi,
AbiStateMutability,
functionName extends ContractFunctionName<abi>
? functionName
: ContractFunctionName<abi>,
never // allow all args. required for overloads to work.
>
| undefined
} & UnionEvaluate<
IsNarrowable<abi, Abi> extends true
? abi['length'] extends 1
? { functionName?: functionName | allFunctionNames | undefined }
: { functionName: functionName | allFunctionNames }
: { functionName?: functionName | allFunctionNames | undefined }
> &
(hasFunctions extends true ? unknown : never)
export type EncodeFunctionResultReturnType = Hex
export type EncodeFunctionResultErrorType =
| AbiFunctionOutputsNotFoundError
| AbiFunctionNotFoundError
| EncodeAbiParametersErrorType
| GetAbiItemErrorType
| ErrorType
export function encodeFunctionResult<
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName<abi> | undefined = undefined,
>(
parameters: EncodeFunctionResultParameters<abi, functionName>,
): EncodeFunctionResultReturnType {
const { abi, functionName, result } =
parameters as EncodeFunctionResultParameters
let abiItem = abi[0]
if (functionName) {
const item = getAbiItem({ abi, name: functionName })
if (!item) throw new AbiFunctionNotFoundError(functionName, { docsPath })
abiItem = item
}
if (abiItem.type !== 'function')
throw new AbiFunctionNotFoundError(undefined, { docsPath })
if (!abiItem.outputs)
throw new AbiFunctionOutputsNotFoundError(abiItem.name, { docsPath })
const values = (() => {
if (abiItem.outputs.length === 0) return []
if (abiItem.outputs.length === 1) return [result]
if (Array.isArray(result)) return result
throw new InvalidArrayError(result)
})()
return encodeAbiParameters(abiItem.outputs, values)
}

140
node_modules/viem/utils/abi/encodePacked.ts generated vendored Normal file
View File

@@ -0,0 +1,140 @@
import type {
AbiParameterToPrimitiveType,
AbiType,
Address,
SolidityAddress,
SolidityArrayWithoutTuple,
SolidityBool,
SolidityBytes,
SolidityInt,
SolidityString,
} from 'abitype'
import {
AbiEncodingLengthMismatchError,
type AbiEncodingLengthMismatchErrorType,
BytesSizeMismatchError,
type BytesSizeMismatchErrorType,
UnsupportedPackedAbiType,
} from '../../errors/abi.js'
import {
InvalidAddressError,
type InvalidAddressErrorType,
} from '../../errors/address.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Hex } from '../../types/misc.js'
import { type IsAddressErrorType, isAddress } from '../address/isAddress.js'
import { type ConcatHexErrorType, concatHex } from '../data/concat.js'
import { type PadErrorType, pad } from '../data/pad.js'
import {
type BoolToHexErrorType,
boolToHex,
type NumberToHexErrorType,
numberToHex,
type StringToHexErrorType,
stringToHex,
} from '../encoding/toHex.js'
import { arrayRegex, bytesRegex, integerRegex } from '../regex.js'
type PackedAbiType =
| SolidityAddress
| SolidityBool
| SolidityBytes
| SolidityInt
| SolidityString
| SolidityArrayWithoutTuple
type EncodePackedValues<
packedAbiTypes extends readonly PackedAbiType[] | readonly unknown[],
> = {
[K in keyof packedAbiTypes]: packedAbiTypes[K] extends AbiType
? AbiParameterToPrimitiveType<{ type: packedAbiTypes[K] }>
: unknown
}
export type EncodePackedErrorType =
| AbiEncodingLengthMismatchErrorType
| ConcatHexErrorType
| EncodeErrorType
| ErrorType
export function encodePacked<
const packedAbiTypes extends readonly PackedAbiType[] | readonly unknown[],
>(types: packedAbiTypes, values: EncodePackedValues<packedAbiTypes>): Hex {
if (types.length !== values.length)
throw new AbiEncodingLengthMismatchError({
expectedLength: types.length as number,
givenLength: values.length as number,
})
const data: Hex[] = []
for (let i = 0; i < (types as unknown[]).length; i++) {
const type = types[i]
const value = values[i]
data.push(encode(type, value))
}
return concatHex(data)
}
type EncodeErrorType =
| BoolToHexErrorType
| BytesSizeMismatchErrorType
| InvalidAddressErrorType
| IsAddressErrorType
| NumberToHexErrorType
| PadErrorType
| StringToHexErrorType
| UnsupportedPackedAbiType
| ErrorType
function encode<const packedAbiType extends PackedAbiType | unknown>(
type: packedAbiType,
value: EncodePackedValues<[packedAbiType]>[0],
isArray = false,
): Hex {
if (type === 'address') {
const address = value as Address
if (!isAddress(address)) throw new InvalidAddressError({ address })
return pad(address.toLowerCase() as Hex, {
size: isArray ? 32 : null,
}) as Address
}
if (type === 'string') return stringToHex(value as string)
if (type === 'bytes') return value as Hex
if (type === 'bool')
return pad(boolToHex(value as boolean), { size: isArray ? 32 : 1 })
const intMatch = (type as string).match(integerRegex)
if (intMatch) {
const [_type, baseType, bits = '256'] = intMatch
const size = Number.parseInt(bits, 10) / 8
return numberToHex(value as number, {
size: isArray ? 32 : size,
signed: baseType === 'int',
})
}
const bytesMatch = (type as string).match(bytesRegex)
if (bytesMatch) {
const [_type, size] = bytesMatch
if (Number.parseInt(size, 10) !== ((value as Hex).length - 2) / 2)
throw new BytesSizeMismatchError({
expectedSize: Number.parseInt(size, 10),
givenSize: ((value as Hex).length - 2) / 2,
})
return pad(value as Hex, { dir: 'right', size: isArray ? 32 : null }) as Hex
}
const arrayMatch = (type as string).match(arrayRegex)
if (arrayMatch && Array.isArray(value)) {
const [_type, childType] = arrayMatch
const data: Hex[] = []
for (let i = 0; i < value.length; i++) {
data.push(encode(childType, value[i], true))
}
if (data.length === 0) return '0x'
return concatHex(data)
}
throw new UnsupportedPackedAbiType(type)
}

54
node_modules/viem/utils/abi/formatAbiItem.ts generated vendored Normal file
View File

@@ -0,0 +1,54 @@
import type { AbiParameter } from 'abitype'
import {
InvalidDefinitionTypeError,
type InvalidDefinitionTypeErrorType,
} from '../../errors/abi.js'
import type { ErrorType } from '../../errors/utils.js'
import type { AbiItem } from '../../types/contract.js'
export type FormatAbiItemErrorType =
| FormatAbiParamsErrorType
| InvalidDefinitionTypeErrorType
| ErrorType
export function formatAbiItem(
abiItem: AbiItem,
{ includeName = false }: { includeName?: boolean | undefined } = {},
) {
if (
abiItem.type !== 'function' &&
abiItem.type !== 'event' &&
abiItem.type !== 'error'
)
throw new InvalidDefinitionTypeError(abiItem.type)
return `${abiItem.name}(${formatAbiParams(abiItem.inputs, { includeName })})`
}
export type FormatAbiParamsErrorType = ErrorType
export function formatAbiParams(
params: readonly AbiParameter[] | undefined,
{ includeName = false }: { includeName?: boolean | undefined } = {},
): string {
if (!params) return ''
return params
.map((param) => formatAbiParam(param, { includeName }))
.join(includeName ? ', ' : ',')
}
export type FormatAbiParamErrorType = ErrorType
function formatAbiParam(
param: AbiParameter,
{ includeName }: { includeName: boolean },
): string {
if (param.type.startsWith('tuple')) {
return `(${formatAbiParams(
(param as unknown as { components: AbiParameter[] }).components,
{ includeName },
)})${param.type.slice('tuple'.length)}`
}
return param.type + (includeName && param.name ? ` ${param.name}` : '')
}

31
node_modules/viem/utils/abi/formatAbiItemWithArgs.ts generated vendored Normal file
View File

@@ -0,0 +1,31 @@
import type { AbiParameter } from 'abitype'
import type { ErrorType } from '../../errors/utils.js'
import type { AbiItem } from '../../types/contract.js'
import { stringify } from '../stringify.js'
export type FormatAbiItemWithArgsErrorType = ErrorType
export function formatAbiItemWithArgs({
abiItem,
args,
includeFunctionName = true,
includeName = false,
}: {
abiItem: AbiItem
args: readonly unknown[]
includeFunctionName?: boolean | undefined
includeName?: boolean | undefined
}) {
if (!('name' in abiItem)) return
if (!('inputs' in abiItem)) return
if (!abiItem.inputs) return
return `${includeFunctionName ? abiItem.name : ''}(${abiItem.inputs
.map(
(input: AbiParameter, i: number) =>
`${includeName && input.name ? `${input.name}: ` : ''}${
typeof args[i] === 'object' ? stringify(args[i]) : args[i]
}`,
)
.join(', ')})`
}

257
node_modules/viem/utils/abi/getAbiItem.ts generated vendored Normal file
View File

@@ -0,0 +1,257 @@
import type { Abi, AbiParameter, Address } from 'abitype'
import {
AbiItemAmbiguityError,
type AbiItemAmbiguityErrorType,
} from '../../errors/abi.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
AbiItem,
AbiItemArgs,
AbiItemName,
ExtractAbiItemForArgs,
Widen,
} from '../../types/contract.js'
import type { Hex } from '../../types/misc.js'
import type { UnionEvaluate } from '../../types/utils.js'
import { type IsHexErrorType, isHex } from '../../utils/data/isHex.js'
import { type IsAddressErrorType, isAddress } from '../address/isAddress.js'
import { toEventSelector } from '../hash/toEventSelector.js'
import {
type ToFunctionSelectorErrorType,
toFunctionSelector,
} from '../hash/toFunctionSelector.js'
export type GetAbiItemParameters<
abi extends Abi | readonly unknown[] = Abi,
name extends AbiItemName<abi> = AbiItemName<abi>,
args extends AbiItemArgs<abi, name> | undefined = AbiItemArgs<abi, name>,
///
allArgs = AbiItemArgs<abi, name>,
allNames = AbiItemName<abi>,
> = {
abi: abi
name:
| allNames // show all options
| (name extends allNames ? name : never) // infer value
| Hex // function selector
} & UnionEvaluate<
readonly [] extends allArgs
? {
args?:
| allArgs // show all options
// infer value, widen inferred value of `args` conditionally to match `allArgs`
| (abi extends Abi
? args extends allArgs
? Widen<args>
: never
: never)
| undefined
}
: {
args?:
| allArgs // show all options
| (Widen<args> & (args extends allArgs ? unknown : never)) // infer value, widen inferred value of `args` match `allArgs` (e.g. avoid union `args: readonly [123n] | readonly [bigint]`)
| undefined
}
>
export type GetAbiItemErrorType =
| IsArgOfTypeErrorType
| IsHexErrorType
| ToFunctionSelectorErrorType
| AbiItemAmbiguityErrorType
| ErrorType
export type GetAbiItemReturnType<
abi extends Abi | readonly unknown[] = Abi,
name extends AbiItemName<abi> = AbiItemName<abi>,
args extends AbiItemArgs<abi, name> | undefined = AbiItemArgs<abi, name>,
> = abi extends Abi
? Abi extends abi
? AbiItem | undefined
: ExtractAbiItemForArgs<
abi,
name,
args extends AbiItemArgs<abi, name> ? args : AbiItemArgs<abi, name>
>
: AbiItem | undefined
export function getAbiItem<
const abi extends Abi | readonly unknown[],
name extends AbiItemName<abi>,
const args extends AbiItemArgs<abi, name> | undefined = undefined,
>(
parameters: GetAbiItemParameters<abi, name, args>,
): GetAbiItemReturnType<abi, name, args> {
const { abi, args = [], name } = parameters as unknown as GetAbiItemParameters
const isSelector = isHex(name, { strict: false })
const abiItems = (abi as Abi).filter((abiItem) => {
if (isSelector) {
if (abiItem.type === 'function')
return toFunctionSelector(abiItem) === name
if (abiItem.type === 'event') return toEventSelector(abiItem) === name
return false
}
return 'name' in abiItem && abiItem.name === name
})
if (abiItems.length === 0)
return undefined as GetAbiItemReturnType<abi, name, args>
if (abiItems.length === 1)
return abiItems[0] as GetAbiItemReturnType<abi, name, args>
let matchedAbiItem: AbiItem | undefined
for (const abiItem of abiItems) {
if (!('inputs' in abiItem)) continue
if (!args || args.length === 0) {
if (!abiItem.inputs || abiItem.inputs.length === 0)
return abiItem as GetAbiItemReturnType<abi, name, args>
continue
}
if (!abiItem.inputs) continue
if (abiItem.inputs.length === 0) continue
if (abiItem.inputs.length !== args.length) continue
const matched = args.every((arg, index) => {
const abiParameter = 'inputs' in abiItem && abiItem.inputs![index]
if (!abiParameter) return false
return isArgOfType(arg, abiParameter)
})
if (matched) {
// Check for ambiguity against already matched parameters (e.g. `address` vs `bytes20`).
if (
matchedAbiItem &&
'inputs' in matchedAbiItem &&
matchedAbiItem.inputs
) {
const ambiguousTypes = getAmbiguousTypes(
abiItem.inputs,
matchedAbiItem.inputs,
args as readonly unknown[],
)
if (ambiguousTypes)
throw new AbiItemAmbiguityError(
{
abiItem,
type: ambiguousTypes[0],
},
{
abiItem: matchedAbiItem,
type: ambiguousTypes[1],
},
)
}
matchedAbiItem = abiItem
}
}
if (matchedAbiItem)
return matchedAbiItem as GetAbiItemReturnType<abi, name, args>
return abiItems[0] as GetAbiItemReturnType<abi, name, args>
}
type IsArgOfTypeErrorType = IsAddressErrorType | ErrorType
/** @internal */
export function isArgOfType(arg: unknown, abiParameter: AbiParameter): boolean {
const argType = typeof arg
const abiParameterType = abiParameter.type
switch (abiParameterType) {
case 'address':
return isAddress(arg as Address, { strict: false })
case 'bool':
return argType === 'boolean'
case 'function':
return argType === 'string'
case 'string':
return argType === 'string'
default: {
if (abiParameterType === 'tuple' && 'components' in abiParameter)
return Object.values(abiParameter.components).every(
(component, index) => {
return (
argType === 'object' &&
isArgOfType(
Object.values(arg as unknown[] | Record<string, unknown>)[
index
],
component as AbiParameter,
)
)
},
)
// `(u)int<M>`: (un)signed integer type of `M` bits, `0 < M <= 256`, `M % 8 == 0`
// https://regexr.com/6v8hp
if (
/^u?int(8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256)?$/.test(
abiParameterType,
)
)
return argType === 'number' || argType === 'bigint'
// `bytes<M>`: binary type of `M` bytes, `0 < M <= 32`
// https://regexr.com/6va55
if (/^bytes([1-9]|1[0-9]|2[0-9]|3[0-2])?$/.test(abiParameterType))
return argType === 'string' || arg instanceof Uint8Array
// fixed-length (`<type>[M]`) and dynamic (`<type>[]`) arrays
// https://regexr.com/6va6i
if (/[a-z]+[1-9]{0,3}(\[[0-9]{0,}\])+$/.test(abiParameterType)) {
return (
Array.isArray(arg) &&
arg.every((x: unknown) =>
isArgOfType(x, {
...abiParameter,
// Pop off `[]` or `[M]` from end of type
type: abiParameterType.replace(/(\[[0-9]{0,}\])$/, ''),
} as AbiParameter),
)
)
}
return false
}
}
}
/** @internal */
export function getAmbiguousTypes(
sourceParameters: readonly AbiParameter[],
targetParameters: readonly AbiParameter[],
args: AbiItemArgs,
): AbiParameter['type'][] | undefined {
for (const parameterIndex in sourceParameters) {
const sourceParameter = sourceParameters[parameterIndex]
const targetParameter = targetParameters[parameterIndex]
if (
sourceParameter.type === 'tuple' &&
targetParameter.type === 'tuple' &&
'components' in sourceParameter &&
'components' in targetParameter
)
return getAmbiguousTypes(
sourceParameter.components,
targetParameter.components,
(args as any)[parameterIndex],
)
const types = [sourceParameter.type, targetParameter.type]
const ambiguous = (() => {
if (types.includes('address') && types.includes('bytes20')) return true
if (types.includes('address') && types.includes('string'))
return isAddress(args[parameterIndex] as Address, { strict: false })
if (types.includes('address') && types.includes('bytes'))
return isAddress(args[parameterIndex] as Address, { strict: false })
return false
})()
if (ambiguous) return types
}
return
}

251
node_modules/viem/utils/abi/parseEventLogs.ts generated vendored Normal file
View File

@@ -0,0 +1,251 @@
// TODO(v3): checksum address.
import type { Abi, AbiEvent, AbiEventParameter, Address } from 'abitype'
import type { ErrorType } from '../../errors/utils.js'
import type { ContractEventName, GetEventArgs } from '../../types/contract.js'
import type { Log } from '../../types/log.js'
import type { RpcLog } from '../../types/rpc.js'
import { isAddressEqual } from '../address/isAddressEqual.js'
import { toBytes } from '../encoding/toBytes.js'
import { formatLog } from '../formatters/log.js'
import { keccak256 } from '../hash/keccak256.js'
import { toEventSelector } from '../hash/toEventSelector.js'
import {
type DecodeEventLogErrorType,
decodeEventLog,
} from './decodeEventLog.js'
export type ParseEventLogsParameters<
abi extends Abi | readonly unknown[] = Abi,
eventName extends
| ContractEventName<abi>
| ContractEventName<abi>[]
| undefined = ContractEventName<abi>,
strict extends boolean | undefined = boolean | undefined,
///
allArgs = GetEventArgs<
abi,
eventName extends ContractEventName<abi>
? eventName
: ContractEventName<abi>,
{
EnableUnion: true
IndexedOnly: false
Required: false
}
>,
> = {
/** Contract ABI. */
abi: abi
/** Arguments for the event. */
args?: allArgs | undefined
/** Contract event. */
eventName?:
| eventName
| ContractEventName<abi>
| ContractEventName<abi>[]
| undefined
/** List of logs. */
logs: (Log | RpcLog)[]
strict?: strict | boolean | undefined
}
export type ParseEventLogsReturnType<
abi extends Abi | readonly unknown[] = Abi,
eventName extends
| ContractEventName<abi>
| ContractEventName<abi>[]
| undefined = ContractEventName<abi>,
strict extends boolean | undefined = boolean | undefined,
///
derivedEventName extends
| ContractEventName<abi>
| undefined = eventName extends ContractEventName<abi>[]
? eventName[number]
: eventName,
> = Log<bigint, number, false, undefined, strict, abi, derivedEventName>[]
export type ParseEventLogsErrorType = DecodeEventLogErrorType | ErrorType
/**
* Extracts & decodes logs matching the provided signature(s) (`abi` + optional `eventName`)
* from a set of opaque logs.
*
* @param parameters - {@link ParseEventLogsParameters}
* @returns The logs. {@link ParseEventLogsReturnType}
*
* @example
* import { createClient, http } from 'viem'
* import { mainnet } from 'viem/chains'
* import { parseEventLogs } from 'viem/op-stack'
*
* const client = createClient({
* chain: mainnet,
* transport: http(),
* })
*
* const receipt = await getTransactionReceipt(client, {
* hash: '0xec23b2ba4bc59ba61554507c1b1bc91649e6586eb2dd00c728e8ed0db8bb37ea',
* })
*
* const logs = parseEventLogs({ logs: receipt.logs })
* // [{ args: { ... }, eventName: 'TransactionDeposited', ... }, ...]
*/
export function parseEventLogs<
abi extends Abi | readonly unknown[],
strict extends boolean | undefined = true,
eventName extends
| ContractEventName<abi>
| ContractEventName<abi>[]
| undefined = undefined,
>(
parameters: ParseEventLogsParameters<abi, eventName, strict>,
): ParseEventLogsReturnType<abi, eventName, strict> {
const { abi, args, logs, strict = true } = parameters
const eventName = (() => {
if (!parameters.eventName) return undefined
if (Array.isArray(parameters.eventName)) return parameters.eventName
return [parameters.eventName as string]
})()
const abiTopics = (abi as Abi)
.filter((abiItem) => abiItem.type === 'event')
.map((abiItem) => ({
abi: abiItem,
selector: toEventSelector(abiItem),
}))
return logs
.map((log) => {
// Normalize RpcLog (hex-encoded quantities) to Log (bigint/number).
// When logs come directly from an RPC response (e.g. eth_getLogs),
// fields like blockNumber are hex strings instead of bigints.
const formattedLog =
typeof log.blockNumber === 'string' ? formatLog(log as RpcLog) : log
// Find all matching ABI items with the same selector.
// Multiple events can share the same selector but differ in indexed parameters
// (e.g., ERC20 vs ERC721 Transfer events).
const abiItems = abiTopics.filter(
(abiTopic) => formattedLog.topics[0] === abiTopic.selector,
)
if (abiItems.length === 0) return null
// Try each matching ABI item until one successfully decodes.
let event: { eventName: string; args: unknown } | undefined
let abiItem: { abi: AbiEvent; selector: Address } | undefined
for (const item of abiItems) {
try {
event = decodeEventLog({
...formattedLog,
abi: [item.abi],
strict: true,
})
abiItem = item
break
} catch {
// Try next ABI item
}
}
// If strict decoding failed for all, and we're in non-strict mode,
// fall back to the first matching ABI item.
if (!event && !strict) {
abiItem = abiItems[0]
try {
event = decodeEventLog({
data: formattedLog.data,
topics: formattedLog.topics,
abi: [abiItem.abi],
strict: false,
})
} catch {
// If decoding still fails, return partial log in non-strict mode.
const isUnnamed = abiItem.abi.inputs?.some(
(x) => !('name' in x && x.name),
)
return {
...formattedLog,
args: isUnnamed ? [] : {},
eventName: abiItem.abi.name,
}
}
}
// If no event was found, return null.
if (!event || !abiItem) return null
// Check that the decoded event name matches the provided event name.
if (eventName && !eventName.includes(event.eventName)) return null
// Check that the decoded event args match the provided args.
if (
!includesArgs({
args: event.args,
inputs: abiItem.abi.inputs,
matchArgs: args,
})
)
return null
return { ...event, ...formattedLog }
})
.filter(Boolean) as unknown as ParseEventLogsReturnType<
abi,
eventName,
strict
>
}
function includesArgs(parameters: {
args: unknown
inputs: AbiEvent['inputs']
matchArgs: unknown
}) {
const { args, inputs, matchArgs } = parameters
if (!matchArgs) return true
if (!args) return false
function isEqual(input: AbiEventParameter, value: unknown, arg: unknown) {
try {
if (input.type === 'address')
return isAddressEqual(value as Address, arg as Address)
if (input.type === 'string' || input.type === 'bytes')
return keccak256(toBytes(value as string)) === arg
return value === arg
} catch {
return false
}
}
if (Array.isArray(args) && Array.isArray(matchArgs)) {
return matchArgs.every((value, index) => {
if (value === null || value === undefined) return true
const input = inputs[index]
if (!input) return false
const value_ = Array.isArray(value) ? value : [value]
return value_.some((value) => isEqual(input, value, args[index]))
})
}
if (
typeof args === 'object' &&
!Array.isArray(args) &&
typeof matchArgs === 'object' &&
!Array.isArray(matchArgs)
)
return Object.entries(matchArgs).every(([key, value]) => {
if (value === null || value === undefined) return true
const input = inputs.find((input) => input.name === key)
if (!input) return false
const value_ = Array.isArray(value) ? value : [value]
return value_.some((value) =>
isEqual(input, value, (args as Record<string, unknown>)[key]),
)
})
return false
}

View File

@@ -0,0 +1,111 @@
import type {
Abi,
AbiStateMutability,
ExtractAbiFunction,
ExtractAbiFunctions,
} from 'abitype'
import {
AbiFunctionNotFoundError,
type AbiFunctionNotFoundErrorType,
} from '../../errors/abi.js'
import type { ErrorType } from '../../errors/utils.js'
import type {
ContractFunctionArgs,
ContractFunctionName,
} from '../../types/contract.js'
import type { Hex } from '../../types/misc.js'
import type { IsNarrowable, UnionEvaluate } from '../../types/utils.js'
import type { ConcatHexErrorType } from '../data/concat.js'
import {
type ToFunctionSelectorErrorType,
toFunctionSelector,
} from '../hash/toFunctionSelector.js'
import { type FormatAbiItemErrorType, formatAbiItem } from './formatAbiItem.js'
import { type GetAbiItemErrorType, getAbiItem } from './getAbiItem.js'
const docsPath = '/docs/contract/encodeFunctionData'
export type PrepareEncodeFunctionDataParameters<
abi extends Abi | readonly unknown[] = Abi,
functionName extends
| ContractFunctionName<abi>
| undefined = ContractFunctionName<abi>,
///
hasFunctions = abi extends Abi
? Abi extends abi
? true
: [ExtractAbiFunctions<abi>] extends [never]
? false
: true
: true,
allArgs = ContractFunctionArgs<
abi,
AbiStateMutability,
functionName extends ContractFunctionName<abi>
? functionName
: ContractFunctionName<abi>
>,
allFunctionNames = ContractFunctionName<abi>,
> = {
abi: abi
} & UnionEvaluate<
IsNarrowable<abi, Abi> extends true
? abi['length'] extends 1
? { functionName?: functionName | allFunctionNames | Hex | undefined }
: { functionName: functionName | allFunctionNames | Hex }
: { functionName?: functionName | allFunctionNames | Hex | undefined }
> &
UnionEvaluate<{ args?: allArgs | undefined }> &
(hasFunctions extends true ? unknown : never)
export type PrepareEncodeFunctionDataReturnType<
abi extends Abi | readonly unknown[] = Abi,
functionName extends
| ContractFunctionName<abi>
| undefined = ContractFunctionName<abi>,
> = {
abi: abi extends Abi
? functionName extends ContractFunctionName<abi>
? [ExtractAbiFunction<abi, functionName>]
: abi
: Abi
functionName: Hex
}
export type PrepareEncodeFunctionDataErrorType =
| AbiFunctionNotFoundErrorType
| ConcatHexErrorType
| FormatAbiItemErrorType
| GetAbiItemErrorType
| ToFunctionSelectorErrorType
| ErrorType
export function prepareEncodeFunctionData<
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName<abi> | undefined = undefined,
>(
parameters: PrepareEncodeFunctionDataParameters<abi, functionName>,
): PrepareEncodeFunctionDataReturnType<abi, functionName> {
const { abi, args, functionName } =
parameters as PrepareEncodeFunctionDataParameters
let abiItem = abi[0]
if (functionName) {
const item = getAbiItem({
abi,
args,
name: functionName,
})
if (!item) throw new AbiFunctionNotFoundError(functionName, { docsPath })
abiItem = item
}
if (abiItem.type !== 'function')
throw new AbiFunctionNotFoundError(undefined, { docsPath })
return {
abi: [abiItem],
functionName: toFunctionSelector(formatAbiItem(abiItem)),
} as unknown as PrepareEncodeFunctionDataReturnType<abi, functionName>
}

81
node_modules/viem/utils/address/getAddress.ts generated vendored Normal file
View File

@@ -0,0 +1,81 @@
import type { Address } from 'abitype'
import { InvalidAddressError } from '../../errors/address.js'
import type { ErrorType } from '../../errors/utils.js'
import {
type StringToBytesErrorType,
stringToBytes,
} from '../encoding/toBytes.js'
import { type Keccak256ErrorType, keccak256 } from '../hash/keccak256.js'
import { LruMap } from '../lru.js'
import { type IsAddressErrorType, isAddress } from './isAddress.js'
const checksumAddressCache = /*#__PURE__*/ new LruMap<Address>(8192)
export type ChecksumAddressErrorType =
| Keccak256ErrorType
| StringToBytesErrorType
| ErrorType
export function checksumAddress(
address_: Address,
/**
* Warning: EIP-1191 checksum addresses are generally not backwards compatible with the
* wider Ethereum ecosystem, meaning it will break when validated against an application/tool
* that relies on EIP-55 checksum encoding (checksum without chainId).
*
* It is highly recommended to not use this feature unless you
* know what you are doing.
*
* See more: https://github.com/ethereum/EIPs/issues/1121
*/
chainId?: number | undefined,
): Address {
if (checksumAddressCache.has(`${address_}.${chainId}`))
return checksumAddressCache.get(`${address_}.${chainId}`)!
const hexAddress = chainId
? `${chainId}${address_.toLowerCase()}`
: address_.substring(2).toLowerCase()
const hash = keccak256(stringToBytes(hexAddress), 'bytes')
const address = (
chainId ? hexAddress.substring(`${chainId}0x`.length) : hexAddress
).split('')
for (let i = 0; i < 40; i += 2) {
if (hash[i >> 1] >> 4 >= 8 && address[i]) {
address[i] = address[i].toUpperCase()
}
if ((hash[i >> 1] & 0x0f) >= 8 && address[i + 1]) {
address[i + 1] = address[i + 1].toUpperCase()
}
}
const result = `0x${address.join('')}` as const
checksumAddressCache.set(`${address_}.${chainId}`, result)
return result
}
export type GetAddressErrorType =
| ChecksumAddressErrorType
| IsAddressErrorType
| ErrorType
export function getAddress(
address: string,
/**
* Warning: EIP-1191 checksum addresses are generally not backwards compatible with the
* wider Ethereum ecosystem, meaning it will break when validated against an application/tool
* that relies on EIP-55 checksum encoding (checksum without chainId).
*
* It is highly recommended to not use this feature unless you
* know what you are doing.
*
* See more: https://github.com/ethereum/EIPs/issues/1121
*/
chainId?: number,
): Address {
if (!isAddress(address, { strict: false }))
throw new InvalidAddressError({ address })
return checksumAddress(address, chainId)
}

87
node_modules/viem/utils/address/getContractAddress.ts generated vendored Normal file
View File

@@ -0,0 +1,87 @@
import type { Address } from 'abitype'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type ConcatErrorType, concat } from '../data/concat.js'
import { type IsBytesErrorType, isBytes } from '../data/isBytes.js'
import { type PadErrorType, pad } from '../data/pad.js'
import { type SliceErrorType, slice } from '../data/slice.js'
import { type ToBytesErrorType, toBytes } from '../encoding/toBytes.js'
import { type ToRlpErrorType, toRlp } from '../encoding/toRlp.js'
import { type Keccak256ErrorType, keccak256 } from '../hash/keccak256.js'
import { type GetAddressErrorType, getAddress } from './getAddress.js'
export type GetCreateAddressOptions = {
from: Address
nonce: bigint
}
export type GetCreate2AddressOptions =
| {
bytecode: ByteArray | Hex
from: Address
salt: ByteArray | Hex
}
| {
bytecodeHash: ByteArray | Hex
from: Address
salt: ByteArray | Hex
}
export type GetContractAddressOptions =
| ({
opcode?: 'CREATE' | undefined
} & GetCreateAddressOptions)
| ({ opcode: 'CREATE2' } & GetCreate2AddressOptions)
export function getContractAddress(opts: GetContractAddressOptions) {
if (opts.opcode === 'CREATE2') return getCreate2Address(opts)
return getCreateAddress(opts)
}
export type GetCreateAddressErrorType =
| Keccak256ErrorType
| GetAddressErrorType
| ToBytesErrorType
| ToRlpErrorType
| ErrorType
export function getCreateAddress(opts: GetCreateAddressOptions) {
const from = toBytes(getAddress(opts.from))
let nonce = toBytes(opts.nonce)
if (nonce[0] === 0) nonce = new Uint8Array([])
return getAddress(
`0x${keccak256(toRlp([from, nonce], 'bytes')).slice(26)}` as Address,
)
}
export type GetCreate2AddressErrorType =
| ConcatErrorType
| Keccak256ErrorType
| GetAddressErrorType
| IsBytesErrorType
| PadErrorType
| SliceErrorType
| ToBytesErrorType
| ToRlpErrorType
| ErrorType
export function getCreate2Address(opts: GetCreate2AddressOptions) {
const from = toBytes(getAddress(opts.from))
const salt = pad(isBytes(opts.salt) ? opts.salt : toBytes(opts.salt), {
size: 32,
})
const bytecodeHash = (() => {
if ('bytecodeHash' in opts) {
if (isBytes(opts.bytecodeHash)) return opts.bytecodeHash
return toBytes(opts.bytecodeHash)
}
return keccak256(opts.bytecode, 'bytes')
})()
return getAddress(
slice(keccak256(concat([toBytes('0xff'), from, salt, bytecodeHash])), 12),
)
}

39
node_modules/viem/utils/address/isAddress.ts generated vendored Normal file
View File

@@ -0,0 +1,39 @@
import type { Address } from 'abitype'
import type { ErrorType } from '../../errors/utils.js'
import { LruMap } from '../lru.js'
import { checksumAddress } from './getAddress.js'
const addressRegex = /^0x[a-fA-F0-9]{40}$/
/** @internal */
export const isAddressCache = /*#__PURE__*/ new LruMap<boolean>(8192)
export type IsAddressOptions = {
/**
* Enables strict mode. Whether or not to compare the address against its checksum.
*
* @default true
*/
strict?: boolean | undefined
}
export type IsAddressErrorType = ErrorType
export function isAddress(
address: string,
options?: IsAddressOptions | undefined,
): address is Address {
const { strict = true } = options ?? {}
const cacheKey = `${address}.${strict}`
if (isAddressCache.has(cacheKey)) return isAddressCache.get(cacheKey)!
const result = (() => {
if (!addressRegex.test(address)) return false
if (address.toLowerCase() === address) return true
if (strict) return checksumAddress(address as Address) === address
return true
})()
isAddressCache.set(cacheKey, result)
return result
}

19
node_modules/viem/utils/address/isAddressEqual.ts generated vendored Normal file
View File

@@ -0,0 +1,19 @@
import type { Address } from 'abitype'
import {
InvalidAddressError,
type InvalidAddressErrorType,
} from '../../errors/address.js'
import type { ErrorType } from '../../errors/utils.js'
import { isAddress } from './isAddress.js'
export type IsAddressEqualReturnType = boolean
export type IsAddressEqualErrorType = InvalidAddressErrorType | ErrorType
export function isAddressEqual(a: Address, b: Address) {
if (!isAddress(a, { strict: false }))
throw new InvalidAddressError({ address: a })
if (!isAddress(b, { strict: false }))
throw new InvalidAddressError({ address: b })
return a.toLowerCase() === b.toLowerCase()
}

View File

@@ -0,0 +1,50 @@
import type { ErrorType } from '../../errors/utils.js'
import type { AuthorizationRequest } from '../../types/authorization.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type ConcatHexErrorType, concatHex } from '../data/concat.js'
import { type HexToBytesErrorType, hexToBytes } from '../encoding/toBytes.js'
import { type NumberToHexErrorType, numberToHex } from '../encoding/toHex.js'
import { type ToRlpErrorType, toRlp } from '../encoding/toRlp.js'
import { type Keccak256ErrorType, keccak256 } from '../hash/keccak256.js'
type To = 'hex' | 'bytes'
export type HashAuthorizationParameters<to extends To> =
AuthorizationRequest & {
/** Output format. @default "hex" */
to?: to | To | undefined
}
export type HashAuthorizationReturnType<to extends To> =
| (to extends 'bytes' ? ByteArray : never)
| (to extends 'hex' ? Hex : never)
export type HashAuthorizationErrorType =
| Keccak256ErrorType
| ConcatHexErrorType
| ToRlpErrorType
| NumberToHexErrorType
| HexToBytesErrorType
| ErrorType
/**
* Computes an Authorization hash in [EIP-7702 format](https://eips.ethereum.org/EIPS/eip-7702): `keccak256('0x05' || rlp([chain_id, address, nonce]))`.
*/
export function hashAuthorization<to extends To = 'hex'>(
parameters: HashAuthorizationParameters<to>,
): HashAuthorizationReturnType<to> {
const { chainId, nonce, to } = parameters
const address = parameters.contractAddress ?? parameters.address
const hash = keccak256(
concatHex([
'0x05',
toRlp([
chainId ? numberToHex(chainId) : '0x',
address,
nonce ? numberToHex(nonce) : '0x',
]),
]),
)
if (to === 'bytes') return hexToBytes(hash) as HashAuthorizationReturnType<to>
return hash as HashAuthorizationReturnType<to>
}

View File

@@ -0,0 +1,66 @@
import type { Address } from 'abitype'
import type { ErrorType } from '../../errors/utils.js'
import type {
Authorization,
AuthorizationRequest,
SignedAuthorization,
} from '../../types/authorization.js'
import type { ByteArray, Hex, Signature } from '../../types/misc.js'
import type { OneOf } from '../../types/utils.js'
import {
type RecoverAddressErrorType,
recoverAddress,
} from '../signature/recoverAddress.js'
import {
type HashAuthorizationErrorType,
hashAuthorization,
} from './hashAuthorization.js'
export type RecoverAuthorizationAddressParameters<
authorization extends OneOf<
Authorization | AuthorizationRequest | SignedAuthorization
> = OneOf<Authorization | AuthorizationRequest | SignedAuthorization>,
//
_signature = Hex | ByteArray | OneOf<Signature | SignedAuthorization>,
> = {
/**
* The Authorization object.
*
* - If an unsigned `authorization` is provided, the `signature` property is required.
* - If a signed `authorization` is provided, the `signature` property does not need to be provided.
*/
authorization:
| authorization
| OneOf<Authorization | AuthorizationRequest | SignedAuthorization>
} & (authorization extends SignedAuthorization
? {
/** Signature of the Authorization. Not required if the `authorization` is signed. */
signature?: _signature | undefined
}
: {
/** Signature of the Authorization. Not required if the `authorization` is signed. */
signature: _signature
})
export type RecoverAuthorizationAddressReturnType = Address
export type RecoverAuthorizationAddressErrorType =
| HashAuthorizationErrorType
| RecoverAddressErrorType
| ErrorType
export async function recoverAuthorizationAddress<
const authorization extends OneOf<
Authorization | AuthorizationRequest | SignedAuthorization
>,
>(
parameters: RecoverAuthorizationAddressParameters<authorization>,
): Promise<RecoverAuthorizationAddressReturnType> {
const { authorization, signature } = parameters
return recoverAddress({
hash: hashAuthorization(authorization as AuthorizationRequest),
signature: (signature ?? authorization) as Signature,
})
}

View File

@@ -0,0 +1,34 @@
import type { ErrorType } from '../../errors/utils.js'
import type {
AuthorizationList,
SerializedAuthorizationList,
} from '../../types/authorization.js'
import { toHex } from '../encoding/toHex.js'
import { toYParitySignatureArray } from '../transaction/serializeTransaction.js'
export type SerializeAuthorizationListReturnType = SerializedAuthorizationList
export type SerializeAuthorizationListErrorType = ErrorType
/*
* Serializes an EIP-7702 authorization list.
*/
export function serializeAuthorizationList(
authorizationList?: AuthorizationList<number, true> | undefined,
): SerializeAuthorizationListReturnType {
if (!authorizationList || authorizationList.length === 0) return []
const serializedAuthorizationList = []
for (const authorization of authorizationList) {
const { chainId, nonce, ...signature } = authorization
const contractAddress = authorization.address
serializedAuthorizationList.push([
chainId ? toHex(chainId) : '0x',
contractAddress,
nonce ? toHex(nonce) : '0x',
...toYParitySignatureArray({}, signature),
])
}
return serializedAuthorizationList as {} as SerializeAuthorizationListReturnType
}

View File

@@ -0,0 +1,49 @@
import type { Address } from 'abitype'
import type { ErrorType } from '../../errors/utils.js'
import { type GetAddressErrorType, getAddress } from '../address/getAddress.js'
import {
type IsAddressEqualErrorType,
isAddressEqual,
} from '../address/isAddressEqual.js'
import {
type RecoverAuthorizationAddressErrorType,
type RecoverAuthorizationAddressParameters,
recoverAuthorizationAddress,
} from './recoverAuthorizationAddress.js'
export type VerifyAuthorizationParameters =
RecoverAuthorizationAddressParameters & {
/** The address that signed the Authorization object. */
address: Address
}
export type VerifyAuthorizationReturnType = boolean
export type VerifyAuthorizationErrorType =
| IsAddressEqualErrorType
| GetAddressErrorType
| RecoverAuthorizationAddressErrorType
| ErrorType
/**
* Verify that an Authorization object was signed by the provided address.
*
* - Docs {@link https://viem.sh/docs/utilities/verifyAuthorization}
*
* @param parameters - {@link VerifyAuthorizationParameters}
* @returns Whether or not the signature is valid. {@link VerifyAuthorizationReturnType}
*/
export async function verifyAuthorization({
address,
authorization,
signature,
}: VerifyAuthorizationParameters): Promise<VerifyAuthorizationReturnType> {
return isAddressEqual(
getAddress(address),
await recoverAuthorizationAddress({
authorization,
signature,
}),
)
}

71
node_modules/viem/utils/blob/blobsToCommitments.ts generated vendored Normal file
View File

@@ -0,0 +1,71 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Kzg } from '../../types/kzg.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type HexToBytesErrorType, hexToBytes } from '../encoding/toBytes.js'
import { type BytesToHexErrorType, bytesToHex } from '../encoding/toHex.js'
type To = 'hex' | 'bytes'
export type BlobsToCommitmentsParameters<
blobs extends readonly ByteArray[] | readonly Hex[] =
| readonly ByteArray[]
| readonly Hex[],
to extends To | undefined = undefined,
> = {
/** Blobs to transform into commitments. */
blobs: blobs | readonly ByteArray[] | readonly Hex[]
/** KZG implementation. */
kzg: Pick<Kzg, 'blobToKzgCommitment'>
/** Return type. */
to?: to | To | undefined
}
export type BlobsToCommitmentsReturnType<to extends To> =
| (to extends 'bytes' ? readonly ByteArray[] : never)
| (to extends 'hex' ? readonly Hex[] : never)
export type BlobsToCommitmentsErrorType =
| HexToBytesErrorType
| BytesToHexErrorType
| ErrorType
/**
* Compute commitments from a list of blobs.
*
* @example
* ```ts
* import { blobsToCommitments, toBlobs } from 'viem'
* import { kzg } from './kzg'
*
* const blobs = toBlobs({ data: '0x1234' })
* const commitments = blobsToCommitments({ blobs, kzg })
* ```
*/
export function blobsToCommitments<
const blobs extends readonly ByteArray[] | readonly Hex[],
to extends To =
| (blobs extends readonly Hex[] ? 'hex' : never)
| (blobs extends readonly ByteArray[] ? 'bytes' : never),
>(
parameters: BlobsToCommitmentsParameters<blobs, to>,
): BlobsToCommitmentsReturnType<to> {
const { kzg } = parameters
const to =
parameters.to ?? (typeof parameters.blobs[0] === 'string' ? 'hex' : 'bytes')
const blobs = (
typeof parameters.blobs[0] === 'string'
? parameters.blobs.map((x) => hexToBytes(x as any))
: parameters.blobs
) as ByteArray[]
const commitments: ByteArray[] = []
for (const blob of blobs)
commitments.push(Uint8Array.from(kzg.blobToKzgCommitment(blob)))
return (to === 'bytes'
? commitments
: commitments.map((x) =>
bytesToHex(x),
)) as {} as BlobsToCommitmentsReturnType<to>
}

93
node_modules/viem/utils/blob/blobsToProofs.ts generated vendored Normal file
View File

@@ -0,0 +1,93 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Kzg } from '../../types/kzg.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type HexToBytesErrorType, hexToBytes } from '../encoding/toBytes.js'
import { type BytesToHexErrorType, bytesToHex } from '../encoding/toHex.js'
type To = 'hex' | 'bytes'
export type blobsToProofsParameters<
blobs extends readonly ByteArray[] | readonly Hex[],
commitments extends readonly ByteArray[] | readonly Hex[],
to extends To =
| (blobs extends readonly Hex[] ? 'hex' : never)
| (blobs extends readonly ByteArray[] ? 'bytes' : never),
///
_blobsType =
| (blobs extends readonly Hex[] ? readonly Hex[] : never)
| (blobs extends readonly ByteArray[] ? readonly ByteArray[] : never),
> = {
/** Blobs to transform into proofs. */
blobs: blobs
/** Commitments for the blobs. */
commitments: commitments &
(commitments extends _blobsType
? {}
: `commitments must be the same type as blobs`)
/** KZG implementation. */
kzg: Pick<Kzg, 'computeBlobKzgProof'>
/** Return type. */
to?: to | To | undefined
}
export type blobsToProofsReturnType<to extends To> =
| (to extends 'bytes' ? ByteArray[] : never)
| (to extends 'hex' ? Hex[] : never)
export type blobsToProofsErrorType =
| BytesToHexErrorType
| HexToBytesErrorType
| ErrorType
/**
* Compute the proofs for a list of blobs and their commitments.
*
* @example
* ```ts
* import {
* blobsToCommitments,
* toBlobs
* } from 'viem'
* import { kzg } from './kzg'
*
* const blobs = toBlobs({ data: '0x1234' })
* const commitments = blobsToCommitments({ blobs, kzg })
* const proofs = blobsToProofs({ blobs, commitments, kzg })
* ```
*/
export function blobsToProofs<
const blobs extends readonly ByteArray[] | readonly Hex[],
const commitments extends readonly ByteArray[] | readonly Hex[],
to extends To =
| (blobs extends readonly Hex[] ? 'hex' : never)
| (blobs extends readonly ByteArray[] ? 'bytes' : never),
>(
parameters: blobsToProofsParameters<blobs, commitments, to>,
): blobsToProofsReturnType<to> {
const { kzg } = parameters
const to =
parameters.to ?? (typeof parameters.blobs[0] === 'string' ? 'hex' : 'bytes')
const blobs = (
typeof parameters.blobs[0] === 'string'
? parameters.blobs.map((x) => hexToBytes(x as any))
: parameters.blobs
) as ByteArray[]
const commitments = (
typeof parameters.commitments[0] === 'string'
? parameters.commitments.map((x) => hexToBytes(x as any))
: parameters.commitments
) as ByteArray[]
const proofs: ByteArray[] = []
for (let i = 0; i < blobs.length; i++) {
const blob = blobs[i]
const commitment = commitments[i]
proofs.push(Uint8Array.from(kzg.computeBlobKzgProof(blob, commitment)))
}
return (to === 'bytes'
? proofs
: proofs.map((x) => bytesToHex(x))) as {} as blobsToProofsReturnType<to>
}

View File

@@ -0,0 +1,62 @@
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type BytesToHexErrorType, bytesToHex } from '../encoding/toHex.js'
import { type Sha256ErrorType, sha256 } from '../hash/sha256.js'
type To = 'hex' | 'bytes'
export type CommitmentToVersionedHashParameters<
commitment extends Uint8Array | Hex = Uint8Array | Hex,
to extends To | undefined = undefined,
> = {
/** Commitment from blob. */
commitment: commitment | Uint8Array | Hex
/** Return type. */
to?: to | To | undefined
/** Version to tag onto the hash. */
version?: number | undefined
}
export type CommitmentToVersionedHashReturnType<to extends To> =
| (to extends 'bytes' ? ByteArray : never)
| (to extends 'hex' ? Hex : never)
export type CommitmentToVersionedHashErrorType =
| Sha256ErrorType
| BytesToHexErrorType
| ErrorType
/**
* Transform a commitment to it's versioned hash.
*
* @example
* ```ts
* import {
* blobsToCommitments,
* commitmentToVersionedHash,
* toBlobs
* } from 'viem'
* import { kzg } from './kzg'
*
* const blobs = toBlobs({ data: '0x1234' })
* const [commitment] = blobsToCommitments({ blobs, kzg })
* const versionedHash = commitmentToVersionedHash({ commitment })
* ```
*/
export function commitmentToVersionedHash<
const commitment extends Hex | ByteArray,
to extends To =
| (commitment extends Hex ? 'hex' : never)
| (commitment extends ByteArray ? 'bytes' : never),
>(
parameters: CommitmentToVersionedHashParameters<commitment, to>,
): CommitmentToVersionedHashReturnType<to> {
const { commitment, version = 1 } = parameters
const to = parameters.to ?? (typeof commitment === 'string' ? 'hex' : 'bytes')
const versionedHash = sha256(commitment, 'bytes')
versionedHash.set([version], 0)
return (
to === 'bytes' ? versionedHash : bytesToHex(versionedHash)
) as CommitmentToVersionedHashReturnType<to>
}

View File

@@ -0,0 +1,73 @@
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import {
type CommitmentToVersionedHashErrorType,
commitmentToVersionedHash,
} from './commitmentToVersionedHash.js'
type To = 'hex' | 'bytes'
export type CommitmentsToVersionedHashesParameters<
commitments extends readonly Uint8Array[] | readonly Hex[] =
| readonly Uint8Array[]
| readonly Hex[],
to extends To | undefined = undefined,
> = {
/** Commitments from blobs. */
commitments: commitments | readonly Uint8Array[] | readonly Hex[]
/** Return type. */
to?: to | To | undefined
/** Version to tag onto the hashes. */
version?: number | undefined
}
export type CommitmentsToVersionedHashesReturnType<to extends To> =
| (to extends 'bytes' ? readonly ByteArray[] : never)
| (to extends 'hex' ? readonly Hex[] : never)
export type CommitmentsToVersionedHashesErrorType =
| CommitmentToVersionedHashErrorType
| ErrorType
/**
* Transform a list of commitments to their versioned hashes.
*
* @example
* ```ts
* import {
* blobsToCommitments,
* commitmentsToVersionedHashes,
* toBlobs
* } from 'viem'
* import { kzg } from './kzg'
*
* const blobs = toBlobs({ data: '0x1234' })
* const commitments = blobsToCommitments({ blobs, kzg })
* const versionedHashes = commitmentsToVersionedHashes({ commitments })
* ```
*/
export function commitmentsToVersionedHashes<
const commitments extends readonly Uint8Array[] | readonly Hex[],
to extends To =
| (commitments extends readonly Hex[] ? 'hex' : never)
| (commitments extends readonly ByteArray[] ? 'bytes' : never),
>(
parameters: CommitmentsToVersionedHashesParameters<commitments, to>,
): CommitmentsToVersionedHashesReturnType<to> {
const { commitments, version } = parameters
const to =
parameters.to ?? (typeof commitments[0] === 'string' ? 'hex' : 'bytes')
const hashes: Uint8Array[] | Hex[] = []
for (const commitment of commitments) {
hashes.push(
commitmentToVersionedHash({
commitment,
to,
version,
}) as any,
)
}
return hashes as any
}

75
node_modules/viem/utils/blob/fromBlobs.ts generated vendored Normal file
View File

@@ -0,0 +1,75 @@
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type CreateCursorErrorType, createCursor } from '../cursor.js'
import { type HexToBytesErrorType, hexToBytes } from '../encoding/toBytes.js'
import { type BytesToHexErrorType, bytesToHex } from '../encoding/toHex.js'
type To = 'hex' | 'bytes'
export type FromBlobsParameters<
blobs extends readonly Hex[] | readonly ByteArray[] =
| readonly Hex[]
| readonly ByteArray[],
to extends To | undefined = undefined,
> = {
/** Blobs to transform to data. */
blobs: blobs | readonly Hex[] | readonly ByteArray[]
to?: to | To | undefined
}
export type FromBlobsReturnType<to extends To> =
| (to extends 'bytes' ? ByteArray : never)
| (to extends 'hex' ? Hex : never)
export type FromBlobsErrorType =
| BytesToHexErrorType
| CreateCursorErrorType
| HexToBytesErrorType
| ErrorType
export function fromBlobs<
const blobs extends readonly Hex[] | readonly ByteArray[],
to extends To =
| (blobs extends readonly Hex[] ? 'hex' : never)
| (blobs extends readonly ByteArray[] ? 'bytes' : never),
>(parameters: FromBlobsParameters<blobs, to>): FromBlobsReturnType<to> {
const to =
parameters.to ?? (typeof parameters.blobs[0] === 'string' ? 'hex' : 'bytes')
const blobs = (
typeof parameters.blobs[0] === 'string'
? parameters.blobs.map((x) => hexToBytes(x as Hex))
: parameters.blobs
) as ByteArray[]
const length = blobs.reduce((length, blob) => length + blob.length, 0)
const data = createCursor(new Uint8Array(length))
let active = true
for (const blob of blobs) {
const cursor = createCursor(blob)
while (active && cursor.position < blob.length) {
// First byte will be a zero 0x00 byte we can skip.
cursor.incrementPosition(1)
let consume = 31
if (blob.length - cursor.position < 31)
consume = blob.length - cursor.position
for (const _ in Array.from({ length: consume })) {
const byte = cursor.readByte()
const isTerminator =
byte === 0x80 && !cursor.inspectBytes(cursor.remaining).includes(0x80)
if (isTerminator) {
active = false
break
}
data.pushByte(byte)
}
}
}
const trimmedData = data.bytes.slice(0, data.position)
return (
to === 'hex' ? bytesToHex(trimmedData) : trimmedData
) as FromBlobsReturnType<to>
}

View File

@@ -0,0 +1,66 @@
import type { ErrorType } from '../../errors/utils.js'
import type { BlobSidecars } from '../../types/eip4844.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import {
type CommitmentToVersionedHashErrorType,
commitmentToVersionedHash,
} from './commitmentToVersionedHash.js'
type To = 'hex' | 'bytes'
export type SidecarsToVersionedHashesParameters<
sidecars extends BlobSidecars = BlobSidecars,
to extends To | undefined = undefined,
> = {
/** Sidecars from blobs. */
sidecars: sidecars | BlobSidecars
/** Return type. */
to?: to | To | undefined
/** Version to tag onto the hashes. */
version?: number | undefined
}
export type SidecarsToVersionedHashesReturnType<to extends To> =
| (to extends 'bytes' ? readonly ByteArray[] : never)
| (to extends 'hex' ? readonly Hex[] : never)
export type SidecarsToVersionedHashesErrorType =
| CommitmentToVersionedHashErrorType
| ErrorType
/**
* Transforms a list of sidecars to their versioned hashes.
*
* @example
* ```ts
* import { toBlobSidecars, sidecarsToVersionedHashes, stringToHex } from 'viem'
*
* const sidecars = toBlobSidecars({ data: stringToHex('hello world') })
* const versionedHashes = sidecarsToVersionedHashes({ sidecars })
* ```
*/
export function sidecarsToVersionedHashes<
const sidecars extends BlobSidecars,
to extends To =
| (sidecars extends BlobSidecars<Hex> ? 'hex' : never)
| (sidecars extends BlobSidecars<ByteArray> ? 'bytes' : never),
>(
parameters: SidecarsToVersionedHashesParameters<sidecars, to>,
): SidecarsToVersionedHashesReturnType<to> {
const { sidecars, version } = parameters
const to =
parameters.to ?? (typeof sidecars[0].blob === 'string' ? 'hex' : 'bytes')
const hashes: Uint8Array[] | Hex[] = []
for (const { commitment } of sidecars) {
hashes.push(
commitmentToVersionedHash({
commitment,
to,
version,
}) as any,
)
}
return hashes as any
}

112
node_modules/viem/utils/blob/toBlobSidecars.ts generated vendored Normal file
View File

@@ -0,0 +1,112 @@
import type { ErrorType } from '../../errors/utils.js'
import type { BlobSidecars } from '../../types/eip4844.js'
import type { Kzg } from '../../types/kzg.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import type { OneOf } from '../../types/utils.js'
import {
type BlobsToCommitmentsErrorType,
blobsToCommitments,
} from './blobsToCommitments.js'
import { blobsToProofs, type blobsToProofsErrorType } from './blobsToProofs.js'
import { type ToBlobsErrorType, toBlobs } from './toBlobs.js'
type To = 'hex' | 'bytes'
export type ToBlobSidecarsParameters<
data extends Hex | ByteArray | undefined = undefined,
blobs extends readonly Hex[] | readonly ByteArray[] | undefined = undefined,
to extends To =
| (blobs extends readonly Hex[] ? 'hex' : never)
| (blobs extends readonly ByteArray[] ? 'bytes' : never),
///
_blobsType =
| (blobs extends readonly Hex[] ? readonly Hex[] : never)
| (blobs extends readonly ByteArray[] ? readonly ByteArray[] : never),
> = {
/** Return type. */
to?: to | To | undefined
} & OneOf<
| {
/** Data to transform into blobs. */
data: data | Hex | ByteArray
/** KZG implementation. */
kzg: Kzg
}
| {
/** Blobs. */
blobs: blobs | readonly Hex[] | readonly ByteArray[]
/** Commitment for each blob. */
commitments: _blobsType | readonly Hex[] | readonly ByteArray[]
/** Proof for each blob. */
proofs: _blobsType | readonly Hex[] | readonly ByteArray[]
}
>
export type ToBlobSidecarsReturnType<to extends To> =
| (to extends 'bytes' ? BlobSidecars<ByteArray> : never)
| (to extends 'hex' ? BlobSidecars<Hex> : never)
export type ToBlobSidecarsErrorType =
| BlobsToCommitmentsErrorType
| ToBlobsErrorType
| blobsToProofsErrorType
| ErrorType
/**
* Transforms arbitrary data (or blobs, commitments, & proofs) into a sidecar array.
*
* @example
* ```ts
* import { toBlobSidecars, stringToHex } from 'viem'
*
* const sidecars = toBlobSidecars({ data: stringToHex('hello world') })
* ```
*
* @example
* ```ts
* import {
* blobsToCommitments,
* toBlobs,
* blobsToProofs,
* toBlobSidecars,
* stringToHex
* } from 'viem'
*
* const blobs = toBlobs({ data: stringToHex('hello world') })
* const commitments = blobsToCommitments({ blobs, kzg })
* const proofs = blobsToProofs({ blobs, commitments, kzg })
*
* const sidecars = toBlobSidecars({ blobs, commitments, proofs })
* ```
*/
export function toBlobSidecars<
const data extends Hex | ByteArray | undefined = undefined,
const blobs extends
| readonly Hex[]
| readonly ByteArray[]
| undefined = undefined,
to extends To =
| (data extends Hex ? 'hex' : never)
| (data extends ByteArray ? 'bytes' : never)
| (blobs extends readonly Hex[] ? 'hex' : never)
| (blobs extends readonly ByteArray[] ? 'bytes' : never),
>(
parameters: ToBlobSidecarsParameters<data, blobs, to>,
): ToBlobSidecarsReturnType<to> {
const { data, kzg, to } = parameters
const blobs = parameters.blobs ?? toBlobs({ data: data!, to })
const commitments =
parameters.commitments ?? blobsToCommitments({ blobs, kzg: kzg!, to })
const proofs =
parameters.proofs ?? blobsToProofs({ blobs, commitments, kzg: kzg!, to })
const sidecars: BlobSidecars = []
for (let i = 0; i < blobs.length; i++)
sidecars.push({
blob: blobs[i],
commitment: commitments[i],
proof: proofs[i],
})
return sidecars as ToBlobSidecarsReturnType<to>
}

114
node_modules/viem/utils/blob/toBlobs.ts generated vendored Normal file
View File

@@ -0,0 +1,114 @@
import {
bytesPerBlob,
bytesPerFieldElement,
fieldElementsPerBlob,
maxBytesPerTransaction,
} from '../../constants/blob.js'
import {
BlobSizeTooLargeError,
type BlobSizeTooLargeErrorType,
EmptyBlobError,
type EmptyBlobErrorType,
} from '../../errors/blob.js'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type CreateCursorErrorType, createCursor } from '../cursor.js'
import { type SizeErrorType, size } from '../data/size.js'
import { type HexToBytesErrorType, hexToBytes } from '../encoding/toBytes.js'
import { type BytesToHexErrorType, bytesToHex } from '../encoding/toHex.js'
type To = 'hex' | 'bytes'
export type ToBlobsParameters<
data extends Hex | ByteArray = Hex | ByteArray,
to extends To | undefined = undefined,
> = {
/** Data to transform to a blob. */
data: data | Hex | ByteArray
/** Return type. */
to?: to | To | undefined
}
export type ToBlobsReturnType<to extends To> =
| (to extends 'bytes' ? readonly ByteArray[] : never)
| (to extends 'hex' ? readonly Hex[] : never)
export type ToBlobsErrorType =
| BlobSizeTooLargeErrorType
| BytesToHexErrorType
| CreateCursorErrorType
| EmptyBlobErrorType
| HexToBytesErrorType
| SizeErrorType
| ErrorType
/**
* Transforms arbitrary data to blobs.
*
* @example
* ```ts
* import { toBlobs, stringToHex } from 'viem'
*
* const blobs = toBlobs({ data: stringToHex('hello world') })
* ```
*/
export function toBlobs<
const data extends Hex | ByteArray,
to extends To =
| (data extends Hex ? 'hex' : never)
| (data extends ByteArray ? 'bytes' : never),
>(parameters: ToBlobsParameters<data, to>): ToBlobsReturnType<to> {
const to =
parameters.to ?? (typeof parameters.data === 'string' ? 'hex' : 'bytes')
const data = (
typeof parameters.data === 'string'
? hexToBytes(parameters.data)
: parameters.data
) as ByteArray
const size_ = size(data)
if (!size_) throw new EmptyBlobError()
if (size_ > maxBytesPerTransaction)
throw new BlobSizeTooLargeError({
maxSize: maxBytesPerTransaction,
size: size_,
})
const blobs = []
let active = true
let position = 0
while (active) {
const blob = createCursor(new Uint8Array(bytesPerBlob))
let size = 0
while (size < fieldElementsPerBlob) {
const bytes = data.slice(position, position + (bytesPerFieldElement - 1))
// Push a zero byte so the field element doesn't overflow the BLS modulus.
blob.pushByte(0x00)
// Push the current segment of data bytes.
blob.pushBytes(bytes)
// If we detect that the current segment of data bytes is less than 31 bytes,
// we can stop processing and push a terminator byte to indicate the end of the blob.
if (bytes.length < 31) {
blob.pushByte(0x80)
active = false
break
}
size++
position += 31
}
blobs.push(blob)
}
return (
to === 'bytes'
? blobs.map((x) => x.bytes)
: blobs.map((x) => bytesToHex(x.bytes))
) as any
}

323
node_modules/viem/utils/buildRequest.ts generated vendored Normal file
View File

@@ -0,0 +1,323 @@
import { BaseError } from '../errors/base.js'
import {
HttpRequestError,
type HttpRequestErrorType,
type RpcRequestErrorType,
type TimeoutErrorType,
type WebSocketRequestErrorType,
} from '../errors/request.js'
import {
AtomicityNotSupportedError,
type AtomicityNotSupportedErrorType,
AtomicReadyWalletRejectedUpgradeError,
type AtomicReadyWalletRejectedUpgradeErrorType,
BundleTooLargeError,
type BundleTooLargeErrorType,
ChainDisconnectedError,
type ChainDisconnectedErrorType,
DuplicateIdError,
type DuplicateIdErrorType,
InternalRpcError,
type InternalRpcErrorType,
InvalidInputRpcError,
type InvalidInputRpcErrorType,
InvalidParamsRpcError,
type InvalidParamsRpcErrorType,
InvalidRequestRpcError,
type InvalidRequestRpcErrorType,
JsonRpcVersionUnsupportedError,
type JsonRpcVersionUnsupportedErrorType,
LimitExceededRpcError,
type LimitExceededRpcErrorType,
MethodNotFoundRpcError,
type MethodNotFoundRpcErrorType,
MethodNotSupportedRpcError,
type MethodNotSupportedRpcErrorType,
ParseRpcError,
type ParseRpcErrorType,
ProviderDisconnectedError,
type ProviderDisconnectedErrorType,
type ProviderRpcErrorCode,
ResourceNotFoundRpcError,
type ResourceNotFoundRpcErrorType,
ResourceUnavailableRpcError,
type ResourceUnavailableRpcErrorType,
type RpcError,
type RpcErrorCode,
type RpcErrorType,
SwitchChainError,
type SwitchChainErrorType,
TransactionRejectedRpcError,
type TransactionRejectedRpcErrorType,
UnauthorizedProviderError,
type UnauthorizedProviderErrorType,
UnknownBundleIdError,
type UnknownBundleIdErrorType,
UnknownRpcError,
type UnknownRpcErrorType,
UnsupportedChainIdError,
type UnsupportedChainIdErrorType,
UnsupportedNonOptionalCapabilityError,
type UnsupportedNonOptionalCapabilityErrorType,
UnsupportedProviderMethodError,
type UnsupportedProviderMethodErrorType,
UserRejectedRequestError,
type UserRejectedRequestErrorType,
WalletConnectSessionSettlementError,
type WalletConnectSessionSettlementErrorType,
} from '../errors/rpc.js'
import type { ErrorType } from '../errors/utils.js'
import type {
EIP1193RequestFn,
EIP1193RequestOptions,
} from '../types/eip1193.js'
import type { CreateBatchSchedulerErrorType } from './promise/createBatchScheduler.js'
import { withDedupe } from './promise/withDedupe.js'
import { type WithRetryErrorType, withRetry } from './promise/withRetry.js'
import type { GetSocketRpcClientErrorType } from './rpc/socket.js'
import { stringify } from './stringify.js'
export type RequestErrorType =
| AtomicityNotSupportedErrorType
| AtomicReadyWalletRejectedUpgradeErrorType
| BundleTooLargeErrorType
| ChainDisconnectedErrorType
| CreateBatchSchedulerErrorType
| DuplicateIdErrorType
| HttpRequestErrorType
| InternalRpcErrorType
| InvalidInputRpcErrorType
| InvalidParamsRpcErrorType
| InvalidRequestRpcErrorType
| GetSocketRpcClientErrorType
| JsonRpcVersionUnsupportedErrorType
| LimitExceededRpcErrorType
| MethodNotFoundRpcErrorType
| MethodNotSupportedRpcErrorType
| ParseRpcErrorType
| ProviderDisconnectedErrorType
| ResourceNotFoundRpcErrorType
| ResourceUnavailableRpcErrorType
| RpcErrorType
| RpcRequestErrorType
| SwitchChainErrorType
| TimeoutErrorType
| TransactionRejectedRpcErrorType
| UnauthorizedProviderErrorType
| UnknownBundleIdErrorType
| UnknownRpcErrorType
| UnsupportedChainIdErrorType
| UnsupportedNonOptionalCapabilityErrorType
| UnsupportedProviderMethodErrorType
| UserRejectedRequestErrorType
| WalletConnectSessionSettlementErrorType
| WebSocketRequestErrorType
| WithRetryErrorType
| ErrorType
export function buildRequest<request extends (args: any) => Promise<any>>(
request: request,
options: EIP1193RequestOptions = {},
): EIP1193RequestFn {
return async (args, overrideOptions = {}) => {
const {
dedupe = false,
methods,
retryDelay = 150,
retryCount = 3,
uid,
} = {
...options,
...overrideOptions,
}
const { method } = args
if (methods?.exclude?.includes(method))
throw new MethodNotSupportedRpcError(new Error('method not supported'), {
method,
})
if (methods?.include && !methods.include.includes(method))
throw new MethodNotSupportedRpcError(new Error('method not supported'), {
method,
})
const requestId = dedupe
? hashString(`${uid}.${stringify(args)}`)
: undefined
return withDedupe(
() =>
withRetry(
async () => {
try {
return await request(args)
} catch (err_) {
const err = err_ as unknown as RpcError<
RpcErrorCode | ProviderRpcErrorCode
>
switch (err.code) {
// -32700
case ParseRpcError.code:
throw new ParseRpcError(err)
// -32600
case InvalidRequestRpcError.code:
throw new InvalidRequestRpcError(err)
// -32601
case MethodNotFoundRpcError.code:
throw new MethodNotFoundRpcError(err, { method: args.method })
// -32602
case InvalidParamsRpcError.code:
throw new InvalidParamsRpcError(err)
// -32603
case InternalRpcError.code:
throw new InternalRpcError(err)
// -32000
case InvalidInputRpcError.code:
throw new InvalidInputRpcError(err)
// -32001
case ResourceNotFoundRpcError.code:
throw new ResourceNotFoundRpcError(err)
// -32002
case ResourceUnavailableRpcError.code:
throw new ResourceUnavailableRpcError(err)
// -32003
case TransactionRejectedRpcError.code:
throw new TransactionRejectedRpcError(err)
// -32004
case MethodNotSupportedRpcError.code:
throw new MethodNotSupportedRpcError(err, {
method: args.method,
})
// -32005
case LimitExceededRpcError.code:
throw new LimitExceededRpcError(err)
// -32006
case JsonRpcVersionUnsupportedError.code:
throw new JsonRpcVersionUnsupportedError(err)
// 4001
case UserRejectedRequestError.code:
throw new UserRejectedRequestError(err)
// 4100
case UnauthorizedProviderError.code:
throw new UnauthorizedProviderError(err)
// 4200
case UnsupportedProviderMethodError.code:
throw new UnsupportedProviderMethodError(err)
// 4900
case ProviderDisconnectedError.code:
throw new ProviderDisconnectedError(err)
// 4901
case ChainDisconnectedError.code:
throw new ChainDisconnectedError(err)
// 4902
case SwitchChainError.code:
throw new SwitchChainError(err)
// 5700
case UnsupportedNonOptionalCapabilityError.code:
throw new UnsupportedNonOptionalCapabilityError(err)
// 5710
case UnsupportedChainIdError.code:
throw new UnsupportedChainIdError(err)
// 5720
case DuplicateIdError.code:
throw new DuplicateIdError(err)
// 5730
case UnknownBundleIdError.code:
throw new UnknownBundleIdError(err)
// 5740
case BundleTooLargeError.code:
throw new BundleTooLargeError(err)
// 5750
case AtomicReadyWalletRejectedUpgradeError.code:
throw new AtomicReadyWalletRejectedUpgradeError(err)
// 5760
case AtomicityNotSupportedError.code:
throw new AtomicityNotSupportedError(err)
// CAIP-25: User Rejected Error
// https://docs.walletconnect.com/2.0/specs/clients/sign/error-codes#rejected-caip-25
case 5000:
throw new UserRejectedRequestError(err)
// WalletConnect: Session Settlement Failed
// https://docs.walletconnect.com/2.0/specs/clients/sign/error-codes
case WalletConnectSessionSettlementError.code:
throw new WalletConnectSessionSettlementError(err)
default:
if (err_ instanceof BaseError) throw err_
throw new UnknownRpcError(err as Error)
}
}
},
{
delay: ({ count, error }) => {
// If we find a Retry-After header, let's retry after the given time.
if (error && error instanceof HttpRequestError) {
const retryAfter = error?.headers?.get('Retry-After')
if (retryAfter?.match(/\d/))
return Number.parseInt(retryAfter, 10) * 1000
}
// Otherwise, let's retry with an exponential backoff.
return ~~(1 << count) * retryDelay
},
retryCount,
shouldRetry: ({ error }) => shouldRetry(error),
},
),
{ enabled: dedupe, id: requestId },
)
}
}
/** @internal */
export function shouldRetry(error: Error) {
if ('code' in error && typeof error.code === 'number') {
if (error.code === -1) return true // Unknown error
if (error.code === LimitExceededRpcError.code) return true
if (error.code === InternalRpcError.code) return true
// Too Many Requests — some providers (e.g. Alchemy in batch mode) return
// HTTP 200 with a JSON-RPC body of `{ code: 429 }` instead of an HTTP 429,
// so we need to handle this code in addition to the HTTP status check below.
if (error.code === 429) return true
return false
}
if (error instanceof HttpRequestError && error.status) {
// Forbidden
if (error.status === 403) return true
// Request Timeout
if (error.status === 408) return true
// Request Entity Too Large
if (error.status === 413) return true
// Too Many Requests
if (error.status === 429) return true
// Internal Server Error
if (error.status === 500) return true
// Bad Gateway
if (error.status === 502) return true
// Service Unavailable
if (error.status === 503) return true
// Gateway Timeout
if (error.status === 504) return true
return false
}
return true
}
/** @internal cyrb53 fast, non-cryptographic 53-bit string hash */
function hashString(str: string, seed = 0): string {
let h1 = 0xdeadbeef ^ seed
let h2 = 0x41c6ce57 ^ seed
for (let i = 0; i < str.length; i++) {
const ch = str.charCodeAt(i)
h1 = Math.imul(h1 ^ ch, 2654435761)
h2 = Math.imul(h2 ^ ch, 1597334677)
}
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507)
h1 ^= Math.imul(h2 ^ (h2 >>> 16), 3266489909)
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507)
h2 ^= Math.imul(h1 ^ (h1 >>> 16), 3266489909)
return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(36)
}

201
node_modules/viem/utils/ccip.ts generated vendored Normal file
View File

@@ -0,0 +1,201 @@
import type { Abi, Address } from 'abitype'
import { type CallParameters, call } from '../actions/public/call.js'
import type { Client } from '../clients/createClient.js'
import type { Transport } from '../clients/transports/createTransport.js'
import type { BaseError } from '../errors/base.js'
import {
OffchainLookupError,
type OffchainLookupErrorType as OffchainLookupErrorType_,
OffchainLookupResponseMalformedError,
type OffchainLookupResponseMalformedErrorType,
OffchainLookupSenderMismatchError,
} from '../errors/ccip.js'
import {
HttpRequestError,
type HttpRequestErrorType,
} from '../errors/request.js'
import type { ErrorType } from '../errors/utils.js'
import type { Chain } from '../types/chain.js'
import type { Hex } from '../types/misc.js'
import { decodeErrorResult } from './abi/decodeErrorResult.js'
import { encodeAbiParameters } from './abi/encodeAbiParameters.js'
import { isAddressEqual } from './address/isAddressEqual.js'
import { concat } from './data/concat.js'
import { isHex } from './data/isHex.js'
import {
localBatchGatewayRequest,
localBatchGatewayUrl,
} from './ens/localBatchGatewayRequest.js'
import { stringify } from './stringify.js'
export const offchainLookupSignature = '0x556f1830'
export const offchainLookupAbiItem = {
name: 'OffchainLookup',
type: 'error',
inputs: [
{
name: 'sender',
type: 'address',
},
{
name: 'urls',
type: 'string[]',
},
{
name: 'callData',
type: 'bytes',
},
{
name: 'callbackFunction',
type: 'bytes4',
},
{
name: 'extraData',
type: 'bytes',
},
],
} as const satisfies Abi[number]
export type OffchainLookupErrorType = OffchainLookupErrorType_ | ErrorType
export async function offchainLookup<chain extends Chain | undefined>(
client: Client<Transport, chain>,
{
blockNumber,
blockTag,
data,
to,
}: Pick<CallParameters, 'blockNumber' | 'blockTag'> & {
data: Hex
to: Address
},
): Promise<Hex> {
const { args } = decodeErrorResult({
data,
abi: [offchainLookupAbiItem],
})
const [sender, urls, callData, callbackSelector, extraData] = args
const { ccipRead } = client
const ccipRequest_ =
ccipRead && typeof ccipRead?.request === 'function'
? ccipRead.request
: ccipRequest
try {
if (!isAddressEqual(to, sender))
throw new OffchainLookupSenderMismatchError({ sender, to })
const result = urls.includes(localBatchGatewayUrl)
? await localBatchGatewayRequest({
data: callData,
ccipRequest: ccipRequest_,
})
: await ccipRequest_({ data: callData, sender, urls })
const { data: data_ } = await call(client, {
blockNumber,
blockTag,
data: concat([
callbackSelector,
encodeAbiParameters(
[{ type: 'bytes' }, { type: 'bytes' }],
[result, extraData],
),
]),
to,
} as CallParameters)
return data_!
} catch (err) {
throw new OffchainLookupError({
callbackSelector,
cause: err as BaseError,
data,
extraData,
sender,
urls,
})
}
}
export type CcipRequestParameters = {
data: Hex
sender: Address
urls: readonly string[]
}
export type CcipRequestReturnType = Hex
export type CcipRequestErrorType =
| HttpRequestErrorType
| OffchainLookupResponseMalformedErrorType
| ErrorType
export async function ccipRequest({
data,
sender,
urls,
}: CcipRequestParameters): Promise<CcipRequestReturnType> {
let error = new Error('An unknown error occurred.')
for (let i = 0; i < urls.length; i++) {
const url = urls[i]
const method = url.includes('{data}') ? 'GET' : 'POST'
const body = method === 'POST' ? { data, sender } : undefined
const headers: HeadersInit =
method === 'POST' ? { 'Content-Type': 'application/json' } : {}
try {
const response = await fetch(
url.replace('{sender}', sender.toLowerCase()).replace('{data}', data),
{
body: JSON.stringify(body),
headers,
method,
},
)
let result: any
if (
response.headers.get('Content-Type')?.startsWith('application/json')
) {
result = (await response.json()).data
} else {
result = (await response.text()) as any
}
if (!response.ok) {
error = new HttpRequestError({
body,
details: result?.error
? stringify(result.error)
: response.statusText,
headers: response.headers,
status: response.status,
url,
})
continue
}
if (!isHex(result)) {
error = new OffchainLookupResponseMalformedError({
result,
url,
})
continue
}
return result
} catch (err) {
error = new HttpRequestError({
body,
details: (err as Error).message,
url,
})
}
}
throw error
}

27
node_modules/viem/utils/chain/assertCurrentChain.ts generated vendored Normal file
View File

@@ -0,0 +1,27 @@
import {
ChainMismatchError,
type ChainMismatchErrorType,
ChainNotFoundError,
type ChainNotFoundErrorType,
} from '../../errors/chain.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Chain } from '../../types/chain.js'
export type AssertCurrentChainParameters = {
chain?: Chain | undefined
currentChainId: number
}
export type AssertCurrentChainErrorType =
| ChainNotFoundErrorType
| ChainMismatchErrorType
| ErrorType
export function assertCurrentChain({
chain,
currentChainId,
}: AssertCurrentChainParameters): void {
if (!chain) throw new ChainNotFoundError()
if (currentChainId !== chain.id)
throw new ChainMismatchError({ chain, currentChainId })
}

44
node_modules/viem/utils/chain/defineChain.ts generated vendored Normal file
View File

@@ -0,0 +1,44 @@
import type { Chain, ChainFormatters } from '../../types/chain.js'
import type { Assign, Prettify } from '../../types/utils.js'
export type DefineChainReturnType<chain extends Chain = Chain> = Prettify<
chain &
(chain['extendSchema'] extends Record<string, unknown>
? {
extend: <const extended extends chain['extendSchema']>(
extended: extended,
) => Assign<chain, extended>
}
: {})
>
export function defineChain<
formatters extends ChainFormatters,
const chain extends Chain<formatters>,
>(chain: chain): DefineChainReturnType<Assign<Chain<undefined>, chain>> {
const chainInstance = {
formatters: undefined,
fees: undefined,
serializers: undefined,
...chain,
} as Assign<Chain<undefined>, chain>
function extend(base: typeof chainInstance) {
type ExtendFn = (base: typeof chainInstance) => unknown
return (fnOrExtended: ExtendFn | Record<string, unknown>) => {
const properties = (
typeof fnOrExtended === 'function' ? fnOrExtended(base) : fnOrExtended
) as (typeof chainInstance)['extendSchema']
const combined = { ...base, ...properties }
return Object.assign(combined, { extend: extend(combined) })
}
}
return Object.assign(chainInstance, {
extend: extend(chainInstance),
}) as never
}
export function extendSchema<schema extends Record<string, unknown>>(): schema {
return {} as schema
}

33
node_modules/viem/utils/chain/extractChain.ts generated vendored Normal file
View File

@@ -0,0 +1,33 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Chain } from '../../types/chain.js'
export type ExtractChainParameters<
chains extends readonly Chain[],
chainId extends chains[number]['id'],
> = {
chains: chains
id: chainId | chains[number]['id']
}
export type ExtractChainReturnType<
chains extends readonly Chain[],
chainId extends chains[number]['id'],
> = Extract<chains[number], { id: chainId }>
export type ExtractChainErrorType = ErrorType
export function extractChain<
const chains extends readonly Chain[],
chainId extends chains[number]['id'],
>({
chains,
id,
}: ExtractChainParameters<chains, chainId>): ExtractChainReturnType<
chains,
chainId
> {
return chains.find((chain) => chain.id === id) as ExtractChainReturnType<
chains,
chainId
>
}

View File

@@ -0,0 +1,41 @@
import {
ChainDoesNotSupportContract,
type ChainDoesNotSupportContractErrorType,
} from '../../errors/chain.js'
import type { Chain, ChainContract } from '../../types/chain.js'
export type GetChainContractAddressErrorType =
ChainDoesNotSupportContractErrorType
export function getChainContractAddress({
blockNumber,
chain,
contract: name,
}: {
blockNumber?: bigint | undefined
chain: Chain
contract: string
}) {
const contract = (chain?.contracts as Record<string, ChainContract>)?.[name]
if (!contract)
throw new ChainDoesNotSupportContract({
chain,
contract: { name },
})
if (
blockNumber &&
contract.blockCreated &&
contract.blockCreated > blockNumber
)
throw new ChainDoesNotSupportContract({
blockNumber,
chain,
contract: {
name,
blockCreated: contract.blockCreated,
},
})
return contract.address
}

243
node_modules/viem/utils/cursor.ts generated vendored Normal file
View File

@@ -0,0 +1,243 @@
import {
NegativeOffsetError,
type NegativeOffsetErrorType,
PositionOutOfBoundsError,
type PositionOutOfBoundsErrorType,
RecursiveReadLimitExceededError,
type RecursiveReadLimitExceededErrorType,
} from '../errors/cursor.js'
import type { ErrorType } from '../errors/utils.js'
import type { ByteArray } from '../types/misc.js'
export type Cursor = {
bytes: ByteArray
dataView: DataView
position: number
positionReadCount: Map<number, number>
recursiveReadCount: number
recursiveReadLimit: number
remaining: number
assertReadLimit(position?: number): void
assertPosition(position: number): void
decrementPosition(offset: number): void
getReadCount(position?: number): number
incrementPosition(offset: number): void
inspectByte(position?: number): ByteArray[number]
inspectBytes(length: number, position?: number): ByteArray
inspectUint8(position?: number): number
inspectUint16(position?: number): number
inspectUint24(position?: number): number
inspectUint32(position?: number): number
pushByte(byte: ByteArray[number]): void
pushBytes(bytes: ByteArray): void
pushUint8(value: number): void
pushUint16(value: number): void
pushUint24(value: number): void
pushUint32(value: number): void
readByte(): ByteArray[number]
readBytes(length: number, size?: number): ByteArray
readUint8(): number
readUint16(): number
readUint24(): number
readUint32(): number
setPosition(position: number): () => void
_touch(): void
}
type CursorErrorType =
| CursorAssertPositionErrorType
| CursorDecrementPositionErrorType
| CursorIncrementPositionErrorType
| ErrorType
type CursorAssertPositionErrorType = PositionOutOfBoundsErrorType | ErrorType
type CursorDecrementPositionErrorType = NegativeOffsetErrorType | ErrorType
type CursorIncrementPositionErrorType = NegativeOffsetErrorType | ErrorType
type StaticCursorErrorType =
| NegativeOffsetErrorType
| RecursiveReadLimitExceededErrorType
const staticCursor: Cursor = {
bytes: new Uint8Array(),
dataView: new DataView(new ArrayBuffer(0)),
position: 0,
positionReadCount: new Map(),
recursiveReadCount: 0,
recursiveReadLimit: Number.POSITIVE_INFINITY,
assertReadLimit() {
if (this.recursiveReadCount >= this.recursiveReadLimit)
throw new RecursiveReadLimitExceededError({
count: this.recursiveReadCount + 1,
limit: this.recursiveReadLimit,
})
},
assertPosition(position) {
if (position < 0 || position > this.bytes.length - 1)
throw new PositionOutOfBoundsError({
length: this.bytes.length,
position,
})
},
decrementPosition(offset) {
if (offset < 0) throw new NegativeOffsetError({ offset })
const position = this.position - offset
this.assertPosition(position)
this.position = position
},
getReadCount(position) {
return this.positionReadCount.get(position || this.position) || 0
},
incrementPosition(offset) {
if (offset < 0) throw new NegativeOffsetError({ offset })
const position = this.position + offset
this.assertPosition(position)
this.position = position
},
inspectByte(position_) {
const position = position_ ?? this.position
this.assertPosition(position)
return this.bytes[position]
},
inspectBytes(length, position_) {
const position = position_ ?? this.position
this.assertPosition(position + length - 1)
return this.bytes.subarray(position, position + length)
},
inspectUint8(position_) {
const position = position_ ?? this.position
this.assertPosition(position)
return this.bytes[position]
},
inspectUint16(position_) {
const position = position_ ?? this.position
this.assertPosition(position + 1)
return this.dataView.getUint16(position)
},
inspectUint24(position_) {
const position = position_ ?? this.position
this.assertPosition(position + 2)
return (
(this.dataView.getUint16(position) << 8) +
this.dataView.getUint8(position + 2)
)
},
inspectUint32(position_) {
const position = position_ ?? this.position
this.assertPosition(position + 3)
return this.dataView.getUint32(position)
},
pushByte(byte: ByteArray[number]) {
this.assertPosition(this.position)
this.bytes[this.position] = byte
this.position++
},
pushBytes(bytes: ByteArray) {
this.assertPosition(this.position + bytes.length - 1)
this.bytes.set(bytes, this.position)
this.position += bytes.length
},
pushUint8(value: number) {
this.assertPosition(this.position)
this.bytes[this.position] = value
this.position++
},
pushUint16(value: number) {
this.assertPosition(this.position + 1)
this.dataView.setUint16(this.position, value)
this.position += 2
},
pushUint24(value: number) {
this.assertPosition(this.position + 2)
this.dataView.setUint16(this.position, value >> 8)
this.dataView.setUint8(this.position + 2, value & ~4294967040)
this.position += 3
},
pushUint32(value: number) {
this.assertPosition(this.position + 3)
this.dataView.setUint32(this.position, value)
this.position += 4
},
readByte() {
this.assertReadLimit()
this._touch()
const value = this.inspectByte()
this.position++
return value
},
readBytes(length, size) {
this.assertReadLimit()
this._touch()
const value = this.inspectBytes(length)
this.position += size ?? length
return value
},
readUint8() {
this.assertReadLimit()
this._touch()
const value = this.inspectUint8()
this.position += 1
return value
},
readUint16() {
this.assertReadLimit()
this._touch()
const value = this.inspectUint16()
this.position += 2
return value
},
readUint24() {
this.assertReadLimit()
this._touch()
const value = this.inspectUint24()
this.position += 3
return value
},
readUint32() {
this.assertReadLimit()
this._touch()
const value = this.inspectUint32()
this.position += 4
return value
},
get remaining() {
return this.bytes.length - this.position
},
setPosition(position) {
const oldPosition = this.position
this.assertPosition(position)
this.position = position
return () => (this.position = oldPosition)
},
_touch() {
if (this.recursiveReadLimit === Number.POSITIVE_INFINITY) return
const count = this.getReadCount()
this.positionReadCount.set(this.position, count + 1)
if (count > 0) this.recursiveReadCount++
},
}
type CursorConfig = { recursiveReadLimit?: number | undefined }
export type CreateCursorErrorType =
| CursorErrorType
| StaticCursorErrorType
| ErrorType
export function createCursor(
bytes: ByteArray,
{ recursiveReadLimit = 8_192 }: CursorConfig = {},
): Cursor {
const cursor: Cursor = Object.create(staticCursor)
cursor.bytes = bytes
cursor.dataView = new DataView(
bytes.buffer ?? bytes,
bytes.byteOffset,
bytes.byteLength,
)
cursor.positionReadCount = new Map()
cursor.recursiveReadLimit = recursiveReadLimit
return cursor
}

44
node_modules/viem/utils/data/concat.ts generated vendored Normal file
View File

@@ -0,0 +1,44 @@
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
export type ConcatReturnType<value extends Hex | ByteArray> = value extends Hex
? Hex
: ByteArray
export type ConcatErrorType =
| ConcatBytesErrorType
| ConcatHexErrorType
| ErrorType
export function concat<value extends Hex | ByteArray>(
values: readonly value[],
): ConcatReturnType<value> {
if (typeof values[0] === 'string')
return concatHex(values as readonly Hex[]) as ConcatReturnType<value>
return concatBytes(values as readonly ByteArray[]) as ConcatReturnType<value>
}
export type ConcatBytesErrorType = ErrorType
export function concatBytes(values: readonly ByteArray[]): ByteArray {
let length = 0
for (const arr of values) {
length += arr.length
}
const result = new Uint8Array(length)
let offset = 0
for (const arr of values) {
result.set(arr, offset)
offset += arr.length
}
return result
}
export type ConcatHexErrorType = ErrorType
export function concatHex(values: readonly Hex[]): Hex {
return `0x${(values as Hex[]).reduce(
(acc, x) => acc + x.replace('0x', ''),
'',
)}`
}

13
node_modules/viem/utils/data/isBytes.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray } from '../../types/misc.js'
export type IsBytesErrorType = ErrorType
export function isBytes(value: unknown): value is ByteArray {
if (!value) return false
if (typeof value !== 'object') return false
if (!('BYTES_PER_ELEMENT' in value)) return false
return (
value.BYTES_PER_ELEMENT === 1 && value.constructor.name === 'Uint8Array'
)
}

13
node_modules/viem/utils/data/isHex.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Hex } from '../../types/misc.js'
export type IsHexErrorType = ErrorType
export function isHex(
value: unknown,
{ strict = true }: { strict?: boolean | undefined } = {},
): value is Hex {
if (!value) return false
if (typeof value !== 'string') return false
return strict ? /^0x[0-9a-fA-F]*$/.test(value) : value.startsWith('0x')
}

65
node_modules/viem/utils/data/pad.ts generated vendored Normal file
View File

@@ -0,0 +1,65 @@
import {
SizeExceedsPaddingSizeError,
type SizeExceedsPaddingSizeErrorType,
} from '../../errors/data.js'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
type PadOptions = {
dir?: 'left' | 'right' | undefined
size?: number | null | undefined
}
export type PadReturnType<value extends ByteArray | Hex> = value extends Hex
? Hex
: ByteArray
export type PadErrorType = PadHexErrorType | PadBytesErrorType | ErrorType
export function pad<value extends ByteArray | Hex>(
hexOrBytes: value,
{ dir, size = 32 }: PadOptions = {},
): PadReturnType<value> {
if (typeof hexOrBytes === 'string')
return padHex(hexOrBytes, { dir, size }) as PadReturnType<value>
return padBytes(hexOrBytes, { dir, size }) as PadReturnType<value>
}
export type PadHexErrorType = SizeExceedsPaddingSizeErrorType | ErrorType
export function padHex(hex_: Hex, { dir, size = 32 }: PadOptions = {}) {
if (size === null) return hex_
const hex = hex_.replace('0x', '')
if (hex.length > size * 2)
throw new SizeExceedsPaddingSizeError({
size: Math.ceil(hex.length / 2),
targetSize: size,
type: 'hex',
})
return `0x${hex[dir === 'right' ? 'padEnd' : 'padStart'](
size * 2,
'0',
)}` as Hex
}
export type PadBytesErrorType = SizeExceedsPaddingSizeErrorType | ErrorType
export function padBytes(
bytes: ByteArray,
{ dir, size = 32 }: PadOptions = {},
) {
if (size === null) return bytes
if (bytes.length > size)
throw new SizeExceedsPaddingSizeError({
size: bytes.length,
targetSize: size,
type: 'bytes',
})
const paddedBytes = new Uint8Array(size)
for (let i = 0; i < size; i++) {
const padEnd = dir === 'right'
paddedBytes[padEnd ? i : size - i - 1] =
bytes[padEnd ? i : bytes.length - i - 1]
}
return paddedBytes
}

17
node_modules/viem/utils/data/size.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type IsHexErrorType, isHex } from './isHex.js'
export type SizeErrorType = IsHexErrorType | ErrorType
/**
* @description Retrieves the size of the value (in bytes).
*
* @param value The value (hex or byte array) to retrieve the size of.
* @returns The size of the value (in bytes).
*/
export function size(value: Hex | ByteArray) {
if (isHex(value, { strict: false })) return Math.ceil((value.length - 2) / 2)
return value.length
}

128
node_modules/viem/utils/data/slice.ts generated vendored Normal file
View File

@@ -0,0 +1,128 @@
import {
SliceOffsetOutOfBoundsError,
type SliceOffsetOutOfBoundsErrorType,
} from '../../errors/data.js'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type IsHexErrorType, isHex } from './isHex.js'
import { type SizeErrorType, size } from './size.js'
export type SliceReturnType<value extends ByteArray | Hex> = value extends Hex
? Hex
: ByteArray
export type SliceErrorType =
| IsHexErrorType
| SliceBytesErrorType
| SliceHexErrorType
| ErrorType
/**
* @description Returns a section of the hex or byte array given a start/end bytes offset.
*
* @param value The hex or byte array to slice.
* @param start The start offset (in bytes).
* @param end The end offset (in bytes).
*/
export function slice<value extends ByteArray | Hex>(
value: value,
start?: number | undefined,
end?: number | undefined,
{ strict }: { strict?: boolean | undefined } = {},
): SliceReturnType<value> {
if (isHex(value, { strict: false }))
return sliceHex(value as Hex, start, end, {
strict,
}) as SliceReturnType<value>
return sliceBytes(value as ByteArray, start, end, {
strict,
}) as SliceReturnType<value>
}
export type AssertStartOffsetErrorType =
| SliceOffsetOutOfBoundsErrorType
| SizeErrorType
| ErrorType
function assertStartOffset(value: Hex | ByteArray, start?: number | undefined) {
if (typeof start === 'number' && start > 0 && start > size(value) - 1)
throw new SliceOffsetOutOfBoundsError({
offset: start,
position: 'start',
size: size(value),
})
}
export type AssertEndOffsetErrorType =
| SliceOffsetOutOfBoundsErrorType
| SizeErrorType
| ErrorType
function assertEndOffset(
value: Hex | ByteArray,
start?: number | undefined,
end?: number | undefined,
) {
if (
typeof start === 'number' &&
typeof end === 'number' &&
size(value) !== end - start
) {
throw new SliceOffsetOutOfBoundsError({
offset: end,
position: 'end',
size: size(value),
})
}
}
export type SliceBytesErrorType =
| AssertStartOffsetErrorType
| AssertEndOffsetErrorType
| ErrorType
/**
* @description Returns a section of the byte array given a start/end bytes offset.
*
* @param value The byte array to slice.
* @param start The start offset (in bytes).
* @param end The end offset (in bytes).
*/
export function sliceBytes(
value_: ByteArray,
start?: number | undefined,
end?: number | undefined,
{ strict }: { strict?: boolean | undefined } = {},
): ByteArray {
assertStartOffset(value_, start)
const value = value_.slice(start, end)
if (strict) assertEndOffset(value, start, end)
return value
}
export type SliceHexErrorType =
| AssertStartOffsetErrorType
| AssertEndOffsetErrorType
| ErrorType
/**
* @description Returns a section of the hex value given a start/end bytes offset.
*
* @param value The hex value to slice.
* @param start The start offset (in bytes).
* @param end The end offset (in bytes).
*/
export function sliceHex(
value_: Hex,
start?: number | undefined,
end?: number | undefined,
{ strict }: { strict?: boolean | undefined } = {},
): Hex {
assertStartOffset(value_, start)
const value = `0x${value_
.replace('0x', '')
.slice((start ?? 0) * 2, (end ?? value_.length) * 2)}` as const
if (strict) assertEndOffset(value, start, end)
return value
}

38
node_modules/viem/utils/data/trim.ts generated vendored Normal file
View File

@@ -0,0 +1,38 @@
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
type TrimOptions = {
dir?: 'left' | 'right' | undefined
}
export type TrimReturnType<value extends ByteArray | Hex> = value extends Hex
? Hex
: ByteArray
export type TrimErrorType = ErrorType
export function trim<value extends ByteArray | Hex>(
hexOrBytes: value,
{ dir = 'left' }: TrimOptions = {},
): TrimReturnType<value> {
let data: any =
typeof hexOrBytes === 'string' ? hexOrBytes.replace('0x', '') : hexOrBytes
let sliceLength = 0
for (let i = 0; i < data.length - 1; i++) {
if (data[dir === 'left' ? i : data.length - i - 1].toString() === '0')
sliceLength++
else break
}
data =
dir === 'left'
? data.slice(sliceLength)
: data.slice(0, data.length - sliceLength)
if (typeof hexOrBytes === 'string') {
if (data.length === 1 && dir === 'right') data = `${data}0`
return `0x${
data.length % 2 === 1 ? `0${data}` : data
}` as TrimReturnType<value>
}
return data as TrimReturnType<value>
}

227
node_modules/viem/utils/encoding/fromBytes.ts generated vendored Normal file
View File

@@ -0,0 +1,227 @@
import { InvalidBytesBooleanError } from '../../errors/encoding.js'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type TrimErrorType, trim } from '../data/trim.js'
import {
type AssertSizeErrorType,
assertSize,
type HexToBigIntErrorType,
type HexToNumberErrorType,
hexToBigInt,
hexToNumber,
} from './fromHex.js'
import { type BytesToHexErrorType, bytesToHex } from './toHex.js'
export type FromBytesParameters<
to extends 'string' | 'hex' | 'bigint' | 'number' | 'boolean',
> =
| to
| {
/** Size of the bytes. */
size?: number | undefined
/** Type to convert to. */
to: to
}
export type FromBytesReturnType<to> = to extends 'string'
? string
: to extends 'hex'
? Hex
: to extends 'bigint'
? bigint
: to extends 'number'
? number
: to extends 'boolean'
? boolean
: never
export type FromBytesErrorType =
| BytesToHexErrorType
| BytesToBigIntErrorType
| BytesToBoolErrorType
| BytesToNumberErrorType
| BytesToStringErrorType
| ErrorType
/**
* Decodes a byte array into a UTF-8 string, hex value, number, bigint or boolean.
*
* - Docs: https://viem.sh/docs/utilities/fromBytes
* - Example: https://viem.sh/docs/utilities/fromBytes#usage
*
* @param bytes Byte array to decode.
* @param toOrOpts Type to convert to or options.
* @returns Decoded value.
*
* @example
* import { fromBytes } from 'viem'
* const data = fromBytes(new Uint8Array([1, 164]), 'number')
* // 420
*
* @example
* import { fromBytes } from 'viem'
* const data = fromBytes(
* new Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]),
* 'string'
* )
* // 'Hello world'
*/
export function fromBytes<
to extends 'string' | 'hex' | 'bigint' | 'number' | 'boolean',
>(
bytes: ByteArray,
toOrOpts: FromBytesParameters<to>,
): FromBytesReturnType<to> {
const opts = typeof toOrOpts === 'string' ? { to: toOrOpts } : toOrOpts
const to = opts.to
if (to === 'number')
return bytesToNumber(bytes, opts) as FromBytesReturnType<to>
if (to === 'bigint')
return bytesToBigInt(bytes, opts) as FromBytesReturnType<to>
if (to === 'boolean')
return bytesToBool(bytes, opts) as FromBytesReturnType<to>
if (to === 'string')
return bytesToString(bytes, opts) as FromBytesReturnType<to>
return bytesToHex(bytes, opts) as FromBytesReturnType<to>
}
export type BytesToBigIntOpts = {
/** Whether or not the number of a signed representation. */
signed?: boolean | undefined
/** Size of the bytes. */
size?: number | undefined
}
export type BytesToBigIntErrorType =
| BytesToHexErrorType
| HexToBigIntErrorType
| ErrorType
/**
* Decodes a byte array into a bigint.
*
* - Docs: https://viem.sh/docs/utilities/fromBytes#bytestobigint
*
* @param bytes Byte array to decode.
* @param opts Options.
* @returns BigInt value.
*
* @example
* import { bytesToBigInt } from 'viem'
* const data = bytesToBigInt(new Uint8Array([1, 164]))
* // 420n
*/
export function bytesToBigInt(
bytes: ByteArray,
opts: BytesToBigIntOpts = {},
): bigint {
if (typeof opts.size !== 'undefined') assertSize(bytes, { size: opts.size })
const hex = bytesToHex(bytes, opts)
return hexToBigInt(hex, opts)
}
export type BytesToBoolOpts = {
/** Size of the bytes. */
size?: number | undefined
}
export type BytesToBoolErrorType =
| AssertSizeErrorType
| TrimErrorType
| ErrorType
/**
* Decodes a byte array into a boolean.
*
* - Docs: https://viem.sh/docs/utilities/fromBytes#bytestobool
*
* @param bytes Byte array to decode.
* @param opts Options.
* @returns Boolean value.
*
* @example
* import { bytesToBool } from 'viem'
* const data = bytesToBool(new Uint8Array([1]))
* // true
*/
export function bytesToBool(
bytes_: ByteArray,
opts: BytesToBoolOpts = {},
): boolean {
let bytes = bytes_
if (typeof opts.size !== 'undefined') {
assertSize(bytes, { size: opts.size })
bytes = trim(bytes)
}
if (bytes.length > 1 || bytes[0] > 1)
throw new InvalidBytesBooleanError(bytes)
return Boolean(bytes[0])
}
export type BytesToNumberOpts = BytesToBigIntOpts
export type BytesToNumberErrorType =
| BytesToHexErrorType
| HexToNumberErrorType
| ErrorType
/**
* Decodes a byte array into a number.
*
* - Docs: https://viem.sh/docs/utilities/fromBytes#bytestonumber
*
* @param bytes Byte array to decode.
* @param opts Options.
* @returns Number value.
*
* @example
* import { bytesToNumber } from 'viem'
* const data = bytesToNumber(new Uint8Array([1, 164]))
* // 420
*/
export function bytesToNumber(
bytes: ByteArray,
opts: BytesToNumberOpts = {},
): number {
if (typeof opts.size !== 'undefined') assertSize(bytes, { size: opts.size })
const hex = bytesToHex(bytes, opts)
return hexToNumber(hex, opts)
}
export type BytesToStringOpts = {
/** Size of the bytes. */
size?: number | undefined
}
export type BytesToStringErrorType =
| AssertSizeErrorType
| TrimErrorType
| ErrorType
/**
* Decodes a byte array into a UTF-8 string.
*
* - Docs: https://viem.sh/docs/utilities/fromBytes#bytestostring
*
* @param bytes Byte array to decode.
* @param opts Options.
* @returns String value.
*
* @example
* import { bytesToString } from 'viem'
* const data = bytesToString(new Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]))
* // 'Hello world'
*/
export function bytesToString(
bytes_: ByteArray,
opts: BytesToStringOpts = {},
): string {
let bytes = bytes_
if (typeof opts.size !== 'undefined') {
assertSize(bytes, { size: opts.size })
bytes = trim(bytes, { dir: 'right' })
}
return new TextDecoder().decode(bytes)
}

267
node_modules/viem/utils/encoding/fromHex.ts generated vendored Normal file
View File

@@ -0,0 +1,267 @@
import {
IntegerOutOfRangeError,
type IntegerOutOfRangeErrorType,
InvalidHexBooleanError,
type InvalidHexBooleanErrorType,
SizeOverflowError,
type SizeOverflowErrorType,
} from '../../errors/encoding.js'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type SizeErrorType, size as size_ } from '../data/size.js'
import { type TrimErrorType, trim } from '../data/trim.js'
import { type HexToBytesErrorType, hexToBytes } from './toBytes.js'
export type AssertSizeErrorType =
| SizeOverflowErrorType
| SizeErrorType
| ErrorType
export function assertSize(
hexOrBytes: Hex | ByteArray,
{ size }: { size: number },
): void {
if (size_(hexOrBytes) > size)
throw new SizeOverflowError({
givenSize: size_(hexOrBytes),
maxSize: size,
})
}
export type FromHexParameters<
to extends 'string' | 'bigint' | 'number' | 'bytes' | 'boolean',
> =
| to
| {
/** Size (in bytes) of the hex value. */
size?: number | undefined
/** Type to convert to. */
to: to
}
export type FromHexReturnType<to> = to extends 'string'
? string
: to extends 'bigint'
? bigint
: to extends 'number'
? number
: to extends 'bytes'
? ByteArray
: to extends 'boolean'
? boolean
: never
export type FromHexErrorType =
| HexToNumberErrorType
| HexToBigIntErrorType
| HexToBoolErrorType
| HexToStringErrorType
| HexToBytesErrorType
| ErrorType
/**
* Decodes a hex string into a string, number, bigint, boolean, or byte array.
*
* - Docs: https://viem.sh/docs/utilities/fromHex
* - Example: https://viem.sh/docs/utilities/fromHex#usage
*
* @param hex Hex string to decode.
* @param toOrOpts Type to convert to or options.
* @returns Decoded value.
*
* @example
* import { fromHex } from 'viem'
* const data = fromHex('0x1a4', 'number')
* // 420
*
* @example
* import { fromHex } from 'viem'
* const data = fromHex('0x48656c6c6f20576f726c6421', 'string')
* // 'Hello world'
*
* @example
* import { fromHex } from 'viem'
* const data = fromHex('0x48656c6c6f20576f726c64210000000000000000000000000000000000000000', {
* size: 32,
* to: 'string'
* })
* // 'Hello world'
*/
export function fromHex<
to extends 'string' | 'bigint' | 'number' | 'bytes' | 'boolean',
>(hex: Hex, toOrOpts: FromHexParameters<to>): FromHexReturnType<to> {
const opts = typeof toOrOpts === 'string' ? { to: toOrOpts } : toOrOpts
const to = opts.to
if (to === 'number') return hexToNumber(hex, opts) as FromHexReturnType<to>
if (to === 'bigint') return hexToBigInt(hex, opts) as FromHexReturnType<to>
if (to === 'string') return hexToString(hex, opts) as FromHexReturnType<to>
if (to === 'boolean') return hexToBool(hex, opts) as FromHexReturnType<to>
return hexToBytes(hex, opts) as FromHexReturnType<to>
}
export type HexToBigIntOpts = {
/** Whether or not the number of a signed representation. */
signed?: boolean | undefined
/** Size (in bytes) of the hex value. */
size?: number | undefined
}
export type HexToBigIntErrorType = AssertSizeErrorType | ErrorType
/**
* Decodes a hex value into a bigint.
*
* - Docs: https://viem.sh/docs/utilities/fromHex#hextobigint
*
* @param hex Hex value to decode.
* @param opts Options.
* @returns BigInt value.
*
* @example
* import { hexToBigInt } from 'viem'
* const data = hexToBigInt('0x1a4', { signed: true })
* // 420n
*
* @example
* import { hexToBigInt } from 'viem'
* const data = hexToBigInt('0x00000000000000000000000000000000000000000000000000000000000001a4', { size: 32 })
* // 420n
*/
export function hexToBigInt(hex: Hex, opts: HexToBigIntOpts = {}): bigint {
const { signed } = opts
if (opts.size) assertSize(hex, { size: opts.size })
const value = BigInt(hex)
if (!signed) return value
const size = (hex.length - 2) / 2
const max = (1n << (BigInt(size) * 8n - 1n)) - 1n
if (value <= max) return value
return value - BigInt(`0x${'f'.padStart(size * 2, 'f')}`) - 1n
}
export type HexToBoolOpts = {
/** Size (in bytes) of the hex value. */
size?: number | undefined
}
export type HexToBoolErrorType =
| AssertSizeErrorType
| InvalidHexBooleanErrorType
| TrimErrorType
| ErrorType
/**
* Decodes a hex value into a boolean.
*
* - Docs: https://viem.sh/docs/utilities/fromHex#hextobool
*
* @param hex Hex value to decode.
* @param opts Options.
* @returns Boolean value.
*
* @example
* import { hexToBool } from 'viem'
* const data = hexToBool('0x01')
* // true
*
* @example
* import { hexToBool } from 'viem'
* const data = hexToBool('0x0000000000000000000000000000000000000000000000000000000000000001', { size: 32 })
* // true
*/
export function hexToBool(hex_: Hex, opts: HexToBoolOpts = {}): boolean {
let hex = hex_
if (opts.size) {
assertSize(hex, { size: opts.size })
hex = trim(hex)
}
if (trim(hex) === '0x00') return false
if (trim(hex) === '0x01') return true
throw new InvalidHexBooleanError(hex)
}
export type HexToNumberOpts = HexToBigIntOpts
export type HexToNumberErrorType =
| HexToBigIntErrorType
| IntegerOutOfRangeErrorType
| ErrorType
/**
* Decodes a hex string into a number.
*
* - Docs: https://viem.sh/docs/utilities/fromHex#hextonumber
*
* @param hex Hex value to decode.
* @param opts Options.
* @returns Number value.
*
* @example
* import { hexToNumber } from 'viem'
* const data = hexToNumber('0x1a4')
* // 420
*
* @example
* import { hexToNumber } from 'viem'
* const data = hexToBigInt('0x00000000000000000000000000000000000000000000000000000000000001a4', { size: 32 })
* // 420
*/
export function hexToNumber(hex: Hex, opts: HexToNumberOpts = {}): number {
const value = hexToBigInt(hex, opts)
const number = Number(value)
if (!Number.isSafeInteger(number))
throw new IntegerOutOfRangeError({
max: `${Number.MAX_SAFE_INTEGER}`,
min: `${Number.MIN_SAFE_INTEGER}`,
signed: opts.signed,
size: opts.size,
value: `${value}n`,
})
return number
}
export type HexToStringOpts = {
/** Size (in bytes) of the hex value. */
size?: number | undefined
}
export type HexToStringErrorType =
| AssertSizeErrorType
| HexToBytesErrorType
| TrimErrorType
| ErrorType
/**
* Decodes a hex value into a UTF-8 string.
*
* - Docs: https://viem.sh/docs/utilities/fromHex#hextostring
*
* @param hex Hex value to decode.
* @param opts Options.
* @returns String value.
*
* @example
* import { hexToString } from 'viem'
* const data = hexToString('0x48656c6c6f20576f726c6421')
* // 'Hello world!'
*
* @example
* import { hexToString } from 'viem'
* const data = hexToString('0x48656c6c6f20576f726c64210000000000000000000000000000000000000000', {
* size: 32,
* })
* // 'Hello world'
*/
export function hexToString(hex: Hex, opts: HexToStringOpts = {}): string {
let bytes = hexToBytes(hex)
if (opts.size) {
assertSize(bytes, { size: opts.size })
bytes = trim(bytes, { dir: 'right' })
}
return new TextDecoder().decode(bytes)
}

102
node_modules/viem/utils/encoding/fromRlp.ts generated vendored Normal file
View File

@@ -0,0 +1,102 @@
import { BaseError, type BaseErrorType } from '../../errors/base.js'
import {
InvalidHexValueError,
type InvalidHexValueErrorType,
} from '../../errors/encoding.js'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import {
type CreateCursorErrorType,
type Cursor,
createCursor,
} from '../cursor.js'
import { type HexToBytesErrorType, hexToBytes } from './toBytes.js'
import { type BytesToHexErrorType, bytesToHex } from './toHex.js'
import type { RecursiveArray } from './toRlp.js'
type To = 'hex' | 'bytes'
export type FromRlpReturnType<to extends To> =
| (to extends 'bytes' ? RecursiveArray<ByteArray> : never)
| (to extends 'hex' ? RecursiveArray<Hex> : never)
export type FromRlpErrorType =
| CreateCursorErrorType
| FromRlpCursorErrorType
| HexToBytesErrorType
| InvalidHexValueErrorType
| ErrorType
export function fromRlp<to extends To = 'hex'>(
value: ByteArray | Hex,
to: to | To | undefined = 'hex',
): FromRlpReturnType<to> {
const bytes = (() => {
if (typeof value === 'string') {
if (value.length > 3 && value.length % 2 !== 0)
throw new InvalidHexValueError(value)
return hexToBytes(value)
}
return value
})()
const cursor = createCursor(bytes, {
recursiveReadLimit: Number.POSITIVE_INFINITY,
})
const result = fromRlpCursor(cursor, to)
return result as FromRlpReturnType<to>
}
type FromRlpCursorErrorType =
| BytesToHexErrorType
| ReadLengthErrorType
| ReadListErrorType
| ErrorType
function fromRlpCursor<to extends To = 'hex'>(
cursor: Cursor,
to: to | To | undefined = 'hex',
): FromRlpReturnType<to> {
if (cursor.bytes.length === 0)
return (
to === 'hex' ? bytesToHex(cursor.bytes) : cursor.bytes
) as FromRlpReturnType<to>
const prefix = cursor.readByte()
if (prefix < 0x80) cursor.decrementPosition(1)
// bytes
if (prefix < 0xc0) {
const length = readLength(cursor, prefix, 0x80)
const bytes = cursor.readBytes(length)
return (to === 'hex' ? bytesToHex(bytes) : bytes) as FromRlpReturnType<to>
}
// list
const length = readLength(cursor, prefix, 0xc0)
return readList(cursor, length, to) as {} as FromRlpReturnType<to>
}
type ReadLengthErrorType = BaseErrorType | ErrorType
function readLength(cursor: Cursor, prefix: number, offset: number) {
if (offset === 0x80 && prefix < 0x80) return 1
if (prefix <= offset + 55) return prefix - offset
if (prefix === offset + 55 + 1) return cursor.readUint8()
if (prefix === offset + 55 + 2) return cursor.readUint16()
if (prefix === offset + 55 + 3) return cursor.readUint24()
if (prefix === offset + 55 + 4) return cursor.readUint32()
throw new BaseError('Invalid RLP prefix')
}
type ReadListErrorType = ErrorType
function readList<to extends To>(cursor: Cursor, length: number, to: to | To) {
const position = cursor.position
const value: FromRlpReturnType<to>[] = []
while (cursor.position - position < length)
value.push(fromRlpCursor(cursor, to))
return value
}

248
node_modules/viem/utils/encoding/toBytes.ts generated vendored Normal file
View File

@@ -0,0 +1,248 @@
import { BaseError } from '../../errors/base.js'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type IsHexErrorType, isHex } from '../data/isHex.js'
import { type PadErrorType, pad } from '../data/pad.js'
import { type AssertSizeErrorType, assertSize } from './fromHex.js'
import {
type NumberToHexErrorType,
type NumberToHexOpts,
numberToHex,
} from './toHex.js'
const encoder = /*#__PURE__*/ new TextEncoder()
export type ToBytesParameters = {
/** Size of the output bytes. */
size?: number | undefined
}
export type ToBytesErrorType =
| NumberToBytesErrorType
| BoolToBytesErrorType
| HexToBytesErrorType
| StringToBytesErrorType
| IsHexErrorType
| ErrorType
/**
* Encodes a UTF-8 string, hex value, bigint, number or boolean to a byte array.
*
* - Docs: https://viem.sh/docs/utilities/toBytes
* - Example: https://viem.sh/docs/utilities/toBytes#usage
*
* @param value Value to encode.
* @param opts Options.
* @returns Byte array value.
*
* @example
* import { toBytes } from 'viem'
* const data = toBytes('Hello world')
* // Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33])
*
* @example
* import { toBytes } from 'viem'
* const data = toBytes(420)
* // Uint8Array([1, 164])
*
* @example
* import { toBytes } from 'viem'
* const data = toBytes(420, { size: 4 })
* // Uint8Array([0, 0, 1, 164])
*/
export function toBytes(
value: string | bigint | number | boolean | Hex,
opts: ToBytesParameters = {},
): ByteArray {
if (typeof value === 'number' || typeof value === 'bigint')
return numberToBytes(value, opts)
if (typeof value === 'boolean') return boolToBytes(value, opts)
if (isHex(value)) return hexToBytes(value, opts)
return stringToBytes(value, opts)
}
export type BoolToBytesOpts = {
/** Size of the output bytes. */
size?: number | undefined
}
export type BoolToBytesErrorType =
| AssertSizeErrorType
| PadErrorType
| ErrorType
/**
* Encodes a boolean into a byte array.
*
* - Docs: https://viem.sh/docs/utilities/toBytes#booltobytes
*
* @param value Boolean value to encode.
* @param opts Options.
* @returns Byte array value.
*
* @example
* import { boolToBytes } from 'viem'
* const data = boolToBytes(true)
* // Uint8Array([1])
*
* @example
* import { boolToBytes } from 'viem'
* const data = boolToBytes(true, { size: 32 })
* // Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
*/
export function boolToBytes(value: boolean, opts: BoolToBytesOpts = {}) {
const bytes = new Uint8Array(1)
bytes[0] = Number(value)
if (typeof opts.size === 'number') {
assertSize(bytes, { size: opts.size })
return pad(bytes, { size: opts.size })
}
return bytes
}
// We use very optimized technique to convert hex string to byte array
const charCodeMap = {
zero: 48,
nine: 57,
A: 65,
F: 70,
a: 97,
f: 102,
} as const
function charCodeToBase16(char: number) {
if (char >= charCodeMap.zero && char <= charCodeMap.nine)
return char - charCodeMap.zero
if (char >= charCodeMap.A && char <= charCodeMap.F)
return char - (charCodeMap.A - 10)
if (char >= charCodeMap.a && char <= charCodeMap.f)
return char - (charCodeMap.a - 10)
return undefined
}
export type HexToBytesOpts = {
/** Size of the output bytes. */
size?: number | undefined
}
export type HexToBytesErrorType = AssertSizeErrorType | PadErrorType | ErrorType
/**
* Encodes a hex string into a byte array.
*
* - Docs: https://viem.sh/docs/utilities/toBytes#hextobytes
*
* @param hex Hex string to encode.
* @param opts Options.
* @returns Byte array value.
*
* @example
* import { hexToBytes } from 'viem'
* const data = hexToBytes('0x48656c6c6f20776f726c6421')
* // Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33])
*
* @example
* import { hexToBytes } from 'viem'
* const data = hexToBytes('0x48656c6c6f20776f726c6421', { size: 32 })
* // Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
*/
export function hexToBytes(hex_: Hex, opts: HexToBytesOpts = {}): ByteArray {
let hex = hex_
if (opts.size) {
assertSize(hex, { size: opts.size })
hex = pad(hex, { dir: 'right', size: opts.size })
}
let hexString = hex.slice(2) as string
if (hexString.length % 2) hexString = `0${hexString}`
const length = hexString.length / 2
const bytes = new Uint8Array(length)
for (let index = 0, j = 0; index < length; index++) {
const nibbleLeft = charCodeToBase16(hexString.charCodeAt(j++))
const nibbleRight = charCodeToBase16(hexString.charCodeAt(j++))
if (nibbleLeft === undefined || nibbleRight === undefined) {
throw new BaseError(
`Invalid byte sequence ("${hexString[j - 2]}${
hexString[j - 1]
}" in "${hexString}").`,
)
}
bytes[index] = nibbleLeft * 16 + nibbleRight
}
return bytes
}
export type NumberToBytesErrorType =
| NumberToHexErrorType
| HexToBytesErrorType
| ErrorType
/**
* Encodes a number into a byte array.
*
* - Docs: https://viem.sh/docs/utilities/toBytes#numbertobytes
*
* @param value Number to encode.
* @param opts Options.
* @returns Byte array value.
*
* @example
* import { numberToBytes } from 'viem'
* const data = numberToBytes(420)
* // Uint8Array([1, 164])
*
* @example
* import { numberToBytes } from 'viem'
* const data = numberToBytes(420, { size: 4 })
* // Uint8Array([0, 0, 1, 164])
*/
export function numberToBytes(
value: bigint | number,
opts?: NumberToHexOpts | undefined,
) {
const hex = numberToHex(value, opts)
return hexToBytes(hex)
}
export type StringToBytesOpts = {
/** Size of the output bytes. */
size?: number | undefined
}
export type StringToBytesErrorType =
| AssertSizeErrorType
| PadErrorType
| ErrorType
/**
* Encodes a UTF-8 string into a byte array.
*
* - Docs: https://viem.sh/docs/utilities/toBytes#stringtobytes
*
* @param value String to encode.
* @param opts Options.
* @returns Byte array value.
*
* @example
* import { stringToBytes } from 'viem'
* const data = stringToBytes('Hello world!')
* // Uint8Array([72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33])
*
* @example
* import { stringToBytes } from 'viem'
* const data = stringToBytes('Hello world!', { size: 32 })
* // Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
*/
export function stringToBytes(
value: string,
opts: StringToBytesOpts = {},
): ByteArray {
const bytes = encoder.encode(value)
if (typeof opts.size === 'number') {
assertSize(bytes, { size: opts.size })
return pad(bytes, { dir: 'right', size: opts.size })
}
return bytes
}

249
node_modules/viem/utils/encoding/toHex.ts generated vendored Normal file
View File

@@ -0,0 +1,249 @@
import {
IntegerOutOfRangeError,
type IntegerOutOfRangeErrorType,
} from '../../errors/encoding.js'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type PadErrorType, pad } from '../data/pad.js'
import { type AssertSizeErrorType, assertSize } from './fromHex.js'
const hexes = /*#__PURE__*/ Array.from({ length: 256 }, (_v, i) =>
i.toString(16).padStart(2, '0'),
)
export type ToHexParameters = {
/** The size (in bytes) of the output hex value. */
size?: number | undefined
}
export type ToHexErrorType =
| BoolToHexErrorType
| BytesToHexErrorType
| NumberToHexErrorType
| StringToHexErrorType
| ErrorType
/**
* Encodes a string, number, bigint, or ByteArray into a hex string
*
* - Docs: https://viem.sh/docs/utilities/toHex
* - Example: https://viem.sh/docs/utilities/toHex#usage
*
* @param value Value to encode.
* @param opts Options.
* @returns Hex value.
*
* @example
* import { toHex } from 'viem'
* const data = toHex('Hello world')
* // '0x48656c6c6f20776f726c6421'
*
* @example
* import { toHex } from 'viem'
* const data = toHex(420)
* // '0x1a4'
*
* @example
* import { toHex } from 'viem'
* const data = toHex('Hello world', { size: 32 })
* // '0x48656c6c6f20776f726c64210000000000000000000000000000000000000000'
*/
export function toHex(
value: string | number | bigint | boolean | ByteArray,
opts: ToHexParameters = {},
): Hex {
if (typeof value === 'number' || typeof value === 'bigint')
return numberToHex(value, opts)
if (typeof value === 'string') {
return stringToHex(value, opts)
}
if (typeof value === 'boolean') return boolToHex(value, opts)
return bytesToHex(value, opts)
}
export type BoolToHexOpts = {
/** The size (in bytes) of the output hex value. */
size?: number | undefined
}
export type BoolToHexErrorType = AssertSizeErrorType | PadErrorType | ErrorType
/**
* Encodes a boolean into a hex string
*
* - Docs: https://viem.sh/docs/utilities/toHex#booltohex
*
* @param value Value to encode.
* @param opts Options.
* @returns Hex value.
*
* @example
* import { boolToHex } from 'viem'
* const data = boolToHex(true)
* // '0x1'
*
* @example
* import { boolToHex } from 'viem'
* const data = boolToHex(false)
* // '0x0'
*
* @example
* import { boolToHex } from 'viem'
* const data = boolToHex(true, { size: 32 })
* // '0x0000000000000000000000000000000000000000000000000000000000000001'
*/
export function boolToHex(value: boolean, opts: BoolToHexOpts = {}): Hex {
const hex: Hex = `0x${Number(value)}`
if (typeof opts.size === 'number') {
assertSize(hex, { size: opts.size })
return pad(hex, { size: opts.size })
}
return hex
}
export type BytesToHexOpts = {
/** The size (in bytes) of the output hex value. */
size?: number | undefined
}
export type BytesToHexErrorType = AssertSizeErrorType | PadErrorType | ErrorType
/**
* Encodes a bytes array into a hex string
*
* - Docs: https://viem.sh/docs/utilities/toHex#bytestohex
*
* @param value Value to encode.
* @param opts Options.
* @returns Hex value.
*
* @example
* import { bytesToHex } from 'viem'
* const data = bytesToHex(Uint8Array.from([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33])
* // '0x48656c6c6f20576f726c6421'
*
* @example
* import { bytesToHex } from 'viem'
* const data = bytesToHex(Uint8Array.from([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]), { size: 32 })
* // '0x48656c6c6f20576f726c64210000000000000000000000000000000000000000'
*/
export function bytesToHex(value: ByteArray, opts: BytesToHexOpts = {}): Hex {
let string = ''
for (let i = 0; i < value.length; i++) {
string += hexes[value[i]]
}
const hex = `0x${string}` as const
if (typeof opts.size === 'number') {
assertSize(hex, { size: opts.size })
return pad(hex, { dir: 'right', size: opts.size })
}
return hex
}
export type NumberToHexOpts =
| {
/** Whether or not the number of a signed representation. */
signed?: boolean | undefined
/** The size (in bytes) of the output hex value. */
size: number
}
| {
signed?: undefined
/** The size (in bytes) of the output hex value. */
size?: number | undefined
}
export type NumberToHexErrorType =
| IntegerOutOfRangeErrorType
| PadErrorType
| ErrorType
/**
* Encodes a number or bigint into a hex string
*
* - Docs: https://viem.sh/docs/utilities/toHex#numbertohex
*
* @param value Value to encode.
* @param opts Options.
* @returns Hex value.
*
* @example
* import { numberToHex } from 'viem'
* const data = numberToHex(420)
* // '0x1a4'
*
* @example
* import { numberToHex } from 'viem'
* const data = numberToHex(420, { size: 32 })
* // '0x00000000000000000000000000000000000000000000000000000000000001a4'
*/
export function numberToHex(
value_: number | bigint,
opts: NumberToHexOpts = {},
): Hex {
const { signed, size } = opts
const value = BigInt(value_)
let maxValue: bigint | number | undefined
if (size) {
if (signed) maxValue = (1n << (BigInt(size) * 8n - 1n)) - 1n
else maxValue = 2n ** (BigInt(size) * 8n) - 1n
} else if (typeof value_ === 'number') {
maxValue = BigInt(Number.MAX_SAFE_INTEGER)
}
const minValue = typeof maxValue === 'bigint' && signed ? -maxValue - 1n : 0
if ((maxValue && value > maxValue) || value < minValue) {
const suffix = typeof value_ === 'bigint' ? 'n' : ''
throw new IntegerOutOfRangeError({
max: maxValue ? `${maxValue}${suffix}` : undefined,
min: `${minValue}${suffix}`,
signed,
size,
value: `${value_}${suffix}`,
})
}
const hex = `0x${(
signed && value < 0 ? (1n << BigInt(size * 8)) + BigInt(value) : value
).toString(16)}` as Hex
if (size) return pad(hex, { size }) as Hex
return hex
}
export type StringToHexOpts = {
/** The size (in bytes) of the output hex value. */
size?: number | undefined
}
export type StringToHexErrorType = BytesToHexErrorType | ErrorType
const encoder = /*#__PURE__*/ new TextEncoder()
/**
* Encodes a UTF-8 string into a hex string
*
* - Docs: https://viem.sh/docs/utilities/toHex#stringtohex
*
* @param value Value to encode.
* @param opts Options.
* @returns Hex value.
*
* @example
* import { stringToHex } from 'viem'
* const data = stringToHex('Hello World!')
* // '0x48656c6c6f20576f726c6421'
*
* @example
* import { stringToHex } from 'viem'
* const data = stringToHex('Hello World!', { size: 32 })
* // '0x48656c6c6f20576f726c64210000000000000000000000000000000000000000'
*/
export function stringToHex(value_: string, opts: StringToHexOpts = {}): Hex {
const value = encoder.encode(value_)
return bytesToHex(value, opts)
}

135
node_modules/viem/utils/encoding/toRlp.ts generated vendored Normal file
View File

@@ -0,0 +1,135 @@
import { BaseError } from '../../errors/base.js'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import {
type CreateCursorErrorType,
type Cursor,
createCursor,
} from '../cursor.js'
import { type HexToBytesErrorType, hexToBytes } from './toBytes.js'
import { type BytesToHexErrorType, bytesToHex } from './toHex.js'
export type RecursiveArray<T> = T | readonly RecursiveArray<T>[]
type To = 'hex' | 'bytes'
type Encodable = {
length: number
encode(cursor: Cursor): void
}
export type ToRlpReturnType<to extends To> =
| (to extends 'bytes' ? ByteArray : never)
| (to extends 'hex' ? Hex : never)
export type ToRlpErrorType =
| CreateCursorErrorType
| BytesToHexErrorType
| HexToBytesErrorType
| ErrorType
export function toRlp<to extends To = 'hex'>(
bytes: RecursiveArray<ByteArray> | RecursiveArray<Hex>,
to: to | To | undefined = 'hex',
): ToRlpReturnType<to> {
const encodable = getEncodable(bytes)
const cursor = createCursor(new Uint8Array(encodable.length))
encodable.encode(cursor)
if (to === 'hex') return bytesToHex(cursor.bytes) as ToRlpReturnType<to>
return cursor.bytes as ToRlpReturnType<to>
}
export type BytesToRlpErrorType = ToRlpErrorType | ErrorType
export function bytesToRlp<to extends To = 'bytes'>(
bytes: RecursiveArray<ByteArray>,
to: to | To | undefined = 'bytes',
): ToRlpReturnType<to> {
return toRlp(bytes, to)
}
export type HexToRlpErrorType = ToRlpErrorType | ErrorType
export function hexToRlp<to extends To = 'hex'>(
hex: RecursiveArray<Hex>,
to: to | To | undefined = 'hex',
): ToRlpReturnType<to> {
return toRlp(hex, to)
}
function getEncodable(
bytes: RecursiveArray<ByteArray> | RecursiveArray<Hex>,
): Encodable {
if (Array.isArray(bytes))
return getEncodableList(bytes.map((x) => getEncodable(x)))
return getEncodableBytes(bytes as any)
}
function getEncodableList(list: Encodable[]): Encodable {
const bodyLength = list.reduce((acc, x) => acc + x.length, 0)
const sizeOfBodyLength = getSizeOfLength(bodyLength)
const length = (() => {
if (bodyLength <= 55) return 1 + bodyLength
return 1 + sizeOfBodyLength + bodyLength
})()
return {
length,
encode(cursor: Cursor) {
if (bodyLength <= 55) {
cursor.pushByte(0xc0 + bodyLength)
} else {
cursor.pushByte(0xc0 + 55 + sizeOfBodyLength)
if (sizeOfBodyLength === 1) cursor.pushUint8(bodyLength)
else if (sizeOfBodyLength === 2) cursor.pushUint16(bodyLength)
else if (sizeOfBodyLength === 3) cursor.pushUint24(bodyLength)
else cursor.pushUint32(bodyLength)
}
for (const { encode } of list) {
encode(cursor)
}
},
}
}
function getEncodableBytes(bytesOrHex: ByteArray | Hex): Encodable {
const bytes =
typeof bytesOrHex === 'string' ? hexToBytes(bytesOrHex) : bytesOrHex
const sizeOfBytesLength = getSizeOfLength(bytes.length)
const length = (() => {
if (bytes.length === 1 && bytes[0] < 0x80) return 1
if (bytes.length <= 55) return 1 + bytes.length
return 1 + sizeOfBytesLength + bytes.length
})()
return {
length,
encode(cursor: Cursor) {
if (bytes.length === 1 && bytes[0] < 0x80) {
cursor.pushBytes(bytes)
} else if (bytes.length <= 55) {
cursor.pushByte(0x80 + bytes.length)
cursor.pushBytes(bytes)
} else {
cursor.pushByte(0x80 + 55 + sizeOfBytesLength)
if (sizeOfBytesLength === 1) cursor.pushUint8(bytes.length)
else if (sizeOfBytesLength === 2) cursor.pushUint16(bytes.length)
else if (sizeOfBytesLength === 3) cursor.pushUint24(bytes.length)
else cursor.pushUint32(bytes.length)
cursor.pushBytes(bytes)
}
},
}
}
function getSizeOfLength(length: number) {
if (length < 2 ** 8) return 1
if (length < 2 ** 16) return 2
if (length < 2 ** 24) return 3
if (length < 2 ** 32) return 4
throw new BaseError('Length is too large.')
}

106
node_modules/viem/utils/ens/avatar/parseAvatarRecord.ts generated vendored Normal file
View File

@@ -0,0 +1,106 @@
import type { Client } from '../../../clients/createClient.js'
import type { Transport } from '../../../clients/transports/createTransport.js'
import type { ErrorType } from '../../../errors/utils.js'
import type { Chain } from '../../../types/chain.js'
import type { AssetGatewayUrls } from '../../../types/ens.js'
import {
type GetJsonImageErrorType,
type GetMetadataAvatarUriErrorType,
type GetNftTokenUriErrorType,
getJsonImage,
getMetadataAvatarUri,
getNftTokenUri,
type ParseAvatarUriErrorType,
type ParseNftUriErrorType,
parseAvatarUri,
parseNftUri,
type ResolveAvatarUriErrorType,
resolveAvatarUri,
} from './utils.js'
export type ParseAvatarRecordErrorType =
| ParseNftAvatarUriErrorType
| ParseAvatarUriErrorType
| ErrorType
/*
* @description Parses an ENS avatar record.
*
* @example
* parseAvatarRecord('eip155:1/erc1155:0xb32979486938aa9694bfc898f35dbed459f44424/10063')
* 'https://ipfs.io/ipfs/QmSP4nq9fnN9dAiCj42ug9Wa79rqmQerZXZch82VqpiH7U/image.gif'
*
* @see https://docs.ens.domains/web/avatars
*
*/
export async function parseAvatarRecord<chain extends Chain | undefined>(
client: Client<Transport, chain>,
{
gatewayUrls,
record,
}: {
gatewayUrls?: AssetGatewayUrls | undefined
record: string
},
): Promise<string> {
if (/eip155:/i.test(record))
return parseNftAvatarUri(client, { gatewayUrls, record })
return parseAvatarUri({ uri: record, gatewayUrls })
}
type ParseNftAvatarUriErrorType =
| ParseNftUriErrorType
| GetNftTokenUriErrorType
| ResolveAvatarUriErrorType
| ParseAvatarUriErrorType
| GetJsonImageErrorType
| GetMetadataAvatarUriErrorType
| ErrorType
async function parseNftAvatarUri<chain extends Chain | undefined>(
client: Client<Transport, chain>,
{
gatewayUrls,
record,
}: {
gatewayUrls?: AssetGatewayUrls | undefined
record: string
},
): Promise<string> {
// parse NFT URI into properties
const nft = parseNftUri(record)
// fetch tokenURI from the NFT contract
const nftUri = await getNftTokenUri(client, { nft })
// resolve the URI from the fetched tokenURI
const {
uri: resolvedNftUri,
isOnChain,
isEncoded,
} = resolveAvatarUri({ uri: nftUri, gatewayUrls })
// if the resolved URI is on chain, return the data
if (
isOnChain &&
(resolvedNftUri.includes('data:application/json;base64,') ||
resolvedNftUri.startsWith('{'))
) {
const encodedJson = isEncoded
? // if it is encoded, decode it
atob(resolvedNftUri.replace('data:application/json;base64,', ''))
: // if it isn't encoded assume it is a JSON string, but it could be anything (it will error if it is)
resolvedNftUri
const decoded = JSON.parse(encodedJson)
return parseAvatarUri({ uri: getJsonImage(decoded), gatewayUrls })
}
let uriTokenId = nft.tokenID
if (nft.namespace === 'erc1155')
uriTokenId = uriTokenId.replace('0x', '').padStart(64, '0')
return getMetadataAvatarUri({
gatewayUrls,
uri: resolvedNftUri.replace(/(?:0x)?{id}/, uriTokenId),
})
}

297
node_modules/viem/utils/ens/avatar/utils.ts generated vendored Normal file
View File

@@ -0,0 +1,297 @@
import type { Address } from 'abitype'
import {
type ReadContractErrorType,
readContract,
} from '../../../actions/public/readContract.js'
import type { Client } from '../../../clients/createClient.js'
import type { Transport } from '../../../clients/transports/createTransport.js'
import {
EnsAvatarInvalidMetadataError,
type EnsAvatarInvalidMetadataErrorType,
EnsAvatarInvalidNftUriError,
type EnsAvatarInvalidNftUriErrorType,
EnsAvatarUnsupportedNamespaceError,
type EnsAvatarUnsupportedNamespaceErrorType,
EnsAvatarUriResolutionError,
type EnsAvatarUriResolutionErrorType,
} from '../../../errors/ens.js'
import type { ErrorType } from '../../../errors/utils.js'
import type { Chain } from '../../../types/chain.js'
import type { AssetGatewayUrls } from '../../../types/ens.js'
type UriItem = {
uri: string
isOnChain: boolean
isEncoded: boolean
}
const networkRegex =
/(?<protocol>https?:\/\/[^/]*|ipfs:\/|ipns:\/|ar:\/)?(?<root>\/)?(?<subpath>ipfs\/|ipns\/)?(?<target>[\w\-.]+)(?<subtarget>\/.*)?/
const ipfsHashRegex =
/^(Qm[1-9A-HJ-NP-Za-km-z]{44,}|b[A-Za-z2-7]{58,}|B[A-Z2-7]{58,}|z[1-9A-HJ-NP-Za-km-z]{48,}|F[0-9A-F]{50,})(\/(?<target>[\w\-.]+))?(?<subtarget>\/.*)?$/
const base64Regex = /^data:([a-zA-Z\-/+]*);base64,([^"].*)/
const dataURIRegex = /^data:([a-zA-Z\-/+]*)?(;[a-zA-Z0-9].*?)?(,)/
type IsImageUriErrorType = ErrorType
/** @internal */
export async function isImageUri(uri: string) {
try {
const res = await fetch(uri, { method: 'HEAD' })
// retrieve content type header to check if content is image
if (res.status === 200) {
const contentType = res.headers.get('content-type')
return contentType?.startsWith('image/')
}
return false
} catch (error: any) {
// if error is not cors related then fail
if (typeof error === 'object' && typeof error.response !== 'undefined') {
return false
}
// fail in NodeJS, since the error is not cors but any other network issue
if (!Object.hasOwn(globalThis, 'Image')) return false
// in case of cors, use image api to validate if given url is an actual image
return new Promise((resolve) => {
const img = new Image()
img.onload = () => {
resolve(true)
}
img.onerror = () => {
resolve(false)
}
img.src = uri
})
}
}
type GetGatewayErrorType = ErrorType
/** @internal */
export function getGateway(custom: string | undefined, defaultGateway: string) {
if (!custom) return defaultGateway
if (custom.endsWith('/')) return custom.slice(0, -1)
return custom
}
export type ResolveAvatarUriErrorType =
| GetGatewayErrorType
| EnsAvatarUriResolutionErrorType
| ErrorType
export function resolveAvatarUri({
uri,
gatewayUrls,
}: {
uri: string
gatewayUrls?: AssetGatewayUrls | undefined
}): UriItem {
const isEncoded = base64Regex.test(uri)
if (isEncoded) return { uri, isOnChain: true, isEncoded }
const ipfsGateway = getGateway(gatewayUrls?.ipfs, 'https://ipfs.io')
const arweaveGateway = getGateway(gatewayUrls?.arweave, 'https://arweave.net')
const networkRegexMatch = uri.match(networkRegex)
const {
protocol,
subpath,
target,
subtarget = '',
} = networkRegexMatch?.groups || {}
const isIPNS = protocol === 'ipns:/' || subpath === 'ipns/'
const isIPFS =
protocol === 'ipfs:/' || subpath === 'ipfs/' || ipfsHashRegex.test(uri)
if (uri.startsWith('http') && !isIPNS && !isIPFS) {
let replacedUri = uri
if (gatewayUrls?.arweave)
replacedUri = uri.replace(/https:\/\/arweave.net/g, gatewayUrls?.arweave)
return { uri: replacedUri, isOnChain: false, isEncoded: false }
}
if ((isIPNS || isIPFS) && target) {
return {
uri: `${ipfsGateway}/${isIPNS ? 'ipns' : 'ipfs'}/${target}${subtarget}`,
isOnChain: false,
isEncoded: false,
}
}
if (protocol === 'ar:/' && target) {
return {
uri: `${arweaveGateway}/${target}${subtarget || ''}`,
isOnChain: false,
isEncoded: false,
}
}
let parsedUri = uri.replace(dataURIRegex, '')
if (parsedUri.startsWith('<svg')) {
// if svg, base64 encode
parsedUri = `data:image/svg+xml;base64,${btoa(parsedUri)}`
}
if (parsedUri.startsWith('data:') || parsedUri.startsWith('{')) {
return {
uri: parsedUri,
isOnChain: true,
isEncoded: false,
}
}
throw new EnsAvatarUriResolutionError({ uri })
}
export type GetJsonImageErrorType =
| EnsAvatarInvalidMetadataErrorType
| ErrorType
export function getJsonImage(data: any) {
// validation check for json data, must include one of theses properties
if (
typeof data !== 'object' ||
(!('image' in data) && !('image_url' in data) && !('image_data' in data))
) {
throw new EnsAvatarInvalidMetadataError({ data })
}
return data.image || data.image_url || data.image_data
}
export type GetMetadataAvatarUriErrorType =
| EnsAvatarUriResolutionErrorType
| ParseAvatarUriErrorType
| GetJsonImageErrorType
| ErrorType
export async function getMetadataAvatarUri({
gatewayUrls,
uri,
}: {
gatewayUrls?: AssetGatewayUrls | undefined
uri: string
}): Promise<string> {
try {
const res = await fetch(uri).then((res) => res.json())
const image = await parseAvatarUri({
gatewayUrls,
uri: getJsonImage(res),
})
return image
} catch {
throw new EnsAvatarUriResolutionError({ uri })
}
}
export type ParseAvatarUriErrorType =
| ResolveAvatarUriErrorType
| IsImageUriErrorType
| EnsAvatarUriResolutionErrorType
| ErrorType
export async function parseAvatarUri({
gatewayUrls,
uri,
}: {
gatewayUrls?: AssetGatewayUrls | undefined
uri: string
}): Promise<string> {
const { uri: resolvedURI, isOnChain } = resolveAvatarUri({ uri, gatewayUrls })
if (isOnChain) return resolvedURI
// check if resolvedURI is an image, if it is return the url
const isImage = await isImageUri(resolvedURI)
if (isImage) return resolvedURI
throw new EnsAvatarUriResolutionError({ uri })
}
type ParsedNft = {
chainID: number
namespace: string
contractAddress: Address
tokenID: string
}
export type ParseNftUriErrorType = EnsAvatarInvalidNftUriErrorType | ErrorType
export function parseNftUri(uri_: string): ParsedNft {
let uri = uri_
// parse valid nft spec (CAIP-22/CAIP-29)
// @see: https://github.com/ChainAgnostic/CAIPs/tree/master/CAIPs
if (uri.startsWith('did:nft:')) {
// convert DID to CAIP
uri = uri.replace('did:nft:', '').replace(/_/g, '/')
}
const [reference, asset_namespace, tokenID] = uri.split('/')
const [eip_namespace, chainID] = reference.split(':')
const [erc_namespace, contractAddress] = asset_namespace.split(':')
if (!eip_namespace || eip_namespace.toLowerCase() !== 'eip155')
throw new EnsAvatarInvalidNftUriError({ reason: 'Only EIP-155 supported' })
if (!chainID)
throw new EnsAvatarInvalidNftUriError({ reason: 'Chain ID not found' })
if (!contractAddress)
throw new EnsAvatarInvalidNftUriError({
reason: 'Contract address not found',
})
if (!tokenID)
throw new EnsAvatarInvalidNftUriError({ reason: 'Token ID not found' })
if (!erc_namespace)
throw new EnsAvatarInvalidNftUriError({ reason: 'ERC namespace not found' })
return {
chainID: Number.parseInt(chainID, 10),
namespace: erc_namespace.toLowerCase(),
contractAddress: contractAddress as Address,
tokenID,
}
}
export type GetNftTokenUriErrorType =
| ReadContractErrorType
| EnsAvatarUnsupportedNamespaceErrorType
| ErrorType
export async function getNftTokenUri<chain extends Chain | undefined>(
client: Client<Transport, chain>,
{ nft }: { nft: ParsedNft },
) {
if (nft.namespace === 'erc721') {
return readContract(client, {
address: nft.contractAddress,
abi: [
{
name: 'tokenURI',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'tokenId', type: 'uint256' }],
outputs: [{ name: '', type: 'string' }],
},
],
functionName: 'tokenURI',
args: [BigInt(nft.tokenID)],
})
}
if (nft.namespace === 'erc1155') {
return readContract(client, {
address: nft.contractAddress,
abi: [
{
name: 'uri',
type: 'function',
stateMutability: 'view',
inputs: [{ name: '_id', type: 'uint256' }],
outputs: [{ name: '', type: 'string' }],
},
],
functionName: 'uri',
args: [BigInt(nft.tokenID)],
})
}
throw new EnsAvatarUnsupportedNamespaceError({ namespace: nft.namespace })
}

8
node_modules/viem/utils/ens/encodeLabelhash.ts generated vendored Normal file
View File

@@ -0,0 +1,8 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Hex } from '../../types/misc.js'
export type EncodeLabelhashErrorType = ErrorType
export function encodeLabelhash(hash: Hex): `[${string}]` {
return `[${hash.slice(2)}]`
}

14
node_modules/viem/utils/ens/encodedLabelToLabelhash.ts generated vendored Normal file
View File

@@ -0,0 +1,14 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Hex } from '../../types/misc.js'
import { type IsHexErrorType, isHex } from '../data/isHex.js'
export type EncodedLabelToLabelhashErrorType = IsHexErrorType | ErrorType
export function encodedLabelToLabelhash(label: string): Hex | null {
if (label.length !== 66) return null
if (label.indexOf('[') !== 0) return null
if (label.indexOf(']') !== 65) return null
const hash = `0x${label.slice(1, 65)}`
if (!isHex(hash)) return null
return hash
}

24
node_modules/viem/utils/ens/errors.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import { BaseError } from '../../errors/base.js'
import { ContractFunctionRevertedError } from '../../errors/contract.js'
import type { ErrorType } from '../../errors/utils.js'
/** @internal */
export type IsNullUniversalResolverErrorErrorType = ErrorType
/*
* @description Checks if error is a valid null result UniversalResolver error
*/
export function isNullUniversalResolverError(err: unknown): boolean {
if (!(err instanceof BaseError)) return false
const cause = err.walk((e) => e instanceof ContractFunctionRevertedError)
if (!(cause instanceof ContractFunctionRevertedError)) return false
if (cause.data?.errorName === 'HttpError') return true
if (cause.data?.errorName === 'ResolverError') return true
if (cause.data?.errorName === 'ResolverNotContract') return true
if (cause.data?.errorName === 'ResolverNotFound') return true
if (cause.data?.errorName === 'ReverseAddressMismatch') return true
if (cause.data?.errorName === 'UnsupportedResolverProfile') return true
return false
}

33
node_modules/viem/utils/ens/labelhash.ts generated vendored Normal file
View File

@@ -0,0 +1,33 @@
import type { ErrorType } from '../../errors/utils.js'
import {
type StringToBytesErrorType,
stringToBytes,
} from '../encoding/toBytes.js'
import { type BytesToHexErrorType, bytesToHex } from '../encoding/toHex.js'
import { type Keccak256ErrorType, keccak256 } from '../hash/keccak256.js'
import {
type EncodedLabelToLabelhashErrorType,
encodedLabelToLabelhash,
} from './encodedLabelToLabelhash.js'
export type LabelhashErrorType =
| BytesToHexErrorType
| EncodedLabelToLabelhashErrorType
| Keccak256ErrorType
| StringToBytesErrorType
| ErrorType
/**
* @description Hashes ENS label
*
* - Since ENS labels prohibit certain forbidden characters (e.g. underscore) and have other validation rules, you likely want to [normalize ENS labels](https://docs.ens.domains/contract-api-reference/name-processing#normalising-names) with [UTS-46 normalization](https://unicode.org/reports/tr46) before passing them to `labelhash`. You can use the built-in [`normalize`](https://viem.sh/docs/ens/utilities/normalize) function for this.
*
* @example
* labelhash('eth')
* '0x4f5b812789fc606be1b3b16908db13fc7a9adf7ca72641f84d75b47069d3d7f0'
*/
export function labelhash(label: string) {
const result = new Uint8Array(32).fill(0)
if (!label) return bytesToHex(result)
return encodedLabelToLabelhash(label) || keccak256(stringToBytes(label))
}

View File

@@ -0,0 +1,62 @@
import { batchGatewayAbi } from '../../constants/abis.js'
import { solidityError } from '../../constants/solidity.js'
import type { Hex } from '../../types/misc.js'
import { decodeFunctionData } from '../abi/decodeFunctionData.js'
import { encodeErrorResult } from '../abi/encodeErrorResult.js'
import { encodeFunctionResult } from '../abi/encodeFunctionResult.js'
import type {
CcipRequestErrorType,
CcipRequestParameters,
CcipRequestReturnType,
} from '../ccip.js'
export const localBatchGatewayUrl = 'x-batch-gateway:true'
export async function localBatchGatewayRequest(parameters: {
data: Hex
ccipRequest: (
parameters: CcipRequestParameters,
) => Promise<CcipRequestReturnType>
}): Promise<Hex> {
const { data, ccipRequest } = parameters
const {
args: [queries],
} = decodeFunctionData({ abi: batchGatewayAbi, data })
const failures: boolean[] = []
const responses: Hex[] = []
await Promise.all(
queries.map(async (query, i) => {
try {
responses[i] = query.urls.includes(localBatchGatewayUrl)
? await localBatchGatewayRequest({ data: query.data, ccipRequest })
: await ccipRequest(query)
failures[i] = false
} catch (err) {
failures[i] = true
responses[i] = encodeError(err as CcipRequestErrorType)
}
}),
)
return encodeFunctionResult({
abi: batchGatewayAbi,
functionName: 'query',
result: [failures, responses],
})
}
function encodeError(error: CcipRequestErrorType): Hex {
if (error.name === 'HttpRequestError' && error.status)
return encodeErrorResult({
abi: batchGatewayAbi,
errorName: 'HttpError',
args: [error.status, error.shortMessage],
})
return encodeErrorResult({
abi: [solidityError],
errorName: 'Error',
args: ['shortMessage' in error ? error.shortMessage : error.message],
})
}

52
node_modules/viem/utils/ens/namehash.ts generated vendored Normal file
View File

@@ -0,0 +1,52 @@
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray } from '../../types/misc.js'
import { type ConcatErrorType, concat } from '../data/concat.js'
import {
type StringToBytesErrorType,
stringToBytes,
type ToBytesErrorType,
toBytes,
} from '../encoding/toBytes.js'
import { type BytesToHexErrorType, bytesToHex } from '../encoding/toHex.js'
import { type Keccak256ErrorType, keccak256 } from '../hash/keccak256.js'
import {
type EncodedLabelToLabelhashErrorType,
encodedLabelToLabelhash,
} from './encodedLabelToLabelhash.js'
export type NamehashErrorType =
| BytesToHexErrorType
| EncodedLabelToLabelhashErrorType
| ToBytesErrorType
| Keccak256ErrorType
| StringToBytesErrorType
| ConcatErrorType
| ErrorType
/**
* @description Hashes ENS name
*
* - Since ENS names prohibit certain forbidden characters (e.g. underscore) and have other validation rules, you likely want to [normalize ENS names](https://docs.ens.domains/contract-api-reference/name-processing#normalising-names) with [UTS-46 normalization](https://unicode.org/reports/tr46) before passing them to `namehash`. You can use the built-in [`normalize`](https://viem.sh/docs/ens/utilities/normalize) function for this.
*
* @example
* namehash('wevm.eth')
* '0x08c85f2f4059e930c45a6aeff9dcd3bd95dc3c5c1cddef6a0626b31152248560'
*
* @link https://eips.ethereum.org/EIPS/eip-137
*/
export function namehash(name: string) {
let result = new Uint8Array(32).fill(0) as ByteArray
if (!name) return bytesToHex(result)
const labels = name.split('.')
// Iterate in reverse order building up hash
for (let i = labels.length - 1; i >= 0; i -= 1) {
const hashFromEncodedLabel = encodedLabelToLabelhash(labels[i])
const hashed = hashFromEncodedLabel
? toBytes(hashFromEncodedLabel)
: keccak256(stringToBytes(labels[i]), 'bytes')
result = keccak256(concat([result, hashed]), 'bytes')
}
return bytesToHex(result)
}

18
node_modules/viem/utils/ens/normalize.ts generated vendored Normal file
View File

@@ -0,0 +1,18 @@
import * as Ens from 'ox/Ens'
import type { ErrorType } from '../../errors/utils.js'
export type NormalizeErrorType = ErrorType
/**
* @description Normalizes ENS name according to ENSIP-15.
*
* @example
* normalize('wevm.eth')
* 'wevm.eth'
*
* @see https://docs.ens.domains/contract-api-reference/name-processing#normalising-names
* @see https://github.com/ensdomains/docs/blob/9edf9443de4333a0ea7ec658a870672d5d180d53/ens-improvement-proposals/ensip-15-normalization-standard.md
*/
export function normalize(name: string) {
return Ens.normalize(name)
}

53
node_modules/viem/utils/ens/packetToBytes.ts generated vendored Normal file
View File

@@ -0,0 +1,53 @@
// Adapted from https://github.com/mafintosh/dns-packet
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray } from '../../types/misc.js'
import {
type StringToBytesErrorType,
stringToBytes,
} from '../encoding/toBytes.js'
import {
type EncodeLabelhashErrorType,
encodeLabelhash,
} from './encodeLabelhash.js'
import { type LabelhashErrorType, labelhash } from './labelhash.js'
export type PacketToBytesErrorType =
| EncodeLabelhashErrorType
| LabelhashErrorType
| StringToBytesErrorType
| ErrorType
/*
* @description Encodes a DNS packet into a ByteArray containing a UDP payload.
*
* @example
* packetToBytes('awkweb.eth')
* '0x0661776b7765620365746800'
*
* @see https://docs.ens.domains/resolution/names#dns
*
*/
export function packetToBytes(packet: string): ByteArray {
// strip leading and trailing `.`
const value = packet.replace(/^\.|\.$/gm, '')
if (value.length === 0) return new Uint8Array(1)
const bytes = new Uint8Array(stringToBytes(value).byteLength + 2)
let offset = 0
const list = value.split('.')
for (let i = 0; i < list.length; i++) {
let encoded = stringToBytes(list[i])
// if the length is > 255, make the encoded label value a labelhash
// this is compatible with the universal resolver
if (encoded.byteLength > 255)
encoded = stringToBytes(encodeLabelhash(labelhash(list[i])))
bytes[offset] = encoded.length
bytes.set(encoded, offset + 1)
offset += encoded.length + 1
}
if (bytes.byteLength !== offset + 1) return bytes.slice(0, offset + 1)
return bytes
}

23
node_modules/viem/utils/ens/toCoinType.ts generated vendored Normal file
View File

@@ -0,0 +1,23 @@
import {
EnsInvalidChainIdError,
type EnsInvalidChainIdErrorType,
} from '../../errors/ens.js'
import type { ErrorType } from '../../errors/utils.js'
export type ToCoinTypeError = EnsInvalidChainIdErrorType | ErrorType
const SLIP44_MSB = 0x80000000
/**
* @description Converts a chainId to a ENSIP-9 compliant coinType
*
* @example
* toCoinType(10)
* 2147483658n
*/
export function toCoinType(chainId: number): bigint {
if (chainId === 1) return 60n
if (chainId >= SLIP44_MSB || chainId < 0)
throw new EnsInvalidChainIdError({ chainId })
return BigInt((0x80000000 | chainId) >>> 0)
}

46
node_modules/viem/utils/errors/getCallError.ts generated vendored Normal file
View File

@@ -0,0 +1,46 @@
import type { CallParameters } from '../../actions/public/call.js'
import type { BaseError } from '../../errors/base.js'
import {
CallExecutionError,
type CallExecutionErrorType,
} from '../../errors/contract.js'
import { UnknownNodeError } from '../../errors/node.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Chain } from '../../types/chain.js'
import {
type GetNodeErrorParameters,
type GetNodeErrorReturnType,
getNodeError,
} from './getNodeError.js'
export type GetCallErrorReturnType<cause = ErrorType> = Omit<
CallExecutionErrorType,
'cause'
> & {
cause: cause | GetNodeErrorReturnType
}
export function getCallError<err extends ErrorType<string>>(
err: err,
{
docsPath,
...args
}: CallParameters & {
chain?: Chain | undefined
docsPath?: string | undefined
},
): GetCallErrorReturnType<err> {
const cause = (() => {
const cause = getNodeError(
err as {} as BaseError,
args as GetNodeErrorParameters,
)
if (cause instanceof UnknownNodeError) return err as {} as BaseError
return cause
})()
return new CallExecutionError(cause, {
docsPath,
...args,
}) as GetCallErrorReturnType<err>
}

90
node_modules/viem/utils/errors/getContractError.ts generated vendored Normal file
View File

@@ -0,0 +1,90 @@
import type { Abi, Address } from 'abitype'
import { AbiDecodingZeroDataError } from '../../errors/abi.js'
import { BaseError } from '../../errors/base.js'
import {
ContractFunctionExecutionError,
type ContractFunctionExecutionErrorType,
ContractFunctionRevertedError,
type ContractFunctionRevertedErrorType,
ContractFunctionZeroDataError,
type ContractFunctionZeroDataErrorType,
RawContractError,
} from '../../errors/contract.js'
import { RpcRequestError } from '../../errors/request.js'
import { InternalRpcError, InvalidInputRpcError } from '../../errors/rpc.js'
import type { ErrorType } from '../../errors/utils.js'
const EXECUTION_REVERTED_ERROR_CODE = 3
export type GetContractErrorReturnType<cause = ErrorType> = Omit<
ContractFunctionExecutionErrorType,
'cause'
> & {
cause:
| cause
| ContractFunctionZeroDataErrorType
| ContractFunctionRevertedErrorType
}
export function getContractError<err extends ErrorType<string>>(
err: err,
{
abi,
address,
args,
docsPath,
functionName,
sender,
}: {
abi: Abi
args: any
address?: Address | undefined
docsPath?: string | undefined
functionName: string
sender?: Address | undefined
},
): GetContractErrorReturnType {
const error = (
err instanceof RawContractError
? err
: err instanceof BaseError
? err.walk((err) => 'data' in (err as Error)) || err.walk()
: {}
) as BaseError
const { code, data, details, message, shortMessage } =
error as RawContractError
const cause = (() => {
if (err instanceof AbiDecodingZeroDataError)
return new ContractFunctionZeroDataError({ functionName, cause: err })
if (
([EXECUTION_REVERTED_ERROR_CODE, InternalRpcError.code].includes(code) &&
(data || details || message || shortMessage)) ||
(code === InvalidInputRpcError.code &&
details === 'execution reverted' &&
data)
) {
return new ContractFunctionRevertedError({
abi,
data: typeof data === 'object' ? data.data : data,
functionName,
message:
error instanceof RpcRequestError
? details
: (shortMessage ?? message),
cause: err,
})
}
return err
})()
return new ContractFunctionExecutionError(cause as BaseError, {
abi,
args,
contractAddress: address,
docsPath,
functionName,
sender,
}) as GetContractErrorReturnType
}

46
node_modules/viem/utils/errors/getEstimateGasError.ts generated vendored Normal file
View File

@@ -0,0 +1,46 @@
import type { Account } from '../../accounts/types.js'
import type { EstimateGasParameters } from '../../actions/public/estimateGas.js'
import type { BaseError } from '../../errors/base.js'
import {
EstimateGasExecutionError,
type EstimateGasExecutionErrorType,
} from '../../errors/estimateGas.js'
import { UnknownNodeError } from '../../errors/node.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Chain } from '../../types/chain.js'
import {
type GetNodeErrorParameters,
type GetNodeErrorReturnType,
getNodeError,
} from './getNodeError.js'
export type GetEstimateGasErrorReturnType<cause = ErrorType> = Omit<
EstimateGasExecutionErrorType,
'cause'
> & { cause: cause | GetNodeErrorReturnType }
export function getEstimateGasError<err extends ErrorType<string>>(
err: err,
{
docsPath,
...args
}: Omit<EstimateGasParameters, 'account'> & {
account?: Account | undefined
chain?: Chain | undefined
docsPath?: string | undefined
},
): GetEstimateGasErrorReturnType<err> {
const cause = (() => {
const cause = getNodeError(
err as {} as BaseError,
args as GetNodeErrorParameters,
)
if (cause instanceof UnknownNodeError) return err as {} as BaseError
return cause
})()
return new EstimateGasExecutionError(cause, {
docsPath,
...args,
}) as GetEstimateGasErrorReturnType<err>
}

119
node_modules/viem/utils/errors/getNodeError.ts generated vendored Normal file
View File

@@ -0,0 +1,119 @@
import type { SendTransactionParameters } from '../../actions/wallet/sendTransaction.js'
import { BaseError } from '../../errors/base.js'
import {
ExecutionRevertedError,
type ExecutionRevertedErrorType,
FeeCapTooHighError,
type FeeCapTooHighErrorType,
FeeCapTooLowError,
type FeeCapTooLowErrorType,
InsufficientFundsError,
type InsufficientFundsErrorType,
IntrinsicGasTooHighError,
type IntrinsicGasTooHighErrorType,
IntrinsicGasTooLowError,
type IntrinsicGasTooLowErrorType,
NonceMaxValueError,
type NonceMaxValueErrorType,
NonceTooHighError,
type NonceTooHighErrorType,
NonceTooLowError,
type NonceTooLowErrorType,
TipAboveFeeCapError,
type TipAboveFeeCapErrorType,
TransactionTypeNotSupportedError,
type TransactionTypeNotSupportedErrorType,
UnknownNodeError,
type UnknownNodeErrorType,
} from '../../errors/node.js'
import { RpcRequestError } from '../../errors/request.js'
import {
InvalidInputRpcError,
TransactionRejectedRpcError,
} from '../../errors/rpc.js'
import type { ExactPartial } from '../../types/utils.js'
export function containsNodeError(err: BaseError) {
return (
err instanceof TransactionRejectedRpcError ||
err instanceof InvalidInputRpcError ||
(err instanceof RpcRequestError && err.code === ExecutionRevertedError.code)
)
}
export type GetNodeErrorParameters = ExactPartial<
SendTransactionParameters<any>
>
export type GetNodeErrorReturnType =
| ExecutionRevertedErrorType
| FeeCapTooHighErrorType
| FeeCapTooLowErrorType
| NonceTooHighErrorType
| NonceTooLowErrorType
| NonceMaxValueErrorType
| InsufficientFundsErrorType
| IntrinsicGasTooHighErrorType
| IntrinsicGasTooLowErrorType
| TransactionTypeNotSupportedErrorType
| TipAboveFeeCapErrorType
| UnknownNodeErrorType
export function getNodeError(
err: BaseError,
args: GetNodeErrorParameters,
): GetNodeErrorReturnType {
const message = (err.details || '').toLowerCase()
const executionRevertedError =
err instanceof BaseError
? err.walk(
(e) =>
(e as { code: number } | null | undefined)?.code ===
ExecutionRevertedError.code,
)
: err
if (executionRevertedError instanceof BaseError)
return new ExecutionRevertedError({
cause: err,
message: executionRevertedError.details,
}) as any
if (ExecutionRevertedError.nodeMessage.test(message))
return new ExecutionRevertedError({
cause: err,
message: err.details,
}) as any
if (FeeCapTooHighError.nodeMessage.test(message))
return new FeeCapTooHighError({
cause: err,
maxFeePerGas: args?.maxFeePerGas,
}) as any
if (FeeCapTooLowError.nodeMessage.test(message))
return new FeeCapTooLowError({
cause: err,
maxFeePerGas: args?.maxFeePerGas,
}) as any
if (NonceTooHighError.nodeMessage.test(message))
return new NonceTooHighError({ cause: err, nonce: args?.nonce }) as any
if (NonceTooLowError.nodeMessage.test(message))
return new NonceTooLowError({ cause: err, nonce: args?.nonce }) as any
if (NonceMaxValueError.nodeMessage.test(message))
return new NonceMaxValueError({ cause: err, nonce: args?.nonce }) as any
if (InsufficientFundsError.nodeMessage.test(message))
return new InsufficientFundsError({ cause: err }) as any
if (IntrinsicGasTooHighError.nodeMessage.test(message))
return new IntrinsicGasTooHighError({ cause: err, gas: args?.gas }) as any
if (IntrinsicGasTooLowError.nodeMessage.test(message))
return new IntrinsicGasTooLowError({ cause: err, gas: args?.gas }) as any
if (TransactionTypeNotSupportedError.nodeMessage.test(message))
return new TransactionTypeNotSupportedError({ cause: err }) as any
if (TipAboveFeeCapError.nodeMessage.test(message))
return new TipAboveFeeCapError({
cause: err,
maxFeePerGas: args?.maxFeePerGas,
maxPriorityFeePerGas: args?.maxPriorityFeePerGas,
}) as any
return new UnknownNodeError({
cause: err,
}) as any
}

48
node_modules/viem/utils/errors/getTransactionError.ts generated vendored Normal file
View File

@@ -0,0 +1,48 @@
import type { Account } from '../../accounts/types.js'
import type { SendTransactionParameters } from '../../actions/wallet/sendTransaction.js'
import type { BaseError } from '../../errors/base.js'
import { UnknownNodeError } from '../../errors/node.js'
import {
TransactionExecutionError,
type TransactionExecutionErrorType,
} from '../../errors/transaction.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Chain } from '../../types/chain.js'
import {
type GetNodeErrorParameters,
type GetNodeErrorReturnType,
getNodeError,
} from './getNodeError.js'
export type GetTransactionErrorParameters = Omit<
SendTransactionParameters,
'account' | 'chain'
> & {
account: Account | null
chain?: Chain | undefined
docsPath?: string | undefined
}
export type GetTransactionErrorReturnType<cause = ErrorType> = Omit<
TransactionExecutionErrorType,
'cause'
> & { cause: cause | GetNodeErrorReturnType }
export function getTransactionError<err extends ErrorType<string>>(
err: err,
{ docsPath, ...args }: GetTransactionErrorParameters,
): GetTransactionErrorReturnType<err> {
const cause = (() => {
const cause = getNodeError(
err as {} as BaseError,
args as GetNodeErrorParameters,
)
if (cause instanceof UnknownNodeError) return err as {} as BaseError
return cause
})()
return new TransactionExecutionError(cause, {
docsPath,
...args,
}) as GetTransactionErrorReturnType<err>
}

View File

@@ -0,0 +1,51 @@
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import type { OnResponseFn } from '../../clients/transports/fallback.js'
import type { Chain } from '../../types/chain.js'
import type { EIP1193RequestFn, PublicRpcSchema } from '../../types/eip1193.js'
import type { Hex } from '../../types/misc.js'
import type { Filter } from '../../types/utils.js'
type CreateFilterRequestScopeParameters = {
method:
| 'eth_newFilter'
| 'eth_newPendingTransactionFilter'
| 'eth_newBlockFilter'
}
type FilterRpcSchema = Filter<
PublicRpcSchema,
{ Method: 'eth_getFilterLogs' | 'eth_getFilterChanges' }
>
type CreateFilterRequestScopeReturnType = (
id: Hex,
) => EIP1193RequestFn<FilterRpcSchema>
/**
* Scopes `request` to the filter ID. If the client is a fallback, it will
* listen for responses and scope the child transport `request` function
* to the successful filter ID.
*/
export function createFilterRequestScope<chain extends Chain | undefined>(
client: Client<Transport, chain>,
{ method }: CreateFilterRequestScopeParameters,
): CreateFilterRequestScopeReturnType {
const requestMap: Record<Hex, EIP1193RequestFn> = {}
if (client.transport.type === 'fallback')
client.transport.onResponse?.(
({
method: method_,
response: id,
status,
transport,
}: Parameters<OnResponseFn>[0]) => {
if (status === 'success' && method === method_)
requestMap[id as Hex] = transport.request
},
)
return ((id) =>
requestMap[id] || client.request) as CreateFilterRequestScopeReturnType
}

76
node_modules/viem/utils/formatters/block.ts generated vendored Normal file
View File

@@ -0,0 +1,76 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Block, BlockTag } from '../../types/block.js'
import type {
Chain,
ExtractChainFormatterExclude,
ExtractChainFormatterReturnType,
} from '../../types/chain.js'
import type { Hash } from '../../types/misc.js'
import type { RpcBlock } from '../../types/rpc.js'
import type { ExactPartial, Prettify } from '../../types/utils.js'
import { type DefineFormatterErrorType, defineFormatter } from './formatter.js'
import { type FormattedTransaction, formatTransaction } from './transaction.js'
type BlockPendingDependencies = 'hash' | 'logsBloom' | 'nonce' | 'number'
export type FormattedBlock<
chain extends Chain | undefined = undefined,
includeTransactions extends boolean = boolean,
blockTag extends BlockTag = BlockTag,
_FormatterReturnType = ExtractChainFormatterReturnType<
chain,
'block',
Block<bigint, includeTransactions>
>,
_ExcludedPendingDependencies extends string = BlockPendingDependencies &
ExtractChainFormatterExclude<chain, 'block'>,
_Formatted = Omit<_FormatterReturnType, BlockPendingDependencies> & {
[_key in _ExcludedPendingDependencies]: never
} & Pick<
Block<bigint, includeTransactions, blockTag>,
BlockPendingDependencies
>,
_Transactions = includeTransactions extends true
? Prettify<FormattedTransaction<chain, blockTag>>[]
: Hash[],
> = Omit<_Formatted, 'transactions'> & {
transactions: _Transactions
}
export type FormatBlockErrorType = ErrorType
export function formatBlock(
block: ExactPartial<RpcBlock>,
_?: string | undefined,
) {
const transactions = (block.transactions ?? []).map((transaction) => {
if (typeof transaction === 'string') return transaction
return formatTransaction(transaction)
})
return {
...block,
baseFeePerGas: block.baseFeePerGas ? BigInt(block.baseFeePerGas) : null,
blobGasUsed: block.blobGasUsed ? BigInt(block.blobGasUsed) : undefined,
difficulty: block.difficulty ? BigInt(block.difficulty) : undefined,
excessBlobGas: block.excessBlobGas
? BigInt(block.excessBlobGas)
: undefined,
gasLimit: block.gasLimit ? BigInt(block.gasLimit) : undefined,
gasUsed: block.gasUsed ? BigInt(block.gasUsed) : undefined,
hash: block.hash ? block.hash : null,
logsBloom: block.logsBloom ? block.logsBloom : null,
nonce: block.nonce ? block.nonce : null,
number: block.number ? BigInt(block.number) : null,
size: block.size ? BigInt(block.size) : undefined,
timestamp: block.timestamp ? BigInt(block.timestamp) : undefined,
transactions,
totalDifficulty: block.totalDifficulty
? BigInt(block.totalDifficulty)
: null,
} as Block
}
export type DefineBlockErrorType = DefineFormatterErrorType | ErrorType
export const defineBlock = /*#__PURE__*/ defineFormatter('block', formatBlock)

33
node_modules/viem/utils/formatters/extract.ts generated vendored Normal file
View File

@@ -0,0 +1,33 @@
import type { ErrorType } from '../../errors/utils.js'
import type { ChainFormatter } from '../../types/chain.js'
export type ExtractErrorType = ErrorType
/**
* @description Picks out the keys from `value` that exist in the formatter..
*/
export function extract(
value_: Record<string, unknown>,
{ format }: { format?: ChainFormatter['format'] | undefined },
) {
if (!format) return {}
const value: Record<string, unknown> = {}
function extract_(formatted: Record<string, any>) {
const keys = Object.keys(formatted)
for (const key of keys) {
if (key in value_) value[key] = value_[key]
if (
formatted[key] &&
typeof formatted[key] === 'object' &&
!Array.isArray(formatted[key])
)
extract_(formatted[key])
}
}
const formatted = format(value_ || {})
extract_(formatted)
return value
}

16
node_modules/viem/utils/formatters/feeHistory.ts generated vendored Normal file
View File

@@ -0,0 +1,16 @@
import type { ErrorType } from '../../errors/utils.js'
import type { FeeHistory } from '../../types/fee.js'
import type { RpcFeeHistory } from '../../types/rpc.js'
export type FormatFeeHistoryErrorType = ErrorType
export function formatFeeHistory(feeHistory: RpcFeeHistory): FeeHistory {
return {
baseFeePerGas: feeHistory.baseFeePerGas.map((value) => BigInt(value)),
gasUsedRatio: feeHistory.gasUsedRatio,
oldestBlock: BigInt(feeHistory.oldestBlock),
reward: feeHistory.reward?.map((reward) =>
reward.map((value) => BigInt(value)),
),
}
}

43
node_modules/viem/utils/formatters/formatter.ts generated vendored Normal file
View File

@@ -0,0 +1,43 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Prettify } from '../../types/utils.js'
export type DefineFormatterErrorType = ErrorType
export function defineFormatter<type extends string, parameters, returnType>(
type: type,
format: (args: parameters, action?: string | undefined) => returnType,
) {
return <
parametersOverride,
returnTypeOverride,
exclude extends (keyof parameters | keyof parametersOverride)[] = [],
>({
exclude,
format: overrides,
}: {
exclude?: exclude | undefined
format: (
args: parametersOverride,
action?: string | undefined,
) => returnTypeOverride
}) => {
return {
exclude,
format: (args: parametersOverride, action?: string | undefined) => {
const formatted = format(args as any, action)
if (exclude) {
for (const key of exclude) {
delete (formatted as any)[key]
}
}
return {
...formatted,
...overrides(args, action),
} as Prettify<returnTypeOverride> & {
[_key in exclude[number]]: never
}
},
type,
}
}
}

31
node_modules/viem/utils/formatters/log.ts generated vendored Normal file
View File

@@ -0,0 +1,31 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Log } from '../../types/log.js'
import type { RpcLog } from '../../types/rpc.js'
import type { ExactPartial } from '../../types/utils.js'
export type FormatLogErrorType = ErrorType
export function formatLog(
log: ExactPartial<RpcLog>,
{
args,
eventName,
}: { args?: unknown | undefined; eventName?: string | undefined } = {},
) {
return {
...log,
blockHash: log.blockHash ? log.blockHash : null,
blockNumber: log.blockNumber ? BigInt(log.blockNumber) : null,
blockTimestamp: log.blockTimestamp
? BigInt(log.blockTimestamp)
: log.blockTimestamp === null
? null
: undefined,
logIndex: log.logIndex ? Number(log.logIndex) : null,
transactionHash: log.transactionHash ? log.transactionHash : null,
transactionIndex: log.transactionIndex
? Number(log.transactionIndex)
: null,
...(eventName ? { args, eventName } : {}),
} as Log
}

25
node_modules/viem/utils/formatters/proof.ts generated vendored Normal file
View File

@@ -0,0 +1,25 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Proof } from '../../types/proof.js'
import type { RpcProof } from '../../types/rpc.js'
import type { ExactPartial } from '../../types/utils.js'
import { hexToNumber } from '../index.js'
export type FormatProofErrorType = ErrorType
function formatStorageProof(storageProof: RpcProof['storageProof']) {
return storageProof.map((proof) => ({
...proof,
value: BigInt(proof.value),
}))
}
export function formatProof(proof: ExactPartial<RpcProof>) {
return {
...proof,
balance: proof.balance ? BigInt(proof.balance) : undefined,
nonce: proof.nonce ? hexToNumber(proof.nonce) : undefined,
storageProof: proof.storageProof
? formatStorageProof(proof.storageProof)
: undefined,
} as Proof
}

139
node_modules/viem/utils/formatters/transaction.ts generated vendored Normal file
View File

@@ -0,0 +1,139 @@
import type { ErrorType } from '../../errors/utils.js'
import type { SignedAuthorizationList } from '../../types/authorization.js'
import type { BlockTag } from '../../types/block.js'
import type {
Chain,
ExtractChainFormatterExclude,
ExtractChainFormatterReturnType,
} from '../../types/chain.js'
import type { Hex } from '../../types/misc.js'
import type { RpcAuthorizationList, RpcTransaction } from '../../types/rpc.js'
import type { Transaction, TransactionType } from '../../types/transaction.js'
import type { ExactPartial, UnionLooseOmit } from '../../types/utils.js'
import { hexToNumber } from '../encoding/fromHex.js'
import { type DefineFormatterErrorType, defineFormatter } from './formatter.js'
type TransactionPendingDependencies =
| 'blockHash'
| 'blockNumber'
| 'transactionIndex'
export type FormattedTransaction<
chain extends Chain | undefined = undefined,
blockTag extends BlockTag = BlockTag,
_FormatterReturnType = ExtractChainFormatterReturnType<
chain,
'transaction',
Transaction
>,
_ExcludedPendingDependencies extends string = TransactionPendingDependencies &
ExtractChainFormatterExclude<chain, 'transaction'>,
> = UnionLooseOmit<_FormatterReturnType, TransactionPendingDependencies> & {
[_K in _ExcludedPendingDependencies]: never
} & Pick<
Transaction<bigint, number, blockTag extends 'pending' ? true : false>,
TransactionPendingDependencies
>
export const transactionType = {
'0x0': 'legacy',
'0x1': 'eip2930',
'0x2': 'eip1559',
'0x3': 'eip4844',
'0x4': 'eip7702',
} as const satisfies Record<Hex, TransactionType>
export type FormatTransactionErrorType = ErrorType
export function formatTransaction(
transaction: ExactPartial<RpcTransaction>,
_?: string | undefined,
) {
const transaction_ = {
...transaction,
blockHash: transaction.blockHash ? transaction.blockHash : null,
blockNumber: transaction.blockNumber
? BigInt(transaction.blockNumber)
: null,
chainId: transaction.chainId ? hexToNumber(transaction.chainId) : undefined,
gas: transaction.gas ? BigInt(transaction.gas) : undefined,
gasPrice: transaction.gasPrice ? BigInt(transaction.gasPrice) : undefined,
maxFeePerBlobGas: transaction.maxFeePerBlobGas
? BigInt(transaction.maxFeePerBlobGas)
: undefined,
maxFeePerGas: transaction.maxFeePerGas
? BigInt(transaction.maxFeePerGas)
: undefined,
maxPriorityFeePerGas: transaction.maxPriorityFeePerGas
? BigInt(transaction.maxPriorityFeePerGas)
: undefined,
nonce: transaction.nonce ? hexToNumber(transaction.nonce) : undefined,
to: transaction.to ? transaction.to : null,
transactionIndex: transaction.transactionIndex
? Number(transaction.transactionIndex)
: null,
type: transaction.type
? (transactionType as any)[transaction.type]
: undefined,
typeHex: transaction.type ? transaction.type : undefined,
value: transaction.value ? BigInt(transaction.value) : undefined,
v: transaction.v ? BigInt(transaction.v) : undefined,
} as Transaction
if (transaction.authorizationList)
transaction_.authorizationList = formatAuthorizationList(
transaction.authorizationList,
)
transaction_.yParity = (() => {
// If `yParity` is provided, we will use it.
if (transaction.yParity) return Number(transaction.yParity)
// If no `yParity` provided, try derive from `v`.
if (typeof transaction_.v === 'bigint') {
if (transaction_.v === 0n || transaction_.v === 27n) return 0
if (transaction_.v === 1n || transaction_.v === 28n) return 1
if (transaction_.v >= 35n) return transaction_.v % 2n === 0n ? 1 : 0
}
return undefined
})()
if (transaction_.type === 'legacy') {
delete transaction_.accessList
delete transaction_.maxFeePerBlobGas
delete transaction_.maxFeePerGas
delete transaction_.maxPriorityFeePerGas
delete transaction_.yParity
}
if (transaction_.type === 'eip2930') {
delete transaction_.maxFeePerBlobGas
delete transaction_.maxFeePerGas
delete transaction_.maxPriorityFeePerGas
}
if (transaction_.type === 'eip1559') delete transaction_.maxFeePerBlobGas
return transaction_
}
export type DefineTransactionErrorType = DefineFormatterErrorType | ErrorType
export const defineTransaction = /*#__PURE__*/ defineFormatter(
'transaction',
formatTransaction,
)
//////////////////////////////////////////////////////////////////////////////
function formatAuthorizationList(
authorizationList: RpcAuthorizationList,
): SignedAuthorizationList {
return authorizationList.map((authorization) => ({
address: (authorization as any).address,
chainId: Number(authorization.chainId),
nonce: Number(authorization.nonce),
r: authorization.r,
s: authorization.s,
yParity: Number(authorization.yParity),
})) as SignedAuthorizationList
}

View File

@@ -0,0 +1,83 @@
import type { ErrorType } from '../../errors/utils.js'
import type {
Chain,
ExtractChainFormatterReturnType,
} from '../../types/chain.js'
import type { RpcTransactionReceipt } from '../../types/rpc.js'
import type { TransactionReceipt } from '../../types/transaction.js'
import type { ExactPartial } from '../../types/utils.js'
import { hexToNumber } from '../encoding/fromHex.js'
import { type DefineFormatterErrorType, defineFormatter } from './formatter.js'
import { formatLog } from './log.js'
import { transactionType } from './transaction.js'
export type FormattedTransactionReceipt<
chain extends Chain | undefined = undefined,
> = ExtractChainFormatterReturnType<
chain,
'transactionReceipt',
TransactionReceipt
>
export const receiptStatuses = {
'0x0': 'reverted',
'0x1': 'success',
} as const
export type FormatTransactionReceiptErrorType = ErrorType
export function formatTransactionReceipt(
transactionReceipt: ExactPartial<RpcTransactionReceipt>,
_?: string | undefined,
) {
const receipt = {
...transactionReceipt,
blockNumber: transactionReceipt.blockNumber
? BigInt(transactionReceipt.blockNumber)
: null,
contractAddress: transactionReceipt.contractAddress
? transactionReceipt.contractAddress
: null,
cumulativeGasUsed: transactionReceipt.cumulativeGasUsed
? BigInt(transactionReceipt.cumulativeGasUsed)
: null,
effectiveGasPrice: transactionReceipt.effectiveGasPrice
? BigInt(transactionReceipt.effectiveGasPrice)
: null,
gasUsed: transactionReceipt.gasUsed
? BigInt(transactionReceipt.gasUsed)
: null,
logs: transactionReceipt.logs
? transactionReceipt.logs.map((log) => formatLog(log))
: null,
to: transactionReceipt.to ? transactionReceipt.to : null,
transactionIndex: transactionReceipt.transactionIndex
? hexToNumber(transactionReceipt.transactionIndex)
: null,
status: transactionReceipt.status
? receiptStatuses[transactionReceipt.status]
: null,
type: transactionReceipt.type
? transactionType[
transactionReceipt.type as keyof typeof transactionType
] || transactionReceipt.type
: null,
} as TransactionReceipt
if (transactionReceipt.blobGasPrice)
receipt.blobGasPrice = BigInt(transactionReceipt.blobGasPrice)
if (transactionReceipt.blobGasUsed)
receipt.blobGasUsed = BigInt(transactionReceipt.blobGasUsed)
return receipt
}
export type DefineTransactionReceiptErrorType =
| DefineFormatterErrorType
| ErrorType
export const defineTransactionReceipt = /*#__PURE__*/ defineFormatter(
'transactionReceipt',
formatTransactionReceipt,
)

View File

@@ -0,0 +1,116 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Account } from '../../types/account.js'
import type { AuthorizationList } from '../../types/authorization.js'
import type {
Chain,
ExtractChainFormatterParameters,
} from '../../types/chain.js'
import type { ByteArray } from '../../types/misc.js'
import type {
RpcAuthorizationList,
RpcTransactionRequest,
} from '../../types/rpc.js'
import type { TransactionRequest } from '../../types/transaction.js'
import type { ExactPartial } from '../../types/utils.js'
import { bytesToHex, numberToHex } from '../encoding/toHex.js'
import { type DefineFormatterErrorType, defineFormatter } from './formatter.js'
export type FormattedTransactionRequest<
chain extends Chain | undefined = Chain | undefined,
> = ExtractChainFormatterParameters<
chain,
'transactionRequest',
TransactionRequest
>
export const rpcTransactionType = {
legacy: '0x0',
eip2930: '0x1',
eip1559: '0x2',
eip4844: '0x3',
eip7702: '0x4',
} as const
export type FormatTransactionRequestErrorType = ErrorType
export function formatTransactionRequest(
request: ExactPartial<TransactionRequest> & { account?: Account | undefined },
_?: string | undefined,
) {
const rpcRequest = {} as RpcTransactionRequest
if (typeof request.authorizationList !== 'undefined')
rpcRequest.authorizationList = formatAuthorizationList(
request.authorizationList,
)
if (typeof request.accessList !== 'undefined')
rpcRequest.accessList = request.accessList
if (typeof request.blobVersionedHashes !== 'undefined')
rpcRequest.blobVersionedHashes = request.blobVersionedHashes
if (typeof request.blobs !== 'undefined') {
if (typeof request.blobs[0] !== 'string')
rpcRequest.blobs = (request.blobs as ByteArray[]).map((x) =>
bytesToHex(x),
)
else rpcRequest.blobs = request.blobs
}
if (typeof request.data !== 'undefined') rpcRequest.data = request.data
if (request.account) rpcRequest.from = request.account.address
if (typeof request.from !== 'undefined') rpcRequest.from = request.from
if (typeof request.gas !== 'undefined')
rpcRequest.gas = numberToHex(request.gas)
if (typeof request.gasPrice !== 'undefined')
rpcRequest.gasPrice = numberToHex(request.gasPrice)
if (typeof request.maxFeePerBlobGas !== 'undefined')
rpcRequest.maxFeePerBlobGas = numberToHex(request.maxFeePerBlobGas)
if (typeof request.maxFeePerGas !== 'undefined')
rpcRequest.maxFeePerGas = numberToHex(request.maxFeePerGas)
if (typeof request.maxPriorityFeePerGas !== 'undefined')
rpcRequest.maxPriorityFeePerGas = numberToHex(request.maxPriorityFeePerGas)
if (typeof request.nonce !== 'undefined')
rpcRequest.nonce = numberToHex(request.nonce)
if (typeof request.to !== 'undefined') rpcRequest.to = request.to
if (typeof request.type !== 'undefined')
rpcRequest.type = rpcTransactionType[request.type]
if (typeof request.value !== 'undefined')
rpcRequest.value = numberToHex(request.value)
return rpcRequest
}
export type DefineTransactionRequestErrorType =
| DefineFormatterErrorType
| ErrorType
export const defineTransactionRequest = /*#__PURE__*/ defineFormatter(
'transactionRequest',
formatTransactionRequest,
)
//////////////////////////////////////////////////////////////////////////////
function formatAuthorizationList(
authorizationList: AuthorizationList<number, boolean>,
): RpcAuthorizationList {
return authorizationList.map(
(authorization) =>
({
address: authorization.address,
r: authorization.r
? numberToHex(BigInt(authorization.r))
: authorization.r,
s: authorization.s
? numberToHex(BigInt(authorization.s))
: authorization.s,
chainId: numberToHex(authorization.chainId),
nonce: numberToHex(authorization.nonce),
...(typeof authorization.yParity !== 'undefined'
? { yParity: numberToHex(authorization.yParity) }
: {}),
...(typeof authorization.v !== 'undefined' &&
typeof authorization.yParity === 'undefined'
? { v: numberToHex(authorization.v) }
: {}),
}) as any,
) as RpcAuthorizationList
}

42
node_modules/viem/utils/getAction.ts generated vendored Normal file
View File

@@ -0,0 +1,42 @@
import type { Client } from '../clients/createClient.js'
import type { PublicActions } from '../clients/decorators/public.js'
import type { WalletActions } from '../clients/decorators/wallet.js'
import type { Transport } from '../clients/transports/createTransport.js'
import type { Account } from '../types/account.js'
import type { Chain } from '../types/chain.js'
import type { RpcSchema } from '../types/eip1193.js'
/**
* Retrieves and returns an action from the client (if exists), and falls
* back to the tree-shakable action.
*
* Useful for extracting overridden actions from a client (ie. if a consumer
* wants to override the `sendTransaction` implementation).
*/
export function getAction<
transport extends Transport,
chain extends Chain | undefined,
account extends Account | undefined,
rpcSchema extends RpcSchema | undefined,
extended extends { [key: string]: unknown },
client extends Client<transport, chain, account, rpcSchema, extended>,
parameters,
returnType,
>(
client: client,
actionFn: (_: any, parameters: parameters) => returnType,
// Some minifiers drop `Function.prototype.name`, or replace it with short letters,
// meaning that `actionFn.name` will not always work. For that case, the consumer
// needs to pass the name explicitly.
name: keyof PublicActions | keyof WalletActions | (string & {}),
): (parameters: parameters) => returnType {
const action_implicit = client[actionFn.name]
if (typeof action_implicit === 'function')
return action_implicit as (params: parameters) => returnType
const action_explicit = client[name]
if (typeof action_explicit === 'function')
return action_explicit as (params: parameters) => returnType
return (params) => actionFn(client, params)
}

14
node_modules/viem/utils/hash/hashSignature.ts generated vendored Normal file
View File

@@ -0,0 +1,14 @@
import type { ErrorType } from '../../errors/utils.js'
import { type ToBytesErrorType, toBytes } from '../encoding/toBytes.js'
import { type Keccak256ErrorType, keccak256 } from './keccak256.js'
const hash = (value: string) => keccak256(toBytes(value))
export type HashSignatureErrorType =
| Keccak256ErrorType
| ToBytesErrorType
| ErrorType
export function hashSignature(sig: string) {
return hash(sig)
}

10
node_modules/viem/utils/hash/isHash.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Hex } from '../../types/misc.js'
import { type IsHexErrorType, isHex } from '../data/isHex.js'
import { type SizeErrorType, size } from '../data/size.js'
export type IsHashErrorType = IsHexErrorType | SizeErrorType | ErrorType
export function isHash(hash: string): hash is Hex {
return isHex(hash) && size(hash) === 32
}

31
node_modules/viem/utils/hash/keccak256.ts generated vendored Normal file
View File

@@ -0,0 +1,31 @@
import { keccak_256 } from '@noble/hashes/sha3'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type IsHexErrorType, isHex } from '../data/isHex.js'
import { type ToBytesErrorType, toBytes } from '../encoding/toBytes.js'
import { type ToHexErrorType, toHex } from '../encoding/toHex.js'
type To = 'hex' | 'bytes'
export type Keccak256Hash<to extends To> =
| (to extends 'bytes' ? ByteArray : never)
| (to extends 'hex' ? Hex : never)
export type Keccak256ErrorType =
| IsHexErrorType
| ToBytesErrorType
| ToHexErrorType
| ErrorType
export function keccak256<to extends To = 'hex'>(
value: Hex | ByteArray,
to_?: to | undefined,
): Keccak256Hash<to> {
const to = to_ || 'hex'
const bytes = keccak_256(
isHex(value, { strict: false }) ? toBytes(value) : value,
)
if (to === 'bytes') return bytes as Keccak256Hash<to>
return toHex(bytes) as Keccak256Hash<to>
}

64
node_modules/viem/utils/hash/normalizeSignature.ts generated vendored Normal file
View File

@@ -0,0 +1,64 @@
import { BaseError } from '../../errors/base.js'
import type { ErrorType } from '../../errors/utils.js'
type NormalizeSignatureParameters = string
type NormalizeSignatureReturnType = string
export type NormalizeSignatureErrorType = ErrorType
export function normalizeSignature(
signature: NormalizeSignatureParameters,
): NormalizeSignatureReturnType {
let active = true
let current = ''
let level = 0
let result = ''
let valid = false
for (let i = 0; i < signature.length; i++) {
const char = signature[i]
// If the character is a separator, we want to reactivate.
if (['(', ')', ','].includes(char)) active = true
// If the character is a "level" token, we want to increment/decrement.
if (char === '(') level++
if (char === ')') level--
// If we aren't active, we don't want to mutate the result.
if (!active) continue
// If level === 0, we are at the definition level.
if (level === 0) {
if (char === ' ' && ['event', 'function', ''].includes(result))
result = ''
else {
result += char
// If we are at the end of the definition, we must be finished.
if (char === ')') {
valid = true
break
}
}
continue
}
// Ignore spaces
if (char === ' ') {
// If the previous character is a separator, and the current section isn't empty, we want to deactivate.
if (signature[i - 1] !== ',' && current !== ',' && current !== ',(') {
current = ''
active = false
}
continue
}
result += char
current += char
}
if (!valid) throw new BaseError('Unable to normalize signature.')
return result
}

31
node_modules/viem/utils/hash/ripemd160.ts generated vendored Normal file
View File

@@ -0,0 +1,31 @@
import { ripemd160 as noble_ripemd160 } from '@noble/hashes/ripemd160'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type IsHexErrorType, isHex } from '../data/isHex.js'
import { type ToBytesErrorType, toBytes } from '../encoding/toBytes.js'
import { type ToHexErrorType, toHex } from '../encoding/toHex.js'
type To = 'hex' | 'bytes'
export type Ripemd160Hash<to extends To> =
| (to extends 'bytes' ? ByteArray : never)
| (to extends 'hex' ? Hex : never)
export type Ripemd160ErrorType =
| IsHexErrorType
| ToBytesErrorType
| ToHexErrorType
| ErrorType
export function ripemd160<to extends To = 'hex'>(
value: Hex | ByteArray,
to_?: to | undefined,
): Ripemd160Hash<to> {
const to = to_ || 'hex'
const bytes = noble_ripemd160(
isHex(value, { strict: false }) ? toBytes(value) : value,
)
if (to === 'bytes') return bytes as Ripemd160Hash<to>
return toHex(bytes) as Ripemd160Hash<to>
}

31
node_modules/viem/utils/hash/sha256.ts generated vendored Normal file
View File

@@ -0,0 +1,31 @@
import { sha256 as noble_sha256 } from '@noble/hashes/sha256'
import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex } from '../../types/misc.js'
import { type IsHexErrorType, isHex } from '../data/isHex.js'
import { type ToBytesErrorType, toBytes } from '../encoding/toBytes.js'
import { type ToHexErrorType, toHex } from '../encoding/toHex.js'
type To = 'hex' | 'bytes'
export type Sha256Hash<to extends To> =
| (to extends 'bytes' ? ByteArray : never)
| (to extends 'hex' ? Hex : never)
export type Sha256ErrorType =
| IsHexErrorType
| ToBytesErrorType
| ToHexErrorType
| ErrorType
export function sha256<to extends To = 'hex'>(
value: Hex | ByteArray,
to_?: to | undefined,
): Sha256Hash<to> {
const to = to_ || 'hex'
const bytes = noble_sha256(
isHex(value, { strict: false }) ? toBytes(value) : value,
)
if (to === 'bytes') return bytes as Sha256Hash<to>
return toHex(bytes) as Sha256Hash<to>
}

5
node_modules/viem/utils/hash/toEventHash.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
// biome-ignore lint/performance/noBarrelFile: intentional
export {
type ToSignatureHashErrorType as ToEventHashErrorType,
toSignatureHash as toEventHash,
} from './toSignatureHash.js'

16
node_modules/viem/utils/hash/toEventSelector.ts generated vendored Normal file
View File

@@ -0,0 +1,16 @@
import type { ErrorType } from '../../errors/utils.js'
import {
type ToSignatureHashErrorType,
toSignatureHash,
} from './toSignatureHash.js'
export type ToEventSelectorErrorType = ToSignatureHashErrorType | ErrorType
/**
* Returns the event selector for a given event definition.
*
* @example
* const selector = toEventSelector('Transfer(address indexed from, address indexed to, uint256 amount)')
* // 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
*/
export const toEventSelector = toSignatureHash

5
node_modules/viem/utils/hash/toEventSignature.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
// biome-ignore lint/performance/noBarrelFile: intentional
export {
type ToSignatureErrorType as ToEventSignatureErrorType,
toSignature as toEventSignature,
} from './toSignature.js'

5
node_modules/viem/utils/hash/toFunctionHash.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
// biome-ignore lint/performance/noBarrelFile: intentional
export {
type ToSignatureHashErrorType as ToFunctionHashErrorType,
toSignatureHash as toFunctionHash,
} from './toSignatureHash.js'

23
node_modules/viem/utils/hash/toFunctionSelector.ts generated vendored Normal file
View File

@@ -0,0 +1,23 @@
import type { AbiFunction } from 'abitype'
import type { ErrorType } from '../../errors/utils.js'
import { type SliceErrorType, slice } from '../data/slice.js'
import {
type ToSignatureHashErrorType,
toSignatureHash,
} from './toSignatureHash.js'
export type ToFunctionSelectorErrorType =
| ToSignatureHashErrorType
| SliceErrorType
| ErrorType
/**
* Returns the function selector for a given function definition.
*
* @example
* const selector = toFunctionSelector('function ownerOf(uint256 tokenId)')
* // 0x6352211e
*/
export const toFunctionSelector = (fn: string | AbiFunction) =>
slice(toSignatureHash(fn), 0, 4)

5
node_modules/viem/utils/hash/toFunctionSignature.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
// biome-ignore lint/performance/noBarrelFile: intentional
export {
type ToSignatureErrorType as ToFunctionSignatureErrorType,
toSignature as toFunctionSignature,
} from './toSignature.js'

34
node_modules/viem/utils/hash/toSignature.ts generated vendored Normal file
View File

@@ -0,0 +1,34 @@
import { type AbiEvent, type AbiFunction, formatAbiItem } from 'abitype'
import type { ErrorType } from '../../errors/utils.js'
import {
type NormalizeSignatureErrorType,
normalizeSignature,
} from './normalizeSignature.js'
export type ToSignatureErrorType = NormalizeSignatureErrorType | ErrorType
/**
* Returns the signature for a given function or event definition.
*
* @example
* const signature = toSignature('function ownerOf(uint256 tokenId)')
* // 'ownerOf(uint256)'
*
* @example
* const signature_3 = toSignature({
* name: 'ownerOf',
* type: 'function',
* inputs: [{ name: 'tokenId', type: 'uint256' }],
* outputs: [],
* stateMutability: 'view',
* })
* // 'ownerOf(uint256)'
*/
export const toSignature = (def: string | AbiFunction | AbiEvent) => {
const def_ = (() => {
if (typeof def === 'string') return def
return formatAbiItem(def)
})()
return normalizeSignature(def_)
}

17
node_modules/viem/utils/hash/toSignatureHash.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
import type { AbiEvent, AbiFunction } from 'abitype'
import type { ErrorType } from '../../errors/utils.js'
import { type HashSignatureErrorType, hashSignature } from './hashSignature.js'
import { type ToSignatureErrorType, toSignature } from './toSignature.js'
export type ToSignatureHashErrorType =
| HashSignatureErrorType
| ToSignatureErrorType
| ErrorType
/**
* Returns the hash (of the function/event signature) for a given event or function definition.
*/
export function toSignatureHash(fn: string | AbiFunction | AbiEvent) {
return hashSignature(toSignature(fn))
}

564
node_modules/viem/utils/index.ts generated vendored Normal file
View File

@@ -0,0 +1,564 @@
// biome-ignore lint/performance/noBarrelFile: entrypoint module
export {
type ParseAbi,
type ParseAbiItem,
type ParseAbiParameter,
type ParseAbiParameters,
parseAbi,
parseAbiItem,
parseAbiParameter,
parseAbiParameters,
} from 'abitype'
export {
type ParseAccountErrorType,
parseAccount,
} from '../accounts/utils/parseAccount.js'
export {
type PublicKeyToAddressErrorType,
publicKeyToAddress,
} from '../accounts/utils/publicKeyToAddress.js'
export {
type DecodeAbiParametersErrorType,
type DecodeAbiParametersReturnType,
decodeAbiParameters,
} from './abi/decodeAbiParameters.js'
export {
type DecodeErrorResultErrorType,
type DecodeErrorResultParameters,
type DecodeErrorResultReturnType,
decodeErrorResult,
} from './abi/decodeErrorResult.js'
export {
type DecodeEventLogErrorType,
type DecodeEventLogParameters,
type DecodeEventLogReturnType,
decodeEventLog,
} from './abi/decodeEventLog.js'
export {
type DecodeFunctionDataErrorType,
type DecodeFunctionDataParameters,
type DecodeFunctionDataReturnType,
decodeFunctionData,
} from './abi/decodeFunctionData.js'
export {
type DecodeFunctionResultErrorType,
type DecodeFunctionResultParameters,
type DecodeFunctionResultReturnType,
decodeFunctionResult,
} from './abi/decodeFunctionResult.js'
export {
type EncodeAbiParametersErrorType,
type EncodeAbiParametersReturnType,
encodeAbiParameters,
} from './abi/encodeAbiParameters.js'
export {
type EncodeDeployDataErrorType,
type EncodeDeployDataParameters,
encodeDeployData,
} from './abi/encodeDeployData.js'
export {
type EncodeErrorResultErrorType,
type EncodeErrorResultParameters,
encodeErrorResult,
} from './abi/encodeErrorResult.js'
export {
type EncodeArgErrorType,
type EncodeEventTopicsParameters,
type EncodeEventTopicsReturnType,
encodeEventTopics,
} from './abi/encodeEventTopics.js'
export {
type EncodeFunctionDataErrorType,
type EncodeFunctionDataParameters,
encodeFunctionData,
} from './abi/encodeFunctionData.js'
export {
type EncodeFunctionResultErrorType,
type EncodeFunctionResultParameters,
encodeFunctionResult,
} from './abi/encodeFunctionResult.js'
export { type EncodePackedErrorType, encodePacked } from './abi/encodePacked.js'
export {
type FormatAbiItemErrorType,
type FormatAbiParamErrorType,
type FormatAbiParamsErrorType,
formatAbiItem,
formatAbiParams,
} from './abi/formatAbiItem.js'
export {
type FormatAbiItemWithArgsErrorType,
formatAbiItemWithArgs,
} from './abi/formatAbiItemWithArgs.js'
export {
type GetAbiItemErrorType,
type GetAbiItemParameters,
getAbiItem,
} from './abi/getAbiItem.js'
export {
type ParseEventLogsErrorType,
type ParseEventLogsParameters,
type ParseEventLogsReturnType,
parseEventLogs,
} from './abi/parseEventLogs.js'
export {
type ChecksumAddressErrorType,
getAddress,
} from './address/getAddress.js'
export {
type GetContractAddressOptions,
type GetCreate2AddressErrorType,
type GetCreate2AddressOptions,
type GetCreateAddressErrorType,
type GetCreateAddressOptions,
getContractAddress,
getCreate2Address,
getCreateAddress,
} from './address/getContractAddress.js'
export { type IsAddressErrorType, isAddress } from './address/isAddress.js'
export {
type IsAddressEqualErrorType,
isAddressEqual,
} from './address/isAddressEqual.js'
export {
type HashAuthorizationErrorType,
type HashAuthorizationParameters,
type HashAuthorizationReturnType,
hashAuthorization,
} from './authorization/hashAuthorization.js'
export {
type RecoverAuthorizationAddressErrorType,
type RecoverAuthorizationAddressParameters,
type RecoverAuthorizationAddressReturnType,
recoverAuthorizationAddress,
} from './authorization/recoverAuthorizationAddress.js'
export {
type SerializeAuthorizationListErrorType,
type SerializeAuthorizationListReturnType,
serializeAuthorizationList,
} from './authorization/serializeAuthorizationList.js'
export {
type VerifyAuthorizationErrorType,
type VerifyAuthorizationParameters,
type VerifyAuthorizationReturnType,
verifyAuthorization,
} from './authorization/verifyAuthorization.js'
export {
buildRequest,
type RequestErrorType,
} from './buildRequest.js'
export {
ccipRequest,
/** @deprecated Use `ccipRequest`. */
ccipRequest as ccipFetch,
type OffchainLookupErrorType,
offchainLookup,
offchainLookupAbiItem,
offchainLookupSignature,
} from './ccip.js'
export {
type AssertCurrentChainErrorType,
type AssertCurrentChainParameters,
assertCurrentChain,
} from './chain/assertCurrentChain.js'
export { defineChain } from './chain/defineChain.js'
export {
type ExtractChainErrorType,
type ExtractChainParameters,
type ExtractChainReturnType,
extractChain,
} from './chain/extractChain.js'
export {
type GetChainContractAddressErrorType,
getChainContractAddress,
} from './chain/getChainContractAddress.js'
export {
type ConcatBytesErrorType,
type ConcatErrorType,
type ConcatHexErrorType,
concat,
concatBytes,
concatHex,
} from './data/concat.js'
export { type IsBytesErrorType, isBytes } from './data/isBytes.js'
export { type IsHexErrorType, isHex } from './data/isHex.js'
export {
type PadBytesErrorType,
type PadErrorType,
type PadHexErrorType,
pad,
padBytes,
padHex,
} from './data/pad.js'
export { type SizeErrorType, size } from './data/size.js'
export {
type AssertEndOffsetErrorType,
type AssertStartOffsetErrorType,
type SliceBytesErrorType,
type SliceErrorType,
type SliceHexErrorType,
type SliceReturnType,
slice,
sliceBytes,
sliceHex,
} from './data/slice.js'
export { type TrimErrorType, type TrimReturnType, trim } from './data/trim.js'
export {
type BytesToBigIntErrorType,
type BytesToBigIntOpts,
type BytesToBoolErrorType,
type BytesToBoolOpts,
type BytesToNumberErrorType,
type BytesToNumberOpts,
type BytesToStringErrorType,
type BytesToStringOpts,
bytesToBigInt,
bytesToBigInt as bytesToBigint,
bytesToBool,
bytesToNumber,
bytesToString,
type FromBytesErrorType,
type FromBytesParameters,
type FromBytesReturnType,
fromBytes,
} from './encoding/fromBytes.js'
export {
type AssertSizeErrorType,
type FromHexErrorType,
type FromHexParameters,
type FromHexReturnType,
fromHex,
type HexToBigIntErrorType,
type HexToBigIntOpts,
type HexToBoolErrorType,
type HexToBoolOpts,
type HexToNumberErrorType,
type HexToNumberOpts,
type HexToStringErrorType,
type HexToStringOpts,
hexToBigInt,
hexToBool,
hexToNumber,
hexToString,
} from './encoding/fromHex.js'
export {
type FromRlpErrorType,
fromRlp,
} from './encoding/fromRlp.js'
export {
type BoolToBytesErrorType,
type BoolToBytesOpts,
boolToBytes,
type HexToBytesErrorType,
type HexToBytesOpts,
hexToBytes,
type NumberToBytesErrorType,
numberToBytes,
type StringToBytesErrorType,
type StringToBytesOpts,
stringToBytes,
type ToBytesErrorType,
type ToBytesParameters,
toBytes,
} from './encoding/toBytes.js'
export {
type BoolToHexErrorType,
type BoolToHexOpts,
type BytesToHexErrorType,
type BytesToHexOpts,
boolToHex,
bytesToHex,
type NumberToHexErrorType,
type NumberToHexOpts,
numberToHex,
type StringToHexErrorType,
type StringToHexOpts,
stringToHex,
type ToHexErrorType,
type ToHexParameters,
toHex,
} from './encoding/toHex.js'
export {
type BytesToRlpErrorType,
type HexToRlpErrorType,
type ToRlpErrorType,
type ToRlpReturnType,
toRlp,
} from './encoding/toRlp.js'
export {
type GetCallErrorReturnType,
getCallError,
} from './errors/getCallError.js'
export {
type GetContractErrorReturnType,
getContractError,
} from './errors/getContractError.js'
export {
type GetEstimateGasErrorReturnType,
getEstimateGasError,
} from './errors/getEstimateGasError.js'
export {
containsNodeError,
type GetNodeErrorParameters,
type GetNodeErrorReturnType,
getNodeError,
} from './errors/getNodeError.js'
export {
type GetTransactionErrorParameters,
type GetTransactionErrorReturnType,
getTransactionError,
} from './errors/getTransactionError.js'
export {
type DefineBlockErrorType,
defineBlock,
type FormatBlockErrorType,
type FormattedBlock,
formatBlock,
} from './formatters/block.js'
export { type ExtractErrorType, extract } from './formatters/extract.js'
export {
type DefineFormatterErrorType,
defineFormatter,
} from './formatters/formatter.js'
export { type FormatLogErrorType, formatLog } from './formatters/log.js'
export {
type DefineTransactionErrorType,
defineTransaction,
type FormatTransactionErrorType,
type FormattedTransaction,
formatTransaction,
transactionType,
} from './formatters/transaction.js'
export {
type DefineTransactionReceiptErrorType,
defineTransactionReceipt,
type FormatTransactionReceiptErrorType,
type FormattedTransactionReceipt,
} from './formatters/transactionReceipt.js'
export {
type DefineTransactionRequestErrorType,
defineTransactionRequest,
type FormatTransactionRequestErrorType,
type FormattedTransactionRequest,
formatTransactionRequest,
} from './formatters/transactionRequest.js'
export { getAction } from './getAction.js'
export { type IsHashErrorType, isHash } from './hash/isHash.js'
export { type Keccak256ErrorType, keccak256 } from './hash/keccak256.js'
export { type Ripemd160ErrorType, ripemd160 } from './hash/ripemd160.js'
export { type Sha256ErrorType, sha256 } from './hash/sha256.js'
export {
type ToEventHashErrorType,
toEventHash,
} from './hash/toEventHash.js'
export {
type ToEventSelectorErrorType,
/** @deprecated use `ToEventSelectorErrorType`. */
type ToEventSelectorErrorType as GetEventSelectorErrorType,
toEventSelector,
/** @deprecated use `toEventSelector`. */
toEventSelector as getEventSelector,
} from './hash/toEventSelector.js'
export {
type ToEventSignatureErrorType,
/** @deprecated use `ToEventSignatureErrorType`. */
type ToEventSignatureErrorType as GetEventSignatureErrorType,
toEventSignature,
/** @deprecated use `toEventSignature`. */
toEventSignature as getEventSignature,
} from './hash/toEventSignature.js'
export {
type ToFunctionHashErrorType,
toFunctionHash,
} from './hash/toFunctionHash.js'
export {
type ToFunctionSelectorErrorType,
/** @deprecated use `ToFunctionSelectorErrorType`. */
type ToFunctionSelectorErrorType as GetFunctionSelectorErrorType,
toFunctionSelector,
/** @deprecated use `toFunctionSelector`. */
toFunctionSelector as getFunctionSelector,
} from './hash/toFunctionSelector.js'
export {
type ToFunctionSignatureErrorType,
/** @deprecated use `ToFunctionSignatureErrorType`. */
type ToFunctionSignatureErrorType as GetFunctionSignatureErrorType,
toFunctionSignature,
/** @deprecated use `toFunctionSignature`. */
toFunctionSignature as getFunctionSignature,
} from './hash/toFunctionSignature.js'
export {
type CreateNonceManagerParameters,
createNonceManager,
type NonceManager,
type NonceManagerSource,
nonceManager,
} from './nonceManager.js'
export { arrayRegex, bytesRegex, integerRegex } from './regex.js'
export {
getSocket,
rpc,
type WebSocketAsyncErrorType,
type WebSocketAsyncOptions,
type WebSocketAsyncReturnType,
type WebSocketErrorType,
type WebSocketOptions,
type WebSocketReturnType,
} from './rpc/compat.js'
export {
getHttpRpcClient,
type HttpRequestErrorType,
type HttpRequestParameters,
type HttpRequestReturnType,
type HttpRpcClient,
type HttpRpcClientOptions,
} from './rpc/http.js'
export {
type GetSocketParameters,
type GetSocketRpcClientErrorType,
type GetSocketRpcClientParameters,
getSocketRpcClient,
type Socket,
type SocketRpcClient,
socketClientCache,
} from './rpc/socket.js'
export { getWebSocketRpcClient } from './rpc/webSocket.js'
export {
type HashMessageErrorType,
type HashMessageReturnType,
hashMessage,
} from './signature/hashMessage.js'
export {
type HashDomainErrorType,
type HashStructErrorType,
type HashTypedDataParameters,
type HashTypedDataReturnType,
hashStruct,
hashTypedData,
} from './signature/hashTypedData.js'
export {
type IsErc6492SignatureErrorType,
type IsErc6492SignatureParameters,
type IsErc6492SignatureReturnType,
isErc6492Signature,
} from './signature/isErc6492Signature.js'
export {
type IsErc8010SignatureErrorType,
type IsErc8010SignatureParameters,
type IsErc8010SignatureReturnType,
isErc8010Signature,
} from './signature/isErc8010Signature.js'
export {
type ParseErc6492SignatureErrorType,
type ParseErc6492SignatureParameters,
type ParseErc6492SignatureReturnType,
parseErc6492Signature,
} from './signature/parseErc6492Signature.js'
export {
type ParseErc8010SignatureErrorType,
type ParseErc8010SignatureParameters,
type ParseErc8010SignatureReturnType,
parseErc8010Signature,
} from './signature/parseErc8010Signature.js'
export {
type RecoverAddressErrorType,
type RecoverAddressParameters,
type RecoverAddressReturnType,
recoverAddress,
} from './signature/recoverAddress.js'
export {
type RecoverMessageAddressErrorType,
type RecoverMessageAddressParameters,
type RecoverMessageAddressReturnType,
recoverMessageAddress,
} from './signature/recoverMessageAddress.js'
export {
type RecoverPublicKeyErrorType,
type RecoverPublicKeyParameters,
type RecoverPublicKeyReturnType,
recoverPublicKey,
} from './signature/recoverPublicKey.js'
export {
type RecoverTypedDataAddressErrorType,
type RecoverTypedDataAddressParameters,
type RecoverTypedDataAddressReturnType,
recoverTypedDataAddress,
} from './signature/recoverTypedDataAddress.js'
export {
type SerializeErc6492SignatureErrorType,
type SerializeErc6492SignatureParameters,
type SerializeErc6492SignatureReturnType,
serializeErc6492Signature,
} from './signature/serializeErc6492Signature.js'
export {
type SerializeErc8010SignatureErrorType,
type SerializeErc8010SignatureParameters,
type SerializeErc8010SignatureReturnType,
serializeErc8010Signature,
} from './signature/serializeErc8010Signature.js'
export {
type VerifyHashErrorType,
type VerifyHashParameters,
type VerifyHashReturnType,
verifyHash,
} from './signature/verifyHash.js'
export {
type VerifyMessageErrorType,
type VerifyMessageParameters,
type VerifyMessageReturnType,
verifyMessage,
} from './signature/verifyMessage.js'
export {
type VerifyTypedDataErrorType,
type VerifyTypedDataParameters,
type VerifyTypedDataReturnType,
verifyTypedData,
} from './signature/verifyTypedData.js'
export { type StringifyErrorType, stringify } from './stringify.js'
export {
type AssertRequestErrorType,
assertRequest,
} from './transaction/assertRequest.js'
export {
type AssertTransactionEIP1559ErrorType,
type AssertTransactionEIP2930ErrorType,
type AssertTransactionLegacyErrorType,
assertTransactionEIP1559,
assertTransactionEIP2930,
assertTransactionLegacy,
} from './transaction/assertTransaction.js'
export {
type GetSerializedTransactionType,
type GetSerializedTransactionTypeErrorType,
getSerializedTransactionType,
} from './transaction/getSerializedTransactionType.js'
export {
type GetTransactionType,
type GetTransactionTypeErrorType,
getTransactionType,
} from './transaction/getTransactionType.js'
export {
type ParseTransactionErrorType,
parseTransaction,
} from './transaction/parseTransaction.js'
export {
type SerializeAccessListErrorType,
serializeAccessList,
} from './transaction/serializeAccessList.js'
export {
type SerializeTransactionErrorType,
type SerializeTransactionFn,
serializeTransaction,
} from './transaction/serializeTransaction.js'
export {
type DomainSeparatorErrorType,
type SerializeTypedDataErrorType,
serializeTypedData,
type ValidateTypedDataErrorType,
validateTypedData,
} from './typedData.js'
export { type FormatEtherErrorType, formatEther } from './unit/formatEther.js'
export { type FormatGweiErrorType, formatGwei } from './unit/formatGwei.js'
export { type FormatUnitsErrorType, formatUnits } from './unit/formatUnits.js'
export { type ParseEtherErrorType, parseEther } from './unit/parseEther.js'
export { type ParseGweiErrorType, parseGwei } from './unit/parseGwei.js'
export { type ParseUnitsErrorType, parseUnits } from './unit/parseUnits.js'

30
node_modules/viem/utils/kzg/defineKzg.ts generated vendored Normal file
View File

@@ -0,0 +1,30 @@
import type { ErrorType } from '../../errors/utils.js'
import type { Kzg } from '../../types/kzg.js'
export type DefineKzgParameters = Kzg
export type DefineKzgReturnType = Kzg
export type DefineKzgErrorType = ErrorType
/**
* Defines a KZG interface.
*
* @example
* ```ts
* import * as cKzg from 'c-kzg'
* import { defineKzg } from 'viem'
* import { mainnetTrustedSetupPath } from 'viem/node'
*
* cKzg.loadTrustedSetup(mainnetTrustedSetupPath)
*
* const kzg = defineKzg(cKzg)
* ```
*/
export function defineKzg({
blobToKzgCommitment,
computeBlobKzgProof,
}: DefineKzgParameters): DefineKzgReturnType {
return {
blobToKzgCommitment,
computeBlobKzgProof,
}
}

38
node_modules/viem/utils/kzg/setupKzg.ts generated vendored Normal file
View File

@@ -0,0 +1,38 @@
import type { ErrorType } from '../../errors/utils.js'
import {
type DefineKzgErrorType,
type DefineKzgParameters,
type DefineKzgReturnType,
defineKzg,
} from './defineKzg.js'
export type SetupKzgParameters = DefineKzgParameters & {
loadTrustedSetup(path: string): void
}
export type SetupKzgReturnType = DefineKzgReturnType
export type SetupKzgErrorType = DefineKzgErrorType | ErrorType
/**
* Sets up and returns a KZG interface.
*
* @example
* ```ts
* import * as cKzg from 'c-kzg'
* import { setupKzg } from 'viem'
* import { mainnetTrustedSetupPath } from 'viem/node'
*
* const kzg = setupKzg(cKzg, mainnetTrustedSetupPath)
* ```
*/
export function setupKzg(
parameters: SetupKzgParameters,
path: string,
): SetupKzgReturnType {
try {
parameters.loadTrustedSetup(path)
} catch (e) {
const error = e as Error
if (!error.message.includes('trusted setup is already loaded')) throw error
}
return defineKzg(parameters)
}

34
node_modules/viem/utils/lru.ts generated vendored Normal file
View File

@@ -0,0 +1,34 @@
/**
* Map with a LRU (Least recently used) policy.
*
* @link https://en.wikipedia.org/wiki/Cache_replacement_policies#LRU
*/
export class LruMap<value = unknown> extends Map<string, value> {
maxSize: number
constructor(size: number) {
super()
this.maxSize = size
}
override get(key: string) {
const value = super.get(key)
if (super.has(key)) {
super.delete(key)
super.set(key, value as value)
}
return value
}
override set(key: string, value: value) {
if (super.has(key)) super.delete(key)
super.set(key, value)
if (this.maxSize && this.size > this.maxSize) {
const firstKey = super.keys().next().value
if (firstKey !== undefined) super.delete(firstKey)
}
return this
}
}

133
node_modules/viem/utils/nonceManager.ts generated vendored Normal file
View File

@@ -0,0 +1,133 @@
import type { Address } from 'abitype'
import { getTransactionCount } from '../actions/public/getTransactionCount.js'
import type { Client } from '../clients/createClient.js'
import type { MaybePromise } from '../types/utils.js'
import { LruMap } from './lru.js'
export type CreateNonceManagerParameters = {
source: NonceManagerSource
}
type FunctionParameters = {
address: Address
chainId: number
}
export type NonceManager = {
/** Get and increment a nonce. */
consume: (
parameters: FunctionParameters & { client: Client },
) => Promise<number>
/** Increment a nonce. */
increment: (chainId: FunctionParameters) => void
/** Get a nonce. */
get: (chainId: FunctionParameters & { client: Client }) => Promise<number>
/** Reset a nonce. */
reset: (chainId: FunctionParameters) => void
}
/**
* Creates a nonce manager for auto-incrementing transaction nonces.
*
* - Docs: https://viem.sh/docs/accounts/createNonceManager
*
* @example
* ```ts
* const nonceManager = createNonceManager({
* source: jsonRpc(),
* })
* ```
*/
export function createNonceManager(
parameters: CreateNonceManagerParameters,
): NonceManager {
const { source } = parameters
const deltaMap = new Map()
const nonceMap = new LruMap<number>(8192)
const promiseMap = new Map<string, Promise<number>>()
const getKey = ({ address, chainId }: FunctionParameters) =>
`${address}.${chainId}`
return {
async consume({ address, chainId, client }) {
const key = getKey({ address, chainId })
const promise = this.get({ address, chainId, client })
this.increment({ address, chainId })
const nonce = await promise
await source.set({ address, chainId }, nonce)
nonceMap.set(key, nonce)
return nonce
},
async increment({ address, chainId }) {
const key = getKey({ address, chainId })
const delta = deltaMap.get(key) ?? 0
deltaMap.set(key, delta + 1)
},
async get({ address, chainId, client }) {
const key = getKey({ address, chainId })
let promise = promiseMap.get(key)
if (!promise) {
promise = (async () => {
try {
const nonce = await source.get({ address, chainId, client })
const previousNonce = nonceMap.get(key) ?? 0
if (previousNonce > 0 && nonce <= previousNonce)
return previousNonce + 1
nonceMap.delete(key)
return nonce
} finally {
this.reset({ address, chainId })
}
})()
promiseMap.set(key, promise)
}
const delta = deltaMap.get(key) ?? 0
return delta + (await promise)
},
reset({ address, chainId }) {
const key = getKey({ address, chainId })
deltaMap.delete(key)
promiseMap.delete(key)
},
}
}
////////////////////////////////////////////////////////////////////////////////////////////
// Sources
export type NonceManagerSource = {
/** Get a nonce. */
get(parameters: FunctionParameters & { client: Client }): MaybePromise<number>
/** Set a nonce. */
set(parameters: FunctionParameters, nonce: number): MaybePromise<void>
}
/** JSON-RPC source for a nonce manager. */
export function jsonRpc(): NonceManagerSource {
return {
async get(parameters) {
const { address, client } = parameters
return getTransactionCount(client, {
address,
blockTag: 'pending',
})
},
set() {},
}
}
////////////////////////////////////////////////////////////////////////////////////////////
// Default
/** Default Nonce Manager with a JSON-RPC source. */
export const nonceManager = /*#__PURE__*/ createNonceManager({
source: jsonRpc(),
})

Some files were not shown because too many files have changed in this diff Show More