forked from elizaOS/eliza
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
915 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
* | ||
|
||
!dist/** | ||
!package.json | ||
!readme.md | ||
!tsup.config.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import eslintGlobalConfig from "../../eslint.config.mjs"; | ||
|
||
export default [...eslintGlobalConfig]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# @elizaos/plugin-movement | ||
|
||
Movement Network plugin for Eliza OS. This plugin enables Movement Network blockchain functionality for your Eliza agent. | ||
|
||
## Features | ||
|
||
- Send MOVE tokens | ||
- Check wallet balances | ||
- Support for Movement Network transactions | ||
|
||
## Installation | ||
|
||
```bash | ||
pnpm add @elizaos/plugin-movement | ||
``` | ||
|
||
## Instructions | ||
|
||
1. First, ensure you have a Movement Network wallet and private key. | ||
|
||
2. Add the Movement plugin to your character's configuration: | ||
|
||
```json | ||
{ | ||
"name": "Movement Agent", | ||
"plugins": ["@elizaos/plugin-movement"], | ||
"settings": { | ||
"secrets": { | ||
"MOVEMENT_PRIVATE_KEY": "your_private_key_here", | ||
"MOVEMENT_NETWORK": "bardock" | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Set up your environment variables in the `.env` file: | ||
|
||
```bash | ||
MOVEMENT_PRIVATE_KEY=your_private_key_here | ||
MOVEMENT_NETWORK=bardock | ||
``` | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
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"; | ||
import { MOVEMENT_NETWORK_CONFIG, MOVE_DECIMALS, MOVEMENT_EXPLORER_URL } from "../constants"; | ||
|
||
export interface TransferContent extends Content { | ||
recipient: string; | ||
amount: string | number; | ||
} | ||
|
||
function isTransferContent(content: any): content is TransferContent { | ||
elizaLogger.debug("Validating transfer content:", content); | ||
return ( | ||
typeof content.recipient === "string" && | ||
(typeof content.amount === "string" || | ||
typeof content.amount === "number") | ||
); | ||
} | ||
|
||
const transferTemplate = `You are processing a token transfer request. Extract the recipient address and amount from the message. | ||
Example request: "can you send 1 move to 0x123..." | ||
Example response: | ||
\`\`\`json | ||
{ | ||
"recipient": "0x123...", | ||
"amount": "1" | ||
} | ||
\`\`\` | ||
Rules: | ||
1. The recipient address always starts with "0x" | ||
2. The amount is typically a number less than 100 | ||
3. Return exact values found in the message | ||
Recent messages: | ||
{{recentMessages}} | ||
Extract and return ONLY the following in a JSON block: | ||
- recipient: The wallet address starting with 0x | ||
- amount: The number of tokens to send | ||
Return ONLY the JSON block with these two fields.`; | ||
|
||
export default { | ||
name: "TRANSFER_MOVE", | ||
similes: [ | ||
"SEND_TOKEN", | ||
"TRANSFER_TOKEN", | ||
"TRANSFER_TOKENS", | ||
"SEND_TOKENS", | ||
"SEND_MOVE", | ||
"PAY", | ||
], | ||
triggers: [ | ||
"send move", | ||
"send 1 move", | ||
"transfer move", | ||
"send token", | ||
"transfer token", | ||
"can you send", | ||
"please send", | ||
"send" | ||
], | ||
shouldHandle: (message: Memory) => { | ||
const text = message.content?.text?.toLowerCase() || ""; | ||
return text.includes("send") && text.includes("move") && text.includes("0x"); | ||
}, | ||
validate: async (runtime: IAgentRuntime, message: Memory) => { | ||
elizaLogger.debug("Starting transfer validation for user:", message.userId); | ||
elizaLogger.debug("Message text:", message.content?.text); | ||
return true; // Let the handler do the validation | ||
}, | ||
priority: 1000, // High priority for transfer actions | ||
description: "Transfer Move 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.debug("Starting TRANSFER_MOVE handler..."); | ||
elizaLogger.debug("Message:", { | ||
text: message.content?.text, | ||
userId: message.userId, | ||
action: message.content?.action | ||
}); | ||
|
||
try { | ||
const privateKey = runtime.getSetting("MOVEMENT_PRIVATE_KEY"); | ||
elizaLogger.debug("Got private key:", privateKey ? "Present" : "Missing"); | ||
|
||
const network = runtime.getSetting("MOVEMENT_NETWORK"); | ||
elizaLogger.debug("Network config:", network); | ||
elizaLogger.debug("Available networks:", Object.keys(MOVEMENT_NETWORK_CONFIG)); | ||
|
||
const movementAccount = Account.fromPrivateKey({ | ||
privateKey: new Ed25519PrivateKey( | ||
PrivateKey.formatPrivateKey( | ||
privateKey, | ||
PrivateKeyVariants.Ed25519 | ||
) | ||
), | ||
}); | ||
elizaLogger.debug("Created Movement account:", movementAccount.accountAddress.toStringLong()); | ||
|
||
const aptosClient = new Aptos( | ||
new AptosConfig({ | ||
network: Network.CUSTOM, | ||
fullnode: MOVEMENT_NETWORK_CONFIG[network].fullnode | ||
}) | ||
); | ||
elizaLogger.debug("Created Aptos client with network:", MOVEMENT_NETWORK_CONFIG[network].fullnode); | ||
|
||
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; | ||
} | ||
|
||
const adjustedAmount = BigInt( | ||
Number(content.amount) * Math.pow(10, MOVE_DECIMALS) | ||
); | ||
console.log( | ||
`Transferring: ${content.amount} tokens (${adjustedAmount} base units)` | ||
); | ||
|
||
const tx = await aptosClient.transaction.build.simple({ | ||
sender: movementAccount.accountAddress.toStringLong(), | ||
data: { | ||
function: "0x1::aptos_account::transfer", | ||
typeArguments: [], | ||
functionArguments: [content.recipient, adjustedAmount], | ||
}, | ||
}); | ||
const committedTransaction = | ||
await aptosClient.signAndSubmitTransaction({ | ||
signer: movementAccount, | ||
transaction: tx, | ||
}); | ||
const executedTransaction = await aptosClient.waitForTransaction({ | ||
transactionHash: committedTransaction.hash, | ||
}); | ||
|
||
const explorerUrl = `${MOVEMENT_EXPLORER_URL}/${executedTransaction.hash}?network=${MOVEMENT_NETWORK_CONFIG[network].explorerNetwork}`; | ||
elizaLogger.debug("Transfer successful:", { | ||
hash: executedTransaction.hash, | ||
amount: content.amount, | ||
recipient: content.recipient, | ||
explorerUrl | ||
}); | ||
|
||
if (callback) { | ||
callback({ | ||
text: `Successfully transferred ${content.amount} MOVE to ${content.recipient}\nTransaction: ${executedTransaction.hash}\nView on Explorer: ${explorerUrl}`, | ||
content: { | ||
success: true, | ||
hash: executedTransaction.hash, | ||
amount: content.amount, | ||
recipient: content.recipient, | ||
explorerUrl | ||
}, | ||
}); | ||
} | ||
|
||
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: "can you send 1 move to 0xa07ab7d3739dc793f9d538f7d7163705176ba59f7a8c994a07357a3a7d97d843", | ||
}, | ||
}, | ||
{ | ||
user: "{{user2}}", | ||
content: { | ||
text: "I'll help you transfer 1 Move token...", | ||
action: "TRANSFER_MOVE", | ||
}, | ||
}, | ||
], | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "send 1 move to 0xa07ab7d3739dc793f9d538f7d7163705176ba59f7a8c994a07357a3a7d97d843", | ||
}, | ||
}, | ||
{ | ||
user: "{{user2}}", | ||
content: { | ||
text: "Processing Move token transfer...", | ||
action: "TRANSFER_MOVE", | ||
}, | ||
}, | ||
] | ||
] as ActionExample[][], | ||
} as Action; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
export const MOVE_DECIMALS = 8; | ||
|
||
export const MOVEMENT_NETWORK_CONFIG = { | ||
mainnet: { | ||
fullnode: 'https://mainnet.movementnetwork.xyz/v1', | ||
chainId: '126', | ||
name: 'Movement Mainnet', | ||
explorerNetwork: 'mainnet' | ||
}, | ||
bardock: { | ||
fullnode: 'https://aptos.testnet.bardock.movementlabs.xyz/v1', | ||
chainId: '250', | ||
name: 'Movement Bardock Testnet', | ||
explorerNetwork: 'bardock+testnet' | ||
} | ||
} as const; | ||
|
||
export const DEFAULT_NETWORK = 'bardock'; | ||
export const MOVEMENT_EXPLORER_URL = 'https://explorer.movementnetwork.xyz/txn'; |
Oops, something went wrong.