@alephium/web3 1.7.0 → 1.7.2

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.
@@ -121,6 +121,9 @@ export interface ContractState<T extends Fields = Fields> {
121
121
  fieldsSig: FieldsSig;
122
122
  asset: Asset;
123
123
  }
124
+ export interface ContractStateWithMaps<T extends Fields = Fields, M extends Record<string, Map<Val, Val>> = Record<string, Map<Val, Val>>> extends ContractState<T> {
125
+ maps?: M;
126
+ }
124
127
  export type TestContractParamsWithoutMaps<F extends Fields = Fields, A extends Arguments = Arguments> = Omit<TestContractParams<F, A>, 'initialMaps'>;
125
128
  export interface TestContractParams<F extends Fields = Fields, A extends Arguments = Arguments, M extends Record<string, Map<Val, Val>> = Record<string, Map<Val, Val>>> {
126
129
  group?: number;
@@ -133,7 +136,7 @@ export interface TestContractParams<F extends Fields = Fields, A extends Argumen
133
136
  initialMaps?: M;
134
137
  initialAsset?: Asset;
135
138
  testArgs: A;
136
- existingContracts?: ContractState[];
139
+ existingContracts?: ContractStateWithMaps[];
137
140
  inputAssets?: InputAsset[];
138
141
  }
139
142
  export interface ContractEvent<T extends Fields = Fields> {
@@ -152,7 +155,7 @@ export interface TestContractResult<R, M extends Record<string, Map<Val, Val>> =
152
155
  returns: R;
153
156
  gasUsed: number;
154
157
  maps?: M;
155
- contracts: ContractState[];
158
+ contracts: ContractStateWithMaps[];
156
159
  txOutputs: Output[];
157
160
  events: ContractEvent[];
158
161
  debugMessages: DebugMessage[];
@@ -190,7 +193,7 @@ export declare abstract class ContractFactory<I extends ContractInstance, F exte
190
193
  abstract at(address: string): I;
191
194
  deploy(signer: SignerProvider, deployParams: DeployContractParams<F>): Promise<DeployContractResult<I>>;
192
195
  deployTemplate(signer: SignerProvider): Promise<DeployContractResult<I>>;
193
- stateForTest(initFields: F, asset?: Asset, address?: string): ContractState<F>;
196
+ protected stateForTest_(initFields: F, asset?: Asset, address?: string, maps?: Record<string, Map<Val, Val>>): ContractState<F> | ContractStateWithMaps<F>;
194
197
  }
195
198
  export declare class ExecutableScript<P extends Fields = Fields, R extends Val | null = null> {
196
199
  readonly script: Script;
@@ -266,6 +269,10 @@ export declare function subscribeEventsFromContract<T extends Fields, M extends
266
269
  export declare function addStdIdToFields<F extends Fields>(contract: Contract, fields: F): F | (F & {
267
270
  __stdInterfaceId: HexString;
268
271
  });
272
+ export declare function extractMapsFromApiResult(selfAddress: string, params: Optional<TestContractParams, 'testArgs' | 'initialFields'>, group: number, apiResult: node.TestContractResult, getContractByCodeHash: (codeHash: string) => Contract): {
273
+ address: string;
274
+ maps: Record<string, Map<Val, Val>>;
275
+ }[];
269
276
  export declare function testMethod<I extends ContractInstance, F extends Fields, A extends Arguments, R, M extends Record<string, Map<Val, Val>> = Record<string, Map<Val, Val>>>(factory: ContractFactory<I, F>, methodName: string, params: Optional<TestContractParams<F, A, M>, 'testArgs' | 'initialFields'>, getContractByCodeHash: (codeHash: string) => Contract): Promise<TestContractResult<R, M>>;
270
277
  export declare class RalphMap<K extends Val, V extends Val> {
271
278
  private readonly parentContract;
@@ -40,7 +40,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
40
40
  return result;
41
41
  };
42
42
  Object.defineProperty(exports, "__esModule", { value: true });
43
- exports.getTokenIdFromUnsignedTx = exports.getContractIdFromUnsignedTx = exports.getContractEventsCurrentCount = exports.multicallMethods = exports.signExecuteMethod = exports.callMethod = exports.subscribeContractEvents = exports.subscribeContractEvent = exports.decodeEvent = exports.subscribeContractDestroyedEvent = exports.subscribeContractCreatedEvent = exports.fetchContractState = exports.ContractInstance = exports.getMapItem = exports.RalphMap = 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.Struct = exports.DEFAULT_COMPILER_OPTIONS = exports.DEFAULT_NODE_COMPILER_OPTIONS = exports.StdIdFieldName = void 0;
43
+ exports.getTokenIdFromUnsignedTx = exports.getContractIdFromUnsignedTx = exports.getContractEventsCurrentCount = exports.multicallMethods = exports.signExecuteMethod = exports.callMethod = exports.subscribeContractEvents = exports.subscribeContractEvent = exports.decodeEvent = exports.subscribeContractDestroyedEvent = exports.subscribeContractCreatedEvent = exports.fetchContractState = exports.ContractInstance = exports.getMapItem = exports.RalphMap = exports.testMethod = exports.extractMapsFromApiResult = 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.Struct = exports.DEFAULT_COMPILER_OPTIONS = exports.DEFAULT_NODE_COMPILER_OPTIONS = exports.StdIdFieldName = void 0;
44
44
  const fs_1 = require("fs");
45
45
  const api_1 = require("../api");
46
46
  const ralph = __importStar(require("./ralph"));
@@ -379,6 +379,9 @@ class Contract extends Artifact {
379
379
  return signerParams;
380
380
  }
381
381
  buildByteCodeToDeploy(initialFields, isDevnet, exposePrivateFunctions = false) {
382
+ if (exposePrivateFunctions && !isDevnet) {
383
+ throw new Error('Cannot expose private functions in non-devnet environment');
384
+ }
382
385
  try {
383
386
  const bytecode = exposePrivateFunctions && isDevnet
384
387
  ? this.getByteCodeForTesting()
@@ -669,12 +672,18 @@ class ContractFactory {
669
672
  });
670
673
  }
671
674
  // This is used for testing contract functions
672
- stateForTest(initFields, asset, address) {
675
+ stateForTest_(initFields, asset, address, maps) {
673
676
  const newAsset = {
674
- alphAmount: asset?.alphAmount ?? constants_1.ONE_ALPH,
677
+ alphAmount: asset?.alphAmount ?? constants_1.MINIMAL_CONTRACT_DEPOSIT,
675
678
  tokens: asset?.tokens
676
679
  };
677
- return this.contract.toState(addStdIdToFields(this.contract, initFields), newAsset, address);
680
+ const state = this.contract.toState(addStdIdToFields(this.contract, initFields), newAsset, address);
681
+ return {
682
+ ...state,
683
+ bytecode: this.contract.bytecodeDebug,
684
+ codeHash: this.contract.codeHash,
685
+ maps: maps
686
+ };
678
687
  }
679
688
  }
680
689
  exports.ContractFactory = ContractFactory;
@@ -872,29 +881,65 @@ function mapsToExistingContracts(contract, parentContractId, group, initialMaps)
872
881
  });
873
882
  return contractStates;
874
883
  }
884
+ function hasMap(state) {
885
+ return state.maps !== undefined;
886
+ }
887
+ function getTestExistingContracts(selfContract, selfContractId, group, params, getContractByCodeHash) {
888
+ const selfMaps = params.initialMaps ?? {};
889
+ const selfMapEntries = mapsToExistingContracts(selfContract, selfContractId, group, selfMaps);
890
+ const existingContracts = params.existingContracts ?? [];
891
+ const existingMapEntries = existingContracts.flatMap((contractState) => {
892
+ return hasMap(contractState)
893
+ ? mapsToExistingContracts(getContractByCodeHash(contractState.codeHash), contractState.contractId, group, contractState.maps ?? {})
894
+ : [];
895
+ });
896
+ return existingContracts.concat(selfMapEntries, existingMapEntries);
897
+ }
898
+ function extractMapsFromApiResult(selfAddress, params, group, apiResult, getContractByCodeHash) {
899
+ const selfMaps = params.initialMaps ?? {};
900
+ const existingContracts = params.existingContracts ?? [];
901
+ const filtered = apiResult.contracts.filter((c) => c.address === selfAddress || existingContracts.find((s) => s.address === c.address) !== undefined);
902
+ const allMaps = [];
903
+ filtered.forEach((state) => {
904
+ const artifact = getContractByCodeHash(state.codeHash);
905
+ if (artifact.mapsSig !== undefined) {
906
+ const originMaps = state.address === selfAddress
907
+ ? selfMaps
908
+ : existingContracts.find((s) => s.address === state.address).maps;
909
+ const maps = existingContractsToMaps(artifact, state.address, group, apiResult, originMaps ?? {});
910
+ allMaps.push({ address: state.address, maps });
911
+ }
912
+ });
913
+ return allMaps;
914
+ }
915
+ exports.extractMapsFromApiResult = extractMapsFromApiResult;
875
916
  async function testMethod(factory, methodName, params, getContractByCodeHash) {
876
917
  const txId = params?.txId ?? randomTxId();
877
- const contract = factory.contract;
878
- const address = params.address ?? (0, address_1.addressFromContractId)((0, utils_1.binToHex)(crypto.getRandomValues(new Uint8Array(32))));
879
- const contractId = (0, utils_1.binToHex)((0, address_1.contractIdFromAddress)(address));
918
+ const selfContract = factory.contract;
919
+ const selfAddress = params.address ?? (0, address_1.addressFromContractId)((0, utils_1.binToHex)(crypto.getRandomValues(new Uint8Array(32))));
920
+ const selfContractId = (0, utils_1.binToHex)((0, address_1.contractIdFromAddress)(selfAddress));
880
921
  const group = params.group ?? 0;
881
- const initialMaps = params.initialMaps ?? {};
882
- const contractStates = mapsToExistingContracts(contract, contractId, group, initialMaps);
883
- const apiParams = contract.toApiTestContractParams(methodName, {
922
+ const existingContracts = getTestExistingContracts(selfContract, selfContractId, group, params, getContractByCodeHash);
923
+ const apiParams = selfContract.toApiTestContractParams(methodName, {
884
924
  ...params,
885
- address,
925
+ address: selfAddress,
886
926
  txId: txId,
887
- initialFields: addStdIdToFields(contract, params.initialFields ?? {}),
927
+ initialFields: addStdIdToFields(selfContract, params.initialFields ?? {}),
888
928
  testArgs: params.testArgs === undefined ? {} : params.testArgs,
889
- existingContracts: (params.existingContracts ?? []).concat(contractStates)
929
+ existingContracts
890
930
  });
891
931
  const apiResult = await (0, global_1.getCurrentNodeProvider)().contracts.postContractsTestContract(apiParams);
892
- const maps = existingContractsToMaps(contract, address, group, apiResult, initialMaps);
893
- const testResult = contract.fromApiTestContractResult(methodName, apiResult, txId, getContractByCodeHash);
894
- contract.printDebugMessages(methodName, testResult.debugMessages);
932
+ const allMaps = extractMapsFromApiResult(selfAddress, params, group, apiResult, getContractByCodeHash);
933
+ const testResult = selfContract.fromApiTestContractResult(methodName, apiResult, txId, getContractByCodeHash);
934
+ testResult.contracts.forEach((c) => {
935
+ const maps = allMaps.find((v) => v.address === c.address)?.maps;
936
+ if (maps !== undefined)
937
+ c['maps'] = maps;
938
+ });
939
+ selfContract.printDebugMessages(methodName, testResult.debugMessages);
895
940
  return {
896
941
  ...testResult,
897
- maps
942
+ maps: allMaps.find((v) => v.address === selfAddress)?.maps
898
943
  };
899
944
  }
900
945
  exports.testMethod = testMethod;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/web3",
3
- "version": "1.7.0",
3
+ "version": "1.7.2",
4
4
  "description": "A JS/TS library to interact with the Alephium platform",
5
5
  "license": "GPL",
6
6
  "main": "dist/src/index.js",
@@ -59,7 +59,7 @@ import {
59
59
  import { contractIdFromAddress, groupOfAddress, addressFromContractId, subContractId } from '../address'
60
60
  import { getCurrentNodeProvider } from '../global'
61
61
  import { EventSubscribeOptions, EventSubscription, subscribeToEvents } from './events'
62
- import { ONE_ALPH, TOTAL_NUMBER_OF_GROUPS } from '../constants'
62
+ import { MINIMAL_CONTRACT_DEPOSIT, ONE_ALPH, TOTAL_NUMBER_OF_GROUPS } from '../constants'
63
63
  import * as blake from 'blakejs'
64
64
  import { isContractDebugMessageEnabled } from '../debug'
65
65
  import {
@@ -589,6 +589,10 @@ export class Contract extends Artifact {
589
589
  }
590
590
 
591
591
  buildByteCodeToDeploy(initialFields: Fields, isDevnet: boolean, exposePrivateFunctions = false): string {
592
+ if (exposePrivateFunctions && !isDevnet) {
593
+ throw new Error('Cannot expose private functions in non-devnet environment')
594
+ }
595
+
592
596
  try {
593
597
  const bytecode =
594
598
  exposePrivateFunctions && isDevnet
@@ -881,6 +885,13 @@ export interface ContractState<T extends Fields = Fields> {
881
885
  asset: Asset
882
886
  }
883
887
 
888
+ export interface ContractStateWithMaps<
889
+ T extends Fields = Fields,
890
+ M extends Record<string, Map<Val, Val>> = Record<string, Map<Val, Val>>
891
+ > extends ContractState<T> {
892
+ maps?: M
893
+ }
894
+
884
895
  function toApiContractState(state: ContractState, structs: Struct[]): node.ContractState {
885
896
  const stateFields = state.fields ?? {}
886
897
  const fieldsSig = state.fieldsSig
@@ -938,7 +949,7 @@ export interface TestContractParams<
938
949
  initialMaps?: M
939
950
  initialAsset?: Asset // default 1 ALPH
940
951
  testArgs: A
941
- existingContracts?: ContractState[] // default no existing contracts
952
+ existingContracts?: ContractStateWithMaps[] // default no existing contracts
942
953
  inputAssets?: InputAsset[] // default no input asserts
943
954
  }
944
955
 
@@ -961,7 +972,7 @@ export interface TestContractResult<R, M extends Record<string, Map<Val, Val>> =
961
972
  returns: R
962
973
  gasUsed: number
963
974
  maps?: M
964
- contracts: ContractState[]
975
+ contracts: ContractStateWithMaps[]
965
976
  txOutputs: Output[]
966
977
  events: ContractEvent[]
967
978
  debugMessages: DebugMessage[]
@@ -1061,12 +1072,23 @@ export abstract class ContractFactory<I extends ContractInstance, F extends Fiel
1061
1072
  }
1062
1073
 
1063
1074
  // This is used for testing contract functions
1064
- stateForTest(initFields: F, asset?: Asset, address?: string): ContractState<F> {
1075
+ protected stateForTest_(
1076
+ initFields: F,
1077
+ asset?: Asset,
1078
+ address?: string,
1079
+ maps?: Record<string, Map<Val, Val>>
1080
+ ): ContractState<F> | ContractStateWithMaps<F> {
1065
1081
  const newAsset = {
1066
- alphAmount: asset?.alphAmount ?? ONE_ALPH,
1082
+ alphAmount: asset?.alphAmount ?? MINIMAL_CONTRACT_DEPOSIT,
1067
1083
  tokens: asset?.tokens
1068
1084
  }
1069
- return this.contract.toState(addStdIdToFields(this.contract, initFields), newAsset, address)
1085
+ const state = this.contract.toState(addStdIdToFields(this.contract, initFields), newAsset, address)
1086
+ return {
1087
+ ...state,
1088
+ bytecode: this.contract.bytecodeDebug,
1089
+ codeHash: this.contract.codeHash,
1090
+ maps: maps
1091
+ }
1070
1092
  }
1071
1093
  }
1072
1094
 
@@ -1377,6 +1399,60 @@ function mapsToExistingContracts(
1377
1399
  return contractStates
1378
1400
  }
1379
1401
 
1402
+ function hasMap(state: ContractState): state is ContractStateWithMaps {
1403
+ return (state as ContractStateWithMaps).maps !== undefined
1404
+ }
1405
+
1406
+ function getTestExistingContracts(
1407
+ selfContract: Contract,
1408
+ selfContractId: string,
1409
+ group: number,
1410
+ params: Optional<TestContractParams, 'testArgs' | 'initialFields'>,
1411
+ getContractByCodeHash: (codeHash: string) => Contract
1412
+ ): ContractState[] {
1413
+ const selfMaps = params.initialMaps ?? {}
1414
+ const selfMapEntries = mapsToExistingContracts(selfContract, selfContractId, group, selfMaps)
1415
+ const existingContracts = params.existingContracts ?? []
1416
+ const existingMapEntries = existingContracts.flatMap((contractState) => {
1417
+ return hasMap(contractState)
1418
+ ? mapsToExistingContracts(
1419
+ getContractByCodeHash(contractState.codeHash),
1420
+ contractState.contractId,
1421
+ group,
1422
+ contractState.maps ?? {}
1423
+ )
1424
+ : []
1425
+ })
1426
+ return existingContracts.concat(selfMapEntries, existingMapEntries)
1427
+ }
1428
+
1429
+ export function extractMapsFromApiResult(
1430
+ selfAddress: string,
1431
+ params: Optional<TestContractParams, 'testArgs' | 'initialFields'>,
1432
+ group: number,
1433
+ apiResult: node.TestContractResult,
1434
+ getContractByCodeHash: (codeHash: string) => Contract
1435
+ ): { address: string; maps: Record<string, Map<Val, Val>> }[] {
1436
+ const selfMaps = params.initialMaps ?? {}
1437
+ const existingContracts = params.existingContracts ?? []
1438
+ const filtered = apiResult.contracts.filter(
1439
+ (c) => c.address === selfAddress || existingContracts.find((s) => s.address === c.address) !== undefined
1440
+ )
1441
+ const allMaps: { address: string; maps: Record<string, Map<Val, Val>> }[] = []
1442
+ filtered.forEach((state) => {
1443
+ const artifact = getContractByCodeHash(state.codeHash)
1444
+ if (artifact.mapsSig !== undefined) {
1445
+ const originMaps =
1446
+ state.address === selfAddress
1447
+ ? selfMaps
1448
+ : (existingContracts.find((s) => s.address === state.address) as ContractStateWithMaps).maps
1449
+ const maps = existingContractsToMaps(artifact, state.address, group, apiResult, originMaps ?? {})
1450
+ allMaps.push({ address: state.address, maps })
1451
+ }
1452
+ })
1453
+ return allMaps
1454
+ }
1455
+
1380
1456
  export async function testMethod<
1381
1457
  I extends ContractInstance,
1382
1458
  F extends Fields,
@@ -1390,27 +1466,31 @@ export async function testMethod<
1390
1466
  getContractByCodeHash: (codeHash: string) => Contract
1391
1467
  ): Promise<TestContractResult<R, M>> {
1392
1468
  const txId = params?.txId ?? randomTxId()
1393
- const contract = factory.contract
1394
- const address = params.address ?? addressFromContractId(binToHex(crypto.getRandomValues(new Uint8Array(32))))
1395
- const contractId = binToHex(contractIdFromAddress(address))
1469
+ const selfContract = factory.contract
1470
+ const selfAddress = params.address ?? addressFromContractId(binToHex(crypto.getRandomValues(new Uint8Array(32))))
1471
+ const selfContractId = binToHex(contractIdFromAddress(selfAddress))
1396
1472
  const group = params.group ?? 0
1397
- const initialMaps = params.initialMaps ?? {}
1398
- const contractStates = mapsToExistingContracts(contract, contractId, group, initialMaps)
1399
- const apiParams = contract.toApiTestContractParams(methodName, {
1473
+ const existingContracts = getTestExistingContracts(selfContract, selfContractId, group, params, getContractByCodeHash)
1474
+
1475
+ const apiParams = selfContract.toApiTestContractParams(methodName, {
1400
1476
  ...params,
1401
- address,
1477
+ address: selfAddress,
1402
1478
  txId: txId,
1403
- initialFields: addStdIdToFields(contract, params.initialFields ?? {}),
1479
+ initialFields: addStdIdToFields(selfContract, params.initialFields ?? {}),
1404
1480
  testArgs: params.testArgs === undefined ? {} : params.testArgs,
1405
- existingContracts: (params.existingContracts ?? []).concat(contractStates)
1481
+ existingContracts
1406
1482
  })
1407
1483
  const apiResult = await getCurrentNodeProvider().contracts.postContractsTestContract(apiParams)
1408
- const maps = existingContractsToMaps(contract, address, group, apiResult, initialMaps)
1409
- const testResult = contract.fromApiTestContractResult(methodName, apiResult, txId, getContractByCodeHash)
1410
- contract.printDebugMessages(methodName, testResult.debugMessages)
1484
+ const allMaps = extractMapsFromApiResult(selfAddress, params, group, apiResult, getContractByCodeHash)
1485
+ const testResult = selfContract.fromApiTestContractResult(methodName, apiResult, txId, getContractByCodeHash)
1486
+ testResult.contracts.forEach((c) => {
1487
+ const maps = allMaps.find((v) => v.address === c.address)?.maps
1488
+ if (maps !== undefined) c['maps'] = maps
1489
+ })
1490
+ selfContract.printDebugMessages(methodName, testResult.debugMessages)
1411
1491
  return {
1412
1492
  ...testResult,
1413
- maps
1493
+ maps: allMaps.find((v) => v.address === selfAddress)?.maps
1414
1494
  } as TestContractResult<R, M>
1415
1495
  }
1416
1496