From a4774374b3d07e87f16532a3456b6da66c8ff78d Mon Sep 17 00:00:00 2001 From: Damjan Date: Thu, 16 Jan 2025 14:13:30 +0100 Subject: [PATCH] Implement getAssetsByCreator tool --- src/actions/index.ts | 6 +- src/actions/metaplex/getAssetByAuthority.ts | 70 ------------ src/actions/metaplex/getAssetsByAuthority.ts | 103 +++++++++++++++++ src/actions/metaplex/getAssetsByCreator.ts | 105 ++++++++++++++++++ src/agent/index.ts | 10 +- src/langchain/index.ts | 2 + ...uthority.ts => get_assets_by_authority.ts} | 0 .../metaplex/get_assets_by_creator.ts | 40 +++++++ src/langchain/metaplex/index.ts | 3 +- src/tools/metaplex/get_assets_by_authority.ts | 3 +- src/tools/metaplex/get_assets_by_creator.ts | 14 +++ src/tools/metaplex/index.ts | 1 + 12 files changed, 281 insertions(+), 76 deletions(-) delete mode 100644 src/actions/metaplex/getAssetByAuthority.ts create mode 100644 src/actions/metaplex/getAssetsByAuthority.ts create mode 100644 src/actions/metaplex/getAssetsByCreator.ts rename src/langchain/metaplex/{get_asset_by_authority.ts => get_assets_by_authority.ts} (100%) create mode 100644 src/langchain/metaplex/get_assets_by_creator.ts create mode 100644 src/tools/metaplex/get_assets_by_creator.ts diff --git a/src/actions/index.ts b/src/actions/index.ts index 32194c5..b9ff530 100644 --- a/src/actions/index.ts +++ b/src/actions/index.ts @@ -60,7 +60,8 @@ import driftUserAccountInfoAction from "./drift/driftUserAccountInfo"; import deriveDriftVaultAddressAction from "./drift/deriveVaultAddress"; import updateDriftVaultDelegateAction from "./drift/updateDriftVaultDelegate"; import getAssetAction from "./metaplex/getAsset"; -import getAssetByAuthorityAction from "./metaplex/getAssetByAuthority"; +import getAssetsByAuthorityAction from "./metaplex/getAssetsByAuthority"; +import getAssetsByCreatorAction from "./metaplex/getAssetsByCreator"; export const ACTIONS = { WALLET_ADDRESS_ACTION: getWalletAddressAction, @@ -126,7 +127,8 @@ export const ACTIONS = { DERIVE_DRIFT_VAULT_ADDRESS_ACTION: deriveDriftVaultAddressAction, UPDATE_DRIFT_VAULT_DELEGATE_ACTION: updateDriftVaultDelegateAction, GET_ASSET_ACTION: getAssetAction, - GET_ASSET_BY_AUTHORITY_ACTION: getAssetByAuthorityAction, + GET_ASSETS_BY_AUTHORITY_ACTION: getAssetsByAuthorityAction, + GET_ASSETS_BY_CREATOR_ACTION: getAssetsByCreatorAction, }; export type { Action, ActionExample, Handler } from "../types/action"; diff --git a/src/actions/metaplex/getAssetByAuthority.ts b/src/actions/metaplex/getAssetByAuthority.ts deleted file mode 100644 index 1711c8f..0000000 --- a/src/actions/metaplex/getAssetByAuthority.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Action } from "../../types/action"; -import { SolanaAgentKit } from "../../agent"; -import { z } from "zod"; -import { get_assets_by_authority } from "../../tools/metaplex"; - -const getAssetByAuthorityAction: Action = { - name: "GET_ASSET_BY_AUTHORITY", - similes: [ - "fetch assets by authority", - "retrieve assets by authority", - "get assets by authority address", - "fetch authority assets", - ], - description: `Fetch a list of assets owned by a specific address using the Metaplex DAS API.`, - examples: [ - [ - { - input: { - authorityAddress: "mRdta4rc2RtsxEUDYuvKLamMZAdW6qHcwuq866Skxxv", - limit: 10, - }, - output: { - status: "success", - message: "Assets retrieved successfully", - result: [ - // Example asset details - { - name: "Example Asset 1", - symbol: "EXA1", - uri: "https://example.com/asset1.json", - }, - { - name: "Example Asset 2", - symbol: "EXA2", - uri: "https://example.com/asset2.json", - }, - ], - }, - explanation: "Fetch a list of assets owned by a specific address", - }, - ], - ], - schema: z.object({ - authorityAddress: z.string().min(1, "Authority address is required"), - sortBy: z - .object({ - sortBy: z.enum(["created", "updated", "recentAction", "none"]), - sortDirection: z.enum(["asc", "desc"]), - }) - .optional(), - limit: z.number().optional(), - page: z.number().optional(), - before: z.string().optional(), - after: z.string().optional(), - }), - handler: async ( - agent: SolanaAgentKit, - input: z.infer, - ) => { - const result = await get_assets_by_authority(agent, input); - - return { - status: "success", - message: "Assets retrieved successfully", - result, - }; - }, -}; - -export default getAssetByAuthorityAction; diff --git a/src/actions/metaplex/getAssetsByAuthority.ts b/src/actions/metaplex/getAssetsByAuthority.ts new file mode 100644 index 0000000..0b10b94 --- /dev/null +++ b/src/actions/metaplex/getAssetsByAuthority.ts @@ -0,0 +1,103 @@ +import { Action } from "../../types/action"; +import { SolanaAgentKit } from "../../agent"; +import { z } from "zod"; +import { get_assets_by_authority } from "../../tools/metaplex"; + +const getAssetsByAuthorityAction: Action = { + name: "GET_ASSETS_BY_AUTHORITY", + similes: [ + "fetch assets by authority", + "retrieve assets by authority", + "get assets by authority address", + "fetch authority assets", + ], + description: `Fetch a list of assets owned by a specific address using the Metaplex DAS API.`, + examples: [ + [ + { + input: { + authorityAddress: "mRdta4rc2RtsxEUDYuvKLamMZAdW6qHcwuq866Skxxv", + limit: 10, + }, + output: { + status: "success", + message: "Assets retrieved successfully", + result: { + total: 2, + limit: 10, + items: [ + { + interface: "V1_NFT", + id: "ExampleAssetId1", + content: { + json_uri: "https://example.com/asset1.json", + metadata: { + name: "Example Asset 1", + symbol: "EXA1", + }, + }, + authorities: [], + compression: {}, + grouping: [], + royalty: {}, + creators: [], + ownership: {}, + supply: {}, + mutable: true, + burnt: false, + }, + { + interface: "V1_NFT", + id: "ExampleAssetId2", + content: { + json_uri: "https://example.com/asset2.json", + metadata: { + name: "Example Asset 2", + symbol: "EXA2", + }, + }, + authorities: [], + compression: {}, + grouping: [], + royalty: {}, + creators: [], + ownership: {}, + supply: {}, + mutable: true, + burnt: false, + }, + ], + }, + }, + explanation: "Fetch a list of assets owned by a specific address", + }, + ], + ], + schema: z.object({ + authorityAddress: z.string().min(1, "Authority address is required"), + sortBy: z + .object({ + sortBy: z.enum(["created", "updated", "recentAction", "none"]), + sortDirection: z.enum(["asc", "desc"]), + }) + .optional(), + limit: z.number().optional(), + page: z.number().optional(), + before: z.string().optional(), + after: z.string().optional(), + }), + handler: async ( + agent: SolanaAgentKit, + input: z.infer, + ) => { + const result = await get_assets_by_authority(agent, input); + + return { + status: "success", + message: "Assets retrieved successfully", + result, + }; + }, +}; + +export default getAssetsByAuthorityAction; diff --git a/src/actions/metaplex/getAssetsByCreator.ts b/src/actions/metaplex/getAssetsByCreator.ts new file mode 100644 index 0000000..e0fdeed --- /dev/null +++ b/src/actions/metaplex/getAssetsByCreator.ts @@ -0,0 +1,105 @@ +import { Action } from "../../types/action"; +import { SolanaAgentKit } from "../../agent"; +import { z } from "zod"; +import { get_assets_by_creator } from "../../tools/metaplex"; + +const getAssetsByCreatorAction: Action = { + name: "GET_ASSETS_BY_CREATOR", + similes: [ + "fetch assets by creator", + "retrieve assets by creator", + "get assets by creator address", + "fetch creator assets", + ], + description: `Fetch a list of assets created by a specific address using the Metaplex DAS API.`, + examples: [ + [ + { + input: { + creatorAddress: "D3XrkNZz6wx6cofot7Zohsf2KSsu2ArngNk8VqU9cTY3", + onlyVerified: true, + limit: 10, + }, + output: { + status: "success", + message: "Assets retrieved successfully", + result: { + total: 2, + limit: 10, + items: [ + { + interface: "V1_NFT", + id: "ExampleAssetId1", + content: { + json_uri: "https://example.com/asset1.json", + metadata: { + name: "Example Asset 1", + symbol: "EXA1", + }, + }, + authorities: [], + compression: {}, + grouping: [], + royalty: {}, + creators: [], + ownership: {}, + supply: {}, + mutable: true, + burnt: false, + }, + { + interface: "V1_NFT", + id: "ExampleAssetId2", + content: { + json_uri: "https://example.com/asset2.json", + metadata: { + name: "Example Asset 2", + symbol: "EXA2", + }, + }, + authorities: [], + compression: {}, + grouping: [], + royalty: {}, + creators: [], + ownership: {}, + supply: {}, + mutable: true, + burnt: false, + }, + ], + }, + }, + explanation: "Fetch a list of assets created by a specific address", + }, + ], + ], + schema: z.object({ + creatorAddress: z.string().min(1, "Creator address is required"), + onlyVerified: z.boolean(), + sortBy: z + .object({ + sortBy: z.enum(["created", "updated", "recentAction", "none"]), + sortDirection: z.enum(["asc", "desc"]), + }) + .optional(), + limit: z.number().optional(), + page: z.number().optional(), + before: z.string().optional(), + after: z.string().optional(), + }), + handler: async ( + agent: SolanaAgentKit, + input: z.infer, + ) => { + const result = await get_assets_by_creator(agent, input); + + return { + status: "success", + message: "Assets retrieved successfully", + result, + }; + }, +}; + +export default getAssetsByCreatorAction; diff --git a/src/agent/index.ts b/src/agent/index.ts index cbdd3b5..60a56b1 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -119,8 +119,11 @@ import { } from "../types"; import { DasApiAsset, + DasApiAssetList, GetAssetsByAuthorityRpcInput, + GetAssetsByCreatorRpcInput, } from "@metaplex-foundation/digital-asset-standard-api"; +import { get_assets_by_creator } from "../tools/metaplex/get_assets_by_creator"; /** * Main class for interacting with Solana blockchain @@ -833,7 +836,12 @@ export class SolanaAgentKit { } async getAssetsByAuthority( params: GetAssetsByAuthorityRpcInput, - ): Promise { + ): Promise { return get_assets_by_authority(this, params); } + async getAssetsByCreator( + params: GetAssetsByCreatorRpcInput, + ): Promise { + return get_assets_by_creator(this, params); + } } diff --git a/src/langchain/index.ts b/src/langchain/index.ts index 78b8b11..22ee136 100644 --- a/src/langchain/index.ts +++ b/src/langchain/index.ts @@ -116,6 +116,7 @@ import { SolanaWithdrawFromDriftVaultTool, SolanaGetAssetTool, SolanaGetAssetsByAuthorityTool, + SolanaGetAssetsByCreatorTool, } from "./index"; export function createSolanaTools(solanaKit: SolanaAgentKit) { @@ -212,5 +213,6 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) { new SolanaWithdrawFromDriftVaultTool(solanaKit), new SolanaGetAssetTool(solanaKit), new SolanaGetAssetsByAuthorityTool(solanaKit), + new SolanaGetAssetsByCreatorTool(solanaKit), ]; } diff --git a/src/langchain/metaplex/get_asset_by_authority.ts b/src/langchain/metaplex/get_assets_by_authority.ts similarity index 100% rename from src/langchain/metaplex/get_asset_by_authority.ts rename to src/langchain/metaplex/get_assets_by_authority.ts diff --git a/src/langchain/metaplex/get_assets_by_creator.ts b/src/langchain/metaplex/get_assets_by_creator.ts new file mode 100644 index 0000000..84def56 --- /dev/null +++ b/src/langchain/metaplex/get_assets_by_creator.ts @@ -0,0 +1,40 @@ +import { Tool } from "langchain/tools"; +import { SolanaAgentKit } from "../../agent"; + +export class SolanaGetAssetsByCreatorTool extends Tool { + name = "solana_get_assets_by_creator"; + description = `Fetch a list of assets created by a specific address using the Metaplex DAS API. + + Inputs (input is a JSON string): + creatorAddress: string, eg "N4f6zftYsuu4yT7icsjLwh4i6pB1zvvKbseHj2NmSQw" (required) + onlyVerified: boolean (optional) + sortBy: { sortBy: "created" | "updated" | "recentAction" | "none", sortDirection: "asc" | "desc" } (optional) + limit: number (optional) + page: number (optional) + before: string (optional) + after: string (optional)`; + + constructor(private solanaKit: SolanaAgentKit) { + super(); + } + + protected async _call(input: string): Promise { + try { + const parsedInput = JSON.parse(input); + + const result = await this.solanaKit.getAssetsByCreator(parsedInput); + + return JSON.stringify({ + status: "success", + message: "Assets retrieved successfully", + result, + }); + } catch (error: any) { + return JSON.stringify({ + status: "error", + message: error.message, + code: error.code || "UNKNOWN_ERROR", + }); + } + } +} diff --git a/src/langchain/metaplex/index.ts b/src/langchain/metaplex/index.ts index 3635d03..41d11c7 100644 --- a/src/langchain/metaplex/index.ts +++ b/src/langchain/metaplex/index.ts @@ -2,4 +2,5 @@ export * from "./deploy_collection"; export * from "./mint_nft"; export * from "./deploy_token"; export * from "./get_asset"; -export * from "./get_asset_by_authority"; +export * from "./get_assets_by_authority"; +export * from "./get_assets_by_creator"; diff --git a/src/tools/metaplex/get_assets_by_authority.ts b/src/tools/metaplex/get_assets_by_authority.ts index 1ddee15..b6f1199 100644 --- a/src/tools/metaplex/get_assets_by_authority.ts +++ b/src/tools/metaplex/get_assets_by_authority.ts @@ -10,6 +10,5 @@ export async function get_assets_by_authority( params: GetAssetsByAuthorityRpcInput, ) { const umi = createUmi(agent.connection.rpcEndpoint).use(dasApi()); - const assets = await umi.rpc.getAssetsByAuthority(params); - return assets.items; + return await umi.rpc.getAssetsByAuthority(params); } diff --git a/src/tools/metaplex/get_assets_by_creator.ts b/src/tools/metaplex/get_assets_by_creator.ts new file mode 100644 index 0000000..64a4ed3 --- /dev/null +++ b/src/tools/metaplex/get_assets_by_creator.ts @@ -0,0 +1,14 @@ +import { SolanaAgentKit } from "../../agent"; +import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"; +import { + dasApi, + GetAssetsByCreatorRpcInput, +} from "@metaplex-foundation/digital-asset-standard-api"; + +export async function get_assets_by_creator( + agent: SolanaAgentKit, + params: GetAssetsByCreatorRpcInput, +) { + const umi = createUmi(agent.connection.rpcEndpoint).use(dasApi()); + return await umi.rpc.getAssetsByCreator(params); +} diff --git a/src/tools/metaplex/index.ts b/src/tools/metaplex/index.ts index 0fc3fa7..41d11c7 100644 --- a/src/tools/metaplex/index.ts +++ b/src/tools/metaplex/index.ts @@ -3,3 +3,4 @@ export * from "./mint_nft"; export * from "./deploy_token"; export * from "./get_asset"; export * from "./get_assets_by_authority"; +export * from "./get_assets_by_creator";