@helios-lang/contract-utils 0.2.71 → 0.2.73
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 +10 -9
- package/src/compiler/CompilerLib_v0_17.js +3 -3
- package/src/context/CacheEntry.js +310 -0
- package/src/context/ContractContextBuilder.js +13 -3
- package/src/context/ContractContextCache.js +179 -318
- package/src/context/index.js +1 -1
- package/src/index.js +5 -0
- package/types/cast/Cast.d.ts.map +1 -1
- package/types/cast/UserFunc.d.ts.map +1 -1
- package/types/codegen/LoadedModule.d.ts.map +1 -1
- package/types/codegen/LoadedValidator.d.ts.map +1 -1
- package/types/codegen/TypeCheckedModule.d.ts.map +1 -1
- package/types/codegen/TypeCheckedValidator.d.ts.map +1 -1
- package/types/compiler/CompilerLib.d.ts.map +1 -1
- package/types/compiler/CompilerLib_v0_16.d.ts.map +1 -1
- package/types/compiler/CompilerLib_v0_17.d.ts +2 -3
- package/types/compiler/CompilerLib_v0_17.d.ts.map +1 -1
- package/types/context/CacheEntry.d.ts +117 -0
- package/types/context/CacheEntry.d.ts.map +1 -0
- package/types/context/ContractContext.d.ts.map +1 -1
- package/types/context/ContractContextBuilder.d.ts +2 -1
- package/types/context/ContractContextBuilder.d.ts.map +1 -1
- package/types/context/ContractContextCache.d.ts +68 -94
- package/types/context/ContractContextCache.d.ts.map +1 -1
- package/types/context/DagCompiler.d.ts.map +1 -1
- package/types/context/index.d.ts +1 -1
- package/types/context/index.d.ts.map +1 -1
- package/types/hl2ts.d.ts.map +1 -1
- package/types/index.d.ts +2 -0
- package/types/index.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helios-lang/contract-utils",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.73",
|
|
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",
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"license": "BSD-3-Clause",
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@types/node": "^20.11.24",
|
|
15
|
-
"prettier": "^3.
|
|
16
|
-
"typescript": "^5.
|
|
15
|
+
"prettier": "^3.3.3",
|
|
16
|
+
"typescript": "^5.6.2"
|
|
17
17
|
},
|
|
18
18
|
"prettier": {
|
|
19
19
|
"trailingComma": "none",
|
|
@@ -25,12 +25,13 @@
|
|
|
25
25
|
"@helios-lang/compiler": "*"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@helios-lang/cli-utils": "^0.1.
|
|
29
|
-
"@helios-lang/codec-utils": "^0.1
|
|
30
|
-
"@helios-lang/compiler-utils": "^0.1
|
|
31
|
-
"@helios-lang/
|
|
32
|
-
"@helios-lang/
|
|
33
|
-
"@helios-lang/
|
|
28
|
+
"@helios-lang/cli-utils": "^0.1.10",
|
|
29
|
+
"@helios-lang/codec-utils": "^0.2.1",
|
|
30
|
+
"@helios-lang/compiler-utils": "^0.2.1",
|
|
31
|
+
"@helios-lang/crypto": "0.1.17",
|
|
32
|
+
"@helios-lang/ledger": "^0.5.8",
|
|
33
|
+
"@helios-lang/type-utils": "^0.1.25",
|
|
34
|
+
"@helios-lang/uplc": "^0.6.1"
|
|
34
35
|
},
|
|
35
36
|
"scripts": {
|
|
36
37
|
"build": "pnpm run prettify && pnpm run build:types && pnpm run test:suite",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { bytesToHex } from "@helios-lang/codec-utils"
|
|
2
2
|
import { None } from "@helios-lang/type-utils"
|
|
3
|
-
import {
|
|
3
|
+
import { UplcSourceMap } from "@helios-lang/uplc"
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @typedef {import("@helios-lang/uplc").UplcData} UplcData
|
|
@@ -24,7 +24,7 @@ import { UplcProgramV2, UplcSourceMap } from "@helios-lang/uplc"
|
|
|
24
24
|
* validatorIndices?: Record<string, number>
|
|
25
25
|
* excludeUserFuncs?: Set<string>
|
|
26
26
|
* onCompileUserFunc?: (name: string, uplc: UplcProgramV2I) => void
|
|
27
|
-
* }):
|
|
27
|
+
* }): UplcProgramV2I
|
|
28
28
|
* }} Program
|
|
29
29
|
*/
|
|
30
30
|
|
|
@@ -90,7 +90,7 @@ export class CompilerLib_v0_17 {
|
|
|
90
90
|
const onCompileUserFunc = options.onCompileUserFunc
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
|
-
* @type {
|
|
93
|
+
* @type {UplcProgramV2I}
|
|
94
94
|
*/
|
|
95
95
|
const uplc = program.compile({
|
|
96
96
|
optimize: options.optimize,
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { bytesToHex } from "@helios-lang/codec-utils"
|
|
2
|
+
import {
|
|
3
|
+
MintingPolicyHash,
|
|
4
|
+
ScriptHash,
|
|
5
|
+
StakingValidatorHash,
|
|
6
|
+
ValidatorHash
|
|
7
|
+
} from "@helios-lang/ledger"
|
|
8
|
+
import { None, expectSome } from "@helios-lang/type-utils"
|
|
9
|
+
import { UplcProgramV1, UplcProgramV2, UplcSourceMap } from "@helios-lang/uplc"
|
|
10
|
+
import { Cast } from "../cast/Cast.js"
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {import("@helios-lang/type-utils").TypeSchema} TypeSchema
|
|
14
|
+
* @typedef {import("@helios-lang/uplc").UplcData} UplcData
|
|
15
|
+
* @typedef {import("@helios-lang/uplc").PlutusVersion} PlutusVersion
|
|
16
|
+
* @typedef {import("@helios-lang/uplc").UplcProgram} UplcProgram
|
|
17
|
+
* @typedef {import("@helios-lang/uplc").UplcProgramV1I} UplcProgramV1I
|
|
18
|
+
* @typedef {import("@helios-lang/uplc").UplcProgramV2I} UplcProgramV2I
|
|
19
|
+
* @typedef {import("@helios-lang/uplc").UplcSourceMapJsonSafe} UplcSourceMapJsonSafe
|
|
20
|
+
* @typedef {import("../cast/index.js").CastConfig} CastConfig
|
|
21
|
+
* @typedef {import("../codegen/LoadedModule.js").LoadedModule} LoadedModule
|
|
22
|
+
* @typedef {import("../codegen/LoadedValidator.js").LoadedValidator} LoadedValidator
|
|
23
|
+
* @typedef {import("./ContractContext.js").AnyContractValidatorContext} AnyContractValidatorContext
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @typedef {{
|
|
28
|
+
* debug?: boolean
|
|
29
|
+
* validators: {[name: string]: AnyContractValidatorContext}
|
|
30
|
+
* userFuncs: {[name: string]: UplcProgram}
|
|
31
|
+
* }} CacheEntry
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @typedef {{[name: string]: {
|
|
36
|
+
* purpose: "minting" | "spending" | "staking" | "mixed"
|
|
37
|
+
* bytes: number[]
|
|
38
|
+
* unoptimizedCborHex?: string
|
|
39
|
+
* unoptimizedIr?: string
|
|
40
|
+
* unoptimizedSourceMap?: UplcSourceMapJsonSafe
|
|
41
|
+
* optimizedCborHex: string
|
|
42
|
+
* optimizedIr?: string
|
|
43
|
+
* optimizedSourceMap?: UplcSourceMapJsonSafe
|
|
44
|
+
* plutusVersion: PlutusVersion
|
|
45
|
+
* castConfig: CastConfig
|
|
46
|
+
* datum?: TypeSchema
|
|
47
|
+
* redeemer: TypeSchema
|
|
48
|
+
* }}} CacheEntryValidatorsJson
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @typedef {{[name: string]: {
|
|
53
|
+
* unoptimizedCborHex?: string
|
|
54
|
+
* unoptimizedIr?: string
|
|
55
|
+
* unoptimizedSourceMap?: UplcSourceMapJsonSafe
|
|
56
|
+
* optimizedCborHex: string
|
|
57
|
+
* optimizedIr?: string
|
|
58
|
+
* optimizedSourceMap?: UplcSourceMapJsonSafe
|
|
59
|
+
* plutusVersion: PlutusVersion
|
|
60
|
+
* }}} CacheEntryUserFuncsJson
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @typedef {{
|
|
65
|
+
* debug?: boolean
|
|
66
|
+
* validators: CacheEntryValidatorsJson
|
|
67
|
+
* userFuncs: CacheEntryUserFuncsJson
|
|
68
|
+
* }} CacheEntryJson
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {CacheEntry} entry
|
|
73
|
+
* @returns {CacheEntryJson}
|
|
74
|
+
*/
|
|
75
|
+
export function cacheEntryToJsonSafe(entry) {
|
|
76
|
+
/**
|
|
77
|
+
* @type {CacheEntryValidatorsJson}
|
|
78
|
+
*/
|
|
79
|
+
const resValidators = {}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @type {CacheEntryUserFuncsJson}
|
|
83
|
+
*/
|
|
84
|
+
const resUserFuncs = {}
|
|
85
|
+
|
|
86
|
+
for (let name in entry.validators) {
|
|
87
|
+
const hash = entry.validators[name]
|
|
88
|
+
|
|
89
|
+
const purpose =
|
|
90
|
+
hash instanceof ValidatorHash
|
|
91
|
+
? "spending"
|
|
92
|
+
: hash instanceof MintingPolicyHash
|
|
93
|
+
? "minting"
|
|
94
|
+
: hash instanceof StakingValidatorHash
|
|
95
|
+
? "staking"
|
|
96
|
+
: hash instanceof ScriptHash
|
|
97
|
+
? "mixed"
|
|
98
|
+
: "unknown"
|
|
99
|
+
if (purpose == "unknown") {
|
|
100
|
+
throw new Error("unhandled hash type")
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const redeemer =
|
|
104
|
+
hash.context.redeemer instanceof Cast ? hash.context.redeemer : None
|
|
105
|
+
|
|
106
|
+
if (!redeemer) {
|
|
107
|
+
throw new Error("Redeemer is not a Cast type")
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @type {Option<Cast>}
|
|
112
|
+
*/
|
|
113
|
+
let datum = None
|
|
114
|
+
|
|
115
|
+
if (hash.context.datum && hash.context.datum instanceof Cast) {
|
|
116
|
+
datum = hash.context.datum
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (["spending", "mixed"].includes(purpose) && !datum) {
|
|
120
|
+
throw new Error("Datum is not a Cast type")
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @type {UplcProgramV1I | UplcProgramV2I}
|
|
125
|
+
*/
|
|
126
|
+
const program = hash.context.program
|
|
127
|
+
|
|
128
|
+
resValidators[name] = {
|
|
129
|
+
purpose: purpose,
|
|
130
|
+
bytes: hash.bytes,
|
|
131
|
+
optimizedCborHex: bytesToHex(program.toCbor()),
|
|
132
|
+
unoptimizedCborHex: program.alt
|
|
133
|
+
? bytesToHex(program.alt.toCbor())
|
|
134
|
+
: undefined,
|
|
135
|
+
optimizedIr:
|
|
136
|
+
/** @type {UplcProgramV2I} */ (program).ir ?? undefined,
|
|
137
|
+
unoptimizedIr:
|
|
138
|
+
/** @type {UplcProgramV2I} */ (program).alt?.ir ?? undefined,
|
|
139
|
+
optimizedSourceMap: UplcSourceMap.fromUplcTerm(
|
|
140
|
+
program.root
|
|
141
|
+
).toJsonSafe(),
|
|
142
|
+
unoptimizedSourceMap: program.alt
|
|
143
|
+
? UplcSourceMap.fromUplcTerm(program.alt.root).toJsonSafe()
|
|
144
|
+
: undefined,
|
|
145
|
+
plutusVersion: hash.context.program.plutusVersion,
|
|
146
|
+
castConfig: redeemer.config,
|
|
147
|
+
redeemer: redeemer.schema,
|
|
148
|
+
datum: datum?.schema
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
for (let name in entry.userFuncs) {
|
|
153
|
+
const userFunc = entry.userFuncs[name]
|
|
154
|
+
|
|
155
|
+
resUserFuncs[name] = {
|
|
156
|
+
optimizedCborHex: bytesToHex(userFunc.toCbor()),
|
|
157
|
+
unoptimizedCborHex: /** @type {UplcProgramV2I} */ (userFunc).alt
|
|
158
|
+
? bytesToHex(
|
|
159
|
+
/** @type {UplcProgramV2I} */ (userFunc).alt.toCbor()
|
|
160
|
+
)
|
|
161
|
+
: undefined,
|
|
162
|
+
optimizedIr: userFunc.ir ?? undefined,
|
|
163
|
+
unoptimizedIr: userFunc.alt?.ir ?? undefined,
|
|
164
|
+
optimizedSourceMap: UplcSourceMap.fromUplcTerm(
|
|
165
|
+
userFunc.root
|
|
166
|
+
).toJsonSafe(),
|
|
167
|
+
unoptimizedSourceMap: userFunc.alt
|
|
168
|
+
? UplcSourceMap.fromUplcTerm(userFunc.alt.root).toJsonSafe()
|
|
169
|
+
: undefined,
|
|
170
|
+
plutusVersion: userFunc.plutusVersion
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
debug: entry.debug ?? false,
|
|
176
|
+
validators: resValidators,
|
|
177
|
+
userFuncs: resUserFuncs
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @param {CacheEntryJson} entry
|
|
183
|
+
* @returns {CacheEntry}
|
|
184
|
+
*/
|
|
185
|
+
export function cacheEntryFromJson(entry) {
|
|
186
|
+
/**
|
|
187
|
+
* @type {CacheEntry}
|
|
188
|
+
*/
|
|
189
|
+
const res = {
|
|
190
|
+
debug: entry.debug ?? false,
|
|
191
|
+
validators: {},
|
|
192
|
+
userFuncs: {}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
for (let name in entry.validators) {
|
|
196
|
+
const props = entry.validators[name]
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* @type {UplcProgram}
|
|
200
|
+
*/
|
|
201
|
+
let program =
|
|
202
|
+
props.plutusVersion == "PlutusScriptV1"
|
|
203
|
+
? UplcProgramV1.fromCbor(props.optimizedCborHex, {
|
|
204
|
+
ir: props.optimizedIr,
|
|
205
|
+
sourceMap: props.optimizedSourceMap
|
|
206
|
+
})
|
|
207
|
+
: UplcProgramV2.fromCbor(props.optimizedCborHex, {
|
|
208
|
+
ir: props.optimizedIr,
|
|
209
|
+
sourceMap: props.optimizedSourceMap
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
if (props.unoptimizedCborHex) {
|
|
213
|
+
if (program.plutusVersion == "PlutusScriptV1") {
|
|
214
|
+
program = program.withAlt(
|
|
215
|
+
UplcProgramV1.fromCbor(props.unoptimizedCborHex, {
|
|
216
|
+
ir: props.unoptimizedIr,
|
|
217
|
+
sourceMap: props.unoptimizedSourceMap
|
|
218
|
+
})
|
|
219
|
+
)
|
|
220
|
+
} else if (program.plutusVersion == "PlutusScriptV2") {
|
|
221
|
+
program = program.withAlt(
|
|
222
|
+
UplcProgramV2.fromCbor(props.unoptimizedCborHex, {
|
|
223
|
+
ir: props.unoptimizedIr,
|
|
224
|
+
sourceMap: props.unoptimizedSourceMap
|
|
225
|
+
})
|
|
226
|
+
)
|
|
227
|
+
} else {
|
|
228
|
+
throw new Error("unhandled Plutus version")
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
let redeemer = new Cast(props.redeemer, props.castConfig)
|
|
233
|
+
|
|
234
|
+
switch (props.purpose) {
|
|
235
|
+
case "spending": {
|
|
236
|
+
res.validators[name] = new ValidatorHash(props.bytes, {
|
|
237
|
+
datum: new Cast(expectSome(props.datum), props.castConfig),
|
|
238
|
+
redeemer: redeemer,
|
|
239
|
+
program: program
|
|
240
|
+
})
|
|
241
|
+
break
|
|
242
|
+
}
|
|
243
|
+
case "minting": {
|
|
244
|
+
res.validators[name] = new MintingPolicyHash(props.bytes, {
|
|
245
|
+
redeemer: redeemer,
|
|
246
|
+
program: program
|
|
247
|
+
})
|
|
248
|
+
break
|
|
249
|
+
}
|
|
250
|
+
case "staking": {
|
|
251
|
+
res.validators[name] = new StakingValidatorHash(props.bytes, {
|
|
252
|
+
redeemer: redeemer,
|
|
253
|
+
program: program
|
|
254
|
+
})
|
|
255
|
+
break
|
|
256
|
+
}
|
|
257
|
+
case "mixed": {
|
|
258
|
+
res.validators[name] = new ScriptHash(props.bytes, {
|
|
259
|
+
datum: new Cast(expectSome(props.datum), props.castConfig),
|
|
260
|
+
redeemer: redeemer,
|
|
261
|
+
program: program
|
|
262
|
+
})
|
|
263
|
+
break
|
|
264
|
+
}
|
|
265
|
+
default:
|
|
266
|
+
throw new Error("unhandled purpose")
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
for (let name in entry.userFuncs) {
|
|
271
|
+
const props = entry.userFuncs[name]
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* @type {UplcProgram}
|
|
275
|
+
*/
|
|
276
|
+
let program =
|
|
277
|
+
props.plutusVersion == "PlutusScriptV1"
|
|
278
|
+
? UplcProgramV1.fromCbor(props.optimizedCborHex, {
|
|
279
|
+
ir: props.optimizedIr,
|
|
280
|
+
sourceMap: props.optimizedSourceMap
|
|
281
|
+
})
|
|
282
|
+
: UplcProgramV2.fromCbor(props.optimizedCborHex, {
|
|
283
|
+
ir: props.optimizedIr,
|
|
284
|
+
sourceMap: props.optimizedSourceMap
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
if (props.unoptimizedCborHex) {
|
|
288
|
+
if (program.plutusVersion == "PlutusScriptV1") {
|
|
289
|
+
program = program.withAlt(
|
|
290
|
+
UplcProgramV1.fromCbor(props.unoptimizedCborHex, {
|
|
291
|
+
ir: props.unoptimizedIr,
|
|
292
|
+
sourceMap: props.unoptimizedSourceMap
|
|
293
|
+
})
|
|
294
|
+
)
|
|
295
|
+
} else if (program.plutusVersion == "PlutusScriptV2") {
|
|
296
|
+
program = program.withAlt(
|
|
297
|
+
UplcProgramV2.fromCbor(props.unoptimizedCborHex, {
|
|
298
|
+
ir: props.unoptimizedIr,
|
|
299
|
+
sourceMap: props.unoptimizedSourceMap
|
|
300
|
+
})
|
|
301
|
+
)
|
|
302
|
+
} else {
|
|
303
|
+
throw new Error("unhandled Plutus version")
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
res.userFuncs[name] = program
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return res
|
|
310
|
+
}
|
|
@@ -47,6 +47,7 @@ export class ContractContextBuilder {
|
|
|
47
47
|
validators
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
+
* @private
|
|
50
51
|
* @readonly
|
|
51
52
|
* @type {Ms}
|
|
52
53
|
*/
|
|
@@ -118,12 +119,22 @@ export class ContractContextBuilder {
|
|
|
118
119
|
const castConfig = { isMainnet: props.isMainnet }
|
|
119
120
|
const lib = loadCompilerLib()
|
|
120
121
|
|
|
122
|
+
// generate a cache key
|
|
123
|
+
const key = contractContextCache.genCacheKey({
|
|
124
|
+
version: lib.version,
|
|
125
|
+
debug: !!props.debug,
|
|
126
|
+
isMainnet: props.isMainnet,
|
|
127
|
+
validators: this.validators,
|
|
128
|
+
modules: this.modules,
|
|
129
|
+
parameters: props.parameters ?? {}
|
|
130
|
+
})
|
|
131
|
+
|
|
121
132
|
const dagCompiler = new DagCompiler(lib, {
|
|
122
133
|
debug: props.debug ?? false,
|
|
123
134
|
...castConfig
|
|
124
135
|
})
|
|
125
136
|
|
|
126
|
-
const cached = contractContextCache.
|
|
137
|
+
const cached = contractContextCache.get(key)
|
|
127
138
|
|
|
128
139
|
const compiled =
|
|
129
140
|
cached ||
|
|
@@ -134,8 +145,7 @@ export class ContractContextBuilder {
|
|
|
134
145
|
props.expectedHashes
|
|
135
146
|
)
|
|
136
147
|
|
|
137
|
-
|
|
138
|
-
contractContextCache.push(compiled)
|
|
148
|
+
contractContextCache.set(key, compiled)
|
|
139
149
|
|
|
140
150
|
if (props.dumpHashes) {
|
|
141
151
|
for (let name in compiled.validators) {
|