@alephium/web3 2.0.1 → 2.0.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.
@@ -43,7 +43,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
43
43
  exports.getContractCodeByCodeHash = 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.printDebugMessagesFromTx = exports.getDebugMessagesFromTx = 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
- const signer_1 = require("../signer");
47
46
  const ralph = __importStar(require("./ralph"));
48
47
  const utils_1 = require("../utils");
49
48
  const address_1 = require("../address");
@@ -54,7 +53,6 @@ const blake = __importStar(require("blakejs"));
54
53
  const debug_1 = require("../debug");
55
54
  const codec_1 = require("../codec");
56
55
  const error_1 = require("../error");
57
- const script_codec_1 = require("../codec/script-codec");
58
56
  const crypto = new utils_1.WebCrypto();
59
57
  exports.StdIdFieldName = '__stdInterfaceId';
60
58
  exports.DEFAULT_NODE_COMPILER_OPTIONS = {
@@ -525,7 +523,6 @@ class Script extends Artifact {
525
523
  async txParamsForExecution(params) {
526
524
  const selectedAccount = await params.signer.getSelectedAccount();
527
525
  const bytecode = this.buildByteCodeToDeploy(params.initialFields ?? {});
528
- const group = getGroupFromTxScript(bytecode, selectedAccount);
529
526
  const signerParams = {
530
527
  signerAddress: selectedAccount.address,
531
528
  signerKeyType: selectedAccount.keyType,
@@ -534,7 +531,6 @@ class Script extends Artifact {
534
531
  tokens: params.tokens,
535
532
  gasAmount: params.gasAmount,
536
533
  gasPrice: params.gasPrice,
537
- group,
538
534
  dustAmount: params.dustAmount
539
535
  };
540
536
  return signerParams;
@@ -549,33 +545,6 @@ class Script extends Artifact {
549
545
  }
550
546
  }
551
547
  exports.Script = Script;
552
- function getGroupFromTxScript(bytecode, account) {
553
- if ((0, signer_1.isGroupedAccount)(account))
554
- return account.group;
555
- const script = script_codec_1.scriptCodec.decode((0, utils_1.hexToBinUnsafe)(bytecode));
556
- const instrs = script.methods.flatMap((method) => method.instrs);
557
- for (let index = 0; index < instrs.length - 1; index += 1) {
558
- const instr = instrs[`${index}`];
559
- const nextInstr = instrs[index + 1];
560
- if (instr.name === 'BytesConst' &&
561
- instr.value.length === 32 &&
562
- (nextInstr.name === 'CallExternal' || nextInstr.name === 'CallExternalBySelector')) {
563
- const groupIndex = instr.value[instr.value.length - 1];
564
- if (groupIndex >= 0 && groupIndex < constants_1.TOTAL_NUMBER_OF_GROUPS) {
565
- return groupIndex;
566
- }
567
- }
568
- }
569
- for (const instr of instrs) {
570
- if (instr.name === 'BytesConst' && instr.value.length === 32) {
571
- const groupIndex = instr.value[instr.value.length - 1];
572
- if (groupIndex >= 0 && groupIndex < constants_1.TOTAL_NUMBER_OF_GROUPS) {
573
- return groupIndex;
574
- }
575
- }
576
- }
577
- return (0, address_1.groupOfAddress)(account.address);
578
- }
579
548
  function fromApiFields(immFields, mutFields, fieldsSig, structs) {
580
549
  let [immIndex, mutIndex] = [0, 0];
581
550
  const func = (type, isMutable) => {
@@ -12,8 +12,11 @@ export declare abstract class TransactionBuilder {
12
12
  static buildUnsignedTx(params: SignUnsignedTxParams): Omit<SignUnsignedTxResult, 'signature'>;
13
13
  private buildTransferTxParams;
14
14
  private buildDeployContractTxParams;
15
+ private static checkAndGetParams;
15
16
  private buildExecuteScriptTxParams;
16
17
  private convertTransferTxResult;
17
18
  private convertDeployContractTxResult;
18
19
  private convertExecuteScriptTxResult;
19
20
  }
21
+ export declare function getGroupFromTxScript(bytecode: string): number | undefined;
22
+ export declare function updateBytecodeWithGroup(bytecode: string, group: number): string;
@@ -17,14 +17,17 @@ 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.TransactionBuilder = void 0;
20
+ exports.updateBytecodeWithGroup = exports.getGroupFromTxScript = exports.TransactionBuilder = void 0;
21
21
  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 types_1 = require("./types");
25
26
  const codec_1 = require("../codec");
26
27
  const transaction_1 = require("../transaction");
27
28
  const hash_1 = require("../codec/hash");
29
+ const constants_1 = require("../constants");
30
+ const script_codec_1 = require("../codec/script-codec");
28
31
  class TransactionBuilder {
29
32
  static from(param0, param1, customFetch) {
30
33
  const nodeProvider = typeof param0 === 'string' ? new api_1.NodeProvider(param0, param1, customFetch) : param0;
@@ -147,12 +150,29 @@ class TransactionBuilder {
147
150
  ...rest
148
151
  };
149
152
  }
153
+ static checkAndGetParams(params) {
154
+ if ((0, types_1.isGroupedKeyType)(params.signerKeyType ?? 'default')) {
155
+ return params;
156
+ }
157
+ if (!(0, address_1.isGrouplessAddress)(params.signerAddress)) {
158
+ throw new Error('Invalid signer key type for groupless address');
159
+ }
160
+ const group = params.group ?? getGroupFromTxScript(params.bytecode);
161
+ const defaultGroup = (0, address_1.groupOfAddress)(params.signerAddress);
162
+ if (group === undefined || group === defaultGroup) {
163
+ return { ...params, group: defaultGroup };
164
+ }
165
+ const newBytecode = updateBytecodeWithGroup(params.bytecode, group);
166
+ const newParams = { ...params, bytecode: newBytecode };
167
+ return { ...newParams, group };
168
+ }
150
169
  buildExecuteScriptTxParams(params, publicKey) {
151
170
  TransactionBuilder.validatePublicKey(params, publicKey, params.signerKeyType);
152
- const { attoAlphAmount, tokens, gasPrice, dustAmount, ...rest } = params;
171
+ const newParams = TransactionBuilder.checkAndGetParams(params);
172
+ const { signerKeyType, attoAlphAmount, tokens, gasPrice, dustAmount, ...rest } = newParams;
153
173
  return {
154
174
  fromPublicKey: publicKey,
155
- fromPublicKeyType: params.signerKeyType,
175
+ fromPublicKeyType: signerKeyType,
156
176
  attoAlphAmount: (0, api_1.toApiNumber256Optional)(attoAlphAmount),
157
177
  tokens: (0, api_1.toApiTokens)(tokens),
158
178
  gasPrice: (0, api_1.toApiNumber256Optional)(gasPrice),
@@ -229,3 +249,45 @@ class TransactionBuilder {
229
249
  }
230
250
  }
231
251
  exports.TransactionBuilder = TransactionBuilder;
252
+ function getGroupFromTxScript(bytecode) {
253
+ const script = script_codec_1.scriptCodec.decode((0, utils_1.hexToBinUnsafe)(bytecode));
254
+ const instrs = script.methods.flatMap((method) => method.instrs);
255
+ for (let index = 0; index < instrs.length - 1; index += 1) {
256
+ const instr = instrs[`${index}`];
257
+ const nextInstr = instrs[index + 1];
258
+ if (instr.name === 'BytesConst' &&
259
+ instr.value.length === 32 &&
260
+ (nextInstr.name === 'CallExternal' || nextInstr.name === 'CallExternalBySelector')) {
261
+ const groupIndex = instr.value[instr.value.length - 1];
262
+ if (groupIndex >= 0 && groupIndex < constants_1.TOTAL_NUMBER_OF_GROUPS) {
263
+ return groupIndex;
264
+ }
265
+ }
266
+ }
267
+ for (const instr of instrs) {
268
+ if (instr.name === 'BytesConst' && instr.value.length === 32) {
269
+ const groupIndex = instr.value[instr.value.length - 1];
270
+ if (groupIndex >= 0 && groupIndex < constants_1.TOTAL_NUMBER_OF_GROUPS) {
271
+ return groupIndex;
272
+ }
273
+ }
274
+ }
275
+ return undefined;
276
+ }
277
+ exports.getGroupFromTxScript = getGroupFromTxScript;
278
+ function updateBytecodeWithGroup(bytecode, group) {
279
+ const script = script_codec_1.scriptCodec.decode((0, utils_1.hexToBinUnsafe)(bytecode));
280
+ const newMethods = script.methods.map((method) => {
281
+ const newInstrs = method.instrs.map((instr) => {
282
+ if (instr.name === 'AddressConst' && instr.value.kind === 'P2PK') {
283
+ const newLockupScript = { ...instr.value, value: { ...instr.value.value, group } };
284
+ return { ...instr, value: newLockupScript };
285
+ }
286
+ return instr;
287
+ });
288
+ return { ...method, instrs: newInstrs };
289
+ });
290
+ const bytes = script_codec_1.scriptCodec.encode({ methods: newMethods });
291
+ return (0, utils_1.binToHex)(bytes);
292
+ }
293
+ exports.updateBytecodeWithGroup = updateBytecodeWithGroup;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/web3",
3
- "version": "2.0.1",
3
+ "version": "2.0.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",
@@ -42,9 +42,7 @@ import {
42
42
  SignExecuteScriptTxParams,
43
43
  SignerProvider,
44
44
  Address,
45
- SignExecuteScriptTxResult,
46
- Account,
47
- isGroupedAccount
45
+ SignExecuteScriptTxResult
48
46
  } from '../signer'
49
47
  import * as ralph from './ralph'
50
48
  import {
@@ -61,13 +59,7 @@ import {
61
59
  isHexString,
62
60
  hexToString
63
61
  } from '../utils'
64
- import {
65
- contractIdFromAddress,
66
- groupOfAddress,
67
- addressFromContractId,
68
- subContractId,
69
- isGrouplessAddressWithoutGroupIndex
70
- } from '../address'
62
+ import { contractIdFromAddress, groupOfAddress, addressFromContractId, subContractId } from '../address'
71
63
  import { getCurrentNodeProvider } from '../global'
72
64
  import { EventSubscribeOptions, EventSubscription, subscribeToEvents } from './events'
73
65
  import { MINIMAL_CONTRACT_DEPOSIT, ONE_ALPH, TOTAL_NUMBER_OF_GROUPS } from '../constants'
@@ -100,7 +92,6 @@ import {
100
92
  } from '../codec'
101
93
  import { TraceableError } from '../error'
102
94
  import { SimulationResult } from '../api/api-alephium'
103
- import { scriptCodec } from '../codec/script-codec'
104
95
 
105
96
  const crypto = new WebCrypto()
106
97
 
@@ -799,7 +790,6 @@ export class Script extends Artifact {
799
790
  async txParamsForExecution<P extends Fields>(params: ExecuteScriptParams<P>): Promise<SignExecuteScriptTxParams> {
800
791
  const selectedAccount = await params.signer.getSelectedAccount()
801
792
  const bytecode = this.buildByteCodeToDeploy(params.initialFields ?? {})
802
- const group = getGroupFromTxScript(bytecode, selectedAccount)
803
793
  const signerParams: SignExecuteScriptTxParams = {
804
794
  signerAddress: selectedAccount.address,
805
795
  signerKeyType: selectedAccount.keyType,
@@ -808,7 +798,6 @@ export class Script extends Artifact {
808
798
  tokens: params.tokens,
809
799
  gasAmount: params.gasAmount,
810
800
  gasPrice: params.gasPrice,
811
- group,
812
801
  dustAmount: params.dustAmount
813
802
  }
814
803
  return signerParams
@@ -823,36 +812,6 @@ export class Script extends Artifact {
823
812
  }
824
813
  }
825
814
 
826
- function getGroupFromTxScript(bytecode: string, account: Account): number {
827
- if (isGroupedAccount(account)) return account.group
828
-
829
- const script = scriptCodec.decode(hexToBinUnsafe(bytecode))
830
- const instrs = script.methods.flatMap((method) => method.instrs)
831
- for (let index = 0; index < instrs.length - 1; index += 1) {
832
- const instr = instrs[`${index}`]
833
- const nextInstr = instrs[index + 1]
834
- if (
835
- instr.name === 'BytesConst' &&
836
- instr.value.length === 32 &&
837
- (nextInstr.name === 'CallExternal' || nextInstr.name === 'CallExternalBySelector')
838
- ) {
839
- const groupIndex = instr.value[instr.value.length - 1]
840
- if (groupIndex >= 0 && groupIndex < TOTAL_NUMBER_OF_GROUPS) {
841
- return groupIndex
842
- }
843
- }
844
- }
845
- for (const instr of instrs) {
846
- if (instr.name === 'BytesConst' && instr.value.length === 32) {
847
- const groupIndex = instr.value[instr.value.length - 1]
848
- if (groupIndex >= 0 && groupIndex < TOTAL_NUMBER_OF_GROUPS) {
849
- return groupIndex
850
- }
851
- }
852
- }
853
- return groupOfAddress(account.address)
854
- }
855
-
856
815
  export function fromApiFields(
857
816
  immFields: node.Val[],
858
817
  mutFields: node.Val[],
@@ -39,13 +39,13 @@ import {
39
39
  instrCodec,
40
40
  u256Codec,
41
41
  toU256,
42
- toI256,
43
- intAs4BytesCodec
42
+ toI256
44
43
  } from '../codec'
45
44
  import { boolCodec } from '../codec/codec'
46
45
  import { TraceableError } from '../error'
47
- import djb2 from '../utils/djb2'
48
- import { addressToBytes, groupFromHint } from '../address'
46
+ import { addressToBytes, isGrouplessAddressWithoutGroupIndex, isValidAddress } from '../address'
47
+ import { scriptCodec } from '../codec/script-codec'
48
+ import { TOTAL_NUMBER_OF_GROUPS } from '../constants'
49
49
 
50
50
  export function encodeByteVec(hex: string): Uint8Array {
51
51
  if (!isHexString(hex)) {
@@ -18,7 +18,7 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
18
18
 
19
19
  import { binToHex, hexToBinUnsafe } from '../utils'
20
20
  import { fromApiNumber256, node, NodeProvider, toApiNumber256Optional, toApiTokens } from '../api'
21
- import { addressFromPublicKey, contractIdFromAddress } from '../address'
21
+ import { addressFromPublicKey, contractIdFromAddress, groupOfAddress, isGrouplessAddress } from '../address'
22
22
  import { toApiDestinations } from './signer'
23
23
  import {
24
24
  SignChainedTxParams,
@@ -36,7 +36,7 @@ import {
36
36
  SignUnsignedTxParams,
37
37
  SignUnsignedTxResult,
38
38
  BuildTxResult,
39
- GrouplessBuildTxResult
39
+ isGroupedKeyType
40
40
  } from './types'
41
41
  import { unsignedTxCodec } from '../codec'
42
42
  import { groupIndexOfTransaction } from '../transaction'
@@ -47,6 +47,9 @@ import {
47
47
  BuildExecuteScriptTxResult,
48
48
  BuildTransferTxResult
49
49
  } from '../api/api-alephium'
50
+ import { TOTAL_NUMBER_OF_GROUPS } from '../constants'
51
+ import { scriptCodec } from '../codec/script-codec'
52
+ import { LockupScript } from '../codec/lockup-script-codec'
50
53
 
51
54
  export abstract class TransactionBuilder {
52
55
  abstract get nodeProvider(): NodeProvider
@@ -204,13 +207,34 @@ export abstract class TransactionBuilder {
204
207
  }
205
208
  }
206
209
 
210
+ private static checkAndGetParams(params: SignExecuteScriptTxParams): SignExecuteScriptTxParams {
211
+ if (isGroupedKeyType(params.signerKeyType ?? 'default')) {
212
+ return params
213
+ }
214
+
215
+ if (!isGrouplessAddress(params.signerAddress)) {
216
+ throw new Error('Invalid signer key type for groupless address')
217
+ }
218
+
219
+ const group = params.group ?? getGroupFromTxScript(params.bytecode)
220
+ const defaultGroup = groupOfAddress(params.signerAddress)
221
+ if (group === undefined || group === defaultGroup) {
222
+ return { ...params, group: defaultGroup }
223
+ }
224
+
225
+ const newBytecode = updateBytecodeWithGroup(params.bytecode, group)
226
+ const newParams = { ...params, bytecode: newBytecode }
227
+ return { ...newParams, group }
228
+ }
229
+
207
230
  private buildExecuteScriptTxParams(params: SignExecuteScriptTxParams, publicKey: string): node.BuildExecuteScriptTx {
208
231
  TransactionBuilder.validatePublicKey(params, publicKey, params.signerKeyType)
209
232
 
210
- const { attoAlphAmount, tokens, gasPrice, dustAmount, ...rest } = params
233
+ const newParams = TransactionBuilder.checkAndGetParams(params)
234
+ const { signerKeyType, attoAlphAmount, tokens, gasPrice, dustAmount, ...rest } = newParams
211
235
  return {
212
236
  fromPublicKey: publicKey,
213
- fromPublicKeyType: params.signerKeyType,
237
+ fromPublicKeyType: signerKeyType,
214
238
  attoAlphAmount: toApiNumber256Optional(attoAlphAmount),
215
239
  tokens: toApiTokens(tokens),
216
240
  gasPrice: toApiNumber256Optional(gasPrice),
@@ -296,3 +320,47 @@ export abstract class TransactionBuilder {
296
320
  }
297
321
  }
298
322
  }
323
+
324
+ export function getGroupFromTxScript(bytecode: string): number | undefined {
325
+ const script = scriptCodec.decode(hexToBinUnsafe(bytecode))
326
+ const instrs = script.methods.flatMap((method) => method.instrs)
327
+ for (let index = 0; index < instrs.length - 1; index += 1) {
328
+ const instr = instrs[`${index}`]
329
+ const nextInstr = instrs[index + 1]
330
+ if (
331
+ instr.name === 'BytesConst' &&
332
+ instr.value.length === 32 &&
333
+ (nextInstr.name === 'CallExternal' || nextInstr.name === 'CallExternalBySelector')
334
+ ) {
335
+ const groupIndex = instr.value[instr.value.length - 1]
336
+ if (groupIndex >= 0 && groupIndex < TOTAL_NUMBER_OF_GROUPS) {
337
+ return groupIndex
338
+ }
339
+ }
340
+ }
341
+ for (const instr of instrs) {
342
+ if (instr.name === 'BytesConst' && instr.value.length === 32) {
343
+ const groupIndex = instr.value[instr.value.length - 1]
344
+ if (groupIndex >= 0 && groupIndex < TOTAL_NUMBER_OF_GROUPS) {
345
+ return groupIndex
346
+ }
347
+ }
348
+ }
349
+ return undefined
350
+ }
351
+
352
+ export function updateBytecodeWithGroup(bytecode: string, group: number): string {
353
+ const script = scriptCodec.decode(hexToBinUnsafe(bytecode))
354
+ const newMethods = script.methods.map((method) => {
355
+ const newInstrs = method.instrs.map((instr) => {
356
+ if (instr.name === 'AddressConst' && instr.value.kind === 'P2PK') {
357
+ const newLockupScript: LockupScript = { ...instr.value, value: { ...instr.value.value, group } }
358
+ return { ...instr, value: newLockupScript }
359
+ }
360
+ return instr
361
+ })
362
+ return { ...method, instrs: newInstrs }
363
+ })
364
+ const bytes = scriptCodec.encode({ methods: newMethods })
365
+ return binToHex(bytes)
366
+ }