diff --git a/.env.example b/.env.example index 200d21bd52c..8d30161cdd4 100644 --- a/.env.example +++ b/.env.example @@ -426,6 +426,23 @@ STARKNET_RPC_URL= # Lens Network Configuration LENS_ADDRESS= LENS_PRIVATE_KEY= +LENS_PROFILE_ID= # Your Lens Protocol profile ID (format: 0x1234) +LENS_DRY_RUN= # Set to 'true' to simulate posts without actually publishing +LENS_POLL_INTERVAL= # Interval in seconds to check for new interactions (default: 60) +LENS_STORAGE_PROVIDER= # Storage provider for media: 'arweave', 'pinata', or 'storj'. Default "storj" + +# Arweave Storage Configuration +ARWEAVE_JWK= # Arweave wallet JSON Web Key (JWK) for permanent storage + +# Storj Decentralized Storage Configuration +STORJ_API_USERNAME= # Storj network access grant username +STORJ_API_PASSWORD= # Storj network access grant password + +# Lens Protocol Configuration +LENS_PROFILE_ID= # Your Lens Protocol profile ID (format: 0x1234) +LENS_DRY_RUN= # Set to 'true' to simulate posts without actually publishing +LENS_POLL_INTERVAL= # Interval in seconds to check for new interactions (default: 60) +LENS_STORAGE_PROVIDER= # Storage provider for media: 'arweave', 'pinata', or 'storj'. Default "storj" # Form Chain FORM_PRIVATE_KEY= # Form character account private key @@ -595,6 +612,7 @@ STORY_PRIVATE_KEY= # Story private key STORY_API_BASE_URL= # Story API base URL STORY_API_KEY= # Story API key PINATA_JWT= # Pinata JWT for uploading files to IPFS +PINATA_GATEWAY_URL= # Pinata Gateway URL. Recommended for more consistent indexing with Lens. # Cosmos COSMOS_RECOVERY_PHRASE= # 12 words recovery phrase (need to be in quotes, because of spaces) diff --git a/packages/client-lens/package.json b/packages/client-lens/package.json index d08e3b33325..14fbecfeaa2 100644 --- a/packages/client-lens/package.json +++ b/packages/client-lens/package.json @@ -30,6 +30,7 @@ "@elizaos/core": "workspace:*", "@lens-protocol/client": "2.2.0", "@lens-protocol/metadata": "1.2.0", + "arweave": "1.15.5", "axios": "^1.7.9" }, "devDependencies": { @@ -40,4 +41,4 @@ "peerDependencies": { "@elizaos/core": "workspace:*" } -} +} \ No newline at end of file diff --git a/packages/client-lens/src/actions.ts b/packages/client-lens/src/actions.ts index 0d359be4a84..594a7b6fab5 100644 --- a/packages/client-lens/src/actions.ts +++ b/packages/client-lens/src/actions.ts @@ -8,7 +8,7 @@ import type { import { textOnly } from "@lens-protocol/metadata"; import { createPublicationMemory } from "./memory"; import type { AnyPublicationFragment } from "@lens-protocol/client"; -import type StorjProvider from "./providers/StorjProvider"; +import { StorageProvider } from "./providers/StorageProvider"; export async function sendPublication({ client, @@ -16,18 +16,28 @@ export async function sendPublication({ content, roomId, commentOn, - ipfs, + storage, }: { client: LensClient; runtime: IAgentRuntime; content: Content; roomId: UUID; commentOn?: string; - ipfs: StorjProvider; + storage: StorageProvider; }): Promise<{ memory?: Memory; publication?: AnyPublicationFragment }> { // TODO: arweave provider for content hosting const metadata = textOnly({ content: content.text }); - const contentURI = await ipfs.pinJson(metadata); + let contentURI; + + try { + const response = await storage.uploadJson(metadata); + contentURI = response.url; + } catch (e) { + elizaLogger.warn( + `Failed to upload metadata with storage provider: ${storage.provider}. Ensure your storage provider is configured correctly.` + ); + throw e; + } const publication = await client.createPublication( contentURI, diff --git a/packages/client-lens/src/index.ts b/packages/client-lens/src/index.ts index 05049d2e4fc..a1db48782a4 100644 --- a/packages/client-lens/src/index.ts +++ b/packages/client-lens/src/index.ts @@ -1,9 +1,15 @@ -import { type Client, type IAgentRuntime, elizaLogger } from "@elizaos/core"; +import { Client, IAgentRuntime, elizaLogger } from "@elizaos/core"; import { privateKeyToAccount } from "viem/accounts"; import { LensClient } from "./client"; import { LensPostManager } from "./post"; import { LensInteractionManager } from "./interactions"; -import StorjProvider from "./providers/StorjProvider"; +import { + StorageProvider, + StorageProviderEnum, +} from "./providers/StorageProvider"; +import { StorjProvider } from "./providers/StorjProvider"; +import { PinataProvider } from "./providers/PinataProvider"; +import { ArweaveProvider } from "./providers/AreweaveProvider"; export class LensAgentClient implements Client { client: LensClient; @@ -11,7 +17,7 @@ export class LensAgentClient implements Client { interactions: LensInteractionManager; private profileId: `0x${string}`; - private ipfs: StorjProvider; + private storage: StorageProvider; constructor(public runtime: IAgentRuntime) { const cache = new Map(); @@ -37,14 +43,14 @@ export class LensAgentClient implements Client { elizaLogger.info("Lens client initialized."); - this.ipfs = new StorjProvider(runtime); + this.storage = this.getStorageProvider(); this.posts = new LensPostManager( this.client, this.runtime, this.profileId, cache, - this.ipfs + this.storage ); this.interactions = new LensInteractionManager( @@ -52,11 +58,46 @@ export class LensAgentClient implements Client { this.runtime, this.profileId, cache, - this.ipfs + this.storage ); } + private getStorageProvider(): StorageProvider { + const storageProvider = this.runtime.getSetting( + "LENS_STORAGE_PROVIDER" + ); + + const storageProviderMap = { + [StorageProviderEnum.PINATA]: PinataProvider, + [StorageProviderEnum.STORJ]: StorjProvider, + [StorageProviderEnum.ARWEAVE]: ArweaveProvider, + }; + + let SelectedProvider = + storageProviderMap[storageProvider as StorageProviderEnum]; + + if (!SelectedProvider) { + elizaLogger.info( + "No valid storage provider specified, defaulting to Storj" + ); + + // Replace default provider with Lens Storage Nodes when on mainnet https://dev-preview.lens.xyz/docs/storage/using-storage + SelectedProvider = StorjProvider; + } + const selected = new SelectedProvider(this.runtime); + + elizaLogger.info( + `Using ${selected.provider} storage provider in Lens Client` + ); + + return selected; + } + async start() { + if (this.storage.initialize) { + await this.storage.initialize(); + } + await Promise.all([this.posts.start(), this.interactions.start()]); } diff --git a/packages/client-lens/src/interactions.ts b/packages/client-lens/src/interactions.ts index af1fbc114fc..16b8fbc6202 100644 --- a/packages/client-lens/src/interactions.ts +++ b/packages/client-lens/src/interactions.ts @@ -23,7 +23,7 @@ import { publicationUuid } from "./utils"; import { sendPublication } from "./actions"; import type { AnyPublicationFragment } from "@lens-protocol/client"; import type { Profile } from "./types"; -import type StorjProvider from "./providers/StorjProvider"; +import { StorageProvider } from "./providers/StorageProvider"; export class LensInteractionManager { private timeout: NodeJS.Timeout | undefined; @@ -32,7 +32,7 @@ export class LensInteractionManager { public runtime: IAgentRuntime, private profileId: string, public cache: Map, - private ipfs: StorjProvider + private storage: StorageProvider ) {} public async start() { @@ -280,7 +280,7 @@ export class LensInteractionManager { content: content, roomId: memory.roomId, commentOn: publication.id, - ipfs: this.ipfs, + storage: this.storage, }); if (!result.publication?.id) throw new Error("publication not sent"); diff --git a/packages/client-lens/src/post.ts b/packages/client-lens/src/post.ts index a7ffdb7f59f..f025edad0bd 100644 --- a/packages/client-lens/src/post.ts +++ b/packages/client-lens/src/post.ts @@ -11,7 +11,7 @@ import { formatTimeline, postTemplate } from "./prompts"; import { publicationUuid } from "./utils"; import { createPublicationMemory } from "./memory"; import { sendPublication } from "./actions"; -import type StorjProvider from "./providers/StorjProvider"; +import { StorageProvider } from "./providers/StorageProvider"; export class LensPostManager { private timeout: NodeJS.Timeout | undefined; @@ -21,7 +21,7 @@ export class LensPostManager { public runtime: IAgentRuntime, private profileId: string, public cache: Map, - private ipfs: StorjProvider + private storage: StorageProvider ) {} public async start() { @@ -105,7 +105,7 @@ export class LensPostManager { runtime: this.runtime, roomId: generateRoomId, content: { text: content }, - ipfs: this.ipfs, + storage: this.storage, }); if (!publication) throw new Error("failed to send publication"); diff --git a/packages/client-lens/src/providers/AreweaveProvider.ts b/packages/client-lens/src/providers/AreweaveProvider.ts new file mode 100644 index 00000000000..ca543274282 --- /dev/null +++ b/packages/client-lens/src/providers/AreweaveProvider.ts @@ -0,0 +1,104 @@ +import { elizaLogger, type IAgentRuntime } from "@elizaos/core"; +import { + StorageProvider, + StorageProviderEnum, + UploadResponse, +} from "./StorageProvider"; +import Arweave from "arweave"; +import { JWKInterface } from "arweave/node/lib/wallet"; + +export class ArweaveProvider implements StorageProvider { + provider = StorageProviderEnum.ARWEAVE; + private arweave: Arweave; + private jwk: JWKInterface; + + constructor(runtime: IAgentRuntime) { + // Initialize Arweave client + this.arweave = Arweave.init({ + host: "arweave.net", + port: 443, + protocol: "https", + }); + + const jwk = runtime.getSetting("ARWEAVE_JWK"); + if (!jwk) { + elizaLogger.warn( + "To use Arweave storage service you need to set ARWEAVE_JWK in environment variables." + ); + } + + try { + this.jwk = JSON.parse(jwk || "{}") as JWKInterface; + } catch (error) { + elizaLogger.error("Failed to parse Arweave JWK:", error); + throw new Error("Invalid Arweave JWK format"); + } + } + + async uploadFile(file: { + buffer: Buffer; + originalname: string; + mimetype: string; + }): Promise { + // Create transaction + const transaction = await this.arweave.createTransaction( + { + data: file.buffer, + }, + this.jwk + ); + + // Add tags + transaction.addTag("Content-Type", file.mimetype); + transaction.addTag("File-Name", file.originalname); + + // Sign the transaction + await this.arweave.transactions.sign(transaction, this.jwk); + + // Submit the transaction + const response = await this.arweave.transactions.post(transaction); + + if (response.status !== 200) { + throw new Error(`Upload failed with status ${response.status}`); + } + + return { + cid: transaction.id, + url: `https://arweave.net/${transaction.id}`, + }; + } + + async uploadJson( + json: Record | string + ): Promise { + // Convert to string if object + const stringifiedData = + typeof json === "string" ? json : JSON.stringify(json); + + // Create transaction + const transaction = await this.arweave.createTransaction( + { + data: stringifiedData, + }, + this.jwk + ); + + // Add tags + transaction.addTag("Content-Type", "application/json"); + + // Sign the transaction + await this.arweave.transactions.sign(transaction, this.jwk); + + // Submit the transaction + const response = await this.arweave.transactions.post(transaction); + + if (response.status !== 200) { + throw new Error(`Upload failed with status ${response.status}`); + } + + return { + cid: transaction.id, + url: `https://arweave.net/${transaction.id}`, + }; + } +} \ No newline at end of file diff --git a/packages/client-lens/src/providers/PinataProvider.ts b/packages/client-lens/src/providers/PinataProvider.ts new file mode 100644 index 00000000000..eec22719bd6 --- /dev/null +++ b/packages/client-lens/src/providers/PinataProvider.ts @@ -0,0 +1,112 @@ +import { + type StorageProvider, + StorageProviderEnum, + type UploadResponse, +} from "./StorageProvider"; +import { elizaLogger, type IAgentRuntime } from "@elizaos/core"; +import axios, { type AxiosInstance } from "axios"; + +export class PinataProvider implements StorageProvider { + provider = StorageProviderEnum.PINATA; + + private PINATA_API_URL = "https://api.pinata.cloud"; + private PINATA_JWT: string; + private PINATA_GATEWAY_URL: string; + private client: AxiosInstance; + + constructor(runtime: IAgentRuntime) { + this.PINATA_JWT = runtime.getSetting("PINATA_JWT")!; + this.PINATA_GATEWAY_URL = runtime.getSetting("PINATA_GATEWAY_URL")!; + + this.client = this.createClient(); + + if (!this.PINATA_JWT) { + elizaLogger.warn( + "To use Pinata IPFS service you need to set PINATA_JWT in environment variables. Get your key at https://pinata.cloud" + ); + } + + if (!this.PINATA_GATEWAY_URL) { + elizaLogger.warn( + "It's recommended to set PINATA_GATEWAY_URL so Lens indexing of 4000ms doesn't get exceeded" + ); + } + } + + private createClient(): AxiosInstance { + return axios.create({ + baseURL: this.PINATA_API_URL, + headers: { + Authorization: `Bearer ${this.PINATA_JWT}`, + "Content-Type": "application/json", + }, + }); + } + + async uploadFile(file: { + buffer: Buffer; + originalname: string; + mimetype: string; + }): Promise { + const formData = new FormData(); + + // Create a Blob from the buffer + const blob = new Blob([file.buffer], { type: file.mimetype }); + + // Append the file to FormData + formData.append("file", blob, file.originalname); + + const { data } = await this.client.post( + "/pinning/pinFileToIPFS", + formData, + { + headers: { + "Content-Type": `multipart/form-data`, + }, + maxContentLength: Number.POSITIVE_INFINITY, + maxBodyLength: Number.POSITIVE_INFINITY, + } + ); + + const url = this.resolveUrl(data.IpfsHash); + + return { + cid: data.IpfsHash, + url, + }; + } + + async uploadJson( + json: Record | string + ): Promise { + const data = typeof json === "string" ? JSON.parse(json) : json; + + const { data: result } = await this.client.post( + "/pinning/pinJSONToIPFS", + { + pinataOptions: { + cidVersion: 1, + }, + pinataMetadata: { + name: "content.json", + }, + pinataContent: data, + } + ); + + const url = this.resolveUrl(result.IpfsHash); + + return { + cid: result.IpfsHash, + url, + }; + } + + private resolveUrl(cid: string): string { + if (this.PINATA_GATEWAY_URL) { + return `https://${this.PINATA_GATEWAY_URL}/ipfs/${cid}`; + } + + return `https://gateway.pinata.cloud/ipfs/${cid}`; + } +} \ No newline at end of file diff --git a/packages/client-lens/src/providers/StorageProvider.ts b/packages/client-lens/src/providers/StorageProvider.ts new file mode 100644 index 00000000000..18f0617ff63 --- /dev/null +++ b/packages/client-lens/src/providers/StorageProvider.ts @@ -0,0 +1,23 @@ +import { IAgentRuntime } from "@elizaos/core"; + +export interface UploadResponse { + cid: string; + url: string; +} + +export enum StorageProviderEnum { + PINATA = "pinata", + STORJ = "storj", + ARWEAVE = "arweave", +} + +export interface StorageProvider { + provider: StorageProviderEnum; + initialize?: () => Promise; + uploadFile(file: { + buffer: Buffer; + originalname: string; + mimetype: string; + }): Promise; + uploadJson(json: Record | string): Promise; +} \ No newline at end of file diff --git a/packages/client-lens/src/providers/StorjProvider.ts b/packages/client-lens/src/providers/StorjProvider.ts index bdd2aa5ede1..9d8b9c774d6 100644 --- a/packages/client-lens/src/providers/StorjProvider.ts +++ b/packages/client-lens/src/providers/StorjProvider.ts @@ -1,10 +1,16 @@ -import axios, { type AxiosInstance } from "axios"; +import axios, { AxiosInstance } from "axios"; import FormData from "form-data"; -import type { IAgentRuntime } from "@elizaos/core"; +import { elizaLogger, type IAgentRuntime } from "@elizaos/core"; +import { + StorageProvider, + StorageProviderEnum, + UploadResponse, +} from "./StorageProvider"; // ipfs pinning service: https://storj.dev/dcs/api/storj-ipfs-pinning -class StorjProvider { - private STORJ_API_URL = "https://www.storj-ipfs.com"; +export class StorjProvider implements StorageProvider { + provider = StorageProviderEnum.STORJ; + private STORJ_API_URL: string = "https://www.storj-ipfs.com"; private STORJ_API_USERNAME: string; private STORJ_API_PASSWORD: string; private baseURL: string; @@ -13,6 +19,11 @@ class StorjProvider { constructor(runtime: IAgentRuntime) { this.STORJ_API_USERNAME = runtime.getSetting("STORJ_API_USERNAME")!; this.STORJ_API_PASSWORD = runtime.getSetting("STORJ_API_PASSWORD")!; + if (!this.STORJ_API_USERNAME || !this.STORJ_API_PASSWORD) { + elizaLogger.warn( + "To use Storj ipfs pinning service you need to set STORJ_API_USERNAME or STORJ_API_PASSWORD in environment variables. Get your keys at https://storj.io" + ); + } this.baseURL = `${this.STORJ_API_URL}/api/v0`; this.client = this.createClient(); } @@ -37,12 +48,19 @@ class StorjProvider { return `${this.STORJ_API_URL}/ipfs/${this.hash(uriOrHash)}`; } - public async pinJson(json: any): Promise { - if (typeof json !== "string") { - json = JSON.stringify(json); - } + public async uploadJson( + uploadData: Record | string + ): Promise { + const stringifiedData = + typeof uploadData === "string" + ? uploadData + : JSON.stringify(uploadData); const formData = new FormData(); - formData.append("path", Buffer.from(json, "utf-8").toString()); + + formData.append( + "path", + Buffer.from(stringifiedData, "utf-8").toString() + ); const headers = { "Content-Type": "multipart/form-data", @@ -55,14 +73,17 @@ class StorjProvider { { headers } ); - return this.gatewayURL(data.Hash); + return { + url: this.gatewayURL(data.Hash), + cid: data.Hash, + }; } - public async pinFile(file: { + public async uploadFile(file: { buffer: Buffer; originalname: string; mimetype: string; - }): Promise { + }): Promise { const formData = new FormData(); formData.append("file", file.buffer, { filename: file.originalname, @@ -73,12 +94,13 @@ class StorjProvider { headers: { "Content-Type": `multipart/form-data; boundary=${formData.getBoundary()}`, }, - maxContentLength: Number.POSITIVE_INFINITY, - maxBodyLength: Number.POSITIVE_INFINITY, + maxContentLength: Infinity, + maxBodyLength: Infinity, }); - return this.gatewayURL(response.data.Hash); + return { + url: this.gatewayURL(response.data.Hash), + cid: response.data.Hash, + }; } } - -export default StorjProvider; diff --git a/packages/client-lens/src/utils.ts b/packages/client-lens/src/utils.ts index d9818a00a85..0f8966515d0 100644 --- a/packages/client-lens/src/utils.ts +++ b/packages/client-lens/src/utils.ts @@ -1,4 +1,7 @@ import { stringToUuid } from "@elizaos/core"; +import { + ProfileMetadataFragment, +} from "@lens-protocol/client"; import type { BroadcastResult } from "./types"; export function publicationId({ @@ -62,11 +65,23 @@ export const handleBroadcastResult = ( } }; -export const getProfilePictureUri = (picture: any): string | undefined => { - if ("optimized" in picture) { - return picture.optimized?.uri || picture.raw?.uri || picture.uri; - } else { - return picture.uri; +export const getProfilePictureUri = ( + picture?: ProfileMetadataFragment["picture"] +): string | undefined => { + if (!picture) { + return; + } + + if (picture.__typename === "ImageSet") { + return ( + picture.optimized?.uri || picture.raw?.uri || picture.thumbnail?.uri + ); + } else if (picture.__typename === "NftImage") { + return ( + picture.image.optimized?.uri || + picture.image.raw?.uri || + picture.image.thumbnail?.uri + ); } }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b1aeacb66b4..26934cf06c3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1206,6 +1206,9 @@ importers: '@lens-protocol/metadata': specifier: 1.2.0 version: 1.2.0(zod@3.24.1) + arweave: + specifier: 1.15.5 + version: 1.15.5 axios: specifier: ^1.7.9 version: 1.7.9 @@ -4361,7 +4364,7 @@ importers: version: link:../plugin-trustdb '@solana/spl-token': specifier: 0.4.9 - version: 0.4.9(@solana/web3.js@1.95.8(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(utf-8-validate@5.0.10) + version: 0.4.9(@solana/web3.js@1.95.8(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: npm:@solana/web3.js@1.95.8 version: 1.95.8(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) @@ -4373,7 +4376,7 @@ importers: version: 5.0.0 fomo-sdk-solana: specifier: 1.3.2 - version: 1.3.2(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(utf-8-validate@5.0.10) + version: 1.3.2(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3)(utf-8-validate@5.0.10) form-data: specifier: 4.0.1 version: 4.0.1 @@ -4382,16 +4385,16 @@ importers: version: 5.1.2 pumpdotfun-sdk: specifier: 1.3.2 - version: 1.3.2(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(rollup@4.34.4)(typescript@5.6.3)(utf-8-validate@5.0.10) + version: 1.3.2(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(rollup@4.34.4)(typescript@5.7.3)(utf-8-validate@5.0.10) solana-agent-kit: specifier: ^1.4.0 - version: 1.4.4(@noble/hashes@1.7.1)(@solana/buffer-layout@4.0.1)(@swc/core@1.10.14(@swc/helpers@0.5.15))(@types/node@20.17.9)(arweave@1.15.5)(axios@1.7.9)(borsh@2.0.0)(buffer@6.0.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(handlebars@4.7.8)(react@19.0.0)(sodium-native@3.4.1)(typescript@5.6.3)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + version: 1.4.4(@noble/hashes@1.7.1)(@solana/buffer-layout@4.0.1)(@swc/core@1.10.14(@swc/helpers@0.5.15))(@types/node@22.13.1)(arweave@1.15.5)(axios@1.7.9)(borsh@2.0.0)(buffer@6.0.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(handlebars@4.7.8)(react@19.0.0)(sodium-native@3.4.1)(typescript@5.7.3)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) tsup: specifier: 8.3.5 - version: 8.3.5(@swc/core@1.10.14(@swc/helpers@0.5.15))(jiti@2.4.2)(postcss@8.5.1)(tsx@4.19.2)(typescript@5.6.3)(yaml@2.7.0) + version: 8.3.5(@swc/core@1.10.14(@swc/helpers@0.5.15))(jiti@2.4.2)(postcss@8.5.1)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0) vitest: specifier: 2.1.9 - version: 2.1.9(@types/node@20.17.9)(jsdom@25.0.1(bufferutil@4.0.9)(canvas@2.11.2(encoding@0.1.13))(utf-8-validate@5.0.10))(terser@5.38.0) + version: 2.1.9(@types/node@22.13.1)(jsdom@25.0.1(bufferutil@4.0.9)(canvas@2.11.2(encoding@0.1.13))(utf-8-validate@5.0.10))(terser@5.38.0) whatwg-url: specifier: 7.1.0 version: 7.1.0 @@ -4416,7 +4419,7 @@ importers: version: link:../plugin-trustdb '@solana/spl-token': specifier: 0.4.9 - version: 0.4.9(@solana/web3.js@1.95.8(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3)(utf-8-validate@5.0.10) + version: 0.4.9(@solana/web3.js@1.95.8(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: npm:@solana/web3.js@1.95.8 version: 1.95.8(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) @@ -4431,7 +4434,7 @@ importers: version: 5.0.0 fomo-sdk-solana: specifier: 1.3.2 - version: 1.3.2(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3)(utf-8-validate@5.0.10) + version: 1.3.2(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(utf-8-validate@5.0.10) form-data: specifier: 4.0.1 version: 4.0.1 @@ -4440,16 +4443,16 @@ importers: version: 5.1.2 pumpdotfun-sdk: specifier: 1.3.2 - version: 1.3.2(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(rollup@4.34.4)(typescript@5.7.3)(utf-8-validate@5.0.10) + version: 1.3.2(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(rollup@4.34.4)(typescript@5.6.3)(utf-8-validate@5.0.10) solana-agent-kit: specifier: ^1.2.0 - version: 1.4.4(@noble/hashes@1.7.1)(@solana/buffer-layout@4.0.1)(@swc/core@1.10.14(@swc/helpers@0.5.15))(@types/node@22.13.1)(arweave@1.15.5)(axios@1.7.9)(borsh@2.0.0)(buffer@6.0.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(handlebars@4.7.8)(react@19.0.0)(sodium-native@3.4.1)(typescript@5.7.3)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + version: 1.4.4(@noble/hashes@1.7.1)(@solana/buffer-layout@4.0.1)(@swc/core@1.10.14(@swc/helpers@0.5.15))(@types/node@20.17.9)(arweave@1.15.5)(axios@1.7.9)(borsh@2.0.0)(buffer@6.0.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(handlebars@4.7.8)(react@19.0.0)(sodium-native@3.4.1)(typescript@5.6.3)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) tsup: specifier: 8.3.5 - version: 8.3.5(@swc/core@1.10.14(@swc/helpers@0.5.15))(jiti@2.4.2)(postcss@8.5.1)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0) + version: 8.3.5(@swc/core@1.10.14(@swc/helpers@0.5.15))(jiti@2.4.2)(postcss@8.5.1)(tsx@4.19.2)(typescript@5.6.3)(yaml@2.7.0) vitest: specifier: 2.1.9 - version: 2.1.9(@types/node@22.13.1)(jsdom@25.0.1(bufferutil@4.0.9)(canvas@2.11.2(encoding@0.1.13))(utf-8-validate@5.0.10))(terser@5.38.0) + version: 2.1.9(@types/node@20.17.9)(jsdom@25.0.1(bufferutil@4.0.9)(canvas@2.11.2(encoding@0.1.13))(utf-8-validate@5.0.10))(terser@5.38.0) whatwg-url: specifier: 7.1.0 version: 7.1.0 @@ -47900,7 +47903,7 @@ snapshots: dependencies: '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/safe-json': 1.0.2 - cross-fetch: 3.1.8(encoding@0.1.13) + cross-fetch: 3.2.0(encoding@0.1.13) events: 3.3.0 transitivePeerDependencies: - encoding @@ -49244,7 +49247,6 @@ snapshots: arconnect@0.4.2: dependencies: arweave: 1.15.5 - optional: true are-docs-informative@0.0.2: {} @@ -49364,7 +49366,6 @@ snapshots: asn1.js: 5.4.1 base64-js: 1.5.1 bignumber.js: 9.1.2 - optional: true ask-sdk-core@2.14.0(ask-sdk-model@1.86.0): dependencies: @@ -53795,7 +53796,7 @@ snapshots: extract-zip@2.0.1: dependencies: - debug: 4.3.4 + debug: 4.4.0(supports-color@8.1.1) get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: