Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POC:plugin-trikon #2570

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions packages/plugin-trikon/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@elizaos/plugin-trikon",
"version": "0.1.0-alpha.1",
"type": "module",
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"@elizaos/source": "./src/index.ts",
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
}
},
"files": [
"dist"
],
"dependencies": {
"@elizaos/core": "workspace:*"
},
"devDependencies": {
"tsup": "8.3.5",
"vitest": "2.1.4"
},
"scripts": {
"build": "tsup --format esm --dts",
"test": "vitest run"
}
}
9 changes: 9 additions & 0 deletions packages/plugin-trikon/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# @elizaos/plugin-trikon

Core Trikon plugin for Eliza OS that provides essential services and actions.

## Overview

This plugin provides functionality for Trikon integration.

## Installation
170 changes: 170 additions & 0 deletions packages/plugin-trikon/src/actions/trikon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// import type { Action } from "@elizaos/core";

// export const trikonAction: Action = {
// name: "Trikon",
// description: "A Trikon action for Trikon plugin",
// execute: async (context) => {
// // Implementation here
// return {
// success: true,
// message: "Trikon action executed successfully"
// };
// }
// };

// export default trikonAction;
import { elizaLogger } from "@elizaos/core";
import {
type ActionExample,
type Content,
type HandlerCallback,
type IAgentRuntime,
type Memory,
ModelClass,
type State,
type Action,
} from "@elizaos/core";
import { composeContext } from "@elizaos/core";
import { generateObjectDeprecated } from "@elizaos/core";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace deprecated function usage.

The generateObjectDeprecated function is marked as deprecated. Consider using the current recommended alternative.


export interface TransferContent extends Content {
recipient: string;
amount: string | number;
}

function isTransferContent(content: any): content is TransferContent {
elizaLogger.log("Content for transfer", content);
return (
typeof content.recipient === "string" &&
(typeof content.amount === "string" ||
typeof content.amount === "number")
);
}
Comment on lines +15 to +27
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Enhance transfer content validation.

The current validation is too permissive for financial transactions:

  • Add wallet address format validation
  • Add amount range and format validation
  • Remove debug logging from production code
 function isTransferContent(content: any): content is TransferContent {
-    elizaLogger.log("Content for transfer", content);
     return (
         typeof content.recipient === "string" &&
+        /^0x[a-fA-F0-9]{40}$/.test(content.recipient) &&
         (typeof content.amount === "string" ||
-            typeof content.amount === "number")
+            typeof content.amount === "number") &&
+        Number(content.amount) > 0
     );
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface TransferContent extends Content {
recipient: string;
amount: string | number;
}
function isTransferContent(content: any): content is TransferContent {
elizaLogger.log("Content for transfer", content);
return (
typeof content.recipient === "string" &&
(typeof content.amount === "string" ||
typeof content.amount === "number")
);
}
export interface TransferContent extends Content {
recipient: string;
amount: string | number;
}
function isTransferContent(content: any): content is TransferContent {
return (
typeof content.recipient === "string" &&
/^0x[a-fA-F0-9]{40}$/.test(content.recipient) &&
(typeof content.amount === "string" ||
typeof content.amount === "number") &&
Number(content.amount) > 0
);
}


const transferTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined.

Example response:
\`\`\`json
{
"recipient": "0x2badda48c062e861ef17a96a806c451fd296a49f45b272dee17f85b0e32663fd",
"amount": "1000"
}
\`\`\`

{{recentMessages}}

Given the recent messages, extract the following information about the requested token transfer:
- Recipient wallet address
- Amount to transfer

Respond with a JSON markdown block containing only the extracted values.`;
AmriteshTrikon marked this conversation as resolved.
Show resolved Hide resolved

export default {
name: "SEND_TOKEN",
similes: [
"TRANSFER_TOKEN",
"TRANSFER_TOKENS",
"SEND_TOKENS",
"SEND_TRK",
"PAY",
],
validate: async (runtime: IAgentRuntime, message: Memory) => {
elizaLogger.log("Validating trikon transfer from user:", message.userId);
return false;
},
AmriteshTrikon marked this conversation as resolved.
Show resolved Hide resolved
description: "Transfer tokens from the agent's wallet to another address",
handler: async (
runtime: IAgentRuntime,
message: Memory,
state: State,
_options: { [key: string]: unknown },
callback?: HandlerCallback
): Promise<boolean> => {
elizaLogger.log("Starting SEND_TOKEN handler...");

// Initialize or update state
if (!state) {
state = (await runtime.composeState(message)) as State;
} else {
state = await runtime.updateRecentMessageState(state);
}

// Compose transfer context
const transferContext = composeContext({
state,
template: transferTemplate,
});

// Generate transfer content
const content = await generateObjectDeprecated({
runtime,
context: transferContext,
modelClass: ModelClass.SMALL,
});

// Validate transfer content
if (!isTransferContent(content)) {
elizaLogger.error("Invalid content for TRANSFER_TOKEN action.");
if (callback) {
callback({
text: "Unable to process transfer request. Invalid content provided.",
content: { error: "Invalid transfer content" },
});
}
return false;
}

try {
// TODO: Implement Trikon-specific transfer logic here
elizaLogger.log(
`Would transfer ${content.amount} tokens to ${content.recipient}`
);

Comment on lines +102 to +107
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Implement transfer logic with proper security measures.

The TODO indicates missing core functionality. Ensure implementation includes:

  • Input sanitization
  • Transaction amount limits
  • Rate limiting
  • Proper error handling

Would you like me to provide a secure implementation template?

if (callback) {
callback({
text: `Transfer simulation successful for ${content.amount} TRK to ${content.recipient}`,
content: {
success: true,
amount: content.amount,
recipient: content.recipient,
},
});
}

return true;
} catch (error) {
elizaLogger.error("Error during token transfer:", error);
if (callback) {
callback({
text: `Error transferring tokens: ${error.message}`,
content: { error: error.message },
});
}
return false;
}
AmriteshTrikon marked this conversation as resolved.
Show resolved Hide resolved
},

examples: [
[
{
user: "{{user1}}",
content: {
text: "Send 100 TRK tokens to 0xa385EEeFB533703dc4c811CB6Eb44cac2C14af07",
},
},
{
user: "{{user2}}",
content: {
text: "I'll send 100 TRK tokens now...",
action: "SEND_TOKEN",
},
},
{
user: "{{user2}}",
content: {
text: "Successfully sent 100 TRK tokens to 0xa385EEeFB533703dc4c811CB6Eb44cac2C14af07",
},
},
],
] as ActionExample[][],
} as Action;
5 changes: 5 additions & 0 deletions packages/plugin-trikon/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from "./plugins/trikonPlugin";
export * from "./actions/trikon";
export * from "./providers/wallet";

export { default } from "./plugins/trikonPlugin";
15 changes: 15 additions & 0 deletions packages/plugin-trikon/src/plugins/trikonPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { Plugin } from "@elizaos/core";
import transferAction from "../actions/trikon";
import walletProvider from "../providers/wallet";

export const trikonPlugin: Plugin = {
name: "trikon",
description: "Trikon Plugin for Eliza",
actions: [transferAction],
providers: [walletProvider],
evaluators: [],
services: [],
clients: [],
};

export default trikonPlugin;
62 changes: 62 additions & 0 deletions packages/plugin-trikon/src/providers/wallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { elizaLogger, type Provider } from "@elizaos/core";

export interface WalletProvider {
address: string;
balance: string;
getBalance(): Promise<string>;
getAddress(): Promise<string>;
}

export const walletProvider: Provider = {
get: async (context) => {
elizaLogger.log("Initializing Trikon wallet provider...");

try {
// TODO: Implement Trikon-specific wallet logic here
const wallet: WalletProvider = {
address: "0xa385EEeFB533703dc4c811CB6Eb44cac2C14af07",
balance: "0",
AmriteshTrikon marked this conversation as resolved.
Show resolved Hide resolved

async getBalance(): Promise<string> {
try {
// TODO: Implement actual balance fetching
elizaLogger.log("Fetching Trikon wallet balance...");
return this.balance;
} catch (error) {
elizaLogger.error("Error fetching balance:", error);
throw error;
AmriteshTrikon marked this conversation as resolved.
Show resolved Hide resolved
}
},

async getAddress(): Promise<string> {
try {
// TODO: Implement actual address fetching
elizaLogger.log("Fetching Trikon wallet address...");
return this.address;
} catch (error) {
elizaLogger.error("Error fetching address:", error);
throw error;
}
}
};

elizaLogger.log("Trikon wallet provider initialized successfully");
return wallet;

} catch (error) {
elizaLogger.error("Error initializing Trikon wallet provider:", error);
throw error;
}
},
// get: async () => {
// elizaLogger.log("Getting Trikon wallet provider...");
// return {
// address: "0xa385EEeFB533703dc4c811CB6Eb44cac2C14af07",
// balance: "0",
// getBalance: async () => "0",
// getAddress: async () => "0xa385EEeFB533703dc4c811CB6Eb44cac2C14af07"
// };
// }
};

export default walletProvider;
10 changes: 10 additions & 0 deletions packages/plugin-trikon/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../core/tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": [
"src/**/*.ts"
]
}
26 changes: 26 additions & 0 deletions packages/plugin-trikon/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { defineConfig } from "tsup";

export default defineConfig({
entry: ["src/index.ts"],
outDir: "dist",
sourcemap: true,
clean: true,
format: ["esm"],
external: [
"dotenv",
"fs",
"path",
"@reflink/reflink",
"@node-llama-cpp",
AmriteshTrikon marked this conversation as resolved.
Show resolved Hide resolved
"https",
"http",
"agentkeepalive",
"safe-buffer",
"base-x",
"bs58",
"borsh",
"stream",
"buffer",
"querystring"
],
});
Loading
Loading