@stacks/rendezvous 0.1.3 → 0.3.0

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.
package/dist/property.js CHANGED
@@ -9,12 +9,42 @@ const transactions_1 = require("@stacks/transactions");
9
9
  const heatstroke_1 = require("./heatstroke");
10
10
  const shared_1 = require("./shared");
11
11
  const ansicolor_1 = require("ansicolor");
12
- const checkProperties = (simnet, sutContractName, rendezvousList, rendezvousAllFunctions, seed, path, runs, radio) => {
12
+ const traits_1 = require("./traits");
13
+ /**
14
+ * Runs property-based tests on the target contract and logs the progress.
15
+ * Reports the test results through a custom reporter.
16
+ * @param simnet The simnet instance.
17
+ * @param targetContractName The name of the target contract.
18
+ * @param rendezvousList The list of contract IDs for each target contract.
19
+ * @param rendezvousAllFunctions A map of all target contract IDs to their
20
+ * function interfaces.
21
+ * @param seed The seed for reproducible property-based tests.
22
+ * @param path The path for reproducible property-based tests.
23
+ * @param runs The number of test runs.
24
+ * @param radio The custom logging event emitter.
25
+ * @returns void
26
+ */
27
+ const checkProperties = (simnet, targetContractName, rendezvousList, rendezvousAllFunctions, seed, path, runs, radio) => {
28
+ const testContractId = rendezvousList[0];
13
29
  // A map where the keys are the test contract identifiers and the values are
14
30
  // arrays of their test functions. This map will be used to access the test
15
31
  // functions for each test contract in the property-based testing routine.
16
32
  const testContractsTestFunctions = filterTestFunctions(rendezvousAllFunctions);
17
- radio.emit("logMessage", `\nStarting property testing type for the ${sutContractName} contract...\n`);
33
+ const traitReferenceFunctions = testContractsTestFunctions
34
+ .get(testContractId)
35
+ .filter((fn) => (0, traits_1.isTraitReferenceFunction)(fn));
36
+ const projectTraitImplementations = (0, traits_1.extractProjectTraitImplementations)(simnet);
37
+ if (Object.entries(projectTraitImplementations).length === 0 &&
38
+ traitReferenceFunctions.length > 0) {
39
+ radio.emit("logMessage", (0, ansicolor_1.red)(`\nFound test functions referencing traits, but no trait implementations were found in the project.
40
+ \nNote: You can add contracts implementing traits either as project contracts or as Clarinet requirements. For more details, visit: https://www.hiro.so/clarinet/.
41
+ \n`));
42
+ return;
43
+ }
44
+ const enrichedTestFunctionsInterfaces = traitReferenceFunctions.length > 0
45
+ ? (0, traits_1.enrichInterfaceWithTraitData)(simnet.getContractAST(targetContractName), (0, traits_1.buildTraitReferenceMap)(testContractsTestFunctions.get(testContractId)), testContractsTestFunctions.get(testContractId), testContractId)
46
+ : testContractsTestFunctions;
47
+ radio.emit("logMessage", `\nStarting property testing type for the ${targetContractName} contract...\n`);
18
48
  // Search for discard functions, for each test function. This map will
19
49
  // be used to pair the test functions with their corresponding discard
20
50
  // functions.
@@ -43,15 +73,9 @@ const checkProperties = (simnet, sutContractName, rendezvousList, rendezvousAllF
43
73
  const simnetAccounts = simnet.getAccounts();
44
74
  const eligibleAccounts = new Map([...simnetAccounts].filter(([key]) => key !== "faucet"));
45
75
  const simnetAddresses = Array.from(simnetAccounts.values());
46
- const testContractId = rendezvousList[0];
47
- const testFunctions = (0, shared_1.getFunctionsListForContract)(testContractsTestFunctions, testContractId);
76
+ const testFunctions = (0, shared_1.getFunctionsListForContract)(enrichedTestFunctionsInterfaces, testContractId);
48
77
  if ((testFunctions === null || testFunctions === void 0 ? void 0 : testFunctions.length) === 0) {
49
- radio.emit("logMessage", (0, ansicolor_1.red)(`No test functions found for the "${sutContractName}" contract.\n`));
50
- return;
51
- }
52
- const eligibleTestFunctions = testFunctions.filter((fn) => !(0, shared_1.isTraitReferenceFunction)(fn));
53
- if (eligibleTestFunctions.length === 0) {
54
- radio.emit("logMessage", (0, ansicolor_1.red)(`No eligible test functions found for the "${sutContractName}" contract. Note: trait references are not supported.\n`));
78
+ radio.emit("logMessage", (0, ansicolor_1.red)(`No test functions found for the "${targetContractName}" contract.\n`));
55
79
  return;
56
80
  }
57
81
  const radioReporter = (runDetails) => {
@@ -65,12 +89,12 @@ const checkProperties = (simnet, sutContractName, rendezvousList, rendezvousAllF
65
89
  })
66
90
  .chain((r) => fast_check_1.default
67
91
  .record({
68
- selectedTestFunction: fast_check_1.default.constantFrom(...eligibleTestFunctions),
92
+ selectedTestFunction: fast_check_1.default.constantFrom(...testFunctions),
69
93
  })
70
94
  .map((selectedTestFunction) => (Object.assign(Object.assign({}, r), selectedTestFunction))))
71
95
  .chain((r) => fast_check_1.default
72
96
  .record({
73
- functionArgsArb: fast_check_1.default.tuple(...(0, shared_1.functionToArbitrary)(r.selectedTestFunction, simnetAddresses)),
97
+ functionArgs: fast_check_1.default.tuple(...(0, shared_1.functionToArbitrary)(r.selectedTestFunction, simnetAddresses, projectTraitImplementations)),
74
98
  })
75
99
  .map((args) => (Object.assign(Object.assign({}, r), args))))
76
100
  .chain((r) => fast_check_1.default
@@ -89,8 +113,8 @@ const checkProperties = (simnet, sutContractName, rendezvousList, rendezvousAllF
89
113
  : fast_check_1.default.constant(0),
90
114
  })
91
115
  .map((burnBlocks) => (Object.assign(Object.assign({}, r), burnBlocks)))), (r) => {
92
- const selectedTestFunctionArgs = (0, shared_1.argsToCV)(r.selectedTestFunction, r.functionArgsArb);
93
- const printedTestFunctionArgs = r.functionArgsArb
116
+ const selectedTestFunctionArgs = (0, shared_1.argsToCV)(r.selectedTestFunction, r.functionArgs);
117
+ const printedTestFunctionArgs = r.functionArgs
94
118
  .map((arg) => {
95
119
  try {
96
120
  return typeof arg === "object"
@@ -112,7 +136,7 @@ const checkProperties = (simnet, sutContractName, rendezvousList, rendezvousAllF
112
136
  `Ӿ ${simnet.blockHeight.toString().padStart(8)} ` +
113
137
  `${(0, ansicolor_1.dim)(testCallerWallet)} ` +
114
138
  `${(0, ansicolor_1.yellow)("[WARN]")} ` +
115
- `${sutContractName} ` +
139
+ `${targetContractName} ` +
116
140
  `${(0, ansicolor_1.underline)(r.selectedTestFunction.name)} ` +
117
141
  (0, ansicolor_1.dim)(printedTestFunctionArgs));
118
142
  }
@@ -128,7 +152,7 @@ const checkProperties = (simnet, sutContractName, rendezvousList, rendezvousAllF
128
152
  `Ӿ ${simnet.blockHeight.toString().padStart(8)} ` +
129
153
  `${(0, ansicolor_1.dim)(testCallerWallet)} ` +
130
154
  `${(0, ansicolor_1.yellow)("[WARN]")} ` +
131
- `${sutContractName} ` +
155
+ `${targetContractName} ` +
132
156
  `${(0, ansicolor_1.underline)(r.selectedTestFunction.name)} ` +
133
157
  (0, ansicolor_1.dim)(printedTestFunctionArgs));
134
158
  }
@@ -139,7 +163,7 @@ const checkProperties = (simnet, sutContractName, rendezvousList, rendezvousAllF
139
163
  `Ӿ ${simnet.blockHeight.toString().padStart(8)} ` +
140
164
  `${(0, ansicolor_1.dim)(testCallerWallet)} ` +
141
165
  `${(0, ansicolor_1.green)("[PASS]")} ` +
142
- `${sutContractName} ` +
166
+ `${targetContractName} ` +
143
167
  `${(0, ansicolor_1.underline)(r.selectedTestFunction.name)} ` +
144
168
  printedTestFunctionArgs);
145
169
  if (r.canMineBlocks) {
@@ -147,7 +171,7 @@ const checkProperties = (simnet, sutContractName, rendezvousList, rendezvousAllF
147
171
  }
148
172
  }
149
173
  else {
150
- throw new Error(`Test failed for ${sutContractName} contract: "${r.selectedTestFunction.name}" returned ${testFunctionCallResultJson.value.value}`);
174
+ throw new Error(`Test failed for ${targetContractName} contract: "${r.selectedTestFunction.name}" returned ${testFunctionCallResultJson.value.value}`);
151
175
  }
152
176
  }
153
177
  catch (error) {
@@ -156,7 +180,7 @@ const checkProperties = (simnet, sutContractName, rendezvousList, rendezvousAllF
156
180
  `Ӿ ${simnet.blockHeight.toString().padStart(8)} ` +
157
181
  `${testCallerWallet} ` +
158
182
  `[FAIL] ` +
159
- `${sutContractName} ` +
183
+ `${targetContractName} ` +
160
184
  `${(0, ansicolor_1.underline)(r.selectedTestFunction.name)} ` +
161
185
  printedTestFunctionArgs));
162
186
  // Re-throw the error for fast-check to catch and process.
@@ -180,12 +204,12 @@ const isTestDiscardedInPlace = (testFunctionCallResultJson) => testFunctionCallR
180
204
  testFunctionCallResultJson.value.value === false;
181
205
  exports.isTestDiscardedInPlace = isTestDiscardedInPlace;
182
206
  /**
183
- * Check if the test function has to be discarded.
207
+ * Checks if the test function has to be discarded.
184
208
  * @param discardFunctionName The discard function name.
185
209
  * @param selectedTestFunctionArgs The generated test function arguments.
186
210
  * @param contractId The contract identifier.
187
211
  * @param simnet The simnet instance.
188
- * @param selectedCaller The selected caller.
212
+ * @param selectedCaller The selected caller address.
189
213
  * @returns A boolean indicating if the test function has to be discarded.
190
214
  */
191
215
  const isTestDiscarded = (discardFunctionName, selectedTestFunctionArgs, contractId, simnet, selectedCaller) => {
@@ -196,7 +220,7 @@ const isTestDiscarded = (discardFunctionName, selectedTestFunctionArgs, contract
196
220
  return jsonDiscardFunctionCallResult.value === false;
197
221
  };
198
222
  /**
199
- * Validate the discard function, ensuring that its parameters match the test
223
+ * Validates a discard function, ensuring that its parameters match the test
200
224
  * function's parameters and that its return type is boolean.
201
225
  * @param contractId The contract identifier.
202
226
  * @param discardFunctionName The discard function name.
@@ -225,23 +249,23 @@ const validateDiscardFunction = (contractId, discardFunctionName, testFunctionNa
225
249
  return true;
226
250
  };
227
251
  /**
228
- * Verify if the test function parameters match the discard function
252
+ * Checks if the test function parameters match the discard function
229
253
  * parameters.
230
- * @param testFunction The test function's interface.
231
- * @param discardFunction The discard function's interface.
254
+ * @param testFunctionInterface The test function's interface.
255
+ * @param discardFunctionInterface The discard function's interface.
232
256
  * @returns A boolean indicating if the parameters match.
233
257
  */
234
- const isParamsMatch = (testFunction, discardFunction) => {
235
- const sortedTestFunctionArgs = [...testFunction.args].sort((a, b) => a.name.localeCompare(b.name));
236
- const sortedDiscardFunctionArgs = [...discardFunction.args].sort((a, b) => a.name.localeCompare(b.name));
258
+ const isParamsMatch = (testFunctionInterface, discardFunctionInterface) => {
259
+ const sortedTestFunctionArgs = [...testFunctionInterface.args].sort((a, b) => a.name.localeCompare(b.name));
260
+ const sortedDiscardFunctionArgs = [...discardFunctionInterface.args].sort((a, b) => a.name.localeCompare(b.name));
237
261
  return (JSON.stringify(sortedTestFunctionArgs) ===
238
262
  JSON.stringify(sortedDiscardFunctionArgs));
239
263
  };
240
264
  exports.isParamsMatch = isParamsMatch;
241
265
  /**
242
- * Verify if the discard function's return type is boolean.
243
- * @param discardFunction The discard function's interface.
266
+ * Checks if the discard function's return type is boolean.
267
+ * @param discardFunctionInterface The discard function's interface.
244
268
  * @returns A boolean indicating if the return type is boolean.
245
269
  */
246
- const isReturnTypeBoolean = (discardFunction) => discardFunction.outputs.type === "bool";
270
+ const isReturnTypeBoolean = (discardFunctionInterface) => discardFunctionInterface.outputs.type === "bool";
247
271
  exports.isReturnTypeBoolean = isReturnTypeBoolean;
package/dist/shared.js CHANGED
@@ -3,42 +3,50 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getContractNameFromContractId = exports.isTraitReferenceFunction = exports.argsToCV = exports.hexaString = exports.functionToArbitrary = exports.getFunctionsListForContract = exports.getFunctionsFromContractInterfaces = exports.getSimnetDeployerContractsInterfaces = void 0;
6
+ exports.getContractNameFromContractId = exports.argsToCV = exports.hexaString = exports.functionToArbitrary = exports.getFunctionsListForContract = exports.getFunctionsFromContractInterfaces = exports.getSimnetDeployerContractsInterfaces = void 0;
7
7
  const fast_check_1 = __importDefault(require("fast-check"));
8
8
  const transactions_1 = require("@stacks/transactions");
9
+ const traits_1 = require("./traits");
9
10
  /**
10
- * Get the interfaces of contracts deployed by the specified deployer from the
11
- * simnet.
11
+ * Retrieves the contract interfaces of the contracts deployed by a specific
12
+ * deployer from the simnet instance.
12
13
  * @param simnet The simnet instance.
13
- * @param deployer The deployer address.
14
- * @returns The contracts interfaces.
14
+ * @returns The contract IDs mapped to their interfaces.
15
15
  */
16
16
  const getSimnetDeployerContractsInterfaces = (simnet) => new Map(Array.from(simnet.getContractsInterfaces()).filter(([key]) => key.split(".")[0] === simnet.deployer));
17
17
  exports.getSimnetDeployerContractsInterfaces = getSimnetDeployerContractsInterfaces;
18
18
  /**
19
- * Get the functions from the smart contract interfaces.
20
- * @param contractsInterfaces The smart contract interfaces map.
21
- * @returns A map containing the contracts functions.
19
+ * Retrieves the function interfaces from the contract interfaces. Filters out
20
+ * other contract interface data such as data maps, variables, and constants.
21
+ * @param contractInterfaces The smart contract interfaces map.
22
+ * @returns The contract IDs mapped to their function interfaces.
22
23
  */
23
- const getFunctionsFromContractInterfaces = (contractsInterfaces) => new Map(Array.from(contractsInterfaces, ([contractId, contractInterface]) => [
24
+ const getFunctionsFromContractInterfaces = (contractInterfaces) => new Map(Array.from(contractInterfaces, ([contractId, contractInterface]) => [
24
25
  contractId,
25
26
  contractInterface.functions,
26
27
  ]));
27
28
  exports.getFunctionsFromContractInterfaces = getFunctionsFromContractInterfaces;
28
29
  const getFunctionsListForContract = (functionsMap, contractId) => functionsMap.get(contractId) || [];
29
30
  exports.getFunctionsListForContract = getFunctionsListForContract;
30
- /** For a given function, dynamically generate fast-check arbitraries.
31
- * @param fn The function interface.
31
+ /** Dynamically generates fast-check arbitraries for a given function
32
+ * interface.
33
+ * @param functionInterface The "enriched" function interface.
34
+ * @param addresses The array of addresses to use for principal types.
35
+ * @param projectTraitImplementations The contract IDs mapped to the traits
36
+ * they implement.
32
37
  * @returns Array of fast-check arbitraries.
33
38
  */
34
- const functionToArbitrary = (fn, addresses) => fn.args.map((arg) => parameterTypeToArbitrary(arg.type, addresses));
39
+ const functionToArbitrary = (functionInterface, addresses, projectTraitImplementations) => functionInterface.args.map((arg) => parameterTypeToArbitrary(arg.type, addresses, projectTraitImplementations));
35
40
  exports.functionToArbitrary = functionToArbitrary;
36
41
  /**
37
- * For a given type, generate a fast-check arbitrary.
38
- * @param type The parameter type.
42
+ * Generates a fast-check arbitrary for a given parameter type.
43
+ * @param type The "enriched" parameter type.
44
+ * @param addresses The array of addresses to use for principal types.
45
+ * @param projectTraitImplementations The contract IDs mapped to the traits
46
+ * they implement.
39
47
  * @returns Fast-check arbitrary.
40
48
  */
41
- const parameterTypeToArbitrary = (type, addresses) => {
49
+ const parameterTypeToArbitrary = (type, addresses, projectTraitImplementations) => {
42
50
  if (typeof type === "string") {
43
51
  // The type is a base type.
44
52
  if (type === "principal") {
@@ -46,9 +54,6 @@ const parameterTypeToArbitrary = (type, addresses) => {
46
54
  throw new Error("No addresses could be retrieved from the simnet instance!");
47
55
  return baseTypesToArbitrary.principal(addresses);
48
56
  }
49
- else if (type === "trait_reference") {
50
- throw new Error("Unsupported parameter type: trait_reference");
51
- }
52
57
  else
53
58
  return baseTypesToArbitrary[type];
54
59
  }
@@ -64,16 +69,19 @@ const parameterTypeToArbitrary = (type, addresses) => {
64
69
  return complexTypesToArbitrary["string-utf8"](type["string-utf8"].length);
65
70
  }
66
71
  else if ("list" in type) {
67
- return complexTypesToArbitrary["list"](type.list.type, type.list.length, addresses);
72
+ return complexTypesToArbitrary["list"](type.list.type, type.list.length, addresses, projectTraitImplementations);
68
73
  }
69
74
  else if ("tuple" in type) {
70
- return complexTypesToArbitrary["tuple"](type.tuple, addresses);
75
+ return complexTypesToArbitrary["tuple"](type.tuple, addresses, projectTraitImplementations);
71
76
  }
72
77
  else if ("optional" in type) {
73
- return complexTypesToArbitrary["optional"](type.optional, addresses);
78
+ return complexTypesToArbitrary["optional"](type.optional, addresses, projectTraitImplementations);
74
79
  }
75
80
  else if ("response" in type) {
76
- return complexTypesToArbitrary.response(type.response.ok, type.response.error, addresses);
81
+ return complexTypesToArbitrary.response(type.response.ok, type.response.error, addresses, projectTraitImplementations);
82
+ }
83
+ else if ("trait_reference" in type) {
84
+ return complexTypesToArbitrary.trait_reference(type.trait_reference, projectTraitImplementations);
77
85
  }
78
86
  else {
79
87
  throw new Error(`Unsupported complex type: ${JSON.stringify(type)}`);
@@ -88,28 +96,7 @@ const baseTypesToArbitrary = {
88
96
  uint128: fast_check_1.default.nat(),
89
97
  bool: fast_check_1.default.boolean(),
90
98
  principal: (addresses) => fast_check_1.default.constantFrom(...addresses),
91
- trait_reference: undefined,
92
99
  };
93
- /**
94
- * Custom hexadecimal string generator. The `hexaString` generator from
95
- * fast-check has been deprecated. This generator is implemented to precisely
96
- * match the behavior of the deprecated generator.
97
- *
98
- * @param constraints Fast-check string constraints.
99
- * @returns Fast-check arbitrary for hexadecimal strings.
100
- *
101
- * Reference for the proposed replacement of the deprecated `hexaString`
102
- * generator:
103
- * https://github.com/dubzzz/fast-check/commit/3f4f1203a8863c07d22b45591bf0de1fac02b948
104
- */
105
- const hexaString = (constraints = {}) => {
106
- const hexa = () => {
107
- const hexCharSet = "0123456789abcdef";
108
- return fast_check_1.default.integer({ min: 0, max: 15 }).map((n) => hexCharSet[n]);
109
- };
110
- return fast_check_1.default.string(Object.assign(Object.assign({}, constraints), { unit: hexa() }));
111
- };
112
- exports.hexaString = hexaString;
113
100
  /**
114
101
  * Complex types to fast-check arbitraries mapping.
115
102
  */
@@ -125,51 +112,76 @@ const complexTypesToArbitrary = {
125
112
  maxLength: length,
126
113
  }),
127
114
  "string-utf8": (length) => fast_check_1.default.string({ maxLength: length }),
128
- list: (type, length, addresses) => fast_check_1.default.array(parameterTypeToArbitrary(type, addresses), { maxLength: length }),
129
- tuple: (items, addresses) => {
115
+ list: (type, length, addresses, projectTraitImplementations) => fast_check_1.default.array(parameterTypeToArbitrary(type, addresses, projectTraitImplementations), {
116
+ maxLength: length,
117
+ }),
118
+ tuple: (items, addresses, projectTraitImplementations) => {
130
119
  const tupleArbitraries = {};
131
120
  items.forEach((item) => {
132
- tupleArbitraries[item.name] = parameterTypeToArbitrary(item.type, addresses);
121
+ tupleArbitraries[item.name] = parameterTypeToArbitrary(item.type, addresses, projectTraitImplementations);
133
122
  });
134
123
  return fast_check_1.default.record(tupleArbitraries);
135
124
  },
136
- optional: (type, addresses) => fast_check_1.default.option(parameterTypeToArbitrary(type, addresses)),
137
- response: (okType, errType, addresses) => fast_check_1.default.oneof(fast_check_1.default.record({
125
+ optional: (type, addresses, projectTraitImplementations) => fast_check_1.default.option(parameterTypeToArbitrary(type, addresses, projectTraitImplementations)),
126
+ response: (okType, errType, addresses, projectTraitImplementations) => fast_check_1.default.oneof(fast_check_1.default.record({
138
127
  status: fast_check_1.default.constant("ok"),
139
- value: parameterTypeToArbitrary(okType, addresses),
128
+ value: parameterTypeToArbitrary(okType, addresses, projectTraitImplementations),
140
129
  }), fast_check_1.default.record({
141
130
  status: fast_check_1.default.constant("error"),
142
- value: parameterTypeToArbitrary(errType, addresses),
131
+ value: parameterTypeToArbitrary(errType, addresses, projectTraitImplementations),
143
132
  })),
133
+ trait_reference: (traitData, projectTraitImplementations) => {
134
+ return fast_check_1.default.constantFrom(...(0, traits_1.getContractIdsImplementingTrait)(traitData, projectTraitImplementations));
135
+ },
144
136
  };
137
+ /**
138
+ * Custom hexadecimal string generator. The `hexaString` generator from
139
+ * fast-check has been deprecated. This generator is implemented to match the
140
+ * behavior of the deprecated generator.
141
+ *
142
+ * @param constraints Fast-check string constraints.
143
+ * @returns Fast-check arbitrary for hexadecimal strings.
144
+ *
145
+ * Reference for the proposed replacement of the deprecated `hexaString`
146
+ * generator:
147
+ * https://github.com/dubzzz/fast-check/commit/3f4f1203a8863c07d22b45591bf0de1fac02b948
148
+ */
149
+ const hexaString = (constraints = {}) => {
150
+ const hexa = () => {
151
+ const hexCharSet = "0123456789abcdef";
152
+ return fast_check_1.default.integer({ min: 0, max: 15 }).map((n) => hexCharSet[n]);
153
+ };
154
+ return fast_check_1.default.string(Object.assign(Object.assign({}, constraints), { unit: hexa() }));
155
+ };
156
+ exports.hexaString = hexaString;
145
157
  /** The character set used for generating ASCII strings.*/
146
158
  const charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
147
159
  /**
148
- * Convert function arguments to Clarity values.
149
- * @param fn The function interface.
150
- * @param args Array of arguments.
160
+ * Converts JavaScript generated function arguments to Clarity values.
161
+ * @param functionInterface The function interface.
162
+ * @param generatedArguments Array of generated arguments.
151
163
  * @returns Array of Clarity values.
152
164
  */
153
- const argsToCV = (fn, args) => fn.args.map((arg, i) => argToCV(args[i], arg.type));
165
+ const argsToCV = (functionInterface, generatedArguments) => functionInterface.args.map((arg, i) => argToCV(generatedArguments[i], arg.type));
154
166
  exports.argsToCV = argsToCV;
155
167
  /**
156
- * Convert a function argument to a Clarity value.
157
- * @param arg Generated argument.
168
+ * Converts a JavaScript generated function argument to a Clarity value.
169
+ * @param generatedArgument Generated argument.
158
170
  * @param type Argument type (base or complex).
159
171
  * @returns Clarity value.
160
172
  */
161
- const argToCV = (arg, type) => {
173
+ const argToCV = (generatedArgument, type) => {
162
174
  if (isBaseType(type)) {
163
175
  // Base type.
164
176
  switch (type) {
165
177
  case "int128":
166
- return baseTypesToCV.int128(arg);
178
+ return baseTypesToCV.int128(generatedArgument);
167
179
  case "uint128":
168
- return baseTypesToCV.uint128(arg);
180
+ return baseTypesToCV.uint128(generatedArgument);
169
181
  case "bool":
170
- return baseTypesToCV.bool(arg);
182
+ return baseTypesToCV.bool(generatedArgument);
171
183
  case "principal":
172
- return baseTypesToCV.principal(arg);
184
+ return baseTypesToCV.principal(generatedArgument);
173
185
  default:
174
186
  throw new Error(`Unsupported base parameter type: ${type}`);
175
187
  }
@@ -177,34 +189,39 @@ const argToCV = (arg, type) => {
177
189
  else {
178
190
  // Complex type.
179
191
  if ("buffer" in type) {
180
- return complexTypesToCV.buffer(arg);
192
+ return complexTypesToCV.buffer(generatedArgument);
181
193
  }
182
194
  else if ("string-ascii" in type) {
183
- return complexTypesToCV["string-ascii"](arg);
195
+ return complexTypesToCV["string-ascii"](generatedArgument);
184
196
  }
185
197
  else if ("string-utf8" in type) {
186
- return complexTypesToCV["string-utf8"](arg);
198
+ return complexTypesToCV["string-utf8"](generatedArgument);
187
199
  }
188
200
  else if ("list" in type) {
189
- const listItems = arg.map((item) => argToCV(item, type.list.type));
201
+ const listItems = generatedArgument.map((item) => argToCV(item, type.list.type));
190
202
  return complexTypesToCV.list(listItems);
191
203
  }
192
204
  else if ("tuple" in type) {
193
205
  const tupleData = {};
194
206
  type.tuple.forEach((field) => {
195
- tupleData[field.name] = argToCV(arg[field.name], field.type);
207
+ tupleData[field.name] = argToCV(generatedArgument[field.name], field.type);
196
208
  });
197
209
  return complexTypesToCV.tuple(tupleData);
198
210
  }
199
211
  else if ("optional" in type) {
200
- return (0, transactions_1.optionalCVOf)(arg ? argToCV(arg, type.optional) : undefined);
212
+ return (0, transactions_1.optionalCVOf)(generatedArgument
213
+ ? argToCV(generatedArgument, type.optional)
214
+ : undefined);
201
215
  }
202
216
  else if ("response" in type) {
203
- const status = arg.status;
217
+ const status = generatedArgument.status;
204
218
  const branchType = type.response[status];
205
- const responseValue = argToCV(arg.value, branchType);
219
+ const responseValue = argToCV(generatedArgument.value, branchType);
206
220
  return complexTypesToCV.response(status, responseValue);
207
221
  }
222
+ else if ("trait_reference" in type) {
223
+ return complexTypesToCV.trait_reference(generatedArgument);
224
+ }
208
225
  else {
209
226
  throw new Error(`Unsupported complex parameter type: ${JSON.stringify(type)}`);
210
227
  }
@@ -241,45 +258,10 @@ const complexTypesToCV = {
241
258
  else
242
259
  throw new Error(`Unsupported response status: ${status}`);
243
260
  },
261
+ trait_reference: (traitImplementation) => (0, transactions_1.principalCV)(traitImplementation),
244
262
  };
245
263
  const isBaseType = (type) => {
246
264
  return ["int128", "uint128", "bool", "principal"].includes(type);
247
265
  };
248
- /**
249
- * Checks if any parameter of the function contains a `trait_reference` type.
250
- * @param fn The function interface.
251
- * @returns Boolean - true if the function contains a trait reference, false
252
- * otherwise.
253
- */
254
- const isTraitReferenceFunction = (fn) => {
255
- const hasTraitReference = (type) => {
256
- if (typeof type === "string") {
257
- // The type is a base type.
258
- return type === "trait_reference";
259
- }
260
- else {
261
- // The type is a complex type.
262
- if ("buffer" in type)
263
- return false;
264
- if ("string-ascii" in type)
265
- return false;
266
- if ("string-utf8" in type)
267
- return false;
268
- if ("list" in type)
269
- return hasTraitReference(type.list.type);
270
- if ("tuple" in type)
271
- return type.tuple.some((item) => hasTraitReference(item.type));
272
- if ("optional" in type)
273
- return hasTraitReference(type.optional);
274
- if ("response" in type)
275
- return (hasTraitReference(type.response.ok) ||
276
- hasTraitReference(type.response.error));
277
- // Default to false for unexpected types.
278
- return false;
279
- }
280
- };
281
- return fn.args.some((arg) => hasTraitReference(arg.type));
282
- };
283
- exports.isTraitReferenceFunction = isTraitReferenceFunction;
284
266
  const getContractNameFromContractId = (contractId) => contractId.split(".")[1];
285
267
  exports.getContractNameFromContractId = getContractNameFromContractId;