Skip to content

Commit

Permalink
seperate movement functionality into its own plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Rahat-ch committed Jan 1, 2025
1 parent 451be6b commit cda69e2
Show file tree
Hide file tree
Showing 18 changed files with 820 additions and 38 deletions.
13 changes: 8 additions & 5 deletions packages/plugin-aptos/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@
"@aptos-labs/ts-sdk": "^1.26.0",
"bignumber": "1.1.0",
"bignumber.js": "9.1.2",
"node-cache": "5.1.2",
"node-cache": "5.1.2"
},
"devDependencies": {
"tsup": "8.3.5",
"vitest": "2.1.4"
"vitest": "2.1.4",
"typescript": "^5.0.0"
},
"scripts": {
"build": "tsup --format esm --dts",
"dev": "tsup --format esm --dts --watch",
"lint": "eslint --fix --cache .",
"build": "tsup",
"dev": "tsup --watch",
"lint": "eslint --fix --cache .",
"test": "vitest run"
},
"peerDependencies": {
Expand Down
10 changes: 1 addition & 9 deletions packages/plugin-aptos/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1 @@
export const APT_DECIMALS = 8;
export const MOVEMENT_NETWORK = {
MAINNET: {
fullnode: 'https://mainnet.movementnetwork.xyz/v1',
},
TESTNET: {
fullnode: 'https://aptos.testnet.bardock.movementlabs.xyz/v1',
},
};
export const APT_DECIMALS = 8;
2 changes: 1 addition & 1 deletion packages/plugin-aptos/src/enviroment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { z } from "zod";

export const aptosEnvSchema = z.object({
APTOS_PRIVATE_KEY: z.string().min(1, "Aptos private key is required"),
APTOS_NETWORK: z.enum(["mainnet", "testnet", "movement_mainnet", "movement_testnet"]),
APTOS_NETWORK: z.enum(["mainnet", "testnet"]),
});

export type AptosConfig = z.infer<typeof aptosEnvSchema>;
Expand Down
10 changes: 2 additions & 8 deletions packages/plugin-aptos/src/providers/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import {
import BigNumber from "bignumber.js";
import NodeCache from "node-cache";
import * as path from "path";
import { APT_DECIMALS, MOVEMENT_NETWORK } from "../constants";
import { isMovementNetwork, getMovementNetworkType } from "../utils";
import { APT_DECIMALS } from "../constants";

// Provider configuration
const PROVIDER_CONFIG = {
Expand Down Expand Up @@ -238,12 +237,7 @@ const walletProvider: Provider = {
try {
const aptosClient = new Aptos(
new AptosConfig({
network: isMovementNetwork(network)
? {
network: Network.CUSTOM,
fullnode: MOVEMENT_NETWORK[getMovementNetworkType(network)].fullnode
}
: { network }
network,
})
);
const provider = new WalletProvider(
Expand Down
32 changes: 17 additions & 15 deletions packages/plugin-aptos/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,27 @@ export default defineConfig({
outDir: "dist",
sourcemap: true,
clean: true,
format: ["esm"], // Ensure you're targeting CommonJS
format: ["esm"],
dts: true,
minify: false,
splitting: false,
external: [
"dotenv", // Externalize dotenv to prevent bundling
"fs", // Externalize fs to use Node.js built-in module
"path", // Externalize other built-ins if necessary
"@reflink/reflink",
"@node-llama-cpp",
"@elizaos/core",
"@aptos-labs/ts-sdk",
"bignumber",
"bignumber.js",
"node-cache",
"dotenv",
"fs",
"path",
"https",
"http",
"agentkeepalive",
"safe-buffer",
"base-x",
"bs58",
"borsh",
"@solana/buffer-layout",
"stream",
"buffer",
"querystring",
"amqplib",
// Add other modules you want to externalize
"querystring"
],
noExternal: [],
esbuildOptions(options) {
options.platform = 'node'
}
});
6 changes: 6 additions & 0 deletions packages/plugin-movement/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*

!dist/**
!package.json
!readme.md
!tsup.config.ts
3 changes: 3 additions & 0 deletions packages/plugin-movement/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import eslintGlobalConfig from "../../eslint.config.mjs";

export default [...eslintGlobalConfig];
30 changes: 30 additions & 0 deletions packages/plugin-movement/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@elizaos/plugin-movement",
"version": "0.1.0",
"main": "dist/index.js",
"type": "module",
"types": "dist/index.d.ts",
"description": "Movement Network Plugin for Eliza",
"dependencies": {
"@elizaos/core": "workspace:*",
"@aptos-labs/ts-sdk": "^1.26.0",
"bignumber": "1.1.0",
"bignumber.js": "9.1.2",
"node-cache": "5.1.2"
},
"devDependencies": {
"tsup": "8.3.5",
"vitest": "2.1.4",
"typescript": "^5.0.0"
},
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"lint": "eslint --fix --cache .",
"test": "vitest run"
},
"peerDependencies": {
"form-data": "4.0.1",
"whatwg-url": "7.1.0"
}
}
224 changes: 224 additions & 0 deletions packages/plugin-movement/src/actions/transfer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import { elizaLogger } from "@elizaos/core";
import {
ActionExample,
Content,
HandlerCallback,
IAgentRuntime,
Memory,
ModelClass,
State,
type Action,
} from "@elizaos/core";
import { composeContext } from "@elizaos/core";
import { generateObjectDeprecated } from "@elizaos/core";
import {
Account,
Aptos,
AptosConfig,
Ed25519PrivateKey,
Network,
PrivateKey,
PrivateKeyVariants,
} from "@aptos-labs/ts-sdk";
import { walletProvider } from "../providers/wallet";

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

function isTransferContent(content: any): content is TransferContent {
console.log("Content for transfer", content);
return (
typeof content.recipient === "string" &&
(typeof content.amount === "string" ||
typeof content.amount === "number")
);
}

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.`;

export default {
name: "SEND_TOKEN",
similes: [
"TRANSFER_TOKEN",
"TRANSFER_TOKENS",
"SEND_TOKENS",
"SEND_APT",
"PAY",
],
validate: async (runtime: IAgentRuntime, message: Memory) => {
console.log("Validating apt transfer from user:", message.userId);
//add custom validate logic here
/*
const adminIds = runtime.getSetting("ADMIN_USER_IDS")?.split(",") || [];
//console.log("Admin IDs from settings:", adminIds);
const isAdmin = adminIds.includes(message.userId);
if (isAdmin) {
//console.log(`Authorized transfer from user: ${message.userId}`);
return true;
}
else
{
//console.log(`Unauthorized transfer attempt from user: ${message.userId}`);
return false;
}
*/
return false;
},
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...");

const walletInfo = await walletProvider.get(runtime, message, state);
state.walletInfo = walletInfo;

// 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)) {
console.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 {
const privateKey = runtime.getSetting("APTOS_PRIVATE_KEY");
const aptosAccount = Account.fromPrivateKey({
privateKey: new Ed25519PrivateKey(
PrivateKey.formatPrivateKey(
privateKey,
PrivateKeyVariants.Ed25519
)
),
});
const network = runtime.getSetting("APTOS_NETWORK") as Network;
const aptosClient = new Aptos(
new AptosConfig({
network,
})
);

const APT_DECIMALS = 8;
const adjustedAmount = BigInt(
Number(content.amount) * Math.pow(10, APT_DECIMALS)
);
console.log(
`Transferring: ${content.amount} tokens (${adjustedAmount} base units)`
);

const tx = await aptosClient.transaction.build.simple({
sender: aptosAccount.accountAddress.toStringLong(),
data: {
function: "0x1::aptos_account::transfer",
typeArguments: [],
functionArguments: [content.recipient, adjustedAmount],
},
});
const committedTransaction =
await aptosClient.signAndSubmitTransaction({
signer: aptosAccount,
transaction: tx,
});
const executedTransaction = await aptosClient.waitForTransaction({
transactionHash: committedTransaction.hash,
});

console.log("Transfer successful:", executedTransaction.hash);

if (callback) {
callback({
text: `Successfully transferred ${content.amount} APT to ${content.recipient}, Transaction: ${executedTransaction.hash}`,
content: {
success: true,
hash: executedTransaction.hash,
amount: content.amount,
recipient: content.recipient,
},
});
}

return true;
} catch (error) {
console.error("Error during token transfer:", error);
if (callback) {
callback({
text: `Error transferring tokens: ${error.message}`,
content: { error: error.message },
});
}
return false;
}
},

examples: [
[
{
user: "{{user1}}",
content: {
text: "Send 69 APT tokens to 0x4f2e63be8e7fe287836e29cde6f3d5cbc96eefd0c0e3f3747668faa2ae7324b0",
},
},
{
user: "{{user2}}",
content: {
text: "I'll send 69 APT tokens now...",
action: "SEND_TOKEN",
},
},
{
user: "{{user2}}",
content: {
text: "Successfully sent 69 APT tokens to 0x4f2e63be8e7fe287836e29cde6f3d5cbc96eefd0c0e3f3747668faa2ae7324b0, Transaction: 0x39a8c432d9bdad993a33cc1faf2e9b58fb7dd940c0425f1d6db3997e4b4b05c0",
},
},
],
] as ActionExample[][],
} as Action;
16 changes: 16 additions & 0 deletions packages/plugin-movement/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const MOV_DECIMALS = 8;

export const MOVEMENT_NETWORKS = {
mainnet: {
fullnode: 'https://fullnode.mainnet.mov.network/v1',
chainId: '1',
name: 'Movement Mainnet'
},
bardock: {
fullnode: 'https://fullnode.testnet.mov.network/v1',
chainId: '2',
name: 'Movement Bardock Testnet'
}
} as const;

export const DEFAULT_NETWORK = 'bardock';
Loading

0 comments on commit cda69e2

Please sign in to comment.