Skip to content

Commit

Permalink
Merge pull request #2877 from AIFlowML/fix-plugin-sei-v1
Browse files Browse the repository at this point in the history
fix: plugin-sei
  • Loading branch information
shakkernerd authored Jan 28, 2025
2 parents d7be423 + 13a63d1 commit c485572
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 37 deletions.
73 changes: 54 additions & 19 deletions packages/plugin-sei/src/actions/transfer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ByteArray, formatEther, parseEther, type Hex } from "viem";
import {
elizaLogger,
Action,
composeContext,
generateObjectDeprecated,
Expand Down Expand Up @@ -63,59 +64,82 @@ export class TransferAction {

async transfer(params: TransferParams): Promise<Transaction> {
const chain = this.walletProvider.getCurrentChain()
console.log(
elizaLogger.log(
`Transferring: ${params.amount} tokens to (${params.toAddress} on ${chain.name})`
);
// let recipientAddress
let recipientAddress: `0x${string}`; // Ensure it's a valid Ethereum address

let recipientAddress
if (params.toAddress.startsWith("sei")) {
const publicClient = this.walletProvider.getEvmPublicClient();
const evmAddress = await publicClient.readContract({
address: ADDRESS_PRECOMPILE_ADDRESS,
abi: ADDRESS_PRECOMPILE_ABI,
functionName: 'getEvmAddr',
args: [params.toAddress],
})
});

if (!evmAddress || !evmAddress.startsWith("0x")) {
throw new Error(`ERROR: Recipient does not have valid EVM address. Got: ${evmAddress}`);
}

console.log(`Translated address ${params.toAddress} to EVM address ${evmAddress}`)
recipientAddress = evmAddress
elizaLogger.log(`Translated address ${params.toAddress} to EVM address ${evmAddress}`);
recipientAddress = evmAddress as `0x${string}`; // Ensure it's a valid Ethereum address
} else {
recipientAddress = params.toAddress
if (!params.toAddress.startsWith("0x")) {
throw new Error(`ERROR: Recipient address must start with '0x'. Got: ${params.toAddress}`);
}
recipientAddress = params.toAddress as `0x${string}`; // Ensure it's a valid Ethereum address
}

const walletClient = this.walletProvider.getEvmWalletClient();
if (!walletClient.account) {
throw new Error("Wallet client account is undefined");
}

try {
const hash = await walletClient.sendTransaction({
account: walletClient.account,
to: recipientAddress,
value: parseEther(params.amount),
data: params.data as Hex,

kzg: {
blobToKzgCommitment: function (_: ByteArray): ByteArray {
blobToKzgCommitment: (_: ByteArray): ByteArray => {
throw new Error("Function not implemented.");
},
computeBlobKzgProof: function (
computeBlobKzgProof: (
_blob: ByteArray,
_commitment: ByteArray
): ByteArray {
): ByteArray => {
throw new Error("Function not implemented.");
},
},
maxFeePerBlobGas: BigInt(0), // Add required property
blobs: [], // Add required property
chain: undefined,
});
// kzg: {
// blobToKzgCommitment: function (_: ByteArray): ByteArray {
// throw new Error("Function not implemented.");
// },
// computeBlobKzgProof: function (
// _blob: ByteArray,
// _commitment: ByteArray
// ): ByteArray {
// throw new Error("Function not implemented.");
// },
// },


return {
hash,
from: walletClient.account.address,
from: walletClient.account.address, // Now guaranteed to be defined
to: params.toAddress,
value: parseEther(params.amount),
data: params.data as Hex,
};

} catch (error) {
throw new Error(`Transfer failed: ${error.message}`);
}
Expand All @@ -125,7 +149,7 @@ export class TransferAction {
const buildTransferDetails = async (
state: State,
runtime: IAgentRuntime,
wp: WalletProvider
_wp: WalletProvider
): Promise<TransferParams> => {
const context = composeContext({
state,
Expand All @@ -148,25 +172,36 @@ export const transferAction: Action = {
runtime: IAgentRuntime,
message: Memory,
state: State,
_options: any,
_options: Record<string, unknown>, // Replace `any` with a safer type
callback?: HandlerCallback
) => {
if (!state) {
state = (await runtime.composeState(message)) as State;

// Create a new variable to avoid reassigning the parameter
let updatedState = state;

if (!updatedState) {
updatedState = (await runtime.composeState(message)) as State;
} else {
state = await runtime.updateRecentMessageState(state);
updatedState = await runtime.updateRecentMessageState(updatedState);
}

console.log("Transfer action handler called");
elizaLogger.debug("Transfer action handler called");
const walletProvider = await initWalletProvider(runtime);
const action = new TransferAction(walletProvider);

// Compose transfer context
const paramOptions = await buildTransferDetails(
state,
updatedState, // Use the new variable
runtime,
walletProvider
);

// // Compose transfer context
// const paramOptions = await buildTransferDetails(
// state,
// runtime,
// walletProvider
// );

try {
const transferResp = await action.transfer(paramOptions);
Expand All @@ -184,7 +219,7 @@ export const transferAction: Action = {
}
return true;
} catch (error) {
console.error("Error during token transfer:", error);
elizaLogger.error("Error during token transfer:", error);
if (callback) {
callback({
text: `Error transferring tokens: ${error.message}`,
Expand Down Expand Up @@ -217,4 +252,4 @@ export const transferAction: Action = {
],
],
similes: ["SEND_TOKENS", "TOKEN_TRANSFER", "MOVE_TOKENS", "SEND_SEI"],
};
};
2 changes: 1 addition & 1 deletion packages/plugin-sei/src/environment.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IAgentRuntime } from "@elizaos/core";
import type { IAgentRuntime } from "@elizaos/core";
import { z } from "zod";

export const seiEnvSchema = z.object({
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-sei/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Plugin } from "@elizaos/core";
import type { Plugin } from "@elizaos/core";
import { evmWalletProvider } from "./providers/wallet.ts";

import { transferAction } from "./actions/transfer";
Expand Down
61 changes: 45 additions & 16 deletions packages/plugin-sei/src/providers/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import type {
} from "viem";
import * as viemChains from "viem/chains";
import NodeCache from "node-cache";
import * as path from "path";
import * as path from "node:path";

import type { ChainWithName } from "../types";

Expand All @@ -37,7 +37,8 @@ export const seiChains = {

export class WalletProvider {
private cache: NodeCache;
private cacheKey: string = "evm/wallet";
// private cacheKey: string = "evm/wallet";
private cacheKey = "evm/wallet"; // Remove explicit type annotation
private currentChain: ChainWithName;
private CACHE_EXPIRY_SEC = 5;
account: PrivateKeyAccount;
Expand Down Expand Up @@ -97,12 +98,11 @@ export class WalletProvider {
}

async getWalletBalance(): Promise<string | null> {
const cacheKey = "seiWalletBalance_" + this.currentChain.name;
const cacheKey = `seiWalletBalance_${this.currentChain.name}`; // Fix: Use template literal
const cachedData = await this.getCachedData<string>(cacheKey);
if (cachedData) {
elizaLogger.log(
"Returning cached wallet balance for sei chain: " +
this.currentChain.name
`Returning cached wallet balance for sei chain: ${this.currentChain.name}` // Fix: Use template literal
);
return cachedData;
}
Expand All @@ -129,8 +129,15 @@ export class WalletProvider {
const cached = await this.cacheManager.get<T>(
path.join(this.cacheKey, key)
);
return cached;
return cached ?? null; // Fix: Return null if cached is undefined
}

// private async readFromCache<T>(key: string): Promise<T | null> {
// const cached = await this.cacheManager.get<T>(
// path.join(this.cacheKey, key)
// );
// return cached;
// }

private async writeToCache<T>(key: string, data: T): Promise<void> {
await this.cacheManager.set(path.join(this.cacheKey, key), data, {
Expand Down Expand Up @@ -212,28 +219,50 @@ export class WalletProvider {
return seiChain;
}
}

const genChainFromRuntime = (
runtime: IAgentRuntime
): ChainWithName => {
const sei_network = runtime.getSetting("SEI_NETWORK");
const validChains = Object.keys(seiChains)
if (typeof sei_network !== "string") { // Fix: Ensure sei_network is a string
throw new Error("SEI_NETWORK must be a string");
}

const validChains = Object.keys(seiChains);
if (!validChains.includes(sei_network)) {
throw new Error("Invalid SEI_NETWORK " + sei_network + " Must be one of " + validChains.join(", "));
throw new Error(`Invalid SEI_NETWORK ${sei_network}. Must be one of ${validChains.join(", ")}`);
}

let chain = seiChains[sei_network]
let chain = seiChains[sei_network];
const rpcurl = runtime.getSetting("SEI_RPC_URL");
if (rpcurl) {
chain = WalletProvider.genSeiChainFromName(
sei_network,
rpcurl
);
if (typeof rpcurl === "string") { // Fix: Ensure rpcurl is a string
chain = WalletProvider.genSeiChainFromName(sei_network, rpcurl);
}

return {name: sei_network, chain: chain};
return { name: sei_network, chain: chain }; // Fix: Ensure name is always a string
};

// const genChainFromRuntime = (
// runtime: IAgentRuntime
// ): ChainWithName => {
// const sei_network = runtime.getSetting("SEI_NETWORK");
// const validChains = Object.keys(seiChains)
// if (!validChains.includes(sei_network)) {
// // throw new Error("Invalid SEI_NETWORK " + sei_network + " Must be one of " + validChains.join(", "));
// throw new Error(`Invalid SEI_NETWORK ${sei_network}. Must be one of ${validChains.join(", ")}`);
// }

// let chain = seiChains[sei_network]
// const rpcurl = runtime.getSetting("SEI_RPC_URL");
// if (rpcurl) {
// chain = WalletProvider.genSeiChainFromName(
// sei_network,
// rpcurl
// );
// }

// return {name: sei_network, chain: chain};
// };

export const initWalletProvider = async (runtime: IAgentRuntime) => {

const chainData = genChainFromRuntime(runtime)
Expand Down

0 comments on commit c485572

Please sign in to comment.