Skip to content

Commit

Permalink
Merge branch 'develop' into 1506--clean-cache
Browse files Browse the repository at this point in the history
  • Loading branch information
monilpat authored Dec 28, 2024
2 parents 4084905 + 2633a5e commit 082bbc4
Show file tree
Hide file tree
Showing 17 changed files with 827 additions and 67 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -344,3 +344,6 @@ PINATA_JWT= # Pinata JWT for uploading files to IPFS
# Cronos zkEVM
CRONOSZKEVM_ADDRESS=
CRONOSZKEVM_PRIVATE_KEY=

# Fuel Ecosystem (FuelVM)
FUEL_WALLET_PRIVATE_KEY=
1 change: 1 addition & 0 deletions agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"@elizaos/plugin-twitter": "workspace:*",
"@elizaos/plugin-cronoszkevm": "workspace:*",
"@elizaos/plugin-3d-generation": "workspace:*",
"@elizaos/plugin-fuel": "workspace:*",
"readline": "1.3.0",
"ws": "8.18.0",
"yargs": "17.7.2"
Expand Down
2 changes: 2 additions & 0 deletions agent/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { confluxPlugin } from "@elizaos/plugin-conflux";
import { evmPlugin } from "@elizaos/plugin-evm";
import { storyPlugin } from "@elizaos/plugin-story";
import { flowPlugin } from "@elizaos/plugin-flow";
import { fuelPlugin } from "@elizaos/plugin-fuel";
import { imageGenerationPlugin } from "@elizaos/plugin-image-generation";
import { ThreeDGenerationPlugin } from "@elizaos/plugin-3d-generation";
import { multiversxPlugin } from "@elizaos/plugin-multiversx";
Expand Down Expand Up @@ -591,6 +592,7 @@ export async function createAgent(
getSecret(character, "TON_PRIVATE_KEY") ? tonPlugin : null,
getSecret(character, "SUI_PRIVATE_KEY") ? suiPlugin : null,
getSecret(character, "STORY_PRIVATE_KEY") ? storyPlugin : null,
getSecret(character, "FUEL_PRIVATE_KEY") ? fuelPlugin : null,
].filter(Boolean),
providers: [],
actions: [],
Expand Down
20 changes: 13 additions & 7 deletions client/tsconfig.app.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
{
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"lib": [
"ES2020",
"DOM",
"DOM.Iterable"
],
"module": "ESNext",
"skipLibCheck": true,

/* Bundler mode */
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",

/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
"@/*": [
"./src/*"
]
}
},
"include": ["src"]
}
"include": [
"src"
]
}
16 changes: 9 additions & 7 deletions client/tsconfig.node.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
{
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022",
"lib": ["ES2023"],
"lib": [
"ES2023"
],
"module": "ESNext",
"skipLibCheck": true,

/* Bundler mode */
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,

/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
"noFallthroughCasesInSwitch": true
},
"include": ["vite.config.ts"]
}
"include": [
"vite.config.ts"
]
}
31 changes: 31 additions & 0 deletions docs/docs/packages/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,37 @@ console.log("Webhook creation response:", response);
- **Validation**: Always validate input parameters to ensure compliance with expected formats and supported networks.
- **Error Handling**: Monitor logs for errors during webhook creation and adjust retry logic as needed.

### 10. Fuel Plugin (`@elizaos/plugin-fuel`)

The Fuel plugin provides an interface to the Fuel Ignition blockchain.

**Actions:**

1. `TRANSFER_FUEL_ETH` - Transfer ETH to a given Fuel address. - **Inputs**: - `toAddress` (string): The Fuel address to transfer ETH to. - `amount` (string): The amount of ETH to transfer. - **Outputs**: Confirmation message with transaction details. - **Example**:
`json
{
"toAddress": "0x8F8afB12402C9a4bD9678Bec363E51360142f8443FB171655eEd55dB298828D1",
"amount": "0.00001"
}
`
**Setup and Configuration:**

1. **Configure the Plugin**
Add the plugin to your character's configuration:

```typescript
import { fuelPlugin } from "@eliza/plugin-fuel";

const character = {
plugins: [fuelPlugin],
};
```

1. **Required Configurations**
Set the following environment variables or runtime settings:

- `FUEL_WALLET_PRIVATE_KEY`: Private key for secure transactions

### Writing Custom Plugins

Create a new plugin by implementing the Plugin interface:
Expand Down
6 changes: 6 additions & 0 deletions packages/plugin-fuel/.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-fuel/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];
23 changes: 23 additions & 0 deletions packages/plugin-fuel/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "@elizaos/plugin-fuel",
"version": "0.1.7-alpha.1",
"main": "dist/index.js",
"type": "module",
"types": "dist/index.d.ts",
"dependencies": {
"@elizaos/core": "workspace:*",
"fuels": "0.97.2",
"tsup": "8.3.5",
"vitest": "2.1.4"
},
"scripts": {
"build": "tsup --format esm --dts",
"dev": "tsup --format esm --dts --watch",
"lint": "eslint --fix --cache .",
"test": "vitest run"
},
"peerDependencies": {
"form-data": "4.0.1",
"whatwg-url": "7.1.0"
}
}
109 changes: 109 additions & 0 deletions packages/plugin-fuel/src/actions/transfer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {
Action,
composeContext,
generateObjectDeprecated,
IAgentRuntime,
ModelClass,
State,
} from "@elizaos/core";
import { initWalletProvider, WalletProvider } from "../providers/wallet";
import { bn } from "fuels";
import { transferTemplate } from "../templates";

type TransferParams = {
toAddress: string;
amount: string;
};

export class TransferAction {
constructor(private walletProvider: WalletProvider) {}

async transfer(params: TransferParams) {
try {
const { toAddress, amount } = params;
const res = await this.walletProvider.wallet.transfer(
toAddress,
bn.parseUnits(amount)
);
const tx = await res.waitForResult();
return tx;
} catch (error) {
throw new Error(`Transfer failed: ${error.message}`);
}
}
}

const buildTransferDetails = async (state: State, runtime: IAgentRuntime) => {
const context = composeContext({
state,
template: transferTemplate,
});

const transferDetails = (await generateObjectDeprecated({
runtime,
context,
modelClass: ModelClass.SMALL,
})) as TransferParams;

return transferDetails;
};

export const transferAction: Action = {
name: "transfer",
description: "Transfer Fuel ETH between addresses on Fuel Ignition",
handler: async (runtime, message, state, options, callback) => {
const walletProvider = await initWalletProvider(runtime);
const action = new TransferAction(walletProvider);

const paramOptions = await buildTransferDetails(state, runtime);

try {
const transferResp = await action.transfer(paramOptions);
if (callback) {
callback({
text: `Successfully transferred ${paramOptions.amount} ETH to ${paramOptions.toAddress}\nTransaction Hash: ${transferResp.id}`,
content: {
success: true,
hash: transferResp.id,
amount: paramOptions.amount,
recipient: paramOptions.toAddress,
},
});
}
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) => {
const privateKey = runtime.getSetting("FUEL_PRIVATE_KEY");
return typeof privateKey === "string" && privateKey.startsWith("0x");
},
examples: [
[
{
user: "assistant",
content: {
text: "I'll help you transfer 1 ETH to 0x8F8afB12402C9a4bD9678Bec363E51360142f8443FB171655eEd55dB298828D1",
action: "SEND_TOKENS",
},
},
{
user: "user",
content: {
text: "Transfer 1 ETH to 0x8F8afB12402C9a4bD9678Bec363E51360142f8443FB171655eEd55dB298828D1",
action: "SEND_TOKENS",
},
},
],
],
similes: ["TRANSFER_FUEL_ETH"],
};
14 changes: 14 additions & 0 deletions packages/plugin-fuel/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Plugin } from "@elizaos/core";
import { transferAction } from "./actions/transfer";
import { fuelWalletProvider } from "./providers/wallet";

export const fuelPlugin: Plugin = {
name: "fuel",
description: "Fuel blockchain integration plugin",
providers: [fuelWalletProvider],
evaluators: [],
services: [],
actions: [transferAction],
};

export default fuelPlugin;
44 changes: 44 additions & 0 deletions packages/plugin-fuel/src/providers/wallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { IAgentRuntime, Provider, Memory, State } from "@elizaos/core";
import { Provider as FuelProvider, Wallet, WalletUnlocked } from "fuels";

export class WalletProvider {
wallet: WalletUnlocked;

constructor(privateKey: `0x${string}`, provider: FuelProvider) {
this.wallet = Wallet.fromPrivateKey(privateKey, provider);
}

getAddress(): string {
return this.wallet.address.toB256();
}

async getBalance() {
const balance = await this.wallet.getBalance();
return balance.format();
}
}

export const initWalletProvider = async (runtime: IAgentRuntime) => {
const privateKey = runtime.getSetting("FUEL_PRIVATE_KEY");
if (!privateKey) {
throw new Error("FUEL_PRIVATE_KEY is missing");
}
const fuelProviderUrl =
runtime.getSetting("FUEL_PROVIDER_URL") ||
"https://mainnet.fuel.network/v1/graphql";

const provider = await FuelProvider.create(fuelProviderUrl);
return new WalletProvider(privateKey as `0x${string}`, provider);
};

export const fuelWalletProvider: Provider = {
async get(
runtime: IAgentRuntime,
_message: Memory,
_state?: State
): Promise<string | null> {
const walletProvider = await initWalletProvider(runtime);
const balance = await walletProvider.getBalance();
return `Fuel Wallet Address: ${walletProvider.getAddress()}\nBalance: ${balance} ETH`;
},
};
19 changes: 19 additions & 0 deletions packages/plugin-fuel/src/templates/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export const transferTemplate = `Given the recent messages and wallet information below:
{{recentMessages}}
{{walletInfo}}
Extract the following information about the requested transfer:
- Amount to transfer: Must be a string representing the amount in ETH (only number without coin symbol, e.g., "0.1")
- Recipient address: Must be a valid Fuel wallet address starting with "0x"
Respond with a JSON markdown block containing only the extracted values. All fields except 'token' are required:
\`\`\`json
{
"amount": string,
"toAddress": string,
}
\`\`\`
`;
Loading

0 comments on commit 082bbc4

Please sign in to comment.