Skip to content

Commit

Permalink
Merge pull request #2207 from cygaar/agw_integration
Browse files Browse the repository at this point in the history
feat: Add AGW support to the Abstract plugin
  • Loading branch information
shakkernerd authored Jan 13, 2025
2 parents 4420a7a + 66c595d commit 00be64c
Show file tree
Hide file tree
Showing 3 changed files with 1,193 additions and 1,084 deletions.
1 change: 1 addition & 0 deletions packages/plugin-abstract/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"dist"
],
"dependencies": {
"@abstract-foundation/agw-client": "^0.1.7",
"@elizaos/core": "workspace:*",
"tsup": "^8.3.5",
"viem": "2.22.2"
Expand Down
135 changes: 100 additions & 35 deletions packages/plugin-abstract/src/actions/transferAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { validateAbstractConfig } from "../environment";

import {
Address,
createWalletClient,
erc20Abi,
http,
parseEther,
Expand All @@ -25,6 +24,7 @@ import {
} from "viem";
import { abstractTestnet, mainnet } from "viem/chains";
import { normalize } from "viem/ens";
import { createAbstractClient } from "@abstract-foundation/agw-client";
import { z } from "zod";
import { ValidateContext } from "../utils";
import { ETH_ADDRESS, ERC20_OVERRIDE_INFO } from "../constants";
Expand All @@ -39,12 +39,14 @@ const TransferSchema = z.object({
tokenAddress: z.string(),
recipient: z.string(),
amount: z.string(),
useAGW: z.boolean(),
});

export interface TransferContent extends Content {
tokenAddress: string;
recipient: string;
amount: string | number;
useAGW: boolean;
}

const transferTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined.
Expand All @@ -58,16 +60,21 @@ Example response:
{
"tokenAddress": "0x5A7d6b2F92C77FAD6CCaBd7EE0624E64907Eaf3E",
"recipient": "0xCCa8009f5e09F8C5dB63cb0031052F9CB635Af62",
"amount": "1000"
"amount": "1000",
"useAGW": true
}
\`\`\`
{{recentMessages}}
User message:
"{{currentMessage}}"
Given the recent messages, extract the following information about the requested token transfer:
Given the message, extract the following information about the requested token transfer:
- Token contract address
- Recipient wallet address
- Amount to transfer
- Whether to use Abstract Global Wallet aka AGW
If the user did not specify "global wallet", "AGW", "agw", or "abstract global wallet" in their message, set useAGW to false, otherwise set it to true.
Respond with a JSON markdown block containing only the extracted values.`;

Expand Down Expand Up @@ -104,6 +111,7 @@ export const transferAction: Action = {
}

// Compose transfer context
state.currentMessage = `${state.recentMessagesData[1].content.text}`;
const transferContext = composeContext({
state,
template: transferTemplate,
Expand Down Expand Up @@ -138,7 +146,7 @@ export const transferAction: Action = {

// Validate transfer content
if (!ValidateContext.transferAction(content)) {
console.error("Invalid content for TRANSFER_TOKEN action.");
elizaLogger.error("Invalid content for TRANSFER_TOKEN action.");
if (callback) {
callback({
text: "Unable to process transfer request. Invalid content provided.",
Expand All @@ -150,40 +158,76 @@ export const transferAction: Action = {

try {
const account = useGetAccount(runtime);
const walletClient = useGetWalletClient();

let hash;

// Check if the token is native
if (
content.tokenAddress.toLowerCase() !== ETH_ADDRESS.toLowerCase()
) {
// Convert amount to proper token decimals
const tokenInfo =
ERC20_OVERRIDE_INFO[content.tokenAddress.toLowerCase()];
const decimals = tokenInfo?.decimals ?? 18; // Default to 18 decimals if not specified
const tokenAmount = parseUnits(
content.amount.toString(),
decimals
);

// Execute ERC20 transfer
hash = await walletClient.writeContract({
account,
if (content.useAGW) {
const abstractClient = await createAbstractClient({
chain: abstractTestnet,
address: content.tokenAddress as Address,
abi: erc20Abi,
functionName: "transfer",
args: [content.recipient as Address, tokenAmount],
signer: account,
});

// Handle AGW transfer based on token type
if (
content.tokenAddress.toLowerCase() !==
ETH_ADDRESS.toLowerCase()
) {
const tokenInfo =
ERC20_OVERRIDE_INFO[content.tokenAddress.toLowerCase()];
const decimals = tokenInfo?.decimals ?? 18;
const tokenAmount = parseUnits(
content.amount.toString(),
decimals
);

// @ts-ignore - will fix later
hash = await abstractClient.writeContract({
chain: abstractTestnet,
address: content.tokenAddress as Address,
abi: erc20Abi,
functionName: "transfer",
args: [content.recipient as Address, tokenAmount],
});
} else {
// @ts-ignore
hash = await abstractClient.sendTransaction({
chain: abstractTestnet,
to: content.recipient as Address,
value: parseEther(content.amount.toString()),
kzg: undefined,
});
}
} else {
hash = await walletClient.sendTransaction({
account: account,
chain: abstractTestnet,
to: content.recipient as Address,
value: parseEther(content.amount.toString()),
kzg: undefined,
});
const walletClient = useGetWalletClient();

// Handle regular wallet transfer based on token type
if (
content.tokenAddress.toLowerCase() !==
ETH_ADDRESS.toLowerCase()
) {
const tokenInfo =
ERC20_OVERRIDE_INFO[content.tokenAddress.toLowerCase()];
const decimals = tokenInfo?.decimals ?? 18;
const tokenAmount = parseUnits(
content.amount.toString(),
decimals
);

hash = await walletClient.writeContract({
account,
chain: abstractTestnet,
address: content.tokenAddress as Address,
abi: erc20Abi,
functionName: "transfer",
args: [content.recipient as Address, tokenAmount],
});
} else {
hash = await walletClient.sendTransaction({
account,
chain: abstractTestnet,
to: content.recipient as Address,
value: parseEther(content.amount.toString()),
kzg: undefined,
});
}
}

elizaLogger.success(
Expand Down Expand Up @@ -233,6 +277,27 @@ export const transferAction: Action = {
},
},
],
[
{
user: "{{user1}}",
content: {
text: "Send 0.01 ETH to 0x114B242D931B47D5cDcEe7AF065856f70ee278C4 using your abstract global wallet",
},
},
{
user: "{{agent}}",
content: {
text: "Sure, I'll send 0.01 ETH to that address now using my AGW.",
action: "SEND_TOKEN",
},
},
{
user: "{{agent}}",
content: {
text: "Successfully sent 0.01 ETH to 0x114B242D931B47D5cDcEe7AF065856f70ee278C4\nTransaction: 0xdde850f9257365fffffc11324726ebdcf5b90b01c6eec9b3e7ab3e81fde6f14b using my AGW",
},
},
],
[
{
user: "{{user1}}",
Expand Down
Loading

0 comments on commit 00be64c

Please sign in to comment.