-
Notifications
You must be signed in to change notification settings - Fork 4.6k
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
luna
committed
Jan 3, 2025
1 parent
76d4f42
commit bbe7cfe
Showing
12 changed files
with
3,700 additions
and
50 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
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 @@ | ||
# Plugin Cardano | ||
|
||
A plugin for handling Cardano blockchain operations, such as wallet management and transfers. | ||
|
||
## Overview and Purpose | ||
|
||
The Plugin provides a streamlined interface to interact with the Cardano blockchain. It simplifies wallet management and facilitates secure, efficient transfers while maintaining compatibility with TypeScript and modern JavaScript development practices. | ||
|
||
## Installation | ||
|
||
Install the plugin using npm: | ||
|
||
```bash | ||
npm install plugin-cardano | ||
``` | ||
|
||
## Configuration Requirements | ||
|
||
Ensure your environment is set up with the necessary configuration files and environment variables. Update the `src/enviroment.ts` file or set environment variables directly for sensitive information. | ||
|
||
### Environment Variables | ||
|
||
| Variable Name | Description | | ||
| ------------------------ | ---------------------------------------------------------------- | | ||
| `CARDANO_NETWORK` | Cardano network (Mainnet/Preprod/Preview) | | ||
| `CARDANO_PRIVATE_KEY` | Cardano mnemonics | | ||
| `CARDANO_MAESTRO_APIKEY` | [Maestro api key(daily limit)](https://dashboard.gomaestro.org/) | | ||
| `CARDANO_RPC_URL` | RPC endpoint | | ||
|
||
* `CARDANO_NETWORK` default value is `Mainnet` | ||
* `CARDANO_RPC_URL` Not supported at the moment | ||
|
||
## Usage Examples | ||
|
||
### Testing Guide Expansion | ||
|
||
Run tests using the following command: | ||
|
||
```bash | ||
pnpm run test | ||
``` | ||
|
||
The `src/tests/wallet.test.ts` file provides unit tests for wallet functionality. Add tests for additional features as needed. |
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,24 @@ | ||
{ | ||
"name": "@elizaos/plugin-cardano", | ||
"version": "0.1.7-alpha.2", | ||
"main": "dist/index.js", | ||
"type": "module", | ||
"types": "dist/index.d.ts", | ||
"dependencies": { | ||
"@elizaos/core": "workspace:*", | ||
"@elizaos/plugin-trustdb": "workspace:*", | ||
"@meshsdk/core": "^1.8.8", | ||
"bignumber": "1.1.0", | ||
"bignumber.js": "9.1.2", | ||
"node-cache": "5.1.2", | ||
"tsup": "8.3.5" | ||
}, | ||
"scripts": { | ||
"build": "tsup --format esm --dts", | ||
"dev": "tsup --format esm --dts --watch", | ||
"test": "vitest run" | ||
}, | ||
"peerDependencies": { | ||
"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,206 @@ | ||
import { | ||
elizaLogger, | ||
composeContext, | ||
Content, | ||
HandlerCallback, | ||
ModelClass, | ||
generateObject, | ||
ActionExample, | ||
Action, | ||
type IAgentRuntime, | ||
type Memory, | ||
type State, | ||
} from "@elizaos/core"; | ||
import { z } from "zod"; | ||
|
||
import { | ||
initWalletProvider, | ||
WalletProvider, | ||
nativeWalletProvider, | ||
} from "../providers/wallet"; | ||
|
||
import { generateObjectDeprecated } from "@elizaos/core"; | ||
|
||
|
||
export interface TransferContent extends Content { | ||
recipient: string; | ||
amount: string | number; | ||
} | ||
|
||
function isTransferContent(content: Content): 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": "addr_test1qq2234h0kv3rmeq0aze7t0n588l87r4erkfnux2zgm4aa8s2vj6ht7wkjr37r57y2ygjgdlyx2kf7n0ytwt9al2qw28sep0k7y", | ||
"amount": "1" | ||
} | ||
\`\`\` | ||
{{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 class TransferAction { | ||
constructor(private walletProvider: WalletProvider) { } | ||
|
||
async transfer(params: TransferContent): Promise<string> { | ||
console.log( | ||
`Transferring: ${params.amount} ada tokens to (${params.recipient})` | ||
); | ||
try { | ||
const walletClient = await this.walletProvider.sendAda(params.recipient, params.amount); | ||
return walletClient; | ||
} catch (error) { | ||
throw new Error(`Transfer failed: ${error.message}`); | ||
} | ||
} | ||
} | ||
|
||
const buildTransferDetails = async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state: State | ||
): Promise<TransferContent> => { | ||
const walletInfo = await nativeWalletProvider.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); | ||
} | ||
|
||
// Define the schema for the expected output | ||
// const transferSchema = z.object({ | ||
// recipient: z.string(), | ||
// amount: z.union([z.string(), z.number()]), | ||
// }); | ||
|
||
// Compose transfer context | ||
const transferContext = composeContext({ | ||
state, | ||
template: transferTemplate, | ||
}); | ||
|
||
// Generate transfer content with the schema | ||
// const content = await generateObjectDeprecated({ | ||
// runtime, | ||
// context: transferContext, | ||
// schema: transferSchema, | ||
// modelClass: ModelClass.SMALL, | ||
// }); | ||
const content = await generateObjectDeprecated({ | ||
runtime, | ||
context: transferContext, | ||
modelClass: ModelClass.SMALL, | ||
}); | ||
|
||
// const transferContent = content.object as TransferContent; | ||
|
||
return content; | ||
}; | ||
|
||
export default { | ||
name: "SEND_TOKEN", | ||
similes: ["SEND_TOKENS", "TOKEN_TRANSFER", "TRANSFER_TOKEN", "TRANSFER_TOKENS", "SEND_ADA"], | ||
description: "Transfer tokens from the agent's wallet to another", | ||
handler: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state: State, | ||
options: any, | ||
callback?: HandlerCallback | ||
) => { | ||
elizaLogger.log("Starting SEND_TOKEN handler..."); | ||
|
||
const transferDetails = await buildTransferDetails( | ||
runtime, | ||
message, | ||
state | ||
); | ||
|
||
// Validate transfer content | ||
if (!isTransferContent(transferDetails)) { | ||
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 walletProvider = await initWalletProvider(runtime); | ||
const action = new TransferAction(walletProvider); | ||
const hash = await action.transfer(transferDetails); | ||
|
||
if (callback) { | ||
callback({ | ||
text: `Successfully transferred ${transferDetails.amount} ADA to ${transferDetails.recipient}, Transaction: ${hash}`, | ||
content: { | ||
success: true, | ||
hash: hash, | ||
amount: transferDetails.amount, | ||
recipient: transferDetails.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; | ||
} | ||
}, | ||
template: transferTemplate, | ||
validate: async (runtime: IAgentRuntime) => { | ||
//console.log("Validating ADA transfer from user:", message.userId); | ||
return true; | ||
}, | ||
examples: [ | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "Send 1 ADA tokens to addr_test1qq2234h0kv3rmeq0aze7t0n588l87r4erkfnux2zgm4aa8s2vj6ht7wkjr37r57y2ygjgdlyx2kf7n0ytwt9al2qw28sep0k7y", | ||
}, | ||
}, | ||
{ | ||
user: "{{user2}}", | ||
content: { | ||
text: "I'll send 1 ADA tokens now...", | ||
action: "SEND_TOKEN", | ||
}, | ||
}, | ||
{ | ||
user: "{{user2}}", | ||
content: { | ||
text: "Successfully sent 1 ADA tokens to addr_test1qq2234h0kv3rmeq0aze7t0n588l87r4erkfnux2zgm4aa8s2vj6ht7wkjr37r57y2ygjgdlyx2kf7n0ytwt9al2qw28sep0k7y, Transaction: a26e4adfe3dc57b5fa8fea515cdcba1315ee8c8fe25d5864419bf2a1378b3d91", | ||
}, | ||
}, | ||
], | ||
] 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,40 @@ | ||
import { IAgentRuntime } from "@elizaos/core"; | ||
import { z } from "zod"; | ||
|
||
export const envSchema = z.object({ | ||
CARDANO_PRIVATE_KEY: z.string().min(1, "Cardano mnemonic is required"), | ||
CARDANO_RPC_URL: z.string(), | ||
CARDANO_NETWORK: z.enum(["mainnet", "preprod", "preview"]), | ||
CARDANO_MAESTRO_APIKEY: z.string(), | ||
}); | ||
|
||
export type EnvConfig = z.infer<typeof envSchema>; | ||
|
||
export async function validateEnvConfig( | ||
runtime: IAgentRuntime | ||
): Promise<EnvConfig> { | ||
try { | ||
const config = { | ||
CARDANO_PRIVATE_KEY: | ||
runtime.getSetting("CARDANO_PRIVATE_KEY") || process.env.CARDANO_PRIVATE_KEY, | ||
CARDANO_RPC_URL: | ||
runtime.getSetting("CARDANO_RPC_URL") || process.env.CARDANO_RPC_URL, | ||
CARDANO_NETWORK: | ||
runtime.getSetting("CARDANO_NETWORK") || process.env.CARDANO_NETWORK, | ||
CARDANO_MAESTRO_APIKEY: | ||
runtime.getSetting("CARDANO_MAESTRO_APIKEY") || process.env.CARDANO_MAESTRO_APIKEY | ||
}; | ||
|
||
return envSchema.parse(config); | ||
} catch (error) { | ||
if (error instanceof z.ZodError) { | ||
const errorMessages = error.errors | ||
.map((err) => `${err.path.join(".")}: ${err.message}`) | ||
.join("\n"); | ||
throw new Error( | ||
`Cardano configuration validation failed:\n${errorMessages}` | ||
); | ||
} | ||
throw error; | ||
} | ||
} |
Oops, something went wrong.