Skip to content

Commit 7725f13

Browse files
Adds new types of transactions (#1679)
* Adds new types of transactions Signed-off-by: Konstantina Blazhukova <[email protected]> * Removes redundancy Signed-off-by: Konstantina Blazhukova <[email protected]> * Adds tests for new types of transactions Signed-off-by: Konstantina Blazhukova <[email protected]> --------- Signed-off-by: Konstantina Blazhukova <[email protected]>
1 parent 5c4a70a commit 7725f13

File tree

4 files changed

+193
-23
lines changed

4 files changed

+193
-23
lines changed

packages/relay/src/formatters.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
import constants from "./lib/constants";
2222
import crypto from "crypto";
23-
import { Transaction } from './lib/model';
23+
import { Transaction, Transaction1559, Transaction2930 } from './lib/model';
2424
import { BigNumber } from '@hashgraph/sdk/lib/Transfer';
2525
import { BigNumber as BN } from "bignumber.js";
2626

@@ -32,7 +32,7 @@ const hashNumber = (num) => {
3232

3333
const generateRandomHex = (bytesLength = 16) => {
3434
return "0x" + crypto.randomBytes(bytesLength).toString('hex');
35-
}
35+
};
3636

3737
/**
3838
* Format message prefix for logger.
@@ -73,11 +73,11 @@ const formatTransactionId = (transactionId: string): string | null => {
7373
return null;
7474
}
7575

76-
var transactionSplit = transactionId.split("@");
76+
const transactionSplit = transactionId.split("@");
7777
const payer = transactionSplit[0];
7878
const timestamp = transactionSplit[1].replace(".","-");
7979
return `${payer}-${timestamp}`;
80-
}
80+
};
8181

8282
/**
8383
* Retrieve formated transactionID without query params
@@ -137,8 +137,7 @@ const formatContractResult = (cr: any) => {
137137
return null;
138138
}
139139

140-
return new Transaction({
141-
accessList: undefined,
140+
const commonFields = {
142141
blockHash: toHash32(cr.block_hash),
143142
blockNumber: nullableNumberTo0x(cr.block_number),
144143
chainId: cr.chain_id,
@@ -147,18 +146,31 @@ const formatContractResult = (cr: any) => {
147146
gasPrice: toNullIfEmptyHex(cr.gas_price),
148147
hash: cr.hash.substring(0, 66),
149148
input: cr.function_parameters,
150-
maxPriorityFeePerGas: toNullIfEmptyHex(cr.max_priority_fee_per_gas),
151-
maxFeePerGas: toNullIfEmptyHex(cr.max_fee_per_gas),
152149
nonce: nanOrNumberTo0x(cr.nonce),
153150
r: cr.r === null ? null : cr.r.substring(0, 66),
154151
s: cr.s === null ? null : cr.s.substring(0, 66),
155152
to: cr.to?.substring(0, 42),
156153
transactionIndex: nullableNumberTo0x(cr.transaction_index),
157154
type: nullableNumberTo0x(cr.type),
158155
v: nanOrNumberTo0x(cr.v),
159-
value: nanOrNumberTo0x(cr.amount)
160-
});
161-
}
156+
value: nanOrNumberTo0x(cr.amount),
157+
};
158+
159+
switch (cr.type) {
160+
case 0: return new Transaction(commonFields); // eip 155 fields
161+
case 1: return new Transaction2930({
162+
...commonFields,
163+
accessList: []
164+
}); // eip 2930 fields
165+
case 2: return new Transaction1559({
166+
...commonFields,
167+
maxPriorityFeePerGas: toNullIfEmptyHex(cr.max_priority_fee_per_gas),
168+
maxFeePerGas: toNullIfEmptyHex(cr.max_fee_per_gas)
169+
}); // eip 1559 fields
170+
case null: return new Transaction(commonFields); //hapi
171+
}
172+
return null;
173+
};
162174

163175
const prepend0x = (input: string): string => {
164176
return input.startsWith(EMPTY_HEX) ? input : EMPTY_HEX + input;

packages/relay/src/lib/model.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ export class Receipt {
120120
}
121121

122122
export class Transaction {
123-
public readonly accessList!: AccessListEntry[] | null;
124123
public readonly blockHash!: string | null;
125124
public readonly blockNumber!: string | null;
126125
public readonly chainId!: string;
@@ -129,8 +128,6 @@ export class Transaction {
129128
public readonly gasPrice!: string;
130129
public readonly hash!: string;
131130
public readonly input!: string;
132-
public readonly maxPriorityFeePerGas!: string;
133-
public readonly maxFeePerGas!: string;
134131
public readonly nonce!: string;
135132
public readonly r!: string;
136133
public readonly s!: string;
@@ -141,7 +138,6 @@ export class Transaction {
141138
public readonly value!: string;
142139

143140
constructor(args: any) {
144-
this.accessList = args.accessList;
145141
this.blockHash = args.blockHash;
146142
this.blockNumber = args.blockNumber;
147143
this.chainId = args.chainId;
@@ -150,8 +146,6 @@ export class Transaction {
150146
this.gasPrice = args.gasPrice;
151147
this.hash = args.hash;
152148
this.input = args.input;
153-
this.maxPriorityFeePerGas = args.maxPriorityFeePerGas;
154-
this.maxFeePerGas = args.maxFeePerGas;
155149
this.nonce = args.nonce;
156150
this.r = args.r;
157151
this.s = args.s;
@@ -163,6 +157,26 @@ export class Transaction {
163157
}
164158
}
165159

160+
export class Transaction2930 extends Transaction {
161+
public readonly accessList!: AccessListEntry[] | null | [];
162+
163+
constructor(args: any) {
164+
super(args);
165+
this.accessList = args.accessList;
166+
}
167+
}
168+
169+
export class Transaction1559 extends Transaction2930 {
170+
public readonly maxPriorityFeePerGas!: string;
171+
public readonly maxFeePerGas!: string;
172+
173+
constructor(args: any) {
174+
super(args);
175+
this.maxPriorityFeePerGas = args.maxPriorityFeePerGas;
176+
this.maxFeePerGas = args.maxFeePerGas;
177+
}
178+
}
179+
166180
export declare class AccessListEntry {
167181
readonly address: string;
168182
readonly storageKeys: string[];

packages/relay/tests/lib/eth.spec.ts

Lines changed: 150 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ import {
5656
} from '../helpers';
5757

5858
import pino from 'pino';
59-
import { Log, Transaction } from '../../src/lib/model';
59+
import { Log, Transaction, Transaction1559, Transaction2930 } from '../../src/lib/model';
6060
import constants from '../../src/lib/constants';
6161
import { SDKClient } from '../../src/lib/clients';
6262
import { SDKClientError } from '../../src/lib/errors/SDKClientError';
@@ -282,6 +282,39 @@ describe('Eth calls using MirrorNode', async function () {
282282
}
283283
};
284284

285+
const contractResultMock = {
286+
address: '0x67d8d32e9bf1a9968a5ff53b87d777aa8ebbee69',
287+
amount: 20,
288+
bloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
289+
call_result: '0x',
290+
contract_id: '0.0.1012',
291+
created_contract_ids: [],
292+
error_message: null,
293+
from: '0x00000000000000000000000000000000000003f7',
294+
function_parameters: '0x',
295+
gas_limit: 250000,
296+
gas_used: 200000,
297+
timestamp: '1692959189.214316721',
298+
to: '0x00000000000000000000000000000000000003f4',
299+
hash: '0x7e8a09541c80ccda1f5f40a1975e031ed46de5ad7f24cd4c37be9bac65149b9e',
300+
block_hash: '0xa414a76539f84ae1c797fa10d00e49d5e7a1adae556dcd43084551e671623d2eba825bcb7bbfd5b7e3fe59d63d8a167f',
301+
block_number: 61033,
302+
logs: [],
303+
result: 'SUCCESS',
304+
transaction_index: 2,
305+
state_changes: [],
306+
status: '0x1',
307+
failed_initcode: null,
308+
block_gas_used: 200000,
309+
chain_id: '0x12a',
310+
gas_price: '0x',
311+
r: '0x85b423416d0164d0b2464d880bccb0679587c00673af8e016c8f0ce573be69b2',
312+
s: '0x3897a5ce2ace1f242d9c989cd9c163d79760af4266f3bf2e69ee288bcffb211a',
313+
type: 2,
314+
v: 1,
315+
nonce: 9
316+
};
317+
285318
const defaultLogTopics = [
286319
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
287320
"0x0000000000000000000000000000000000000000000000000000000000000000",
@@ -1293,6 +1326,46 @@ describe('Eth calls using MirrorNode', async function () {
12931326
expect(result).to.equal(null);
12941327
});
12951328

1329+
it('eth_getTransactionByBlockHashAndIndex returns 155 transaction for type 0', async function () {
1330+
restMock.onGet(`contracts/results?block.hash=${defaultBlock.hash}&transaction.index=${defaultBlock.count}&limit=100&order=asc`).reply(200, {
1331+
'results' : [{
1332+
...contractResultMock,
1333+
type: 0
1334+
}]
1335+
});
1336+
1337+
const result = await ethImpl.getTransactionByBlockHashAndIndex(defaultBlock.hash.toString(), numberTo0x(defaultBlock.count));
1338+
expect(result).to.be.an.instanceOf(Transaction);
1339+
});
1340+
1341+
it('eth_getTransactionByBlockHashAndIndex returns 2930 transaction for type 1', async function () {
1342+
restMock.onGet(`contracts/results?block.hash=${defaultBlock.hash}&transaction.index=${defaultBlock.count}&limit=100&order=asc`).reply(200, {
1343+
'results' : [{
1344+
...contractResultMock,
1345+
type: 1,
1346+
access_list: []
1347+
}]
1348+
});
1349+
1350+
const result = await ethImpl.getTransactionByBlockHashAndIndex(defaultBlock.hash.toString(), numberTo0x(defaultBlock.count));
1351+
expect(result).to.be.an.instanceOf(Transaction2930);
1352+
});
1353+
1354+
it('eth_getTransactionByBlockHashAndIndex returns 1559 transaction for type 2', async function () {
1355+
restMock.onGet(`contracts/results?block.hash=${defaultBlock.hash}&transaction.index=${defaultBlock.count}&limit=100&order=asc`).reply(200, {
1356+
'results' : [{
1357+
...contractResultMock,
1358+
type: 2,
1359+
access_list: [],
1360+
max_fee_per_gas: '0x47',
1361+
max_priority_fee_per_gas: '0x47'
1362+
}]
1363+
});
1364+
1365+
const result = await ethImpl.getTransactionByBlockHashAndIndex(defaultBlock.hash.toString(), numberTo0x(defaultBlock.count));
1366+
expect(result).to.be.an.instanceOf(Transaction1559);
1367+
});
1368+
12961369
describe('Block transaction count', async function () {
12971370
let currentMaxBlockRange: number;
12981371

@@ -4936,15 +5009,89 @@ describe('Eth', async function () {
49365009
});
49375010

49385011
describe('eth_getTransactionByHash', async function () {
4939-
const uniqueTxHash = '0x27cad7b827375d12d73af57b6a3e84353645fd31305ea58ff52dda53ec640533';
5012+
const from = '0x00000000000000000000000000000000000003f7';
5013+
const evm_address = '0xc37f417fa09933335240fca72dd257bfbde9c275';
5014+
const contractResultMock = {
5015+
address: '0x67d8d32e9bf1a9968a5ff53b87d777aa8ebbee69',
5016+
amount: 20,
5017+
bloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
5018+
call_result: '0x',
5019+
contract_id: '0.0.1012',
5020+
created_contract_ids: [],
5021+
error_message: null,
5022+
from: '0x00000000000000000000000000000000000003f7',
5023+
function_parameters: '0x',
5024+
gas_limit: 250000,
5025+
gas_used: 200000,
5026+
timestamp: '1692959189.214316721',
5027+
to: '0x00000000000000000000000000000000000003f4',
5028+
hash: '0x7e8a09541c80ccda1f5f40a1975e031ed46de5ad7f24cd4c37be9bac65149b9e',
5029+
block_hash: '0xa414a76539f84ae1c797fa10d00e49d5e7a1adae556dcd43084551e671623d2eba825bcb7bbfd5b7e3fe59d63d8a167f',
5030+
block_number: 61033,
5031+
logs: [],
5032+
result: 'SUCCESS',
5033+
transaction_index: 2,
5034+
state_changes: [],
5035+
status: '0x1',
5036+
failed_initcode: null,
5037+
block_gas_used: 200000,
5038+
chain_id: '0x12a',
5039+
gas_price: '0x',
5040+
r: '0x85b423416d0164d0b2464d880bccb0679587c00673af8e016c8f0ce573be69b2',
5041+
s: '0x3897a5ce2ace1f242d9c989cd9c163d79760af4266f3bf2e69ee288bcffb211a',
5042+
v: 1,
5043+
nonce: 9
5044+
};
49405045

4941-
beforeEach(function() {
5046+
this.beforeEach(function() {
5047+
restMock.reset();
49425048
restMock.onGet(`accounts/${defaultFromLongZeroAddress}${noTransactions}`).reply(200, {
49435049
evm_address: `${defaultTransaction.from}`
49445050
});
5051+
restMock.onGet(`accounts/${from}?transactions=false`).reply(200, {
5052+
evm_address: evm_address
5053+
});
5054+
});
5055+
5056+
it('returns 155 transaction for type 0', async function () {
5057+
const uniqueTxHash = '0x27cad7b827375d12d73af57b6a3e84353645fd31305ea58ff52dda53ec640533';
5058+
restMock.onGet(`contracts/results/${uniqueTxHash}`).reply(200, {
5059+
...contractResultMock,
5060+
type: 0
5061+
});
5062+
5063+
const result = await ethImpl.getTransactionByHash(uniqueTxHash);
5064+
expect(result).to.be.an.instanceOf(Transaction);
5065+
});
5066+
5067+
it('returns 2930 transaction for type 1', async function () {
5068+
const uniqueTxHash = '0x28cad7b827375d12d73af57b6a3e84353645fd31305ea58ff52dda53ec640533';
5069+
restMock.onGet(`contracts/results/${uniqueTxHash}`).reply(200, {
5070+
...contractResultMock,
5071+
type: 1,
5072+
access_list: []
5073+
});
5074+
5075+
const result = await ethImpl.getTransactionByHash(uniqueTxHash);
5076+
expect(result).to.be.an.instanceOf(Transaction2930);
5077+
});
5078+
5079+
it('returns 1559 transaction for type 2', async function () {
5080+
const uniqueTxHash = '0x27cad7b827375d12d73af57b7a3e84353645fd31305ea58ff52dda53ec640533';
5081+
restMock.onGet(`contracts/results/${uniqueTxHash}`).reply(200, {
5082+
...contractResultMock,
5083+
type: 2,
5084+
access_list: [],
5085+
max_fee_per_gas: '0x47',
5086+
max_priority_fee_per_gas: '0x47'
5087+
});
5088+
5089+
const result = await ethImpl.getTransactionByHash(uniqueTxHash);
5090+
expect(result).to.be.an.instanceOf(Transaction1559);
49455091
});
49465092

49475093
it('returns `null` for non-existing hash', async function () {
5094+
const uniqueTxHash = '0x27cAd7b838375d12d73af57b6a3e84353645fd31305ea58ff52dda53ec640533';
49485095
restMock.onGet(`contracts/results/${uniqueTxHash}`).reply(404, {
49495096
'_status': {
49505097
'messages': [

packages/relay/tests/lib/formatters.spec.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,11 +233,9 @@ describe('Formatters', () => {
233233
r: null,
234234
s: null,
235235
transaction_index: null,
236-
type: null,
237236
v: null,
238237
value: null
239238
});
240-
expect(formattedResult.accessList).to.equal(undefined);
241239
expect(formattedResult.blockHash).to.equal('0xb0f10139fa0bf9e66402c8c0e5ed364e07cf83b3726c8045fabf86a07f488713');
242240
expect(formattedResult.blockNumber).to.equal(null);
243241
expect(formattedResult.chainId).to.equal('0x12a');
@@ -253,7 +251,6 @@ describe('Formatters', () => {
253251
expect(formattedResult.s).to.equal(null);
254252
expect(formattedResult.to).to.equal('0x0000000000000000000000000000000000000409');
255253
expect(formattedResult.transactionIndex).to.equal(null);
256-
expect(formattedResult.type).to.equal(null);
257254
expect(formattedResult.v).to.equal('0x0');
258255
expect(formattedResult.value).to.equal('0x0');
259256
});

0 commit comments

Comments
 (0)