@helios-lang/contract-utils 0.1.20 → 0.1.24

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 (104) hide show
  1. package/examples/multi-validator/README.md +13 -0
  2. package/examples/multi-validator/contract.js +28 -0
  3. package/examples/{spending → multi-validator}/index.d.ts +3 -3
  4. package/examples/multi-validator/index.js +27 -0
  5. package/examples/multi-validator/minting.hl +5 -0
  6. package/examples/{spending → multi-validator}/package-lock.json +6 -15
  7. package/examples/{spending → multi-validator}/package.json +0 -1
  8. package/examples/multi-validator/spending.hl +18 -0
  9. package/examples/multi-validator/utils.hl +9 -0
  10. package/package.json +7 -6
  11. package/src/{runtime → cast}/Cast.js +31 -8
  12. package/src/cast/index.js +12 -0
  13. package/src/codegen/LoadedModule.js +9 -0
  14. package/src/codegen/{TypescriptWriter.js → LoadedScriptsWriter.js} +149 -108
  15. package/src/codegen/LoadedValidator.js +23 -0
  16. package/src/codegen/{Module.js → TypeCheckedModule.js} +3 -3
  17. package/src/codegen/{Validator.js → TypeCheckedValidator.js} +5 -8
  18. package/src/codegen/TypeSchema.js +6 -2
  19. package/src/codegen/index.js +5 -4
  20. package/src/compiler/CompilerLib.js +51 -0
  21. package/src/{lib/Libg_v0_16.js → compiler/CompilerLib_v0_16.js} +244 -255
  22. package/src/compiler/index.js +6 -0
  23. package/src/compiler/ops.js +137 -0
  24. package/src/context/ContractContext.js +78 -0
  25. package/src/context/ContractContextBuilder.js +69 -0
  26. package/src/context/DagCompiler.js +229 -0
  27. package/src/context/index.js +1 -0
  28. package/src/hl2ts.js +116 -104
  29. package/src/index.js +12 -1
  30. package/types/cast/Cast.d.ts +32 -0
  31. package/types/cast/Cast.d.ts.map +1 -0
  32. package/types/cast/PermissiveType.d.ts +3 -0
  33. package/types/cast/PermissiveType.d.ts.map +1 -0
  34. package/types/cast/StrictType.d.ts +3 -0
  35. package/types/cast/StrictType.d.ts.map +1 -0
  36. package/types/cast/index.d.ts +5 -0
  37. package/types/cast/index.d.ts.map +1 -0
  38. package/types/codegen/LoadedModule.d.ts +6 -0
  39. package/types/codegen/LoadedModule.d.ts.map +1 -0
  40. package/types/codegen/LoadedScriptsWriter.d.ts +57 -0
  41. package/types/codegen/LoadedScriptsWriter.d.ts.map +1 -0
  42. package/types/codegen/LoadedValidator.d.ts +16 -0
  43. package/types/codegen/LoadedValidator.d.ts.map +1 -0
  44. package/types/codegen/TypeCheckedModule.d.ts +11 -0
  45. package/types/codegen/TypeCheckedModule.d.ts.map +1 -0
  46. package/types/codegen/TypeCheckedValidator.d.ts +8 -0
  47. package/types/codegen/TypeCheckedValidator.d.ts.map +1 -0
  48. package/types/codegen/TypeSchema.d.ts +10 -0
  49. package/types/codegen/TypeSchema.d.ts.map +1 -1
  50. package/types/codegen/TypescriptWriter.d.ts +4 -4
  51. package/types/codegen/Validator.d.ts +1 -1
  52. package/types/codegen/index.d.ts +5 -4
  53. package/types/codegen/index.d.ts.map +1 -1
  54. package/types/compiler/CompilerLib.d.ts +45 -0
  55. package/types/compiler/CompilerLib.d.ts.map +1 -0
  56. package/types/compiler/CompilerLib_v0_16.d.ts +271 -0
  57. package/types/compiler/CompilerLib_v0_16.d.ts.map +1 -0
  58. package/types/compiler/index.d.ts +4 -0
  59. package/types/compiler/index.d.ts.map +1 -0
  60. package/types/compiler/ops.d.ts +24 -0
  61. package/types/compiler/ops.d.ts.map +1 -0
  62. package/types/context/ContractContext.d.ts +23 -0
  63. package/types/context/ContractContext.d.ts.map +1 -0
  64. package/types/context/ContractContextBuilder.d.ts +53 -0
  65. package/types/context/ContractContextBuilder.d.ts.map +1 -0
  66. package/types/context/DagCompiler.d.ts +64 -0
  67. package/types/context/DagCompiler.d.ts.map +1 -0
  68. package/types/context/index.d.ts +2 -0
  69. package/types/context/index.d.ts.map +1 -0
  70. package/types/hl2ts.d.ts +9 -4
  71. package/types/hl2ts.d.ts.map +1 -1
  72. package/types/index.d.ts +4 -1
  73. package/types/index.d.ts.map +1 -1
  74. package/types/lib/Lib.d.ts +13 -71
  75. package/types/lib/Lib.d.ts.map +1 -1
  76. package/types/lib/Libg_v0_16.d.ts +53 -52
  77. package/types/lib/Libg_v0_16.d.ts.map +1 -1
  78. package/types/lib/index.d.ts +0 -1
  79. package/types/lib/index.d.ts.map +1 -1
  80. package/types/lib/load.d.ts +1 -7
  81. package/types/lib/load.d.ts.map +1 -1
  82. package/types/runtime/ContractContext.d.ts +22 -43
  83. package/types/runtime/ContractContext.d.ts.map +1 -1
  84. package/types/runtime/ContractContextBuilder.d.ts +15 -123
  85. package/types/runtime/ContractContextBuilder.d.ts.map +1 -1
  86. package/types/runtime/DagCompiler.d.ts +64 -0
  87. package/types/runtime/DagCompiler.d.ts.map +1 -0
  88. package/types/runtime/PermissiveType.d.ts +1 -1
  89. package/types/runtime/StrictType.d.ts +1 -1
  90. package/types/runtime/index.d.ts +0 -2
  91. package/examples/spending/contract.js +0 -16
  92. package/examples/spending/index.js +0 -27
  93. package/examples/spending/minting.hl +0 -5
  94. package/examples/spending/spending.hl +0 -17
  95. package/examples/spending/utils.hl +0 -5
  96. package/src/codegen/Writer.js +0 -37
  97. package/src/lib/Lib.js +0 -56
  98. package/src/lib/index.js +0 -6
  99. package/src/lib/load.js +0 -26
  100. package/src/runtime/ContractContext.js +0 -35
  101. package/src/runtime/ContractContextBuilder.js +0 -340
  102. package/src/runtime/index.js +0 -3
  103. /package/src/{runtime → cast}/PermissiveType.js +0 -0
  104. /package/src/{runtime → cast}/StrictType.js +0 -0
@@ -0,0 +1,13 @@
1
+ # Codegen multi policy
2
+
3
+ Run `npx hl2ts` to generate Javascript/Typescript equivalents of the `spending.hl` and `minting.hl` validators.
4
+
5
+ Then have a look at `contract.js` to see how these validators can be used within Javascript/Typescript in a type-safe way (ideally using VSCode so you can hover over the types).
6
+
7
+ # Installing compilers
8
+
9
+ If you want to use an older version of Helios (under the @hyperionbt org), you can use the following command.
10
+
11
+ ```
12
+ npm install --save-exact @helios-lang/compiler:npm@hyperionbt/helios@<version>
13
+ ```
@@ -0,0 +1,28 @@
1
+ import { ContractContextBuilder } from "@helios-lang/contract-utils"
2
+ import { Address, AssetClass, TxBuilder } from "@helios-lang/ledger"
3
+ import { match_string, match_string_policy } from "./index.js"
4
+
5
+ export function createApp() {
6
+ const context = ContractContextBuilder.new()
7
+ .with(match_string)
8
+ .with(match_string_policy)
9
+ .build({
10
+ match_string_policy:
11
+ "f7c8a87011f1aec5967dd3cd68b7a2c26135d750867bfd957b4d8967" // expected hash for match_string_policy
12
+ })
13
+
14
+ console.log(context.match_string_policy.toHex())
15
+
16
+ const assetClass = new AssetClass(context.match_string_policy, [])
17
+
18
+ const address = Address.fromHash(context.match_string)
19
+
20
+ let b = new TxBuilder().mint(assetClass, 10, true)
21
+
22
+ let c = b
23
+ .pay(address, 1_000_000n, { hash: { One: { message: "hello" } } })
24
+ // Types from Helios are propagated into Typescript, allowing typesafe conversion of Datums
25
+ .pay(address, 2_000_000n, { hash: { Two: { code: "hello" } } })
26
+ }
27
+
28
+ createApp()
@@ -1,5 +1,5 @@
1
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";
2
+ import { Address, AssetClass, DatumHash, MintingPolicyHash, PubKey, PubKeyHash, SpendingCredential, StakingCredential, StakingHash, StakingValidatorHash, TimeRange, TxId, TxOutputDatum, ValidatorHash, Value } from "@helios-lang/ledger";
3
3
  import { Cast } from "@helios-lang/contract-utils";
4
4
  export const utils: {
5
5
  $name: string
@@ -14,7 +14,7 @@ export const match_string_policy: {
14
14
  $dependencies: []
15
15
  $hashDependencies: []
16
16
  $dependsOnOwnHash: boolean
17
- $Redeemer: Cast<string, string>
17
+ $Redeemer: Cast<boolean, boolean>
18
18
 
19
19
  }
20
20
  export const match_string: {
@@ -22,7 +22,7 @@ export const match_string: {
22
22
  $purpose: "spending"
23
23
  $sourceCode: string
24
24
  $dependencies: [typeof utils]
25
- $hashDependencies: []
25
+ $hashDependencies: [typeof match_string_policy]
26
26
  $dependsOnOwnHash: boolean
27
27
  $Redeemer: Cast<string, string>
28
28
  $Datum: Cast<{One: {message: string}} | {Two: {code: bigint}}, {One: {message: string}} | {Two: {code: bigint | number | string}}>
@@ -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\nconst my_assetclass: AssetClass = AssetClass::new(Scripts::match_string_policy, #)\n\nconst my_hash: ValidatorHash = Scripts::match_string\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: Bool, _) -> Bool {\n redeemer\n}",
12
+ $dependencies: [],
13
+ $hashDependencies: [],
14
+ $dependsOnOwnHash: false,
15
+ $Redeemer: new Cast({"primitiveType":"Bool"}),
16
+
17
+ }
18
+ export const match_string = {
19
+ $name: "match_string",
20
+ $purpose: "spending",
21
+ $sourceCode: "spending match_string\n\nimport { compare, my_assetclass } 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, ctx: ScriptContext) -> Bool {\n compare(datum.switch{d: One => d.message, d: Two => d.code.show()}, redeemer) &&\n ctx.tx.minted.get(my_assetclass) > 0\n}",
22
+ $dependencies: [utils],
23
+ $hashDependencies: [match_string_policy],
24
+ $dependsOnOwnHash: true,
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: Bool, _) -> Bool {
4
+ redeemer
5
+ }
@@ -6,7 +6,6 @@
6
6
  "": {
7
7
  "name": "spending_example",
8
8
  "dependencies": {
9
- "@helios-lang/compiler": "0.16.7-1",
10
9
  "@helios-lang/contract-utils": "file:../..",
11
10
  "@hyperionbt/helios": "^0.16.7"
12
11
  },
@@ -16,14 +15,14 @@
16
15
  },
17
16
  "../..": {
18
17
  "name": "@helios-lang/contract-utils",
19
- "version": "0.1.7",
18
+ "version": "0.1.23",
20
19
  "license": "BSD-3-Clause",
21
20
  "dependencies": {
22
- "@helios-lang/codec-utils": "^0.1.26",
23
- "@helios-lang/compiler-utils": "^0.1.20",
24
- "@helios-lang/ledger": "^0.1.10",
21
+ "@helios-lang/codec-utils": "^0.1.27",
22
+ "@helios-lang/compiler-utils": "^0.1.21",
23
+ "@helios-lang/ledger": "^0.1.21",
25
24
  "@helios-lang/type-utils": "^0.1.8",
26
- "@helios-lang/uplc": "^0.1.21"
25
+ "@helios-lang/uplc": "^0.1.22"
27
26
  },
28
27
  "bin": {
29
28
  "hl2ts": "src/hl2ts.js"
@@ -34,15 +33,7 @@
34
33
  "typescript": "^5.3.2"
35
34
  },
36
35
  "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"
36
+ "@helios-lang/compiler": "*"
46
37
  }
47
38
  },
48
39
  "node_modules/@helios-lang/contract-utils": {
@@ -2,7 +2,6 @@
2
2
  "name": "spending_example",
3
3
  "type": "module",
4
4
  "dependencies": {
5
- "@helios-lang/compiler": "0.16.7-1",
6
5
  "@helios-lang/contract-utils": "file:../..",
7
6
  "@hyperionbt/helios": "^0.16.7"
8
7
  },
@@ -0,0 +1,18 @@
1
+ spending match_string
2
+
3
+ import { compare, my_assetclass } from "./utils.hl"
4
+
5
+ enum Datum {
6
+ One {
7
+ message: String
8
+ }
9
+
10
+ Two {
11
+ code: Int
12
+ }
13
+ }
14
+
15
+ func main(datum: Datum, redeemer: String, ctx: ScriptContext) -> Bool {
16
+ compare(datum.switch{d: One => d.message, d: Two => d.code.show()}, redeemer) &&
17
+ ctx.tx.minted.get(my_assetclass) > 0
18
+ }
@@ -0,0 +1,9 @@
1
+ module utils
2
+
3
+ const my_assetclass: AssetClass = AssetClass::new(Scripts::match_string_policy, #)
4
+
5
+ const my_hash: ValidatorHash = Scripts::match_string
6
+
7
+ func compare(a: String, b: String) -> Bool {
8
+ a == b
9
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helios-lang/contract-utils",
3
- "version": "0.1.20",
3
+ "version": "0.1.24",
4
4
  "description": "Convenience and type-safety utilities for using Helios validators from within Typescript",
5
5
  "main": "src/index.js",
6
6
  "types": "types/index.d.ts",
@@ -9,14 +9,14 @@
9
9
  "hl2ts": "src/hl2ts.js"
10
10
  },
11
11
  "scripts": {
12
- "build": "npm run build:types",
12
+ "build": "npm run prettify && npm run build:types && npm run test:suite",
13
13
  "build:types": "npx tsc -p jsconfig.json --noEmit false --emitDeclarationOnly",
14
- "clean": "find src/ -name *.d.ts* | xargs rm",
14
+ "prepack": "npm run build",
15
15
  "prettify": "npx prettier . --write",
16
16
  "test": "npm run test:pretty && npm run test:types && npm run test:suite",
17
17
  "test:pretty": "npx prettier . --check",
18
18
  "test:suite": "node --test --experimental-test-coverage",
19
- "test:types": "npx tsc -p jsconfig.json --noEmit"
19
+ "test:types": "npm run build:types"
20
20
  },
21
21
  "author": "Christian Schmitz",
22
22
  "license": "BSD-3-Clause",
@@ -35,9 +35,10 @@
35
35
  "@helios-lang/compiler": "*"
36
36
  },
37
37
  "dependencies": {
38
- "@helios-lang/codec-utils": "^0.1.26",
38
+ "@helios-lang/cli-utils": "^0.1.2",
39
+ "@helios-lang/codec-utils": "^0.1.27",
39
40
  "@helios-lang/compiler-utils": "^0.1.21",
40
- "@helios-lang/ledger": "^0.1.20",
41
+ "@helios-lang/ledger": "^0.1.21",
41
42
  "@helios-lang/type-utils": "^0.1.8",
42
43
  "@helios-lang/uplc": "^0.1.22"
43
44
  }
@@ -6,7 +6,6 @@ import {
6
6
  AssetClass,
7
7
  Credential,
8
8
  DatumHash,
9
- DCert,
10
9
  MintingPolicyHash,
11
10
  PubKeyHash,
12
11
  ScriptHash,
@@ -26,7 +25,9 @@ import {
26
25
  IntData,
27
26
  ListData,
28
27
  MapData,
28
+ decodeBoolData,
29
29
  decodeOptionData,
30
+ encodeBoolData,
30
31
  encodeOptionData
31
32
  } from "@helios-lang/uplc"
32
33
 
@@ -36,8 +37,8 @@ import {
36
37
  */
37
38
 
38
39
  /**
39
- * @template [TStrict=UplcData]
40
- * @template [TPermissive=UplcData]
40
+ * @template [TStrict=any]
41
+ * @template [TPermissive=any]
41
42
  */
42
43
  export class Cast {
43
44
  /**
@@ -85,7 +86,7 @@ function schemaToUplc(schema, x) {
85
86
  case "AssetClass":
86
87
  return AssetClass.fromAlike(x).toUplcData()
87
88
  case "Bool":
88
- return new ConstrData(x ? 1 : 0, [])
89
+ return encodeBoolData(x)
89
90
  case "ByteArray":
90
91
  return new ByteArrayData(x)
91
92
  case "Credential":
@@ -186,6 +187,7 @@ function schemaToUplc(schema, x) {
186
187
  }
187
188
 
188
189
  /**
190
+ * This should fail when deviating
189
191
  * @param {TypeSchema} schema
190
192
  * @param {UplcData} data
191
193
  * @returns {any}
@@ -199,7 +201,7 @@ function uplcToSchema(schema, data) {
199
201
  // TODO: should this throw an error?
200
202
  return null
201
203
  case "Bool":
202
- return ConstrData.expect(data).tag == 1
204
+ return decodeBoolData(data, true)
203
205
  case "ByteArray":
204
206
  return ByteArrayData.expect(data).bytes
205
207
  case "Credential":
@@ -261,8 +263,9 @@ function uplcToSchema(schema, data) {
261
263
  ? uplcToSchema(schema.optionSomeType, optionData)
262
264
  : None
263
265
  } else if ("structFieldTypes" in schema) {
266
+ const nExpected = schema.structFieldTypes.length
264
267
  // TODO: Cip-68 support
265
- if (schema.structFieldTypes.length == 1) {
268
+ if (nExpected == 1) {
266
269
  return {
267
270
  [schema.structFieldTypes[0].name]: uplcToSchema(
268
271
  schema.structFieldTypes[0].type,
@@ -270,10 +273,18 @@ function uplcToSchema(schema, data) {
270
273
  )
271
274
  }
272
275
  } else {
276
+ const fields = ListData.expect(data).items
277
+
278
+ if (fields.length != nExpected) {
279
+ throw new Error(
280
+ `expected ${nExpected} fields in struct, got ${fields.length} fields`
281
+ )
282
+ }
283
+
273
284
  return Object.fromEntries(
274
- ListData.expect(data).items.map((item, i) => [
285
+ fields.map((field, i) => [
275
286
  schema.structFieldTypes[i].name,
276
- uplcToSchema(schema.structFieldTypes[i].type, item)
287
+ uplcToSchema(schema.structFieldTypes[i].type, field)
277
288
  ])
278
289
  )
279
290
  }
@@ -282,6 +293,18 @@ function uplcToSchema(schema, data) {
282
293
 
283
294
  const variantSchema = schema.enumVariantTypes[tag]
284
295
 
296
+ if (!variantSchema) {
297
+ throw new Error(`tag ${tag} out of range`)
298
+ }
299
+
300
+ const nExpected = variantSchema.fieldTypes.length
301
+
302
+ if (fields.length != nExpected) {
303
+ throw new Error(
304
+ `expected ${nExpected} fields for variant ${variantSchema.name} (tag ${tag}), got ${fields.length} fields`
305
+ )
306
+ }
307
+
285
308
  return {
286
309
  [variantSchema.name]: Object.fromEntries(
287
310
  fields.map((f, i) => [
@@ -0,0 +1,12 @@
1
+ import { Cast } from "./Cast.js"
2
+ export { Cast }
3
+
4
+ /**
5
+ * @template {Cast} C
6
+ * @typedef {import("./PermissiveType.js").PermissiveType<C>} PermissiveType
7
+ */
8
+
9
+ /**
10
+ * @template {Cast} C
11
+ * @typedef {import("./StrictType.js").StrictType<C>} StrictType
12
+ */
@@ -0,0 +1,9 @@
1
+ export {}
2
+
3
+ /**
4
+ * @typedef {{
5
+ * $name: string
6
+ * $sourceCode: string
7
+ * $dependencies: LoadedModule[]
8
+ * }} LoadedModule
9
+ */
@@ -1,121 +1,36 @@
1
+ import { StringWriter } from "@helios-lang/codec-utils"
1
2
  import { genTypes } from "./TypeSchema.js"
2
- import { Writer } from "./Writer.js"
3
3
 
4
4
  /**
5
- * @typedef {import("./Module.js").Module} Module
6
- * @typedef {import("./Validator.js").Validator} Validator
5
+ * @typedef {import("./TypeCheckedModule.js").TypeCheckedModule} TypeCheckedModule
6
+ * @typedef {import("./TypeCheckedValidator.js").TypeCheckedValidator} TypeCheckedValidator
7
7
  */
8
8
 
9
- export class TypescriptWriter {
10
- constructor() {
11
- this.wjs = new Writer()
12
- this.wdts = new Writer()
13
- }
14
-
9
+ export class LoadedScriptsWriter {
15
10
  /**
16
- * @param {string} js
17
- * @param {string} dts
18
- * @returns {TypescriptWriter}
11
+ * @private
19
12
  */
20
- write(js, dts = "") {
21
- this.wjs.write(js)
22
- this.wdts.write(dts)
23
- return this
13
+ constructor() {
14
+ this.definition = new StringWriter()
15
+ this.declaration = new StringWriter()
16
+ this.combined = new StringWriter()
24
17
  }
25
18
 
26
19
  /**
27
- * @param {string} js
28
- * @param {string} dts
29
- * @returns {TypescriptWriter}
20
+ * Constructs a LoadedScriptsWriter instance and initializes it be writing the header
21
+ * @returns {LoadedScriptsWriter}
30
22
  */
31
- writeLine(js, dts = "") {
32
- if (js != "") {
33
- this.wjs.writeLine(js)
34
- }
23
+ static new() {
24
+ const w = new LoadedScriptsWriter()
35
25
 
36
- if (dts != "") {
37
- this.wdts.writeLine(dts)
38
- }
26
+ w.writeHeaders()
39
27
 
40
- return this
28
+ return w
41
29
  }
42
30
 
43
31
  /**
44
- * @param {Module} m
45
- */
46
- writeModule(m) {
47
- this.write(
48
- `export const ${m.name} = {
49
- $name: "${m.name}",
50
- $purpose: "${m.purpose}",
51
- $sourceCode: ${JSON.stringify(m.sourceCode)},
52
- $dependencies: [${m.moduleDepedencies.join(", ")}],
53
- }
54
- `,
55
- `export const ${m.name}: {
56
- $name: string
57
- $purpose: string
58
- $sourceCode: string
59
- $dependencies: [${m.moduleDepedencies.map((d) => `typeof ${d}`).join(", ")}]
60
- }
61
- `
62
- )
63
- }
64
-
65
- /**
66
- * @param {Validator} v
67
- */
68
- writeValidator(v) {
69
- const redeemerTypes = genTypes(v.Redeemer)
70
- const datumTypes = v.Datum ? genTypes(v.Datum) : undefined
71
-
72
- this.write(
73
- `export const ${v.name} = {
74
- $name: "${v.name}",
75
- $purpose: "${v.purpose}",
76
- $sourceCode: ${JSON.stringify(v.sourceCode)},
77
- $dependencies: [${v.moduleDepedencies.join(", ")}],
78
- $hashDependencies: [${v.hashDependencies.filter((d) => d != v.name).join(", ")}],
79
- $dependsOnOwnHash: ${v.hashDependencies.some((d) => d == v.name)},
80
- $Redeemer: new Cast(${JSON.stringify(v.Redeemer)}),
81
- ${datumTypes ? `$Datum: new Cast(${JSON.stringify(v.Datum)})` : ""}
82
- }
83
- `,
84
- `export const ${v.name}: {
85
- $name: "${v.name}"
86
- $purpose: "${v.purpose}"
87
- $sourceCode: string
88
- $dependencies: [${v.moduleDepedencies.map((d) => `typeof ${d}`).join(", ")}]
89
- $hashDependencies: [${v.hashDependencies
90
- .filter((d) => d != v.name)
91
- .map((d) => `typeof ${d}`)
92
- .join(", ")}]
93
- $dependsOnOwnHash: boolean
94
- $Redeemer: Cast<${redeemerTypes[0]}, ${redeemerTypes[1]}>
95
- ${datumTypes ? `$Datum: Cast<${datumTypes[0]}, ${datumTypes[1]}>` : ""}
96
- }
97
- `
98
- )
99
- }
100
-
101
- writeHeaders() {
102
- this.wjs.writeLine(
103
- 'import { Cast } from "@helios-lang/contract-utils";'
104
- )
105
-
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
- )
115
- }
116
-
117
- /**
118
- * @param {{[name: string]: Module}} ms
32
+ * @param {{[name: string]: TypeCheckedModule}} ms
33
+ * @returns {LoadedScriptsWriter}
119
34
  */
120
35
  writeModules(ms) {
121
36
  /**
@@ -127,7 +42,7 @@ export class TypescriptWriter {
127
42
 
128
43
  while (todo.length > 0) {
129
44
  /**
130
- * @type {Module[]}
45
+ * @type {TypeCheckedModule[]}
131
46
  */
132
47
  let todoNext = []
133
48
 
@@ -145,11 +60,13 @@ export class TypescriptWriter {
145
60
 
146
61
  todo = todoNext
147
62
  }
63
+
64
+ return this
148
65
  }
149
66
 
150
67
  /**
151
- *
152
- * @param {{[name: string]: Validator}} validators
68
+ * @param {{[name: string]: TypeCheckedValidator}} validators
69
+ * @returns {LoadedScriptsWriter}
153
70
  */
154
71
  writeValidators(validators) {
155
72
  /**
@@ -161,7 +78,7 @@ export class TypescriptWriter {
161
78
 
162
79
  while (todo.length > 0) {
163
80
  /**
164
- * @type {Validator[]}
81
+ * @type {TypeCheckedValidator[]}
165
82
  */
166
83
  let todoNext = []
167
84
 
@@ -181,12 +98,136 @@ export class TypescriptWriter {
181
98
 
182
99
  todo = todoNext
183
100
  }
101
+
102
+ return this
184
103
  }
185
104
 
186
105
  /**
187
- * @returns {[string, string]}
106
+ * @returns {[string, string, string]}
188
107
  */
189
108
  finalize() {
190
- return [this.wjs.finalize(), this.wdts.finalize()]
109
+ return [
110
+ this.definition.finalize(),
111
+ this.declaration.finalize(),
112
+ this.combined.finalize()
113
+ ]
114
+ }
115
+
116
+ /**
117
+ * @private
118
+ * @param {string} def
119
+ * @param {string} decl
120
+ * @returns {LoadedScriptsWriter}
121
+ */
122
+ write(def, decl = "") {
123
+ this.definition.write(def)
124
+ this.declaration.write(decl)
125
+
126
+ return this
127
+ }
128
+
129
+ /**
130
+ * @private
131
+ */
132
+ writeHeaders() {
133
+ this.definition.writeLine(
134
+ 'import { Cast } from "@helios-lang/contract-utils";'
135
+ )
136
+ ;[this.declaration, this.combined].forEach((w) => {
137
+ w.writeLine('import type {UplcData} from "@helios-lang/ledger";')
138
+ w.writeLine(
139
+ 'import { Address, AssetClass, DatumHash, MintingPolicyHash, PubKey, PubKeyHash, SpendingCredential, StakingCredential, StakingHash, StakingValidatorHash, TimeRange, TxId, TxOutputDatum, ValidatorHash, Value } from "@helios-lang/ledger";'
140
+ )
141
+ w.writeLine('import { Cast } from "@helios-lang/contract-utils";')
142
+ })
143
+ }
144
+
145
+ /**
146
+ * @private
147
+ * @param {TypeCheckedModule} m
148
+ */
149
+ writeModule(m) {
150
+ this.definition.write(
151
+ `export const ${m.name} = {
152
+ $name: "${m.name}",
153
+ $purpose: "${m.purpose}",
154
+ $sourceCode: ${JSON.stringify(m.sourceCode)},
155
+ $dependencies: [${m.moduleDepedencies.join(", ")}],
156
+ }
157
+ `
158
+ )
159
+
160
+ this.declaration.write(
161
+ `export const ${m.name}: {
162
+ $name: string
163
+ $purpose: string
164
+ $sourceCode: string
165
+ $dependencies: [${m.moduleDepedencies.map((d) => `typeof ${d}`).join(", ")}]
166
+ }
167
+ `
168
+ )
169
+
170
+ this.combined.write(
171
+ `export const ${m.name} = {
172
+ $name: "${m.name}",
173
+ $purpose: "${m.purpose}",
174
+ $sourceCode: ${JSON.stringify(m.sourceCode)} as string,
175
+ $dependencies: [${m.moduleDepedencies.join(", ")}],
176
+ }
177
+ `
178
+ )
179
+ }
180
+
181
+ /**
182
+ * @private
183
+ * @param {TypeCheckedValidator} v
184
+ */
185
+ writeValidator(v) {
186
+ const redeemerTypes = genTypes(v.Redeemer)
187
+ const datumTypes = v.Datum ? genTypes(v.Datum) : undefined
188
+
189
+ this.definition.write(
190
+ `export const ${v.name} = {
191
+ $name: "${v.name}",
192
+ $purpose: "${v.purpose}",
193
+ $sourceCode: ${JSON.stringify(v.sourceCode)},
194
+ $dependencies: [${v.moduleDepedencies.join(", ")}],
195
+ $hashDependencies: [${v.hashDependencies.filter((d) => d != v.name).join(", ")}],
196
+ $dependsOnOwnHash: ${v.hashDependencies.some((d) => d == v.name)},
197
+ $Redeemer: new Cast(${JSON.stringify(v.Redeemer)}),
198
+ ${datumTypes ? `$Datum: new Cast(${JSON.stringify(v.Datum)})` : ""}
199
+ }
200
+ `
201
+ )
202
+ this.declaration.write(
203
+ `export const ${v.name}: {
204
+ $name: "${v.name}"
205
+ $purpose: "${v.purpose}"
206
+ $sourceCode: string
207
+ $dependencies: [${v.moduleDepedencies.map((d) => `typeof ${d}`).join(", ")}]
208
+ $hashDependencies: [${v.hashDependencies
209
+ .filter((d) => d != v.name)
210
+ .map((d) => `typeof ${d}`)
211
+ .join(", ")}]
212
+ $dependsOnOwnHash: boolean
213
+ $Redeemer: Cast<${redeemerTypes[0]}, ${redeemerTypes[1]}>
214
+ ${datumTypes ? `$Datum: Cast<${datumTypes[0]}, ${datumTypes[1]}>` : ""}
215
+ }
216
+ `
217
+ )
218
+
219
+ this.combined.write(
220
+ `export const ${v.name} = {
221
+ $name: "${v.name}",
222
+ $purpose: "${v.purpose}",
223
+ $sourceCode: ${JSON.stringify(v.sourceCode)} as string,
224
+ $dependencies: [${v.moduleDepedencies.join(", ")}],
225
+ $hashDependencies: [${v.hashDependencies.filter((d) => d != v.name).join(", ")}],
226
+ $dependsOnOwnHash: ${v.hashDependencies.some((d) => d == v.name)} as boolean,
227
+ $Redeemer: new Cast<${redeemerTypes[0]}, ${redeemerTypes[1]}>(${JSON.stringify(v.Redeemer)}),
228
+ ${datumTypes ? `$Datum: new Cast<${datumTypes[0]}, ${datumTypes[1]}>(${JSON.stringify(v.Datum)})` : ""}
229
+ }
230
+ `
231
+ )
191
232
  }
192
233
  }