@alephium/web3 0.37.0 → 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 +5 -0
- 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 +10 -4
- package/dist/src/contract/contract.js +184 -11
- 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 +4 -3
- package/src/api/api-alephium.ts +6 -0
- 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 +271 -14
- package/src/contract/ralph.ts +140 -2
- package/src/index.ts +1 -1
|
@@ -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",
|
|
@@ -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
|
}
|
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
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
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 { ArrayCodec, DecodedArray } from './array-codec'
|
|
21
|
+
import { DecodedCompactInt, compactUnsignedIntCodec } from './compact-int-codec'
|
|
22
|
+
import { signedIntCodec } from './signed-int-codec'
|
|
23
|
+
import { longCodec } from './long-codec'
|
|
24
|
+
import { ByteString, byteStringCodec } from './bytestring-codec'
|
|
25
|
+
import { LockupScript, MultiSig, P2C, P2SH, lockupScriptCodec } from './lockup-script-codec'
|
|
26
|
+
import { FixedAssetOutput } from '../api/api-alephium'
|
|
27
|
+
import { blakeHash, createHint } from './hash'
|
|
28
|
+
import { bs58, binToHex } from '../utils'
|
|
29
|
+
import { Codec } from './codec'
|
|
30
|
+
import { PublicKeyHash } from './lockup-script-codec'
|
|
31
|
+
import { Token, tokensCodec } from './token-codec'
|
|
32
|
+
|
|
33
|
+
export interface AssetOutput {
|
|
34
|
+
amount: DecodedCompactInt
|
|
35
|
+
lockupScript: LockupScript
|
|
36
|
+
lockTime: Buffer
|
|
37
|
+
tokens: DecodedArray<Token>
|
|
38
|
+
additionalData: ByteString
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class AssetOutputCodec implements Codec<AssetOutput> {
|
|
42
|
+
parser = Parser.start()
|
|
43
|
+
.nest('amount', {
|
|
44
|
+
type: compactUnsignedIntCodec.parser
|
|
45
|
+
})
|
|
46
|
+
.nest('lockupScript', {
|
|
47
|
+
type: lockupScriptCodec.parser
|
|
48
|
+
})
|
|
49
|
+
.buffer('lockTime', {
|
|
50
|
+
length: 8
|
|
51
|
+
})
|
|
52
|
+
.nest('tokens', {
|
|
53
|
+
type: tokensCodec.parser
|
|
54
|
+
})
|
|
55
|
+
.nest('additionalData', {
|
|
56
|
+
type: byteStringCodec.parser
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
encode(input: AssetOutput): Buffer {
|
|
60
|
+
const amount = Buffer.from(compactUnsignedIntCodec.encode(input.amount))
|
|
61
|
+
const lockupScript = lockupScriptCodec.encode(input.lockupScript)
|
|
62
|
+
const lockTime = Buffer.from(input.lockTime)
|
|
63
|
+
const tokens = Buffer.from(tokensCodec.encode(input.tokens.value))
|
|
64
|
+
const additionalData = Buffer.from(byteStringCodec.encode(input.additionalData))
|
|
65
|
+
|
|
66
|
+
return Buffer.concat([amount, lockupScript, lockTime, tokens, additionalData])
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
decode(input: Buffer): AssetOutput {
|
|
70
|
+
return this.parser.parse(input)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static toFixedAssetOutputs(txIdBytes: Uint8Array, outputs: AssetOutput[]): FixedAssetOutput[] {
|
|
74
|
+
return outputs.map((output, index) => AssetOutputCodec.toFixedAssetOutput(txIdBytes, output, index))
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static toFixedAssetOutput(txIdBytes: Uint8Array, output: AssetOutput, index: number): FixedAssetOutput {
|
|
78
|
+
const attoAlphAmount = compactUnsignedIntCodec.toU256(output.amount).toString()
|
|
79
|
+
const lockTime = Number(longCodec.decode(output.lockTime))
|
|
80
|
+
const tokens = output.tokens.value.map((token) => {
|
|
81
|
+
return {
|
|
82
|
+
id: token.tokenId.toString('hex'),
|
|
83
|
+
amount: compactUnsignedIntCodec.toU256(token.amount).toString()
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
const message = output.additionalData.value.toString('hex')
|
|
87
|
+
const scriptType = output.lockupScript.scriptType
|
|
88
|
+
const key = binToHex(blakeHash(Buffer.concat([txIdBytes, signedIntCodec.encode(index)])))
|
|
89
|
+
const outputLockupScript = output.lockupScript.script
|
|
90
|
+
const address = bs58.encode(lockupScriptCodec.encode(output.lockupScript))
|
|
91
|
+
|
|
92
|
+
let hint: number | undefined = undefined
|
|
93
|
+
if (scriptType === 0) {
|
|
94
|
+
// P2PKH
|
|
95
|
+
hint = createHint((outputLockupScript as PublicKeyHash).publicKeyHash)
|
|
96
|
+
} else if (scriptType === 1) {
|
|
97
|
+
// P2MPKH
|
|
98
|
+
hint = createHint((outputLockupScript as MultiSig).publicKeyHashes.value[0].publicKeyHash)
|
|
99
|
+
} else if (scriptType === 2) {
|
|
100
|
+
// P2SH
|
|
101
|
+
hint = createHint((outputLockupScript as P2SH).scriptHash)
|
|
102
|
+
} else if (scriptType === 3) {
|
|
103
|
+
throw new Error(`P2C script type not allowed for asset output`)
|
|
104
|
+
} else {
|
|
105
|
+
throw new Error(`Unexpected output script type: ${scriptType}`)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return { hint, key, attoAlphAmount, lockTime, tokens, address, message }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static fromFixedAssetOutputs(fixedOutputs: FixedAssetOutput[]): AssetOutput[] {
|
|
112
|
+
return fixedOutputs.map((output) => {
|
|
113
|
+
return AssetOutputCodec.fromFixedAssetOutput(output)
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static fromFixedAssetOutput(fixedOutput: FixedAssetOutput): AssetOutput {
|
|
118
|
+
const amount: DecodedCompactInt = compactUnsignedIntCodec.fromU256(BigInt(fixedOutput.attoAlphAmount))
|
|
119
|
+
|
|
120
|
+
const lockTime: Buffer = longCodec.encode(BigInt(fixedOutput.lockTime))
|
|
121
|
+
const lockupScript: LockupScript = lockupScriptCodec.decode(Buffer.from(bs58.decode(fixedOutput.address)))
|
|
122
|
+
const tokensValue = fixedOutput.tokens.map((token) => {
|
|
123
|
+
return {
|
|
124
|
+
tokenId: Buffer.from(token.id, 'hex'),
|
|
125
|
+
amount: compactUnsignedIntCodec.fromU256(BigInt(token.amount))
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
const tokens: DecodedArray<Token> = {
|
|
129
|
+
length: compactUnsignedIntCodec.fromU32(tokensValue.length),
|
|
130
|
+
value: tokensValue
|
|
131
|
+
}
|
|
132
|
+
const additionalDataValue = Buffer.from(fixedOutput.message, 'hex')
|
|
133
|
+
const additionalData: ByteString = {
|
|
134
|
+
length: compactUnsignedIntCodec.fromU32(additionalDataValue.length),
|
|
135
|
+
value: additionalDataValue
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
amount,
|
|
140
|
+
lockupScript,
|
|
141
|
+
lockTime,
|
|
142
|
+
tokens,
|
|
143
|
+
additionalData
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export const assetOutputCodec = new AssetOutputCodec()
|
|
149
|
+
export const assetOutputsCodec = new ArrayCodec(assetOutputCodec)
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
export class BigIntCodec {
|
|
20
|
+
static encode(value: bigint): Buffer {
|
|
21
|
+
// Special case for zero.
|
|
22
|
+
if (value === 0n) {
|
|
23
|
+
return Buffer.from([0])
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const isNegative = value < 0n
|
|
27
|
+
let absValue = isNegative ? -value : value
|
|
28
|
+
const bytes: number[] = []
|
|
29
|
+
|
|
30
|
+
// Extract bytes from absolute value.
|
|
31
|
+
while (absValue > 0n) {
|
|
32
|
+
bytes.push(Number(absValue & 0xffn))
|
|
33
|
+
absValue >>= 8n
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// If the bigint is positive and the most significant byte has its high bit set,
|
|
37
|
+
// prefix the byte array with a zero byte to signify positive value.
|
|
38
|
+
if (!isNegative && (bytes[bytes.length - 1] & 0x80) !== 0) {
|
|
39
|
+
bytes.push(0)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// If the bigint is negative, compute the two's complement of the byte array.
|
|
43
|
+
if (isNegative) {
|
|
44
|
+
let carry = true
|
|
45
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
46
|
+
bytes[i] = ~bytes[i] & 0xff // Invert the bits of the byte.
|
|
47
|
+
if (carry) {
|
|
48
|
+
if (bytes[i] === 0xff) {
|
|
49
|
+
bytes[i] = 0
|
|
50
|
+
} else {
|
|
51
|
+
bytes[i] += 1
|
|
52
|
+
carry = false
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// If there's still a carry, and the most significant byte is not 0xFF (to store the negative sign bit),
|
|
58
|
+
// or if no bytes were set (which means the value was -1), append a 0xFF byte to hold the carry.
|
|
59
|
+
if (carry || bytes.length === 0 || (bytes[bytes.length - 1] & 0x80) === 0) {
|
|
60
|
+
bytes.push(0xff)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// The byte array needs to be reversed since we've constructed it in little-endian order.
|
|
65
|
+
return Buffer.from(new Uint8Array(bytes.reverse()))
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static decode(encoded: Buffer, signed: boolean): bigint {
|
|
69
|
+
// Special case for zero.
|
|
70
|
+
if (encoded.length === 1 && encoded[0] === 0) {
|
|
71
|
+
return 0n
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Determine if the number is negative by checking the most significant byte (MSB)
|
|
75
|
+
const isNegative = signed ? encoded[0] === 0xff : signed
|
|
76
|
+
|
|
77
|
+
// Convert the byte array to a bigint
|
|
78
|
+
let value = 0n
|
|
79
|
+
for (const byte of encoded) {
|
|
80
|
+
value = (value << 8n) | BigInt(byte)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// If the number is negative, convert from two's complement
|
|
84
|
+
if (isNegative) {
|
|
85
|
+
// Create a mask for the value's bit length
|
|
86
|
+
const mask = (1n << (8n * BigInt(encoded.length))) - 1n
|
|
87
|
+
value = -(~value & mask) - 1n
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return value
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
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 { DecodedCompactInt, compactUnsignedIntCodec } from './compact-int-codec'
|
|
21
|
+
import { Codec } from './codec'
|
|
22
|
+
|
|
23
|
+
export interface ByteString {
|
|
24
|
+
length: DecodedCompactInt
|
|
25
|
+
value: Buffer
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class ByteStringCodec implements Codec<ByteString> {
|
|
29
|
+
parser = new Parser()
|
|
30
|
+
.nest('length', {
|
|
31
|
+
type: compactUnsignedIntCodec.parser
|
|
32
|
+
})
|
|
33
|
+
.buffer('value', {
|
|
34
|
+
length: function (ctx) {
|
|
35
|
+
return compactUnsignedIntCodec.toU32(this['length']! as any as DecodedCompactInt)
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
encode(input: ByteString): Buffer {
|
|
40
|
+
return Buffer.from([...compactUnsignedIntCodec.encode(input.length), ...input.value])
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
decode(input: Buffer): ByteString {
|
|
44
|
+
return this.parser.parse(input)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
encodeBuffer(input: Buffer): Buffer {
|
|
48
|
+
return Buffer.from([...compactUnsignedIntCodec.encodeU32(input.length), ...input])
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
decodeBuffer(input: Buffer): Buffer {
|
|
52
|
+
return this.decode(input).value
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const byteStringCodec = new ByteStringCodec()
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
|
|
21
|
+
export interface Codec<T> {
|
|
22
|
+
parser: Parser
|
|
23
|
+
encode(input: T): Buffer
|
|
24
|
+
decode(input: Buffer): T
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function assert(value: boolean, message: string) {
|
|
28
|
+
if (!value) {
|
|
29
|
+
throw new Error(message)
|
|
30
|
+
}
|
|
31
|
+
}
|