Skip to content

Commit

Permalink
Merge branch 'develop' into odi-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
odilitime authored Jan 14, 2025
2 parents 43f9e62 + 8f92573 commit f5aa3dc
Show file tree
Hide file tree
Showing 16 changed files with 5,434 additions and 1 deletion.
65 changes: 65 additions & 0 deletions packages/plugin-evm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,71 @@ Swap tokens on the same chain using LiFi:
Swap 1 ETH for USDC on Base
```

### 4. Propose

Propose a proposal to a governor on a specific chain.

- **Proposal**
- **Targets**
- **Values**
- **Calldatas**
- **Description**
- **Chain**
- **Governor**

**Example usage:**

```bash
Propose a proposal to the 0xdeadbeef00000000000000000000000000000000 governor on Ethereum to transfer 1 ETH to 0xRecipient.
```

### 5. Vote

Vote on a proposal to a governor on a specific chain.

- **Proposal ID**
- **Support**
- **Chain**
- **Governor**

**Example usage:**

```bash
Vote on the proposal with ID 1 to support the proposal on the 0xdeadbeef00000000000000000000000000000000 governor on Ethereum.
```

### 6. Queue

Queue a proposal to a governor on a specific chain.

- **Proposal**
- **Targets**
- **Values**
- **Calldatas**
- **Description**
- **Chain**
- **Governor**

**Example usage:**

```bash
Queue the proposal to the 0xdeadbeef00000000000000000000000000000000 governor on Ethereum.
```

### 7. Execute

Execute a proposal to a governor on a specific chain.

- **Proposal ID**
- **Chain**
- **Governor**

**Example usage:**

```bash
Execute the proposal with ID 1 on the 0xdeadbeef00000000000000000000000000000000 governor on Ethereum.
```

## Development

1. Clone the repository
Expand Down
130 changes: 130 additions & 0 deletions packages/plugin-evm/src/actions/gov-execute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import type { IAgentRuntime, Memory, State } from "@ai16z/eliza";
import { WalletProvider } from "../providers/wallet";
import { executeProposalTemplate } from "../templates";
import type { ExecuteProposalParams, Transaction } from "../types";
import governorArtifacts from "../contracts/artifacts/OZGovernor.json";
import {
ByteArray,
Hex,
encodeFunctionData,
getContract,
keccak256,
stringToHex,
} from "viem";
import { Chain } from "viem";
import voteTokenArtifacts from "../contracts/artifacts/VoteToken.json";

export { executeProposalTemplate };

export class ExecuteAction {
constructor(private walletProvider: WalletProvider) {
this.walletProvider = walletProvider;
}

async execute(params: ExecuteProposalParams): Promise<Transaction> {
const walletClient = this.walletProvider.getWalletClient(params.chain);

const descriptionHash = keccak256(stringToHex(params.description));

const txData = encodeFunctionData({
abi: governorArtifacts.abi,
functionName: "execute",
args: [
params.targets,
params.values,
params.calldatas,
descriptionHash,
],
});

try {
const chainConfig = this.walletProvider.getChainConfigs(
params.chain
);

// Log current block before sending transaction
const publicClient = this.walletProvider.getPublicClient(
params.chain
);

const hash = await walletClient.sendTransaction({
account: walletClient.account,
to: params.governor,
value: BigInt(0),
data: txData as Hex,
chain: chainConfig,
kzg: {
blobToKzgCommitment: function (blob: ByteArray): ByteArray {
throw new Error("Function not implemented.");
},
computeBlobKzgProof: function (
blob: ByteArray,
commitment: ByteArray
): ByteArray {
throw new Error("Function not implemented.");
},
},
});

const receipt = await publicClient.waitForTransactionReceipt({
hash,
});

return {
hash,
from: walletClient.account.address,
to: params.governor,
value: BigInt(0),
data: txData as Hex,
chainId: this.walletProvider.getChainConfigs(params.chain).id,
logs: receipt.logs,
};
} catch (error) {
throw new Error(`Vote failed: ${error.message}`);
}
}
}

export const executeAction = {
name: "execute",
description: "Execute a DAO governance proposal",
handler: async (
runtime: IAgentRuntime,
message: Memory,
state: State,
options: any,
callback?: any
) => {
try {
const privateKey = runtime.getSetting(
"EVM_PRIVATE_KEY"
) as `0x${string}`;
const walletProvider = new WalletProvider(privateKey);
const action = new ExecuteAction(walletProvider);
return await action.execute(options);
} catch (error) {
console.error("Error in vote handler:", error.message);
if (callback) {
callback({ text: `Error: ${error.message}` });
}
return false;
}
},
template: executeProposalTemplate,
validate: async (runtime: IAgentRuntime) => {
const privateKey = runtime.getSetting("EVM_PRIVATE_KEY");
return typeof privateKey === "string" && privateKey.startsWith("0x");
},
examples: [
[
{
user: "user",
content: {
text: "Execute proposal 123 on the governor at 0x1234567890123456789012345678901234567890 on Ethereum",
action: "EXECUTE_PROPOSAL",
},
},
],
],
similes: ["EXECUTE_PROPOSAL", "GOVERNANCE_EXECUTE"],
}; // TODO: add more examples
126 changes: 126 additions & 0 deletions packages/plugin-evm/src/actions/gov-propose.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import type { IAgentRuntime, Memory, State } from "@ai16z/eliza";
import { WalletProvider } from "../providers/wallet";
import { proposeTemplate, voteTemplate } from "../templates";
import type { ProposeProposalParams, Transaction } from "../types";
import governorArtifacts from "../contracts/artifacts/OZGovernor.json";
import {
ByteArray,
Hex,
encodeFunctionData,
getContract,
keccak256,
stringToHex,
} from "viem";

export { proposeTemplate };

export class ProposeAction {
constructor(private walletProvider: WalletProvider) {
this.walletProvider = walletProvider;
}

async propose(params: ProposeProposalParams): Promise<Transaction> {
const walletClient = this.walletProvider.getWalletClient(params.chain);

const txData = encodeFunctionData({
abi: governorArtifacts.abi,
functionName: "propose",
args: [
params.targets,
params.values,
params.calldatas,
params.description,
],
});

try {
const chainConfig = this.walletProvider.getChainConfigs(
params.chain
);

// Log current block before sending transaction
const publicClient = this.walletProvider.getPublicClient(
params.chain
);

const hash = await walletClient.sendTransaction({
account: walletClient.account,
to: params.governor,
value: BigInt(0),
data: txData as Hex,
chain: chainConfig,
kzg: {
blobToKzgCommitment: function (blob: ByteArray): ByteArray {
throw new Error("Function not implemented.");
},
computeBlobKzgProof: function (
blob: ByteArray,
commitment: ByteArray
): ByteArray {
throw new Error("Function not implemented.");
},
},
});

const receipt = await publicClient.waitForTransactionReceipt({
hash,
});

return {
hash,
from: walletClient.account.address,
to: params.governor,
value: BigInt(0),
data: txData as Hex,
chainId: this.walletProvider.getChainConfigs(params.chain).id,
logs: receipt.logs,
};
} catch (error) {
throw new Error(`Vote failed: ${error.message}`);
}
}
}

export const proposeAction = {
name: "propose",
description: "Execute a DAO governance proposal",
handler: async (
runtime: IAgentRuntime,
message: Memory,
state: State,
options: any,
callback?: any
) => {
try {
const privateKey = runtime.getSetting(
"EVM_PRIVATE_KEY"
) as `0x${string}`;
const walletProvider = new WalletProvider(privateKey);
const action = new ProposeAction(walletProvider);
return await action.propose(options);
} catch (error) {
console.error("Error in vote handler:", error.message);
if (callback) {
callback({ text: `Error: ${error.message}` });
}
return false;
}
},
template: proposeTemplate,
validate: async (runtime: IAgentRuntime) => {
const privateKey = runtime.getSetting("EVM_PRIVATE_KEY");
return typeof privateKey === "string" && privateKey.startsWith("0x");
},
examples: [
[
{
user: "user",
content: {
text: "Propose transferring 1e18 tokens on the governor at 0x1234567890123456789012345678901234567890 on Ethereum",
action: "PROPOSE",
},
},
],
],
similes: ["PROPOSE", "GOVERNANCE_PROPOSE"],
}; // TODO: add more examples
Loading

0 comments on commit f5aa3dc

Please sign in to comment.