@helios-lang/contract-utils 0.3.10 → 0.3.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helios-lang/contract-utils",
3
- "version": "0.3.10",
3
+ "version": "0.3.12",
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",
@@ -1,8 +1,10 @@
1
1
  import { makeStringWriter } from "@helios-lang/codec-utils"
2
2
  import { expectDefined } from "@helios-lang/type-utils"
3
+ import { collectBuiltinTypes } from "../codegen/TypeSchema.js"
3
4
 
4
5
  /**
5
6
  * @import { StringWriter } from "@helios-lang/codec-utils"
7
+ * @import { TypeSchema } from "@helios-lang/type-utils"
6
8
  * @import { FileSystem } from "../index.js"
7
9
  */
8
10
 
@@ -61,6 +63,17 @@ export class ArtifactWriter {
61
63
  return this
62
64
  }
63
65
 
66
+ /**
67
+ * @param {TypeSchema} schema
68
+ */
69
+ collectAndImportTypes(schema) {
70
+ const internalTypes = collectBuiltinTypes(schema)
71
+
72
+ Array.from(internalTypes.entries()).forEach(([name, from]) => {
73
+ this.addImport(name, from, true)
74
+ })
75
+ }
76
+
64
77
  /**
65
78
  * @param {string} line
66
79
  * @returns {ArtifactWriter}
@@ -45,6 +45,14 @@ export class ChildArtifactWriter extends ArtifactWriter {
45
45
  * @returns {ChildArtifactWriter}
46
46
  */
47
47
  writeProgram(name, program, includeDef) {
48
+ this.writeDeclLine(`export const $programCborHex: string`)
49
+
50
+ if (includeDef) {
51
+ this.writeDefLine(
52
+ `export const $programCborHex = "${bytesToHex(program.toCbor())}"`
53
+ )
54
+ }
55
+
48
56
  if (program.plutusVersion == "PlutusScriptV1") {
49
57
  this.addImport("UplcProgramV1", "@helios-lang/uplc", true)
50
58
  this.writeDeclLine(`export const ${name}: UplcProgramV1`)
@@ -102,7 +110,7 @@ function stringifyProgram(decoderName, program) {
102
110
  const sourceMap = makeUplcSourceMap({ term: program.root })
103
111
 
104
112
  return `/* @__PURE__ */ ${decoderName}(
105
- "${bytesToHex(program.toCbor())}",
113
+ $programCborHex,
106
114
  {${stringifyAlt("decodeUplcProgramV2FromCbor", program.alt)}
107
115
  sourceMap: ${JSON.stringify(sourceMap.toJsonSafe(), undefined, 4).split("\n").join("\n ")}
108
116
  }
@@ -1,11 +1,17 @@
1
+ import { bytesToHex } from "@helios-lang/codec-utils"
2
+ import { expectDefined, isRight } from "@helios-lang/type-utils"
3
+ import { convertFromUplcData } from "../cast/index.js"
1
4
  import {
2
- genFuncType,
3
5
  genUserFuncArgsType,
4
6
  genUserFuncRetType
5
7
  } from "../codegen/LoadedScriptsWriter.js"
8
+ import { genTypes } from "../codegen/TypeSchema.js"
6
9
  import { ChildArtifactWriter } from "./ChildArtifactWriter.js"
7
10
 
8
11
  /**
12
+ * @import { Address, AssetClass } from "@helios-lang/ledger"
13
+ * @import { TypeSchema } from "@helios-lang/type-utils"
14
+ * @import { UplcData, UplcProgram } from "@helios-lang/uplc"
9
15
  * @import { UserFuncProps } from "../index.js"
10
16
  * @import { Artifact } from "./Artifact.js"
11
17
  * @import { FunctionDetails } from "./symbols.js"
@@ -24,7 +30,7 @@ export function writeFunctionArtifact(parent, name, details) {
24
30
 
25
31
  artifact.writeProgram("$program", program, true)
26
32
  artifact.writeProps(props)
27
- artifact.writeEvals(props)
33
+ artifact.writeEvals(program, props)
28
34
 
29
35
  artifact.save()
30
36
 
@@ -49,13 +55,15 @@ export const $props = ${JSON.stringify(props, undefined, 4)}`)
49
55
  }
50
56
 
51
57
  /**
58
+ * @param {UplcProgram} program
52
59
  * @param {UserFuncProps} props
53
60
  */
54
- writeEvals(props) {
61
+ writeEvals(program, props) {
55
62
  const safeArgsType = genUserFuncArgsType(props)
56
63
  const unsafeArgsType = genUserFuncArgsType(props, true)
57
64
  const retType = genUserFuncRetType(props)
58
65
  const unsafeRetType = genUserFuncRetType(props, true)
66
+ const isConst = safeArgsType == "{}"
59
67
 
60
68
  this.addImport("UplcLogger", "@helios-lang/uplc", true)
61
69
  this.addImport("UplcData", "@helios-lang/uplc", true)
@@ -63,28 +71,190 @@ export const $props = ${JSON.stringify(props, undefined, 4)}`)
63
71
 
64
72
  this.addImport("evalUserFunc", "@helios-lang/contract-utils")
65
73
  .writeDeclLine(
66
- `export function $eval(args${safeArgsType == "{}" ? "?" : ""}: ${safeArgsType}, logOptions?: UplcLogger | undefined): ${retType}`
74
+ `export function $eval(args${isConst ? "?" : ""}: ${safeArgsType}, logOptions?: UplcLogger | undefined): ${retType}`
67
75
  )
68
76
  .writeDefLine(
69
- `export function $eval(args${safeArgsType == "{}" ? " = {}" : ""}, logOptions = undefined) {
77
+ `export function $eval(args${isConst ? " = {}" : ""}, logOptions = undefined) {
70
78
  return evalUserFunc($program, $props, args, logOptions)
71
79
  }`
72
80
  )
73
81
  .addImport("evalUserFuncUnsafe", "@helios-lang/contract-utils")
74
82
  .writeDeclLine(
75
- `export function $evalUnsafe(args${unsafeArgsType == "{}" ? "?" : ""}: ${unsafeArgsType}, logOptions?: UplcLogger | undefined): ${unsafeRetType}`
83
+ `export function $evalUnsafe(args${isConst ? "?" : ""}: ${unsafeArgsType}, logOptions?: UplcLogger | undefined): ${unsafeRetType}`
76
84
  )
77
85
  .writeDefLine(
78
- `export function $evalUnsafe(args${unsafeArgsType == "{}" ? " = {}" : ""}, logOptions = undefined) {
86
+ `export function $evalUnsafe(args${isConst ? " = {}" : ""}, logOptions = undefined) {
79
87
  return evalUserFuncUnsafe($program, $props, args, logOptions)
80
88
  }`
81
89
  )
82
90
  .addImport("profileUserFunc", "@helios-lang/contract-utils")
83
91
  .writeDeclLine(
84
- `export function $profile(args${unsafeArgsType == "{}" ? "?" : ""}: ${unsafeArgsType}, logOptions?: UplcLogger | undefined): CekResult`
92
+ `export function $profile(args${isConst ? "?" : ""}: ${unsafeArgsType}, logOptions?: UplcLogger | undefined): CekResult`
85
93
  )
86
- .writeDefLine(`export function $profile(args${unsafeArgsType == "{}" ? " = {}" : ""}, logOptions = undefined) {
94
+ .writeDefLine(`export function $profile(args${isConst ? " = {}" : ""}, logOptions = undefined) {
87
95
  return profileUserFunc($program, $props, args, logOptions)
88
96
  }`)
97
+
98
+ if (isConst && props.returns) {
99
+ // attempt to evaluate, and add $constData and $constValue
100
+ try {
101
+ const result = program.eval([])
102
+
103
+ if (
104
+ isRight(result.result) &&
105
+ typeof result.result.right != "string" &&
106
+ result.result.right.kind == "data"
107
+ ) {
108
+ const data = result.result.right.value
109
+
110
+ const uplcDataType = expectDefined(
111
+ {
112
+ int: "IntData",
113
+ bytes: "ByteArrayData",
114
+ constr: "ConstrData",
115
+ map: "MapData",
116
+ list: "ListData"
117
+ }[data.kind]
118
+ )
119
+
120
+ this.addImport(uplcDataType, "@helios-lang/uplc", true)
121
+ .writeDeclLine(`export const $constCborHex: string`)
122
+ .writeDefLine(
123
+ `export const $constCborHex = "${bytesToHex(data.toCbor())}"`
124
+ )
125
+ .writeDeclLine(
126
+ `export const $constData: ${uplcDataType}`
127
+ )
128
+ .addImport("decodeUplcData", "@helios-lang/uplc", false)
129
+ .writeDefLine(
130
+ `export const $constData = /* @__PURE__ */ decodeUplcData($constCborHex)`
131
+ )
132
+
133
+ const valueTypeSchema = props.returns
134
+ const valueTypes = genTypes(valueTypeSchema)
135
+ this.collectAndImportTypes(valueTypeSchema)
136
+ this.writeDeclLine(
137
+ `export const $constValue: ${valueTypes[0]}`
138
+ )
139
+
140
+ const value = convertFromUplcData(valueTypeSchema, data, {
141
+ isMainnet: this.isMainnet
142
+ })
143
+ const constValueStr = this.stringifyConstValue(
144
+ valueTypeSchema,
145
+ data,
146
+ value
147
+ )
148
+
149
+ if (constValueStr !== undefined) {
150
+ this.writeDefLine(
151
+ `export const $constValue = ${constValueStr}`
152
+ )
153
+ } else {
154
+ // fallback
155
+ this.addImport(
156
+ "convertFromUplcData",
157
+ "@helios-lang/contract-utils"
158
+ )
159
+ .writeDefLine(`export const $constValue = /* @__PURE__ */ convertFromUplcData(${JSON.stringify(valueTypeSchema)}, $constData, {
160
+ isMainnet: ${this.isMainnet}
161
+ })`)
162
+ }
163
+ }
164
+ } catch (_e) {
165
+ // don't do anything, simply ignore
166
+ }
167
+ }
168
+ }
169
+
170
+ /**
171
+ * @param {TypeSchema} schema
172
+ * @param {UplcData} data
173
+ * @param {any} value
174
+ * @returns {string | undefined}
175
+ */
176
+ stringifyConstValue(schema, data, value) {
177
+ // TODO: it might be more efficient to represent the following directly as a primitive value
178
+ if (schema.kind == "internal" && schema.name == "Address") {
179
+ /**
180
+ * @type {Address}
181
+ */
182
+ const v = value
183
+ if (v.era == "Shelley") {
184
+ this.addImport(
185
+ "makeShelleyAddress",
186
+ "@helios-lang/ledger",
187
+ false
188
+ )
189
+ return `/* @__PURE__ */ makeShelleyAddress("${v.toBech32()}")`
190
+ }
191
+ } else if (schema.kind == "internal" && schema.name == "AssetClass") {
192
+ /**
193
+ * @type {AssetClass}
194
+ */
195
+ const v = value
196
+ this.addImport("parseAssetClass", "@helios-lang/ledger", false)
197
+ return `/* @__PURE__ */ parseAssetClass("${v.toString()}")`
198
+ } else if (schema.kind == "internal" && schema.name == "Bool") {
199
+ /**
200
+ * @type {boolean}
201
+ */
202
+ const v = value
203
+ return v.toString()
204
+ } else if (schema.kind == "internal" && schema.name == "ByteArray") {
205
+ /**
206
+ * @type {number[]}
207
+ */
208
+ const v = value
209
+ return `[${v.map((b) => b.toString()).join(", ")}]`
210
+ } else if (
211
+ schema.kind == "internal" &&
212
+ ["Any", "Data"].includes(schema.name)
213
+ ) {
214
+ return "$constData"
215
+ } else if (
216
+ schema.kind == "internal" &&
217
+ ["Duration", "Int"].includes(schema.name)
218
+ ) {
219
+ /**
220
+ * @type {bigint}
221
+ */
222
+ const v = value
223
+ return `${v.toString()}n`
224
+ } else if (
225
+ schema.kind == "internal" &&
226
+ [
227
+ "MintingPolicyHash",
228
+ "PubKeyHash",
229
+ "StakingValidatorHash",
230
+ "TxId",
231
+ "ValidatorHash"
232
+ ].includes(schema.name)
233
+ ) {
234
+ /**
235
+ * @type {{bytes: number[]}}
236
+ */
237
+ const v = value
238
+ const makerFunc = `make${schema.name}`
239
+ this.addImport(makerFunc, "@helios-lang/ledger", false)
240
+ return `/* @__PURE__ */ ${makerFunc}("${bytesToHex(v.bytes)}")`
241
+ } else if (
242
+ schema.kind == "internal" &&
243
+ ["Real", "Time"].includes(schema.name)
244
+ ) {
245
+ /**
246
+ * @type {number}
247
+ */
248
+ const v = value
249
+ return v.toString()
250
+ } else if (schema.kind == "internal" && schema.name == "String") {
251
+ /**
252
+ * @type {string}
253
+ */
254
+ const v = value
255
+ return `"${v.toString()}"`
256
+ }
257
+
258
+ return undefined
89
259
  }
90
260
  }
@@ -1,4 +1,4 @@
1
- import { collectBuiltinTypes, genTypes } from "../codegen/TypeSchema.js"
1
+ import { genTypes } from "../codegen/TypeSchema.js"
2
2
  import { ChildArtifactWriter } from "./ChildArtifactWriter.js"
3
3
  import { writeFunctionArtifact } from "./FunctionArtifact.js"
4
4
 
@@ -73,11 +73,7 @@ export const $schema = ${JSON.stringify(schema, undefined, 4)}`
73
73
  this.writeDeclLine(`export type $StrictType = ${types[0]}`)
74
74
  this.writeDeclLine(`export type $PermissiveType = ${types[1]}`)
75
75
 
76
- const internalTypes = collectBuiltinTypes(schema)
77
-
78
- Array.from(internalTypes.entries()).forEach(([name, from]) => {
79
- this.addImport(name, from, true)
80
- })
76
+ this.collectAndImportTypes(schema)
81
77
  }
82
78
 
83
79
  writeConverters() {
@@ -206,9 +206,11 @@ class ValdiatorArtifact extends ModuleArtifact {
206
206
  super.writeAggregateExport(name)
207
207
 
208
208
  if (name == "main") {
209
- this.writeDefLine(
210
- `import { $program } from "./${name}/index.js"`
211
- ).writeDefLine(`export { $program }`)
209
+ this.writeDefLine(`import { $program } from "./${name}/index.js"`)
210
+ .writeDefLine(`export { $program }`)
211
+ .writeDefLine(
212
+ `export { $programCborHex } from "./${name}/index.js"`
213
+ )
212
214
  this.hasMainFunction = true
213
215
  }
214
216
 
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * @import { StringWriter } from "@helios-lang/codec-utils"
3
+ * @import { TypeSchema } from "@helios-lang/type-utils"
3
4
  * @import { FileSystem } from "../index.js"
4
5
  */
5
6
  export class ArtifactWriter {
@@ -40,6 +41,10 @@ export class ArtifactWriter {
40
41
  * @returns {ArtifactWriter}
41
42
  */
42
43
  addImport(name: string, from: string, isType?: boolean): ArtifactWriter;
44
+ /**
45
+ * @param {TypeSchema} schema
46
+ */
47
+ collectAndImportTypes(schema: TypeSchema): void;
43
48
  /**
44
49
  * @param {string} line
45
50
  * @returns {ArtifactWriter}
@@ -61,4 +66,5 @@ export class ArtifactWriter {
61
66
  save(): void;
62
67
  }
63
68
  import type { FileSystem } from "../index.js";
69
+ import type { TypeSchema } from "@helios-lang/type-utils";
64
70
  //# sourceMappingURL=ArtifactWriter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ArtifactWriter.d.ts","sourceRoot":"","sources":["../../src/artifacts/ArtifactWriter.js"],"names":[],"mappings":"AAGA;;;GAGG;AAEH;IA+BI;;;OAGG;IACH,gBAHW,UAAU,OACV,MAAM,EAShB;IAzCD;;;OAGG;IACH,aAFU,UAAU,CAElB;IAEF;;;OAGG;IACH,cAFU,MAAM,CAEb;IAEH;;;OAGG;IACH,aAAI;IAEJ;;;OAGG;IACH,YAAG;IAEH;;;OAGG;IACH,gBAAO;IAeP;;;;;OAKG;IACH,gBALW,MAAM,QACN,MAAM,WACN,OAAO,GACL,cAAc,CAK1B;IAED;;;OAGG;IACH,oBAHW,MAAM,GACJ,cAAc,CAK1B;IAED;;;OAGG;IACH,mBAHW,MAAM,GACJ,cAAc,CAK1B;IAED;;;OAGG;IACH,2BAHW,MAAM,GACJ,cAAc,CAM1B;IAED;;OAEG;IACH,aA8DC;CACJ;gCAxJ8B,aAAa"}
1
+ {"version":3,"file":"ArtifactWriter.d.ts","sourceRoot":"","sources":["../../src/artifacts/ArtifactWriter.js"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH;IA+BI;;;OAGG;IACH,gBAHW,UAAU,OACV,MAAM,EAShB;IAzCD;;;OAGG;IACH,aAFU,UAAU,CAElB;IAEF;;;OAGG;IACH,cAFU,MAAM,CAEb;IAEH;;;OAGG;IACH,aAAI;IAEJ;;;OAGG;IACH,YAAG;IAEH;;;OAGG;IACH,gBAAO;IAeP;;;;;OAKG;IACH,gBALW,MAAM,QACN,MAAM,WACN,OAAO,GACL,cAAc,CAK1B;IAED;;OAEG;IACH,8BAFW,UAAU,QAQpB;IAED;;;OAGG;IACH,oBAHW,MAAM,GACJ,cAAc,CAK1B;IAED;;;OAGG;IACH,mBAHW,MAAM,GACJ,cAAc,CAK1B;IAED;;;OAGG;IACH,2BAHW,MAAM,GACJ,cAAc,CAM1B;IAED;;OAEG;IACH,aA8DC;CACJ;gCAnK8B,aAAa;gCADb,yBAAyB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ChildArtifactWriter.d.ts","sourceRoot":"","sources":["../../src/artifacts/ChildArtifactWriter.js"],"names":[],"mappings":"AAIA;;;GAGG;AAEH;IAaI;;;OAGG;IACH,oBAHW,QAAQ,QACR,MAAM,EAOhB;IArBD;;;OAGG;IACH,iBAFU,QAAQ,CAEZ;IAEN;;;OAGG;IACH,eAFU,MAAM,CAEZ;IAaJ;;OAEG;IACH,iBAFU,OAAO,CAIhB;IAED;;;;;OAKG;IACH,mBALW,MAAM,WACN,WAAW,cACX,OAAO,GACL,mBAAmB,CA+C/B;CACJ;+BA1F8B,qBAAqB;8BAIvB,eAAe;iCADZ,mBAAmB"}
1
+ {"version":3,"file":"ChildArtifactWriter.d.ts","sourceRoot":"","sources":["../../src/artifacts/ChildArtifactWriter.js"],"names":[],"mappings":"AAIA;;;GAGG;AAEH;IAaI;;;OAGG;IACH,oBAHW,QAAQ,QACR,MAAM,EAOhB;IArBD;;;OAGG;IACH,iBAFU,QAAQ,CAEZ;IAEN;;;OAGG;IACH,eAFU,MAAM,CAEZ;IAaJ;;OAEG;IACH,iBAFU,OAAO,CAIhB;IAED;;;;;OAKG;IACH,mBALW,MAAM,WACN,WAAW,cACX,OAAO,GACL,mBAAmB,CAuD/B;CACJ;+BAlG8B,qBAAqB;8BAIvB,eAAe;iCADZ,mBAAmB"}
@@ -1,4 +1,7 @@
1
1
  /**
2
+ * @import { Address, AssetClass } from "@helios-lang/ledger"
3
+ * @import { TypeSchema } from "@helios-lang/type-utils"
4
+ * @import { UplcData, UplcProgram } from "@helios-lang/uplc"
2
5
  * @import { UserFuncProps } from "../index.js"
3
6
  * @import { Artifact } from "./Artifact.js"
4
7
  * @import { FunctionDetails } from "./symbols.js"
@@ -1 +1 @@
1
- {"version":3,"file":"FunctionArtifact.d.ts","sourceRoot":"","sources":["../../src/artifacts/FunctionArtifact.js"],"names":[],"mappings":"AAOA;;;;GAIG;AAEH;;;;GAIG;AACH,8CAJW,QAAQ,QACR,MAAM,WACN,eAAe,QAezB;8BAtB4B,eAAe;qCACR,cAAc"}
1
+ {"version":3,"file":"FunctionArtifact.d.ts","sourceRoot":"","sources":["../../src/artifacts/FunctionArtifact.js"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AAEH;;;;GAIG;AACH,8CAJW,QAAQ,QACR,MAAM,WACN,eAAe,QAezB;8BAtB4B,eAAe;qCACR,cAAc"}