From b05e8eba43d7cedeeabbd7a4ddcc63815c967fca Mon Sep 17 00:00:00 2001 From: Hernan Rajchert Date: Fri, 15 Dec 2023 13:42:50 -0300 Subject: [PATCH] wip apply merkleized inputs --- examples/nodejs/package-lock.json | 103 --------------------- examples/nodejs/package.json | 1 - examples/nodejs/src/marlowe-object-flow.ts | 45 ++++++--- packages/language/core/v1/src/contract.ts | 32 +++++++ packages/language/core/v1/src/index.ts | 1 + 5 files changed, 67 insertions(+), 115 deletions(-) diff --git a/examples/nodejs/package-lock.json b/examples/nodejs/package-lock.json index 2cb10d5f..ce29a126 100644 --- a/examples/nodejs/package-lock.json +++ b/examples/nodejs/package-lock.json @@ -9,7 +9,6 @@ "version": "0.0.1", "dependencies": { "@inquirer/prompts": "^3.3.0", - "@marlowe.io/language-core-v1": "^0.2.0-alpha-22", "arg": "^5.0.2" }, "devDependencies": { @@ -450,26 +449,6 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@marlowe.io/language-core-v1": { - "version": "0.2.0-alpha-22", - "resolved": "https://registry.npmjs.org/@marlowe.io/language-core-v1/-/language-core-v1-0.2.0-alpha-22.tgz", - "integrity": "sha512-NC0fXyNXcusK1VElOvgpk0M1y+QNvi4W8x1QMej6R/apA/gSdUOXcVA8zUa6QDglVyWieYstYyi5aso1sefqyQ==", - "dependencies": { - "date-fns": "2.29.3", - "fp-ts": "^2.16.0", - "io-ts": "2.2.20", - "io-ts-types": "0.5.19", - "json-bigint": "^1.0.0", - "jsonbigint-io-ts-reporters": "2.0.1", - "newtype-ts": "0.3.5" - } - }, - "node_modules/@scarf/scarf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.3.0.tgz", - "integrity": "sha512-lHKK8M5CTcpFj2hZDB3wIjb0KAbEOgDmiJGDv1WBRfQgRm/a8/XMEkG/N1iM01xgbUDsPQwi42D+dFo1XPAKew==", - "hasInstallScript": true - }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -577,14 +556,6 @@ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" }, - "node_modules/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", - "engines": { - "node": "*" - } - }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -631,18 +602,6 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, - "node_modules/date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -670,11 +629,6 @@ "node": ">=4" } }, - "node_modules/fp-ts": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.1.tgz", - "integrity": "sha512-by7U5W8dkIzcvDofUcO42yl9JbnHTEDBrzu3pt5fKT+Z4Oy85I21K80EYJYdjQGC2qum4Vo55Ag57iiIK4FYuA==" - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -694,25 +648,6 @@ "node": ">=0.10.0" } }, - "node_modules/io-ts": { - "version": "2.2.20", - "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.2.20.tgz", - "integrity": "sha512-Rq2BsYmtwS5vVttie4rqrOCIfHCS9TgpRLFpKQCM1wZBBRY9nWVGmEvm2FnDbSE2un1UE39DvFpTR5UL47YDcA==", - "peerDependencies": { - "fp-ts": "^2.5.0" - } - }, - "node_modules/io-ts-types": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/io-ts-types/-/io-ts-types-0.5.19.tgz", - "integrity": "sha512-kQOYYDZG5vKre+INIDZbLeDJe+oM+4zLpUkjXyTMyUfoCpjJNyi29ZLkuEAwcPufaYo3yu/BsemZtbdD+NtRfQ==", - "peerDependencies": { - "fp-ts": "^2.0.0", - "io-ts": "^2.0.0", - "monocle-ts": "^2.0.0", - "newtype-ts": "^0.3.2" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -721,41 +656,12 @@ "node": ">=8" } }, - "node_modules/json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "dependencies": { - "bignumber.js": "^9.0.0" - } - }, - "node_modules/jsonbigint-io-ts-reporters": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jsonbigint-io-ts-reporters/-/jsonbigint-io-ts-reporters-2.0.1.tgz", - "integrity": "sha512-Sk8PAR1l/nSGa1h26VbxIYpcOHONcQsS4i1nuHW7xkG+sqh6j4YhII8tU3PiimNBGK7LTlmL4E6wNth0hyayew==", - "dependencies": { - "@scarf/scarf": "^1.1.1" - }, - "peerDependencies": { - "fp-ts": "^2.10.5", - "io-ts": "^2.2.16" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "node_modules/monocle-ts": { - "version": "2.3.13", - "resolved": "https://registry.npmjs.org/monocle-ts/-/monocle-ts-2.3.13.tgz", - "integrity": "sha512-D5Ygd3oulEoAm3KuGO0eeJIrhFf1jlQIoEVV2DYsZUMz42j4tGxgct97Aq68+F8w4w4geEnwFa8HayTS/7lpKQ==", - "peer": true, - "peerDependencies": { - "fp-ts": "^2.5.0" - } - }, "node_modules/mute-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", @@ -764,15 +670,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/newtype-ts": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/newtype-ts/-/newtype-ts-0.3.5.tgz", - "integrity": "sha512-v83UEQMlVR75yf1OUdoSFssjitxzjZlqBAjiGQ4WJaML8Jdc68LJ+BaSAXUmKY4bNzp7hygkKLYTsDi14PxI2g==", - "peerDependencies": { - "fp-ts": "^2.0.0", - "monocle-ts": "^2.0.0" - } - }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", diff --git a/examples/nodejs/package.json b/examples/nodejs/package.json index 2f017d98..91167ead 100644 --- a/examples/nodejs/package.json +++ b/examples/nodejs/package.json @@ -16,7 +16,6 @@ }, "dependencies": { "@inquirer/prompts": "^3.3.0", - "@marlowe.io/language-core-v1": "^0.2.0-alpha-22", "arg": "^5.0.2" } } diff --git a/examples/nodejs/src/marlowe-object-flow.ts b/examples/nodejs/src/marlowe-object-flow.ts index c6f5b817..0b949268 100644 --- a/examples/nodejs/src/marlowe-object-flow.ts +++ b/examples/nodejs/src/marlowe-object-flow.ts @@ -8,15 +8,15 @@ import { mkLucidWallet, WalletAPI } from "@marlowe.io/wallet"; import { mkRuntimeLifecycle } from "@marlowe.io/runtime-lifecycle"; import { Lucid, Blockfrost, C } from "lucid-cardano"; import { readConfig } from "./config.js"; -import { datetoTimeout } from "@marlowe.io/language-core-v1"; +import { datetoTimeout, getNextTimeout, Timeout } from "@marlowe.io/language-core-v1"; import { addressBech32, + contractId, ContractId, contractIdToTxId, Tags, transactionWitnessSetTextEnvelope, TxId, - unAddressBech32, } from "@marlowe.io/runtime-core"; import { Address } from "@marlowe.io/language-core-v1"; import { Bundle, Label, lovelace } from "@marlowe.io/marlowe-object"; @@ -108,7 +108,7 @@ async function createContractMenu(lifecycle: RuntimeLifecycle) { ); const [contractId, txId] = await createContract(lifecycle, { - payFrom: { address: unAddressBech32(walletAddress) }, + payFrom: { address: walletAddress }, payTo: { address: payee }, amount, depositDeadline, @@ -118,20 +118,43 @@ async function createContractMenu(lifecycle: RuntimeLifecycle) { console.log(`Contract created with id ${contractId}`); await waitIndicator(lifecycle.wallet, txId); - await contractMenu(); + await contractMenu(lifecycle, contractId); } -async function loadContractMenu() { - const answer = await input({ +async function loadContractMenu(lifecycle: RuntimeLifecycle) { + const cid = await input({ message: "Enter the contractId", }); - console.log(answer); - await contractMenu(); + await contractMenu(lifecycle, contractId(cid)); } -// async function contractMenu(contractId: ContractId) { -async function contractMenu() { +async function contractMenu( + lifecycle: RuntimeLifecycle, + contractId: ContractId +) { console.log("TODO: print contract state"); + const contractDetails = await lifecycle.restClient.getContractById( + contractId + ); + const now = datetoTimeout(new Date()); + + if (contractDetails.currentContract._tag === "None") { + console.log("DEBUG: current contract none"); + } + + const currentContract = + contractDetails.currentContract._tag === "None" + ? contractDetails.initialContract + : contractDetails.currentContract.value; + const nextTimeout = getNextTimeout(currentContract, now); + const oneDayFrom = (time: Timeout) => time + 24n * 60n * 60n * 1000n; // in milliseconds + const applicableInputs = await lifecycle.contracts.getApplicableInputs( + contractId, + { timeInterval: { from: now, to: nextTimeout ?? oneDayFrom(now)} } + ); + console.log("applicable inputs"); + console.log(applicableInputs); + const answer = await select({ message: "Contract menu", choices: [ @@ -159,7 +182,7 @@ async function mainLoop(lifecycle: RuntimeLifecycle) { await createContractMenu(lifecycle); break; case "load": - await loadContractMenu(); + await loadContractMenu(lifecycle); break; case "exit": process.exit(0); diff --git a/packages/language/core/v1/src/contract.ts b/packages/language/core/v1/src/contract.ts index c357b78c..294fb004 100644 --- a/packages/language/core/v1/src/contract.ts +++ b/packages/language/core/v1/src/contract.ts @@ -331,3 +331,35 @@ export function matchContract(matcher: Partial>) { } }; } +// Copied from semantic module, maybe we want to move this to a common place? An adaptor bigint maybe? +const minBigint = (a: bigint, b: bigint): bigint => (a < b ? a : b); + +/** + * This function calculates the next timeout of a contract after a given minTime. + * @param minTime Normally the current time, but it represents any time for which you want to see what is the next timeout after that. + * @param contract The contract to analyze + * @returns The next timeout after minTime, or undefined if there is no timeout after minTime. + * @category Introspection + */ +export function getNextTimeout(contract: Contract, minTime: Timeout): Timeout | undefined { + return matchContract({ + close: () => undefined, + pay: (pay) => getNextTimeout(pay.then, minTime), + if: (ifContract) => { + const thenTimeout = getNextTimeout(ifContract.then, minTime); + const elseTimeout = getNextTimeout(ifContract.else, minTime); + return thenTimeout && elseTimeout + ? minBigint(thenTimeout, elseTimeout) + : thenTimeout || elseTimeout; + }, + when: (whenContract) => { + if (minTime > whenContract.timeout) { + return getNextTimeout(whenContract.timeout_continuation, minTime); + } else { + return whenContract.timeout; + } + }, + let: (letContract) => getNextTimeout(letContract.then, minTime), + assert: (assertContract) => getNextTimeout(assertContract.then, minTime) + })(contract) +} diff --git a/packages/language/core/v1/src/index.ts b/packages/language/core/v1/src/index.ts index 0bce3c99..b6e4d92d 100644 --- a/packages/language/core/v1/src/index.ts +++ b/packages/language/core/v1/src/index.ts @@ -40,6 +40,7 @@ export { datetoTimeout, timeoutToDate, Timeout, + getNextTimeout } from "./contract.js"; export { Environment, mkEnvironment, TimeInterval } from "./environment.js";