UNPKG

@0xfutbol/id

Version:

React component library with shared providers for 0xFutbol ID

1,214 lines (1,213 loc) 41 kB
import {bl as BaseError,bm as fromBytes,bn as fromHex$1,bo as fromNumber,bp as size,bq as assert$4,bb as concat,br as trimLeft,bs as toBigInt,au as getContract,aH as toSerializableTransaction,P as readContract}from'./index-BJCJzM2_.js';import {e as extract,t as toTuple$1,y as yParityToV,I as InvalidVError,f as fromLegacy,v as vToYParity}from'./Signature-TDCoSgpl.js';import'react';import'react/jsx-runtime';import'@0xfutbol/id-sign';import'react-use';import'@0xfutbol/constants';import'thirdweb';import'@matchain/matchid-sdk-react';import'@tanstack/react-query';import'@matchain/matchid-sdk-react/index.css';import'react-dom';const staticCursor = { 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) { this.assertPosition(this.position); this.bytes[this.position] = byte; this.position++; }, pushBytes(bytes) { this.assertPosition(this.position + bytes.length - 1); this.bytes.set(bytes, this.position); this.position += bytes.length; }, pushUint8(value) { this.assertPosition(this.position); this.bytes[this.position] = value; this.position++; }, pushUint16(value) { this.assertPosition(this.position + 1); this.dataView.setUint16(this.position, value); this.position += 2; }, pushUint24(value) { this.assertPosition(this.position + 2); this.dataView.setUint16(this.position, value >> 8); this.dataView.setUint8(this.position + 2, value & 255); this.position += 3; }, pushUint32(value) { 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++; }, }; /** @internal */ function create(bytes, { recursiveReadLimit = 8_192 } = {}) { const cursor = Object.create(staticCursor); cursor.bytes = bytes; cursor.dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); cursor.positionReadCount = new Map(); cursor.recursiveReadLimit = recursiveReadLimit; return cursor; } /** @internal */ class NegativeOffsetError extends BaseError { constructor({ offset }) { super(`Offset \`${offset}\` cannot be negative.`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'Cursor.NegativeOffsetError' }); } } /** @internal */ class PositionOutOfBoundsError extends BaseError { constructor({ length, position }) { super(`Position \`${position}\` is out of bounds (\`0 < position < ${length}\`).`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'Cursor.PositionOutOfBoundsError' }); } } /** @internal */ class RecursiveReadLimitExceededError extends BaseError { constructor({ count, limit }) { super(`Recursive read limit of \`${limit}\` exceeded (recursive read count: \`${count}\`).`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'Cursor.RecursiveReadLimitExceededError' }); } }/** * Encodes a {@link ox#Bytes.Bytes} or {@link ox#Hex.Hex} value into a Recursive-Length Prefix (RLP) value. * * @example * ```ts twoslash * import { Bytes, Rlp } from 'ox' * * Rlp.from('0x68656c6c6f20776f726c64', { as: 'Hex' }) * // @log: 0x8b68656c6c6f20776f726c64 * * Rlp.from(Bytes.from([139, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]), { as: 'Bytes' }) * // @log: Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]) * ``` * * @param value - The {@link ox#Bytes.Bytes} or {@link ox#Hex.Hex} value to encode. * @param options - Options. * @returns The RLP value. */ function from(value, options) { const { as } = options; const encodable = getEncodable(value); const cursor = create(new Uint8Array(encodable.length)); encodable.encode(cursor); if (as === 'Hex') return fromBytes(cursor.bytes); return cursor.bytes; } /** * Encodes a {@link ox#Hex.Hex} value into a Recursive-Length Prefix (RLP) value. * * @example * ```ts twoslash * import { Rlp } from 'ox' * * Rlp.fromHex('0x68656c6c6f20776f726c64') * // @log: 0x8b68656c6c6f20776f726c64 * ``` * * @param hex - The {@link ox#Hex.Hex} value to encode. * @param options - Options. * @returns The RLP value. */ function fromHex(hex, options = {}) { const { as = 'Hex' } = options; return from(hex, { as }); } ///////////////////////////////////////////////////////////////////////////////// // Internal ///////////////////////////////////////////////////////////////////////////////// function getEncodable(bytes) { if (Array.isArray(bytes)) return getEncodableList(bytes.map((x) => getEncodable(x))); return getEncodableBytes(bytes); } function getEncodableList(list) { 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) { 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) { const bytes = typeof bytesOrHex === 'string' ? fromHex$1(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) { 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) { 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.'); }/** * Converts an {@link ox#Authorization.Authorization} to an {@link ox#Authorization.Tuple}. * * @example * ```ts twoslash * import { Authorization } from 'ox' * * const authorization = Authorization.from({ * address: '0x1234567890abcdef1234567890abcdef12345678', * chainId: 1, * nonce: 69n, * }) * * const tuple = Authorization.toTuple(authorization) // [!code focus] * // @log: [ * // @log: address: '0x1234567890abcdef1234567890abcdef12345678', * // @log: chainId: 1, * // @log: nonce: 69n, * // @log: ] * ``` * * @param authorization - The {@link ox#Authorization.Authorization}. * @returns An [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Authorization tuple. */ function toTuple(authorization) { const { address, chainId, nonce } = authorization; const signature = extract(authorization); return [ chainId ? fromNumber(chainId) : '0x', address, nonce ? fromNumber(nonce) : '0x', ...(signature ? toTuple$1(signature) : []), ]; } /** * Converts an {@link ox#Authorization.List} to an {@link ox#Authorization.TupleList}. * * @example * ```ts twoslash * import { Authorization } from 'ox' * * const authorization_1 = Authorization.from({ * address: '0x1234567890abcdef1234567890abcdef12345678', * chainId: 1, * nonce: 69n, * }) * const authorization_2 = Authorization.from({ * address: '0x1234567890abcdef1234567890abcdef12345678', * chainId: 3, * nonce: 20n, * }) * * const tuple = Authorization.toTupleList([authorization_1, authorization_2]) // [!code focus] * // @log: [ * // @log: [ * // @log: address: '0x1234567890abcdef1234567890abcdef12345678', * // @log: chainId: 1, * // @log: nonce: 69n, * // @log: ], * // @log: [ * // @log: address: '0x1234567890abcdef1234567890abcdef12345678', * // @log: chainId: 3, * // @log: nonce: 20n, * // @log: ], * // @log: ] * ``` * * @param list - An {@link ox#Authorization.List}. * @returns An [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Authorization tuple list. */ function toTupleList$1(list) { if (!list || list.length === 0) return []; const tupleList = []; for (const authorization of list) tupleList.push(toTuple(authorization)); return tupleList; }/** * Converts a structured Access List into a list of tuples. * * @example * ```ts twoslash * import { AccessList } from 'ox' * * const accessList = AccessList.toTupleList([ * { * address: '0x0000000000000000000000000000000000000000', * storageKeys: [ * '0x0000000000000000000000000000000000000000000000000000000000000001', * '0x60fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe'], * }, * ]) * // @log: [ * // @log: [ * // @log: '0x0000000000000000000000000000000000000000', * // @log: [ * // @log: '0x0000000000000000000000000000000000000000000000000000000000000001', * // @log: '0x60fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe', * // @log: ], * // @log: ], * // @log: ] * ``` * * @param accessList - Access list. * @returns List of tuples. */ function toTupleList(accessList) { if (!accessList || accessList.length === 0) return []; const tuple = []; for (const { address, storageKeys } of accessList) { for (let j = 0; j < storageKeys.length; j++) if (size(storageKeys[j]) !== 32) throw new InvalidStorageKeySizeError({ storageKey: storageKeys[j], }); if (address) assert$4(address, { strict: false }); tuple.push([address, storageKeys]); } return tuple; } /** Thrown when the size of a storage key is invalid. */ class InvalidStorageKeySizeError extends BaseError { constructor({ storageKey }) { super(`Size for storage key "${storageKey}" is invalid. Expected 32 bytes. Got ${size(storageKey)} bytes.`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'AccessList.InvalidStorageKeySizeError' }); } }/** @see https://ethereum.github.io/yellowpaper/paper.pdf */ const exponents = { wei: 0, gwei: 9, szabo: 12, finney: 15, ether: 18, }; /** * Formats a `bigint` Value to its string representation (divided by the given exponent). * * @example * ```ts twoslash * import { Value } from 'ox' * * Value.format(420_000_000_000n, 9) * // @log: '420' * ``` * * @param value - The `bigint` Value to format. * @param decimals - The exponent to divide the `bigint` Value by. * @returns The string representation of the Value. */ function format(value, decimals = 0) { let display = value.toString(); const negative = display.startsWith('-'); if (negative) display = display.slice(1); display = display.padStart(decimals, '0'); let [integer, fraction] = [ display.slice(0, display.length - decimals), display.slice(display.length - decimals), ]; fraction = fraction.replace(/(0+)$/, ''); return `${negative ? '-' : ''}${integer || '0'}${fraction ? `.${fraction}` : ''}`; } /** * Formats a `bigint` Value (default: wei) to a string representation of Gwei. * * @example * ```ts twoslash * import { Value } from 'ox' * * Value.formatGwei(1_000_000_000n) * // @log: '1' * ``` * * @param wei - The Value to format. * @param unit - The unit to format the Value in. @default 'wei'. * @returns The Gwei string representation of the Value. */ function formatGwei(wei, unit = 'wei') { return format(wei, exponents.gwei - exponents[unit]); }/** * Thrown when a fee cap is too high. * * @example * ```ts twoslash * import { TransactionEnvelopeEip1559 } from 'ox' * * TransactionEnvelopeEip1559.assert({ * maxFeePerGas: 2n ** 256n - 1n + 1n, * chainId: 1, * }) * // @error: TransactionEnvelope.FeeCapTooHighError: The fee cap (`maxFeePerGas`/`maxPriorityFeePerGas` = 115792089237316195423570985008687907853269984665640564039457584007913.129639936 gwei) cannot be higher than the maximum allowed value (2^256-1). * ``` */ class FeeCapTooHighError extends BaseError { constructor({ feeCap, } = {}) { super(`The fee cap (\`maxFeePerGas\`/\`maxPriorityFeePerGas\`${feeCap ? ` = ${formatGwei(feeCap)} gwei` : ''}) cannot be higher than the maximum allowed value (2^256-1).`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'TransactionEnvelope.FeeCapTooHighError' }); } } /** * Thrown when a gas price is too high. * * @example * ```ts twoslash * import { TransactionEnvelopeLegacy } from 'ox' * * TransactionEnvelopeLegacy.assert({ * gasPrice: 2n ** 256n - 1n + 1n, * chainId: 1, * }) * // @error: TransactionEnvelope.GasPriceTooHighError: The gas price (`gasPrice` = 115792089237316195423570985008687907853269984665640564039457584007913.129639936 gwei) cannot be higher than the maximum allowed value (2^256-1). * ``` */ class GasPriceTooHighError extends BaseError { constructor({ gasPrice, } = {}) { super(`The gas price (\`gasPrice\`${gasPrice ? ` = ${formatGwei(gasPrice)} gwei` : ''}) cannot be higher than the maximum allowed value (2^256-1).`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'TransactionEnvelope.GasPriceTooHighError' }); } } /** * Thrown when a chain ID is invalid. * * @example * ```ts twoslash * import { TransactionEnvelopeEip1559 } from 'ox' * * TransactionEnvelopeEip1559.assert({ chainId: 0 }) * // @error: TransactionEnvelope.InvalidChainIdError: Chain ID "0" is invalid. * ``` */ class InvalidChainIdError extends BaseError { constructor({ chainId }) { super(typeof chainId !== 'undefined' ? `Chain ID "${chainId}" is invalid.` : 'Chain ID is invalid.'); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'TransactionEnvelope.InvalidChainIdError' }); } } /** * Thrown when a tip is higher than a fee cap. * * @example * ```ts twoslash * import { TransactionEnvelopeEip1559 } from 'ox' * * TransactionEnvelopeEip1559.assert({ * chainId: 1, * maxFeePerGas: 10n, * maxPriorityFeePerGas: 11n, * }) * // @error: TransactionEnvelope.TipAboveFeeCapError: The provided tip (`maxPriorityFeePerGas` = 11 gwei) cannot be higher than the fee cap (`maxFeePerGas` = 10 gwei). * ``` */ class TipAboveFeeCapError extends BaseError { constructor({ maxPriorityFeePerGas, maxFeePerGas, } = {}) { super([ `The provided tip (\`maxPriorityFeePerGas\`${maxPriorityFeePerGas ? ` = ${formatGwei(maxPriorityFeePerGas)} gwei` : ''}) cannot be higher than the fee cap (\`maxFeePerGas\`${maxFeePerGas ? ` = ${formatGwei(maxFeePerGas)} gwei` : ''}).`, ].join('\n')); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'TransactionEnvelope.TipAboveFeeCapError' }); } }const serializedType$1 = '0x02'; /** * Asserts a {@link ox#TransactionEnvelopeEip1559.TransactionEnvelopeEip1559} is valid. * * @example * ```ts twoslash * import { TransactionEnvelopeEip1559, Value } from 'ox' * * TransactionEnvelopeEip1559.assert({ * maxFeePerGas: 2n ** 256n - 1n + 1n, * chainId: 1, * to: '0x0000000000000000000000000000000000000000', * value: Value.fromEther('1'), * }) * // @error: FeeCapTooHighError: * // @error: The fee cap (`masFeePerGas` = 115792089237316195423570985008687907853269984665640564039457584007913 gwei) cannot be * // @error: higher than the maximum allowed value (2^256-1). * ``` * * @param envelope - The transaction envelope to assert. */ function assert$3(envelope) { const { chainId, maxPriorityFeePerGas, maxFeePerGas, to } = envelope; if (chainId <= 0) throw new InvalidChainIdError({ chainId }); if (to) assert$4(to, { strict: false }); if (maxFeePerGas && BigInt(maxFeePerGas) > 2n ** 256n - 1n) throw new FeeCapTooHighError({ feeCap: maxFeePerGas }); if (maxPriorityFeePerGas && maxFeePerGas && maxPriorityFeePerGas > maxFeePerGas) throw new TipAboveFeeCapError({ maxFeePerGas, maxPriorityFeePerGas, }); } /** * Serializes a {@link ox#TransactionEnvelopeEip1559.TransactionEnvelopeEip1559}. * * @example * ```ts twoslash * import { TransactionEnvelopeEip1559, Value } from 'ox' * * const envelope = TransactionEnvelopeEip1559.from({ * chainId: 1, * maxFeePerGas: Value.fromGwei('10'), * maxPriorityFeePerGas: Value.fromGwei('1'), * to: '0x0000000000000000000000000000000000000000', * value: Value.fromEther('1'), * }) * * const serialized = TransactionEnvelopeEip1559.serialize(envelope) // [!code focus] * ``` * * @example * ### Attaching Signatures * * It is possible to attach a `signature` to the serialized Transaction Envelope. * * ```ts twoslash * import { Secp256k1, TransactionEnvelopeEip1559, Value } from 'ox' * * const envelope = TransactionEnvelopeEip1559.from({ * chainId: 1, * maxFeePerGas: Value.fromGwei('10'), * maxPriorityFeePerGas: Value.fromGwei('1'), * to: '0x0000000000000000000000000000000000000000', * value: Value.fromEther('1'), * }) * * const signature = Secp256k1.sign({ * payload: TransactionEnvelopeEip1559.getSignPayload(envelope), * privateKey: '0x...', * }) * * const serialized = TransactionEnvelopeEip1559.serialize(envelope, { // [!code focus] * signature, // [!code focus] * }) // [!code focus] * * // ... send `serialized` transaction to JSON-RPC `eth_sendRawTransaction` * ``` * * @param envelope - The Transaction Envelope to serialize. * @param options - Options. * @returns The serialized Transaction Envelope. */ function serialize$3(envelope, options = {}) { const { chainId, gas, nonce, to, value, maxFeePerGas, maxPriorityFeePerGas, accessList, data, input, } = envelope; assert$3(envelope); const accessTupleList = toTupleList(accessList); const signature = extract(options.signature || envelope); const serialized = [ fromNumber(chainId), nonce ? fromNumber(nonce) : '0x', maxPriorityFeePerGas ? fromNumber(maxPriorityFeePerGas) : '0x', maxFeePerGas ? fromNumber(maxFeePerGas) : '0x', gas ? fromNumber(gas) : '0x', to ?? '0x', value ? fromNumber(value) : '0x', data ?? input ?? '0x', accessTupleList, ...(signature ? toTuple$1(signature) : []), ]; return concat(serializedType$1, fromHex(serialized)); }/** * Asserts a {@link ox#TransactionEnvelopeEip2930.TransactionEnvelopeEip2930} is valid. * * @example * ```ts twoslash * import { TransactionEnvelopeEip2930, Value } from 'ox' * * TransactionEnvelopeEip2930.assert({ * gasPrice: 2n ** 256n - 1n + 1n, * chainId: 1, * to: '0x0000000000000000000000000000000000000000', * value: Value.fromEther('1'), * }) * // @error: GasPriceTooHighError: * // @error: The gas price (`gasPrice` = 115792089237316195423570985008687907853269984665640564039457584007913 gwei) cannot be * // @error: higher than the maximum allowed value (2^256-1). * ``` * * @param envelope - The transaction envelope to assert. */ function assert$2(envelope) { const { chainId, gasPrice, to } = envelope; if (chainId <= 0) throw new InvalidChainIdError({ chainId }); if (to) assert$4(to, { strict: false }); if (gasPrice && BigInt(gasPrice) > 2n ** 256n - 1n) throw new GasPriceTooHighError({ gasPrice }); } /** * Serializes a {@link ox#TransactionEnvelopeEip2930.TransactionEnvelopeEip2930}. * * @example * ```ts twoslash * import { TransactionEnvelopeEip2930, Value } from 'ox' * * const envelope = TransactionEnvelopeEip2930.from({ * chainId: 1, * gasPrice: Value.fromGwei('10'), * to: '0x0000000000000000000000000000000000000000', * value: Value.fromEther('1'), * }) * * const serialized = TransactionEnvelopeEip2930.serialize(envelope) // [!code focus] * ``` * * @example * ### Attaching Signatures * * It is possible to attach a `signature` to the serialized Transaction Envelope. * * ```ts twoslash * import { Secp256k1, TransactionEnvelopeEip2930, Value } from 'ox' * * const envelope = TransactionEnvelopeEip2930.from({ * chainId: 1, * gasPrice: Value.fromGwei('10'), * to: '0x0000000000000000000000000000000000000000', * value: Value.fromEther('1'), * }) * * const signature = Secp256k1.sign({ * payload: TransactionEnvelopeEip2930.getSignPayload(envelope), * privateKey: '0x...', * }) * * const serialized = TransactionEnvelopeEip2930.serialize(envelope, { // [!code focus] * signature, // [!code focus] * }) // [!code focus] * * // ... send `serialized` transaction to JSON-RPC `eth_sendRawTransaction` * ``` * * @param envelope - The Transaction Envelope to serialize. * @param options - Options. * @returns The serialized Transaction Envelope. */ function serialize$2(envelope, options = {}) { const { chainId, gas, data, input, nonce, to, value, accessList, gasPrice } = envelope; assert$2(envelope); const accessTupleList = toTupleList(accessList); const signature = extract(options.signature || envelope); const serialized = [ fromNumber(chainId), nonce ? fromNumber(nonce) : '0x', gasPrice ? fromNumber(gasPrice) : '0x', gas ? fromNumber(gas) : '0x', to ?? '0x', value ? fromNumber(value) : '0x', data ?? input ?? '0x', accessTupleList, ...(signature ? toTuple$1(signature) : []), ]; return concat('0x01', fromHex(serialized)); }const serializedType = '0x04'; /** * Asserts a {@link ox#TransactionEnvelopeEip7702.TransactionEnvelopeEip7702} is valid. * * @example * ```ts twoslash * import { TransactionEnvelopeEip7702, Value } from 'ox' * * TransactionEnvelopeEip7702.assert({ * authorizationList: [], * maxFeePerGas: 2n ** 256n - 1n + 1n, * chainId: 1, * to: '0x0000000000000000000000000000000000000000', * value: Value.fromEther('1'), * }) * // @error: FeeCapTooHighError: * // @error: The fee cap (`masFeePerGas` = 115792089237316195423570985008687907853269984665640564039457584007913 gwei) cannot be * // @error: higher than the maximum allowed value (2^256-1). * ``` * * @param envelope - The transaction envelope to assert. */ function assert$1(envelope) { const { authorizationList } = envelope; if (authorizationList) { for (const authorization of authorizationList) { const { address, chainId } = authorization; if (address) assert$4(address, { strict: false }); if (Number(chainId) < 0) throw new InvalidChainIdError({ chainId }); } } assert$3(envelope); } /** * Serializes a {@link ox#TransactionEnvelopeEip7702.TransactionEnvelopeEip7702}. * * @example * ```ts twoslash * // @noErrors * import { Authorization, Secp256k1, TransactionEnvelopeEip7702, Value } from 'ox' * * const authorization = Authorization.from({ * address: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', * chainId: 1, * nonce: 0n, * }) * * const signature = Secp256k1.sign({ * payload: Authorization.getSignPayload(authorization), * privateKey: '0x...', * }) * * const authorizationList = [Authorization.from(authorization, { signature })] * * const envelope = TransactionEnvelopeEip7702.from({ * authorizationList, * chainId: 1, * maxFeePerGas: Value.fromGwei('10'), * to: '0x0000000000000000000000000000000000000000', * value: Value.fromEther('1'), * }) * * const serialized = TransactionEnvelopeEip7702.serialize(envelope) // [!code focus] * ``` * * @example * ### Attaching Signatures * * It is possible to attach a `signature` to the serialized Transaction Envelope. * * ```ts twoslash * // @noErrors * import { Secp256k1, TransactionEnvelopeEip7702, Value } from 'ox' * * const envelope = TransactionEnvelopeEip7702.from({ * authorizationList: [...], * chainId: 1, * maxFeePerGas: Value.fromGwei('10'), * to: '0x0000000000000000000000000000000000000000', * value: Value.fromEther('1'), * }) * * const signature = Secp256k1.sign({ * payload: TransactionEnvelopeEip7702.getSignPayload(envelope), * privateKey: '0x...', * }) * * const serialized = TransactionEnvelopeEip7702.serialize(envelope, { // [!code focus] * signature, // [!code focus] * }) // [!code focus] * * // ... send `serialized` transaction to JSON-RPC `eth_sendRawTransaction` * ``` * * @param envelope - The Transaction Envelope to serialize. * @param options - Options. * @returns The serialized Transaction Envelope. */ function serialize$1(envelope, options = {}) { const { authorizationList, chainId, gas, nonce, to, value, maxFeePerGas, maxPriorityFeePerGas, accessList, data, input, } = envelope; assert$1(envelope); const accessTupleList = toTupleList(accessList); const authorizationTupleList = toTupleList$1(authorizationList); const signature = extract(options.signature || envelope); const serialized = [ fromNumber(chainId), nonce ? fromNumber(nonce) : '0x', maxPriorityFeePerGas ? fromNumber(maxPriorityFeePerGas) : '0x', maxFeePerGas ? fromNumber(maxFeePerGas) : '0x', gas ? fromNumber(gas) : '0x', to ?? '0x', value ? fromNumber(value) : '0x', data ?? input ?? '0x', accessTupleList, authorizationTupleList, ...(signature ? toTuple$1(signature) : []), ]; return concat(serializedType, fromHex(serialized)); }/** * Asserts a {@link ox#TransactionEnvelopeLegacy.TransactionEnvelopeLegacy} is valid. * * @example * ```ts twoslash * import { TransactionEnvelopeLegacy, Value } from 'ox' * * TransactionEnvelopeLegacy.assert({ * gasPrice: 2n ** 256n - 1n + 1n, * chainId: 1, * to: '0x0000000000000000000000000000000000000000', * value: Value.fromEther('1'), * }) * // @error: GasPriceTooHighError: * // @error: The gas price (`gasPrice` = 115792089237316195423570985008687907853269984665640564039457584007913 gwei) cannot be * // @error: higher than the maximum allowed value (2^256-1). * ``` * * @param envelope - The transaction envelope to assert. */ function assert(envelope) { const { chainId, gasPrice, to } = envelope; if (to) assert$4(to, { strict: false }); if (typeof chainId !== 'undefined' && chainId <= 0) throw new InvalidChainIdError({ chainId }); if (gasPrice && BigInt(gasPrice) > 2n ** 256n - 1n) throw new GasPriceTooHighError({ gasPrice }); } /** * Serializes a {@link ox#TransactionEnvelopeLegacy.TransactionEnvelopeLegacy}. * * @example * ```ts twoslash * // @noErrors * import { TransactionEnvelopeLegacy } from 'ox' * * const envelope = TransactionEnvelopeLegacy.from({ * chainId: 1, * gasPrice: Value.fromGwei('10'), * to: '0x0000000000000000000000000000000000000000', * value: Value.fromEther('1'), * }) * * const serialized = TransactionEnvelopeLegacy.serialize(envelope) // [!code focus] * ``` * * @example * ### Attaching Signatures * * It is possible to attach a `signature` to the serialized Transaction Envelope. * * ```ts twoslash * // @noErrors * import { Secp256k1, TransactionEnvelopeLegacy, Value } from 'ox' * * const envelope = TransactionEnvelopeLegacy.from({ * chainId: 1, * gasPrice: Value.fromGwei('10'), * to: '0x0000000000000000000000000000000000000000', * value: Value.fromEther('1'), * }) * * const signature = Secp256k1.sign({ * payload: TransactionEnvelopeLegacy.getSignPayload(envelope), * privateKey: '0x...', * }) * * const serialized = TransactionEnvelopeLegacy.serialize(envelope, { // [!code focus] * signature, // [!code focus] * }) // [!code focus] * * // ... send `serialized` transaction to JSON-RPC `eth_sendRawTransaction` * ``` * * @param envelope - The Transaction Envelope to serialize. * @param options - Options. * @returns The serialized Transaction Envelope. */ function serialize(envelope, options = {}) { const { chainId = 0, gas, data, input, nonce, to, value, gasPrice } = envelope; assert(envelope); let serialized = [ nonce ? fromNumber(nonce) : '0x', gasPrice ? fromNumber(gasPrice) : '0x', gas ? fromNumber(gas) : '0x', to ?? '0x', value ? fromNumber(value) : '0x', data ?? input ?? '0x', ]; const signature = (() => { if (options.signature) return { r: options.signature.r, s: options.signature.s, v: yParityToV(options.signature.yParity), }; if (typeof envelope.r === 'undefined' || typeof envelope.s === 'undefined') return undefined; return { r: envelope.r, s: envelope.s, v: envelope.v, }; })(); if (signature) { const v = (() => { // EIP-155 (inferred chainId) if (signature.v >= 35) { const inferredChainId = Math.floor((signature.v - 35) / 2); if (inferredChainId > 0) return signature.v; return 27 + (signature.v === 35 ? 0 : 1); } // EIP-155 (explicit chainId) if (chainId > 0) return chainId * 2 + 35 + signature.v - 27; // Pre-EIP-155 (no chainId) const v = 27 + (signature.v === 27 ? 0 : 1); if (signature.v !== v) throw new InvalidVError({ value: signature.v }); return v; })(); serialized = [ ...serialized, fromNumber(v), signature.r === 0n ? '0x' : trimLeft(fromNumber(signature.r)), signature.s === 0n ? '0x' : trimLeft(fromNumber(signature.s)), ]; } else if (chainId > 0) serialized = [...serialized, fromNumber(chainId), '0x', '0x']; return fromHex(serialized); }/** * Serializes a legacy, EIP-1559, EIP-2930, EIP-4844, or EIP-7702 transaction object. * * @param options - The serialization options. * @param options.transaction - The transaction object to be serialized. * @param [options.signature] - The signature to include with the transaction, if necessary. * @returns The serialized transaction. * @throws An error if the provided transaction object is invalid. * @transaction * @example * ```ts * import { serializeTransaction } from "thirdweb"; * * const serializedTransaction = serializeTransaction({ transaction: { * to: "0x", * value: 0n, * } * }); * ``` */ function serializeTransaction(options) { const { transaction } = options; const type = getTransactionEnvelopeType(transaction); // This is to maintain compatibility with our old interface (including the signature in the transaction object) const signature = (() => { if (options.signature) { if ("v" in options.signature && typeof options.signature.v !== "undefined") { return fromLegacy({ r: toBigInt(options.signature.r), s: toBigInt(options.signature.s), v: Number(options.signature.v), }); } return { r: toBigInt(options.signature.r), s: toBigInt(options.signature.s), // We force the Signature type here because we filter for legacy type above yParity: options.signature .yParity, }; } if (typeof transaction.v === "undefined" && typeof transaction.yParity === "undefined") { return undefined; } if (transaction.r === undefined || transaction.s === undefined) { throw new Error("Invalid signature provided with transaction"); } return { r: typeof transaction.r === "bigint" ? transaction.r : toBigInt(transaction.r), s: typeof transaction.s === "bigint" ? transaction.s : toBigInt(transaction.s), yParity: typeof transaction.v !== "undefined" && typeof transaction.yParity === "undefined" ? vToYParity(Number(transaction.v)) : Number(transaction.yParity), }; })(); if (type === "eip1559") { const typedTransaction = transaction; assert$3(typedTransaction); return serialize$3(typedTransaction, { signature, }); } if (type === "legacy") { const typedTransaction = transaction; assert(typedTransaction); return serialize(typedTransaction, { signature, }); } if (type === "eip2930") { const typedTransaction = transaction; assert$2(typedTransaction); return serialize$2(typedTransaction, { signature, }); } if (type === "eip7702") { const typedTransaction = transaction; assert$1(typedTransaction); return serialize$1(typedTransaction, { signature, }); } throw new Error("Invalid transaction type"); } /** * @internal */ function getTransactionEnvelopeType(transactionEnvelope) { if (typeof transactionEnvelope.type !== "undefined") { return transactionEnvelope.type; } if (typeof transactionEnvelope.authorizationList !== "undefined") { return "eip7702"; } if (typeof transactionEnvelope.maxFeePerGas !== "undefined" || typeof transactionEnvelope.maxPriorityFeePerGas !== "undefined") { return "eip1559"; } if (typeof transactionEnvelope.gasPrice !== "undefined") { if (typeof transactionEnvelope.accessList !== "undefined") { return "eip2930"; } return "legacy"; } throw new Error("Invalid transaction type"); }const OPStackGasPriceOracleAddress = "0x420000000000000000000000000000000000000F"; /** * @internal */ async function estimateL1Fee(options) { const { transaction, gasPriceOracleAddress } = options; const oracleContract = getContract({ client: transaction.client, address: gasPriceOracleAddress || OPStackGasPriceOracleAddress, chain: transaction.chain, }); // purposefully remove gasPrice from the transaction const { gasPrice, ...serializableTx } = await toSerializableTransaction({ transaction, }); const serialized = serializeTransaction({ transaction: serializableTx, }); //serializeTransaction(transaction); return readContract({ contract: oracleContract, method: "function getL1Fee(bytes memory _data) view returns (uint256)", params: [serialized], }); }export{estimateL1Fee};//# sourceMappingURL=estimate-l1-fee-TT1HWvx5.js.map