diff --git a/README.md b/README.md index 7d49bc6..f56e1f3 100644 --- a/README.md +++ b/README.md @@ -183,60 +183,14 @@ import { PublicKey } from "@solana/web3.js"; ### Fetch Price Data from Pyth ```typescript -import { pythFetchPrice } from "solana-agent-kit"; -const price = await pythFetchPrice( - agent, +const price = await agent.pythFetchPrice( "0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43" ); console.log("Price in BTC/USD:", price); ``` -## API Reference - -### Core Functions - -#### `deploy_token(agent, decimals?, name, uri, symbol, initialSupply?)` - -Deploy a new SPL token with optional initial supply. If not specified, decimals default to 9. - -#### `deploy_collection(agent, options)` - -Create a new NFT collection with customizable metadata and royalties. - -#### `mintCollectionNFT(agent, collectionMint, metadata, recipient?)` - -Mint a new NFT as part of an existing collection. - -#### `transfer(agent, to, amount, mint?)` - -Transfer SOL or SPL tokens to a recipient. - -#### `trade(agent, outputMint, inputAmount, inputMint?, slippageBps?)` - -Swap tokens using Jupiter Exchange integration. - -#### `get_balance(agent, token_address)` - -Check SOL or token balance for the agent's wallet. - -#### `lendAsset(agent, assetMint, amount, apiKey)` - -Lend idle assets to earn interest with Lulo. - -#### `stakeWithJup(agent, amount)` - -Stake SOL with Jupiter to earn rewards. - -#### `sendCompressedAirdrop(agent, mintAddress, amount, recipients, priorityFeeInLamports?, shouldLog?)` - -Send an SPL token airdrop to many recipients at low cost via ZK Compression. - -#### `pythFetchPrice(agent, priceFeedID)` - -Fetch price data from Pyth's Hermes service. - ## Dependencies The toolkit relies on several key Solana and Metaplex libraries: diff --git a/docs/assets/navigation.js b/docs/assets/navigation.js index 73cf8f1..bcaae4e 100644 --- a/docs/assets/navigation.js +++ b/docs/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAE4XTQUvDMBTA8e+Sc7E4dEhvw9KDzm1ob+IhxNc1LH0vJC+gyL67bBNdXfZ26SX//l4T0tcvxfDBqlIv5DTq2RqQHy2rQnnNvaqUcTpGiOV4/arnwalCbSy+q+p6crctfqV7cg4MW8IavKPPAfDIs8gQOm0glrlwDE9up1l46XfPeEH9qUQygGYKeeiwJr3eAJt+FayBZ4ieMEJWOs0k9CF5yxBa2gDWmnWW/B9J4Dw5mhlDCbkG1tZF8WvP59KQJ4v8d/SLphVnnK2lEas0+C7hXCc0vchny0t0k3B/nNLlynQSa3ZXCA6/TkvkjtAu4X7vsTyJxuL0Zvv2DYU9ByOnAwAA" \ No newline at end of file +window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAE42TwU7DMAyG3yXniooJJtTbRNUDDJigN8QhCi6JltpR40hMaO+OtiFYWebtkos/f7asP69fiuGTVaVeyGvUsw9AvnesChU0W1Up43WMEMtx/cJy71Whlg7fVXU5uVkXv6Zb8h4MO8IagqdVD7jnc8gwdNpALHPgWDy5nmbFT2HzxhPWH0pUDqCZhrxoV5PaG2BjF4Mz8AwxEEbImg4xSXqXgmMYWloC1pp1VvkfkoTz5GlmDCXkGlg7H8Vtj+PSkAeH/Hf6x6YVZxylpRGL1Icu4VwnNFbUZ8lT6ibh9pxSuDKcqF2xPTMjeVSSm00+YfcvWyK/t3GXcHvYWB5AY+P0av32DUTvPWMEBAAA" \ No newline at end of file diff --git a/docs/assets/search.js b/docs/assets/search.js index 0bcb10d..b0786c5 100644 --- a/docs/assets/search.js +++ b/docs/assets/search.js @@ -1 +1 @@ -window.searchData = "data:application/octet-stream;base64,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"; \ No newline at end of file +window.searchData = "data:application/octet-stream;base64,H4sIAAAAAAAAE7Wd33OcOBLH/xf8OuUEkPjhNyc+V+Uuu0kl3r2HqZQLD/KEMwMsaOKbS+V/vxIwQ/eoGTeD9ylbHnX3V9JHLSGQ9qdTl8+Nc7X86TxlRepcuV60cIpko5wr52uZJ0VyvVaF/lemnYWzrXPnylnlSdOo5g3++fK73uTOYv+rc+U4vxZ7r9L1Dl5XZdHoervSZc1xeYHLA/cLp0pqVWhb6RDYfesJGLlQK52VBTfwUHxO3OckzxWr/S4ORefHu0/StFZNMyEuMJkTv6xUkWT3SZXdP6kdK75lMjG+91YM3Nbqr61q9G2yXSl9uy1SXhuQZnN0pKrKy91d+aR4wOHy8yO/L/N8Au+E0RwNa6XfJXlSrBQrOio+J+4mK/Tvt3esoEPZORF1nRTNo+KlM1B4HuPrrNGqvik3ScbrX8tkXvymzH+or2U+SYFlNJOwz3W2SerdBA2E0cy+T3mA70vOiZarIr1uGqV5GQ0Vn9nSd5+/ctu3Kzo3nkmDN4lO3u2uJ0xkY5avp+YuWz0xx/qI4Rwtj0qvvrdOP9cZM7XaNrMYTLbF6vvn7aa63Rb8yY00m6Oj0ckTr/77krOiqSJ9X24qg5NKr7M6rcuKF33Eco6aVa0SrT7Vq+RrVqxz9TVLVfrv71mdV2WZ81a3L7l4hdnhOu8TPXcBZlvNHLefnguVTpRBmr2Gjt7bbVnffbyZJOXYcqaaoWZ3H2/YjWJZzVfxpV+SnNNH4+Yzdf2WZMXgb9rSYsR21lhKdmm23bxvx+v1ZvOn4A0myuzVdLzPN5vpMnqr11NRnaWimq3CPK4+lOVT5/C3pH5iPt+PGM7RUu3091szw/MXBJbJxPiBOJqJupJ3ZZkPw/dxW7SPkc0bq8zJvSJPBgfvbTOBfaKs0Kp+TFaqedP/dNIV2pU43g4Z8XXx0h7IXtNImErVK1XoZK1ejISKcoOh5jk8q3+q2qYmQx4X4jdZ+w/b5UVffKQmltaRoNs6mxCzKz0zZF3uklzv3iVN1nwus0JPaMgL0nimoFXX7VNkAJPpwWmobtoNoY0xP6ljKMdHa3WwPn6644S4oMxfqjaozoioJlsXid7WL0B/LAaanSUCNv9vWaGH4r/f3n1RTVUWDalptDC/I8wW2HTXF70ZXd3xOoyJUDpJE52cI2QwPV8M7AD4iHoirRLF+I2unzOtFTmvjfm9GGzoelK6x8KrXK3rZDMt/mA0W8CzemgyTSI9Gn+wmR0+KzKdJfnH7K9tlmZ69/XTx0lSaPvZspo8q6pkrd5Vk4i7wHazZVR1VtaZ3t2qaR2E7c6RcTwMH7fFx3bb6FQOJAvyh+LJnD/um5H06RpMTMMnFJxMwdOC9zn0D3rpdUoDsnwFKaqu6fX+CRF7m/PCQ+g+bvPyerUqt4W+UTrJ8uYUeeOlJ8wEpU7yP5N8e06EC2RNV/9ElUazo9lSafQ/krpQ6TmyLA+vJa1WSa6zjbqudufowuavJapRWmfFmszZLykCtjPkBFL6A8T393pXnYXTXs3lwcVUUZeHCo19G/Bc0Oueidou947OVriv5Nh2QZ6Xzyr9XJe6XMF9jRmaCZ9/l/zv5UY9JGflLUs28PV3yd1kRbbZbr4k9KJwqmLs7hVFw8nin9sq06o+vOGjhB+XeZXtKtLpi/tWltyJmz501JN7PtyQzW7zAF5bvRj0UH5e2FStsk1CD206MLCYF1on9HxBh+1LzwuZl+vyjy8f+FEHg5nNnGT57v5HmW+ngHVkNU/CY63U/9R9stXf20cUvgzCcp4Us2o/R4hlN09GpepNUqhC36fmuX4k79JSSNt5ctR/tSqasb0WWgaymRyeu2Z6KfZLayXLHsge3RvNirVaPZUfyNU3U9EldjNZ3enJb3h9dOoJyS414cFcJ3pL4jDi9eJgQdeVkDz6UPakCrrxx2IPJnODV6bQh+KPrzfvpwjAZnNFbFTTjLzCGhMwmMwNvirTSZH78meERRtO6KXoyR0nsuRrkH3C80t0j8g/BdmtUumHm6k6sOmriTlLxisJOEH7KQkvET9NxBj1pxScJH8s/LeFkxWp+q9z9dP5oWqT7J0rx7v0L2Nn4TxmKk/NiZD9g8Cq3PSvANNytW3/81tf7E+1al85Xi270m/eOovl24VwL+M4/PZtsdwbtz+0f9j7GP7SGrrOYulShq5l6CJDz1ksPcrQsww9ZOg7i6VPGfqWoY8MhbNYCspQWIYCGUpnsZSUobQMJTIMnMUyoAwDyzBAhqGzWIaUYWgZhsgwchbLiDKMLMMIGcbOYhlThrFlGGMADA8uyY5rw+Me0dPiQ/NDAIQJcg0XLsmQa0PkYopcw4ZLcuTaILmYJNfw4ZIsuTZMLqbJNYy4JE+uDZSLiXINJy7JlGtD5WKqXMOKS3Ll2mC5mCzX8OKSbLk2XC6myzXMuCRfrg2YiwnzDDMeSZhnE+ZhwjzDjEcS5tmEeUc5qk1SdJYi0hQmzDPMeCRhnk2YhwnzDDMeSZhnE+ZhwjzDjEcS5tmEeZgwzzDjkYR5NmEeJswzzHgkYZ5NmIcJ8wwzHkmYZxPmYcI8w4xHEubZhHmYMN8w45OE+TZhPibMN8z4JGG+TZiPCfMNMz5JmG8T5h/NhO1USM+FxGSICfMNMz5JmG8T5mPCfMOMTxLm24T5mDDfMOOThPk2YT4mzDfM+CRhvk2YjwnzDTN+tPCDyyiKsbFNmI8J8w0zPkmYbxPmY8KEYUaQhAmbMIEJE4YZ4VKyhU2YwIQJw4wgCRM2YQITJgwzgiRM2ISJo/VWu+CiV1zEkgsTJgwzgiRM2IQJTJgwzAiSMGETJjBhwjAjQrK1bcIEJkwYZgSZw4RNmMCECcOMiMnINmECEyYNM5IkTNqESUyYNMxIModJmzCJCZOGGUkSJm3CJCZMGmYkSZi0CZOYMGmYkSRh0iZMHq3q22U9va4nFvaYMGmYkSRh0iZMYsKkYUaSOUzahElMmDTMSJIwaRMmMWEyHmVb2oRJTFjwdhTPwCYswIQFLWFk9gxswgJMWGCYCUi2A5uwABMWGGYCku3AJizAhAWGmYBkO7AJCzBhgWEmINkObMKCo2fH9uGRZDsgHh8xYYFhJiDZDmzCAkxYYJgJArKfbcICTFhgmAlItgObsAATFhpmApLt0CYsxISFhpmAJCy0CQsxYaFhJiQJC23CQkxYaJgJScJCm7AQExaK0TVJaBMWYsJCOboyCG3CQkxYaJgJSbZDm7DwaIei3aIg2Q6JTQpMWGiYCUm2Q5uwEBMWGmZCku3QJizEhEWGmZDM25FNWIQJiwwzIcl2ZBMWYcKiljB6b8YmLMKERS1hJNuRTViECYsMMxHJdmQTFmHCIjmaDCKbsAgTFhlmInJgRDZhESYsMsxEJJ6RTVh0tA/WboT5pGxiKwwTFhlmIhLPyCYswoTFhpmIxDO2CYsxYbFhJiJbO7YJizFhsWEmIif32CYsxoTFhpmIxDO2CYsxYbEYbe3YJizGhMWGmYjee7QJizFhsWEmJtmObcJiTFgcjre2TViMCYuj8da2Cev/1O7g/1C1VumHbid/uTy8wv7p3Pfb+8Hh5dZPJ4icq5+/Fk4kzb+/hm399q+HnX3zm4l4+Jho8OZHgze/9xYKnrfuu7dq+O4NiARuw7csd91bj8FFFA4uYq8ziiOmq/4deZYij+7gMQqYnvZHTIi2E6AnxFR/KTiGBVxK4JLXqYPLcn+uBfh7C/xx+2G4IGtw5A1+PK6b4YKvwQ/oApfnpz1mWtarpGlvNGjMjQbPw40GQKIAGnkId86b9gyrLo8Y9kH3+szu3Z9sBV4Axn44xQvuSFA5wasc/tZqcBWCekU8JoYv5IAbHwxxXsU65lfgLiowOIGoCc50d+cIkAVUsfz05wxA7gJjJuDBDj9aAlUCjiJen7WXurQvwevDpwrAIRiFEa92rcO2kfpX62C8AHkejwP7uznQ8KDlI97YXiud5HnaXaugzQtqKA8Q4fGQ6PzVh/sjBufIcQwcx1zHD/trzAZHwA/bjVEzyEr7qyRAugCd4vM6Za20+Wx+rLZgtHu8LLZ32Ht7LGudo4nUA13t8ThcK111F3TZdXZBbnN542StdAu1OaX0sCPmZhfQ47LpAT51f68TcAn622V3uK6wLtB0Lq/phg/1QY4CWkLeYOuPN+b7440Nnj0lWHlI3spjfyBI9QeCgDwwNwQ8Z//pvlk89ABKLWDVEPosd93FVFV3SsyaJDzg0OM1n7l1LelvXQPdCUaXyxtd5gPs9n4DUD/Q9iGPrHybl0l3ziHtzjlQE0YA6hnwGu7w+ROYdkAlY7dfifPYHc5xA9JAipO8FLd3c9RuEoyCgNeN/RmSuv28GfQA0BTy5vzuoCZYoQExIu6MAmb1jr4CB7rgsoiva1hiFY+aAkMAv4KXHo3f4hFV2QWt5vKq2haHQgChomcr5GWM49tlARcAMLYrc4FP9zyw6S/wAbMymKF83gzVn2QDYxFk/oA3yOFVMkAMAM1nO7K+7QeQAYcRL0tYi8kYoBDzEmHr41Gp9OgpHS6reN3XesqKbZOukCfAQczDc3/a/VGh2knQd5KX+fqpp5uHqCEowRCUvCEIpzPiYV+CsSR56dDcGTU8cyDKQOP5zG5AzsgHGFDnmEdaf8lXNzKTzeaHQCpBlX1elZHDVXt3GfAHnrB8Xr7F/qojf2Ah5DMr3B9nTiqU0wKQggLeANs/CBErblBNl1nN7h7tx/Ye7cfuHm2gDohjumtvhRx5ZgHseTz2en9NmRO1BZ3gMjuhu/7pwVz/VPXXP4FJCzgUPIfmvtDV4b7QZH9fKKgz8Olxfe6PmYOOAE0X8DIVuPMCVBFkPBF2lpI32ewvLnnATz4SMCJ5kHQbc4m5qu4pQxMymG14ib2/LRa0N9zR5A2B/VkNkM9Ap0X97nnMWx/sT7uCaRgoCnkN1B0hBS5Akgh5c8pwARDoKlAtyWOxnZOOJnIgJuKh09588aO7+QIwDRom4LVufy03yAFgXLi8lDLc6Q7cwP1r3nxzuOEJtC+okOSxd/TkI4AHwfOw/59QgMkJzE0TXNxTr0KAHJ6r/b1PoFWAE8nw8m3hVFml8qxQztXy269f/wdrfe1E92QAAA=="; \ No newline at end of file diff --git a/docs/classes/SolanaAgentKit.html b/docs/classes/SolanaAgentKit.html index b767597..eccbc8c 100644 --- a/docs/classes/SolanaAgentKit.html +++ b/docs/classes/SolanaAgentKit.html @@ -1,7 +1,7 @@ SolanaAgentKit | solana-agent-kit

Class SolanaAgentKit

Main class for interacting with Solana blockchain -Provides a unified interface for token operations, NFT management, and trading

+Provides a unified interface for token operations, NFT management, trading and more

SolanaAgentKit

-

Constructors

Constructors

  • Parameters

    • private_key: string
    • rpc_url: string = "https://api.mainnet-beta.solana.com"
    • openai_api_key: string

    Returns SolanaAgentKit

Properties

connection: Connection

Solana RPC connection

-
openai_api_key: string
wallet: Keypair

Wallet keypair for signing transactions

-
wallet_address: PublicKey

Public key of the wallet

-

Methods

  • Parameters

    • depositTokenAmount: BN
    • depositTokenMint: PublicKey
    • otherTokenMint: PublicKey
    • initialPrice: Decimal
    • maxPrice: Decimal
    • feeTier:
          | 0.01
          | 0.02
          | 0.04
          | 0.05
          | 0.16
          | 0.3
          | 0.65
          | 1
          | 2

    Returns Promise<string>

  • Parameters

    • name: string
    • uri: string
    • symbol: string
    • decimals: number = DEFAULT_OPTIONS.TOKEN_DECIMALS
    • OptionalinitialSupply: number

    Returns Promise<{
        mint: PublicKey;
    }>

  • Parameters

    • Optionaltoken_address: PublicKey

    Returns Promise<null | number>

  • Parameters

    • account: PublicKey

    Returns Promise<string>

  • Parameters

    • tokenName: string
    • tokenTicker: string
    • description: string
    • imageUrl: string
    • Optionaloptions: PumpFunTokenOptions

    Returns Promise<{
        metadataUri: any;
        mint: string;
        signature: string;
    }>

  • Parameters

    • amount: number

    Returns Promise<string>

  • Parameters

    • collectionMint: PublicKey
    • metadata: {
          creators?: {
              address: string;
              share: number;
          }[];
          name: string;
          sellerFeeBasisPoints?: number;
          uri: string;
      }
      • Optionalcreators?: {
            address: string;
            share: number;
        }[]
      • name: string
      • OptionalsellerFeeBasisPoints?: number
      • uri: string
    • Optionalrecipient: PublicKey

    Returns Promise<MintCollectionNFTResponse>

  • Parameters

    • baseMint: PublicKey
    • quoteMint: PublicKey
    • lotSize: number = 1
    • tickSize: number = 0.01

    Returns Promise<string[]>

  • Parameters

    • marketId: PublicKey
    • baseAmount: BN
    • quoteAmount: BN
    • startTime: BN

    Returns Promise<string>

  • Parameters

    • mint1: PublicKey
    • mint2: PublicKey
    • configId: PublicKey
    • initialPrice: Decimal
    • startTime: BN

    Returns Promise<string>

  • Parameters

    • mint1: PublicKey
    • mint2: PublicKey
    • configId: PublicKey
    • mintAAmount: BN
    • mintBAmount: BN
    • startTime: BN

    Returns Promise<string>

  • Parameters

    • name: string
    • OptionalspaceKB: number

    Returns Promise<string>

  • Returns Promise<string>

  • Parameters

    • domain: string

    Returns Promise<PublicKey>

  • Parameters

    • mintAddress: string
    • amount: number
    • decimals: number
    • recipients: string[]
    • priorityFeeInLamports: number
    • shouldLog: boolean

    Returns Promise<string[]>

  • Parameters

    • amount: number

    Returns Promise<string>

  • Parameters

    • outputMint: PublicKey
    • inputAmount: number
    • OptionalinputMint: PublicKey
    • slippageBps: number = DEFAULT_OPTIONS.SLIPPAGE_BPS

    Returns Promise<string>

  • Parameters

    • to: PublicKey
    • amount: number
    • Optionalmint: PublicKey

    Returns Promise<string>

+

Constructors

  • Parameters

    • private_key: string
    • rpc_url: string = "https://api.mainnet-beta.solana.com"
    • openai_api_key: string

    Returns SolanaAgentKit

Properties

connection: Connection

Solana RPC connection

+
openai_api_key: string
wallet: Keypair

Wallet keypair for signing transactions

+
wallet_address: PublicKey

Public key of the wallet

+

Methods

  • Parameters

    • depositTokenAmount: BN
    • depositTokenMint: PublicKey
    • otherTokenMint: PublicKey
    • initialPrice: Decimal
    • maxPrice: Decimal
    • feeTier:
          | 0.01
          | 0.02
          | 0.04
          | 0.05
          | 0.16
          | 0.3
          | 0.65
          | 1
          | 2

    Returns Promise<string>

  • Parameters

    • name: string
    • uri: string
    • symbol: string
    • decimals: number = DEFAULT_OPTIONS.TOKEN_DECIMALS
    • OptionalinitialSupply: number

    Returns Promise<{
        mint: PublicKey;
    }>

  • Parameters

    • mint: string

    Returns Promise<string>

  • Returns Promise<String[]>

  • Returns Promise<string[]>

  • Parameters

    • Optionaltoken_address: PublicKey

    Returns Promise<number>

  • Parameters

    • owner: PublicKey

    Returns Promise<null | string>

  • Parameters

    • owner: PublicKey

    Returns Promise<string[]>

  • Parameters

    • tld: string

    Returns Promise<string[]>

  • Parameters

    • account: PublicKey

    Returns Promise<string>

  • Parameters

    • amount: number

    Returns Promise<string>

  • Parameters

    • collectionMint: PublicKey
    • metadata: {
          creators?: {
              address: string;
              share: number;
          }[];
          name: string;
          sellerFeeBasisPoints?: number;
          uri: string;
      }
      • Optionalcreators?: {
            address: string;
            share: number;
        }[]
      • name: string
      • OptionalsellerFeeBasisPoints?: number
      • uri: string
    • Optionalrecipient: PublicKey

    Returns Promise<MintCollectionNFTResponse>

  • Parameters

    • baseMint: PublicKey
    • quoteMint: PublicKey
    • lotSize: number = 1
    • tickSize: number = 0.01

    Returns Promise<string[]>

  • Parameters

    • priceFeedID: string

    Returns Promise<string>

  • Parameters

    • marketId: PublicKey
    • baseAmount: BN
    • quoteAmount: BN
    • startTime: BN

    Returns Promise<string>

  • Parameters

    • mint1: PublicKey
    • mint2: PublicKey
    • configId: PublicKey
    • initialPrice: Decimal
    • startTime: BN

    Returns Promise<string>

  • Parameters

    • mint1: PublicKey
    • mint2: PublicKey
    • configId: PublicKey
    • mintAAmount: BN
    • mintBAmount: BN
    • startTime: BN

    Returns Promise<string>

  • Parameters

    • name: string
    • OptionalspaceKB: number

    Returns Promise<string>

  • Returns Promise<string>

  • Parameters

    • domain: string

    Returns Promise<undefined | PublicKey>

  • Parameters

    • domain: string

    Returns Promise<PublicKey>

  • Parameters

    • mintAddress: string
    • amount: number
    • decimals: number
    • recipients: string[]
    • priorityFeeInLamports: number
    • shouldLog: boolean

    Returns Promise<string[]>

  • Parameters

    • amount: number

    Returns Promise<string>

  • Parameters

    • outputMint: PublicKey
    • inputAmount: number
    • OptionalinputMint: PublicKey
    • slippageBps: number = DEFAULT_OPTIONS.SLIPPAGE_BPS

    Returns Promise<string>

  • Parameters

    • to: PublicKey
    • amount: number
    • Optionalmint: PublicKey

    Returns Promise<string>

diff --git a/docs/functions/createSolanaTools.html b/docs/functions/createSolanaTools.html index ca5e484..e52f87a 100644 --- a/docs/functions/createSolanaTools.html +++ b/docs/functions/createSolanaTools.html @@ -1 +1 @@ -createSolanaTools | solana-agent-kit

Function createSolanaTools

  • Parameters

    Returns (
        | SolanaBalanceTool
        | SolanaTransferTool
        | SolanaDeployTokenTool
        | SolanaDeployCollectionTool
        | SolanaMintNFTTool
        | SolanaTradeTool
        | SolanaRequestFundsTool
        | SolanaRegisterDomainTool
        | SolanaResolveDomainTool
        | SolanaGetDomainTool
        | SolanaGetWalletAddressTool
        | SolanaPumpfunTokenLaunchTool
        | SolanaCreateImageTool
        | SolanaLendAssetTool
        | SolanaTPSCalculatorTool
        | SolanaStakeTool
        | SolanaFetchPriceTool
        | SolanaTokenDataTool
        | SolanaTokenDataByTickerTool
        | SolanaCompressedAirdropTool
        | SolanaCreateSingleSidedWhirlpoolTool
        | SolanaRaydiumCreateAmmV4
        | SolanaRaydiumCreateClmm
        | SolanaRaydiumCreateCpmm
        | SolanaOpenbookCreateMarket)[]

+createSolanaTools | solana-agent-kit

Function createSolanaTools

  • Parameters

    Returns (
        | SolanaBalanceTool
        | SolanaTransferTool
        | SolanaDeployTokenTool
        | SolanaDeployCollectionTool
        | SolanaMintNFTTool
        | SolanaTradeTool
        | SolanaRequestFundsTool
        | SolanaRegisterDomainTool
        | SolanaResolveDomainTool
        | SolanaGetDomainTool
        | SolanaGetWalletAddressTool
        | SolanaPumpfunTokenLaunchTool
        | SolanaCreateImageTool
        | SolanaLendAssetTool
        | SolanaTPSCalculatorTool
        | SolanaStakeTool
        | SolanaFetchPriceTool
        | SolanaTokenDataTool
        | SolanaTokenDataByTickerTool
        | SolanaCompressedAirdropTool
        | SolanaCreateSingleSidedWhirlpoolTool
        | SolanaRaydiumCreateAmmV4
        | SolanaRaydiumCreateClmm
        | SolanaRaydiumCreateCpmm
        | SolanaOpenbookCreateMarket
        | SolanaPythFetchPrice
        | SolanaResolveAllDomainsTool
        | SolanaGetOwnedDomains
        | SolanaGetOwnedTldDomains
        | SolanaGetAllTlds
        | SolanaGetMainDomain)[]

diff --git a/docs/index.html b/docs/index.html index e7acd0e..7dd0878 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,80 +1,115 @@ -solana-agent-kit

solana-agent-kit

Solana Agent Kit

A powerful toolkit for interacting with the Solana blockchain, providing easy-to-use functions for token operations, NFT management, and trading. Now integrated with LangChain for enhanced functionality.

-
    -
  • -

    🪙 Token Operations

    +solana-agent-kit

    solana-agent-kit

    +

    Solana Agent Kit

    +

    Solana Agent Kit Cover 1 (3)

    +

    An open-source toolkit for connecting AI agents to Solana protocols. Now, any agent, using any model can autonomously perform 15+ Solana actions:

      -
    • Deploy new SPL tokens
    • -
    • Transfer SOL and SPL tokens
    • -
    • Check token balances
    • +
    • Trade tokens
    • +
    • Launch new tokens
    • +
    • Lend assets
    • +
    • Send compressed airdrops
    • +
    • Execute blinks
    • +
    • Launch tokens on AMMs
    • +
    • And more...
    • +
    +

    Anyone - whether an SF-based AI researcher or a crypto-native builder - can bring their AI agents trained with any model and seamlessly integrate with Solana.

    +
      +
    • +

      Token Operations

      +
        +
      • Deploy SPL tokens by Metaplex
      • +
      • Transfer assets
      • +
      • Balance checks
      • Stake SOL
      • +
      • Zk compressed Airdrop by Light Protocol and Helius
    • -

      🖼️ NFT Management

      +

      NFT Management via Metaplex

        -
      • Deploy NFT collections
      • -
      • Mint NFTs to collections
      • -
      • Manage metadata and royalties
      • +
      • Collection deployment
      • +
      • NFT minting
      • +
      • Metadata management
      • +
      • Royalty configuration
    • -

      💱 Trading

      +

      DeFi Integration

        -
      • Integrated Jupiter Exchange support
      • -
      • Token swaps with customizable slippage
      • -
      • Direct routing options
      • +
      • Jupiter Exchange swaps
      • +
      • Launch on Pump via PumpPortal
      • +
      • Raydium pool creation (CPMM, CLMM, AMMv4)
      • +
      • Orca whirlpool integration
      • +
      • Meteora Dynamic AMM, DLMM Pool, and Alpga Vault
      • +
      • Openbook market creation
      • +
      • Register and Resolve SNS
      • +
      • Jito Bundles
    • -

      🏦 Yield Farming

      +

      Solana Blinks

        -
      • Lend idle assets to earn interest with Lulo
      • +
      • Lending by Lulo
      • +
      • Send Arcade Games
      • +
      • JupSOL staking
      • +
      +
    • +
    +
      +
    • +

      LangChain Integration

      +
        +
      • Ready-to-use LangChain tools for blockchain operations
      • +
      • Autonomous agent support with React framework
      • +
      • Memory management for persistent interactions
      • +
      • Streaming responses for real-time feedback
    • -

      🔗 LangChain Integration

      +

      Autonomous Modes

        -
      • Utilize LangChain tools for enhanced blockchain interactions
      • -
      • Access a suite of tools for balance checks, transfers, token deployments, and more
      • +
      • Interactive chat mode for guided operations
      • +
      • Autonomous mode for independent agent actions
      • +
      • Configurable action intervals
      • +
      • Built-in error handling and recovery
      • +
      +
    • +
    • +

      AI Tools

      +
        +
      • DALL-E integration for NFT artwork generation
      • +
      • Natural language processing for blockchain commands
      • +
      • Price feed integration for market analysis
      • +
      • Automated decision-making capabilities
    -
    npm install solana-agent-kit
    +
    npm install solana-agent-kit
     
    import { SolanaAgentKit, createSolanaTools } from "solana-agent-kit";

    // Initialize with private key and optional RPC URL
    const agent = new SolanaAgentKit(
    "your-wallet-private-key-as-base58",
    "https://api.mainnet-beta.solana.com",
    "your-openai-api-key"
    );

    // Create LangChain tools
    const tools = createSolanaTools(agent);
    -
    import { deploy_token } from "solana-agent-kit";

    const result = await deploy_token(
    agent,
    9, // decimals
    1000000 // initial supply
    );

    console.log("Token Mint Address:", result.mint.toString()); +
    const result = await agent.deployToken(
    "my ai token", // name
    "uri", // uri
    "token", // symbol
    9, // decimals
    1000000 // initial supply
    );

    console.log("Token Mint Address:", result.mint.toString());
    -
    import { deploy_collection } from "solana-agent-kit";

    const collection = await deploy_collection(agent, {
    name: "My NFT Collection",
    uri: "https://arweave.net/metadata.json",
    royaltyBasisPoints: 500, // 5%
    creators: [
    {
    address: "creator-wallet-address",
    percentage: 100,
    },
    ],
    }); +
    const collection = await agent.deployCollection({
    name: "My NFT Collection",
    uri: "https://arweave.net/metadata.json",
    royaltyBasisPoints: 500, // 5%
    creators: [
    {
    address: "creator-wallet-address",
    percentage: 100,
    },
    ],
    });
    -
    import { trade } from "solana-agent-kit";
    import { PublicKey } from "@solana/web3.js";

    const signature = await trade(
    agent,
    new PublicKey("target-token-mint"),
    100, // amount
    new PublicKey("source-token-mint"),
    300 // 3% slippage
    ); +
    import { PublicKey } from "@solana/web3.js";

    const signature = await agent.trade(
    new PublicKey("target-token-mint"),
    100, // amount
    new PublicKey("source-token-mint"),
    300 // 3% slippage
    );
    -
    import { lendAsset } from "solana-agent-kit";
    import { PublicKey } from "@solana/web3.js";

    const signature = await lendAsset(
    agent,
    100 // amount
    ); +
    import { PublicKey } from "@solana/web3.js";

    const signature = await agent.lendAssets(
    100 // amount of USDC to lend
    );
    -
    import { stakeWithJup } from "solana-agent-kit";

    const signature = await stakeWithJup(
    agent,
    1 // amount in SOL
    ); +
    const signature = await agent.stake(
    1 // amount in SOL to stake
    );
    -
    import { fetchPrice } from "solana-agent-kit";

    const price = await fetchPrice(
    agent,
    "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN" // Token mint address
    );

    console.log("Price in USDC:", price); +
    import { PublicKey } from "@solana/web3.js";

    (async () => {
    console.log(
    "~Airdrop cost estimate:",
    getAirdropCostEstimate(
    1000, // recipients
    30_000 // priority fee in lamports
    )
    );

    const signature = await agent.sendCompressedAirdrop(
    new PublicKey("JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"), // mint
    42, // amount per recipient
    [
    new PublicKey("1nc1nerator11111111111111111111111111111111"),
    // ... add more recipients
    ],
    30_000 // priority fee in lamports
    );
    })();
    -
    import {
    sendCompressedAirdrop,
    getAirdropCostEstimate,
    } from "solana-agent-kit";
    import { PublicKey } from "@solana/web3.js";

    (async () => {
    console.log(
    "~Airdrop cost estimate:",
    getAirdropCostEstimate(
    1000, // recipients
    30_000 // priority fee in lamports
    )
    );

    const signature = await sendCompressedAirdrop(
    agent,
    new PublicKey("JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"), // mint
    42, // amount per recipient
    [
    new PublicKey("1nc1nerator11111111111111111111111111111111"),
    // ... add more recipients
    ],
    30_000 // priority fee in lamports
    );
    })(); +

    const price = await agent.pythFetchPrice(
    "0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"
    );

    console.log("Price in BTC/USD:", price);
    -

    Deploy a new SPL token with optional initial supply. If not specified, decimals default to 9.

    -

    Create a new NFT collection with customizable metadata and royalties.

    -

    Mint a new NFT as part of an existing collection.

    -

    Transfer SOL or SPL tokens to a recipient.

    -

    Swap tokens using Jupiter Exchange integration.

    -

    Check SOL or token balance for the agent's wallet.

    -

    Lend idle assets to earn interest with Lulo.

    -

    Stake SOL with Jupiter to earn rewards.

    -

    Send an SPL token airdrop to many recipients at low cost via ZK Compression.

    The toolkit relies on several key Solana and Metaplex libraries:

    • @solana/web3.js
    • @@ -84,8 +119,10 @@
    • @metaplex-foundation/umi
    • @lightprotocol/compressed-token
    • @lightprotocol/stateless.js
    • +
    • @pythnetwork/price-service-client
    -

    Contributions are welcome! Please feel free to submit a Pull Request.

    -

    ISC License

    +

    Contributions are welcome! Please feel free to submit a Pull Request. +Refer to CONTRIBUTING.md for detailed guidelines on how to contribute to this project.

    +

    MIT License

    This toolkit handles private keys and transactions. Always ensure you're using it in a secure environment and never share your private keys.

    -
    +
diff --git a/docs/interfaces/CollectionDeployment.html b/docs/interfaces/CollectionDeployment.html index 0438e92..c03b39a 100644 --- a/docs/interfaces/CollectionDeployment.html +++ b/docs/interfaces/CollectionDeployment.html @@ -1,3 +1,3 @@ -CollectionDeployment | solana-agent-kit

Interface CollectionDeployment

interface CollectionDeployment {
    collectionAddress: PublicKey;
    signature: Uint8Array<ArrayBufferLike>;
}

Properties

collectionAddress +CollectionDeployment | solana-agent-kit

Interface CollectionDeployment

interface CollectionDeployment {
    collectionAddress: PublicKey;
    signature: Uint8Array<ArrayBufferLike>;
}

Properties

collectionAddress: PublicKey
signature: Uint8Array<ArrayBufferLike>
+

Properties

collectionAddress: PublicKey
signature: Uint8Array<ArrayBufferLike>
diff --git a/docs/interfaces/CollectionOptions.html b/docs/interfaces/CollectionOptions.html index 997e32b..6790105 100644 --- a/docs/interfaces/CollectionOptions.html +++ b/docs/interfaces/CollectionOptions.html @@ -1,5 +1,5 @@ -CollectionOptions | solana-agent-kit

Interface CollectionOptions

interface CollectionOptions {
    creators?: Creator[];
    name: string;
    royaltyBasisPoints?: number;
    uri: string;
}

Properties

creators? +CollectionOptions | solana-agent-kit

Interface CollectionOptions

interface CollectionOptions {
    creators?: Creator[];
    name: string;
    royaltyBasisPoints?: number;
    uri: string;
}

Properties

creators?: Creator[]
name: string
royaltyBasisPoints?: number
uri: string
+

Properties

creators?: Creator[]
name: string
royaltyBasisPoints?: number
uri: string
diff --git a/docs/interfaces/Creator.html b/docs/interfaces/Creator.html index 72a3136..4e33592 100644 --- a/docs/interfaces/Creator.html +++ b/docs/interfaces/Creator.html @@ -1,3 +1,3 @@ -Creator | solana-agent-kit

Interface Creator

interface Creator {
    address: string;
    percentage: number;
}

Properties

address +Creator | solana-agent-kit

Interface Creator

interface Creator {
    address: string;
    percentage: number;
}

Properties

Properties

address: string
percentage: number
+

Properties

address: string
percentage: number
diff --git a/docs/interfaces/FetchPriceResponse.html b/docs/interfaces/FetchPriceResponse.html index f2ffea8..defd401 100644 --- a/docs/interfaces/FetchPriceResponse.html +++ b/docs/interfaces/FetchPriceResponse.html @@ -1,6 +1,6 @@ -FetchPriceResponse | solana-agent-kit

Interface FetchPriceResponse

interface FetchPriceResponse {
    code?: string;
    message?: string;
    priceInUSDC?: string;
    status: "success" | "error";
    tokenId?: string;
}

Properties

code? +FetchPriceResponse | solana-agent-kit

Interface FetchPriceResponse

interface FetchPriceResponse {
    code?: string;
    message?: string;
    priceInUSDC?: string;
    status: "success" | "error";
    tokenId?: string;
}

Properties

code?: string
message?: string
priceInUSDC?: string
status: "success" | "error"
tokenId?: string
+

Properties

code?: string
message?: string
priceInUSDC?: string
status: "success" | "error"
tokenId?: string
diff --git a/docs/interfaces/JupiterTokenData.html b/docs/interfaces/JupiterTokenData.html index 1fbabda..2b23375 100644 --- a/docs/interfaces/JupiterTokenData.html +++ b/docs/interfaces/JupiterTokenData.html @@ -1,4 +1,4 @@ -JupiterTokenData | solana-agent-kit

Interface JupiterTokenData

interface JupiterTokenData {
    address: string;
    daily_volume: number;
    decimals: number;
    extensions: {
        coingeckoId?: string;
    };
    freeze_authority: null | string;
    logoURI: string;
    mint_authority: null | string;
    name: string;
    permanent_delegate: null | string;
    symbol: string;
    tags: string[];
}

Properties

address +JupiterTokenData | solana-agent-kit

Interface JupiterTokenData

interface JupiterTokenData {
    address: string;
    daily_volume: number;
    decimals: number;
    extensions: {
        coingeckoId?: string;
    };
    freeze_authority: null | string;
    logoURI: string;
    mint_authority: null | string;
    name: string;
    permanent_delegate: null | string;
    symbol: string;
    tags: string[];
}

Properties

address: string
daily_volume: number
decimals: number
extensions: {
    coingeckoId?: string;
}
freeze_authority: null | string
logoURI: string
mint_authority: null | string
name: string
permanent_delegate: null | string
symbol: string
tags: string[]
+

Properties

address: string
daily_volume: number
decimals: number
extensions: {
    coingeckoId?: string;
}
freeze_authority: null | string
logoURI: string
mint_authority: null | string
name: string
permanent_delegate: null | string
symbol: string
tags: string[]
diff --git a/docs/interfaces/LuloAccountDetailsResponse.html b/docs/interfaces/LuloAccountDetailsResponse.html index 0aafae9..fa19d62 100644 --- a/docs/interfaces/LuloAccountDetailsResponse.html +++ b/docs/interfaces/LuloAccountDetailsResponse.html @@ -1,6 +1,6 @@ LuloAccountDetailsResponse | solana-agent-kit

Interface LuloAccountDetailsResponse

Lulo Account Details response format

-
interface LuloAccountDetailsResponse {
    interestEarned: number;
    realtimeApy: number;
    settings: {
        allowedProtocols: null | string;
        homebase: null | string;
        minimumRate: string;
        owner: string;
    };
    totalValue: number;
}

Properties

interface LuloAccountDetailsResponse {
    interestEarned: number;
    realtimeApy: number;
    settings: {
        allowedProtocols: null | string;
        homebase: null | string;
        minimumRate: string;
        owner: string;
    };
    totalValue: number;
}

Properties

interestEarned: number
realtimeApy: number
settings: {
    allowedProtocols: null | string;
    homebase: null | string;
    minimumRate: string;
    owner: string;
}
totalValue: number
+

Properties

interestEarned: number
realtimeApy: number
settings: {
    allowedProtocols: null | string;
    homebase: null | string;
    minimumRate: string;
    owner: string;
}
totalValue: number
diff --git a/docs/interfaces/MintCollectionNFTResponse.html b/docs/interfaces/MintCollectionNFTResponse.html index 4c85a86..e2e1479 100644 --- a/docs/interfaces/MintCollectionNFTResponse.html +++ b/docs/interfaces/MintCollectionNFTResponse.html @@ -1,3 +1,3 @@ -MintCollectionNFTResponse | solana-agent-kit

Interface MintCollectionNFTResponse

interface MintCollectionNFTResponse {
    metadata: PublicKey;
    mint: PublicKey;
}

Properties

metadata +MintCollectionNFTResponse | solana-agent-kit

Interface MintCollectionNFTResponse

interface MintCollectionNFTResponse {
    metadata: PublicKey;
    mint: PublicKey;
}

Properties

Properties

metadata: PublicKey
mint: PublicKey
+

Properties

metadata: PublicKey
mint: PublicKey
diff --git a/docs/interfaces/PumpFunTokenOptions.html b/docs/interfaces/PumpFunTokenOptions.html index d904b0c..d1c0142 100644 --- a/docs/interfaces/PumpFunTokenOptions.html +++ b/docs/interfaces/PumpFunTokenOptions.html @@ -1,7 +1,7 @@ -PumpFunTokenOptions | solana-agent-kit

Interface PumpFunTokenOptions

interface PumpFunTokenOptions {
    initialLiquiditySOL?: number;
    priorityFee?: number;
    slippageBps?: number;
    telegram?: string;
    twitter?: string;
    website?: string;
}

Properties

initialLiquiditySOL? +PumpFunTokenOptions | solana-agent-kit

Interface PumpFunTokenOptions

interface PumpFunTokenOptions {
    initialLiquiditySOL?: number;
    priorityFee?: number;
    slippageBps?: number;
    telegram?: string;
    twitter?: string;
    website?: string;
}

Properties

initialLiquiditySOL?: number
priorityFee?: number
slippageBps?: number
telegram?: string
twitter?: string
website?: string
+

Properties

initialLiquiditySOL?: number
priorityFee?: number
slippageBps?: number
telegram?: string
twitter?: string
website?: string
diff --git a/docs/interfaces/PumpfunLaunchResponse.html b/docs/interfaces/PumpfunLaunchResponse.html index 7e65f2a..f667de7 100644 --- a/docs/interfaces/PumpfunLaunchResponse.html +++ b/docs/interfaces/PumpfunLaunchResponse.html @@ -1,5 +1,5 @@ -PumpfunLaunchResponse | solana-agent-kit

Interface PumpfunLaunchResponse

interface PumpfunLaunchResponse {
    error?: string;
    metadataUri?: string;
    mint: string;
    signature: string;
}

Properties

error? +PumpfunLaunchResponse | solana-agent-kit

Interface PumpfunLaunchResponse

interface PumpfunLaunchResponse {
    error?: string;
    metadataUri?: string;
    mint: string;
    signature: string;
}

Properties

error?: string
metadataUri?: string
mint: string
signature: string
+

Properties

error?: string
metadataUri?: string
mint: string
signature: string
diff --git a/docs/interfaces/PythFetchPriceResponse.html b/docs/interfaces/PythFetchPriceResponse.html new file mode 100644 index 0000000..fcfb217 --- /dev/null +++ b/docs/interfaces/PythFetchPriceResponse.html @@ -0,0 +1,6 @@ +PythFetchPriceResponse | solana-agent-kit

Interface PythFetchPriceResponse

interface PythFetchPriceResponse {
    code?: string;
    message?: string;
    price?: string;
    priceFeedID: string;
    status: "success" | "error";
}

Properties

code?: string
message?: string
price?: string
priceFeedID: string
status: "success" | "error"
diff --git a/docs/media/CONTRIBUTING.md b/docs/media/CONTRIBUTING.md new file mode 100644 index 0000000..9cc1837 --- /dev/null +++ b/docs/media/CONTRIBUTING.md @@ -0,0 +1,154 @@ +# Contributing to Solana Agent Kit + +First off, thank you for considering contributing to Solana Agent Kit! 🎉 Your contributions are **greatly appreciated**. + +## Table of Contents + +- [Contributing to Solana Agent Kit](#contributing-to-solana-agent-kit) + - [Table of Contents](#table-of-contents) + - [Code of Conduct](#code-of-conduct) + - [How Can I Contribute?](#how-can-i-contribute) + - [Reporting Bugs](#reporting-bugs) + - [Suggesting Enhancements](#suggesting-enhancements) + - [Your First Code Contribution](#your-first-code-contribution) + - [Pull Requests](#pull-requests) + - [Style Guides](#style-guides) + - [Code Style](#code-style) + - [Commit Messages](#commit-messages) + - [Naming Conventions](#naming-conventions) + - [Development Setup](#development-setup) + - [Prerequisites](#prerequisites) + - [Installation](#installation) + - [Building the Project](#building-the-project) + - [Running Tests](#running-tests) + - [Generating Documentation](#generating-documentation) + - [Security](#security) + - [License](#license) + +## Code of Conduct + +This project adheres to the [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org/version/2/0/code_of_conduct/). By participating, you are expected to uphold this code. Please report unacceptable behavior to [aryan@sendai.fun](mailto:aryan@sendai.fun). + +## How Can I Contribute? + +### Reporting Bugs + +**Great**! Opening an issue is the best way to help us improve. Here's how you can report a bug: + +1. **Search** the [existing issues](https://github.com/sendaifun/solana-agent-kit/issues) to make sure it hasn't been reported. +2. **Open a new issue** and fill out the template with as much information as possible. +3. **Provide reproduction steps** if applicable. + +### Suggesting Enhancements + +We welcome your ideas for improving Solana Agent Kit! To suggest an enhancement: + +1. **Search** the [existing issues](https://github.com/sendaifun/solana-agent-kit/issues) to see if it's already been suggested. +2. **Open a new issue** and describe your idea in detail. + +### Your First Code Contribution + +Unsure where to start? You can help out by: + +- Fixing simple bugs. +- Improving documentation. +- Adding tests. + +Check out the [Good First Issues](https://github.com/sendaifun/solana-agent-kit/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) to get started! + +### Pull Requests + +1. **Fork** the repository. +2. **Create** a new branch for your feature or bugfix. + ```bash + git checkout -b feature/your-feature-name + ``` +3. **Commit** your changes with clear and descriptive messages. +4. **Push** to your fork. + ```bash + git push origin feature/your-feature-name + ``` +5. **Open a Pull Request** against the `main` branch of this repository. + +## Style Guides + +### Code Style + +- **Language**: TypeScript +- **Formatting**: Follow the existing codebase formatting. Consider using [Prettier](https://prettier.io/) for consistent code formatting. +- **Code Quality**: Adhere to the code quality rules defined in `.eslintrc`. Ensure all checks pass before submitting a PR. + +### Commit Messages + +Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for your commit messages. Examples: + +- `feat: add ability to deploy new SPL token` +- `fix: handle edge case when deploying collection` +- `docs: update README with new usage examples` + +### Naming Conventions + +- **Variables and Functions**: `camelCase` +- **Classes and Types**: `PascalCase` +- **Constants**: `UPPER_SNAKE_CASE` + +## Development Setup + +### Prerequisites + +- **Node.js**: v23.x or higher +- **npm**: v10.x or higher +- **Git**: Installed and configured + +### Installation + +1. **Clone** the repository: + ```bash + git clone https://github.com/yourusername/solana-agent-kit.git + ``` +2. **Navigate** to the project directory: + ```bash + cd solana-agent-kit + ``` +3. **Install** dependencies: + ```bash + pnpm install + ``` + +### Building the Project + +To compile the TypeScript code: + +```bash +pnpm run build +``` + +### Running Tests + +To execute the test suite: + +```bash +pnpm run test +``` + +### Generating Documentation + +To generate the project documentation using TypeDoc: + +```bash +npm run docs +``` + +The documentation will be available in the `docs/` directory. + +## Security + +This toolkit handles sensitive information such as private keys and API keys. **Ensure you never commit `.env` files or any sensitive data**. Review the `.gitignore` to confirm that sensitive files are excluded. + +For security vulnerabilities, please follow the [responsible disclosure](mailto:aryan@sendai.fun) process. + +## License + +This project is licensed under the [ISC License](LICENSE). + +--- diff --git a/docs/modules.html b/docs/modules.html index b5e59c9..29440e3 100644 --- a/docs/modules.html +++ b/docs/modules.html @@ -8,5 +8,6 @@ MintCollectionNFTResponse PumpfunLaunchResponse PumpFunTokenOptions +PythFetchPriceResponse

Functions

diff --git a/guides/add_your_own_tool.md b/guides/add_your_own_tool.md index 803198c..6c41606 100644 --- a/guides/add_your_own_tool.md +++ b/guides/add_your_own_tool.md @@ -178,4 +178,4 @@ If you encounter any issues while implementing your custom tool: - Contact the maintainer - Check existing tools for implementation examples ---- \ No newline at end of file +--- diff --git a/package.json b/package.json index 2882be6..9c16fd6 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,6 @@ "build": "tsc", "docs": "typedoc src --out docs", "test": "ts-node test/index.ts", - "test:domain": "ts-node test/domain_methods.test.ts", "generate": "ts-node src/utils/keypair.ts" }, "engines": { @@ -16,7 +15,7 @@ "pnpm": ">=8.0.0" }, "keywords": [], - "author": "", + "author": "sendaifun", "license": "ISC", "dependencies": { "@bonfida/spl-name-service": "^3.0.7", diff --git a/src/agent/index.ts b/src/agent/index.ts index 6eafa1d..f1833f7 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -25,8 +25,9 @@ import { stakeWithJup, sendCompressedAirdrop, createOrcaSingleSidedWhirlpool, - FEE_TIERS, + fetchPrice, pythFetchPrice, + FEE_TIERS, getAllDomainsTLDs, getAllRegisteredAllDomains, getOwnedDomainsForTLD, @@ -47,7 +48,7 @@ import { NameAccountAndDomain } from "@onsol/tldparser"; /** * Main class for interacting with Solana blockchain - * Provides a unified interface for token operations, NFT management, and trading + * Provides a unified interface for token operations, NFT management, trading and more * * @class SolanaAgentKit * @property {Connection} connection - Solana RPC connection @@ -153,6 +154,10 @@ export class SolanaAgentKit { return getTokenDataByTicker(ticker); } + async fetchTokenPrice(mint: string) { + return fetchPrice(new PublicKey(mint)); + } + async launchPumpFunToken( tokenName: string, tokenTicker: string, @@ -307,10 +312,10 @@ export class SolanaAgentKit { lotSize, tickSize, - ) + ); } - async pythFetchPrice(priceFeedID: string) { - return pythFetchPrice(this, priceFeedID); + async pythFetchPrice(priceFeedID: string): Promise { + return pythFetchPrice(priceFeedID); } } diff --git a/src/index.ts b/src/index.ts index a1fd258..1b4116f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ -import { SolanaAgentKit } from './agent'; // Move the SolanaAgentKit class to src/agent.ts -import { createSolanaTools } from './langchain'; +import { SolanaAgentKit } from "./agent"; +import { createSolanaTools } from "./langchain"; export { SolanaAgentKit, createSolanaTools }; // Optional: Export types that users might need -export * from './types'; \ No newline at end of file +export * from "./types"; diff --git a/src/langchain/index.ts b/src/langchain/index.ts index a5fd13c..51fc6b4 100644 --- a/src/langchain/index.ts +++ b/src/langchain/index.ts @@ -3,7 +3,6 @@ import Decimal from "decimal.js"; import { Tool } from "langchain/tools"; import { PythFetchPriceResponse, SolanaAgentKit } from "../index"; import { create_image } from "../tools/create_image"; -import { fetchPrice } from "../tools/fetch_price"; import { BN } from "@coral-xyz/anchor"; import { FEE_TIERS } from "../tools"; import { toJSON } from "../utils/toJSON"; @@ -67,7 +66,7 @@ export class SolanaTransferTool extends Tool { const tx = await this.solanaKit.transfer( recipient, parsedInput.amount, - mintAddress + mintAddress, ); return JSON.stringify({ @@ -94,7 +93,7 @@ export class SolanaDeployTokenTool extends Tool { Inputs (input is a JSON string): name: string, eg "My Token" (required) - uri: string, eg "https://example.com/token.json" (required) + uri: string, eg "https://example.com/token.json" (required) symbol: string, eg "MTK" (required) decimals?: number, eg 9 (optional, defaults to 9) initialSupply?: number, eg 1000000 (optional)`; @@ -112,7 +111,7 @@ export class SolanaDeployTokenTool extends Tool { parsedInput.uri, parsedInput.symbol, parsedInput.decimals, - parsedInput.initialSupply + parsedInput.initialSupply, ); return JSON.stringify({ @@ -192,7 +191,7 @@ export class SolanaMintNFTTool extends Tool { }, parsedInput.recipient ? new PublicKey(parsedInput.recipient) - : this.solanaKit.wallet_address + : this.solanaKit.wallet_address, ); return JSON.stringify({ @@ -240,7 +239,7 @@ export class SolanaTradeTool extends Tool { parsedInput.inputMint ? new PublicKey(parsedInput.inputMint) : new PublicKey("So11111111111111111111111111111111111111112"), - parsedInput.slippageBps + parsedInput.slippageBps, ); return JSON.stringify({ @@ -320,7 +319,7 @@ export class SolanaRegisterDomainTool extends Tool { const tx = await this.solanaKit.registerDomain( parsedInput.name, - parsedInput.spaceKB || 1 + parsedInput.spaceKB || 1, ); return JSON.stringify({ @@ -477,7 +476,7 @@ export class SolanaPumpfunTokenLaunchTool extends Tool { telegram: parsedInput.telegram, website: parsedInput.website, initialLiquiditySOL: parsedInput.initialLiquiditySOL, - } + }, ); return JSON.stringify({ @@ -621,7 +620,7 @@ export class SolanaStakeTool extends Tool { export class SolanaFetchPriceTool extends Tool { name = "solana_fetch_price"; description = `Fetch the price of a given token in USDC. - + Inputs: - tokenId: string, the mint address of the token, e.g., "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"`; @@ -631,7 +630,7 @@ export class SolanaFetchPriceTool extends Tool { async _call(input: string): Promise { try { - const price = await fetchPrice(this.solanaKit, input.trim()); + const price = await this.solanaKit.fetchTokenPrice(input.trim()); return JSON.stringify({ status: "success", tokenId: input.trim(), @@ -710,7 +709,7 @@ export class SolanaTokenDataByTickerTool extends Tool { export class SolanaCompressedAirdropTool extends Tool { name = "solana_compressed_airdrop"; description = `Airdrop SPL tokens with ZK Compression (also called as airdropping tokens) - + Inputs (input is a JSON string): mintAddress: string, the mint address of the token, e.g., "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN" (required) amount: number, the amount of tokens to airdrop per recipient, e.g., 42 (required) @@ -733,7 +732,7 @@ export class SolanaCompressedAirdropTool extends Tool { parsedInput.decimals, parsedInput.recipients, parsedInput.priorityFeeInLamports || 30_000, - parsedInput.shouldLog || false + parsedInput.shouldLog || false, ); return JSON.stringify({ @@ -897,7 +896,7 @@ export class SolanaRaydiumCreateClmm extends Tool { export class SolanaRaydiumCreateCpmm extends Tool { name = "raydium_create_cpmm"; - description = `Raydium's newest CPMM, does not require marketID, supports Token 2022 standard + description = `Raydium's newest CPMM, does not require marketID, supports Token 2022 standard Inputs (input is a json string): mint1: string (required) @@ -945,7 +944,7 @@ export class SolanaRaydiumCreateCpmm extends Tool { export class SolanaOpenbookCreateMarket extends Tool { name = "solana_openbook_create_market"; - description = `Openbook marketId, required for ammv4 + description = `Openbook marketId, required for ammv4 Inputs (input is a json string): baseMint: string (required) diff --git a/src/tools/create_orca_single_sided_whirlpool.ts b/src/tools/create_orca_single_sided_whirlpool.ts index aefc93c..7f3c4a9 100644 --- a/src/tools/create_orca_single_sided_whirlpool.ts +++ b/src/tools/create_orca_single_sided_whirlpool.ts @@ -1,5 +1,5 @@ import { Keypair, PublicKey, Transaction } from "@solana/web3.js"; -import { SolanaAgentKit } from "../agent"; +import { SolanaAgentKit } from "../index"; import { BN, Wallet } from "@coral-xyz/anchor"; import { Decimal } from "decimal.js"; import { @@ -40,7 +40,7 @@ import { sendTx } from "../utils/send_tx"; * @remarks * Fee tiers determine the percentage of fees collected on swaps, while tick spacing affects * the granularity of price ranges for liquidity positions. - * + * * For more details, refer to: * - [Whirlpool Fees](https://orca-so.github.io/whirlpools/Architecture%20Overview/Whirlpool%20Fees) * - [Whirlpool Parameters](https://orca-so.github.io/whirlpools/Architecture%20Overview/Whirlpool%20Parameters) @@ -54,17 +54,17 @@ export const FEE_TIERS = { 0.04: 4, 0.05: 8, 0.16: 16, - 0.30: 64, + 0.3: 64, 0.65: 96, - 1.00: 128, - 2.00: 256, + 1.0: 128, + 2.0: 256, } as const; /** * # Creates a single-sided Whirlpool. * * This function initializes a new Whirlpool (liquidity pool) on Orca and seeds it with liquidity from a single token. - * + * * ## Example Usage: * You created a new token called SHARK, and you want to set the initial price to 0.001 USDC. * You set `depositTokenMint` to SHARK's mint address and `otherTokenMint` to USDC's mint address. @@ -72,7 +72,7 @@ export const FEE_TIERS = { * 1. Increase the amount of tokens you deposit * 2. Set the initial price very low * 3. Set the maximum price closer to the initial price - * + * * ### Note for experts: * The Wrhirlpool program initializes the Whirlpool with the in a specific order. This might not be * the order you expect, so the function checks the order and adjusts the inverts the prices. This means that @@ -86,13 +86,13 @@ export const FEE_TIERS = { * @param initialPrice - The initial price of the deposit token in terms of the other token. * @param maxPrice - The maximum price at which liquidity is added. * @param feeTier - The fee tier percentage for the pool, determining tick spacing and fee collection rates. - * + * * @returns A promise that resolves to a transaction ID (`string`) of the transaction creating the pool. - * + * * @throws Will throw an error if: * - Mint accounts for the tokens cannot be fetched. * - Prices are out of bounds. - * + * * @remarks * This function is designed for single-sided deposits where users only contribute one type of token, * and the function manages mint order and necessary calculations. @@ -103,7 +103,7 @@ export const FEE_TIERS = { * import { PublicKey } from "@solana/web3.js"; * import { BN } from "@coral-xyz/anchor"; * import Decimal from "decimal.js"; - * + * * const agent = new SolanaAgentKit(wallet, connection); * const depositAmount = new BN(1_000_000_000_000); // 1 million SHARK if SHARK has 6 decimals * const depositTokenMint = new PublicKey("DEPOSTI_TOKEN_ADDRESS"); @@ -111,7 +111,7 @@ export const FEE_TIERS = { * const initialPrice = new Decimal(0.001); * const maxPrice = new Decimal(5.0); * const feeTier = 0.30; - * + * * const txId = await createOrcaSingleSidedWhirlpool( * agent, * depositAmount, @@ -134,13 +134,19 @@ export async function createOrcaSingleSidedWhirlpool( feeTier: keyof typeof FEE_TIERS, ): Promise { const wallet = new Wallet(agent.wallet); - const ctx = WhirlpoolContext.from(agent.connection, wallet, ORCA_WHIRLPOOL_PROGRAM_ID); + const ctx = WhirlpoolContext.from( + agent.connection, + wallet, + ORCA_WHIRLPOOL_PROGRAM_ID, + ); const fetcher = ctx.fetcher; - const correctTokenOrder = PoolUtil.orderMints(otherTokenMint, depositTokenMint).map( - (addr) => addr.toString(), - ); - const isCorrectMintOrder = correctTokenOrder[0] === depositTokenMint.toString(); + const correctTokenOrder = PoolUtil.orderMints( + otherTokenMint, + depositTokenMint, + ).map((addr) => addr.toString()); + const isCorrectMintOrder = + correctTokenOrder[0] === depositTokenMint.toString(); let mintA, mintB; if (isCorrectMintOrder) { [mintA, mintB] = [depositTokenMint, otherTokenMint]; @@ -151,10 +157,18 @@ export async function createOrcaSingleSidedWhirlpool( } const mintAAccount = await fetcher.getMintInfo(mintA); const mintBAccount = await fetcher.getMintInfo(mintB); - if (mintAAccount === null || mintBAccount === null) throw Error('Mint account not found'); + if (mintAAccount === null || mintBAccount === null) + throw Error("Mint account not found"); const tickSpacing = FEE_TIERS[feeTier]; - const tickIndex = PriceMath.priceToTickIndex(initialPrice, mintAAccount.decimals, mintBAccount.decimals); - const initialTick = TickUtil.getInitializableTickIndex(tickIndex, tickSpacing); + const tickIndex = PriceMath.priceToTickIndex( + initialPrice, + mintAAccount.decimals, + mintBAccount.decimals, + ); + const initialTick = TickUtil.getInitializableTickIndex( + tickIndex, + tickSpacing, + ); const tokenExtensionCtx: TokenExtensionContextForPool = { ...NO_TOKEN_EXTENSION_CONTEXT, @@ -196,17 +210,17 @@ export async function createOrcaSingleSidedWhirlpool( tokenVaultBKeypair, feeTierKey, tickSpacing: tickSpacing, - funder: wallet.publicKey + funder: wallet.publicKey, }; const initPoolIx = !TokenExtensionUtil.isV2IxRequiredPool(tokenExtensionCtx) ? WhirlpoolIx.initializePoolIx(ctx.program, baseParamsPool) : WhirlpoolIx.initializePoolV2Ix(ctx.program, { - ...baseParamsPool, - tokenProgramA: tokenExtensionCtx.tokenMintWithProgramA.tokenProgram, - tokenProgramB: tokenExtensionCtx.tokenMintWithProgramB.tokenProgram, - tokenBadgeA, - tokenBadgeB, - }); + ...baseParamsPool, + tokenProgramA: tokenExtensionCtx.tokenMintWithProgramA.tokenProgram, + tokenProgramB: tokenExtensionCtx.tokenMintWithProgramB.tokenProgram, + tokenBadgeA, + tokenBadgeB, + }); const initialTickArrayStartTick = TickUtil.getStartTickIndex( initialTick, tickSpacing, @@ -235,14 +249,32 @@ export async function createOrcaSingleSidedWhirlpool( let tickLowerIndex, tickUpperIndex; if (isCorrectMintOrder) { tickLowerIndex = initialTick; - tickUpperIndex = PriceMath.priceToTickIndex(maxPrice, mintAAccount.decimals, mintBAccount.decimals); + tickUpperIndex = PriceMath.priceToTickIndex( + maxPrice, + mintAAccount.decimals, + mintBAccount.decimals, + ); } else { - tickLowerIndex = PriceMath.priceToTickIndex(maxPrice, mintAAccount.decimals, mintBAccount.decimals); + tickLowerIndex = PriceMath.priceToTickIndex( + maxPrice, + mintAAccount.decimals, + mintBAccount.decimals, + ); tickUpperIndex = initialTick; } - const tickLowerInitializableIndex = TickUtil.getInitializableTickIndex(tickLowerIndex, tickSpacing); - const tickUpperInitializableIndex = TickUtil.getInitializableTickIndex(tickUpperIndex, tickSpacing); - if (!TickUtil.checkTickInBounds(tickLowerInitializableIndex) || !TickUtil.checkTickInBounds(tickUpperInitializableIndex)) throw Error('Prices out of bounds'); + const tickLowerInitializableIndex = TickUtil.getInitializableTickIndex( + tickLowerIndex, + tickSpacing, + ); + const tickUpperInitializableIndex = TickUtil.getInitializableTickIndex( + tickUpperIndex, + tickSpacing, + ); + if ( + !TickUtil.checkTickInBounds(tickLowerInitializableIndex) || + !TickUtil.checkTickInBounds(tickUpperInitializableIndex) + ) + throw Error("Prices out of bounds"); const increasLiquidityQuoteParam: IncreaseLiquidityQuoteParam = { inputTokenAmount: new BN(depositTokenAmount), inputTokenMint: depositTokenMint, @@ -253,11 +285,11 @@ export async function createOrcaSingleSidedWhirlpool( tickLowerIndex: tickLowerInitializableIndex, tickUpperIndex: tickUpperInitializableIndex, tokenExtensionCtx: tokenExtensionCtx, - slippageTolerance: Percentage.fromFraction(0, 100) - } + slippageTolerance: Percentage.fromFraction(0, 100), + }; const liquidityInput = increaseLiquidityQuoteByInputTokenWithParams( - increasLiquidityQuoteParam - ) + increasLiquidityQuoteParam, + ); const { liquidityAmount: liquidity, tokenMaxA, tokenMaxB } = liquidityInput; const positionMintKeypair = Keypair.generate(); @@ -285,7 +317,7 @@ export async function createOrcaSingleSidedWhirlpool( ...params, positionMint: positionMintPubkey, withTokenMetadataExtension: true, - }) + }); txBuilder.addInstruction(positionIx); txBuilder.addSigner(positionMintKeypair); @@ -365,35 +397,33 @@ export async function createOrcaSingleSidedWhirlpool( tickArrayUpper: tickArrayUpperPda.publicKey, }; - const liquidityIx = !TokenExtensionUtil.isV2IxRequiredPool( - tokenExtensionCtx, - ) + const liquidityIx = !TokenExtensionUtil.isV2IxRequiredPool(tokenExtensionCtx) ? increaseLiquidityIx(ctx.program, baseParamsLiquidity) : increaseLiquidityV2Ix(ctx.program, { - ...baseParamsLiquidity, - tokenMintA: mintA, - tokenMintB: mintB, - tokenProgramA: tokenExtensionCtx.tokenMintWithProgramA.tokenProgram, - tokenProgramB: tokenExtensionCtx.tokenMintWithProgramB.tokenProgram, - }); + ...baseParamsLiquidity, + tokenMintA: mintA, + tokenMintB: mintB, + tokenProgramA: tokenExtensionCtx.tokenMintWithProgramA.tokenProgram, + tokenProgramB: tokenExtensionCtx.tokenMintWithProgramB.tokenProgram, + }); txBuilder.addInstruction(liquidityIx); const txPayload = await txBuilder.build({ - maxSupportedTransactionVersion: "legacy" + maxSupportedTransactionVersion: "legacy", }); if (txPayload.transaction instanceof Transaction) { try { - const txId = await sendTx( - agent, - txPayload.transaction, - [positionMintKeypair, tokenVaultAKeypair, tokenVaultBKeypair], - ); + const txId = await sendTx(agent, txPayload.transaction, [ + positionMintKeypair, + tokenVaultAKeypair, + tokenVaultBKeypair, + ]); return txId; } catch (error) { - throw new Error(`Failed to create pool: ${JSON.stringify(error)}`); + throw new Error(`Failed to create pool: ${JSON.stringify(error)}`); } } else { - throw new Error('Failed to create pool: Transaction not created'); + throw new Error("Failed to create pool: Transaction not created"); } } diff --git a/src/tools/deploy_collection.ts b/src/tools/deploy_collection.ts index 4528b92..10fef9d 100644 --- a/src/tools/deploy_collection.ts +++ b/src/tools/deploy_collection.ts @@ -1,8 +1,19 @@ import { SolanaAgentKit } from "../index"; -import { generateSigner, keypairIdentity, publicKey } from "@metaplex-foundation/umi"; -import { createCollection, mplCore, ruleSet } from "@metaplex-foundation/mpl-core"; +import { + generateSigner, + keypairIdentity, + publicKey, +} from "@metaplex-foundation/umi"; +import { + createCollection, + mplCore, + ruleSet, +} from "@metaplex-foundation/mpl-core"; import { CollectionOptions, CollectionDeployment } from "../types"; -import { fromWeb3JsKeypair, toWeb3JsPublicKey } from "@metaplex-foundation/umi-web3js-adapters"; +import { + fromWeb3JsKeypair, + toWeb3JsPublicKey, +} from "@metaplex-foundation/umi-web3js-adapters"; import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"; /** @@ -28,11 +39,11 @@ export async function deploy_collection( address: publicKey(creator.address), percentage: creator.percentage, })) || [ - { - address: publicKey(agent.wallet_address.toString()), - percentage: 100, - }, - ]; + { + address: publicKey(agent.wallet_address.toString()), + percentage: 100, + }, + ]; // Create collection const tx = await createCollection(umi, { diff --git a/src/tools/deploy_token.ts b/src/tools/deploy_token.ts index 93502ec..7532eef 100644 --- a/src/tools/deploy_token.ts +++ b/src/tools/deploy_token.ts @@ -2,9 +2,17 @@ import { SolanaAgentKit } from "../index"; import { PublicKey } from "@solana/web3.js"; import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"; import { generateSigner, keypairIdentity } from "@metaplex-foundation/umi"; -import { createFungible, mintV1, TokenStandard } from "@metaplex-foundation/mpl-token-metadata"; -import { fromWeb3JsKeypair, fromWeb3JsPublicKey, toWeb3JsPublicKey } from "@metaplex-foundation/umi-web3js-adapters"; -import {mplToolbox} from "@metaplex-foundation/mpl-toolbox" +import { + createFungible, + mintV1, + TokenStandard, +} from "@metaplex-foundation/mpl-token-metadata"; +import { + fromWeb3JsKeypair, + fromWeb3JsPublicKey, + toWeb3JsPublicKey, +} from "@metaplex-foundation/umi-web3js-adapters"; +import { mplToolbox } from "@metaplex-foundation/mpl-toolbox"; /** * Deploy a new SPL token @@ -22,11 +30,11 @@ export async function deploy_token( uri: string, symbol: string, decimals: number = 9, - initialSupply?: number + initialSupply?: number, ): Promise<{ mint: PublicKey }> { try { // Create UMI instance from agent - const umi = createUmi(agent.connection.rpcEndpoint).use(mplToolbox()) + const umi = createUmi(agent.connection.rpcEndpoint).use(mplToolbox()); umi.use(keypairIdentity(fromWeb3JsKeypair(agent.wallet))); // Create new token mint @@ -52,11 +60,11 @@ export async function deploy_token( tokenStandard: TokenStandard.Fungible, tokenOwner: fromWeb3JsPublicKey(agent.wallet_address), amount: initialSupply, - }) + }), ); } - builder.sendAndConfirm(umi, { confirm: { commitment: 'finalized' } }); + builder.sendAndConfirm(umi, { confirm: { commitment: "finalized" } }); return { mint: toWeb3JsPublicKey(mint.publicKey), diff --git a/src/tools/fetch_price.ts b/src/tools/fetch_price.ts index 764e8e6..cca1925 100644 --- a/src/tools/fetch_price.ts +++ b/src/tools/fetch_price.ts @@ -1,20 +1,13 @@ -import { SolanaAgentKit } from "../index"; -import { Tool } from "langchain/tools"; +import { PublicKey } from "@solana/web3.js"; /** - * Fetch the price of a given token in USDC using Jupiter API - * @param agent SolanaAgentKit instance + * Fetch the price of a given token quoted in USDC using Jupiter API * @param tokenId The token mint address - * @returns The price of the token in USDC + * @returns The price of the token quoted in USDC */ -export async function fetchPrice( - agent: SolanaAgentKit, - tokenId: string -): Promise { +export async function fetchPrice(tokenId: PublicKey): Promise { try { - const response = await fetch( - `https://api.jup.ag/price/v2?ids=${tokenId}` - ); + const response = await fetch(`https://api.jup.ag/price/v2?ids=${tokenId}`); if (!response.ok) { throw new Error(`Failed to fetch price: ${response.statusText}`); @@ -22,7 +15,7 @@ export async function fetchPrice( const data = await response.json(); - const price = data.data[tokenId]?.price; + const price = data.data[tokenId.toBase58()]?.price; if (!price) { throw new Error("Price data not available for the given token."); @@ -32,4 +25,4 @@ export async function fetchPrice( } catch (error: any) { throw new Error(`Price fetch failed: ${error.message}`); } -} \ No newline at end of file +} diff --git a/src/tools/get_primary_domain.ts b/src/tools/get_primary_domain.ts index 775af4b..1a2bd8c 100644 --- a/src/tools/get_primary_domain.ts +++ b/src/tools/get_primary_domain.ts @@ -16,22 +16,22 @@ import { SolanaAgentKit } from "../index"; */ export async function getPrimaryDomain( agent: SolanaAgentKit, - account: PublicKey + account: PublicKey, ): Promise { try { const { reverse, stale } = await _getPrimaryDomain( agent.connection, - account + account, ); if (stale) { throw new Error( - `Primary domain is stale for account: ${account.toBase58()}` + `Primary domain is stale for account: ${account.toBase58()}`, ); } return reverse; } catch (error) { throw new Error( - `Failed to get primary domain for account: ${account.toBase58()}` + `Failed to get primary domain for account: ${account.toBase58()}`, ); } } diff --git a/src/tools/lend.ts b/src/tools/lend.ts index 7889343..732f00c 100644 --- a/src/tools/lend.ts +++ b/src/tools/lend.ts @@ -1,6 +1,5 @@ import { VersionedTransaction } from "@solana/web3.js"; -import { LuloAccountDetailsResponse } from "../types"; -import { SolanaAgentKit } from "../agent"; +import { SolanaAgentKit } from "../index"; /** * Lend tokens for yields using Lulo @@ -10,7 +9,7 @@ import { SolanaAgentKit } from "../agent"; */ export async function lendAsset( agent: SolanaAgentKit, - amount: number + amount: number, ): Promise { try { const response = await fetch( @@ -23,14 +22,14 @@ export async function lendAsset( body: JSON.stringify({ account: agent.wallet.publicKey.toBase58(), }), - } + }, ); const data = await response.json(); // Deserialize the transaction const luloTxn = VersionedTransaction.deserialize( - Buffer.from(data.transaction, "base64") + Buffer.from(data.transaction, "base64"), ); // Get a recent blockhash and set it diff --git a/src/tools/mint_nft.ts b/src/tools/mint_nft.ts index 09bfe32..4c25b91 100644 --- a/src/tools/mint_nft.ts +++ b/src/tools/mint_nft.ts @@ -1,11 +1,15 @@ import { SolanaAgentKit } from "../index"; -import { generateSigner, keypairIdentity } from '@metaplex-foundation/umi'; -import { create, mplCore } from '@metaplex-foundation/mpl-core'; -import { fetchCollection } from '@metaplex-foundation/mpl-core'; +import { generateSigner, keypairIdentity } from "@metaplex-foundation/umi"; +import { create, mplCore } from "@metaplex-foundation/mpl-core"; +import { fetchCollection } from "@metaplex-foundation/mpl-core"; import { PublicKey } from "@solana/web3.js"; -import { fromWeb3JsKeypair, fromWeb3JsPublicKey, toWeb3JsPublicKey } from "@metaplex-foundation/umi-web3js-adapters"; -import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'; -import { MintCollectionNFTResponse } from '../types'; +import { + fromWeb3JsKeypair, + fromWeb3JsPublicKey, + toWeb3JsPublicKey, +} from "@metaplex-foundation/umi-web3js-adapters"; +import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"; +import { MintCollectionNFTResponse } from "../types"; /** * Mint a new NFT as part of an existing collection @@ -27,7 +31,7 @@ export async function mintCollectionNFT( share: number; }>; }, - recipient?: PublicKey + recipient?: PublicKey, ): Promise { try { // Create UMI instance from agent @@ -49,15 +53,15 @@ export async function mintCollectionNFT( collection: collection, name: metadata.name, uri: metadata.uri, - owner: fromWeb3JsPublicKey(recipient ?? agent.wallet.publicKey) + owner: fromWeb3JsPublicKey(recipient ?? agent.wallet.publicKey), }).sendAndConfirm(umi); return { mint: toWeb3JsPublicKey(assetSigner.publicKey), // Note: Token account is now handled automatically by the create instruction - metadata: toWeb3JsPublicKey(assetSigner.publicKey) + metadata: toWeb3JsPublicKey(assetSigner.publicKey), }; } catch (error: any) { throw new Error(`Collection NFT minting failed: ${error.message}`); } -} \ No newline at end of file +} diff --git a/src/tools/openbook_create_market.ts b/src/tools/openbook_create_market.ts index 4e9c592..c7c12aa 100644 --- a/src/tools/openbook_create_market.ts +++ b/src/tools/openbook_create_market.ts @@ -1,33 +1,34 @@ -import { OPEN_BOOK_PROGRAM, Raydium, TxVersion } from "@raydium-io/raydium-sdk-v2"; +import { + OPEN_BOOK_PROGRAM, + Raydium, + TxVersion, +} from "@raydium-io/raydium-sdk-v2"; import { MintLayout, TOKEN_PROGRAM_ID } from "@solana/spl-token"; import { PublicKey } from "@solana/web3.js"; -import { SolanaAgentKit } from "../agent"; +import { SolanaAgentKit } from "../index"; export async function openbookCreateMarket( agent: SolanaAgentKit, - baseMint: PublicKey, quoteMint: PublicKey, - lotSize: number = 1, tickSize: number = 0.01, ): Promise { - const raydium = await Raydium.load({ owner: agent.wallet, connection: agent.connection, - }) + }); - const baseMintInfo = await agent.connection.getAccountInfo(baseMint) - const quoteMintInfo = await agent.connection.getAccountInfo(quoteMint) + const baseMintInfo = await agent.connection.getAccountInfo(baseMint); + const quoteMintInfo = await agent.connection.getAccountInfo(quoteMint); if ( baseMintInfo?.owner.toString() !== TOKEN_PROGRAM_ID.toBase58() || quoteMintInfo?.owner.toString() !== TOKEN_PROGRAM_ID.toBase58() ) { throw new Error( - 'openbook market only support TOKEN_PROGRAM_ID mints, if you want to create pool with token-2022, please create raydium cpmm pool instead' - ) + "openbook market only support TOKEN_PROGRAM_ID mints, if you want to create pool with token-2022, please create raydium cpmm pool instead", + ); } const { execute } = await raydium.marketV2.create({ @@ -44,9 +45,9 @@ export async function openbookCreateMarket( dexProgramId: OPEN_BOOK_PROGRAM, txVersion: TxVersion.V0, - }) + }); - const { txIds } = await execute({ sequentially: true, }) + const { txIds } = await execute({ sequentially: true }); - return txIds + return txIds; } diff --git a/src/tools/pyth_fetch_price.ts b/src/tools/pyth_fetch_price.ts index 5ff7317..29129f8 100644 --- a/src/tools/pyth_fetch_price.ts +++ b/src/tools/pyth_fetch_price.ts @@ -1,6 +1,3 @@ -import { PublicKey } from "@solana/web3.js"; -import { SolanaAgentKit } from "../index"; -import { Tool } from "langchain/tools"; import { PriceServiceConnection } from "@pythnetwork/price-service-client"; import BN from "bn.js"; @@ -9,40 +6,35 @@ import BN from "bn.js"; * @param agent SolanaAgentKit instance * @param priceFeedID Price feed ID * @returns Latest price value from feed - * + * * You can find priceFeedIDs here: https://www.pyth.network/developers/price-feed-ids#stable */ -export async function pythFetchPrice( - agent: SolanaAgentKit, - priceFeedID: string -) { - // get Hermes service URL from https://docs.pyth.network/price-feeds/api-instances-and-providers/hermes +export async function pythFetchPrice(priceFeedID: string): Promise { + // get Hermes service URL from https://docs.pyth.network/price-feeds/api-instances-and-providers/hermes const stableHermesServiceUrl: string = "https://hermes.pyth.network"; const connection = new PriceServiceConnection(stableHermesServiceUrl); const feeds = [priceFeedID]; try { const currentPrice = await connection.getLatestPriceFeeds(feeds); - + if (currentPrice === undefined) { throw new Error("Price data not available for the given token."); } - + if (currentPrice.length === 0) { throw new Error("Price data not available for the given token."); } - + // get price and exponent from price feed let price = new BN(currentPrice[0].getPriceUnchecked().price); let exponent = new BN(currentPrice[0].getPriceUnchecked().expo); - + // convert to scaled price let scaledPrice = price.div(new BN(10).pow(exponent)); - + return scaledPrice.toString(); } catch (error: any) { throw new Error(`Fetching price from Pyth failed: ${error.message}`); } } - - diff --git a/src/tools/raydium_create_ammV4.ts b/src/tools/raydium_create_ammV4.ts index 53d78b3..98f641e 100644 --- a/src/tools/raydium_create_ammV4.ts +++ b/src/tools/raydium_create_ammV4.ts @@ -1,42 +1,59 @@ -import { AMM_V4, FEE_DESTINATION_ID, MARKET_STATE_LAYOUT_V3, OPEN_BOOK_PROGRAM, Raydium, TxVersion } from "@raydium-io/raydium-sdk-v2"; +import { + AMM_V4, + FEE_DESTINATION_ID, + MARKET_STATE_LAYOUT_V3, + OPEN_BOOK_PROGRAM, + Raydium, + TxVersion, +} from "@raydium-io/raydium-sdk-v2"; import { MintLayout, TOKEN_PROGRAM_ID } from "@solana/spl-token"; import { PublicKey } from "@solana/web3.js"; -import BN from 'bn.js'; -import { SolanaAgentKit } from "../agent"; +import BN from "bn.js"; +import { SolanaAgentKit } from "../index"; export async function raydiumCreateAmmV4( agent: SolanaAgentKit, - marketId: PublicKey, - baseAmount: BN, quoteAmount: BN, - startTime: BN, ): Promise { - const raydium = await Raydium.load({ owner: agent.wallet, connection: agent.connection, - }) + }); - const marketBufferInfo = await agent.connection.getAccountInfo(new PublicKey(marketId)) - const { baseMint, quoteMint } = MARKET_STATE_LAYOUT_V3.decode(marketBufferInfo!.data) + const marketBufferInfo = await agent.connection.getAccountInfo( + new PublicKey(marketId), + ); + const { baseMint, quoteMint } = MARKET_STATE_LAYOUT_V3.decode( + marketBufferInfo!.data, + ); - const baseMintInfo = await agent.connection.getAccountInfo(baseMint) - const quoteMintInfo = await agent.connection.getAccountInfo(quoteMint) + const baseMintInfo = await agent.connection.getAccountInfo(baseMint); + const quoteMintInfo = await agent.connection.getAccountInfo(quoteMint); if ( baseMintInfo?.owner.toString() !== TOKEN_PROGRAM_ID.toBase58() || quoteMintInfo?.owner.toString() !== TOKEN_PROGRAM_ID.toBase58() ) { throw new Error( - 'amm pools with openbook market only support TOKEN_PROGRAM_ID mints, if you want to create pool with token-2022, please create cpmm pool instead' - ) + "amm pools with openbook market only support TOKEN_PROGRAM_ID mints, if you want to create pool with token-2022, please create cpmm pool instead", + ); } - if (baseAmount.mul(quoteAmount).lte(new BN(1).mul(new BN(10 ** MintLayout.decode(baseMintInfo.data).decimals)).pow(new BN(2)))) { - throw new Error('initial liquidity too low, try adding more baseAmount/quoteAmount') + if ( + baseAmount + .mul(quoteAmount) + .lte( + new BN(1) + .mul(new BN(10 ** MintLayout.decode(baseMintInfo.data).decimals)) + .pow(new BN(2)), + ) + ) { + throw new Error( + "initial liquidity too low, try adding more baseAmount/quoteAmount", + ); } const { execute } = await raydium.liquidity.createPoolV4({ @@ -63,9 +80,9 @@ export async function raydiumCreateAmmV4( associatedOnly: false, txVersion: TxVersion.V0, feeDestinationId: FEE_DESTINATION_ID, - }) + }); - const { txId } = await execute({ sendAndConfirm: true }) + const { txId } = await execute({ sendAndConfirm: true }); - return txId -} \ No newline at end of file + return txId; +} diff --git a/src/tools/raydium_create_clmm.ts b/src/tools/raydium_create_clmm.ts index 8dbd5e6..b77ab74 100644 --- a/src/tools/raydium_create_clmm.ts +++ b/src/tools/raydium_create_clmm.ts @@ -1,55 +1,58 @@ -import { CLMM_PROGRAM_ID, Raydium, TxVersion } from '@raydium-io/raydium-sdk-v2' -import { MintLayout } from '@solana/spl-token' -import { PublicKey } from '@solana/web3.js' -import BN from 'bn.js' -import Decimal from 'decimal.js' -import { SolanaAgentKit } from '../agent' +import { + CLMM_PROGRAM_ID, + Raydium, + TxVersion, +} from "@raydium-io/raydium-sdk-v2"; +import { MintLayout } from "@solana/spl-token"; +import { PublicKey } from "@solana/web3.js"; +import BN from "bn.js"; +import Decimal from "decimal.js"; +import { SolanaAgentKit } from "../index"; export async function raydiumCreateClmm( agent: SolanaAgentKit, - mint1: PublicKey, mint2: PublicKey, - configId: PublicKey, - initialPrice: Decimal, startTime: BN, ): Promise { - const raydium = await Raydium.load({ owner: agent.wallet, connection: agent.connection, - }) + }); - const [mintInfo1, mintInfo2] = await agent.connection.getMultipleAccountsInfo([mint1, mint2]) - if (mintInfo1 === null || mintInfo2 === null) throw Error('fetch mint info error') + const [mintInfo1, mintInfo2] = await agent.connection.getMultipleAccountsInfo( + [mint1, mint2], + ); + if (mintInfo1 === null || mintInfo2 === null) + throw Error("fetch mint info error"); - const mintDecodeInfo1 = MintLayout.decode(mintInfo1.data) - const mintDecodeInfo2 = MintLayout.decode(mintInfo2.data) + const mintDecodeInfo1 = MintLayout.decode(mintInfo1.data); + const mintDecodeInfo2 = MintLayout.decode(mintInfo2.data); const mintFormatInfo1 = { chainId: 101, address: mint1.toString(), programId: mintInfo1.owner.toString(), - logoURI: '', - symbol: '', - name: '', + logoURI: "", + symbol: "", + name: "", decimals: mintDecodeInfo1.decimals, tags: [], - extensions: {} - } + extensions: {}, + }; const mintFormatInfo2 = { chainId: 101, address: mint2.toString(), programId: mintInfo2.owner.toString(), - logoURI: '', - symbol: '', - name: '', + logoURI: "", + symbol: "", + name: "", decimals: mintDecodeInfo2.decimals, tags: [], - extensions: {} - } + extensions: {}, + }; const { execute } = await raydium.clmm.createPool({ programId: CLMM_PROGRAM_ID, @@ -65,9 +68,9 @@ export async function raydiumCreateClmm( // units: 600000, // microLamports: 46591500, // }, - }) + }); - const { txId } = await execute({ sendAndConfirm: true }) + const { txId } = await execute({ sendAndConfirm: true }); - return txId + return txId; } diff --git a/src/tools/raydium_create_cpmm.ts b/src/tools/raydium_create_cpmm.ts index 4a520e2..d1c4dbd 100644 --- a/src/tools/raydium_create_cpmm.ts +++ b/src/tools/raydium_create_cpmm.ts @@ -2,60 +2,58 @@ import { CREATE_CPMM_POOL_FEE_ACC, CREATE_CPMM_POOL_PROGRAM, Raydium, - TxVersion -} from '@raydium-io/raydium-sdk-v2' -import { MintLayout } from '@solana/spl-token' -import { PublicKey } from '@solana/web3.js' -import BN from 'bn.js' -import { SolanaAgentKit } from '../agent' + TxVersion, +} from "@raydium-io/raydium-sdk-v2"; +import { MintLayout } from "@solana/spl-token"; +import { PublicKey } from "@solana/web3.js"; +import BN from "bn.js"; +import { SolanaAgentKit } from "../index"; export async function raydiumCreateCpmm( agent: SolanaAgentKit, - mintA: PublicKey, mintB: PublicKey, - configId: PublicKey, - mintAAmount: BN, mintBAmount: BN, - startTime: BN, ): Promise { - const raydium = await Raydium.load({ owner: agent.wallet, connection: agent.connection, - }) + }); - const [mintInfoA, mintInfoB] = await agent.connection.getMultipleAccountsInfo([mintA, mintB]) - if (mintInfoA === null || mintInfoB === null) throw Error('fetch mint info error') + const [mintInfoA, mintInfoB] = await agent.connection.getMultipleAccountsInfo( + [mintA, mintB], + ); + if (mintInfoA === null || mintInfoB === null) + throw Error("fetch mint info error"); - const mintDecodeInfoA = MintLayout.decode(mintInfoA.data) - const mintDecodeInfoB = MintLayout.decode(mintInfoB.data) + const mintDecodeInfoA = MintLayout.decode(mintInfoA.data); + const mintDecodeInfoB = MintLayout.decode(mintInfoB.data); const mintFormatInfoA = { chainId: 101, address: mintA.toString(), programId: mintInfoA.owner.toString(), - logoURI: '', - symbol: '', - name: '', + logoURI: "", + symbol: "", + name: "", decimals: mintDecodeInfoA.decimals, tags: [], - extensions: {} - } + extensions: {}, + }; const mintFormatInfoB = { chainId: 101, address: mintB.toString(), programId: mintInfoB.owner.toString(), - logoURI: '', - symbol: '', - name: '', + logoURI: "", + symbol: "", + name: "", decimals: mintDecodeInfoB.decimals, tags: [], - extensions: {} - } + extensions: {}, + }; const { execute, extInfo } = await raydium.cpmm.createPool({ programId: CREATE_CPMM_POOL_PROGRAM, @@ -76,9 +74,9 @@ export async function raydiumCreateCpmm( // units: 600000, // microLamports: 46591500, // }, - }) + }); - const { txId } = await execute({ sendAndConfirm: true }) + const { txId } = await execute({ sendAndConfirm: true }); - return txId + return txId; } diff --git a/src/tools/resolve_sol_domain.ts b/src/tools/resolve_sol_domain.ts index d8764cc..6969a4c 100644 --- a/src/tools/resolve_sol_domain.ts +++ b/src/tools/resolve_sol_domain.ts @@ -16,7 +16,7 @@ import { SolanaAgentKit } from "../index"; */ export async function resolveSolDomain( agent: SolanaAgentKit, - domain: string + domain: string, ): Promise { if (!domain || typeof domain !== "string") { throw new Error("Invalid domain. Expected a non-empty string."); diff --git a/src/tools/send_compressed_airdrop.ts b/src/tools/send_compressed_airdrop.ts index 313bbdb..2a66e47 100644 --- a/src/tools/send_compressed_airdrop.ts +++ b/src/tools/send_compressed_airdrop.ts @@ -1,12 +1,11 @@ import { AddressLookupTableAccount, ComputeBudgetProgram, - Connection, Keypair, PublicKey, TransactionInstruction, } from "@solana/web3.js"; -import { SolanaAgentKit } from "../agent/index.js"; +import { SolanaAgentKit } from "../index"; import { buildAndSignTx, calculateComputeUnitPrice, @@ -33,7 +32,7 @@ const MAX_CONCURRENT_TXS = 30; */ export const getAirdropCostEstimate = ( numberOfRecipients: number, - priorityFeeInLamports: number + priorityFeeInLamports: number, ) => { const baseFee = 5000; const perRecipientCompressedStateFee = 300; @@ -63,22 +62,21 @@ export async function sendCompressedAirdrop( decimals: number, recipients: PublicKey[], priorityFeeInLamports: number, - shouldLog: boolean = false + shouldLog: boolean = false, ): Promise { if (recipients.length > MAX_AIRDROP_RECIPIENTS) { throw new Error( - `Max airdrop can be ${MAX_AIRDROP_RECIPIENTS} recipients at a time. For more scale, use open source ZK Compression airdrop tools such as https://github.com/helius-labs/airship.` + `Max airdrop can be ${MAX_AIRDROP_RECIPIENTS} recipients at a time. For more scale, use open source ZK Compression airdrop tools such as https://github.com/helius-labs/airship.`, ); } - const url = agent.connection.rpcEndpoint; if (url.includes("devnet")) { throw new Error("Devnet is not supported for airdrop. Please use mainnet."); } if (!url.includes("helius")) { console.warn( - "Warning: Must use RPC with ZK Compression support. Double check with your RPC provider if in doubt." + "Warning: Must use RPC with ZK Compression support. Double check with your RPC provider if in doubt.", ); } @@ -88,11 +86,11 @@ export async function sendCompressedAirdrop( agent.connection, agent.wallet, mintAddress, - agent.wallet.publicKey + agent.wallet.publicKey, ); } catch (error) { throw new Error( - "Source token account not found and failed to create it. Please add funds to your wallet and try again." + "Source token account not found and failed to create it. Please add funds to your wallet and try again.", ); } @@ -100,7 +98,7 @@ export async function sendCompressedAirdrop( await createTokenPool( agent.connection as unknown as Rpc, agent.wallet, - mintAddress + mintAddress, ); } catch (error: any) { if (error.message.includes("already in use")) { @@ -116,7 +114,7 @@ export async function sendCompressedAirdrop( mintAddress, recipients, priorityFeeInLamports, - shouldLog + shouldLog, ); } @@ -126,7 +124,7 @@ async function processAll( mint: PublicKey, recipients: PublicKey[], priorityFeeInLamports: number, - shouldLog: boolean + shouldLog: boolean, ): Promise { const mintAddress = mint; const payer = agent.wallet; @@ -135,13 +133,13 @@ async function processAll( agent.connection, agent.wallet, mintAddress, - agent.wallet.publicKey + agent.wallet.publicKey, ); const maxRecipientsPerInstruction = 5; const maxIxs = 3; // empirically determined (as of 12/15/2024) const lookupTableAddress = new PublicKey( - "9NYFyEqPkyXUhkerbGHXUXkvb4qpzeEdHuGpgbgpH1NJ" + "9NYFyEqPkyXUhkerbGHXUXkvb4qpzeEdHuGpgbgpH1NJ", ); const lookupTableAccount = ( @@ -164,7 +162,7 @@ async function processAll( ComputeBudgetProgram.setComputeUnitPrice({ microLamports: calculateComputeUnitPrice( priorityFeeInLamports, - 500_000 + 500_000, ), }), ]; @@ -184,13 +182,13 @@ async function processAll( toAddress: batch, amount: batch.map(() => amount), mint: mintAddress, - }) + }), ); } const compressIxs = await Promise.all(compressIxPromises); return [...instructions, ...compressIxs]; - }) + }), ); const url = agent.connection.rpcEndpoint; @@ -225,12 +223,12 @@ async function processAll( instructions, payer, lookupTableAccount, - i + idx + i + idx, ).then((signature) => { confirmedCount++; log("\r" + renderProgressBar(confirmedCount, totalBatches)); return signature; - }) + }), ); const batchResults = await Promise.allSettled(batchPromises); @@ -250,7 +248,7 @@ async function processAll( throw new Error( `Failed to process ${failures.length} batches: ${failures .map((f) => f.error) - .join(", ")}` + .join(", ")}`, ); } @@ -262,7 +260,7 @@ async function sendTransactionWithRetry( instructions: TransactionInstruction[], payer: Keypair, lookupTableAccount: AddressLookupTableAccount, - batchIndex: number + batchIndex: number, ): Promise { const MAX_RETRIES = 3; const INITIAL_BACKOFF = 500; // ms @@ -275,7 +273,7 @@ async function sendTransactionWithRetry( payer, blockhash, [], - [lookupTableAccount] + [lookupTableAccount], ); const signature = await sendAndConfirmTx(connection, tx); @@ -292,7 +290,7 @@ async function sendTransactionWithRetry( throw new Error( `Batch ${batchIndex} failed after ${attempt + 1} attempts: ${ error.message - }` + }`, ); } diff --git a/src/tools/stake_with_jup.ts b/src/tools/stake_with_jup.ts index e152532..c05915b 100644 --- a/src/tools/stake_with_jup.ts +++ b/src/tools/stake_with_jup.ts @@ -1,5 +1,5 @@ import { VersionedTransaction } from "@solana/web3.js"; -import { SolanaAgentKit } from "../agent"; +import { SolanaAgentKit } from "../index"; /** * Stake SOL with Jup validator diff --git a/src/tools/trade.ts b/src/tools/trade.ts index b17bc41..b42cc2a 100644 --- a/src/tools/trade.ts +++ b/src/tools/trade.ts @@ -1,4 +1,8 @@ -import { VersionedTransaction, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js"; +import { + VersionedTransaction, + PublicKey, + LAMPORTS_PER_SOL, +} from "@solana/web3.js"; import { SolanaAgentKit } from "../index"; import { TOKENS, DEFAULT_OPTIONS, JUP_API } from "../constants"; diff --git a/src/tools/transfer.ts b/src/tools/transfer.ts index acfec82..9e11dd7 100644 --- a/src/tools/transfer.ts +++ b/src/tools/transfer.ts @@ -1,14 +1,10 @@ import { SolanaAgentKit } from "../index"; -import { - PublicKey, - SystemProgram, - Transaction -} from "@solana/web3.js"; +import { PublicKey, SystemProgram, Transaction } from "@solana/web3.js"; import { LAMPORTS_PER_SOL } from "@solana/web3.js"; -import { - getAssociatedTokenAddress, +import { + getAssociatedTokenAddress, createTransferInstruction, - getMint + getMint, } from "@solana/spl-token"; /** @@ -23,7 +19,7 @@ export async function transfer( agent: SolanaAgentKit, to: PublicKey, amount: number, - mint?: PublicKey + mint?: PublicKey, ): Promise { try { let tx: string; @@ -34,19 +30,19 @@ export async function transfer( SystemProgram.transfer({ fromPubkey: agent.wallet_address, toPubkey: to, - lamports: amount * LAMPORTS_PER_SOL - }) + lamports: amount * LAMPORTS_PER_SOL, + }), ); - tx = await agent.connection.sendTransaction( - transaction, - [agent.wallet] - ); + tx = await agent.connection.sendTransaction(transaction, [agent.wallet]); } else { // Transfer SPL token - const fromAta = await getAssociatedTokenAddress(mint, agent.wallet_address); + const fromAta = await getAssociatedTokenAddress( + mint, + agent.wallet_address, + ); const toAta = await getAssociatedTokenAddress(mint, to); - + // Get mint info to determine decimals const mintInfo = await getMint(agent.connection, mint); const adjustedAmount = amount * Math.pow(10, mintInfo.decimals); @@ -56,18 +52,15 @@ export async function transfer( fromAta, toAta, agent.wallet_address, - adjustedAmount - ) + adjustedAmount, + ), ); - tx = await agent.connection.sendTransaction( - transaction, - [agent.wallet] - ); + tx = await agent.connection.sendTransaction(transaction, [agent.wallet]); } return tx; } catch (error: any) { throw new Error(`Transfer failed: ${error.message}`); } -} \ No newline at end of file +} diff --git a/src/utils/send_tx.ts b/src/utils/send_tx.ts index 903ddd5..593cbc8 100644 --- a/src/utils/send_tx.ts +++ b/src/utils/send_tx.ts @@ -41,7 +41,7 @@ export async function getPriorityFees(connection: Connection): Promise<{ const median = sortedFees.length % 2 === 0 ? ((sortedFees[mid - 1] ?? 0) + (sortedFees[mid] ?? 0)) / 2 - : sortedFees[mid] ?? 0; + : (sortedFees[mid] ?? 0); // Helper to create priority fee IX based on chosen strategy const createPriorityFeeIx = (fee: number) => { @@ -76,7 +76,7 @@ export async function getPriorityFees(connection: Connection): Promise<{ export async function sendTx( agent: SolanaAgentKit, tx: Transaction, - otherKeypairs?: Keypair[] + otherKeypairs?: Keypair[], ) { tx.recentBlockhash = (await agent.connection.getLatestBlockhash()).blockhash; tx.feePayer = agent.wallet_address; @@ -90,9 +90,8 @@ export async function sendTx( await agent.connection.confirmTransaction({ signature: txid, blockhash: (await agent.connection.getLatestBlockhash()).blockhash, - lastValidBlockHeight: ( - await agent.connection.getLatestBlockhash() - ).lastValidBlockHeight, + lastValidBlockHeight: (await agent.connection.getLatestBlockhash()) + .lastValidBlockHeight, }); return txid; } diff --git a/test/domain_methods.test.ts b/test/domain_methods.test.ts deleted file mode 100644 index 2485ed7..0000000 --- a/test/domain_methods.test.ts +++ /dev/null @@ -1,146 +0,0 @@ - -import { SolanaAgentKit } from "../src"; -import { PublicKey } from "@solana/web3.js"; -import * as dotenv from "dotenv"; -import { expect } from "chai"; -import { before, describe, it } from "node:test"; -import { TldParser } from "@onsol/tldparser"; - -dotenv.config(); - -describe("Solana Domain Methods Tests", () => { - let agent: SolanaAgentKit; - - before(() => { - // Initialize the agent before running tests - if ( - !process.env.SOLANA_PRIVATE_KEY || - !process.env.RPC_URL || - !process.env.OPENAI_API_KEY - ) { - throw new Error("Required environment variables are not set"); - } - - agent = new SolanaAgentKit( - process.env.SOLANA_PRIVATE_KEY, - process.env.RPC_URL, - process.env.OPENAI_API_KEY - ); - }); - - describe("resolveAllDomains", () => { - it("should resolve a valid domain to a public key", async () => { - const testDomain = "hero.sol"; - const result = await agent.resolveAllDomains(testDomain); - expect(result).to.be.instanceof(PublicKey); - }); - it("should perform fetching of an owner an nft domain", async () => { - const parser = new TldParser(agent.connection); - const domanTld = "miester.sol"; - const ownerReceived = await parser.getOwnerFromDomainTld(domanTld); - const owner = new PublicKey( - "2EGGxj2qbNAJNgLCPKca8sxZYetyTjnoRspTPjzN2D67" - ); - expect(ownerReceived).to.be(owner.toString()); - }); - it("should return null for non-existent domain", async () => { - const nonExistentDomain = "nonexistent123456789.sol"; - const result = await agent.resolveAllDomains(nonExistentDomain); - expect(result).to.be.null; - }); - - it("should handle invalid domain format", async () => { - const invalidDomain = ""; - try { - await agent.resolveAllDomains(invalidDomain); - expect.fail("Should have thrown an error"); - } catch (error) { - expect(error).to.be.instanceof(Error); - } - }); - }); - - describe("getOwnedAllDomains", () => { - it("should return array of domains for an owner", async () => { - const owner = new PublicKey( - "2EGGxj2qbNAJNgLCPKca8sxZYetyTjnoRspTPjzN2D67" - ); - const domains = await agent.getOwnedAllDomains(owner); - expect(domains).to.be.an("array").that.includes("miester.sol"); - domains.forEach((domain) => { - expect(domain).to.be.a("string"); - }); - }); - it("should return array of domains for an owner", async () => { - const owner = new PublicKey(agent.wallet_address); - const domains = await agent.getOwnedAllDomains(owner); - expect(domains).to.be.an("array"); - domains.forEach((domain) => { - expect(domain).to.be.a("string"); - }); - }); - - it("should handle owner with no domains", async () => { - // Create a new random public key that likely owns no domains - const emptyOwner = PublicKey.unique(); - const domains = await agent.getOwnedAllDomains(emptyOwner); - expect(domains).to.be.an("array"); - expect(domains).to.have.lengthOf(0); - }); - }); - - describe("getOwnedDomainsForTLD", () => { - it("should return domains for specific TLD", async () => { - const tld = "sol"; - const domains = await agent.getOwnedDomainsForTLD(tld); - expect(domains).to.be.an("array"); - domains.forEach((domain) => { - console.log(`these are the domains ${domain.domain}`) - }); - }); - - it("should return empty array for non-existent TLD", async () => { - const nonExistentTLD = "nonexistent"; - const domains = await agent.getOwnedDomainsForTLD(nonExistentTLD); - expect(domains).to.be.an("array"); - expect(domains).to.have.lengthOf(0); - }); - }); - - describe("getAllDomainsTLDs", () => { - it("should return array of TLDs", async () => { - const tlds = await agent.getAllDomainsTLDs(); - expect(tlds).to.be.an("array"); - }); - }); - - describe("getAllRegisteredAllDomains", () => { - it("should return array of all registered domains", async () => { - const domains = await agent.getAllRegisteredAllDomains(); - expect(domains).to.be.an("array"); - domains.forEach((domain) => { - expect(domain).to.be.a("string"); - expect(domain).to.include("."); - }); - }); - }); - - describe("getMainAllDomainsDomain", () => { - it("should return main domain or null for an owner", async () => { - const owner = new PublicKey( - "2EGGxj2qbNAJNgLCPKca8sxZYetyTjnoRspTPjzN2D67" - ); - const mainDomain = await agent.getMainAllDomainsDomain(owner); - expect(mainDomain).to.satisfy((domain: string | null) => { - return domain === null || typeof domain === "string"; - }); - }); - - it("should return null for address without main domain", async () => { - const emptyOwner = PublicKey.unique(); - const mainDomain = await agent.getMainAllDomainsDomain(emptyOwner); - expect(mainDomain).to.be.null; - }); - }); -}); - diff --git a/test/index.ts b/test/index.ts index 00faade..7cbf8bc 100644 --- a/test/index.ts +++ b/test/index.ts @@ -14,7 +14,7 @@ function validateEnvironment(): void { const missingVars: string[] = []; const requiredVars = ["OPENAI_API_KEY", "RPC_URL", "SOLANA_PRIVATE_KEY"]; - requiredVars.forEach(varName => { + requiredVars.forEach((varName) => { if (!process.env[varName]) { missingVars.push(varName); } @@ -22,7 +22,7 @@ function validateEnvironment(): void { if (missingVars.length > 0) { console.error("Error: Required environment variables are not set"); - missingVars.forEach(varName => { + missingVars.forEach((varName) => { console.error(`${varName}=your_${varName.toLowerCase()}_here`); }); process.exit(1); @@ -50,13 +50,13 @@ async function initializeAgent() { } } - const solanaKit = new SolanaAgentKit( + const solanaAgent = new SolanaAgentKit( process.env.SOLANA_PRIVATE_KEY!, process.env.RPC_URL, - process.env.OPENAI_API_KEY! + process.env.OPENAI_API_KEY!, ); - const tools = createSolanaTools(solanaKit); + const tools = createSolanaTools(solanaAgent); const memory = new MemorySaver(); const config = { configurable: { thread_id: "Solana Agent Kit!" } }; @@ -65,14 +65,13 @@ async function initializeAgent() { tools, checkpointSaver: memory, messageModifier: ` - You are a helpful agent that can interact onchain using the Solana Agent Kit. You are - empowered to interact onchain using your tools. If you ever need funds, you can request them from the - faucet. If not, you can provide your wallet details and request funds from the user. If there is a 5XX - (internal) HTTP error code, ask the user to try again later. If someone asks you to do something you - can't do with your currently available tools, you must say so, and encourage them to implement it - themselves using the Solana Agent Kit, recommend they go to https://www.solanaagentkit.xyz for more information. Be - concise and helpful with your responses. Refrain from restating your tools' descriptions unless it is - explicitly requested. + You are a helpful agent that can interact onchain using the Solana Agent Kit. You are + empowered to interact onchain using your tools. If you ever need funds, you can request them from the + faucet. If not, you can provide your wallet details and request funds from the user. If there is a 5XX + (internal) HTTP error code, ask the user to try again later. If someone asks you to do something you + can't do with your currently available tools, you must say so, and encourage them to implement it + themselves using the Solana Agent Kit, recommend they go to https://www.solanaagentkit.xyz for more information. Be + concise and helpful with your responses. Refrain from restating your tools' descriptions unless it is explicitly requested. `, }); @@ -96,7 +95,10 @@ async function runAutonomousMode(agent: any, config: any, interval = 10) { "Be creative and do something interesting on the blockchain. " + "Choose an action or set of actions and execute it that highlights your abilities."; - const stream = await agent.stream({ messages: [new HumanMessage(thought)] }, config); + const stream = await agent.stream( + { messages: [new HumanMessage(thought)] }, + config, + ); for await (const chunk of stream) { if ("agent" in chunk) { @@ -107,7 +109,7 @@ async function runAutonomousMode(agent: any, config: any, interval = 10) { console.log("-------------------"); } - await new Promise(resolve => setTimeout(resolve, interval * 1000)); + await new Promise((resolve) => setTimeout(resolve, interval * 1000)); } catch (error) { if (error instanceof Error) { console.error("Error:", error.message); @@ -126,7 +128,7 @@ async function runChatMode(agent: any, config: any) { }); const question = (prompt: string): Promise => - new Promise(resolve => rl.question(prompt, resolve)); + new Promise((resolve) => rl.question(prompt, resolve)); try { while (true) { @@ -136,7 +138,10 @@ async function runChatMode(agent: any, config: any) { break; } - const stream = await agent.stream({ messages: [new HumanMessage(userInput)] }, config); + const stream = await agent.stream( + { messages: [new HumanMessage(userInput)] }, + config, + ); for await (const chunk of stream) { if ("agent" in chunk) { @@ -164,7 +169,7 @@ async function chooseMode(): Promise<"chat" | "auto"> { }); const question = (prompt: string): Promise => - new Promise(resolve => rl.question(prompt, resolve)); + new Promise((resolve) => rl.question(prompt, resolve)); while (true) { console.log("\nAvailable modes:"); @@ -206,7 +211,7 @@ async function main() { } if (require.main === module) { - main().catch(error => { + main().catch((error) => { console.error("Fatal error:", error); process.exit(1); });