@btc-vision/btc-runtime 1.4.7 → 1.5.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.
Files changed (59) hide show
  1. package/package.json +44 -53
  2. package/runtime/abort/abort.ts +25 -0
  3. package/runtime/buffer/BytesReader.ts +171 -140
  4. package/runtime/buffer/BytesWriter.ts +120 -152
  5. package/runtime/contracts/DeployableOP_20.ts +29 -15
  6. package/runtime/contracts/OP_NET.ts +1 -1
  7. package/runtime/env/BlockchainEnvironment.ts +79 -137
  8. package/runtime/env/classes/Block.ts +4 -8
  9. package/runtime/env/classes/Transaction.ts +14 -7
  10. package/runtime/env/classes/UTXO.ts +4 -2
  11. package/runtime/env/global.ts +49 -20
  12. package/runtime/events/predefined/MintEvent.ts +1 -1
  13. package/runtime/exports/index.ts +29 -8
  14. package/runtime/generic/AddressMap.ts +7 -5
  15. package/runtime/generic/Map.ts +32 -2
  16. package/runtime/generic/MapU256.ts +7 -5
  17. package/runtime/generic/MapUint8Array.ts +93 -0
  18. package/runtime/index.ts +4 -12
  19. package/runtime/math/abi.ts +71 -11
  20. package/runtime/math/bytes.ts +177 -41
  21. package/runtime/memory/AddressMemoryMap.ts +22 -19
  22. package/runtime/memory/FastUint8Array.ts +122 -0
  23. package/runtime/memory/KeyMerger.ts +25 -23
  24. package/runtime/memory/MultiAddressMemoryMap.ts +11 -8
  25. package/runtime/memory/MultiStringMemoryMap.ts +8 -5
  26. package/runtime/memory/StringMemoryMap.ts +15 -15
  27. package/runtime/memory/Uint8ArrayMerger.ts +22 -15
  28. package/runtime/storage/Serializable.ts +19 -20
  29. package/runtime/storage/StoredAddress.ts +16 -15
  30. package/runtime/storage/StoredBoolean.ts +26 -21
  31. package/runtime/storage/StoredString.ts +158 -102
  32. package/runtime/storage/StoredU256.ts +25 -28
  33. package/runtime/storage/StoredU64.ts +23 -35
  34. package/runtime/storage/arrays/StoredAddressArray.ts +83 -175
  35. package/runtime/storage/arrays/StoredBooleanArray.ts +146 -271
  36. package/runtime/storage/arrays/StoredPackedArray.ts +313 -0
  37. package/runtime/storage/arrays/StoredU128Array.ts +38 -374
  38. package/runtime/storage/arrays/StoredU16Array.ts +34 -420
  39. package/runtime/storage/arrays/StoredU256Array.ts +21 -347
  40. package/runtime/storage/arrays/StoredU32Array.ts +37 -440
  41. package/runtime/storage/arrays/StoredU64Array.ts +66 -0
  42. package/runtime/storage/arrays/StoredU8Array.ts +29 -453
  43. package/runtime/types/Address.ts +72 -5
  44. package/runtime/types/index.ts +1 -4
  45. package/runtime/utils/encodings.ts +5 -6
  46. package/runtime/utils/hex.ts +1 -1
  47. package/runtime/interfaces/DeployContractResponse.ts +0 -12
  48. package/runtime/math/cyrb53.ts +0 -48
  49. package/runtime/math/sha256.ts +0 -12
  50. package/runtime/memory/MemorySlot.ts +0 -1
  51. package/runtime/memory/MemorySlotPointer.ts +0 -3
  52. package/runtime/storage/utils/StorageBacked.ts +0 -5
  53. package/runtime/storage/utils/StorageLayout.ts +0 -7
  54. package/runtime/storage/utils/StorageSlot.ts +0 -106
  55. package/runtime/storage/utils/StorageStruct.ts +0 -23
  56. package/runtime/storage/utils/StorageValue.ts +0 -36
  57. package/runtime/tests/assert.ts +0 -11
  58. package/runtime/tests/env.ts +0 -7
  59. package/runtime/tests/tests.ts +0 -28
package/package.json CHANGED
@@ -1,55 +1,46 @@
1
1
  {
2
- "name": "@btc-vision/btc-runtime",
3
- "version": "1.4.7",
4
- "description": "Bitcoin Smart Contract Runtime",
5
- "main": "btc/index.ts",
6
- "scripts": {
7
- "build": "cross-env node scripts/asc tests/tests.ts",
8
- "test": "ts-mocha tests/**/*.spec.ts"
9
- },
10
- "types": "btc/index.ts",
11
- "keywords": [
12
- "bitcoin",
13
- "smart",
14
- "contract",
15
- "runtime",
16
- "opnet",
17
- "OP_NET"
18
- ],
19
- "homepage": "https://opnet.org",
20
- "author": "BlobMaster41",
21
- "license": "MIT",
22
- "devDependencies": {
23
- "@types/mocha": "^10.0.8",
24
- "@types/node": "^22.7.5",
25
- "assemblyscript": "^0.27.30",
26
- "cross-env": "^7.0.3",
27
- "fs-extra": "^11.2.0",
28
- "ts-mocha": "^10.0.0"
29
- },
30
- "repository": {
31
- "type": "git",
32
- "url": "https://github.com/btc-vision/btc-runtime"
33
- },
34
- "type": "module",
35
- "files": [
36
- "package.json",
37
- "runtime",
38
- "runtime/*.ts",
39
- "runtime/**/*.ts",
40
- "!**/*.js.map",
41
- "!**/*.tsbuildinfo",
42
- "test/*.ts"
43
- ],
44
- "dependencies": {
45
- "@assemblyscript/loader": "^0.27.30",
46
- "@btc-vision/as-bignum": "^0.0.4",
47
- "@eslint/js": "^9.10.0",
48
- "gulplog": "^2.2.0",
49
- "mocha": "^10.7.3",
50
- "ts-node": "^10.9.2",
51
- "typescript": "^5.6.2",
52
- "typescript-eslint": "^8.6.0",
53
- "yargs": "^17.7.2"
54
- }
2
+ "name": "@btc-vision/btc-runtime",
3
+ "version": "1.5.0",
4
+ "description": "Bitcoin Smart Contract Runtime",
5
+ "main": "btc/index.ts",
6
+ "scripts": {},
7
+ "types": "btc/index.ts",
8
+ "keywords": [
9
+ "bitcoin",
10
+ "smart",
11
+ "contract",
12
+ "runtime",
13
+ "opnet",
14
+ "OP_NET"
15
+ ],
16
+ "homepage": "https://opnet.org",
17
+ "author": "BlobMaster41",
18
+ "license": "MIT",
19
+ "devDependencies": {
20
+ "@types/node": "^22.13.10",
21
+ "assemblyscript": "^0.27.35"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/btc-vision/btc-runtime"
26
+ },
27
+ "type": "module",
28
+ "files": [
29
+ "package.json",
30
+ "runtime",
31
+ "runtime/*.ts",
32
+ "runtime/**/*.ts",
33
+ "!**/*.js.map",
34
+ "!**/*.tsbuildinfo",
35
+ "test/*.ts"
36
+ ],
37
+ "dependencies": {
38
+ "@assemblyscript/loader": "^0.27.35",
39
+ "@btc-vision/as-bignum": "^0.0.5",
40
+ "@eslint/js": "^9.22.0",
41
+ "gulplog": "^2.2.0",
42
+ "ts-node": "^10.9.2",
43
+ "typescript": "^5.8.2",
44
+ "typescript-eslint": "^8.26.1"
45
+ }
55
46
  }
@@ -0,0 +1,25 @@
1
+ import { DataView } from 'dataview';
2
+ import { ArrayBuffer } from 'arraybuffer';
3
+ import { env_exit } from '../env/global';
4
+
5
+ export function revertOnError(message: string, fileName: string, line: u32, column: u32): void {
6
+ const selector = 0x63739d5c; // Error(string)
7
+
8
+ const revertMessage = `${message} at ${fileName}:${line}:${column}`;
9
+
10
+ // THIS MIGHT OVERFLOW, IT'S OK.
11
+ const length = u16(revertMessage.length);
12
+ const _length_i32 = i32(length);
13
+
14
+ const arrayBuffer = new ArrayBuffer(4 + _length_i32 + 2);
15
+ const writer = new DataView(arrayBuffer);
16
+
17
+ writer.setUint32(0, selector, false);
18
+ writer.setUint16(4, length, false);
19
+
20
+ for (let i = 0; i < _length_i32; i++) {
21
+ writer.setUint8(6 + i, <u8>revertMessage.charCodeAt(i));
22
+ }
23
+
24
+ env_exit(1, arrayBuffer, arrayBuffer.byteLength);
25
+ }
@@ -19,238 +19,270 @@ import {
19
19
  @final
20
20
  export class BytesReader {
21
21
  private readonly buffer: DataView;
22
-
23
22
  private currentOffset: i32 = 0;
24
23
 
25
24
  constructor(bytes: Uint8Array) {
26
25
  this.buffer = new DataView(bytes.buffer);
27
26
  }
28
27
 
28
+ public get byteLength(): i32 {
29
+ return this.buffer.byteLength;
30
+ }
31
+
29
32
  public readU8(): u8 {
30
33
  this.verifyEnd(this.currentOffset + U8_BYTE_LENGTH);
31
-
32
34
  const value = this.buffer.getUint8(this.currentOffset);
33
35
  this.currentOffset += U8_BYTE_LENGTH;
34
-
35
36
  return value;
36
37
  }
37
38
 
38
- public readU16(): u16 {
39
+ /**
40
+ * By default, big-endian (be = true).
41
+ */
42
+ public readU16(be: boolean = true): u16 {
39
43
  this.verifyEnd(this.currentOffset + U16_BYTE_LENGTH);
40
-
41
- const value = this.buffer.getUint16(this.currentOffset, true);
44
+ const value = this.buffer.getUint16(this.currentOffset, !be);
42
45
  this.currentOffset += U16_BYTE_LENGTH;
43
-
44
46
  return value;
45
47
  }
46
48
 
47
- public readU32(le: boolean = true): u32 {
49
+ /**
50
+ * By default, big-endian (be = true).
51
+ */
52
+ public readU32(be: boolean = true): u32 {
48
53
  this.verifyEnd(this.currentOffset + U32_BYTE_LENGTH);
49
-
50
- const value = this.buffer.getUint32(this.currentOffset, le);
54
+ const value = this.buffer.getUint32(this.currentOffset, !be);
51
55
  this.currentOffset += U32_BYTE_LENGTH;
52
56
  return value;
53
57
  }
54
58
 
55
- public readU64(): u64 {
59
+ /**
60
+ * By default, big-endian (be = true).
61
+ */
62
+ public readU64(be: boolean = true): u64 {
56
63
  this.verifyEnd(this.currentOffset + U64_BYTE_LENGTH);
57
-
58
- const value = this.buffer.getUint64(this.currentOffset, true);
64
+ const value = this.buffer.getUint64(this.currentOffset, !be);
59
65
  this.currentOffset += U64_BYTE_LENGTH;
60
-
61
66
  return value;
62
67
  }
63
68
 
64
- public readU256(): u256 {
69
+ /**
70
+ * Reads 256 bits. The writer calls `writeU256(value, be)`.
71
+ * If be=true, we do big-endian; if be=false, little-endian.
72
+ */
73
+ public readU256(be: boolean = true): u256 {
65
74
  this.verifyEnd(this.currentOffset + U256_BYTE_LENGTH);
66
-
67
- const next32Bytes: u8[] = this.readBytesBE(U256_BYTE_LENGTH);
68
-
69
- return u256.fromBytesBE(next32Bytes);
70
- }
71
-
72
- @inline
73
- public readBytesBE(count: i32): u8[] {
74
- const next32Bytes: u8[] = [];
75
- for (let i = 0; i < count; i++) {
76
- next32Bytes[i] = this.readU8();
77
- }
78
-
79
- return next32Bytes;
75
+ const raw: u8[] = this.readBytesArray(U256_BYTE_LENGTH);
76
+ return be ? u256.fromBytesBE(raw) : u256.fromBytesLE(raw);
80
77
  }
81
78
 
82
- public readI64(): i64 {
79
+ public readI64(be: boolean = true): i64 {
83
80
  this.verifyEnd(this.currentOffset + I64_BYTE_LENGTH);
84
-
85
- const value = this.buffer.getInt64(this.currentOffset, true);
81
+ const value = this.buffer.getInt64(this.currentOffset, !be);
86
82
  this.currentOffset += I64_BYTE_LENGTH;
87
-
88
83
  return value;
89
84
  }
90
85
 
91
- public readU128(): u128 {
86
+ public readU128(be: boolean = true): u128 {
92
87
  this.verifyEnd(this.currentOffset + U128_BYTE_LENGTH);
93
-
94
- const next16Bytes: u8[] = this.readBytesBE(U128_BYTE_LENGTH);
95
-
96
- return u128.fromBytesBE(next16Bytes);
88
+ const raw: u8[] = this.readBytesArray(U128_BYTE_LENGTH);
89
+ return be ? u128.fromBytesBE(raw) : u128.fromBytesLE(raw);
97
90
  }
98
91
 
99
- public readI128(): i128 {
92
+ public readI128(be: boolean = true): i128 {
100
93
  this.verifyEnd(this.currentOffset + I128_BYTE_LENGTH);
101
-
102
- const next16Bytes: u8[] = this.readBytesBE(I128_BYTE_LENGTH);
103
-
104
- return i128.fromBytesBE(next16Bytes);
94
+ const raw: u8[] = this.readBytesArray(I128_BYTE_LENGTH);
95
+ return be ? i128.fromBytesBE(raw) : i128.fromBytesLE(raw);
105
96
  }
106
97
 
98
+ /**
99
+ * Reads `length` bytes, optionally stopping early if a 0x00 is seen.
100
+ */
107
101
  public readBytes(length: u32, zeroStop: boolean = false): Uint8Array {
108
- let bytes: Uint8Array = new Uint8Array(length);
102
+ let bytes = new Uint8Array(length);
109
103
  for (let i: u32 = 0; i < length; i++) {
110
- const byte: u8 = this.readU8();
111
- if (zeroStop && byte === 0) {
112
- bytes = bytes.slice(0, i);
104
+ const b: u8 = this.readU8();
105
+ if (zeroStop && b === 0) {
106
+ bytes = bytes.subarray(0, i);
113
107
  break;
114
108
  }
115
-
116
- bytes[i] = byte;
109
+ bytes[i] = b;
117
110
  }
118
-
119
111
  return bytes;
120
112
  }
121
113
 
122
- public readMultiBytesAddressMap(): AddressMap<Uint8Array[]> {
123
- const map: AddressMap<Uint8Array[]> = new AddressMap<Uint8Array[]>();
124
- const size: u8 = this.readU8();
125
-
126
- if (size > 8) throw new Revert('Too many contract called.');
127
-
128
- for (let i: u8 = 0; i < size; i++) {
129
- const address: Address = this.readAddress();
130
- const responseSize: u8 = this.readU8();
131
-
132
- if (responseSize > 10) throw new Revert('Too many calls.');
133
-
134
- const calls: Uint8Array[] = [];
135
- for (let j: u8 = 0; j < responseSize; j++) {
136
- const response: Uint8Array = this.readBytesWithLength();
137
- calls.push(response);
138
- }
139
-
140
- map.set(address, calls);
114
+ /**
115
+ * Convenience for reading a fixed number of bytes into a plain u8[] array.
116
+ */
117
+ @inline
118
+ public readBytesArray(count: i32): u8[] {
119
+ const arr = new Array<u8>(count);
120
+ for (let i = 0; i < count; i++) {
121
+ arr[i] = this.readU8();
141
122
  }
142
-
143
- return map;
123
+ return arr;
144
124
  }
145
125
 
146
- public readBytesWithLength(): Uint8Array {
147
- const length = this.readU32();
148
-
126
+ /**
127
+ * [u32 length][raw bytes]. By default big-endian for the length,
128
+ * to match AS BytesWriter's `writeBytesWithLength`.
129
+ */
130
+ public readBytesWithLength(be: boolean = true): Uint8Array {
131
+ const length = this.readU32(be);
149
132
  return this.readBytes(length);
150
133
  }
151
134
 
135
+ /**
136
+ * Reads a string of `length` raw bytes, zeroStop = true for convenience.
137
+ * (Or the writer may not have used zeroStop.)
138
+ */
152
139
  public readString(length: u16): string {
153
140
  const bytes = this.readBytes(length, true);
154
-
155
141
  return String.UTF8.decode(bytes.buffer);
156
142
  }
157
143
 
158
- public readTransactionInputs(): TransactionInput[] {
159
- const length = this.readU8();
160
- const result = new Array<TransactionInput>(length);
144
+ /**
145
+ * [u16 length][raw bytes].
146
+ * The AS writer calls `writeStringWithLength(value: string)` => writes length big-endian by default.
147
+ */
148
+ public readStringWithLength(be: boolean = true): string {
149
+ const length = this.readU16(be);
150
+ return this.readString(length);
151
+ }
161
152
 
162
- for (let i: u16 = 0; i < length; i++) {
163
- const txId = this.readBytes(32);
164
- const outputIndex = this.readU8();
165
- const scriptSig = this.readBytesWithLength();
153
+ public readBoolean(): boolean {
154
+ return this.readU8() !== 0;
155
+ }
166
156
 
167
- result[i] = new TransactionInput(txId, outputIndex, scriptSig);
168
- }
157
+ public readSelector(): Selector {
158
+ return this.readU32(true);
159
+ }
169
160
 
170
- return result;
161
+ /**
162
+ * Reads an Address (32 bytes).
163
+ */
164
+ public readAddress(): Address {
165
+ const addr = new Address();
166
+ for (let i: i32 = 0; i < ADDRESS_BYTE_LENGTH; i++) {
167
+ addr[i] = this.readU8();
168
+ }
169
+ return addr;
171
170
  }
172
171
 
173
- public readTransactionOutputs(): TransactionOutput[] {
174
- const length = this.readU8();
175
- const result = new Array<TransactionOutput>(length);
172
+ // ------------------- Arrays ------------------- //
176
173
 
177
- for (let i: u16 = 0; i < length; i++) {
178
- const index = this.readU8();
179
- const scriptPubKey = this.readStringWithLength();
180
- const value = this.readU64();
181
-
182
- result[i] = new TransactionOutput(index, scriptPubKey, value);
174
+ /**
175
+ * The AS writer does `writeU32(length)` for U256 arrays, so we read a u32.
176
+ * If you changed it to a `u16`, then do readU16() here.
177
+ */
178
+ public readU256Array(be: boolean = true): u256[] {
179
+ // The AS writer currently writes a u32 length for U256 arrays
180
+ const length = this.readU32();
181
+ const result = new Array<u256>(length);
182
+ for (let i: u32 = 0; i < length; i++) {
183
+ result[i] = this.readU256(be);
183
184
  }
184
-
185
185
  return result;
186
186
  }
187
187
 
188
- public readTuple(): u256[] {
189
- const length = this.readU32();
190
- const result: u256[] = new Array<u256>(length);
191
-
188
+ /**
189
+ * The AS writer uses a [u16 length] for U64 arrays.
190
+ */
191
+ public readU64Array(be: boolean = true): u64[] {
192
+ const length = this.readU16(be);
193
+ const result = new Array<u64>(length);
192
194
  for (let i: u32 = 0; i < length; i++) {
193
- result[i] = this.readU256();
195
+ result[i] = this.readU64(be);
194
196
  }
197
+ return result;
198
+ }
195
199
 
200
+ public readU32Array(be: boolean = true): u32[] {
201
+ const length = this.readU16(be);
202
+ const result = new Array<u32>(length);
203
+ for (let i: u16 = 0; i < length; i++) {
204
+ result[i] = this.readU32(be);
205
+ }
196
206
  return result;
197
207
  }
198
208
 
199
- public readU128Array(): u128[] {
200
- const length = this.readU16();
201
- const result: u128[] = new Array<u128>(length);
209
+ public readU16Array(be: boolean = true): u16[] {
210
+ const length = this.readU16(be);
211
+ const result = new Array<u16>(length);
212
+ for (let i: u16 = 0; i < length; i++) {
213
+ result[i] = this.readU16(be);
214
+ }
215
+ return result;
216
+ }
202
217
 
218
+ public readU128Array(be: boolean = true): u128[] {
219
+ const length = this.readU16(be);
220
+ const result = new Array<u128>(length);
203
221
  for (let i: u16 = 0; i < length; i++) {
204
- result[i] = this.readU128();
222
+ result[i] = this.readU128(be);
205
223
  }
224
+ return result;
225
+ }
206
226
 
227
+ /**
228
+ * The AS writer uses a [u8 length] for transaction inputs/outputs in the example,
229
+ * but for an "AddressArray" we use [u16 length].
230
+ */
231
+ public readAddressArray(be: boolean = true): Address[] {
232
+ const length = this.readU16(be);
233
+ const result = new Array<Address>(length);
234
+ for (let i: u16 = 0; i < length; i++) {
235
+ result[i] = this.readAddress();
236
+ }
207
237
  return result;
208
238
  }
209
239
 
210
- public readAddressValueTuple(): AddressMap<u256> {
211
- const length: u16 = this.readU16();
240
+ /**
241
+ * Map of [u16 length] entries, each entry = [Address, U256], consistent with the writer’s `writeAddressMapU256`.
242
+ */
243
+ public readAddressMapU256(be: boolean = true): AddressMap<u256> {
244
+ const length = this.readU16(be);
212
245
  const result = new AddressMap<u256>();
213
246
 
214
247
  for (let i: u16 = 0; i < length; i++) {
215
248
  const address = this.readAddress();
216
- const value = this.readU256();
217
-
218
- if (result.has(address)) throw new Revert('Duplicate address found in map');
249
+ const value = this.readU256(be);
219
250
 
251
+ if (result.has(address)) {
252
+ throw new Revert('Duplicate address found in map');
253
+ }
220
254
  result.set(address, value);
221
255
  }
222
256
 
223
257
  return result;
224
258
  }
225
259
 
226
- public readSelector(): Selector {
227
- return this.readU32(false);
228
- }
229
-
230
- public readStringWithLength(): string {
231
- const length = this.readU16();
260
+ public readTransactionInputs(): TransactionInput[] {
261
+ const length = this.readU8();
262
+ const result = new Array<TransactionInput>(length);
232
263
 
233
- return this.readString(length);
234
- }
264
+ for (let i: u16 = 0; i < length; i++) {
265
+ const txId = this.readBytes(32);
266
+ const outputIndex = this.readU8();
267
+ const scriptSig = this.readBytesWithLength();
268
+ result[i] = new TransactionInput(txId, outputIndex, scriptSig);
269
+ }
235
270
 
236
- public readBoolean(): boolean {
237
- return this.readU8() !== 0;
271
+ return result;
238
272
  }
239
273
 
240
- public readFloat(): f32 {
241
- const value = this.buffer.getFloat32(this.currentOffset, true);
242
- this.currentOffset += 4;
243
-
244
- return value;
245
- }
274
+ public readTransactionOutputs(): TransactionOutput[] {
275
+ const length = this.readU8();
276
+ const result = new Array<TransactionOutput>(length);
246
277
 
247
- public readAddress(): Address {
248
- const bytes: Address = new Address();
249
- for (let i: u32 = 0; i < u32(ADDRESS_BYTE_LENGTH); i++) {
250
- bytes[i] = this.readU8();
278
+ for (let i: u16 = 0; i < length; i++) {
279
+ const index = this.readU8();
280
+ const scriptPubKey = this.readStringWithLength();
281
+ const value = this.readU64();
282
+ result[i] = new TransactionOutput(index, scriptPubKey, value);
251
283
  }
252
284
 
253
- return bytes;
285
+ return result;
254
286
  }
255
287
 
256
288
  public getOffset(): i32 {
@@ -261,20 +293,19 @@ export class BytesReader {
261
293
  this.currentOffset = offset;
262
294
  }
263
295
 
296
+ /**
297
+ * Checks if we have enough bytes left in the buffer.
298
+ */
264
299
  public verifyEnd(size: i32): void {
265
300
  if (size > this.buffer.byteLength) {
266
- throw new Error(`Expected to read ${size} bytes but read ${this.currentOffset} bytes`);
301
+ throw new Error(
302
+ `Attempt to read beyond buffer length. Requested up to offset ${size}, ` +
303
+ `but buffer is only ${this.buffer.byteLength} bytes.`,
304
+ );
267
305
  }
268
306
  }
269
307
 
270
- public readAddressArray(): Address[] {
271
- const length = this.readU16();
272
- const result = new Array<Address>(length);
273
-
274
- for (let i: u16 = 0; i < length; i++) {
275
- result[i] = this.readAddress();
276
- }
277
-
278
- return result;
308
+ public toString(): string {
309
+ return Uint8Array.wrap(this.buffer.buffer).toString();
279
310
  }
280
311
  }