Skip to content

Commit

Permalink
simple signer tool
Browse files Browse the repository at this point in the history
  • Loading branch information
awisniew207 committed Dec 20, 2024
1 parent a3dd540 commit 90133fc
Show file tree
Hide file tree
Showing 14 changed files with 549 additions and 4 deletions.
13 changes: 12 additions & 1 deletion packages/lit-agent-cli/src/commands/pkp/add-tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,18 @@ async function promptForPolicy(

// Handle each property in sequence
for (const [key, prop] of Object.entries<any>(schema.properties)) {
if (prop.type === "array") {
if (prop.type === "boolean") {
// Special handling for boolean values
const { value } = await inquirer.prompt<{ value: boolean }>([
{
type: "confirm",
name: "value",
message: prop.description,
default: prop.default,
},
]);
answers[key] = value;
} else if (prop.type === "array") {
console.log(`\n${prop.description}`);
if (prop.example) {
console.log("Examples:", JSON.stringify(prop.example, null, 2));
Expand Down
3 changes: 1 addition & 2 deletions packages/lit-agent-cli/src/core/agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ export async function processAgentRequest(
rpcUrl: chainToSubmitTxnOnRpcUrl,
chainId: parseInt(chainToSubmitTxnOnChainId),
},
publicKey: config.pkp!.publicKey!,
pkpEthAddress: config.pkp!.ethAddress!,
pkp: config.pkp,
params: {
...analysis,
user: ethersSigner.address,
Expand Down
18 changes: 18 additions & 0 deletions packages/lit-agent-cli/src/utils/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ import {
decodeSwapPolicy,
} from "lit-agent-tool-uniswap";

import {
signerMetadata,
signerLitActionDescription,
SignerPolicy,
signerPolicySchema,
encodeSignerPolicy,
decodeSignerPolicy,
} from "lit-agent-tool-signer";

export interface LitAgentTool {
name: string;
description: string;
Expand All @@ -28,5 +37,14 @@ export const getAvailableTools = (): LitAgentTool[] => {
encodePolicyFn: encodeSwapPolicy,
decodePolicyFn: decodeSwapPolicy,
},
{
name: "Signer",
description: signerLitActionDescription,
ipfsId: signerMetadata.signerLitAction.IpfsHash,
package: "lit-agent-tool-signer",
policySchema: signerPolicySchema,
encodePolicyFn: encodeSignerPolicy,
decodePolicyFn: decodeSignerPolicy,
},
];
};
1 change: 1 addition & 0 deletions packages/lit-agent-tool-signer/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PINATA_JWT=
1 change: 1 addition & 0 deletions packages/lit-agent-tool-signer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!dist/
1 change: 1 addition & 0 deletions packages/lit-agent-tool-signer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

29 changes: 29 additions & 0 deletions packages/lit-agent-tool-signer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "lit-agent-tool-signer",
"version": "0.1.0",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"scripts": {
"build": "tsc && node scripts/build.js",
"deploy": "yarn build && node scripts/deploy.js"
},
"dependencies": {
"@dotenvx/dotenvx": "^1.31.0",
"ethers": "v5",
"node-fetch": "^3.3.2"
},
"devDependencies": {
"esbuild": "^0.20.1",
"typescript": "^5.0.0"
}
}
168 changes: 168 additions & 0 deletions packages/lit-agent-tool-signer/scripts/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import * as esbuild from "esbuild";
import { fileURLToPath } from "url";
import { dirname, join } from "path";
import fs from "fs/promises";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const rootDir = join(__dirname, "..");

// Function to get the description from index.ts
async function getDescription() {
const result = await esbuild.build({
entryPoints: [join(rootDir, "src", "index.ts")],
bundle: false,
write: false,
format: "esm",
target: "esnext",
platform: "neutral",
});

const code = result.outputFiles[0].text;
const match = code.match(
/const signerLitActionDescription\s*=\s*["']([^"']+)["']/
);

if (!match) {
console.error("Code content:", code);
throw new Error("Could not find description in index.ts");
}

return match[1];
}

// Function to generate the action string
async function generateActionString() {
// Build the action file to get its contents
const result = await esbuild.build({
entryPoints: [join(rootDir, "src", "litAction.ts")],
bundle: true, // Enable bundling to resolve imports
write: false,
format: "esm",
target: "esnext",
platform: "neutral",
minify: false,
define: {
"process.env.NODE_ENV": '"production"',
},
});

const actionCode = result.outputFiles[0].text;

// Extract everything between the var assignment and the export statement
const startMatch = actionCode.indexOf("var litAction_default = ");
const endMatch = actionCode.indexOf("export {");

if (startMatch === -1 || endMatch === -1) {
console.error("Compiled code:", actionCode);
throw new Error("Could not find function boundaries in compiled code");
}

// Extract the function definition (excluding the variable assignment)
const functionBody = actionCode
.slice(startMatch + "var litAction_default = ".length, endMatch)
.trim()
.replace(/;$/, ""); // Remove trailing semicolon if present

// Create self-executing function
return `(${functionBody})();`;
}

// Function to get existing metadata
async function getExistingMetadata() {
try {
const content = await fs.readFile(
join(rootDir, "dist", "ipfs.json"),
"utf-8"
);
const metadata = JSON.parse(content);
return metadata.signerLitAction || {};
} catch (error) {
return {};
}
}

// Function to generate the index files
async function generateIndexFiles(ipfsMetadata = {}) {
const [actionString, description, existingMetadata] = await Promise.all([
generateActionString(),
getDescription(),
getExistingMetadata(),
]);

// Use existing metadata if no new metadata is provided
const metadata =
Object.keys(ipfsMetadata).length > 0
? ipfsMetadata.signerLitAction
: existingMetadata;

// Create the JavaScript content
const jsContent = `
export const signerLitActionDescription = ${JSON.stringify(description)};
export const signerLitAction = ${JSON.stringify(actionString)};
export const signerMetadata = {
signerLitAction: {
IpfsHash: ${JSON.stringify(metadata.IpfsHash || "")},
PinSize: ${metadata.PinSize || 0},
Timestamp: ${JSON.stringify(metadata.Timestamp || "")},
isDuplicate: ${metadata.isDuplicate || false},
Duration: ${metadata.Duration || 0}
}
};
export * from "./policy";
`;

// Create the TypeScript declaration content
const dtsContent = `
export type SignerMetadata = {
IpfsHash: string;
PinSize: number;
Timestamp: string;
isDuplicate: boolean;
Duration: number;
};
export type SignerLitActionString = string;
export declare const signerLitActionDescription: string;
export declare const signerLitAction: SignerLitActionString;
export declare const signerMetadata: {
signerLitAction: SignerMetadata;
};
export * from "./policy";
`;

// Write the files
await Promise.all([
fs.writeFile(join(rootDir, "dist", "index.js"), jsContent),
fs.writeFile(join(rootDir, "dist", "index.d.ts"), dtsContent),
fs.writeFile(join(rootDir, "dist", "litAction.js"), actionString),
]);
}

// Main build function
async function build() {
try {
// Ensure dist directory exists
await fs.mkdir(join(rootDir, "dist"), { recursive: true });

// Generate index files and write action string
await generateIndexFiles();

console.log("Build completed successfully");
} catch (error) {
console.error("Build failed:", error);
process.exit(1);
}
}

export { generateIndexFiles };

// Only run build if this is the main module
if (import.meta.url === `file://${process.argv[1]}`) {
build();
}
Loading

0 comments on commit 90133fc

Please sign in to comment.