Merge branch 'main' into main

This commit is contained in:
Damjan Dimitrov
2025-01-10 11:35:22 +01:00
committed by GitHub
80 changed files with 12866 additions and 2983 deletions

View File

@@ -2,4 +2,5 @@ OPENAI_API_KEY=
RPC_URL=
SOLANA_PRIVATE_KEY=
JUPITER_REFERRAL_ACCOUNT=
JUPITER_FEE_BPS=
JUPITER_FEE_BPS=
FLASH_PRIVILEGE= referral | nft | none

29
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: ci
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
version: 9.4.0
- uses: actions/setup-node@v4
with:
node-version: "23"
cache: "pnpm"
- name: Install dependencies
run: pnpm install -r --no-frozen-lockfile
- name: Run lint and fix
run: pnpm run lint:fix
- name: Build packages
run: pnpm run build

1
.husky/pre-commit Normal file
View File

@@ -0,0 +1 @@
tsc && lint-staged

5
.lintstagedrc Normal file
View File

@@ -0,0 +1,5 @@
{
"**/*.+(ts|tsx)": [
"eslint . --ext .ts --fix"
]
}

View File

@@ -4,7 +4,6 @@
![Solana Agent Kit Cover 1 (3)](https://github.com/user-attachments/assets/cfa380f6-79d9-474d-9852-3e1976c6de70)
![NPM Downloads](https://img.shields.io/npm/dm/solana-agent-kit?style=for-the-badge)
![GitHub forks](https://img.shields.io/github/forks/sendaifun/solana-agent-kit?style=for-the-badge)
![GitHub License](https://img.shields.io/github/license/sendaifun/solana-agent-kit?style=for-the-badge)
@@ -23,7 +22,6 @@ An open-source toolkit for connecting AI agents to Solana protocols. Now, any ag
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.
[![Run on Repl.it](https://replit.com/badge/github/sendaifun/solana-agent-kit)](https://replit.com/@sendaifun/Solana-Agent-Kit)
> Replit template created by [Arpit Singh](https://github.com/The-x-35)
@@ -35,7 +33,10 @@ Anyone - whether an SF-based AI researcher or a crypto-native builder - can brin
- Balance checks
- Stake SOL
- Zk compressed Airdrop by Light Protocol and Helius
- **NFTs on 3.Land**
- Create your own collection
- NFT creation and automatic listing on 3.land
- List your NFT for sale in any SPL token
- **NFT Management via Metaplex**
- Collection deployment
- NFT minting
@@ -90,6 +91,9 @@ Anyone - whether an SF-based AI researcher or a crypto-native builder - can brin
- Price feed integration for market analysis
- Automated decision-making capabilities
## 📃 Documentation
You can view the full documentation of the kit at [docs.solanaagentkit.xyz](https://docs.solanaagentkit.xyz)
## 📦 Installation
```bash
@@ -127,6 +131,57 @@ const result = await agent.deployToken(
console.log("Token Mint Address:", result.mint.toString());
```
### Create NFT Collection on 3Land
```typescript
const optionsWithBase58: StoreInitOptions = {
privateKey: "",
isMainnet: true, // if false, collection will be created on devnet 3.land (dev.3.land)
};
const collectionOpts: CreateCollectionOptions = {
collectionName: "",
collectionSymbol: "",
collectionDescription: "",
mainImageUrl: ""
};
const result = await agent.create3LandCollection(
optionsWithBase58,
collectionOpts
);
```
### Create NFT on 3Land
When creating an NFT using 3Land's tool, it automatically goes for sale on 3.land website
```typescript
const optionsWithBase58: StoreInitOptions = {
privateKey: "",
isMainnet: true, // if false, listing will be on devnet 3.land (dev.3.land)
};
const collectionAccount = ""; //hash for the collection
const createItemOptions: CreateSingleOptions = {
itemName: "",
sellerFee: 500, //5%
itemAmount: 100, //total items to be created
itemSymbol: "",
itemDescription: "",
traits: [
{ trait_type: "", value: "" },
],
price: 0, //100000000 == 0.1 sol, can be set to 0 for a free mint
mainImageUrl: "",
splHash: "", //present if listing is on a specific SPL token, if not present sale will be on $SOL
};
const isMainnet = true;
const result = await agent.create3LandNft(
optionsWithBase58,
collectionAccount,
createItemOptions,
isMainnet
);
```
### Create NFT Collection
@@ -214,11 +269,11 @@ import { PublicKey } from "@solana/web3.js";
```typescript
const price = await agent.pythFetchPrice(
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"
);
const priceFeedID = await agent.getPythPriceFeedID("SOL");
console.log("Price in BTC/USD:", price);
const price = await agent.getPythPrice(priceFeedID);
console.log("Price of SOL/USD:", price);
```
### Open PERP Trade
@@ -247,6 +302,13 @@ const signature = await agent.closePerpTradeLong({
});
```
### Close Empty Token Accounts
``` typescript
const { signature } = await agent.closeEmptyTokenAccounts();
```
## Examples
### LangGraph Multi-Agent System
@@ -275,7 +337,6 @@ The toolkit relies on several key Solana and Metaplex libraries:
- @metaplex-foundation/umi
- @lightprotocol/compressed-token
- @lightprotocol/stateless.js
- @pythnetwork/price-service-client
## Contributing
@@ -288,7 +349,6 @@ Refer to [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines on how to co
<img src="https://contrib.rocks/image?repo=sendaifun/solana-agent-kit" />
</a>
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=sendaifun/solana-agent-kit&type=Date)](https://star-history.com/#sendaifun/solana-agent-kit&Date)
@@ -305,4 +365,4 @@ Solana Network : EKHTbXpsm6YDgJzMkFxNU1LNXeWcUW7Ezf8mjUNQQ4Pa
## Security
This toolkit handles private keys and transactions. Always ensure you're using it in a secure environment and never share your private keys.
This toolkit handles private keys and transactions. Always ensure you're using it in a secure environment and never share your private keys.

View File

@@ -1 +1 @@
window.hierarchyData = "eJyrVirKzy8pVrKKjtVRKkpNy0lNLsnMzytWsqqurQUAmx4Kpg=="
window.hierarchyData = "eJyrVirKzy8pVrKKjtVRKkpNy0lNLsnMzwMKVNfWAgCbHgqm"

View File

@@ -1 +1 @@
window.navigationData = "eJyNlU1PwkAQhv/LnokIfnMjIH6hEmy8GA/rMqWbLrNNd1Yhxv9uKMRSuh289NB53mfayXT79i0IliR64sUaibI/B6QHTaIlMkmJ6AllpHPg2tX6UUILI1oi1TgTvU738qf1Z+or0hZLg0aCPJYKXHtTqoa7Z+e18PVSLjIDjGNLcKqBNQYKeAiZsasFIAWNIfB/4udsfXUHrFuKV2Ks5w2edYkN5yDJ5uH0psbFR0AqmeRawRRcZtGF517HOOmN/viyeVq0h0i6dArN6iaYa3DvM02QRzYFHEqSQfE+xAnH3ti+UtYjDYGkNo4dRzPONXnUSOViPI0itkcjzbWY+EUWexxLjyph9UHykHrksRgnt/oBjtWuKPnnEoZRTl48xCABlQaFZZmT3EqcGdj5wmiVgWtvb+8lj68uOmfd3TNtEN09P72U6U+Za/lh1ofZplQ1nOyGVfFRbE7fyFqzM/HYY7EYrl2DqsLz05rwFXIFpn93QFnBGCksQXmC/aO/1FUARhRrnDVbyiqjmANV/hHB16tBNeH7L4Zcd8U="
window.navigationData = "eJyNlsFy0zAQQP/F5w6lKS3QW0gIBEqTaT1cOhy28ibWWJY80hqSYfh3FCdT27G89iUH7du3ykob5flvRLij6C56Mgo0TLeo6buk6CIqgFK/LhQ4h+6yHX+TUq48lEmdRHdXkw//Ll5NU0HS6NogNaHdgPCSY6idPLm57SR/3kFeKGQcJ4JTfQIS6comaNdAPj28pQ7FKWdGKazqz7FQZp/7bgStIXCceFUcPt2A9UTxSr2R2x7PIcQmWwQyNpx9jHHpC/RNXVsp8BFd4TcaPsouxkr9TUxnyjiMLSS4Bgt5uE9BclA9yjpS+EW+/DE2q1qFMbjsEfvb0AdzBb6VhfSC2GSo50AQFJ9DnPC+VGYqhCk1zZFAKsceXT/OFfnhDfUlfljEbI1emitxGuXeU2zEOc26zItNqe+h1CJldxkkh9SLUlenwk17gGO1e0pHzl0YHZJX8AIxWc6XhHmv+YwbpR0WDqmqNs1SFFnQU4c5yVfQicLGzx7tC598Wj7LfPvx/dXNpPl2zeLl6uGpzv4NVsKLOjxax1DbcN1MFtX0H1/Z2BjVuBP+dlUT4C47UFt4+64j/IlWoJouB5QtjJHiDkVJeP7E17oWwIg2fqnfUkcZxRap9V8g+PU6UEf46z+zhSAU"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
<!DOCTYPE html><html class="default" lang="en" data-base=".."><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>executeAction | solana-agent-kit</title><meta name="description" content="Documentation for solana-agent-kit"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><div class="table-cell" id="tsd-search"><div class="field"><label for="tsd-search-field" class="tsd-widget tsd-toolbar-icon search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-search"></use></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div><div class="field"><div id="tsd-toolbar-links"></div></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">solana-agent-kit</a></div><div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget tsd-toolbar-icon menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb"><li><a href="../modules.html">solana-agent-kit</a></li><li><a href="executeAction.html">executeAction</a></li></ul><h1>Function executeAction</h1></div><section class="tsd-panel"><ul class="tsd-signatures"><li class="tsd-signature tsd-anchor-link"><a id="executeaction" class="tsd-anchor"></a><span class="tsd-kind-call-signature">executeAction</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">action</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Action</span><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">agent</span><span class="tsd-signature-symbol">:</span> <a href="../classes/SolanaAgentKit.html" class="tsd-signature-type tsd-kind-class">SolanaAgentKit</a><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">input</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">&gt;</span><a href="#executeaction" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></li><li class="tsd-description"><div class="tsd-comment tsd-typography"><p>Execute an action with the given input</p>
</div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">action</span>: <span class="tsd-signature-type">Action</span></span></li><li><span><span class="tsd-kind-parameter">agent</span>: <a href="../classes/SolanaAgentKit.html" class="tsd-signature-type tsd-kind-class">SolanaAgentKit</a></span></li><li><span><span class="tsd-kind-parameter">input</span>: <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">&gt;</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">&gt;</span></h4><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/sendaifun/solana-agent-kit/blob/da09193d9d98e5d5a2ee1df9b1d5b8500b8c5a55/src/utils/actionExecutor.ts#L20">utils/actionExecutor.ts:20</a></li></ul></aside></li></ul></section></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">solana-agent-kit</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
</div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">action</span>: <span class="tsd-signature-type">Action</span></span></li><li><span><span class="tsd-kind-parameter">agent</span>: <a href="../classes/SolanaAgentKit.html" class="tsd-signature-type tsd-kind-class">SolanaAgentKit</a></span></li><li><span><span class="tsd-kind-parameter">input</span>: <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">&gt;</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">&gt;</span></h4><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/UjjwalGupta49/solana-agent-kit/blob/f77cada52ac7e1627f9218cc72a2789f712a4532/src/utils/actionExecutor.ts#L20">utils/actionExecutor.ts:20</a></li></ul></aside></li></ul></section></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">solana-agent-kit</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>

View File

@@ -1,2 +1,2 @@
<!DOCTYPE html><html class="default" lang="en" data-base=".."><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>findAction | solana-agent-kit</title><meta name="description" content="Documentation for solana-agent-kit"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><div class="table-cell" id="tsd-search"><div class="field"><label for="tsd-search-field" class="tsd-widget tsd-toolbar-icon search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-search"></use></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div><div class="field"><div id="tsd-toolbar-links"></div></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">solana-agent-kit</a></div><div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget tsd-toolbar-icon menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb"><li><a href="../modules.html">solana-agent-kit</a></li><li><a href="findAction.html">findAction</a></li></ul><h1>Function findAction</h1></div><section class="tsd-panel"><ul class="tsd-signatures"><li class="tsd-signature tsd-anchor-link"><a id="findaction" class="tsd-anchor"></a><span class="tsd-kind-call-signature">findAction</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">query</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Action</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><a href="#findaction" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></li><li class="tsd-description"><div class="tsd-comment tsd-typography"><p>Find an action by its name or one of its similes</p>
</div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">query</span>: <span class="tsd-signature-type">string</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Action</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span></h4><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/sendaifun/solana-agent-kit/blob/da09193d9d98e5d5a2ee1df9b1d5b8500b8c5a55/src/utils/actionExecutor.ts#L8">utils/actionExecutor.ts:8</a></li></ul></aside></li></ul></section></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">solana-agent-kit</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
</div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">query</span>: <span class="tsd-signature-type">string</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Action</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span></h4><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/UjjwalGupta49/solana-agent-kit/blob/f77cada52ac7e1627f9218cc72a2789f712a4532/src/utils/actionExecutor.ts#L8">utils/actionExecutor.ts:8</a></li></ul></aside></li></ul></section></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">solana-agent-kit</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>

View File

@@ -1,2 +1,2 @@
<!DOCTYPE html><html class="default" lang="en" data-base=".."><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>getActionExamples | solana-agent-kit</title><meta name="description" content="Documentation for solana-agent-kit"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><div class="table-cell" id="tsd-search"><div class="field"><label for="tsd-search-field" class="tsd-widget tsd-toolbar-icon search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-search"></use></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div><div class="field"><div id="tsd-toolbar-links"></div></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">solana-agent-kit</a></div><div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget tsd-toolbar-icon menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb"><li><a href="../modules.html">solana-agent-kit</a></li><li><a href="getActionExamples.html">getActionExamples</a></li></ul><h1>Function getActionExamples</h1></div><section class="tsd-panel"><ul class="tsd-signatures"><li class="tsd-signature tsd-anchor-link"><a id="getactionexamples" class="tsd-anchor"></a><span class="tsd-kind-call-signature">getActionExamples</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">action</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Action</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><a href="#getactionexamples" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></li><li class="tsd-description"><div class="tsd-comment tsd-typography"><p>Get examples for an action</p>
</div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">action</span>: <span class="tsd-signature-type">Action</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">string</span></h4><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/sendaifun/solana-agent-kit/blob/da09193d9d98e5d5a2ee1df9b1d5b8500b8c5a55/src/utils/actionExecutor.ts#L58">utils/actionExecutor.ts:58</a></li></ul></aside></li></ul></section></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">solana-agent-kit</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
</div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">action</span>: <span class="tsd-signature-type">Action</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">string</span></h4><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/UjjwalGupta49/solana-agent-kit/blob/f77cada52ac7e1627f9218cc72a2789f712a4532/src/utils/actionExecutor.ts#L58">utils/actionExecutor.ts:58</a></li></ul></aside></li></ul></section></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">solana-agent-kit</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>

View File

@@ -53,6 +53,7 @@
<li>Jito Bundles</li>
<li>Pyth Price feeds for fetching Asset Prices</li>
<li>Register/resolve Alldomains</li>
<li>Perpetuals Trading with Adrena Protocol</li>
</ul>
</li>
<li>
@@ -61,6 +62,7 @@
<li>Lending by Lulo (Best APR for USDC)</li>
<li>Send Arcade Games</li>
<li>JupSOL staking</li>
<li>Solayer SOL (sSOL)staking</li>
</ul>
</li>
<li>
@@ -128,10 +130,19 @@
<a id="stake-sol" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Stake SOL<a href="#stake-sol" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="typescript"><span class="hl-6">const</span><span class="hl-1"> </span><span class="hl-7">signature</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-4">agent</span><span class="hl-1">.</span><span class="hl-0">stake</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-8">1</span><span class="hl-1"> </span><span class="hl-5">// amount in SOL to stake</span><br/><span class="hl-1">);</span>
</code><button type="button">Copy</button></pre>
<a id="stake-sol-on-solayer" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Stake SOL on Solayer<a href="#stake-sol-on-solayer" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="typescript"><span class="hl-6">const</span><span class="hl-1"> </span><span class="hl-7">signature</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-4">agent</span><span class="hl-1">.</span><span class="hl-0">restake</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-8">1</span><span class="hl-1"> </span><span class="hl-5">// amount in SOL to stake</span><br/><span class="hl-1">);</span><br/>
</code><button type="button">Copy</button></pre>
<a id="send-an-spl-token-airdrop-via-zk-compression" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Send an SPL Token Airdrop via ZK Compression<a href="#send-an-spl-token-airdrop-via-zk-compression" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="typescript"><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-4">PublicKey</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">&quot;@solana/web3.js&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-1">(</span><span class="hl-6">async</span><span class="hl-1"> () </span><span class="hl-6">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">&quot;~Airdrop cost estimate:&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-0">getAirdropCostEstimate</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-8">1000</span><span class="hl-1">, </span><span class="hl-5">// recipients</span><br/><span class="hl-1"> </span><span class="hl-8">30_000</span><span class="hl-1"> </span><span class="hl-5">// priority fee in lamports</span><br/><span class="hl-1"> )</span><br/><span class="hl-1"> );</span><br/><br/><span class="hl-1"> </span><span class="hl-6">const</span><span class="hl-1"> </span><span class="hl-7">signature</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-4">agent</span><span class="hl-1">.</span><span class="hl-0">sendCompressedAirdrop</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-6">new</span><span class="hl-1"> </span><span class="hl-0">PublicKey</span><span class="hl-1">(</span><span class="hl-2">&quot;JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN&quot;</span><span class="hl-1">), </span><span class="hl-5">// mint</span><br/><span class="hl-1"> </span><span class="hl-8">42</span><span class="hl-1">, </span><span class="hl-5">// amount per recipient</span><br/><span class="hl-1"> [</span><br/><span class="hl-1"> </span><span class="hl-6">new</span><span class="hl-1"> </span><span class="hl-0">PublicKey</span><span class="hl-1">(</span><span class="hl-2">&quot;1nc1nerator11111111111111111111111111111111&quot;</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-5">// ... add more recipients</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> </span><span class="hl-8">30_000</span><span class="hl-1"> </span><span class="hl-5">// priority fee in lamports</span><br/><span class="hl-1"> );</span><br/><span class="hl-1">})();</span>
</code><button type="button">Copy</button></pre>
<a id="fetch-price-data-from-pyth" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Fetch Price Data from Pyth<a href="#fetch-price-data-from-pyth" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="typescript"><br/><span class="hl-6">const</span><span class="hl-1"> </span><span class="hl-7">price</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-4">agent</span><span class="hl-1">.</span><span class="hl-0">pythFetchPrice</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">&quot;0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43&quot;</span><br/><span class="hl-1">);</span><br/><br/><span class="hl-4">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">&quot;Price in BTC/USD:&quot;</span><span class="hl-1">, </span><span class="hl-4">price</span><span class="hl-1">);</span>
<a id="fetch-price-data-from-pyth" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Fetch Price Data from Pyth<a href="#fetch-price-data-from-pyth" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="typescript"><br/><span class="hl-6">const</span><span class="hl-1"> </span><span class="hl-7">priceFeedID</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-4">agent</span><span class="hl-1">.</span><span class="hl-0">getPythPriceFeedID</span><span class="hl-1">(</span><span class="hl-2">&quot;SOL&quot;</span><span class="hl-1">);</span><br/><br/><span class="hl-6">const</span><span class="hl-1"> </span><span class="hl-7">price</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-4">agent</span><span class="hl-1">.</span><span class="hl-0">getPythPrice</span><span class="hl-1">(</span><span class="hl-4">priceFeedID</span><span class="hl-1">);</span><br/><br/><span class="hl-4">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">&quot;Price of SOL/USD:&quot;</span><span class="hl-1">, </span><span class="hl-4">price</span><span class="hl-1">);</span>
</code><button type="button">Copy</button></pre>
<a id="open-perp-trade" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Open PERP Trade<a href="#open-perp-trade" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="typescript"><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-4">PublicKey</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">&quot;@solana/web3.js&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-6">const</span><span class="hl-1"> </span><span class="hl-7">signature</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-4">agent</span><span class="hl-1">.</span><span class="hl-0">openPerpTradeLong</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-4">price:</span><span class="hl-1"> </span><span class="hl-8">300</span><span class="hl-1">, </span><span class="hl-5">// $300 SOL Max price</span><br/><span class="hl-1"> </span><span class="hl-4">collateralAmount:</span><span class="hl-1"> </span><span class="hl-8">10</span><span class="hl-1">, </span><span class="hl-5">// 10 jitoSOL in</span><br/><span class="hl-1"> </span><span class="hl-4">collateralMint:</span><span class="hl-1"> </span><span class="hl-6">new</span><span class="hl-1"> </span><span class="hl-0">PublicKey</span><span class="hl-1">(</span><span class="hl-2">&quot;J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn&quot;</span><span class="hl-1">), </span><span class="hl-5">// jitoSOL</span><br/><span class="hl-1"> </span><span class="hl-4">leverage:</span><span class="hl-1"> </span><span class="hl-8">50000</span><span class="hl-1">, </span><span class="hl-5">// x5</span><br/><span class="hl-1"> </span><span class="hl-4">tradeMint:</span><span class="hl-1"> </span><span class="hl-6">new</span><span class="hl-1"> </span><span class="hl-0">PublicKey</span><span class="hl-1">(</span><span class="hl-2">&quot;J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn&quot;</span><span class="hl-1">), </span><span class="hl-5">// jitoSOL</span><br/><span class="hl-1"> </span><span class="hl-4">slippage:</span><span class="hl-1"> </span><span class="hl-8">0.3</span><span class="hl-1">, </span><span class="hl-5">// 0.3%</span><br/><span class="hl-1">});</span>
</code><button type="button">Copy</button></pre>
<a id="close-perp-trade" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Close PERP Trade<a href="#close-perp-trade" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="typescript"><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-4">PublicKey</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">&quot;@solana/web3.js&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-6">const</span><span class="hl-1"> </span><span class="hl-7">signature</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-4">agent</span><span class="hl-1">.</span><span class="hl-0">closePerpTradeLong</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-4">price:</span><span class="hl-1"> </span><span class="hl-8">200</span><span class="hl-1">, </span><span class="hl-5">// $200 SOL price</span><br/><span class="hl-1"> </span><span class="hl-4">tradeMint:</span><span class="hl-1"> </span><span class="hl-6">new</span><span class="hl-1"> </span><span class="hl-0">PublicKey</span><span class="hl-1">(</span><span class="hl-2">&quot;J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn&quot;</span><span class="hl-1">), </span><span class="hl-5">// jitoSOL</span><br/><span class="hl-1">});</span>
</code><button type="button">Copy</button></pre>
<a id="examples" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Examples<a href="#examples" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><a id="langgraph-multi-agent-system" class="tsd-anchor"></a><h3 class="tsd-anchor-link">LangGraph Multi-Agent System<a href="#langgraph-multi-agent-system" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>The repository includes an advanced example of building a multi-agent system using LangGraph and Solana Agent Kit. Located in <code>examples/agent-kit-langgraph</code>, this example demonstrates:</p>
@@ -158,7 +169,6 @@
<li>@metaplex-foundation/umi</li>
<li>@lightprotocol/compressed-token</li>
<li>@lightprotocol/stateless.js</li>
<li>@pythnetwork/price-service-client</li>
</ul>
<a id="contributing" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Contributing<a href="#contributing" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><p>Contributions are welcome! Please feel free to submit a Pull Request.
Refer to <a href="media/CONTRIBUTING.md">CONTRIBUTING.md</a> for detailed guidelines on how to contribute to this project.</p>
@@ -167,5 +177,7 @@ Refer to <a href="media/CONTRIBUTING.md">CONTRIBUTING.md</a> for detailed guidel
</a>
<a id="star-history" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Star History<a href="#star-history" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><p><a href="https://star-history.com/#sendaifun/solana-agent-kit&amp;Date"><img src="https://api.star-history.com/svg?repos=sendaifun/solana-agent-kit&amp;type=Date" alt="Star History Chart"></a></p>
<a id="license" class="tsd-anchor"></a><h2 class="tsd-anchor-link">License<a href="#license" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><p>Apache-2 License</p>
<a id="funding" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Funding<a href="#funding" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><p>If you wanna give back any tokens or donations to the OSS community -- The Public Solana Agent Kit Treasury Address:</p>
<p>Solana Network : EKHTbXpsm6YDgJzMkFxNU1LNXeWcUW7Ezf8mjUNQQ4Pa</p>
<a id="security" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Security<a href="#security" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><p>This toolkit handles private keys and transactions. Always ensure you're using it in a secure environment and never share your private keys.</p>
</div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="assets/icons.svg#icon-chevronDown"></use></svg>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#solana-agent-kit"><span>Solana <wbr/>Agent <wbr/>Kit</span></a><ul><li><a href="#🔧-core-blockchain-features"><span>🔧 <wbr/>Core <wbr/>Blockchain <wbr/>Features</span></a></li><li><a href="#🤖-ai-integration-features"><span>🤖 AI <wbr/>Integration <wbr/>Features</span></a></li><li><a href="#📦-installation"><span>📦 <wbr/>Installation</span></a></li><li><a href="#quick-start"><span>Quick <wbr/>Start</span></a></li><li><a href="#usage-examples"><span>Usage <wbr/>Examples</span></a></li><li><ul><li><a href="#deploy-a-new-token"><span>Deploy a <wbr/>New <wbr/>Token</span></a></li><li><a href="#create-nft-collection"><span>Create NFT <wbr/>Collection</span></a></li><li><a href="#swap-tokens"><span>Swap <wbr/>Tokens</span></a></li><li><a href="#lend-tokens"><span>Lend <wbr/>Tokens</span></a></li><li><a href="#stake-sol"><span>Stake SOL</span></a></li><li><a href="#send-an-spl-token-airdrop-via-zk-compression"><span>Send an SPL <wbr/>Token <wbr/>Airdrop via ZK <wbr/>Compression</span></a></li><li><a href="#fetch-price-data-from-pyth"><span>Fetch <wbr/>Price <wbr/>Data from <wbr/>Pyth</span></a></li></ul></li><li><a href="#examples"><span>Examples</span></a></li><li><ul><li><a href="#langgraph-multi-agent-system"><span>Lang<wbr/>Graph <wbr/>Multi-<wbr/>Agent <wbr/>System</span></a></li></ul></li><li><a href="#dependencies"><span>Dependencies</span></a></li><li><a href="#contributing"><span>Contributing</span></a></li><li><a href="#contributors"><span>Contributors</span></a></li><li><a href="#star-history"><span>Star <wbr/>History</span></a></li><li><a href="#license"><span>License</span></a></li><li><a href="#security"><span>Security</span></a></li></ul></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="modules.html">solana-agent-kit</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
</div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="assets/icons.svg#icon-chevronDown"></use></svg>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#solana-agent-kit"><span>Solana <wbr/>Agent <wbr/>Kit</span></a><ul><li><a href="#🔧-core-blockchain-features"><span>🔧 <wbr/>Core <wbr/>Blockchain <wbr/>Features</span></a></li><li><a href="#🤖-ai-integration-features"><span>🤖 AI <wbr/>Integration <wbr/>Features</span></a></li><li><a href="#📦-installation"><span>📦 <wbr/>Installation</span></a></li><li><a href="#quick-start"><span>Quick <wbr/>Start</span></a></li><li><a href="#usage-examples"><span>Usage <wbr/>Examples</span></a></li><li><ul><li><a href="#deploy-a-new-token"><span>Deploy a <wbr/>New <wbr/>Token</span></a></li><li><a href="#create-nft-collection"><span>Create NFT <wbr/>Collection</span></a></li><li><a href="#swap-tokens"><span>Swap <wbr/>Tokens</span></a></li><li><a href="#lend-tokens"><span>Lend <wbr/>Tokens</span></a></li><li><a href="#stake-sol"><span>Stake SOL</span></a></li><li><a href="#stake-sol-on-solayer"><span>Stake SOL on <wbr/>Solayer</span></a></li><li><a href="#send-an-spl-token-airdrop-via-zk-compression"><span>Send an SPL <wbr/>Token <wbr/>Airdrop via ZK <wbr/>Compression</span></a></li><li><a href="#fetch-price-data-from-pyth"><span>Fetch <wbr/>Price <wbr/>Data from <wbr/>Pyth</span></a></li><li><a href="#open-perp-trade"><span>Open PERP <wbr/>Trade</span></a></li><li><a href="#close-perp-trade"><span>Close PERP <wbr/>Trade</span></a></li></ul></li><li><a href="#examples"><span>Examples</span></a></li><li><ul><li><a href="#langgraph-multi-agent-system"><span>Lang<wbr/>Graph <wbr/>Multi-<wbr/>Agent <wbr/>System</span></a></li></ul></li><li><a href="#dependencies"><span>Dependencies</span></a></li><li><a href="#contributing"><span>Contributing</span></a></li><li><a href="#contributors"><span>Contributors</span></a></li><li><a href="#star-history"><span>Star <wbr/>History</span></a></li><li><a href="#license"><span>License</span></a></li><li><a href="#funding"><span>Funding</span></a></li><li><a href="#security"><span>Security</span></a></li></ul></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="modules.html">solana-agent-kit</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>

View File

@@ -1,16 +1,16 @@
<!DOCTYPE html><html class="default" lang="en" data-base=".."><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>Action | solana-agent-kit</title><meta name="description" content="Documentation for solana-agent-kit"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><div class="table-cell" id="tsd-search"><div class="field"><label for="tsd-search-field" class="tsd-widget tsd-toolbar-icon search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-search"></use></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div><div class="field"><div id="tsd-toolbar-links"></div></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">solana-agent-kit</a></div><div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget tsd-toolbar-icon menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb"><li><a href="../modules.html">solana-agent-kit</a></li><li><a href="Action.html">Action</a></li></ul><h1>Interface Action</h1></div><section class="tsd-panel tsd-comment"><div class="tsd-comment tsd-typography"><p>Main Action interface inspired by ELIZA
This interface makes it easier to implement actions across different frameworks</p>
</div><div class="tsd-comment tsd-typography"></div></section><div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Action</span> <span class="tsd-signature-symbol">{</span><br/>    <a class="tsd-kind-property" href="Action.html#description">description</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br/>    <a class="tsd-kind-property" href="Action.html#examples">examples</a><span class="tsd-signature-symbol">:</span> <a href="ActionExample.html" class="tsd-signature-type tsd-kind-interface">ActionExample</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">;</span><br/>    <a class="tsd-kind-property" href="Action.html#handler">handler</a><span class="tsd-signature-symbol">:</span> <a href="../types/Handler.html" class="tsd-signature-type tsd-kind-type-alias">Handler</a><span class="tsd-signature-symbol">;</span><br/>    <a class="tsd-kind-property" href="Action.html#name">name</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br/>    <a class="tsd-kind-property" href="Action.html#schema">schema</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">ZodType</span><span class="tsd-signature-symbol">;</span><br/>    <a class="tsd-kind-property" href="Action.html#similes">similes</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">;</span><br/><span class="tsd-signature-symbol">}</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/sendaifun/solana-agent-kit/blob/da09193d9d98e5d5a2ee1df9b1d5b8500b8c5a55/src/types/index.ts#L124">types/index.ts:124</a></li></ul></aside><section class="tsd-panel-group tsd-index-group"><section class="tsd-panel tsd-index-panel"><details class="tsd-index-content tsd-accordion" open><summary class="tsd-accordion-summary tsd-index-summary"><h5 class="tsd-index-heading uppercase" role="button" aria-expanded="false" tabIndex="0"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-chevronSmall"></use></svg> Index</h5></summary><div class="tsd-accordion-details"><section class="tsd-index-section"><h3 class="tsd-index-heading">Properties</h3><div class="tsd-index-list"><a href="Action.html#description" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>description</span></a>
</div><div class="tsd-comment tsd-typography"></div></section><div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Action</span> <span class="tsd-signature-symbol">{</span><br/>    <a class="tsd-kind-property" href="Action.html#description">description</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br/>    <a class="tsd-kind-property" href="Action.html#examples">examples</a><span class="tsd-signature-symbol">:</span> <a href="ActionExample.html" class="tsd-signature-type tsd-kind-interface">ActionExample</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">;</span><br/>    <a class="tsd-kind-property" href="Action.html#handler">handler</a><span class="tsd-signature-symbol">:</span> <a href="../types/Handler.html" class="tsd-signature-type tsd-kind-type-alias">Handler</a><span class="tsd-signature-symbol">;</span><br/>    <a class="tsd-kind-property" href="Action.html#name">name</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br/>    <a class="tsd-kind-property" href="Action.html#schema">schema</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">ZodType</span><span class="tsd-signature-symbol">;</span><br/>    <a class="tsd-kind-property" href="Action.html#similes">similes</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">;</span><br/><span class="tsd-signature-symbol">}</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/UjjwalGupta49/solana-agent-kit/blob/f77cada52ac7e1627f9218cc72a2789f712a4532/src/types/index.ts#L126">types/index.ts:126</a></li></ul></aside><section class="tsd-panel-group tsd-index-group"><section class="tsd-panel tsd-index-panel"><details class="tsd-index-content tsd-accordion" open><summary class="tsd-accordion-summary tsd-index-summary"><h5 class="tsd-index-heading uppercase" role="button" aria-expanded="false" tabIndex="0"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-chevronSmall"></use></svg> Index</h5></summary><div class="tsd-accordion-details"><section class="tsd-index-section"><h3 class="tsd-index-heading">Properties</h3><div class="tsd-index-list"><a href="Action.html#description" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>description</span></a>
<a href="Action.html#examples" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>examples</span></a>
<a href="Action.html#handler" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>handler</span></a>
<a href="Action.html#name" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>name</span></a>
<a href="Action.html#schema" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>schema</span></a>
<a href="Action.html#similes" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>similes</span></a>
</div></section></div></details></section></section><details class="tsd-panel-group tsd-member-group tsd-accordion" open><summary class="tsd-accordion-summary" data-key="section-Properties"><h2><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg> Properties</h2></summary><section><section class="tsd-panel tsd-member"><a id="description" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>description</span><a href="#description" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">description</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div><div class="tsd-comment tsd-typography"><p>Detailed description of what the action does</p>
</div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/sendaifun/solana-agent-kit/blob/da09193d9d98e5d5a2ee1df9b1d5b8500b8c5a55/src/types/index.ts#L138">types/index.ts:138</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="examples" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>examples</span><a href="#examples" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">examples</span><span class="tsd-signature-symbol">:</span> <a href="ActionExample.html" class="tsd-signature-type tsd-kind-interface">ActionExample</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">[]</span></div><div class="tsd-comment tsd-typography"><p>Array of example inputs and outputs for the action
</div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/UjjwalGupta49/solana-agent-kit/blob/f77cada52ac7e1627f9218cc72a2789f712a4532/src/types/index.ts#L140">types/index.ts:140</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="examples" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>examples</span><a href="#examples" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">examples</span><span class="tsd-signature-symbol">:</span> <a href="ActionExample.html" class="tsd-signature-type tsd-kind-interface">ActionExample</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">[]</span></div><div class="tsd-comment tsd-typography"><p>Array of example inputs and outputs for the action
Each inner array represents a group of related examples</p>
</div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/sendaifun/solana-agent-kit/blob/da09193d9d98e5d5a2ee1df9b1d5b8500b8c5a55/src/types/index.ts#L144">types/index.ts:144</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="handler" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>handler</span><a href="#handler" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">handler</span><span class="tsd-signature-symbol">:</span> <a href="../types/Handler.html" class="tsd-signature-type tsd-kind-type-alias">Handler</a></div><div class="tsd-comment tsd-typography"><p>Function that executes the action</p>
</div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/sendaifun/solana-agent-kit/blob/da09193d9d98e5d5a2ee1df9b1d5b8500b8c5a55/src/types/index.ts#L154">types/index.ts:154</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="name" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>name</span><a href="#name" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">name</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div><div class="tsd-comment tsd-typography"><p>Unique name of the action</p>
</div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/sendaifun/solana-agent-kit/blob/da09193d9d98e5d5a2ee1df9b1d5b8500b8c5a55/src/types/index.ts#L128">types/index.ts:128</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="schema" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>schema</span><a href="#schema" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">schema</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">ZodType</span></div><div class="tsd-comment tsd-typography"><p>Zod schema for input validation</p>
</div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/sendaifun/solana-agent-kit/blob/da09193d9d98e5d5a2ee1df9b1d5b8500b8c5a55/src/types/index.ts#L149">types/index.ts:149</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="similes" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>similes</span><a href="#similes" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">similes</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">[]</span></div><div class="tsd-comment tsd-typography"><p>Alternative names/phrases that can trigger this action</p>
</div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/sendaifun/solana-agent-kit/blob/da09193d9d98e5d5a2ee1df9b1d5b8500b8c5a55/src/types/index.ts#L133">types/index.ts:133</a></li></ul></aside></section></section></details></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>On This Page</h3></summary><div class="tsd-accordion-details"><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Properties"><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Properties</summary><div><a href="#description" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>description</span></a><a href="#examples" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>examples</span></a><a href="#handler" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>handler</span></a><a href="#name" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>name</span></a><a href="#schema" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>schema</span></a><a href="#similes" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>similes</span></a></div></details></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">solana-agent-kit</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
</div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/UjjwalGupta49/solana-agent-kit/blob/f77cada52ac7e1627f9218cc72a2789f712a4532/src/types/index.ts#L146">types/index.ts:146</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="handler" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>handler</span><a href="#handler" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">handler</span><span class="tsd-signature-symbol">:</span> <a href="../types/Handler.html" class="tsd-signature-type tsd-kind-type-alias">Handler</a></div><div class="tsd-comment tsd-typography"><p>Function that executes the action</p>
</div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/UjjwalGupta49/solana-agent-kit/blob/f77cada52ac7e1627f9218cc72a2789f712a4532/src/types/index.ts#L156">types/index.ts:156</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="name" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>name</span><a href="#name" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">name</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div><div class="tsd-comment tsd-typography"><p>Unique name of the action</p>
</div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/UjjwalGupta49/solana-agent-kit/blob/f77cada52ac7e1627f9218cc72a2789f712a4532/src/types/index.ts#L130">types/index.ts:130</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="schema" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>schema</span><a href="#schema" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">schema</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">ZodType</span></div><div class="tsd-comment tsd-typography"><p>Zod schema for input validation</p>
</div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/UjjwalGupta49/solana-agent-kit/blob/f77cada52ac7e1627f9218cc72a2789f712a4532/src/types/index.ts#L151">types/index.ts:151</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="similes" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>similes</span><a href="#similes" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">similes</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">[]</span></div><div class="tsd-comment tsd-typography"><p>Alternative names/phrases that can trigger this action</p>
</div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/UjjwalGupta49/solana-agent-kit/blob/f77cada52ac7e1627f9218cc72a2789f712a4532/src/types/index.ts#L135">types/index.ts:135</a></li></ul></aside></section></section></details></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>On This Page</h3></summary><div class="tsd-accordion-details"><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Properties"><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Properties</summary><div><a href="#description" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>description</span></a><a href="#examples" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>examples</span></a><a href="#handler" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>handler</span></a><a href="#name" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>name</span></a><a href="#schema" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>schema</span></a><a href="#similes" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>similes</span></a></div></details></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">solana-agent-kit</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@ import { SolanaAgentKit, createSolanaTools } from "solana-agent-kit";
export const agentKit = new SolanaAgentKit(
process.env.SOLANA_PRIVATE_KEY!,
process.env.RPC_URL!,
process.env.OPENAI_API_KEY!,
{ OPENAI_API_KEY: process.env.OPENAI_API_KEY! },
);
export const solanaTools = createSolanaTools(agentKit);

View File

@@ -0,0 +1,3 @@
OPENAI_API_KEY=
RPC_URL=
SOLANA_PRIVATE_KEY=

View File

@@ -0,0 +1,50 @@
# AI Guided Market Making Agent
This agent showcases an ai guided market maker on Manifest, Solana's CLOB DEX. The agent guides the user to setup basic two-sided quotes on Manifest markets.
[Reference](https://github.com/CKS-Systems/manifest)
## Key Features
- **Automated Quoting**: The agent automatically refreshes quotes on an interval.
- **Reducing Complexity**: Designed to abstract away parameters for setting up market making.
- **Random Model**: The market making introduces randomness to prevent front running or other negative botting behavoirs.
## Example
=== Market Maker Configuration ===
Enter the market ID: 2Uj8277fkaVBtTU6Wp2GPRbQC86SkSdgQ2mp1Q5N2LHc
Enter the base token symbol (e.g., SEND): SEND
Enter the quote token symbol (e.g., USDC): USDC
=== Quote Parameters (applies to both buy and sell sides) ===
Enter number of quotes to place on each side: 4
Enter minimum quote depth (% distance from mid price): 0.1
Enter maximum quote depth (% distance from mid price): 2
=== Token Allowances ===
Enter total SEND allowance: 2
Enter total USDC allowance: 3
Enter update interval in seconds: 20
=== Configuration Summary ===
{
"marketId": "2Uj8277fkaVBtTU6Wp2GPRbQC86SkSdgQ2mp1Q5N2LHc",
"baseToken": "SEND",
"quoteToken": "USDC",
"quoteParams": {
"number": 4,
"minDepth": 0.1,
"maxDepth": 2
},
"allowance": {
"base": 2,
"quote": 3
},
"intervalSeconds": 20
}
Is this configuration correct? (yes/no): yes
Starting market maker mode for SEND/USDC...

View File

@@ -0,0 +1,389 @@
import { HumanMessage } from "@langchain/core/messages";
import { MemorySaver } from "@langchain/langgraph";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { ChatOpenAI } from "@langchain/openai";
import * as dotenv from "dotenv";
import * as fs from "fs";
import * as readline from "readline";
import { createSolanaTools, SolanaAgentKit } from "../../src";
dotenv.config();
function validateEnvironment(): void {
const missingVars: string[] = [];
const requiredVars = ["OPENAI_API_KEY", "RPC_URL", "SOLANA_PRIVATE_KEY"];
requiredVars.forEach((varName) => {
if (!process.env[varName]) {
missingVars.push(varName);
}
});
if (missingVars.length > 0) {
console.error("Error: Required environment variables are not set");
missingVars.forEach((varName) => {
console.error(`${varName}=your_${varName.toLowerCase()}_here`);
});
process.exit(1);
}
}
validateEnvironment();
const WALLET_DATA_FILE = "wallet_data.txt";
async function initializeAgent() {
try {
const llm = new ChatOpenAI({
modelName: "gpt-4o-mini",
temperature: 0.3,
});
let walletDataStr: string | null = null;
if (fs.existsSync(WALLET_DATA_FILE)) {
try {
walletDataStr = fs.readFileSync(WALLET_DATA_FILE, "utf8");
} catch (error) {
console.error("Error reading wallet data:", error);
}
}
const solanaAgent = new SolanaAgentKit(
process.env.SOLANA_PRIVATE_KEY!,
process.env.RPC_URL!,
{
OPENAI_API_KEY: process.env.OPENAI_API_KEY!,
},
);
const tools = createSolanaTools(solanaAgent);
const memory = new MemorySaver();
const config = { configurable: { thread_id: "Solana Agent Kit!" } };
const agent = createReactAgent({
llm,
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.
`,
});
if (walletDataStr) {
fs.writeFileSync(WALLET_DATA_FILE, walletDataStr);
}
return { agent, config };
} catch (error) {
console.error("Failed to initialize agent:", error);
throw error;
}
}
async function runAutonomousMode(agent: any, config: any, interval = 10) {
console.log("Starting autonomous mode...");
while (true) {
try {
const thought =
"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,
);
for await (const chunk of stream) {
if ("agent" in chunk) {
console.log(chunk.agent.messages[0].content);
} else if ("tools" in chunk) {
console.log(chunk.tools.messages[0].content);
}
console.log("-------------------");
}
await new Promise((resolve) => setTimeout(resolve, interval * 1000));
} catch (error) {
if (error instanceof Error) {
console.error("Error:", error.message);
}
process.exit(1);
}
}
}
async function runChatMode(agent: any, config: any) {
console.log("Starting chat mode... Type 'exit' to end.");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const question = (prompt: string): Promise<string> =>
new Promise((resolve) => rl.question(prompt, resolve));
try {
while (true) {
const userInput = await question("\nPrompt: ");
if (userInput.toLowerCase() === "exit") {
break;
}
const stream = await agent.stream(
{ messages: [new HumanMessage(userInput)] },
config,
);
for await (const chunk of stream) {
if ("agent" in chunk) {
console.log(chunk.agent.messages[0].content);
} else if ("tools" in chunk) {
console.log(chunk.tools.messages[0].content);
}
console.log("-------------------");
}
}
} catch (error) {
if (error instanceof Error) {
console.error("Error:", error.message);
}
process.exit(1);
} finally {
rl.close();
}
}
interface MarketMakerConfig {
marketId: string;
baseToken: string;
quoteToken: string;
quoteParams: {
number: number; // Number of quotes on each side
minDepth: number; // Minimum distance from mid (%)
maxDepth: number; // Maximum distance from mid (%)
};
allowance: {
base: number;
quote: number;
};
intervalSeconds: number;
}
function createReadlineInterface() {
return readline.createInterface({
input: process.stdin,
output: process.stdout,
});
}
async function askQuestion(
rl: readline.Interface,
question: string,
): Promise<string> {
return new Promise((resolve) => {
rl.question(question, (answer) => {
resolve(answer);
});
});
}
async function configureMarketMaker(): Promise<MarketMakerConfig> {
const rl = createReadlineInterface();
try {
console.log("\n=== Market Maker Configuration ===\n");
// Basic market information
const marketId = await askQuestion(rl, "Enter the market ID: ");
const baseToken = await askQuestion(
rl,
"Enter the base token symbol (e.g., SEND): ",
);
const quoteToken = await askQuestion(
rl,
"Enter the quote token symbol (e.g., USDC): ",
);
// Quote parameters
console.log(
"\n=== Quote Parameters (applies to both buy and sell sides) ===",
);
const quoteNumber = parseInt(
await askQuestion(rl, "Enter number of quotes to place on each side: "),
);
const minDepth = parseFloat(
await askQuestion(
rl,
"Enter minimum quote depth (% distance from mid price): ",
),
);
const maxDepth = parseFloat(
await askQuestion(
rl,
"Enter maximum quote depth (% distance from mid price): ",
),
);
// Token allowances
console.log("\n=== Token Allowances ===");
const baseAllowance = parseFloat(
await askQuestion(rl, `Enter total ${baseToken} allowance: `),
);
const quoteAllowance = parseFloat(
await askQuestion(rl, `Enter total ${quoteToken} allowance: `),
);
// Update interval
const interval = parseInt(
await askQuestion(rl, "\nEnter update interval in seconds: "),
);
const config: MarketMakerConfig = {
marketId,
baseToken,
quoteToken,
quoteParams: {
number: quoteNumber,
minDepth: minDepth,
maxDepth: maxDepth,
},
allowance: {
base: baseAllowance,
quote: quoteAllowance,
},
intervalSeconds: interval,
};
// Display summary
console.log("\n=== Configuration Summary ===");
console.log(JSON.stringify(config, null, 2));
const confirm = await askQuestion(
rl,
"\nIs this configuration correct? (yes/no): ",
);
if (confirm.toLowerCase() !== "yes") {
throw new Error("Configuration cancelled by user");
}
return config;
} finally {
rl.close();
}
}
async function runMarketMakerMode(agent: any, config: any) {
try {
const marketMakerConfig = await configureMarketMaker();
console.log(
`\nStarting market maker mode for ${marketMakerConfig.baseToken}/${marketMakerConfig.quoteToken}...`,
);
while (true) {
try {
const thought = `You are an on-chain Solana market maker for the ${marketMakerConfig.baseToken}/${marketMakerConfig.quoteToken} Manifest market, ${marketMakerConfig.marketId}.
Find the ${marketMakerConfig.baseToken}/${marketMakerConfig.quoteToken} live price by checking Jupiter.
Use solana_batch_order to provide ${marketMakerConfig.quoteParams.number} buys at different prices between -${marketMakerConfig.quoteParams.minDepth}% to -${marketMakerConfig.quoteParams.maxDepth}% and ${marketMakerConfig.quoteParams.number} sells at different prices between +${marketMakerConfig.quoteParams.minDepth}% to +${marketMakerConfig.quoteParams.maxDepth}% with increasing quantities further from the live price.
You have an allowance of ${marketMakerConfig.allowance.base} ${marketMakerConfig.baseToken} and ${marketMakerConfig.allowance.quote} ${marketMakerConfig.quoteToken}.
Important! Only send 1 transaction, buy and sells can be combined into a single solana_batch_order.`;
const stream = await agent.stream(
{ messages: [new HumanMessage(thought)] },
config,
);
for await (const chunk of stream) {
if ("agent" in chunk) {
console.log(chunk.agent.messages[0].content);
} else if ("tools" in chunk) {
console.log(chunk.tools.messages[0].content);
}
console.log("-------------------");
}
await new Promise((resolve) =>
setTimeout(resolve, marketMakerConfig.intervalSeconds * 1000),
);
} catch (error) {
if (error instanceof Error) {
console.error("Error:", error);
}
process.exit(1);
}
}
} catch (error) {
console.error("Configuration error:", error);
process.exit(1);
}
}
async function chooseMode(): Promise<"chat" | "auto" | "mm"> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const question = (prompt: string): Promise<string> =>
new Promise((resolve) => rl.question(prompt, resolve));
while (true) {
console.log("\nAvailable modes:");
console.log("1. chat - Interactive chat mode");
console.log("2. auto - Autonomous action mode");
console.log("3. mm - AI guided market making");
const choice = (await question("\nChoose a mode (enter number or name): "))
.toLowerCase()
.trim();
rl.close();
if (choice === "1" || choice === "chat") {
return "chat";
} else if (choice === "2" || choice === "auto") {
return "auto";
} else if (choice === "3" || choice === "mm") {
return "mm";
}
console.log("Invalid choice. Please try again.");
}
}
async function main() {
try {
console.log("Starting Agent...");
const { agent, config } = await initializeAgent();
const mode = await chooseMode();
if (mode === "chat") {
await runChatMode(agent, config);
} else if (mode === "auto") {
await runAutonomousMode(agent, config);
} else {
await runMarketMakerMode(agent, config);
}
} catch (error) {
if (error instanceof Error) {
console.error("Error:", error.message);
}
process.exit(1);
}
}
if (require.main === module) {
main().catch((error) => {
console.error("Fatal error:", error);
process.exit(1);
});
}

View File

@@ -0,0 +1,16 @@
{
"name": "market-making-agent",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"main": "ts-node index.ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@langchain/langgraph-checkpoint-postgres": "^0.0.2",
"solana-agent-kit": "^1.3.6"
}
}

6000
examples/market-making-agent/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "solana-agent-kit",
"version": "1.3.4",
"version": "1.3.7",
"description": "connect any ai agents to solana protocols",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -12,7 +12,8 @@
"generate": "ts-node src/utils/keypair.ts",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\""
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"prepare": "husky"
},
"engines": {
"node": ">=22.0.0",
@@ -22,9 +23,10 @@
"author": "sendaifun",
"license": "Apache-2.0",
"dependencies": {
"@3land/listings-sdk": "^0.0.4",
"@ai-sdk/openai": "^1.0.11",
"@bonfida/spl-name-service": "^3.0.7",
"@cks-systems/manifest-sdk": "^0.1.73",
"@cks-systems/manifest-sdk": "0.1.59",
"@coral-xyz/anchor": "0.29",
"@langchain/core": "^0.3.26",
"@langchain/groq": "^0.1.2",
@@ -41,23 +43,25 @@
"@onsol/tldparser": "^0.6.7",
"@orca-so/common-sdk": "0.6.4",
"@orca-so/whirlpools-sdk": "^0.13.12",
"@pythnetwork/price-service-client": "^1.9.0",
"@pythnetwork/hermes-client": "^1.3.0",
"@raydium-io/raydium-sdk-v2": "0.1.95-alpha",
"@solana/spl-token": "^0.4.9",
"ai": "^4.0.22",
"@tensor-oss/tensorswap-sdk": "^4.5.0",
"@solana/web3.js": "^1.98.0",
"@tensor-oss/tensorswap-sdk": "^4.5.0",
"@sqds/multisig": "^2.1.3",
"@tiplink/api": "^0.3.1",
"ai": "^4.0.22",
"bn.js": "^5.2.1",
"bs58": "^6.0.0",
"chai": "^5.1.2",
"decimal.js": "^10.4.3",
"dotenv": "^16.4.7",
"flash-sdk": "^2.24.3",
"form-data": "^4.0.1",
"zod": "^3.24.1",
"langchain": "^0.3.8",
"openai": "^4.77.0",
"typedoc": "^0.27.6"
"typedoc": "^0.27.6",
"zod": "^3.24.1"
},
"devDependencies": {
"@types/bn.js": "^5.1.6",
@@ -68,6 +72,8 @@
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"husky": "^9.1.7",
"lint-staged": "^15.3.0",
"prettier": "^3.4.2",
"ts-node": "^10.9.2",
"typescript": "^5.7.2"

6143
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,71 @@
import { Action } from "../types/action";
import { SolanaAgentKit } from "../agent";
import { z } from "zod";
import { closeEmptyTokenAccounts } from "../tools";
const closeEmptyTokenAccountsAction: Action = {
name: "CLOSE_EMPTY_TOKEN_ACCOUNTS",
similes: [
"close token accounts",
"remove empty accounts",
"clean up token accounts",
"close SPL token accounts",
"clean wallet",
],
description: `Close empty SPL Token accounts associated with your wallet to reclaim rent.
This action will close both regular SPL Token accounts and Token-2022 accounts that have zero balance. `,
examples: [
[
{
input: {},
output: {
status: "success",
signature:
"3KmPyiZvJQk8CfBVVaz8nf3c2crb6iqjQVDqNxknnusyb1FTFpXqD8zVSCBAd1X3rUcD8WiG1bdSjFbeHsmcYGXY",
accountsClosed: 10,
},
explanation: "Closed 10 empty token accounts successfully.",
},
],
[
{
input: {},
output: {
status: "success",
signature: "",
accountsClosed: 0,
},
explanation: "No empty token accounts were found to close.",
},
],
],
schema: z.object({}),
handler: async (agent: SolanaAgentKit) => {
try {
const result = await closeEmptyTokenAccounts(agent);
if (result.size === 0) {
return {
status: "success",
signature: "",
accountsClosed: 0,
message: "No empty token accounts found to close",
};
}
return {
status: "success",
signature: result.signature,
accountsClosed: result.size,
message: `Successfully closed ${result.size} empty token accounts`,
};
} catch (error: any) {
return {
status: "error",
message: `Failed to close empty token accounts: ${error.message}`,
};
}
},
};
export default closeEmptyTokenAccountsAction;

View File

@@ -0,0 +1,68 @@
import { Action } from "../types/action";
import { SolanaAgentKit } from "../agent";
import { z } from "zod";
import { flashCloseTrade } from "../tools";
const flashCloseTradeAction: Action = {
name: "FLASH_CLOSE_TRADE",
similes: [
"close trade",
"close leveraged trade",
"exit position",
"close position",
"exit trade",
"close long",
"close short",
"take profit",
"stop loss",
],
description:
"Close an existing leveraged trading position on Flash.Trade protocol",
examples: [
[
{
input: {
token: "SOL",
side: "long",
},
output: {
status: "success",
signature: "4xKpN2...",
message: "Successfully closed long position on SOL",
},
explanation: "Close an existing long position on SOL",
},
],
],
schema: z.object({
token: z
.string()
.describe("Token symbol of the position to close (e.g. SOL, ETH)"),
side: z
.enum(["long", "short"])
.describe("Position side to close - long or short"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
try {
const params = {
token: input.token as string,
side: input.side as "long" | "short",
};
const response = await flashCloseTrade(agent, params);
return {
status: "success",
signature: response,
message: `Successfully closed ${params.side} position on ${params.token}`,
};
} catch (error: any) {
return {
status: "error",
message: `Flash trade close failed: ${error.message}`,
};
}
},
};
export default flashCloseTradeAction;

View File

@@ -0,0 +1,78 @@
import { Action } from "../types/action";
import { SolanaAgentKit } from "../agent";
import { z } from "zod";
import { flashOpenTrade } from "../tools";
const flashOpenTradeAction: Action = {
name: "FLASH_OPEN_TRADE",
similes: [
"open trade",
"open leveraged trade",
"start trading position",
"open position",
"long position",
"short position",
"leverage trade",
"margin trade",
],
description: "Open a leveraged trading position on Flash.Trade protocol",
examples: [
[
{
input: {
token: "SOL",
side: "long",
collateralUsd: 100,
leverage: 5,
},
output: {
status: "success",
signature: "4xKpN2...",
message:
"Successfully opened 5x long position on SOL with $100 collateral",
},
explanation:
"Open a 5x leveraged long position on SOL using $100 as collateral",
},
],
],
schema: z.object({
token: z.string().describe("Token symbol to trade (e.g. SOL, ETH)"),
side: z
.enum(["long", "short"])
.describe("Trading direction - long or short"),
collateralUsd: z
.number()
.positive()
.describe("Amount of collateral in USD"),
leverage: z
.number()
.positive()
.describe("Leverage multiplier for the trade"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
try {
const params = {
token: input.token as string,
side: input.side as "long" | "short",
collateralUsd: input.collateralUsd as number,
leverage: input.leverage as number,
};
const response = await flashOpenTrade(agent, params);
return {
status: "success",
signature: response,
message: `Successfully opened ${params.leverage}x ${params.side} position on ${params.token} with $${params.collateralUsd} collateral`,
};
} catch (error: any) {
return {
status: "error",
message: `Flash trade failed: ${error.message}`,
};
}
},
};
export default flashOpenTradeAction;

View File

@@ -28,6 +28,8 @@ import raydiumCreateAmmV4Action from "./raydiumCreateAmmV4";
import createOrcaSingleSidedWhirlpoolAction from "./createOrcaSingleSidedWhirlpool";
import launchPumpfunTokenAction from "./launchPumpfunToken";
import getWalletAddressAction from "./getWalletAddress";
import flashOpenTradeAction from "./flashOpenTrade";
import flashCloseTradeAction from "./flashCloseTrade";
export const ACTIONS = {
WALLET_ADDRESS_ACTION: getWalletAddressAction,
@@ -43,7 +45,7 @@ export const ACTIONS = {
GET_TPS_ACTION: getTPSAction,
FETCH_PRICE_ACTION: fetchPriceAction,
STAKE_WITH_JUP_ACTION: stakeWithJupAction,
STAKE_WITH_SOLAYER_ACTION : stakeWithSolayerAction,
STAKE_WITH_SOLAYER_ACTION: stakeWithSolayerAction,
REGISTER_DOMAIN_ACTION: registerDomainAction,
LEND_ASSET_ACTION: lendAssetAction,
CREATE_GIBWORK_TASK_ACTION: createGibworkTaskAction,
@@ -61,6 +63,8 @@ export const ACTIONS = {
CREATE_ORCA_SINGLE_SIDED_WHIRLPOOL_ACTION:
createOrcaSingleSidedWhirlpoolAction,
LAUNCH_PUMPFUN_TOKEN_ACTION: launchPumpfunTokenAction,
FLASH_OPEN_TRADE_ACTION: flashOpenTradeAction,
FLASH_CLOSE_TRADE_ACTION: flashCloseTradeAction,
};
export type { Action, ActionExample, Handler } from "../types/action";

View File

@@ -1,7 +1,7 @@
import { Action } from "../types/action";
import { SolanaAgentKit } from "../agent";
import { z } from "zod";
import { pythFetchPrice } from "../tools";
import { fetchPythPrice, fetchPythPriceFeedID } from "../tools";
const pythFetchPriceAction: Action = {
name: "PYTH_FETCH_PRICE",
@@ -18,7 +18,7 @@ const pythFetchPriceAction: Action = {
[
{
input: {
priceFeedId: "Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD", // SOL/USD price feed
tokenSymbol: "SOL", // SOL/USD price feed
},
output: {
status: "success",
@@ -30,15 +30,19 @@ const pythFetchPriceAction: Action = {
],
],
schema: z.object({
priceFeedId: z
tokenSymbol: z
.string()
.min(1)
.describe("The Pyth price feed ID to fetch the price from"),
.describe("The token symbol to fetch the price for"),
}),
handler: async (_agent: SolanaAgentKit, input: Record<string, any>) => {
try {
const priceFeedId = input.tokenId as string;
const priceStr = await pythFetchPrice(priceFeedId);
const priceFeedId = await fetchPythPriceFeedID(
input.tokenSymbol as string,
);
const priceStr = await fetchPythPrice(priceFeedId);
return {
status: "success",
price: priceStr,

View File

@@ -1,4 +1,5 @@
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import { BN } from "@coral-xyz/anchor";
import bs58 from "bs58";
import Decimal from "decimal.js";
import { DEFAULT_OPTIONS } from "../constants";
@@ -42,7 +43,6 @@ import {
orcaOpenSingleSidedPosition,
FEE_TIERS,
fetchPrice,
pythFetchPrice,
getAllDomainsTLDs,
getAllRegisteredAllDomains,
getOwnedDomainsForTLD,
@@ -56,11 +56,14 @@ import {
create_TipLink,
listNFTForSale,
cancelListing,
closeEmptyTokenAccounts,
fetchTokenReportSummary,
fetchTokenDetailedReport,
OrderParams,
fetchPythPrice,
fetchPythPriceFeedID,
flashOpenTrade,
flashCloseTrade,
} from "../tools";
import {
CollectionDeployment,
CollectionOptions,
@@ -69,8 +72,26 @@ import {
MintCollectionNFTResponse,
PumpfunLaunchResponse,
PumpFunTokenOptions,
OrderParams,
FlashTradeParams,
FlashCloseTradeParams,
} from "../types";
import { BN } from "@coral-xyz/anchor";
import {
createCollection,
createSingle,
} from "../tools/create_3land_collectible";
import {
CreateCollectionOptions,
CreateSingleOptions,
StoreInitOptions,
} from "@3land/listings-sdk/dist/types/implementation/implementationTypes";
import { create_squads_multisig } from "../tools/squads_multisig/create_multisig";
import { deposit_to_multisig } from "../tools/squads_multisig/deposit_to_multisig";
import { transfer_from_multisig } from "../tools/squads_multisig/transfer_from_multisig";
import { create_proposal } from "../tools/squads_multisig/create_proposal";
import { approve_proposal } from "../tools/squads_multisig/approve_proposal";
import { execute_transaction } from "../tools/squads_multisig/execute_proposal";
import { reject_proposal } from "../tools/squads_multisig/reject_proposal";
/**
* Main class for interacting with Solana blockchain
@@ -487,8 +508,12 @@ export class SolanaAgentKit {
return manifestCreateMarket(this, baseMint, quoteMint);
}
async pythFetchPrice(priceFeedID: string): Promise<string> {
return pythFetchPrice(priceFeedID);
async getPythPriceFeedID(tokenSymbol: string): Promise<string> {
return fetchPythPriceFeedID(tokenSymbol);
}
async getPythPrice(priceFeedID: string): Promise<string> {
return fetchPythPrice(priceFeedID);
}
async createGibworkTask(
@@ -530,6 +555,13 @@ export class SolanaAgentKit {
return cancelListing(this, nftMint);
}
async closeEmptyTokenAccounts(): Promise<{
signature: string;
size: number;
}> {
return closeEmptyTokenAccounts(this);
}
async fetchTokenReportSummary(mint: string): Promise<TokenCheck> {
return fetchTokenReportSummary(mint);
}
@@ -537,4 +569,90 @@ export class SolanaAgentKit {
async fetchTokenDetailedReport(mint: string): Promise<TokenCheck> {
return fetchTokenDetailedReport(mint);
}
/**
* Opens a new trading position on Flash.Trade
* @param params Flash trade parameters including market, side, collateral, leverage, and pool name
* @returns Transaction signature
*/
async flashOpenTrade(params: FlashTradeParams): Promise<string> {
return flashOpenTrade(this, params);
}
/**
* Closes an existing trading position on Flash.Trade
* @param params Flash trade close parameters
* @returns Transaction signature
*/
async flashCloseTrade(params: FlashCloseTradeParams): Promise<string> {
return flashCloseTrade(this, params);
}
async create3LandCollection(
optionsWithBase58: StoreInitOptions,
collectionOpts: CreateCollectionOptions,
): Promise<string> {
const tx = await createCollection(optionsWithBase58, collectionOpts);
return `Transaction: ${tx}`;
}
async create3LandNft(
optionsWithBase58: StoreInitOptions,
collectionAccount: string,
createItemOptions: CreateSingleOptions,
isMainnet: boolean,
): Promise<string> {
const tx = await createSingle(
optionsWithBase58,
collectionAccount,
createItemOptions,
isMainnet,
);
return `Transaction: ${tx}`;
}
async createSquadsMultisig(creator: PublicKey): Promise<string> {
return create_squads_multisig(this, creator);
}
async depositToMultisig(
amount: number,
vaultIndex: number = 0,
mint?: PublicKey,
): Promise<string> {
return deposit_to_multisig(this, amount, vaultIndex, mint);
}
async transferFromMultisig(
amount: number,
to: PublicKey,
vaultIndex: number = 0,
mint?: PublicKey,
): Promise<string> {
return transfer_from_multisig(this, amount, to, vaultIndex, mint);
}
async createMultisigProposal(
transactionIndex?: number | bigint,
): Promise<string> {
return create_proposal(this, transactionIndex);
}
async approveMultisigProposal(
transactionIndex?: number | bigint,
): Promise<string> {
return approve_proposal(this, transactionIndex);
}
async rejectMultisigProposal(
transactionIndex?: number | bigint,
): Promise<string> {
return reject_proposal(this, transactionIndex);
}
async executeMultisigTransaction(
transactionIndex?: number | bigint,
): Promise<string> {
return execute_transaction(this, transactionIndex);
}
}

View File

@@ -1,14 +1,20 @@
import { PublicKey } from "@solana/web3.js";
import { BN } from "@coral-xyz/anchor";
import Decimal from "decimal.js";
import { Tool } from "langchain/tools";
import {
GibworkCreateTaskReponse,
OrderParams,
PythFetchPriceResponse,
SolanaAgentKit,
} from "../index";
import { create_image } from "../tools/create_image";
import { BN } from "@coral-xyz/anchor";
import { FEE_TIERS, generateOrdersfromPattern, OrderParams } from "../tools";
import { create_image, FEE_TIERS, generateOrdersfromPattern } from "../tools";
import { marketTokenMap } from "../utils/flashUtils";
import {
CreateCollectionOptions,
CreateSingleOptions,
StoreInitOptions,
} from "@3land/listings-sdk/dist/types/implementation/implementationTypes";
export class SolanaBalanceTool extends Tool {
name = "solana_balance";
@@ -774,6 +780,135 @@ export class SolanaGetWalletAddressTool extends Tool {
}
}
export class SolanaFlashOpenTrade extends Tool {
name = "solana_flash_open_trade";
description = `This tool can be used to open a new leveraged trading position on Flash.Trade exchange.
Inputs ( input is a JSON string ):
token: string, eg "SOL", "BTC", "ETH" (required)
type: string, eg "long", "short" (required)
collateral: number, eg 10, 100, 1000 (required)
leverage: number, eg 5, 10, 20 (required)
Example prompt is Open a 20x leveraged trade for SOL on long side using flash trade with 500 USD as collateral`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const parsedInput = JSON.parse(input);
// Validate input parameters
if (!parsedInput.token) {
throw new Error("Token is required, received: " + parsedInput.token);
}
if (!Object.keys(marketTokenMap).includes(parsedInput.token)) {
throw new Error(
"Token must be one of " +
Object.keys(marketTokenMap).join(", ") +
", received: " +
parsedInput.token +
"\n" +
"Please check https://beast.flash.trade/ for the list of supported tokens",
);
}
if (!["long", "short"].includes(parsedInput.type)) {
throw new Error(
'Type must be either "long" or "short", received: ' +
parsedInput.type,
);
}
if (!parsedInput.collateral || parsedInput.collateral <= 0) {
throw new Error(
"Collateral amount must be positive, received: " +
parsedInput.collateral,
);
}
if (!parsedInput.leverage || parsedInput.leverage <= 0) {
throw new Error(
"Leverage must be positive, received: " + parsedInput.leverage,
);
}
const tx = await this.solanaKit.flashOpenTrade({
token: parsedInput.token,
side: parsedInput.type,
collateralUsd: parsedInput.collateral,
leverage: parsedInput.leverage,
});
return JSON.stringify({
status: "success",
message: "Flash trade position opened successfully",
transaction: tx,
token: parsedInput.token,
side: parsedInput.type,
collateral: parsedInput.collateral,
leverage: parsedInput.leverage,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
export class SolanaFlashCloseTrade extends Tool {
name = "solana_flash_close_trade";
description = `Close an existing leveraged trading position on Flash.Trade exchange.
Inputs ( input is a JSON string ):
token: string, eg "SOL", "BTC", "ETH" (required)
side: string, eg "long", "short" (required)
Example prompt is Close a 20x leveraged trade for SOL on long side`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const parsedInput = JSON.parse(input);
// Validate input parameters
if (!parsedInput.token) {
throw new Error("Token is required");
}
if (!["SOL", "BTC", "ETH"].includes(parsedInput.token)) {
throw new Error('Token must be one of ["SOL", "BTC", "ETH"]');
}
if (!["long", "short"].includes(parsedInput.side)) {
throw new Error('Side must be either "long" or "short"');
}
const tx = await this.solanaKit.flashCloseTrade({
token: parsedInput.token,
side: parsedInput.side,
});
return JSON.stringify({
status: "success",
message: "Flash trade position closed successfully",
transaction: tx,
token: parsedInput.token,
side: parsedInput.side,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
export class SolanaPumpfunTokenLaunchTool extends Tool {
name = "solana_launch_pumpfun_token";
@@ -1638,7 +1773,7 @@ export class SolanaPythFetchPrice extends Tool {
description = `Fetch the price of a given price feed from Pyth's Hermes service
Inputs:
priceFeedID: string, the price feed ID, e.g., "0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43" for BTC/USD`;
tokenSymbol: string, e.g., BTC for bitcoin`;
constructor(private solanaKit: SolanaAgentKit) {
super();
@@ -1646,17 +1781,21 @@ export class SolanaPythFetchPrice extends Tool {
async _call(input: string): Promise<string> {
try {
const price = await this.solanaKit.pythFetchPrice(input);
const priceFeedID = await this.solanaKit.getPythPriceFeedID(input);
const price = await this.solanaKit.getPythPrice(priceFeedID);
const response: PythFetchPriceResponse = {
status: "success",
priceFeedID: input,
tokenSymbol: input,
priceFeedID,
price,
};
return JSON.stringify(response);
} catch (error: any) {
const response: PythFetchPriceResponse = {
status: "error",
priceFeedID: input,
tokenSymbol: input,
message: error.message,
code: error.code || "UNKNOWN_ERROR",
};
@@ -2121,6 +2260,434 @@ export class SolanaFetchTokenDetailedReportTool extends Tool {
}
}
export class Solana3LandCreateSingle extends Tool {
name = "3land_minting_tool";
description = `Creates an NFT and lists it on 3.land's website
Inputs:
privateKey (required): represents the privateKey of the wallet - can be an array of numbers, Uint8Array or base58 string
collectionAccount (optional): represents the account for the nft collection
itemName (required): the name of the NFT
sellerFee (required): the fee of the seller
itemAmount (required): the amount of the NFTs that can be minted
itemDescription (required): the description of the NFT
traits (required): the traits of the NFT [{trait_type: string, value: string}]
price (required): the price of the item, if is 0 the listing will be free
mainImageUrl (required): the main image of the NFT
coverImageUrl (optional): the cover image of the NFT
splHash (optional): the hash of the spl token, if not provided listing will be in $SOL
isMainnet (required): defines is the tx takes places in mainnet
`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const inputFormat = JSON.parse(input);
const privateKey = inputFormat.privateKey;
const isMainnet = inputFormat.isMainnet;
const optionsWithBase58: StoreInitOptions = {
...(privateKey && { privateKey }),
...(isMainnet && { isMainnet }),
};
const collectionAccount = inputFormat.collectionAccount;
const itemName = inputFormat?.itemName;
const sellerFee = inputFormat?.sellerFee;
const itemAmount = inputFormat?.itemAmount;
const itemSymbol = inputFormat?.itemSymbol;
const itemDescription = inputFormat?.itemDescription;
const traits = inputFormat?.traits;
const price = inputFormat?.price;
const mainImageUrl = inputFormat?.mainImageUrl;
const coverImageUrl = inputFormat?.coverImageUrl;
const splHash = inputFormat?.splHash;
const createItemOptions: CreateSingleOptions = {
...(itemName && { itemName }),
...(sellerFee && { sellerFee }),
...(itemAmount && { itemAmount }),
...(itemSymbol && { itemSymbol }),
...(itemDescription && { itemDescription }),
...(traits && { traits }),
...(price && { price }),
...(mainImageUrl && { mainImageUrl }),
...(coverImageUrl && { coverImageUrl }),
...(splHash && { splHash }),
};
if (!collectionAccount) {
throw new Error("Collection account is required");
}
const tx = await this.solanaKit.create3LandNft(
optionsWithBase58,
collectionAccount,
createItemOptions,
isMainnet,
);
return JSON.stringify({
status: "success",
message: `Created listing successfully ${tx}`,
transaction: tx,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
export class Solana3LandCreateCollection extends Tool {
name = "3land_minting_tool";
description = `Creates an NFT Collection that you can visit on 3.land's website (3.land/collection/{collectionAccount})
Inputs:
privateKey (required): represents the privateKey of the wallet - can be an array of numbers, Uint8Array or base58 string
isMainnet (required): defines is the tx takes places in mainnet
collectionSymbol (required): the symbol of the collection
collectionName (required): the name of the collection
collectionDescription (required): the description of the collection
mainImageUrl (required): the image of the collection
coverImageUrl (optional): the cover image of the collection
`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const inputFormat = JSON.parse(input);
const privateKey = inputFormat.privateKey;
const isMainnet = inputFormat.isMainnet;
const optionsWithBase58: StoreInitOptions = {
...(privateKey && { privateKey }),
...(isMainnet && { isMainnet }),
};
const collectionSymbol = inputFormat?.collectionSymbol;
const collectionName = inputFormat?.collectionName;
const collectionDescription = inputFormat?.collectionDescription;
const mainImageUrl = inputFormat?.mainImageUrl;
const coverImageUrl = inputFormat?.coverImageUrl;
const collectionOpts: CreateCollectionOptions = {
...(collectionSymbol && { collectionSymbol }),
...(collectionName && { collectionName }),
...(collectionDescription && { collectionDescription }),
...(mainImageUrl && { mainImageUrl }),
...(coverImageUrl && { coverImageUrl }),
};
const tx = await this.solanaKit.create3LandCollection(
optionsWithBase58,
collectionOpts,
);
return JSON.stringify({
status: "success",
message: `Created Collection successfully ${tx}`,
transaction: tx,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
export class SolanaCloseEmptyTokenAccounts extends Tool {
name = "close_empty_token_accounts";
description = `Close all empty spl-token accounts and reclaim the rent`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(): Promise<string> {
try {
const { signature, size } =
await this.solanaKit.closeEmptyTokenAccounts();
return JSON.stringify({
status: "success",
message: `${size} accounts closed successfully. ${size === 48 ? "48 accounts can be closed in a single transaction try again to close more accounts" : ""}`,
signature,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
export class SolanaCreate2by2Multisig extends Tool {
name = "create_2by2_multisig";
description = `Create a 2-of-2 multisig account on Solana with the user and the agent, where both approvals will be required to run the transactions.
Note: For one AI agent, only one 2-by-2 multisig can be created as it is pair-wise.
Inputs (JSON string):
- creator: string, the public key of the creator (required).`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const inputFormat = JSON.parse(input);
const creator = new PublicKey(inputFormat.creator);
const multisig = await this.solanaKit.createSquadsMultisig(creator);
return JSON.stringify({
status: "success",
message: "2-by-2 multisig account created successfully",
multisig,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "CREATE_2BY2_MULTISIG_ERROR",
});
}
}
}
export class SolanaDepositTo2by2Multisig extends Tool {
name = "deposit_to_2by2_multisig";
description = `Deposit funds to a 2-of-2 multisig account on Solana with the user and the agent, where both approvals will be required to run the transactions.
Inputs (JSON string):
- amount: number, the amount to deposit in SOL (required).`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const inputFormat = JSON.parse(input);
const amount = new Decimal(inputFormat.amount);
const tx = await this.solanaKit.depositToMultisig(amount.toNumber());
return JSON.stringify({
status: "success",
message: "Funds deposited to 2-by-2 multisig account successfully",
transaction: tx,
amount: amount.toString(),
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "DEPOSIT_TO_2BY2_MULTISIG_ERROR",
});
}
}
}
export class SolanaTransferFrom2by2Multisig extends Tool {
name = "transfer_from_2by2_multisig";
description = `Create a transaction to transfer funds from a 2-of-2 multisig account on Solana with the user and the agent, where both approvals will be required to run the transactions.
Inputs (JSON string):
- amount: number, the amount to transfer in SOL (required).
- recipient: string, the public key of the recipient (required).`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const inputFormat = JSON.parse(input);
const amount = new Decimal(inputFormat.amount);
const recipient = new PublicKey(inputFormat.recipient);
const tx = await this.solanaKit.transferFromMultisig(
amount.toNumber(),
recipient,
);
return JSON.stringify({
status: "success",
message: "Transaction added to 2-by-2 multisig account successfully",
transaction: tx,
amount: amount.toString(),
recipient: recipient.toString(),
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "TRANSFER_FROM_2BY2_MULTISIG_ERROR",
});
}
}
}
export class SolanaCreateProposal2by2Multisig extends Tool {
name = "create_proposal_2by2_multisig";
description = `Create a proposal to transfer funds from a 2-of-2 multisig account on Solana with the user and the agent, where both approvals will be required to run the transactions.
If transactionIndex is not provided, the latest index will automatically be fetched and used.
Inputs (JSON string):
- transactionIndex: number, the index of the transaction (optional).`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const inputFormat = JSON.parse(input);
const transactionIndex = inputFormat.transactionIndex ?? undefined;
const tx = await this.solanaKit.createMultisigProposal(transactionIndex);
return JSON.stringify({
status: "success",
message: "Proposal created successfully",
transaction: tx,
transactionIndex: transactionIndex?.toString(),
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "CREATE_PROPOSAL_2BY2_MULTISIG_ERROR",
});
}
}
}
export class SolanaApproveProposal2by2Multisig extends Tool {
name = "approve_proposal_2by2_multisig";
description = `Approve a proposal to transfer funds from a 2-of-2 multisig account on Solana with the user and the agent, where both approvals will be required to run the transactions.
If proposalIndex is not provided, the latest index will automatically be fetched and used.
Inputs (JSON string):
- proposalIndex: number, the index of the proposal (optional).`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const inputFormat = JSON.parse(input);
const proposalIndex = inputFormat.proposalIndex ?? undefined;
const tx = await this.solanaKit.approveMultisigProposal(proposalIndex);
return JSON.stringify({
status: "success",
message: "Proposal approved successfully",
transaction: tx,
proposalIndex: proposalIndex.toString(),
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "APPROVE_PROPOSAL_2BY2_MULTISIG_ERROR",
});
}
}
}
export class SolanaRejectProposal2by2Multisig extends Tool {
name = "reject_proposal_2by2_multisig";
description = `Reject a proposal to transfer funds from a 2-of-2 multisig account on Solana with the user and the agent, where both approvals will be required to run the transactions.
If proposalIndex is not provided, the latest index will automatically be fetched and used.
Inputs (JSON string):
- proposalIndex: number, the index of the proposal (optional).`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const inputFormat = JSON.parse(input);
const proposalIndex = inputFormat.proposalIndex ?? undefined;
const tx = await this.solanaKit.rejectMultisigProposal(proposalIndex);
return JSON.stringify({
status: "success",
message: "Proposal rejected successfully",
transaction: tx,
proposalIndex: proposalIndex.toString(),
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "REJECT_PROPOSAL_2BY2_MULTISIG_ERROR",
});
}
}
}
export class SolanaExecuteProposal2by2Multisig extends Tool {
name = "execute_proposal_2by2_multisig";
description = `Execute a proposal/transaction to transfer funds from a 2-of-2 multisig account on Solana with the user and the agent, where both approvals will be required to run the transactions.
If proposalIndex is not provided, the latest index will automatically be fetched and used.
Inputs (JSON string):
- proposalIndex: number, the index of the proposal (optional).`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const inputFormat = JSON.parse(input);
const proposalIndex = inputFormat.proposalIndex ?? undefined;
const tx = await this.solanaKit.executeMultisigTransaction(proposalIndex);
return JSON.stringify({
status: "success",
message: "Proposal executed successfully",
transaction: tx,
proposalIndex: proposalIndex.toString(),
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "EXECUTE_PROPOSAL_2BY2_MULTISIG_ERROR",
});
}
}
}
export function createSolanaTools(solanaKit: SolanaAgentKit) {
return [
new SolanaBalanceTool(solanaKit),
@@ -2171,9 +2738,22 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) {
new SolanaTipLinkTool(solanaKit),
new SolanaListNFTForSaleTool(solanaKit),
new SolanaCancelNFTListingTool(solanaKit),
new SolanaCloseEmptyTokenAccounts(solanaKit),
new SolanaFetchTokenReportSummaryTool(solanaKit),
new SolanaFetchTokenDetailedReportTool(solanaKit),
new Solana3LandCreateSingle(solanaKit),
new Solana3LandCreateCollection(solanaKit),
new SolanaPerpOpenTradeTool(solanaKit),
new SolanaPerpCloseTradeTool(solanaKit),
new SolanaFlashOpenTrade(solanaKit),
new SolanaFlashCloseTrade(solanaKit),
new Solana3LandCreateSingle(solanaKit),
new SolanaCreate2by2Multisig(solanaKit),
new SolanaDepositTo2by2Multisig(solanaKit),
new SolanaTransferFrom2by2Multisig(solanaKit),
new SolanaCreateProposal2by2Multisig(solanaKit),
new SolanaApproveProposal2by2Multisig(solanaKit),
new SolanaRejectProposal2by2Multisig(solanaKit),
new SolanaExecuteProposal2by2Multisig(solanaKit),
];
}

View File

@@ -1,37 +0,0 @@
import {
PublicKey,
sendAndConfirmTransaction,
Transaction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { ManifestClient } from "@cks-systems/manifest-sdk";
/**
* Cancels all orders from Manifest
* @param agent SolanaAgentKit instance
* @param marketId Public key for the manifest market
* @returns Transaction signature
*/
export async function cancelAllOrders(
agent: SolanaAgentKit,
marketId: PublicKey,
): Promise<string> {
try {
const mfxClient = await ManifestClient.getClientForMarket(
agent.connection,
marketId,
agent.wallet,
);
const cancelAllOrdersIx = await mfxClient.cancelAllIx();
const signature = await sendAndConfirmTransaction(
agent.connection,
new Transaction().add(cancelAllOrdersIx),
[agent.wallet],
);
return signature;
} catch (error: any) {
throw new Error(`Cancel all orders failed: ${error.message}`);
}
}

View File

@@ -0,0 +1,103 @@
import {
PublicKey,
Transaction,
TransactionInstruction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../agent";
import {
AccountLayout,
createCloseAccountInstruction,
TOKEN_2022_PROGRAM_ID,
TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
/**
* Close Empty SPL Token accounts of the agent
* @param agent SolanaAgentKit instance
* @returns transaction signature and total number of accounts closed
*/
export async function closeEmptyTokenAccounts(
agent: SolanaAgentKit,
): Promise<{ signature: string; size: number }> {
try {
const spl_token = await create_close_instruction(agent, TOKEN_PROGRAM_ID);
const token_2022 = await create_close_instruction(
agent,
TOKEN_2022_PROGRAM_ID,
);
const transaction = new Transaction();
const MAX_INSTRUCTIONS = 40; // 40 instructions can be processed in a single transaction without failing
spl_token
.slice(0, Math.min(MAX_INSTRUCTIONS, spl_token.length))
.forEach((instruction) => transaction.add(instruction));
token_2022
.slice(0, Math.max(0, MAX_INSTRUCTIONS - spl_token.length))
.forEach((instruction) => transaction.add(instruction));
const size = spl_token.length + token_2022.length;
if (size === 0) {
return {
signature: "",
size: 0,
};
}
const signature = await agent.connection.sendTransaction(transaction, [
agent.wallet,
]);
return { signature, size };
} catch (error) {
throw new Error(`Error closing empty token accounts: ${error}`);
}
}
/**
* creates the close instuctions of a spl token account
* @param agnet SolanaAgentKit instance
* @param token_program Token Program Id
* @returns close instuction array
*/
async function create_close_instruction(
agent: SolanaAgentKit,
token_program: PublicKey,
): Promise<TransactionInstruction[]> {
const instructions = [];
const ata_accounts = await agent.connection.getTokenAccountsByOwner(
agent.wallet_address,
{ programId: token_program },
"confirmed",
);
const tokens = ata_accounts.value;
const accountExceptions = [
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC
];
for (let i = 0; i < tokens.length; i++) {
const token_data = AccountLayout.decode(tokens[i].account.data);
if (
token_data.amount === BigInt(0) &&
!accountExceptions.includes(token_data.mint.toString())
) {
const closeInstruction = createCloseAccountInstruction(
ata_accounts.value[i].pubkey,
agent.wallet_address,
agent.wallet_address,
[],
token_program,
);
instructions.push(closeInstruction);
}
}
return instructions;
}

View File

@@ -0,0 +1,69 @@
import { createCollectionImp, createSingleImp } from "@3land/listings-sdk";
import {
StoreInitOptions,
CreateCollectionOptions,
CreateSingleOptions,
} from "@3land/listings-sdk/dist/types/implementation/implementationTypes";
/**
* Create a collection on 3Land
* @param optionsWithBase58 represents the privateKey of the wallet - can be an array of numbers, Uint8Array or base58 string
* @param collectionOpts represents the options for the collection creation
* @returns
*/
export async function createCollection(
optionsWithBase58: StoreInitOptions,
collectionOpts: CreateCollectionOptions,
) {
try {
const collection = await createCollectionImp(
optionsWithBase58,
collectionOpts,
);
return collection;
} catch (error: any) {
throw new Error(`Collection creation failed: ${error.message}`);
}
}
/**
* Create a single edition on 3Land
* @param optionsWithBase58 represents the privateKey of the wallet - can be an array of numbers, Uint8Array or base58 string
* @param collectionAccount represents the account for the nft collection
* @param createItemOptions the options for the creation of the single NFT listing
* @returns
*/
export async function createSingle(
optionsWithBase58: StoreInitOptions,
collectionAccount: string,
createItemOptions: CreateSingleOptions,
isMainnet: boolean,
) {
try {
const landStore = isMainnet
? "AmQNs2kgw4LvS9sm6yE9JJ4Hs3JpVu65eyx9pxMG2xA"
: "GyPCu89S63P9NcCQAtuSJesiefhhgpGWrNVJs4bF2cSK";
const singleEditionTx = await createSingleImp(
optionsWithBase58,
landStore,
collectionAccount,
createItemOptions,
);
return singleEditionTx;
} catch (error: any) {
throw new Error(`Single edition creation failed: ${error.message}`);
}
}
/**
* Buy a single edition on 3Land
* @param
* @returns
*/
// export async function buySingle() {
// try {
// } catch (error: any) {
// throw new Error(`Buying single edition failed: ${error.message}`);
// }
// }

View File

@@ -0,0 +1,118 @@
import { ComputeBudgetProgram } from "@solana/web3.js";
import { PoolConfig, Side } from "flash-sdk";
import { BN } from "@coral-xyz/anchor";
import { SolanaAgentKit } from "../index";
import {
CLOSE_POSITION_CU,
marketSdkInfo,
marketTokenMap,
getNftTradingAccountInfo,
fetchOraclePrice,
createPerpClient,
get_flash_privilege,
} from "../utils/flashUtils";
import { FlashCloseTradeParams } from "../types";
/**
* Closes an existing position on Flash.Trade
* @param agent SolanaAgentKit instance
* @param params Trade parameters
* @returns Transaction signature
*/
export async function flashCloseTrade(
agent: SolanaAgentKit,
params: FlashCloseTradeParams,
): Promise<string> {
try {
const { token, side } = params;
// Get market ID from token and side using marketTokenMap
const tokenMarkets = marketTokenMap[token];
if (!tokenMarkets) {
throw new Error(`Token ${token} not supported for trading`);
}
const sideEntry = tokenMarkets[side];
if (!sideEntry) {
throw new Error(`${side} side not available for ${token}`);
}
const market = sideEntry.marketID;
// Validate market data using marketSdkInfo
const marketData = marketSdkInfo[market];
if (!marketData) {
throw new Error(`Invalid market configuration for ${token}/${side}`);
}
// Get token information
const [targetSymbol, collateralSymbol] = marketData.tokenPair.split("/");
// Fetch oracle prices
const [targetPrice] = await Promise.all([
fetchOraclePrice(targetSymbol),
fetchOraclePrice(collateralSymbol),
]);
// Initialize pool configuration and perpClient
const poolConfig = PoolConfig.fromIdsByName(
marketData.pool,
"mainnet-beta",
);
const perpClient = createPerpClient(agent.connection, agent.wallet);
// Calculate price after slippage
const slippageBpsBN = new BN(100); // 1% slippage
const sideEnum = side === "long" ? Side.Long : Side.Short;
const priceWithSlippage = perpClient.getPriceAfterSlippage(
false, // isEntry = false for closing position
slippageBpsBN,
targetPrice.price,
sideEnum,
);
// Get NFT trading account info
const tradingAccounts = await getNftTradingAccountInfo(
agent.wallet_address,
perpClient,
poolConfig,
collateralSymbol,
);
if (
!tradingAccounts.nftTradingAccountPk ||
!tradingAccounts.nftReferralAccountPK ||
!tradingAccounts.nftOwnerRebateTokenAccountPk
) {
throw new Error("Required NFT trading accounts not found");
}
// Build and send transaction
const { instructions, additionalSigners } = await perpClient.closePosition(
targetSymbol,
collateralSymbol,
priceWithSlippage,
sideEnum,
poolConfig,
get_flash_privilege(agent),
tradingAccounts.nftTradingAccountPk,
tradingAccounts.nftReferralAccountPK,
tradingAccounts.nftOwnerRebateTokenAccountPk,
);
const computeBudgetIx = ComputeBudgetProgram.setComputeUnitLimit({
units: CLOSE_POSITION_CU,
});
return await perpClient.sendTransaction(
[computeBudgetIx, ...instructions],
{
additionalSigners: additionalSigners,
alts: perpClient.addressLookupTables,
prioritizationFee: 5000000,
},
);
} catch (error) {
throw new Error(`Flash trade close failed: ${error}`);
}
}

View File

@@ -0,0 +1,251 @@
import { ComputeBudgetProgram } from "@solana/web3.js";
import {
PerpetualsClient,
OraclePrice,
PoolConfig,
Side,
CustodyAccount,
Custody,
} from "flash-sdk";
import { BN } from "@coral-xyz/anchor";
import { SolanaAgentKit } from "../index";
import {
ALL_TOKENS,
marketSdkInfo,
marketTokenMap,
getNftTradingAccountInfo,
OPEN_POSITION_CU,
fetchOraclePrice,
createPerpClient,
get_flash_privilege,
} from "../utils/flashUtils";
import { FlashTradeParams } from "../types";
/**
* Opens a new position on Flash.Trade
* @param agent SolanaAgentKit instance
* @param params Trade parameters
* @returns Transaction signature
*/
export async function flashOpenTrade(
agent: SolanaAgentKit,
params: FlashTradeParams,
): Promise<string> {
try {
const { token, side, collateralUsd, leverage } = params;
// Get market ID from token and side using marketTokenMap
const tokenMarkets = marketTokenMap[token];
if (!tokenMarkets) {
throw new Error(`Token ${token} not supported for trading`);
}
const sideEntry = tokenMarkets[side];
if (!sideEntry) {
throw new Error(`${side} side not available for ${token}`);
}
const market = sideEntry.marketID;
// Validate market data using marketSdkInfo
const marketData = marketSdkInfo[market];
if (!marketData) {
throw new Error(`Invalid market configuration for ${token}/${side}`);
}
// Get token information
const [targetSymbol, collateralSymbol] = marketData.tokenPair.split("/");
const targetToken = ALL_TOKENS.find((t) => t.symbol === targetSymbol);
const collateralToken = ALL_TOKENS.find(
(t) => t.symbol === collateralSymbol,
);
if (!targetToken || !collateralToken) {
throw new Error(`Token not found for pair ${marketData.tokenPair}`);
}
// Fetch oracle prices
const [targetPrice, collateralPrice] = await Promise.all([
fetchOraclePrice(targetSymbol),
fetchOraclePrice(collateralSymbol),
]);
// Initialize pool configuration and perpClient
const poolConfig = PoolConfig.fromIdsByName(
marketData.pool,
"mainnet-beta",
);
const perpClient = createPerpClient(agent.connection, agent.wallet);
// Calculate position parameters
const leverageBN = new BN(leverage);
const collateralTokenPrice = convertPriceToNumber(collateralPrice.price);
const collateralAmount = calculateCollateralAmount(
collateralUsd,
collateralTokenPrice,
collateralToken.decimals,
);
// Get custody accounts
const { targetCustody, collateralCustody } = await fetchCustodyAccounts(
perpClient,
poolConfig,
targetSymbol,
collateralSymbol,
);
// Calculate position size
const positionSize = calculatePositionSize(
perpClient,
collateralAmount,
leverageBN,
targetToken,
collateralToken,
side,
targetPrice.price,
collateralPrice.price,
targetCustody,
collateralCustody,
);
// Get NFT trading account info
const tradingAccounts = await getNftTradingAccountInfo(
agent.wallet_address,
perpClient,
poolConfig,
collateralSymbol,
);
if (
!tradingAccounts.nftTradingAccountPk ||
!tradingAccounts.nftReferralAccountPK
) {
throw new Error("Required NFT trading accounts not found");
}
// Prepare transaction
const slippageBps = new BN(1000);
const priceWithSlippage = perpClient.getPriceAfterSlippage(
true,
slippageBps,
targetPrice.price,
side === "long" ? Side.Long : Side.Short,
);
// Build and send transaction
const { instructions, additionalSigners } = await perpClient.openPosition(
targetSymbol,
collateralSymbol,
priceWithSlippage,
collateralAmount,
positionSize,
side === "long" ? Side.Long : Side.Short,
poolConfig,
get_flash_privilege(agent),
tradingAccounts.nftTradingAccountPk,
tradingAccounts.nftReferralAccountPK,
tradingAccounts.nftOwnerRebateTokenAccountPk!,
false,
);
const computeBudgetIx = ComputeBudgetProgram.setComputeUnitLimit({
units: OPEN_POSITION_CU,
});
return await perpClient.sendTransaction(
[computeBudgetIx, ...instructions],
{
additionalSigners: additionalSigners,
alts: perpClient.addressLookupTables,
prioritizationFee: 5000000,
},
);
} catch (error) {
throw new Error(`Flash trade failed: ${error}`);
}
}
// Helper functions
function convertPriceToNumber(oraclePrice: OraclePrice): number {
const price = parseInt(oraclePrice.price.toString("hex"), 16);
const exponent = parseInt(oraclePrice.exponent.toString("hex"), 16);
return price * Math.pow(10, exponent);
}
function calculateCollateralAmount(
usdAmount: number,
tokenPrice: number,
decimals: number,
): BN {
return new BN((usdAmount / tokenPrice) * Math.pow(10, decimals));
}
async function fetchCustodyAccounts(
perpClient: PerpetualsClient,
poolConfig: PoolConfig,
targetSymbol: string,
collateralSymbol: string,
) {
const targetConfig = poolConfig.custodies.find(
(c) => c.symbol === targetSymbol,
);
const collateralConfig = poolConfig.custodies.find(
(c) => c.symbol === collateralSymbol,
);
if (!targetConfig || !collateralConfig) {
throw new Error("Custody configuration not found");
}
const accounts = await perpClient.provider.connection.getMultipleAccountsInfo(
[targetConfig.custodyAccount, collateralConfig.custodyAccount],
);
if (!accounts[0] || !accounts[1]) {
throw new Error("Failed to fetch custody accounts");
}
return {
targetCustody: CustodyAccount.from(
targetConfig.custodyAccount,
perpClient.program.coder.accounts.decode<Custody>(
"custody",
accounts[0].data,
),
),
collateralCustody: CustodyAccount.from(
collateralConfig.custodyAccount,
perpClient.program.coder.accounts.decode<Custody>(
"custody",
accounts[1].data,
),
),
};
}
function calculatePositionSize(
perpClient: PerpetualsClient,
collateralAmount: BN,
leverage: BN,
targetToken: any,
collateralToken: any,
side: "long" | "short",
targetPrice: OraclePrice,
collateralPrice: OraclePrice,
targetCustody: CustodyAccount,
collateralCustody: CustodyAccount,
): BN {
return perpClient.getSizeAmountFromLeverageAndCollateral(
collateralAmount,
leverage.toString(),
targetToken,
collateralToken,
side === "long" ? Side.Long : Side.Short,
targetPrice,
targetPrice,
targetCustody,
collateralPrice,
collateralPrice,
collateralCustody,
);
}

View File

@@ -9,17 +9,14 @@ export async function getTokenDataByAddress(
throw new Error("Mint address is required");
}
const response = await fetch("https://tokens.jup.ag/tokens?tags=verified", {
const response = await fetch(`https://tokens.jup.ag/token/${mint}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
const data = (await response.json()) as JupiterTokenData[];
const token = data.find((token: JupiterTokenData) => {
return token.address === mint.toBase58();
});
const token = (await response.json()) as JupiterTokenData;
return token;
} catch (error: any) {
throw new Error(`Error fetching token data: ${error.message}`);

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "..";
import { SolanaAgentKit } from "../agent";
/**
* Get the agents wallet address

View File

@@ -1,61 +1,52 @@
export * from "./get_wallet_address";
export * from "./request_faucet_funds";
export * from "./get_wallet_address";
export * from "./request_faucet_funds";
export * from "./deploy_token";
export * from "./adrena_perp_trading";
export * from "./create_gibwork_task";
export * from "./create_image";
export * from "./create_tiplinks";
export * from "./deploy_collection";
export * from "./deploy_token";
export * from "./fetch_price";
export * from "./get_all_domains_tlds";
export * from "./get_all_registered_all_domains";
export * from "./get_balance";
export * from "./get_balance_other";
export * from "./mint_nft";
export * from "./transfer";
export * from "./trade";
export * from "./limit_order";
export * from "./batch_order";
export * from "./cancel_all_orders";
export * from "./withdraw_all";
export * from "./adrena_perp_trading";
export * from "./register_domain";
export * from "./resolve_sol_domain";
export * from "./get_main_all_domains_domain";
export * from "./get_owned_all_domains";
export * from "./get_owned_domains_for_tld";
export * from "./get_primary_domain";
export * from "./get_token_data";
export * from "./get_tps";
export * from "./get_wallet_address";
export * from "./launch_pumpfun_token";
export * from "./lend";
export * from "./get_tps";
export * from "./get_token_data";
export * from "./stake_with_jup";
export * from "./stake_with_solayer";
export * from "./fetch_price";
export * from "./send_compressed_airdrop";
export * from "./manifest_trade";
export * from "./mint_nft";
export * from "./openbook_create_market";
export * from "./orca_close_position";
export * from "./orca_create_clmm";
export * from "./orca_create_single_sided_liquidity_pool";
export * from "./orca_fetch_positions";
export * from "./orca_open_centered_position_with_liquidity";
export * from "./orca_open_single_sided_position";
export * from "./get_all_domains_tlds";
export * from "./get_all_registered_all_domains";
export * from "./get_owned_domains_for_tld";
export * from "./get_main_all_domains_domain";
export * from "./get_owned_all_domains";
export * from "./resolve_domain";
export * from "./get_all_domains_tlds";
export * from "./get_all_registered_all_domains";
export * from "./get_owned_domains_for_tld";
export * from "./get_main_all_domains_domain";
export * from "./get_owned_all_domains";
export * from "./resolve_domain";
export * from "./pyth_fetch_price";
export * from "./raydium_create_ammV4";
export * from "./raydium_create_clmm";
export * from "./raydium_create_cpmm";
export * from "./openbook_create_market";
export * from "./manifest_create_market";
export * from "./pyth_fetch_price";
export * from "./create_gibwork_task";
export * from "./register_domain";
export * from "./request_faucet_funds";
export * from "./resolve_domain";
export * from "./resolve_sol_domain";
export * from "./rock_paper_scissor";
export * from "./create_tiplinks";
export * from "./tensor_trade";
export * from "./rugcheck";
export * from "./send_compressed_airdrop";
export * from "./stake_with_jup";
export * from "./stake_with_solayer";
export * from "./tensor_trade";
export * from "./close_empty_token_accounts";
export * from "./trade";
export * from "./transfer";
export * from "./flash_open_trade";
export * from "./flash_close_trade";
export * from "./create_3land_collectible";

View File

@@ -1,61 +0,0 @@
import {
PublicKey,
Transaction,
sendAndConfirmTransaction,
TransactionInstruction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import {
ManifestClient,
WrapperPlaceOrderParamsExternal,
} from "@cks-systems/manifest-sdk";
import { OrderType } from "@cks-systems/manifest-sdk/client/ts/src/wrapper/types/OrderType";
/**
* Place limit orders using Manifest
* @param agent SolanaAgentKit instance
* @param marketId Public key for the manifest market
* @param quantity Amount to trade in tokens
* @param side Buy or Sell
* @param price Price in tokens ie. SOL/USDC
* @returns Transaction signature
*/
export async function limitOrder(
agent: SolanaAgentKit,
marketId: PublicKey,
quantity: number,
side: string,
price: number,
): Promise<string> {
try {
const mfxClient = await ManifestClient.getClientForMarket(
agent.connection,
marketId,
agent.wallet,
);
const orderParams: WrapperPlaceOrderParamsExternal = {
numBaseTokens: quantity,
tokenPrice: price,
isBid: side === "Buy",
lastValidSlot: 0,
orderType: OrderType.Limit,
clientOrderId: Number(Math.random() * 1000),
};
const depositPlaceOrderIx: TransactionInstruction[] =
await mfxClient.placeOrderWithRequiredDepositIx(
agent.wallet.publicKey,
orderParams,
);
const signature = await sendAndConfirmTransaction(
agent.connection,
new Transaction().add(...depositPlaceOrderIx),
[agent.wallet],
);
return signature;
} catch (error: any) {
throw new Error(`Limit Order failed: ${error.message}`);
}
}

View File

@@ -1,43 +0,0 @@
import { ManifestClient } from "@cks-systems/manifest-sdk";
import {
Keypair,
PublicKey,
sendAndConfirmTransaction,
SystemProgram,
Transaction,
TransactionInstruction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
export async function manifestCreateMarket(
agent: SolanaAgentKit,
baseMint: PublicKey,
quoteMint: PublicKey,
): Promise<string[]> {
const marketKeypair: Keypair = Keypair.generate();
const FIXED_MANIFEST_HEADER_SIZE: number = 256;
const createAccountIx: TransactionInstruction = SystemProgram.createAccount({
fromPubkey: agent.wallet.publicKey,
newAccountPubkey: marketKeypair.publicKey,
space: FIXED_MANIFEST_HEADER_SIZE,
lamports: await agent.connection.getMinimumBalanceForRentExemption(
FIXED_MANIFEST_HEADER_SIZE,
),
programId: new PublicKey("MNFSTqtC93rEfYHB6hF82sKdZpUDFWkViLByLd1k1Ms"),
});
const createMarketIx = ManifestClient["createMarketIx"](
agent.wallet.publicKey,
baseMint,
quoteMint,
marketKeypair.publicKey,
);
const tx: Transaction = new Transaction();
tx.add(createAccountIx);
tx.add(createMarketIx);
const signature = await sendAndConfirmTransaction(agent.connection, tx, [
agent.wallet,
marketKeypair,
]);
return [signature, marketKeypair.publicKey.toBase58()];
}

View File

@@ -1,35 +1,158 @@
import {
PublicKey,
Transaction,
sendAndConfirmTransaction,
TransactionInstruction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import {
ManifestClient,
OrderType,
WrapperPlaceOrderParamsExternal,
} from "@cks-systems/manifest-sdk";
import { OrderType } from "@cks-systems/manifest-sdk/client/ts/src/wrapper/types/OrderType";
import {
Keypair,
PublicKey,
sendAndConfirmTransaction,
SystemProgram,
Transaction,
TransactionInstruction,
} from "@solana/web3.js";
import { BatchOrderPattern, OrderParams, SolanaAgentKit } from "../index";
export interface OrderParams {
quantity: number;
side: string;
price: number;
export async function manifestCreateMarket(
agent: SolanaAgentKit,
baseMint: PublicKey,
quoteMint: PublicKey,
): Promise<string[]> {
const marketKeypair: Keypair = Keypair.generate();
const FIXED_MANIFEST_HEADER_SIZE: number = 256;
const createAccountIx: TransactionInstruction = SystemProgram.createAccount({
fromPubkey: agent.wallet.publicKey,
newAccountPubkey: marketKeypair.publicKey,
space: FIXED_MANIFEST_HEADER_SIZE,
lamports: await agent.connection.getMinimumBalanceForRentExemption(
FIXED_MANIFEST_HEADER_SIZE,
),
programId: new PublicKey("MNFSTqtC93rEfYHB6hF82sKdZpUDFWkViLByLd1k1Ms"),
});
const createMarketIx = ManifestClient["createMarketIx"](
agent.wallet.publicKey,
baseMint,
quoteMint,
marketKeypair.publicKey,
);
const tx: Transaction = new Transaction();
tx.add(createAccountIx);
tx.add(createMarketIx);
const signature = await sendAndConfirmTransaction(agent.connection, tx, [
agent.wallet,
marketKeypair,
]);
return [signature, marketKeypair.publicKey.toBase58()];
}
interface BatchOrderPattern {
side: string;
totalQuantity?: number;
priceRange?: {
min?: number;
max?: number;
};
spacing?: {
type: "percentage" | "fixed";
value: number;
};
numberOfOrders?: number;
individualQuantity?: number;
/**
* Place limit orders using Manifest
* @param agent SolanaAgentKit instance
* @param marketId Public key for the manifest market
* @param quantity Amount to trade in tokens
* @param side Buy or Sell
* @param price Price in tokens ie. SOL/USDC
* @returns Transaction signature
*/
export async function limitOrder(
agent: SolanaAgentKit,
marketId: PublicKey,
quantity: number,
side: string,
price: number,
): Promise<string> {
try {
const mfxClient = await ManifestClient.getClientForMarket(
agent.connection,
marketId,
agent.wallet,
);
const orderParams: WrapperPlaceOrderParamsExternal = {
numBaseTokens: quantity,
tokenPrice: price,
isBid: side === "Buy",
lastValidSlot: 0,
orderType: OrderType.Limit,
clientOrderId: Number(Math.random() * 1000),
};
const depositPlaceOrderIx: TransactionInstruction[] =
await mfxClient.placeOrderWithRequiredDepositIx(
agent.wallet.publicKey,
orderParams,
);
const signature = await sendAndConfirmTransaction(
agent.connection,
new Transaction().add(...depositPlaceOrderIx),
[agent.wallet],
);
return signature;
} catch (error: any) {
throw new Error(`Limit Order failed: ${error.message}`);
}
}
/**
* Cancels all orders from Manifest
* @param agent SolanaAgentKit instance
* @param marketId Public key for the manifest market
* @returns Transaction signature
*/
export async function cancelAllOrders(
agent: SolanaAgentKit,
marketId: PublicKey,
): Promise<string> {
try {
const mfxClient = await ManifestClient.getClientForMarket(
agent.connection,
marketId,
agent.wallet,
);
const cancelAllOrdersIx = await mfxClient.cancelAllIx();
const signature = await sendAndConfirmTransaction(
agent.connection,
new Transaction().add(cancelAllOrdersIx),
[agent.wallet],
);
return signature;
} catch (error: any) {
throw new Error(`Cancel all orders failed: ${error.message}`);
}
}
/**
* Withdraws all funds from Manifest
* @param agent SolanaAgentKit instance
* @param marketId Public key for the manifest market
* @returns Transaction signature
*/
export async function withdrawAll(
agent: SolanaAgentKit,
marketId: PublicKey,
): Promise<string> {
try {
const mfxClient = await ManifestClient.getClientForMarket(
agent.connection,
marketId,
agent.wallet,
);
const withdrawAllIx = await mfxClient.withdrawAllIx();
const signature = await sendAndConfirmTransaction(
agent.connection,
new Transaction().add(...withdrawAllIx),
[agent.wallet],
);
return signature;
} catch (error: any) {
throw new Error(`Withdraw all failed: ${error.message}`);
}
}
/**

View File

@@ -26,7 +26,7 @@ import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token";
* # Opens a Centered Liquidity Position in an Orca Whirlpool
*
* This function opens a centered liquidity position in a specified Orca Whirlpool. The user defines
* a basis point (bps) offset from the cuurent price of the pool to set the lower and upper bounds of the position.
* a basis point (bps) offset from the current price of the pool to set the lower and upper bounds of the position.
* The user also specifies the token mint and the amount to deposit. The required amount of the other token
* is calculated automatically.
*

View File

@@ -1,38 +1,91 @@
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
import BN from "bn.js";
import { PythPriceFeedIDItem } from "../types";
/**
* Fetch the price feed ID for a given token symbol from Pyth
* @param tokenSymbol Token symbol
* @returns Price feed ID
*/
export async function fetchPythPriceFeedID(
tokenSymbol: string,
): Promise<string> {
try {
const stableHermesServiceUrl: string = "https://hermes.pyth.network";
const response = await fetch(
`${stableHermesServiceUrl}/v2/price_feeds?query=${tokenSymbol}&asset_type=crypto`,
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (data.length === 0) {
throw new Error(`No price feed found for ${tokenSymbol}`);
}
if (data.length > 1) {
const filteredData = data.filter(
(item: PythPriceFeedIDItem) =>
item.attributes.base.toLowerCase() === tokenSymbol.toLowerCase(),
);
if (filteredData.length === 0) {
throw new Error(`No price feed found for ${tokenSymbol}`);
}
return filteredData[0].id;
}
return data[0].id;
} catch (error: any) {
throw new Error(
`Fetching price feed ID from Pyth failed: ${error.message}`,
);
}
}
/**
* Fetch the price of a given price feed from Pyth
* @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(priceFeedID: string): Promise<string> {
// 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];
export async function fetchPythPrice(feedID: string): Promise<string> {
try {
const currentPrice = await connection.getLatestPriceFeeds(feeds);
const stableHermesServiceUrl: string = "https://hermes.pyth.network";
if (currentPrice === undefined) {
throw new Error("Price data not available for the given token.");
const response = await fetch(
`${stableHermesServiceUrl}/v2/updates/price/latest?ids[]=${feedID}`,
);
const data = await response.json();
const parsedData = data.parsed;
if (parsedData.length === 0) {
throw new Error(`No price data found for ${feedID}`);
}
if (currentPrice.length === 0) {
throw new Error("Price data not available for the given token.");
const price = new BN(parsedData[0].price.price);
const exponent = parsedData[0].price.expo;
if (exponent < 0) {
const adjustedPrice = price.mul(new BN(100));
const divisor = new BN(10).pow(new BN(-exponent));
const scaledPrice = adjustedPrice.div(divisor);
const priceStr = scaledPrice.toString();
const formattedPrice = `${priceStr.slice(0, -2)}.${priceStr.slice(-2)}`;
return formattedPrice.startsWith(".")
? `0${formattedPrice}`
: formattedPrice;
}
// get price and exponent from price feed
const price = new BN(currentPrice[0].getPriceUnchecked().price);
const exponent = new BN(currentPrice[0].getPriceUnchecked().expo);
// convert to scaled price
const scaledPrice = price.div(new BN(10).pow(exponent));
const scaledPrice = price.div(new BN(10).pow(new BN(exponent)));
return scaledPrice.toString();
} catch (error: any) {
throw new Error(`Fetching price from Pyth failed: ${error.message}`);

View File

@@ -0,0 +1,52 @@
import { SolanaAgentKit } from "../../index";
import * as multisig from "@sqds/multisig";
const { Multisig } = multisig.accounts;
/**
* Approves a proposal in a Solana multisig wallet.
*
* @param {SolanaAgentKit} agent - The Solana agent kit instance.
* @param {number | bigint} [transactionIndex] - The index of the transaction to approve. If not provided, the current transaction index will be used.
* @returns {Promise<string>} - A promise that resolves to the transaction ID of the approved proposal.
* @throws {Error} - Throws an error if the approval process fails.
*/
export async function approve_proposal(
agent: SolanaAgentKit,
transactionIndex?: number | bigint,
): Promise<string> {
try {
const createKey = agent.wallet;
const [multisigPda] = multisig.getMultisigPda({
createKey: createKey.publicKey,
});
const multisigInfo = await Multisig.fromAccountAddress(
agent.connection,
multisigPda,
);
const currentTransactionIndex = Number(multisigInfo.transactionIndex);
if (!transactionIndex) {
transactionIndex = BigInt(currentTransactionIndex);
} else if (typeof transactionIndex !== "bigint") {
transactionIndex = BigInt(transactionIndex);
}
// const [proposalPda, proposalBump] = multisig.getProposalPda({
// multisigPda,
// transactionIndex,
// });
const multisigTx = multisig.transactions.proposalApprove({
blockhash: (await agent.connection.getLatestBlockhash()).blockhash,
feePayer: agent.wallet.publicKey,
multisigPda,
transactionIndex: transactionIndex,
member: agent.wallet.publicKey,
});
multisigTx.sign([agent.wallet]);
const tx = await agent.connection.sendRawTransaction(
multisigTx.serialize(),
);
return tx;
} catch (error: any) {
throw new Error(`Transfer failed: ${error}`);
}
}

View File

@@ -0,0 +1,62 @@
import * as multisig from "@sqds/multisig";
import { PublicKey } from "@solana/web3.js";
import { SolanaAgentKit } from "../../index";
/**
* Creates a new Squads multisig account.
*
* @param agent - The SolanaAgentKit instance containing the connection and wallet information.
* @param creator - The public key of the creator who will be a member of the multisig.
* @returns A promise that resolves to the transaction ID of the multisig creation transaction.
*
* @throws Will throw an error if the transaction fails.
*/
export async function create_squads_multisig(
agent: SolanaAgentKit,
creator: PublicKey,
): Promise<string> {
const connection = agent.connection;
const createKey = agent.wallet; // can be any keypair, using the agent wallet as only one multisig is required
console.log("Multisig Create Key:", createKey.publicKey.toBase58());
const [multisigPda] = multisig.getMultisigPda({
createKey: createKey.publicKey,
});
const programConfigPda = multisig.getProgramConfigPda({})[0];
const programConfig =
await multisig.accounts.ProgramConfig.fromAccountAddress(
connection,
programConfigPda,
);
const configTreasury = programConfig.treasury;
const tx = multisig.transactions.multisigCreateV2({
blockhash: (await connection.getLatestBlockhash()).blockhash,
treasury: configTreasury,
createKey: createKey.publicKey,
creator: agent.wallet.publicKey,
multisigPda,
configAuthority: null,
timeLock: 0,
threshold: 2,
rentCollector: null,
members: [
{
key: agent.wallet.publicKey,
permissions: multisig.types.Permissions.all(),
},
{
key: creator,
permissions: multisig.types.Permissions.all(),
},
],
});
tx.sign([agent.wallet, createKey]);
const txId = connection.sendRawTransaction(tx.serialize());
return txId;
}

View File

@@ -0,0 +1,48 @@
import { SolanaAgentKit } from "../../index";
import * as multisig from "@sqds/multisig";
const { Multisig } = multisig.accounts;
/**
* Creates a proposal for a multisig transaction.
*
* @param {SolanaAgentKit} agent - The Solana agent kit instance.
* @param {number | bigint} [transactionIndex] - Optional transaction index. If not provided, the current transaction index will be used.
* @returns {Promise<string>} - The transaction ID of the created proposal.
* @throws {Error} - Throws an error if the proposal creation fails.
*/
export async function create_proposal(
agent: SolanaAgentKit,
transactionIndex?: number | bigint,
): Promise<string> {
try {
const createKey = agent.wallet;
const [multisigPda] = multisig.getMultisigPda({
createKey: createKey.publicKey,
});
const multisigInfo = await Multisig.fromAccountAddress(
agent.connection,
multisigPda,
);
const currentTransactionIndex = Number(multisigInfo.transactionIndex);
if (!transactionIndex) {
transactionIndex = BigInt(currentTransactionIndex);
} else if (typeof transactionIndex !== "bigint") {
transactionIndex = BigInt(transactionIndex);
}
const multisigTx = multisig.transactions.proposalCreate({
blockhash: (await agent.connection.getLatestBlockhash()).blockhash,
feePayer: agent.wallet_address,
multisigPda,
transactionIndex,
creator: agent.wallet_address,
});
multisigTx.sign([agent.wallet]);
const tx = await agent.connection.sendRawTransaction(
multisigTx.serialize(),
);
return tx;
} catch (error: any) {
throw new Error(`Transfer failed: ${error}`);
}
}

View File

@@ -0,0 +1,91 @@
import { SolanaAgentKit } from "../../index";
import { PublicKey, SystemProgram, Transaction } from "@solana/web3.js";
import { LAMPORTS_PER_SOL } from "@solana/web3.js";
import {
getAssociatedTokenAddress,
createTransferInstruction,
getMint,
createAssociatedTokenAccountInstruction,
} from "@solana/spl-token";
import * as multisig from "@sqds/multisig";
/**
* Transfer SOL or SPL tokens to a multisig vault.
* @param agent SolanaAgentKit instance
* @param amount Amount to transfer
* @param vaultIndex Optional vault index, default is 0
* @param mint Optional mint address for SPL tokens
* @returns Transaction signature
*/
export async function deposit_to_multisig(
agent: SolanaAgentKit,
amount: number,
vaultIndex?: number,
mint?: PublicKey,
): Promise<string> {
try {
let tx: string;
if (!vaultIndex) {
vaultIndex = 0;
}
const createKey = agent.wallet;
const [multisigPda] = multisig.getMultisigPda({
createKey: createKey.publicKey,
});
const [vaultPda] = multisig.getVaultPda({
multisigPda,
index: vaultIndex,
});
const to = vaultPda;
if (!mint) {
// Transfer native SOL
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: agent.wallet_address,
toPubkey: to,
lamports: amount * LAMPORTS_PER_SOL,
}),
);
tx = await agent.connection.sendTransaction(transaction, [agent.wallet]);
} else {
// Transfer SPL token
const fromAta = await getAssociatedTokenAddress(
mint,
agent.wallet_address,
);
let transaction = new Transaction();
const toAta = await getAssociatedTokenAddress(mint, to, true);
const toTokenAccountInfo = await agent.connection.getAccountInfo(toAta);
// Create associated token account if it doesn't exist
if (!toTokenAccountInfo) {
transaction.add(
createAssociatedTokenAccountInstruction(
agent.wallet_address,
toAta,
to,
mint,
),
);
}
// Get mint info to determine decimals
const mintInfo = await getMint(agent.connection, mint);
const adjustedAmount = amount * Math.pow(10, mintInfo.decimals);
transaction.add(
createTransferInstruction(
fromAta,
toAta,
agent.wallet_address,
adjustedAmount,
),
);
tx = await agent.connection.sendTransaction(transaction, [agent.wallet]);
}
return tx;
} catch (error: any) {
throw new Error(`Transfer failed: ${error}`);
}
}

View File

@@ -0,0 +1,49 @@
import { SolanaAgentKit } from "../../index";
import * as multisig from "@sqds/multisig";
const { Multisig } = multisig.accounts;
/**
* Executes a transaction on the Solana blockchain using the provided agent.
*
* @param {SolanaAgentKit} agent - The Solana agent kit instance containing the wallet and connection.
* @param {number | bigint} [transactionIndex] - Optional transaction index to execute. If not provided, the current transaction index from the multisig account will be used.
* @returns {Promise<string>} - A promise that resolves to the transaction signature string.
* @throws {Error} - Throws an error if the transaction execution fails.
*/
export async function execute_transaction(
agent: SolanaAgentKit,
transactionIndex?: number | bigint,
): Promise<string> {
try {
const createKey = agent.wallet;
const [multisigPda] = multisig.getMultisigPda({
createKey: createKey.publicKey,
});
const multisigInfo = await Multisig.fromAccountAddress(
agent.connection,
multisigPda,
);
const currentTransactionIndex = Number(multisigInfo.transactionIndex);
if (!transactionIndex) {
transactionIndex = BigInt(currentTransactionIndex);
} else if (typeof transactionIndex !== "bigint") {
transactionIndex = BigInt(transactionIndex);
}
const multisigTx = await multisig.transactions.vaultTransactionExecute({
connection: agent.connection,
blockhash: (await agent.connection.getLatestBlockhash()).blockhash,
feePayer: agent.wallet.publicKey,
multisigPda,
transactionIndex,
member: agent.wallet.publicKey,
});
multisigTx.sign([agent.wallet]);
const tx = await agent.connection.sendRawTransaction(
multisigTx.serialize(),
);
return tx;
} catch (error: any) {
throw new Error(`Transfer failed: ${error}`);
}
}

View File

@@ -0,0 +1,52 @@
import { SolanaAgentKit } from "../../index";
import * as multisig from "@sqds/multisig";
const { Multisig } = multisig.accounts;
/**
* Rejects a proposal in a Solana multisig setup.
*
* @param agent - The SolanaAgentKit instance containing the wallet and connection.
* @param transactionIndex - Optional. The index of the transaction to reject. If not provided, the current transaction index will be used.
* @returns A promise that resolves to the transaction ID of the rejection transaction.
* @throws Will throw an error if the transaction fails.
*/
export async function reject_proposal(
agent: SolanaAgentKit,
transactionIndex?: number | bigint,
): Promise<string> {
try {
const createKey = agent.wallet;
const [multisigPda] = multisig.getMultisigPda({
createKey: createKey.publicKey,
});
const multisigInfo = await Multisig.fromAccountAddress(
agent.connection,
multisigPda,
);
const currentTransactionIndex = Number(multisigInfo.transactionIndex);
if (!transactionIndex) {
transactionIndex = BigInt(currentTransactionIndex);
} else if (typeof transactionIndex !== "bigint") {
transactionIndex = BigInt(transactionIndex);
}
// const [proposalPda, proposalBump] = multisig.getProposalPda({
// multisigPda,
// transactionIndex,
// });
const multisigTx = multisig.transactions.proposalReject({
blockhash: (await agent.connection.getLatestBlockhash()).blockhash,
feePayer: agent.wallet.publicKey,
multisigPda,
transactionIndex: transactionIndex,
member: agent.wallet.publicKey,
});
multisigTx.sign([agent.wallet]);
const tx = await agent.connection.sendRawTransaction(
multisigTx.serialize(),
);
return tx;
} catch (error: any) {
throw new Error(`Transfer failed: ${error}`);
}
}

View File

@@ -0,0 +1,98 @@
import { SolanaAgentKit } from "../../index";
import {
PublicKey,
SystemProgram,
TransactionInstruction,
TransactionMessage,
} from "@solana/web3.js";
import { LAMPORTS_PER_SOL } from "@solana/web3.js";
import {
getAssociatedTokenAddress,
createTransferInstruction,
getMint,
} from "@solana/spl-token";
import * as multisig from "@sqds/multisig";
const { Multisig } = multisig.accounts;
/**
* Transfer SOL or SPL tokens to a recipient from a multisig vault.
* @param agent - SolanaAgentKit instance.
* @param amount - Amount to transfer.
* @param to - Recipient's public key.
* @param vaultIndex - Optional vault index, default is 0.
* @param mint - Optional mint address for SPL tokens.
* @returns Transaction signature.
*/
export async function transfer_from_multisig(
agent: SolanaAgentKit,
amount: number,
to: PublicKey,
vaultIndex: number = 0,
mint?: PublicKey,
): Promise<string> {
try {
let transferInstruction: TransactionInstruction;
const createKey = agent.wallet;
const [multisigPda] = multisig.getMultisigPda({
createKey: createKey.publicKey,
});
const multisigInfo = await Multisig.fromAccountAddress(
agent.connection,
multisigPda,
);
const currentTransactionIndex = Number(multisigInfo.transactionIndex);
const transactionIndex = BigInt(currentTransactionIndex + 1);
const [vaultPda] = multisig.getVaultPda({
multisigPda,
index: vaultIndex,
});
if (!mint) {
// Transfer native SOL
transferInstruction = SystemProgram.transfer({
fromPubkey: agent.wallet_address,
toPubkey: to,
lamports: amount * LAMPORTS_PER_SOL,
});
} else {
// Transfer SPL token
const fromAta = await getAssociatedTokenAddress(mint, vaultPda, true);
const toAta = await getAssociatedTokenAddress(mint, to, true);
const mintInfo = await getMint(agent.connection, mint);
const adjustedAmount = amount * Math.pow(10, mintInfo.decimals);
transferInstruction = createTransferInstruction(
fromAta,
toAta,
agent.wallet_address,
adjustedAmount,
);
}
const transferMessage = new TransactionMessage({
payerKey: vaultPda,
recentBlockhash: (await agent.connection.getLatestBlockhash()).blockhash,
instructions: [transferInstruction],
});
const multisigTx = multisig.transactions.vaultTransactionCreate({
blockhash: (await agent.connection.getLatestBlockhash()).blockhash,
feePayer: agent.wallet_address,
multisigPda,
transactionIndex,
creator: agent.wallet_address,
vaultIndex: 0,
ephemeralSigners: 0,
transactionMessage: transferMessage,
});
multisigTx.sign([agent.wallet]);
const tx = await agent.connection.sendRawTransaction(
multisigTx.serialize(),
);
return tx;
} catch (error: any) {
throw new Error(`Transfer failed: ${error}`);
}
}

View File

@@ -27,7 +27,7 @@ export async function stakeWithSolayer(
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Staking request failed');
throw new Error(errorData.message || "Staking request failed");
}
const data = await response.json();
@@ -61,4 +61,4 @@ export async function stakeWithSolayer(
console.error(error);
throw new Error(`Solayer sSOL staking failed: ${error.message}`);
}
}
}

View File

@@ -1,37 +0,0 @@
import {
PublicKey,
sendAndConfirmTransaction,
Transaction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { ManifestClient } from "@cks-systems/manifest-sdk";
/**
* Withdraws all funds from Manifest
* @param agent SolanaAgentKit instance
* @param marketId Public key for the manifest market
* @returns Transaction signature
*/
export async function withdrawAll(
agent: SolanaAgentKit,
marketId: PublicKey,
): Promise<string> {
try {
const mfxClient = await ManifestClient.getClientForMarket(
agent.connection,
marketId,
agent.wallet,
);
const withdrawAllIx = await mfxClient.withdrawAllIx();
const signature = await sendAndConfirmTransaction(
agent.connection,
new Transaction().add(...withdrawAllIx),
[agent.wallet],
);
return signature;
} catch (error: any) {
throw new Error(`Withdraw all failed: ${error.message}`);
}
}

View File

@@ -6,6 +6,7 @@ export interface Config {
OPENAI_API_KEY?: string;
JUPITER_REFERRAL_ACCOUNT?: string;
JUPITER_FEE_BPS?: number;
FLASH_PRIVILEGE?: string;
}
export interface Creator {
@@ -88,7 +89,8 @@ export interface FetchPriceResponse {
export interface PythFetchPriceResponse {
status: "success" | "error";
priceFeedID: string;
tokenSymbol: string;
priceFeedID?: string;
price?: string;
message?: string;
code?: string;
@@ -165,3 +167,73 @@ export interface TokenCheck {
}>;
score: number;
}
export interface PythPriceFeedIDItem {
id: string;
attributes: {
asset_type: string;
base: string;
};
}
export interface PythPriceItem {
binary: {
data: string[];
encoding: string;
};
parsed: [
Array<{
id: string;
price: {
price: string;
conf: string;
expo: number;
publish_time: number;
};
ema_price: {
price: string;
conf: string;
expo: number;
publish_time: number;
};
metadata: {
slot: number;
proof_available_time: number;
prev_publish_time: number;
};
}>,
];
}
export interface OrderParams {
quantity: number;
side: string;
price: number;
}
export interface BatchOrderPattern {
side: string;
totalQuantity?: number;
priceRange?: {
min?: number;
max?: number;
};
spacing?: {
type: "percentage" | "fixed";
value: number;
};
numberOfOrders?: number;
individualQuantity?: number;
}
export interface FlashTradeParams {
token: string;
side: "long" | "short";
collateralUsd: number;
leverage: number;
}
export interface FlashCloseTradeParams {
token: string;
side: "long" | "short";
}

300
src/utils/flashUtils.ts Normal file
View File

@@ -0,0 +1,300 @@
import { HermesClient } from "@pythnetwork/hermes-client";
import { OraclePrice } from "flash-sdk";
import { AnchorProvider, BN, Wallet } from "@coral-xyz/anchor";
import {
PoolConfig,
Token,
Referral,
PerpetualsClient,
Privilege,
} from "flash-sdk";
import { Cluster, PublicKey, Connection, Keypair } from "@solana/web3.js";
import { getAssociatedTokenAddressSync } from "@solana/spl-token";
import { SolanaAgentKit } from "../index";
const POOL_NAMES = [
"Crypto.1",
"Virtual.1",
"Governance.1",
"Community.1",
"Community.2",
"Community.3",
];
const DEFAULT_CLUSTER: Cluster = "mainnet-beta";
export const POOL_CONFIGS = POOL_NAMES.map((f) =>
PoolConfig.fromIdsByName(f, DEFAULT_CLUSTER),
);
const DUPLICATE_TOKENS = POOL_CONFIGS.map((f) => f.tokens).flat();
const tokenMap = new Map();
for (const token of DUPLICATE_TOKENS) {
tokenMap.set(token.symbol, token);
}
export const ALL_TOKENS: Token[] = Array.from(tokenMap.values());
export const ALL_CUSTODIES = POOL_CONFIGS.map((f) => f.custodies).flat();
const PROGRAM_ID = POOL_CONFIGS[0].programId;
// CU for trade instructions
export const OPEN_POSITION_CU = 150_000;
export const CLOSE_POSITION_CU = 180_000;
const HERMES_URL = "https://hermes.pyth.network"; // Replace with the actual Hermes URL if different
// Create a map of symbol to Pyth price ID
const PRICE_FEED_IDS = ALL_TOKENS.reduce(
(acc, token) => {
acc[token.symbol] = token.pythPriceId;
return acc;
},
{} as { [key: string]: string },
);
const hermesClient = new HermesClient(HERMES_URL, {});
export interface PythPriceEntry {
price: OraclePrice;
emaPrice: OraclePrice;
isStale: boolean;
status: PriceStatus;
}
export enum PriceStatus {
Trading,
Unknown,
Halted,
Auction,
}
export const fetchOraclePrice = async (
symbol: string,
): Promise<PythPriceEntry> => {
const priceFeedId = PRICE_FEED_IDS[symbol];
if (!priceFeedId) {
throw new Error(`Price feed ID not found for symbol: ${symbol}`);
}
try {
const hermesPriceFeed = await hermesClient.getPriceFeeds({
query: symbol,
filter: "crypto",
});
if (!hermesPriceFeed || hermesPriceFeed.length === 0) {
throw new Error(`No price feed received for ${symbol}`);
}
const hemrmesPriceUdpate = await hermesClient.getLatestPriceUpdates(
[priceFeedId],
{
encoding: "hex",
parsed: true,
},
);
if (!hemrmesPriceUdpate.parsed) {
throw new Error(`No price feed received for ${symbol}`);
}
const hermesEma = hemrmesPriceUdpate.parsed[0].ema_price;
const hermesPrice = hemrmesPriceUdpate.parsed[0].price;
const hermesPriceOracle = new OraclePrice({
price: new BN(hermesPrice.price),
exponent: new BN(hermesPrice.expo),
confidence: new BN(hermesPrice.conf),
timestamp: new BN(hermesPrice.publish_time),
});
const hermesEmaOracle = new OraclePrice({
price: new BN(hermesEma.price),
exponent: new BN(hermesEma.expo),
confidence: new BN(hermesEma.conf),
timestamp: new BN(hermesEma.publish_time),
});
const token = ALL_TOKENS.find((t) => t.pythPriceId === priceFeedId);
if (!token) {
throw new Error(`Token not found for price feed ID: ${priceFeedId}`);
}
const status = !token.isVirtual ? PriceStatus.Trading : PriceStatus.Unknown;
const pythPriceEntry: PythPriceEntry = {
price: hermesPriceOracle,
emaPrice: hermesEmaOracle,
isStale: false,
status: status,
};
return pythPriceEntry;
} catch (error) {
console.error(`Error in fetchOraclePrice for ${symbol}:`, error);
throw error;
}
};
export interface MarketInfo {
[key: string]: {
tokenPair: string;
token: string;
side: string;
pool: string;
};
}
const marketSdkInfo: MarketInfo = {};
// Loop through POOL_CONFIGS to process each market
POOL_CONFIGS.forEach((poolConfig) => {
poolConfig.markets.forEach((market) => {
const targetToken = ALL_TOKENS.find(
(token) => token.mintKey.toString() === market.targetMint.toString(),
);
// Find collateral token by matching mintKey
const collateralToken = ALL_TOKENS.find(
(token) => token.mintKey.toString() === market.collateralMint.toString(),
);
if (targetToken?.symbol && collateralToken?.symbol) {
marketSdkInfo[market.marketAccount.toString()] = {
tokenPair: `${targetToken.symbol}/${collateralToken.symbol}`,
token: targetToken.symbol,
side: Object.keys(market.side)[0],
pool: poolConfig.poolName,
};
}
});
});
export { marketSdkInfo };
export interface MarketTokenSides {
[token: string]: {
long?: { marketID: string };
short?: { marketID: string };
};
}
const marketTokenMap: MarketTokenSides = {};
// Convert marketSdkInfo into marketTokenMap
Object.entries(marketSdkInfo).forEach(([marketID, info]) => {
if (!marketTokenMap[info.token]) {
marketTokenMap[info.token] = {};
}
marketTokenMap[info.token][info.side.toLowerCase() as "long" | "short"] = {
marketID,
};
});
export { marketTokenMap };
interface TradingAccountResult {
nftReferralAccountPK: PublicKey | null;
nftTradingAccountPk: PublicKey | null;
nftOwnerRebateTokenAccountPk: PublicKey | null;
}
export async function getNftTradingAccountInfo(
userPublicKey: PublicKey,
perpClient: PerpetualsClient,
poolConfig: PoolConfig,
collateralCustodySymbol: string,
): Promise<TradingAccountResult> {
const getNFTReferralAccountPK = (publicKey: PublicKey) => {
return PublicKey.findProgramAddressSync(
[Buffer.from("referral"), publicKey.toBuffer()],
PROGRAM_ID,
)[0];
};
const nftReferralAccountPK = getNFTReferralAccountPK(userPublicKey);
const nftReferralAccountInfo =
await perpClient.provider.connection.getAccountInfo(nftReferralAccountPK);
let nftTradingAccountPk: PublicKey | null = null;
let nftOwnerRebateTokenAccountPk: PublicKey | null = null;
if (nftReferralAccountInfo) {
const nftReferralAccountData = perpClient.program.coder.accounts.decode(
"referral",
nftReferralAccountInfo.data,
) as Referral;
nftTradingAccountPk = nftReferralAccountData.refererTradingAccount;
if (nftTradingAccountPk) {
const nftTradingAccountInfo =
await perpClient.provider.connection.getAccountInfo(
nftTradingAccountPk,
);
if (nftTradingAccountInfo) {
const nftTradingAccount = perpClient.program.coder.accounts.decode(
"trading",
nftTradingAccountInfo.data,
) as { owner: PublicKey };
nftOwnerRebateTokenAccountPk = getAssociatedTokenAddressSync(
poolConfig.getTokenFromSymbol(collateralCustodySymbol).mintKey,
nftTradingAccount.owner,
);
// Check if the account exists
const accountExists =
await perpClient.provider.connection.getAccountInfo(
nftOwnerRebateTokenAccountPk,
);
if (!accountExists) {
console.error(
"NFT owner rebate token account does not exist and may need to be created",
);
}
}
}
}
return {
nftReferralAccountPK,
nftTradingAccountPk,
nftOwnerRebateTokenAccountPk,
};
}
/**
* Creates a new PerpetualsClient instance with the given connection and wallet
* @param connection Solana connection
* @param wallet Solana wallet
* @returns PerpetualsClient instance
*/
export function createPerpClient(
connection: Connection,
wallet: Keypair,
): PerpetualsClient {
const provider = new AnchorProvider(connection, new Wallet(wallet), {
commitment: "confirmed",
preflightCommitment: "confirmed",
skipPreflight: true,
});
return new PerpetualsClient(
provider,
POOL_CONFIGS[0].programId,
POOL_CONFIGS[0].perpComposibilityProgramId,
POOL_CONFIGS[0].fbNftRewardProgramId,
POOL_CONFIGS[0].rewardDistributionProgram.programId,
{},
);
}
export function get_flash_privilege(agent: SolanaAgentKit): Privilege {
const FLASH_PRIVILEGE = agent.config.FLASH_PRIVILEGE || "None";
switch (FLASH_PRIVILEGE.toLowerCase()) {
case "referral":
return Privilege.Referral;
case "nft":
return Privilege.NFT;
default:
return Privilege.None;
}
}

63
test/tools/3land.ts Normal file
View File

@@ -0,0 +1,63 @@
import {
CreateCollectionOptions,
CreateSingleOptions,
StoreInitOptions,
} from "@3land/listings-sdk/dist/types/implementation/implementationTypes";
import "dotenv/config";
import { SolanaAgentKit, createSolanaTools } from "../../src";
const agent = new SolanaAgentKit(
process.env.SOLANA_PRIVATE_KEY!,
process.env.RPC_URL!,
{ OPENAI_API_KEY: process.env.OPENAI_API_KEY! },
);
const optionsWithBase58: StoreInitOptions = {
privateKey: process.env.SOLANA_PRIVATE_KEY!,
isMainnet: false,
};
/****************************** CREATING COLLECTION ******************************** */
const collectionOpts: CreateCollectionOptions = {
collectionName: "",
collectionSymbol: "",
collectionDescription: "",
mainImageUrl: "",
};
(async () => {
const collection = await agent.create3LandCollection(
optionsWithBase58,
collectionOpts,
);
console.log("collection: ", collection);
})();
/****************************** CREATING NFT ******************************** */
const collectionAccount = "";
const createItemOptions: CreateSingleOptions = {
itemName: "",
sellerFee: 500, //5%
itemAmount: 100,
itemSymbol: "",
itemDescription: "",
traits: [{ trait_type: "", value: "" }],
price: 0, //100000000 == 0.1 sol
mainImageUrl: "",
};
const isMainnet = false;
(async () => {
const result = agent.create3LandNft(
optionsWithBase58,
collectionAccount,
createItemOptions,
isMainnet,
);
console.log("result: ", result);
})();
export { SolanaAgentKit, createSolanaTools };

View File

@@ -22,7 +22,6 @@
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]