@alephium/web3 2.0.0-rc.2 → 2.0.0-rc.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.
@@ -250,6 +250,8 @@ export interface BuildExecuteScriptTx {
250
250
  group?: number;
251
251
  /** @format double */
252
252
  gasEstimationMultiplier?: number;
253
+ /** @format uint256 */
254
+ dustAmount?: string;
253
255
  }
254
256
  /** BuildExecuteScriptTxResult */
255
257
  export type BuildExecuteScriptTxResult = BuildGrouplessExecuteScriptTxResult | BuildSimpleExecuteScriptTxResult;
@@ -958,6 +960,8 @@ export interface RichAssetInput {
958
960
  /** @format address */
959
961
  address: string;
960
962
  tokens: Token[];
963
+ /** @format 32-byte-hash */
964
+ outputRefTxId: string;
961
965
  }
962
966
  /** RichBlockAndEvents */
963
967
  export interface RichBlockAndEvents {
@@ -1004,6 +1008,8 @@ export interface RichContractInput {
1004
1008
  /** @format address */
1005
1009
  address: string;
1006
1010
  tokens: Token[];
1011
+ /** @format 32-byte-hash */
1012
+ outputRefTxId: string;
1007
1013
  }
1008
1014
  /** RichTransaction */
1009
1015
  export interface RichTransaction {
@@ -1421,7 +1427,7 @@ export declare class HttpClient<SecurityDataType = unknown> {
1421
1427
  }
1422
1428
  /**
1423
1429
  * @title Alephium API
1424
- * @version 3.15.2
1430
+ * @version 4.0.0
1425
1431
  * @baseUrl ../
1426
1432
  */
1427
1433
  export declare class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
@@ -151,7 +151,7 @@ class HttpClient {
151
151
  exports.HttpClient = HttpClient;
152
152
  /**
153
153
  * @title Alephium API
154
- * @version 3.15.2
154
+ * @version 4.0.0
155
155
  * @baseUrl ../
156
156
  */
157
157
  class Api extends HttpClient {
@@ -22,6 +22,7 @@ export declare function toApiAddress(v0: Val): string;
22
22
  export declare function toApiArray(tpe: string, v: Val): node.Val;
23
23
  export declare function toApiVal(v: Val, tpe: string): node.Val;
24
24
  export declare function fromApiPrimitiveVal(value: node.Val, tpe: string, systemEvent?: boolean): Val;
25
+ export declare function decodeTupleType(tpe: string): string[];
25
26
  export declare function decodeArrayType(tpe: string): [string, number];
26
27
  export declare function getDefaultPrimitiveValue(tpe: string): Val;
27
28
  export interface ApiRequestArguments {
@@ -17,7 +17,7 @@ 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.StdInterfaceIds = exports.request = exports.requestWithLog = exports.forwardRequests = exports.getDefaultPrimitiveValue = exports.decodeArrayType = exports.fromApiPrimitiveVal = exports.toApiVal = exports.toApiArray = exports.toApiAddress = exports.toApiByteVec = exports.fromApiNumber256 = exports.toApiNumber256Optional = exports.toApiNumber256 = exports.toApiBoolean = exports.fromApiTokens = exports.fromApiToken = exports.toApiTokens = exports.toApiToken = exports.PrimitiveTypes = void 0;
20
+ exports.StdInterfaceIds = exports.request = exports.requestWithLog = exports.forwardRequests = exports.getDefaultPrimitiveValue = exports.decodeArrayType = exports.decodeTupleType = exports.fromApiPrimitiveVal = exports.toApiVal = exports.toApiArray = exports.toApiAddress = exports.toApiByteVec = exports.fromApiNumber256 = exports.toApiNumber256Optional = exports.toApiNumber256 = exports.toApiBoolean = exports.fromApiTokens = exports.fromApiToken = exports.toApiTokens = exports.toApiToken = exports.PrimitiveTypes = void 0;
21
21
  const address_1 = require("../address");
22
22
  const constants_1 = require("../constants");
23
23
  const debug_1 = require("../debug");
@@ -159,6 +159,29 @@ function fromApiPrimitiveVal(value, tpe, systemEvent = false) {
159
159
  }
160
160
  }
161
161
  exports.fromApiPrimitiveVal = fromApiPrimitiveVal;
162
+ function decodeTupleType(tpe) {
163
+ const str = tpe.slice(1, -1);
164
+ const types = [];
165
+ let current = '';
166
+ let depth = 0;
167
+ for (const char of str) {
168
+ if (char === ',' && depth === 0) {
169
+ types.push(current);
170
+ current = '';
171
+ }
172
+ else {
173
+ if (char === '(')
174
+ depth++;
175
+ if (char === ')')
176
+ depth--;
177
+ current += char;
178
+ }
179
+ }
180
+ if (current !== '')
181
+ types.push(current);
182
+ return types;
183
+ }
184
+ exports.decodeTupleType = decodeTupleType;
162
185
  function decodeArrayType(tpe) {
163
186
  const semiColonIndex = tpe.lastIndexOf(';');
164
187
  if (semiColonIndex === -1) {
@@ -216,6 +216,7 @@ export interface ExecuteScriptParams<P extends Fields = Fields> {
216
216
  tokens?: Token[];
217
217
  gasAmount?: number;
218
218
  gasPrice?: Number256;
219
+ dustAmount?: Number256;
219
220
  }
220
221
  export interface ExecuteScriptResult {
221
222
  groupIndex: number;
@@ -259,6 +260,7 @@ export interface SignExecuteContractMethodParams<T extends Arguments = Arguments
259
260
  tokens?: Token[];
260
261
  gasAmount?: number;
261
262
  gasPrice?: Number256;
263
+ dustAmount?: Number256;
262
264
  }
263
265
  export declare const CreateContractEventAddresses: string[];
264
266
  export declare const DestroyContractEventAddresses: string[];
@@ -43,6 +43,7 @@ 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");
46
47
  const ralph = __importStar(require("./ralph"));
47
48
  const utils_1 = require("../utils");
48
49
  const address_1 = require("../address");
@@ -53,6 +54,7 @@ const blake = __importStar(require("blakejs"));
53
54
  const debug_1 = require("../debug");
54
55
  const codec_1 = require("../codec");
55
56
  const error_1 = require("../error");
57
+ const script_codec_1 = require("../codec/script-codec");
56
58
  const crypto = new utils_1.WebCrypto();
57
59
  exports.StdIdFieldName = '__stdInterfaceId';
58
60
  exports.DEFAULT_NODE_COMPILER_OPTIONS = {
@@ -522,14 +524,18 @@ class Script extends Artifact {
522
524
  }
523
525
  async txParamsForExecution(params) {
524
526
  const selectedAccount = await params.signer.getSelectedAccount();
527
+ const bytecode = this.buildByteCodeToDeploy(params.initialFields ?? {});
528
+ const group = getGroupFromTxScript(bytecode, selectedAccount);
525
529
  const signerParams = {
526
530
  signerAddress: selectedAccount.address,
527
531
  signerKeyType: selectedAccount.keyType,
528
- bytecode: this.buildByteCodeToDeploy(params.initialFields ?? {}),
532
+ bytecode,
529
533
  attoAlphAmount: params.attoAlphAmount,
530
534
  tokens: params.tokens,
531
535
  gasAmount: params.gasAmount,
532
- gasPrice: params.gasPrice
536
+ gasPrice: params.gasPrice,
537
+ group,
538
+ dustAmount: params.dustAmount
533
539
  };
534
540
  return signerParams;
535
541
  }
@@ -543,6 +549,33 @@ class Script extends Artifact {
543
549
  }
544
550
  }
545
551
  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
+ }
546
579
  function fromApiFields(immFields, mutFields, fieldsSig, structs) {
547
580
  let [immIndex, mutIndex] = [0, 0];
548
581
  const func = (type, isMutable) => {
@@ -562,6 +595,13 @@ function buildVal(isMutable, type, structs, func) {
562
595
  const [baseType, size] = (0, api_1.decodeArrayType)(type);
563
596
  return Array.from(Array(size).keys()).map(() => buildVal(isMutable, baseType, structs, func));
564
597
  }
598
+ if (type.startsWith('(')) {
599
+ const tuple = (0, api_1.decodeTupleType)(type);
600
+ return tuple.reduce((acc, fieldType) => {
601
+ acc.push(buildVal(isMutable, fieldType, structs, func));
602
+ return acc;
603
+ }, []);
604
+ }
565
605
  const struct = structs.find((s) => s.name === type);
566
606
  if (struct !== undefined) {
567
607
  return struct.fieldNames.reduce((acc, name, index) => {
@@ -1265,7 +1305,9 @@ async function signExecuteMethod(contract, instance, methodName, params) {
1265
1305
  attoAlphAmount: params.attoAlphAmount,
1266
1306
  tokens: params.tokens,
1267
1307
  gasAmount: params.gasAmount,
1268
- gasPrice: params.gasPrice
1308
+ gasPrice: params.gasPrice,
1309
+ group: instance.groupIndex,
1310
+ dustAmount: params.dustAmount
1269
1311
  };
1270
1312
  const result = (await signer.signAndSubmitExecuteScriptTx(signerParams));
1271
1313
  if ((0, debug_1.isContractDebugMessageEnabled)() && isDevnet) {
@@ -178,6 +178,16 @@ function calcFieldSize(type, isMutable, structs) {
178
178
  const base = calcFieldSize(baseType, isMutable, structs);
179
179
  return { immFields: base.immFields * size, mutFields: base.mutFields * size };
180
180
  }
181
+ if (type.startsWith('(')) {
182
+ const tuple = (0, api_1.decodeTupleType)(type);
183
+ return tuple.reduce((acc, fieldType) => {
184
+ const subFieldSize = calcFieldSize(fieldType, isMutable, structs);
185
+ return {
186
+ immFields: acc.immFields + subFieldSize.immFields,
187
+ mutFields: acc.mutFields + subFieldSize.mutFields
188
+ };
189
+ }, { immFields: 0, mutFields: 0 });
190
+ }
181
191
  return isMutable ? { immFields: 0, mutFields: 1 } : { immFields: 1, mutFields: 0 };
182
192
  }
183
193
  exports.calcFieldSize = calcFieldSize;
@@ -251,6 +261,10 @@ function typeLength(typ, structs) {
251
261
  const [baseType, size] = (0, api_1.decodeArrayType)(typ);
252
262
  return size * typeLength(baseType, structs);
253
263
  }
264
+ if (typ.startsWith('(')) {
265
+ const tuple = (0, api_1.decodeTupleType)(typ);
266
+ return tuple.reduce((acc, fieldType) => acc + typeLength(fieldType, structs), 0);
267
+ }
254
268
  const struct = structs.find((s) => s.name === typ);
255
269
  if (struct !== undefined) {
256
270
  return struct.fieldTypes.reduce((acc, fieldType) => acc + typeLength(fieldType, structs), 0);
@@ -277,6 +291,15 @@ function flattenField(isMutable, name, type, value, structs) {
277
291
  return flattenField(isMutable, `${name}[${index}]`, baseType, item, structs);
278
292
  });
279
293
  }
294
+ if (Array.isArray(value) && type.startsWith('(')) {
295
+ const tuple = (0, api_1.decodeTupleType)(type);
296
+ if (value.length !== tuple.length) {
297
+ throw Error(`Invalid tuple length, expected ${tuple.length}, got ${value.length}`);
298
+ }
299
+ return tuple.flatMap((fieldType, index) => {
300
+ return flattenField(isMutable, `${name}._${index}`, fieldType, value[`${index}`], structs);
301
+ });
302
+ }
280
303
  const struct = structs.find((s) => s.name === type);
281
304
  if (struct !== undefined) {
282
305
  if (typeof value !== 'object') {
@@ -149,13 +149,14 @@ class TransactionBuilder {
149
149
  }
150
150
  buildExecuteScriptTxParams(params, publicKey) {
151
151
  TransactionBuilder.validatePublicKey(params, publicKey, params.signerKeyType);
152
- const { attoAlphAmount, tokens, gasPrice, ...rest } = params;
152
+ const { attoAlphAmount, tokens, gasPrice, dustAmount, ...rest } = params;
153
153
  return {
154
154
  fromPublicKey: publicKey,
155
155
  fromPublicKeyType: params.signerKeyType,
156
156
  attoAlphAmount: (0, api_1.toApiNumber256Optional)(attoAlphAmount),
157
157
  tokens: (0, api_1.toApiTokens)(tokens),
158
158
  gasPrice: (0, api_1.toApiNumber256Optional)(gasPrice),
159
+ dustAmount: (0, api_1.toApiNumber256Optional)(dustAmount),
159
160
  ...rest
160
161
  };
161
162
  }
@@ -11,8 +11,11 @@ export interface Destination {
11
11
  lockTime?: number;
12
12
  message?: string;
13
13
  }
14
- export type GroupedKeyType = 'default' | 'bip340-schnorr';
15
- export type GrouplessKeyType = 'gl-secp256k1' | 'gl-secp256r1' | 'gl-ed25519' | 'gl-webauthn';
14
+ export declare const groupedKeyTypes: readonly ["default", "bip340-schnorr"];
15
+ export declare const grouplessKeyTypes: readonly ["gl-secp256k1", "gl-secp256r1", "gl-ed25519", "gl-webauthn"];
16
+ export declare const keyTypes: readonly ["default", "bip340-schnorr", "gl-secp256k1", "gl-secp256r1", "gl-ed25519", "gl-webauthn"];
17
+ export type GroupedKeyType = (typeof groupedKeyTypes)[number];
18
+ export type GrouplessKeyType = (typeof grouplessKeyTypes)[number];
16
19
  export type KeyType = GroupedKeyType | GrouplessKeyType;
17
20
  export interface GroupedAccount {
18
21
  keyType: GroupedKeyType;
@@ -26,6 +29,8 @@ export interface GrouplessAccount {
26
29
  publicKey: string;
27
30
  }
28
31
  export type Account = GroupedAccount | GrouplessAccount;
32
+ export declare function isGroupedKeyType(keyType: KeyType): keyType is GroupedKeyType;
33
+ export declare function isGrouplessKeyType(keyType: KeyType): keyType is GrouplessKeyType;
29
34
  export declare function isGroupedAccount(account: Account): account is GroupedAccount;
30
35
  export declare function isGrouplessAccount(account: Account): account is GrouplessAccount;
31
36
  export type SignerAddress = {
@@ -82,6 +87,7 @@ export interface SignExecuteScriptTxParams {
82
87
  gasPrice?: Number256;
83
88
  gasEstimationMultiplier?: number;
84
89
  group?: number;
90
+ dustAmount?: Number256;
85
91
  }
86
92
  export interface SignExecuteScriptTxResult {
87
93
  groupIndex: number;
@@ -17,15 +17,26 @@ 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.isGrouplessAccount = exports.isGroupedAccount = void 0;
20
+ exports.isGrouplessAccount = exports.isGroupedAccount = exports.isGrouplessKeyType = exports.isGroupedKeyType = exports.keyTypes = exports.grouplessKeyTypes = exports.groupedKeyTypes = void 0;
21
21
  const utils_1 = require("../utils");
22
22
  utils_1.assertType;
23
+ exports.groupedKeyTypes = ['default', 'bip340-schnorr'];
24
+ exports.grouplessKeyTypes = ['gl-secp256k1', 'gl-secp256r1', 'gl-ed25519', 'gl-webauthn'];
25
+ exports.keyTypes = [...exports.groupedKeyTypes, ...exports.grouplessKeyTypes];
26
+ function isGroupedKeyType(keyType) {
27
+ return keyType === 'default' || keyType === 'bip340-schnorr';
28
+ }
29
+ exports.isGroupedKeyType = isGroupedKeyType;
30
+ function isGrouplessKeyType(keyType) {
31
+ return keyType !== 'default' && keyType !== 'bip340-schnorr';
32
+ }
33
+ exports.isGrouplessKeyType = isGrouplessKeyType;
23
34
  function isGroupedAccount(account) {
24
- return account.keyType === 'default' || account.keyType === 'bip340-schnorr';
35
+ return isGroupedKeyType(account.keyType);
25
36
  }
26
37
  exports.isGroupedAccount = isGroupedAccount;
27
38
  function isGrouplessAccount(account) {
28
- return account.keyType !== 'default' && account.keyType !== 'bip340-schnorr';
39
+ return isGrouplessKeyType(account.keyType);
29
40
  }
30
41
  exports.isGrouplessAccount = isGrouplessAccount;
31
42
  (0, utils_1.assertType)();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/web3",
3
- "version": "2.0.0-rc.2",
3
+ "version": "2.0.0-rc.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",
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "author": "Alephium dev <dev@alephium.org>",
35
35
  "config": {
36
- "alephium_version": "3.15.2",
36
+ "alephium_version": "4.0.0",
37
37
  "explorer_backend_version": "2.3.2"
38
38
  },
39
39
  "type": "commonjs",
@@ -292,6 +292,8 @@ export interface BuildExecuteScriptTx {
292
292
  group?: number
293
293
  /** @format double */
294
294
  gasEstimationMultiplier?: number
295
+ /** @format uint256 */
296
+ dustAmount?: string
295
297
  }
296
298
 
297
299
  /** BuildExecuteScriptTxResult */
@@ -1085,6 +1087,8 @@ export interface RichAssetInput {
1085
1087
  /** @format address */
1086
1088
  address: string
1087
1089
  tokens: Token[]
1090
+ /** @format 32-byte-hash */
1091
+ outputRefTxId: string
1088
1092
  }
1089
1093
 
1090
1094
  /** RichBlockAndEvents */
@@ -1135,6 +1139,8 @@ export interface RichContractInput {
1135
1139
  /** @format address */
1136
1140
  address: string
1137
1141
  tokens: Token[]
1142
+ /** @format 32-byte-hash */
1143
+ outputRefTxId: string
1138
1144
  }
1139
1145
 
1140
1146
  /** RichTransaction */
@@ -1754,7 +1760,7 @@ export class HttpClient<SecurityDataType = unknown> {
1754
1760
 
1755
1761
  /**
1756
1762
  * @title Alephium API
1757
- * @version 3.15.2
1763
+ * @version 4.0.0
1758
1764
  * @baseUrl ../
1759
1765
  */
1760
1766
  export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
package/src/api/types.ts CHANGED
@@ -160,6 +160,26 @@ export function fromApiPrimitiveVal(value: node.Val, tpe: string, systemEvent =
160
160
  }
161
161
  }
162
162
 
163
+ export function decodeTupleType(tpe: string): string[] {
164
+ const str = tpe.slice(1, -1)
165
+ const types: string[] = []
166
+ let current = ''
167
+ let depth = 0
168
+
169
+ for (const char of str) {
170
+ if (char === ',' && depth === 0) {
171
+ types.push(current)
172
+ current = ''
173
+ } else {
174
+ if (char === '(') depth++
175
+ if (char === ')') depth--
176
+ current += char
177
+ }
178
+ }
179
+ if (current !== '') types.push(current)
180
+ return types
181
+ }
182
+
163
183
  export function decodeArrayType(tpe: string): [string, number] {
164
184
  const semiColonIndex = tpe.lastIndexOf(';')
165
185
  if (semiColonIndex === -1) {
@@ -33,7 +33,8 @@ import {
33
33
  PrimitiveTypes,
34
34
  decodeArrayType,
35
35
  fromApiPrimitiveVal,
36
- tryGetCallResult
36
+ tryGetCallResult,
37
+ decodeTupleType
37
38
  } from '../api'
38
39
  import {
39
40
  SignDeployContractTxParams,
@@ -41,7 +42,9 @@ import {
41
42
  SignExecuteScriptTxParams,
42
43
  SignerProvider,
43
44
  Address,
44
- SignExecuteScriptTxResult
45
+ SignExecuteScriptTxResult,
46
+ Account,
47
+ isGroupedAccount
45
48
  } from '../signer'
46
49
  import * as ralph from './ralph'
47
50
  import {
@@ -97,6 +100,7 @@ import {
97
100
  } from '../codec'
98
101
  import { TraceableError } from '../error'
99
102
  import { SimulationResult } from '../api/api-alephium'
103
+ import { scriptCodec } from '../codec/script-codec'
100
104
 
101
105
  const crypto = new WebCrypto()
102
106
 
@@ -794,14 +798,18 @@ export class Script extends Artifact {
794
798
 
795
799
  async txParamsForExecution<P extends Fields>(params: ExecuteScriptParams<P>): Promise<SignExecuteScriptTxParams> {
796
800
  const selectedAccount = await params.signer.getSelectedAccount()
801
+ const bytecode = this.buildByteCodeToDeploy(params.initialFields ?? {})
802
+ const group = getGroupFromTxScript(bytecode, selectedAccount)
797
803
  const signerParams: SignExecuteScriptTxParams = {
798
804
  signerAddress: selectedAccount.address,
799
805
  signerKeyType: selectedAccount.keyType,
800
- bytecode: this.buildByteCodeToDeploy(params.initialFields ?? {}),
806
+ bytecode,
801
807
  attoAlphAmount: params.attoAlphAmount,
802
808
  tokens: params.tokens,
803
809
  gasAmount: params.gasAmount,
804
- gasPrice: params.gasPrice
810
+ gasPrice: params.gasPrice,
811
+ group,
812
+ dustAmount: params.dustAmount
805
813
  }
806
814
  return signerParams
807
815
  }
@@ -815,6 +823,36 @@ export class Script extends Artifact {
815
823
  }
816
824
  }
817
825
 
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
+
818
856
  export function fromApiFields(
819
857
  immFields: node.Val[],
820
858
  mutFields: node.Val[],
@@ -845,6 +883,13 @@ function buildVal(
845
883
  const [baseType, size] = decodeArrayType(type)
846
884
  return Array.from(Array(size).keys()).map(() => buildVal(isMutable, baseType, structs, func))
847
885
  }
886
+ if (type.startsWith('(')) {
887
+ const tuple = decodeTupleType(type)
888
+ return tuple.reduce<Val[]>((acc, fieldType) => {
889
+ acc.push(buildVal(isMutable, fieldType, structs, func))
890
+ return acc
891
+ }, [])
892
+ }
848
893
  const struct = structs.find((s) => s.name === type)
849
894
  if (struct !== undefined) {
850
895
  return struct.fieldNames.reduce((acc, name, index) => {
@@ -1190,6 +1235,7 @@ export interface ExecuteScriptParams<P extends Fields = Fields> {
1190
1235
  tokens?: Token[]
1191
1236
  gasAmount?: number
1192
1237
  gasPrice?: Number256
1238
+ dustAmount?: Number256
1193
1239
  }
1194
1240
 
1195
1241
  export interface ExecuteScriptResult {
@@ -1239,6 +1285,7 @@ export interface SignExecuteContractMethodParams<T extends Arguments = Arguments
1239
1285
  tokens?: Token[]
1240
1286
  gasAmount?: number
1241
1287
  gasPrice?: Number256
1288
+ dustAmount?: Number256
1242
1289
  }
1243
1290
 
1244
1291
  function specialContractAddress(eventIndex: number, groupIndex: number): string {
@@ -1963,7 +2010,9 @@ export async function signExecuteMethod<I extends ContractInstance, F extends Fi
1963
2010
  attoAlphAmount: params.attoAlphAmount,
1964
2011
  tokens: params.tokens,
1965
2012
  gasAmount: params.gasAmount,
1966
- gasPrice: params.gasPrice
2013
+ gasPrice: params.gasPrice,
2014
+ group: instance.groupIndex,
2015
+ dustAmount: params.dustAmount
1967
2016
  }
1968
2017
 
1969
2018
  const result = (await signer.signAndSubmitExecuteScriptTx(signerParams)) as SignExecuteScriptTxResult
@@ -16,7 +16,16 @@ You should have received a copy of the GNU Lesser General Public License
16
16
  along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
 
19
- import { Val, decodeArrayType, toApiAddress, toApiBoolean, toApiByteVec, toApiNumber256, PrimitiveTypes } from '../api'
19
+ import {
20
+ Val,
21
+ decodeArrayType,
22
+ toApiAddress,
23
+ toApiBoolean,
24
+ toApiByteVec,
25
+ toApiNumber256,
26
+ PrimitiveTypes,
27
+ decodeTupleType
28
+ } from '../api'
20
29
  import { HexString, binToHex, bs58, hexToBinUnsafe, isHexString } from '../utils'
21
30
  import { Fields, FieldsSig, Struct } from './contract'
22
31
  import {
@@ -208,6 +217,19 @@ export function calcFieldSize(
208
217
  const base = calcFieldSize(baseType, isMutable, structs)
209
218
  return { immFields: base.immFields * size, mutFields: base.mutFields * size }
210
219
  }
220
+ if (type.startsWith('(')) {
221
+ const tuple = decodeTupleType(type)
222
+ return tuple.reduce(
223
+ (acc, fieldType) => {
224
+ const subFieldSize = calcFieldSize(fieldType, isMutable, structs)
225
+ return {
226
+ immFields: acc.immFields + subFieldSize.immFields,
227
+ mutFields: acc.mutFields + subFieldSize.mutFields
228
+ }
229
+ },
230
+ { immFields: 0, mutFields: 0 }
231
+ )
232
+ }
211
233
  return isMutable ? { immFields: 0, mutFields: 1 } : { immFields: 1, mutFields: 0 }
212
234
  }
213
235
 
@@ -284,6 +306,11 @@ export function typeLength(typ: string, structs: Struct[]): number {
284
306
  return size * typeLength(baseType, structs)
285
307
  }
286
308
 
309
+ if (typ.startsWith('(')) {
310
+ const tuple = decodeTupleType(typ)
311
+ return tuple.reduce((acc, fieldType) => acc + typeLength(fieldType, structs), 0)
312
+ }
313
+
287
314
  const struct = structs.find((s) => s.name === typ)
288
315
  if (struct !== undefined) {
289
316
  return struct.fieldTypes.reduce((acc, fieldType) => acc + typeLength(fieldType, structs), 0)
@@ -323,6 +350,15 @@ function flattenField(
323
350
  return flattenField(isMutable, `${name}[${index}]`, baseType, item, structs)
324
351
  })
325
352
  }
353
+ if (Array.isArray(value) && type.startsWith('(')) {
354
+ const tuple = decodeTupleType(type)
355
+ if (value.length !== tuple.length) {
356
+ throw Error(`Invalid tuple length, expected ${tuple.length}, got ${value.length}`)
357
+ }
358
+ return tuple.flatMap((fieldType, index) => {
359
+ return flattenField(isMutable, `${name}._${index}`, fieldType, value[`${index}`], structs)
360
+ })
361
+ }
326
362
  const struct = structs.find((s) => s.name === type)
327
363
  if (struct !== undefined) {
328
364
  if (typeof value !== 'object') {
@@ -207,13 +207,14 @@ export abstract class TransactionBuilder {
207
207
  private buildExecuteScriptTxParams(params: SignExecuteScriptTxParams, publicKey: string): node.BuildExecuteScriptTx {
208
208
  TransactionBuilder.validatePublicKey(params, publicKey, params.signerKeyType)
209
209
 
210
- const { attoAlphAmount, tokens, gasPrice, ...rest } = params
210
+ const { attoAlphAmount, tokens, gasPrice, dustAmount, ...rest } = params
211
211
  return {
212
212
  fromPublicKey: publicKey,
213
213
  fromPublicKeyType: params.signerKeyType,
214
214
  attoAlphAmount: toApiNumber256Optional(attoAlphAmount),
215
215
  tokens: toApiTokens(tokens),
216
216
  gasPrice: toApiNumber256Optional(gasPrice),
217
+ dustAmount: toApiNumber256Optional(dustAmount),
217
218
  ...rest
218
219
  }
219
220
  }
@@ -34,8 +34,12 @@ export interface Destination {
34
34
  }
35
35
  assertType<Eq<keyof Destination, keyof node.Destination>>
36
36
 
37
- export type GroupedKeyType = 'default' | 'bip340-schnorr'
38
- export type GrouplessKeyType = 'gl-secp256k1' | 'gl-secp256r1' | 'gl-ed25519' | 'gl-webauthn'
37
+ export const groupedKeyTypes = ['default', 'bip340-schnorr'] as const
38
+ export const grouplessKeyTypes = ['gl-secp256k1', 'gl-secp256r1', 'gl-ed25519', 'gl-webauthn'] as const
39
+ export const keyTypes = [...groupedKeyTypes, ...grouplessKeyTypes] as const
40
+
41
+ export type GroupedKeyType = (typeof groupedKeyTypes)[number]
42
+ export type GrouplessKeyType = (typeof grouplessKeyTypes)[number]
39
43
 
40
44
  export type KeyType = GroupedKeyType | GrouplessKeyType
41
45
 
@@ -54,12 +58,20 @@ export interface GrouplessAccount {
54
58
 
55
59
  export type Account = GroupedAccount | GrouplessAccount
56
60
 
61
+ export function isGroupedKeyType(keyType: KeyType): keyType is GroupedKeyType {
62
+ return keyType === 'default' || keyType === 'bip340-schnorr'
63
+ }
64
+
65
+ export function isGrouplessKeyType(keyType: KeyType): keyType is GrouplessKeyType {
66
+ return keyType !== 'default' && keyType !== 'bip340-schnorr'
67
+ }
68
+
57
69
  export function isGroupedAccount(account: Account): account is GroupedAccount {
58
- return account.keyType === 'default' || account.keyType === 'bip340-schnorr'
70
+ return isGroupedKeyType(account.keyType)
59
71
  }
60
72
 
61
73
  export function isGrouplessAccount(account: Account): account is GrouplessAccount {
62
- return account.keyType !== 'default' && account.keyType !== 'bip340-schnorr'
74
+ return isGrouplessKeyType(account.keyType)
63
75
  }
64
76
 
65
77
  export type SignerAddress = { signerAddress: string; signerKeyType?: KeyType }
@@ -127,6 +139,7 @@ export interface SignExecuteScriptTxParams {
127
139
  gasPrice?: Number256
128
140
  gasEstimationMultiplier?: number
129
141
  group?: number
142
+ dustAmount?: Number256
130
143
  }
131
144
  assertType<Eq<keyof SignExecuteScriptTxParams, keyof TxBuildParams<node.BuildExecuteScriptTx>>>()
132
145
  export interface SignExecuteScriptTxResult {