Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Allow strings and bigints instead of numbers in decoder input fields #6131

Merged
merged 3 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/decoder/lib/decoders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,8 @@ export class ProjectDecoder {
overrideContext?: Contexts.Context,
isForSelectorBasedDecoding?: boolean
): Promise<CalldataDecoding> {
const block = transaction.blockNumber;
const block =
transaction.blockNumber !== null ? Number(transaction.blockNumber) : null;
const blockNumber = await this.regularizeBlock(block);
const isConstructor = transaction.to === null;
const context =
Expand Down Expand Up @@ -615,7 +616,7 @@ export class ProjectDecoder {
options: DecoderTypes.EventOptions = {},
additionalContexts: Contexts.Contexts = {}
): Promise<LogDecoding[]> {
const block = log.blockNumber;
const block = log.blockNumber !== null ? Number(log.blockNumber) : null;
const blockNumber = await this.regularizeBlock(block);
const data = Conversion.toBytes(log.data);
const topics = log.topics.map(Conversion.toBytes);
Expand Down
39 changes: 28 additions & 11 deletions packages/decoder/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,28 @@ export interface ContractState {

/**
* This type represents a web3 Log object that has been decoded.
* Note that it extends the Log type and just adds an additional field
* with the decoding.
* Note that it extends the Log type. The differences are:
*
* 1. It adds an additional field with the decodings;
* 2. Some fields that in Log are allowed to be strings,
* here are specified as numbers. (Because this type is
* for output and that type is for input.)
* @category Results
*/
export interface DecodedLog extends Log {
/**
* Index of the log within the block.
*/
logIndex?: number;
/**
* Index within the block of the emitting transaction; null if
* block is pending.
*/
transactionIndex?: number | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these optional fields need explanation on why they might be undefined. Probably warrants a note in the DecodedLog docstring, to say that @truffle/decoder re-emits everything given, and unspecified optional input fields will thus not appear in output

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, that's not how this works! Which raises a good point: These fields shouldn't be optional. I guess I should just not make this an extension of Log, huh? Because it doesn't save me any work if everything is mandatory. :-/

To explain: If you use decodeLog, passing in your own logs, you just get back the decodings, you don't get DecodedLog. You only get DecodedLog if you call events(), to which one does not pass in their own logs. So actually these fields will always be present in this type.

...so do you agree that's what I should do?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this emit the same info in both situations? It's weird that passing in a Log will remove fields, while events() will return everything log-related

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What? Passing in a Log doesn't remove fields. What I'm saying is that decodeLog doesn't use the DecodedLog type at all. It returns the decodings, they're not inside a DecodedLog container. Only events uses that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh, sorry to misunderstand. Yeah, let's not extend Log

/**
* The block number. Null if pending.
*/
blockNumber: number | null;
/**
* An array of possible decodings of the given log -- it's an array because logs can be ambiguous.
*
Expand Down Expand Up @@ -247,7 +264,7 @@ export interface ReturnOptions {
*
* Intended to work like Web3's
* [Transaction](https://web3js.readthedocs.io/en/v1.2.1/web3-eth.html#eth-gettransaction-return)
* type.
* type, but with strings allowed where it requires numbers.
* @category Inputs
*/
export interface Transaction {
Expand All @@ -258,19 +275,19 @@ export interface Transaction {
/**
* The nonce of the sender before this transaction was sent.
*/
nonce?: number;
nonce?: number | string | bigint;
/**
* Hash of this transaction's block as hex string; null if pending.
*/
blockHash?: string | null;
/**
* This transaction's block number; null if pending.
*/
blockNumber: number | null;
blockNumber: number | string | bigint | null;
/**
* Index of transaction in block; null if block is pending.
*/
transactionIndex?: number | null;
transactionIndex?: number | string | bigint | null;
/**
* Address of the sender (as checksummed hex string).
*/
Expand Down Expand Up @@ -299,7 +316,7 @@ export interface Transaction {
/**
* A positive unsigned 8-bit number between 0 and 0x7f that represents the type of the transaction.
*/
type?: number;
type?: number | string | bigint;
/**
* The maximum fee per gas that the transaction is willing to pay in total.
*/
Expand All @@ -317,7 +334,7 @@ export interface Transaction {
*
* Intended to work like Web3's
* [Log](https://web3js.readthedocs.io/en/v1.2.1/web3-eth.html#eth-getpastlogs-return)
* type.
* type, but with strings allowed where it requires numbers.
* @category Inputs
*/
export interface Log {
Expand All @@ -336,12 +353,12 @@ export interface Log {
/**
* Index of the log within the block.
*/
logIndex?: number;
logIndex?: number | string | bigint;
/**
* Index within the block of the emitting transaction; null if
* block is pending.
*/
transactionIndex?: number | null;
transactionIndex?: number | string | bigint | null;
/**
* The emitting transaction's hash (as hex string).
*/
Expand All @@ -353,7 +370,7 @@ export interface Log {
/**
* The block number. Null if pending.
*/
blockNumber: number | null;
blockNumber: number | string | bigint | null;
}

//HACK
Expand Down
3 changes: 2 additions & 1 deletion packages/decoder/test/current/test/compatible-nativize.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ describe("nativize (ethers format)", function () {
});
const logs = receipt.logs;
assert.lengthOf(logs, 1);
const log = logs[0];
let log = logs[0];
log.blockNumber = String(log.blockNumber); //while we're here, let's test the ability to take strings :P
const decodings = await decoder.decodeLog(log);
assert.lengthOf(decodings, 1);
const decoding = decodings[0];
Expand Down
14 changes: 14 additions & 0 deletions packages/decoder/test/current/test/wire-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,20 @@ describe("Over-the-wire decoding", function () {
defaultConstructorHash
);

for (let tx of [
constructorTx,
emitStuffTx,
moreStuffTx,
globalTestTx,
inheritedTx,
getterTx1,
getterTx2,
defaultConstructorTx
]) {
//while we're here, let's test string input to the decoder
tx.blockNumber = String(tx.blockNumber);
}

let constructorDecoding = await decoder.decodeTransaction(constructorTx);
let emitStuffDecoding = await decoder.decodeTransaction(emitStuffTx);
let moreStuffDecoding = await decoder.decodeTransaction(moreStuffTx);
Expand Down