@helios-lang/contract-utils
Advanced tools
Comparing version 0.1.26 to 0.1.27
@@ -8,3 +8,4 @@ import type {UplcData} from "@helios-lang/ledger"; | ||
$sourceCode: string | ||
$dependencies: [] | ||
$dependencies: [], | ||
MyUtilType: Cast<{hello: bigint}, {hello: bigint | number | string}>, | ||
} | ||
@@ -19,3 +20,2 @@ export const match_string_policy: { | ||
$Redeemer: Cast<boolean, boolean> | ||
} | ||
@@ -30,3 +30,4 @@ export const match_string: { | ||
$Redeemer: Cast<string, string> | ||
$Datum: Cast<{One: {message: string}} | {Two: {code: bigint}}, {One: {message: string}} | {Two: {code: bigint | number | string}}> | ||
$Datum: Cast<{One: {message: string}} | {Two: {code: bigint}}, {One: {message: string}} | {Two: {code: bigint | number | string}}>, | ||
Datum: Cast<{One: {message: string}} | {Two: {code: bigint}}, {One: {message: string}} | {Two: {code: bigint | number | string}}>, | ||
} |
@@ -5,4 +5,5 @@ import { Cast } from "@helios-lang/contract-utils"; | ||
$purpose: "module", | ||
$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}", | ||
$sourceCode: "module utils\n\nstruct MyUtilType {\n hello: Int\n}\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}", | ||
$dependencies: [], | ||
MyUtilType: new Cast({"structFieldTypes":[{"name":"hello","type":{"primitiveType":"Int"}}]}), | ||
} | ||
@@ -17,3 +18,2 @@ export const match_string_policy = { | ||
$Redeemer: new Cast({"primitiveType":"Bool"}), | ||
} | ||
@@ -28,3 +28,4 @@ export const match_string = { | ||
$Redeemer: new Cast({"primitiveType":"String"}), | ||
$Datum: new Cast({"enumVariantTypes":[{"name":"One","fieldTypes":[{"name":"message","type":{"primitiveType":"String"}}]},{"name":"Two","fieldTypes":[{"name":"code","type":{"primitiveType":"Int"}}]}]}) | ||
$Datum: new Cast({"enumVariantTypes":[{"name":"One","fieldTypes":[{"name":"message","type":{"primitiveType":"String"}}]},{"name":"Two","fieldTypes":[{"name":"code","type":{"primitiveType":"Int"}}]}]}), | ||
Datum: new Cast({"enumVariantTypes":[{"name":"One","fieldTypes":[{"name":"message","type":{"primitiveType":"String"}}]},{"name":"Two","fieldTypes":[{"name":"code","type":{"primitiveType":"Int"}}]}]}), | ||
} |
{ | ||
"name": "@helios-lang/contract-utils", | ||
"version": "0.1.26", | ||
"version": "0.1.27", | ||
"description": "Convenience and type-safety utilities for using Helios validators from within Typescript", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
@@ -7,2 +7,3 @@ import { StringWriter } from "@helios-lang/codec-utils" | ||
* @typedef {import("./TypeCheckedValidator.js").TypeCheckedValidator} TypeCheckedValidator | ||
* @typedef {import("./TypeSchema.js").TypeSchema} TypeSchema | ||
*/ | ||
@@ -147,2 +148,23 @@ | ||
/** | ||
* | ||
* @param {Record<string, TypeSchema>} types | ||
*/ | ||
writeTypes(types) { | ||
for (let key in types) { | ||
const t = types[key] | ||
const tsTypes = genTypes(t) | ||
this.definition.write( | ||
` ${key}: new Cast(${JSON.stringify(t)}),\n` | ||
) | ||
this.declaration.write( | ||
` ${key}: Cast<${tsTypes[0]}, ${tsTypes[1]}>,\n` | ||
) | ||
this.combined.write( | ||
` ${key}: new Cast<${tsTypes[0]}, ${tsTypes[1]}>(${JSON.stringify(t)}),\n` | ||
) | ||
} | ||
} | ||
/** | ||
* @private | ||
@@ -152,11 +174,7 @@ * @param {TypeCheckedModule} m | ||
writeModule(m) { | ||
this.definition.write( | ||
`export const ${m.name} = { | ||
this.definition.write(`export const ${m.name} = { | ||
$name: "${m.name}", | ||
$purpose: "${m.purpose}", | ||
$sourceCode: ${JSON.stringify(m.sourceCode)}, | ||
$dependencies: [${m.moduleDepedencies.join(", ")}], | ||
} | ||
` | ||
) | ||
$dependencies: [${m.moduleDepedencies.join(", ")}],\n`) | ||
@@ -168,5 +186,3 @@ this.declaration.write( | ||
$sourceCode: string | ||
$dependencies: [${m.moduleDepedencies.map((d) => `typeof ${d}`).join(", ")}] | ||
} | ||
` | ||
$dependencies: [${m.moduleDepedencies.map((d) => `typeof ${d}`).join(", ")}],\n` | ||
) | ||
@@ -179,6 +195,10 @@ | ||
$sourceCode: ${JSON.stringify(m.sourceCode)} as string, | ||
$dependencies: [${m.moduleDepedencies.join(", ")}], | ||
} | ||
` | ||
$dependencies: [${m.moduleDepedencies.join(", ")}],\n` | ||
) | ||
this.writeTypes(m.types) | ||
this.definition.write(`}\n`) | ||
this.declaration.write(`}\n`) | ||
this.combined.write(`}\n`) | ||
} | ||
@@ -203,6 +223,5 @@ | ||
$Redeemer: new Cast(${JSON.stringify(v.Redeemer)}), | ||
${datumTypes ? `$Datum: new Cast(${JSON.stringify(v.Datum)})` : ""} | ||
} | ||
` | ||
${datumTypes ? ` $Datum: new Cast(${JSON.stringify(v.Datum)}),\n` : ""}` | ||
) | ||
this.declaration.write( | ||
@@ -220,5 +239,3 @@ `export const ${v.name}: { | ||
$Redeemer: Cast<${redeemerTypes[0]}, ${redeemerTypes[1]}> | ||
${datumTypes ? `$Datum: Cast<${datumTypes[0]}, ${datumTypes[1]}>` : ""} | ||
} | ||
` | ||
${datumTypes ? ` $Datum: Cast<${datumTypes[0]}, ${datumTypes[1]}>,\n` : ""}` | ||
) | ||
@@ -235,7 +252,11 @@ | ||
$Redeemer: new Cast<${redeemerTypes[0]}, ${redeemerTypes[1]}>(${JSON.stringify(v.Redeemer)}), | ||
${datumTypes ? `$Datum: new Cast<${datumTypes[0]}, ${datumTypes[1]}>(${JSON.stringify(v.Datum)})` : ""} | ||
} | ||
` | ||
${datumTypes ? ` $Datum: new Cast<${datumTypes[0]}, ${datumTypes[1]}>(${JSON.stringify(v.Datum)}),\n` : ""}` | ||
) | ||
this.writeTypes(v.types) | ||
this.definition.write(`}\n`) | ||
this.declaration.write(`}\n`) | ||
this.combined.write(`}\n`) | ||
} | ||
} |
import { bytesToHex } from "@helios-lang/compiler" | ||
import { readHeader } from "@helios-lang/compiler-utils" | ||
import { expectSome } from "@helios-lang/type-utils" | ||
@@ -34,4 +35,4 @@ /** | ||
* @typedef {{ | ||
* name: string | ||
* }} EnumStatement | ||
* name: WordToken | ||
* }} Statement | ||
*/ | ||
@@ -41,12 +42,2 @@ | ||
* @typedef {{ | ||
* name: string | ||
* }} StructStatement | ||
*/ | ||
/** | ||
* @typedef {StructStatement | EnumStatement | any} Statement | ||
*/ | ||
/** | ||
* @typedef {{ | ||
* src: { | ||
@@ -76,3 +67,3 @@ * raw: string | ||
* purpose: "testing" | "minting" | "spending" | "staking" | "endpoint" | "module" | "unknown" | ||
* toIR: (ctx: any, extra: Map<string, IR>) => IR | ||
* toIR(ctx: any, extra: Map<string, IR>): IR | ||
* types: UserTypes | ||
@@ -82,2 +73,4 @@ * mainImportedModules: Module[] | ||
* mainArgTypes: DataType[] | ||
* throwErrors() | ||
* evalTypes(validatorTypes: {[name: string]: ScriptHashType}): TopScope | ||
* }} Program | ||
@@ -88,2 +81,20 @@ */ | ||
* @typedef {{ | ||
* getModuleScope(name: WordToken): Scope | ||
* }} TopScope | ||
*/ | ||
/** | ||
* @typedef {{ | ||
* asDataType?: DataType | ||
* }} HeliosType | ||
*/ | ||
/** | ||
* @typedef {{ | ||
* loopTypes(callback: (name: string, type: HeliosType) => void) | ||
* }} Scope | ||
*/ | ||
/** | ||
* @typedef {{ | ||
* typeDetails?: TypeDetails | ||
@@ -170,2 +181,49 @@ * }} DataType | ||
/** | ||
* @param {string} main | ||
* @param {string[]} modules | ||
* @param {CompileOptions} options | ||
* @returns {CompileOutput} | ||
*/ | ||
compile(main, modules, options) { | ||
const [purpose, name] = readHeader(main) | ||
// use `Program.newInternal()` instead of `Program.new()` so we can inject custom IR before finally compiling to a UplcProgram | ||
const program = this.lib.Program.newInternal( | ||
main, | ||
modules, | ||
options.allValidatorHashTypes, | ||
{ | ||
allowPosParams: false, | ||
invertEntryPoint: true | ||
} | ||
) | ||
const extra = this.generateExtraIRDefinitions( | ||
name, | ||
purpose, | ||
program.nPosParams, | ||
options | ||
) | ||
const optimize = options.optimize | ||
const ir = program.toIR(new this.lib.ToIRContext(optimize), extra) | ||
const irProgram = | ||
program.nPosParams > 0 | ||
? this.lib.IRParametricProgram.new( | ||
ir, | ||
purpose, | ||
program.nPosParams, | ||
optimize | ||
) | ||
: this.lib.IRProgram.new(ir, purpose, optimize) | ||
const cborHex = bytesToHex(irProgram.toUplc().toCbor()) | ||
return { | ||
prettyIR: irProgram.program.annotate(), | ||
cborHex | ||
} | ||
} | ||
/** | ||
* @param {string[]} validators | ||
@@ -209,2 +267,3 @@ * @param {string[]} modules | ||
const hashDependencies = dag[name] | ||
const allTypes = this.getProgramTypes(v, validatorTypes) | ||
@@ -222,3 +281,10 @@ const allModules = v.mainImportedModules | ||
moduleDepedencies: moduleDepedencies, | ||
types: {}, | ||
types: Object.fromEntries( | ||
Object.entries(allTypes[name]).map( | ||
([typeName, typeDetails]) => [ | ||
typeName, | ||
this.getInternalTypeDetails(typeDetails) | ||
] | ||
) | ||
), | ||
Redeemer: this.getInternalTypeDetails( | ||
@@ -249,3 +315,10 @@ v.mainArgTypes[purpose == "spending" ? 1 : 0] | ||
.map((m) => m.name.value), | ||
types: {} | ||
types: Object.fromEntries( | ||
Object.entries(allTypes[name]).map( | ||
([typeName, typeDetails]) => [ | ||
typeName, | ||
this.getInternalTypeDetails(typeDetails) | ||
] | ||
) | ||
) | ||
} | ||
@@ -328,49 +401,2 @@ } | ||
/** | ||
* @param {string} main | ||
* @param {string[]} modules | ||
* @param {CompileOptions} options | ||
* @returns {CompileOutput} | ||
*/ | ||
compile(main, modules, options) { | ||
const [purpose, name] = readHeader(main) | ||
// use `Program.newInternal()` instead of `Program.new()` so we can inject custom IR before finally compiling to a UplcProgram | ||
const program = this.lib.Program.newInternal( | ||
main, | ||
modules, | ||
options.allValidatorHashTypes, | ||
{ | ||
allowPosParams: false, | ||
invertEntryPoint: true | ||
} | ||
) | ||
const extra = this.generateExtraIRDefinitions( | ||
name, | ||
purpose, | ||
program.nPosParams, | ||
options | ||
) | ||
const optimize = options.optimize | ||
const ir = program.toIR(new this.lib.ToIRContext(optimize), extra) | ||
const irProgram = | ||
program.nPosParams > 0 | ||
? this.lib.IRParametricProgram.new( | ||
ir, | ||
purpose, | ||
program.nPosParams, | ||
optimize | ||
) | ||
: this.lib.IRProgram.new(ir, purpose, optimize) | ||
const cborHex = bytesToHex(irProgram.toUplc().toCbor()) | ||
return { | ||
prettyIR: irProgram.program.annotate(), | ||
cborHex | ||
} | ||
} | ||
/** | ||
* @private | ||
@@ -485,2 +511,12 @@ * @param {string[]} validators | ||
return { primitiveType: "Data" } | ||
} else if (e.message.includes("DCert")) { | ||
return { primitiveType: "DCert" } | ||
} else if (e.message.includes("Credential")) { | ||
return { primitiveType: "SpendingCredential" } | ||
} else if (e.message.includes("OutputDatum")) { | ||
return { primitiveType: "TxOutputDatum" } | ||
} else if (e.message.includes("PubKey")) { | ||
return { primitiveType: "PubKey" } | ||
} else if (e.message.includes("ScriptHash")) { | ||
return { primitiveType: "ScriptHash" } | ||
} else { | ||
@@ -491,2 +527,55 @@ throw e | ||
} | ||
/** | ||
* @private | ||
* @param {Program} program | ||
* @param {{[name: string]: ScriptHashType}} validatorTypes | ||
* @returns {Record<string, Record<string, DataType>>}} | ||
*/ | ||
getProgramTypes(program, validatorTypes) { | ||
const topScope = program.evalTypes(validatorTypes) | ||
program.throwErrors() | ||
/** | ||
* @type {Record<string, Record<string, DataType>>} | ||
*/ | ||
const result = {} | ||
if (program.purpose != "endpoint") { | ||
const moduleNames = [program.mainModule.name].concat( | ||
program.mainImportedModules.map((m) => m.name) | ||
) | ||
for (let moduleName of moduleNames) { | ||
const module_ = | ||
moduleName.value == program.name | ||
? program.mainModule | ||
: expectSome( | ||
program.mainImportedModules.find( | ||
(m) => m.name.value == moduleName.value | ||
) | ||
) | ||
/** | ||
* @type {Record<string, DataType>} | ||
*/ | ||
const moduleTypes = {} | ||
const moduleScope = topScope.getModuleScope(moduleName) | ||
moduleScope.loopTypes((name, type) => { | ||
if (module_.statements.some((s) => s.name.value == name)) { | ||
if (type?.asDataType) { | ||
moduleTypes[name] = type.asDataType | ||
} | ||
} | ||
}) | ||
result[moduleName.value] = moduleTypes | ||
} | ||
} | ||
return result | ||
} | ||
} |
/** | ||
* @typedef {import("./TypeCheckedModule.js").TypeCheckedModule} TypeCheckedModule | ||
* @typedef {import("./TypeCheckedValidator.js").TypeCheckedValidator} TypeCheckedValidator | ||
* @typedef {import("./TypeSchema.js").TypeSchema} TypeSchema | ||
*/ | ||
@@ -44,2 +45,7 @@ export class LoadedScriptsWriter { | ||
/** | ||
* | ||
* @param {Record<string, TypeSchema>} types | ||
*/ | ||
writeTypes(types: Record<string, TypeSchema>): void; | ||
/** | ||
* @private | ||
@@ -57,3 +63,4 @@ * @param {TypeCheckedModule} m | ||
export type TypeCheckedValidator = import("./TypeCheckedValidator.js").TypeCheckedValidator; | ||
export type TypeSchema = import("./TypeSchema.js").TypeSchema; | ||
import { StringWriter } from "@helios-lang/codec-utils"; | ||
//# sourceMappingURL=LoadedScriptsWriter.d.ts.map |
@@ -27,15 +27,7 @@ /** | ||
* @typedef {{ | ||
* name: string | ||
* }} EnumStatement | ||
* name: WordToken | ||
* }} Statement | ||
*/ | ||
/** | ||
* @typedef {{ | ||
* name: string | ||
* }} StructStatement | ||
*/ | ||
/** | ||
* @typedef {StructStatement | EnumStatement | any} Statement | ||
*/ | ||
/** | ||
* @typedef {{ | ||
* src: { | ||
@@ -63,3 +55,3 @@ * raw: string | ||
* purpose: "testing" | "minting" | "spending" | "staking" | "endpoint" | "module" | "unknown" | ||
* toIR: (ctx: any, extra: Map<string, IR>) => IR | ||
* toIR(ctx: any, extra: Map<string, IR>): IR | ||
* types: UserTypes | ||
@@ -69,2 +61,4 @@ * mainImportedModules: Module[] | ||
* mainArgTypes: DataType[] | ||
* throwErrors() | ||
* evalTypes(validatorTypes: {[name: string]: ScriptHashType}): TopScope | ||
* }} Program | ||
@@ -74,2 +68,17 @@ */ | ||
* @typedef {{ | ||
* getModuleScope(name: WordToken): Scope | ||
* }} TopScope | ||
*/ | ||
/** | ||
* @typedef {{ | ||
* asDataType?: DataType | ||
* }} HeliosType | ||
*/ | ||
/** | ||
* @typedef {{ | ||
* loopTypes(callback: (name: string, type: HeliosType) => void) | ||
* }} Scope | ||
*/ | ||
/** | ||
* @typedef {{ | ||
* typeDetails?: TypeDetails | ||
@@ -134,2 +143,9 @@ * }} DataType | ||
/** | ||
* @param {string} main | ||
* @param {string[]} modules | ||
* @param {CompileOptions} options | ||
* @returns {CompileOutput} | ||
*/ | ||
compile(main: string, modules: string[], options: CompileOptions): CompileOutput; | ||
/** | ||
* @param {string[]} validators | ||
@@ -154,9 +170,2 @@ * @param {string[]} modules | ||
/** | ||
* @param {string} main | ||
* @param {string[]} modules | ||
* @param {CompileOptions} options | ||
* @returns {CompileOutput} | ||
*/ | ||
compile(main: string, modules: string[], options: CompileOptions): CompileOutput; | ||
/** | ||
* @private | ||
@@ -197,2 +206,9 @@ * @param {string[]} validators | ||
private getInternalTypeDetails; | ||
/** | ||
* @private | ||
* @param {Program} program | ||
* @param {{[name: string]: ScriptHashType}} validatorTypes | ||
* @returns {Record<string, Record<string, DataType>>}} | ||
*/ | ||
private getProgramTypes; | ||
} | ||
@@ -214,9 +230,5 @@ export type TypeCheckedModule = import("../codegen/index.js").TypeCheckedModule; | ||
}; | ||
export type EnumStatement = { | ||
name: string; | ||
export type Statement = { | ||
name: WordToken; | ||
}; | ||
export type StructStatement = { | ||
name: string; | ||
}; | ||
export type Statement = StructStatement | EnumStatement | any; | ||
export type Site = { | ||
@@ -239,3 +251,3 @@ src: { | ||
purpose: "testing" | "minting" | "spending" | "staking" | "endpoint" | "module" | "unknown"; | ||
toIR: (ctx: any, extra: Map<string, IR>) => IR; | ||
toIR(ctx: any, extra: Map<string, IR>): IR; | ||
types: UserTypes; | ||
@@ -245,3 +257,16 @@ mainImportedModules: Module[]; | ||
mainArgTypes: DataType[]; | ||
throwErrors(): any; | ||
evalTypes(validatorTypes: { | ||
[name: string]: ScriptHashType; | ||
}): TopScope; | ||
}; | ||
export type TopScope = { | ||
getModuleScope(name: WordToken): Scope; | ||
}; | ||
export type HeliosType = { | ||
asDataType?: DataType; | ||
}; | ||
export type Scope = { | ||
loopTypes(callback: (name: string, type: HeliosType) => void): any; | ||
}; | ||
export type DataType = { | ||
@@ -248,0 +273,0 @@ typeDetails?: TypeDetails; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
133428
3397