@alephium/web3 0.36.1 → 0.38.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/dist/alephium-web3.min.js +1 -1
- package/dist/alephium-web3.min.js.map +1 -1
- package/dist/src/api/api-alephium.d.ts +6 -1
- package/dist/src/api/api-alephium.js +1 -1
- package/dist/src/api/types.d.ts +1 -1
- package/dist/src/codec/array-codec.d.ts +17 -0
- package/dist/src/codec/array-codec.js +59 -0
- package/dist/src/codec/asset-output-codec.d.ts +27 -0
- package/dist/src/codec/asset-output-codec.js +135 -0
- package/dist/src/codec/bigint-codec.d.ts +5 -0
- package/dist/src/codec/bigint-codec.js +86 -0
- package/dist/src/codec/bytestring-codec.d.ts +16 -0
- package/dist/src/codec/bytestring-codec.js +50 -0
- package/dist/src/codec/codec.d.ts +8 -0
- package/dist/src/codec/codec.js +9 -0
- package/dist/src/codec/compact-int-codec.d.ts +51 -0
- package/dist/src/codec/compact-int-codec.js +300 -0
- package/dist/src/codec/contract-codec.d.ts +23 -0
- package/dist/src/codec/contract-codec.js +81 -0
- package/dist/src/codec/contract-output-codec.d.ts +21 -0
- package/dist/src/codec/contract-output-codec.js +82 -0
- package/dist/src/codec/contract-output-ref-codec.d.ts +15 -0
- package/dist/src/codec/contract-output-ref-codec.js +38 -0
- package/dist/src/codec/either-codec.d.ts +17 -0
- package/dist/src/codec/either-codec.js +67 -0
- package/dist/src/codec/hash.d.ts +4 -0
- package/dist/src/codec/hash.js +23 -0
- package/dist/src/codec/index.d.ts +23 -0
- package/dist/src/codec/index.js +69 -0
- package/dist/src/codec/input-codec.d.ts +22 -0
- package/dist/src/codec/input-codec.js +71 -0
- package/dist/src/codec/instr-codec.d.ts +230 -0
- package/dist/src/codec/instr-codec.js +471 -0
- package/dist/src/codec/lockup-script-codec.d.ts +28 -0
- package/dist/src/codec/lockup-script-codec.js +80 -0
- package/dist/src/codec/long-codec.d.ts +9 -0
- package/dist/src/codec/long-codec.js +56 -0
- package/dist/src/codec/method-codec.d.ts +31 -0
- package/dist/src/codec/method-codec.js +78 -0
- package/dist/src/codec/option-codec.d.ts +15 -0
- package/dist/src/codec/option-codec.js +55 -0
- package/dist/src/codec/output-codec.d.ts +7 -0
- package/dist/src/codec/output-codec.js +26 -0
- package/dist/src/codec/script-codec.d.ts +16 -0
- package/dist/src/codec/script-codec.js +41 -0
- package/dist/src/codec/signature-codec.d.ts +14 -0
- package/dist/src/codec/signature-codec.js +19 -0
- package/dist/src/codec/signed-int-codec.d.ts +9 -0
- package/dist/src/codec/signed-int-codec.js +39 -0
- package/dist/src/codec/token-codec.d.ts +16 -0
- package/dist/src/codec/token-codec.js +46 -0
- package/dist/src/codec/transaction-codec.d.ts +27 -0
- package/dist/src/codec/transaction-codec.js +128 -0
- package/dist/src/codec/unlock-script-codec.d.ts +40 -0
- package/dist/src/codec/unlock-script-codec.js +170 -0
- package/dist/src/codec/unsigned-tx-codec.d.ts +30 -0
- package/dist/src/codec/unsigned-tx-codec.js +103 -0
- package/dist/src/contract/contract.d.ts +14 -8
- package/dist/src/contract/contract.js +205 -22
- package/dist/src/contract/ralph.d.ts +16 -0
- package/dist/src/contract/ralph.js +127 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +2 -1
- package/package.json +5 -4
- package/src/api/api-alephium.ts +7 -1
- package/src/api/types.ts +1 -1
- package/src/codec/array-codec.ts +63 -0
- package/src/codec/asset-output-codec.ts +149 -0
- package/src/codec/bigint-codec.ts +92 -0
- package/src/codec/bytestring-codec.ts +56 -0
- package/src/codec/codec.ts +31 -0
- package/src/codec/compact-int-codec.ts +316 -0
- package/src/codec/contract-codec.ts +95 -0
- package/src/codec/contract-output-codec.ts +95 -0
- package/src/codec/contract-output-ref-codec.ts +42 -0
- package/src/codec/either-codec.ts +74 -0
- package/src/codec/hash.ts +35 -0
- package/src/codec/index.ts +41 -0
- package/src/codec/input-codec.ts +81 -0
- package/src/codec/instr-codec.ts +479 -0
- package/src/codec/lockup-script-codec.ts +99 -0
- package/src/codec/long-codec.ts +59 -0
- package/src/codec/method-codec.ts +97 -0
- package/src/codec/option-codec.ts +60 -0
- package/src/codec/output-codec.ts +26 -0
- package/src/codec/script-codec.ts +45 -0
- package/src/codec/signature-codec.ts +40 -0
- package/src/codec/signed-int-codec.ts +37 -0
- package/src/codec/token-codec.ts +51 -0
- package/src/codec/transaction-codec.ts +147 -0
- package/src/codec/unlock-script-codec.ts +194 -0
- package/src/codec/unsigned-tx-codec.ts +124 -0
- package/src/contract/contract.ts +299 -23
- package/src/contract/ralph.ts +140 -2
- package/src/index.ts +1 -1
|
@@ -43,7 +43,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
43
43
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
44
44
|
};
|
|
45
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
-
exports.tryGetCallResult = exports.getTokenIdFromUnsignedTx = exports.getContractIdFromUnsignedTx = exports.getContractEventsCurrentCount = exports.multicallMethods = exports.callMethod = exports.subscribeContractEvents = exports.subscribeContractEvent = exports.decodeEvent = exports.subscribeContractDestroyedEvent = exports.subscribeContractCreatedEvent = exports.fetchContractState = exports.ContractInstance = exports.testMethod = exports.addStdIdToFields = exports.subscribeEventsFromContract = exports.decodeContractDestroyedEvent = exports.decodeContractCreatedEvent = exports.
|
|
46
|
+
exports.tryGetCallResult = exports.getTokenIdFromUnsignedTx = exports.getContractIdFromUnsignedTx = exports.getContractEventsCurrentCount = exports.multicallMethods = exports.callMethod = exports.subscribeContractEvents = exports.subscribeContractEvent = exports.decodeEvent = exports.subscribeContractDestroyedEvent = exports.subscribeContractCreatedEvent = exports.fetchContractState = exports.ContractInstance = exports.testMethod = exports.addStdIdToFields = exports.subscribeEventsFromContract = exports.decodeContractDestroyedEvent = exports.decodeContractCreatedEvent = exports.DestroyContractEventAddresses = exports.CreateContractEventAddresses = exports.ExecutableScript = exports.ContractFactory = exports.randomTxId = exports.fromApiEventFields = exports.fromApiArray = exports.getDefaultValue = exports.fromApiFields = exports.Script = exports.Contract = exports.Artifact = exports.Project = exports.Struct = exports.ProjectArtifact = exports.DEFAULT_COMPILER_OPTIONS = exports.DEFAULT_NODE_COMPILER_OPTIONS = exports.StdIdFieldName = void 0;
|
|
47
47
|
const buffer_1 = require("buffer/");
|
|
48
48
|
const fs_1 = __importDefault(require("fs"));
|
|
49
49
|
const fs_2 = require("fs");
|
|
@@ -57,6 +57,7 @@ const constants_1 = require("../constants");
|
|
|
57
57
|
const blake = __importStar(require("blakejs"));
|
|
58
58
|
const error_1 = require("../utils/error");
|
|
59
59
|
const debug_1 = require("../debug");
|
|
60
|
+
const codec_1 = require("../codec");
|
|
60
61
|
const crypto = new utils_1.WebCrypto();
|
|
61
62
|
exports.StdIdFieldName = '__stdInterfaceId';
|
|
62
63
|
var SourceKind;
|
|
@@ -610,7 +611,7 @@ class Artifact {
|
|
|
610
611
|
}
|
|
611
612
|
exports.Artifact = Artifact;
|
|
612
613
|
class Contract extends Artifact {
|
|
613
|
-
constructor(version, name, bytecode, bytecodeDebugPatch, codeHash, codeHashDebug, fieldsSig, eventsSig, functions, constants, enums, structs, stdInterfaceId) {
|
|
614
|
+
constructor(version, name, bytecode, bytecodeDebugPatch, codeHash, codeHashDebug, fieldsSig, eventsSig, functions, constants, enums, structs, mapsSig, stdInterfaceId) {
|
|
614
615
|
super(version, name, functions);
|
|
615
616
|
this.bytecode = bytecode;
|
|
616
617
|
this.bytecodeDebugPatch = bytecodeDebugPatch;
|
|
@@ -620,6 +621,7 @@ class Contract extends Artifact {
|
|
|
620
621
|
this.constants = constants;
|
|
621
622
|
this.enums = enums;
|
|
622
623
|
this.structs = structs;
|
|
624
|
+
this.mapsSig = mapsSig;
|
|
623
625
|
this.stdInterfaceId = stdInterfaceId;
|
|
624
626
|
this.bytecodeDebug = ralph.buildDebugBytecode(this.bytecode, this.bytecodeDebugPatch);
|
|
625
627
|
this.codeHashDebug = codeHashDebug;
|
|
@@ -637,11 +639,11 @@ class Contract extends Artifact {
|
|
|
637
639
|
artifact.functions == null) {
|
|
638
640
|
throw Error('The artifact JSON for contract is incomplete');
|
|
639
641
|
}
|
|
640
|
-
const contract = new Contract(artifact.version, artifact.name, artifact.bytecode, bytecodeDebugPatch, artifact.codeHash, codeHashDebug ? codeHashDebug : artifact.codeHash, artifact.fieldsSig, artifact.eventsSig, artifact.functions, artifact.constants, artifact.enums, structs, artifact.stdInterfaceId === null ? undefined : artifact.stdInterfaceId);
|
|
642
|
+
const contract = new Contract(artifact.version, artifact.name, artifact.bytecode, bytecodeDebugPatch, artifact.codeHash, codeHashDebug ? codeHashDebug : artifact.codeHash, artifact.fieldsSig, artifact.eventsSig, artifact.functions, artifact.constants, artifact.enums, structs, artifact.mapsSig === null ? undefined : artifact.mapsSig, artifact.stdInterfaceId === null ? undefined : artifact.stdInterfaceId);
|
|
641
643
|
return contract;
|
|
642
644
|
}
|
|
643
645
|
static fromCompileResult(result, structs = []) {
|
|
644
|
-
return new Contract(result.version, result.name, result.bytecode, result.bytecodeDebugPatch, result.codeHash, result.codeHashDebug, result.fields, result.events, result.functions, result.constants, result.enums, structs, result.stdInterfaceId);
|
|
646
|
+
return new Contract(result.version, result.name, result.bytecode, result.bytecodeDebugPatch, result.codeHash, result.codeHashDebug, result.fields, result.events, result.functions, result.constants, result.enums, structs, result.maps, result.stdInterfaceId);
|
|
645
647
|
}
|
|
646
648
|
// support both 'code.ral' and 'code.ral.json'
|
|
647
649
|
static async fromArtifactFile(path, bytecodeDebugPatch, codeHashDebug, structs = []) {
|
|
@@ -661,6 +663,9 @@ class Contract extends Artifact {
|
|
|
661
663
|
constants: this.constants,
|
|
662
664
|
enums: this.enums
|
|
663
665
|
};
|
|
666
|
+
if (this.mapsSig !== undefined) {
|
|
667
|
+
object.mapsSig = this.mapsSig;
|
|
668
|
+
}
|
|
664
669
|
if (this.stdInterfaceId !== undefined) {
|
|
665
670
|
object.stdInterfaceId = this.stdInterfaceId;
|
|
666
671
|
}
|
|
@@ -1129,13 +1134,14 @@ class ExecutableScript {
|
|
|
1129
1134
|
}
|
|
1130
1135
|
}
|
|
1131
1136
|
exports.ExecutableScript = ExecutableScript;
|
|
1132
|
-
function specialContractAddress(
|
|
1137
|
+
function specialContractAddress(eventIndex, groupIndex) {
|
|
1133
1138
|
const bytes = new Uint8Array(32).fill(0);
|
|
1134
|
-
bytes[
|
|
1139
|
+
bytes[30] = eventIndex;
|
|
1140
|
+
bytes[31] = groupIndex;
|
|
1135
1141
|
return (0, utils_1.addressFromContractId)((0, utils_1.binToHex)(bytes));
|
|
1136
1142
|
}
|
|
1137
|
-
exports.
|
|
1138
|
-
exports.
|
|
1143
|
+
exports.CreateContractEventAddresses = Array.from(Array(constants_1.TOTAL_NUMBER_OF_GROUPS).keys()).map((groupIndex) => specialContractAddress(Contract.ContractCreatedEventIndex, groupIndex));
|
|
1144
|
+
exports.DestroyContractEventAddresses = Array.from(Array(constants_1.TOTAL_NUMBER_OF_GROUPS).keys()).map((groupIndex) => specialContractAddress(Contract.ContractDestroyedEventIndex, groupIndex));
|
|
1139
1145
|
function decodeSystemEvent(event, eventSig, eventIndex) {
|
|
1140
1146
|
if (event.eventIndex !== eventIndex) {
|
|
1141
1147
|
throw new Error(`Invalid event index: ${event.eventIndex}, expected: ${eventIndex}`);
|
|
@@ -1199,21 +1205,189 @@ function addStdIdToFields(contract, fields) {
|
|
|
1199
1205
|
: { ...fields, __stdInterfaceId: stdInterfaceIdPrefix + contract.stdInterfaceId };
|
|
1200
1206
|
}
|
|
1201
1207
|
exports.addStdIdToFields = addStdIdToFields;
|
|
1202
|
-
|
|
1208
|
+
function calcWrapperContractId(parentContractId, mapIndex, key, keyType, group) {
|
|
1209
|
+
const prefix = ralph.encodeMapPrefix(mapIndex);
|
|
1210
|
+
const encodedKey = ralph.primitiveToByteVec(key, keyType);
|
|
1211
|
+
const path = (0, utils_1.binToHex)(prefix) + (0, utils_1.binToHex)(encodedKey);
|
|
1212
|
+
return (0, utils_1.subContractId)(parentContractId, path, group);
|
|
1213
|
+
}
|
|
1214
|
+
function genCodeForType(type, structs) {
|
|
1215
|
+
const { immFields, mutFields } = ralph.calcFieldSize(type, true, structs);
|
|
1216
|
+
const loadImmFieldByIndex = {
|
|
1217
|
+
isPublic: true,
|
|
1218
|
+
assetModifier: 0,
|
|
1219
|
+
argsLength: 1,
|
|
1220
|
+
localsLength: 1,
|
|
1221
|
+
returnLength: 1,
|
|
1222
|
+
instrs: [(0, codec_1.LoadLocal)(0), codec_1.LoadImmFieldByIndex]
|
|
1223
|
+
};
|
|
1224
|
+
const loadMutFieldByIndex = {
|
|
1225
|
+
...loadImmFieldByIndex,
|
|
1226
|
+
instrs: [(0, codec_1.LoadLocal)(0), codec_1.LoadMutFieldByIndex]
|
|
1227
|
+
};
|
|
1228
|
+
const parentContractIdIndex = immFields;
|
|
1229
|
+
const storeMutFieldByIndex = {
|
|
1230
|
+
...loadImmFieldByIndex,
|
|
1231
|
+
argsLength: 2,
|
|
1232
|
+
localsLength: 2,
|
|
1233
|
+
returnLength: 0,
|
|
1234
|
+
instrs: [
|
|
1235
|
+
codec_1.CallerContractId,
|
|
1236
|
+
(0, codec_1.LoadImmField)(parentContractIdIndex),
|
|
1237
|
+
codec_1.ByteVecEq,
|
|
1238
|
+
codec_1.Assert,
|
|
1239
|
+
(0, codec_1.LoadLocal)(0),
|
|
1240
|
+
(0, codec_1.LoadLocal)(1),
|
|
1241
|
+
codec_1.StoreMutFieldByIndex
|
|
1242
|
+
]
|
|
1243
|
+
};
|
|
1244
|
+
const destroy = {
|
|
1245
|
+
isPublic: true,
|
|
1246
|
+
assetModifier: 2,
|
|
1247
|
+
argsLength: 1,
|
|
1248
|
+
localsLength: 1,
|
|
1249
|
+
returnLength: 0,
|
|
1250
|
+
instrs: [codec_1.CallerContractId, (0, codec_1.LoadImmField)(parentContractIdIndex), codec_1.ByteVecEq, codec_1.Assert, (0, codec_1.LoadLocal)(0), codec_1.DestroySelf]
|
|
1251
|
+
};
|
|
1252
|
+
const c = {
|
|
1253
|
+
fieldLength: immFields + mutFields + 1,
|
|
1254
|
+
methods: [loadImmFieldByIndex, loadMutFieldByIndex, storeMutFieldByIndex, destroy]
|
|
1255
|
+
};
|
|
1256
|
+
const bytecode = codec_1.contract.contractCodec.encode(codec_1.contract.toHalfDecoded(c));
|
|
1257
|
+
const codeHash = blake.blake2b(bytecode, undefined, 32);
|
|
1258
|
+
return { bytecode: (0, utils_1.binToHex)(bytecode), codeHash: (0, utils_1.binToHex)(codeHash) };
|
|
1259
|
+
}
|
|
1260
|
+
function getContractFieldsSig(mapValueType) {
|
|
1261
|
+
return {
|
|
1262
|
+
names: ['value', 'parentContractId'],
|
|
1263
|
+
types: [mapValueType, 'ByteVec'],
|
|
1264
|
+
isMutable: [true, false]
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
function mapToExistingContracts(contract, parentContractId, group, map, mapIndex, type) {
|
|
1268
|
+
const [keyType, valueType] = ralph.parseMapType(type);
|
|
1269
|
+
const generatedContract = genCodeForType(valueType, contract.structs);
|
|
1270
|
+
return Array.from(map.entries()).map(([key, value]) => {
|
|
1271
|
+
const fields = { value, parentContractId };
|
|
1272
|
+
const contractId = calcWrapperContractId(parentContractId, mapIndex, key, keyType, group);
|
|
1273
|
+
return {
|
|
1274
|
+
...generatedContract,
|
|
1275
|
+
address: (0, utils_1.addressFromContractId)(contractId),
|
|
1276
|
+
contractId: contractId,
|
|
1277
|
+
fieldsSig: getContractFieldsSig(valueType),
|
|
1278
|
+
fields,
|
|
1279
|
+
asset: { alphAmount: constants_1.ONE_ALPH }
|
|
1280
|
+
};
|
|
1281
|
+
});
|
|
1282
|
+
}
|
|
1283
|
+
function mapsToExistingContracts(contract, parentContractId, group, initialMaps) {
|
|
1284
|
+
const mapsSig = contract.mapsSig;
|
|
1285
|
+
if (mapsSig === undefined)
|
|
1286
|
+
return [];
|
|
1287
|
+
const contractStates = [];
|
|
1288
|
+
Object.keys(initialMaps).forEach((name) => {
|
|
1289
|
+
const index = mapsSig.names.findIndex((n) => n === name);
|
|
1290
|
+
if (index === -1)
|
|
1291
|
+
throw new Error(`Map var ${name} does not exist in contract ${contract.name}`);
|
|
1292
|
+
const mapType = mapsSig.types[`${index}`];
|
|
1293
|
+
const states = mapToExistingContracts(contract, parentContractId, group, initialMaps[`${name}`], index, mapType);
|
|
1294
|
+
contractStates.push(...states);
|
|
1295
|
+
});
|
|
1296
|
+
return contractStates;
|
|
1297
|
+
}
|
|
1298
|
+
async function testMethod(factory, methodName, params) {
|
|
1203
1299
|
const txId = params?.txId ?? randomTxId();
|
|
1204
|
-
const
|
|
1205
|
-
const
|
|
1300
|
+
const contract = factory.contract;
|
|
1301
|
+
const address = params.address ?? (0, utils_1.addressFromContractId)((0, utils_1.binToHex)(crypto.getRandomValues(new Uint8Array(32))));
|
|
1302
|
+
const contractId = (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(address));
|
|
1303
|
+
const group = params.group ?? 0;
|
|
1304
|
+
const initialMaps = params.initialMaps ?? {};
|
|
1305
|
+
const contractStates = mapsToExistingContracts(contract, contractId, group, initialMaps);
|
|
1306
|
+
const apiParams = contract.toApiTestContractParams(methodName, {
|
|
1206
1307
|
...params,
|
|
1308
|
+
address,
|
|
1207
1309
|
txId: txId,
|
|
1208
|
-
initialFields: addStdIdToFields(contract
|
|
1209
|
-
testArgs: params.testArgs === undefined ? {} : params.testArgs
|
|
1310
|
+
initialFields: addStdIdToFields(contract, params.initialFields ?? {}),
|
|
1311
|
+
testArgs: params.testArgs === undefined ? {} : params.testArgs,
|
|
1312
|
+
existingContracts: (params.existingContracts ?? []).concat(contractStates)
|
|
1210
1313
|
});
|
|
1211
1314
|
const apiResult = await (0, global_1.getCurrentNodeProvider)().contracts.postContractsTestContract(apiParams);
|
|
1212
|
-
const
|
|
1213
|
-
contract.
|
|
1214
|
-
|
|
1315
|
+
const maps = existingContractsToMaps(contract, address, group, apiResult, initialMaps);
|
|
1316
|
+
const testResult = contract.fromApiTestContractResult(methodName, apiResult, txId);
|
|
1317
|
+
contract.printDebugMessages(methodName, testResult.debugMessages);
|
|
1318
|
+
return {
|
|
1319
|
+
...testResult,
|
|
1320
|
+
maps
|
|
1321
|
+
};
|
|
1215
1322
|
}
|
|
1216
1323
|
exports.testMethod = testMethod;
|
|
1324
|
+
function buildMapInfo(contract, fields) {
|
|
1325
|
+
const mapsSig = contract.mapsSig;
|
|
1326
|
+
if (mapsSig === undefined)
|
|
1327
|
+
return [];
|
|
1328
|
+
return mapsSig.names.map((name, index) => {
|
|
1329
|
+
const mapType = mapsSig.types[`${index}`];
|
|
1330
|
+
const value = (fields[`${name}`] ?? new Map());
|
|
1331
|
+
const [keyType, valueType] = ralph.parseMapType(mapType);
|
|
1332
|
+
return { name, value, keyType, valueType, index };
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
function extractFromEventLog(contract, result, allMaps, address, group) {
|
|
1336
|
+
const parentContractId = (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(address));
|
|
1337
|
+
const newInserted = [];
|
|
1338
|
+
result.debugMessages.forEach((message) => {
|
|
1339
|
+
if (message.contractAddress !== address)
|
|
1340
|
+
return;
|
|
1341
|
+
const decoded = ralph.tryDecodeMapDebugLog(message.message);
|
|
1342
|
+
if (decoded === undefined)
|
|
1343
|
+
return;
|
|
1344
|
+
const map = allMaps[`${decoded.mapIndex}`];
|
|
1345
|
+
const decodedKey = ralph.decodePrimitive(decoded.encodedKey, map.keyType);
|
|
1346
|
+
const contractId = (0, utils_1.subContractId)(parentContractId, decoded.path, group);
|
|
1347
|
+
if (!decoded.isInsert) {
|
|
1348
|
+
map.value.delete(decodedKey);
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
const state = result.contracts.find((s) => s.address === (0, utils_1.addressFromContractId)(contractId));
|
|
1352
|
+
if (state === undefined) {
|
|
1353
|
+
throw new Error(`Cannot find contract state for map value, map field: ${map.name}, value type: ${map.valueType}`);
|
|
1354
|
+
}
|
|
1355
|
+
newInserted.push(state.address);
|
|
1356
|
+
const fieldsSig = getContractFieldsSig(map.valueType);
|
|
1357
|
+
const fields = fromApiFields(state.immFields, state.mutFields, fieldsSig, contract.structs);
|
|
1358
|
+
map.value.set(decodedKey, fields['value']);
|
|
1359
|
+
});
|
|
1360
|
+
return newInserted;
|
|
1361
|
+
}
|
|
1362
|
+
function updateMaps(contract, result, allMaps, address, group) {
|
|
1363
|
+
const parentContractId = (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(address));
|
|
1364
|
+
const updated = [];
|
|
1365
|
+
allMaps.forEach((map) => {
|
|
1366
|
+
Array.from(map.value.keys()).forEach((key) => {
|
|
1367
|
+
const contractId = calcWrapperContractId(parentContractId, map.index, key, map.keyType, group);
|
|
1368
|
+
const updatedState = result.contracts.find((s) => s.address === (0, utils_1.addressFromContractId)(contractId));
|
|
1369
|
+
if (updatedState === undefined)
|
|
1370
|
+
return;
|
|
1371
|
+
updated.push(updatedState.address);
|
|
1372
|
+
const fieldsSig = getContractFieldsSig(map.valueType);
|
|
1373
|
+
const fields = fromApiFields(updatedState.immFields, updatedState.mutFields, fieldsSig, contract.structs);
|
|
1374
|
+
map.value.set(key, fields['value']);
|
|
1375
|
+
});
|
|
1376
|
+
});
|
|
1377
|
+
return updated;
|
|
1378
|
+
}
|
|
1379
|
+
function existingContractsToMaps(contract, address, group, result, maps) {
|
|
1380
|
+
const allMaps = buildMapInfo(contract, maps);
|
|
1381
|
+
const updated = updateMaps(contract, result, allMaps, address, group);
|
|
1382
|
+
const newInserted = extractFromEventLog(contract, result, allMaps, address, group);
|
|
1383
|
+
const mapEntries = updated.concat(newInserted);
|
|
1384
|
+
const remainContracts = result.contracts.filter((c) => mapEntries.find((addr) => c.address === addr) === undefined);
|
|
1385
|
+
result.contracts = remainContracts;
|
|
1386
|
+
return allMaps.reduce((acc, map) => {
|
|
1387
|
+
acc[`${map.name}`] = map.value;
|
|
1388
|
+
return acc;
|
|
1389
|
+
}, {});
|
|
1390
|
+
}
|
|
1217
1391
|
class ContractInstance {
|
|
1218
1392
|
constructor(address) {
|
|
1219
1393
|
this.address = address;
|
|
@@ -1231,20 +1405,29 @@ async function fetchContractState(contract, instance) {
|
|
|
1231
1405
|
};
|
|
1232
1406
|
}
|
|
1233
1407
|
exports.fetchContractState = fetchContractState;
|
|
1234
|
-
function
|
|
1235
|
-
|
|
1408
|
+
function checkGroupIndex(groupIndex) {
|
|
1409
|
+
if (groupIndex < 0 || groupIndex >= constants_1.TOTAL_NUMBER_OF_GROUPS) {
|
|
1410
|
+
throw new Error(`Invalid group index ${groupIndex}, expected a value within the range [0, ${constants_1.TOTAL_NUMBER_OF_GROUPS})`);
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
function subscribeContractCreatedEvent(options, fromGroup, fromCount) {
|
|
1414
|
+
checkGroupIndex(fromGroup);
|
|
1415
|
+
const contractAddress = exports.CreateContractEventAddresses[`${fromGroup}`];
|
|
1416
|
+
return subscribeEventsFromContract(options, contractAddress, Contract.ContractCreatedEventIndex, (event) => {
|
|
1236
1417
|
return {
|
|
1237
1418
|
...decodeContractCreatedEvent(event),
|
|
1238
|
-
contractAddress:
|
|
1419
|
+
contractAddress: contractAddress
|
|
1239
1420
|
};
|
|
1240
1421
|
}, fromCount);
|
|
1241
1422
|
}
|
|
1242
1423
|
exports.subscribeContractCreatedEvent = subscribeContractCreatedEvent;
|
|
1243
|
-
function subscribeContractDestroyedEvent(options, fromCount) {
|
|
1244
|
-
|
|
1424
|
+
function subscribeContractDestroyedEvent(options, fromGroup, fromCount) {
|
|
1425
|
+
checkGroupIndex(fromGroup);
|
|
1426
|
+
const contractAddress = exports.DestroyContractEventAddresses[`${fromGroup}`];
|
|
1427
|
+
return subscribeEventsFromContract(options, contractAddress, Contract.ContractDestroyedEventIndex, (event) => {
|
|
1245
1428
|
return {
|
|
1246
1429
|
...decodeContractDestroyedEvent(event),
|
|
1247
|
-
contractAddress:
|
|
1430
|
+
contractAddress: contractAddress
|
|
1248
1431
|
};
|
|
1249
1432
|
}, fromCount);
|
|
1250
1433
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Val } from '../api';
|
|
2
2
|
import { Fields, FieldsSig, Struct } from './contract';
|
|
3
3
|
export declare function encodeBool(bool: boolean): Uint8Array;
|
|
4
|
+
export declare function decodeBool(bytes: Uint8Array): boolean;
|
|
4
5
|
export declare function encodeI256(i256: bigint): Uint8Array;
|
|
5
6
|
export declare function encodeU256(u256: bigint): Uint8Array;
|
|
6
7
|
export declare function encodeByteVec(bytes: string): Uint8Array;
|
|
@@ -19,6 +20,21 @@ export declare function encodeVmByteVec(bytes: string): Uint8Array;
|
|
|
19
20
|
export declare function encodeVmAddress(address: string): Uint8Array;
|
|
20
21
|
export declare function encodeScriptFieldAsString(tpe: string, value: Val): string;
|
|
21
22
|
export declare function encodeScriptField(tpe: string, value: Val): Uint8Array;
|
|
23
|
+
export declare function splitFields(fieldsSig: FieldsSig): [FieldsSig, FieldsSig];
|
|
24
|
+
export declare function parseMapType(type: string): [string, string];
|
|
25
|
+
export declare function encodeMapPrefix(mapIndex: number): Uint8Array;
|
|
26
|
+
export declare function calcFieldSize(type: string, isMutable: boolean, structs: Struct[]): {
|
|
27
|
+
immFields: number;
|
|
28
|
+
mutFields: number;
|
|
29
|
+
};
|
|
30
|
+
export declare function tryDecodeMapDebugLog(message: string): {
|
|
31
|
+
path: string;
|
|
32
|
+
mapIndex: number;
|
|
33
|
+
encodedKey: Uint8Array;
|
|
34
|
+
isInsert: boolean;
|
|
35
|
+
} | undefined;
|
|
36
|
+
export declare function decodePrimitive(value: Uint8Array, type: string): Val;
|
|
37
|
+
export declare function primitiveToByteVec(value: Val, type: string): Uint8Array;
|
|
22
38
|
export declare function flattenFields(fields: Fields, names: string[], types: string[], isMutable: boolean[], structs: Struct[]): {
|
|
23
39
|
name: string;
|
|
24
40
|
type: string;
|
|
@@ -18,10 +18,11 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
18
18
|
*/
|
|
19
19
|
var _a;
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.buildDebugBytecode = exports.encodeContractField = exports.buildContractByteCode = exports.buildScriptByteCode = exports.flattenFields = exports.encodeScriptField = exports.encodeScriptFieldAsString = exports.encodeVmAddress = exports.encodeVmByteVec = exports.encodeVmU256 = exports.encodeVmI256 = exports.encodeVmBool = exports.VmValType = exports.encodeAddress = exports.encodeByteVec = exports.encodeU256 = exports.encodeI256 = exports.encodeBool = void 0;
|
|
21
|
+
exports.buildDebugBytecode = exports.encodeContractField = exports.buildContractByteCode = exports.buildScriptByteCode = exports.flattenFields = exports.primitiveToByteVec = exports.decodePrimitive = exports.tryDecodeMapDebugLog = exports.calcFieldSize = exports.encodeMapPrefix = exports.parseMapType = exports.splitFields = exports.encodeScriptField = exports.encodeScriptFieldAsString = exports.encodeVmAddress = exports.encodeVmByteVec = exports.encodeVmU256 = exports.encodeVmI256 = exports.encodeVmBool = exports.VmValType = exports.encodeAddress = exports.encodeByteVec = exports.encodeU256 = exports.encodeI256 = exports.decodeBool = exports.encodeBool = void 0;
|
|
22
22
|
const buffer_1 = require("buffer/");
|
|
23
23
|
const api_1 = require("../api");
|
|
24
24
|
const utils_1 = require("../utils");
|
|
25
|
+
const codec_1 = require("../codec");
|
|
25
26
|
const bigIntZero = BigInt(0);
|
|
26
27
|
class UnSigned {
|
|
27
28
|
}
|
|
@@ -50,6 +51,13 @@ function encodeBool(bool) {
|
|
|
50
51
|
return bool ? Uint8Array.from([1]) : Uint8Array.from([0]);
|
|
51
52
|
}
|
|
52
53
|
exports.encodeBool = encodeBool;
|
|
54
|
+
function decodeBool(bytes) {
|
|
55
|
+
if (bytes.length !== 1) {
|
|
56
|
+
throw new Error(`Expected one byte for encoded bool, got ${bytes.length}`);
|
|
57
|
+
}
|
|
58
|
+
return bytes[0] === 1 ? true : false;
|
|
59
|
+
}
|
|
60
|
+
exports.decodeBool = decodeBool;
|
|
53
61
|
function encodeI256(i256) {
|
|
54
62
|
if (i256 >= bigIntZero) {
|
|
55
63
|
return encodeI256Positive(i256);
|
|
@@ -250,6 +258,124 @@ function encodeScriptField(tpe, value) {
|
|
|
250
258
|
throw invalidScriptField(tpe, value);
|
|
251
259
|
}
|
|
252
260
|
exports.encodeScriptField = encodeScriptField;
|
|
261
|
+
function splitFields(fieldsSig) {
|
|
262
|
+
return fieldsSig.types.reduce(([mapFields, fieldsExceptMaps], type, index) => {
|
|
263
|
+
const fieldSig = type.startsWith('Map[') ? mapFields : fieldsExceptMaps;
|
|
264
|
+
fieldSig.names.push(fieldsSig.names[`${index}`]);
|
|
265
|
+
fieldSig.types.push(type);
|
|
266
|
+
fieldSig.isMutable.push(fieldsSig.isMutable[`${index}`]);
|
|
267
|
+
return [mapFields, fieldsExceptMaps];
|
|
268
|
+
}, [
|
|
269
|
+
{ names: [], types: [], isMutable: [] },
|
|
270
|
+
{ names: [], types: [], isMutable: [] }
|
|
271
|
+
]);
|
|
272
|
+
}
|
|
273
|
+
exports.splitFields = splitFields;
|
|
274
|
+
function parseMapType(type) {
|
|
275
|
+
if (!type.startsWith('Map[')) {
|
|
276
|
+
throw new Error(`Expected map type, got ${type}`);
|
|
277
|
+
}
|
|
278
|
+
const keyStartIndex = type.indexOf('[');
|
|
279
|
+
const keyEndIndex = type.indexOf(',');
|
|
280
|
+
return [type.slice(keyStartIndex + 1, keyEndIndex), type.slice(keyEndIndex + 1, type.length - 1)];
|
|
281
|
+
}
|
|
282
|
+
exports.parseMapType = parseMapType;
|
|
283
|
+
function encodeMapPrefix(mapIndex) {
|
|
284
|
+
const str = `__map__${mapIndex}__`;
|
|
285
|
+
const bytes = new Uint8Array(str.length);
|
|
286
|
+
for (let i = 0; i < str.length; i += 1) {
|
|
287
|
+
bytes[i] = str.charCodeAt(i);
|
|
288
|
+
}
|
|
289
|
+
return bytes;
|
|
290
|
+
}
|
|
291
|
+
exports.encodeMapPrefix = encodeMapPrefix;
|
|
292
|
+
function fromAscii(str) {
|
|
293
|
+
let result = '';
|
|
294
|
+
for (let i = 0; i < str.length; i += 2) {
|
|
295
|
+
const ascii = parseInt(str.slice(i, i + 2), 16);
|
|
296
|
+
result += String.fromCharCode(ascii);
|
|
297
|
+
}
|
|
298
|
+
return result;
|
|
299
|
+
}
|
|
300
|
+
function calcFieldSize(type, isMutable, structs) {
|
|
301
|
+
const struct = structs.find((s) => s.name === type);
|
|
302
|
+
if (struct !== undefined) {
|
|
303
|
+
return struct.fieldTypes.reduce((acc, fieldType, index) => {
|
|
304
|
+
const isFieldMutable = isMutable && struct.isMutable[`${index}`];
|
|
305
|
+
const subFieldSize = calcFieldSize(fieldType, isFieldMutable, structs);
|
|
306
|
+
return {
|
|
307
|
+
immFields: acc.immFields + subFieldSize.immFields,
|
|
308
|
+
mutFields: acc.mutFields + subFieldSize.mutFields
|
|
309
|
+
};
|
|
310
|
+
}, { immFields: 0, mutFields: 0 });
|
|
311
|
+
}
|
|
312
|
+
if (type.startsWith('[')) {
|
|
313
|
+
const [baseType, size] = (0, api_1.decodeArrayType)(type);
|
|
314
|
+
const base = calcFieldSize(baseType, isMutable, structs);
|
|
315
|
+
return { immFields: base.immFields * size, mutFields: base.mutFields * size };
|
|
316
|
+
}
|
|
317
|
+
return isMutable ? { immFields: 0, mutFields: 1 } : { immFields: 1, mutFields: 0 };
|
|
318
|
+
}
|
|
319
|
+
exports.calcFieldSize = calcFieldSize;
|
|
320
|
+
function tryDecodeMapDebugLog(message) {
|
|
321
|
+
const prefix = '5f5f6d61705f5f'; // __map__
|
|
322
|
+
const parts = message.split(',');
|
|
323
|
+
if (!message.startsWith(prefix) || parts.length !== 2)
|
|
324
|
+
return undefined;
|
|
325
|
+
if (parts[1] !== 'true' && parts[1] !== 'false')
|
|
326
|
+
return undefined;
|
|
327
|
+
if (!(0, utils_1.isHexString)(parts[0]))
|
|
328
|
+
return undefined;
|
|
329
|
+
const remain = parts[0].slice(prefix.length);
|
|
330
|
+
const suffixIndex = remain.indexOf('5f5f'); // __
|
|
331
|
+
if (suffixIndex === -1)
|
|
332
|
+
return undefined;
|
|
333
|
+
const encodedMapIndex = remain.slice(0, suffixIndex);
|
|
334
|
+
const mapIndex = parseInt(fromAscii(encodedMapIndex));
|
|
335
|
+
const encodedKey = (0, utils_1.hexToBinUnsafe)(remain.slice(suffixIndex + 4));
|
|
336
|
+
const isInsert = parts[1] === 'true' ? true : false;
|
|
337
|
+
return { path: parts[0], mapIndex, encodedKey, isInsert };
|
|
338
|
+
}
|
|
339
|
+
exports.tryDecodeMapDebugLog = tryDecodeMapDebugLog;
|
|
340
|
+
function decodePrimitive(value, type) {
|
|
341
|
+
switch (type) {
|
|
342
|
+
case 'Bool':
|
|
343
|
+
return decodeBool(value);
|
|
344
|
+
case 'I256':
|
|
345
|
+
return codec_1.compactSignedIntCodec.decodeI256(buffer_1.Buffer.from(value));
|
|
346
|
+
case 'U256':
|
|
347
|
+
return codec_1.compactUnsignedIntCodec.decodeU256(buffer_1.Buffer.from(value));
|
|
348
|
+
case 'ByteVec':
|
|
349
|
+
return (0, utils_1.binToHex)(value);
|
|
350
|
+
case 'Address':
|
|
351
|
+
return utils_1.bs58.encode(value);
|
|
352
|
+
default:
|
|
353
|
+
throw Error(`Expected primitive type, got ${type}`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
exports.decodePrimitive = decodePrimitive;
|
|
357
|
+
function primitiveToByteVec(value, type) {
|
|
358
|
+
switch (type) {
|
|
359
|
+
case 'Bool':
|
|
360
|
+
const byte = (0, api_1.toApiBoolean)(value) ? 1 : 0;
|
|
361
|
+
return new Uint8Array([byte]);
|
|
362
|
+
case 'I256':
|
|
363
|
+
const i256 = (0, api_1.toApiNumber256)(value);
|
|
364
|
+
return encodeI256(BigInt(i256));
|
|
365
|
+
case 'U256':
|
|
366
|
+
const u256 = (0, api_1.toApiNumber256)(value);
|
|
367
|
+
return encodeU256(BigInt(u256));
|
|
368
|
+
case 'ByteVec':
|
|
369
|
+
const hexStr = (0, api_1.toApiByteVec)(value);
|
|
370
|
+
return encodeByteVec(hexStr);
|
|
371
|
+
case 'Address':
|
|
372
|
+
const address = (0, api_1.toApiAddress)(value);
|
|
373
|
+
return encodeAddress(address);
|
|
374
|
+
default:
|
|
375
|
+
throw Error(`Expected primitive type, got ${type}`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
exports.primitiveToByteVec = primitiveToByteVec;
|
|
253
379
|
function flattenFields(fields, names, types, isMutable, structs) {
|
|
254
380
|
return names.flatMap((name, index) => {
|
|
255
381
|
if (!(name in fields)) {
|
package/dist/src/index.d.ts
CHANGED
package/dist/src/index.js
CHANGED
|
@@ -43,7 +43,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
43
43
|
return result;
|
|
44
44
|
};
|
|
45
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
-
exports.utils = exports.web3 = void 0;
|
|
46
|
+
exports.utils = exports.codec = exports.web3 = void 0;
|
|
47
47
|
BigInt.prototype['toJSON'] = function () {
|
|
48
48
|
return this.toString();
|
|
49
49
|
};
|
|
@@ -55,5 +55,6 @@ __exportStar(require("./transaction"), exports);
|
|
|
55
55
|
__exportStar(require("./token"), exports);
|
|
56
56
|
__exportStar(require("./constants"), exports);
|
|
57
57
|
exports.web3 = __importStar(require("./global"));
|
|
58
|
+
exports.codec = __importStar(require("./codec"));
|
|
58
59
|
exports.utils = __importStar(require("./utils"));
|
|
59
60
|
__exportStar(require("./debug"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alephium/web3",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "A JS/TS library to interact with the Alephium platform",
|
|
5
5
|
"license": "GPL",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"author": "Alephium dev <dev@alephium.org>",
|
|
29
29
|
"config": {
|
|
30
|
-
"alephium_version": "2.
|
|
30
|
+
"alephium_version": "2.11.0",
|
|
31
31
|
"explorer_backend_version": "1.17.0"
|
|
32
32
|
},
|
|
33
33
|
"type": "commonjs",
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"elliptic": "6.5.4",
|
|
44
44
|
"eventemitter3": "^4.0.7",
|
|
45
45
|
"path-browserify": "^1.0.1",
|
|
46
|
-
"stream-browserify": "^3.0.0"
|
|
46
|
+
"stream-browserify": "^3.0.0",
|
|
47
|
+
"binary-parser": "2.2.1"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
50
|
"@babel/eslint-parser": "^7.21.3",
|
|
@@ -89,7 +90,7 @@
|
|
|
89
90
|
"build": "rm -rf dist/* && npx tsc --build . && webpack",
|
|
90
91
|
"test": "jest -i --config ./jest-config.json",
|
|
91
92
|
"update-schemas": "npm run update-schema:alephium && npm run update-schema:explorer",
|
|
92
|
-
"update-schema:alephium": "npx swagger-typescript-api --disable-throw-on-error -t ./configs -o ./src/api -n api-alephium.ts -p https://raw.githubusercontent.com/alephium/alephium/
|
|
93
|
+
"update-schema:alephium": "npx swagger-typescript-api --disable-throw-on-error -t ./configs -o ./src/api -n api-alephium.ts -p https://raw.githubusercontent.com/alephium/alephium/rhone-upgrade/api/src/main/resources/openapi.json",
|
|
93
94
|
"update-schema:explorer": "npx swagger-typescript-api --disable-throw-on-error -t ./configs -o ./src/api -n api-explorer.ts -p https://raw.githubusercontent.com/alephium/explorer-backend/v${npm_package_config_explorer_backend_version}/app/src/main/resources/explorer-backend-openapi.json",
|
|
94
95
|
"check-versions": "node scripts/check-versions.js ${npm_package_config_alephium_version} ${npm_package_config_explorer_backend_version}"
|
|
95
96
|
}
|
package/src/api/api-alephium.ts
CHANGED
|
@@ -424,6 +424,7 @@ export interface CompileContractResult {
|
|
|
424
424
|
enums: Enum[]
|
|
425
425
|
events: EventSig[]
|
|
426
426
|
warnings: string[]
|
|
427
|
+
maps?: MapsSig
|
|
427
428
|
stdInterfaceId?: string
|
|
428
429
|
}
|
|
429
430
|
|
|
@@ -658,6 +659,11 @@ export interface InternalServerError {
|
|
|
658
659
|
detail: string
|
|
659
660
|
}
|
|
660
661
|
|
|
662
|
+
export interface MapsSig {
|
|
663
|
+
names: string[]
|
|
664
|
+
types: string[]
|
|
665
|
+
}
|
|
666
|
+
|
|
661
667
|
export interface MemPooled {
|
|
662
668
|
type: string
|
|
663
669
|
}
|
|
@@ -1300,7 +1306,7 @@ export class HttpClient<SecurityDataType = unknown> {
|
|
|
1300
1306
|
|
|
1301
1307
|
/**
|
|
1302
1308
|
* @title Alephium API
|
|
1303
|
-
* @version 2.
|
|
1309
|
+
* @version 2.11.0
|
|
1304
1310
|
* @baseUrl ../
|
|
1305
1311
|
*/
|
|
1306
1312
|
export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
|
package/src/api/types.ts
CHANGED
|
@@ -22,7 +22,7 @@ import { assertType, bs58, Eq, isBase58, isHexString } from '../utils'
|
|
|
22
22
|
import * as node from './api-alephium'
|
|
23
23
|
|
|
24
24
|
export type Number256 = bigint | string
|
|
25
|
-
export type Val = Number256 | boolean | string | Val[] | ValObject
|
|
25
|
+
export type Val = Number256 | boolean | string | Val[] | ValObject | Map<Val, Val>
|
|
26
26
|
// eslint-disable-next-line
|
|
27
27
|
export interface ValObject extends Record<string, Val> {} // bypassing typescript recursive type limitations
|
|
28
28
|
export type NamedVals = Record<string, Val>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2018 - 2022 The Alephium Authors
|
|
3
|
+
This file is part of the alephium project.
|
|
4
|
+
|
|
5
|
+
The library is free software: you can redistribute it and/or modify
|
|
6
|
+
it under the terms of the GNU Lesser General Public License as published by
|
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
The library is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU Lesser General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU Lesser General Public License
|
|
16
|
+
along with the library. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
18
|
+
import { Buffer } from 'buffer/'
|
|
19
|
+
import { Parser } from 'binary-parser'
|
|
20
|
+
import { compactSignedIntCodec, compactUnsignedIntCodec, DecodedCompactInt } from './compact-int-codec'
|
|
21
|
+
import { Codec } from './codec'
|
|
22
|
+
|
|
23
|
+
export interface DecodedArray<T> {
|
|
24
|
+
length: DecodedCompactInt
|
|
25
|
+
value: T[]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class ArrayCodec<T> implements Codec<T[]> {
|
|
29
|
+
constructor(private childCodec: Codec<T>, public parser = ArrayCodec.arrayParser(childCodec.parser)) {}
|
|
30
|
+
|
|
31
|
+
encode(input: T[]): Buffer {
|
|
32
|
+
const result = [...compactSignedIntCodec.encodeI256(BigInt(input.length))]
|
|
33
|
+
for (const element of input) {
|
|
34
|
+
result.push(...this.childCodec.encode(element))
|
|
35
|
+
}
|
|
36
|
+
return Buffer.from(result)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
decode(input: Buffer): T[] {
|
|
40
|
+
const result = this.parser.parse(input)
|
|
41
|
+
return result.value.map((v) => this.childCodec.decode(v.value))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static arrayParser(parser: Parser) {
|
|
45
|
+
return new Parser()
|
|
46
|
+
.nest('length', {
|
|
47
|
+
type: compactSignedIntCodec.parser
|
|
48
|
+
})
|
|
49
|
+
.array('value', {
|
|
50
|
+
length: function (ctx) {
|
|
51
|
+
return compactSignedIntCodec.toI32(this['length']! as any as DecodedCompactInt)
|
|
52
|
+
},
|
|
53
|
+
type: parser
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
fromArray(inputs: T[]): DecodedArray<T> {
|
|
58
|
+
return {
|
|
59
|
+
length: compactUnsignedIntCodec.fromU32(inputs.length),
|
|
60
|
+
value: inputs
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|