Skip to content

Commit 0a3499d

Browse files
authored
fix(utils): fix block identifier (#1076)
* fix(utils): fix block identifier * docs: class Block docs
1 parent 11dc600 commit 0a3499d

File tree

5 files changed

+158
-23
lines changed

5 files changed

+158
-23
lines changed

__tests__/utils/block.test.ts

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import { Block } from '../../src/utils/provider';
2+
3+
describe('new Block()', () => {
4+
test('decimal number 0 BlockIdentifier', () => {
5+
const block = new Block(0);
6+
expect(block.identifier).toMatchObject({ block_number: 0 });
7+
expect(block.queryIdentifier).toBe('blockNumber=0');
8+
expect(block.hash).toBe(null);
9+
expect(block.number).toBe(0);
10+
expect(block.tag).toBe(null);
11+
});
12+
13+
test('decimal number 631581 BlockIdentifier', () => {
14+
const block1 = new Block(631581);
15+
expect(block1.identifier).toMatchObject({ block_number: 631581 });
16+
expect(block1.queryIdentifier).toBe('blockNumber=631581');
17+
expect(block1.hash).toBe(null);
18+
expect(block1.number).toBe(631581);
19+
expect(block1.tag).toBe(null);
20+
});
21+
22+
test('non-decimal number -1 BlockIdentifier', () => {
23+
expect(() => {
24+
const block = new Block(-1);
25+
return block;
26+
}).toThrow(TypeError);
27+
});
28+
29+
test('decimal string `0` BlockIdentifier', () => {
30+
const block = new Block('0');
31+
expect(block.identifier).toMatchObject({ block_number: 0 });
32+
expect(block.queryIdentifier).toBe('blockNumber=0');
33+
expect(block.hash).toBe(null);
34+
expect(block.number).toBe(0);
35+
expect(block.tag).toBe(null);
36+
});
37+
38+
test('decimal string `631581` BlockIdentifier', () => {
39+
const block1 = new Block('631581');
40+
expect(block1.identifier).toMatchObject({ block_number: 631581 });
41+
expect(block1.queryIdentifier).toBe('blockNumber=631581');
42+
expect(block1.hash).toBe(null);
43+
expect(block1.number).toBe(631581);
44+
expect(block1.tag).toBe(null);
45+
});
46+
47+
test('non-decimal string `-1` BlockIdentifier', () => {
48+
expect(() => {
49+
const block = new Block('-1');
50+
return block;
51+
}).toThrow(TypeError);
52+
});
53+
54+
test('(Irregular support) hex string `0x0` BlockIdentifier.', () => {
55+
const block = new Block('0x0');
56+
expect(block.identifier).toMatchObject({ block_hash: '0x0' });
57+
expect(block.queryIdentifier).toBe('blockHash=0x0');
58+
expect(block.hash).toBe('0x0');
59+
expect(block.number).toBe(null);
60+
expect(block.tag).toBe(null);
61+
});
62+
63+
test('hex string `0x2a70fb03fe363a2d6be843343a1d81ce6abeda1e9bd5cc6ad8fa9f45e30fdeb` BlockIdentifier', () => {
64+
const block = new Block('0x2a70fb03fe363a2d6be843343a1d81ce6abeda1e9bd5cc6ad8fa9f45e30fdeb');
65+
expect(block.identifier).toMatchObject({
66+
block_hash: '0x2a70fb03fe363a2d6be843343a1d81ce6abeda1e9bd5cc6ad8fa9f45e30fdeb',
67+
});
68+
expect(block.queryIdentifier).toBe(
69+
'blockHash=0x2a70fb03fe363a2d6be843343a1d81ce6abeda1e9bd5cc6ad8fa9f45e30fdeb'
70+
);
71+
expect(block.hash).toBe('0x2a70fb03fe363a2d6be843343a1d81ce6abeda1e9bd5cc6ad8fa9f45e30fdeb');
72+
expect(block.number).toBe(null);
73+
expect(block.tag).toBe(null);
74+
});
75+
76+
test('BigInt 1100871802642964430494835386862140987097292376415056243504467124241116103854n BlockIdentifier', () => {
77+
const block = new Block(
78+
1100871802642964430494835386862140987097292376415056243504467124241116103854n
79+
);
80+
expect(block.identifier).toMatchObject({
81+
block_hash: '0x26f12449d649a5339d4891b312a381f23ebc1106792d169b42e6646e87304ae',
82+
});
83+
expect(block.queryIdentifier).toBe(
84+
'blockHash=0x26f12449d649a5339d4891b312a381f23ebc1106792d169b42e6646e87304ae'
85+
);
86+
expect(block.hash).toBe('0x26f12449d649a5339d4891b312a381f23ebc1106792d169b42e6646e87304ae');
87+
expect(block.number).toBe(null);
88+
expect(block.tag).toBe(null);
89+
});
90+
91+
test('String BigInt `1100871802642964430494835386862140987097292376415056243504467124241116103854n` BlockIdentifier', () => {
92+
expect(() => {
93+
const block = new Block(
94+
'1100871802642964430494835386862140987097292376415056243504467124241116103854n'
95+
);
96+
return block;
97+
}).toThrow(TypeError);
98+
});
99+
100+
test('string `pending` BlockIdentifier', () => {
101+
const block1 = new Block('pending');
102+
expect(block1.identifier).toBe('pending');
103+
expect(block1.queryIdentifier).toBe('blockNumber=pending');
104+
expect(block1.hash).toBe(null);
105+
expect(block1.number).toBe(null);
106+
expect(block1.tag).toBe('pending');
107+
});
108+
109+
test('string `latest` BlockIdentifier', () => {
110+
const block1 = new Block('latest');
111+
expect(block1.identifier).toBe('latest');
112+
expect(block1.queryIdentifier).toBe('blockNumber=latest');
113+
expect(block1.hash).toBe(null);
114+
expect(block1.number).toBe(null);
115+
expect(block1.tag).toBe('latest');
116+
});
117+
118+
test('False string `supernova` BlockIdentifier', () => {
119+
expect(() => {
120+
const block = new Block('supernova');
121+
return block;
122+
}).toThrow(TypeError);
123+
});
124+
125+
test('null BlockIdentifier', () => {
126+
const block1 = new Block(null);
127+
expect(block1.identifier).toBe('pending');
128+
expect(block1.queryIdentifier).toBe('blockNumber=pending');
129+
expect(block1.hash).toBe(null);
130+
expect(block1.number).toBe(null);
131+
expect(block1.tag).toBe('pending');
132+
});
133+
});

__tests__/utils/utils.test.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import * as starkCurve from '@scure/starknet';
22

33
import { constants, ec, hash, num, stark } from '../../src';
4-
import { Block } from '../../src/utils/provider';
54
import { isBigInt, isHex } from '../../src/utils/num';
65

76
const { IS_BROWSER } = constants;
@@ -117,22 +116,6 @@ describe('calculateContractAddressFromHash()', () => {
117116
});
118117
});
119118

120-
describe('new Block()', () => {
121-
test('Block identifier and queryIdentifier', () => {
122-
const blockA = new Block(0);
123-
expect(blockA.identifier).toMatchObject({ block_number: 0 });
124-
expect(blockA.queryIdentifier).toBe('blockNumber=0');
125-
126-
const blockB = new Block('latest');
127-
expect(blockB.identifier).toBe('latest');
128-
expect(blockB.queryIdentifier).toBe('blockNumber=latest');
129-
130-
const blockC = new Block('0x01');
131-
expect(blockC.identifier).toMatchObject({ block_hash: '0x01' });
132-
expect(blockC.queryIdentifier).toBe('blockHash=0x01');
133-
});
134-
});
135-
136119
describe('Num utility functions', () => {
137120
describe('isBigInt', () => {
138121
test('should return true for big integers', () => {

src/types/lib/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,13 @@ export enum BlockTag {
210210
export type BlockNumber = BlockTag | null | number;
211211

212212
/**
213-
* hex string and BN are detected as block hashes
213+
* hex string and BigInt are detected as block hashes
214+
*
214215
* decimal string and number are detected as block numbers
215-
* null appends nothing to the request url
216+
*
217+
* text string are detected as block tag
218+
*
219+
* null return 'pending' block tag
216220
*/
217221
export type BlockIdentifier = BlockNumber | BigNumberish;
218222

src/utils/provider.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ import { isSierra } from './contract';
2020
import { formatSpaces } from './hash';
2121
import { parse, stringify } from './json';
2222
import { isBigInt, isHex, isNumber, toHex } from './num';
23+
import { isDecimalString, isString } from './shortString';
2324
import { compressProgram } from './stark';
2425
import type { GetTransactionReceiptResponse } from './transactionReceipt';
25-
import { isString } from './shortString';
2626

2727
/**
2828
* Helper - Async Sleep for 'delay' time
@@ -103,6 +103,15 @@ export function txIdentifier(txHash?: BigNumberish, txId?: BigNumberish): string
103103

104104
export const validBlockTags = Object.values(BlockTag);
105105

106+
/**
107+
* hex string and BigInt are detected as block hashes. identifier return { block_hash: hash }
108+
*
109+
* decimal string and number are detected as block numbers. identifier return { block_number: number }
110+
*
111+
* text string are detected as block tag. identifier return tag
112+
*
113+
* null is detected as 'pending' block tag. identifier return 'pending'
114+
*/
106115
export class Block {
107116
hash: BlockIdentifier = null;
108117

@@ -112,10 +121,14 @@ export class Block {
112121

113122
private setIdentifier(__identifier: BlockIdentifier) {
114123
if (isString(__identifier)) {
115-
if (isHex(__identifier)) {
124+
if (isDecimalString(__identifier)) {
125+
this.number = parseInt(__identifier, 10);
126+
} else if (isHex(__identifier)) {
116127
this.hash = __identifier;
117128
} else if (validBlockTags.includes(__identifier as BlockTag)) {
118129
this.tag = __identifier;
130+
} else {
131+
throw TypeError(`Block identifier unmanaged: ${__identifier}`);
119132
}
120133
} else if (isBigInt(__identifier)) {
121134
this.hash = toHex(__identifier);
@@ -124,6 +137,10 @@ export class Block {
124137
} else {
125138
this.tag = BlockTag.pending;
126139
}
140+
141+
if (isNumber(this.number) && this.number < 0) {
142+
throw TypeError(`Block number (${this.number}) can't be negative`);
143+
}
127144
}
128145

129146
constructor(_identifier: BlockIdentifier) {

src/utils/responseParser/rpc.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ import { toBigInt } from '../num';
2020
import { isString } from '../shortString';
2121
import { estimateFeeToBounds, estimatedFeeToMaxFee } from '../stark';
2222
import { ResponseParser } from '.';
23-
import { isString } from '../shortString';
24-
2523

2624
export class RPCResponseParser
2725
implements

0 commit comments

Comments
 (0)