@helios-lang/contract-utils 0.1.6 → 0.1.8

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.
Files changed (62) hide show
  1. package/examples/spending/contract.js +16 -0
  2. package/examples/spending/index.d.ts +29 -0
  3. package/examples/spending/index.js +27 -0
  4. package/examples/spending/minting.hl +5 -0
  5. package/examples/spending/package-lock.json +34 -2
  6. package/examples/spending/package.json +5 -0
  7. package/jsconfig.json +16 -0
  8. package/package.json +9 -4
  9. package/src/codegen/TypescriptWriter.js +14 -6
  10. package/src/hl2ts.js +2 -0
  11. package/src/index.js +1 -0
  12. package/src/lib/Lib.js +15 -0
  13. package/src/lib/Libg_v0_16.js +106 -5
  14. package/src/lib/load.js +12 -49
  15. package/src/runtime/Cast.js +9 -6
  16. package/src/runtime/ContractContext.js +35 -0
  17. package/src/runtime/ContractContextBuilder.js +325 -0
  18. package/src/runtime/PermissiveType.js +6 -0
  19. package/src/runtime/StrictType.js +6 -0
  20. package/src/runtime/index.js +3 -0
  21. package/types/codegen/Module.d.ts +24 -0
  22. package/types/codegen/Module.d.ts.map +1 -0
  23. package/types/codegen/TypeSchema.d.ts +54 -0
  24. package/types/codegen/TypeSchema.d.ts.map +1 -0
  25. package/types/codegen/TypescriptWriter.d.ts +50 -0
  26. package/types/codegen/TypescriptWriter.d.ts.map +1 -0
  27. package/types/codegen/Validator.d.ts +22 -0
  28. package/types/codegen/Validator.d.ts.map +1 -0
  29. package/types/codegen/Writer.d.ts +23 -0
  30. package/types/codegen/Writer.d.ts.map +1 -0
  31. package/types/codegen/index.d.ts +6 -0
  32. package/types/codegen/index.d.ts.map +1 -0
  33. package/types/hl2ts.d.ts +6 -0
  34. package/types/hl2ts.d.ts.map +1 -0
  35. package/types/index.d.ts +2 -0
  36. package/types/index.d.ts.map +1 -0
  37. package/types/lib/Lib.d.ts +79 -0
  38. package/types/lib/Lib.d.ts.map +1 -0
  39. package/types/lib/Libg_v0_16.d.ts +233 -0
  40. package/types/lib/Libg_v0_16.d.ts.map +1 -0
  41. package/types/lib/index.d.ts +2 -0
  42. package/types/lib/index.d.ts.map +1 -0
  43. package/types/lib/load.d.ts +9 -0
  44. package/types/lib/load.d.ts.map +1 -0
  45. package/types/runtime/Cast.d.ts +32 -0
  46. package/types/runtime/Cast.d.ts.map +1 -0
  47. package/types/runtime/ContractContext.d.ts +44 -0
  48. package/types/runtime/ContractContext.d.ts.map +1 -0
  49. package/types/runtime/ContractContextBuilder.d.ts +133 -0
  50. package/types/runtime/ContractContextBuilder.d.ts.map +1 -0
  51. package/types/runtime/PermissiveType.d.ts +3 -0
  52. package/types/runtime/PermissiveType.d.ts.map +1 -0
  53. package/types/runtime/StrictType.d.ts +3 -0
  54. package/types/runtime/StrictType.d.ts.map +1 -0
  55. package/types/runtime/index.d.ts +4 -0
  56. package/types/runtime/index.d.ts.map +1 -0
  57. package/examples/spending/app.js +0 -13
  58. package/examples/spending/output.d.ts +0 -18
  59. package/examples/spending/output2.d.ts +0 -24
  60. package/examples/spending/output2.js +0 -34
  61. package/examples/spending/specialized.js +0 -6
  62. package/examples/spending/unspecialized.js +0 -18
@@ -0,0 +1,16 @@
1
+ import { ContractContextBuilder } from "@helios-lang/contract-utils"
2
+ import { Address, TxBuilder } from "@helios-lang/ledger"
3
+ import { match_string, match_string_policy } from "./index.js"
4
+
5
+ const context = ContractContextBuilder.new()
6
+ .with(match_string)
7
+ .with(match_string_policy)
8
+ .build()
9
+
10
+ console.log(context.match_string_policy.toHex())
11
+
12
+ const address = Address.fromHash(context.match_string)
13
+
14
+ const b = new TxBuilder()
15
+ .mint(context.match_string_policy, [["", 10]], "hello")
16
+ .pay(address, 0n, { hash: { One: { message: "hello" } } })
@@ -0,0 +1,29 @@
1
+ import type {UplcData} from "@helios-lang/ledger";
2
+ import { Address, AssetClass, Credential, DatumHash, MintingPolicyHash, PubKeyHash, StakingCredential, StakingHash, StakingValidatorHash, TimeRange, TxId, TxOutputDatum, ValidatorHash, Value} from "@helios-lang/ledger";
3
+ import { Cast } from "@helios-lang/contract-utils";
4
+ export const utils: {
5
+ $name: string
6
+ $purpose: string
7
+ $sourceCode: string
8
+ $dependencies: []
9
+ }
10
+ export const match_string_policy: {
11
+ $name: "match_string_policy"
12
+ $purpose: "minting"
13
+ $sourceCode: string
14
+ $dependencies: []
15
+ $hashDependencies: []
16
+ $dependsOnOwnHash: boolean
17
+ $Redeemer: Cast<string, string>
18
+
19
+ }
20
+ export const match_string: {
21
+ $name: "match_string"
22
+ $purpose: "spending"
23
+ $sourceCode: string
24
+ $dependencies: [typeof utils]
25
+ $hashDependencies: []
26
+ $dependsOnOwnHash: boolean
27
+ $Redeemer: Cast<string, string>
28
+ $Datum: Cast<{One: {message: string}} | {Two: {code: bigint}}, {One: {message: string}} | {Two: {code: bigint | number | string}}>
29
+ }
@@ -0,0 +1,27 @@
1
+ import { Cast } from "@helios-lang/contract-utils";
2
+ export const utils = {
3
+ $name: "utils",
4
+ $purpose: "module",
5
+ $sourceCode: "module utils\n\nfunc compare(a: String, b: String) -> Bool {\n a == b\n}",
6
+ $dependencies: [],
7
+ }
8
+ export const match_string_policy = {
9
+ $name: "match_string_policy",
10
+ $purpose: "minting",
11
+ $sourceCode: "minting match_string_policy\n\nfunc main(redeemer: String, _) -> Bool {\n redeemer == \"Hello\"\n}",
12
+ $dependencies: [],
13
+ $hashDependencies: [],
14
+ $dependsOnOwnHash: false,
15
+ $Redeemer: new Cast({"primitiveType":"String"}),
16
+
17
+ }
18
+ export const match_string = {
19
+ $name: "match_string",
20
+ $purpose: "spending",
21
+ $sourceCode: "spending match_string\n\nimport { compare } from utils\n\nenum Datum {\n One {\n message: String\n }\n\n Two {\n code: Int\n }\n}\n\nfunc main(datum: Datum, redeemer: String, _) -> Bool {\n compare(datum.switch{d: One => d.message, d: Two => d.code.show()}, redeemer)\n}",
22
+ $dependencies: [utils],
23
+ $hashDependencies: [],
24
+ $dependsOnOwnHash: false,
25
+ $Redeemer: new Cast({"primitiveType":"String"}),
26
+ $Datum: new Cast({"enumVariantTypes":[{"name":"One","fieldTypes":[{"name":"message","type":{"primitiveType":"String"}}]},{"name":"Two","fieldTypes":[{"name":"code","type":{"primitiveType":"Int"}}]}]})
27
+ }
@@ -0,0 +1,5 @@
1
+ minting match_string_policy
2
+
3
+ func main(redeemer: String, _) -> Bool {
4
+ redeemer == "Hello"
5
+ }
@@ -6,16 +6,24 @@
6
6
  "": {
7
7
  "name": "spending_example",
8
8
  "dependencies": {
9
+ "@helios-lang/compiler": "0.16.7-1",
9
10
  "@helios-lang/contract-utils": "file:../..",
10
11
  "@hyperionbt/helios": "^0.16.7"
12
+ },
13
+ "devDependencies": {
14
+ "typescript": "^5.4.3"
11
15
  }
12
16
  },
13
17
  "../..": {
14
18
  "name": "@helios-lang/contract-utils",
15
- "version": "0.1.1",
19
+ "version": "0.1.7",
16
20
  "license": "BSD-3-Clause",
17
21
  "dependencies": {
18
- "@helios-lang/compiler-utils": "^0.1.2"
22
+ "@helios-lang/codec-utils": "^0.1.26",
23
+ "@helios-lang/compiler-utils": "^0.1.20",
24
+ "@helios-lang/ledger": "^0.1.10",
25
+ "@helios-lang/type-utils": "^0.1.8",
26
+ "@helios-lang/uplc": "^0.1.21"
19
27
  },
20
28
  "bin": {
21
29
  "hl2ts": "src/hl2ts.js"
@@ -24,6 +32,17 @@
24
32
  "@types/node": "^20.11.24",
25
33
  "prettier": "^3.1.0",
26
34
  "typescript": "^5.3.2"
35
+ },
36
+ "peerDependencies": {
37
+ "@helios-lang/compiler": "^0.16.7"
38
+ }
39
+ },
40
+ "node_modules/@helios-lang/compiler": {
41
+ "version": "0.16.7-1",
42
+ "resolved": "https://registry.npmjs.org/@helios-lang/compiler/-/compiler-0.16.7-1.tgz",
43
+ "integrity": "sha512-M6x99ApFUNtNrPucx5IrcTbqHP1yyVQXeaKuQWOICgioSbWMKeogN7Hn2INk6f//DzGaqFZ7Cd1JOtt8zXHE/Q==",
44
+ "dependencies": {
45
+ "@hyperionbt/helios": "0.16.7"
27
46
  }
28
47
  },
29
48
  "node_modules/@helios-lang/contract-utils": {
@@ -34,6 +53,19 @@
34
53
  "version": "0.16.7",
35
54
  "resolved": "https://registry.npmjs.org/@hyperionbt/helios/-/helios-0.16.7.tgz",
36
55
  "integrity": "sha512-ysPaF0OCY0NJa1mc+LXERjH71VDNGUbYrrovKUHJv1v+eS1WJhKmxSHWh9sVa6b+sYoXdKwoCR20UQhzCF5jzA=="
56
+ },
57
+ "node_modules/typescript": {
58
+ "version": "5.4.3",
59
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz",
60
+ "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==",
61
+ "dev": true,
62
+ "bin": {
63
+ "tsc": "bin/tsc",
64
+ "tsserver": "bin/tsserver"
65
+ },
66
+ "engines": {
67
+ "node": ">=14.17"
68
+ }
37
69
  }
38
70
  }
39
71
  }
@@ -1,7 +1,12 @@
1
1
  {
2
2
  "name": "spending_example",
3
+ "type": "module",
3
4
  "dependencies": {
5
+ "@helios-lang/compiler": "0.16.7-1",
4
6
  "@helios-lang/contract-utils": "file:../..",
5
7
  "@hyperionbt/helios": "^0.16.7"
8
+ },
9
+ "devDependencies": {
10
+ "typescript": "^5.4.3"
6
11
  }
7
12
  }
package/jsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "checkJs": true,
4
+ "declaration": true,
5
+ "declarationMap": true,
6
+ "declarationDir": "./types",
7
+ "skipLibCheck": true,
8
+ "noImplicitThis": true,
9
+ "strictNullChecks": true,
10
+ "moduleResolution": "nodenext",
11
+ "module": "nodenext",
12
+ "target": "esnext"
13
+ },
14
+ "exclude": ["node_modules", "**/*.d.ts"],
15
+ "include": ["src/**/*.js", "node_modules/@helios-lang/type-utils"]
16
+ }
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "@helios-lang/contract-utils",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Convenience and type-safety utilities for using Helios validators from within Typescript",
5
5
  "main": "src/index.js",
6
+ "types": "types/index.d.ts",
6
7
  "type": "module",
7
8
  "bin": {
8
9
  "hl2ts": "src/hl2ts.js"
9
10
  },
10
11
  "scripts": {
11
- "build": "npx tsc",
12
+ "build": "npm run build:types",
13
+ "build:types": "npx tsc -p jsconfig.json --noEmit false --emitDeclarationOnly",
12
14
  "clean": "find src/ -name *.d.ts* | xargs rm",
13
15
  "prettify": "npx prettier . --write",
14
16
  "test": "npm run test:pretty && npm run test:types && npm run test:suite",
@@ -32,8 +34,11 @@
32
34
  "dependencies": {
33
35
  "@helios-lang/codec-utils": "^0.1.26",
34
36
  "@helios-lang/compiler-utils": "^0.1.20",
35
- "@helios-lang/ledger": "^0.1.10",
37
+ "@helios-lang/ledger": "^0.1.20",
36
38
  "@helios-lang/type-utils": "^0.1.8",
37
- "@helios-lang/uplc": "^0.1.21"
39
+ "@helios-lang/uplc": "^0.1.22"
40
+ },
41
+ "peerDependencies": {
42
+ "@helios-lang/compiler": "0.16.7-1"
38
43
  }
39
44
  }
@@ -82,8 +82,8 @@ export class TypescriptWriter {
82
82
  }
83
83
  `,
84
84
  `export const ${v.name}: {
85
- $name: string
86
- $purpose: string
85
+ $name: "${v.name}"
86
+ $purpose: "${v.purpose}"
87
87
  $sourceCode: string
88
88
  $dependencies: [${v.moduleDepedencies.map((d) => `typeof ${d}`).join(", ")}]
89
89
  $hashDependencies: [${v.hashDependencies
@@ -99,11 +99,19 @@ export class TypescriptWriter {
99
99
  }
100
100
 
101
101
  writeHeaders() {
102
- this.wjs.writeLine("import { Cast } from \"@helios-lang/contract-utils\";")
102
+ this.wjs.writeLine(
103
+ 'import { Cast } from "@helios-lang/contract-utils";'
104
+ )
103
105
 
104
- this.wdts.writeLine("import type {UplcData} from \"@helios-lang/ledger\";")
105
- this.wdts.writeLine("import { Address, AssetClass, Credential, DatumHash, MintingPolicyHash, PubKeyHash, StakingCredential, StakingHash, StakingValidatorHash, TimeRange, TxId, TxOutputDatum, ValidatorHash, Value} from \"@helios-lang/ledger\";")
106
- this.wdts.writeLine("import { Cast } from \"@helios-lang/contract-utils\";")
106
+ this.wdts.writeLine(
107
+ 'import type {UplcData} from "@helios-lang/ledger";'
108
+ )
109
+ this.wdts.writeLine(
110
+ 'import { Address, AssetClass, Credential, DatumHash, MintingPolicyHash, PubKeyHash, StakingCredential, StakingHash, StakingValidatorHash, TimeRange, TxId, TxOutputDatum, ValidatorHash, Value} from "@helios-lang/ledger";'
111
+ )
112
+ this.wdts.writeLine(
113
+ 'import { Cast } from "@helios-lang/contract-utils";'
114
+ )
107
115
  }
108
116
 
109
117
  /**
package/src/hl2ts.js CHANGED
@@ -26,8 +26,10 @@ async function main() {
26
26
 
27
27
  const w = new TypescriptWriter()
28
28
 
29
+ w.writeHeaders()
29
30
  w.writeModules(modules)
30
31
  w.writeValidators(validators)
32
+
31
33
  const [js, dts] = w.finalize()
32
34
 
33
35
  const jsPath = join(outDir, "index.js")
package/src/index.js CHANGED
@@ -0,0 +1 @@
1
+ export { Cast, ContractContextBuilder } from "./runtime/index.js"
package/src/lib/Lib.js CHANGED
@@ -1,8 +1,23 @@
1
+ /**
2
+ * @typedef {{
3
+ * otherValidators: {[name: string]: {purpose: string, hash: string}},
4
+ * dependsOnOwnHash?: boolean,
5
+ * ownHash?: string,
6
+ * optimize: boolean
7
+ * }} CompileOptions
8
+ */
9
+
10
+ /**
11
+ * @typedef {{
12
+ * cborHex: string
13
+ * }} CompileOutput
14
+ */
1
15
  /**
2
16
  * @typedef {{
3
17
  * version: string
4
18
  * typeCheck: (validators: {[name: string]: SourceDetails}, modules: {[name: string]: SourceDetails}) => ({
5
19
  * modules: {[name: string]: ModuleDetails}, validators: {[name: string]: ValidatorDetails}})
20
+ * compile: (main: string, modules: string[], options: CompileOptions) => CompileOutput
6
21
  * }} Lib
7
22
  */
8
23
 
@@ -1,14 +1,17 @@
1
- /**
2
- * @typedef {import("./Lib.js").Lib} Lib
3
- * @typedef {import("./Lib.js").SourceDetails} SourceDetails
4
- */
5
-
6
1
  /**
7
2
  * @typedef {import("../codegen/index.js").Module} ModuleDetails
8
3
  * @typedef {import("../codegen/index.js").Validator} ValidatorDetails
9
4
  * @typedef {import("../codegen/index.js").TypeSchema} InternalTypeDetails
5
+ * @typedef {import("./Lib.js").CompileOptions} CompileOptions
6
+ * @typedef {import("./Lib.js").CompileOutput} CompileOutput
7
+ * @typedef {import("./Lib.js").Lib} Lib
8
+ * @typedef {import("./Lib.js").SourceDetails} SourceDetails
10
9
  */
11
10
 
11
+ import { bytesToHex } from "@helios-lang/compiler"
12
+ import { readHeader } from "@helios-lang/compiler-utils"
13
+ import { UplcProgramV1 } from "@helios-lang/uplc"
14
+
12
15
  /**
13
16
  * @typedef {{
14
17
  * [name: string]: string[]
@@ -339,4 +342,102 @@ export class Lib_v0_16 {
339
342
  }
340
343
  }
341
344
  }
345
+
346
+ /**
347
+ * @param {string} main
348
+ * @param {string[]} modules
349
+ * @param {CompileOptions} options
350
+ * @returns {CompileOutput}
351
+ */
352
+ compile(main, modules, options) {
353
+ const [purpose, name] = readHeader(main)
354
+ const otherValidators = options.otherValidators ?? {}
355
+ const otherValidatorTypes = Object.fromEntries(
356
+ Object.keys(otherValidators).map((k) => {
357
+ return [k, this.getValidatorType(otherValidators[k].purpose)]
358
+ })
359
+ )
360
+
361
+ const program = this.lib.Program.newInternal(
362
+ main,
363
+ modules,
364
+ otherValidatorTypes,
365
+ {
366
+ allowPosParams: false,
367
+ invertEntryPoint: true
368
+ }
369
+ )
370
+
371
+ /**
372
+ * @type {Map<any, any>}
373
+ */
374
+ const extra = new Map()
375
+ const IR = this.lib.IR
376
+
377
+ if (options.ownHash) {
378
+ const key = `__helios__scripts__${name}`
379
+
380
+ extra.set(key, new IR(`#${options.ownHash}`))
381
+ } else if (options.dependsOnOwnHash) {
382
+ const key = `__helios__scripts__${name}`
383
+ let ir = new IR(`__PARAM_${program.nPosParams - 1}`)
384
+
385
+ switch (purpose) {
386
+ case "spending":
387
+ ir = new IR([
388
+ new IR(
389
+ `__helios__scriptcontext__get_current_validator_hash(`
390
+ ),
391
+ ir,
392
+ new IR(`)()`)
393
+ ])
394
+ break
395
+ case "minting":
396
+ ir = new IR([
397
+ new IR(
398
+ `__helios__scriptcontext__get_current_minting_policy_hash(`
399
+ ),
400
+ ir,
401
+ new IR(`)()`)
402
+ ])
403
+ break
404
+ default:
405
+ throw new Error("unhandled purpose")
406
+ }
407
+
408
+ extra.set(key, ir)
409
+ }
410
+
411
+ for (let other in otherValidators) {
412
+ const key = `__helios__scripts__${other}`
413
+
414
+ extra.set(key, new IR(`#${otherValidators[other]}`))
415
+ }
416
+
417
+ const optimize = options.optimize
418
+ const ir = program.toIR(new this.lib.ToIRContext(optimize), extra)
419
+
420
+ if (program.nPosParams > 0) {
421
+ const irProgram = this.lib.IRParametricProgram.new(
422
+ ir,
423
+ purpose,
424
+ program.nPosParams,
425
+ optimize
426
+ )
427
+
428
+ const cborHex = bytesToHex(irProgram.toUplc().toCbor())
429
+
430
+ return {
431
+ cborHex
432
+ }
433
+ } else {
434
+ const irProgram = this.lib.IRProgram.new(ir, purpose, optimize)
435
+
436
+ const cborHex = bytesToHex(irProgram.toUplc().toCbor())
437
+
438
+ return {
439
+ cborHex
440
+ }
441
+ }
442
+ }
342
443
  }
package/src/lib/load.js CHANGED
@@ -1,5 +1,4 @@
1
- import { existsSync } from "node:fs"
2
- import { dirname, join } from "node:path"
1
+ import * as lib from "@helios-lang/compiler"
3
2
  import { getVersion } from "./Lib.js"
4
3
  import { Lib_v0_16 } from "./Libg_v0_16.js"
5
4
 
@@ -8,54 +7,18 @@ import { Lib_v0_16 } from "./Libg_v0_16.js"
8
7
  */
9
8
 
10
9
  /**
11
- * @returns {string}
10
+ * @returns {Lib}
12
11
  */
13
- function findRootDir() {
14
- let dir = process.cwd()
15
-
16
- while (dir != "/") {
17
- if (existsSync(join(dir, "package.json"))) {
18
- return dir
19
- } else {
20
- dir = dirname(dir)
21
- }
22
- }
23
-
24
- throw new Error("package.json not found")
25
- }
26
-
27
- /**
28
- * @returns {Promise<Lib>}
29
- */
30
- export async function loadLibrary() {
31
- const rootDir = findRootDir()
32
-
33
- const packageNames = ["@hyperionbt/helios/helios.js"]
34
-
35
- for (let packageName of packageNames) {
36
- try {
37
- const lib = await eval(
38
- `import("${rootDir}/node_modules/${packageName}")`
39
- )
40
-
41
- const [major, minor] = getVersion(lib)
42
-
43
- switch (major) {
44
- case 0:
45
- switch (minor) {
46
- case 16:
47
- return new Lib_v0_16(lib)
48
- }
49
- default:
50
- throw new Error(
51
- `compiler version ${lib.VERSION} not supported`
52
- )
12
+ export function loadLibrary() {
13
+ const [major, minor] = getVersion(lib)
14
+
15
+ switch (major) {
16
+ case 0:
17
+ switch (minor) {
18
+ case 16:
19
+ return new Lib_v0_16(lib)
53
20
  }
54
- } catch (_e) {
55
- console.error(_e)
56
- continue
57
- }
21
+ default:
22
+ throw new Error(`compiler version ${lib.VERSION} not supported`)
58
23
  }
59
-
60
- throw new Error("compiler not installed")
61
24
  }
@@ -36,8 +36,8 @@ import {
36
36
  */
37
37
 
38
38
  /**
39
- * @template TStrict
40
- * @template TPermissive
39
+ * @template [TStrict=UplcData]
40
+ * @template [TPermissive=UplcData]
41
41
  */
42
42
  export class Cast {
43
43
  /**
@@ -57,7 +57,7 @@ export class Cast {
57
57
  * @param {UplcData} data
58
58
  * @returns {TStrict}
59
59
  */
60
- fromUplc(data) {
60
+ fromUplcData(data) {
61
61
  return uplcToSchema(this.schema, data)
62
62
  }
63
63
 
@@ -65,7 +65,7 @@ export class Cast {
65
65
  * @param {TPermissive} x
66
66
  * @returns {UplcData}
67
67
  */
68
- toUplc(x) {
68
+ toUplcData(x) {
69
69
  return schemaToUplc(this.schema, x)
70
70
  }
71
71
  }
@@ -167,8 +167,11 @@ function schemaToUplc(schema, x) {
167
167
  const tag = schema.enumVariantTypes.findIndex(
168
168
  (v) => v.name == variantName
169
169
  )
170
- if (tag != -1) {
171
- throw new Error("invalid variant")
170
+
171
+ if (tag == -1) {
172
+ throw new Error(
173
+ `invalid variant ${variantName} (expected: ${schema.enumVariantTypes.map((v) => v.name).join(", ")})`
174
+ )
172
175
  }
173
176
 
174
177
  return new ConstrData(
@@ -0,0 +1,35 @@
1
+ import { ScriptHash } from "@helios-lang/ledger"
2
+ import { UplcProgramV2 } from "@helios-lang/uplc"
3
+ import { Cast } from "./Cast.js"
4
+
5
+ /**
6
+ * @typedef {{
7
+ * $name: string
8
+ * $purpose: string
9
+ * $program: {
10
+ * optimized: UplcProgramV2
11
+ * unoptimized: UplcProgramV2
12
+ * }
13
+ * $hash: ScriptHash
14
+ * $Redeemer: Cast<any, any>
15
+ * $Datum?: Cast<any, any>
16
+ * }} Validator
17
+ */
18
+
19
+ /**
20
+ * @template {{[name: string]: Validator}} T
21
+ */
22
+ export class ContractContext {
23
+ /**
24
+ * @readonly
25
+ * @type {T}
26
+ */
27
+ validators
28
+
29
+ /**
30
+ * @param {T} validators
31
+ */
32
+ constructor(validators) {
33
+ this.validators = validators
34
+ }
35
+ }