diff --git a/nx.json b/nx.json index b59088d47..a47351252 100644 --- a/nx.json +++ b/nx.json @@ -60,7 +60,8 @@ "tool-erc20-approval", "tool-uniswap-swap", "mcp-server", - "toolpolicies-e2e" + "toolpolicies-e2e", + "@lit-protocol/lit-action-bundler" ], "projectsRelationship": "independent", "releaseTagPattern": "vincent/{projectName}/{version}", diff --git a/package.json b/package.json index 2d9e52f7c..413c70014 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@swc-node/register": "~1.9.1", "@swc/core": "~1.5.7", "@swc/helpers": "~0.5.11", + "@swc/jest": "~0.2.36", "@types/jest": "^29.5.14", "@types/node": "^20", "@typescript-eslint/eslint-plugin": "^8.26.1", @@ -85,9 +86,23 @@ "typedoc-plugin-extras": "^4.0.0", "typedoc-plugin-zod": "^1.4.1", "typescript": "^5.8.3", - "typescript-eslint": "^8.29.0" + "typescript-eslint": "^8.29.0", + "verdaccio": "^6.0.5" }, "overrides": { "typescript": "5.8.3" + }, + "nx": { + "includedScripts": [], + "targets": { + "local-registry": { + "executor": "@nx/js:verdaccio", + "options": { + "port": 4873, + "config": ".verdaccio/config.yml", + "storage": "tmp/local-registry/storage" + } + } + } } } diff --git a/packages/apps/app-dashboard/tsconfig.app.json b/packages/apps/app-dashboard/tsconfig.app.json index 9b3762555..957001b89 100644 --- a/packages/apps/app-dashboard/tsconfig.app.json +++ b/packages/apps/app-dashboard/tsconfig.app.json @@ -29,6 +29,12 @@ }, "include": ["src"], "references": [ + { + "path": "../../libs/registry-sdk/tsconfig.lib.json" + }, + { + "path": "../../libs/contracts-sdk/tsconfig.lib.json" + }, { "path": "../../libs/app-sdk/tsconfig.lib.json" } diff --git a/packages/apps/app-dashboard/tsconfig.json b/packages/apps/app-dashboard/tsconfig.json index 7a7e2e9e3..48761b50d 100644 --- a/packages/apps/app-dashboard/tsconfig.json +++ b/packages/apps/app-dashboard/tsconfig.json @@ -8,6 +8,12 @@ }, "files": [], "references": [ + { + "path": "../../libs/registry-sdk" + }, + { + "path": "../../libs/contracts-sdk" + }, { "path": "../../libs/app-sdk" }, diff --git a/packages/apps/mcp/tsconfig.app.json b/packages/apps/mcp/tsconfig.app.json index 0804fd6a7..2a9da88f4 100644 --- a/packages/apps/mcp/tsconfig.app.json +++ b/packages/apps/mcp/tsconfig.app.json @@ -26,10 +26,10 @@ ], "references": [ { - "path": "../../libs/app-sdk/tsconfig.lib.json" + "path": "../../libs/mcp-sdk/tsconfig.lib.json" }, { - "path": "../../libs/tool-sdk/tsconfig.lib.json" + "path": "../../libs/app-sdk/tsconfig.lib.json" } ] } diff --git a/packages/apps/mcp/tsconfig.json b/packages/apps/mcp/tsconfig.json index f83f385b6..8acd98f7a 100644 --- a/packages/apps/mcp/tsconfig.json +++ b/packages/apps/mcp/tsconfig.json @@ -4,10 +4,10 @@ "include": [], "references": [ { - "path": "../../libs/app-sdk" + "path": "../../libs/mcp-sdk" }, { - "path": "../../libs/tool-sdk" + "path": "../../libs/app-sdk" } ] } diff --git a/packages/apps/policy-spending-limit/tsconfig.json b/packages/apps/policy-spending-limit/tsconfig.json index 8e2c98ee0..e04815bba 100644 --- a/packages/apps/policy-spending-limit/tsconfig.json +++ b/packages/apps/policy-spending-limit/tsconfig.json @@ -6,6 +6,9 @@ { "path": "../../libs/tool-sdk" }, + { + "path": "../../libs/app-sdk" + }, { "path": "./tsconfig.lib.json" } diff --git a/packages/apps/policy-spending-limit/tsconfig.lib.json b/packages/apps/policy-spending-limit/tsconfig.lib.json index 5ada9b361..d89683ac9 100644 --- a/packages/apps/policy-spending-limit/tsconfig.lib.json +++ b/packages/apps/policy-spending-limit/tsconfig.lib.json @@ -17,6 +17,9 @@ "references": [ { "path": "../../libs/tool-sdk/tsconfig.lib.json" + }, + { + "path": "../../libs/app-sdk/tsconfig.lib.json" } ], "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] diff --git a/packages/apps/registry-backend/tsconfig.app.json b/packages/apps/registry-backend/tsconfig.app.json index 0a10741e4..2f96a730f 100644 --- a/packages/apps/registry-backend/tsconfig.app.json +++ b/packages/apps/registry-backend/tsconfig.app.json @@ -15,6 +15,9 @@ "references": [ { "path": "../../libs/registry-sdk/tsconfig.lib.json" + }, + { + "path": "../../libs/contracts-sdk/tsconfig.lib.json" } ] } diff --git a/packages/apps/registry-backend/tsconfig.json b/packages/apps/registry-backend/tsconfig.json index 94bc22849..51acf6e86 100644 --- a/packages/apps/registry-backend/tsconfig.json +++ b/packages/apps/registry-backend/tsconfig.json @@ -4,6 +4,9 @@ { "path": "../../libs/registry-sdk" }, + { + "path": "../../libs/contracts-sdk" + }, { "path": "./tsconfig.spec.json" }, diff --git a/packages/apps/tool-erc20-approval/tsconfig.json b/packages/apps/tool-erc20-approval/tsconfig.json index 8e2c98ee0..e04815bba 100644 --- a/packages/apps/tool-erc20-approval/tsconfig.json +++ b/packages/apps/tool-erc20-approval/tsconfig.json @@ -6,6 +6,9 @@ { "path": "../../libs/tool-sdk" }, + { + "path": "../../libs/app-sdk" + }, { "path": "./tsconfig.lib.json" } diff --git a/packages/apps/tool-erc20-approval/tsconfig.lib.json b/packages/apps/tool-erc20-approval/tsconfig.lib.json index 1230a2593..a32abd3a2 100644 --- a/packages/apps/tool-erc20-approval/tsconfig.lib.json +++ b/packages/apps/tool-erc20-approval/tsconfig.lib.json @@ -17,6 +17,9 @@ "references": [ { "path": "../../libs/tool-sdk/tsconfig.lib.json" + }, + { + "path": "../../libs/app-sdk/tsconfig.lib.json" } ], "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] diff --git a/packages/apps/tool-uniswap-swap/tsconfig.json b/packages/apps/tool-uniswap-swap/tsconfig.json index d33f2f7eb..62de2efbd 100644 --- a/packages/apps/tool-uniswap-swap/tsconfig.json +++ b/packages/apps/tool-uniswap-swap/tsconfig.json @@ -9,6 +9,9 @@ { "path": "../policy-spending-limit" }, + { + "path": "../../libs/app-sdk" + }, { "path": "./tsconfig.lib.json" }, diff --git a/packages/apps/tool-uniswap-swap/tsconfig.lib.json b/packages/apps/tool-uniswap-swap/tsconfig.lib.json index bb85ee0a1..b2c236e8d 100644 --- a/packages/apps/tool-uniswap-swap/tsconfig.lib.json +++ b/packages/apps/tool-uniswap-swap/tsconfig.lib.json @@ -20,6 +20,9 @@ }, { "path": "../policy-spending-limit/tsconfig.lib.json" + }, + { + "path": "../../libs/app-sdk/tsconfig.lib.json" } ], "exclude": [ diff --git a/packages/apps/toolpolicies-e2e/tsconfig.app.json b/packages/apps/toolpolicies-e2e/tsconfig.app.json index 090198ac4..856854de3 100644 --- a/packages/apps/toolpolicies-e2e/tsconfig.app.json +++ b/packages/apps/toolpolicies-e2e/tsconfig.app.json @@ -27,10 +27,10 @@ ], "references": [ { - "path": "../tool-uniswap-swap/tsconfig.lib.json" + "path": "../../libs/contracts-sdk/tsconfig.lib.json" }, { - "path": "../../libs/app-sdk/tsconfig.lib.json" + "path": "../tool-uniswap-swap/tsconfig.lib.json" }, { "path": "../../libs/tool-sdk/tsconfig.lib.json" @@ -40,6 +40,9 @@ }, { "path": "../policy-spending-limit/tsconfig.lib.json" + }, + { + "path": "../../libs/app-sdk/tsconfig.lib.json" } ] } diff --git a/packages/apps/toolpolicies-e2e/tsconfig.json b/packages/apps/toolpolicies-e2e/tsconfig.json index cebad7ff6..9a641a6ed 100644 --- a/packages/apps/toolpolicies-e2e/tsconfig.json +++ b/packages/apps/toolpolicies-e2e/tsconfig.json @@ -4,10 +4,10 @@ "include": [], "references": [ { - "path": "../tool-uniswap-swap" + "path": "../../libs/contracts-sdk" }, { - "path": "../../libs/app-sdk" + "path": "../tool-uniswap-swap" }, { "path": "../../libs/tool-sdk" @@ -18,6 +18,9 @@ { "path": "../policy-spending-limit" }, + { + "path": "../../libs/app-sdk" + }, { "path": "./tsconfig.app.json" }, diff --git a/packages/libs/app-sdk/tsconfig.json b/packages/libs/app-sdk/tsconfig.json index 8c49ee84c..7fc962b7b 100644 --- a/packages/libs/app-sdk/tsconfig.json +++ b/packages/libs/app-sdk/tsconfig.json @@ -4,6 +4,9 @@ { "path": "../tool-sdk" }, + { + "path": "../contracts-sdk" + }, { "path": "./tsconfig.lib.json" } diff --git a/packages/libs/app-sdk/tsconfig.lib.json b/packages/libs/app-sdk/tsconfig.lib.json index 0ec687320..1444580f6 100644 --- a/packages/libs/app-sdk/tsconfig.lib.json +++ b/packages/libs/app-sdk/tsconfig.lib.json @@ -25,6 +25,9 @@ "references": [ { "path": "../tool-sdk/tsconfig.lib.json" + }, + { + "path": "../contracts-sdk/tsconfig.lib.json" } ] } diff --git a/packages/libs/lit-action-bundler/README.md b/packages/libs/lit-action-bundler/README.md new file mode 100644 index 000000000..521b05855 --- /dev/null +++ b/packages/libs/lit-action-bundler/README.md @@ -0,0 +1,11 @@ +# lit-action-bundler + +This library was generated with [Nx](https://nx.dev). + +## Building + +Run `nx build lit-action-bundler` to build the library. + +## Running unit tests + +Run `nx test lit-action-bundler` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/packages/libs/lit-action-bundler/buffer.js b/packages/libs/lit-action-bundler/buffer.js new file mode 100644 index 000000000..b0553aba5 --- /dev/null +++ b/packages/libs/lit-action-bundler/buffer.js @@ -0,0 +1,5 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:buffer'; +import { default as buffer } from 'node:buffer'; +export default buffer; diff --git a/packages/libs/lit-action-bundler/eslint.config.js b/packages/libs/lit-action-bundler/eslint.config.js new file mode 100644 index 000000000..67a19db6c --- /dev/null +++ b/packages/libs/lit-action-bundler/eslint.config.js @@ -0,0 +1,4 @@ +// Incrementally enforcing some stricter rules +const strictConfig = require('../../../eslint.config.strict.js'); + +module.exports = [...strictConfig]; diff --git a/packages/libs/lit-action-bundler/jest.config.ts b/packages/libs/lit-action-bundler/jest.config.ts new file mode 100644 index 000000000..b4081f100 --- /dev/null +++ b/packages/libs/lit-action-bundler/jest.config.ts @@ -0,0 +1,8 @@ +module.exports = { + preset: '../../../jest.preset.js', + testEnvironment: 'node', + testMatch: ['**/tests/**/*.test.ts'], + collectCoverage: true, + coverageDirectory: 'coverage', + collectCoverageFrom: ['src/**/*.ts'], +}; diff --git a/packages/libs/lit-action-bundler/package.json b/packages/libs/lit-action-bundler/package.json new file mode 100644 index 000000000..5d256a6c6 --- /dev/null +++ b/packages/libs/lit-action-bundler/package.json @@ -0,0 +1,43 @@ +{ + "name": "@lit-protocol/lit-action-bundler", + "version": "0.0.1", + "description": "Bundling tools for LIT actions which provide node compat shims for Deno", + "author": "LIT Protocol", + "license": "ISC", + "access": "public", + "packageManager": "pnpm@10.7.0", + "publishConfig": { + "access": "public" + }, + "engines": { + "node": "^20.11.1", + "pnpm": "10.7.0" + }, + "main": "./dist/index.js", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + "./package.json": "./package.json", + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "default": "./dist/index.js" + } + }, + "files": [ + "dist", + "!**/*.tsbuildinfo" + ], + "dependencies": { + "@lit-protocol/auth-helpers": "^7.2.0", + "@lit-protocol/constants": "^7.2.0", + "@lit-protocol/lit-node-client": "^7.2.0", + "esbuild": "^0.25.5", + "ethers": "5.8.0", + "ipfs-only-hash": "^4.0.0", + "tslib": "^2.8.1" + }, + "devDependencies": { + "@lit-protocol/types": "^7.2.0" + } +} diff --git a/packages/libs/lit-action-bundler/project.json b/packages/libs/lit-action-bundler/project.json new file mode 100644 index 000000000..82234a64d --- /dev/null +++ b/packages/libs/lit-action-bundler/project.json @@ -0,0 +1,64 @@ +{ + "name": "lit-action-bundler", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "packages/libs/lit-action-bundler/src", + "projectType": "library", + "tags": [], + "// targets": "to see all targets run: nx show project @lit-protocol/lit-action-bundler --web", + "targets": { + "clean": {}, + "dev": { + "executor": "@nx/js:tsc", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "packages/libs/lit-action-bundler/dist", + "tsConfig": "packages/libs/lit-action-bundler/tsconfig.lib.json", + "assets": ["packages/libs/lit-action-bundler/*.md"], + "formats": ["cjs"], + "watch": true + } + }, + "typedoc:build": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "pnpm typedoc --skipErrorChecking --logLevel Verbose --options ./typedoc-configs/json.config.js" + ], + "cwd": "{projectRoot}", + "tty": true + } + }, + "typedoc:watch": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "pnpm typedoc --watch --logLevel Verbose --options ./typedoc-configs/html.config.js", + "node ./scripts/typedocServer.mjs" + ], + "cwd": "{projectRoot}", + "tty": true + } + }, + "typedoc:watch:json": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "pnpm typedoc --watch --logLevel Verbose --options ./typedoc-configs/json.config.js" + ], + "cwd": "{projectRoot}", + "tty": true + } + }, + "build": { + "executor": "@nx/js:tsc", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "packages/libs/lit-action-bundler/dist", + "main": "packages/libs/lit-action-bundler/src/index.ts", + "tsConfig": "packages/libs/lit-action-bundler/tsconfig.lib.json", + "assets": ["packages/libs/lit-action-bundler/*.md"], + "formats": ["cjs"] + } + } + } +} diff --git a/packages/libs/lit-action-bundler/src/LitNodeClient/LitNodeClientInstance.ts b/packages/libs/lit-action-bundler/src/LitNodeClient/LitNodeClientInstance.ts new file mode 100644 index 000000000..d21f96f68 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/LitNodeClient/LitNodeClientInstance.ts @@ -0,0 +1,71 @@ +import type { LIT_NETWORKS_KEYS } from '@lit-protocol/types'; + +import { LitNodeClient } from '@lit-protocol/lit-node-client'; + +export class LitNodeClientInstance { + private readonly litNodeClientInstance: LitNodeClient; + + private isConnected = false; + + private connectHandle: Promise | null = null; + + constructor({ network }: { network: LIT_NETWORKS_KEYS }) { + this.litNodeClientInstance = new LitNodeClient({ + debug: true, + litNetwork: network, + }); + } + + async connect(): Promise { + if (!this.isConnected) { + // Coalesce concurrent calls + if (this.connectHandle) { + return this.connectHandle; + } + + // Stash a handle so concurrent calls to connect are coaelesced into 1 + this.connectHandle = this.litNodeClientInstance.connect().then(() => true); + + try { + // Don't return until we know the result of pending connect attempt + await this.connectHandle; + this.isConnected = true; + } catch (e) { + // We allow multiple calls to (retries!) to `connect()` even in case where one succeeded + // if `isConnected` is false (e.g. a prior attempt failed) + this.isConnected = false; + throw e; + } finally { + this.connectHandle = null; + } + return this.isConnected; + } + + return true; + } + + async disconnect(): Promise { + if (!this.isConnected && this.connectHandle) { + // Wait for connect attempt to finish so we don't end up just re-adding the listener when it finishes. + try { + await this.connectHandle; + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (e) { + /* Ignore errors on connect; we're disconnecting! */ + } + } + + try { + await this.litNodeClientInstance.disconnect(); + } catch (e) { + /* We did our best */ + console.log('Failed to disconnect from LitNodeClientInstance.', (e as Error).message); + } finally { + this.isConnected = false; + } + } + + get litNodeClient(): LitNodeClient { + return this.litNodeClientInstance; + } +} diff --git a/packages/libs/lit-action-bundler/src/LitNodeClient/generateVincentToolSessionSigs.ts b/packages/libs/lit-action-bundler/src/LitNodeClient/generateVincentToolSessionSigs.ts new file mode 100644 index 000000000..8d54e9ee3 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/LitNodeClient/generateVincentToolSessionSigs.ts @@ -0,0 +1,47 @@ +// src/toolClient/execute/generateVincentToolSessionSigs.ts + +import type { ethers } from 'ethers'; + +import type { LitNodeClient } from '@lit-protocol/lit-node-client'; + +import { + createSiweMessageWithRecaps, + generateAuthSig, + LitActionResource, + LitPKPResource, +} from '@lit-protocol/auth-helpers'; +import { LIT_ABILITY } from '@lit-protocol/constants'; + +/** @hidden */ +export const generateVincentToolSessionSigs = async ({ + litNodeClient, + ethersSigner, +}: { + litNodeClient: LitNodeClient; + ethersSigner: ethers.Signer; +}) => { + return litNodeClient.getSessionSigs({ + chain: 'ethereum', + resourceAbilityRequests: [ + { resource: new LitPKPResource('*'), ability: LIT_ABILITY.PKPSigning }, + { resource: new LitActionResource('*'), ability: LIT_ABILITY.LitActionExecution }, + ], + authNeededCallback: async ({ resourceAbilityRequests, uri }) => { + const [walletAddress, nonce] = await Promise.all([ + ethersSigner.getAddress(), + litNodeClient.getLatestBlockhash(), + ]); + + const toSign = await createSiweMessageWithRecaps({ + uri: uri || 'http://localhost:3000', + expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), + resources: resourceAbilityRequests || [], + walletAddress, + nonce, + litNodeClient, + }); + + return await generateAuthSig({ signer: ethersSigner, toSign }); + }, + }); +}; diff --git a/packages/libs/lit-action-bundler/src/LitNodeClient/getLitNodeClient.ts b/packages/libs/lit-action-bundler/src/LitNodeClient/getLitNodeClient.ts new file mode 100644 index 000000000..8a5e197a6 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/LitNodeClient/getLitNodeClient.ts @@ -0,0 +1,32 @@ +import type { LitNodeClient } from '@lit-protocol/lit-node-client'; +import type { LIT_NETWORKS_KEYS } from '@lit-protocol/types'; + +import { LitNodeClientInstance } from './LitNodeClientInstance'; + +let instance: LitNodeClientInstance | null = null; + +export async function getLitNodeClientInstance({ + network, +}: { + network: LIT_NETWORKS_KEYS; +}): Promise { + if (instance) { + // connect() is idempotent; if we're retrying from outside, attempt to connect again + // This is a no-op if already connected 🎉 but if a prior attempt fails, it'll try again. + await instance.connect(); + return instance.litNodeClient; + } + + instance = new LitNodeClientInstance({ network }); + await instance.connect(); + + return instance.litNodeClient; +} + +export async function disconnectLitNodeClientInstance() { + if (instance) { + await instance.disconnect(); + instance = null; + } + return true; +} diff --git a/packages/libs/lit-action-bundler/src/bundleTest.spec.ts b/packages/libs/lit-action-bundler/src/bundleTest.spec.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/libs/lit-action-bundler/src/index.ts b/packages/libs/lit-action-bundler/src/index.ts new file mode 100644 index 000000000..068cc65fd --- /dev/null +++ b/packages/libs/lit-action-bundler/src/index.ts @@ -0,0 +1 @@ +export * from './lib/lit-action-bundler.js'; diff --git a/packages/libs/lit-action-bundler/src/lib/esbuild/esbuild.ts b/packages/libs/lit-action-bundler/src/lib/esbuild/esbuild.ts new file mode 100644 index 000000000..947887efd --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/esbuild/esbuild.ts @@ -0,0 +1,76 @@ +import type { BuildResult } from 'esbuild'; + +import path from 'path'; + +import { build } from 'esbuild'; + +import type { BuildLitActionOptions } from './types'; + +import { aliasFetch } from './plugins/aliasFetch'; +import { createBundledFile } from './plugins/createBundledFile'; +import { nodeBuiltinDenoShims } from './plugins/nodeBuiltinDenoShims'; +import { wrapIIFEInStringPlugin } from './plugins/wrapIIFEInString'; +import { assertOutputFiles } from './utils'; + +export function getCompatPluginCreators() { + return { + aliasFetch: aliasFetch, + nodeBuiltinDenoShims: nodeBuiltinDenoShims, + wrapIIFEInStringPlugin: wrapIIFEInStringPlugin, + createBundledFile: createBundledFile, + }; +} + +export const esbuildConfigDefaults = { + bundle: true, + minify: false, + sourcemap: false, + treeShaking: true, + metafile: true, + // inject: [path.resolve(__dirname, './plugins/node-global-shims.ts')], + platform: 'browser' as const, + write: false, + external: ['node:*'], +}; + +/** Builds a Lit Action + */ +export async function buildLitAction({ + entryPoint, + outdir, + tsconfigPath, + getLitActionHandler, +}: BuildLitActionOptions) { + const sourceDir = path.dirname(entryPoint); + + const plugins = [aliasFetch(), await nodeBuiltinDenoShims(), await wrapIIFEInStringPlugin()]; + + if (getLitActionHandler) { + plugins.push( + await createBundledFile({ + sourceDir: sourceDir, + getLitActionHandler: getLitActionHandler, + }), + ); + } + + await build({ + outdir, + tsconfig: tsconfigPath, + entryPoints: [entryPoint], + plugins, + ...esbuildConfigDefaults, + }).then((result: BuildResult) => { + assertOutputFiles(result); + + result.outputFiles.forEach((file) => { + const bytes = file.text.length; + const mbInDecimal = (bytes / 1_000_000).toFixed(4); + + const filePathArr = file.path.split('/'); + console.log( + `✅ ${filePathArr.slice(filePathArr.length - 2, filePathArr.length - 1)} - ${mbInDecimal} MB`, + ); + }); + }); +} diff --git a/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/aliasFetch.ts b/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/aliasFetch.ts new file mode 100644 index 000000000..8437083dd --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/aliasFetch.ts @@ -0,0 +1,13 @@ +import type { Plugin } from 'esbuild'; + +const DENO_FETCH_SHIM = './deno-fetch-shim.js'; + +export function aliasFetch(): Plugin { + return { + name: 'alias-fetch', + setup(build) { + build.onResolve({ filter: /^node-fetch$/ }, () => ({ path: DENO_FETCH_SHIM })); + build.onResolve({ filter: /^cross-fetch(\/.*)?$/ }, () => ({ path: DENO_FETCH_SHIM })); + }, + }; +} diff --git a/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/createBundledFile.ts b/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/createBundledFile.ts new file mode 100644 index 000000000..1ebb1c6a9 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/createBundledFile.ts @@ -0,0 +1,65 @@ +import type { Plugin } from 'esbuild'; + +import fs from 'fs'; +import path from 'path'; + +/** @ts-expect-error No types for this pkg */ +import Hash from 'ipfs-only-hash'; + +import type { GetLitActionWrapperContentFunc } from '../types'; + +import { getMetadataJsonFileContent } from '../templates'; +import { assertOutputFiles, ensureDirectoryExistence } from '../utils'; + +export async function createBundledFile({ + sourceDir, + getLitActionHandler, +}: { + sourceDir: string; + getLitActionHandler: GetLitActionWrapperContentFunc; +}): Promise { + return { + name: `create-bundled-lit-action-file`, + setup(build) { + build.initialOptions.write = false; + + build.onEnd(async (result) => { + if (result.errors.length > 0) { + console.error('Build failed with errors:', result.errors); + return; + } + + assertOutputFiles(result); + + const outputFile = result.outputFiles[0]; + const content = outputFile.text; + const ipfsCid = await Hash.of(content); + + const outputPath = path.dirname(path.resolve(outputFile.path)); + + // Calculate the relative path from the output directory to the source directory so we can codegen the wrapper + // using the passed `getLitActionHandler()` method + const relativePathToSourceDir = path.relative(outputPath, sourceDir); + + // Construct the path to the lit-action.ts file relative to the output directory + const sourcePath = path.join(relativePathToSourceDir, `lit-action`); + + // Generate the bundled source code with the computed relative path + const bundledSource = getLitActionHandler({ outputPath, ipfsCid, sourcePath }); + + // Use the output path to determine the bundled path + const bundledPath = path.join(outputPath, `bundled-lit-action.ts`); + + ensureDirectoryExistence(bundledPath); + fs.writeFileSync(bundledPath, bundledSource); + + // Write metadata JSON + // Use the directory of the generated output file + const metadataPath = path.join(outputPath, `lit-action-metadata.json`); + const metadataContent = getMetadataJsonFileContent({ ipfsCid }); + ensureDirectoryExistence(metadataPath); + fs.writeFileSync(metadataPath, metadataContent); + }); + }, + }; +} diff --git a/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/deno-fetch-shim.js b/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/deno-fetch-shim.js new file mode 100644 index 000000000..c7e1f0e7c --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/deno-fetch-shim.js @@ -0,0 +1,2 @@ +const denoFetch = (...args) => globalThis.fetch(...args); +export default denoFetch; diff --git a/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/node-global-shims.ts b/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/node-global-shims.ts new file mode 100644 index 000000000..954041388 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/node-global-shims.ts @@ -0,0 +1,8 @@ +// shims/node-globals.ts +export { Buffer } from 'node:buffer'; +export { setTimeout, clearTimeout } from 'node:timers'; +export const process = { + env: { + NODE_ENV: 'production', + }, +}; diff --git a/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/nodeBuiltinDenoShims.ts b/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/nodeBuiltinDenoShims.ts new file mode 100644 index 000000000..be322c0c5 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/nodeBuiltinDenoShims.ts @@ -0,0 +1,85 @@ +import type { Plugin } from 'esbuild'; + +import path from 'path'; + +// Path to the shims directory relative to this file +const SHIMS_DIR = '../../shims'; + +export function nodeBuiltinDenoShims(): Plugin { + return { + name: 'node-builtin-deno-shims', + setup(build) { + // Handle top-level modules + build.onResolve( + { + filter: + /^(node:)?(assert|async_hooks|console|constants|crypto|dgram|dns|events|http|http2|https|net|os|path|querystring|readline|stream|string_decoder|timers|url|util|zlib)$/, + }, + (args) => { + const moduleName = args.path.replace(/^node:/, ''); + const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${moduleName}.js`)); + return { path: shimPath }; + }, + ); + + // Handle stream submodules + build.onResolve( + { filter: /^(node:)?_stream_(duplex|passthrough|readable|transform|writable)$/ }, + (args) => { + const moduleName = args.path.replace(/^node:/, ''); + const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${moduleName}.js`)); + return { path: shimPath }; + }, + ); + + // Handle path submodules + build.onResolve({ filter: /^(node:)?path\/(posix|win32)$/ }, (args) => { + const modulePath = args.path.replace(/^node:/, ''); + const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`)); + return { path: shimPath }; + }); + + // Handle assert submodules + build.onResolve({ filter: /^(node:)?assert\/(strict)$/ }, (args) => { + const modulePath = args.path.replace(/^node:/, ''); + const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`)); + return { path: shimPath }; + }); + + // Handle readline submodules + build.onResolve({ filter: /^(node:)?readline\/(promises)$/ }, (args) => { + const modulePath = args.path.replace(/^node:/, ''); + const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`)); + return { path: shimPath }; + }); + + // Handle stream submodules + build.onResolve({ filter: /^(node:)?stream\/(consumers|promises|web)$/ }, (args) => { + const modulePath = args.path.replace(/^node:/, ''); + const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`)); + return { path: shimPath }; + }); + + // Handle timers submodules + build.onResolve({ filter: /^(node:)?timers\/(promises)$/ }, (args) => { + const modulePath = args.path.replace(/^node:/, ''); + const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`)); + return { path: shimPath }; + }); + + // Handle dns submodules + build.onResolve({ filter: /^(node:)?dns\/(promises)$/ }, (args) => { + const modulePath = args.path.replace(/^node:/, ''); + const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`)); + return { path: shimPath }; + }); + + // Handle util submodules + build.onResolve({ filter: /^(node:)?util\/(types)$/ }, (args) => { + const modulePath = args.path.replace(/^node:/, ''); + const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`)); + return { path: shimPath }; + }); + }, + }; +} diff --git a/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/wrapIIFEInString.ts b/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/wrapIIFEInString.ts new file mode 100644 index 000000000..0b82c52ee --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/esbuild/plugins/wrapIIFEInString.ts @@ -0,0 +1,40 @@ +import type { Plugin } from 'esbuild'; + +import fs from 'fs'; +import path from 'path'; + +/** @ts-expect-error No types for this pkg */ +import Hash from 'ipfs-only-hash'; + +import { getLitActionBundledCodeModuleContent } from '../templates'; +import { assertOutputFiles, ensureDirectoryExistence } from '../utils'; + +export async function wrapIIFEInStringPlugin(): Promise { + return { + name: 'wrap-iife-in-string', + setup(build) { + build.initialOptions.write = false; + + build.onEnd(async (result) => { + if (result.errors.length > 0) { + console.error('Build failed with errors:', result.errors); + return; + } + + assertOutputFiles(result); + + const outputFile = result.outputFiles[0]; + const content = outputFile.text; + const ipfsCid = await Hash.of(content); + + const wrapped = getLitActionBundledCodeModuleContent({ content, ipfsCid }); + + // Use the path from the generated output file + const outputPath = path.resolve(outputFile.path); + + ensureDirectoryExistence(outputPath); + fs.writeFileSync(outputPath, wrapped); + }); + }, + }; +} diff --git a/packages/libs/lit-action-bundler/src/lib/esbuild/templates.ts b/packages/libs/lit-action-bundler/src/lib/esbuild/templates.ts new file mode 100644 index 000000000..355611e17 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/esbuild/templates.ts @@ -0,0 +1,52 @@ +export function getLitActionBundledCodeModuleContent({ + ipfsCid, + content, +}: { + ipfsCid: string; + content: string; +}) { + return `/** +* DO NOT EDIT THIS FILE. IT IS GENERATED ON BUILD. +* @type {string} +*/ +const code = ${JSON.stringify(content)}; +module.exports = { + "code": code, + "ipfsCid": "${ipfsCid}", +}; +`; +} + +export function getMetadataJsonFileContent({ ipfsCid }: { ipfsCid: string }) { + return `{ + "ipfsCid": "${ipfsCid}" +} +`; +} + +export function getLitActionWrapperFileContest() { + return ` +// @ts-nocheck +import { vincentToolHandler } from '@lit-protocol/vincent-tool-sdk'; +import { z } from 'zod'; + +import { vincentTool } from './vincent-tool'; +import { toolParams as toolParamsSchema } from '../../../../schemas'; + +declare const toolParams: z.infer; +declare const context: { + delegatorPkpEthAddress: string; +}; + +(async () => { + const func = vincentToolHandler({ + vincentTool: vincentTool, + context: { + delegatorPkpEthAddress: context.delegatorPkpEthAddress, + }, + toolParams, + }); + await func(); +})(); +`; +} diff --git a/packages/libs/lit-action-bundler/src/lib/esbuild/types.ts b/packages/libs/lit-action-bundler/src/lib/esbuild/types.ts new file mode 100644 index 000000000..3e65eef93 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/esbuild/types.ts @@ -0,0 +1,16 @@ +export type GetLitActionWrapperContentFunc = ({ + outputPath, + ipfsCid, + sourcePath, +}: { + outputPath: string; + ipfsCid: string; + sourcePath: string; +}) => string; + +export type BuildLitActionOptions = { + entryPoint: string; + outdir: string; + tsconfigPath: string; + getLitActionHandler?: GetLitActionWrapperContentFunc; +}; diff --git a/packages/libs/lit-action-bundler/src/lib/esbuild/utils.ts b/packages/libs/lit-action-bundler/src/lib/esbuild/utils.ts new file mode 100644 index 000000000..8bd25412a --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/esbuild/utils.ts @@ -0,0 +1,19 @@ +import type { BuildResult, OutputFile } from 'esbuild'; + +import fs from 'fs'; +import path from 'path'; + +export const ensureDirectoryExistence = (filePath: string) => { + const dirname = path.dirname(filePath); + if (!fs.existsSync(dirname)) { + fs.mkdirSync(dirname, { recursive: true }); + } +}; + +export function assertOutputFiles( + result: BuildResult, +): asserts result is BuildResult & { outputFiles: OutputFile[] } { + if (!result.outputFiles) { + throw new Error('No output files found'); + } +} diff --git a/packages/libs/lit-action-bundler/src/lib/litActionHandler/Lit.d.ts b/packages/libs/lit-action-bundler/src/lib/litActionHandler/Lit.d.ts new file mode 100644 index 000000000..511d7e758 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/litActionHandler/Lit.d.ts @@ -0,0 +1,356 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import type { ethers } from 'ethers'; + +// @ts-nocheck - got this directly from the lit-assets repo +export declare namespace LitNamespace { + export namespace Actions { + /** + * Check if a given IPFS ID is permitted to sign using a given PKP tokenId + * @function isPermittedAction + * @param {Object} params + * @param {string} params.tokenId The tokenId to check + * @param {string} params.ipfsId The IPFS ID of some JS code (a lit action) + * @returns {Promise} A boolean indicating whether the IPFS ID is permitted to sign using the PKP tokenId + */ + function isPermittedAction({ + tokenId, + ipfsId, + }: { + tokenId: string; + ipfsId: string; + }): Promise; + /** + * Check if a given wallet address is permitted to sign using a given PKP tokenId + * @function isPermittedAddress + * @param {Object} params + * @param {string} params.tokenId The tokenId to check + * @param {string} params.address The wallet address to check + * @returns {Promise} A boolean indicating whether the wallet address is permitted to sign using the PKP tokenId + */ + function isPermittedAddress({ + tokenId, + address, + }: { + tokenId: string; + address: string; + }): Promise; + /** + * Check if a given auth method is permitted to sign using a given PKP tokenId + * @function isPermittedAuthMethod + * @param {Object} params + * @param {string} params.tokenId The tokenId to check + * @param {number} params.authMethodType The auth method type. This is an integer. This mapping shows the initial set but this set may be expanded over time without updating this contract: https://github.com/LIT-Protocol/LitNodeContracts/blob/main/contracts/PKPPermissions.sol#L25 + * @param {Uint8Array} params.userId The id of the auth method to check expressed as an array of unsigned 8-bit integers (a Uint8Array) + * @returns {Promise} A boolean indicating whether the auth method is permitted to sign using the PKP tokenId + */ + function isPermittedAuthMethod({ + tokenId, + authMethodType, + userId, + }: { + tokenId: string; + authMethodType: number; + userId: Uint8Array; + }): Promise; + /** + * Get the full list of actions that are permitted to sign using a given PKP tokenId + * @function getPermittedActions + * @param {Object} params + * @param {string} params.tokenId The tokenId to check + * @returns {Promise>} An array of IPFS IDs of lit actions that are permitted to sign using the PKP tokenId + */ + function getPermittedActions({ tokenId }: { tokenId: string }): Promise; + /** + * Get the full list of addresses that are permitted to sign using a given PKP tokenId + * @function getPermittedAddresses + * @param {Object} params + * @param {string} params.tokenId The tokenId to check + * @returns {Promise>} An array of addresses that are permitted to sign using the PKP tokenId + */ + function getPermittedAddresses({ tokenId }: { tokenId: string }): Promise; + /** + * Get the full list of auth methods that are permitted to sign using a given PKP tokenId + * @function getPermittedAuthMethods + * @param {Object} params + * @param {string} params.tokenId The tokenId to check + * @returns {Promise>} An array of auth methods that are permitted to sign using the PKP tokenId. Each auth method is an object with the following properties: auth_method_type, id, and user_pubkey (used for web authn, this is the pubkey of the user's authentication keypair) + */ + function getPermittedAuthMethods({ tokenId }: { tokenId: string }): Promise; + /** + * Get the permitted auth method scopes for a given PKP tokenId and auth method type + id + * @function getPermittedAuthMethodScopes + * @param {Object} params + * @param {string} params.tokenId The tokenId to check + * @param {string} params.authMethodType The auth method type to look up + * @param {Uint8Array} params.userId The id of the auth method to check expressed as an array of unsigned 8-bit integers (a Uint8Array) + * @param {number} params.maxScopeId The maximum scope id to check. This is an integer. + * @returns {Promise>} An array of booleans that define if a given scope id is turned on. The index of the array is the scope id. For example, if the array is [true, false, true], then scope ids 0 and 2 are turned on, but scope id 1 is turned off. + */ + function getPermittedAuthMethodScopes({ + tokenId, + authMethodType, + userId, + maxScopeId, + }: { + tokenId: string; + authMethodType: string; + userId: Uint8Array; + maxScopeId: number; + }): Promise; + /** + * Converts a PKP public key to a PKP token ID by hashing it with keccak256 + * @function pubkeyToTokenId + * @param {Object} params + * @param {string} params.publicKey The public key to convert + * @returns {Promise} The token ID as a string + */ + function pubkeyToTokenId({ publicKey }: { publicKey: string }): Promise; + /** + * Gets latest nonce for the given address on a supported chain + * @function getLatestNonce + * @param {Object} params + * @param {string} params.address The wallet address for getting the nonce + * @param {string} params.chain The chain of which the nonce is fetched + * @returns {Promise} The token ID as a string + */ + function getLatestNonce({ + address, + chain, + }: { + address: string; + chain: string; + }): Promise; + /** + * Ask the Lit Node to sign any data using the ECDSA Algorithm with it's private key share. The resulting signature share will be returned to the Lit JS SDK which will automatically combine the shares and give you the full signature to use. + * @function signEcdsa + * @param {Object} params + * @param {Uint8Array} params.toSign The data to sign. Should be an array of 8-bit integers. + * @param {string} params.publicKey The public key of the PKP you wish to sign with + * @param {string} params.sigName You can put any string here. This is used to identify the signature in the response by the Lit JS SDK. This is useful if you are signing multiple messages at once. When you get the final signature out, it will be in an object with this signature name as the key. + * @returns {Promise} This function will return the string "success" if it works. The signature share is returned behind the scenes to the Lit JS SDK which will automatically combine the shares and give you the full signature to use. + */ + function signEcdsa({ + toSign, + publicKey, + sigName, + }: { + toSign: Uint8Array; + publicKey: string; + sigName: string; + }): Promise; + /** + * Ask the Lit Node to sign a message using the eth_personalSign algorithm. The resulting signature share will be returned to the Lit JS SDK which will automatically combine the shares and give you the full signature to use. + * @function ethPersonalSignMessageEcdsa + * @param {Object} params + * @param {string} params.message The message to sign. Should be a string. + * @param {string} params.publicKey The public key of the PKP you wish to sign with + * @param {string} params.sigName You can put any string here. This is used to identify the signature in the response by the Lit JS SDK. This is useful if you are signing multiple messages at once. When you get the final signature out, it will be in an object with this signature name as the key. + * @returns {Promise} This function will return the string "success" if it works. The signature share is returned behind the scenes to the Lit JS SDK which will automatically combine the shares and give you the full signature to use. + */ + function ethPersonalSignMessageEcdsa({ + message, + publicKey, + sigName, + }: { + message: string; + publicKey: string; + sigName: string; + }): Promise; + /** + * Checks a condition using the Lit condition checking engine. This is the same engine that powers our Access Control product. You can use this to check any condition that you can express in our condition language. This is a powerful tool that allows you to build complex conditions that can be checked in a decentralized way. Visit https://developer.litprotocol.com and click on the "Access Control" section to learn more. + * @function checkConditions + * @param {Object} params + * @param {Array} params.conditions An array of access control condition objects + * @param {Object} params.authSig The AuthSig to use for the condition check. For example, if you were checking for NFT ownership, this AuthSig would be the signature from the NFT owner's wallet. + * @param {string} params.chain The chain this AuthSig comes from + * @returns {Promise} A boolean indicating whether the condition check passed or failed + */ + function checkConditions({ + conditions, + authSig, + chain, + }: { + conditions: any[]; + authSig: any; + chain: string; + }): Promise; + /** + * Set the response returned to the client + * @function setResponse + * @param {Object} params + * @param {string} params.response The response to send to the client. You can put any string here, like you could use JSON.stringify on a JS object and send it here. + */ + function setResponse({ response }: { response: string }): any; + /** + * Call a child Lit Action + * @function call + * @param {Object} params + * @param {string} params.ipfsId The IPFS ID of the Lit Action to call + * @param {Object=} params.params Optional parameters to pass to the child Lit Action + * @returns {Promise} The response from the child Lit Action. Note that any signatures performed by the child Lit Action will be automatically combined and returned with the parent Lit Action to the Lit JS SDK client. + */ + function call({ + ipfsId, + params, + }: { + ipfsId: string; + params?: any | undefined; + }): Promise; + /** + * Call a smart contract + * @function callContract + * @param {Object} params + * @param {string} params.chain The name of the chain to use. Check out the lit docs "Supported Blockchains" page to find the name. For example, "ethereum" + * @param {string} params.txn The RLP Encoded txn, as a hex string + * @returns {Promise} The response from calling the contract + */ + function callContract({ chain, txn }: { chain: string; txn: string }): Promise; + /** + * Convert a Uint8Array to a string. This is a re-export of this function: https://www.npmjs.com/package/uint8arrays#tostringarray-encoding--utf8 + * @function uint8arrayToString + * @param {Uint8Array} array The Uint8Array to convert + * @param {string} encoding The encoding to use. Defaults to "utf8" + * @returns {string} The string representation of the Uint8Array + */ + function uint8arrayToString(...args: any[]): string; + /** + * Convert a string to a Uint8Array. This is a re-export of this function: https://www.npmjs.com/package/uint8arrays#fromstringstring-encoding--utf8 + * @function uint8arrayFromString + * @param {string} string The string to convert + * @param {string} encoding The encoding to use. Defaults to "utf8" + * @returns {Uint8Array} The Uint8Array representation of the string + */ + function uint8arrayFromString(...args: any[]): Uint8Array; + function aesDecrypt({ symmetricKey, ciphertext }: { symmetricKey: any; ciphertext: any }): any; + /** + * Claim a key through a key identifier, the result of the claim will be added to `claim_id` + * under the `keyId` given. + * @param {Object} params + * @param {string} params.keyId user id of the claim + */ + function claimKey({ keyId }: { keyId: string }): any; + /** + * Broadcast a message to all connected clients and collect their responses + * @param {string} name The name of the broadcast + * @param {string} value The value to broadcast + * @returns {string} The collected responses as a json array + */ + function broadcastAndCollect({ name, value }: string): string; + /** + * Decrypt and combine the provided + * @param {string} accessControlConditions The access control conditions + * @param {string} ciphertext The ciphertext to decrypt + * @param {string} dataToEncryptHash The hash of the data to + @ @param {string} authSig The auth signature + * @param {string} chain The chain + * @returns {string} The combined data + */ + function decryptAndCombine({ + accessControlConditions, + ciphertext, + dataToEncryptHash, + authSig, + chain, + }: string): string; + /** + * Decrypt to a single node. + * @param {string} accessControlConditions The access control conditions + * @param {string} ciphertext The ciphertext to decrypt + * @param {string} dataToEncryptHash The hash of the data to + @ @param { any} authSig The auth signature + * @param {string} chain The chain + * @returns {string} The combined data + */ + function decryptToSingleNode({ + accessControlConditions, + ciphertext, + dataToEncryptHash, + authSig, + chain, + }: { + accessControlConditions: string; + ciphertext: string; + dataToEncryptHash: string; + chain: string; + authSig: any; + }): Promise; + /** + * @param {Uint8array} toSign the message to sign + * @param {string} publicKey the public key of the PKP + * @param {string} sigName the name of the signature + * @returns {Uint8array} The resulting signature + */ + function signAndCombineEcdsa({ toSign, publicKey, sigName }: Uint8array): Uint8array; + /** + * + * @param {bool} waitForResponse Whether to wait for a response or not - if false, the function will return immediately. + * @returns {bool} Whether the node can run the code in the next block or not. + */ + function runOnce({ waitForResponse, name }: bool, async_fn: any): bool; + /** + * + * @param {string} chain The chain to get the RPC URL for + * @returns {string} The RPC URL for the chain + */ + function getRpcUrl({ chain }: { chain: string }): Promise; + /** + * + * @param {string} accessControlConditions The access control conditions + * @param {string} to_encrypt The message to encrypt + * @returns { {ciphertext: string, dataToEncryptHash: string} } Contains two items: The ciphertext result after encryption, named "ciphertext" and the dataToEncryptHash, named "dataToEncryptHash" + */ + function encrypt({ + accessControlConditions, + to_encrypt, + }: { + accessControlConditions: string; + to_encrypt: Uint8Array; + }): { + ciphertext: string; + dataToEncryptHash: string; + }; + } + + export namespace Auth { + /** + * Array of action IPFS IDs. + * @type {Array<`Qm${string}` | string>} + */ + const actionIpfsIds: (`Qm${string}` | string)[]; + + /** + * Array of authentication method contexts. + * @type {Array<{ + * userId: string; + * appId: string; + * authMethodType: number; + * lastRetrievedAt: string; + * expiration: number; + * usedForSignSessionKeyRequest: boolean; + * }>} + */ + const authMethodContexts: { + userId: string; + appId: string; + authMethodType: number; + lastRetrievedAt: string; + expiration: number; + usedForSignSessionKeyRequest: boolean; + }[]; + + /** + * Array of resources. + * @type {Array} + */ + const resources: any[]; + + /** + * Custom authentication resource. + * @type {string | `"\\(true,${string})\\"`} + */ + const customAuthResource: string | `"\\(true,${string})\\"`; + } +} +export type EthersType = typeof ethers; + +export {}; diff --git a/packages/libs/lit-action-bundler/src/lib/litActionHandler/abortError.ts b/packages/libs/lit-action-bundler/src/lib/litActionHandler/abortError.ts new file mode 100644 index 000000000..9755ab0ad --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/litActionHandler/abortError.ts @@ -0,0 +1,9 @@ +export class AbortError extends Error { + override name = 'AbortError'; +} + +export const rethrowIfAbortError = (err: unknown) => { + if (err instanceof AbortError) { + throw err; + } +}; diff --git a/packages/libs/lit-action-bundler/src/lib/litActionHandler/litActionHandler.ts b/packages/libs/lit-action-bundler/src/lib/litActionHandler/litActionHandler.ts new file mode 100644 index 000000000..f2512b03d --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/litActionHandler/litActionHandler.ts @@ -0,0 +1,28 @@ +import type { LitNamespace /*, EthersType*/ } from './Lit'; + +import { AbortError } from './abortError'; + +declare const Lit: typeof LitNamespace; +// declare const ethers: EthersType; + +export async function litActionHandler(actionFunc: () => Promise) { + try { + const litActionResult = await actionFunc(); + // Don't re-stringify a string; we don't want to double-escape it + const response = + typeof litActionResult === 'string' ? litActionResult : JSON.stringify(litActionResult); + + Lit.Actions.setResponse({ response }); + } catch (err: unknown) { + // AbortError means exit immediately and do _NOT_ set a response + // Nested code should really only throw this in cases where using e.g. `decryptToSingleNode` + // And this execution isn't that node. + if (err instanceof AbortError) { + return; + } + + Lit.Actions.setResponse({ + response: `Error: ${err instanceof Error ? err.message : String(err)}`, + }); + } +} diff --git a/packages/libs/lit-action-bundler/src/lib/prelude.ts b/packages/libs/lit-action-bundler/src/lib/prelude.ts new file mode 100644 index 000000000..3373b0bca --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/prelude.ts @@ -0,0 +1,22 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +// @ts-nocheck +// prelude.ts +export async function installNodeGlobals() { + const { Buffer } = await import('node:buffer'); // ✅ Real source + const { process } = await import('node:process'); + + const timers = await import('node:timers'); + const { setTimeout, clearTimeout, setInterval, clearInterval, setImmediate, clearImmediate } = + timers; + + Object.assign(globalThis, { + Buffer, + process, + setTimeout, + clearTimeout, + setInterval, + clearInterval, + setImmediate, + clearImmediate, + }); +} diff --git a/packages/libs/lit-action-bundler/src/lib/shims/_stream_duplex.js b/packages/libs/lit-action-bundler/src/lib/shims/_stream_duplex.js new file mode 100644 index 000000000..3ae4510cc --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/_stream_duplex.js @@ -0,0 +1,7 @@ +/* eslint-disable */ +// @ts-nocheck +import { Duplex } from 'node:stream'; +export const from = Duplex.from; +export const fromWeb = Duplex.fromWeb; +export const toWeb = Duplex.toWeb; +export { Duplex as default }; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/_stream_passthrough.js b/packages/libs/lit-action-bundler/src/lib/shims/_stream_passthrough.js new file mode 100644 index 000000000..db8b9a2a1 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/_stream_passthrough.js @@ -0,0 +1,3 @@ +/* eslint-disable */ +// @ts-nocheck +export { PassThrough as default } from 'node:stream'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/_stream_readable.js b/packages/libs/lit-action-bundler/src/lib/shims/_stream_readable.js new file mode 100644 index 000000000..b1a0eaddc --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/_stream_readable.js @@ -0,0 +1,7 @@ +/* eslint-disable */ +// @ts-nocheck +import { Readable } from 'node:stream'; +export { Readable as default }; +export const from = Readable.from; +export const ReadableState = Readable.ReadableState; +export const _fromList = Readable._fromList; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/_stream_transform.js b/packages/libs/lit-action-bundler/src/lib/shims/_stream_transform.js new file mode 100644 index 000000000..36432c090 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/_stream_transform.js @@ -0,0 +1,3 @@ +/* eslint-disable */ +// @ts-nocheck +export { Transform as default } from 'node:stream'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/_stream_writable.js b/packages/libs/lit-action-bundler/src/lib/shims/_stream_writable.js new file mode 100644 index 000000000..bbb593378 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/_stream_writable.js @@ -0,0 +1,7 @@ +/* eslint-disable */ +// @ts-nocheck +import { Writable } from 'node:stream'; +export { Writable as default }; +export const WritableState = Writable.WritableState; +export const fromWeb = Writable.fromWeb; +export const toWeb = Writable.toWeb; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/assert.js b/packages/libs/lit-action-bundler/src/lib/shims/assert.js new file mode 100644 index 000000000..f44d2b068 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/assert.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:assert'; +export { default } from 'node:assert'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/assert/strict.js b/packages/libs/lit-action-bundler/src/lib/shims/assert/strict.js new file mode 100644 index 000000000..3294b80a2 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/assert/strict.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:assert/strict'; +export { default } from 'node:assert/strict'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/async_hooks.js b/packages/libs/lit-action-bundler/src/lib/shims/async_hooks.js new file mode 100644 index 000000000..02a9812b4 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/async_hooks.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:async_hooks'; +export { default } from 'node:async_hooks'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/console.js b/packages/libs/lit-action-bundler/src/lib/shims/console.js new file mode 100644 index 000000000..b6d4431a3 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/console.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:console'; +export { default } from 'node:console'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/constants.js b/packages/libs/lit-action-bundler/src/lib/shims/constants.js new file mode 100644 index 000000000..b60d8f270 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/constants.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:constants'; +export { default } from 'node:constants'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/crypto.js b/packages/libs/lit-action-bundler/src/lib/shims/crypto.js new file mode 100644 index 000000000..dc62c45e7 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/crypto.js @@ -0,0 +1,16 @@ +/* eslint-disable */ +// @ts-nocheck +// shims/crypto.js + +import * as _crypto from 'node:crypto'; +export * from 'node:crypto'; + +// Clone to make it mutable +const crypto = { ..._crypto }; + +// Patch in Deno-native WebCrypto +if (!('webcrypto' in crypto) && typeof globalThis.crypto === 'object') { + crypto.webcrypto = globalThis.crypto; +} + +export default crypto; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/dgram.js b/packages/libs/lit-action-bundler/src/lib/shims/dgram.js new file mode 100644 index 000000000..920e2ece2 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/dgram.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:dgram'; +export { default } from 'node:dgram'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/dns.js b/packages/libs/lit-action-bundler/src/lib/shims/dns.js new file mode 100644 index 000000000..f4a666770 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/dns.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:dns'; +export { default } from 'node:dns'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/dns/promises.js b/packages/libs/lit-action-bundler/src/lib/shims/dns/promises.js new file mode 100644 index 000000000..89bcad1f7 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/dns/promises.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:dns/promises'; +export { default } from 'node:dns/promises'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/events.js b/packages/libs/lit-action-bundler/src/lib/shims/events.js new file mode 100644 index 000000000..23c24e620 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/events.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:events'; +export { default } from 'node:events'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/http.js b/packages/libs/lit-action-bundler/src/lib/shims/http.js new file mode 100644 index 000000000..29cf5b579 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/http.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:http'; +export { default } from 'node:http'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/http2.js b/packages/libs/lit-action-bundler/src/lib/shims/http2.js new file mode 100644 index 000000000..699ce67cb --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/http2.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:http2'; +export { default } from 'node:http2'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/https.js b/packages/libs/lit-action-bundler/src/lib/shims/https.js new file mode 100644 index 000000000..6cd62aa2e --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/https.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:https'; +export { default } from 'node:https'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/net.js b/packages/libs/lit-action-bundler/src/lib/shims/net.js new file mode 100644 index 000000000..3ea0cd0d1 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/net.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:net'; +export { default } from 'node:net'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/os.js b/packages/libs/lit-action-bundler/src/lib/shims/os.js new file mode 100644 index 000000000..7d4e7b9a3 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/os.js @@ -0,0 +1,6 @@ +/* eslint-disable */ +// @ts-nocheck +// shims/os.js +export * from 'node:os'; +import * as os from 'node:os'; +export default os; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/path.js b/packages/libs/lit-action-bundler/src/lib/shims/path.js new file mode 100644 index 000000000..31858c4bf --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/path.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:path'; +export { default } from 'node:path'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/path/posix.js b/packages/libs/lit-action-bundler/src/lib/shims/path/posix.js new file mode 100644 index 000000000..651b707ea --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/path/posix.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:path/posix'; +export { default } from 'node:path/posix'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/path/win32.js b/packages/libs/lit-action-bundler/src/lib/shims/path/win32.js new file mode 100644 index 000000000..9b2ccad6d --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/path/win32.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:path/win32'; +export { default } from 'node:path/win32'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/querystring.js b/packages/libs/lit-action-bundler/src/lib/shims/querystring.js new file mode 100644 index 000000000..54f872b1e --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/querystring.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:querystring'; +export { default } from 'node:querystring'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/readline.js b/packages/libs/lit-action-bundler/src/lib/shims/readline.js new file mode 100644 index 000000000..194fe42ed --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/readline.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:readline'; +export { default } from 'node:readline'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/readline/promises.js b/packages/libs/lit-action-bundler/src/lib/shims/readline/promises.js new file mode 100644 index 000000000..15a187668 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/readline/promises.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:readline/promises'; +export { default } from 'node:readline/promises'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/stream.js b/packages/libs/lit-action-bundler/src/lib/shims/stream.js new file mode 100644 index 000000000..630845bff --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/stream.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:stream'; +export { default } from 'node:stream'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/stream/consumers.js b/packages/libs/lit-action-bundler/src/lib/shims/stream/consumers.js new file mode 100644 index 000000000..63738b828 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/stream/consumers.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:stream/consumers.mjs'; +export { default } from 'node:stream/consumers.mjs'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/stream/promises.js b/packages/libs/lit-action-bundler/src/lib/shims/stream/promises.js new file mode 100644 index 000000000..60e491224 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/stream/promises.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:stream/promises.mjs'; +export { default } from 'node:stream/promises.mjs'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/stream/web.js b/packages/libs/lit-action-bundler/src/lib/shims/stream/web.js new file mode 100644 index 000000000..b8bbc63bf --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/stream/web.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:stream/web'; +export { default } from 'node:stream/web'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/string_decoder.js b/packages/libs/lit-action-bundler/src/lib/shims/string_decoder.js new file mode 100644 index 000000000..837abd8c3 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/string_decoder.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:string_decoder'; +export { default } from 'node:string_decoder'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/timers.js b/packages/libs/lit-action-bundler/src/lib/shims/timers.js new file mode 100644 index 000000000..6c47b922a --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/timers.js @@ -0,0 +1,6 @@ +/* eslint-disable */ +// @ts-nocheck +// shims/os.js +export * from 'node:timers'; +import * as timers from 'node:timers'; +export default timers; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/timers/promises.js b/packages/libs/lit-action-bundler/src/lib/shims/timers/promises.js new file mode 100644 index 000000000..ac891ecd8 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/timers/promises.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:timers/promises'; +export { default } from 'node:timers/promises'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/url.js b/packages/libs/lit-action-bundler/src/lib/shims/url.js new file mode 100644 index 000000000..b037a8877 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/url.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:url'; +export { default } from 'node:url'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/util.js b/packages/libs/lit-action-bundler/src/lib/shims/util.js new file mode 100644 index 000000000..349da752a --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/util.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:util'; +export { default } from 'node:util'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/util/types.js b/packages/libs/lit-action-bundler/src/lib/shims/util/types.js new file mode 100644 index 000000000..1a56db41f --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/util/types.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export * from 'node:util/types'; +export { default } from 'node:util/types'; diff --git a/packages/libs/lit-action-bundler/src/lib/shims/zlib.js b/packages/libs/lit-action-bundler/src/lib/shims/zlib.js new file mode 100644 index 000000000..b04f45206 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/lib/shims/zlib.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +// @ts-nocheck +export { default } from 'node:zlib'; +export * from 'node:zlib'; diff --git a/packages/libs/lit-action-bundler/src/test-action/build.ts b/packages/libs/lit-action-bundler/src/test-action/build.ts new file mode 100644 index 000000000..2a2e84101 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/test-action/build.ts @@ -0,0 +1,8 @@ + +import { buildLitAction } from '../lib/esbuild/esbuild'; + +buildLitAction({ + entryPoint: './lit-action/lit-action.ts', + tsconfigPath: '../../tsconfig.lib.json', + outdir: './generated', +}); diff --git a/packages/libs/lit-action-bundler/src/test-action/execute.ts b/packages/libs/lit-action-bundler/src/test-action/execute.ts new file mode 100644 index 000000000..34799f95f --- /dev/null +++ b/packages/libs/lit-action-bundler/src/test-action/execute.ts @@ -0,0 +1,26 @@ + +import { ethers } from 'ethers'; + +import { generateVincentToolSessionSigs } from '../LitNodeClient/generateVincentToolSessionSigs'; +import { getLitNodeClientInstance } from '../LitNodeClient/getLitNodeClient'; +// @ts-expect-error yes, there are no types for the IIFE +import { code } from './generated/lit-action.js'; + +const signer = new ethers.Wallet(process.env['TEST_APP_MANAGER_PRIVATE_KEY']!); + +async function gogo() { + const litNodeClient = await getLitNodeClientInstance({ network: 'datil' }); + + const sessionSigs = await generateVincentToolSessionSigs({ + litNodeClient, + ethersSigner: signer, + }); + + return litNodeClient.executeJs({ + sessionSigs, + jsParams: { wat: 'beef' }, + code, + }); +} + +gogo(); diff --git a/packages/libs/lit-action-bundler/src/test-action/generated/lit-action.js b/packages/libs/lit-action-bundler/src/test-action/generated/lit-action.js new file mode 100644 index 000000000..ddd749643 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/test-action/generated/lit-action.js @@ -0,0 +1,9 @@ +/** +* DO NOT EDIT THIS FILE. IT IS GENERATED ON BUILD. +* @type {string} +*/ +const code = "\"use strict\";\n(() => {\n var __create = Object.create;\n var __defProp = Object.defineProperty;\n var __getOwnPropDesc = Object.getOwnPropertyDescriptor;\n var __getOwnPropNames = Object.getOwnPropertyNames;\n var __getProtoOf = Object.getPrototypeOf;\n var __hasOwnProp = Object.prototype.hasOwnProperty;\n var __require = /* @__PURE__ */ ((x) => typeof require !== \"undefined\" ? require : typeof Proxy !== \"undefined\" ? new Proxy(x, {\n get: (a, b) => (typeof require !== \"undefined\" ? require : a)[b]\n }) : x)(function(x) {\n if (typeof require !== \"undefined\") return require.apply(this, arguments);\n throw Error('Dynamic require of \"' + x + '\" is not supported');\n });\n var __esm = (fn, res) => function __init() {\n return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;\n };\n var __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n };\n var __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n };\n var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n ));\n\n // ../lib/shims/timers.js\n var timers_exports = {};\n __export(timers_exports, {\n default: () => timers_default\n });\n var timers_default;\n var init_timers = __esm({\n \"../lib/shims/timers.js\"() {\n \"use strict\";\n init_timers();\n init_timers();\n timers_default = timers_exports;\n }\n });\n\n // ../lib/litActionHandler/abortError.ts\n var AbortError = class extends Error {\n name = \"AbortError\";\n };\n\n // ../lib/litActionHandler/litActionHandler.ts\n async function litActionHandler(actionFunc) {\n try {\n const litActionResult = await actionFunc();\n const response = typeof litActionResult === \"string\" ? litActionResult : JSON.stringify(litActionResult);\n Lit.Actions.setResponse({ response });\n } catch (err) {\n if (err instanceof AbortError) {\n return;\n }\n Lit.Actions.setResponse({\n response: `Error: ${err instanceof Error ? err.message : String(err)}`\n });\n }\n }\n\n // ../lib/prelude.ts\n async function installNodeGlobals() {\n const { Buffer: Buffer2 } = await import(\"node:buffer\");\n const { process } = await import(\"node:process\");\n const timers = await Promise.resolve().then(() => (init_timers(), timers_exports));\n const { setTimeout, clearTimeout, setInterval, clearInterval, setImmediate, clearImmediate } = timers;\n Object.assign(globalThis, {\n Buffer: Buffer2,\n process,\n setTimeout,\n clearTimeout,\n setInterval,\n clearInterval,\n setImmediate,\n clearImmediate\n });\n }\n\n // ../lib/shims/crypto.js\n var crypto_exports = {};\n __export(crypto_exports, {\n default: () => crypto_default\n });\n var crypto = { ...crypto_exports };\n if (!(\"webcrypto\" in crypto) && typeof globalThis.crypto === \"object\") {\n crypto.webcrypto = globalThis.crypto;\n }\n var crypto_default = crypto;\n\n // ../lib/shims/os.js\n var os_exports = {};\n __export(os_exports, {\n default: () => os_default\n });\n var os_default = os_exports;\n\n // lit-action/myLitAction.ts\n async function myLitAction({ wat: wat2 }) {\n console.log(\"Hello world\");\n console.log(\"wat?\", wat2);\n console.log(\"Global Buffer\", typeof Buffer);\n console.log(\"Node os import\", typeof os_default);\n console.log(\"Node crypto import\", typeof crypto_default);\n console.log(\"Node webcrypto\", typeof crypto_default.webcrypto);\n const yellowstoneUrl = await Lit.Actions.getRpcUrl({ chain: \"yellowstone\" });\n console.log(\"Yellowstone RPC URL\", yellowstoneUrl);\n return { great: \"success, yo\" };\n }\n\n // lit-action/lit-action.ts\n (async () => {\n await installNodeGlobals();\n return await litActionHandler(() => myLitAction({ wat }));\n })();\n})();\n"; +module.exports = { + "code": code, + "ipfsCid": "QmVjhQXUHz9apnDHzjM68AffxSMW3HFZuxrcTVLxGYrVcx", +}; diff --git a/packages/libs/lit-action-bundler/src/test-action/lit-action/lit-action.ts b/packages/libs/lit-action-bundler/src/test-action/lit-action/lit-action.ts new file mode 100644 index 000000000..35f4be510 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/test-action/lit-action/lit-action.ts @@ -0,0 +1,12 @@ + +import { litActionHandler } from '../../lib/litActionHandler/litActionHandler'; +import { installNodeGlobals } from '../../lib/prelude'; +import { myLitAction } from './myLitAction'; + +declare const wat: string; + +(async () => { + await installNodeGlobals(); + + return await litActionHandler(() => myLitAction({ wat })); +})(); diff --git a/packages/libs/lit-action-bundler/src/test-action/lit-action/myLitAction.ts b/packages/libs/lit-action-bundler/src/test-action/lit-action/myLitAction.ts new file mode 100644 index 000000000..ae9a67eb8 --- /dev/null +++ b/packages/libs/lit-action-bundler/src/test-action/lit-action/myLitAction.ts @@ -0,0 +1,22 @@ +import crypto from 'crypto'; +import os from 'os'; + +import type { LitNamespace } from '../../lib/litActionHandler/Lit'; + +declare const Lit: typeof LitNamespace; + +export async function myLitAction({ wat }: { wat: string }) { + console.log('Hello world'); + + console.log('wat?', wat); + + console.log('Global Buffer', typeof Buffer); + console.log('Node os import', typeof os); + console.log('Node crypto import', typeof crypto); + console.log('Node webcrypto', typeof crypto.webcrypto); + + const yellowstoneUrl = await Lit.Actions.getRpcUrl({ chain: 'yellowstone' }); + console.log('Yellowstone RPC URL', yellowstoneUrl); + + return { great: 'success, yo' }; +} diff --git a/packages/libs/lit-action-bundler/tsconfig.json b/packages/libs/lit-action-bundler/tsconfig.json new file mode 100644 index 000000000..667a3463d --- /dev/null +++ b/packages/libs/lit-action-bundler/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/packages/libs/lit-action-bundler/tsconfig.lib.json b/packages/libs/lit-action-bundler/tsconfig.lib.json new file mode 100644 index 000000000..ebd01ed68 --- /dev/null +++ b/packages/libs/lit-action-bundler/tsconfig.lib.json @@ -0,0 +1,15 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "baseUrl": ".", + "rootDir": "src", + "outDir": "dist", + "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo", + "emitDeclarationOnly": false, + "forceConsistentCasingInFileNames": true, + "types": ["node"] + }, + "include": ["src/**/*.ts"], + "references": [], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/packages/libs/lit-action-bundler/tsconfig.spec.json b/packages/libs/lit-action-bundler/tsconfig.spec.json new file mode 100644 index 000000000..74b7e8b05 --- /dev/null +++ b/packages/libs/lit-action-bundler/tsconfig.spec.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./out-tsc/jest", + "types": ["jest", "node"], + "forceConsistentCasingInFileNames": true + }, + "include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ] +} diff --git a/packages/libs/mcp-sdk/tsconfig.json b/packages/libs/mcp-sdk/tsconfig.json index 8c49ee84c..0548fc308 100644 --- a/packages/libs/mcp-sdk/tsconfig.json +++ b/packages/libs/mcp-sdk/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../../../tsconfig.base.json", "references": [ { - "path": "../tool-sdk" + "path": "../app-sdk" }, { "path": "./tsconfig.lib.json" diff --git a/packages/libs/mcp-sdk/tsconfig.lib.json b/packages/libs/mcp-sdk/tsconfig.lib.json index 4c60457e9..4c9563cb7 100644 --- a/packages/libs/mcp-sdk/tsconfig.lib.json +++ b/packages/libs/mcp-sdk/tsconfig.lib.json @@ -23,7 +23,7 @@ "exclude": ["node_modules", "dist", "tests", "**/*.spec.ts", "**/*.test.ts"], "references": [ { - "path": "../tool-sdk/tsconfig.lib.json" + "path": "../app-sdk/tsconfig.lib.json" } ] } diff --git a/packages/libs/tool-sdk/tsconfig.json b/packages/libs/tool-sdk/tsconfig.json index f4023e39f..eb2d3076d 100644 --- a/packages/libs/tool-sdk/tsconfig.json +++ b/packages/libs/tool-sdk/tsconfig.json @@ -3,6 +3,9 @@ "files": [], "include": [], "references": [ + { + "path": "../contracts-sdk" + }, { "path": "./tsconfig.lib.json" } diff --git a/packages/libs/tool-sdk/tsconfig.lib.json b/packages/libs/tool-sdk/tsconfig.lib.json index f620a639a..46f4e591a 100644 --- a/packages/libs/tool-sdk/tsconfig.lib.json +++ b/packages/libs/tool-sdk/tsconfig.lib.json @@ -11,6 +11,10 @@ "composite": true }, "include": ["src/**/*.ts"], - "references": [], + "references": [ + { + "path": "../contracts-sdk/tsconfig.lib.json" + } + ], "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] } diff --git a/tsconfig.json b/tsconfig.json index 79e095f27..2b4dbd172 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -38,6 +38,9 @@ }, { "path": "./packages/apps/mcp" + }, + { + "path": "./packages/libs/lit-action-bundler" } ] }