koilib 5.5.2 → 5.5.4
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/dist/koinos.js +34 -18
- package/dist/koinos.min.js +1 -1
- package/package.json +4 -3
- package/src/Contract.ts +614 -0
- package/src/Provider.ts +512 -0
- package/src/Serializer.ts +366 -0
- package/src/Signer.ts +827 -0
- package/src/Transaction.ts +241 -0
- package/src/index.ts +9 -0
- package/src/index2.ts +17 -0
- package/src/indexUtils.ts +2 -0
- package/src/interface.ts +767 -0
- package/src/jsonDescriptors/chain-proto.json +726 -0
- package/src/jsonDescriptors/pow-proto.json +68 -0
- package/src/jsonDescriptors/token-proto.json +255 -0
- package/src/jsonDescriptors/value-proto.json +161 -0
- package/src/protoModules/protocol-proto.js +8138 -0
- package/src/protoModules/value-proto.js +1736 -0
- package/src/utils.ts +533 -0
- package/src/utilsNode.ts +378 -0
package/src/utilsNode.ts
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { sha256 } from "@noble/hashes/sha256";
|
|
2
|
+
import {
|
|
3
|
+
DictionaryGenesisData,
|
|
4
|
+
GenesisDataDecoded,
|
|
5
|
+
GenesisDataEncoded,
|
|
6
|
+
} from "./interface";
|
|
7
|
+
import { Serializer } from "./Serializer";
|
|
8
|
+
import {
|
|
9
|
+
multihash,
|
|
10
|
+
encodeBase64,
|
|
11
|
+
decodeBase64,
|
|
12
|
+
encodeBase64url,
|
|
13
|
+
decodeBase64url,
|
|
14
|
+
encodeBase58,
|
|
15
|
+
decodeBase58,
|
|
16
|
+
} from "./utils";
|
|
17
|
+
import chainJson from "./jsonDescriptors/chain-proto.json";
|
|
18
|
+
|
|
19
|
+
const defaultAlias: DictionaryGenesisData = {
|
|
20
|
+
"object_key::head_block": { typeName: "block" },
|
|
21
|
+
"object_key::chain_id": {},
|
|
22
|
+
"object_key::genesis_key": { isAddress: true },
|
|
23
|
+
"object_key::resource_limit_data": { typeName: "resource_limit_data" },
|
|
24
|
+
"object_key::max_account_resources": { typeName: "max_account_resources" },
|
|
25
|
+
"object_key::protocol_descriptor": {},
|
|
26
|
+
"object_key::compute_bandwidth_registry": {
|
|
27
|
+
typeName: "compute_bandwidth_registry",
|
|
28
|
+
},
|
|
29
|
+
"object_key::block_hash_code": {},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function prepareDictionary(
|
|
33
|
+
dictionary: DictionaryGenesisData
|
|
34
|
+
): DictionaryGenesisData {
|
|
35
|
+
const serializerChain = new Serializer(chainJson, { bytesConversion: true });
|
|
36
|
+
|
|
37
|
+
const defaultDictionary: DictionaryGenesisData = {};
|
|
38
|
+
Object.keys(defaultAlias).forEach((alias) => {
|
|
39
|
+
const key = encodeBase64(multihash(sha256(alias)));
|
|
40
|
+
defaultDictionary[key] = {
|
|
41
|
+
serializer: serializerChain,
|
|
42
|
+
alias,
|
|
43
|
+
...defaultAlias[alias],
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const dic = {
|
|
48
|
+
...defaultDictionary,
|
|
49
|
+
...dictionary,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return dic;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Function to encode genesis data in order to launch a
|
|
57
|
+
* new blockchain. The different values are serialized using
|
|
58
|
+
* protobuffers. One of the arguments is the dictionary which
|
|
59
|
+
* contains the relevant information to perform the serialization.
|
|
60
|
+
* By default the function contains the dictionary for the
|
|
61
|
+
* following keys:
|
|
62
|
+
*
|
|
63
|
+
* - "object_key::head_block"
|
|
64
|
+
* - "object_key::chain_id"
|
|
65
|
+
* - "object_key::genesis_key"
|
|
66
|
+
* - "object_key::resource_limit_data"
|
|
67
|
+
* - "object_key::max_account_resources"
|
|
68
|
+
* - "object_key::protocol_descriptor"
|
|
69
|
+
* - "object_key::compute_bandwidth_registry"
|
|
70
|
+
* - "object_key::block_hash_code"
|
|
71
|
+
*
|
|
72
|
+
* @param genesisDataDecoded - Genesis data where the values are
|
|
73
|
+
* objects.
|
|
74
|
+
* @param dictionary - Set of keys which contains the relevant
|
|
75
|
+
* information to perform the serialization
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
*
|
|
79
|
+
* ```ts
|
|
80
|
+
* const signer = Signer.fromSeed("seed");
|
|
81
|
+
* const genesisDataDecoded = {
|
|
82
|
+
* entries: [
|
|
83
|
+
* {
|
|
84
|
+
* space: { system: true },
|
|
85
|
+
* alias: "object_key::genesis_key",
|
|
86
|
+
* value: signer.address,
|
|
87
|
+
* },
|
|
88
|
+
* ],
|
|
89
|
+
* };
|
|
90
|
+
*
|
|
91
|
+
* const genesisData = await encodeGenesisData(genesisDataDecoded);
|
|
92
|
+
* console.log(genesisData);
|
|
93
|
+
*
|
|
94
|
+
* // {
|
|
95
|
+
* // entries: [
|
|
96
|
+
* // {
|
|
97
|
+
* // space: { system: true },
|
|
98
|
+
* // key: "EiC3nO+XbeKg4C8ugW7M7XdfmJKY4i3l91KoJWxosQPImA==",
|
|
99
|
+
* // value: "AMpASH7CjUHBpl2QR8E5lGKVjVLAvJRg5g==",
|
|
100
|
+
* // },
|
|
101
|
+
* // ],
|
|
102
|
+
* // }
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @example adding a custom dictionary
|
|
106
|
+
*
|
|
107
|
+
* ```ts
|
|
108
|
+
* const contractId = Signer.fromSeed("seed").address;
|
|
109
|
+
* const zone = encodeBase64(decodeBase58(contractId));
|
|
110
|
+
* const genesisDataDecoded = {
|
|
111
|
+
* entries: [
|
|
112
|
+
* {
|
|
113
|
+
* space: { system: true, zone, id: 1 },
|
|
114
|
+
* key: "difficulty_metadata_key",
|
|
115
|
+
* value: {
|
|
116
|
+
* target: encodeBase64url(toUint8Array("F".repeat(64))),
|
|
117
|
+
* last_block_time: "1641038400000",
|
|
118
|
+
* difficulty: encodeBase64url(toUint8Array("1".repeat(64))),
|
|
119
|
+
* target_block_interval: "10",
|
|
120
|
+
* },
|
|
121
|
+
* },
|
|
122
|
+
* ],
|
|
123
|
+
* };
|
|
124
|
+
*
|
|
125
|
+
* const powJson = {
|
|
126
|
+
* nested: {
|
|
127
|
+
* mypackage: {
|
|
128
|
+
* nested: {
|
|
129
|
+
* difficulty_metadata: {
|
|
130
|
+
* "fields": {
|
|
131
|
+
* "target": { "type": "bytes", "id": 1 },
|
|
132
|
+
* "last_block_time": { "type": "uint64", "id": 2,
|
|
133
|
+
* "options": { "jstype": "JS_STRING" }
|
|
134
|
+
* },
|
|
135
|
+
* "difficulty": { "type": "bytes", "id": 3 },
|
|
136
|
+
* "target_block_interval": { "type": "uint64", "id": 4,
|
|
137
|
+
* "options": { "jstype": "JS_STRING" }
|
|
138
|
+
* }
|
|
139
|
+
* }
|
|
140
|
+
* },
|
|
141
|
+
* }
|
|
142
|
+
* }
|
|
143
|
+
* }
|
|
144
|
+
* }
|
|
145
|
+
*
|
|
146
|
+
* const dic = {
|
|
147
|
+
* difficulty_metadata_key: {
|
|
148
|
+
* serializer: new Serializer(powJson),
|
|
149
|
+
* typeName: "difficulty_metadata",
|
|
150
|
+
* },
|
|
151
|
+
* };
|
|
152
|
+
*
|
|
153
|
+
* const genesisData = await encodeGenesisData(genesisDataDecoded, dic);
|
|
154
|
+
* console.log(genesisData);
|
|
155
|
+
*
|
|
156
|
+
* // {
|
|
157
|
+
* // entries: [
|
|
158
|
+
* // {
|
|
159
|
+
* // key: "difficulty_metadata_key",
|
|
160
|
+
* // space: {
|
|
161
|
+
* // id: 1,
|
|
162
|
+
* // system: true,
|
|
163
|
+
* // zone: "AMpASH7CjUHBpl2QR8E5lGKVjVLAvJRg5g==",
|
|
164
|
+
* // },
|
|
165
|
+
* // value:
|
|
166
|
+
* // "CiD//////////////////////////////////////////xCAlIus4S8aIBERERERERERERERERERERERERERERERERERERERERERIAo=",
|
|
167
|
+
* // },
|
|
168
|
+
* // ],
|
|
169
|
+
* // };
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
export async function encodeGenesisData(
|
|
173
|
+
genesisDataDecoded: GenesisDataDecoded,
|
|
174
|
+
dictionary: DictionaryGenesisData = {}
|
|
175
|
+
): Promise<GenesisDataEncoded> {
|
|
176
|
+
const genesisData: GenesisDataEncoded = {};
|
|
177
|
+
if (!genesisDataDecoded || !genesisDataDecoded.entries) return genesisData;
|
|
178
|
+
const dic = prepareDictionary(dictionary);
|
|
179
|
+
|
|
180
|
+
genesisData.entries = await Promise.all(
|
|
181
|
+
genesisDataDecoded.entries.map(async (entry) => {
|
|
182
|
+
const key = Object.keys(dic).find(
|
|
183
|
+
(k) => k === entry.key || (entry.alias && dic[k].alias === entry.alias)
|
|
184
|
+
);
|
|
185
|
+
if (!key)
|
|
186
|
+
return {
|
|
187
|
+
error: `key ${entry.key!} not found in the dictionary`,
|
|
188
|
+
space: entry.space,
|
|
189
|
+
key: entry.key,
|
|
190
|
+
value: encodeBase64(new Uint8Array()),
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const { isAddress, serializer, typeName } = dic[key];
|
|
194
|
+
let valueBytes: Uint8Array;
|
|
195
|
+
let error = "";
|
|
196
|
+
if (isAddress) {
|
|
197
|
+
valueBytes = decodeBase58(entry.value as string);
|
|
198
|
+
} else if (serializer && typeName) {
|
|
199
|
+
valueBytes = await serializer.serialize(
|
|
200
|
+
entry.value as Record<string, unknown>,
|
|
201
|
+
typeName
|
|
202
|
+
);
|
|
203
|
+
} else {
|
|
204
|
+
valueBytes = new Uint8Array();
|
|
205
|
+
error = "no serializer or typeName defined in the dictionary";
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
...(error && { error }),
|
|
210
|
+
space: entry.space,
|
|
211
|
+
key,
|
|
212
|
+
value: encodeBase64(valueBytes),
|
|
213
|
+
};
|
|
214
|
+
})
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
return genesisData;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Function to decode genesis data used to launch a
|
|
222
|
+
* new blockchain. The different values are deserialized using
|
|
223
|
+
* protobuffers. One of the arguments is the dictionary which
|
|
224
|
+
* contains the relevant information for the deserialization.
|
|
225
|
+
* By default the function contains the dictionary for the
|
|
226
|
+
* following keys:
|
|
227
|
+
*
|
|
228
|
+
* - "object_key::head_block"
|
|
229
|
+
* - "object_key::chain_id"
|
|
230
|
+
* - "object_key::genesis_key"
|
|
231
|
+
* - "object_key::resource_limit_data"
|
|
232
|
+
* - "object_key::max_account_resources"
|
|
233
|
+
* - "object_key::protocol_descriptor"
|
|
234
|
+
* - "object_key::compute_bandwidth_registry"
|
|
235
|
+
* - "object_key::block_hash_code"
|
|
236
|
+
*
|
|
237
|
+
* @param genesisData - Genesis data
|
|
238
|
+
* @param dictionary - Set of keys which contains the relevant
|
|
239
|
+
* information to perform the deserialization
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
*
|
|
243
|
+
* ```ts
|
|
244
|
+
* const genesisData = {
|
|
245
|
+
* entries: [
|
|
246
|
+
* {
|
|
247
|
+
* space: { system: true },
|
|
248
|
+
* key: "EiC3nO+XbeKg4C8ugW7M7XdfmJKY4i3l91KoJWxosQPImA==",
|
|
249
|
+
* value: "AMpASH7CjUHBpl2QR8E5lGKVjVLAvJRg5g==",
|
|
250
|
+
* },
|
|
251
|
+
* ],
|
|
252
|
+
* }
|
|
253
|
+
*
|
|
254
|
+
* const genesisDataDecoded = await decodeGenesisData(genesisData);
|
|
255
|
+
* console.log(genesisDataDecoded);
|
|
256
|
+
*
|
|
257
|
+
* // {
|
|
258
|
+
* // entries: [
|
|
259
|
+
* // {
|
|
260
|
+
* // space: { system: true },
|
|
261
|
+
* // key: "EiC3nO+XbeKg4C8ugW7M7XdfmJKY4i3l91KoJWxosQPImA==",
|
|
262
|
+
* // alias: "object_key::genesis_key",
|
|
263
|
+
* // value: "1KSQWDyUnFZ48Pf2hsW8Akh1b5fKUWc8Z3",
|
|
264
|
+
* // },
|
|
265
|
+
* // ],
|
|
266
|
+
* // };
|
|
267
|
+
* ```
|
|
268
|
+
*
|
|
269
|
+
* @example adding a custom dictionary
|
|
270
|
+
*
|
|
271
|
+
* ```ts
|
|
272
|
+
* const genesisData = {
|
|
273
|
+
* entries: [
|
|
274
|
+
* {
|
|
275
|
+
* key: "difficulty_metadata_key",
|
|
276
|
+
* space: {
|
|
277
|
+
* id: 1,
|
|
278
|
+
* system: true,
|
|
279
|
+
* zone: "AMpASH7CjUHBpl2QR8E5lGKVjVLAvJRg5g==",
|
|
280
|
+
* },
|
|
281
|
+
* value:
|
|
282
|
+
* "CiD//////////////////////////////////////////xCAlIus4S8aIBERERERERERERERERERERERERERERERERERERERERERIAo=",
|
|
283
|
+
* },
|
|
284
|
+
* ],
|
|
285
|
+
* };
|
|
286
|
+
*
|
|
287
|
+
* const powJson = {
|
|
288
|
+
* nested: {
|
|
289
|
+
* mypackage: {
|
|
290
|
+
* nested: {
|
|
291
|
+
* difficulty_metadata: {
|
|
292
|
+
* "fields": {
|
|
293
|
+
* "target": { "type": "bytes", "id": 1 },
|
|
294
|
+
* "last_block_time": { "type": "uint64", "id": 2,
|
|
295
|
+
* "options": { "jstype": "JS_STRING" }
|
|
296
|
+
* },
|
|
297
|
+
* "difficulty": { "type": "bytes", "id": 3 },
|
|
298
|
+
* "target_block_interval": { "type": "uint64", "id": 4,
|
|
299
|
+
* "options": { "jstype": "JS_STRING" }
|
|
300
|
+
* }
|
|
301
|
+
* }
|
|
302
|
+
* },
|
|
303
|
+
* }
|
|
304
|
+
* }
|
|
305
|
+
* }
|
|
306
|
+
* }
|
|
307
|
+
*
|
|
308
|
+
* const dic = {
|
|
309
|
+
* difficulty_metadata_key: {
|
|
310
|
+
* serializer: new Serializer(powJson),
|
|
311
|
+
* typeName: "difficulty_metadata",
|
|
312
|
+
* },
|
|
313
|
+
* };
|
|
314
|
+
*
|
|
315
|
+
* const genesisDataDecoded = await decodeGenesisData(genesisData, dic);
|
|
316
|
+
* console.log(genesisData);
|
|
317
|
+
*
|
|
318
|
+
* // {
|
|
319
|
+
* // entries: [
|
|
320
|
+
* // {
|
|
321
|
+
* // space: { system: true, zone, id: 1 },
|
|
322
|
+
* // key: "difficulty_metadata_key",
|
|
323
|
+
* // value: {
|
|
324
|
+
* // target: "__________________________________________8=",
|
|
325
|
+
* // last_block_time: "1641038400000",
|
|
326
|
+
* // difficulty: "ERERERERERERERERERERERERERERERERERERERERERE=",
|
|
327
|
+
* // target_block_interval: "10",
|
|
328
|
+
* // },
|
|
329
|
+
* // },
|
|
330
|
+
* // ],
|
|
331
|
+
* // };
|
|
332
|
+
* ```
|
|
333
|
+
*/
|
|
334
|
+
export async function decodeGenesisData(
|
|
335
|
+
genesisData: GenesisDataEncoded,
|
|
336
|
+
dictionary: DictionaryGenesisData = {}
|
|
337
|
+
): Promise<GenesisDataDecoded> {
|
|
338
|
+
const genesisDataDecoded: GenesisDataDecoded = {};
|
|
339
|
+
if (!genesisData || !genesisData.entries) return genesisDataDecoded;
|
|
340
|
+
const dic = prepareDictionary(dictionary);
|
|
341
|
+
|
|
342
|
+
genesisDataDecoded.entries = await Promise.all(
|
|
343
|
+
genesisData.entries.map(async (entry) => {
|
|
344
|
+
const key = Object.keys(dic).find((k) => k === entry.key);
|
|
345
|
+
if (!key)
|
|
346
|
+
return {
|
|
347
|
+
error: `key ${entry.key!} not found in the dictionary`,
|
|
348
|
+
...entry,
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
const { isAddress, serializer, typeName, alias } = dic[key];
|
|
352
|
+
|
|
353
|
+
const valueBase64url = encodeBase64url(decodeBase64(entry.value));
|
|
354
|
+
let value: string | Record<string, unknown>;
|
|
355
|
+
let error = "";
|
|
356
|
+
if (isAddress) {
|
|
357
|
+
value = encodeBase58(decodeBase64url(valueBase64url));
|
|
358
|
+
} else if (serializer && typeName) {
|
|
359
|
+
value = await serializer.deserialize(valueBase64url, typeName);
|
|
360
|
+
} else {
|
|
361
|
+
value = valueBase64url;
|
|
362
|
+
error = "no serializer or typeName defined in the dictionary";
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return {
|
|
366
|
+
...(error && { error }),
|
|
367
|
+
space: entry.space,
|
|
368
|
+
key,
|
|
369
|
+
value,
|
|
370
|
+
...(alias && { alias }),
|
|
371
|
+
};
|
|
372
|
+
})
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
return genesisDataDecoded;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export const ChainTypes = chainJson;
|