Skip to content

Commit 00be64c

Browse files
authored
Merge pull request #2207 from cygaar/agw_integration
feat: Add AGW support to the Abstract plugin
2 parents 4420a7a + 66c595d commit 00be64c

File tree

3 files changed

+1193
-1084
lines changed

3 files changed

+1193
-1084
lines changed

packages/plugin-abstract/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"dist"
2020
],
2121
"dependencies": {
22+
"@abstract-foundation/agw-client": "^0.1.7",
2223
"@elizaos/core": "workspace:*",
2324
"tsup": "^8.3.5",
2425
"viem": "2.22.2"

packages/plugin-abstract/src/actions/transferAction.ts

+100-35
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { validateAbstractConfig } from "../environment";
1515

1616
import {
1717
Address,
18-
createWalletClient,
1918
erc20Abi,
2019
http,
2120
parseEther,
@@ -25,6 +24,7 @@ import {
2524
} from "viem";
2625
import { abstractTestnet, mainnet } from "viem/chains";
2726
import { normalize } from "viem/ens";
27+
import { createAbstractClient } from "@abstract-foundation/agw-client";
2828
import { z } from "zod";
2929
import { ValidateContext } from "../utils";
3030
import { ETH_ADDRESS, ERC20_OVERRIDE_INFO } from "../constants";
@@ -39,12 +39,14 @@ const TransferSchema = z.object({
3939
tokenAddress: z.string(),
4040
recipient: z.string(),
4141
amount: z.string(),
42+
useAGW: z.boolean(),
4243
});
4344

4445
export interface TransferContent extends Content {
4546
tokenAddress: string;
4647
recipient: string;
4748
amount: string | number;
49+
useAGW: boolean;
4850
}
4951

5052
const transferTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined.
@@ -58,16 +60,21 @@ Example response:
5860
{
5961
"tokenAddress": "0x5A7d6b2F92C77FAD6CCaBd7EE0624E64907Eaf3E",
6062
"recipient": "0xCCa8009f5e09F8C5dB63cb0031052F9CB635Af62",
61-
"amount": "1000"
63+
"amount": "1000",
64+
"useAGW": true
6265
}
6366
\`\`\`
6467
65-
{{recentMessages}}
68+
User message:
69+
"{{currentMessage}}"
6670
67-
Given the recent messages, extract the following information about the requested token transfer:
71+
Given the message, extract the following information about the requested token transfer:
6872
- Token contract address
6973
- Recipient wallet address
7074
- Amount to transfer
75+
- Whether to use Abstract Global Wallet aka AGW
76+
77+
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.
7178
7279
Respond with a JSON markdown block containing only the extracted values.`;
7380

@@ -104,6 +111,7 @@ export const transferAction: Action = {
104111
}
105112

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

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

151159
try {
152160
const account = useGetAccount(runtime);
153-
const walletClient = useGetWalletClient();
154-
155161
let hash;
156-
157-
// Check if the token is native
158-
if (
159-
content.tokenAddress.toLowerCase() !== ETH_ADDRESS.toLowerCase()
160-
) {
161-
// Convert amount to proper token decimals
162-
const tokenInfo =
163-
ERC20_OVERRIDE_INFO[content.tokenAddress.toLowerCase()];
164-
const decimals = tokenInfo?.decimals ?? 18; // Default to 18 decimals if not specified
165-
const tokenAmount = parseUnits(
166-
content.amount.toString(),
167-
decimals
168-
);
169-
170-
// Execute ERC20 transfer
171-
hash = await walletClient.writeContract({
172-
account,
162+
if (content.useAGW) {
163+
const abstractClient = await createAbstractClient({
173164
chain: abstractTestnet,
174-
address: content.tokenAddress as Address,
175-
abi: erc20Abi,
176-
functionName: "transfer",
177-
args: [content.recipient as Address, tokenAmount],
165+
signer: account,
178166
});
167+
168+
// Handle AGW transfer based on token type
169+
if (
170+
content.tokenAddress.toLowerCase() !==
171+
ETH_ADDRESS.toLowerCase()
172+
) {
173+
const tokenInfo =
174+
ERC20_OVERRIDE_INFO[content.tokenAddress.toLowerCase()];
175+
const decimals = tokenInfo?.decimals ?? 18;
176+
const tokenAmount = parseUnits(
177+
content.amount.toString(),
178+
decimals
179+
);
180+
181+
// @ts-ignore - will fix later
182+
hash = await abstractClient.writeContract({
183+
chain: abstractTestnet,
184+
address: content.tokenAddress as Address,
185+
abi: erc20Abi,
186+
functionName: "transfer",
187+
args: [content.recipient as Address, tokenAmount],
188+
});
189+
} else {
190+
// @ts-ignore
191+
hash = await abstractClient.sendTransaction({
192+
chain: abstractTestnet,
193+
to: content.recipient as Address,
194+
value: parseEther(content.amount.toString()),
195+
kzg: undefined,
196+
});
197+
}
179198
} else {
180-
hash = await walletClient.sendTransaction({
181-
account: account,
182-
chain: abstractTestnet,
183-
to: content.recipient as Address,
184-
value: parseEther(content.amount.toString()),
185-
kzg: undefined,
186-
});
199+
const walletClient = useGetWalletClient();
200+
201+
// Handle regular wallet transfer based on token type
202+
if (
203+
content.tokenAddress.toLowerCase() !==
204+
ETH_ADDRESS.toLowerCase()
205+
) {
206+
const tokenInfo =
207+
ERC20_OVERRIDE_INFO[content.tokenAddress.toLowerCase()];
208+
const decimals = tokenInfo?.decimals ?? 18;
209+
const tokenAmount = parseUnits(
210+
content.amount.toString(),
211+
decimals
212+
);
213+
214+
hash = await walletClient.writeContract({
215+
account,
216+
chain: abstractTestnet,
217+
address: content.tokenAddress as Address,
218+
abi: erc20Abi,
219+
functionName: "transfer",
220+
args: [content.recipient as Address, tokenAmount],
221+
});
222+
} else {
223+
hash = await walletClient.sendTransaction({
224+
account,
225+
chain: abstractTestnet,
226+
to: content.recipient as Address,
227+
value: parseEther(content.amount.toString()),
228+
kzg: undefined,
229+
});
230+
}
187231
}
188232

189233
elizaLogger.success(
@@ -233,6 +277,27 @@ export const transferAction: Action = {
233277
},
234278
},
235279
],
280+
[
281+
{
282+
user: "{{user1}}",
283+
content: {
284+
text: "Send 0.01 ETH to 0x114B242D931B47D5cDcEe7AF065856f70ee278C4 using your abstract global wallet",
285+
},
286+
},
287+
{
288+
user: "{{agent}}",
289+
content: {
290+
text: "Sure, I'll send 0.01 ETH to that address now using my AGW.",
291+
action: "SEND_TOKEN",
292+
},
293+
},
294+
{
295+
user: "{{agent}}",
296+
content: {
297+
text: "Successfully sent 0.01 ETH to 0x114B242D931B47D5cDcEe7AF065856f70ee278C4\nTransaction: 0xdde850f9257365fffffc11324726ebdcf5b90b01c6eec9b3e7ab3e81fde6f14b using my AGW",
298+
},
299+
},
300+
],
236301
[
237302
{
238303
user: "{{user1}}",

0 commit comments

Comments
 (0)