@alephium/web3 1.6.0 → 1.7.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.
@@ -2,7 +2,7 @@ import { NamedVals, node, NodeProvider, Number256, Token, Val } from '../api';
2
2
  import { SignDeployContractTxParams, SignDeployContractTxResult, SignExecuteScriptTxParams, SignerProvider, Address, SignExecuteScriptTxResult } from '../signer';
3
3
  import { Optional, HexString } from '../utils';
4
4
  import { EventSubscribeOptions, EventSubscription } from './events';
5
- import { Method } from '../codec';
5
+ import { contract, Method } from '../codec';
6
6
  export type FieldsSig = node.FieldsSig;
7
7
  export type MapsSig = node.MapsSig;
8
8
  export type EventSig = node.EventSig;
@@ -32,7 +32,7 @@ export declare abstract class Artifact {
32
32
  readonly name: string;
33
33
  readonly functions: FunctionSig[];
34
34
  constructor(version: string, name: string, functions: FunctionSig[]);
35
- abstract buildByteCodeToDeploy(initialFields: Fields, isDevnet: boolean): string;
35
+ abstract buildByteCodeToDeploy(initialFields: Fields, isDevnet: boolean, exposePrivateFunctions: boolean): string;
36
36
  isDevnet(signer: SignerProvider): Promise<boolean>;
37
37
  }
38
38
  export declare class Contract extends Artifact {
@@ -48,11 +48,17 @@ export declare class Contract extends Artifact {
48
48
  readonly stdInterfaceId?: HexString;
49
49
  readonly bytecodeDebug: string;
50
50
  readonly codeHashDebug: string;
51
- readonly decodedMethods: Method[];
51
+ readonly decodedContract: contract.Contract;
52
+ private bytecodeForTesting;
53
+ private codeHashForTesting;
52
54
  constructor(version: string, name: string, bytecode: string, bytecodeDebugPatch: string, codeHash: string, codeHashDebug: string, fieldsSig: FieldsSig, eventsSig: EventSig[], functions: FunctionSig[], constants: Constant[], enums: Enum[], structs: Struct[], mapsSig?: MapsSig, stdInterfaceId?: HexString);
55
+ getByteCodeForTesting(): string;
56
+ hasCodeHash(hash: string): boolean;
57
+ getDecodedMethod(methodIndex: number): Method;
53
58
  publicFunctions(): FunctionSig[];
54
59
  usingPreapprovedAssetsFunctions(): FunctionSig[];
55
60
  usingAssetsInContractFunctions(): FunctionSig[];
61
+ isMethodUsePreapprovedAssets(methodIndex: number): boolean;
56
62
  static fromJson(artifact: any, bytecodeDebugPatch?: string, codeHashDebug?: string, structs?: Struct[]): Contract;
57
63
  static fromCompileResult(result: node.CompileContractResult, structs?: Struct[]): Contract;
58
64
  static fromArtifactFile(path: string, bytecodeDebugPatch: string, codeHashDebug: string, structs?: Struct[]): Promise<Contract>;
@@ -75,7 +81,7 @@ export declare class Contract extends Artifact {
75
81
  static fromApiEvent(event: node.ContractEventByTxId, codeHash: string | undefined, txId: string, getContractByCodeHash: (codeHash: string) => Contract): ContractEvent;
76
82
  fromApiTestContractResult(methodName: string, result: node.TestContractResult, txId: string, getContractByCodeHash: (codeHash: string) => Contract): TestContractResult<unknown>;
77
83
  txParamsForDeployment<P extends Fields>(signer: SignerProvider, params: DeployContractParams<P>): Promise<SignDeployContractTxParams>;
78
- buildByteCodeToDeploy(initialFields: Fields, isDevnet: boolean): string;
84
+ buildByteCodeToDeploy(initialFields: Fields, isDevnet: boolean, exposePrivateFunctions?: boolean): string;
79
85
  static fromApiEvents(events: node.ContractEventByTxId[], addressToCodeHash: Map<string, string>, txId: string, getContractByCodeHash: (codeHash: string) => Contract): ContractEvent[];
80
86
  toApiCallContract<T extends Arguments>(params: CallContractParams<T>, groupIndex: number, contractAddress: string, methodIndex: number): node.CallContract;
81
87
  fromApiCallContractResult(result: node.CallContractResult, txId: string, methodIndex: number, getContractByCodeHash: (codeHash: string) => Contract): CallContractResult<unknown>;
@@ -173,6 +179,7 @@ export interface DeployContractParams<P extends Fields = Fields> {
173
179
  issueTokenTo?: string;
174
180
  gasAmount?: number;
175
181
  gasPrice?: Number256;
182
+ exposePrivateFunctions?: boolean;
176
183
  }
177
184
  export type DeployContractResult<T extends ContractInstance> = Omit<SignDeployContractTxResult, 'contractId' | 'contractAddress' | 'groupIndex'> & {
178
185
  contractInstance: T;
@@ -129,16 +129,46 @@ class Contract extends Artifact {
129
129
  this.stdInterfaceId = stdInterfaceId;
130
130
  this.bytecodeDebug = ralph.buildDebugBytecode(this.bytecode, this.bytecodeDebugPatch);
131
131
  this.codeHashDebug = codeHashDebug;
132
- this.decodedMethods = codec_1.contract.contractCodec.decodeContract((0, utils_1.hexToBinUnsafe)(bytecode)).methods;
132
+ this.decodedContract = codec_1.contract.contractCodec.decodeContract((0, utils_1.hexToBinUnsafe)(this.bytecode));
133
+ this.bytecodeForTesting = undefined;
134
+ this.codeHashForTesting = undefined;
135
+ }
136
+ getByteCodeForTesting() {
137
+ if (this.bytecodeForTesting !== undefined)
138
+ return this.bytecodeForTesting;
139
+ if (this.publicFunctions().length == this.functions.length) {
140
+ this.bytecodeForTesting = this.bytecodeDebug;
141
+ this.codeHashForTesting = this.codeHashDebug;
142
+ return this.bytecodeForTesting;
143
+ }
144
+ const decodedDebugContract = codec_1.contract.contractCodec.decodeContract((0, utils_1.hexToBinUnsafe)(this.bytecodeDebug));
145
+ const methods = decodedDebugContract.methods.map((method) => ({ ...method, isPublic: true }));
146
+ const bytecodeForTesting = codec_1.contract.contractCodec.encodeContract({
147
+ fieldLength: decodedDebugContract.fieldLength,
148
+ methods: methods
149
+ });
150
+ const codeHashForTesting = blake.blake2b(bytecodeForTesting, undefined, 32);
151
+ this.bytecodeForTesting = (0, utils_1.binToHex)(bytecodeForTesting);
152
+ this.codeHashForTesting = (0, utils_1.binToHex)(codeHashForTesting);
153
+ return this.bytecodeForTesting;
154
+ }
155
+ hasCodeHash(hash) {
156
+ return this.codeHash === hash || this.codeHashDebug === hash || this.codeHashForTesting === hash;
157
+ }
158
+ getDecodedMethod(methodIndex) {
159
+ return this.decodedContract.methods[`${methodIndex}`];
133
160
  }
134
161
  publicFunctions() {
135
- return this.functions.filter((_, index) => this.decodedMethods[`${index}`].isPublic);
162
+ return this.functions.filter((_, index) => this.getDecodedMethod(index).isPublic);
136
163
  }
137
164
  usingPreapprovedAssetsFunctions() {
138
- return this.functions.filter((_, index) => this.decodedMethods[`${index}`].usePreapprovedAssets);
165
+ return this.functions.filter((_, index) => this.getDecodedMethod(index).usePreapprovedAssets);
139
166
  }
140
167
  usingAssetsInContractFunctions() {
141
- return this.functions.filter((_, index) => this.decodedMethods[`${index}`].useContractAssets);
168
+ return this.functions.filter((_, index) => this.getDecodedMethod(index).useContractAssets);
169
+ }
170
+ isMethodUsePreapprovedAssets(methodIndex) {
171
+ return this.getDecodedMethod(methodIndex).usePreapprovedAssets;
142
172
  }
143
173
  // TODO: safely parse json
144
174
  static fromJson(artifact, bytecodeDebugPatch = '', codeHashDebug = '', structs = []) {
@@ -333,7 +363,7 @@ class Contract extends Artifact {
333
363
  async txParamsForDeployment(signer, params) {
334
364
  const isDevnet = await this.isDevnet(signer);
335
365
  const initialFields = params.initialFields ?? {};
336
- const bytecode = this.buildByteCodeToDeploy(addStdIdToFields(this, initialFields), isDevnet);
366
+ const bytecode = this.buildByteCodeToDeploy(addStdIdToFields(this, initialFields), isDevnet, params.exposePrivateFunctions ?? false);
337
367
  const selectedAccount = await signer.getSelectedAccount();
338
368
  const signerParams = {
339
369
  signerAddress: selectedAccount.address,
@@ -348,9 +378,17 @@ class Contract extends Artifact {
348
378
  };
349
379
  return signerParams;
350
380
  }
351
- buildByteCodeToDeploy(initialFields, isDevnet) {
381
+ buildByteCodeToDeploy(initialFields, isDevnet, exposePrivateFunctions = false) {
382
+ if (exposePrivateFunctions && !isDevnet) {
383
+ throw new Error('Cannot expose private functions in non-devnet environment');
384
+ }
352
385
  try {
353
- return ralph.buildContractByteCode(isDevnet ? this.bytecodeDebug : this.bytecode, initialFields, this.fieldsSig, this.structs);
386
+ const bytecode = exposePrivateFunctions && isDevnet
387
+ ? this.getByteCodeForTesting()
388
+ : isDevnet
389
+ ? this.bytecodeDebug
390
+ : this.bytecode;
391
+ return ralph.buildContractByteCode(bytecode, initialFields, this.fieldsSig, this.structs);
354
392
  }
355
393
  catch (error) {
356
394
  throw new Error(`Failed to build bytecode for contract ${this.name}, error: ${error}`);
@@ -1074,7 +1112,7 @@ exports.callMethod = callMethod;
1074
1112
  async function signExecuteMethod(contract, instance, methodName, params) {
1075
1113
  const methodIndex = contract.contract.getMethodIndex(methodName);
1076
1114
  const functionSig = contract.contract.functions[methodIndex];
1077
- const methodUsePreapprovedAssets = contract.contract.decodedMethods[methodIndex].usePreapprovedAssets;
1115
+ const methodUsePreapprovedAssets = contract.contract.isMethodUsePreapprovedAssets(methodIndex);
1078
1116
  const bytecodeTemplate = getBytecodeTemplate(methodIndex, methodUsePreapprovedAssets, functionSig, contract.contract.structs, params.attoAlphAmount, params.tokens);
1079
1117
  const fieldsSig = toFieldsSig(contract.contract.name, functionSig);
1080
1118
  const bytecode = ralph.buildScriptByteCode(bytecodeTemplate, { __contract__: instance.contractId, ...params.args }, fieldsSig, contract.contract.structs);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/web3",
3
- "version": "1.6.0",
3
+ "version": "1.7.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",
@@ -162,7 +162,7 @@ export abstract class Artifact {
162
162
  this.functions = functions
163
163
  }
164
164
 
165
- abstract buildByteCodeToDeploy(initialFields: Fields, isDevnet: boolean): string
165
+ abstract buildByteCodeToDeploy(initialFields: Fields, isDevnet: boolean, exposePrivateFunctions: boolean): string
166
166
 
167
167
  async isDevnet(signer: SignerProvider): Promise<boolean> {
168
168
  if (!signer.nodeProvider) {
@@ -197,7 +197,10 @@ export class Contract extends Artifact {
197
197
 
198
198
  readonly bytecodeDebug: string
199
199
  readonly codeHashDebug: string
200
- readonly decodedMethods: Method[]
200
+ readonly decodedContract: contract.Contract
201
+
202
+ private bytecodeForTesting: string | undefined
203
+ private codeHashForTesting: string | undefined
201
204
 
202
205
  constructor(
203
206
  version: string,
@@ -230,19 +233,54 @@ export class Contract extends Artifact {
230
233
  this.bytecodeDebug = ralph.buildDebugBytecode(this.bytecode, this.bytecodeDebugPatch)
231
234
  this.codeHashDebug = codeHashDebug
232
235
 
233
- this.decodedMethods = contract.contractCodec.decodeContract(hexToBinUnsafe(bytecode)).methods
236
+ this.decodedContract = contract.contractCodec.decodeContract(hexToBinUnsafe(this.bytecode))
237
+ this.bytecodeForTesting = undefined
238
+ this.codeHashForTesting = undefined
239
+ }
240
+
241
+ getByteCodeForTesting(): string {
242
+ if (this.bytecodeForTesting !== undefined) return this.bytecodeForTesting
243
+
244
+ if (this.publicFunctions().length == this.functions.length) {
245
+ this.bytecodeForTesting = this.bytecodeDebug
246
+ this.codeHashForTesting = this.codeHashDebug
247
+ return this.bytecodeForTesting
248
+ }
249
+
250
+ const decodedDebugContract = contract.contractCodec.decodeContract(hexToBinUnsafe(this.bytecodeDebug))
251
+ const methods = decodedDebugContract.methods.map((method) => ({ ...method, isPublic: true }))
252
+ const bytecodeForTesting = contract.contractCodec.encodeContract({
253
+ fieldLength: decodedDebugContract.fieldLength,
254
+ methods: methods
255
+ })
256
+ const codeHashForTesting = blake.blake2b(bytecodeForTesting, undefined, 32)
257
+ this.bytecodeForTesting = binToHex(bytecodeForTesting)
258
+ this.codeHashForTesting = binToHex(codeHashForTesting)
259
+ return this.bytecodeForTesting
260
+ }
261
+
262
+ hasCodeHash(hash: string): boolean {
263
+ return this.codeHash === hash || this.codeHashDebug === hash || this.codeHashForTesting === hash
264
+ }
265
+
266
+ getDecodedMethod(methodIndex: number): Method {
267
+ return this.decodedContract.methods[`${methodIndex}`]
234
268
  }
235
269
 
236
270
  publicFunctions(): FunctionSig[] {
237
- return this.functions.filter((_, index) => this.decodedMethods[`${index}`].isPublic)
271
+ return this.functions.filter((_, index) => this.getDecodedMethod(index).isPublic)
238
272
  }
239
273
 
240
274
  usingPreapprovedAssetsFunctions(): FunctionSig[] {
241
- return this.functions.filter((_, index) => this.decodedMethods[`${index}`].usePreapprovedAssets)
275
+ return this.functions.filter((_, index) => this.getDecodedMethod(index).usePreapprovedAssets)
242
276
  }
243
277
 
244
278
  usingAssetsInContractFunctions(): FunctionSig[] {
245
- return this.functions.filter((_, index) => this.decodedMethods[`${index}`].useContractAssets)
279
+ return this.functions.filter((_, index) => this.getDecodedMethod(index).useContractAssets)
280
+ }
281
+
282
+ isMethodUsePreapprovedAssets(methodIndex: number): boolean {
283
+ return this.getDecodedMethod(methodIndex).usePreapprovedAssets
246
284
  }
247
285
 
248
286
  // TODO: safely parse json
@@ -530,7 +568,11 @@ export class Contract extends Artifact {
530
568
  ): Promise<SignDeployContractTxParams> {
531
569
  const isDevnet = await this.isDevnet(signer)
532
570
  const initialFields: Fields = params.initialFields ?? {}
533
- const bytecode = this.buildByteCodeToDeploy(addStdIdToFields(this, initialFields), isDevnet)
571
+ const bytecode = this.buildByteCodeToDeploy(
572
+ addStdIdToFields(this, initialFields),
573
+ isDevnet,
574
+ params.exposePrivateFunctions ?? false
575
+ )
534
576
  const selectedAccount = await signer.getSelectedAccount()
535
577
  const signerParams: SignDeployContractTxParams = {
536
578
  signerAddress: selectedAccount.address,
@@ -546,14 +588,19 @@ export class Contract extends Artifact {
546
588
  return signerParams
547
589
  }
548
590
 
549
- buildByteCodeToDeploy(initialFields: Fields, isDevnet: boolean): string {
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
+
550
596
  try {
551
- return ralph.buildContractByteCode(
552
- isDevnet ? this.bytecodeDebug : this.bytecode,
553
- initialFields,
554
- this.fieldsSig,
555
- this.structs
556
- )
597
+ const bytecode =
598
+ exposePrivateFunctions && isDevnet
599
+ ? this.getByteCodeForTesting()
600
+ : isDevnet
601
+ ? this.bytecodeDebug
602
+ : this.bytecode
603
+ return ralph.buildContractByteCode(bytecode, initialFields, this.fieldsSig, this.structs)
557
604
  } catch (error) {
558
605
  throw new Error(`Failed to build bytecode for contract ${this.name}, error: ${error}`)
559
606
  }
@@ -975,10 +1022,11 @@ export interface DeployContractParams<P extends Fields = Fields> {
975
1022
  issueTokenTo?: string
976
1023
  gasAmount?: number
977
1024
  gasPrice?: Number256
1025
+ exposePrivateFunctions?: boolean
978
1026
  }
979
1027
  assertType<
980
1028
  Eq<
981
- Omit<DeployContractParams<undefined>, 'initialFields'>,
1029
+ Omit<DeployContractParams<undefined>, 'initialFields' | 'exposePrivateFunctions'>,
982
1030
  Omit<SignDeployContractTxParams, 'signerAddress' | 'signerKeyType' | 'bytecode'>
983
1031
  >
984
1032
  >
@@ -1687,7 +1735,7 @@ export async function signExecuteMethod<I extends ContractInstance, F extends Fi
1687
1735
  ): Promise<SignExecuteScriptTxResult> {
1688
1736
  const methodIndex = contract.contract.getMethodIndex(methodName)
1689
1737
  const functionSig = contract.contract.functions[methodIndex]
1690
- const methodUsePreapprovedAssets = contract.contract.decodedMethods[methodIndex].usePreapprovedAssets
1738
+ const methodUsePreapprovedAssets = contract.contract.isMethodUsePreapprovedAssets(methodIndex)
1691
1739
  const bytecodeTemplate = getBytecodeTemplate(
1692
1740
  methodIndex,
1693
1741
  methodUsePreapprovedAssets,