Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chroe: optimize and fix test issues of plugin-bnb #2

Merged
merged 1 commit into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/plugin-bnb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ Request testnet tokens from the faucet. You could request any of the supported t
- **Token**(Optional)
- **Recipient Address**

The recipient address must maintain a minimum balance of 0.002 BNB on BSC Mainnet to qualify.
The faucet is rate-limited. One claim is allowed per IP address within a 24-hour period. And the recipient address must maintain a minimum balance of 0.002 BNB on BSC Mainnet to qualify.

**Example usage:**

Expand Down
85 changes: 48 additions & 37 deletions packages/plugin-bnb/src/actions/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import {
} from "@elizaos/core";
import { parseEther, getContract, Address, parseUnits } from "viem";

import { initWalletProvider, WalletProvider } from "../providers/wallet";
import {
bnbWalletProvider,
initWalletProvider,
WalletProvider,
} from "../providers/wallet";
import { bridgeTemplate } from "../templates";
import {
ERC20Abi,
Expand Down Expand Up @@ -97,13 +101,28 @@ export class BridgeAction {

// check ERC20 allowance
if (!nativeTokenBridge) {
await this.checkTokenAllowance(
const diff = await this.walletProvider.checkERC20Allowance(
params.fromChain,
params.fromToken!,
fromAddress,
this.L1_BRIDGE_ADDRESS,
amount
);
if (diff > 0n) {
elizaLogger.log(
`Increasing ERC20 allowance for L1 bridge. ${diff} more needed`
);
const txHash =
await this.walletProvider.increaseERC20Allowance(
params.fromChain,
params.fromToken!,
this.L1_BRIDGE_ADDRESS,
diff
);
await publicClient.waitForTransactionReceipt({
hash: txHash,
});
}
}

if (selfBridge && nativeTokenBridge) {
Expand Down Expand Up @@ -189,13 +208,28 @@ export class BridgeAction {

// check ERC20 allowance
if (!nativeTokenBridge) {
await this.checkTokenAllowance(
const diff = await this.walletProvider.checkERC20Allowance(
params.fromChain,
params.fromToken!,
fromAddress,
this.L2_BRIDGE_ADDRESS,
amount
);
if (diff > 0n) {
elizaLogger.log(
`Increasing ERC20 allowance for L2 bridge. ${diff} more needed`
);
const txHash =
await this.walletProvider.increaseERC20Allowance(
params.fromChain,
params.fromToken!,
this.L2_BRIDGE_ADDRESS,
diff
);
await publicClient.waitForTransactionReceipt({
hash: txHash,
});
}
}

if (selfBridge && nativeTokenBridge) {
Expand Down Expand Up @@ -268,6 +302,15 @@ export class BridgeAction {
throw new Error("Unsupported bridge direction");
}

if (!resp.txHash || resp.txHash == "0x") {
throw new Error("Get transaction hash failed");
}

// wait for the transaction to be confirmed
await publicClient.waitForTransactionReceipt({
hash: resp.txHash,
});

return resp;
} catch (error) {
throw error;
Expand All @@ -286,44 +329,11 @@ export class BridgeAction {
if (params.fromChain == "bsc" && params.toChain == "opBNB") {
if (params.fromToken && !params.toToken) {
throw new Error(
"token address on opBNB is required for bridge ERC20 from BSC to opBNB"
"token address on opBNB is required when bridging ERC20 from BSC to opBNB"
);
}
}
}

async checkTokenAllowance(
chain: SupportedChain,
token: Address,
owner: Address,
spender: Address,
amount: bigint
) {
const publicClient = this.walletProvider.getPublicClient(chain);
const allowance = await publicClient.readContract({
address: token,
abi: ERC20Abi,
functionName: "allowance",
args: [owner, spender],
});

if (allowance < amount) {
elizaLogger.log("Increasing allowance for ERC20 bridge");
const walletClient = this.walletProvider.getWalletClient(chain);
const { request } = await publicClient.simulateContract({
account: walletClient.account,
address: token,
abi: ERC20Abi,
functionName: "increaseAllowance",
args: [spender, amount - allowance],
});

const hash = await walletClient.writeContract(request);
await publicClient.waitForTransactionReceipt({
hash,
});
}
}
}

// NOTE: The bridge action only supports bridge funds between BSC and opBNB for now. We may adding stargate support later.
Expand All @@ -345,6 +355,7 @@ export const bridgeAction = {
} else {
state = await runtime.updateRecentMessageState(state);
}
state.walletInfo = await bnbWalletProvider.get(runtime, message, state);

// Compose bridge context
const bridgeContext = composeContext({
Expand Down
28 changes: 14 additions & 14 deletions packages/plugin-bnb/src/actions/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import {
type State,
} from "@elizaos/core";
import solc from "solc";
import { Abi, Address, formatEther, formatUnits, parseUnits } from "viem";
import { initWalletProvider, WalletProvider } from "../providers/wallet";
import { Abi, Address, formatEther, parseUnits } from "viem";
import {
bnbWalletProvider,
initWalletProvider,
WalletProvider,
} from "../providers/wallet";
import { ercContractTemplate } from "../templates";
import {
IDeployERC1155Params,
Expand Down Expand Up @@ -174,16 +178,6 @@ export class DeployAction {

this.walletProvider.switchChain(chain);

// check wallet balance
const publicClient = this.walletProvider.getPublicClient(chain);
const balance = await publicClient.getBalance({
address: this.walletProvider.getAddress(),
});
elizaLogger.debug(`Wallet balance: ${formatEther(balance)} BNB`);
if (balance === 0n) {
elizaLogger.error("Wallet has no BNB for gas fees");
}

const chainConfig = this.walletProvider.getChainConfigs(chain);
const walletClient = this.walletProvider.getWalletClient(chain);
const hash = await walletClient.deployContract({
Expand All @@ -195,6 +189,7 @@ export class DeployAction {
});

elizaLogger.debug("Waiting for deployment transaction...", hash);
const publicClient = this.walletProvider.getPublicClient(chain);
const receipt = await publicClient.waitForTransactionReceipt({
hash,
});
Expand Down Expand Up @@ -223,6 +218,7 @@ export const deployAction = {
} else {
state = await runtime.updateRecentMessageState(state);
}
state.walletInfo = await bnbWalletProvider.get(runtime, message, state);

// Compose context
const context = composeContext({
Expand Down Expand Up @@ -302,15 +298,19 @@ export const deployAction = {
action: "DEPLOY_TOKEN",
},
},
],
[
{
user: "{{user2}}",
user: "{{user1}}",
content: {
text: "Deploy an ERC721 NFT contract with name 'MyNFT', symbol 'MNFT', baseURI 'https://my-nft-base-uri.com'",
action: "DEPLOY_TOKEN",
},
},
],
[
{
user: "{{user3}}",
user: "{{user1}}",
content: {
text: "Deploy an ERC1155 contract with name 'My1155', baseURI 'https://my-1155-base-uri.com'",
action: "DEPLOY_TOKEN",
Expand Down
7 changes: 6 additions & 1 deletion packages/plugin-bnb/src/actions/faucet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import WebSocket, { ClientOptions } from "ws";

import { faucetTemplate } from "../templates";
import { FaucetResponse, type FaucetParams } from "../types";
import { initWalletProvider, WalletProvider } from "../providers/wallet";
import {
bnbWalletProvider,
initWalletProvider,
WalletProvider,
} from "../providers/wallet";

export { faucetTemplate };

Expand Down Expand Up @@ -135,6 +139,7 @@ export const faucetAction = {
} else {
state = await runtime.updateRecentMessageState(state);
}
state.walletInfo = await bnbWalletProvider.get(runtime, message, state);

// Compose faucet context
const faucetContext = composeContext({
Expand Down
81 changes: 58 additions & 23 deletions packages/plugin-bnb/src/actions/getBalance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,21 @@ import {
type Memory,
type State,
} from "@elizaos/core";
import {
getTokens,
getToken,
getTokenBalance,
getTokenBalances,
ChainId,
} from "@lifi/sdk";
import { getToken, getTokens, getTokenBalances, ChainId } from "@lifi/sdk";

import { initWalletProvider, WalletProvider } from "../providers/wallet";
import {
bnbWalletProvider,
initWalletProvider,
WalletProvider,
} from "../providers/wallet";
import { getBalanceTemplate } from "../templates";
import type { Balance, GetBalanceParams, GetBalanceResponse } from "../types";
import { Address, formatEther, formatUnits } from "viem";
import type {
Balance,
GetBalanceParams,
GetBalanceResponse,
SupportedChain,
} from "../types";
import { Address, erc20Abi, formatEther, formatUnits } from "viem";

export { getBalanceTemplate };

Expand Down Expand Up @@ -48,17 +51,30 @@ export class GetBalanceAction {

// If no specific token is requested, get all token balances
if (!token) {
this.walletProvider.configureLiFiSdk(chain);
const balances = await this.getTokenBalances(chainId, address!);
resp.balances = balances;
} else {
// If specific token is requested and it's not the native token
if (token !== nativeSymbol) {
const balance = await this.getERC20TokenBalance(
chainId,
address!,
token!
);
resp.balances = [{ token: token!, balance }];
if (token.toLowerCase() !== nativeSymbol.toLowerCase()) {
let balance: string;
if (token.startsWith("0x")) {
balance = await this.getERC20TokenBalance(
chain,
address!,
token as `0x${string}`
);
} else {
this.walletProvider.configureLiFiSdk(chain);
const tokenInfo = await getToken(chainId, token);
balance = await this.getERC20TokenBalance(
chain,
address!,
tokenInfo.address as `0x${string}`
);
}

resp.balances = [{ token, balance }];
} else {
// If native token is requested
const nativeBalanceWei = await this.walletProvider
Expand All @@ -80,13 +96,26 @@ export class GetBalanceAction {
}

async getERC20TokenBalance(
chainId: ChainId,
chain: SupportedChain,
address: Address,
tokenSymbol: string
tokenAddress: Address
): Promise<string> {
const token = await getToken(chainId, tokenSymbol);
const tokenBalance = await getTokenBalance(address, token);
return formatUnits(tokenBalance?.amount ?? 0n, token.decimals);
const publicClient = this.walletProvider.getPublicClient(chain);

const balance = await publicClient.readContract({
address: tokenAddress,
abi: erc20Abi,
functionName: "balanceOf",
args: [address],
});

const decimals = await publicClient.readContract({
address: tokenAddress,
abi: erc20Abi,
functionName: "decimals",
});

return formatUnits(balance, decimals);
}

async getTokenBalances(
Expand Down Expand Up @@ -115,7 +144,12 @@ export class GetBalanceAction {
}

if (params.chain != "bsc") {
throw new Error("Only BSC mainnet is supported");
// if token contract address is not provided, only BSC mainnet is supported
if (!(params.token && params.token.startsWith("0x"))) {
throw new Error(
"If token contract address is not provided, only BSC mainnet is supported"
);
}
}
}
}
Expand All @@ -138,6 +172,7 @@ export const getBalanceAction = {
} else {
state = await runtime.updateRecentMessageState(state);
}
state.walletInfo = await bnbWalletProvider.get(runtime, message, state);

// Compose swap context
const getBalanceContext = composeContext({
Expand Down
Loading