@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.
- 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 +8 -1
- package/dist/src/api/api-alephium.js +1 -1
- package/dist/src/api/types.d.ts +7 -6
- package/dist/src/api/types.js +19 -100
- package/dist/src/contract/contract.d.ts +31 -11
- package/dist/src/contract/contract.js +167 -89
- package/dist/src/contract/ralph.d.ts +6 -5
- package/dist/src/contract/ralph.js +71 -83
- package/package.json +2 -2
- package/src/api/api-alephium.ts +9 -1
- package/src/api/types.ts +20 -103
- package/src/contract/contract.ts +218 -92
- package/src/contract/ralph.ts +98 -84
package/src/contract/ralph.ts
CHANGED
|
@@ -17,9 +17,9 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { Buffer } from 'buffer/'
|
|
20
|
-
import { Val, toApiAddress, toApiBoolean, toApiByteVec, toApiNumber256 } from '../api'
|
|
21
|
-
import { bs58, isHexString } from '../utils'
|
|
22
|
-
import { Fields, FieldsSig } from './contract'
|
|
20
|
+
import { PrimitiveTypes, Val, decodeArrayType, toApiAddress, toApiBoolean, toApiByteVec, toApiNumber256 } from '../api'
|
|
21
|
+
import { binToHex, bs58, isHexString } from '../utils'
|
|
22
|
+
import { Fields, FieldsSig, Struct } from './contract'
|
|
23
23
|
|
|
24
24
|
const bigIntZero = BigInt(0)
|
|
25
25
|
|
|
@@ -236,58 +236,97 @@ export function encodeScriptField(tpe: string, value: Val): Uint8Array {
|
|
|
236
236
|
case 'U256':
|
|
237
237
|
const u256 = toApiNumber256(value)
|
|
238
238
|
return encodeScriptFieldU256(BigInt(u256))
|
|
239
|
-
case 'ByteVec':
|
|
240
|
-
const hexStr = toApiByteVec(value)
|
|
241
|
-
return new Uint8Array([Instruction.bytesConst, ...encodeByteVec(hexStr)])
|
|
242
239
|
case 'Address':
|
|
243
240
|
const address = toApiAddress(value)
|
|
244
241
|
return new Uint8Array([Instruction.addressConst, ...encodeAddress(address)])
|
|
242
|
+
default: // ByteVec or Contract
|
|
243
|
+
const hexStr = toApiByteVec(value)
|
|
244
|
+
return new Uint8Array([Instruction.bytesConst, ...encodeByteVec(hexStr)])
|
|
245
245
|
}
|
|
246
246
|
|
|
247
247
|
throw invalidScriptField(tpe, value)
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
function
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
flattenArray(`${name}[${index}]`, subType, v, acc)
|
|
261
|
-
} else if (!isArrayType && !isArrayValue) {
|
|
262
|
-
acc.push({ name: `${name}[${index}]`, type: subType, value: v })
|
|
263
|
-
} else {
|
|
264
|
-
const value = isArrayValue ? `[` + v.join(', ') + `]` : v.toString()
|
|
265
|
-
throw new Error(`Invalid field, expected type is ${subType}, but value is ${value}`)
|
|
250
|
+
export function flattenFields(
|
|
251
|
+
fields: Fields,
|
|
252
|
+
names: string[],
|
|
253
|
+
types: string[],
|
|
254
|
+
isMutable: boolean[],
|
|
255
|
+
structs: Struct[]
|
|
256
|
+
): { name: string; type: string; value: Val; isMutable: boolean }[] {
|
|
257
|
+
return names.flatMap((name, index) => {
|
|
258
|
+
if (!(name in fields)) {
|
|
259
|
+
throw new Error(`The value of field ${name} is not provided`)
|
|
266
260
|
}
|
|
261
|
+
return flattenField(isMutable[`${index}`], name, types[`${index}`], fields[`${name}`], structs)
|
|
267
262
|
})
|
|
268
263
|
}
|
|
269
264
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
265
|
+
function flattenField(
|
|
266
|
+
isMutable: boolean,
|
|
267
|
+
name: string,
|
|
268
|
+
type: string,
|
|
269
|
+
value: Val,
|
|
270
|
+
structs: Struct[]
|
|
271
|
+
): { name: string; type: string; value: Val; isMutable: boolean }[] {
|
|
272
|
+
if (Array.isArray(value) && type.startsWith('[')) {
|
|
273
|
+
const [baseType, size] = decodeArrayType(type)
|
|
274
|
+
if (value.length !== size) {
|
|
275
|
+
throw Error(`Invalid array length, expected ${size}, got ${value.length}`)
|
|
276
276
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
277
|
+
return value.flatMap((item, index) => {
|
|
278
|
+
return flattenField(isMutable, `${name}[${index}]`, baseType, item, structs)
|
|
279
|
+
})
|
|
280
|
+
}
|
|
281
|
+
const struct = structs.find((s) => s.name === type)
|
|
282
|
+
if (struct !== undefined) {
|
|
283
|
+
if (typeof value !== 'object') {
|
|
284
|
+
throw Error(`Expected an object, but got ${typeof value}`)
|
|
282
285
|
}
|
|
283
|
-
|
|
284
|
-
|
|
286
|
+
return struct.fieldNames.flatMap((fieldName, index) => {
|
|
287
|
+
if (!(fieldName in value)) {
|
|
288
|
+
throw new Error(`The value of field ${fieldName} is not provided`)
|
|
289
|
+
}
|
|
290
|
+
const isFieldMutable = struct.isMutable[`${index}`]
|
|
291
|
+
const fieldType = struct.fieldTypes[`${index}`]
|
|
292
|
+
const fieldValue = value[`${fieldName}`]
|
|
293
|
+
return flattenField(isMutable && isFieldMutable, `${name}.${fieldName}`, fieldType, fieldValue, structs)
|
|
294
|
+
})
|
|
295
|
+
}
|
|
296
|
+
const primitiveType = checkPrimitiveValue(name, type, value)
|
|
297
|
+
return [{ name, type: primitiveType, value, isMutable }]
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function checkPrimitiveValue(name: string, ralphType: string, value: Val): string {
|
|
301
|
+
const tsType = typeof value
|
|
302
|
+
if (ralphType === 'Bool' && tsType === 'boolean') {
|
|
303
|
+
return ralphType
|
|
304
|
+
}
|
|
305
|
+
if (
|
|
306
|
+
(ralphType === 'U256' || ralphType === 'I256') &&
|
|
307
|
+
(tsType === 'string' || tsType === 'number' || tsType === 'bigint')
|
|
308
|
+
) {
|
|
309
|
+
return ralphType
|
|
310
|
+
}
|
|
311
|
+
if ((ralphType === 'Address' || ralphType === 'ByteVec') && tsType === 'string') {
|
|
312
|
+
return ralphType
|
|
313
|
+
}
|
|
314
|
+
if (!ralphType.startsWith('[') && tsType === 'string') {
|
|
315
|
+
// contract type
|
|
316
|
+
return 'ByteVec'
|
|
317
|
+
}
|
|
318
|
+
throw Error(`Invalid value ${value} for ${name}, expected a value of type ${ralphType}`)
|
|
285
319
|
}
|
|
286
320
|
|
|
287
321
|
const scriptFieldRegex = /\{([0-9]*)\}/g
|
|
288
322
|
|
|
289
|
-
export function buildScriptByteCode(
|
|
290
|
-
|
|
323
|
+
export function buildScriptByteCode(
|
|
324
|
+
bytecodeTemplate: string,
|
|
325
|
+
fields: Fields,
|
|
326
|
+
fieldsSig: FieldsSig,
|
|
327
|
+
structs: Struct[]
|
|
328
|
+
): string {
|
|
329
|
+
const allFields = flattenFields(fields, fieldsSig.names, fieldsSig.types, fieldsSig.isMutable, structs)
|
|
291
330
|
return bytecodeTemplate.replace(scriptFieldRegex, (_, fieldIndex: string) => {
|
|
292
331
|
const field = allFields[`${fieldIndex}`]
|
|
293
332
|
return _encodeField(field.name, () => encodeScriptFieldAsString(field.type, field.value))
|
|
@@ -305,27 +344,23 @@ function _encodeField<T>(fieldName: string, encodeFunc: () => T): T {
|
|
|
305
344
|
}
|
|
306
345
|
}
|
|
307
346
|
|
|
308
|
-
function encodeFields(fields:
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
.
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const fieldType = fieldsSig.types[`${fieldIndex}`]
|
|
315
|
-
if (fieldName in fields) {
|
|
316
|
-
const fieldValue = fields[`${fieldName}`]
|
|
317
|
-
return _encodeField(fieldName, () => encodeContractField(fieldType, fieldValue))
|
|
318
|
-
} else {
|
|
319
|
-
throw new Error(`The value of field ${fieldName} is not provided`)
|
|
320
|
-
}
|
|
321
|
-
})
|
|
322
|
-
const fieldsLength = Buffer.from(encodeI256(BigInt(fieldsEncoded.length))).toString('hex')
|
|
323
|
-
return fieldsLength + fieldsEncoded.map((f) => Buffer.from(f).toString('hex')).join('')
|
|
347
|
+
function encodeFields(fields: { name: string; type: string; value: Val }[]): string {
|
|
348
|
+
const prefix = binToHex(encodeI256(BigInt(fields.length)))
|
|
349
|
+
const encoded = fields
|
|
350
|
+
.map((field) => binToHex(_encodeField(field.name, () => encodeContractField(field.type, field.value))))
|
|
351
|
+
.join('')
|
|
352
|
+
return prefix + encoded
|
|
324
353
|
}
|
|
325
354
|
|
|
326
|
-
export function buildContractByteCode(
|
|
327
|
-
|
|
328
|
-
|
|
355
|
+
export function buildContractByteCode(
|
|
356
|
+
bytecode: string,
|
|
357
|
+
fields: Fields,
|
|
358
|
+
fieldsSig: FieldsSig,
|
|
359
|
+
structs: Struct[]
|
|
360
|
+
): string {
|
|
361
|
+
const allFields = flattenFields(fields, fieldsSig.names, fieldsSig.types, fieldsSig.isMutable, structs)
|
|
362
|
+
const encodedImmFields = encodeFields(allFields.filter((f) => !f.isMutable))
|
|
363
|
+
const encodedMutFields = encodeFields(allFields.filter((f) => f.isMutable))
|
|
329
364
|
return bytecode + encodedImmFields + encodedMutFields
|
|
330
365
|
}
|
|
331
366
|
|
|
@@ -345,46 +380,25 @@ function encodeContractFieldU256(value: bigint): Uint8Array {
|
|
|
345
380
|
return new Uint8Array([ApiValType.U256, ...encodeU256(value)])
|
|
346
381
|
}
|
|
347
382
|
|
|
348
|
-
function
|
|
349
|
-
if (!Array.isArray(val)) {
|
|
350
|
-
throw new Error(`Expected array, got ${val}`)
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
const semiColonIndex = tpe.lastIndexOf(';')
|
|
354
|
-
if (semiColonIndex == -1) {
|
|
355
|
-
throw new Error(`Invalid Array type: ${tpe}`)
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
const subType = tpe.slice(1, semiColonIndex)
|
|
359
|
-
const dim = parseInt(tpe.slice(semiColonIndex + 1, -1))
|
|
360
|
-
if ((val as Val[]).length != dim) {
|
|
361
|
-
throw new Error(`Invalid val dimension: ${val}`)
|
|
362
|
-
} else {
|
|
363
|
-
return (val as Val[]).flatMap((v) => encodeContractField(subType, v))
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
export function encodeContractField(tpe: string, value: Val): Uint8Array[] {
|
|
383
|
+
export function encodeContractField(tpe: string, value: Val): Uint8Array {
|
|
368
384
|
switch (tpe) {
|
|
369
385
|
case 'Bool':
|
|
370
386
|
const byte = toApiBoolean(value) ? 1 : 0
|
|
371
|
-
return
|
|
387
|
+
return new Uint8Array([ApiValType.Bool, byte])
|
|
372
388
|
case 'I256':
|
|
373
389
|
const i256 = toApiNumber256(value)
|
|
374
|
-
return
|
|
390
|
+
return encodeContractFieldI256(BigInt(i256))
|
|
375
391
|
case 'U256':
|
|
376
392
|
const u256 = toApiNumber256(value)
|
|
377
|
-
return
|
|
393
|
+
return encodeContractFieldU256(BigInt(u256))
|
|
378
394
|
case 'ByteVec':
|
|
379
395
|
const hexStr = toApiByteVec(value)
|
|
380
|
-
return
|
|
396
|
+
return new Uint8Array([ApiValType.ByteVec, ...encodeByteVec(hexStr)])
|
|
381
397
|
case 'Address':
|
|
382
398
|
const address = toApiAddress(value)
|
|
383
|
-
return
|
|
384
|
-
|
|
399
|
+
return new Uint8Array([ApiValType.Address, ...encodeAddress(address)])
|
|
385
400
|
default:
|
|
386
|
-
|
|
387
|
-
return encodeContractFieldArray(tpe, value)
|
|
401
|
+
throw Error(`Expected primitive type, got ${tpe}`)
|
|
388
402
|
}
|
|
389
403
|
}
|
|
390
404
|
|