Skip to content

Commit b3afa28

Browse files
authored
Merge pull request #2167 from IkigaiLabsETH/tcm-refactor-nft-plugin
feat: nft plugin
2 parents 7df280d + 1d45efc commit b3afa28

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+7474
-47
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,4 @@ agent/content
6060

6161
eliza.manifest
6262
eliza.manifest.sgx
63-
eliza.sig
63+
eliza.sig

agent/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
"@elizaos/plugin-hyperliquid": "workspace:*",
9393
"@elizaos/plugin-akash": "workspace:*",
9494
"@elizaos/plugin-quai": "workspace:*",
95+
"@elizaos/plugin-nft-collections": "workspace:*",
9596
"readline": "1.3.0",
9697
"ws": "8.18.0",
9798
"yargs": "17.7.2"

agent/src/index.ts

+65-38
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { SlackClientInterface } from "@elizaos/client-slack";
1111
import { TelegramClientInterface } from "@elizaos/client-telegram";
1212
import { TwitterClientInterface } from "@elizaos/client-twitter";
1313
// import { ReclaimAdapter } from "@elizaos/plugin-reclaim";
14-
import { DirectClient } from "@elizaos/client-direct";
1514
import { PrimusAdapter } from "@elizaos/plugin-primus";
1615

1716
import {
@@ -102,7 +101,7 @@ import net from "net";
102101
import path from "path";
103102
import { fileURLToPath } from "url";
104103
import yargs from "yargs";
105-
import {dominosPlugin} from "@elizaos/plugin-dominos";
104+
import createNFTCollectionsPlugin from "@elizaos/plugin-nft-collections";
106105

107106
const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file
108107
const __dirname = path.dirname(__filename); // get the name of the directory
@@ -152,14 +151,29 @@ function tryLoadFile(filePath: string): string | null {
152151
function mergeCharacters(base: Character, child: Character): Character {
153152
const mergeObjects = (baseObj: any, childObj: any) => {
154153
const result: any = {};
155-
const keys = new Set([...Object.keys(baseObj || {}), ...Object.keys(childObj || {})]);
156-
keys.forEach(key => {
157-
if (typeof baseObj[key] === 'object' && typeof childObj[key] === 'object' && !Array.isArray(baseObj[key]) && !Array.isArray(childObj[key])) {
154+
const keys = new Set([
155+
...Object.keys(baseObj || {}),
156+
...Object.keys(childObj || {}),
157+
]);
158+
keys.forEach((key) => {
159+
if (
160+
typeof baseObj[key] === "object" &&
161+
typeof childObj[key] === "object" &&
162+
!Array.isArray(baseObj[key]) &&
163+
!Array.isArray(childObj[key])
164+
) {
158165
result[key] = mergeObjects(baseObj[key], childObj[key]);
159-
} else if (Array.isArray(baseObj[key]) || Array.isArray(childObj[key])) {
160-
result[key] = [...(baseObj[key] || []), ...(childObj[key] || [])];
166+
} else if (
167+
Array.isArray(baseObj[key]) ||
168+
Array.isArray(childObj[key])
169+
) {
170+
result[key] = [
171+
...(baseObj[key] || []),
172+
...(childObj[key] || []),
173+
];
161174
} else {
162-
result[key] = childObj[key] !== undefined ? childObj[key] : baseObj[key];
175+
result[key] =
176+
childObj[key] !== undefined ? childObj[key] : baseObj[key];
163177
}
164178
});
165179
return result;
@@ -174,32 +188,36 @@ async function loadCharacter(filePath: string): Promise<Character> {
174188
let character = JSON.parse(content);
175189
validateCharacterConfig(character);
176190

177-
// .id isn't really valid
178-
const characterId = character.id || character.name;
179-
const characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, "_")}.`;
180-
const characterSettings = Object.entries(process.env)
181-
.filter(([key]) => key.startsWith(characterPrefix))
182-
.reduce((settings, [key, value]) => {
183-
const settingKey = key.slice(characterPrefix.length);
184-
return { ...settings, [settingKey]: value };
185-
}, {});
186-
if (Object.keys(characterSettings).length > 0) {
187-
character.settings = character.settings || {};
188-
character.settings.secrets = {
189-
...characterSettings,
190-
...character.settings.secrets,
191-
};
192-
}
193-
// Handle plugins
194-
character.plugins = await handlePluginImporting(
195-
character.plugins
196-
);
191+
// .id isn't really valid
192+
const characterId = character.id || character.name;
193+
const characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, "_")}.`;
194+
const characterSettings = Object.entries(process.env)
195+
.filter(([key]) => key.startsWith(characterPrefix))
196+
.reduce((settings, [key, value]) => {
197+
const settingKey = key.slice(characterPrefix.length);
198+
return { ...settings, [settingKey]: value };
199+
}, {});
200+
if (Object.keys(characterSettings).length > 0) {
201+
character.settings = character.settings || {};
202+
character.settings.secrets = {
203+
...characterSettings,
204+
...character.settings.secrets,
205+
};
206+
}
207+
// Handle plugins
208+
character.plugins = await handlePluginImporting(character.plugins);
197209
if (character.extends) {
198-
elizaLogger.info(`Merging ${character.name} character with parent characters`);
210+
elizaLogger.info(
211+
`Merging ${character.name} character with parent characters`
212+
);
199213
for (const extendPath of character.extends) {
200-
const baseCharacter = await loadCharacter(path.resolve(path.dirname(filePath), extendPath));
214+
const baseCharacter = await loadCharacter(
215+
path.resolve(path.dirname(filePath), extendPath)
216+
);
201217
character = mergeCharacters(baseCharacter, character);
202-
elizaLogger.info(`Merged ${character.name} with ${baseCharacter.name}`);
218+
elizaLogger.info(
219+
`Merged ${character.name} with ${baseCharacter.name}`
220+
);
203221
}
204222
}
205223
return character;
@@ -472,7 +490,9 @@ function initializeDatabase(dataDir: string) {
472490
// Test the connection
473491
db.init()
474492
.then(() => {
475-
elizaLogger.success("Successfully connected to Supabase database");
493+
elizaLogger.success(
494+
"Successfully connected to Supabase database"
495+
);
476496
})
477497
.catch((error) => {
478498
elizaLogger.error("Failed to connect to Supabase:", error);
@@ -489,7 +509,9 @@ function initializeDatabase(dataDir: string) {
489509
// Test the connection
490510
db.init()
491511
.then(() => {
492-
elizaLogger.success("Successfully connected to PostgreSQL database");
512+
elizaLogger.success(
513+
"Successfully connected to PostgreSQL database"
514+
);
493515
})
494516
.catch((error) => {
495517
elizaLogger.error("Failed to connect to PostgreSQL:", error);
@@ -504,14 +526,17 @@ function initializeDatabase(dataDir: string) {
504526
});
505527
return db;
506528
} else {
507-
const filePath = process.env.SQLITE_FILE ?? path.resolve(dataDir, "db.sqlite");
529+
const filePath =
530+
process.env.SQLITE_FILE ?? path.resolve(dataDir, "db.sqlite");
508531
elizaLogger.info(`Initializing SQLite database at ${filePath}...`);
509532
const db = new SqliteDatabaseAdapter(new Database(filePath));
510533

511534
// Test the connection
512535
db.init()
513536
.then(() => {
514-
elizaLogger.success("Successfully connected to SQLite database");
537+
elizaLogger.success(
538+
"Successfully connected to SQLite database"
539+
);
515540
})
516541
.catch((error) => {
517542
elizaLogger.error("Failed to connect to SQLite:", error);
@@ -689,7 +714,8 @@ export async function createAgent(
689714
if (
690715
process.env.PRIMUS_APP_ID &&
691716
process.env.PRIMUS_APP_SECRET &&
692-
process.env.VERIFIABLE_INFERENCE_ENABLED === "true"){
717+
process.env.VERIFIABLE_INFERENCE_ENABLED === "true"
718+
) {
693719
verifiableInferenceAdapter = new PrimusAdapter({
694720
appId: process.env.PRIMUS_APP_ID,
695721
appSecret: process.env.PRIMUS_APP_SECRET,
@@ -851,8 +877,9 @@ export async function createAgent(
851877
getSecret(character, "AKASH_WALLET_ADDRESS")
852878
? akashPlugin
853879
: null,
854-
getSecret(character, "QUAI_PRIVATE_KEY")
855-
? quaiPlugin
880+
getSecret(character, "QUAI_PRIVATE_KEY") ? quaiPlugin : null,
881+
getSecret(character, "RESERVOIR_API_KEY")
882+
? createNFTCollectionsPlugin()
856883
: null,
857884
].filter(Boolean),
858885
providers: [],

package.json

+7-6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"devDependencies": {
2828
"@commitlint/cli": "18.6.1",
2929
"@commitlint/config-conventional": "18.6.3",
30+
"@types/jest": "^29.5.11",
3031
"@typescript-eslint/eslint-plugin": "8.16.0",
3132
"@typescript-eslint/parser": "8.16.0",
3233
"@vitest/eslint-plugin": "1.1.13",
@@ -35,18 +36,17 @@
3536
"eslint": "9.16.0",
3637
"eslint-config-prettier": "9.1.0",
3738
"husky": "9.1.7",
39+
"jest": "^29.7.0",
3840
"lerna": "8.1.5",
3941
"only-allow": "1.2.1",
4042
"prettier": "3.4.1",
43+
"ts-jest": "^29.1.1",
4144
"turbo": "2.3.3",
4245
"typedoc": "0.26.11",
4346
"typescript": "5.6.3",
44-
"vite": "5.4.11",
45-
"vitest": "2.1.5",
4647
"viem": "2.21.58",
47-
"ts-jest": "^29.1.1",
48-
"@types/jest": "^29.5.11",
49-
"jest": "^29.7.0"
48+
"vite": "5.4.11",
49+
"vitest": "2.1.5"
5050
},
5151
"pnpm": {
5252
"overrides": {
@@ -64,6 +64,7 @@
6464
"@vitest/eslint-plugin": "1.0.1",
6565
"amqplib": "0.10.5",
6666
"csv-parse": "5.6.0",
67+
"langdetect": "^0.2.1",
6768
"ollama-ai-provider": "0.16.1",
6869
"optional": "0.1.4",
6970
"pnpm": "9.14.4",
@@ -74,4 +75,4 @@
7475
"workspaces": [
7576
"packages/*"
7677
]
77-
}
78+
}

packages/core/src/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1554,4 +1554,4 @@ export enum TranscriptionProvider {
15541554
export enum ActionTimelineType {
15551555
ForYou = "foryou",
15561556
Following = "following",
1557-
}
1557+
}

packages/plugin-evm/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@
3535
"peerDependencies": {
3636
"whatwg-url": "7.1.0"
3737
}
38-
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "../../.eslintrc.json",
3+
"parser": "@typescript-eslint/parser",
4+
"plugins": [
5+
"@typescript-eslint"
6+
],
7+
"root": true
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"tabWidth": 4,
3+
"semi": true,
4+
"singleQuote": false,
5+
"trailingComma": "es5",
6+
"printWidth": 80
7+
}

0 commit comments

Comments
 (0)