├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── assets ├── docs_on_hover.gif ├── errorTree_plu-ts.drawio ├── errorTree_plu-ts.drawio.svg └── logo │ └── plu-ts.svg ├── babel.config.cjs ├── catalyst-proposals.md ├── jest.config.cjs ├── package-lock.json ├── package.json ├── sponsors.md ├── src ├── IR │ ├── IRHash.ts │ ├── IRNodeKind.ts │ ├── IRNodes │ │ ├── BaseIRMetadata.ts │ │ ├── IRApp.ts │ │ ├── IRCase.ts │ │ ├── IRConst.ts │ │ ├── IRConstr.ts │ │ ├── IRDelayed.ts │ │ ├── IRError.ts │ │ ├── IRForced.ts │ │ ├── IRFunc.ts │ │ ├── IRHoisted.ts │ │ ├── IRLetted.ts │ │ ├── IRNative │ │ │ ├── IRNativeTag.ts │ │ │ ├── __tests__ │ │ │ │ └── IRNative.hash.test.ts │ │ │ ├── index.ts │ │ │ └── isForcedNative.ts │ │ ├── IRRecursive.ts │ │ ├── IRSelfCall.ts │ │ ├── IRVar.ts │ │ ├── __tests__ │ │ │ ├── IRFunc.body.test.ts │ │ │ ├── IRLetted.dependencies.test.ts │ │ │ ├── IRLetted.getLettedTerms.test.ts │ │ │ ├── IRLetted.hash.test.ts │ │ │ └── isClosedIRTerm.test.ts │ │ ├── index.ts │ │ └── utils │ │ │ ├── dependsByDbns.ts │ │ │ ├── isClosedAtDbn.ts │ │ │ ├── makeArrayLikeProxy.ts │ │ │ └── mapArrayLike.ts │ ├── IRTerm.ts │ ├── index.ts │ ├── interfaces │ │ ├── IHash.ts │ │ ├── IIRParent.ts │ │ ├── IRMetadata.ts │ │ ├── ToIR.ts │ │ └── index.ts │ ├── toUPLC │ │ ├── CompilerOptions.ts │ │ ├── __tests__ │ │ │ ├── compile.pfactorial.test.ts │ │ │ ├── compileIR.PMaybe.test.ts │ │ │ ├── compileIR.hoistForcedNatives.test.ts │ │ │ ├── compileIR.letted.test.ts │ │ │ ├── compileIR.natives.test.ts │ │ │ └── compileIR.test.ts │ │ ├── _internal │ │ │ ├── __tests__ │ │ │ │ ├── IR.compile._modifyChildFromTo.test.ts │ │ │ │ └── IR.compile.getDebruijnInTerm.test.ts │ │ │ ├── _addDepth.ts │ │ │ ├── _irToUplc.ts │ │ │ ├── _makeAllNegativeNativesHoisted.ts │ │ │ ├── _modifyChildFromTo.ts │ │ │ ├── depth.ts │ │ │ ├── findAll.ts │ │ │ ├── getDebruijnInTerm.ts │ │ │ ├── getDiffDbn.ts │ │ │ ├── includesLettedTerms.ts │ │ │ ├── includesNode.ts │ │ │ ├── iterTree.ts │ │ │ └── lowestCommonAncestor.ts │ │ ├── compileIRToUPLC.ts │ │ ├── index.ts │ │ └── subRoutines │ │ │ ├── handleHoistedAndReturnRoot │ │ │ ├── __tests__ │ │ │ │ └── IR.handleHoistedAndReturnRoot.test.ts │ │ │ └── index.ts │ │ │ ├── handleLetted │ │ │ ├── __tests__ │ │ │ │ ├── IR.compile.handleLetted.test.ts │ │ │ │ ├── IR.handleLetted._getMinUnboundDbn.test.ts │ │ │ │ └── IR.handleLetted.groupByScopes.test.ts │ │ │ ├── findHighestRecursiveParent.ts │ │ │ ├── groupByScope.ts │ │ │ ├── incrementUnboundDbns.ts │ │ │ └── index.ts │ │ │ ├── handleRecursiveTerms.ts │ │ │ ├── hoistForcedNatives.ts │ │ │ ├── inlineSingleUseApplications.ts │ │ │ ├── markRecursiveHoistsAsForced.ts │ │ │ ├── performUplcOptimizationsAndReturnRoot │ │ │ ├── __tests__ │ │ │ │ ├── groupIndipendentLets.test.ts │ │ │ │ └── uplcOptimizations.test.ts │ │ │ ├── expandFuncsAndReturnRoot.ts │ │ │ └── index.ts │ │ │ ├── replaceClosedLettedWithHoisted.ts │ │ │ ├── replaceForcedNativesWithHoisted.ts │ │ │ ├── replaceHoistedWithLetted.ts │ │ │ ├── replaceNatives │ │ │ ├── index.ts │ │ │ └── nativeToIR.ts │ │ │ └── sanifyTree.ts │ ├── tree_utils │ │ ├── _ir_apps.ts │ │ ├── _ir_let.ts │ │ ├── getChildren.ts │ │ └── getRoot.ts │ └── utils │ │ ├── MutArrayLike.ts │ │ ├── concatUint8Arr.ts │ │ ├── equalIRTerm.ts │ │ ├── index.ts │ │ ├── isClosedIRTerm.ts │ │ ├── isIRParentTerm.ts │ │ ├── isIRTerm.ts │ │ ├── positiveIntAsBytes.ts │ │ └── showIR.ts ├── index.ts ├── pluts │ ├── API │ │ ├── V1 │ │ │ ├── Address │ │ │ │ ├── PAddress.ts │ │ │ │ ├── PCredential.ts │ │ │ │ ├── PStakingCredential.ts │ │ │ │ └── __tests__ │ │ │ │ │ ├── API.V1.PAddress.PStakingCredential.test.ts │ │ │ │ │ └── API.V1.PCredential.pmatch.test.ts │ │ │ ├── Interval │ │ │ │ ├── PBound.ts │ │ │ │ ├── PExtended.ts │ │ │ │ └── PInterval.ts │ │ │ ├── PDCert │ │ │ │ └── index.ts │ │ │ ├── PubKey │ │ │ │ ├── PPubKey.ts │ │ │ │ └── PPubKeyHash.ts │ │ │ ├── ScriptContext │ │ │ │ ├── PScriptContext.ts │ │ │ │ ├── PScriptPurpose │ │ │ │ │ └── index.ts │ │ │ │ └── PTxInfo │ │ │ │ │ └── PTxInfo.ts │ │ │ ├── ScriptsHashes │ │ │ │ ├── PDatumHash.ts │ │ │ │ ├── PScriptHash.ts │ │ │ │ └── PValidatorHash.ts │ │ │ ├── Time │ │ │ │ └── index.ts │ │ │ ├── Tx │ │ │ │ ├── PTxId.ts │ │ │ │ ├── PTxInInfo.ts │ │ │ │ ├── PTxOut.ts │ │ │ │ └── PTxOutRef.ts │ │ │ ├── Value │ │ │ │ ├── PCurrencySymbol.ts │ │ │ │ ├── PTokenName.ts │ │ │ │ ├── PValue │ │ │ │ │ └── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── PValue.evalScript.test.ts │ │ │ └── index.ts │ │ ├── V2 │ │ │ ├── ScriptContext │ │ │ │ ├── PScriptContext.ts │ │ │ │ └── PTxInfo │ │ │ │ │ ├── PTxInfo.ts │ │ │ │ │ └── __tests__ │ │ │ │ │ └── PTxInfo.pmatch.extract.input.value.test.ts │ │ │ ├── Tx │ │ │ │ ├── POutputDatum.ts │ │ │ │ ├── PTxInInfo.ts │ │ │ │ └── PTxOut.ts │ │ │ └── index.ts │ │ ├── V3 │ │ │ ├── Governance │ │ │ │ ├── PChangedParams.ts │ │ │ │ ├── PDRep.ts │ │ │ │ ├── PGovernanceAction.ts │ │ │ │ ├── PProposalProcedure.ts │ │ │ │ ├── PProtocolVersion.ts │ │ │ │ ├── PVote.ts │ │ │ │ ├── PVoter.ts │ │ │ │ └── index.ts │ │ │ ├── ScriptContext │ │ │ │ ├── PCertificate.ts │ │ │ │ ├── PDelegatee.ts │ │ │ │ ├── PScriptContext.ts │ │ │ │ ├── PScriptInfo │ │ │ │ │ └── index.ts │ │ │ │ ├── PScriptPurpose │ │ │ │ │ └── index.ts │ │ │ │ ├── PTxInfo │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── Tx │ │ │ │ ├── PTxId.ts │ │ │ │ ├── PTxInInfo.ts │ │ │ │ ├── PTxOutRef.ts │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ └── index.ts │ ├── PType │ │ ├── PDataRepresentable.ts │ │ └── index.ts │ ├── PTypes │ │ ├── PAlias │ │ │ ├── __tests__ │ │ │ │ └── PAlias.evalScript.test.ts │ │ │ ├── index.ts │ │ │ └── palias.ts │ │ ├── PBlsG1.ts │ │ ├── PBlsG2.ts │ │ ├── PBlsMlRes.ts │ │ ├── PBool.ts │ │ ├── PByteString.ts │ │ ├── PData │ │ │ ├── PData.ts │ │ │ └── index.ts │ │ ├── PDelayed.ts │ │ ├── PFn │ │ │ ├── PFn.ts │ │ │ ├── PLam.ts │ │ │ └── index.ts │ │ ├── PInt.ts │ │ ├── PList.ts │ │ ├── PPair │ │ │ └── index.ts │ │ ├── PSoP │ │ │ ├── index.ts │ │ │ └── psop.ts │ │ ├── PString.ts │ │ ├── PStruct │ │ │ ├── __tests__ │ │ │ │ ├── PStruct.evalScript.test.ts │ │ │ │ ├── PStruct.list.head.test.ts │ │ │ │ ├── PStruct.pgenericStruct.test.ts │ │ │ │ ├── PStruct.pmatch.duble_extract.test.ts │ │ │ │ ├── PStruct.pmatch.getElemAtTerm.test.ts │ │ │ │ ├── PStruct.pmatch.test.ts │ │ │ │ └── PStruct.typeofGenericStruct.test.ts │ │ │ ├── cloneStructDef.ts │ │ │ ├── index.ts │ │ │ ├── pgenericStruct.ts │ │ │ ├── pstruct.ts │ │ │ └── structDefEq.ts │ │ ├── PUnit.ts │ │ ├── __tests__ │ │ │ └── PList │ │ │ │ └── PList.pList.test.ts │ │ └── index.ts │ ├── Script │ │ ├── LitteralPurpose.ts │ │ ├── Parametrized │ │ │ ├── __tests__ │ │ │ │ └── getFnTypes.test.ts │ │ │ ├── getFnTypes.ts │ │ │ └── index.ts │ │ ├── __tests__ │ │ │ ├── Script.compile.NFTVendingMachine_v05.test.ts │ │ │ ├── Script.compile.incremental.test.ts │ │ │ ├── Script.compile.okScript.test.ts │ │ │ ├── Script.compile.oneShotPolicy.test.ts │ │ │ ├── Script.compile.run.tempura.mintEntry.test.ts │ │ │ ├── Script.compile.run.tempura.ownOuts.test.ts │ │ │ ├── Script.compile.run.tempura.test.ts │ │ │ ├── Script.compile.tempura.test.ts │ │ │ ├── Script.compile.tx_interval.test.ts │ │ │ ├── ownOuts.outsOnly.correct.uplc.txt │ │ │ ├── ownOuts.outsOnly.tempura.uplc.txt │ │ │ ├── simple_tempura.ir.json │ │ │ └── simpler_tx_interval.ir.json │ │ ├── blueprint │ │ │ ├── getBlueprint.ts │ │ │ ├── index.ts │ │ │ ├── toBlueprintValidator.ts │ │ │ ├── toDataSchema.ts │ │ │ └── types.ts │ │ ├── compile.ts │ │ ├── getValidVersion.ts │ │ ├── index.ts │ │ └── makeScript.ts │ ├── Term │ │ ├── __tests__ │ │ │ └── Term.Hoisted.phoist.test.ts │ │ └── index.ts │ ├── __tests__ │ │ ├── contract.docs.v3.hello.test.ts │ │ └── contract.docs.v3.no_datum.test.ts │ ├── index.ts │ ├── lib │ │ ├── __tests__ │ │ │ ├── Syntax.papp.arg.test.ts │ │ │ ├── Syntax.pfn.test.ts │ │ │ ├── Syntax.plet.test.ts │ │ │ └── Syntax.precursive.test.ts │ │ ├── builtins │ │ │ ├── __tests__ │ │ │ │ ├── bool.eval.test.ts │ │ │ │ └── builtin.bench.test.ts │ │ │ ├── _pflipIR.ts │ │ │ ├── addApplications.ts │ │ │ ├── bls12_381_G1_element │ │ │ │ └── index.ts │ │ │ ├── bls12_381_G2_element │ │ │ │ └── index.ts │ │ │ ├── bls12_381_MlResult │ │ │ │ └── index.ts │ │ │ ├── bool │ │ │ │ └── index.ts │ │ │ ├── bs │ │ │ │ └── index.ts │ │ │ ├── data │ │ │ │ └── index.ts │ │ │ ├── hoisted.ts │ │ │ ├── index.ts │ │ │ ├── int │ │ │ │ ├── index.ts │ │ │ │ ├── intBinOpToBool.ts │ │ │ │ ├── intBinOpToInt.ts │ │ │ │ ├── padd.ts │ │ │ │ ├── pdiv.ts │ │ │ │ ├── pmod.ts │ │ │ │ ├── pmult.ts │ │ │ │ ├── pquot.ts │ │ │ │ ├── prem.ts │ │ │ │ └── psub.ts │ │ │ ├── list │ │ │ │ ├── __tests__ │ │ │ │ │ └── list.builtins.test.ts │ │ │ │ ├── index.ts │ │ │ │ └── minimal.ts │ │ │ ├── pair │ │ │ │ ├── index.ts │ │ │ │ └── noUnwrap.ts │ │ │ ├── pchooseUnit.ts │ │ │ ├── ppairData.ts │ │ │ ├── pprepend │ │ │ │ ├── index.ts │ │ │ │ └── minimal.ts │ │ │ ├── ptrace.ts │ │ │ └── str │ │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── papp.ts │ │ ├── pappArg.ts │ │ ├── pdelay.ts │ │ ├── perror.ts │ │ ├── pfn.ts │ │ ├── pforce │ │ │ ├── index.ts │ │ │ └── minimal.ts │ │ ├── phoist.ts │ │ ├── plam.ts │ │ ├── plet │ │ │ ├── __tests__ │ │ │ │ ├── plet.deps.test.ts │ │ │ │ └── plet.test.ts │ │ │ ├── index.ts │ │ │ ├── minimal.ts │ │ │ └── old.ts │ │ ├── pmatch │ │ │ ├── PMatchOptions.ts │ │ │ ├── __tests__ │ │ │ │ ├── pmatch.ctx.purpose.ts │ │ │ │ ├── pmatch.new.test.ts │ │ │ │ └── pmatch.sop.test.ts │ │ │ ├── getElemAtTerm.ts │ │ │ ├── index.ts │ │ │ ├── matchNCtors.ts │ │ │ ├── matchSingleCtorStruct.ts │ │ │ ├── pmatch.ts │ │ │ ├── pmatchSop.ts │ │ │ └── pmatchStruct.ts │ │ ├── precursive │ │ │ ├── index.ts │ │ │ └── minimal.ts │ │ ├── punsafeConvertType │ │ │ ├── index.ts │ │ │ └── minimal.ts │ │ ├── show │ │ │ ├── bool.ts │ │ │ ├── bs.ts │ │ │ ├── data.ts │ │ │ ├── index.ts │ │ │ ├── int.ts │ │ │ ├── list.ts │ │ │ ├── pair.ts │ │ │ ├── pshow.ts │ │ │ ├── ptraceVal.ts │ │ │ ├── str.ts │ │ │ └── unit.ts │ │ └── std │ │ │ ├── PMaybe │ │ │ ├── PListMaybe.ts │ │ │ ├── PMaybe.ts │ │ │ ├── __tests__ │ │ │ │ └── PMaybe.test.ts │ │ │ └── index.ts │ │ │ ├── UtilityTerms │ │ │ ├── BaseUtilityTerm.ts │ │ │ ├── TermAlias.ts │ │ │ ├── TermBS.ts │ │ │ ├── TermBool.ts │ │ │ ├── TermInt.ts │ │ │ ├── TermList.ts │ │ │ ├── TermPair.ts │ │ │ ├── TermStr.ts │ │ │ ├── TermStruct.ts │ │ │ ├── __tests__ │ │ │ │ ├── TermList.pprepend.test.ts │ │ │ │ └── TermStruct.dot_notation.test.ts │ │ │ ├── addUtilityForType.ts │ │ │ ├── index.ts │ │ │ ├── mockUtilityTerms │ │ │ │ ├── __tests__ │ │ │ │ │ └── mockUtilityTerm.test.ts │ │ │ │ ├── makeMockTerm.ts │ │ │ │ ├── makeMockUtilityTerm.ts │ │ │ │ ├── mockPBoolMethods.ts │ │ │ │ ├── mockPByteStringMethods.ts │ │ │ │ ├── mockPIntMethods.ts │ │ │ │ ├── mockPListMethods.ts │ │ │ │ ├── mockPPairMethods.ts │ │ │ │ ├── mockPStringMethods.ts │ │ │ │ ├── mockPStructMethods.ts │ │ │ │ ├── mockPapp.ts │ │ │ │ ├── mockUserMethods.ts │ │ │ │ └── mockUtilityForType.ts │ │ │ ├── types.ts │ │ │ └── userMethods │ │ │ │ ├── __tests__ │ │ │ │ ├── addUserMethods.instance.test.ts │ │ │ │ └── isWellFormedMethods.test.ts │ │ │ │ ├── addUserMethods.ts │ │ │ │ ├── assertWellFormedMethods.ts │ │ │ │ └── methodsTypes.ts │ │ │ ├── __tests__ │ │ │ ├── Pluts.Builtins.pchooseData.test.ts │ │ │ ├── Pluts.Builtins.pchooseList.test.ts │ │ │ ├── Pluts.Builtins.pif.test.ts │ │ │ └── Pluts.combinators.pflip.test.ts │ │ │ ├── bool │ │ │ ├── index.ts │ │ │ ├── pBool.ts │ │ │ ├── pBoolFromData.ts │ │ │ └── pBoolToData.ts │ │ │ ├── bs │ │ │ ├── index.ts │ │ │ └── pByteString.ts │ │ │ ├── combinators │ │ │ ├── index.ts │ │ │ ├── pcompose.ts │ │ │ └── pflip.ts │ │ │ ├── data │ │ │ ├── conversion │ │ │ │ ├── __tests__ │ │ │ │ │ ├── data.conversion.fromData.test.ts │ │ │ │ │ └── data.conversion.toData.test.ts │ │ │ │ ├── fromData.ts │ │ │ │ ├── fromData_minimal.ts │ │ │ │ ├── index.ts │ │ │ │ ├── minimal_common.ts │ │ │ │ ├── toData.ts │ │ │ │ └── toData_minimal.ts │ │ │ ├── index.ts │ │ │ └── pData.ts │ │ │ ├── index.ts │ │ │ ├── int │ │ │ ├── index.ts │ │ │ └── pInt.ts │ │ │ ├── list │ │ │ ├── __tests__ │ │ │ │ ├── find.empty.uplc.txt │ │ │ │ ├── list.const.pList.test.ts │ │ │ │ ├── list.const.pnil.test.ts │ │ │ │ ├── list.pfind.test.ts │ │ │ │ ├── list.pfind.toIR.test.ts │ │ │ │ └── list.pindex.test.ts │ │ │ ├── const │ │ │ │ ├── index.ts │ │ │ │ └── minimal.ts │ │ │ ├── index.ts │ │ │ ├── pcompareList │ │ │ │ ├── __tests__ │ │ │ │ │ └── pcompareList.piterList.benchmark.test.ts │ │ │ │ └── index.ts │ │ │ ├── peqList.ts │ │ │ ├── pevery.ts │ │ │ ├── pfilter.ts │ │ │ ├── pfind.ts │ │ │ ├── pfoldl.ts │ │ │ ├── pfoldr │ │ │ │ ├── __tests__ │ │ │ │ │ └── list.pfoldr.test.ts │ │ │ │ ├── index.ts │ │ │ │ └── minimal.ts │ │ │ ├── pincludes │ │ │ │ └── index.ts │ │ │ ├── pindexList.ts │ │ │ ├── piterLists │ │ │ │ ├── __tests__ │ │ │ │ │ └── piterLists.test.ts │ │ │ │ └── index.ts │ │ │ ├── plength.ts │ │ │ ├── plookup │ │ │ │ ├── __tests__ │ │ │ │ │ └── plookup.test.ts │ │ │ │ └── index.ts │ │ │ ├── pmap │ │ │ │ ├── index.ts │ │ │ │ └── minimal.ts │ │ │ ├── pmatchList │ │ │ │ ├── __tests__ │ │ │ │ │ ├── list._pmatch.test.ts │ │ │ │ │ └── list.pmatch.test.ts │ │ │ │ ├── index.ts │ │ │ │ └── minimal.ts │ │ │ ├── precursiveList │ │ │ │ ├── __tests__ │ │ │ │ │ └── list.precursiveList.test.ts │ │ │ │ ├── index.ts │ │ │ │ └── minimal.ts │ │ │ ├── preverse.ts │ │ │ └── psome.ts │ │ │ ├── pair │ │ │ ├── index.ts │ │ │ ├── pPair.ts │ │ │ └── peqPair.ts │ │ │ ├── passert.ts │ │ │ ├── stdEq │ │ │ ├── __tests__ │ │ │ │ └── pstdEq.test.ts │ │ │ ├── index.ts │ │ │ └── pstdEq.ts │ │ │ ├── str │ │ │ ├── index.ts │ │ │ └── pStr.ts │ │ │ ├── traces.ts │ │ │ └── unit │ │ │ ├── index.ts │ │ │ ├── pUnitFromData.ts │ │ │ ├── peqUnit.ts │ │ │ ├── pmakeUnit.ts │ │ │ └── pmakeUnitData.ts │ └── type_system │ │ ├── __tests__ │ │ ├── typeSys.typeCreation.test.ts │ │ └── typeSys.typeExtends.test.ts │ │ ├── cloneTermType.ts │ │ ├── includesDynamicPairs.ts │ │ ├── index.ts │ │ ├── kinds │ │ ├── __tests__ │ │ │ └── typeSys.isWellFormedType.test.ts │ │ ├── index.ts │ │ ├── isPrimTypeTag.ts │ │ ├── isTaggedAsAlias.ts │ │ ├── isTypePAram.ts │ │ └── isWellFormedType.ts │ │ ├── termTyToConstTy.ts │ │ ├── ts-pluts-conversion.ts │ │ ├── tyArgs │ │ ├── __tests__ │ │ │ ├── clearAsData.test.ts │ │ │ └── getElemsT.test.ts │ │ ├── clearAsData.ts │ │ ├── getDirectFstT.ts │ │ ├── getDirectSndT.ts │ │ ├── getElemsT.ts │ │ ├── getFstT.ts │ │ ├── getSndT.ts │ │ ├── index.ts │ │ ├── unwrapAlias.ts │ │ └── unwrapAsData.ts │ │ ├── typeExtends.ts │ │ ├── types.ts │ │ ├── utils.ts │ │ └── withAllPairElemsAsData.ts └── utils │ ├── BasePlutsError.ts │ ├── BitUtils │ └── index.ts │ ├── Cloneable.ts │ ├── InvalidCborFormatError.ts │ ├── IsSingleKey.ts │ ├── PlutusScriptType.ts │ ├── ToJson.ts │ ├── UPLCFlatUtils │ ├── __tests__ │ │ ├── encodeBigIntAsVaraibleLengthBitStream.test.ts │ │ ├── unzigzagBigint.test.ts │ │ └── zigzagBigint.test.ts │ └── index.ts │ ├── assert.ts │ ├── capitalize.ts │ ├── combinators.ts │ ├── getCallStackAt │ ├── __tests__ │ │ └── getCallStackAt.test.ts │ └── index.ts │ ├── hex.ts │ ├── ints.ts │ ├── maybeData.ts │ ├── stringify.ts │ ├── test_utils.ts │ └── types.ts ├── tsconfig.json └── workers-tsconfig.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: HarmonicLabs 4 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: push 4 | 5 | jobs: 6 | CI: 7 | strategy: 8 | matrix: 9 | os: [windows-latest, ubuntu-latest, macos-latest] 10 | runs-on: ${{ matrix.os }} 11 | 12 | steps: 13 | - name: Check out repository code 14 | uses: actions/checkout@v3 15 | 16 | - uses: actions/setup-node@v3 17 | with: 18 | node-version: 16 19 | 20 | - name: Install dependencies 21 | run: npm ci 22 | 23 | - name: Build 24 | run: npm run build 25 | 26 | - name: Run tests 27 | run: npm test 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependecies can be retreived via ```npm install``` as long ```package.json``` is present 2 | node_modules/ 3 | # can be retreived by running tests 4 | coverage/ 5 | 6 | .vscode* 7 | 8 | .npmrc* 9 | 10 | # npm pack 11 | *.tgz 12 | 13 | # output of build 14 | dist 15 | 16 | *private.test.ts 17 | 18 | src/offchain/tx/builder/__tests__/TxBuilder.contracts.test.ts 19 | 20 | # workers compilation 21 | tsc-out/ 22 | src/offchain/tx/builder/rollup-out/ -------------------------------------------------------------------------------- /assets/docs_on_hover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarmonicLabs/plu-ts/73040becada7092ce7193467776775d72d8af392/assets/docs_on_hover.gif -------------------------------------------------------------------------------- /babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@babel/preset-typescript",['@babel/preset-env', {targets: {node: 'current'}}]], 3 | }; -------------------------------------------------------------------------------- /catalyst-proposals.md: -------------------------------------------------------------------------------- 1 | # plu-ts related Catalyst proposals 2 | 3 | - Fund 12: none 4 | - Fund 11: 5 | - [HLabs: plu-ts - ts framework for Cardano smart contracts](https://cardano.ideascale.com/c/idea/111482) FUNDED 6 | - Fund 10: 7 | - [plu-ts Typescript smart-contracts - road to production](https://cardano.ideascale.com/c/idea/100658) NOT FUNDED 8 | - [plu-ts - 0 to full Cardano dApp tutorial/documentation](https://cardano.ideascale.com/c/idea/101023) FUNDED 9 | - Fund 9: 10 | - [(passed, not founded) Typescript smart-contracts](https://cardano.ideascale.com/c/idea/414103) NOT FUNDED 11 | - [(passed, not founded) 100% Typescript offchain code](https://cardano.ideascale.com/c/idea/414144) NOT FUNDED 12 | - Fund 8: 13 | - [(passed, not founded) Offchain Typescript library](https://cardano.ideascale.com/c/idea/396949) NOT FUNDED -------------------------------------------------------------------------------- /sponsors.md: -------------------------------------------------------------------------------- 1 | # Sponsors ❤️ 2 | 3 | Here's a list of supportes of this project. 4 | 5 | Everyone of them is special and is contribuitng in making this software aviable for everyone. 6 | 7 | - [VledicFranco](https://github.com/VledicFranco) by [Drunken Dragon Entertainment](https://twitter.com/DrunkenDragnEnt) 8 | - [KtorZ](https://github.com/KtorZ) 9 | - [eddiefleurent](https://github.com/eddiefleurent) 10 | -------------------------------------------------------------------------------- /src/IR/IRNodeKind.ts: -------------------------------------------------------------------------------- 1 | 2 | export enum IRNodeKind { 3 | Var = 0, 4 | Func = 1, 5 | App = 2, 6 | Const = 3, 7 | Native = 4, 8 | Letted = 5, 9 | Hoisted = 6, 10 | Error = 7, 11 | Forced = 8, 12 | Delayed = 9, 13 | Constr = 10, 14 | Case = 11, 15 | Recursive = 12, 16 | SelfCall = 13 17 | } 18 | Object.freeze( IRNodeKind ); -------------------------------------------------------------------------------- /src/IR/IRNodes/BaseIRMetadata.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface BaseIRMetadata { 3 | name?: string | undefined 4 | } 5 | -------------------------------------------------------------------------------- /src/IR/IRNodes/IRNative/__tests__/IRNative.hash.test.ts: -------------------------------------------------------------------------------- 1 | import { IRNative } from ".."; 2 | 3 | describe("IRNative.hash", () => { 4 | 5 | test("sndPair != unConstrData", () => { 6 | 7 | expect( IRNative.sndPair.tag ) 8 | .not.toEqual( IRNative.unConstrData.tag ); 9 | 10 | expect( IRNative.sndPair.hash ) 11 | .not.toEqual( IRNative.unConstrData.hash ); 12 | 13 | }); 14 | 15 | }); -------------------------------------------------------------------------------- /src/IR/IRNodes/IRNative/isForcedNative.ts: -------------------------------------------------------------------------------- 1 | import { IRNative } from "./index"; 2 | import { IRTerm } from "../../IRTerm"; 3 | import { IRNativeTag } from "./IRNativeTag"; 4 | 5 | function isForcedNativeTag( tag: IRNativeTag ): boolean 6 | { 7 | return ( 8 | tag === IRNativeTag.strictIfThenElse || 9 | tag === IRNativeTag.chooseUnit || 10 | tag === IRNativeTag.trace || 11 | tag === IRNativeTag.mkCons || 12 | tag === IRNativeTag.headList || 13 | tag === IRNativeTag.tailList || 14 | tag === IRNativeTag.nullList || 15 | tag === IRNativeTag.chooseData || 16 | tag === IRNativeTag.fstPair || 17 | tag === IRNativeTag.sndPair || 18 | tag === IRNativeTag.strictChooseList 19 | ); 20 | } 21 | 22 | export function isForcedNative( node: IRTerm ): node is IRNative 23 | { 24 | return node instanceof IRNative && isForcedNativeTag( node.tag ); 25 | } -------------------------------------------------------------------------------- /src/IR/IRNodes/__tests__/IRFunc.body.test.ts: -------------------------------------------------------------------------------- 1 | import { IRFunc } from "../IRFunc"; 2 | import { IRVar } from "../IRVar" 3 | 4 | 5 | describe("IRFunc.body", () => { 6 | 7 | test("same body", () => { 8 | 9 | const body = new IRVar(0); 10 | 11 | const func = new IRFunc( 12 | 1, 13 | body 14 | ); 15 | 16 | expect( 17 | func.body 18 | ).toEqual( 19 | body 20 | ); 21 | 22 | }) 23 | }) -------------------------------------------------------------------------------- /src/IR/IRNodes/__tests__/IRLetted.getLettedTerms.test.ts: -------------------------------------------------------------------------------- 1 | import { int } from "../../../pluts"; 2 | import { IRApp } from "../IRApp"; 3 | import { IRConst } from "../IRConst"; 4 | import { IRDelayed } from "../IRDelayed"; 5 | import { IRForced } from "../IRForced"; 6 | import { IRLetted, getLettedTerms } from "../IRLetted"; 7 | import { IRNative } from "../IRNative"; 8 | import { IRNativeTag } from "../IRNative/IRNativeTag"; 9 | 10 | describe("getLettedTerms", () => { 11 | 12 | test("single letted", () => { 13 | 14 | const root = new IRForced( 15 | new IRDelayed( 16 | new IRApp( 17 | new IRLetted( 18 | 0, 19 | new IRApp( 20 | new IRNative( IRNativeTag.addInteger ), 21 | new IRConst( int, 2 ) 22 | ) 23 | ), 24 | new IRConst( int, 2 ) 25 | ) 26 | ) 27 | ); 28 | 29 | expect( getLettedTerms( root ).length ).toEqual( 1 ); 30 | 31 | }) 32 | }) -------------------------------------------------------------------------------- /src/IR/IRNodes/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./IRApp"; 2 | export * from "./IRConst"; 3 | export * from "./IRDelayed"; 4 | export * from "./IRError"; 5 | export * from "./IRForced"; 6 | export * from "./IRFunc"; 7 | export * from "./IRHoisted"; 8 | export * from "./IRLetted"; 9 | export * from "./IRNative"; 10 | export * from "./IRVar"; 11 | export * from "./IRConstr"; 12 | export * from "./IRCase"; -------------------------------------------------------------------------------- /src/IR/IRNodes/utils/dependsByDbns.ts: -------------------------------------------------------------------------------- 1 | import { IRTerm } from "../../IRTerm"; 2 | import { iterTree } from "../../toUPLC/_internal/iterTree"; 3 | import { IRSelfCall } from "../IRSelfCall"; 4 | import { IRVar } from "../IRVar"; 5 | 6 | /** 7 | * returns true if the term depends on *ANY* of the deBrujin indices specified 8 | */ 9 | export function dependsByDbns( term: IRTerm, depsDbns: readonly number[] ): boolean 10 | { 11 | if( depsDbns.length === 0 ) return false; 12 | let doesDepend = false; 13 | iterTree( term, 14 | (node, diff) => { 15 | if( 16 | node instanceof IRVar || 17 | node instanceof IRSelfCall 18 | ) 19 | { 20 | doesDepend = doesDepend || depsDbns.some( dbn => { 21 | const realDbn = dbn + diff; 22 | // realDbn === 0 implies no variables are in scope 23 | // so if node.dbn === 0 and realDbn === 1 then the 24 | // variable is pointing to that definition 25 | return node.dbn === realDbn; 26 | }); 27 | } 28 | }, 29 | // shouldSkipNode 30 | undefined, 31 | // shouldStop 32 | () => doesDepend // exit early 33 | ); 34 | return doesDepend; 35 | } -------------------------------------------------------------------------------- /src/IR/IRNodes/utils/isClosedAtDbn.ts: -------------------------------------------------------------------------------- 1 | import { IRTerm } from "../../IRTerm"; 2 | import { iterTree } from "../../toUPLC/_internal/iterTree"; 3 | import { IRSelfCall } from "../IRSelfCall"; 4 | import { IRVar } from "../IRVar"; 5 | 6 | export function isClosedAtDbn( term: IRTerm, dbn: number = 0 ): boolean 7 | { 8 | let isClosed = true; 9 | iterTree( term, 10 | (node, diff) => { 11 | const realDbn = dbn + diff; 12 | if( 13 | node instanceof IRVar || 14 | node instanceof IRSelfCall 15 | ) 16 | { 17 | // realDbn === 0 implies no variables are in scope 18 | // so if node.dbn === 0 and realDbn === 0 then the variable is open 19 | // and is pointing outside of the scope 20 | isClosed = isClosed || node.dbn < realDbn; 21 | } 22 | 23 | }, 24 | // shouldSkipNode 25 | undefined, 26 | // shouldStop 27 | () => !isClosed // exit early 28 | ) 29 | return isClosed; 30 | } -------------------------------------------------------------------------------- /src/IR/IRNodes/utils/makeArrayLikeProxy.ts: -------------------------------------------------------------------------------- 1 | 2 | export function makeArrayLikeProxy( 3 | arr: ArrayLike, 4 | isValidElem: ( elem: T ) => boolean, 5 | initModifyElem: ( elem: T ) => T, 6 | modifyElem: ( elem: T, oldElem: T ) => T 7 | ): ArrayLike 8 | { 9 | const like = {} as ArrayLike; 10 | 11 | Object.defineProperty( 12 | like, "length", { 13 | value: arr.length, 14 | writable: false, 15 | enumerable: false, 16 | configurable: false 17 | } 18 | ); 19 | 20 | const clonedArr = Array.from( arr ); 21 | 22 | for( let i = 0; i < arr.length; i++ ) 23 | { 24 | clonedArr[i] = initModifyElem( arr[i] ); 25 | Object.defineProperty( 26 | like, i, { 27 | get: () => clonedArr[i], 28 | set: ( newElem: T ) => { 29 | if( isValidElem( newElem ) ) 30 | clonedArr[i] = modifyElem( newElem, clonedArr[i] ); 31 | 32 | return newElem; 33 | }, 34 | enumerable: true, 35 | configurable: false 36 | } 37 | ); 38 | } 39 | 40 | Object.defineProperty( 41 | like, Symbol.iterator, { 42 | value: iterArrayLikeProxy.bind( like ), 43 | writable: false, 44 | enumerable: false, 45 | configurable: false 46 | } 47 | ); 48 | 49 | return like; 50 | } 51 | 52 | function* iterArrayLikeProxy( this: ArrayLike ) 53 | { 54 | for( let i = 0; i < this.length; i++ ) yield this[i]; 55 | } 56 | -------------------------------------------------------------------------------- /src/IR/IRNodes/utils/mapArrayLike.ts: -------------------------------------------------------------------------------- 1 | 2 | export function mapArrayLike( arr: ArrayLike, fn: ( elem: T, idx: number, thisArr: ArrayLike ) => Out ): Out[] 3 | { 4 | const len = arr.length; 5 | const result = new Array( len ); 6 | 7 | for( let i = 0; i < len; i++ ) 8 | { 9 | result[i] = fn( arr[i], i, arr ); 10 | } 11 | 12 | return result; 13 | } -------------------------------------------------------------------------------- /src/IR/IRTerm.ts: -------------------------------------------------------------------------------- 1 | import { IRApp } from "./IRNodes/IRApp"; 2 | import { IRConst } from "./IRNodes/IRConst"; 3 | import { IRFunc } from "./IRNodes/IRFunc"; 4 | import { IRHoisted } from "./IRNodes/IRHoisted"; 5 | import { IRLetted } from "./IRNodes/IRLetted"; 6 | import { IRNative } from "./IRNodes/IRNative"; 7 | import { IRError } from "./IRNodes/IRError"; 8 | import { IRDelayed } from "./IRNodes/IRDelayed"; 9 | import { IRForced } from "./IRNodes/IRForced"; 10 | import { IRVar } from "./IRNodes/IRVar"; 11 | import { IRConstr } from "./IRNodes/IRConstr"; 12 | import { IRCase } from "./IRNodes/IRCase"; 13 | import { IRRecursive } from "./IRNodes/IRRecursive"; 14 | import { IRSelfCall } from "./IRNodes/IRSelfCall"; 15 | 16 | export type IRTerm 17 | = IRVar 18 | | IRFunc 19 | | IRApp 20 | | IRConst 21 | | IRNative 22 | | IRLetted 23 | | IRHoisted 24 | | IRError 25 | | IRForced 26 | | IRDelayed 27 | | IRConstr 28 | | IRCase 29 | | IRRecursive 30 | | IRSelfCall; -------------------------------------------------------------------------------- /src/IR/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./IRTerm"; 2 | export * from "./IRNodes"; 3 | export * from "./interfaces"; 4 | export * from "./toUPLC"; 5 | export * from "./utils"; -------------------------------------------------------------------------------- /src/IR/interfaces/IHash.ts: -------------------------------------------------------------------------------- 1 | import { IRHash } from "../IRHash" 2 | 3 | export interface IHash { 4 | readonly hash: IRHash // supposed to be a getter only 5 | markHashAsInvalid: () => void // something changed 6 | isHashPresent: () => boolean 7 | } -------------------------------------------------------------------------------- /src/IR/interfaces/IIRParent.ts: -------------------------------------------------------------------------------- 1 | import { IRTerm } from "../IRTerm"; 2 | 3 | export interface IIRParent { 4 | parent: IRTerm | undefined 5 | } -------------------------------------------------------------------------------- /src/IR/interfaces/IRMetadata.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface IRMetadata { 3 | meta: object 4 | }; -------------------------------------------------------------------------------- /src/IR/interfaces/ToIR.ts: -------------------------------------------------------------------------------- 1 | import { IRTerm } from "../IRTerm"; 2 | import { CompilerOptions } from "../toUPLC/CompilerOptions"; 3 | 4 | export interface ToIR { 5 | toIR: ( config: CompilerOptions, dbn?: number | bigint ) => IRTerm 6 | } -------------------------------------------------------------------------------- /src/IR/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./IHash"; 2 | export * from "./IIRParent"; 3 | export * from "./IRMetadata"; 4 | export * from "./ToIR"; -------------------------------------------------------------------------------- /src/IR/toUPLC/__tests__/compile.pfactorial.test.ts: -------------------------------------------------------------------------------- 1 | import { precursive, pfn, lam, int, pif } from "../../.." 2 | 3 | const pfactorial = precursive( 4 | pfn([ 5 | lam( int, int ), // self 6 | int 7 | ], int) 8 | (( self, n ) => 9 | pif( int ) 10 | .$( n.ltEq( 1 ) ) 11 | .then( 1 ) 12 | .else( 13 | n.mult( self.$( n.sub( 1 ) ) ) 14 | ) 15 | ) 16 | ) 17 | 18 | test("compiles", () => { 19 | 20 | const uplc = pfactorial.toUPLC() 21 | 22 | }) -------------------------------------------------------------------------------- /src/IR/toUPLC/__tests__/compileIR.test.ts: -------------------------------------------------------------------------------- 1 | import { UPLCVar, Lambda } from "@harmoniclabs/uplc"; 2 | import { IRFunc } from "../../IRNodes/IRFunc"; 3 | import { IRVar } from "../../IRNodes/IRVar"; 4 | import { _irToUplc } from "../_internal/_irToUplc"; 5 | 6 | 7 | describe("compileIRToUPLC", () => { 8 | 9 | test("IRVar", () => { 10 | 11 | const ir = new IRVar( 0 ); 12 | const _irUPlC = _irToUplc( ir ).term; 13 | 14 | expect( 15 | _irUPlC 16 | ).toEqual( 17 | new UPLCVar( 0 ) 18 | ) 19 | }) 20 | 21 | test("simple",() => { 22 | 23 | const idIR = new IRFunc( 1, new IRVar(0) ); 24 | 25 | const idUPLC = _irToUplc( idIR ).term; 26 | 27 | const expected = new Lambda( new UPLCVar( 0 ) ); 28 | 29 | expect( 30 | idUPLC 31 | ).toEqual( 32 | expected 33 | ); 34 | 35 | }); 36 | 37 | }); -------------------------------------------------------------------------------- /src/IR/toUPLC/_internal/__tests__/IR.compile._modifyChildFromTo.test.ts: -------------------------------------------------------------------------------- 1 | import { int } from "../../../../pluts"; 2 | import { IRConst } from "../../../IRNodes/IRConst"; 3 | import { IRForced } from "../../../IRNodes/IRForced"; 4 | import { IRHoisted } from "../../../IRNodes/IRHoisted"; 5 | import { _modifyChildFromTo } from "../_modifyChildFromTo"; 6 | 7 | describe("_modifyChildFromTo", () => { 8 | 9 | test("inline hoisted", () => { 10 | const elem = new IRConst( int, 0 ); 11 | const hoisted = new IRHoisted( elem ); 12 | 13 | const someParent = new IRForced( hoisted ); 14 | 15 | _modifyChildFromTo( 16 | hoisted.parent, 17 | hoisted, 18 | hoisted.hoisted 19 | ); 20 | 21 | expect( 22 | someParent.forced.hash 23 | ).toEqual( 24 | elem.hash 25 | ); 26 | 27 | }) 28 | }) -------------------------------------------------------------------------------- /src/IR/toUPLC/_internal/__tests__/IR.compile.getDebruijnInTerm.test.ts: -------------------------------------------------------------------------------- 1 | import { int } from "../../../../pluts"; 2 | import { IRConst } from "../../../IRNodes/IRConst"; 3 | import { IRForced } from "../../../IRNodes/IRForced"; 4 | import { IRFunc } from "../../../IRNodes/IRFunc"; 5 | import { getDebruijnInTerm } from "../getDebruijnInTerm" 6 | 7 | describe("getDebruijnInTerm", () => { 8 | 9 | const target = new IRConst( int, 0 ); 10 | 11 | test("zero", () => { 12 | 13 | expect( 14 | getDebruijnInTerm( 15 | new IRForced( target ), 16 | target 17 | ) 18 | ).toBe( 0 ); 19 | 20 | }); 21 | 22 | test("one", () => { 23 | 24 | expect( 25 | getDebruijnInTerm( 26 | new IRFunc( 27 | 1, 28 | target 29 | ), 30 | target 31 | ) 32 | ).toBe( 1 ); 33 | 34 | }); 35 | 36 | test("4", () => { 37 | 38 | expect( 39 | getDebruijnInTerm( 40 | new IRFunc( 41 | 4, 42 | target 43 | ), 44 | target 45 | ) 46 | ).toBe( 4 ); 47 | 48 | }); 49 | 50 | 51 | test("deep equality (hash equality)", () => { 52 | 53 | expect( 54 | getDebruijnInTerm( 55 | new IRFunc( 56 | 4, 57 | target.clone() 58 | ), 59 | target 60 | ) 61 | ).toBe( 4 ); 62 | 63 | }); 64 | 65 | }) -------------------------------------------------------------------------------- /src/IR/toUPLC/_internal/_makeAllNegativeNativesHoisted.ts: -------------------------------------------------------------------------------- 1 | import { IRHoisted } from "../../IRNodes/IRHoisted"; 2 | import { IRNative } from "../../IRNodes/IRNative"; 3 | import { IRTerm } from "../../IRTerm"; 4 | import { _modifyChildFromTo } from "./_modifyChildFromTo"; 5 | import { iterTree } from "./iterTree"; 6 | 7 | export function _makeAllNegativeNativesHoisted( term: IRTerm ): void 8 | { 9 | iterTree( term, elem => { 10 | if( elem instanceof IRNative && !(elem.parent instanceof IRHoisted) ) 11 | { 12 | _modifyChildFromTo( 13 | elem.parent, 14 | elem, 15 | new IRHoisted( elem ) 16 | ); 17 | return true; 18 | } 19 | }) 20 | } -------------------------------------------------------------------------------- /src/IR/toUPLC/_internal/depth.ts: -------------------------------------------------------------------------------- 1 | import { IRTerm } from "../../IRTerm"; 2 | 3 | export type IRTermWithDepth = IRTerm & { depth: number }; 4 | 5 | export function defineDepth( term: IRTerm, depth: number ): IRTermWithDepth 6 | { 7 | return Object.defineProperty( 8 | term, "depth", { 9 | value: depth, 10 | writable: true, 11 | enumerable: true, 12 | configurable: false 13 | } 14 | ) as any; 15 | } -------------------------------------------------------------------------------- /src/IR/toUPLC/_internal/lowestCommonAncestor.ts: -------------------------------------------------------------------------------- 1 | import type { IRTerm } from "../../IRTerm"; 2 | import { isIRTerm } from "../../utils/isIRTerm"; 3 | 4 | // type IRWithDepth = IRTerm & { depth: number } 5 | 6 | export function getDepthInMaxScope( term: IRTerm, maxScope: IRTerm ): number | undefined 7 | { 8 | let depth = 0; 9 | 10 | while( term.parent !== maxScope ) 11 | { 12 | depth++; 13 | if( term.parent === undefined ) return undefined 14 | term = term.parent; 15 | } 16 | 17 | return depth; 18 | } 19 | 20 | export function lowestCommonAncestor( n1: IRTerm | undefined, n2: IRTerm | undefined, maxScope: IRTerm ): IRTerm | undefined 21 | { 22 | if( !isIRTerm( n1 ) || !isIRTerm( n2 ) ) return undefined; 23 | 24 | let d1: number | undefined = getDepthInMaxScope( n1, maxScope ); 25 | let d2: number | undefined = getDepthInMaxScope( n2, maxScope ); 26 | 27 | if( d1 === undefined || d2 === undefined ) 28 | { 29 | return undefined; 30 | } 31 | 32 | let diff: number = d1 - d2; 33 | 34 | // If node b is deeper, swap node a and node b 35 | if (diff < 0) 36 | { 37 | let temp = n1; 38 | n1 = n2; 39 | n2 = temp; 40 | diff = -diff; 41 | } 42 | 43 | // Move n1 up until it reaches the same level as n2 44 | while( diff-- > 0 && n1.parent ) 45 | n1 = n1.parent; 46 | 47 | // Now n1 and n2 are at same levels 48 | while( n1 && n2 ) 49 | { 50 | if(n1 === n2) 51 | return n1; 52 | 53 | // undefined will exit the loop 54 | n1 = n1.parent; 55 | n2 = n2.parent; 56 | } 57 | 58 | return undefined; 59 | } 60 | -------------------------------------------------------------------------------- /src/IR/toUPLC/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./compileIRToUPLC"; -------------------------------------------------------------------------------- /src/IR/toUPLC/subRoutines/handleLetted/findHighestRecursiveParent.ts: -------------------------------------------------------------------------------- 1 | import { IRRecursive } from "../../../IRNodes/IRRecursive"; 2 | import { IRTerm } from "../../../IRTerm"; 3 | import { IRApp, IRNative } from "../../../IRNodes"; 4 | import { IRNativeTag } from "../../../IRNodes/IRNative/IRNativeTag"; 5 | 6 | export type RecursiveIRNode = IRRecursive | IRApp; 7 | 8 | export function findHighestRecursiveParent( term: IRTerm, maxScope: IRTerm ): RecursiveIRNode | undefined 9 | { 10 | let highest: RecursiveIRNode | undefined = undefined; 11 | while( 12 | term.parent !== maxScope && 13 | term.parent !== undefined 14 | ) 15 | { 16 | if( isRecursiveNode( term ) ) highest = term; 17 | term = term.parent; 18 | } 19 | return highest; 20 | } 21 | 22 | function isRecursiveNode( term: IRTerm ): term is RecursiveIRNode 23 | { 24 | return ( 25 | term instanceof IRRecursive || 26 | ( 27 | term instanceof IRApp && 28 | term.fn instanceof IRNative && 29 | term.fn.tag === IRNativeTag.z_comb 30 | ) 31 | ); 32 | } -------------------------------------------------------------------------------- /src/IR/toUPLC/subRoutines/inlineSingleUseApplications.ts: -------------------------------------------------------------------------------- 1 | import { IRVar } from "../../IRNodes/IRVar"; 2 | import { IRTerm } from "../../IRTerm"; 3 | import { iterTree } from "../_internal/iterTree"; 4 | 5 | 6 | function hasAtLeastNVarsAtDbn( term: IRTerm, baseDbn: number = 0 ): boolean 7 | { 8 | let n = 0; 9 | 10 | iterTree( term, 11 | (node, dbn) => { 12 | if( node instanceof IRVar && node.dbn === baseDbn + dbn ) n++; 13 | }, 14 | undefined, // shouldSkipNode 15 | () => n > 1 // shouldExit 16 | ); 17 | 18 | return n > 1; 19 | } -------------------------------------------------------------------------------- /src/IR/toUPLC/subRoutines/replaceClosedLettedWithHoisted.ts: -------------------------------------------------------------------------------- 1 | import { IRHoisted } from "../../IRNodes/IRHoisted"; 2 | import { IRLetted } from "../../IRNodes/IRLetted"; 3 | import { IRTerm } from "../../IRTerm"; 4 | import { isClosedIRTerm } from "../../utils/isClosedIRTerm"; 5 | import { _modifyChildFromTo } from "../_internal/_modifyChildFromTo"; 6 | import { iterTree } from "../_internal/iterTree"; 7 | 8 | export function replaceClosedLettedWithHoisted( root: IRTerm ) 9 | { 10 | iterTree( root, (node) => { 11 | if( node instanceof IRLetted && isClosedIRTerm( node.value ) ) 12 | { 13 | _modifyChildFromTo( 14 | node.parent, 15 | node, 16 | new IRHoisted( 17 | node.value, 18 | node.meta 19 | ) 20 | ); 21 | return true; 22 | } 23 | }); 24 | } -------------------------------------------------------------------------------- /src/IR/toUPLC/subRoutines/replaceForcedNativesWithHoisted.ts: -------------------------------------------------------------------------------- 1 | import { IRHoisted } from "../../IRNodes/IRHoisted"; 2 | import { isForcedNative } from "../../IRNodes/IRNative/isForcedNative"; 3 | import { IRTerm } from "../../IRTerm"; 4 | import { _modifyChildFromTo } from "../_internal/_modifyChildFromTo"; 5 | import { iterTree } from "../_internal/iterTree"; 6 | 7 | export function replaceForcedNativesWithHoisted( term: IRTerm ): void 8 | { 9 | iterTree( term, ( node, _dbn ) => { 10 | if( isForcedNative( node ) ) 11 | { 12 | _modifyChildFromTo( 13 | node.parent, 14 | node, 15 | new IRHoisted( node ) 16 | ); 17 | } 18 | }); 19 | } -------------------------------------------------------------------------------- /src/IR/toUPLC/subRoutines/replaceHoistedWithLetted.ts: -------------------------------------------------------------------------------- 1 | import { IRFunc } from "../../IRNodes"; 2 | import { IRHoisted } from "../../IRNodes/IRHoisted"; 3 | import { IRLetted } from "../../IRNodes/IRLetted"; 4 | import { IRRecursive } from "../../IRNodes/IRRecursive"; 5 | import { IRTerm } from "../../IRTerm"; 6 | import { getChildren } from "../../tree_utils/getChildren"; 7 | import { _modifyChildFromTo } from "../_internal/_modifyChildFromTo"; 8 | import { findAll } from "../_internal/findAll"; 9 | import { sanifyTree } from "./sanifyTree"; 10 | 11 | 12 | export function replaceHoistedWithLetted( term: IRTerm ): void 13 | { 14 | const allHoisted: IRHoisted[] = findAll( term, node => node instanceof IRHoisted ) as IRHoisted[]; 15 | 16 | for( const hoisted of allHoisted ) 17 | { 18 | const parent = hoisted.parent!; 19 | const letted = new IRLetted( 20 | 0x0fffffff, // doesn't matter since closed term 21 | hoisted.hoisted, 22 | { isClosed: true } 23 | ); 24 | letted.hash; // precompute 25 | 26 | // replace hoisted with letted 27 | _modifyChildFromTo( parent, hoisted, letted ); 28 | } 29 | 30 | // sanifyTree( term ); 31 | } -------------------------------------------------------------------------------- /src/IR/toUPLC/subRoutines/replaceNatives/index.ts: -------------------------------------------------------------------------------- 1 | import { IRNative } from "../../../IRNodes/IRNative"; 2 | import { IRTerm } from "../../../IRTerm"; 3 | import { _modifyChildFromTo } from "../../_internal/_modifyChildFromTo"; 4 | import { iterTree } from "../../_internal/iterTree"; 5 | import { nativeToIR } from "./nativeToIR"; 6 | 7 | export function replaceNativesAndReturnRoot( tree: IRTerm ): IRTerm 8 | { 9 | if( tree instanceof IRNative ) 10 | { 11 | return nativeToIR( tree ); 12 | } 13 | 14 | iterTree( tree, elem => { 15 | if( elem instanceof IRNative && elem.tag < 0 ) 16 | { 17 | _modifyChildFromTo( 18 | elem.parent, 19 | elem, 20 | nativeToIR( elem ) 21 | ); 22 | return true; 23 | } 24 | }); 25 | return tree; 26 | } -------------------------------------------------------------------------------- /src/IR/tree_utils/_ir_apps.ts: -------------------------------------------------------------------------------- 1 | import { IRApp } from "../IRNodes/IRApp"; 2 | import { IRTerm } from "../IRTerm"; 3 | 4 | export function _ir_apps( ...terms: [ IRTerm, IRTerm, ...IRTerm[] ] ): IRApp 5 | { 6 | let term = new IRApp( terms[0], terms[1] ); 7 | for( let i = 2; i < terms.length; i++ ) 8 | { 9 | term = new IRApp( 10 | term, 11 | terms[i] 12 | ); 13 | } 14 | return term; 15 | } -------------------------------------------------------------------------------- /src/IR/tree_utils/_ir_let.ts: -------------------------------------------------------------------------------- 1 | import { IRApp, IRFunc } from "../IRNodes"; 2 | import { IRTerm } from "../IRTerm"; 3 | 4 | export function _ir_let( value: IRTerm, body: IRTerm ): IRApp 5 | { 6 | return new IRApp( 7 | new IRFunc(1, body), 8 | value 9 | ); 10 | } -------------------------------------------------------------------------------- /src/IR/tree_utils/getChildren.ts: -------------------------------------------------------------------------------- 1 | import { IRCase } from "../IRNodes/IRCase"; 2 | import { IRApp } from "../IRNodes/IRApp"; 3 | import { IRDelayed } from "../IRNodes/IRDelayed"; 4 | import { IRForced } from "../IRNodes/IRForced"; 5 | import { IRFunc } from "../IRNodes/IRFunc"; 6 | import { IRHoisted } from "../IRNodes/IRHoisted"; 7 | import { IRLetted } from "../IRNodes/IRLetted"; 8 | import { IRTerm } from "../IRTerm"; 9 | import { IRConstr } from "../IRNodes/IRConstr"; 10 | import { IRRecursive } from "../IRNodes/IRRecursive"; 11 | 12 | export function getChildren( term: IRTerm ): IRTerm[] 13 | { 14 | if( term instanceof IRApp ) return [ term.fn, term.arg ]; 15 | if( term instanceof IRCase ) return [ term.constrTerm, ...term.continuations ]; 16 | if( term instanceof IRConstr ) return [ ...term.fields ]; 17 | if( term instanceof IRFunc ) return [ term.body ]; 18 | if( term instanceof IRRecursive ) return [ term.body ]; 19 | if( term instanceof IRDelayed ) return [ term.delayed ]; 20 | if( term instanceof IRForced ) return [ term.forced ]; 21 | if( term instanceof IRHoisted ) return [ term.hoisted ]; 22 | if( term instanceof IRLetted ) return [ term.value ]; 23 | 24 | // term 25 | // IRVar | IRConst | IRNative | IRError | IRSelfCall 26 | // none have children 27 | return []; 28 | } -------------------------------------------------------------------------------- /src/IR/tree_utils/getRoot.ts: -------------------------------------------------------------------------------- 1 | import { IRTerm } from "../IRTerm"; 2 | 3 | export function getRoot( node: IRTerm ): IRTerm 4 | { 5 | let root = node; 6 | while( root.parent ) root = root.parent; 7 | return root; 8 | } -------------------------------------------------------------------------------- /src/IR/utils/MutArrayLike.ts: -------------------------------------------------------------------------------- 1 | export interface MutArrayLike { 2 | readonly length: number; 3 | [n: number]: T; 4 | [Symbol.iterator](): IterableIterator; 5 | } -------------------------------------------------------------------------------- /src/IR/utils/concatUint8Arr.ts: -------------------------------------------------------------------------------- 1 | 2 | export function concatUint8Arr( ...arrs: (Uint8Array | Uint32Array)[] ): Uint8Array 3 | { 4 | arrs = arrs .map( arr => arr instanceof Uint8Array ? arr : new Uint8Array( arr.buffer ) ); 5 | 6 | const len = arrs.reduce( (acc, arr) => acc + arr.length, 0 ); 7 | const res = new Uint8Array(len); 8 | 9 | let idx = 0; 10 | for(const arr of arrs) 11 | { 12 | res.set( arr, idx ); 13 | idx += arr.length; 14 | } 15 | return res; 16 | } -------------------------------------------------------------------------------- /src/IR/utils/equalIRTerm.ts: -------------------------------------------------------------------------------- 1 | import { equalIrHash } from "../IRHash"; 2 | import { IRTerm } from "../IRTerm"; 3 | 4 | /** 5 | * forces hash evaluation 6 | */ 7 | export function equalIRTermHash( a: IRTerm, b: IRTerm ): boolean 8 | { 9 | return a === b || equalIrHash( a.hash, b.hash ); 10 | } 11 | 12 | /** 13 | * only checks the hash if already present ON BOTH 14 | * 15 | * otherwise it assumes the terms are different and returns false 16 | * (even if they might be the same) 17 | */ 18 | export function shallowEqualIRTermHash( a: IRTerm, b: IRTerm ): boolean 19 | { 20 | if( a === b ) return true; 21 | 22 | return ( 23 | a.isHashPresent() && b.isHashPresent() && 24 | equalIrHash( a.hash, b.hash ) 25 | ); 26 | } -------------------------------------------------------------------------------- /src/IR/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./isClosedIRTerm"; 2 | export * from "./isIRTerm"; 3 | export * from "./showIR"; -------------------------------------------------------------------------------- /src/IR/utils/isIRParentTerm.ts: -------------------------------------------------------------------------------- 1 | import { IRApp } from "../IRNodes/IRApp"; 2 | import { IRCase } from "../IRNodes/IRCase"; 3 | import { IRConstr } from "../IRNodes/IRConstr"; 4 | import { IRDelayed } from "../IRNodes/IRDelayed"; 5 | import { IRForced } from "../IRNodes/IRForced"; 6 | import { IRFunc } from "../IRNodes/IRFunc"; 7 | import { IRHoisted } from "../IRNodes/IRHoisted"; 8 | import { IRLetted } from "../IRNodes/IRLetted"; 9 | import { IRRecursive } from "../IRNodes/IRRecursive"; 10 | import type { IRTerm } from "../IRTerm"; 11 | 12 | export type IRParentTerm 13 | = // IRVar 14 | // | IRSelfCall 15 | | IRFunc 16 | | IRApp 17 | // | IRConst 18 | // | IRNative 19 | | IRLetted 20 | | IRHoisted 21 | // | IRError 22 | | IRForced 23 | | IRDelayed 24 | | IRConstr 25 | | IRCase 26 | | IRRecursive; 27 | 28 | export function isIRParentTerm( stuff: T | undefined ): stuff is (T & IRParentTerm) 29 | { 30 | return ( 31 | // stuff instanceof IRVar || 32 | // stuff instanceof IRSelfCall || 33 | stuff instanceof IRFunc || 34 | stuff instanceof IRRecursive || 35 | stuff instanceof IRApp || 36 | // stuff instanceof IRConst || 37 | // stuff instanceof IRNative || 38 | stuff instanceof IRLetted || 39 | stuff instanceof IRHoisted || 40 | // stuff instanceof IRError || 41 | stuff instanceof IRForced || 42 | stuff instanceof IRDelayed || 43 | stuff instanceof IRConstr || 44 | stuff instanceof IRCase 45 | ); 46 | } -------------------------------------------------------------------------------- /src/IR/utils/isIRTerm.ts: -------------------------------------------------------------------------------- 1 | import { IRApp } from "../IRNodes/IRApp"; 2 | import { IRCase } from "../IRNodes/IRCase"; 3 | import { IRConst } from "../IRNodes/IRConst"; 4 | import { IRConstr } from "../IRNodes/IRConstr"; 5 | import { IRDelayed } from "../IRNodes/IRDelayed"; 6 | import { IRError } from "../IRNodes/IRError"; 7 | import { IRForced } from "../IRNodes/IRForced"; 8 | import { IRFunc } from "../IRNodes/IRFunc"; 9 | import { IRHoisted } from "../IRNodes/IRHoisted"; 10 | import { IRLetted } from "../IRNodes/IRLetted"; 11 | import { IRNative } from "../IRNodes/IRNative"; 12 | import { IRRecursive } from "../IRNodes/IRRecursive"; 13 | import { IRSelfCall } from "../IRNodes/IRSelfCall"; 14 | import { IRVar } from "../IRNodes/IRVar"; 15 | import type { IRTerm } from "../IRTerm"; 16 | 17 | export function isIRTerm( stuff: any ): stuff is IRTerm 18 | { 19 | return ( 20 | stuff instanceof IRVar || 21 | stuff instanceof IRSelfCall || 22 | stuff instanceof IRFunc || 23 | stuff instanceof IRRecursive || 24 | stuff instanceof IRApp || 25 | stuff instanceof IRConst || 26 | stuff instanceof IRNative || 27 | stuff instanceof IRLetted || 28 | stuff instanceof IRHoisted || 29 | stuff instanceof IRError || 30 | stuff instanceof IRForced || 31 | stuff instanceof IRDelayed || 32 | stuff instanceof IRConstr || 33 | stuff instanceof IRCase 34 | ); 35 | } -------------------------------------------------------------------------------- /src/IR/utils/positiveIntAsBytes.ts: -------------------------------------------------------------------------------- 1 | import { fromHex } from "@harmoniclabs/uint8array-utils"; 2 | 3 | /** 4 | * writes the number in a new `Uint8Array` Big Endian 5 | */ 6 | export function positiveIntAsBytes( n: number | bigint ): Uint8Array 7 | { 8 | if( typeof n === "bigint" ) 9 | { 10 | return positiveBigIntAsBytes( n ); 11 | } 12 | 13 | if( !Number.isSafeInteger( n ) || n < 0 ) 14 | { 15 | console.log( n ); 16 | console.trace(); // some help 17 | throw new Error( 18 | "how did you end up here? the name of the function explicitly says 'positiveIntAsBytes'" 19 | ); 20 | } 21 | 22 | let str = n.toString(16); 23 | str = str.length % 2 === 0 ? str : "0" + str; 24 | return fromHex( str ); 25 | } 26 | 27 | export function positiveBigIntAsBytes( n: bigint ): Uint8Array 28 | { 29 | if( n < 0 || typeof n !== "bigint" ) 30 | { 31 | console.log( n ); 32 | console.trace(); // some help 33 | throw new Error( 34 | "how did you end up here? the name of the function explicitly says 'positiveBigIntAsBytes'" 35 | ); 36 | } 37 | 38 | let strHex = n.toString(16); 39 | strHex = strHex.length % 2 === 0 ? strHex : "0" + strHex; 40 | return fromHex( strHex ); 41 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "@harmoniclabs/bytestring"; 2 | export * from "@harmoniclabs/cbor"; 3 | export * from "@harmoniclabs/obj-utils"; 4 | export * from "@harmoniclabs/pair"; 5 | export * from "@harmoniclabs/plutus-data"; 6 | export * from "@harmoniclabs/plutus-machine"; 7 | export * from "@harmoniclabs/uint8array-utils"; 8 | export * from "@harmoniclabs/uplc"; 9 | 10 | export * from "./pluts"; 11 | export * from "./IR"; -------------------------------------------------------------------------------- /src/pluts/API/V1/Address/PAddress.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { PMaybe } from "../../../lib/std/PMaybe/PMaybe"; 3 | import { PCredential } from "./PCredential"; 4 | import { PStakingCredential } from "./PStakingCredential"; 5 | 6 | export const PAddress = pstruct({ 7 | PAddress: { 8 | credential: PCredential.type, 9 | stakingCredential: PMaybe( PStakingCredential.type ).type 10 | } 11 | }) -------------------------------------------------------------------------------- /src/pluts/API/V1/Address/PCredential.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { punBData } from "../../../lib/builtins/data"; 3 | import { pfn } from "../../../lib/pfn"; 4 | import { phoist } from "../../../lib/phoist"; 5 | import { bs } from "../../../type_system/types"; 6 | import { PPubKeyHash } from "../PubKey/PPubKeyHash"; 7 | import { PValidatorHash } from "../ScriptsHashes/PValidatorHash"; 8 | 9 | export const PCredential = pstruct({ 10 | PPubKeyCredential: { pkh: PPubKeyHash.type }, 11 | PScriptCredential: { valHash: PValidatorHash.type }, 12 | }, 13 | ( self_t ) => { 14 | 15 | const pcredHash = phoist( 16 | pfn([ self_t ], bs ) 17 | ( self => punBData.$( self.raw.fields.head ) ) 18 | ) 19 | 20 | return { 21 | hash: pcredHash 22 | }; 23 | }); -------------------------------------------------------------------------------- /src/pluts/API/V1/Address/PStakingCredential.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { int } from "../../../type_system/types"; 3 | import { PCredential } from "./PCredential"; 4 | 5 | export const PStakingCredential = pstruct({ 6 | PStakingHash: { _0: PCredential.type }, 7 | PStakingPtr: { 8 | _0: int, 9 | _1: int, 10 | _2: int 11 | } 12 | }); -------------------------------------------------------------------------------- /src/pluts/API/V1/Address/__tests__/API.V1.PAddress.PStakingCredential.test.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../../PTypes/PStruct/pstruct"; 2 | import { isStructDefinition } from "../../../../type_system"; 3 | import { int } from "../../../../type_system/types"; 4 | import { PPubKeyHash } from "../../PubKey/PPubKeyHash"; 5 | import { PValidatorHash } from "../../ScriptsHashes/PValidatorHash"; 6 | import { PCredential } from "../PCredential"; 7 | 8 | 9 | describe("PStakingCredential", () => { 10 | 11 | test("def", () => { 12 | 13 | const PCredentialSDef = { 14 | PPubKeyCredential: { pkh: PPubKeyHash.type }, 15 | PScriptCredential: { valHash: PValidatorHash.type }, 16 | }; 17 | 18 | expect( 19 | isStructDefinition( PCredentialSDef ) 20 | ).toBe( true ) 21 | 22 | expect( 23 | isStructDefinition({ 24 | PStakingHash: { _0: PCredential.type }, 25 | PStakingPtr: { 26 | _0: int, 27 | _1: int, 28 | _2: int 29 | } 30 | }) 31 | ).toBe( true ) 32 | 33 | const TestPStakingCredential = pstruct({ 34 | PStakingHash: { _0: PCredential.type }, 35 | PStakingPtr: { 36 | _0: int, 37 | _1: int, 38 | _2: int 39 | } 40 | }); 41 | 42 | }) 43 | }) -------------------------------------------------------------------------------- /src/pluts/API/V1/Address/__tests__/API.V1.PCredential.pmatch.test.ts: -------------------------------------------------------------------------------- 1 | import { perror, pmatch, toData } from "../../../../lib" 2 | import { PPubKeyHash } from "../../PubKey/PPubKeyHash" 3 | import { PCredential } from "../PCredential" 4 | 5 | 6 | describe("pmatch( PCredentials )", () => { 7 | 8 | test("finds ctros", () => { 9 | 10 | expect( 11 | pmatch( 12 | PCredential.PPubKeyCredential({ 13 | pkh: toData( PPubKeyHash.type )( PPubKeyHash.from("ff".repeat(28)) ) 14 | }) 15 | ) 16 | .onPPubKeyCredential( ({ pkh }) => pkh ) 17 | .onPScriptCredential( _ => perror( PPubKeyHash.type ) as any ) 18 | ); 19 | 20 | }); 21 | 22 | }) -------------------------------------------------------------------------------- /src/pluts/API/V1/Interval/PBound.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { bool } from "../../../type_system/types"; 3 | import { PExtended } from "./PExtended"; 4 | 5 | export const PBound = pstruct({ 6 | PBound: { 7 | bound: PExtended.type, 8 | inclusive: bool 9 | } 10 | }); -------------------------------------------------------------------------------- /src/pluts/API/V1/Interval/PExtended.ts: -------------------------------------------------------------------------------- 1 | import { palias } from "../../../PTypes/PAlias/palias"; 2 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 3 | import { pfn } from "../../../lib/pfn"; 4 | import { pInt } from "../../../lib/std/int"; 5 | import { int } from "../../../type_system"; 6 | 7 | export const PExtended = pstruct({ 8 | PNegInf: {}, 9 | PFinite: { n: int }, 10 | PPosInf: {} 11 | }); 12 | 13 | 14 | const PPOSIXTime = palias( int ) 15 | 16 | PPOSIXTime.from( pInt( 1 ) ) -------------------------------------------------------------------------------- /src/pluts/API/V1/Interval/PInterval.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { PBound } from "./PBound"; 3 | 4 | export const PInterval = pstruct({ 5 | PInterval: { 6 | from: PBound.type, 7 | to: PBound.type 8 | } 9 | }); -------------------------------------------------------------------------------- /src/pluts/API/V1/PDCert/index.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { int } from "../../../type_system/types"; 3 | import { PStakingCredential } from "../Address/PStakingCredential"; 4 | import { PPubKeyHash } from "../PubKey/PPubKeyHash"; 5 | 6 | export const PDCert = pstruct({ 7 | KeyRegistration: { stakeKey: PStakingCredential.type }, 8 | KeyDeRegistration: { stakeKey: PStakingCredential.type }, 9 | KeyDelegation: { 10 | delegator: PStakingCredential.type, 11 | poolKeyHash: PPubKeyHash.type 12 | }, 13 | PoolRegistration: { 14 | poolId: PPubKeyHash.type, 15 | poolVRF: PPubKeyHash.type, 16 | }, 17 | PoolRetire: { 18 | poolId: PPubKeyHash.type, 19 | epoch: int, // epoch 20 | }, 21 | Genesis: {}, 22 | MoveInstantRewards: {} 23 | }); -------------------------------------------------------------------------------- /src/pluts/API/V1/PubKey/PPubKey.ts: -------------------------------------------------------------------------------- 1 | import { palias } from "../../../PTypes/PAlias/palias"; 2 | import { bs } from "../../../type_system/types"; 3 | 4 | export const PPubKey = palias( bs ); -------------------------------------------------------------------------------- /src/pluts/API/V1/PubKey/PPubKeyHash.ts: -------------------------------------------------------------------------------- 1 | import { palias } from "../../../PTypes/PAlias/palias"; 2 | import { bs } from "../../../type_system/types"; 3 | 4 | export const PPubKeyHash = palias( bs ); 5 | -------------------------------------------------------------------------------- /src/pluts/API/V1/ScriptContext/PScriptContext.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { PScriptPurpose } from "./PScriptPurpose"; 3 | import { PTxInfo } from "./PTxInfo/PTxInfo"; 4 | 5 | export const PScriptContext = pstruct({ 6 | PScriptContext: { 7 | tx: PTxInfo.type, 8 | purpose: PScriptPurpose.type 9 | } 10 | }); -------------------------------------------------------------------------------- /src/pluts/API/V1/ScriptContext/PScriptPurpose/index.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../../PTypes/PStruct/pstruct"; 2 | import { PStakingCredential } from "../../Address/PStakingCredential"; 3 | import { PDCert } from "../../PDCert"; 4 | import { PTxOutRef } from "../../Tx/PTxOutRef"; 5 | import { PCurrencySymbol } from "../../Value/PCurrencySymbol"; 6 | 7 | export const PScriptPurpose = pstruct({ 8 | Minting: { currencySym: PCurrencySymbol.type }, 9 | Spending: { utxoRef: PTxOutRef.type }, 10 | Rewarding: { stakeCredential: PStakingCredential.type }, 11 | Certifying: { dCert: PDCert.type } 12 | }); -------------------------------------------------------------------------------- /src/pluts/API/V1/ScriptContext/PTxInfo/PTxInfo.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../../PTypes/PStruct/pstruct"; 2 | import { data, int, list, pair } from "../../../../type_system/types"; 3 | import { PStakingCredential } from "../../Address/PStakingCredential"; 4 | import { PDCert } from "../../PDCert"; 5 | import { PPubKeyHash } from "../../PubKey/PPubKeyHash"; 6 | import { PDatumHash } from "../../ScriptsHashes/PDatumHash"; 7 | import { PPOSIXTimeRange } from "../../Time"; 8 | import { PTxId } from "../../Tx/PTxId"; 9 | import { PTxInInfo } from "../../Tx/PTxInInfo"; 10 | import { PTxOut } from "../../Tx/PTxOut"; 11 | import { PValue } from "../../Value/PValue"; 12 | 13 | export const PTxInfo = pstruct({ 14 | PTxInfo: { 15 | inputs: list( PTxInInfo.type ), 16 | outputs: list( PTxOut.type ), 17 | fee: PValue.type, 18 | mint: PValue.type, 19 | dCertificates: list( PDCert.type ), 20 | withdrawals: list( pair( PStakingCredential.type, int ) ), 21 | interval: PPOSIXTimeRange.type, 22 | signatories: list( PPubKeyHash.type ), 23 | datums: list( pair( PDatumHash.type, data ) ), 24 | id: PTxId.type 25 | } 26 | }) -------------------------------------------------------------------------------- /src/pluts/API/V1/ScriptsHashes/PDatumHash.ts: -------------------------------------------------------------------------------- 1 | import { palias } from "../../../PTypes/PAlias/palias"; 2 | import { bs } from "../../../type_system/types"; 3 | 4 | export const PDatumHash = palias( bs ); -------------------------------------------------------------------------------- /src/pluts/API/V1/ScriptsHashes/PScriptHash.ts: -------------------------------------------------------------------------------- 1 | import { palias } from "../../../PTypes/PAlias/palias"; 2 | import { bs } from "../../../type_system/types"; 3 | 4 | export const PScriptHash = palias( bs ); -------------------------------------------------------------------------------- /src/pluts/API/V1/ScriptsHashes/PValidatorHash.ts: -------------------------------------------------------------------------------- 1 | import { palias } from "../../../PTypes/PAlias/palias"; 2 | import { bs } from "../../../type_system/types"; 3 | 4 | export const PValidatorHash = palias( bs ); 5 | -------------------------------------------------------------------------------- /src/pluts/API/V1/Time/index.ts: -------------------------------------------------------------------------------- 1 | import { PInterval } from "../Interval/PInterval"; 2 | 3 | export const PPOSIXTimeRange = PInterval; 4 | -------------------------------------------------------------------------------- /src/pluts/API/V1/Tx/PTxId.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { bs } from "../../../type_system/types"; 3 | 4 | // plutarch implementation https://github.com/Plutonomicon/plutarch-plutus/blob/f0805033ec7ad83643ba3c90902673ba6e5b90c3/Plutarch/Api/V1/Tx.hs#L39 5 | // no idea why this is not an alias 6 | export const PTxId = pstruct({ 7 | PTxId: { txId: bs } 8 | }); -------------------------------------------------------------------------------- /src/pluts/API/V1/Tx/PTxInInfo.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { PTxOut } from "./PTxOut"; 3 | import { PTxOutRef } from "./PTxOutRef"; 4 | 5 | export const PTxInInfo = pstruct({ 6 | PTxInInfo: { 7 | utxoRef: PTxOutRef.type, 8 | resolved: PTxOut.type 9 | } 10 | }); -------------------------------------------------------------------------------- /src/pluts/API/V1/Tx/PTxOut.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { PDatumHash } from "../ScriptsHashes/PDatumHash"; 3 | import { PValue } from "../Value/PValue"; 4 | import { PAddress } from "../Address/PAddress"; 5 | import { PMaybe } from "../../../lib/std/PMaybe/PMaybe"; 6 | 7 | export const PTxOut = pstruct({ 8 | PTxOut: { 9 | address: PAddress.type, 10 | value: PValue.type, 11 | datumHash: PMaybe( PDatumHash.type ).type 12 | } 13 | }); -------------------------------------------------------------------------------- /src/pluts/API/V1/Tx/PTxOutRef.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { int } from "../../../type_system/types"; 3 | import { PTxId } from "./PTxId"; 4 | 5 | export const PTxOutRef = pstruct({ 6 | PTxOutRef: { 7 | id: PTxId.type, 8 | index: int 9 | } 10 | }); -------------------------------------------------------------------------------- /src/pluts/API/V1/Value/PCurrencySymbol.ts: -------------------------------------------------------------------------------- 1 | import { palias } from "../../../PTypes/PAlias/palias"; 2 | import { bs } from "../../../type_system/types"; 3 | 4 | export const PCurrencySymbol = palias( bs ); -------------------------------------------------------------------------------- /src/pluts/API/V1/Value/PTokenName.ts: -------------------------------------------------------------------------------- 1 | import { palias } from "../../../PTypes/PAlias/palias"; 2 | import { bs } from "../../../type_system/types"; 3 | 4 | export const PTokenName = palias( bs ); -------------------------------------------------------------------------------- /src/pluts/API/V2/ScriptContext/PScriptContext.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { V1 } from "../../V1"; 3 | import { PTxInfo } from "./PTxInfo/PTxInfo"; 4 | 5 | export const PScriptContext = pstruct({ 6 | PScriptContext: { 7 | tx: PTxInfo.type, 8 | purpose: V1.PScriptPurpose.type 9 | } 10 | }); -------------------------------------------------------------------------------- /src/pluts/API/V2/ScriptContext/PTxInfo/PTxInfo.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../../PTypes/PStruct/pstruct"; 2 | import { PTxInInfo } from "../../Tx/PTxInInfo"; 3 | import { PTxOut } from "../../Tx/PTxOut"; 4 | import { list, pair, int, data } from "../../../../type_system"; 5 | import { PValue } from "../../../V1/Value/PValue"; 6 | import { PDCert } from "../../../V1/PDCert"; 7 | import { PStakingCredential } from "../../../V1/Address/PStakingCredential"; 8 | import { PPOSIXTimeRange } from "../../../V1/Time"; 9 | import { PPubKeyHash } from "../../../V1/PubKey/PPubKeyHash"; 10 | import { PScriptPurpose } from "../../../V1/ScriptContext/PScriptPurpose"; 11 | import { PDatumHash } from "../../../V1/ScriptsHashes/PDatumHash"; 12 | import { PTxId } from "../../../V1/Tx/PTxId"; 13 | 14 | export const PTxInfo = pstruct({ 15 | PTxInfo: { 16 | inputs: list( PTxInInfo.type ), 17 | refInputs: list( PTxInInfo.type ), 18 | outputs: list( PTxOut.type ), 19 | fee: PValue.type, 20 | mint: PValue.type, 21 | dCertificates: list( PDCert.type ), 22 | withdrawals: list( pair( PStakingCredential.type, int ) ), 23 | interval: PPOSIXTimeRange.type, 24 | signatories: list( PPubKeyHash.type ), 25 | redeemers: list( pair( PScriptPurpose.type, data ) ), 26 | datums: list( pair( PDatumHash.type, data ) ), 27 | id: PTxId.type 28 | } 29 | }); -------------------------------------------------------------------------------- /src/pluts/API/V2/Tx/POutputDatum.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { data } from "../../../type_system/types"; 3 | import { PDatumHash } from "../../V1/ScriptsHashes/PDatumHash"; 4 | 5 | export const POutputDatum = pstruct({ 6 | NoDatum: {}, 7 | DatumHash: { datumHash: PDatumHash.type }, 8 | InlineDatum: { datum: data } 9 | }); -------------------------------------------------------------------------------- /src/pluts/API/V2/Tx/PTxInInfo.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { V1 } from "../../V1"; 3 | import { PTxOut } from "./PTxOut"; 4 | 5 | export const PTxInInfo = pstruct({ 6 | PTxInInfo: { 7 | utxoRef: V1.PTxOutRef.type, 8 | resolved: PTxOut.type 9 | } 10 | }); -------------------------------------------------------------------------------- /src/pluts/API/V2/Tx/PTxOut.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { PMaybe } from "../../../lib/std/PMaybe/PMaybe"; 3 | import { V1 } from "../../V1"; 4 | import { POutputDatum } from "./POutputDatum"; 5 | 6 | export const PTxOut = pstruct({ 7 | PTxOut: { 8 | address: V1.PAddress.type, 9 | value: V1.PValue.type, 10 | datum: POutputDatum.type, 11 | refScrpt: PMaybe( V1.PScriptHash.type ).type 12 | } 13 | }); -------------------------------------------------------------------------------- /src/pluts/API/V2/index.ts: -------------------------------------------------------------------------------- 1 | // export * from "./ScriptContext/PScriptContext"; 2 | // export * from "./ScriptContext/PTxInfo/PTxInfo"; 3 | export * from "./Tx/POutputDatum"; 4 | export * from "./Tx/PTxOut"; 5 | // export * from "./Tx/PTxInInfo"; 6 | 7 | import { V1 } from "../V1"; 8 | import { PScriptContext } from "./ScriptContext/PScriptContext"; 9 | import { PTxInfo } from "./ScriptContext/PTxInfo/PTxInfo"; 10 | import { POutputDatum } from "./Tx/POutputDatum"; 11 | import { PTxOut } from "./Tx/PTxOut"; 12 | import { PTxInInfo } from "./Tx/PTxInInfo"; 13 | 14 | export const V2 = Object.freeze({ 15 | ...V1, 16 | 17 | PScriptContext, 18 | PTxInfo, 19 | 20 | POutputDatum, 21 | PTxInInfo, 22 | PTxOut 23 | } as const); -------------------------------------------------------------------------------- /src/pluts/API/V3/Governance/PDRep.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { PCredential } from "../../V1/Address/PCredential"; 3 | 4 | export const PDrep = pstruct({ 5 | DRep: { credentials: PCredential.type }, 6 | AlwaysAbstain: {}, 7 | AlwaysNoConfidence: {} 8 | }); -------------------------------------------------------------------------------- /src/pluts/API/V3/Governance/PProposalProcedure.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { int } from "../../../type_system"; 3 | import { PCredential } from "../../V1/Address/PCredential"; 4 | import { PGovernanceAction } from "./PGovernanceAction"; 5 | 6 | export const PProposalProcedure = pstruct({ 7 | PProposalProcedure: { 8 | /** lovelaces */ 9 | deposit: int, 10 | returnCredentials: PCredential.type, 11 | governanceAction: PGovernanceAction.type 12 | } 13 | }); -------------------------------------------------------------------------------- /src/pluts/API/V3/Governance/PProtocolVersion.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { int } from "../../../type_system/types"; 3 | 4 | export const PProtocolVersion = pstruct({ 5 | PProtocolVersion: { 6 | major: int, 7 | minor: int 8 | } 9 | }); -------------------------------------------------------------------------------- /src/pluts/API/V3/Governance/PVote.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | 3 | export const PVote = pstruct({ 4 | No: {}, 5 | Yes: {}, 6 | Abstain: {} 7 | }); -------------------------------------------------------------------------------- /src/pluts/API/V3/Governance/PVoter.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { PCredential } from "../../V1/Address/PCredential"; 3 | import { PPubKeyHash } from "../../V1/PubKey/PPubKeyHash"; 4 | 5 | export const PVoter = pstruct({ 6 | Committee: { hotCredentials: PCredential.type }, 7 | DRep: { credentials: PCredential.type }, 8 | StakePool: { poolHash: PPubKeyHash.type } 9 | }); -------------------------------------------------------------------------------- /src/pluts/API/V3/Governance/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./PChangedParams"; 2 | export * from "./PGovernanceAction"; 3 | export * from "./PProposalProcedure"; 4 | export * from "./PProtocolVersion"; 5 | export * from "./PVote"; 6 | export * from "./PVoter"; 7 | export * from "./PDRep"; -------------------------------------------------------------------------------- /src/pluts/API/V3/ScriptContext/PCertificate.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { PMaybe } from "../../../lib/std/PMaybe/PMaybe"; 3 | import { int } from "../../../type_system/types"; 4 | import { PCredential } from "../../V1/Address/PCredential"; 5 | import { PPubKeyHash } from "../../V1/PubKey/PPubKeyHash"; 6 | import { PDelegatee } from "./PDelegatee"; 7 | 8 | const PMaybeInt = PMaybe( int ); 9 | 10 | export const PCertificate = pstruct({ 11 | StakeRegistration: { 12 | stakeKey: PCredential.type, 13 | deposit: PMaybeInt.type 14 | }, 15 | StakeDeRegistration: { 16 | stakeKey: PCredential.type, 17 | refound: PMaybeInt.type 18 | }, 19 | Delegation: { 20 | delegator: PCredential.type, 21 | delegatee: PDelegatee.type 22 | }, 23 | RegistrationAndDelegation: { 24 | delegator: PCredential.type, 25 | delegatee: PDelegatee.type, 26 | lovelacesDeposit: int 27 | }, 28 | DRepRegistration: { 29 | drep: PCredential.type, 30 | lovelacesDeposit: int 31 | }, 32 | DRepUpdate: { 33 | drep: PCredential.type 34 | }, 35 | DRepDeRegistration: { 36 | drep: PCredential.type, 37 | refound: int 38 | }, 39 | PoolRegistration: { 40 | poolId: PPubKeyHash.type, 41 | poolVFR: PPubKeyHash.type, 42 | }, 43 | PoolRetire: { 44 | poolId: PPubKeyHash.type, 45 | epoch: int, 46 | }, 47 | CommitteeHotAuthorization: { 48 | cold: PCredential.type, 49 | hot: PCredential.type 50 | }, 51 | CommitteeResignation: { 52 | cold: PCredential.type 53 | } 54 | }); -------------------------------------------------------------------------------- /src/pluts/API/V3/ScriptContext/PDelegatee.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { PPubKeyHash } from "../../V1/PubKey/PPubKeyHash"; 3 | import { PDrep } from "../Governance/PDRep"; 4 | 5 | export const PDelegatee = pstruct({ 6 | DelegStake: { poolId: PPubKeyHash.type }, 7 | DelegVote: { drep: PDrep.type }, 8 | DelegStakeVote: { poolId: PPubKeyHash.type, drep: PDrep.type } 9 | }); -------------------------------------------------------------------------------- /src/pluts/API/V3/ScriptContext/PScriptContext.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { data } from "../../../type_system"; 3 | import { PScriptInfo } from "./PScriptInfo"; 4 | import { PTxInfo } from "./PTxInfo"; 5 | 6 | export const PScriptContext = pstruct({ 7 | PScriptContext: { 8 | tx: PTxInfo.type, 9 | redeemer: data, 10 | purpose: PScriptInfo.type 11 | } 12 | }); -------------------------------------------------------------------------------- /src/pluts/API/V3/ScriptContext/PScriptInfo/index.ts: -------------------------------------------------------------------------------- 1 | import { PMaybe } from "../../../../lib/std/PMaybe/PMaybe"; 2 | import { pstruct } from "../../../../PTypes/PStruct/pstruct"; 3 | import { data, int } from "../../../../type_system/types"; 4 | import { PCredential } from "../../../V1/Address/PCredential"; 5 | import { PCurrencySymbol } from "../../../V1/Value/PCurrencySymbol"; 6 | import { PProposalProcedure } from "../../Governance/PProposalProcedure"; 7 | import { PVoter } from "../../Governance/PVoter"; 8 | import { PTxOutRef } from "../../Tx/PTxOutRef"; 9 | import { PCertificate } from "../PCertificate"; 10 | 11 | export const PScriptInfo = pstruct({ 12 | Minting: { currencySym: PCurrencySymbol.type }, 13 | Spending: { 14 | utxoRef: PTxOutRef.type, 15 | datum: PMaybe( data ).type 16 | }, 17 | Rewarding: { stakeCredential: PCredential.type }, 18 | Certifying: { 19 | index: int, 20 | cert: PCertificate.type 21 | }, 22 | Voting: { 23 | voter: PVoter.type 24 | }, 25 | Proposing: { 26 | index: int, 27 | proposal: PProposalProcedure.type 28 | } 29 | }); -------------------------------------------------------------------------------- /src/pluts/API/V3/ScriptContext/PScriptPurpose/index.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../../PTypes/PStruct/pstruct"; 2 | import { int } from "../../../../type_system/types"; 3 | import { PCredential } from "../../../V1/Address/PCredential"; 4 | import { PCurrencySymbol } from "../../../V1/Value/PCurrencySymbol"; 5 | import { PProposalProcedure } from "../../Governance/PProposalProcedure"; 6 | import { PVoter } from "../../Governance/PVoter"; 7 | import { PTxOutRef } from "../../Tx/PTxOutRef"; 8 | import { PCertificate } from "../PCertificate"; 9 | 10 | export const PScriptPurpose = pstruct({ 11 | Minting: { currencySym: PCurrencySymbol.type }, 12 | Spending: { utxoRef: PTxOutRef.type }, 13 | Rewarding: { stakeCredential: PCredential.type }, 14 | Certifying: { 15 | index: int, 16 | cert: PCertificate.type 17 | }, 18 | Voting: { 19 | voter: PVoter.type 20 | }, 21 | Proposing: { 22 | index: int, 23 | proposal: PProposalProcedure.type 24 | } 25 | }); -------------------------------------------------------------------------------- /src/pluts/API/V3/ScriptContext/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./PCertificate"; 2 | export * from "./PScriptContext"; 3 | export * from "./PScriptInfo"; 4 | export * from "./PScriptPurpose"; 5 | export * from "./PTxInfo"; 6 | export * from "./PDelegatee"; -------------------------------------------------------------------------------- /src/pluts/API/V3/Tx/PTxId.ts: -------------------------------------------------------------------------------- 1 | import { palias } from "../../../PTypes"; 2 | import { bs } from "../../../type_system"; 3 | 4 | export const PTxId = palias( bs ); -------------------------------------------------------------------------------- /src/pluts/API/V3/Tx/PTxInInfo.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { PTxOut } from "../../V2/Tx/PTxOut"; 3 | import { PTxOutRef } from "./PTxOutRef"; 4 | 5 | export const PTxInInfo = pstruct({ 6 | PTxInInfo: { 7 | utxoRef: PTxOutRef.type, 8 | resolved: PTxOut.type 9 | } 10 | }); -------------------------------------------------------------------------------- /src/pluts/API/V3/Tx/PTxOutRef.ts: -------------------------------------------------------------------------------- 1 | import { pstruct } from "../../../PTypes/PStruct/pstruct"; 2 | import { int } from "../../../type_system/types"; 3 | import { PTxId } from "./PTxId"; 4 | 5 | export const PTxOutRef = pstruct({ 6 | PTxOutRef: { 7 | id: PTxId.type, 8 | index: int 9 | } 10 | }); -------------------------------------------------------------------------------- /src/pluts/API/V3/Tx/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./PTxId"; 2 | export * from "./PTxInInfo"; 3 | export * from "./PTxOutRef"; -------------------------------------------------------------------------------- /src/pluts/API/V3/index.ts: -------------------------------------------------------------------------------- 1 | // import { V2 } from "../V2"; 2 | 3 | export * from "./Governance"; 4 | export * from "./ScriptContext"; 5 | export * from "./Tx"; 6 | 7 | // import { PChangedParams, PDrep, PGovernanceAction, PProposalProcedure, PProtocolVersion, PVote, PVoter, PConstitution, PRational } from "./Governance"; 8 | // import { PCertificate, PDelegatee, PScriptContext, PScriptInfo, PScriptPurpose, PTxInfo } from "./ScriptContext"; 9 | // import { PTxId, PTxInInfo, PTxOutRef } from "./Tx"; 10 | 11 | // @ts-ignore The inferred type of this node exceeds the maximum length the compiler will serialize. An explicit type annotation is needed.ts(7056) 12 | // export const V3 = Object.freeze({ 13 | // ...V2, 14 | // 15 | // PChangedParams, PDrep, PGovernanceAction, PProposalProcedure, PProtocolVersion, PVote, PVoter, PConstitution, PRational, 16 | // PCertificate, PDelegatee, PScriptContext, PScriptInfo, PScriptPurpose, PTxInfo, 17 | // PTxId, PTxInInfo, PTxOutRef 18 | // } as const); -------------------------------------------------------------------------------- /src/pluts/API/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./V1"; 2 | export * from "./V2"; 3 | export * from "./V3"; -------------------------------------------------------------------------------- /src/pluts/PType/PDataRepresentable.ts: -------------------------------------------------------------------------------- 1 | import { PType } from "."; 2 | 3 | /** 4 | * @abstract 5 | */ 6 | export class PDataRepresentable extends PType 7 | { 8 | constructor() { super(); } 9 | } -------------------------------------------------------------------------------- /src/pluts/PType/index.ts: -------------------------------------------------------------------------------- 1 | import { UPLCTerm } from "@harmoniclabs/uplc"; 2 | 3 | /** 4 | * @abstract 5 | */ 6 | export class PType 7 | { 8 | /** 9 | * probably never used; 10 | * 11 | * here only to make a difference from any generic object 12 | */ 13 | protected readonly _isPType: true = true; 14 | protected readonly _PTypeUPLCTerm?: UPLCTerm; 15 | 16 | constructor() {} 17 | }; 18 | -------------------------------------------------------------------------------- /src/pluts/PTypes/PAlias/__tests__/PAlias.evalScript.test.ts: -------------------------------------------------------------------------------- 1 | import { palias } from "../palias" 2 | import { pInt } from "../../../lib/std/int/pInt"; 3 | import { int } from "../../../type_system/types"; 4 | import { CEKConst, Machine } from "@harmoniclabs/plutus-machine"; 5 | 6 | 7 | describe("palias", () => { 8 | 9 | const FancyInt = palias( int ); 10 | const fancy69 = FancyInt.from( pInt(69) ) 11 | 12 | test("evaluates to the aliased type", () => { 13 | 14 | expect( 15 | Machine.evalSimple( 16 | fancy69 17 | ) 18 | ).toEqual( CEKConst.int( 69 ) ) 19 | 20 | }); 21 | 22 | test("aliases can be used in place of original types", () => { 23 | 24 | expect( 25 | Machine.evalSimple( 26 | pInt(1).add( fancy69 as any ) 27 | ) 28 | ).toEqual( CEKConst.int( 69 + 1 ) ) 29 | 30 | }); 31 | 32 | 33 | }) -------------------------------------------------------------------------------- /src/pluts/PTypes/PAlias/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./palias"; -------------------------------------------------------------------------------- /src/pluts/PTypes/PBlsG1.ts: -------------------------------------------------------------------------------- 1 | import { BlsG1 } from "@harmoniclabs/crypto"; 2 | import { PType } from "../PType"; 3 | 4 | export class PBlsG1 extends PType 5 | { 6 | private _pblsg1: BlsG1 7 | 8 | constructor( bs: BlsG1 ) 9 | { 10 | super(); 11 | this._pblsg1 = bs; 12 | } 13 | } -------------------------------------------------------------------------------- /src/pluts/PTypes/PBlsG2.ts: -------------------------------------------------------------------------------- 1 | import { BlsG2 } from "@harmoniclabs/crypto"; 2 | import { PType } from "../PType"; 3 | 4 | export class PBlsG2 extends PType 5 | { 6 | private _pblsg2: BlsG2 7 | 8 | constructor( bs: BlsG2 ) 9 | { 10 | super(); 11 | this._pblsg2 = bs; 12 | } 13 | } -------------------------------------------------------------------------------- /src/pluts/PTypes/PBlsMlRes.ts: -------------------------------------------------------------------------------- 1 | import { BlsResult } from "@harmoniclabs/crypto"; 2 | import { PType } from "../PType"; 3 | 4 | export class PBlsMlRes extends PType 5 | { 6 | private _pblsRes: BlsResult 7 | 8 | constructor( bs: BlsResult ) 9 | { 10 | super(); 11 | this._pblsRes = bs; 12 | } 13 | } -------------------------------------------------------------------------------- /src/pluts/PTypes/PBool.ts: -------------------------------------------------------------------------------- 1 | import { Cloneable } from "../../utils/Cloneable"; 2 | import { PDataRepresentable } from "../PType/PDataRepresentable"; 3 | 4 | export class PBool extends PDataRepresentable 5 | implements Cloneable< PBool > 6 | { 7 | private _pbool: boolean 8 | 9 | constructor( bool: boolean = false ) 10 | { 11 | super(); 12 | this._pbool = bool; 13 | } 14 | 15 | clone(): PBool 16 | { 17 | return new PBool( this._pbool ); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/pluts/PTypes/PByteString.ts: -------------------------------------------------------------------------------- 1 | import { ByteString } from "@harmoniclabs/bytestring"; 2 | import { PDataRepresentable } from "../PType/PDataRepresentable"; 3 | 4 | export class PByteString extends PDataRepresentable 5 | { 6 | private _pbytestring: ByteString 7 | 8 | constructor( bs: ByteString ) 9 | { 10 | super(); 11 | this._pbytestring = bs; 12 | } 13 | } -------------------------------------------------------------------------------- /src/pluts/PTypes/PData/PData.ts: -------------------------------------------------------------------------------- 1 | import { Data, DataConstr } from "@harmoniclabs/plutus-data"; 2 | import { PType } from "../../PType"; 3 | 4 | export class PData extends PType 5 | { 6 | protected _data: Data 7 | get data(): Data { return this._data; } 8 | 9 | constructor( data: Data = new DataConstr( 0, [] ) ) 10 | { 11 | super(); 12 | 13 | this._data = data; 14 | } 15 | } 16 | 17 | export class PAsData extends PData 18 | { 19 | protected _pty: PT 20 | 21 | get pty(): PT { return this._pty; } 22 | 23 | constructor( pty: PT, data: Data = new DataConstr( 0, [] ) ) 24 | { 25 | super( data ); 26 | 27 | this._pty = pty; 28 | } 29 | } -------------------------------------------------------------------------------- /src/pluts/PTypes/PData/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./PData"; -------------------------------------------------------------------------------- /src/pluts/PTypes/PDelayed.ts: -------------------------------------------------------------------------------- 1 | import { Cloneable, isCloneable } from "../../utils/Cloneable"; 2 | import { PType } from "../PType"; 3 | 4 | export class PDelayed< DelayedPType extends PType > extends PType 5 | implements Cloneable> 6 | { 7 | private _delayedPType: DelayedPType; 8 | 9 | constructor( toDelay: DelayedPType = new PType as DelayedPType ) 10 | { 11 | super(); 12 | this._delayedPType = toDelay; 13 | } 14 | 15 | clone(): PDelayed 16 | { 17 | return new PDelayed( 18 | isCloneable( this._delayedPType ) ? 19 | this._delayedPType.clone() : 20 | this._delayedPType 21 | ); 22 | } 23 | } -------------------------------------------------------------------------------- /src/pluts/PTypes/PFn/PLam.ts: -------------------------------------------------------------------------------- 1 | import { PType } from "../../PType" 2 | import { Cloneable, isCloneable } from "../../../utils/Cloneable"; 3 | 4 | export class PLam extends PType 5 | implements Cloneable> 6 | { 7 | // phantom 8 | private _input: A 9 | private _output: B 10 | 11 | constructor( input: A = new PType as A, output: B = new PType as B ) 12 | { 13 | super(); 14 | this._input = input; 15 | this._output = output; 16 | } 17 | 18 | clone(): PLam 19 | { 20 | return new PLam( 21 | isCloneable( this._input ) ? this._input.clone() : this._input , 22 | isCloneable( this._output ) ? this._output.clone() : this._output 23 | ) as PLam; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/pluts/PTypes/PInt.ts: -------------------------------------------------------------------------------- 1 | import { Cloneable } from "../../utils/Cloneable"; 2 | import { PDataRepresentable } from "../PType/PDataRepresentable"; 3 | 4 | export class PInt extends PDataRepresentable 5 | implements Cloneable 6 | { 7 | private _pint: bigint 8 | get pint(): bigint { return this._pint } 9 | 10 | constructor( int: number | bigint = 0 ) 11 | { 12 | super(); 13 | 14 | if( typeof int === "number" ) int = BigInt( int ); 15 | 16 | this._pint = int; 17 | } 18 | 19 | clone(): PInt 20 | { 21 | return new PInt( this.pint ); 22 | } 23 | } -------------------------------------------------------------------------------- /src/pluts/PTypes/PList.ts: -------------------------------------------------------------------------------- 1 | import { PType } from "../PType"; 2 | import { PDataRepresentable } from "../PType/PDataRepresentable"; 3 | 4 | //@ts-ignoreType instantiation is excessively deep and possibly infinite 5 | export class PList extends PDataRepresentable 6 | { 7 | private _elems: A[]; 8 | 9 | constructor( elements: A[] = [] ) 10 | { 11 | super(); 12 | 13 | this._elems = elements 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/pluts/PTypes/PPair/index.ts: -------------------------------------------------------------------------------- 1 | import { PType } from "../../PType"; 2 | import { PDataRepresentable } from "../../PType/PDataRepresentable"; 3 | /* 4 | Class static side 'typeof PPair' incorrectly extends base class static side 'typeof PDataRepresentable'. 5 | The types returned by 'fromData(...)' are incompatible between these types. 6 | Type 'Term>' is not assignable to type 'Term'. 7 | Type 'PDataRepresentable' is missing the following properties from type 'PPair': _a, _bts(2417) 8 | Type instantiation is excessively deep and possibly infinite. 9 | */ 10 | // @ts-ignore 11 | export class PPair extends PDataRepresentable 12 | { 13 | private _a: A 14 | private _b: B 15 | 16 | constructor( a: A = new PType as A, b: B = new PType as B ) 17 | { 18 | super(); 19 | 20 | this._a = a; 21 | this._b = b; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/pluts/PTypes/PSoP/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./psop"; -------------------------------------------------------------------------------- /src/pluts/PTypes/PString.ts: -------------------------------------------------------------------------------- 1 | import { Cloneable } from "../../utils/Cloneable"; 2 | import { PDataRepresentable } from "../PType/PDataRepresentable"; 3 | 4 | export class PString extends PDataRepresentable 5 | implements Cloneable 6 | { 7 | private _pstring: string 8 | 9 | constructor( str: string = "" ) 10 | { 11 | super(); 12 | this._pstring = str; 13 | } 14 | 15 | clone(): PString 16 | { 17 | return new PString( this._pstring ) 18 | } 19 | } -------------------------------------------------------------------------------- /src/pluts/PTypes/PStruct/__tests__/PStruct.pgenericStruct.test.ts: -------------------------------------------------------------------------------- 1 | import { toData } from "../../../lib"; 2 | import { PMaybe } from "../../../lib/std/PMaybe/PMaybe"; 3 | import { pStr } from "../../../lib/std/str/pStr"; 4 | import { int, str } from "../../../type_system/types"; 5 | 6 | 7 | describe("pgenericStruct", () => { 8 | 9 | test( "throws on wrong type, even if typescript is stupid", () => { 10 | 11 | expect( () => 12 | PMaybe( int ).Just({ val: toData( str )( pStr("") ) as any } ) 13 | ).toThrow(); 14 | 15 | }) 16 | 17 | }) -------------------------------------------------------------------------------- /src/pluts/PTypes/PStruct/__tests__/PStruct.pmatch.duble_extract.test.ts: -------------------------------------------------------------------------------- 1 | import { Machine } from "@harmoniclabs/plutus-machine"; 2 | import { int } from "../../../type_system"; 3 | import { pstruct } from "../pstruct"; 4 | import { pInt } from "../../../lib/std/int/pInt"; 5 | import { pDataI } from "../../../lib/std/data/pData"; 6 | 7 | 8 | const Child = pstruct({ 9 | Constr: { 10 | age: int 11 | } 12 | }); 13 | 14 | const Parent = pstruct({ 15 | Constr: { 16 | child: Child.type 17 | } 18 | }); 19 | 20 | describe("double extract", () => { 21 | 22 | test("extract child age", () => { 23 | 24 | const childAge = 2; 25 | 26 | const child = Child.Constr({ 27 | age: pDataI( childAge ) 28 | }); 29 | 30 | const parent = Parent.Constr({ 31 | child: child as any 32 | }); 33 | 34 | expect( 35 | Machine.evalSimple( 36 | parent.child.age 37 | ) 38 | ).toEqual( 39 | Machine.evalSimple( 40 | pInt( childAge ) 41 | ) 42 | ) 43 | 44 | }) 45 | }); 46 | -------------------------------------------------------------------------------- /src/pluts/PTypes/PStruct/__tests__/PStruct.typeofGenericStruct.test.ts: -------------------------------------------------------------------------------- 1 | import { PMaybe } from "../../../lib/std/PMaybe/PMaybe"; 2 | import { struct, tyVar } from "../../../type_system/types"; 3 | import { termTypeToString, typeExtends } from "../../../type_system"; 4 | import { typeofGenericStruct } from "../pgenericStruct"; 5 | 6 | 7 | describe("typeofGenericStruct", () => { 8 | 9 | test("single arguent", () => { 10 | 11 | const PMaybeTermType = typeofGenericStruct( PMaybe as any ) as any; 12 | const manualType = struct({ 13 | Just: { val: tyVar() as any }, 14 | Nothing: {} 15 | }); 16 | 17 | 18 | expect( 19 | termTypeToString( PMaybeTermType ) 20 | ) 21 | .toEqual( 22 | termTypeToString( manualType ) 23 | ) 24 | 25 | }); 26 | 27 | }) -------------------------------------------------------------------------------- /src/pluts/PTypes/PStruct/cloneStructDef.ts: -------------------------------------------------------------------------------- 1 | import { defineReadOnlyProperty } from "@harmoniclabs/obj-utils"; 2 | import { GenericStructDefinition, SopCtorDef, SopDefinition, StructCtorDef, StructDefinition } from "../../type_system"; 3 | 4 | 5 | export function cloneSopCtorDef( ctorDef: Readonly ): CtorDef 6 | { 7 | const clone: CtorDef = {} as any; 8 | 9 | for( const fieldName in ctorDef ) 10 | { 11 | clone[ fieldName ] = ctorDef[ fieldName ]; 12 | } 13 | 14 | return clone; 15 | } 16 | 17 | export const cloneStructCtorDef = cloneSopCtorDef as ( ctorDef: Readonly ) => CtorDef 18 | 19 | export function cloneSopDef( def: Readonly ): SDef 20 | { 21 | const clone: SDef = {} as SDef; 22 | const ctors = Object.keys( def ); 23 | 24 | for(let i = 0; i < ctors.length; i++ ) 25 | { 26 | defineReadOnlyProperty( 27 | clone, 28 | ctors[ i ], 29 | cloneSopCtorDef( def[ ctors[i] ] ) 30 | ); 31 | } 32 | 33 | return clone; 34 | } 35 | 36 | export const cloneStructDef = cloneSopDef as ( def: Readonly ) => SDef -------------------------------------------------------------------------------- /src/pluts/PTypes/PStruct/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pstruct"; 2 | export * from "./pgenericStruct"; 3 | export * from "./structDefEq"; -------------------------------------------------------------------------------- /src/pluts/PTypes/PStruct/structDefEq.ts: -------------------------------------------------------------------------------- 1 | import { typeExtends } from "../../type_system/typeExtends"; 2 | import { StructCtorDef, StructDefinition } from "../../type_system/types"; 3 | 4 | function structCtorEq( a: StructCtorDef, b: StructCtorDef ): boolean 5 | { 6 | if( a === b ) return true; // shallow eqality; 7 | 8 | const aFieldsNames = Object.keys( a ); 9 | const bFieldsNames = Object.keys( b ); 10 | 11 | if( aFieldsNames.length !== bFieldsNames.length ) return false; 12 | 13 | for( let i = 0; i < aFieldsNames.length; i++ ) 14 | { 15 | if( aFieldsNames[i] !== bFieldsNames[i] ) return false; 16 | 17 | const thisAField = a[ aFieldsNames[i] ]; 18 | const thisBField = b[ bFieldsNames[i] ]; 19 | 20 | if(!( 21 | typeExtends( thisAField, thisBField ) && 22 | typeExtends( thisBField, thisAField ) 23 | )) return false; 24 | } 25 | 26 | return true; 27 | } 28 | 29 | export function structDefEq( a: StructDefinition, b: StructDefinition ): boolean 30 | { 31 | if( a === b ) return true; // shallow eqality; 32 | 33 | const aCtors = Object.keys( a ); 34 | const bCtors = Object.keys( b ); 35 | 36 | if( aCtors.length !== bCtors.length ) return false; 37 | 38 | for( let i = 0; i < aCtors.length; i++ ) 39 | { 40 | if( aCtors[i] !== bCtors[i] ) return false; 41 | 42 | if( !structCtorEq( a[ aCtors[i] ], b[ bCtors[i] ] ) ) return false; 43 | } 44 | 45 | return true; 46 | } -------------------------------------------------------------------------------- /src/pluts/PTypes/PUnit.ts: -------------------------------------------------------------------------------- 1 | import { PDataRepresentable } from "../PType/PDataRepresentable"; 2 | 3 | export class PUnit extends PDataRepresentable 4 | { 5 | private _unit: undefined 6 | 7 | constructor() 8 | { 9 | super(); 10 | this._unit = undefined; 11 | } 12 | 13 | clone(): PUnit 14 | { 15 | return new PUnit; 16 | } 17 | } -------------------------------------------------------------------------------- /src/pluts/PTypes/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./PStruct"; 2 | export * from "./PSoP"; 3 | export * from "./PAlias"; 4 | export * from "./PData"; 5 | export * from "./PFn"; 6 | 7 | export * from "./PBool"; 8 | export * from "./PByteString"; 9 | export * from "./PDelayed"; 10 | export * from "./PInt"; 11 | export * from "./PList"; 12 | export * from "./PPair"; 13 | export * from "./PString"; 14 | export * from "./PUnit"; -------------------------------------------------------------------------------- /src/pluts/Script/LitteralPurpose.ts: -------------------------------------------------------------------------------- 1 | 2 | export type LitteralPurpose = "spend" | "mint" | "withdraw" | "certify"; 3 | 4 | export function isLitteralPurpose( stuff: any ): stuff is LitteralPurpose 5 | { 6 | return ( 7 | typeof stuff === "string" && 8 | ( 9 | stuff === "spend" || 10 | stuff === "mint" || 11 | stuff === "withdraw" || 12 | stuff === "certify" 13 | ) 14 | ) 15 | } -------------------------------------------------------------------------------- /src/pluts/Script/Parametrized/__tests__/getFnTypes.test.ts: -------------------------------------------------------------------------------- 1 | import { bs, fn, int, lam, str } from "../../../type_system/types"; 2 | import { getFnTypes } from "../getFnTypes"; 3 | 4 | describe("getFnTypes", () => { 5 | 6 | test("int", () => { 7 | 8 | expect( 9 | getFnTypes( int ) 10 | ).toEqual([ int ]); 11 | 12 | }); 13 | 14 | test("lam( int, bs )", () => { 15 | 16 | expect( 17 | getFnTypes( lam( int, bs ) ) 18 | ).toEqual([ int, bs ]); 19 | 20 | }); 21 | 22 | test("fn([ int, str ], bs )", () => { 23 | 24 | expect( 25 | getFnTypes( fn([ int, str ], bs ) ) 26 | ).toEqual([ int, str, bs ]); 27 | 28 | }); 29 | 30 | }) -------------------------------------------------------------------------------- /src/pluts/Script/Parametrized/getFnTypes.ts: -------------------------------------------------------------------------------- 1 | import { PrimType, TermType } from "../../type_system"; 2 | 3 | /** 4 | * given a term type of a function (lambda) 5 | * extracts all the types from the inputs to the output 6 | * 7 | * the last type is the final output of the funciton. 8 | * 9 | * 10 | * @example 11 | * ```ts 12 | * const notFn = getFnTypes( int ); // [ int ]; 13 | * const simleLam = getFnTypes( lam( int, bs ) ); // [ int, bs ]; 14 | * const twoIns = getFnTypes( fn([ int, str ], bs ) ); // [ int, str, bs ]; 15 | * ``` 16 | * 17 | * @param {TermType} fnT function term type 18 | * @returns {TermType[]} 19 | */ 20 | export function getFnTypes( fnT: TermType ): TermType[] 21 | { 22 | const result: TermType[] = []; 23 | 24 | while( fnT[0] === PrimType.Lambda ) 25 | { 26 | result.push( fnT[1] ), 27 | fnT = fnT[2]; 28 | } 29 | 30 | result.push( fnT ); 31 | 32 | return result; 33 | } -------------------------------------------------------------------------------- /src/pluts/Script/__tests__/Script.compile.okScript.test.ts: -------------------------------------------------------------------------------- 1 | import { Lambda, UPLCConst } from "@harmoniclabs/uplc"; 2 | import { data, pfn, pmakeUnit, unit } from "../.."; 3 | import { productionOptions } from "../../../IR/toUPLC/CompilerOptions"; 4 | 5 | test("okScript", () => { 6 | 7 | const okScript = pfn([ data, data, data ], unit ) 8 | (( d, r, c ) => pmakeUnit()); 9 | 10 | expect( 11 | okScript.toUPLC(0, { ...productionOptions, addMarker: false }) 12 | ).toEqual( 13 | new Lambda( 14 | new Lambda( 15 | new Lambda( 16 | UPLCConst.unit 17 | ) 18 | ) 19 | ) 20 | ); 21 | 22 | }) -------------------------------------------------------------------------------- /src/pluts/Script/blueprint/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./getBlueprint"; 2 | export * from "./types"; 3 | export * from "./toBlueprintValidator"; 4 | export * from "./toDataSchema"; -------------------------------------------------------------------------------- /src/pluts/Script/compile.ts: -------------------------------------------------------------------------------- 1 | import { Cbor, CborBytes } from "@harmoniclabs/cbor"; 2 | import { UPLCEncoder, UPLCProgram, UPLCVersion } from "@harmoniclabs/uplc"; 3 | import type { PType } from "../PType"; 4 | import type { Term } from "../Term"; 5 | import { defaultVersion, getValidVersion } from "./getValidVersion"; 6 | import { PlutusScriptJsonFormat, PlutusScriptType } from "../../utils/PlutusScriptType"; 7 | 8 | 9 | export function compile( term: Term, version: Readonly<[number, number, number]> = defaultVersion ): Uint8Array 10 | { 11 | const v = getValidVersion( version ); 12 | 13 | return UPLCEncoder.compile( 14 | new UPLCProgram( 15 | new UPLCVersion( v[0], v[1], v[2] ), 16 | term.toUPLC( 0 ) 17 | ) 18 | ).toBuffer().buffer; 19 | } 20 | 21 | export function scriptToJsonFormat( 22 | compiledScript: Uint8Array, 23 | plutusScriptVersion: PlutusScriptType = "PlutusScriptV2", 24 | description: string = "" 25 | ): PlutusScriptJsonFormat 26 | { 27 | return { 28 | type: plutusScriptVersion, 29 | description: description, 30 | cborHex: Cbor.encode( 31 | new CborBytes( 32 | Cbor.encode( 33 | new CborBytes( 34 | compiledScript 35 | ) 36 | ).toBuffer() 37 | ) 38 | ).toString() 39 | } 40 | } -------------------------------------------------------------------------------- /src/pluts/Script/getValidVersion.ts: -------------------------------------------------------------------------------- 1 | 2 | export const defaultVersion: [ number, number, number ] = Object.freeze([ 1, 1, 0 ]) as any; 3 | 4 | export function getValidVersion( version: Readonly<[number, number, number]> ): [number, number, number] 5 | { 6 | const v = !Array.isArray( version ) || (version as any).length === 0 ? defaultVersion : version; 7 | return ([0,1,2].map( i => Math.abs( Math.round( v[i] ?? 0 ) ) )) as any; 8 | } -------------------------------------------------------------------------------- /src/pluts/Script/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./compile" 2 | export * from "./makeScript" 3 | // export * from "./blueprint"; -------------------------------------------------------------------------------- /src/pluts/Term/__tests__/Term.Hoisted.phoist.test.ts: -------------------------------------------------------------------------------- 1 | import { pgreaterInt } from "../../lib/builtins/int/intBinOpToBool" 2 | import { pInt } from "../../lib/std/int/pInt" 3 | 4 | 5 | describe("phoist", () => { 6 | 7 | it("keeps Term's properties", () => { 8 | 9 | /** 10 | * ```pgreaterInt``` definition: 11 | * ```ts 12 | * phoist( 13 | * pfn<[ PInt , PInt ], PBool>([ Type.Int, Type.Int ], Type.Bool )( 14 | * ( a: Term, b: Term ): TermBool => plessInt.$( b ).$( a ) 15 | * ) 16 | * ) 17 | * ``` 18 | */ 19 | expect( () => pgreaterInt.$( pInt( 2 ) ) ).not.toThrow(); 20 | 21 | }) 22 | }) -------------------------------------------------------------------------------- /src/pluts/__tests__/contract.docs.v3.hello.test.ts: -------------------------------------------------------------------------------- 1 | import { toHex } from "@harmoniclabs/uint8array-utils"; 2 | import { compile, data, passert, pBool, perror, pfn, plet, pmatch, PMaybe, PPubKeyHash, PScriptContext, punBData, unit } from ".." 3 | 4 | test("hello pluts", () => { 5 | 6 | const contract = pfn([ 7 | PScriptContext.type 8 | ], unit) 9 | (({ redeemer, tx, purpose }) => { 10 | 11 | const message = plet( punBData.$( redeemer ) ); 12 | 13 | const maybeDatum = plet( 14 | pmatch( purpose ) 15 | .onSpending(({ datum }) => datum ) 16 | ._(_ => perror( PMaybe( data ).type ) ) 17 | ); 18 | 19 | const signedByOwner = plet( 20 | pmatch( maybeDatum ) 21 | .onNothing( _ => pBool( true ) ) // no owner, so we approve it 22 | .onJust(({ val }) => 23 | tx.signatories.includes( punBData.$( val ) ) 24 | ) 25 | ); 26 | 27 | const isBeingPolite = message.eq("Hello plu-ts"); 28 | 29 | return passert.$( 30 | signedByOwner.and( isBeingPolite ) 31 | ); 32 | }); 33 | 34 | const compiled = compile( contract ); 35 | 36 | // console.log( toHex( compiled ) ); 37 | }); -------------------------------------------------------------------------------- /src/pluts/__tests__/contract.docs.v3.no_datum.test.ts: -------------------------------------------------------------------------------- 1 | import { toHex } from "@harmoniclabs/uint8array-utils"; 2 | import { compile, data, passert, pBool, bool, perror, pfn, plet, pmatch, PMaybe, UtilityTermOf, PScriptContext, unit, PData } from ".." 3 | 4 | test("hello pluts", () => { 5 | 6 | const contract = pfn([ 7 | PScriptContext.type 8 | ], unit) 9 | (({ redeemer, tx, purpose }) => { 10 | 11 | const maybeDatum = plet( 12 | pmatch( purpose ) 13 | .onSpending(({ datum }) => datum ) 14 | ._(_ => perror( PMaybe( data ).type ) ) 15 | ); 16 | 17 | return passert.$( 18 | maybeDatum.raw.index.eq( 1 ) 19 | ); 20 | }); 21 | 22 | const compiled = compile( contract ); 23 | 24 | // console.log( toHex( compiled ) ); 25 | }); -------------------------------------------------------------------------------- /src/pluts/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./PType"; 2 | export * from "./PTypes"; 3 | export * from "./Script"; 4 | export * from "./Script"; 5 | export * from "./Term"; 6 | export * from "./lib"; 7 | export * from "./type_system"; 8 | export * from "./API"; -------------------------------------------------------------------------------- /src/pluts/lib/__tests__/Syntax.plet.test.ts: -------------------------------------------------------------------------------- 1 | import { DataI } from "@harmoniclabs/plutus-data"; 2 | import { compile, int, passert, pData, perror, pfn, plet, pmatch, PScriptContext, PTxOut, punIData, PValue, Term, termTypeToString, unit } from "../.." 3 | 4 | test("plet keeps utility", () => { 5 | 6 | const contract = pfn([ 7 | PTxOut.type 8 | ], unit) 9 | ((input) => { 10 | 11 | const ownValue = plet( input.value ); 12 | 13 | expect( ownValue.lovelaces instanceof Term ).toBe( true ); 14 | expect( typeof ownValue.amountOf === "function" ).toBe( true ); 15 | 16 | const isValueLocked = ( 17 | ownValue.lovelaces.lt( 100 ) 18 | ); 19 | 20 | return passert.$( isValueLocked ); 21 | }) 22 | 23 | const compiled = compile( contract ); 24 | 25 | }) 26 | -------------------------------------------------------------------------------- /src/pluts/lib/builtins/__tests__/bool.eval.test.ts: -------------------------------------------------------------------------------- 1 | import { Machine } from "@harmoniclabs/plutus-machine"; 2 | import { pBool } from "../../std" 3 | 4 | describe("Machine.evalSimple( boolStatement )", () => { 5 | 6 | test("simple bool", () => { 7 | 8 | expect( 9 | Machine.evalSimple( 10 | pBool( true ) 11 | .and( 12 | pBool( true ) 13 | ) 14 | ) 15 | ).toEqual( 16 | Machine.evalSimple( 17 | pBool( true ) 18 | ) 19 | ); 20 | 21 | }); 22 | 23 | 24 | }) -------------------------------------------------------------------------------- /src/pluts/lib/builtins/__tests__/builtin.bench.test.ts: -------------------------------------------------------------------------------- 1 | import { Machine } from "@harmoniclabs/plutus-machine" 2 | import { pif, pstrictIf } from "../bool" 3 | import { int } from "../../../type_system" 4 | import { pBool, pInt, perror, pmatch, psop } from "../../.." 5 | import { defaultV3Costs } from "@harmoniclabs/cardano-costmodels-ts"; 6 | import { UPLCDecoder, UPLCEncoder, UPLCProgram, showUPLC } from "@harmoniclabs/uplc"; 7 | 8 | const SopBool = psop({ 9 | True: {}, 10 | False: {} 11 | }); 12 | 13 | describe("builtin bench", () => { 14 | 15 | test("ifThenElse", () => { 16 | 17 | const machine = new Machine( defaultV3Costs ); 18 | 19 | const _ifTerm = ( 20 | pif( int ).$( pBool( true ) ) 21 | .$( 1 ) 22 | .$( 2 ) 23 | ); 24 | const ifTerm = UPLCDecoder.parse( 25 | UPLCEncoder.compile( 26 | new UPLCProgram( 27 | [ 1, 1, 0 ], 28 | _ifTerm.toUPLC( 0 ), 29 | ) 30 | ).toBuffer().buffer 31 | ).body; 32 | const a = machine.eval( ifTerm ); 33 | 34 | const sopIfTerm = ( 35 | pmatch( SopBool.True({}) ) 36 | .onTrue( _ => pInt( 1 ) ) 37 | .onFalse( _ => pInt( 2 ) ) 38 | ) 39 | const b = machine.eval( sopIfTerm ); 40 | 41 | // console.log( showUPLC( ifTerm ) ); 42 | // console.log( showUPLC( sopIfTerm.toUPLC() ) ); 43 | 44 | // console.log( 45 | // a.budgetSpent.toJson(), 46 | // b.budgetSpent.toJson(), 47 | // ); 48 | }) 49 | 50 | }) -------------------------------------------------------------------------------- /src/pluts/lib/builtins/_pflipIR.ts: -------------------------------------------------------------------------------- 1 | import { IRApp } from "../../../IR/IRNodes/IRApp"; 2 | import { IRFunc } from "../../../IR/IRNodes/IRFunc"; 3 | import { IRHoisted } from "../../../IR/IRNodes/IRHoisted"; 4 | import { IRVar } from "../../../IR/IRNodes/IRVar"; 5 | 6 | // identicall to `pflip` just at UPLC level to avoid using `papp` 7 | export const _pflipIR = new IRHoisted( 8 | new IRFunc( 3, // toFlip, secondarg, fstArg 9 | new IRApp( 10 | new IRApp( 11 | new IRVar( 2 ), // toFlip, 12 | new IRVar( 0 ) // firstArg 13 | ), 14 | new IRVar( 1 ) // secondArg 15 | ) 16 | ) 17 | ); 18 | _pflipIR.hash; -------------------------------------------------------------------------------- /src/pluts/lib/builtins/addApplications.ts: -------------------------------------------------------------------------------- 1 | import { defineReadOnlyProperty } from "@harmoniclabs/obj-utils"; 2 | import type { PType } from "../../PType"; 3 | import type { PFn, TermFn } from "../../PTypes/PFn/PFn"; 4 | import type { Term } from "../../Term"; 5 | 6 | import { getNRequiredLambdaArgs } from "../../type_system/utils"; 7 | import { papp } from "../papp"; 8 | import { PappArg } from "../pappArg"; 9 | import { Head } from "../../../utils/types"; 10 | 11 | 12 | export function addApplications 13 | ( 14 | lambdaTerm: Term< PFn< Ins, Out > > 15 | ) 16 | : TermFn< Ins, Out > 17 | { 18 | const nMissingArgs = getNRequiredLambdaArgs( lambdaTerm.type ); 19 | 20 | if( nMissingArgs <= 1 ) 21 | { 22 | return defineReadOnlyProperty( 23 | lambdaTerm, 24 | "$", 25 | ( input: PappArg< Head > ) => { 26 | let output: any = papp( lambdaTerm as any, input ); 27 | 28 | return output; 29 | } 30 | ) as any; 31 | } 32 | 33 | return defineReadOnlyProperty( 34 | lambdaTerm, 35 | "$", 36 | ( input: PappArg< Head > ) => 37 | // @ts-ignore 38 | // Type 'PType[]' is not assignable to type '[PType, ...PType[]]'. 39 | // Source provides no match for required element at position 0 in target 40 | addApplications< Tail, Out >( 41 | papp( lambdaTerm as any , input ) as any 42 | ) 43 | ) as any; 44 | } -------------------------------------------------------------------------------- /src/pluts/lib/builtins/bls12_381_MlResult/index.ts: -------------------------------------------------------------------------------- 1 | import { PBlsG2 } from "../../../PTypes/PBlsG2"; 2 | import { blsG1, blsG2, blsResult, bool, fn } from "../../../type_system/types"; 3 | import { IRNative } from "../../../../IR/IRNodes/IRNative"; 4 | import { Term } from "../../../Term"; 5 | import { PBool } from "../../../PTypes/PBool"; 6 | import { PBlsMlRes } from "../../../PTypes/PBlsMlRes"; 7 | import { addApplications } from "../addApplications"; 8 | 9 | export const bls12_381_millerLoop = addApplications<[ PBlsG2, PBlsG2 ], PBlsMlRes>( 10 | new Term( 11 | fn([ blsG1, blsG2 ], blsResult ), 12 | _dbn => { 13 | return IRNative.bls12_381_millerLoop; 14 | } 15 | ) 16 | ); 17 | 18 | export const bls12_381_mulMlResult = addApplications<[ PBlsMlRes, PBlsMlRes ], PBlsMlRes>( 19 | new Term( 20 | fn([ blsResult, blsResult ], blsResult ), 21 | _dbn => { 22 | return IRNative.bls12_381_mulMlResult; 23 | } 24 | ) 25 | ); 26 | 27 | export const bls12_381_finalVerify = addApplications<[ PBlsMlRes, PBlsMlRes ], PBool>( 28 | new Term( 29 | fn([ blsResult, blsResult ], bool ), 30 | _dbn => { 31 | return IRNative.bls12_381_finalVerify; 32 | } 33 | ) 34 | ); -------------------------------------------------------------------------------- /src/pluts/lib/builtins/hoisted.ts: -------------------------------------------------------------------------------- 1 | import { defineReadOnlyProperty } from "@harmoniclabs/obj-utils"; 2 | import { TermFn, PLam } from "../../PTypes"; 3 | import { Term } from "../../Term"; 4 | import { TermType, ToPType, lam } from "../../type_system"; 5 | import { papp } from "../papp"; 6 | import { phoist } from "../phoist"; 7 | import { IRNative } from "../../../IR/IRNodes/IRNative"; 8 | 9 | 10 | export function pid( termT: TermT ): TermFn<[ ToPType ], ToPType> 11 | { 12 | const idTerm = new Term,ToPType>>( 13 | lam( termT, termT ) as any, 14 | _dbn => IRNative._id 15 | ); 16 | return phoist( 17 | defineReadOnlyProperty( 18 | idTerm, 19 | "$", 20 | ( whatever: Term> ) => papp( idTerm, whatever ) 21 | ) 22 | ) as any; 23 | } -------------------------------------------------------------------------------- /src/pluts/lib/builtins/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./bool"; 2 | export * from "./bs"; 3 | export * from "./data"; 4 | export * from "./hoisted"; 5 | export * from "./int"; 6 | export * from "./list"; 7 | export * from "./pair"; 8 | export * from "./pchooseUnit"; 9 | export * from "./ppairData"; 10 | export * from "./pprepend"; 11 | export * from "./ptrace"; 12 | export * from "./str"; 13 | export * from "./bls12_381_G1_element"; 14 | export * from "./bls12_381_G2_element"; 15 | export * from "./bls12_381_MlResult"; -------------------------------------------------------------------------------- /src/pluts/lib/builtins/int/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./padd"; 2 | export * from "./pdiv"; 3 | export * from "./pmod"; 4 | export * from "./pmult"; 5 | export * from "./pquot"; 6 | export * from "./prem"; 7 | export * from "./psub"; 8 | export * from "./intBinOpToBool" -------------------------------------------------------------------------------- /src/pluts/lib/builtins/int/intBinOpToInt.ts: -------------------------------------------------------------------------------- 1 | import { defineReadOnlyProperty } from "@harmoniclabs/obj-utils"; 2 | import { IRTerm } from "../../../../IR/IRTerm"; 3 | import { PLam, PInt } from "../../../PTypes"; 4 | import { Term } from "../../../Term"; 5 | import { fn, int } from "../../../type_system"; 6 | import { papp } from "../../papp"; 7 | import { PappArg } from "../../pappArg"; 8 | import { TermInt } from "../../std"; 9 | 10 | 11 | export type IntBinOPToInt = Term>> 12 | & { 13 | $: ( input: PappArg ) => 14 | Term> 15 | & { 16 | $: ( input: PappArg ) => 17 | TermInt 18 | } 19 | } 20 | 21 | export function intBinOpToInt( builtin: IRTerm ) 22 | : IntBinOPToInt 23 | { 24 | const op = new Term>>( 25 | fn([ int, int ], int ), 26 | _dbn => builtin 27 | ); 28 | 29 | return defineReadOnlyProperty( 30 | op, 31 | "$", 32 | ( fstIn: PappArg ): Term> => { 33 | 34 | const oneIn = papp( op, fstIn ); 35 | 36 | return defineReadOnlyProperty( 37 | oneIn, 38 | "$", 39 | ( sndIn: PappArg ): TermInt => { 40 | return papp( oneIn, sndIn ) 41 | } 42 | ); 43 | } 44 | ) as any; 45 | } -------------------------------------------------------------------------------- /src/pluts/lib/builtins/int/padd.ts: -------------------------------------------------------------------------------- 1 | import { IRNative } from "../../../../IR/IRNodes/IRNative"; 2 | import { intBinOpToInt } from "./intBinOpToInt"; 3 | 4 | export const padd = intBinOpToInt( IRNative.addInteger ); -------------------------------------------------------------------------------- /src/pluts/lib/builtins/int/pdiv.ts: -------------------------------------------------------------------------------- 1 | import { intBinOpToInt } from "./intBinOpToInt"; 2 | import { IRNative } from "../../../../IR/IRNodes/IRNative"; 3 | 4 | export const pdiv = intBinOpToInt( IRNative.divideInteger); -------------------------------------------------------------------------------- /src/pluts/lib/builtins/int/pmod.ts: -------------------------------------------------------------------------------- 1 | import { intBinOpToInt } from "./intBinOpToInt"; 2 | import { IRNative } from "../../../../IR/IRNodes/IRNative"; 3 | 4 | export const pmod = intBinOpToInt( IRNative.modInteger ); -------------------------------------------------------------------------------- /src/pluts/lib/builtins/int/pmult.ts: -------------------------------------------------------------------------------- 1 | import { intBinOpToInt } from "./intBinOpToInt"; 2 | import { IRNative } from "../../../../IR/IRNodes/IRNative"; 3 | 4 | export const pmult = intBinOpToInt( IRNative.multiplyInteger ); -------------------------------------------------------------------------------- /src/pluts/lib/builtins/int/pquot.ts: -------------------------------------------------------------------------------- 1 | import { intBinOpToInt } from "./intBinOpToInt"; 2 | import { IRNative } from "../../../../IR/IRNodes/IRNative"; 3 | 4 | export const pquot = intBinOpToInt( IRNative.quotientInteger ); -------------------------------------------------------------------------------- /src/pluts/lib/builtins/int/prem.ts: -------------------------------------------------------------------------------- 1 | import { IRNative } from "../../../../IR/IRNodes/IRNative"; 2 | import { intBinOpToInt } from "./intBinOpToInt"; 3 | 4 | export const prem = intBinOpToInt( IRNative.remainderInteger ); -------------------------------------------------------------------------------- /src/pluts/lib/builtins/int/psub.ts: -------------------------------------------------------------------------------- 1 | import { intBinOpToInt } from "./intBinOpToInt"; 2 | import { IRNative } from "../../../../IR/IRNodes/IRNative"; 3 | 4 | export const psub = intBinOpToInt( IRNative.subtractInteger); -------------------------------------------------------------------------------- /src/pluts/lib/builtins/list/__tests__/list.builtins.test.ts: -------------------------------------------------------------------------------- 1 | import { Machine } from "@harmoniclabs/plutus-machine" 2 | import { pchooseList } from ".." 3 | import { int, unit } from "../../../../type_system/types" 4 | import { pInt } from "../../../std/int/pInt" 5 | import { perror } from "../../../perror" 6 | 7 | describe("list.builtins", () => { 8 | 9 | describe("pchooseList", () => { 10 | 11 | test("[] -> 0", () => { 12 | expect( 13 | Machine.evalSimple( 14 | pchooseList( unit, int ) 15 | .$( [] as any ) 16 | .$( pInt(0) ) 17 | .$( perror( int ) ) 18 | ) 19 | ) 20 | .toEqual( 21 | Machine.evalSimple( 22 | pInt( 0 ) 23 | ) 24 | ) 25 | }); 26 | 27 | test("[] -> 0", () => { 28 | expect( 29 | Machine.evalSimple( 30 | pchooseList( unit, int ) 31 | .$( [] as any ) 32 | .$( pInt(0) ) 33 | .$( perror( int ) ) 34 | ) 35 | ) 36 | .toEqual( 37 | Machine.evalSimple( 38 | pInt( 0 ) 39 | ) 40 | ) 41 | }); 42 | 43 | }) 44 | }) -------------------------------------------------------------------------------- /src/pluts/lib/builtins/list/minimal.ts: -------------------------------------------------------------------------------- 1 | import { IRNative } from "../../../../IR/IRNodes/IRNative"; 2 | import { TermFn, PList } from "../../../PTypes"; 3 | import { Term } from "../../../Term"; 4 | import { TermType, ToPType, fn, lam, list } from "../../../type_system"; 5 | 6 | export function _pstrictChooseList( listElemT: ListElemT, returnT: ReturnT ) 7 | : TermFn<[ PList< ToPType> , ToPType, ToPType ], ToPType> 8 | { 9 | return new Term( 10 | fn([ list( listElemT ), returnT, returnT ], returnT ) as any, 11 | _dbn => IRNative.strictChooseList 12 | ) as any; 13 | } 14 | 15 | 16 | export function _phead( listElemType: ListElemT ) 17 | : TermFn<[ PList> ], ToPType> 18 | { 19 | const listElemT = listElemType; 20 | 21 | return new Term( 22 | lam( list( listElemT ), listElemT ) as any, 23 | _dbn => IRNative.headList 24 | ) as any; 25 | } 26 | 27 | export function _ptail( listElemT: ListElemT ) 28 | : TermFn<[ PList< ToPType> ], PList< ToPType>> 29 | { 30 | return new Term( 31 | lam( list( listElemT ), list( listElemT ) ) as any, 32 | _dbn => IRNative.tailList 33 | ) as any; 34 | } -------------------------------------------------------------------------------- /src/pluts/lib/builtins/pchooseUnit.ts: -------------------------------------------------------------------------------- 1 | import { IRNative } from "../../../IR/IRNodes/IRNative"; 2 | import { TermFn, PUnit } from "../../PTypes"; 3 | import { Term } from "../../Term"; 4 | import { TermType, ToPType, fn, unit } from "../../type_system"; 5 | import { addApplications } from "./addApplications"; 6 | 7 | export function pchooseUnit( returnT: ReturnT ) 8 | : TermFn<[ PUnit, ToPType ], ToPType> 9 | { 10 | return addApplications<[ PUnit, ToPType ], ToPType>( 11 | new Term( 12 | fn([ unit, returnT ], returnT ) as any, 13 | _dbn => IRNative.chooseUnit, 14 | ) 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /src/pluts/lib/builtins/ppairData.ts: -------------------------------------------------------------------------------- 1 | import { IRNative } from "../../../IR/IRNodes/IRNative"; 2 | import { TermFn, PData, PPair } from "../../PTypes"; 3 | import { Term } from "../../Term"; 4 | import { fn, data, pair } from "../../type_system"; 5 | import { addApplications } from "./addApplications"; 6 | 7 | 8 | export const ppairData: TermFn<[ PData, PData ], PPair> 9 | = addApplications<[ PData, PData ], PPair>( 10 | new Term( 11 | fn([ data, data ], pair( data, data ) ), 12 | _dbn => IRNative.mkPairData 13 | ) 14 | ); -------------------------------------------------------------------------------- /src/pluts/lib/builtins/pprepend/index.ts: -------------------------------------------------------------------------------- 1 | import { IRNative } from "../../../../IR/IRNodes/IRNative"; 2 | import { TermFn, PList } from "../../../PTypes"; 3 | import { Term } from "../../../Term"; 4 | import { TermType, ToPType, fn, list } from "../../../type_system"; 5 | import { addApplications } from "../addApplications"; 6 | 7 | 8 | export function pprepend( listElemType: ListElemT ) 9 | : TermFn<[ ToPType , PList> ], PList>> 10 | { 11 | const listElemT = listElemType ; 12 | 13 | return addApplications<[ ToPType , PList> ], PList>>( 14 | new Term( 15 | fn([ listElemT, list( listElemT ) ], list( listElemT ) ) as any, 16 | _dbn => IRNative.mkCons 17 | ) 18 | ); 19 | } -------------------------------------------------------------------------------- /src/pluts/lib/builtins/pprepend/minimal.ts: -------------------------------------------------------------------------------- 1 | import { IRNative } from "../../../../IR/IRNodes/IRNative"; 2 | import { PList, PLam } from "../../../PTypes"; 3 | import { Term } from "../../../Term"; 4 | import { TermType, ToPType, fn, list } from "../../../type_system"; 5 | 6 | export function _pprepend( listElemType: ListElemT ) 7 | : Term, PList>>, PList>>> 8 | { 9 | const listElemT = listElemType ; 10 | 11 | return new Term( 12 | fn([ listElemT, list( listElemT ) ], list( listElemT ) ) as any, 13 | _dbn => IRNative.mkCons 14 | ) as any; 15 | } -------------------------------------------------------------------------------- /src/pluts/lib/builtins/ptrace.ts: -------------------------------------------------------------------------------- 1 | import { IRNative } from "../../../IR/IRNodes/IRNative"; 2 | import type { TermFn, PString } from "../../PTypes"; 3 | import { Term } from "../../Term"; 4 | import { TermType, ToPType, fn, str, bool, delayed } from "../../type_system"; 5 | import { pdelay } from "../pdelay"; 6 | import { perror } from "../perror"; 7 | import { pfn } from "../pfn"; 8 | import { pforce } from "../pforce"; 9 | import { phoist } from "../phoist"; 10 | import { plam } from "../plam"; 11 | import { pBool } from "../std/bool/pBool"; 12 | import { addApplications } from "./addApplications"; 13 | import { pif } from "./bool"; 14 | 15 | 16 | export function ptrace( returnT: ReturnT ) 17 | : TermFn<[ PString, ToPType ], ToPType> 18 | { 19 | return addApplications<[ PString, ToPType ], ToPType>( 20 | new Term( 21 | fn([ str, returnT ], returnT ) as any, 22 | _dbn => IRNative.trace 23 | ) 24 | ); 25 | } -------------------------------------------------------------------------------- /src/pluts/lib/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./perror"; 2 | export * from "./pdelay"; 3 | export * from "./pforce"; 4 | export * from "./phoist"; 5 | export * from "./punsafeConvertType"; 6 | export * from "./pappArg"; 7 | export * from "./papp"; 8 | export * from "./plam"; 9 | export * from "./pfn"; 10 | export * from "./precursive"; 11 | export * from "./std/UtilityTerms/addUtilityForType"; 12 | export * from "./builtins"; 13 | export * from "./builtins/ptrace"; 14 | export * from "./plet"; 15 | export * from "./pmatch/pmatch"; 16 | export * from "./std"; 17 | export * from "./show"; -------------------------------------------------------------------------------- /src/pluts/lib/pdelay.ts: -------------------------------------------------------------------------------- 1 | import { IRDelayed } from "../../IR/IRNodes/IRDelayed"; 2 | import { PType } from "../PType"; 3 | import { PDelayed } from "../PTypes"; 4 | import { Term } from "../Term"; 5 | import { delayed } from "../type_system/types"; 6 | 7 | export function pdelay(toDelay: Term): Term> 8 | { 9 | return new Term( 10 | delayed( toDelay.type ), 11 | (cfg, dbn) => { 12 | return new IRDelayed( 13 | toDelay.toIR( cfg, dbn ) 14 | ); 15 | } 16 | ); 17 | } -------------------------------------------------------------------------------- /src/pluts/lib/perror.ts: -------------------------------------------------------------------------------- 1 | import { IRError } from "../../IR/IRNodes/IRError"; 2 | import { Term } from "../Term"; 3 | import { TermType, ToPType } from "../type_system"; 4 | 5 | export function perror( type: T , msg: string | undefined = undefined, addInfos: object | undefined = {}): Term> 6 | { 7 | addInfos = 8 | typeof addInfos === "object" && 9 | addInfos !== null ? 10 | addInfos : 11 | { __original__: addInfos }; 12 | 13 | let src = new Error().stack?.split("\n")[2]; 14 | src = src?.slice( src.indexOf("at ") + 3 ); 15 | 16 | (addInfos as any).__src__ = src; 17 | 18 | return new Term( 19 | type as any, 20 | _dbn => new IRError( msg, addInfos ) 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /src/pluts/lib/pforce/index.ts: -------------------------------------------------------------------------------- 1 | import { IRDelayed } from "../../../IR/IRNodes/IRDelayed"; 2 | import { IRForced } from "../../../IR/IRNodes/IRForced"; 3 | import { PType } from "../../PType"; 4 | import { PDelayed } from "../../PTypes"; 5 | import { Term } from "../../Term"; 6 | import { PrimType } from "../../type_system"; 7 | import { UtilityTermOf, addUtilityForType } from "../std/UtilityTerms/addUtilityForType"; 8 | 9 | export function pforce( toForce: Term> ): UtilityTermOf 10 | export function pforce( toForce: Term ): UtilityTermOf 11 | export function pforce( toForce: Term> | Term ): UtilityTermOf 12 | { 13 | const outType = toForce.type[0] === PrimType.Delayed ? toForce.type[1] : toForce.type; 14 | 15 | return addUtilityForType( outType )( 16 | new Term( 17 | outType as any, 18 | (cfg, dbn) => { 19 | const toForceUPLC = toForce.toIR( cfg, dbn ); 20 | 21 | // if directly applying to Delay UPLC just remove the delay 22 | // example: 23 | // (force (delay (con int 11))) === (con int 11) 24 | if( toForceUPLC instanceof IRDelayed ) 25 | { 26 | return toForceUPLC.delayed; 27 | } 28 | 29 | // any other case 30 | return new IRForced( 31 | toForceUPLC 32 | ); 33 | } 34 | ) 35 | ) as any; 36 | } -------------------------------------------------------------------------------- /src/pluts/lib/pforce/minimal.ts: -------------------------------------------------------------------------------- 1 | import { IRDelayed } from "../../../IR/IRNodes/IRDelayed"; 2 | import { IRForced } from "../../../IR/IRNodes/IRForced"; 3 | import { PType } from "../../PType"; 4 | import { PDelayed } from "../../PTypes/PDelayed"; 5 | import { Term } from "../../Term"; 6 | import { PrimType } from "../../type_system/types"; 7 | 8 | export function _pforce 9 | ( toForce: Term> | Term ): Term 10 | { 11 | const outType = toForce.type[0] === PrimType.Delayed ? toForce.type[1] : toForce.type; 12 | 13 | return new Term( 14 | outType as any, 15 | (cfg, dbn) => { 16 | const toForceUPLC = toForce.toIR( cfg, dbn ); 17 | 18 | // if directly applying to Delay UPLC just remove the delay 19 | // example: 20 | // (force (delay (con int 11))) === (con int 11) 21 | if( toForceUPLC instanceof IRDelayed ) 22 | { 23 | return toForceUPLC.delayed; 24 | } 25 | 26 | // any other case 27 | return new IRForced( 28 | toForceUPLC 29 | ); 30 | } 31 | ); 32 | } 33 | 34 | export const pforce_minimal = _pforce; -------------------------------------------------------------------------------- /src/pluts/lib/phoist.ts: -------------------------------------------------------------------------------- 1 | import { getCallStackAt } from "../../utils/getCallStackAt"; 2 | import type { PType } from "../PType"; 3 | import type { Term } from "../Term"; 4 | 5 | export function phoist( closedTerm: Term & SomeExtension ): Term & SomeExtension 6 | { 7 | /* 8 | the implementation has been moved to a method of the term 9 | since all 'phoist' is doing is wrapping whatever UPLC the 'Term' represent 10 | into an 'HoistedUPLC' 11 | 12 | however proevious implementaiton achieved this by creating a new term and then **copying** eventual extension 13 | 14 | this was a problem since the extension methods are defined using the **raw** UPLC rather than the hoisted 15 | causing the hoisted result not to be actually hoisted if accessed using the methods 16 | 17 | moving the "wrapping" of the 'toUPLC' method inside the term, preserves the same 'Term' object 18 | but the same 'Term' object is now properly hoisted 19 | 20 | this also removes the `O(n)` operation of copying the methods; since the methods are already there 21 | */ 22 | (closedTerm as any).hoist(); 23 | return closedTerm; 24 | } -------------------------------------------------------------------------------- /src/pluts/lib/plet/__tests__/plet.test.ts: -------------------------------------------------------------------------------- 1 | import { pBool, pfn, plet } from "../.." 2 | import { compileIRToUPLC } from "../../../../IR/toUPLC/compileIRToUPLC"; 3 | import { bool, int } from "../../../type_system" 4 | 5 | 6 | const double = pfn([ int ], int) 7 | ( n => n.add( n ) ) 8 | 9 | describe("plet", () => { 10 | 11 | test("quadruple", () => { 12 | 13 | const quadruple = pfn([ int ], int ) 14 | ( n => { 15 | 16 | const doubled = plet( double.$( n ) ); 17 | 18 | return doubled.add( doubled ); 19 | }); 20 | 21 | const oldQuadruple = pfn([ int ], int ) 22 | ( n => { 23 | return plet( double.$( n ) ).in( doubled => 24 | 25 | doubled.add( doubled ) 26 | 27 | ) 28 | }) 29 | 30 | const ir = quadruple.toIR(); 31 | const uplc = compileIRToUPLC( ir ); 32 | 33 | const oldIR = oldQuadruple.toIR(); 34 | const oldUPLC = compileIRToUPLC( oldIR ) 35 | 36 | expect( uplc ).toEqual( oldUPLC ) 37 | }); 38 | 39 | test("let in and", () => { 40 | 41 | const fancyIsZero = pfn([ int ], bool ) 42 | ( n => pBool( true ) 43 | .and( 44 | plet( n.add( 4 ) ).in( expected4 => expected4.eq( 4 ) ) 45 | ) 46 | ); 47 | 48 | const ir = fancyIsZero.toIR(); 49 | const uplc = compileIRToUPLC( ir ); 50 | 51 | // console.log( showUPLC( uplc ) ); 52 | 53 | }); 54 | 55 | }) -------------------------------------------------------------------------------- /src/pluts/lib/plet/minimal.ts: -------------------------------------------------------------------------------- 1 | import { IRHoisted } from "../../../IR/IRNodes/IRHoisted"; 2 | import { IRLetted } from "../../../IR/IRNodes/IRLetted"; 3 | import { IRSelfCall } from "../../../IR/IRNodes/IRSelfCall"; 4 | import { IRVar } from "../../../IR/IRNodes/IRVar"; 5 | import { isClosedIRTerm } from "../../../IR/utils/isClosedIRTerm"; 6 | import type { PType } from "../../PType"; 7 | import { Term } from "../../Term"; 8 | 9 | export function _plet( varValue: Term ): Term 10 | { 11 | return new Term( 12 | varValue.type, 13 | (cfg, dbn) => { 14 | 15 | const ir = varValue.toIR( cfg, dbn ); 16 | 17 | // `compileIRToUPLC` can handle it even if this check is not present 18 | // but why spend useful tree iterations if we can avoid them here? 19 | if( 20 | ir instanceof IRLetted || 21 | ir instanceof IRHoisted || 22 | ir instanceof IRVar || 23 | ir instanceof IRSelfCall 24 | ) 25 | { 26 | return ir; 27 | } 28 | 29 | if( isClosedIRTerm( ir ) ) 30 | { 31 | return new IRHoisted( ir ); 32 | } 33 | 34 | return new IRLetted( 35 | Number( dbn ), 36 | ir 37 | ); 38 | } 39 | ) 40 | } -------------------------------------------------------------------------------- /src/pluts/lib/pmatch/__tests__/pmatch.ctx.purpose.ts: -------------------------------------------------------------------------------- 1 | import { perror, pfn, pmatch } from "../.."; 2 | import { PScriptContext, PTxOutRef } from "../../../API" 3 | 4 | test("ctx.purpose", () => { 5 | 6 | const term = pfn([ PScriptContext.type ], PTxOutRef.type ) 7 | (({ purpose }) => 8 | pmatch( purpose ) 9 | .onSpending(({ utxoRef }) => utxoRef ) 10 | ._(_ => perror( PTxOutRef.type )) 11 | ); 12 | 13 | const uplc = term.toUPLC(); 14 | }) -------------------------------------------------------------------------------- /src/pluts/lib/pmatch/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pmatch"; -------------------------------------------------------------------------------- /src/pluts/lib/pmatch/pmatch.ts: -------------------------------------------------------------------------------- 1 | import { PrimType, SopDefinition, StructCtorDef, StructDefinition, TermType, data, list } from "../../type_system/types"; 2 | import type { Term } from "../../Term"; 3 | import { PStruct } from "../../PTypes/PStruct/pstruct"; 4 | import { termTypeToString } from "../../type_system/utils"; 5 | import type { PSop } from "../../PTypes/PSoP/psop"; 6 | import { isTaggedAsAlias, unwrapAlias } from "../../type_system"; 7 | import { pmatchStruct } from "./pmatchStruct"; 8 | import { pmatchSop } from "./pmatchSop"; 9 | import { PMatchOptions } from "./PMatchOptions"; 10 | 11 | export function pmatch( term: Term> | Term> ): PMatchOptions 12 | { 13 | let t: TermType = term.type as any; 14 | t = isTaggedAsAlias( t as any ) ? unwrapAlias( t ) : t; 15 | 16 | if( t[0] === PrimType.Struct ) return pmatchStruct( term as any ); 17 | else if( t[0] === PrimType.Sop ) return pmatchSop( term as any ); 18 | 19 | throw new Error( 20 | "invalid term to match; term type is: " + 21 | termTypeToString( term.type ) 22 | ); 23 | } -------------------------------------------------------------------------------- /src/pluts/lib/precursive/index.ts: -------------------------------------------------------------------------------- 1 | import { IRApp } from "../../../IR/IRNodes/IRApp"; 2 | import { IRNative } from "../../../IR/IRNodes/IRNative"; 3 | import { assert } from "../../../utils/assert"; 4 | import { PType } from "../../PType"; 5 | import { PLam, TermFn } from "../../PTypes"; 6 | import { Term } from "../../Term"; 7 | import { TermType, lam, tyVar, typeExtends } from "../../type_system"; 8 | import { addUtilityForType } from "../std/UtilityTerms/addUtilityForType"; 9 | import { _precursive } from "./minimal"; 10 | 11 | 12 | /** 13 | * for reference the "Z combinator in js": https://medium.com/swlh/y-and-z-combinators-in-javascript-lambda-calculus-with-real-code-31f25be934ec 14 | * 15 | * ```js 16 | * const Zcombinator = ( 17 | * Z => ( 18 | * toMakeRecursive => Z( value => toMakeRecursive(toMakeRecursive)(value) ) 19 | * )( toMakeRecursive => Z( value => toMakeRecursive(toMakeRecursive)(value)) ) 20 | * ); 21 | * ``` 22 | * of type 23 | * ```js 24 | * Z => toMakeRecursive => value => result 25 | * ``` 26 | * and ```toMakeRecursive``` has to be of type 27 | * ```js 28 | * self => value => result 29 | * ``` 30 | */ 31 | export function precursive 32 | ( fnBody: 33 | Term, // self 35 | PLam> // the actual function 36 | > 37 | ): TermFn<[ A ], B > 38 | { 39 | return addUtilityForType( fnBody.type[2] as TermType )( _precursive( fnBody ) ) as any; 40 | } 41 | -------------------------------------------------------------------------------- /src/pluts/lib/punsafeConvertType/index.ts: -------------------------------------------------------------------------------- 1 | import type { PType } from "../../PType"; 2 | import type { TermType } from "../../type_system/types"; 3 | import type { ToPType } from "../../type_system/ts-pluts-conversion"; 4 | import { type UtilityTermOf, addUtilityForType } from "../std/UtilityTerms/addUtilityForType"; 5 | import { isWellFormedType } from "../../type_system/kinds/isWellFormedType"; 6 | import { Term } from "../../Term"; 7 | 8 | 9 | export function punsafeConvertType 10 | ( psome: Term, toType: ToTermType ): UtilityTermOf> 11 | { 12 | if( !isWellFormedType( toType ) ) 13 | { 14 | throw new Error("`punsafeConvertType` called with invalid type"); 15 | } 16 | 17 | const converted = new Term( 18 | toType, 19 | psome.toIR, 20 | Boolean((psome as any).isConstant) // isConstant 21 | ) as any; 22 | 23 | Object.keys( psome ).forEach( k => { 24 | 25 | // do not overwrite `type` and `toUPLC` properties 26 | if( 27 | k === "type" || 28 | k === "toUPLC" || 29 | k === "toIR" 30 | ) return; 31 | 32 | Object.defineProperty( 33 | converted, 34 | k, 35 | Object.getOwnPropertyDescriptor( 36 | psome, 37 | k 38 | ) ?? {} 39 | ) 40 | 41 | }); 42 | 43 | return addUtilityForType( toType )( converted ) as any; 44 | } 45 | 46 | export function term_as( this: Term, toType: ToTermType ): UtilityTermOf> 47 | { 48 | return punsafeConvertType( this, toType ); 49 | } -------------------------------------------------------------------------------- /src/pluts/lib/punsafeConvertType/minimal.ts: -------------------------------------------------------------------------------- 1 | import type { PType } from "../../PType"; 2 | import type { TermType } from "../../type_system/types"; 3 | import type { ToPType } from "../../type_system/ts-pluts-conversion"; 4 | import { isWellFormedType } from "../../type_system/kinds/isWellFormedType"; 5 | import { Term } from "../../Term"; 6 | 7 | 8 | export function _punsafeConvertType 9 | ( psome: Term, toType: ToTermType ): Term> 10 | { 11 | if( !isWellFormedType( toType ) ) 12 | throw new Error(""); 13 | 14 | const converted = new Term( 15 | toType, 16 | psome.toIR, 17 | Boolean((psome as any).isConstant) // isConstant 18 | ) as any; 19 | 20 | Object.keys( psome ).forEach( k => { 21 | 22 | // do not overwrite `type` and `toUPLC` properties 23 | if( 24 | k === "type" || 25 | k === "toUPLC" || 26 | k === "toIR" 27 | ) return; 28 | 29 | Object.defineProperty( 30 | converted, 31 | k, 32 | Object.getOwnPropertyDescriptor( 33 | psome, 34 | k 35 | ) ?? {} 36 | ) 37 | 38 | }); 39 | 40 | return converted as any; 41 | } -------------------------------------------------------------------------------- /src/pluts/lib/show/bool.ts: -------------------------------------------------------------------------------- 1 | import { fromAscii } from "@harmoniclabs/uint8array-utils"; 2 | import { bool, bs } from "../../type_system"; 3 | import { pstrictIf, ptrace } from "../builtins"; 4 | import { phoist } from "../phoist"; 5 | import { plam } from "../plam"; 6 | 7 | export const pshowBool = phoist( 8 | plam( bool, bs ) 9 | ( b => 10 | pstrictIf( bs ).$( b ) 11 | .$( fromAscii("true") ) 12 | .$( fromAscii("false") ) 13 | ) 14 | ); 15 | 16 | export const ptraceBool = phoist( 17 | plam( bool, bool ) 18 | ( b => ptrace( bool ).$( pshowBool.$( b ).utf8Decoded ).$( b ) ) 19 | ) -------------------------------------------------------------------------------- /src/pluts/lib/show/data.ts: -------------------------------------------------------------------------------- 1 | import { bs, data } from "../../type_system"; 2 | import { pserialiseData, ptrace } from "../builtins"; 3 | import { phoist } from "../phoist"; 4 | import { plam } from "../plam"; 5 | import { pbsToHex } from "./bs"; 6 | 7 | export const pshowData = phoist( 8 | plam( data, bs ) 9 | ( d => pbsToHex.$( pserialiseData.$( d ) ) ) 10 | ); 11 | 12 | export const ptraceData = phoist( 13 | plam( data, data ) 14 | ( d => ptrace( data ).$( pshowData.$( d ).utf8Decoded ).$( d ) ) 15 | ); -------------------------------------------------------------------------------- /src/pluts/lib/show/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./bool"; 2 | export * from "./bs"; 3 | export * from "./data"; 4 | export * from "./int"; 5 | export * from "./pair"; 6 | export * from "./pshow"; 7 | export * from "./ptraceVal"; 8 | export * from "./list"; 9 | export * from "./str"; 10 | export * from "./unit"; -------------------------------------------------------------------------------- /src/pluts/lib/show/int.ts: -------------------------------------------------------------------------------- 1 | import { fromAscii } from "@harmoniclabs/uint8array-utils"; 2 | import { pif } from "../builtins/bool"; 3 | import { bs, int, lam } from "../../type_system/types"; 4 | import { phoist } from "../phoist"; 5 | import { pfn } from "../pfn"; 6 | import { plam } from "../plam"; 7 | import { precursive } from "../precursive"; 8 | import { punsafeConvertType } from "../punsafeConvertType"; 9 | import { pByteString, pInt } from "../std"; 10 | 11 | export const pdigitToString = phoist( 12 | pfn([ 13 | int 14 | ], bs) 15 | ( n => pByteString("").prepend( n.add(48) ) ) 16 | ); 17 | 18 | export const ppositiveIntToBs = phoist( 19 | precursive( 20 | pfn([ 21 | lam( int, bs ), 22 | int 23 | ], bs) 24 | (( _self, n ) => { 25 | 26 | const self = punsafeConvertType( _self, lam( int, bs ) ); 27 | 28 | return pif( bs ).$( n.gtEq( 10 ) ) 29 | .then( self.$( n.div(10) ).concat( pdigitToString.$( n.mod(10) ) ) ) 30 | .else( pdigitToString.$( n ) ); 31 | }) 32 | ) 33 | ); 34 | 35 | export const pshowInt = phoist( 36 | plam( int, bs ) 37 | ( n => 38 | pif( bs ).$( n.gtEq( 0 ) ) 39 | .then( ppositiveIntToBs.$( n ) ) 40 | .else( 41 | pByteString(fromAscii("-")).concat( 42 | ppositiveIntToBs.$( 43 | pInt( 0 ).sub( n ) 44 | ) 45 | ) 46 | ) 47 | ) 48 | ); -------------------------------------------------------------------------------- /src/pluts/lib/show/list.ts: -------------------------------------------------------------------------------- 1 | import { PByteString, PList, TermFn } from "../../PTypes"; 2 | import { TermType, bs, lam, list } from "../../type_system/types"; 3 | import { pshow } from "./pshow"; 4 | import { ToPType } from "../../type_system"; 5 | import { phoist } from "../phoist"; 6 | import { pfn } from "../pfn"; 7 | import { pfoldl } from "../std/list/pfoldl"; 8 | import { fromAscii } from "@harmoniclabs/uint8array-utils"; 9 | 10 | export function pshowList( elems_t: ElemsT ) 11 | : TermFn<[ PList> ], PByteString> 12 | { 13 | return phoist( 14 | pfn([ 15 | lam( elems_t, bs ), 16 | list( elems_t ) 17 | ], bs ) 18 | (( pshowElem, lst ) => 19 | pfoldl( elems_t, bs ) 20 | .$(( accum, elem ) => 21 | accum 22 | .concat( pshowElem.$( elem as any ) ) 23 | .concat( fromAscii(",") ) 24 | ) 25 | .$( fromAscii("[") ) 26 | .$( lst ) 27 | .concat( fromAscii("]") ) 28 | ) 29 | ).$( pshow( elems_t ) ) 30 | } -------------------------------------------------------------------------------- /src/pluts/lib/show/pair.ts: -------------------------------------------------------------------------------- 1 | import { fromAscii } from "@harmoniclabs/uint8array-utils"; 2 | import { PByteString } from "../../PTypes"; 3 | import { TermFn } from "../../PTypes/PFn/PFn"; 4 | import { ToPType } from "../../type_system/ts-pluts-conversion"; 5 | import { clearAsData } from "../../type_system/tyArgs/clearAsData"; 6 | import { getDirectFstT } from "../../type_system/tyArgs/getDirectFstT"; 7 | import { getDirectSndT } from "../../type_system/tyArgs/getDirectSndT"; 8 | import { PairT, TermType, bool, bs, lam } from "../../type_system/types"; 9 | import { pfstPair, psndPair } from "../builtins"; 10 | import { pfn } from "../pfn"; 11 | import { phoist } from "../phoist"; 12 | import { pByteString, pstdEq } from "../std"; 13 | import { pshow } from "./pshow"; 14 | 15 | export function pshowPair>( t: T ) 16 | : TermFn<[ ToPType, ToPType ], PByteString> 17 | { 18 | const fstT = clearAsData( getDirectFstT( t ) ); 19 | const sndT = clearAsData( getDirectSndT( t ) ); 20 | 21 | const pfst = pfstPair( fstT, sndT ); 22 | const psnd = psndPair( fstT, sndT ); 23 | 24 | return phoist( 25 | pfn([ 26 | lam( fstT, bs ), 27 | lam( sndT, bs ), 28 | t 29 | ], bs) 30 | (( showFst, showSnd, p ) => 31 | pByteString( fromAscii("( ") ) 32 | .concat( 33 | showFst.$( pfst.$( p ) ) 34 | ) 35 | .concat( fromAscii(", ") ) 36 | .concat( 37 | showSnd.$( psnd.$( p ) ) 38 | ) 39 | .concat( fromAscii(" )") ) 40 | ) 41 | ) 42 | .$( pshow( fstT ) ) 43 | .$( pshow( sndT ) ) as any; 44 | } 45 | -------------------------------------------------------------------------------- /src/pluts/lib/show/pshow.ts: -------------------------------------------------------------------------------- 1 | import { PByteString, PString, TermFn } from "../../PTypes"; 2 | import { TermType, ToPType, bool, bs, data, int, list, pair, str, termTypeToString, tyVar, typeExtends, unit } from "../../type_system"; 3 | import { getElemsT } from "../../type_system/tyArgs"; 4 | import { pshowBool } from "./bool"; 5 | import { pshowBs } from "./bs"; 6 | import { pshowData } from "./data"; 7 | import { pshowInt } from "./int"; 8 | import { pshowPair } from "./pair"; 9 | import { pshowList } from "./list"; 10 | import { pshowStr } from "./str"; 11 | import { pshowUnit } from "./unit"; 12 | 13 | export function pshow( t: T ) 14 | : TermFn<[ ToPType ], PByteString> 15 | { 16 | if( typeExtends( t, int ) ) return pshowInt as any; 17 | if( typeExtends( t, bs ) ) return pshowBs as any; 18 | if( typeExtends( t, str ) ) return pshowStr as any; 19 | if( typeExtends( t, unit ) ) return pshowUnit as any; 20 | if( typeExtends( t, bool ) ) return pshowBool as any; 21 | if( typeExtends( t, data ) ) return pshowData as any; 22 | 23 | if( typeExtends( t, list( tyVar() ) ) ) return pshowList( getElemsT( t ) ) as any; 24 | if( typeExtends( t, pair( tyVar(), tyVar() ) ) ) return pshowPair( t as any ) as any; 25 | 26 | throw new Error("missing standard show for type: " + termTypeToString( t )); 27 | } -------------------------------------------------------------------------------- /src/pluts/lib/show/ptraceVal.ts: -------------------------------------------------------------------------------- 1 | import { TermFn } from "../../PTypes"; 2 | import { ToPType } from "../../type_system/ts-pluts-conversion"; 3 | import { TermType, int } from "../../type_system/types"; 4 | import { ptrace } from "../builtins"; 5 | import { phoist } from "../phoist"; 6 | import { plam } from "../plam"; 7 | import { pshow } from "./pshow"; 8 | 9 | export function ptraceVal( t: T ) 10 | : TermFn<[ ToPType ], ToPType > 11 | { 12 | return phoist( 13 | plam( t, t ) 14 | ( val => ptrace( t ).$( pshow( t ).$( val ).utf8Decoded ).$( val ) as any ) 15 | ) as any; 16 | }; 17 | 18 | export const ptraceInt = ptraceVal( int ); -------------------------------------------------------------------------------- /src/pluts/lib/show/str.ts: -------------------------------------------------------------------------------- 1 | import { str } from "../../type_system/types"; 2 | import { pid, ptrace } from "../builtins"; 3 | import { phoist } from "../phoist"; 4 | import { plam } from "../plam"; 5 | 6 | export const pshowStr = pid( str ); 7 | 8 | export const ptraceStr = phoist( 9 | plam( str, str ) 10 | ( s => ptrace( str ).$( s ).$( s ) ) 11 | ); -------------------------------------------------------------------------------- /src/pluts/lib/show/unit.ts: -------------------------------------------------------------------------------- 1 | import { fromAscii } from "@harmoniclabs/uint8array-utils"; 2 | import { bs, unit } from "../../type_system"; 3 | import { phoist } from "../phoist"; 4 | import { plam } from "../plam"; 5 | import { pByteString } from "../std"; 6 | 7 | export const pshowUnit = phoist( 8 | plam( unit, bs ) 9 | ( _ => pByteString( fromAscii("()") ) 10 | ) 11 | ); -------------------------------------------------------------------------------- /src/pluts/lib/std/PMaybe/__tests__/PMaybe.test.ts: -------------------------------------------------------------------------------- 1 | import { CEKError, Machine } from "@harmoniclabs/plutus-machine"; 2 | import { PMaybe } from ".."; 3 | import { int } from "../../../../type_system/types"; 4 | import { pDataI } from "../../data/pData"; 5 | import { pInt } from "../../int/pInt"; 6 | 7 | describe("PMaybe", () => { 8 | 9 | const PMaybeInt = PMaybe( int ); 10 | const just = PMaybeInt.Just({ val: pDataI( 1 ) }); 11 | const nothing = PMaybeInt.Nothing({}); 12 | 13 | test("unwrap just", () => { 14 | 15 | const res = Machine.evalSimple( 16 | just.unwrap 17 | ); 18 | 19 | const expected = Machine.evalSimple( pInt( 1 ) ); 20 | 21 | expect( res ).toEqual( expected ); 22 | 23 | }); 24 | 25 | test("unwrap nothing", () => { 26 | 27 | const res = Machine.evalSimple( 28 | nothing.unwrap 29 | ); 30 | 31 | // const expected = Machine.evalSimple( perror( int ) ); 32 | 33 | expect( res instanceof CEKError ).toEqual( true ); 34 | 35 | }); 36 | 37 | test("default just", () => { 38 | 39 | const res = Machine.evalSimple( 40 | just.default( 0 ) 41 | ); 42 | 43 | const expected = Machine.evalSimple( pInt( 1 ) ); 44 | 45 | expect( res ).toEqual( expected ); 46 | 47 | }); 48 | 49 | test("default nothing", () => { 50 | 51 | const res = Machine.evalSimple( 52 | nothing.default( 0 ) 53 | ); 54 | 55 | const expected = Machine.evalSimple( pInt( 0 ) ); 56 | 57 | expect( res ).toEqual( expected ); 58 | 59 | }); 60 | }) -------------------------------------------------------------------------------- /src/pluts/lib/std/PMaybe/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./PMaybe"; 2 | export * from "./PListMaybe"; -------------------------------------------------------------------------------- /src/pluts/lib/std/UtilityTerms/BaseUtilityTerm.ts: -------------------------------------------------------------------------------- 1 | import { UtilityTermOf } from "./addUtilityForType"; 2 | import { ToPType } from "../../../type_system/ts-pluts-conversion"; 3 | import { TermType } from "../../../type_system/types"; 4 | import { hasOwn, defineReadOnlyProperty } from "@harmoniclabs/obj-utils"; 5 | import { term_as } from "../../punsafeConvertType"; 6 | import { Term } from "../../../Term"; 7 | import { PType } from "../../../PType"; 8 | 9 | export type BaseUtilityTermExtension = { 10 | readonly as: ( t: T ) => UtilityTermOf> 11 | } 12 | 13 | export function addBaseUtilityTerm( term: Term ): Term & BaseUtilityTermExtension 14 | { 15 | if( 16 | !hasOwn( term, "as" ) || 17 | typeof term.as !== "function" || 18 | term.as === (Term.prototype as any).as 19 | ) 20 | { 21 | defineReadOnlyProperty( 22 | term, "as", term_as.bind( term ) 23 | ); 24 | } 25 | 26 | return term as any; 27 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/UtilityTerms/TermAlias.ts: -------------------------------------------------------------------------------- 1 | import type { PType } from "../../../PType" 2 | import type { PAlias } from "../../../PTypes" 3 | import type { Term } from "../../../Term" 4 | import type { Methods } from "../../../type_system" 5 | import type { UtilityTermOf } from "./addUtilityForType" 6 | import type { BaseUtilityTermExtension } from "./BaseUtilityTerm" 7 | import type { FilterMethodsByInput, LiftMethods, MethodsAsTerms } from "./userMethods/methodsTypes" 8 | 9 | 10 | /** 11 | * basically unwraps the alias until it finds an actual type 12 | **/ 13 | type ActualTermUtility = 14 | PT extends PAlias ? 15 | ActualTermUtility : 16 | UtilityTermOf 17 | 18 | 19 | type ActualTermAlias = 20 | Term> & 21 | ActualTermUtility & 22 | LiftMethods< 23 | FilterMethodsByInput> 24 | > & 25 | MethodsAsTerms< 26 | FilterMethodsByInput> 27 | > 28 | 29 | export type TermAlias = ( 30 | // if the type is already an alias 31 | PT extends PAlias ? 32 | // add utility of the actual type 33 | ActualTermAlias : 34 | // else add utility to this type (aliased) 35 | ActualTermAlias 36 | ) & BaseUtilityTermExtension 37 | 38 | // `addPAliasMethod` is (necessarily) mutually recursive with `addUtilityForType` 39 | // so it is defined in "../addUtilityForType.ts" -------------------------------------------------------------------------------- /src/pluts/lib/std/UtilityTerms/__tests__/TermList.pprepend.test.ts: -------------------------------------------------------------------------------- 1 | import { Machine } from "@harmoniclabs/plutus-machine"; 2 | import { int } from "../../../../type_system/types"; 3 | import { pInt } from "../../int"; 4 | import { pList } from "../../list"; 5 | 6 | describe("pprepend", () => { 7 | 8 | test("prepend something", () => { 9 | 10 | const uplc = pList(int)([ pInt(2) ]).prepend( 1 ).toUPLC(0); 11 | 12 | const res = Machine.evalSimple( uplc ); 13 | 14 | expect( 15 | res 16 | ).toEqual( 17 | Machine.evalSimple( 18 | pList(int)([ 1, 2 ].map( pInt )) 19 | ) 20 | ) 21 | 22 | }); 23 | 24 | test("pprepend", () => { 25 | 26 | expect( 27 | () => pList(int)([ pInt(2) ]).pprepend 28 | ).not.toThrow() 29 | 30 | }) 31 | 32 | }); -------------------------------------------------------------------------------- /src/pluts/lib/std/UtilityTerms/__tests__/TermStruct.dot_notation.test.ts: -------------------------------------------------------------------------------- 1 | import { Machine } from "@harmoniclabs/plutus-machine" 2 | import { pmatch, pstruct } from "../../../../PTypes" 3 | import { bs, int, list, unit } from "../../../../type_system" 4 | import { plet } from "../../../plet" 5 | import { pDataB, pDataI } from "../../data" 6 | import { pInt } from "../../int" 7 | import { passert } from "../../passert" 8 | import { pList } from "../../list/const" 9 | import { PTxOut } from "../../../../API/V2/Tx/PTxOut" 10 | import { phoist } from "../../../phoist" 11 | import { PTxInInfo } from "../../../../API/V2/Tx/PTxInInfo" 12 | import { pfn } from "../../../pfn" 13 | import { UtilityTermOf } from "../addUtilityForType" 14 | import { pmakeUnit } from "../../unit/pmakeUnit" 15 | import { TermStruct } from "../TermStruct" 16 | 17 | const SingleCtor = pstruct({ 18 | SingleCtor: { 19 | num: int, 20 | byteStr: bs 21 | } 22 | }) 23 | 24 | describe("dot notation", () => { 25 | 26 | test("num + bs.length", () => { 27 | 28 | const myStruct = plet( 29 | SingleCtor.SingleCtor({ 30 | num: pDataI( 2 ), 31 | byteStr: pDataB("caffee") 32 | }) 33 | ); 34 | 35 | expect( 36 | Machine.evalSimple( 37 | myStruct.num.add( myStruct.byteStr.length ) 38 | ) 39 | ).toEqual( 40 | Machine.evalSimple( 41 | pInt( 2 + 3 ) 42 | ) 43 | ); 44 | 45 | }); 46 | 47 | }) -------------------------------------------------------------------------------- /src/pluts/lib/std/UtilityTerms/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./TermAlias"; 2 | export * from "./TermBS"; 3 | export * from "./TermInt"; 4 | export * from "./TermList"; 5 | export * from "./TermPair"; 6 | export * from "./TermStr"; 7 | export * from "./TermStruct"; 8 | export * from "./types"; 9 | export * from "./TermBool"; -------------------------------------------------------------------------------- /src/pluts/lib/std/UtilityTerms/mockUtilityTerms/__tests__/mockUtilityTerm.test.ts: -------------------------------------------------------------------------------- 1 | import { TermType, bool, bs, data, delayed, int, lam, list, pair, str, termTypeToString, unit } from "../../../../../type_system"; 2 | import { addUtilityForType } from "../../addUtilityForType"; 3 | import { makeMockTerm } from "../makeMockTerm"; 4 | import { mockUtilityForType } from "../mockUtilityForType"; 5 | 6 | function testSameKeys( a: object, b: object ): void 7 | { 8 | const aKeys = Object.keys( a ); 9 | const bKeys = Object.keys( b ); 10 | 11 | expect( aKeys ).toEqual( bKeys ); 12 | expect( aKeys.length ).toEqual( bKeys.length ); 13 | 14 | for(let i = 0; i < aKeys.length; i++ ) 15 | { 16 | expect( aKeys[i] ).toEqual( bKeys[i] ); 17 | } 18 | } 19 | 20 | function testType( t: TermType ): void 21 | { 22 | test(termTypeToString( t ), () => { 23 | 24 | const term = makeMockTerm( t ); 25 | const utility = addUtilityForType( t )( term ); 26 | const mock = mockUtilityForType( t )( term ); 27 | 28 | testSameKeys( utility, mock ); 29 | 30 | }) 31 | } 32 | 33 | describe("mockUtilityTerm", () => { 34 | 35 | testType( bool ); 36 | testType( bs ); 37 | testType( int ); 38 | testType( unit ); 39 | testType( str ); 40 | testType( data ); 41 | testType( pair( int, int ) ); 42 | testType( list( int ) ); 43 | testType( list( pair( int, int ) ) ); 44 | testType( lam( int, int ) ); 45 | testType( delayed( int ) ); 46 | 47 | }) -------------------------------------------------------------------------------- /src/pluts/lib/std/UtilityTerms/mockUtilityTerms/makeMockTerm.ts: -------------------------------------------------------------------------------- 1 | import { IRVar } from "../../../../../IR/IRNodes/IRVar"; 2 | import { CompilerOptions } from "../../../../../IR/toUPLC/CompilerOptions"; 3 | import { Term } from "../../../../Term"; 4 | import { ToPType } from "../../../../type_system/ts-pluts-conversion"; 5 | import { TermType } from "../../../../type_system/types"; 6 | 7 | const mockTermIr = Object.freeze( new IRVar( 0 ) ); 8 | 9 | function genMockTermIr( _cfg: CompilerOptions, _dbn: bigint ): IRVar 10 | { 11 | return mockTermIr as IRVar; 12 | } 13 | 14 | export function makeMockTerm( t: T ): Term> 15 | { 16 | return new Term( 17 | t, 18 | genMockTermIr 19 | ); 20 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/UtilityTerms/mockUtilityTerms/makeMockUtilityTerm.ts: -------------------------------------------------------------------------------- 1 | import { ToPType } from "../../../../type_system/ts-pluts-conversion"; 2 | import { TermType } from "../../../../type_system/types"; 3 | import { UtilityTermOf } from "../addUtilityForType"; 4 | import { makeMockTerm } from "./makeMockTerm"; 5 | import { mockUtilityForType } from "./mockUtilityForType"; 6 | 7 | export function makeMockUtilityTerm( t: T ): UtilityTermOf> 8 | { 9 | return (mockUtilityForType( t )( makeMockTerm( t ) )); 10 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/UtilityTerms/mockUtilityTerms/mockPapp.ts: -------------------------------------------------------------------------------- 1 | import { PType } from "../../../../PType"; 2 | import { PLam } from "../../../../PTypes/PFn/PLam"; 3 | import { Term } from "../../../../Term"; 4 | import { makeMockTerm } from "./makeMockTerm"; 5 | import { mockUtilityForType } from "./mockUtilityForType"; 6 | 7 | export function mockPapp( a: Term>, b: Term ): Term 8 | { 9 | const outT = a.type[2]; 10 | if( outT === undefined ) 11 | { 12 | console.log( a.type ); 13 | } 14 | return mockUtilityForType( outT as any )( 15 | makeMockTerm( outT as any ) as any 16 | ) as any 17 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/UtilityTerms/types.ts: -------------------------------------------------------------------------------- 1 | import type { PType } from "../../../PType"; 2 | import type { PInt, PBool, PByteString, PString, PList } from "../../../PTypes"; 3 | import type { Term } from "../../../Term"; 4 | import type { TermBS } from "./TermBS"; 5 | import type { TermBool } from "./TermBool"; 6 | import type { TermInt } from "./TermInt"; 7 | import type { TermList } from "./TermList"; 8 | import type { TermStr } from "./TermStr"; 9 | 10 | export type PTypeWithUtility 11 | = PInt 12 | | PBool 13 | | PByteString 14 | | PString 15 | | PList; 16 | 17 | export type UtilityFromPType = 18 | PT extends PInt ? TermInt : 19 | PT extends PBool ? TermBool : 20 | PT extends PByteString ? TermBS : 21 | PT extends PString ? TermStr : 22 | PT extends PList ? TermList : 23 | never 24 | 25 | export type UtitlityFromTerm> 26 | = UtilityTerm extends Term ? 27 | UtilityFromPType : never; 28 | 29 | /** 30 | * @deprecated use `UtilityTermOf` instead 31 | */ 32 | export type TryUtitlityFromPType 33 | = PT extends infer UtilityPType extends PTypeWithUtility ? 34 | UtilityFromPType : 35 | Term; // return the term with the same PType if it doesn't have utilites 36 | 37 | export type TryUtitlityFromTerm> 38 | = UtilityTerm extends Term ? 39 | UtilityFromPType : 40 | UtilityTerm; // return the same term if it doesn't have utilites -------------------------------------------------------------------------------- /src/pluts/lib/std/UtilityTerms/userMethods/assertWellFormedMethods.ts: -------------------------------------------------------------------------------- 1 | import type { Methods } from "../../../../type_system"; 2 | 3 | /** 4 | * checks thatevery method name does not have an equivalent that starts with "p" 5 | * (added by convention to indicate the term rather than the funciton) 6 | * 7 | * @example 8 | * ```ts 9 | * const notOk: Methods = { 10 | * foo: pfn([ int ], bool)( ... ), 11 | * bar: pfn([ int ], bool)( ... ), 12 | * // ERROR: 'pfoo' is used to indicate the term counterpart of 'foo' 13 | * pfoo: pfn([ int ], bool)( ... ) 14 | * } 15 | * const ok: Methods = { 16 | * foo: pfn([ int ], bool)( ... ), 17 | * bar: pfn([ int ], bool)( ... ), 18 | * // no problem 19 | * // this will generate 'prop' and 'pprop' 20 | * // where 'prop' is the funciton and 'pprop' is the term 21 | * prop: pfn([ int ], bool)( ... ) 22 | * } 23 | * ``` 24 | */ 25 | export function isWellFormedMethods( methods: Methods ): boolean 26 | { 27 | const names = Object.keys( methods ); 28 | const pnames: string[] = []; 29 | 30 | for( const name of names ) 31 | { 32 | if( name.length === 0 ) continue; 33 | if( name[0] === "p" ) 34 | { 35 | pnames.push( name.slice(1) ); 36 | } 37 | } 38 | 39 | return !pnames.some( pname => names.includes( pname ) ) 40 | } 41 | 42 | export function assertWellFormedMethods( methods: Methods ): void 43 | { 44 | if( !isWellFormedMethods( methods ) ) throw new Error("methods are not well formed"); 45 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/__tests__/Pluts.combinators.pflip.test.ts: -------------------------------------------------------------------------------- 1 | import { ByteString } from "@harmoniclabs/bytestring"; 2 | import { bs, int } from "../../../type_system"; 3 | import { pconsBs } from "../../builtins"; 4 | import { pByteString } from "../bs/pByteString"; 5 | import { pflip } from "../combinators"; 6 | import { pInt } from "../int/pInt"; 7 | import { Machine } from "@harmoniclabs/plutus-machine"; 8 | 9 | 10 | describe("pflip", () => { 11 | 12 | test("flip pconsBs", () => { 13 | 14 | const flippedCons = pflip( bs, int, bs ).$( pconsBs ); 15 | 16 | const fst = pInt( 31 ); 17 | const snd = pByteString( ByteString.fromAscii("hello") ); 18 | expect( 19 | Machine.evalSimple( 20 | flippedCons.$( snd ).$( fst ) 21 | ) 22 | ).toEqual( 23 | Machine.evalSimple( 24 | pconsBs.$( fst ).$( snd ) 25 | ) 26 | ) 27 | 28 | expect( 29 | flippedCons.$( snd ).$( fst ) 30 | ).not.toEqual( 31 | pconsBs.$( fst ).$( snd ) 32 | ) 33 | 34 | }) 35 | }) -------------------------------------------------------------------------------- /src/pluts/lib/std/bool/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pBool"; 2 | export * from "./pBoolToData"; 3 | export * from "./pBoolFromData"; -------------------------------------------------------------------------------- /src/pluts/lib/std/bool/pBool.ts: -------------------------------------------------------------------------------- 1 | import { IRConst } from "../../../../IR/IRNodes/IRConst"; 2 | import type { PBool } from "../../../PTypes/PBool"; 3 | import { Term } from "../../../Term"; 4 | import { bool } from "../../../type_system"; 5 | import { TermBool, addPBoolMethods } from "../UtilityTerms/TermBool"; 6 | 7 | export function pBool( b: boolean ): TermBool 8 | { 9 | return addPBoolMethods( 10 | new Term( 11 | bool, 12 | _dbn => IRConst.bool( b ), 13 | true 14 | ) 15 | ); 16 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/bool/pBoolFromData.ts: -------------------------------------------------------------------------------- 1 | import { bool, data } from "../../../type_system/types"; 2 | import { punConstrData } from "../../builtins/data"; 3 | import { phoist } from "../../phoist"; 4 | import { plam } from "../../plam"; 5 | 6 | export const pBoolFromData = phoist( 7 | plam( data, bool ) 8 | ( 9 | d => punConstrData.$( d ).fst.eq( 0 ), 10 | "pBoolFromData" 11 | ) 12 | ) -------------------------------------------------------------------------------- /src/pluts/lib/std/bool/pBoolToData.ts: -------------------------------------------------------------------------------- 1 | import { DataConstr } from "@harmoniclabs/plutus-data"; 2 | import { asData, bool } from "../../../type_system/types"; 3 | import { pif } from "../../builtins/bool"; 4 | import { phoist } from "../../phoist"; 5 | import { plam } from "../../plam"; 6 | import { _punsafeConvertType } from "../../punsafeConvertType/minimal"; 7 | import { pData } from "../data/pData"; 8 | 9 | export const pBoolToData = phoist( 10 | plam( bool, asData( bool ) ) 11 | ( b => 12 | pif( asData( bool ) ).$( b ) 13 | .then( 14 | _punsafeConvertType( 15 | pData( 16 | new DataConstr( 0, [] ) 17 | ), 18 | asData( bool ) 19 | ) 20 | ) 21 | .else( 22 | _punsafeConvertType( 23 | pData( 24 | new DataConstr( 1, [] ) 25 | ), 26 | asData( bool ) 27 | ) 28 | ), 29 | "pBoolToData" 30 | ) 31 | ); -------------------------------------------------------------------------------- /src/pluts/lib/std/bs/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pByteString"; -------------------------------------------------------------------------------- /src/pluts/lib/std/bs/pByteString.ts: -------------------------------------------------------------------------------- 1 | import { ByteString } from "@harmoniclabs/bytestring"; 2 | import { IRConst } from "../../../../IR/IRNodes/IRConst"; 3 | import { Term } from "../../../Term"; 4 | import { bs } from "../../../type_system/types"; 5 | import { TermBS, addPByteStringMethods } from "../UtilityTerms/TermBS"; 6 | 7 | export function pByteString( _bs: ByteString | string | Uint8Array ): TermBS 8 | { 9 | const _bs_ = _bs instanceof ByteString ? _bs.clone() : new ByteString( _bs ); 10 | return addPByteStringMethods( 11 | new Term( 12 | bs, 13 | _dbn => IRConst.byteString( _bs_ ), 14 | true, // isConstant 15 | ) 16 | ); 17 | } 18 | 19 | export const pBs = pByteString; -------------------------------------------------------------------------------- /src/pluts/lib/std/combinators/index.ts: -------------------------------------------------------------------------------- 1 | 2 | export * from "./pcompose"; 3 | export * from "./pflip"; -------------------------------------------------------------------------------- /src/pluts/lib/std/combinators/pcompose.ts: -------------------------------------------------------------------------------- 1 | import { PFn, PLam, TermFn } from "../../../PTypes"; 2 | import { Term } from "../../../Term"; 3 | import { ToPType } from "../../../type_system"; 4 | import { TermType, lam } from "../../../type_system/types"; 5 | import { papp } from "../../papp"; 6 | import { pfn } from "../../pfn"; 7 | import { phoist } from "../../phoist"; 8 | 9 | export const pcompose: ( a: A, b: B, c: C ) => 10 | Term,ToPType>, 12 | PLam,ToPType>, 13 | ToPType 14 | ], ToPType>> & { 15 | $: ( bToC: Term,ToPType>> ) 16 | => Term,ToPType>, 18 | ToPType 19 | ], ToPType>> & { 20 | $: ( aToB: Term,ToPType>> ) 21 | => TermFn<[ ToPType ], ToPType> 22 | } 23 | } = (( a: TermType, b: TermType, c: TermType ) => phoist( 24 | pfn([ 25 | lam( b, c ), 26 | lam( a, b ), 27 | a 28 | ], c) 29 | (( bToC, aToB, _a ) => { 30 | return papp( bToC, papp( aToB, _a ) ) as any; 31 | }, "pcompose") 32 | )) as any 33 | 34 | -------------------------------------------------------------------------------- /src/pluts/lib/std/combinators/pflip.ts: -------------------------------------------------------------------------------- 1 | import { PFn, TermFn } from "../../../PTypes" 2 | import { Term } from "../../../Term" 3 | import { TermType, ToPType, fn } from "../../../type_system" 4 | import { papp } from "../../papp" 5 | import { pfn } from "../../pfn" 6 | import { phoist } from "../../phoist" 7 | 8 | export function pflip( a: A, b: B, c: C ): 9 | Term, ToPType], ToPType>, ToPType, ToPType ], ToPType>> 10 | & { 11 | $: ( termFn: Term, ToPType ], ToPType >>) => 12 | TermFn<[ ToPType, ToPType ], ToPType> 13 | } 14 | { 15 | return phoist( 16 | pfn([ 17 | fn([ b, a ], c ), 18 | a, 19 | b 20 | ], c) 21 | (( toFlip, _b, _a ) => 22 | papp( papp( toFlip, _a ), _b ) 23 | , "pflip") 24 | ) as any 25 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/data/conversion/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./fromData"; 2 | export * from "./toData"; -------------------------------------------------------------------------------- /src/pluts/lib/std/data/conversion/toData.ts: -------------------------------------------------------------------------------- 1 | import { definePropertyIfNotPresent } from "@harmoniclabs/obj-utils"; 2 | import { PAsData } from "../../../../PTypes"; 3 | import { TermFn } from "../../../../PTypes/PFn/PFn"; 4 | import { Term } from "../../../../Term"; 5 | import { TermType } from "../../../../type_system"; 6 | import { ToPType } from "../../../../type_system/ts-pluts-conversion"; 7 | import { UtilityTermOf, addUtilityForType } from "../../UtilityTerms/addUtilityForType"; 8 | import { papp } from "../../../papp"; 9 | import { _ptoData, _toData } from "./toData_minimal"; 10 | 11 | 12 | export function toData( t: T ): ( term: Term> ) => UtilityTermOf>> 13 | { 14 | return ( term: Term> ) => { 15 | const theTerm = _toData( t )( term ); 16 | return addUtilityForType( theTerm.type )( theTerm ) as any 17 | } 18 | } 19 | 20 | 21 | export function ptoData( t: T ): TermFn<[ ToPType ], PAsData>> 22 | { 23 | const term = _ptoData( t ); 24 | 25 | return definePropertyIfNotPresent( 26 | term, "$", 27 | { 28 | get: () => ( other: Term> ) => { 29 | const theTerm = papp( term, other ); 30 | (theTerm as any).isConstant = (other as any).isConstant; 31 | return theTerm; 32 | }, 33 | set: () => {}, 34 | configurable: false, 35 | enumerable: true 36 | } 37 | ) as any; 38 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/data/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pData"; 2 | export * from "./conversion"; -------------------------------------------------------------------------------- /src/pluts/lib/std/data/pData.ts: -------------------------------------------------------------------------------- 1 | import { Term } from "../../../Term"; 2 | import { PAsData, PByteString, PData, PInt } from "../../../PTypes"; 3 | import { asData, bs, data, int } from "../../../type_system/types"; 4 | import { Data, DataB, DataI } from "@harmoniclabs/plutus-data"; 5 | import { ByteString } from "@harmoniclabs/bytestring"; 6 | import { IRConst } from "../../../../IR/IRNodes/IRConst"; 7 | 8 | export function pData( dataElem: Data ) 9 | : Term 10 | { 11 | return new Term( 12 | data, 13 | _dbn => IRConst.data( dataElem ), 14 | true // isConstant 15 | ); 16 | } 17 | 18 | export function pDataI( n: number | bigint ): Term> 19 | { 20 | return new Term( 21 | asData( int ), 22 | _dbn => IRConst.data( new DataI( n ) ), 23 | true // isConstant 24 | ); 25 | } 26 | 27 | 28 | export function pDataB( b: string | ByteString | Uint8Array ): Term> 29 | { 30 | return new Term( 31 | asData( bs ), 32 | _dbn => IRConst.data( new DataB( b ) ), 33 | true // isConstant 34 | ); 35 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./bs"; 2 | export * from "./int"; 3 | export * from "./str"; 4 | export * from "./unit"; 5 | export * from "./bool"; 6 | export * from "./data"; 7 | export * from "./list"; 8 | export * from "./pair"; 9 | export * from "./stdEq"; 10 | export * from "./PMaybe"; 11 | export * from "./combinators"; 12 | export * from "./UtilityTerms"; 13 | export * from "./passert"; 14 | export * from "./traces"; -------------------------------------------------------------------------------- /src/pluts/lib/std/int/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pInt"; -------------------------------------------------------------------------------- /src/pluts/lib/std/int/pInt.ts: -------------------------------------------------------------------------------- 1 | import { IRConst } from "../../../../IR/IRNodes/IRConst"; 2 | import { PInt } from "../../../PTypes"; 3 | import { Term } from "../../../Term"; 4 | import { int } from "../../../type_system/types"; 5 | import { TermInt, addPIntMethods } from "../UtilityTerms/TermInt"; 6 | 7 | export function pInt( n: number | bigint ): TermInt 8 | { 9 | return addPIntMethods( 10 | new Term( 11 | int, 12 | _dbn => IRConst.int( BigInt( n ) ), 13 | true 14 | ) 15 | ); 16 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/list/__tests__/list.pfind.toIR.test.ts: -------------------------------------------------------------------------------- 1 | import { IRHoisted, getHoistedTerms } from "../../../../../IR/IRNodes/IRHoisted"; 2 | import { compileIRToUPLC } from "../../../../../IR/toUPLC/compileIRToUPLC"; 3 | import { showIR } from "../../../../../IR/utils/showIR"; 4 | import { int } from "../../../../type_system"; 5 | import { pfind } from "../pfind" 6 | 7 | describe("pfind.toIR", () => { 8 | 9 | test("pfind( int )", () => { 10 | 11 | const term = pfind( int ); 12 | const ir: IRHoisted = term.toIR() as any; 13 | 14 | expect( ir instanceof IRHoisted ).toBe( true ); 15 | 16 | expect( 17 | () => compileIRToUPLC( ir ) 18 | ).not.toThrow() 19 | 20 | }) 21 | }) -------------------------------------------------------------------------------- /src/pluts/lib/std/list/__tests__/list.pindex.test.ts: -------------------------------------------------------------------------------- 1 | import { Machine } from "@harmoniclabs/plutus-machine"; 2 | import { int } from "../../../../type_system" 3 | import { pInt } from "../../int" 4 | import { pList } from "../const" 5 | 6 | describe("pindex", () => { 7 | 8 | test("[1,2,3]", () => { 9 | 10 | const arr: number[] = new Array( 10 ).fill( 0 ).map( (_, i) => i + 1) ; 11 | const myList = pList( int )( arr.map( pInt ) ); 12 | 13 | for(const n of arr) 14 | { 15 | expect( 16 | Machine.evalSimple( 17 | myList.at(n - 1) 18 | ) 19 | ).toEqual( 20 | Machine.evalSimple( 21 | pInt( n ) 22 | ) 23 | ) 24 | } 25 | }); 26 | 27 | }) -------------------------------------------------------------------------------- /src/pluts/lib/std/list/const/minimal.ts: -------------------------------------------------------------------------------- 1 | import { assertValidListType } from "."; 2 | import { IRConst } from "../../../../../IR/IRNodes/IRConst"; 3 | import { PList } from "../../../../PTypes"; 4 | import { Term } from "../../../../Term"; 5 | import { TermType, ToPType, typeExtends, pair, data, list } from "../../../../type_system"; 6 | import { pnilPairData, pnilData } from "../../../builtins/data"; 7 | import { _punsafeConvertType } from "../../../punsafeConvertType/minimal"; 8 | 9 | 10 | export function _pnil( elemsT: ElemsT ): Term>> 11 | { 12 | assertValidListType( elemsT ); 13 | 14 | if( 15 | typeExtends( elemsT, pair( data, data ) ) 16 | ) 17 | { 18 | return _punsafeConvertType( pnilPairData, list( elemsT ) ); 19 | } 20 | 21 | if( typeExtends( elemsT, data ) ) 22 | { 23 | return _punsafeConvertType( pnilData, list( elemsT ) ); 24 | } 25 | 26 | return new Term>>( 27 | list( elemsT ), 28 | _dbn => IRConst.listOf( elemsT )([]), 29 | true 30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /src/pluts/lib/std/list/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pmatchList"; 2 | export * from "./precursiveList"; 3 | export * from "./plength"; 4 | export * from "./pindexList"; 5 | export * from "./pfoldl"; 6 | export * from "./pfoldr"; 7 | export * from "./pfind"; 8 | export * from "./pmap"; 9 | export * from "./pfilter"; 10 | export * from "./pevery"; 11 | export * from "./psome"; 12 | export * from "./preverse"; 13 | export * from "./const"; 14 | export * from "./peqList"; 15 | export * from "./plookup"; 16 | export * from "./pincludes"; -------------------------------------------------------------------------------- /src/pluts/lib/std/list/peqList.ts: -------------------------------------------------------------------------------- 1 | import { PBool, PList, TermFn } from "../../../PTypes"; 2 | import { ToPType } from "../../../type_system"; 3 | import { TermType, bool, lam, list } from "../../../type_system/types"; 4 | import { pisEmpty } from "../../builtins/list"; 5 | import { pfn } from "../../pfn"; 6 | import { phoist } from "../../phoist"; 7 | import { punsafeConvertType } from "../../punsafeConvertType"; 8 | import { pBool } from "../bool/pBool"; 9 | import { pstdEq } from "../stdEq/pstdEq"; 10 | import { pcompareList } from "./pcompareList"; 11 | 12 | /** 13 | * @since v0.5.0 14 | * @param {TermType} t type of the elements of the list 15 | */ 16 | export function peqList( t: ElemsT ) 17 | : TermFn<[ PList>, PList> ], PBool> 18 | { 19 | return phoist( 20 | pcompareList( t, t ) 21 | .$( punsafeConvertType( pisEmpty, lam( list( t ), bool ) ) ) 22 | // if rest second is matched then restFst is not empty 23 | .$(( _restFst ) => pBool( false ) ) 24 | .$( pstdEq( t ) ) 25 | ) 26 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/list/pevery.ts: -------------------------------------------------------------------------------- 1 | import type { TermFn, PLam, PBool, PList } from "../../../PTypes"; 2 | import { ToPType, lam, bool, list, TermType } from "../../../type_system"; 3 | import { papp } from "../../papp"; 4 | import { pdelay } from "../../pdelay"; 5 | import { pfn } from "../../pfn"; 6 | import { phoist } from "../../phoist"; 7 | import { plam } from "../../plam"; 8 | import { pBool } from "../bool/pBool"; 9 | import { precursiveList } from "./precursiveList"; 10 | 11 | 12 | export function pevery( elemsT: ElemsT ) 13 | : TermFn<[ PLam,PBool>, PList> ], PBool> 14 | { 15 | return phoist( 16 | plam( 17 | lam( elemsT, bool ), 18 | lam( 19 | list( elemsT ), 20 | bool 21 | ) 22 | ) 23 | (( predicate ) => { 24 | 25 | return precursiveList( bool, elemsT ) 26 | .$( _self => pdelay( pBool( true ) ) ) 27 | .$( 28 | pfn([ 29 | lam( list( elemsT ), bool ), 30 | elemsT, 31 | list( elemsT ) 32 | ], bool ) 33 | (( self, head, rest ) => 34 | 35 | papp( 36 | predicate, 37 | head as any 38 | ).and( 39 | papp( 40 | self, 41 | rest 42 | ) 43 | ) 44 | 45 | ) 46 | ) 47 | // .$( _list ) 48 | }, "pevery") 49 | ) as any; 50 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/list/pfilter.ts: -------------------------------------------------------------------------------- 1 | import type { TermFn, PLam, PBool, PList } from "../../../PTypes"; 2 | import { TermType, ToPType, lam, bool, list } from "../../../type_system"; 3 | import { pif } from "../../builtins/bool"; 4 | import { papp } from "../../papp"; 5 | import { pfn } from "../../pfn"; 6 | import { phoist } from "../../phoist"; 7 | import { plam } from "../../plam"; 8 | import { pnil } from "./const"; 9 | import { pfoldr } from "./pfoldr"; 10 | 11 | 12 | export function pfilter( elemsT: ElemsT ) 13 | : TermFn<[ PLam,PBool>, PList> ], PList>> 14 | { 15 | return phoist( 16 | plam( 17 | lam( elemsT, bool ), 18 | lam( 19 | list( elemsT ), 20 | list( elemsT ) 21 | ) 22 | )(( predicate ) => 23 | 24 | pfoldr( elemsT, list( elemsT ) ) 25 | .$( 26 | pfn([ 27 | elemsT, 28 | list( elemsT ) 29 | ], list( elemsT )) 30 | (( elem, accum ) => 31 | pif( list(elemsT) ).$( 32 | papp( predicate, elem ) 33 | ) 34 | .then( accum.prepend( elem ) ) 35 | .else( accum ) 36 | ) 37 | ).$( pnil( elemsT ) ) as any 38 | // .$( lst ) 39 | , "pfilter" 40 | 41 | ) 42 | ) as any; 43 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/list/pincludes/index.ts: -------------------------------------------------------------------------------- 1 | import { TermType, bool, fn, list } from "../../../../type_system"; 2 | import { papp } from "../../../papp"; 3 | import { pfn } from "../../../pfn"; 4 | import { phoist } from "../../../phoist"; 5 | import { pstdEq } from "../../stdEq"; 6 | 7 | export function pincludes< 8 | ElemsT extends TermType 9 | >( 10 | elems_t: ElemsT 11 | ) 12 | { 13 | return phoist( 14 | phoist( 15 | pfn([ 16 | fn([ elems_t, elems_t ], bool ), 17 | list( elems_t ), 18 | elems_t 19 | ], bool) 20 | (( eqFn, lst, elem ) => lst.some( papp( eqFn, elem ) ), "mk_pincludes") 21 | ).$( 22 | pstdEq( elems_t ) 23 | ) 24 | ) 25 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/list/plength.ts: -------------------------------------------------------------------------------- 1 | import { TermType, delayed, int, lam, list } from "../../../type_system"; 2 | import { papp } from "../../papp"; 3 | import { pdelay } from "../../pdelay"; 4 | import { pfn } from "../../pfn"; 5 | import { phoist } from "../../phoist"; 6 | import { plam } from "../../plam"; 7 | import { pInt } from "../int/pInt"; 8 | import { precursiveList } from "./precursiveList"; 9 | 10 | 11 | export const plength = ( elemsT: TermType ) => { 12 | 13 | return phoist( 14 | precursiveList( int, elemsT ) 15 | .$( 16 | plam( 17 | lam( list( elemsT ), int ), 18 | delayed(int) 19 | ) 20 | (_self => pdelay( pInt( 0 ) ) ) 21 | ) 22 | .$( 23 | pfn([ 24 | lam( list( elemsT ), int ), 25 | elemsT, 26 | list( elemsT ) 27 | ], int) 28 | ( 29 | ( self, _x, xs ) => pInt(1).add( papp( self, xs ) ) 30 | ) 31 | ) 32 | 33 | ) 34 | }; -------------------------------------------------------------------------------- /src/pluts/lib/std/list/pmatchList/__tests__/list._pmatch.test.ts: -------------------------------------------------------------------------------- 1 | import { Machine } from "@harmoniclabs/plutus-machine" 2 | import { pfn } from "../../../.." 3 | import { int, list } from "../../../../../type_system" 4 | import { pdelay } from "../../../../pdelay" 5 | import { pInt } from "../../../int" 6 | import { _pmatchList } from "../minimal" 7 | 8 | 9 | describe("_pmatchList", () => { 10 | 11 | test("nil", () => { 12 | 13 | expect( 14 | Machine.evalSimple( 15 | _pmatchList( int, int ) 16 | .$( pdelay( pInt( -1 ) ) ) 17 | .$( 18 | pfn([ int, list( int ) ], int ) 19 | (( head, _tail ) => head ) 20 | ) 21 | .$([]) 22 | ) 23 | ).toEqual( 24 | Machine.evalSimple( 25 | pInt( -1 ) 26 | ) 27 | ) 28 | 29 | }); 30 | 31 | test("[42]", () => { 32 | 33 | expect( 34 | Machine.evalSimple( 35 | _pmatchList( int, int ) 36 | .$( pdelay( pInt( -1 ) ) ) 37 | .$( 38 | pfn([ int, list( int ) ], int ) 39 | (( head, _tail ) => head ) 40 | ) 41 | .$([pInt( 42 )]) 42 | ) 43 | ).toEqual( 44 | Machine.evalSimple( 45 | pInt( 42 ) 46 | ) 47 | ) 48 | 49 | }); 50 | 51 | }) -------------------------------------------------------------------------------- /src/pluts/lib/std/list/pmatchList/__tests__/list.pmatch.test.ts: -------------------------------------------------------------------------------- 1 | import { Machine } from "@harmoniclabs/plutus-machine" 2 | import { pmatchList } from ".." 3 | import { pfn } from "../../../.." 4 | import { int, list } from "../../../../../type_system" 5 | import { pdelay } from "../../../../pdelay" 6 | import { pInt } from "../../../int" 7 | 8 | 9 | describe("pmatch", () => { 10 | 11 | test("nil", () => { 12 | 13 | expect( 14 | Machine.evalSimple( 15 | pmatchList( int, int ) 16 | .$( pdelay( pInt( -1 ) ) ) 17 | .$( 18 | pfn([ int, list( int ) ], int ) 19 | (( head, _tail ) => head ) 20 | ) 21 | .$([] as any) 22 | ) 23 | ).toEqual( 24 | Machine.evalSimple( 25 | pInt( -1 ) 26 | ) 27 | ) 28 | 29 | }); 30 | 31 | test("[42]", () => { 32 | 33 | expect( 34 | Machine.evalSimple( 35 | pmatchList( int, int ) 36 | .$( pdelay( pInt( -1 ) ) ) 37 | .$( 38 | pfn([ int, list( int ) ], int ) 39 | (( head, _tail ) => head ) 40 | ) 41 | .$([pInt( 42 )] as any) 42 | ) 43 | ).toEqual( 44 | Machine.evalSimple( 45 | pInt( 42 ) 46 | ) 47 | ) 48 | 49 | }); 50 | 51 | }) -------------------------------------------------------------------------------- /src/pluts/lib/std/list/preverse.ts: -------------------------------------------------------------------------------- 1 | import { TermFn, PList } from "../../../PTypes"; 2 | import { TermType, ToPType, list } from "../../../type_system"; 3 | import { pprepend } from "../../builtins/pprepend"; 4 | import { phoist } from "../../phoist"; 5 | import { pflip } from "../combinators/pflip"; 6 | import { pnil } from "./const"; 7 | import { pfoldl } from "./pfoldl"; 8 | 9 | export function preverse( elemsT: ElemsT ) 10 | : TermFn<[ PList> ], PList>> 11 | { 12 | return phoist( 13 | pfoldl( elemsT, list( elemsT ) ) 14 | .$( 15 | pflip( list( elemsT ), elemsT, list( elemsT ) ) 16 | .$( pprepend( elemsT ) ) 17 | ) 18 | .$( pnil( elemsT ) ) 19 | ); 20 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/pair/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pPair"; 2 | export * from "./peqPair"; -------------------------------------------------------------------------------- /src/pluts/lib/std/pair/peqPair.ts: -------------------------------------------------------------------------------- 1 | import { PBool, TermFn } from "../../../PTypes"; 2 | import { PairT, TermType, ToPType, bool } from "../../../type_system"; 3 | import { getDirectFstT } from "../../../type_system/tyArgs/getDirectFstT"; 4 | import { getDirectSndT } from "../../../type_system/tyArgs/getDirectSndT"; 5 | import { pfn } from "../../pfn"; 6 | import { pfstPairNoUnwrap, psndPairNoUnwrap } from "../../builtins/pair/noUnwrap"; 7 | import { pstdEq } from "../stdEq/pstdEq"; 8 | import { phoist } from "../../phoist"; 9 | 10 | export function peqPair>( t: T ) 11 | : TermFn<[ ToPType, ToPType ], PBool> 12 | { 13 | const fstT = getDirectFstT( t ); 14 | const sndT = getDirectSndT( t ); 15 | 16 | const pfst = pfstPairNoUnwrap( fstT, sndT ); 17 | const psnd = psndPairNoUnwrap( fstT, sndT ); 18 | 19 | return phoist( 20 | pfn([ t, t ], bool) 21 | (( a, b ) => 22 | pstdEq( fstT ).$( pfst.$( a ) ).$( pfst.$( b ) ) 23 | .and( 24 | pstdEq( sndT ).$( psnd.$( a ) ).$( psnd.$( b ) ) 25 | ) 26 | ) 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /src/pluts/lib/std/passert.ts: -------------------------------------------------------------------------------- 1 | import { PBool } from "../../PTypes/PBool"; 2 | import { PDelayed } from "../../PTypes/PDelayed"; 3 | import { TermFn } from "../../PTypes/PFn/PFn"; 4 | import { bool, delayed, str, TermType, unit } from "../../type_system/types"; 5 | import { pif, pstrictIf } from "../builtins/bool"; 6 | import { pdelay } from "../pdelay"; 7 | import { perror } from "../perror"; 8 | import { pfn } from "../pfn"; 9 | import { pforce } from "../pforce"; 10 | import { phoist } from "../phoist"; 11 | import { ptraceError } from "./traces"; 12 | import { pmakeUnit } from "./unit/pmakeUnit"; 13 | import { ToPType } from "../../type_system/ts-pluts-conversion"; 14 | 15 | export const passert = phoist( 16 | pfn([ bool ], unit) 17 | ( condition => pif( unit ).$( condition ).then( pmakeUnit() ).else( perror( unit ) ) ) 18 | ); 19 | 20 | export const passertOrTrace = phoist( 21 | pfn([ str, bool ], unit) 22 | ( (msg, condition) => 23 | pif( unit ).$( condition ) 24 | .then( pmakeUnit() ) 25 | .else( ptraceError( unit ).$( msg ) ) 26 | ) 27 | ); 28 | 29 | export const passertAndContinue = ( 30 | resultType: T 31 | ): TermFn<[ PBool, PDelayed>], ToPType> => phoist( 32 | pfn([ bool, delayed( resultType ) ], resultType ) 33 | (( condition, continuation ) => 34 | pforce( 35 | pstrictIf( delayed( resultType ) ) 36 | .$( condition ) 37 | .$( continuation ) 38 | .$( pdelay( perror( resultType ) ) ) 39 | ) 40 | ) as any 41 | ); -------------------------------------------------------------------------------- /src/pluts/lib/std/stdEq/__tests__/pstdEq.test.ts: -------------------------------------------------------------------------------- 1 | import { Machine } from "@harmoniclabs/plutus-machine"; 2 | import { int, list } from "../../../../type_system"; 3 | import { pstdEq } from "../pstdEq"; 4 | import { pList } from "../../list"; 5 | import { pInt } from "../../int"; 6 | import { pBool } from "../../bool/pBool"; 7 | 8 | describe("pstdEq", () => { 9 | 10 | test("list(int)", () => { 11 | 12 | const eq = pstdEq( list( int ) ); 13 | 14 | // console.log( prettyUPLC( eq.toUPLC() ) ) 15 | 16 | const pListInt = ( ns: number[] ) => pList( int )( ns.map( pInt ) ); 17 | 18 | const eqTestExpected = Machine.evalSimple( 19 | pBool( true ) 20 | ); 21 | 22 | function eqTest( ns: number[] ) 23 | { 24 | const res = Machine.evalSimple( 25 | eq 26 | .$( pListInt(ns) ) 27 | .$( pListInt(ns) ) 28 | ); 29 | 30 | expect( res ).toEqual( eqTestExpected ) 31 | } 32 | 33 | eqTest([]); 34 | eqTest([1]); 35 | eqTest([1,2,3,4]); 36 | eqTest([ 0, 1, -1, 2, -2 ]); 37 | 38 | }); 39 | 40 | }) -------------------------------------------------------------------------------- /src/pluts/lib/std/stdEq/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pstdEq"; -------------------------------------------------------------------------------- /src/pluts/lib/std/stdEq/pstdEq.ts: -------------------------------------------------------------------------------- 1 | import type { PBool } from "../../../PTypes/PBool"; 2 | import type { PFn } from "../../../PTypes/PFn/PFn"; 3 | import { int, typeExtends, type TermType, type ToPType, bs, str, unit, bool, data, list, tyVar, termTypeToString, pair } from "../../../type_system"; 4 | import { getElemsT } from "../../../type_system/tyArgs"; 5 | import { peqBool } from "../../builtins/bool"; 6 | import { peqBs } from "../../builtins/bs"; 7 | import { peqData } from "../../builtins/data"; 8 | import { peqInt } from "../../builtins/int/intBinOpToBool"; 9 | import { peqStr } from "../../builtins/str"; 10 | import type { UtilityTermOf } from "../UtilityTerms/addUtilityForType"; 11 | import { peqList } from "../list"; 12 | import { peqPair } from "../pair/peqPair"; 13 | import { peqUnit } from "../unit/peqUnit"; 14 | 15 | export function pstdEq( t: T ): UtilityTermOf, ToPType ], PBool>> 16 | { 17 | if( typeExtends( t, int ) ) return peqInt as any; 18 | if( typeExtends( t, bs ) ) return peqBs as any; 19 | if( typeExtends( t, str ) ) return peqStr as any; 20 | if( typeExtends( t, unit ) ) return peqUnit as any; 21 | if( typeExtends( t, bool ) ) return peqBool as any; 22 | if( typeExtends( t, data ) ) return peqData as any; 23 | 24 | if( typeExtends( t, list( tyVar() ) ) ) return peqList( getElemsT( t ) ) as any; 25 | if( typeExtends( t, pair( tyVar(), tyVar() ) ) ) return peqPair( t as any ) as any; 26 | 27 | throw new Error("missing standard equality for type: " + termTypeToString( t )); 28 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/str/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pStr" -------------------------------------------------------------------------------- /src/pluts/lib/std/str/pStr.ts: -------------------------------------------------------------------------------- 1 | import { Term } from "../../../Term"; 2 | import { TermStr, addPStringMethods } from "../UtilityTerms"; 3 | import { str } from "../../../type_system/types" 4 | import { IRConst } from "../../../../IR/IRNodes/IRConst"; 5 | 6 | export function pStr( string: string ): TermStr 7 | { 8 | return addPStringMethods( 9 | new Term( 10 | str, 11 | _dbn => IRConst.str( string ), 12 | // true // isConstant 13 | ) 14 | ); 15 | } 16 | 17 | export const pString = pStr; -------------------------------------------------------------------------------- /src/pluts/lib/std/traces.ts: -------------------------------------------------------------------------------- 1 | import { bool, delayed, str, TermType } from "../../type_system/types"; 2 | import { pdelay } from "../pdelay"; 3 | import { perror } from "../perror"; 4 | import { pfn } from "../pfn"; 5 | import { plam } from "../plam"; 6 | import { pforce } from "../pforce"; 7 | import { phoist } from "../phoist"; 8 | import { pBool } from "./bool"; 9 | import { pif } from "../builtins/bool"; 10 | import { ptrace } from "../builtins/ptrace"; 11 | import { TermFn } from "../../PTypes/PFn/PFn"; 12 | import { PString } from "../../PTypes/PString"; 13 | import { ToPType } from "../../type_system/ts-pluts-conversion"; 14 | 15 | export const ptraceIfTrue = phoist( 16 | pfn([ 17 | delayed( str ), 18 | bool, 19 | ], bool) 20 | (( msg, boolean ) => 21 | pif( bool ).$( boolean ) 22 | .then( ptrace( bool ).$( pforce( msg ) ).$( pBool( true ) ) ) 23 | .else( pBool( false ) ) 24 | ) 25 | ); 26 | 27 | export const ptraceIfFalse = phoist( 28 | pfn([ 29 | delayed( str ), 30 | bool, 31 | ], bool) 32 | (( msg, boolean ) => 33 | pif( bool ).$( boolean ) 34 | .then( pBool( true ) ) 35 | .else( ptrace( bool ).$( pforce( msg ) ).$( pBool( false ) ) ) 36 | ) 37 | ); 38 | 39 | export function ptraceError( t: T, somemsg?: string ) 40 | : TermFn<[ PString ], ToPType> 41 | { 42 | return phoist( 43 | plam( str, t ) 44 | ( msg => pforce( 45 | ptrace( delayed( t ) ).$( msg ).$( pdelay( perror( t, somemsg ) ) ) 46 | ) as any ) 47 | ) as any; 48 | } -------------------------------------------------------------------------------- /src/pluts/lib/std/unit/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pmakeUnit"; 2 | export * from "./pmakeUnitData"; 3 | export * from "./pUnitFromData"; 4 | export * from "./peqUnit"; -------------------------------------------------------------------------------- /src/pluts/lib/std/unit/pUnitFromData.ts: -------------------------------------------------------------------------------- 1 | import { phoist } from "../../phoist"; 2 | import { plam } from "../../plam"; 3 | import { pmakeUnit } from "./pmakeUnit"; 4 | import { unit, data } from "../../../type_system/types"; 5 | 6 | export const pUnitFromData = phoist( 7 | plam( data, unit ) 8 | ( _ => pmakeUnit() ) 9 | ) -------------------------------------------------------------------------------- /src/pluts/lib/std/unit/peqUnit.ts: -------------------------------------------------------------------------------- 1 | import { IRFunc, IRHoisted, IRConst } from "../../../../IR"; 2 | import { bool, unit, fn } from "../../../type_system"; 3 | import { addApplications } from "../../builtins/addApplications"; 4 | import { PBool } from "../../../PTypes/PBool"; 5 | import { PUnit } from "../../../PTypes/PUnit"; 6 | import { Term } from "../../../Term"; 7 | 8 | /** 9 | we could use `mkNilData` builtin to check if we actually have units 10 | but we likely dont want the execution to fail by calling `peqUnit` 11 | so this is just a dummy function that always retuns true. 12 | */ 13 | export const peqUnit = 14 | addApplications<[ PUnit, PUnit ], PBool>( 15 | new Term( 16 | fn([ unit, unit ], bool ), 17 | _dbn => new IRHoisted( 18 | new IRFunc( 2, IRConst.bool( true ) ) 19 | ) 20 | ) 21 | ); -------------------------------------------------------------------------------- /src/pluts/lib/std/unit/pmakeUnit.ts: -------------------------------------------------------------------------------- 1 | import { IRConst } from "../../../../IR/IRNodes/IRConst"; 2 | import type { PUnit } from "../../../PTypes/PUnit"; 3 | import { Term } from "../../../Term"; 4 | import { unit } from "../../../type_system/types"; 5 | 6 | export const pmakeUnit = () => new Term( 7 | unit, 8 | _dbn => IRConst.unit, 9 | true // isConstant 10 | ); -------------------------------------------------------------------------------- /src/pluts/lib/std/unit/pmakeUnitData.ts: -------------------------------------------------------------------------------- 1 | import { DataConstr } from "@harmoniclabs/plutus-data"; 2 | import type { PData } from "../../../PTypes"; 3 | import { Term } from "../../../Term"; 4 | import { data } from "../../../type_system/types"; 5 | import { IRHoisted } from "../../../../IR/IRNodes/IRHoisted"; 6 | import { IRConst } from "../../../../IR/IRNodes/IRConst"; 7 | 8 | export const pmakeUnitData = () => new Term( 9 | data, 10 | _dbn => new IRHoisted( 11 | IRConst.data( 12 | new DataConstr( 0, [] ) 13 | ) 14 | ) 15 | ); -------------------------------------------------------------------------------- /src/pluts/type_system/__tests__/typeSys.typeCreation.test.ts: -------------------------------------------------------------------------------- 1 | import { PScriptPurpose } from "../../API/V1/ScriptContext/PScriptPurpose"; 2 | import { pList } from "../../lib/std/list/const"; 3 | import { PrimType, asData, data, int, list, pair, struct } from "../types" 4 | import { termTypeToString } from "../utils"; 5 | 6 | describe("type creation", () => { 7 | 8 | test("asData", () => { 9 | 10 | expect( 11 | asData( data ) 12 | ).toEqual( data ) 13 | 14 | expect( 15 | asData( asData( data ) ) 16 | ).toEqual( data ) 17 | 18 | expect( 19 | asData( 20 | struct({ F: { h: int } }) 21 | ) 22 | ).toEqual( 23 | struct({ F: { h: int } }) 24 | ) 25 | 26 | expect( 27 | asData( 28 | pair( int, int ) 29 | ) 30 | ).not.toEqual( 31 | pair( asData( int ), asData( int ) ) 32 | ); 33 | 34 | expect( 35 | asData( 36 | pair( int, int ) 37 | ) 38 | ).toEqual( 39 | [ PrimType.AsData, pair( int, int ) ] 40 | ); 41 | 42 | expect( 43 | asData( 44 | list( int ) 45 | ) 46 | ).not.toEqual( 47 | list( asData( int ) ) 48 | ); 49 | 50 | expect( 51 | asData( 52 | pList( pair( PScriptPurpose.type, data ) )([]).type 53 | ) 54 | ).toEqual( 55 | [ 56 | PrimType.AsData, 57 | list( pair( PScriptPurpose.type, data ) ) 58 | ] 59 | ) 60 | 61 | }); 62 | }) -------------------------------------------------------------------------------- /src/pluts/type_system/cloneTermType.ts: -------------------------------------------------------------------------------- 1 | import { cloneStructDef } from "../PTypes/PStruct/cloneStructDef"; 2 | import { GenericTermType, PrimType, lam, struct, pair, list, delayed, asData, alias, sop } from "./types"; 3 | 4 | export function cloneTermType( t: T ): T 5 | { 6 | if( t[ 0 ] === PrimType.Struct ) 7 | return struct( cloneStructDef( t[1] ), t[2] ) as any; 8 | 9 | if( t[ 0 ] === PrimType.Sop ) 10 | return sop( cloneStructDef( t[1] ), t[2] ) as any; 11 | 12 | if( t[ 0 ] === PrimType.Lambda ) 13 | return lam( cloneTermType( t[1] ), cloneTermType( t[2] ) ) as any; 14 | 15 | if( t[ 0 ] === PrimType.Pair ) 16 | return pair( cloneTermType( t[1] ), cloneTermType( t[2] ) ) as any; 17 | 18 | if( t[ 0 ] === PrimType.List ) 19 | return list( cloneTermType( t[1] ) ) as any; 20 | 21 | if( t[ 0 ] === PrimType.Delayed ) 22 | return delayed( cloneTermType( t[1] ) ) as any; 23 | 24 | if( t[ 0 ] === PrimType.AsData ) 25 | return asData( cloneTermType( t[1] ) ) as any; 26 | 27 | if( t[ 0 ] === PrimType.Alias ) 28 | return alias( cloneTermType( t[1] ), t[2] ) as any; 29 | 30 | return [ t[0] ] as any; 31 | } -------------------------------------------------------------------------------- /src/pluts/type_system/includesDynamicPairs.ts: -------------------------------------------------------------------------------- 1 | import { unwrapAlias } from "./tyArgs"; 2 | import { GenericTermType, PrimType, StructDefinition } from "./types"; 3 | 4 | 5 | export function includesDynamicPairs( t: GenericTermType | StructDefinition ): boolean 6 | { 7 | if( !Array.isArray( t ) ) return false; 8 | if( t[0] === PrimType.Alias ) return includesDynamicPairs( unwrapAlias( t as any ) ); 9 | if( t[0] === PrimType.AsData ) return false; 10 | if( t[0] === PrimType.List ) return includesDynamicPairs( t[1] ); 11 | if( t[0] === PrimType.Delayed ) return includesDynamicPairs( t[1] ); 12 | if( t[0] === PrimType.Lambda ) 13 | { 14 | return ( 15 | includesDynamicPairs( t[1] ) || 16 | includesDynamicPairs( t[2] ) 17 | ) 18 | } 19 | if( t[0] === PrimType.Pair ) 20 | { 21 | return ( 22 | t[1][0] === PrimType.AsData || 23 | t[2][0] === PrimType.AsData 24 | ) 25 | } 26 | 27 | return false; 28 | } -------------------------------------------------------------------------------- /src/pluts/type_system/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./kinds"; 2 | export * from "./ts-pluts-conversion"; 3 | export * from "./typeExtends"; 4 | export * from "./types"; 5 | export * from "./tyArgs/unwrapAlias"; 6 | export * from "./utils"; 7 | export * from "./withAllPairElemsAsData"; -------------------------------------------------------------------------------- /src/pluts/type_system/kinds/__tests__/typeSys.isWellFormedType.test.ts: -------------------------------------------------------------------------------- 1 | import { TermType, alias, bool, bs, fn, int, lam } from "../../types" 2 | import { isWellFormedType, isWellFormedGenericType } from "../../kinds"; 3 | import { termTypeToString } from "../../utils"; 4 | import { pBool } from "../../../lib/std/bool/pBool"; 5 | import { pfn } from "../../../lib/pfn"; 6 | 7 | const fakeTerm = pfn([ int ], bool )(( n ) => pBool( true )); 8 | 9 | describe("isWellFormedType", () => { 10 | 11 | function yes( t: TermType ) 12 | { 13 | test( termTypeToString( t ), () => { 14 | expect( 15 | isWellFormedType( t ) 16 | ).toBe( true ); 17 | // every well formed term type is also a well formed generic term type 18 | expect( 19 | isWellFormedGenericType( t ) 20 | ).toBe( true ); 21 | }) 22 | } 23 | 24 | yes( lam( bs, int ) ); 25 | yes( fn([ bs, int ], int) ); 26 | 27 | yes( alias( int ) ); 28 | yes( alias( int, {} ) ); 29 | yes( alias( int, { foo: fakeTerm } ) ); 30 | 31 | }) -------------------------------------------------------------------------------- /src/pluts/type_system/kinds/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./isPrimTypeTag"; 2 | export * from "./isTaggedAsAlias"; 3 | export * from "./isTypePAram"; 4 | export * from "./isWellFormedType"; -------------------------------------------------------------------------------- /src/pluts/type_system/kinds/isTaggedAsAlias.ts: -------------------------------------------------------------------------------- 1 | import { GenericTermType, PrimType, TermType } from "../types"; 2 | 3 | export function isTaggedAsAlias( t: GenericTermType ): t is [ PrimType.Alias, TermType, {} ] 4 | { 5 | return ( 6 | Array.isArray( t ) && t.length >= 2 && 7 | t[0] === PrimType.Alias 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /src/pluts/type_system/kinds/isTypePAram.ts: -------------------------------------------------------------------------------- 1 | import { GenericTermType } from "../types"; 2 | 3 | export function isTypeParam( t: GenericTermType ): t is [ symbol ] 4 | { 5 | return (( 6 | Array.isArray( t ) && 7 | t.length === 1 && 8 | typeof t[0] === "symbol" 9 | ) || typeof t === "symbol"); 10 | } -------------------------------------------------------------------------------- /src/pluts/type_system/termTyToConstTy.ts: -------------------------------------------------------------------------------- 1 | import { PrimType, TermType } from "./types"; 2 | import { unwrapAlias } from "./tyArgs/unwrapAlias"; 3 | import { ConstType, constT } from "@harmoniclabs/uplc"; 4 | 5 | export function termTyToConstTy( t: TermType ): ConstType 6 | { 7 | switch( t[0] ) 8 | { 9 | case PrimType.Alias: return termTyToConstTy( unwrapAlias( t as any ) ); 10 | case PrimType.Unit: return constT.unit; 11 | case PrimType.Int: return constT.int; 12 | case PrimType.BS: return constT.byteStr; 13 | case PrimType.bls12_381_G1_element: return constT.bls12_381_G1_element; 14 | case PrimType.bls12_381_G2_element: return constT.bls12_381_G2_element; 15 | case PrimType.bls12_381_MlResult : return constT.bls12_381_MlResult ; 16 | case PrimType.Bool: return constT.bool; 17 | case PrimType.Str: return constT.str; 18 | case PrimType.Struct: 19 | case PrimType.Data: 20 | case PrimType.AsData: return constT.data; 21 | case PrimType.List: return constT.listOf( termTyToConstTy( t[1] ) ); 22 | case PrimType.Pair: return constT.pairOf( termTyToConstTy( t[1] ), termTyToConstTy( t[2] ) ) 23 | 24 | case PrimType.Delayed: 25 | case PrimType.Lambda: 26 | case PrimType.Sop: 27 | default: 28 | throw new Error("unable to convert term type to uplc constant type") 29 | } 30 | } -------------------------------------------------------------------------------- /src/pluts/type_system/tyArgs/__tests__/clearAsData.test.ts: -------------------------------------------------------------------------------- 1 | import { TermType, int, asData } from "../../types" 2 | import { termTypeToString } from "../../utils" 3 | import { clearAsData } from "../clearAsData" 4 | import { unwrapAsData } from "../unwrapAsData" 5 | 6 | describe("clearAsData", () => { 7 | 8 | function testType( t: TermType, expected: TermType ): void 9 | { 10 | test( termTypeToString( t ), () => { 11 | 12 | expect( clearAsData( t ) ).toEqual( expected ); 13 | expect( clearAsData( t )[0] ).toEqual( unwrapAsData( t )[0] ); 14 | 15 | }) 16 | } 17 | 18 | testType( asData( int ), int ); 19 | }) -------------------------------------------------------------------------------- /src/pluts/type_system/tyArgs/__tests__/getElemsT.test.ts: -------------------------------------------------------------------------------- 1 | import { PAssetsEntry, TermType, alias, int, list, termTypeToString } from "../../.." 2 | import { getElemsT } from "../getElemsT" 3 | 4 | describe("getElemsT", () => { 5 | 6 | describe("just list", () => { 7 | 8 | test("list(int) -> int", () => { 9 | expect( getElemsT( list( int ) ) ).toEqual( int ); 10 | }); 11 | 12 | test("list(list(int)) -> list(int)", () => { 13 | expect( getElemsT( list( list( int ) ) ) ).toEqual( list( int ) ); 14 | }); 15 | 16 | test("list(list(list(int))) -> list(list(int))", () => { 17 | expect( getElemsT( list( list( list( int ) ) ) ) ).toEqual( list( list( int ) ) ); 18 | }); 19 | 20 | }); 21 | 22 | describe("alias list", () => { 23 | 24 | test("alias(list(int)) -> int", () => { 25 | expect( getElemsT( alias( list( int ) ) ) ).toEqual( int ); 26 | }); 27 | 28 | }); 29 | 30 | }) -------------------------------------------------------------------------------- /src/pluts/type_system/tyArgs/clearAsData.ts: -------------------------------------------------------------------------------- 1 | import { PrimType, TermType, alias, asData, list, pair } from "../types"; 2 | import { getElemsT } from "./getElemsT"; 3 | import { getFstT } from "./getFstT"; 4 | import { getSndT } from "./getSndT"; 5 | import { unwrapAsData } from "./unwrapAsData"; 6 | 7 | /** 8 | * undoes the `asData` call 9 | */ 10 | export function clearAsData( t: TermType ): TermType 11 | { 12 | // invalid asData type but not worth to rise an error 13 | if( 14 | t[0] === PrimType.Lambda || 15 | t[0] === PrimType.Delayed 16 | ) return t; 17 | 18 | // already data 19 | if( 20 | t[0] === PrimType.Struct || 21 | t[0] === PrimType.Data 22 | ) return t; 23 | 24 | t = unwrapAsData( t ); 25 | 26 | if( t[0] === PrimType.Alias ) 27 | { 28 | t = alias( clearAsData( t[1] ), t[2] ); 29 | } 30 | else if( t[0] === PrimType.List ) 31 | { 32 | const listElemsT = getElemsT( t ); 33 | 34 | if( listElemsT[ 0 ] === PrimType.Pair ) 35 | { 36 | const fstT = getFstT( listElemsT ); 37 | const sndT = getSndT( listElemsT ); 38 | t = list( pair( clearAsData( fstT ), clearAsData( sndT ) ) ) 39 | } 40 | else 41 | { 42 | t = list( clearAsData( listElemsT ) ) 43 | } 44 | } 45 | 46 | return t; 47 | } -------------------------------------------------------------------------------- /src/pluts/type_system/tyArgs/getDirectFstT.ts: -------------------------------------------------------------------------------- 1 | import { GenericTermType, PrimType, TermType } from "../types"; 2 | 3 | export function getDirectFstT( t: [ PrimType.Pair, T, GenericTermType ] ): T 4 | export function getDirectFstT( t: TermType ): TermType 5 | export function getDirectFstT( t: GenericTermType ): GenericTermType 6 | export function getDirectFstT( t: GenericTermType ): GenericTermType 7 | { 8 | // !!! IMPORTANT !!! 9 | // **this unwrapping is assumed to happen here** by `typeExtends` 10 | // if this ever changes please reflect the change to `typeExtends` too 11 | // !!! IMPORTANT !!! 12 | while( 13 | t[0] !== PrimType.Pair 14 | ) t = t[1] as any; 15 | 16 | return t[1] as any; 17 | } -------------------------------------------------------------------------------- /src/pluts/type_system/tyArgs/getDirectSndT.ts: -------------------------------------------------------------------------------- 1 | import { GenericTermType, PrimType, TermType } from "../types"; 2 | 3 | export function getDirectSndT( t: [ PrimType.Pair, GenericTermType, T ] ): T 4 | export function getDirectSndT( t: TermType ): TermType 5 | export function getDirectSndT( t: GenericTermType ): GenericTermType 6 | export function getDirectSndT( t: GenericTermType ): GenericTermType 7 | { 8 | // !!! IMPORTANT !!! 9 | // **this unwrapping is assumed to happen here** by `typeExtends` 10 | // if this ever changes please reflect the change to `typeExtends` too 11 | // !!! IMPORTANT !!! 12 | while( 13 | t[0] !== PrimType.Pair 14 | ) t = t[1] as any; 15 | 16 | return t[2] as any; 17 | } -------------------------------------------------------------------------------- /src/pluts/type_system/tyArgs/getElemsT.ts: -------------------------------------------------------------------------------- 1 | import { GenericTermType, PrimType, TermType } from "../types"; 2 | 3 | export function getElemsT( t: [ PrimType.Alias, [ PrimType.List, T ], any ] ): T 4 | export function getElemsT( t: [ PrimType.AsData, [ PrimType.List, T ] ] ): T 5 | export function getElemsT( t: [ PrimType.List, T ] ): T 6 | export function getElemsT( t: TermType ): TermType 7 | export function getElemsT( t: GenericTermType ): GenericTermType 8 | export function getElemsT( t: GenericTermType ): GenericTermType 9 | { 10 | // get to the first list type 11 | // aka, skips `alias` `asData` etc. 12 | while( t[0] !== PrimType.List ) t = t[1] as any; 13 | 14 | return t[1] as any; 15 | } -------------------------------------------------------------------------------- /src/pluts/type_system/tyArgs/getFstT.ts: -------------------------------------------------------------------------------- 1 | import { GenericTermType, PrimType, TermType } from "../types"; 2 | 3 | export function getFstT( t: [ PrimType.Alias, [ PrimType.Pair, T, GenericTermType ], any ] ): T 4 | export function getFstT( t: [ PrimType.AsData, [ PrimType.Pair, T, GenericTermType ] ] ): T 5 | export function getFstT( t: [ PrimType.Pair, T, GenericTermType ] ): T 6 | export function getFstT( t: TermType ): TermType 7 | export function getFstT( t: GenericTermType ): GenericTermType 8 | export function getFstT( t: GenericTermType ): GenericTermType 9 | { 10 | // !!! IMPORTANT !!! 11 | // **this unwrapping is assumed to happen here** by `typeExtends` 12 | // if this ever changes please reflect the change to `typeExtends` too 13 | // !!! IMPORTANT !!! 14 | while( 15 | t[0] === PrimType.AsData || 16 | t[0] === PrimType.Alias 17 | ) t = t[1]; 18 | 19 | if( t[0] !== PrimType.Pair ) 20 | throw new Error("getSndT used on non-pair type"); 21 | 22 | t = t[1] as any; 23 | 24 | return t as any; 25 | } -------------------------------------------------------------------------------- /src/pluts/type_system/tyArgs/getSndT.ts: -------------------------------------------------------------------------------- 1 | import { GenericTermType, PrimType, TermType } from "../types"; 2 | 3 | export function getSndT( t: [ PrimType.Alias, [ PrimType.Pair, GenericTermType, T ], any ] ): T 4 | export function getSndT( t: [ PrimType.AsData, [ PrimType.Pair, GenericTermType, T ] ] ): T 5 | export function getSndT( t: [ PrimType.Pair, GenericTermType, T ] ): T 6 | export function getSndT( t: TermType ): TermType 7 | export function getSndT( t: GenericTermType ): GenericTermType 8 | export function getSndT( t: GenericTermType ): GenericTermType 9 | { 10 | // !!! IMPORTANT !!! 11 | // **this unwrapping is assumed to happen here** by `typeExtends` 12 | // if this ever changes please reflect the change to `typeExtends` too 13 | // !!! IMPORTANT !!! 14 | while( 15 | t[0] === PrimType.AsData || 16 | t[0] === PrimType.Alias 17 | ) t = t[1]; 18 | 19 | if( t[0] !== PrimType.Pair ) 20 | throw new Error("getSndT used on non-pair type"); 21 | 22 | t = t[2]; 23 | return t; 24 | } -------------------------------------------------------------------------------- /src/pluts/type_system/tyArgs/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./getElemsT"; 2 | export * from "./getFstT"; 3 | export * from "./getSndT"; 4 | export * from "./unwrapAlias"; 5 | export * from "./unwrapAsData"; -------------------------------------------------------------------------------- /src/pluts/type_system/tyArgs/unwrapAlias.ts: -------------------------------------------------------------------------------- 1 | import { PrimType, TermType } from "../types"; 2 | 3 | export function unwrapAlias( t: [ PrimType.Alias, T, any ] | T ): T 4 | { 5 | while( t[0] === PrimType.Alias ) t = t[1] as any; 6 | return t as any; 7 | } -------------------------------------------------------------------------------- /src/pluts/type_system/tyArgs/unwrapAsData.ts: -------------------------------------------------------------------------------- 1 | import { PrimType, TermType } from "../types"; 2 | 3 | export function unwrapAsData( t: [ PrimType.AsData, T ] ): T 4 | export function unwrapAsData( t: T ): T 5 | export function unwrapAsData( t: TermType ): T 6 | { 7 | while( t[0] === PrimType.AsData ) t = t[1] as any; 8 | return t as any; 9 | } -------------------------------------------------------------------------------- /src/utils/BasePlutsError.ts: -------------------------------------------------------------------------------- 1 | export class BasePlutsError extends Error {} -------------------------------------------------------------------------------- /src/utils/Cloneable.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface Cloneable 3 | { 4 | clone: () => T 5 | } 6 | 7 | export function isCloneable( something: T ): something is T & { clone: () => T } 8 | { 9 | return ( 10 | typeof ( (something as any)["clone"] ) === "function" && 11 | (something as any)["clone"].length === 0 12 | ) 13 | } -------------------------------------------------------------------------------- /src/utils/InvalidCborFormatError.ts: -------------------------------------------------------------------------------- 1 | export class InvalidCborFormatError extends Error 2 | { 3 | constructor( str: string, restMsg: string = "" ) 4 | { 5 | super(`Invalid CBOR format for "${str}"; ${restMsg}`) 6 | } 7 | } -------------------------------------------------------------------------------- /src/utils/IsSingleKey.ts: -------------------------------------------------------------------------------- 1 | type SingleKeyObj = { 2 | [Prop in K]: (Record & 3 | // `infer O` here is just binding 4 | Record, never>) extends infer O 5 | ? { [Q in keyof O]: O[Q] } 6 | : never 7 | }[K]; 8 | 9 | export default SingleKeyObj; 10 | 11 | export type IsSingleKey = Obj extends SingleKeyObj ? true : false; -------------------------------------------------------------------------------- /src/utils/PlutusScriptType.ts: -------------------------------------------------------------------------------- 1 | export const enum ScriptType { 2 | NativeScript = "NativeScript", 3 | PlutusV1 = "PlutusScriptV1", 4 | PlutusV2 = "PlutusScriptV2" 5 | } 6 | 7 | export type PlutusScriptType = ScriptType.PlutusV1 | ScriptType.PlutusV2 | "PlutusScriptV1" | "PlutusScriptV2" 8 | 9 | export type LitteralScriptType = ScriptType | "NativeScript" | "PlutusScriptV1" | "PlutusScriptV2" 10 | 11 | export interface PlutusScriptJsonFormat { 12 | type: T, 13 | description?: string, 14 | cborHex: string 15 | } -------------------------------------------------------------------------------- /src/utils/ToJson.ts: -------------------------------------------------------------------------------- 1 | import { stringify } from "./stringify"; 2 | 3 | export interface ToJson { 4 | toJson: () => any 5 | } 6 | 7 | export function logJson( jsonLike: ToJson, indent: number = 4 ): void 8 | { 9 | const obj = typeof jsonLike !== "undefined" && typeof (jsonLike as any).toJson === "function" ? (jsonLike as any).toJson() : jsonLike 10 | 11 | console.log( 12 | stringify( obj, undefined, indent ), 13 | Error().stack?.split("\n")[2] 14 | ); 15 | } -------------------------------------------------------------------------------- /src/utils/UPLCFlatUtils/__tests__/unzigzagBigint.test.ts: -------------------------------------------------------------------------------- 1 | import UPLCFlatUtils from ".." 2 | 3 | 4 | describe( "UPLCFlatUtils.zigzagBigint", () => { 5 | 6 | it( "0 -> 0" , () => { 7 | 8 | expect( 9 | UPLCFlatUtils.unzigzagBigint( 10 | BigInt( 0 ) 11 | ) 12 | ).toEqual( BigInt( 0 ) ) 13 | 14 | }); 15 | 16 | it( "even -> positive", () => { 17 | 18 | for( let i = 2; i < 0x10000; i += 2 ) 19 | { 20 | expect( 21 | UPLCFlatUtils.unzigzagBigint( 22 | BigInt( i ) 23 | ) 24 | ).toBeGreaterThan( BigInt( 0 ) ) 25 | } 26 | 27 | }) 28 | 29 | it( "odd -> negative", () => { 30 | 31 | for( let i = 1; i < 0x10000; i += 2 ) 32 | { 33 | expect( 34 | UPLCFlatUtils.unzigzagBigint( 35 | BigInt( i ) 36 | ) 37 | ).toBeLessThan( BigInt( 0 ) ) 38 | } 39 | 40 | }) 41 | 42 | it( "throws on negative input", () => { 43 | 44 | for( let i = -1; i < -0xffff; i -= Math.floor( Math.random() * 15 ) ) 45 | { 46 | expect( () => 47 | UPLCFlatUtils.unzigzagBigint( 48 | BigInt( i ) 49 | ) 50 | ).toThrow() 51 | } 52 | 53 | }) 54 | 55 | }) 56 | -------------------------------------------------------------------------------- /src/utils/UPLCFlatUtils/__tests__/zigzagBigint.test.ts: -------------------------------------------------------------------------------- 1 | import UPLCFlatUtils from ".." 2 | 3 | 4 | describe( "UPLCFlatUtils.zigzagBigint", () => { 5 | 6 | it( "0 -> 0" , () => { 7 | 8 | expect( 9 | UPLCFlatUtils.zigzagBigint( 10 | BigInt( 0 ) 11 | ) 12 | ).toEqual( BigInt( 0 ) ) 13 | 14 | }); 15 | 16 | it( "positive -> positive * 2", () => { 17 | 18 | for( let i = 1; i < 0xffff; i++ ) 19 | { 20 | expect( 21 | UPLCFlatUtils.zigzagBigint( 22 | BigInt( i ) 23 | ) 24 | ).toEqual( BigInt( i * 2 ) ) 25 | } 26 | 27 | }) 28 | 29 | it( "negative -> -negative * 2 - 1", () => { 30 | 31 | for( let i = -1; i < -0xffff; i-- ) 32 | { 33 | expect( 34 | UPLCFlatUtils.zigzagBigint( 35 | BigInt( i ) 36 | ) 37 | ).toEqual( BigInt( -i * 2 - 1 ) ) 38 | } 39 | 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /src/utils/assert.ts: -------------------------------------------------------------------------------- 1 | export function assert( condition: boolean, errorMessage: string | Error , addInfos?: any ,...args: any[]) 2 | { 3 | if( condition ) return; 4 | 5 | args.length > 0 && console.error(...args); 6 | addInfos && console.error(addInfos); 7 | 8 | if( errorMessage instanceof Error ) 9 | { 10 | throw errorMessage 11 | }; 12 | 13 | throw new Error( errorMessage ); 14 | } -------------------------------------------------------------------------------- /src/utils/capitalize.ts: -------------------------------------------------------------------------------- 1 | export function capitalize( s: str ): Capitalize 2 | { 3 | if( s.length === 0 ) return s as any; 4 | return (s[0].toUpperCase() + s.slice( 1 )) as any; 5 | } -------------------------------------------------------------------------------- /src/utils/hex.ts: -------------------------------------------------------------------------------- 1 | const hexChars = Object.freeze(Array.from("0123456789abcdef")); 2 | 3 | export function isHex( str: string ): boolean 4 | { 5 | if(!( typeof str === "string" )) return false; 6 | 7 | return Array.from(str).every( ch => hexChars.includes( ch ) ); 8 | } -------------------------------------------------------------------------------- /src/utils/ints.ts: -------------------------------------------------------------------------------- 1 | export type CanBeUInteger 2 | = bigint 3 | | number; 4 | 5 | export function canBeUInteger( something: any ): something is (number | bigint) 6 | { 7 | return ( 8 | (typeof something === "bigint" && something >= BigInt( 0 ) ) || 9 | (typeof something === "number" && something === Math.round( Math.abs( something ) ) ) 10 | ); 11 | } 12 | 13 | export function forceBigUInt( toForce: CanBeUInteger ): bigint 14 | { 15 | if( !canBeUInteger( toForce ) ) 16 | { 17 | // console.error( toForce ); 18 | throw new Error( "trying to convert an integer to an unsigned Integer, the number was negative" ); 19 | } 20 | 21 | return BigInt( toForce ); 22 | }; 23 | 24 | export function unsafeForceUInt( toForce: CanBeUInteger ): number 25 | { 26 | if( !canBeUInteger( toForce ) ) 27 | { 28 | // console.error( toForce ); 29 | throw new Error( "trying to convert an integer to an unsigned Integer, the number was negative" ); 30 | } 31 | 32 | return Number( toForce ); 33 | } -------------------------------------------------------------------------------- /src/utils/maybeData.ts: -------------------------------------------------------------------------------- 1 | import { DataConstr, Data } from "@harmoniclabs/plutus-data"; 2 | 3 | export function nothingData(): DataConstr 4 | { 5 | return new DataConstr( 1, [] ); 6 | } 7 | 8 | export function justData( someData: Data ): DataConstr 9 | { 10 | return new DataConstr( 11 | 0, [ someData ] 12 | ) 13 | } 14 | 15 | export function maybeData( optionalData: Data | undefined ): DataConstr 16 | { 17 | return optionalData === undefined ? nothingData() : justData( optionalData ); 18 | } -------------------------------------------------------------------------------- /src/utils/stringify.ts: -------------------------------------------------------------------------------- 1 | import { isObject } from "@harmoniclabs/obj-utils"; 2 | import { toHex } from "@harmoniclabs/uint8array-utils"; 3 | 4 | export function mkReplacer( 5 | replacer?: (key: string, value: any) => any | null, 6 | map: WeakMap = new WeakMap() 7 | ) 8 | { 9 | if( typeof replacer !== "function" ) replacer = ( k, v ) => v; 10 | return function( key: string, value: any ) 11 | { 12 | value = replacer!(key, value); 13 | if( isObject( value ) ) 14 | { 15 | if ( map.has(value) ) { 16 | return { _circular_ref_: map.get(value) }; 17 | } 18 | map.set(value, key); 19 | 20 | if( typeof value.buffer === "object" && value.buffer instanceof ArrayBuffer ) 21 | { 22 | value = new Uint8Array(value.buffer); 23 | } 24 | if( value instanceof Uint8Array) 25 | { 26 | value = toHex(value); 27 | } 28 | } 29 | if( typeof value === "bigint" ) 30 | { 31 | value = value.toString(); 32 | } 33 | 34 | return value; 35 | }; 36 | } 37 | 38 | export function stringify( 39 | value: any, 40 | replacer?: (key: string, value: any) => any | null | (number | string)[], 41 | space: string | number = 0 42 | ): string 43 | { 44 | if( replacer ) 45 | { 46 | return JSON.stringify(value, replacer, space); 47 | } 48 | return JSON.stringify(value, mkReplacer( replacer, new WeakMap() ), space); 49 | } -------------------------------------------------------------------------------- /src/utils/types.ts: -------------------------------------------------------------------------------- 1 | export type Head = Types extends [ infer First, ...any[] ] ? First : never; 2 | export type Tail = Types extends [ any, ...infer Lasts extends any[] ] ? Lasts: never; 3 | 4 | export type NonEmptyTail = 5 | Types extends [ any, infer Snd ] ? [ Snd ] : 6 | Types extends [ any, infer Snd, ...infer Lasts extends any[] ] ? [ Snd, ...Lasts ] : never; 7 | 8 | 9 | export type Last = Types extends [ ...any[], infer Last ] ? Last : never; 10 | export type Init = Types extends [ ...infer All, any ] ? All: never; 11 | 12 | export type VoidIfEmpty< Arr extends Array > = Arr extends [] ? void : Arr; 13 | 14 | export type NoInfer = T & {[K in keyof T]: T[K]}; 15 | 16 | export type DefaultUndefined = A extends undefined ? Def : A; 17 | export type DefaultNever = A extends never ? Def : A; 18 | 19 | export type ConcreteInstanceType any> = T extends new (...args: any) => infer R ? R : any; -------------------------------------------------------------------------------- /workers-tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "skipLibCheck": true, 4 | "target": "ES5", 5 | "module": "commonjs", 6 | "allowJs": true, 7 | "checkJs": false, 8 | "outDir": "./tsc-out", 9 | "rootDir": "./src", 10 | "downlevelIteration": true, 11 | "strict": false, 12 | "noImplicitAny": true, 13 | "strictNullChecks": true, 14 | "strictFunctionTypes": false, 15 | "strictBindCallApply": true, 16 | "strictPropertyInitialization": false, 17 | "noImplicitThis": true, 18 | "alwaysStrict": false, 19 | "moduleResolution": "node", 20 | "allowSyntheticDefaultImports": true, 21 | "esModuleInterop": true, 22 | "forceConsistentCasingInFileNames": true 23 | }, 24 | "files": [ 25 | "src/offchain/tx/builder/buildWorker.ts" 26 | ], 27 | "tsc-alias": { 28 | "verbose": false, 29 | "resolveFullPaths": true 30 | } 31 | } --------------------------------------------------------------------------------