diff --git a/src/types.ts b/src/types.ts index 6c77a64..e05955a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,7 +1,8 @@ import { + assert, assertArgument, BigNumberish, - BytesLike, + BytesLike, defineProperties, ethers, Signature as EthersSignature, TransactionRequest as EthersTransactionRequest, @@ -136,14 +137,16 @@ export interface MessageProof { */ export class TransactionResponse extends ethers.TransactionResponse { /** The batch number on the L1 network. */ - readonly l1BatchNumber: null | number; + readonly l1BatchNumber!: null | number; /** The transaction index within the batch on the L1 network. */ - readonly l1BatchTxIndex: null | number; + readonly l1BatchTxIndex!: null | number; constructor(params: any, provider: ethers.Provider) { super(params, provider); - this.l1BatchNumber = params.l1BatchNumber; - this.l1BatchTxIndex = params.l1BatchTxIndex; + defineProperties(this, { + l1BatchNumber: params.l1BatchNumber, + l1BatchTxIndex: params.l1BatchTxIndex + }); } /** @@ -167,7 +170,7 @@ export class TransactionResponse extends ethers.TransactionResponse { } override async getTransaction(): Promise { - return (await super.getTransaction()) as TransactionResponse; + return await super.getTransaction() as TransactionResponse; } override replaceableTransaction(startBlock: number): TransactionResponse { @@ -178,7 +181,7 @@ export class TransactionResponse extends ethers.TransactionResponse { } override async getBlock(): Promise { - return (await super.getBlock()) as Block; + return await super.getBlock() as Block; } /** Waits for transaction to be finalized. */ @@ -216,20 +219,23 @@ export class TransactionResponse extends ethers.TransactionResponse { */ export class TransactionReceipt extends ethers.TransactionReceipt { /** The batch number on the L1 network. */ - readonly l1BatchNumber: null | number; + readonly l1BatchNumber!: null | number; /** The transaction index within the batch on the L1 network. */ - readonly l1BatchTxIndex: null | number; + readonly l1BatchTxIndex!: null | number; /** The logs of L2 to L1 messages. */ - readonly l2ToL1Logs: L2ToL1Log[]; + readonly l2ToL1Logs!: L2ToL1Log[]; /** All logs included in the transaction receipt. */ - readonly _logs: ReadonlyArray; + readonly #logs: ReadonlyArray; constructor(params: any, provider: ethers.Provider) { super(params, provider); - this.l1BatchNumber = params.l1BatchNumber; - this.l1BatchTxIndex = params.l1BatchTxIndex; - this.l2ToL1Logs = params.l2ToL1Logs; - this._logs = Object.freeze( + defineProperties(this, { + l1BatchNumber: params.l1BatchNumber, + l1BatchTxIndex: params.l1BatchTxIndex, + l2ToL1Logs: params.l2ToL1Logs, + }); + + this.#logs = Object.freeze( params.logs.map((log: Log) => { return new Log(log, provider); }) @@ -237,7 +243,7 @@ export class TransactionReceipt extends ethers.TransactionReceipt { } override get logs(): ReadonlyArray { - return this._logs; + return this.#logs; } override getBlock(): Promise { @@ -262,33 +268,78 @@ export class TransactionReceipt extends ethers.TransactionReceipt { /** A `Block` is an extension of {@link ethers.Block} with additional features for interacting with zkSync Era. */ export class Block extends ethers.Block { /** The batch number on L1. */ - readonly l1BatchNumber: null | number; + readonly l1BatchNumber!: null | number; /** The timestamp of the batch on L1. */ - readonly l1BatchTimestamp: null | number; + readonly l1BatchTimestamp!: null | number; + + readonly #transactions: Array; constructor(params: any, provider: ethers.Provider) { super(params, provider); - this.l1BatchNumber = params.l1BatchNumber; - this.l1BatchTimestamp = params.l1BatchTxIndex; + this.#transactions = params.transactions.map((tx: TransactionResponse | string) => { + if (typeof(tx) !== "string") { + return new TransactionResponse(tx, provider); + } + return tx; + }); + defineProperties(this, { + l1BatchNumber: params.l1BatchNumber, + l1BatchTimestamp: params.l1BatchTimestamp + }); } override toJSON(): any { - const {l1BatchNumber, l1BatchTimestamp: l1BatchTxIndex} = this; + const {l1BatchNumber, l1BatchTimestamp} = this; return { ...super.toJSON(), l1BatchNumber, - l1BatchTxIndex, + l1BatchTimestamp, }; } override get prefetchedTransactions(): TransactionResponse[] { - return super.prefetchedTransactions as TransactionResponse[]; + const txs = this.#transactions.slice(); + + // Doesn't matter... + if (txs.length === 0) { return [ ]; } + + // Make sure we prefetched the transactions + assert(typeof(txs[0]) === "object", "transactions were not prefetched with block request", "UNSUPPORTED_OPERATION", { + operation: "transactionResponses()" + }); + + return txs as TransactionResponse[]; } - override getTransaction( + override async getTransaction( indexOrHash: number | string ): Promise { - return super.getTransaction(indexOrHash) as Promise; + // Find the internal value by its index or hash + let tx: string | TransactionResponse | undefined = undefined; + if (typeof(indexOrHash) === "number") { + tx = this.#transactions[indexOrHash]; + + } else { + const hash = indexOrHash.toLowerCase(); + for (const v of this.#transactions) { + if (typeof(v) === "string") { + if (v !== hash) { continue; } + tx = v; + break; + } else { + if (v.hash === hash) { continue; } + tx = v; + break; + } + } + } + if (tx == null) { throw new Error("no such tx"); } + + if (typeof(tx) === "string") { + return (await this.provider.getTransaction(tx)); + } else { + return tx; + } } } @@ -317,15 +368,15 @@ export class Log extends ethers.Log { } override async getBlock(): Promise { - return (await super.getBlock()) as Block; + return await super.getBlock() as Block; } override async getTransaction(): Promise { - return (await super.getTransaction()) as TransactionResponse; + return await super.getTransaction() as TransactionResponse; } override async getTransactionReceipt(): Promise { - return (await super.getTransactionReceipt()) as TransactionReceipt; + return await super.getTransactionReceipt() as TransactionReceipt; } }