@subsquid/evm-codec 0.3.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/codec.d.ts +57 -12
- package/lib/codec.d.ts.map +1 -1
- package/lib/codec.js.map +1 -1
- package/lib/codecs/array.d.ts +1 -3
- package/lib/codecs/array.d.ts.map +1 -1
- package/lib/codecs/array.js +13 -9
- package/lib/codecs/array.js.map +1 -1
- package/lib/codecs/primitives.d.ts +2 -17
- package/lib/codecs/primitives.d.ts.map +1 -1
- package/lib/codecs/primitives.js +46 -152
- package/lib/codecs/primitives.js.map +1 -1
- package/lib/codecs/struct.d.ts +16 -9
- package/lib/codecs/struct.d.ts.map +1 -1
- package/lib/codecs/struct.js +53 -40
- package/lib/codecs/struct.js.map +1 -1
- package/lib/dsl.d.ts +11 -0
- package/lib/dsl.d.ts.map +1 -0
- package/lib/dsl.js +33 -0
- package/lib/dsl.js.map +1 -0
- package/lib/index.d.ts +7 -4
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +7 -6
- package/lib/index.js.map +1 -1
- package/lib/sink/bounds.d.ts +21 -0
- package/lib/sink/bounds.d.ts.map +1 -0
- package/lib/sink/bounds.js +24 -0
- package/lib/sink/bounds.js.map +1 -0
- package/lib/sink/bytes.d.ts +41 -0
- package/lib/sink/bytes.d.ts.map +1 -0
- package/lib/sink/bytes.js +261 -0
- package/lib/sink/bytes.js.map +1 -0
- package/lib/sink/hex.d.ts +33 -0
- package/lib/sink/hex.d.ts.map +1 -0
- package/lib/sink/hex.js +289 -0
- package/lib/sink/hex.js.map +1 -0
- package/lib/{src.d.ts → src/bytes.d.ts} +7 -5
- package/lib/src/bytes.d.ts.map +1 -0
- package/lib/src/bytes.js +161 -0
- package/lib/src/bytes.js.map +1 -0
- package/lib/src/hex.d.ts +33 -0
- package/lib/src/hex.d.ts.map +1 -0
- package/lib/src/hex.js +164 -0
- package/lib/src/hex.js.map +1 -0
- package/lib/util.d.ts +6 -0
- package/lib/util.d.ts.map +1 -0
- package/lib/util.js +20 -0
- package/lib/util.js.map +1 -0
- package/package.json +6 -8
- package/src/codec.ts +65 -19
- package/src/codecs/array.test.ts +87 -0
- package/src/codecs/array.ts +6 -11
- package/src/codecs/primitives.test.ts +27 -0
- package/src/codecs/primitives.ts +87 -208
- package/src/codecs/struct.test.ts +69 -0
- package/src/codecs/struct.ts +80 -61
- package/src/dsl.ts +16 -0
- package/src/index.ts +7 -4
- package/src/sink/bounds.ts +26 -0
- package/src/sink/bytes.test.ts +92 -0
- package/src/sink/bytes.ts +290 -0
- package/src/sink/hex.ts +311 -0
- package/src/src/bytes.test.ts +114 -0
- package/src/src/bytes.ts +187 -0
- package/src/src/hex.ts +191 -0
- package/src/util.ts +19 -0
- package/lib/safeToNumber.d.ts +0 -2
- package/lib/safeToNumber.d.ts.map +0 -1
- package/lib/safeToNumber.js +0 -11
- package/lib/safeToNumber.js.map +0 -1
- package/lib/sink.d.ts +0 -43
- package/lib/sink.d.ts.map +0 -1
- package/lib/sink.js +0 -215
- package/lib/sink.js.map +0 -1
- package/lib/src.d.ts.map +0 -1
- package/lib/src.js +0 -141
- package/lib/src.js.map +0 -1
- package/src/safeToNumber.ts +0 -6
- package/src/sink.ts +0 -241
- package/src/src.ts +0 -158
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import {describe, expect, it} from 'vitest'
|
|
2
|
+
import {BytesSink, BytesSrc} from '..'
|
|
3
|
+
|
|
4
|
+
describe('src', () => {
|
|
5
|
+
it('negative numbers', () => {
|
|
6
|
+
const sink = new BytesSink(6)
|
|
7
|
+
sink.i8(-1)
|
|
8
|
+
sink.i16(-123)
|
|
9
|
+
sink.i32(-123456)
|
|
10
|
+
sink.i64(-1234567890n)
|
|
11
|
+
sink.i128(-12345678901234567890n)
|
|
12
|
+
sink.i256(-1234567890123456789012345678901234567890n)
|
|
13
|
+
|
|
14
|
+
const src = new BytesSrc(sink.result())
|
|
15
|
+
expect(src.i8()).toBe(-1)
|
|
16
|
+
expect(src.i16()).toBe(-123)
|
|
17
|
+
expect(src.i32()).toBe(-123456)
|
|
18
|
+
expect(src.i64()).toBe(-1234567890n)
|
|
19
|
+
expect(src.i128()).toBe(-12345678901234567890n)
|
|
20
|
+
expect(src.i256()).toBe(-1234567890123456789012345678901234567890n)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('positive signed numbers', () => {
|
|
24
|
+
const sink = new BytesSink(6)
|
|
25
|
+
sink.i8(1)
|
|
26
|
+
sink.i16(123)
|
|
27
|
+
sink.i32(123456)
|
|
28
|
+
sink.i64(1234567890n)
|
|
29
|
+
sink.i128(12345678901234567890n)
|
|
30
|
+
sink.i256(1234567890123456789012345678901234567890n)
|
|
31
|
+
|
|
32
|
+
const src = new BytesSrc(sink.result())
|
|
33
|
+
expect(src.i8()).toBe(1)
|
|
34
|
+
expect(src.i16()).toBe(123)
|
|
35
|
+
expect(src.i32()).toBe(123456)
|
|
36
|
+
expect(src.i64()).toBe(1234567890n)
|
|
37
|
+
expect(src.i128()).toBe(12345678901234567890n)
|
|
38
|
+
expect(src.i256()).toBe(1234567890123456789012345678901234567890n)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('mixed static types', () => {
|
|
42
|
+
const sink = new BytesSink(4)
|
|
43
|
+
sink.u8(1)
|
|
44
|
+
sink.i8(-2)
|
|
45
|
+
sink.address('0x1234567890123456789012345678901234567890')
|
|
46
|
+
sink.u256(3n)
|
|
47
|
+
|
|
48
|
+
const src = new BytesSrc(sink.result())
|
|
49
|
+
expect(src.u8()).toBe(1)
|
|
50
|
+
expect(src.i8()).toBe(-2)
|
|
51
|
+
expect(src.address()).toBe('0x1234567890123456789012345678901234567890')
|
|
52
|
+
expect(src.u256()).toBe(3n)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('mixed dynamic types', () => {
|
|
56
|
+
const str1 = 'abc'.repeat(100)
|
|
57
|
+
const bytes1 = Buffer.alloc(100).fill('321')
|
|
58
|
+
const bytes7 = Buffer.from('1234567890abcd', 'hex')
|
|
59
|
+
const str2 = 'hello'
|
|
60
|
+
const addressValue = '0xabc4567890123456789012345678901234567890'
|
|
61
|
+
|
|
62
|
+
// Build a 7-field ABI-encoded tuple: each dynamic field (string/bytes) gets its
|
|
63
|
+
// own head slot (openTail writes the pointer) + tail data, while static fields
|
|
64
|
+
// (u8, staticBytes, i128, address) are written directly into the head.
|
|
65
|
+
const sink = new BytesSink(7)
|
|
66
|
+
sink.u8(69)
|
|
67
|
+
sink.openTail()
|
|
68
|
+
sink.string(str1)
|
|
69
|
+
sink.closeTail()
|
|
70
|
+
sink.staticBytes(7, bytes7)
|
|
71
|
+
sink.i128(-21312312452243312424534213123123123123n)
|
|
72
|
+
sink.openTail()
|
|
73
|
+
sink.bytes(bytes1)
|
|
74
|
+
sink.closeTail()
|
|
75
|
+
sink.address(addressValue)
|
|
76
|
+
sink.openTail()
|
|
77
|
+
sink.string(str2)
|
|
78
|
+
sink.closeTail()
|
|
79
|
+
|
|
80
|
+
const src = new BytesSrc(sink.result())
|
|
81
|
+
expect(src.u8()).toBe(69)
|
|
82
|
+
expect(src.string()).toBe(str1)
|
|
83
|
+
expect(src.staticBytes(7)).toStrictEqual(new Uint8Array(bytes7))
|
|
84
|
+
expect(src.i128()).toBe(-21312312452243312424534213123123123123n)
|
|
85
|
+
expect(src.bytes()).toStrictEqual(new Uint8Array(bytes1))
|
|
86
|
+
expect(src.address()).toBe(addressValue)
|
|
87
|
+
expect(src.string()).toBe(str2)
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
describe('string', () => {
|
|
91
|
+
function testString(str: string) {
|
|
92
|
+
const sink = new BytesSink(1)
|
|
93
|
+
sink.openTail()
|
|
94
|
+
sink.string(str)
|
|
95
|
+
sink.closeTail()
|
|
96
|
+
expect(new BytesSrc(sink.result()).string()).toBe(str)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
it('short string', () => testString('hello'))
|
|
100
|
+
it('32 byte string', () => testString('this string length is 32 bytes!!'))
|
|
101
|
+
it('longer string', () => testString('this string length is 33 bytes!!!'))
|
|
102
|
+
it('UTF', () => testString('привет 👍'))
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('bytes', () => {
|
|
106
|
+
const buffer = Buffer.alloc(150)
|
|
107
|
+
buffer.fill('xd')
|
|
108
|
+
const sink = new BytesSink(1)
|
|
109
|
+
sink.openTail()
|
|
110
|
+
sink.bytes(buffer)
|
|
111
|
+
sink.closeTail()
|
|
112
|
+
expect(new BytesSrc(sink.result()).bytes()).toStrictEqual(new Uint8Array(buffer))
|
|
113
|
+
})
|
|
114
|
+
})
|
package/src/src/bytes.ts
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import {WORD_SIZE, type Src} from '../codec'
|
|
2
|
+
import {toHex} from '@subsquid/util-internal-hex'
|
|
3
|
+
|
|
4
|
+
const I64_SIGN_BIT = 1n << 63n
|
|
5
|
+
const I64_RANGE = 1n << 64n
|
|
6
|
+
const I128_SIGN_BIT = 1n << 127n
|
|
7
|
+
const I128_RANGE = 1n << 128n
|
|
8
|
+
const I256_SIGN_BIT = 1n << 255n
|
|
9
|
+
const I256_RANGE = 1n << 256n
|
|
10
|
+
|
|
11
|
+
const TEXT_DECODER = new TextDecoder('utf-8')
|
|
12
|
+
|
|
13
|
+
export class BytesSrc implements Src {
|
|
14
|
+
private view: DataView
|
|
15
|
+
private pos = 0
|
|
16
|
+
private oldPos = 0
|
|
17
|
+
|
|
18
|
+
constructor(private buf: Uint8Array) {
|
|
19
|
+
this.view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
slice(start: number, end?: number): BytesSrc {
|
|
23
|
+
return new BytesSrc(this.buf.subarray(start, end))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
u8(): number {
|
|
27
|
+
this.pos += WORD_SIZE - 1
|
|
28
|
+
let val = this.view.getUint8(this.pos)
|
|
29
|
+
this.pos += 1
|
|
30
|
+
return val
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
i8(): number {
|
|
34
|
+
return Number(this.i256())
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
u16(): number {
|
|
38
|
+
this.pos += WORD_SIZE - 2
|
|
39
|
+
let val = this.view.getUint16(this.pos, false)
|
|
40
|
+
this.pos += 2
|
|
41
|
+
return val
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
i16(): number {
|
|
45
|
+
return Number(this.i256())
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
u32(): number {
|
|
49
|
+
this.pos += WORD_SIZE - 4
|
|
50
|
+
let val = this.view.getUint32(this.pos, false)
|
|
51
|
+
this.pos += 4
|
|
52
|
+
return val
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
i32(): number {
|
|
56
|
+
return Number(this.i256())
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
u64(): bigint {
|
|
60
|
+
this.pos += WORD_SIZE - 8
|
|
61
|
+
return this.#u64()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
#u64(): bigint {
|
|
65
|
+
let val = this.view.getBigUint64(this.pos, false)
|
|
66
|
+
this.pos += 8
|
|
67
|
+
return val
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
i64(): bigint {
|
|
71
|
+
this.pos += WORD_SIZE - 8
|
|
72
|
+
const raw = this.#u64()
|
|
73
|
+
return raw < I64_SIGN_BIT ? raw : raw - I64_RANGE
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
u128(): bigint {
|
|
77
|
+
this.pos += WORD_SIZE - 16
|
|
78
|
+
return this.#u128()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
#u128(): bigint {
|
|
82
|
+
const hi = this.view.getBigUint64(this.pos, false)
|
|
83
|
+
const lo = this.view.getBigUint64(this.pos + 8, false)
|
|
84
|
+
this.pos += 16
|
|
85
|
+
return (hi << 64n) | lo
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
i128(): bigint {
|
|
89
|
+
this.pos += WORD_SIZE - 16
|
|
90
|
+
const raw = this.#u128()
|
|
91
|
+
return raw < I128_SIGN_BIT ? raw : raw - I128_RANGE
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
u256(): bigint {
|
|
95
|
+
const hi = this.#u128()
|
|
96
|
+
const lo = this.#u128()
|
|
97
|
+
return (hi << 128n) | lo
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
i256(): bigint {
|
|
101
|
+
const hi = this.#u128()
|
|
102
|
+
const lo = this.#u128()
|
|
103
|
+
const raw = (hi << 128n) | lo
|
|
104
|
+
return raw < I256_SIGN_BIT ? raw : raw - I256_RANGE
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
address(): string {
|
|
108
|
+
const start = this.pos + WORD_SIZE - 20
|
|
109
|
+
this.pos += WORD_SIZE
|
|
110
|
+
return toHex(this.buf, start, 20)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
bytes(): Uint8Array {
|
|
114
|
+
const ptr = this.u32()
|
|
115
|
+
this.jump(ptr)
|
|
116
|
+
const len = Number(this.u256())
|
|
117
|
+
this.#assertLength(len, 'bytes')
|
|
118
|
+
const val = this.buf.subarray(this.pos, this.pos + len)
|
|
119
|
+
this.jumpBack()
|
|
120
|
+
return val
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
bytesHex(): string {
|
|
124
|
+
const ptr = this.u32()
|
|
125
|
+
this.jump(ptr)
|
|
126
|
+
const len = Number(this.u256())
|
|
127
|
+
this.#assertLength(len, 'bytes')
|
|
128
|
+
const val = toHex(this.buf, this.pos, len)
|
|
129
|
+
this.jumpBack()
|
|
130
|
+
return val
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
staticBytes(len: number): Uint8Array {
|
|
134
|
+
if (len > 32) {
|
|
135
|
+
throw new Error(`bytes${len} is not a valid type`)
|
|
136
|
+
}
|
|
137
|
+
const val = this.buf.subarray(this.pos, this.pos + len)
|
|
138
|
+
this.pos += WORD_SIZE
|
|
139
|
+
return val
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
staticBytesHex(len: number): string {
|
|
143
|
+
if (len > 32) {
|
|
144
|
+
throw new Error(`bytes${len} is not a valid type`)
|
|
145
|
+
}
|
|
146
|
+
const start = this.pos
|
|
147
|
+
this.pos += WORD_SIZE
|
|
148
|
+
return toHex(this.buf, start, len)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
string(): string {
|
|
152
|
+
const ptr = this.u32()
|
|
153
|
+
this.jump(ptr, 'string')
|
|
154
|
+
const len = Number(this.u256())
|
|
155
|
+
this.#assertLength(len, 'string')
|
|
156
|
+
const val = TEXT_DECODER.decode(this.buf.subarray(this.pos, this.pos + len))
|
|
157
|
+
this.jumpBack()
|
|
158
|
+
return val
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
bool(): boolean {
|
|
162
|
+
return !!this.u8()
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
#assertLength(len: number, typeName: string): void {
|
|
166
|
+
if (this.buf.length - this.pos < len) {
|
|
167
|
+
throw new RangeError(
|
|
168
|
+
`Unexpected end of input. Attempting to read ${typeName} of length ${len} from ${toHex(this.buf)}`,
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
jump(pos: number, typeName?: string): void {
|
|
174
|
+
if (pos < 0 || pos >= this.buf.length) {
|
|
175
|
+
const what = typeName ? `${typeName} ` : ''
|
|
176
|
+
throw new RangeError(
|
|
177
|
+
`Unexpected pointer location: 0x${pos.toString(16)}. Attempting to read ${what}from ${toHex(this.buf)}`,
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
this.oldPos = this.pos
|
|
181
|
+
this.pos = pos
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
jumpBack(): void {
|
|
185
|
+
this.pos = this.oldPos
|
|
186
|
+
}
|
|
187
|
+
}
|
package/src/src/hex.ts
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import {WORD_SIZE, type Src} from '../codec'
|
|
2
|
+
|
|
3
|
+
const HEX_BYTE = 2
|
|
4
|
+
const WORD_HEX = WORD_SIZE * HEX_BYTE
|
|
5
|
+
|
|
6
|
+
const I64_SIGN_BIT = 1n << 63n
|
|
7
|
+
const I64_RANGE = 1n << 64n
|
|
8
|
+
const I128_SIGN_BIT = 1n << 127n
|
|
9
|
+
const I128_RANGE = 1n << 128n
|
|
10
|
+
const I256_SIGN_BIT = 1n << 255n
|
|
11
|
+
const I256_RANGE = 1n << 256n
|
|
12
|
+
|
|
13
|
+
const TEXT_DECODER = new TextDecoder('utf-8')
|
|
14
|
+
|
|
15
|
+
export class HexSrc implements Src {
|
|
16
|
+
private readonly buf: string
|
|
17
|
+
private readonly base: number
|
|
18
|
+
private readonly endChar: number
|
|
19
|
+
private pos: number
|
|
20
|
+
private oldPos: number
|
|
21
|
+
|
|
22
|
+
constructor(hex: string, strOffset = 2, strEnd: number = hex.length) {
|
|
23
|
+
this.buf = hex
|
|
24
|
+
this.base = strOffset
|
|
25
|
+
this.endChar = strEnd
|
|
26
|
+
this.pos = strOffset
|
|
27
|
+
this.oldPos = strOffset
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
slice(start: number, end?: number): HexSrc {
|
|
31
|
+
const s = this.base + HEX_BYTE * start
|
|
32
|
+
const e = end == null ? this.endChar : this.base + HEX_BYTE * end
|
|
33
|
+
return new HexSrc(this.buf, s, e)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
u8(): number {
|
|
37
|
+
const start = this.pos + WORD_HEX - 2
|
|
38
|
+
const val = Number.parseInt(this.buf.slice(start, start + 2), 16)
|
|
39
|
+
this.pos += WORD_HEX
|
|
40
|
+
return val
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
i8(): number {
|
|
44
|
+
return Number(this.i256())
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
u16(): number {
|
|
48
|
+
const start = this.pos + WORD_HEX - 4
|
|
49
|
+
const val = Number.parseInt(this.buf.slice(start, start + 4), 16)
|
|
50
|
+
this.pos += WORD_HEX
|
|
51
|
+
return val
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
i16(): number {
|
|
55
|
+
return Number(this.i256())
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
u32(): number {
|
|
59
|
+
const start = this.pos + WORD_HEX - 8
|
|
60
|
+
const val = Number.parseInt(this.buf.slice(start, start + 8), 16)
|
|
61
|
+
this.pos += WORD_HEX
|
|
62
|
+
return val
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
i32(): number {
|
|
66
|
+
return Number(this.i256())
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
u64(): bigint {
|
|
70
|
+
const start = this.pos + WORD_HEX - 16
|
|
71
|
+
const val = BigInt(`0x${this.buf.slice(start, start + 16)}`)
|
|
72
|
+
this.pos += WORD_HEX
|
|
73
|
+
return val
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
i64(): bigint {
|
|
77
|
+
const raw = this.u64()
|
|
78
|
+
return raw < I64_SIGN_BIT ? raw : raw - I64_RANGE
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
u128(): bigint {
|
|
82
|
+
const start = this.pos + WORD_HEX - 32
|
|
83
|
+
const val = BigInt(`0x${this.buf.slice(start, start + 32)}`)
|
|
84
|
+
this.pos += WORD_HEX
|
|
85
|
+
return val
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
i128(): bigint {
|
|
89
|
+
const raw = this.u128()
|
|
90
|
+
return raw < I128_SIGN_BIT ? raw : raw - I128_RANGE
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
u256(): bigint {
|
|
94
|
+
const val = BigInt(`0x${this.buf.slice(this.pos, this.pos + WORD_HEX)}`)
|
|
95
|
+
this.pos += WORD_HEX
|
|
96
|
+
return val
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
i256(): bigint {
|
|
100
|
+
const raw = this.u256()
|
|
101
|
+
return raw < I256_SIGN_BIT ? raw : raw - I256_RANGE
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
address(): string {
|
|
105
|
+
const start = this.pos + WORD_HEX - 40
|
|
106
|
+
const val = `0x${this.buf.slice(start, start + 40)}`
|
|
107
|
+
this.pos += WORD_HEX
|
|
108
|
+
return val
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
bytes(): Uint8Array {
|
|
112
|
+
const ptr = this.u32()
|
|
113
|
+
this.jump(ptr)
|
|
114
|
+
const len = Number(this.u256())
|
|
115
|
+
this.#assertLength(len, 'bytes')
|
|
116
|
+
const sub = this.buf.slice(this.pos, this.pos + HEX_BYTE * len)
|
|
117
|
+
const val = Buffer.from(sub, 'hex')
|
|
118
|
+
this.jumpBack()
|
|
119
|
+
return val
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
bytesHex(): string {
|
|
123
|
+
const ptr = this.u32()
|
|
124
|
+
this.jump(ptr)
|
|
125
|
+
const len = Number(this.u256())
|
|
126
|
+
this.#assertLength(len, 'bytes')
|
|
127
|
+
const val = `0x${this.buf.slice(this.pos, this.pos + HEX_BYTE * len)}`
|
|
128
|
+
this.jumpBack()
|
|
129
|
+
return val
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
staticBytes(len: number): Uint8Array {
|
|
133
|
+
if (len > 32) {
|
|
134
|
+
throw new Error(`bytes${len} is not a valid type`)
|
|
135
|
+
}
|
|
136
|
+
const sub = this.buf.slice(this.pos, this.pos + HEX_BYTE * len)
|
|
137
|
+
this.pos += WORD_HEX
|
|
138
|
+
return Buffer.from(sub, 'hex')
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
staticBytesHex(len: number): string {
|
|
142
|
+
if (len > 32) {
|
|
143
|
+
throw new Error(`bytes${len} is not a valid type`)
|
|
144
|
+
}
|
|
145
|
+
const val = `0x${this.buf.slice(this.pos, this.pos + HEX_BYTE * len)}`
|
|
146
|
+
this.pos += WORD_HEX
|
|
147
|
+
return val
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
string(): string {
|
|
151
|
+
const ptr = this.u32()
|
|
152
|
+
this.jump(ptr, 'string')
|
|
153
|
+
const len = Number(this.u256())
|
|
154
|
+
this.#assertLength(len, 'string')
|
|
155
|
+
const sub = this.buf.slice(this.pos, this.pos + HEX_BYTE * len)
|
|
156
|
+
const val = TEXT_DECODER.decode(Buffer.from(sub, 'hex'))
|
|
157
|
+
this.jumpBack()
|
|
158
|
+
return val
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
bool(): boolean {
|
|
162
|
+
const a = this.buf.charCodeAt(this.pos + WORD_HEX - 2)
|
|
163
|
+
const b = this.buf.charCodeAt(this.pos + WORD_HEX - 1)
|
|
164
|
+
this.pos += WORD_HEX
|
|
165
|
+
return a !== 48 /* '0' */ || b !== 48
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
#assertLength(len: number, typeName: string): void {
|
|
169
|
+
if (this.endChar - this.pos < HEX_BYTE * len) {
|
|
170
|
+
throw new RangeError(
|
|
171
|
+
`Unexpected end of input. Attempting to read ${typeName} of length ${len} from 0x${this.buf.slice(this.base, this.endChar)}`,
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
jump(pos: number, typeName?: string): void {
|
|
177
|
+
const target = this.base + HEX_BYTE * pos
|
|
178
|
+
if (pos < 0 || target >= this.endChar) {
|
|
179
|
+
const what = typeName ? `${typeName} ` : ''
|
|
180
|
+
throw new RangeError(
|
|
181
|
+
`Unexpected pointer location: 0x${pos.toString(16)}. Attempting to read ${what}from 0x${this.buf.slice(this.base, this.endChar)}`,
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
this.oldPos = this.pos
|
|
185
|
+
this.pos = target
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
jumpBack(): void {
|
|
189
|
+
this.pos = this.oldPos
|
|
190
|
+
}
|
|
191
|
+
}
|
package/src/util.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type Pretty<T> = {[K in keyof T]: T[K]} & unknown
|
|
2
|
+
|
|
3
|
+
export function propName(prop: string): string {
|
|
4
|
+
if (isValidProperty(prop)) {
|
|
5
|
+
return prop
|
|
6
|
+
}
|
|
7
|
+
return `[${JSON.stringify(prop)}]`
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function propAccess(prop: string): string {
|
|
11
|
+
if (isValidProperty(prop)) {
|
|
12
|
+
return `.${prop}`
|
|
13
|
+
}
|
|
14
|
+
return `[${JSON.stringify(prop)}]`
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function isValidProperty(s: string): boolean {
|
|
18
|
+
return /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(s)
|
|
19
|
+
}
|
package/lib/safeToNumber.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"safeToNumber.d.ts","sourceRoot":"","sources":["../src/safeToNumber.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAK3D"}
|
package/lib/safeToNumber.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.safeToNumber = void 0;
|
|
4
|
-
function safeToNumber(value) {
|
|
5
|
-
if (value < Number.MIN_SAFE_INTEGER || value > Number.MAX_SAFE_INTEGER) {
|
|
6
|
-
throw new Error(`${value} is not a safe integer`);
|
|
7
|
-
}
|
|
8
|
-
return Number(value);
|
|
9
|
-
}
|
|
10
|
-
exports.safeToNumber = safeToNumber;
|
|
11
|
-
//# sourceMappingURL=safeToNumber.js.map
|
package/lib/safeToNumber.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"safeToNumber.js","sourceRoot":"","sources":["../src/safeToNumber.ts"],"names":[],"mappings":";;;AAAA,SAAgB,YAAY,CAAC,KAAsB;IACjD,IAAK,KAAK,GAAG,MAAM,CAAC,gBAAgB,IAAI,KAAK,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,wBAAwB,CAAC,CAAA;IACnD,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;AACtB,CAAC;AALD,oCAKC"}
|
package/lib/sink.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
export declare class Sink {
|
|
3
|
-
#private;
|
|
4
|
-
private pos;
|
|
5
|
-
private buf;
|
|
6
|
-
private view;
|
|
7
|
-
private stack;
|
|
8
|
-
constructor(fields: number, capacity?: number);
|
|
9
|
-
result(): Buffer;
|
|
10
|
-
toString(): string;
|
|
11
|
-
reserve(additional: number): void;
|
|
12
|
-
size(): number;
|
|
13
|
-
private _allocate;
|
|
14
|
-
private checkNumberBounds;
|
|
15
|
-
u8(val: number): void;
|
|
16
|
-
i8(val: number): void;
|
|
17
|
-
u16(val: number): void;
|
|
18
|
-
i16(val: number): void;
|
|
19
|
-
u32(val: number): void;
|
|
20
|
-
i32(val: number): void;
|
|
21
|
-
u64(val: bigint): void;
|
|
22
|
-
i64(val: bigint): void;
|
|
23
|
-
u128(val: bigint): void;
|
|
24
|
-
i128(val: bigint): void;
|
|
25
|
-
u256(val: bigint): void;
|
|
26
|
-
i256(val: bigint): void;
|
|
27
|
-
bytes(val: Uint8Array): void;
|
|
28
|
-
staticBytes(len: number, val: Uint8Array): void;
|
|
29
|
-
address(val: string): void;
|
|
30
|
-
string(val: string): void;
|
|
31
|
-
bool(val: boolean): void;
|
|
32
|
-
/**
|
|
33
|
-
* @example
|
|
34
|
-
* @link [Solidity docs](https://docs.soliditylang.org/en/latest/abi-spec.html#use-of-dynamic-types)
|
|
35
|
-
*/
|
|
36
|
-
newStaticDataArea(slotsCount?: number): void;
|
|
37
|
-
newDynamicDataArea(slotsCount: number): void;
|
|
38
|
-
private currentDataAreaStart;
|
|
39
|
-
increaseCurrentDataAreaSize(amount: number): void;
|
|
40
|
-
private pushDataArea;
|
|
41
|
-
endCurrentDataArea(): void;
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=sink.d.ts.map
|
package/lib/sink.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sink.d.ts","sourceRoot":"","sources":["../src/sink.ts"],"names":[],"mappings":";AAGA,qBAAa,IAAI;;IACf,OAAO,CAAC,GAAG,CAAI;IACf,OAAO,CAAC,GAAG,CAAQ;IACnB,OAAO,CAAC,IAAI,CAAU;IACtB,OAAO,CAAC,KAAK,CAA6D;gBAC9D,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAa;IAUnD,MAAM,IAAI,MAAM;IAKhB,QAAQ;IAIR,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAMjC,IAAI;IAIJ,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,iBAAiB;IAMzB,EAAE,CAAC,GAAG,EAAE,MAAM;IAQd,EAAE,CAAC,GAAG,EAAE,MAAM;IAKd,GAAG,CAAC,GAAG,EAAE,MAAM;IAQf,GAAG,CAAC,GAAG,EAAE,MAAM;IAKf,GAAG,CAAC,GAAG,EAAE,MAAM;IAQf,GAAG,CAAC,GAAG,EAAE,MAAM;IAKf,GAAG,CAAC,GAAG,EAAE,MAAM;IAQf,GAAG,CAAC,GAAG,EAAE,MAAM;IAUf,IAAI,CAAC,GAAG,EAAE,MAAM;IAQhB,IAAI,CAAC,GAAG,EAAE,MAAM;IAWhB,IAAI,CAAC,GAAG,EAAE,MAAM;IAOhB,IAAI,CAAC,GAAG,EAAE,MAAM;IAiBhB,KAAK,CAAC,GAAG,EAAE,UAAU;IAWrB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU;IAaxC,OAAO,CAAC,GAAG,EAAE,MAAM;IAInB,MAAM,CAAC,GAAG,EAAE,MAAM;IAWlB,IAAI,CAAC,GAAG,EAAE,OAAO;IAIjB;;;OAGG;IACH,iBAAiB,CAAC,UAAU,SAAI;IAShC,kBAAkB,CAAC,UAAU,EAAE,MAAM;IASrC,OAAO,CAAC,oBAAoB;IAIrB,2BAA2B,CAAC,MAAM,EAAE,MAAM;IAIjD,OAAO,CAAC,YAAY;IAUb,kBAAkB;CAM1B"}
|