Skip to content

Commit 1f97116

Browse files
committed
Merge branch 'main' of https://github.com/robin-rrt/eliza into HEAD
2 parents 492ca47 + 268adc0 commit 1f97116

16 files changed

+1292
-1
lines changed

.env.example

+6
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,12 @@ NEAR_NETWORK=testnet # or mainnet
351351
ZKSYNC_ADDRESS=
352352
ZKSYNC_PRIVATE_KEY=
353353

354+
# Avail DA Configuration
355+
AVAIL_ADDRESS=
356+
AVAIL_SEED=
357+
AVAIL_APP_ID=0
358+
AVAIL_RPC_URL=wss://avail-turing.public.blastapi.io/ # (Default) Testnet: wss://avail-turing.public.blastapi.io/ | Mainnet: wss://avail-mainnet.public.blastapi.io/
359+
354360
# Ton
355361
TON_PRIVATE_KEY= # Ton Mnemonic Seed Phrase Join With Empty String
356362
TON_RPC_URL= # ton rpc

agent/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"@elizaos/plugin-0g": "workspace:*",
3434
"@elizaos/plugin-abstract": "workspace:*",
3535
"@elizaos/plugin-aptos": "workspace:*",
36+
"@elizaos/plugin-avail": "workspace:*",
3637
"@elizaos/plugin-bootstrap": "workspace:*",
3738
"@elizaos/plugin-intiface": "workspace:*",
3839
"@elizaos/plugin-coinbase": "workspace:*",

agent/src/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import { TEEMode, teePlugin } from "@elizaos/plugin-tee";
6464
import { tonPlugin } from "@elizaos/plugin-ton";
6565
import { webSearchPlugin } from "@elizaos/plugin-web-search";
6666
import { zksyncEraPlugin } from "@elizaos/plugin-zksync-era";
67+
import { availPlugin } from "@elizaos/plugin-avail";
6768
import Database from "better-sqlite3";
6869
import fs from "fs";
6970
import net from "net";
@@ -617,6 +618,8 @@ export async function createAgent(
617618
getSecret(character, "GENLAYER_PRIVATE_KEY")
618619
? genLayerPlugin
619620
: null,
621+
getSecret(character, "AVAIL_SEED") ? availPlugin : null,
622+
getSecret(character, "AVAIL_APP_ID") ? availPlugin : null,
620623
].filter(Boolean),
621624
providers: [],
622625
actions: [],

packages/core/src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ export enum ModelProviderName {
243243
VENICE = "venice",
244244
AKASH_CHAT_API = "akash_chat_api",
245245
LIVEPEER = "livepeer",
246+
INFERA = "infera",
246247
}
247248

248249
/**

packages/plugin-0g/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ ZEROG_FLOW_ADDRESS=<0G Flow contract address>
2828
### Basic Integration
2929

3030
```typescript
31-
import { zgPlugin } from "@ai16z/plugin-0g";
31+
import { zgPlugin } from "@eliza/plugin-0g";
3232
```
3333

3434
### File Upload Example

packages/plugin-avail/.npmignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*
2+
3+
!dist/**
4+
!package.json
5+
!readme.md
6+
!tsup.config.ts

packages/plugin-avail/README.md

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# @elizaos/plugin-avail - Plugin for Avail
2+
3+
This is a plugin for using Eliza to interact with the Avail DA network. Defaults to Turing testnet, but can be customized to use Mainnet by changing the RPC in the `.env` file at `AVAIL_RPC_URL`.
4+
5+
## Actions
6+
- **transfer**: This action enables the transfer of AVAIL tokens from the agent's wallet (as defined by the keyring generated from `AVAIL_SEED`) to another wallet. To use just mention the transfer of AVAIL tokens to an Avail account.
7+
8+
- name: `SEND_AVAIL`
9+
10+
- Message sample: `Send 100 AVAIL to 5GWbvXjefEvXXETtKQH7YBsUaPc379KAQATW1eqeJT26cbsK`
11+
12+
- **submitData**: This action enables the submission of any arbitrary data to the Avail DA network. To use just mention that you need to send "any data" to Avail. You can customize the Avail `appID` through which the agent submits the data by modifying the `AVAIL_APP_ID` env config.
13+
14+
- name: `SUBMIT_DATA`
15+
16+
- Message sample: `Submit the following data to Avail "Hello World!"`
17+
18+
## Usage & Testing
19+
20+
### Detailed testing steps
21+
- In `.env` you should set the value for `AVAIL_ADDRESS` (this is the public address for the agent account - [learn how to get one here](https://docs.availproject.org/user-guides/accounts#seed-phrases)) and `AVAIL_SEED` (seed phrase for the same account).
22+
23+
- **Transfer AVAIL**
24+
- To test transfer function, you need tokens in your Avail account. On testnet, you can use the [Avail Faucet](https://faucet.avail.tools/). If you need more please ping us on [Discord](https://discord.gg/y6fHnxZQX8), and we can send it over.
25+
- Run the agent and prompt it with: "send <AMOUNT> AVAIL to <any other Avail account> " - e.g. `send 1 AVAIL to 5GWbvXjefEvXXETtKQH7YBsUaPc379KAQATW1eqeJT26cbsK`
26+
- Assuming everything goes smoothly the agent returns with the Tx Hash, and Block Hash.
27+
The tx hash can be checked on the Avail block explorer at https://avail-turing.subscan.io/
28+
29+
- **Submit Data**
30+
- To test data submission, you need tokens in your Avail account to pay fees. On testnet, you can use the [Avail Faucet](https://faucet.avail.tools/). If you need more please ping us on [Discord](https://discord.gg/y6fHnxZQX8), and we can send it over.
31+
- Run the agent and prompt it with: "Submit the following data to Avail <DATA>" - e.g. `Submit the following data to Avail "Hello World!"`
32+
- Assuming everything goes smoothly the agent returns with the Tx Hash, and Block Hash. The tx hash can be checked on the Avail block explorer at https://avail-turing.subscan.io/
33+
34+
35+
## Resources
36+
- [Avail Documentation](https://docs.availproject.org/)
37+
- [Set up an Avail Account](https://docs.availproject.org/user-guides/accounts#seed-phrases) - Learn how to get your `AVAIL_SEED`
38+
- [Find more Network Information like RPC endpoints](https://docs.availproject.org/docs/networks)
39+
- [Learn more about appIDs](https://docs.availproject.org/docs/build-with-avail/interact-with-avail-da/app-id)
40+
- [Learn more about Avail](https://www.availproject.org/)
41+
- [Awesome Avail Repo](https://github.com/availproject/awesome-avail)
42+
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import eslintGlobalConfig from "../../eslint.config.mjs";
2+
3+
export default [...eslintGlobalConfig];

packages/plugin-avail/package.json

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "@elizaos/plugin-avail",
3+
"main": "dist/index.js",
4+
"type": "module",
5+
"types": "dist/index.d.ts",
6+
"dependencies": {
7+
"@elizaos/core": "workspace:*",
8+
"@elizaos/plugin-trustdb": "workspace:*",
9+
"avail-js-sdk": "^0.3.0"
10+
},
11+
"devDependencies": {
12+
"tsup": "8.3.5",
13+
"@types/node": "^20.0.0"
14+
},
15+
"scripts": {
16+
"build": "tsup --format esm --dts",
17+
"dev": "tsup --format esm --dts --watch",
18+
"lint": "eslint --fix --cache ."
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
import {
2+
ActionExample,
3+
Content,
4+
HandlerCallback,
5+
IAgentRuntime,
6+
Memory,
7+
ModelClass,
8+
State,
9+
type Action,
10+
elizaLogger,
11+
composeContext,
12+
generateObject,
13+
generateObjectDeprecated,
14+
} from "@elizaos/core";
15+
import { validateAvailConfig } from "../environment";
16+
import {
17+
getDecimals,
18+
initialize,
19+
formatNumberToBalance,
20+
getKeyringFromSeed,
21+
isValidAddress,
22+
} from "avail-js-sdk";
23+
import { ISubmittableResult } from "@polkadot/types/types/extrinsic";
24+
import { H256 } from "@polkadot/types/interfaces/runtime";
25+
26+
export interface DataContent extends Content {
27+
data: string;
28+
}
29+
30+
export function isDataContent(content: DataContent): content is DataContent {
31+
// Validate types
32+
const validTypes = typeof content.data === "string";
33+
if (!validTypes) {
34+
return false;
35+
}
36+
}
37+
38+
const submitDataTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined.
39+
40+
41+
Example response:
42+
\`\`\`json
43+
{
44+
"data": "Hello World, this is the data I submitted"
45+
}
46+
\`\`\`
47+
48+
{{recentMessages}}
49+
50+
Given the recent messages, extract the following information about the requested AVAIL token transfer:
51+
- Data to be submitted
52+
53+
Respond with a JSON markdown block containing only the extracted values.`;
54+
55+
export default {
56+
name: "SUBMIT_DATA",
57+
similes: [
58+
"SUBMIT_DATA_TO_AVAIL",
59+
"SEND_DATA",
60+
"SEND_DATA_TO_AVAIL",
61+
"POST_DATA",
62+
"POST_DATA_TO_AVAIL",
63+
"POST_DATA_ON_AVAIL_NETWORK",
64+
"POST_DATA_TO_AVAIL_NETWORK",
65+
"SEND_DATA_ON_AVAIL_NETWORK",
66+
"SEND_DATA_TO_AVAIL_NETWORK",
67+
"SUBMIT_DATA_ON_AVAIL_NETWORK",
68+
"SUBMIT_DATA_TO_AVAIL_NETWORK",
69+
],
70+
validate: async (runtime: IAgentRuntime, message: Memory) => {
71+
await validateAvailConfig(runtime);
72+
return true;
73+
},
74+
description: "Submit data to Avail as per user command",
75+
handler: async (
76+
runtime: IAgentRuntime,
77+
message: Memory,
78+
state: State,
79+
_options: { [key: string]: unknown },
80+
callback?: HandlerCallback
81+
): Promise<boolean> => {
82+
elizaLogger.log("Starting SUBMIT_DATA handler...");
83+
84+
// Initialize or update state
85+
if (!state) {
86+
state = (await runtime.composeState(message)) as State;
87+
} else {
88+
state = await runtime.updateRecentMessageState(state);
89+
}
90+
91+
// Compose transfer context
92+
const submitDataContext = composeContext({
93+
state,
94+
template: submitDataTemplate,
95+
});
96+
97+
// Generate transfer content
98+
const content = await generateObjectDeprecated({
99+
runtime,
100+
context: submitDataContext,
101+
modelClass: ModelClass.SMALL,
102+
});
103+
104+
// Validate transfer content
105+
// if (!isDataContent(content)) {
106+
// console.log(content + typeof(content.data))
107+
// console.error("Invalid content for SUBMIT_DATA action.");
108+
// if (callback) {
109+
// callback({
110+
// text: "Unable to process submit data request. Invalid content provided.",
111+
// content: { error: "Invalid data content" },
112+
// });
113+
// }
114+
// return false;
115+
// }
116+
if (content.data != null) {
117+
try {
118+
const SEED = runtime.getSetting("AVAIL_SEED")!;
119+
const ACCOUNT = runtime.getSetting("AVAIL_ADDRESS")!;
120+
const ENDPOINT = runtime.getSetting("AVAIL_RPC_URL");
121+
const APP_ID = runtime.getSetting("AVAIL_APP_ID");
122+
123+
const api = await initialize(ENDPOINT);
124+
const keyring = getKeyringFromSeed(SEED);
125+
const options = { app_id: APP_ID, nonce: -1 };
126+
const decimals = getDecimals(api);
127+
const data = content.data;
128+
129+
const submitDataInfo = await api.tx.dataAvailability
130+
.submitData(data)
131+
.paymentInfo(keyring);
132+
//print estimated fees
133+
elizaLogger.log(`Transaction Fee for Submit Data:
134+
class=${submitDataInfo.class.toString()},
135+
weight=${submitDataInfo.weight.toString()},
136+
partialFee=${submitDataInfo.partialFee.toHuman()}
137+
`);
138+
139+
//submit data
140+
const txResult = await new Promise<ISubmittableResult>(
141+
(res) => {
142+
api.tx.dataAvailability
143+
.submitData(data)
144+
.signAndSend(
145+
keyring,
146+
options,
147+
(result: ISubmittableResult) => {
148+
elizaLogger.log(
149+
`Tx status: ${result.status}`
150+
);
151+
if (result.isFinalized || result.isError) {
152+
res(result);
153+
}
154+
}
155+
);
156+
}
157+
);
158+
159+
// Rejected Transaction handling
160+
if (txResult.isError) {
161+
console.log(`Transaction was not executed`);
162+
}
163+
164+
// Failed Transaction handling
165+
const error = txResult.dispatchError;
166+
if (error != undefined) {
167+
if (error.isModule) {
168+
const decoded = api.registry.findMetaError(
169+
error.asModule
170+
);
171+
const { docs, name, section } = decoded;
172+
console.log(`${section}.${name}: ${docs.join(" ")}`);
173+
} else {
174+
console.log(error.toString());
175+
}
176+
}
177+
178+
elizaLogger.success(
179+
"Data submitted successfully! tx: \n " +
180+
`Tx Hash: ${txResult.txHash as H256}, Block Hash: ${txResult.status.asFinalized as H256}`
181+
);
182+
if (callback) {
183+
callback({
184+
text: `Data submitted successfully! tx hash: ${txResult.txHash as H256} Block Hash: ${txResult.status.asFinalized as H256} `,
185+
content: {},
186+
});
187+
}
188+
189+
return true;
190+
} catch (error) {
191+
elizaLogger.error("Error during data submission:", error);
192+
if (callback) {
193+
callback({
194+
text: `Error submitting data: ${error.message}`,
195+
content: { error: error.message },
196+
});
197+
}
198+
return false;
199+
}
200+
} else {
201+
elizaLogger.log("No data mentioned to be submitted");
202+
}
203+
},
204+
205+
examples: [
206+
[
207+
{
208+
user: "{{user1}}",
209+
content: {
210+
text: "Submit the following data to Avail 'Hello World!'",
211+
},
212+
},
213+
{
214+
user: "{{agent}}",
215+
content: {
216+
text: "Sure, I'll send the data 'Hello World!' to Avail now.",
217+
action: "SUBMIT_DATA",
218+
},
219+
},
220+
{
221+
user: "{{agent}}",
222+
content: {
223+
text: "Successfully submitted the data 'Hello World!' to Avail \nTransaction: 0x748057951ff79cea6de0e13b2ef70a1e9f443e9c83ed90e5601f8b45144a4ed4",
224+
},
225+
},
226+
],
227+
[
228+
{
229+
user: "{{user1}}",
230+
content: {
231+
text: "Submit 'Don't Fight, Unite!' to Avail",
232+
},
233+
},
234+
{
235+
user: "{{agent}}",
236+
content: {
237+
text: "Sure, I'll send the data 'Don't Fight, Unite!' to Avail now.",
238+
action: "SUBMIT_DATA",
239+
},
240+
},
241+
{
242+
user: "{{agent}}",
243+
content: {
244+
text: "Successfully submitted the data 'Don't Fight, Unite!' to Avail \nTransaction: 0x748057951ff79cea6de0e13b2ef70a1e9f443e9c83ed90e5601f8b45144a4ed4",
245+
},
246+
},
247+
],
248+
] as ActionExample[][],
249+
} as Action;

0 commit comments

Comments
 (0)