@alephium/web3 0.35.1 → 0.36.1

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.
@@ -18,7 +18,7 @@ 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.falttenFields = 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.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;
22
22
  const buffer_1 = require("buffer/");
23
23
  const api_1 = require("../api");
24
24
  const utils_1 = require("../utils");
@@ -240,58 +240,74 @@ function encodeScriptField(tpe, value) {
240
240
  case 'U256':
241
241
  const u256 = (0, api_1.toApiNumber256)(value);
242
242
  return encodeScriptFieldU256(BigInt(u256));
243
- case 'ByteVec':
244
- const hexStr = (0, api_1.toApiByteVec)(value);
245
- return new Uint8Array([Instruction.bytesConst, ...encodeByteVec(hexStr)]);
246
243
  case 'Address':
247
244
  const address = (0, api_1.toApiAddress)(value);
248
245
  return new Uint8Array([Instruction.addressConst, ...encodeAddress(address)]);
246
+ default: // ByteVec or Contract
247
+ const hexStr = (0, api_1.toApiByteVec)(value);
248
+ return new Uint8Array([Instruction.bytesConst, ...encodeByteVec(hexStr)]);
249
249
  }
250
250
  throw invalidScriptField(tpe, value);
251
251
  }
252
252
  exports.encodeScriptField = encodeScriptField;
253
- function flattenArray(name, type, val, acc) {
254
- const semiColonIndex = type.lastIndexOf(';');
255
- if (semiColonIndex == -1) {
256
- throw new Error(`Invalid array type: ${type}`);
257
- }
258
- const subType = type.slice(1, semiColonIndex);
259
- val.forEach((v, index) => {
260
- const isArrayType = subType.includes(';');
261
- const isArrayValue = Array.isArray(v);
262
- if (isArrayType && isArrayValue) {
263
- flattenArray(`${name}[${index}]`, subType, v, acc);
264
- }
265
- else if (!isArrayType && !isArrayValue) {
266
- acc.push({ name: `${name}[${index}]`, type: subType, value: v });
267
- }
268
- else {
269
- const value = isArrayValue ? `[` + v.join(', ') + `]` : v.toString();
270
- throw new Error(`Invalid field, expected type is ${subType}, but value is ${value}`);
271
- }
272
- });
273
- }
274
- function falttenFields(fields, fieldsSig) {
275
- const allFields = [];
276
- fieldsSig.names.forEach((name, index) => {
277
- const field = fields[`${name}`];
253
+ function flattenFields(fields, names, types, isMutable, structs) {
254
+ return names.flatMap((name, index) => {
278
255
  if (!(name in fields)) {
279
256
  throw new Error(`The value of field ${name} is not provided`);
280
257
  }
281
- const type = fieldsSig.types[`${index}`];
282
- if (Array.isArray(field)) {
283
- flattenArray(name, type, field, allFields);
258
+ return flattenField(isMutable[`${index}`], name, types[`${index}`], fields[`${name}`], structs);
259
+ });
260
+ }
261
+ exports.flattenFields = flattenFields;
262
+ function flattenField(isMutable, name, type, value, structs) {
263
+ if (Array.isArray(value) && type.startsWith('[')) {
264
+ const [baseType, size] = (0, api_1.decodeArrayType)(type);
265
+ if (value.length !== size) {
266
+ throw Error(`Invalid array length, expected ${size}, got ${value.length}`);
284
267
  }
285
- else {
286
- allFields.push({ name, type, value: field });
268
+ return value.flatMap((item, index) => {
269
+ return flattenField(isMutable, `${name}[${index}]`, baseType, item, structs);
270
+ });
271
+ }
272
+ const struct = structs.find((s) => s.name === type);
273
+ if (struct !== undefined) {
274
+ if (typeof value !== 'object') {
275
+ throw Error(`Expected an object, but got ${typeof value}`);
287
276
  }
288
- });
289
- return allFields;
277
+ return struct.fieldNames.flatMap((fieldName, index) => {
278
+ if (!(fieldName in value)) {
279
+ throw new Error(`The value of field ${fieldName} is not provided`);
280
+ }
281
+ const isFieldMutable = struct.isMutable[`${index}`];
282
+ const fieldType = struct.fieldTypes[`${index}`];
283
+ const fieldValue = value[`${fieldName}`];
284
+ return flattenField(isMutable && isFieldMutable, `${name}.${fieldName}`, fieldType, fieldValue, structs);
285
+ });
286
+ }
287
+ const primitiveType = checkPrimitiveValue(name, type, value);
288
+ return [{ name, type: primitiveType, value, isMutable }];
289
+ }
290
+ function checkPrimitiveValue(name, ralphType, value) {
291
+ const tsType = typeof value;
292
+ if (ralphType === 'Bool' && tsType === 'boolean') {
293
+ return ralphType;
294
+ }
295
+ if ((ralphType === 'U256' || ralphType === 'I256') &&
296
+ (tsType === 'string' || tsType === 'number' || tsType === 'bigint')) {
297
+ return ralphType;
298
+ }
299
+ if ((ralphType === 'Address' || ralphType === 'ByteVec') && tsType === 'string') {
300
+ return ralphType;
301
+ }
302
+ if (!ralphType.startsWith('[') && tsType === 'string') {
303
+ // contract type
304
+ return 'ByteVec';
305
+ }
306
+ throw Error(`Invalid value ${value} for ${name}, expected a value of type ${ralphType}`);
290
307
  }
291
- exports.falttenFields = falttenFields;
292
308
  const scriptFieldRegex = /\{([0-9]*)\}/g;
293
- function buildScriptByteCode(bytecodeTemplate, fields, fieldsSig) {
294
- const allFields = falttenFields(fields, fieldsSig);
309
+ function buildScriptByteCode(bytecodeTemplate, fields, fieldsSig, structs) {
310
+ const allFields = flattenFields(fields, fieldsSig.names, fieldsSig.types, fieldsSig.isMutable, structs);
295
311
  return bytecodeTemplate.replace(scriptFieldRegex, (_, fieldIndex) => {
296
312
  const field = allFields[`${fieldIndex}`];
297
313
  return _encodeField(field.name, () => encodeScriptFieldAsString(field.type, field.value));
@@ -309,27 +325,17 @@ function _encodeField(fieldName, encodeFunc) {
309
325
  throw error;
310
326
  }
311
327
  }
312
- function encodeFields(fields, fieldsSig, mutable) {
313
- const fieldIndexes = fieldsSig.isMutable
314
- .map((_, index) => index)
315
- .filter((index) => fieldsSig.isMutable[`${index}`] === mutable);
316
- const fieldsEncoded = fieldIndexes.flatMap((fieldIndex) => {
317
- const fieldName = fieldsSig.names[`${fieldIndex}`];
318
- const fieldType = fieldsSig.types[`${fieldIndex}`];
319
- if (fieldName in fields) {
320
- const fieldValue = fields[`${fieldName}`];
321
- return _encodeField(fieldName, () => encodeContractField(fieldType, fieldValue));
322
- }
323
- else {
324
- throw new Error(`The value of field ${fieldName} is not provided`);
325
- }
326
- });
327
- const fieldsLength = buffer_1.Buffer.from(encodeI256(BigInt(fieldsEncoded.length))).toString('hex');
328
- return fieldsLength + fieldsEncoded.map((f) => buffer_1.Buffer.from(f).toString('hex')).join('');
328
+ function encodeFields(fields) {
329
+ const prefix = (0, utils_1.binToHex)(encodeI256(BigInt(fields.length)));
330
+ const encoded = fields
331
+ .map((field) => (0, utils_1.binToHex)(_encodeField(field.name, () => encodeContractField(field.type, field.value))))
332
+ .join('');
333
+ return prefix + encoded;
329
334
  }
330
- function buildContractByteCode(bytecode, fields, fieldsSig) {
331
- const encodedImmFields = encodeFields(fields, fieldsSig, false);
332
- const encodedMutFields = encodeFields(fields, fieldsSig, true);
335
+ function buildContractByteCode(bytecode, fields, fieldsSig, structs) {
336
+ const allFields = flattenFields(fields, fieldsSig.names, fieldsSig.types, fieldsSig.isMutable, structs);
337
+ const encodedImmFields = encodeFields(allFields.filter((f) => !f.isMutable));
338
+ const encodedMutFields = encodeFields(allFields.filter((f) => f.isMutable));
333
339
  return bytecode + encodedImmFields + encodedMutFields;
334
340
  }
335
341
  exports.buildContractByteCode = buildContractByteCode;
@@ -347,43 +353,25 @@ function encodeContractFieldI256(value) {
347
353
  function encodeContractFieldU256(value) {
348
354
  return new Uint8Array([ApiValType.U256, ...encodeU256(value)]);
349
355
  }
350
- function encodeContractFieldArray(tpe, val) {
351
- if (!Array.isArray(val)) {
352
- throw new Error(`Expected array, got ${val}`);
353
- }
354
- const semiColonIndex = tpe.lastIndexOf(';');
355
- if (semiColonIndex == -1) {
356
- throw new Error(`Invalid Array type: ${tpe}`);
357
- }
358
- const subType = tpe.slice(1, semiColonIndex);
359
- const dim = parseInt(tpe.slice(semiColonIndex + 1, -1));
360
- if (val.length != dim) {
361
- throw new Error(`Invalid val dimension: ${val}`);
362
- }
363
- else {
364
- return val.flatMap((v) => encodeContractField(subType, v));
365
- }
366
- }
367
356
  function encodeContractField(tpe, value) {
368
357
  switch (tpe) {
369
358
  case 'Bool':
370
359
  const byte = (0, api_1.toApiBoolean)(value) ? 1 : 0;
371
- return [new Uint8Array([ApiValType.Bool, byte])];
360
+ return new Uint8Array([ApiValType.Bool, byte]);
372
361
  case 'I256':
373
362
  const i256 = (0, api_1.toApiNumber256)(value);
374
- return [encodeContractFieldI256(BigInt(i256))];
363
+ return encodeContractFieldI256(BigInt(i256));
375
364
  case 'U256':
376
365
  const u256 = (0, api_1.toApiNumber256)(value);
377
- return [encodeContractFieldU256(BigInt(u256))];
366
+ return encodeContractFieldU256(BigInt(u256));
378
367
  case 'ByteVec':
379
368
  const hexStr = (0, api_1.toApiByteVec)(value);
380
- return [new Uint8Array([ApiValType.ByteVec, ...encodeByteVec(hexStr)])];
369
+ return new Uint8Array([ApiValType.ByteVec, ...encodeByteVec(hexStr)]);
381
370
  case 'Address':
382
371
  const address = (0, api_1.toApiAddress)(value);
383
- return [new Uint8Array([ApiValType.Address, ...encodeAddress(address)])];
372
+ return new Uint8Array([ApiValType.Address, ...encodeAddress(address)]);
384
373
  default:
385
- // Array type
386
- return encodeContractFieldArray(tpe, value);
374
+ throw Error(`Expected primitive type, got ${tpe}`);
387
375
  }
388
376
  }
389
377
  exports.encodeContractField = encodeContractField;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/web3",
3
- "version": "0.35.1",
3
+ "version": "0.36.1",
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.9.0",
30
+ "alephium_version": "2.10.0",
31
31
  "explorer_backend_version": "1.17.0"
32
32
  },
33
33
  "type": "commonjs",
@@ -430,6 +430,7 @@ export interface CompileContractResult {
430
430
  export interface CompileProjectResult {
431
431
  contracts: CompileContractResult[]
432
432
  scripts: CompileScriptResult[]
433
+ structs?: StructSig[]
433
434
  }
434
435
 
435
436
  export interface CompileScriptResult {
@@ -802,6 +803,13 @@ export interface Source {
802
803
  utxos?: OutputRef[]
803
804
  }
804
805
 
806
+ export interface StructSig {
807
+ name: string
808
+ fieldNames: string[]
809
+ fieldTypes: string[]
810
+ isMutable: boolean[]
811
+ }
812
+
805
813
  export interface SubmitMultisig {
806
814
  unsignedTx: string
807
815
  signatures: string[]
@@ -1292,7 +1300,7 @@ export class HttpClient<SecurityDataType = unknown> {
1292
1300
 
1293
1301
  /**
1294
1302
  * @title Alephium API
1295
- * @version 2.9.0
1303
+ * @version 2.10.0
1296
1304
  * @baseUrl ../
1297
1305
  */
1298
1306
  export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
package/src/api/types.ts CHANGED
@@ -22,9 +22,13 @@ 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[]
25
+ export type Val = Number256 | boolean | string | Val[] | ValObject
26
+ // eslint-disable-next-line
27
+ export interface ValObject extends Record<string, Val> {} // bypassing typescript recursive type limitations
26
28
  export type NamedVals = Record<string, Val>
27
29
 
30
+ export const PrimitiveTypes = ['U256', 'I256', 'Bool', 'ByteVec', 'Address']
31
+
28
32
  export interface Token {
29
33
  id: string
30
34
  amount: Number256
@@ -144,121 +148,34 @@ export function toApiVal(v: Val, tpe: string): node.Val {
144
148
  }
145
149
  }
146
150
 
147
- function _fromApiVal(
148
- vals: node.Val[],
149
- valIndex: number,
150
- tpe: string,
151
- systemEvent = false
152
- ): [result: Val, nextIndex: number] {
153
- if (vals.length === 0) {
154
- throw new Error('Not enough Vals')
155
- }
156
-
157
- const firstVal = vals[`${valIndex}`]
158
- if (tpe === 'Bool' && firstVal.type === tpe) {
159
- return [firstVal.value as boolean, valIndex + 1]
160
- } else if ((tpe === 'U256' || tpe === 'I256') && firstVal.type === tpe) {
161
- return [fromApiNumber256(firstVal.value as string), valIndex + 1]
162
- } else if ((tpe === 'ByteVec' || tpe === 'Address') && (firstVal.type === tpe || systemEvent)) {
163
- return [firstVal.value as string, valIndex + 1]
164
- } else {
165
- const [baseType, dims] = decodeArrayType(tpe)
166
- const arraySize = dims.reduce((a, b) => a * b)
167
- const nextIndex = valIndex + arraySize
168
- const valsToUse = vals.slice(valIndex, nextIndex)
169
- if (valsToUse.length == arraySize && valsToUse.every((val) => val.type === baseType)) {
170
- const localVals = valsToUse.map((val) => fromApiVal(val, baseType))
171
- return [foldVals(localVals, dims), nextIndex]
172
- } else {
173
- throw new Error(`Invalid array Val type: ${valsToUse}, ${tpe}`)
174
- }
175
- }
176
- }
177
-
178
- export function fromApiVals(vals: node.Val[], names: string[], types: string[], systemEvent = false): NamedVals {
179
- let valIndex = 0
180
- const result: NamedVals = {}
181
- types.forEach((currentType, index) => {
182
- const currentName = names[`${index}`]
183
- const [val, nextIndex] = _fromApiVal(vals, valIndex, currentType, systemEvent)
184
- valIndex = nextIndex
185
- result[`${currentName}`] = val
186
- })
187
- return result
188
- }
189
-
190
- export function fromApiArray(vals: node.Val[], types: string[]): Val[] {
191
- let valIndex = 0
192
- const result: Val[] = []
193
- for (const currentType of types) {
194
- const [val, nextIndex] = _fromApiVal(vals, valIndex, currentType)
195
- result.push(val)
196
- valIndex = nextIndex
197
- }
198
- return result
199
- }
200
-
201
- export function fromApiVal(v: node.Val, tpe: string): Val {
202
- if (v.type === 'Bool' && v.type === tpe) {
203
- return v.value as boolean
204
- } else if ((v.type === 'U256' || v.type === 'I256') && v.type === tpe) {
205
- return fromApiNumber256(v.value as string)
206
- } else if ((v.type === 'ByteVec' || v.type === 'Address') && v.type === tpe) {
207
- return v.value as string
151
+ export function fromApiPrimitiveVal(value: node.Val, tpe: string, systemEvent = false): Val {
152
+ if (tpe === 'Bool' && value.type === tpe) {
153
+ return value.value as boolean
154
+ } else if ((tpe === 'U256' || tpe === 'I256') && value.type === tpe) {
155
+ return fromApiNumber256(value.value as string)
156
+ } else if ((tpe === 'ByteVec' || tpe === 'Address') && (value.type === tpe || systemEvent)) {
157
+ return value.value as string
208
158
  } else {
209
- throw new Error(`Invalid node.Val type: ${v}`)
159
+ throw new Error(`Expected primitive type, got ${tpe}`)
210
160
  }
211
161
  }
212
162
 
213
- function decodeArrayType(tpe: string): [baseType: string, dims: number[]] {
163
+ export function decodeArrayType(tpe: string): [string, number] {
214
164
  const semiColonIndex = tpe.lastIndexOf(';')
215
165
  if (semiColonIndex === -1) {
216
- throw new Error(`Invalid Val type: ${tpe}`)
217
- }
218
-
219
- const subType = tpe.slice(1, semiColonIndex)
220
- const dim = parseInt(tpe.slice(semiColonIndex + 1, -1))
221
- if (subType[0] == '[') {
222
- const [baseType, subDim] = decodeArrayType(subType)
223
- return [baseType, (subDim.unshift(dim), subDim)]
224
- } else {
225
- return [subType, [dim]]
166
+ throw new Error(`Invalid array type: ${tpe}`)
226
167
  }
168
+ const baseType = tpe.slice(1, semiColonIndex)
169
+ const size = parseInt(tpe.slice(semiColonIndex + 1, -1))
170
+ return [baseType, size]
227
171
  }
228
172
 
229
- export function getDefaultValue(tpe: string): Val {
173
+ export function getDefaultPrimitiveValue(tpe: string): Val {
230
174
  if (tpe === 'U256' || tpe === 'I256') return 0n
231
175
  if (tpe === 'Bool') return false
232
176
  if (tpe === 'ByteVec') return ''
233
177
  if (tpe === 'Address') return ZERO_ADDRESS
234
-
235
- // array type
236
- const [baseType, dims] = decodeArrayType(tpe)
237
- const defaultBaseValue = getDefaultValue(baseType)
238
- return dims.reduceRight((acc, length) => Array(length).fill(acc), defaultBaseValue)
239
- }
240
-
241
- function foldVals(vals: Val[], dims: number[]): Val {
242
- if (dims.length == 1) {
243
- return vals
244
- } else {
245
- const result: Val[] = []
246
- const chunkSize = vals.length / dims[0]
247
- const chunkDims = dims.slice(1)
248
- for (let i = 0; i < vals.length; i += chunkSize) {
249
- const chunk = vals.slice(i, i + chunkSize)
250
- result.push(foldVals(chunk, chunkDims))
251
- }
252
- return result
253
- }
254
- }
255
-
256
- export function typeLength(tpe: string): number {
257
- if (tpe === 'U256' || tpe === 'I256' || tpe === 'Bool' || tpe === 'ByteVec' || tpe === 'Address') {
258
- return 1
259
- }
260
- const [, dims] = decodeArrayType(tpe)
261
- return dims.reduce((a, b) => a * b)
178
+ throw Error(`Expected primitive type, got ${tpe}`)
262
179
  }
263
180
 
264
181
  export interface ApiRequestArguments {