@alephium/web3 1.7.1 → 1.7.3

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.
@@ -1,4 +1,5 @@
1
1
  import { KeyType } from '../signer';
2
+ import { LockupScript } from '../codec/lockup-script-codec';
2
3
  export declare enum AddressType {
3
4
  P2PKH = 0,
4
5
  P2MPKH = 1,
@@ -20,4 +21,4 @@ export declare function addressFromContractId(contractId: string): string;
20
21
  export declare function addressFromTokenId(tokenId: string): string;
21
22
  export declare function contractIdFromTx(txId: string, outputIndex: number): string;
22
23
  export declare function subContractId(parentContractId: string, pathInHex: string, group: number): string;
23
- export declare function xorByte(intValue: number): number;
24
+ export declare function groupOfLockupScript(lockupScript: LockupScript): number;
@@ -20,16 +20,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
20
20
  return (mod && mod.__esModule) ? mod : { "default": mod };
21
21
  };
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.xorByte = exports.subContractId = exports.contractIdFromTx = exports.addressFromTokenId = exports.addressFromContractId = exports.addressFromScript = exports.addressFromPublicKey = exports.publicKeyFromPrivateKey = exports.groupOfPrivateKey = exports.tokenIdFromAddress = exports.contractIdFromAddress = exports.groupOfAddress = exports.isContractAddress = exports.isAssetAddress = exports.isValidAddress = exports.validateAddress = exports.AddressType = void 0;
23
+ exports.groupOfLockupScript = exports.subContractId = exports.contractIdFromTx = exports.addressFromTokenId = exports.addressFromContractId = exports.addressFromScript = exports.addressFromPublicKey = exports.publicKeyFromPrivateKey = exports.groupOfPrivateKey = exports.tokenIdFromAddress = exports.contractIdFromAddress = exports.groupOfAddress = exports.isContractAddress = exports.isAssetAddress = exports.isValidAddress = exports.validateAddress = exports.AddressType = void 0;
24
24
  const elliptic_1 = require("elliptic");
25
25
  const bn_js_1 = __importDefault(require("bn.js"));
26
26
  const constants_1 = require("../constants");
27
27
  const blakejs_1 = __importDefault(require("blakejs"));
28
28
  const bs58_1 = __importDefault(require("../utils/bs58"));
29
- const djb2_1 = __importDefault(require("../utils/djb2"));
30
29
  const utils_1 = require("../utils");
31
30
  const lockup_script_codec_1 = require("../codec/lockup-script-codec");
32
31
  const codec_1 = require("../codec");
32
+ const djb2_1 = __importDefault(require("../utils/djb2"));
33
33
  const ec = new elliptic_1.ec('secp256k1');
34
34
  const PublicKeyHashSize = 32;
35
35
  var AddressType;
@@ -120,23 +120,17 @@ function groupOfAddress(address) {
120
120
  }
121
121
  }
122
122
  exports.groupOfAddress = groupOfAddress;
123
- function groupOfAddressBytes(bytes) {
124
- const hint = (0, djb2_1.default)(bytes) | 1;
125
- const hash = xorByte(hint);
126
- const group = hash % constants_1.TOTAL_NUMBER_OF_GROUPS;
127
- return group;
128
- }
129
123
  // Pay to public key hash address
130
124
  function groupOfP2pkhAddress(address) {
131
- return groupOfAddressBytes(address);
125
+ return groupFromBytesForAssetAddress(address);
132
126
  }
133
127
  // Pay to multiple public key hash address
134
128
  function groupOfP2mpkhAddress(address) {
135
- return groupOfAddressBytes(address.slice(1, 33));
129
+ return groupFromBytesForAssetAddress(address.slice(1, 33));
136
130
  }
137
131
  // Pay to script hash address
138
132
  function groupOfP2shAddress(address) {
139
- return groupOfAddressBytes(address);
133
+ return groupFromBytesForAssetAddress(address);
140
134
  }
141
135
  function contractIdFromAddress(address) {
142
136
  return idFromAddress(address);
@@ -228,11 +222,25 @@ function subContractId(parentContractId, pathInHex, group) {
228
222
  return (0, utils_1.binToHex)(bytes);
229
223
  }
230
224
  exports.subContractId = subContractId;
231
- function xorByte(intValue) {
232
- const byte0 = (intValue >> 24) & 0xff;
233
- const byte1 = (intValue >> 16) & 0xff;
234
- const byte2 = (intValue >> 8) & 0xff;
235
- const byte3 = intValue & 0xff;
236
- return (byte0 ^ byte1 ^ byte2 ^ byte3) & 0xff;
237
- }
238
- exports.xorByte = xorByte;
225
+ function groupOfLockupScript(lockupScript) {
226
+ if (lockupScript.kind === 'P2PKH') {
227
+ return groupFromBytesForAssetAddress(lockupScript.value);
228
+ }
229
+ else if (lockupScript.kind === 'P2MPKH') {
230
+ return groupFromBytesForAssetAddress(lockupScript.value.publicKeyHashes[0]);
231
+ }
232
+ else if (lockupScript.kind === 'P2SH') {
233
+ return groupFromBytesForAssetAddress(lockupScript.value);
234
+ }
235
+ else {
236
+ // P2C
237
+ const contractId = lockupScript.value;
238
+ return contractId[`${contractId.length - 1}`];
239
+ }
240
+ }
241
+ exports.groupOfLockupScript = groupOfLockupScript;
242
+ function groupFromBytesForAssetAddress(bytes) {
243
+ const hint = (0, djb2_1.default)(bytes) | 1;
244
+ const hash = (0, utils_1.xorByte)(hint);
245
+ return hash % constants_1.TOTAL_NUMBER_OF_GROUPS;
246
+ }
@@ -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"));
@@ -672,12 +672,18 @@ class ContractFactory {
672
672
  });
673
673
  }
674
674
  // This is used for testing contract functions
675
- stateForTest(initFields, asset, address) {
675
+ stateForTest_(initFields, asset, address, maps) {
676
676
  const newAsset = {
677
- alphAmount: asset?.alphAmount ?? constants_1.ONE_ALPH,
677
+ alphAmount: asset?.alphAmount ?? constants_1.MINIMAL_CONTRACT_DEPOSIT,
678
678
  tokens: asset?.tokens
679
679
  };
680
- 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
+ };
681
687
  }
682
688
  }
683
689
  exports.ContractFactory = ContractFactory;
@@ -875,29 +881,65 @@ function mapsToExistingContracts(contract, parentContractId, group, initialMaps)
875
881
  });
876
882
  return contractStates;
877
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;
878
916
  async function testMethod(factory, methodName, params, getContractByCodeHash) {
879
917
  const txId = params?.txId ?? randomTxId();
880
- const contract = factory.contract;
881
- const address = params.address ?? (0, address_1.addressFromContractId)((0, utils_1.binToHex)(crypto.getRandomValues(new Uint8Array(32))));
882
- 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));
883
921
  const group = params.group ?? 0;
884
- const initialMaps = params.initialMaps ?? {};
885
- const contractStates = mapsToExistingContracts(contract, contractId, group, initialMaps);
886
- const apiParams = contract.toApiTestContractParams(methodName, {
922
+ const existingContracts = getTestExistingContracts(selfContract, selfContractId, group, params, getContractByCodeHash);
923
+ const apiParams = selfContract.toApiTestContractParams(methodName, {
887
924
  ...params,
888
- address,
925
+ address: selfAddress,
889
926
  txId: txId,
890
- initialFields: addStdIdToFields(contract, params.initialFields ?? {}),
927
+ initialFields: addStdIdToFields(selfContract, params.initialFields ?? {}),
891
928
  testArgs: params.testArgs === undefined ? {} : params.testArgs,
892
- existingContracts: (params.existingContracts ?? []).concat(contractStates)
929
+ existingContracts
893
930
  });
894
931
  const apiResult = await (0, global_1.getCurrentNodeProvider)().contracts.postContractsTestContract(apiParams);
895
- const maps = existingContractsToMaps(contract, address, group, apiResult, initialMaps);
896
- const testResult = contract.fromApiTestContractResult(methodName, apiResult, txId, getContractByCodeHash);
897
- 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);
898
940
  return {
899
941
  ...testResult,
900
- maps
942
+ maps: allMaps.find((v) => v.address === selfAddress)?.maps
901
943
  };
902
944
  }
903
945
  exports.testMethod = testMethod;
@@ -8,5 +8,5 @@ export declare abstract class TransactionBuilder {
8
8
  buildTransferTx(params: SignTransferTxParams, publicKey: string): Promise<Omit<SignTransferTxResult, 'signature'>>;
9
9
  buildDeployContractTx(params: SignDeployContractTxParams, publicKey: string): Promise<Omit<SignDeployContractTxResult, 'signature'>>;
10
10
  buildExecuteScriptTx(params: SignExecuteScriptTxParams, publicKey: string): Promise<Omit<SignExecuteScriptTxResult, 'signature'>>;
11
- buildUnsignedTx(params: SignUnsignedTxParams): Promise<Omit<SignUnsignedTxResult, 'signature'>>;
11
+ buildUnsignedTx(params: SignUnsignedTxParams): Omit<SignUnsignedTxResult, 'signature'>;
12
12
  }
@@ -22,6 +22,9 @@ const utils_1 = require("../utils");
22
22
  const api_1 = require("../api");
23
23
  const address_1 = require("../address");
24
24
  const signer_1 = require("./signer");
25
+ const codec_1 = require("../codec");
26
+ const transaction_1 = require("../transaction");
27
+ const hash_1 = require("../codec/hash");
25
28
  class TransactionBuilder {
26
29
  static from(param0, param1, customFetch) {
27
30
  const nodeProvider = typeof param0 === 'string' ? new api_1.NodeProvider(param0, param1, customFetch) : param0;
@@ -80,16 +83,18 @@ class TransactionBuilder {
80
83
  const response = await this.nodeProvider.contracts.postContractsUnsignedTxExecuteScript(data);
81
84
  return { ...response, groupIndex: response.fromGroup, gasPrice: (0, api_1.fromApiNumber256)(response.gasPrice) };
82
85
  }
83
- async buildUnsignedTx(params) {
84
- const data = { unsignedTx: params.unsignedTx };
85
- const decoded = await this.nodeProvider.transactions.postTransactionsDecodeUnsignedTx(data);
86
+ buildUnsignedTx(params) {
87
+ const unsignedTxBin = (0, utils_1.hexToBinUnsafe)(params.unsignedTx);
88
+ const decoded = codec_1.unsignedTxCodec.decode(unsignedTxBin);
89
+ const txId = (0, utils_1.binToHex)((0, hash_1.blakeHash)(unsignedTxBin));
90
+ const [fromGroup, toGroup] = (0, transaction_1.groupIndexOfTransaction)(decoded);
86
91
  return {
87
- fromGroup: decoded.fromGroup,
88
- toGroup: decoded.toGroup,
92
+ fromGroup: fromGroup,
93
+ toGroup: toGroup,
89
94
  unsignedTx: params.unsignedTx,
90
- txId: decoded.unsignedTx.txId,
91
- gasAmount: decoded.unsignedTx.gasAmount,
92
- gasPrice: (0, api_1.fromApiNumber256)(decoded.unsignedTx.gasPrice)
95
+ txId: txId,
96
+ gasAmount: decoded.gasAmount,
97
+ gasPrice: decoded.gasPrice
93
98
  };
94
99
  }
95
100
  }
@@ -1,2 +1,4 @@
1
1
  import { node } from '../api';
2
+ import { UnsignedTx } from '../codec';
2
3
  export declare function waitForTxConfirmation(txId: string, confirmations: number, requestInterval: number): Promise<node.Confirmed>;
4
+ export declare function groupIndexOfTransaction(unsignedTx: UnsignedTx): [number, number];
@@ -17,8 +17,11 @@ You should have received a copy of the GNU Lesser General Public License
17
17
  along with the library. If not, see <http://www.gnu.org/licenses/>.
18
18
  */
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.waitForTxConfirmation = void 0;
20
+ exports.groupIndexOfTransaction = exports.waitForTxConfirmation = void 0;
21
+ const address_1 = require("../address");
22
+ const constants_1 = require("../constants");
21
23
  const global_1 = require("../global");
24
+ const utils_1 = require("../utils");
22
25
  function isConfirmed(txStatus) {
23
26
  return txStatus.type === 'Confirmed';
24
27
  }
@@ -32,3 +35,22 @@ async function waitForTxConfirmation(txId, confirmations, requestInterval) {
32
35
  return waitForTxConfirmation(txId, confirmations, requestInterval);
33
36
  }
34
37
  exports.waitForTxConfirmation = waitForTxConfirmation;
38
+ function groupIndexOfTransaction(unsignedTx) {
39
+ if (unsignedTx.inputs.length === 0)
40
+ throw new Error('Empty inputs for unsignedTx');
41
+ const fromGroup = groupFromHint(unsignedTx.inputs[0].hint);
42
+ let toGroup = fromGroup;
43
+ for (const output of unsignedTx.fixedOutputs) {
44
+ const outputGroup = (0, address_1.groupOfLockupScript)(output.lockupScript);
45
+ if (outputGroup !== fromGroup) {
46
+ toGroup = outputGroup;
47
+ break;
48
+ }
49
+ }
50
+ return [fromGroup, toGroup];
51
+ }
52
+ exports.groupIndexOfTransaction = groupIndexOfTransaction;
53
+ function groupFromHint(hint) {
54
+ const hash = (0, utils_1.xorByte)(hint);
55
+ return hash % constants_1.TOTAL_NUMBER_OF_GROUPS;
56
+ }
@@ -24,6 +24,7 @@ export declare function isDevnet(networkId?: number): boolean;
24
24
  export declare function targetToDifficulty(compactedTarget: HexString): bigint;
25
25
  export declare function difficultyToTarget(diff: bigint): HexString;
26
26
  export declare function concatBytes(arrays: Uint8Array[]): Uint8Array;
27
+ export declare function xorByte(intValue: number): number;
27
28
  type _Eq<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
28
29
  export type Eq<X, Y> = _Eq<{
29
30
  [P in keyof X]: X[P];
@@ -20,7 +20,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
20
20
  return (mod && mod.__esModule) ? mod : { "default": mod };
21
21
  };
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.assertType = exports.concatBytes = exports.difficultyToTarget = exports.targetToDifficulty = exports.isDevnet = exports.sleep = exports.hexToString = exports.stringToHex = exports.blockChainIndex = exports.binToHex = exports.hexToBinUnsafe = exports.toNonNegativeBigInt = exports.isHexString = exports.signatureDecode = exports.encodeHexSignature = exports.encodeSignature = exports.networkIds = void 0;
23
+ exports.assertType = exports.xorByte = exports.concatBytes = exports.difficultyToTarget = exports.targetToDifficulty = exports.isDevnet = exports.sleep = exports.hexToString = exports.stringToHex = exports.blockChainIndex = exports.binToHex = exports.hexToBinUnsafe = exports.toNonNegativeBigInt = exports.isHexString = exports.signatureDecode = exports.encodeHexSignature = exports.encodeSignature = exports.networkIds = void 0;
24
24
  const elliptic_1 = require("elliptic");
25
25
  const bn_js_1 = __importDefault(require("bn.js"));
26
26
  const constants_1 = require("../constants");
@@ -153,6 +153,14 @@ function concatBytes(arrays) {
153
153
  return result;
154
154
  }
155
155
  exports.concatBytes = concatBytes;
156
+ function xorByte(intValue) {
157
+ const byte0 = (intValue >> 24) & 0xff;
158
+ const byte1 = (intValue >> 16) & 0xff;
159
+ const byte2 = (intValue >> 8) & 0xff;
160
+ const byte3 = intValue & 0xff;
161
+ return (byte0 ^ byte1 ^ byte2 ^ byte3) & 0xff;
162
+ }
163
+ exports.xorByte = xorByte;
156
164
  // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
157
165
  function assertType() { }
158
166
  exports.assertType = assertType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/web3",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "A JS/TS library to interact with the Alephium platform",
5
5
  "license": "GPL",
6
6
  "main": "dist/src/index.js",
@@ -83,7 +83,7 @@
83
83
  "ts-node": "^10.9.1",
84
84
  "tslib": "^2.5.0",
85
85
  "typescript": "^4.9.5",
86
- "webpack": "^5.77.0",
86
+ "webpack": "^5.94.0",
87
87
  "webpack-cli": "^4.10.0"
88
88
  },
89
89
  "engines": {
@@ -21,11 +21,12 @@ import BN from 'bn.js'
21
21
  import { TOTAL_NUMBER_OF_GROUPS } from '../constants'
22
22
  import blake from 'blakejs'
23
23
  import bs58 from '../utils/bs58'
24
- import djb2 from '../utils/djb2'
25
- import { binToHex, concatBytes, hexToBinUnsafe, isHexString } from '../utils'
24
+ import { binToHex, concatBytes, hexToBinUnsafe, isHexString, xorByte } from '../utils'
26
25
  import { KeyType } from '../signer'
27
26
  import { P2MPKH, lockupScriptCodec } from '../codec/lockup-script-codec'
28
27
  import { i32Codec } from '../codec'
28
+ import { LockupScript } from '../codec/lockup-script-codec'
29
+ import djb2 from '../utils/djb2'
29
30
 
30
31
  const ec = new EC('secp256k1')
31
32
  const PublicKeyHashSize = 32
@@ -112,26 +113,19 @@ export function groupOfAddress(address: string): number {
112
113
  }
113
114
  }
114
115
 
115
- function groupOfAddressBytes(bytes: Uint8Array): number {
116
- const hint = djb2(bytes) | 1
117
- const hash = xorByte(hint)
118
- const group = hash % TOTAL_NUMBER_OF_GROUPS
119
- return group
120
- }
121
-
122
116
  // Pay to public key hash address
123
117
  function groupOfP2pkhAddress(address: Uint8Array): number {
124
- return groupOfAddressBytes(address)
118
+ return groupFromBytesForAssetAddress(address)
125
119
  }
126
120
 
127
121
  // Pay to multiple public key hash address
128
122
  function groupOfP2mpkhAddress(address: Uint8Array): number {
129
- return groupOfAddressBytes(address.slice(1, 33))
123
+ return groupFromBytesForAssetAddress(address.slice(1, 33))
130
124
  }
131
125
 
132
126
  // Pay to script hash address
133
127
  function groupOfP2shAddress(address: Uint8Array): number {
134
- return groupOfAddressBytes(address)
128
+ return groupFromBytesForAssetAddress(address)
135
129
  }
136
130
 
137
131
  export function contractIdFromAddress(address: string): Uint8Array {
@@ -225,10 +219,22 @@ export function subContractId(parentContractId: string, pathInHex: string, group
225
219
  return binToHex(bytes)
226
220
  }
227
221
 
228
- export function xorByte(intValue: number): number {
229
- const byte0 = (intValue >> 24) & 0xff
230
- const byte1 = (intValue >> 16) & 0xff
231
- const byte2 = (intValue >> 8) & 0xff
232
- const byte3 = intValue & 0xff
233
- return (byte0 ^ byte1 ^ byte2 ^ byte3) & 0xff
222
+ export function groupOfLockupScript(lockupScript: LockupScript): number {
223
+ if (lockupScript.kind === 'P2PKH') {
224
+ return groupFromBytesForAssetAddress(lockupScript.value)
225
+ } else if (lockupScript.kind === 'P2MPKH') {
226
+ return groupFromBytesForAssetAddress(lockupScript.value.publicKeyHashes[0])
227
+ } else if (lockupScript.kind === 'P2SH') {
228
+ return groupFromBytesForAssetAddress(lockupScript.value)
229
+ } else {
230
+ // P2C
231
+ const contractId = lockupScript.value
232
+ return contractId[`${contractId.length - 1}`]
233
+ }
234
+ }
235
+
236
+ function groupFromBytesForAssetAddress(bytes: Uint8Array): number {
237
+ const hint = djb2(bytes) | 1
238
+ const hash = xorByte(hint)
239
+ return hash % TOTAL_NUMBER_OF_GROUPS
234
240
  }
@@ -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 {
@@ -885,6 +885,13 @@ export interface ContractState<T extends Fields = Fields> {
885
885
  asset: Asset
886
886
  }
887
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
+
888
895
  function toApiContractState(state: ContractState, structs: Struct[]): node.ContractState {
889
896
  const stateFields = state.fields ?? {}
890
897
  const fieldsSig = state.fieldsSig
@@ -942,7 +949,7 @@ export interface TestContractParams<
942
949
  initialMaps?: M
943
950
  initialAsset?: Asset // default 1 ALPH
944
951
  testArgs: A
945
- existingContracts?: ContractState[] // default no existing contracts
952
+ existingContracts?: ContractStateWithMaps[] // default no existing contracts
946
953
  inputAssets?: InputAsset[] // default no input asserts
947
954
  }
948
955
 
@@ -965,7 +972,7 @@ export interface TestContractResult<R, M extends Record<string, Map<Val, Val>> =
965
972
  returns: R
966
973
  gasUsed: number
967
974
  maps?: M
968
- contracts: ContractState[]
975
+ contracts: ContractStateWithMaps[]
969
976
  txOutputs: Output[]
970
977
  events: ContractEvent[]
971
978
  debugMessages: DebugMessage[]
@@ -1065,12 +1072,23 @@ export abstract class ContractFactory<I extends ContractInstance, F extends Fiel
1065
1072
  }
1066
1073
 
1067
1074
  // This is used for testing contract functions
1068
- 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> {
1069
1081
  const newAsset = {
1070
- alphAmount: asset?.alphAmount ?? ONE_ALPH,
1082
+ alphAmount: asset?.alphAmount ?? MINIMAL_CONTRACT_DEPOSIT,
1071
1083
  tokens: asset?.tokens
1072
1084
  }
1073
- 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
+ }
1074
1092
  }
1075
1093
  }
1076
1094
 
@@ -1381,6 +1399,60 @@ function mapsToExistingContracts(
1381
1399
  return contractStates
1382
1400
  }
1383
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
+
1384
1456
  export async function testMethod<
1385
1457
  I extends ContractInstance,
1386
1458
  F extends Fields,
@@ -1394,27 +1466,31 @@ export async function testMethod<
1394
1466
  getContractByCodeHash: (codeHash: string) => Contract
1395
1467
  ): Promise<TestContractResult<R, M>> {
1396
1468
  const txId = params?.txId ?? randomTxId()
1397
- const contract = factory.contract
1398
- const address = params.address ?? addressFromContractId(binToHex(crypto.getRandomValues(new Uint8Array(32))))
1399
- 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))
1400
1472
  const group = params.group ?? 0
1401
- const initialMaps = params.initialMaps ?? {}
1402
- const contractStates = mapsToExistingContracts(contract, contractId, group, initialMaps)
1403
- const apiParams = contract.toApiTestContractParams(methodName, {
1473
+ const existingContracts = getTestExistingContracts(selfContract, selfContractId, group, params, getContractByCodeHash)
1474
+
1475
+ const apiParams = selfContract.toApiTestContractParams(methodName, {
1404
1476
  ...params,
1405
- address,
1477
+ address: selfAddress,
1406
1478
  txId: txId,
1407
- initialFields: addStdIdToFields(contract, params.initialFields ?? {}),
1479
+ initialFields: addStdIdToFields(selfContract, params.initialFields ?? {}),
1408
1480
  testArgs: params.testArgs === undefined ? {} : params.testArgs,
1409
- existingContracts: (params.existingContracts ?? []).concat(contractStates)
1481
+ existingContracts
1410
1482
  })
1411
1483
  const apiResult = await getCurrentNodeProvider().contracts.postContractsTestContract(apiParams)
1412
- const maps = existingContractsToMaps(contract, address, group, apiResult, initialMaps)
1413
- const testResult = contract.fromApiTestContractResult(methodName, apiResult, txId, getContractByCodeHash)
1414
- 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)
1415
1491
  return {
1416
1492
  ...testResult,
1417
- maps
1493
+ maps: allMaps.find((v) => v.address === selfAddress)?.maps
1418
1494
  } as TestContractResult<R, M>
1419
1495
  }
1420
1496