@meshsdk/common 1.9.0-beta.55 → 1.9.0-beta.56

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/index.cjs CHANGED
@@ -52,6 +52,7 @@ __export(index_exports, {
52
52
  SUPPORTED_OGMIOS_LINKS: () => SUPPORTED_OGMIOS_LINKS,
53
53
  SUPPORTED_TOKENS: () => SUPPORTED_TOKENS,
54
54
  SUPPORTED_WALLETS: () => SUPPORTED_WALLETS,
55
+ TxTester: () => TxTester,
55
56
  UtxoSelection: () => UtxoSelection,
56
57
  assetClass: () => assetClass,
57
58
  assetName: () => assetName,
@@ -85,6 +86,7 @@ __export(index_exports, {
85
86
  isNetwork: () => isNetwork,
86
87
  jsonProofToPlutusData: () => jsonProofToPlutusData,
87
88
  keepRelevant: () => keepRelevant,
89
+ keySignedLogic: () => keySignedLogic,
88
90
  largestFirst: () => largestFirst,
89
91
  largestFirstMultiAsset: () => largestFirstMultiAsset,
90
92
  list: () => list,
@@ -140,11 +142,13 @@ __export(index_exports, {
140
142
  stringToHex: () => stringToHex,
141
143
  toBytes: () => toBytes,
142
144
  toUTF8: () => toUTF8,
145
+ tokenMintedLogic: () => tokenMintedLogic,
143
146
  tokenName: () => tokenName,
144
147
  tuple: () => tuple,
145
148
  txInToUtxo: () => txInToUtxo,
146
149
  txOutRef: () => txOutRef,
147
150
  unixTimeToEnclosingSlot: () => unixTimeToEnclosingSlot,
151
+ validityRangeFromObj: () => validityRangeFromObj,
148
152
  validityRangeToObj: () => validityRangeToObj,
149
153
  value: () => value,
150
154
  verificationKey: () => verificationKey
@@ -1049,6 +1053,16 @@ var validityRangeToObj = (validityRange) => {
1049
1053
  invalidHereafter: validityRange.invalidHereafter ?? null
1050
1054
  };
1051
1055
  };
1056
+ var validityRangeFromObj = (obj) => {
1057
+ const validityRange = {};
1058
+ if (obj.invalidBefore !== null && obj.invalidBefore !== void 0) {
1059
+ validityRange.invalidBefore = Number(obj.invalidBefore);
1060
+ }
1061
+ if (obj.invalidHereafter !== null && obj.invalidHereafter !== void 0) {
1062
+ validityRange.invalidHereafter = Number(obj.invalidHereafter);
1063
+ }
1064
+ return validityRange;
1065
+ };
1052
1066
 
1053
1067
  // src/data/mesh/constructors.ts
1054
1068
  var mConStr = (alternative, fields) => ({
@@ -1638,6 +1652,23 @@ var MeshValue = class _MeshValue {
1638
1652
  get = (unit) => {
1639
1653
  return this.value[unit] ? BigInt(this.value[unit]) : BigInt(0);
1640
1654
  };
1655
+ /**
1656
+ * Get all assets that belong to a specific policy ID
1657
+ * @param policyId The policy ID to filter by
1658
+ * @returns Array of assets that match the policy ID
1659
+ */
1660
+ getPolicyAssets = (policyId2) => {
1661
+ const assets = [];
1662
+ Object.entries(this.value).forEach(([unit, quantity]) => {
1663
+ if (unit.startsWith(policyId2)) {
1664
+ assets.push({
1665
+ unit,
1666
+ quantity: quantity.toString()
1667
+ });
1668
+ }
1669
+ });
1670
+ return assets;
1671
+ };
1641
1672
  /**
1642
1673
  * Get all asset units
1643
1674
  * @returns The asset units
@@ -2058,6 +2089,473 @@ var UtxoSelection = class {
2058
2089
  }
2059
2090
  };
2060
2091
 
2092
+ // src/tx-tester/index.ts
2093
+ var TxTester = class {
2094
+ txBody;
2095
+ inputsEvaluating;
2096
+ outputsEvaluating;
2097
+ traces;
2098
+ /**
2099
+ * Create a new TxTester instance
2100
+ * @param txBody The transaction builder body
2101
+ */
2102
+ constructor(txBody) {
2103
+ this.txBody = { ...txBody };
2104
+ this.inputsEvaluating = [];
2105
+ this.outputsEvaluating = [];
2106
+ this.traces = [];
2107
+ }
2108
+ /**
2109
+ * Add a trace to the TxTester
2110
+ * @param funcName The function name where the error occurred
2111
+ * @param message The error message
2112
+ */
2113
+ addTrace(funcName, message) {
2114
+ const msg = `[Error - ${funcName}]: ${message}`;
2115
+ this.traces.push(msg);
2116
+ }
2117
+ /**
2118
+ * Check if the transaction evaluation was successful
2119
+ * @returns true if there are no errors, false otherwise
2120
+ */
2121
+ success() {
2122
+ return this.traces.length === 0;
2123
+ }
2124
+ /**
2125
+ * Get the error messages if any
2126
+ * @returns A string representation of the errors or "No errors" if there are none
2127
+ */
2128
+ errors() {
2129
+ if (this.traces.length > 0) {
2130
+ return `${this.traces}`;
2131
+ } else {
2132
+ return "No errors";
2133
+ }
2134
+ }
2135
+ /**
2136
+ * Checks if the transaction is valid after a specified timestamp.
2137
+ * @param requiredTimestamp The timestamp after which the transaction should be valid
2138
+ * @returns The TxTester instance for chaining
2139
+ */
2140
+ validAfter = (requiredTimestamp) => {
2141
+ const invalidBefore = this.txBody.validityRange?.invalidHereafter ? this.txBody.validityRange.invalidHereafter : 9999999999999;
2142
+ const isValidAfter = this.txBody.validityRange?.invalidBefore ? this.txBody.validityRange.invalidBefore < requiredTimestamp : true;
2143
+ if (!isValidAfter) {
2144
+ this.addTrace(
2145
+ "validAfter",
2146
+ `tx invalid before ${invalidBefore}, with requiredTimestamp ${requiredTimestamp}`
2147
+ );
2148
+ }
2149
+ return this;
2150
+ };
2151
+ /**
2152
+ * Checks if the transaction is valid before a specified timestamp.
2153
+ * @param requiredTimestamp The timestamp before which the transaction should be valid
2154
+ * @returns The TxTester instance for chaining
2155
+ */
2156
+ validBefore = (requiredTimestamp) => {
2157
+ const invalidHereafter = this.txBody.validityRange?.invalidBefore ? this.txBody.validityRange.invalidBefore : 0;
2158
+ const isValidBefore = this.txBody.validityRange?.invalidHereafter ? this.txBody.validityRange.invalidHereafter > requiredTimestamp : true;
2159
+ if (!isValidBefore) {
2160
+ this.addTrace(
2161
+ "validBefore",
2162
+ `tx invalid after ${invalidHereafter}, with requiredTimestamp ${requiredTimestamp}`
2163
+ );
2164
+ }
2165
+ return this;
2166
+ };
2167
+ // Extra Signatories Methods
2168
+ /**
2169
+ * Checks if a specific key is signed in the transaction.
2170
+ * @param keyHash The key hash to check
2171
+ * @returns The TxTester instance for chaining
2172
+ */
2173
+ keySigned = (keyHash) => {
2174
+ const isKeySigned = keySignedLogic(this.txBody.requiredSignatures, keyHash);
2175
+ if (!isKeySigned) {
2176
+ this.addTrace("keySigned", `tx does not have key ${keyHash} signed`);
2177
+ }
2178
+ return this;
2179
+ };
2180
+ /**
2181
+ * Checks if any one of the specified keys is signed in the transaction.
2182
+ * @param keyHashes The array of key hashes to check
2183
+ * @returns The TxTester instance for chaining
2184
+ */
2185
+ oneOfKeysSigned = (keyHashes) => {
2186
+ const isOneOfKeysSigned = keyHashes.some(
2187
+ (keyHash) => keySignedLogic(this.txBody.requiredSignatures, keyHash)
2188
+ );
2189
+ if (!isOneOfKeysSigned) {
2190
+ this.addTrace(
2191
+ "oneOfKeysSigned",
2192
+ `tx does not have any of the keys signed: ${keyHashes.join(", ")}`
2193
+ );
2194
+ }
2195
+ return this;
2196
+ };
2197
+ /**
2198
+ * Checks if all specified keys are signed in the transaction.
2199
+ * @param keyHashes The array of key hashes to check
2200
+ * @returns The TxTester instance for chaining
2201
+ */
2202
+ allKeysSigned = (keyHashes) => {
2203
+ const missingKeys = [];
2204
+ const isAllKeysSigned = keyHashes.every((keyHash) => {
2205
+ const isKeySigned = keySignedLogic(
2206
+ this.txBody.requiredSignatures,
2207
+ keyHash
2208
+ );
2209
+ if (!isKeySigned) {
2210
+ missingKeys.push(keyHash);
2211
+ }
2212
+ return isKeySigned;
2213
+ });
2214
+ if (!isAllKeysSigned) {
2215
+ this.addTrace(
2216
+ "allKeysSigned",
2217
+ `tx does not have all keys signed: ${missingKeys.join(", ")}`
2218
+ );
2219
+ }
2220
+ return this;
2221
+ };
2222
+ /**
2223
+ * Checks if a specific token is minted in the transaction.
2224
+ * @param policyId The policy ID of the token
2225
+ * @param assetName The asset name of the token
2226
+ * @param quantity The quantity of the token
2227
+ * @returns The TxTester instance for chaining
2228
+ */
2229
+ tokenMinted = (policyId2, assetName2, quantity) => {
2230
+ const isTokenMinted = tokenMintedLogic(
2231
+ this.txBody.mints,
2232
+ policyId2,
2233
+ assetName2,
2234
+ quantity
2235
+ );
2236
+ if (!isTokenMinted) {
2237
+ this.addTrace(
2238
+ "tokenMinted",
2239
+ `Token with policy_id: ${policyId2}, asset_name: ${assetName2}, quantity: ${quantity} not found in mints.`
2240
+ );
2241
+ }
2242
+ return this;
2243
+ };
2244
+ /**
2245
+ * Checks if a specific token is minted in the transaction and that it is the only mint.
2246
+ * @param policyId The policy ID of the token
2247
+ * @param assetName The asset name of the token
2248
+ * @param quantity The quantity of the token
2249
+ * @returns The TxTester instance for chaining
2250
+ */
2251
+ onlyTokenMinted = (policyId2, assetName2, quantity) => {
2252
+ const isTokenMinted = tokenMintedLogic(
2253
+ this.txBody.mints,
2254
+ policyId2,
2255
+ assetName2,
2256
+ quantity
2257
+ );
2258
+ const isOnlyOneMint = this.txBody.mints?.length === 1;
2259
+ if (!isTokenMinted) {
2260
+ this.addTrace(
2261
+ "onlyTokenMinted",
2262
+ `Token with policy_id: ${policyId2}, asset_name: ${assetName2}, quantity: ${quantity} not found in mints`
2263
+ );
2264
+ }
2265
+ if (!isOnlyOneMint) {
2266
+ this.addTrace(
2267
+ "onlyTokenMinted",
2268
+ `Expected only one mint, but found ${this.txBody.mints?.length || 0} mints.`
2269
+ );
2270
+ }
2271
+ return this;
2272
+ };
2273
+ /**
2274
+ * Checks if a specific token is minted in the transaction, ensuring that it is the only mint for the given policy ID.
2275
+ * @param policyId The policy ID of the token
2276
+ * @param assetName The asset name of the token
2277
+ * @param quantity The quantity of the token
2278
+ * @returns The TxTester instance for chaining
2279
+ */
2280
+ policyOnlyMintedToken = (policyId2, assetName2, quantity) => {
2281
+ const filteredMints = this.txBody.mints?.filter((token) => {
2282
+ return token.policyId === policyId2;
2283
+ }) || [];
2284
+ const isTokenMinted = tokenMintedLogic(
2285
+ this.txBody.mints,
2286
+ policyId2,
2287
+ assetName2,
2288
+ quantity
2289
+ );
2290
+ const isOnlyOneMint = filteredMints.length === 1;
2291
+ if (!isOnlyOneMint) {
2292
+ this.addTrace(
2293
+ "policyOnlyMintedToken",
2294
+ `Expected only one mint for policy_id: ${policyId2}, but found ${filteredMints.length} mints.`
2295
+ );
2296
+ }
2297
+ if (!isTokenMinted) {
2298
+ this.addTrace(
2299
+ "policyOnlyMintedToken",
2300
+ `Token with policy_id: ${policyId2}, asset_name: ${assetName2}, quantity: ${quantity} not found in mints.`
2301
+ );
2302
+ }
2303
+ return this;
2304
+ };
2305
+ /**
2306
+ * Checks if a specific policy ID is burned in the transaction, ensuring that it is the only minting (i.e. burning item).
2307
+ * @param policyId The policy ID to check
2308
+ * @returns true if the policy is the only burn, false otherwise
2309
+ */
2310
+ checkPolicyOnlyBurn = (policyId2) => {
2311
+ const filteredMints = this.txBody.mints?.filter((token) => {
2312
+ return token.policyId === policyId2 && token.mintValue.findIndex((m) => BigInt(m.amount) > 0) >= 0;
2313
+ }) || [];
2314
+ return filteredMints.length === 0;
2315
+ };
2316
+ /**
2317
+ * Not apply filter to inputs
2318
+ * @returns The TxTester instance for chaining
2319
+ */
2320
+ allInputs = () => {
2321
+ this.inputsEvaluating = this.txBody.inputs?.slice() || [];
2322
+ return this;
2323
+ };
2324
+ /**
2325
+ * Filter inputs by address
2326
+ * @param address The address to filter by
2327
+ * @returns The TxTester instance for chaining
2328
+ */
2329
+ inputsAt = (address) => {
2330
+ this.inputsEvaluating = this.txBody.inputs?.filter(
2331
+ (input) => txInToUtxo(input.txIn).output.address === address
2332
+ ) || [];
2333
+ return this;
2334
+ };
2335
+ /**
2336
+ * Filter inputs by unit
2337
+ * @param unit The unit to filter by
2338
+ * @returns The TxTester instance for chaining
2339
+ */
2340
+ inputsWith = (unit) => {
2341
+ this.inputsEvaluating = this.txBody.inputs?.filter((input) => {
2342
+ const inputValue = MeshValue.fromAssets(
2343
+ txInToUtxo(input.txIn).output.amount
2344
+ );
2345
+ const quantity = inputValue.get(unit);
2346
+ return quantity > 0;
2347
+ }) || [];
2348
+ return this;
2349
+ };
2350
+ /**
2351
+ * Filter inputs by policy ID
2352
+ * @param policyId The policy ID to filter by
2353
+ * @returns The TxTester instance for chaining
2354
+ */
2355
+ inputsWithPolicy = (policyId2) => {
2356
+ this.inputsEvaluating = this.txBody.inputs?.filter((input) => {
2357
+ const inputValue = MeshValue.fromAssets(
2358
+ txInToUtxo(input.txIn).output.amount
2359
+ );
2360
+ const assets = inputValue.getPolicyAssets(policyId2);
2361
+ return assets.length > 0;
2362
+ }) || [];
2363
+ return this;
2364
+ };
2365
+ /**
2366
+ * Filter inputs by address and policy ID
2367
+ * @param address The address to filter by
2368
+ * @param policyId The policy ID to filter by
2369
+ * @returns The TxTester instance for chaining
2370
+ */
2371
+ inputsAtWithPolicy = (address, policyId2) => {
2372
+ this.inputsEvaluating = this.txBody.inputs?.filter((input) => {
2373
+ const utxo = txInToUtxo(input.txIn);
2374
+ const inputValue = MeshValue.fromAssets(utxo.output.amount);
2375
+ const assets = inputValue.getPolicyAssets(policyId2);
2376
+ return utxo.output.address === address && assets.length > 0;
2377
+ }) || [];
2378
+ return this;
2379
+ };
2380
+ /**
2381
+ * Filter inputs by address and unit
2382
+ * @param address The address to filter by
2383
+ * @param unit The unit to filter by
2384
+ * @returns The TxTester instance for chaining
2385
+ */
2386
+ inputsAtWith = (address, unit) => {
2387
+ this.inputsEvaluating = this.txBody.inputs?.filter((input) => {
2388
+ const utxo = txInToUtxo(input.txIn);
2389
+ const inputValue = MeshValue.fromAssets(utxo.output.amount);
2390
+ const quantity = inputValue.get(unit);
2391
+ return utxo.output.address === address && quantity > 0;
2392
+ }) || [];
2393
+ return this;
2394
+ };
2395
+ /**
2396
+ * Check if inputs contain the expected value.
2397
+ * *Reminder - It must be called after filtering methods for inputs*
2398
+ * @param expectedValue The expected value
2399
+ * @returns The TxTester instance for chaining
2400
+ */
2401
+ inputsValue = (expectedValue) => {
2402
+ let value2 = new MeshValue();
2403
+ this.inputsEvaluating.forEach((input) => {
2404
+ const utxo = txInToUtxo(input.txIn);
2405
+ value2.addAssets(utxo.output.amount);
2406
+ });
2407
+ const isValueCorrect = value2.eq(expectedValue);
2408
+ if (!isValueCorrect) {
2409
+ this.addTrace(
2410
+ "inputsValue",
2411
+ `inputs ${JSON.stringify(this.inputsEvaluating)} have value ${JSON.stringify(value2)}, expect ${JSON.stringify(expectedValue)}`
2412
+ );
2413
+ }
2414
+ return this;
2415
+ };
2416
+ // /**
2417
+ // * Check if inputs contain a specific inline datum.
2418
+ // * *Reminder - It must be called after filtering methods for inputs*
2419
+ // * @param datumCbor The datum CBOR to check
2420
+ // * @returns The TxTester instance for chaining
2421
+ // */
2422
+ // inputsInlineDatumExist = (datumCbor: string): this => {
2423
+ // const inputsWithInlineDatum = this.inputsEvaluating.filter((input) => {
2424
+ // const utxo = txInToUtxo(input.txIn);
2425
+ // return utxo.output.plutusData === datumCbor;
2426
+ // });
2427
+ // if (inputsWithInlineDatum.length === 0) {
2428
+ // this.addTrace(
2429
+ // "inputsInlineDatumExist",
2430
+ // `No inputs with inline datum matching: ${datumCbor}`,
2431
+ // );
2432
+ // }
2433
+ // return this;
2434
+ // };
2435
+ /**
2436
+ * Not apply filter to outputs
2437
+ * @returns The TxTester instance for chaining
2438
+ */
2439
+ allOutputs = () => {
2440
+ this.outputsEvaluating = this.txBody.outputs?.slice() || [];
2441
+ return this;
2442
+ };
2443
+ /**
2444
+ * Filter outputs by address
2445
+ * @param address The address to filter by
2446
+ * @returns The TxTester instance for chaining
2447
+ */
2448
+ outputsAt = (address) => {
2449
+ this.outputsEvaluating = this.txBody.outputs?.filter((output) => output.address === address) || [];
2450
+ return this;
2451
+ };
2452
+ /**
2453
+ * Filter outputs by unit
2454
+ * @param unit The unit to filter by
2455
+ * @returns The TxTester instance for chaining
2456
+ */
2457
+ outputsWith = (unit) => {
2458
+ this.outputsEvaluating = this.txBody.outputs?.filter((output) => {
2459
+ const outputValue = MeshValue.fromAssets(output.amount);
2460
+ const quantity = outputValue.get(unit);
2461
+ return quantity > 0;
2462
+ }) || [];
2463
+ return this;
2464
+ };
2465
+ /**
2466
+ * Filter outputs by policy ID
2467
+ * @param policyId The policy ID to filter by
2468
+ * @returns The TxTester instance for chaining
2469
+ */
2470
+ outputsWithPolicy = (policyId2) => {
2471
+ this.outputsEvaluating = this.txBody.outputs?.filter((output) => {
2472
+ const outputValue = MeshValue.fromAssets(output.amount);
2473
+ const assets = outputValue.getPolicyAssets(policyId2);
2474
+ return assets.length > 0;
2475
+ }) || [];
2476
+ return this;
2477
+ };
2478
+ /**
2479
+ * Filter outputs by address and policy ID
2480
+ * @param address The address to filter by
2481
+ * @param policyId The policy ID to filter by
2482
+ * @returns The TxTester instance for chaining
2483
+ */
2484
+ outputsAtWithPolicy = (address, policyId2) => {
2485
+ this.outputsEvaluating = this.txBody.outputs?.filter((output) => {
2486
+ const outputValue = MeshValue.fromAssets(output.amount);
2487
+ const assets = outputValue.getPolicyAssets(policyId2);
2488
+ return output.address === address && assets.length > 0;
2489
+ }) || [];
2490
+ return this;
2491
+ };
2492
+ /**
2493
+ * Filter outputs by address and unit
2494
+ * @param address The address to filter by
2495
+ * @param unit The unit to filter by
2496
+ * @returns The TxTester instance for chaining
2497
+ */
2498
+ outputsAtWith = (address, unit) => {
2499
+ this.outputsEvaluating = this.txBody.outputs?.filter((output) => {
2500
+ const outputValue = MeshValue.fromAssets(output.amount);
2501
+ const quantity = outputValue.get(unit);
2502
+ return output.address === address && quantity > 0;
2503
+ }) || [];
2504
+ return this;
2505
+ };
2506
+ /**
2507
+ * Check if outputs contain the expected value.
2508
+ * *Reminder - It must be called after filtering methods for outputs*
2509
+ * @param expectedValue The expected value
2510
+ * @returns The TxTester instance for chaining
2511
+ */
2512
+ outputsValue = (expectedValue) => {
2513
+ let value2 = new MeshValue();
2514
+ this.outputsEvaluating.forEach((output) => {
2515
+ value2.addAssets(output.amount);
2516
+ });
2517
+ const isValueCorrect = value2.eq(expectedValue);
2518
+ if (!isValueCorrect) {
2519
+ this.addTrace(
2520
+ "outputsValue",
2521
+ `tx outputs ${JSON.stringify(this.outputsEvaluating)} have value ${JSON.stringify(value2)}, expected ${JSON.stringify(expectedValue)}`
2522
+ );
2523
+ }
2524
+ return this;
2525
+ };
2526
+ /**
2527
+ * Check if outputs contain a specific inline datum.
2528
+ * *Reminder - It must be called after filtering methods for outputs*
2529
+ * @param datumCbor The datum CBOR to check
2530
+ * @returns The TxTester instance for chaining
2531
+ */
2532
+ outputsInlineDatumExist = (datumCbor) => {
2533
+ const outputsWithInlineDatum = this.outputsEvaluating.filter((output) => {
2534
+ if (output.datum && output.datum.type === "Inline") {
2535
+ return output.datum.data.content === datumCbor;
2536
+ }
2537
+ return false;
2538
+ });
2539
+ if (outputsWithInlineDatum.length === 0) {
2540
+ this.addTrace(
2541
+ "outputs_inline_datum_exist",
2542
+ `No outputs with inline datum matching: ${datumCbor}`
2543
+ );
2544
+ }
2545
+ return this;
2546
+ };
2547
+ };
2548
+ function keySignedLogic(requiredSignatures, keyHash) {
2549
+ return requiredSignatures?.some((signatory) => signatory === keyHash) || false;
2550
+ }
2551
+ function tokenMintedLogic(mints, policyId2, assetName2, quantity) {
2552
+ return mints?.some((token) => {
2553
+ return token.policyId === policyId2 && token.mintValue.findIndex(
2554
+ (m) => m.assetName === assetName2 && BigInt(m.amount) === BigInt(quantity)
2555
+ ) >= 0;
2556
+ }) || false;
2557
+ }
2558
+
2061
2559
  // src/index.ts
2062
2560
  var import_bip39 = require("bip39");
2063
2561
  // Annotate the CommonJS export names for ESM import in node:
@@ -2084,6 +2582,7 @@ var import_bip39 = require("bip39");
2084
2582
  SUPPORTED_OGMIOS_LINKS,
2085
2583
  SUPPORTED_TOKENS,
2086
2584
  SUPPORTED_WALLETS,
2585
+ TxTester,
2087
2586
  UtxoSelection,
2088
2587
  assetClass,
2089
2588
  assetName,
@@ -2117,6 +2616,7 @@ var import_bip39 = require("bip39");
2117
2616
  isNetwork,
2118
2617
  jsonProofToPlutusData,
2119
2618
  keepRelevant,
2619
+ keySignedLogic,
2120
2620
  largestFirst,
2121
2621
  largestFirstMultiAsset,
2122
2622
  list,
@@ -2172,11 +2672,13 @@ var import_bip39 = require("bip39");
2172
2672
  stringToHex,
2173
2673
  toBytes,
2174
2674
  toUTF8,
2675
+ tokenMintedLogic,
2175
2676
  tokenName,
2176
2677
  tuple,
2177
2678
  txInToUtxo,
2178
2679
  txOutRef,
2179
2680
  unixTimeToEnclosingSlot,
2681
+ validityRangeFromObj,
2180
2682
  validityRangeToObj,
2181
2683
  value,
2182
2684
  verificationKey