@0xfutbol/id
Version:
React component library with shared providers for 0xFutbol ID
1,214 lines (1,213 loc) • 41 kB
JavaScript
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