Skip to content

Commit d049425

Browse files
committed
feat(plugin-conflux): support bridge transfer
1 parent e9d343d commit d049425

File tree

8 files changed

+179
-27
lines changed

8 files changed

+179
-27
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes20","name":"sender","type":"bytes20"},{"indexed":true,"internalType":"bytes20","name":"receiver","type":"bytes20"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"Call","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes20","name":"sender","type":"bytes20"},{"indexed":true,"internalType":"bytes20","name":"contract_address","type":"bytes20"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"init","type":"bytes"}],"name":"Create","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"Outcome","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes20","name":"sender","type":"bytes20"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"bytes","name":"init","type":"bytes"}],"name":"createEVM","outputs":[{"internalType":"bytes20","name":"","type":"bytes20"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes20","name":"to","type":"bytes20"}],"name":"transferEVM","outputs":[{"internalType":"bytes","name":"output","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes20","name":"to","type":"bytes20"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"callEVM","outputs":[{"internalType":"bytes","name":"output","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes20","name":"to","type":"bytes20"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"staticCallEVM","outputs":[{"internalType":"bytes","name":"output","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deployEip1820","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"withdrawFromMapped","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"mappedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"mappedNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import {
2+
Action,
3+
IAgentRuntime,
4+
Memory,
5+
State,
6+
HandlerCallback,
7+
} from "@ai16z/eliza";
8+
import { generateObjectV2, composeContext, ModelClass, Content } from "@ai16z/eliza";
9+
import { createPublicClient, createWalletClient, http, parseCFX, encodeFunctionData } from "cive";
10+
import { hexAddressToBase32 } from "cive/utils";
11+
import { privateKeyToAccount } from "cive/accounts";
12+
import { testnet } from "cive/chains";
13+
import { confluxBridgeTransferTemplate } from "../templates/bridgeTransfer";
14+
import { TransferSchema, isTransferContent } from "../types";
15+
import crossSpaceCallAbi from "../abi/crossSpaceCall.json";
16+
17+
const bridgeSendCFX = async (
18+
secretKey: `0x${string}`,
19+
rpcUrl: string,
20+
espaceTo: `0x${string}`,
21+
amount: string
22+
) => {
23+
const client = createPublicClient({
24+
transport: http(rpcUrl),
25+
});
26+
const networkId = await client.getChainId();
27+
const account = privateKeyToAccount(secretKey, { networkId });
28+
29+
const walletClient = createWalletClient({
30+
transport: http(rpcUrl),
31+
chain: testnet,
32+
});
33+
34+
const toAddress = hexAddressToBase32({
35+
hexAddress: "0x0888000000000000000000000000000000000006",
36+
networkId,
37+
}); // crossSpaceCall Address
38+
39+
const hash = await walletClient.sendTransaction({
40+
account,
41+
to: toAddress,
42+
value: parseCFX(amount),
43+
chain: testnet,
44+
data: encodeFunctionData({
45+
abi: crossSpaceCallAbi,
46+
functionName: "transferEVM",
47+
args: [espaceTo],
48+
}),
49+
});
50+
51+
// await client.waitForTransactionReceipt({
52+
// hash,
53+
// });
54+
return hash;
55+
};
56+
57+
export const bridgeTransfer: Action = {
58+
name: "BRIDGE_SEND_CFX",
59+
description:
60+
"Bridge transfer CFX from Conflux Core Space to another in Conflux eSpace. The address is a 0x-prefix address",
61+
similes: ["BRIDGE_SEND_CONFLUX", "CROSS_SPACE_SEND_CFX", "BRIDGE_TRANSFER_CFX", "CROSS_SPACE_TRANSFER_CFX"],
62+
examples: [
63+
[
64+
{
65+
user: "{{user1}}",
66+
content: {
67+
text: "Send 1 CFX to eSpace Address 0x119DA8bbe74B1C5c987D0c64D10eC1dB301d4752",
68+
},
69+
},
70+
{
71+
user: "{{user2}}",
72+
content: {
73+
text: "1 CFX sent to espace Address 0x119DA8bbe74B1C5c987D0c64D10eC1dB301d4752: 0x1234567890abcdef",
74+
content: {
75+
to: "0x119DA8bbe74B1C5c987D0c64D10eC1dB301d4752",
76+
amount: "1",
77+
},
78+
},
79+
},
80+
],
81+
],
82+
validate: async (runtime: IAgentRuntime, message: Memory) => {
83+
// no extra validation needed
84+
return true;
85+
},
86+
handler: async (
87+
runtime: IAgentRuntime,
88+
message: Memory,
89+
state?: State,
90+
options?: { [key: string]: unknown },
91+
callback?: HandlerCallback
92+
) => {
93+
if (!state) {
94+
state = (await runtime.composeState(message)) as State;
95+
} else {
96+
state = await runtime.updateRecentMessageState(state);
97+
}
98+
99+
const context = composeContext({
100+
state,
101+
template: confluxBridgeTransferTemplate,
102+
});
103+
104+
const content = await generateObjectV2({
105+
runtime,
106+
context,
107+
modelClass: ModelClass.SMALL,
108+
schema: TransferSchema,
109+
});
110+
111+
if (!isTransferContent(content.object)) {
112+
throw new Error("Invalid content");
113+
}
114+
115+
const secretKey = runtime.getSetting("CONFLUX_CORE_PRIVATE_KEY") as `0x${string}`;
116+
const rpcUrl = runtime.getSetting("CONFLUX_CORE_SPACE_RPC_URL");
117+
118+
let success = false;
119+
120+
try {
121+
const hash = await bridgeSendCFX(secretKey, rpcUrl, content.object.to as `0x${string}`, content.object.amount.toString());
122+
success = true;
123+
if (!callback) {
124+
return success;
125+
}
126+
callback({
127+
text: `${content.object.amount} CFX sent to ${content.object.to}: ${hash}`,
128+
content: content.object,
129+
});
130+
} catch (error) {
131+
console.error(`Error sending CFX: ${error}`);
132+
if (!callback) {
133+
return success;
134+
}
135+
callback({
136+
text: `Failed to send ${content.object.amount} CFX to ${content.object.to}: ${error}`,
137+
});
138+
}
139+
return success;
140+
},
141+
};

packages/plugin-conflux/src/actions/confiPump.ts

Whitespace-only changes.

packages/plugin-conflux/src/actions/sponsor.ts

Whitespace-only changes.

packages/plugin-conflux/src/actions/transfer.ts

+8-26
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,12 @@ import {
55
State,
66
HandlerCallback,
77
} from "@ai16z/eliza";
8-
import { z } from "zod";
98
import { generateObjectV2, composeContext, ModelClass, Content } from "@ai16z/eliza";
109
import { createPublicClient, createWalletClient, http, parseCFX } from "cive";
1110
import { privateKeyToAccount } from "cive/accounts";
1211
import { testnet } from "cive/chains";
1312
import { confluxTransferTemplate } from "../templates/transfer";
14-
15-
const TransferSchema = z.object({
16-
to: z.string(),
17-
amount: z.number(), // use number ignoring decimals issue
18-
});
19-
20-
interface TransferContent extends Content {
21-
to: string;
22-
amount: number;
23-
}
24-
25-
const isTransferContent = (object: any): object is TransferContent => {
26-
if (TransferSchema.safeParse(object).success) {
27-
return true;
28-
}
29-
console.error("Invalid content: ", object);
30-
return false;
31-
};
13+
import { TransferSchema, isTransferContent } from "../types";
3214

3315
const sendCFX = async (
3416
secretKey: `0x${string}`,
@@ -54,31 +36,31 @@ const sendCFX = async (
5436
chain: testnet,
5537
});
5638

57-
await client.waitForTransactionReceipt({
58-
hash,
59-
});
39+
// await client.waitForTransactionReceipt({
40+
// hash,
41+
// });
6042
return hash;
6143
};
6244

6345
export const transfer: Action = {
6446
name: "SEND_CFX",
6547
description:
66-
"Transfer CFX from to another in Conflux Core Space",
48+
"Transfer CFX to another address in Conflux Core Space. The address starts with `cfx:` or `cfxtest:`",
6749
similes: ["SEND_CONFLUX", "SEND_CFX_CORE_SPACE", "TRANSFER_CFX"],
6850
examples: [
6951
[
7052
{
7153
user: "{{user1}}",
7254
content: {
73-
text: "Send 1 CFX to 0x1234567890abcdef",
55+
text: "Send 1 CFX to cfx:aaejuaaaaaaaaaaaaaaaaaaaaaaaaaaaa2eaeg85p5",
7456
},
7557
},
7658
{
7759
user: "{{user2}}",
7860
content: {
79-
text: "1 CFX sent to 0x1234567890abcdef: 0x1234567890abcdef",
61+
text: "1 CFX sent to cfx:aaejuaaaaaaaaaaaaaaaaaaaaaaaaaaaa2eaeg85p5: 0x1234567890abcdef",
8062
content: {
81-
to: "0x1234567890abcdef",
63+
to: "cfx:aaejuaaaaaaaaaaaaaaaaaaaaaaaaaaaa2eaeg85p5",
8264
amount: "1",
8365
},
8466
},

packages/plugin-conflux/src/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { Plugin } from "@ai16z/eliza";
22
import { transfer } from "./actions/transfer";
3+
import { bridgeTransfer } from "./actions/bridgeTransfer";
34

45
export const confluxPlugin: Plugin = {
56
name: "conflux",
67
description: "Conflux Plugin for Eliza",
7-
actions: [transfer],
8+
actions: [transfer, bridgeTransfer],
89
providers: [],
910
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const confluxBridgeTransferTemplate = `
2+
Extract Conflux Cross Space Transfer Parameters from the latest message:
3+
4+
{{recentMessages}}
5+
6+
The to address should be the Conflux eSpace address, starting with "0x".
7+
`;

packages/plugin-conflux/src/types.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { z } from "zod";
2+
import { Content } from "@ai16z/eliza";
3+
4+
export const TransferSchema = z.object({
5+
to: z.string(),
6+
amount: z.number(), // use number ignoring decimals issue
7+
});
8+
9+
export interface TransferContent extends Content {
10+
to: string;
11+
amount: number;
12+
}
13+
14+
export const isTransferContent = (object: any): object is TransferContent => {
15+
if (TransferSchema.safeParse(object).success) {
16+
return true;
17+
}
18+
console.error("Invalid content: ", object);
19+
return false;
20+
};

0 commit comments

Comments
 (0)