@haneullabs/bcs 0.1.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/CHANGELOG.md +388 -0
- package/README.md +358 -0
- package/dist/cjs/bcs-type.d.ts +127 -0
- package/dist/cjs/bcs-type.js +386 -0
- package/dist/cjs/bcs-type.js.map +7 -0
- package/dist/cjs/bcs.d.ts +175 -0
- package/dist/cjs/bcs.js +406 -0
- package/dist/cjs/bcs.js.map +7 -0
- package/dist/cjs/index.d.ts +22 -0
- package/dist/cjs/index.js +59 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/package.json +5 -0
- package/dist/cjs/reader.d.ts +92 -0
- package/dist/cjs/reader.js +136 -0
- package/dist/cjs/reader.js.map +7 -0
- package/dist/cjs/types.d.ts +28 -0
- package/dist/cjs/types.js +17 -0
- package/dist/cjs/types.js.map +7 -0
- package/dist/cjs/uleb.d.ts +5 -0
- package/dist/cjs/uleb.js +66 -0
- package/dist/cjs/uleb.js.map +7 -0
- package/dist/cjs/utils.d.ts +18 -0
- package/dist/cjs/utils.js +74 -0
- package/dist/cjs/utils.js.map +7 -0
- package/dist/cjs/writer.d.ts +117 -0
- package/dist/cjs/writer.js +196 -0
- package/dist/cjs/writer.js.map +7 -0
- package/dist/esm/bcs-type.d.ts +127 -0
- package/dist/esm/bcs-type.js +366 -0
- package/dist/esm/bcs-type.js.map +7 -0
- package/dist/esm/bcs.d.ts +175 -0
- package/dist/esm/bcs.js +397 -0
- package/dist/esm/bcs.js.map +7 -0
- package/dist/esm/index.d.ts +22 -0
- package/dist/esm/index.js +46 -0
- package/dist/esm/index.js.map +7 -0
- package/dist/esm/package.json +5 -0
- package/dist/esm/reader.d.ts +92 -0
- package/dist/esm/reader.js +116 -0
- package/dist/esm/reader.js.map +7 -0
- package/dist/esm/types.d.ts +28 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/types.js.map +7 -0
- package/dist/esm/uleb.d.ts +5 -0
- package/dist/esm/uleb.js +46 -0
- package/dist/esm/uleb.js.map +7 -0
- package/dist/esm/utils.d.ts +18 -0
- package/dist/esm/utils.js +54 -0
- package/dist/esm/utils.js.map +7 -0
- package/dist/esm/writer.d.ts +117 -0
- package/dist/esm/writer.js +176 -0
- package/dist/esm/writer.js.map +7 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +73 -0
- package/src/bcs-type.ts +531 -0
- package/src/bcs.ts +543 -0
- package/src/index.ts +82 -0
- package/src/reader.ts +156 -0
- package/src/types.ts +52 -0
- package/src/uleb.ts +61 -0
- package/src/utils.ts +75 -0
- package/src/writer.ts +222 -0
package/src/bcs.ts
ADDED
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
// Copyright (c) Mysten Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { BcsTypeOptions } from './bcs-type.js';
|
|
5
|
+
import {
|
|
6
|
+
BcsEnum,
|
|
7
|
+
BcsStruct,
|
|
8
|
+
BcsTuple,
|
|
9
|
+
BcsType,
|
|
10
|
+
bigUIntBcsType,
|
|
11
|
+
dynamicSizeBcsType,
|
|
12
|
+
fixedSizeBcsType,
|
|
13
|
+
lazyBcsType,
|
|
14
|
+
stringLikeBcsType,
|
|
15
|
+
uIntBcsType,
|
|
16
|
+
} from './bcs-type.js';
|
|
17
|
+
import type {
|
|
18
|
+
EnumInputShape,
|
|
19
|
+
EnumOutputShape,
|
|
20
|
+
InferBcsInput,
|
|
21
|
+
InferBcsType,
|
|
22
|
+
JoinString,
|
|
23
|
+
} from './types.js';
|
|
24
|
+
import { ulebEncode } from './uleb.js';
|
|
25
|
+
|
|
26
|
+
function fixedArray<T extends BcsType<any>, Name extends string = string>(
|
|
27
|
+
size: number,
|
|
28
|
+
type: T,
|
|
29
|
+
options?: BcsTypeOptions<
|
|
30
|
+
InferBcsType<T>[],
|
|
31
|
+
Iterable<InferBcsInput<T>> & { length: number },
|
|
32
|
+
Name
|
|
33
|
+
>,
|
|
34
|
+
): BcsType<InferBcsType<T>[], Iterable<InferBcsInput<T>> & { length: number }, Name>;
|
|
35
|
+
function fixedArray<T, Input, Name extends string = string>(
|
|
36
|
+
size: number,
|
|
37
|
+
type: BcsType<T, Input>,
|
|
38
|
+
options?: BcsTypeOptions<T[], Iterable<Input> & { length: number }, Name>,
|
|
39
|
+
): BcsType<T[], Iterable<Input> & { length: number }, Name>;
|
|
40
|
+
function fixedArray<T extends BcsType<any>, Name extends string = `${T['name']}[${number}]`>(
|
|
41
|
+
size: number,
|
|
42
|
+
type: T,
|
|
43
|
+
options?: BcsTypeOptions<
|
|
44
|
+
InferBcsType<T>[],
|
|
45
|
+
Iterable<InferBcsInput<T>> & { length: number },
|
|
46
|
+
Name
|
|
47
|
+
>,
|
|
48
|
+
): BcsType<InferBcsType<T>[], Iterable<InferBcsInput<T>> & { length: number }, Name> {
|
|
49
|
+
return new BcsType<InferBcsType<T>[], Iterable<InferBcsInput<T>> & { length: number }, Name>({
|
|
50
|
+
read: (reader) => {
|
|
51
|
+
const result: InferBcsType<T>[] = new Array(size);
|
|
52
|
+
for (let i = 0; i < size; i++) {
|
|
53
|
+
result[i] = type.read(reader);
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
},
|
|
57
|
+
write: (value, writer) => {
|
|
58
|
+
for (const item of value) {
|
|
59
|
+
type.write(item, writer);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
...options,
|
|
63
|
+
name: (options?.name ?? `${type.name}[${size}]`) as Name,
|
|
64
|
+
validate: (value) => {
|
|
65
|
+
options?.validate?.(value);
|
|
66
|
+
if (!value || typeof value !== 'object' || !('length' in value)) {
|
|
67
|
+
throw new TypeError(`Expected array, found ${typeof value}`);
|
|
68
|
+
}
|
|
69
|
+
if (value.length !== size) {
|
|
70
|
+
throw new TypeError(`Expected array of length ${size}, found ${value.length}`);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function option<T extends BcsType<any>>(
|
|
77
|
+
type: T,
|
|
78
|
+
): BcsType<InferBcsType<T> | null, InferBcsInput<T> | null | undefined, `Option<${T['name']}>`>;
|
|
79
|
+
function option<T, Input, Name extends string = string>(
|
|
80
|
+
type: BcsType<T, Input, Name>,
|
|
81
|
+
): BcsType<T | null, Input | null | undefined>;
|
|
82
|
+
function option<T extends BcsType<any>>(
|
|
83
|
+
type: T,
|
|
84
|
+
): BcsType<InferBcsType<T> | null, InferBcsInput<T> | null | undefined, `Option<${T['name']}>`> {
|
|
85
|
+
return bcs
|
|
86
|
+
.enum(`Option<${type.name}>`, {
|
|
87
|
+
None: null,
|
|
88
|
+
Some: type,
|
|
89
|
+
})
|
|
90
|
+
.transform({
|
|
91
|
+
input: (value: InferBcsInput<T> | null | undefined) => {
|
|
92
|
+
if (value == null) {
|
|
93
|
+
return { None: true };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return { Some: value };
|
|
97
|
+
},
|
|
98
|
+
output: (value) => {
|
|
99
|
+
if (value.$kind === 'Some') {
|
|
100
|
+
return value.Some as InferBcsType<T>;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return null;
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function vector<T extends BcsType<any>, Name extends string = `vector<${T['name']}>`>(
|
|
109
|
+
type: T,
|
|
110
|
+
options?: BcsTypeOptions<
|
|
111
|
+
InferBcsType<T>[],
|
|
112
|
+
Iterable<InferBcsInput<T>> & { length: number },
|
|
113
|
+
Name
|
|
114
|
+
>,
|
|
115
|
+
): BcsType<InferBcsType<T>[], Iterable<InferBcsInput<T>> & { length: number }, Name>;
|
|
116
|
+
function vector<T, Input, Name extends string = string>(
|
|
117
|
+
type: BcsType<T, Input, Name>,
|
|
118
|
+
options?: BcsTypeOptions<T[], Iterable<Input> & { length: number }, `vector<${Name}>`>,
|
|
119
|
+
): BcsType<T[], Iterable<Input> & { length: number }, `vector<${Name}>`>;
|
|
120
|
+
function vector<T extends BcsType<any>, Name extends string = `vector<${T['name']}>`>(
|
|
121
|
+
type: T,
|
|
122
|
+
options?: BcsTypeOptions<
|
|
123
|
+
InferBcsType<T>[],
|
|
124
|
+
Iterable<InferBcsInput<T>> & { length: number },
|
|
125
|
+
Name
|
|
126
|
+
>,
|
|
127
|
+
): BcsType<InferBcsType<T>[], Iterable<InferBcsInput<T>> & { length: number }, Name> {
|
|
128
|
+
return new BcsType<InferBcsType<T>[], Iterable<InferBcsInput<T>> & { length: number }, Name>({
|
|
129
|
+
read: (reader) => {
|
|
130
|
+
const length = reader.readULEB();
|
|
131
|
+
const result: InferBcsType<T>[] = new Array(length);
|
|
132
|
+
for (let i = 0; i < length; i++) {
|
|
133
|
+
result[i] = type.read(reader);
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
},
|
|
137
|
+
write: (value, writer) => {
|
|
138
|
+
writer.writeULEB(value.length);
|
|
139
|
+
for (const item of value) {
|
|
140
|
+
type.write(item, writer);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
...options,
|
|
144
|
+
name: (options?.name ?? `vector<${type.name}>`) as Name,
|
|
145
|
+
validate: (value) => {
|
|
146
|
+
options?.validate?.(value);
|
|
147
|
+
if (!value || typeof value !== 'object' || !('length' in value)) {
|
|
148
|
+
throw new TypeError(`Expected array, found ${typeof value}`);
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function map<K extends BcsType<any>, V extends BcsType<any>>(
|
|
155
|
+
keyType: K,
|
|
156
|
+
valueType: V,
|
|
157
|
+
): BcsType<
|
|
158
|
+
Map<InferBcsType<K>, InferBcsType<V>>,
|
|
159
|
+
Map<InferBcsInput<K>, InferBcsInput<V>>,
|
|
160
|
+
`Map<${K['name']}, ${V['name']}>`
|
|
161
|
+
>;
|
|
162
|
+
function map<K, V, InputK = K, InputV = V>(
|
|
163
|
+
keyType: BcsType<K, InputK>,
|
|
164
|
+
valueType: BcsType<V, InputV>,
|
|
165
|
+
): BcsType<Map<K, V>, Map<InputK, InputV>, `Map<${string}, ${string}>`>;
|
|
166
|
+
function map<K extends BcsType<any>, V extends BcsType<any>>(
|
|
167
|
+
keyType: K,
|
|
168
|
+
valueType: V,
|
|
169
|
+
): BcsType<
|
|
170
|
+
Map<InferBcsType<K>, InferBcsType<V>>,
|
|
171
|
+
Map<InferBcsInput<K>, InferBcsInput<V>>,
|
|
172
|
+
`Map<${K['name']}, ${V['name']}>`
|
|
173
|
+
> {
|
|
174
|
+
return bcs.vector(bcs.tuple([keyType, valueType])).transform({
|
|
175
|
+
name: `Map<${keyType.name}, ${valueType.name}>`,
|
|
176
|
+
input: (value: Map<InferBcsInput<K>, InferBcsInput<V>>) => {
|
|
177
|
+
return [...value.entries()];
|
|
178
|
+
},
|
|
179
|
+
output: (value) => {
|
|
180
|
+
const result = new Map<InferBcsType<K>, InferBcsType<V>>();
|
|
181
|
+
for (const [key, val] of value) {
|
|
182
|
+
result.set(key, val);
|
|
183
|
+
}
|
|
184
|
+
return result;
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export const bcs = {
|
|
190
|
+
/**
|
|
191
|
+
* Creates a BcsType that can be used to read and write an 8-bit unsigned integer.
|
|
192
|
+
* @example
|
|
193
|
+
* bcs.u8().serialize(255).toBytes() // Uint8Array [ 255 ]
|
|
194
|
+
*/
|
|
195
|
+
u8(options?: BcsTypeOptions<number>) {
|
|
196
|
+
return uIntBcsType({
|
|
197
|
+
readMethod: 'read8',
|
|
198
|
+
writeMethod: 'write8',
|
|
199
|
+
size: 1,
|
|
200
|
+
maxValue: 2 ** 8 - 1,
|
|
201
|
+
...options,
|
|
202
|
+
name: (options?.name ?? 'u8') as 'u8',
|
|
203
|
+
});
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Creates a BcsType that can be used to read and write a 16-bit unsigned integer.
|
|
208
|
+
* @example
|
|
209
|
+
* bcs.u16().serialize(65535).toBytes() // Uint8Array [ 255, 255 ]
|
|
210
|
+
*/
|
|
211
|
+
u16(options?: BcsTypeOptions<number>) {
|
|
212
|
+
return uIntBcsType({
|
|
213
|
+
readMethod: 'read16',
|
|
214
|
+
writeMethod: 'write16',
|
|
215
|
+
size: 2,
|
|
216
|
+
maxValue: 2 ** 16 - 1,
|
|
217
|
+
...options,
|
|
218
|
+
name: (options?.name ?? 'u16') as 'u16',
|
|
219
|
+
});
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Creates a BcsType that can be used to read and write a 32-bit unsigned integer.
|
|
224
|
+
* @example
|
|
225
|
+
* bcs.u32().serialize(4294967295).toBytes() // Uint8Array [ 255, 255, 255, 255 ]
|
|
226
|
+
*/
|
|
227
|
+
u32(options?: BcsTypeOptions<number>) {
|
|
228
|
+
return uIntBcsType({
|
|
229
|
+
readMethod: 'read32',
|
|
230
|
+
writeMethod: 'write32',
|
|
231
|
+
size: 4,
|
|
232
|
+
maxValue: 2 ** 32 - 1,
|
|
233
|
+
...options,
|
|
234
|
+
name: (options?.name ?? 'u32') as 'u32',
|
|
235
|
+
});
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Creates a BcsType that can be used to read and write a 64-bit unsigned integer.
|
|
240
|
+
* @example
|
|
241
|
+
* bcs.u64().serialize(1).toBytes() // Uint8Array [ 1, 0, 0, 0, 0, 0, 0, 0 ]
|
|
242
|
+
*/
|
|
243
|
+
u64(options?: BcsTypeOptions<string, number | bigint | string>) {
|
|
244
|
+
return bigUIntBcsType({
|
|
245
|
+
readMethod: 'read64',
|
|
246
|
+
writeMethod: 'write64',
|
|
247
|
+
size: 8,
|
|
248
|
+
maxValue: 2n ** 64n - 1n,
|
|
249
|
+
...options,
|
|
250
|
+
name: (options?.name ?? 'u64') as 'u64',
|
|
251
|
+
});
|
|
252
|
+
},
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Creates a BcsType that can be used to read and write a 128-bit unsigned integer.
|
|
256
|
+
* @example
|
|
257
|
+
* bcs.u128().serialize(1).toBytes() // Uint8Array [ 1, ..., 0 ]
|
|
258
|
+
*/
|
|
259
|
+
u128(options?: BcsTypeOptions<string, number | bigint | string>) {
|
|
260
|
+
return bigUIntBcsType({
|
|
261
|
+
readMethod: 'read128',
|
|
262
|
+
writeMethod: 'write128',
|
|
263
|
+
size: 16,
|
|
264
|
+
maxValue: 2n ** 128n - 1n,
|
|
265
|
+
...options,
|
|
266
|
+
name: (options?.name ?? 'u128') as 'u128',
|
|
267
|
+
});
|
|
268
|
+
},
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Creates a BcsType that can be used to read and write a 256-bit unsigned integer.
|
|
272
|
+
* @example
|
|
273
|
+
* bcs.u256().serialize(1).toBytes() // Uint8Array [ 1, ..., 0 ]
|
|
274
|
+
*/
|
|
275
|
+
u256(options?: BcsTypeOptions<string, number | bigint | string>) {
|
|
276
|
+
return bigUIntBcsType({
|
|
277
|
+
readMethod: 'read256',
|
|
278
|
+
writeMethod: 'write256',
|
|
279
|
+
size: 32,
|
|
280
|
+
maxValue: 2n ** 256n - 1n,
|
|
281
|
+
...options,
|
|
282
|
+
name: (options?.name ?? 'u256') as 'u256',
|
|
283
|
+
});
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Creates a BcsType that can be used to read and write boolean values.
|
|
288
|
+
* @example
|
|
289
|
+
* bcs.bool().serialize(true).toBytes() // Uint8Array [ 1 ]
|
|
290
|
+
*/
|
|
291
|
+
bool(options?: BcsTypeOptions<boolean>) {
|
|
292
|
+
return fixedSizeBcsType({
|
|
293
|
+
size: 1,
|
|
294
|
+
read: (reader) => reader.read8() === 1,
|
|
295
|
+
write: (value, writer) => writer.write8(value ? 1 : 0),
|
|
296
|
+
...options,
|
|
297
|
+
name: (options?.name ?? 'bool') as 'bool',
|
|
298
|
+
validate: (value) => {
|
|
299
|
+
options?.validate?.(value);
|
|
300
|
+
if (typeof value !== 'boolean') {
|
|
301
|
+
throw new TypeError(`Expected boolean, found ${typeof value}`);
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
},
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Creates a BcsType that can be used to read and write unsigned LEB encoded integers
|
|
309
|
+
* @example
|
|
310
|
+
*
|
|
311
|
+
*/
|
|
312
|
+
uleb128(options?: BcsTypeOptions<number>) {
|
|
313
|
+
return dynamicSizeBcsType({
|
|
314
|
+
read: (reader) => reader.readULEB(),
|
|
315
|
+
serialize: (value) => {
|
|
316
|
+
return Uint8Array.from(ulebEncode(value));
|
|
317
|
+
},
|
|
318
|
+
...options,
|
|
319
|
+
name: (options?.name ?? 'uleb128') as 'uleb128',
|
|
320
|
+
});
|
|
321
|
+
},
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Creates a BcsType representing a fixed length byte array
|
|
325
|
+
* @param size The number of bytes this types represents
|
|
326
|
+
* @example
|
|
327
|
+
* bcs.bytes(3).serialize(new Uint8Array([1, 2, 3])).toBytes() // Uint8Array [1, 2, 3]
|
|
328
|
+
*/
|
|
329
|
+
bytes<T extends number>(size: T, options?: BcsTypeOptions<Uint8Array, Iterable<number>>) {
|
|
330
|
+
return fixedSizeBcsType<Uint8Array, Iterable<number>, `bytes[${T}]`>({
|
|
331
|
+
size,
|
|
332
|
+
read: (reader) => reader.readBytes(size),
|
|
333
|
+
write: (value, writer) => {
|
|
334
|
+
writer.writeBytes(new Uint8Array(value));
|
|
335
|
+
},
|
|
336
|
+
...options,
|
|
337
|
+
name: (options?.name ?? `bytes[${size}]`) as `bytes[${T}]`,
|
|
338
|
+
validate: (value) => {
|
|
339
|
+
options?.validate?.(value);
|
|
340
|
+
if (!value || typeof value !== 'object' || !('length' in value)) {
|
|
341
|
+
throw new TypeError(`Expected array, found ${typeof value}`);
|
|
342
|
+
}
|
|
343
|
+
if (value.length !== size) {
|
|
344
|
+
throw new TypeError(`Expected array of length ${size}, found ${value.length}`);
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
});
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Creates a BcsType representing a variable length byte array
|
|
352
|
+
*
|
|
353
|
+
* @example
|
|
354
|
+
* bcs.byteVector().serialize([1, 2, 3]).toBytes() // Uint8Array [3, 1, 2, 3]
|
|
355
|
+
*/
|
|
356
|
+
byteVector(options?: BcsTypeOptions<Uint8Array, Iterable<number>>) {
|
|
357
|
+
return new BcsType<Uint8Array, Iterable<number>, 'vector<u8>'>({
|
|
358
|
+
read: (reader) => {
|
|
359
|
+
const length = reader.readULEB();
|
|
360
|
+
|
|
361
|
+
return reader.readBytes(length);
|
|
362
|
+
},
|
|
363
|
+
write: (value, writer) => {
|
|
364
|
+
const array = new Uint8Array(value);
|
|
365
|
+
writer.writeULEB(array.length);
|
|
366
|
+
writer.writeBytes(array);
|
|
367
|
+
},
|
|
368
|
+
...options,
|
|
369
|
+
name: (options?.name ?? 'vector<u8>') as 'vector<u8>',
|
|
370
|
+
serializedSize: (value) => {
|
|
371
|
+
const length = 'length' in value ? (value.length as number) : null;
|
|
372
|
+
return length == null ? null : ulebEncode(length).length + length;
|
|
373
|
+
},
|
|
374
|
+
validate: (value) => {
|
|
375
|
+
options?.validate?.(value);
|
|
376
|
+
if (!value || typeof value !== 'object' || !('length' in value)) {
|
|
377
|
+
throw new TypeError(`Expected array, found ${typeof value}`);
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
});
|
|
381
|
+
},
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Creates a BcsType that can ser/de string values. Strings will be UTF-8 encoded
|
|
385
|
+
* @example
|
|
386
|
+
* bcs.string().serialize('a').toBytes() // Uint8Array [ 1, 97 ]
|
|
387
|
+
*/
|
|
388
|
+
string(options?: BcsTypeOptions<string>) {
|
|
389
|
+
return stringLikeBcsType({
|
|
390
|
+
toBytes: (value) => new TextEncoder().encode(value),
|
|
391
|
+
fromBytes: (bytes) => new TextDecoder().decode(bytes),
|
|
392
|
+
...options,
|
|
393
|
+
name: (options?.name ?? 'string') as 'string',
|
|
394
|
+
});
|
|
395
|
+
},
|
|
396
|
+
/**
|
|
397
|
+
* Creates a BcsType that represents a fixed length array of a given type
|
|
398
|
+
* @param size The number of elements in the array
|
|
399
|
+
* @param type The BcsType of each element in the array
|
|
400
|
+
* @example
|
|
401
|
+
* bcs.fixedArray(3, bcs.u8()).serialize([1, 2, 3]).toBytes() // Uint8Array [ 1, 2, 3 ]
|
|
402
|
+
*/
|
|
403
|
+
fixedArray,
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Creates a BcsType representing an optional value
|
|
407
|
+
* @param type The BcsType of the optional value
|
|
408
|
+
* @example
|
|
409
|
+
* bcs.option(bcs.u8()).serialize(null).toBytes() // Uint8Array [ 0 ]
|
|
410
|
+
* bcs.option(bcs.u8()).serialize(1).toBytes() // Uint8Array [ 1, 1 ]
|
|
411
|
+
*/
|
|
412
|
+
option,
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Creates a BcsType representing a variable length vector of a given type
|
|
416
|
+
* @param type The BcsType of each element in the vector
|
|
417
|
+
*
|
|
418
|
+
* @example
|
|
419
|
+
* bcs.vector(bcs.u8()).toBytes([1, 2, 3]) // Uint8Array [ 3, 1, 2, 3 ]
|
|
420
|
+
*/
|
|
421
|
+
vector,
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Creates a BcsType representing a tuple of a given set of types
|
|
425
|
+
* @param types The BcsTypes for each element in the tuple
|
|
426
|
+
*
|
|
427
|
+
* @example
|
|
428
|
+
* const tuple = bcs.tuple([bcs.u8(), bcs.string(), bcs.bool()])
|
|
429
|
+
* tuple.serialize([1, 'a', true]).toBytes() // Uint8Array [ 1, 1, 97, 1 ]
|
|
430
|
+
*/
|
|
431
|
+
tuple<
|
|
432
|
+
const T extends readonly BcsType<any, any>[],
|
|
433
|
+
const Name extends string =
|
|
434
|
+
`(${JoinString<{ [K in keyof T]: T[K] extends BcsType<any, any, infer T> ? T : never }, ', '>})`,
|
|
435
|
+
>(
|
|
436
|
+
fields: T,
|
|
437
|
+
options?: BcsTypeOptions<
|
|
438
|
+
{
|
|
439
|
+
-readonly [K in keyof T]: T[K] extends BcsType<infer T, any> ? T : never;
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
[K in keyof T]: T[K] extends BcsType<any, infer T> ? T : never;
|
|
443
|
+
},
|
|
444
|
+
Name
|
|
445
|
+
>,
|
|
446
|
+
) {
|
|
447
|
+
return new BcsTuple<T, Name>({
|
|
448
|
+
fields,
|
|
449
|
+
...options,
|
|
450
|
+
});
|
|
451
|
+
},
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Creates a BcsType representing a struct of a given set of fields
|
|
455
|
+
* @param name The name of the struct
|
|
456
|
+
* @param fields The fields of the struct. The order of the fields affects how data is serialized and deserialized
|
|
457
|
+
*
|
|
458
|
+
* @example
|
|
459
|
+
* const struct = bcs.struct('MyStruct', {
|
|
460
|
+
* a: bcs.u8(),
|
|
461
|
+
* b: bcs.string(),
|
|
462
|
+
* })
|
|
463
|
+
* struct.serialize({ a: 1, b: 'a' }).toBytes() // Uint8Array [ 1, 1, 97 ]
|
|
464
|
+
*/
|
|
465
|
+
struct<T extends Record<string, BcsType<any>>, const Name extends string = string>(
|
|
466
|
+
name: Name,
|
|
467
|
+
fields: T,
|
|
468
|
+
options?: Omit<
|
|
469
|
+
BcsTypeOptions<
|
|
470
|
+
{
|
|
471
|
+
[K in keyof T]: T[K] extends BcsType<infer U, any> ? U : never;
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
[K in keyof T]: T[K] extends BcsType<any, infer U> ? U : never;
|
|
475
|
+
}
|
|
476
|
+
>,
|
|
477
|
+
'name'
|
|
478
|
+
>,
|
|
479
|
+
) {
|
|
480
|
+
return new BcsStruct<T>({
|
|
481
|
+
name,
|
|
482
|
+
fields,
|
|
483
|
+
...options,
|
|
484
|
+
});
|
|
485
|
+
},
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Creates a BcsType representing an enum of a given set of options
|
|
489
|
+
* @param name The name of the enum
|
|
490
|
+
* @param values The values of the enum. The order of the values affects how data is serialized and deserialized.
|
|
491
|
+
* null can be used to represent a variant with no data.
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* const enum = bcs.enum('MyEnum', {
|
|
495
|
+
* A: bcs.u8(),
|
|
496
|
+
* B: bcs.string(),
|
|
497
|
+
* C: null,
|
|
498
|
+
* })
|
|
499
|
+
* enum.serialize({ A: 1 }).toBytes() // Uint8Array [ 0, 1 ]
|
|
500
|
+
* enum.serialize({ B: 'a' }).toBytes() // Uint8Array [ 1, 1, 97 ]
|
|
501
|
+
* enum.serialize({ C: true }).toBytes() // Uint8Array [ 2 ]
|
|
502
|
+
*/
|
|
503
|
+
enum<T extends Record<string, BcsType<any> | null>, const Name extends string = string>(
|
|
504
|
+
name: Name,
|
|
505
|
+
fields: T,
|
|
506
|
+
options?: Omit<
|
|
507
|
+
BcsTypeOptions<
|
|
508
|
+
EnumOutputShape<{
|
|
509
|
+
[K in keyof T]: T[K] extends BcsType<infer U, any, any> ? U : true;
|
|
510
|
+
}>,
|
|
511
|
+
EnumInputShape<{
|
|
512
|
+
[K in keyof T]: T[K] extends BcsType<any, infer U, any> ? U : boolean | object | null;
|
|
513
|
+
}>,
|
|
514
|
+
Name
|
|
515
|
+
>,
|
|
516
|
+
'name'
|
|
517
|
+
>,
|
|
518
|
+
) {
|
|
519
|
+
return new BcsEnum<T, Name>({
|
|
520
|
+
name,
|
|
521
|
+
fields,
|
|
522
|
+
...options,
|
|
523
|
+
});
|
|
524
|
+
},
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Creates a BcsType representing a map of a given key and value type
|
|
528
|
+
* @param keyType The BcsType of the key
|
|
529
|
+
* @param valueType The BcsType of the value
|
|
530
|
+
* @example
|
|
531
|
+
* const map = bcs.map(bcs.u8(), bcs.string())
|
|
532
|
+
* map.serialize(new Map([[2, 'a']])).toBytes() // Uint8Array [ 1, 2, 1, 97 ]
|
|
533
|
+
*/
|
|
534
|
+
map,
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Creates a BcsType that wraps another BcsType which is lazily evaluated. This is useful for creating recursive types.
|
|
538
|
+
* @param cb A callback that returns the BcsType
|
|
539
|
+
*/
|
|
540
|
+
lazy<T extends BcsType<any>>(cb: () => T): T {
|
|
541
|
+
return lazyBcsType(cb) as T;
|
|
542
|
+
},
|
|
543
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Copyright (c) Mysten Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* BCS implementation {@see https://github.com/diem/bcs } for JavaScript.
|
|
6
|
+
* Intended to be used for Move applications; supports both NodeJS and browser.
|
|
7
|
+
*
|
|
8
|
+
* For more details and examples {@see README.md }.
|
|
9
|
+
*
|
|
10
|
+
* @module bcs
|
|
11
|
+
* @property {BcsReader}
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { toBase58, fromBase58, toBase64, fromBase64, toHex, fromHex } from '@haneullabs/utils';
|
|
15
|
+
import type { BcsTypeOptions } from './bcs-type.js';
|
|
16
|
+
import {
|
|
17
|
+
BcsType,
|
|
18
|
+
BcsStruct,
|
|
19
|
+
BcsEnum,
|
|
20
|
+
BcsTuple,
|
|
21
|
+
isSerializedBcs,
|
|
22
|
+
SerializedBcs,
|
|
23
|
+
} from './bcs-type.js';
|
|
24
|
+
import { bcs } from './bcs.js';
|
|
25
|
+
import { BcsReader } from './reader.js';
|
|
26
|
+
import type {
|
|
27
|
+
EnumInputShape,
|
|
28
|
+
EnumOutputShape,
|
|
29
|
+
EnumOutputShapeWithKeys,
|
|
30
|
+
InferBcsInput,
|
|
31
|
+
InferBcsType,
|
|
32
|
+
} from './types.js';
|
|
33
|
+
import { decodeStr, encodeStr, splitGenericParameters } from './utils.js';
|
|
34
|
+
import type { BcsWriterOptions } from './writer.js';
|
|
35
|
+
import { BcsWriter } from './writer.js';
|
|
36
|
+
|
|
37
|
+
// Re-export all encoding dependencies.
|
|
38
|
+
export {
|
|
39
|
+
bcs,
|
|
40
|
+
BcsType,
|
|
41
|
+
BcsStruct,
|
|
42
|
+
BcsEnum,
|
|
43
|
+
BcsTuple,
|
|
44
|
+
type BcsTypeOptions,
|
|
45
|
+
SerializedBcs,
|
|
46
|
+
isSerializedBcs,
|
|
47
|
+
toBase58,
|
|
48
|
+
fromBase58,
|
|
49
|
+
toBase64,
|
|
50
|
+
fromBase64,
|
|
51
|
+
toHex,
|
|
52
|
+
fromHex,
|
|
53
|
+
encodeStr,
|
|
54
|
+
decodeStr,
|
|
55
|
+
splitGenericParameters,
|
|
56
|
+
BcsReader,
|
|
57
|
+
BcsWriter,
|
|
58
|
+
type BcsWriterOptions,
|
|
59
|
+
type InferBcsInput,
|
|
60
|
+
type InferBcsType,
|
|
61
|
+
type EnumOutputShape,
|
|
62
|
+
type EnumInputShape,
|
|
63
|
+
type EnumOutputShapeWithKeys,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/** @deprecated use toBase58 instead */
|
|
67
|
+
export const toB58 = toBase58;
|
|
68
|
+
|
|
69
|
+
/** @deprecated use fromBase58 instead */
|
|
70
|
+
export const fromB58 = fromBase58;
|
|
71
|
+
|
|
72
|
+
/** @deprecated use toBase64 instead */
|
|
73
|
+
export const toB64 = toBase64;
|
|
74
|
+
|
|
75
|
+
/** @deprecated use fromBase64 instead */
|
|
76
|
+
export const fromB64 = fromBase64;
|
|
77
|
+
|
|
78
|
+
/** @deprecated use toHex instead */
|
|
79
|
+
export const toHEX = toHex;
|
|
80
|
+
|
|
81
|
+
/** @deprecated use fromHex instead */
|
|
82
|
+
export const fromHEX = fromHex;
|