UNPKG

@harmoniclabs/plu-ts-onchain

Version:

An embedded DSL for Cardano smart contracts creation coupled with a library for Cardano transactions, all in Typescript

198 lines (197 loc) 11.1 kB
"use strict"; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Precompiled = void 0; var LitteralPurpose_1 = require("../LitteralPurpose.js"); var type_system_1 = require("../../type_system/index.js"); var getFnTypes_1 = require("./getFnTypes.js"); var uplc_1 = require("@harmoniclabs/uplc"); var plutus_machine_1 = require("@harmoniclabs/plutus-machine"); var conversion_1 = require("../../lib/std/data/conversion/index.js"); var cloneTermType_1 = require("../../type_system/cloneTermType.js"); var uint8array_utils_1 = require("@harmoniclabs/uint8array-utils"); var obj_utils_1 = require("@harmoniclabs/obj-utils"); var crypto_1 = require("@harmoniclabs/crypto"); var cbor_1 = require("@harmoniclabs/cbor"); var Precompiled = /** @class */ (function () { function Precompiled(purpose, fullType, precompiled, pulutsVersion) { if (pulutsVersion === void 0) { pulutsVersion = "PlutusScriptV2"; } if (!(0, LitteralPurpose_1.isLitteralPurpose)(purpose)) throw new Error("invalid purpose passed to Precompiled constructor"); var tys = (0, getFnTypes_1.getFnTypes)(fullType); var outT = tys[tys.length - 1][0]; if (!(outT === type_system_1.PrimType.Bool || outT === type_system_1.PrimType.Unit)) throw new Error("invalid return type for typed or untyped validator"); if ((purpose === "spend" && tys.length < 4) || tys.length < 3) throw new Error("invalid term to precompile"); var paramsTys = purpose === "spend" ? tys.slice(0, tys.length - 4) : tys.slice(0, tys.length - 3); var validatorArgs = purpose === "spend" ? tys.slice(tys.length - 4, tys.length - 1) : tys.slice(tys.length - 3, tys.length - 1); var validatorType = (0, type_system_1.fn)(validatorArgs, [outT]); var _hash = undefined; var _getHash = function () { if (!(_hash instanceof Uint8Array)) _hash = new Uint8Array((0, crypto_1.blake2b_224)(new Uint8Array(__spreadArray([ pulutsVersion === "PlutusScriptV2" ? 0x02 : 0x01 ], __read(cbor_1.Cbor.encode(new cbor_1.CborBytes(precompiled)).toBuffer()), false)))); return Uint8Array.prototype.slice.call(_hash); }; Object.defineProperties(this, { params: { get: function () { return paramsTys.map(cloneTermType_1.cloneTermType); }, set: function () { }, enumerable: true, configurable: false }, validatorType: { get: function () { return (0, cloneTermType_1.cloneTermType)(validatorType); }, set: function () { }, enumerable: true, configurable: false }, outputType: { get: function () { return [outT]; }, set: function () { }, enumerable: true, configurable: false }, precompiled: { get: function () { return precompiled.slice(); }, set: function () { }, enumerable: true, configurable: false }, purpose: { value: purpose, writable: false, enumerable: true, configurable: false }, hash: { get: _getHash, set: function () { }, enumerable: true, configurable: false } }); Object.defineProperty(this, "apply", { value: function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } if (paramsTys.length === 0) return precompiled; if (args.length < paramsTys.length) throw new Error("required ".concat(paramsTys.length, " arguments in order to instantiate a precompiled script, but only ").concat(args.length, " where passed")); var wrongTypeIdx = paramsTys.findIndex(function (t, i) { return !(0, type_system_1.typeExtends)(args[i].type, t); }); if (wrongTypeIdx >= 0) throw new Error("parameter at position ".concat(wrongTypeIdx, " was expected to be of type: \"").concat((0, type_system_1.termTypeToString)(paramsTys[wrongTypeIdx]), "\" but was instead of type \"").concat((0, type_system_1.termTypeToString)(args[wrongTypeIdx].type), "\"")); var _a = uplc_1.UPLCDecoder.parse(precompiled), version = _a.version, body = _a.body; for (var i = paramsTys.length - 1; i >= 0; i--) { var theArg = args[i]; var theParamT = paramsTys[i]; while ((0, type_system_1.isTaggedAsAlias)(theParamT)) theParamT = (0, type_system_1.unwrapAlias)(theParamT); var uplcArg = void 0; if (theParamT[0] === type_system_1.PrimType.Lambda || theParamT[0] === type_system_1.PrimType.Delayed) { uplcArg = theArg.toUPLC(); } else { uplcArg = plutus_machine_1.Machine.evalSimple(theArg); if (!(uplcArg instanceof plutus_machine_1.CEKConst)) throw new Error("applied parameter did not evaluate to a constant"); uplcArg = new uplc_1.UPLCConst(uplcArg.type, uplcArg.value); } body = new uplc_1.Application(body, uplcArg); } if (outT === type_system_1.PrimType.Unit) // already untyped { return uplc_1.UPLCEncoder.compile(new uplc_1.UPLCProgram(version, body)).toBuffer().buffer; } // else typed validator if (purpose === "spend") { var _b = __read(tys.slice(tys.length - 4, tys.length - 1), 3), datumType = _b[0], redeemerType_1 = _b[1], ctxType_1 = _b[2]; var datumUplc = (0, type_system_1.typeExtends)(datumType, type_system_1.data) ? new uplc_1.UPLCVar(2) : new uplc_1.Application((0, conversion_1.ptoData)(datumType).toUPLC(), new uplc_1.UPLCVar(2)); var redeemerUplc_1 = (0, type_system_1.typeExtends)(redeemerType_1, type_system_1.data) ? new uplc_1.UPLCVar(1) : new uplc_1.Application((0, conversion_1.ptoData)(redeemerType_1).toUPLC(), new uplc_1.UPLCVar(1)); var ctxUplc_1 = (0, type_system_1.typeExtends)(ctxType_1, type_system_1.data) ? new uplc_1.UPLCVar(0) : new uplc_1.Application((0, conversion_1.ptoData)(ctxType_1).toUPLC(), new uplc_1.UPLCVar(0)); body = new uplc_1.Lambda(// datum new uplc_1.Lambda(//redeemer new uplc_1.Lambda(// ctx new uplc_1.Force(new uplc_1.Application(new uplc_1.Application(new uplc_1.Application(uplc_1.Builtin.ifThenElse, new uplc_1.Application(new uplc_1.Application(new uplc_1.Application(body, datumUplc), redeemerUplc_1), ctxUplc_1)), new uplc_1.Delay(uplc_1.UPLCConst.unit)), new uplc_1.Delay(new uplc_1.ErrorUPLC)))))); return uplc_1.UPLCEncoder.compile(new uplc_1.UPLCProgram(version, body)).toBuffer().buffer; } // else redeemer validator var _c = __read(tys.slice(tys.length - 3, tys.length - 1), 2), redeemerType = _c[0], ctxType = _c[1]; var redeemerUplc = (0, type_system_1.typeExtends)(redeemerType, type_system_1.data) ? new uplc_1.UPLCVar(1) : new uplc_1.Application((0, conversion_1.ptoData)(redeemerType).toUPLC(), new uplc_1.UPLCVar(1)); var ctxUplc = (0, type_system_1.typeExtends)(ctxType, type_system_1.data) ? new uplc_1.UPLCVar(0) : new uplc_1.Application((0, conversion_1.ptoData)(ctxType).toUPLC(), new uplc_1.UPLCVar(0)); body = new uplc_1.Lambda(//redeemer new uplc_1.Lambda(// ctx new uplc_1.Force(new uplc_1.Application(new uplc_1.Application(new uplc_1.Application(uplc_1.Builtin.ifThenElse, new uplc_1.Application(new uplc_1.Application(body, redeemerUplc), ctxUplc)), new uplc_1.Delay(uplc_1.UPLCConst.unit)), new uplc_1.Delay(new uplc_1.ErrorUPLC))))); return uplc_1.UPLCEncoder.compile(new uplc_1.UPLCProgram(version, body)).toBuffer().buffer; }, writable: false, enumerable: true, configurable: false }); } Precompiled.prototype.toJSON = function () { return this.toJson(); }; Precompiled.prototype.toJson = function () { return { purpose: this.purpose, params: this.params.map(type_system_1.termTypeToJson), validatorType: (0, type_system_1.termTypeToJson)(this.validatorType), precompiledHex: (0, uint8array_utils_1.toHex)(this.precompiled) }; }; Precompiled.fromJson = function (json) { if (!(0, obj_utils_1.isObject)(json)) throw new Error("'Precompiled.formJson' espects an object as argument"); var params = json["params"].map(type_system_1.termTypeFromJson); var validatroType = (0, type_system_1.termTypeFromJson)(json["validatorType"]); var validatorTypes = (0, getFnTypes_1.getFnTypes)(validatroType); var outT = validatorTypes[validatorTypes.length - 1]; var validatorArgs = validatorTypes.slice(0, validatorTypes.length - 1); var fullType = (0, type_system_1.fn)(__spreadArray(__spreadArray([], __read(params), false), __read(validatorArgs), false), outT); return new Precompiled(json["purpose"], fullType, (0, uint8array_utils_1.fromHex)(json["precompiledHex"])); }; return Precompiled; }()); exports.Precompiled = Precompiled;