Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions typescript/packages/plugins/solentic/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# @goat-sdk/plugin-solentic

## 0.1.0

### Minor Changes

- Initial release. Native Solana staking via Solentic API with the Blueprint validator. Exposes 8 tools: stake, unstake, withdraw, getApy, getStakeAccounts, checkWithdrawReady, simulateStake, getValidatorInfo.
79 changes: 79 additions & 0 deletions typescript/packages/plugins/solentic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# @goat-sdk/plugin-solentic

Native Solana staking with [Blueprint validator](https://solentic.theblueprint.xyz) via the [GOAT SDK](https://github.com/goat-sdk/goat). Stake, unstake, withdraw, and monitor SOL staking positions through AI agents.

## Installation

```bash
npm install @goat-sdk/plugin-solentic
```

Make sure you also have the required peer dependencies:

```bash
npm install @goat-sdk/core @goat-sdk/wallet-solana
```

## Usage

```typescript
import { getOnChainTools } from "@goat-sdk/adapter-vercel-ai";
import { solana } from "@goat-sdk/wallet-solana";
import { solentic } from "@goat-sdk/plugin-solentic";

const tools = await getOnChainTools({
wallet: solana({ /* wallet config */ }),
plugins: [solentic()],
});

// Use with your LLM framework of choice (Vercel AI, LangChain, etc.)
```

### Custom API URL

```typescript
solentic({ baseUrl: "https://your-solentic-instance.com" })
```

## Available Tools

### Transaction Tools

| Tool | Description |
|------|-------------|
| `stakeSol` | Stake SOL with Blueprint validator. Builds, signs, and submits in one call. |
| `unstakeSol` | Deactivate a stake account. SOL becomes withdrawable after the epoch ends (~2-3 days). |
| `withdrawStake` | Withdraw SOL from a fully deactivated stake account back to the wallet. |

### Read-Only Tools

| Tool | Description |
|------|-------------|
| `getValidatorInfo` | Full validator details: commission, rank, APY, performance, infrastructure. |
| `getStakingApy` | APY breakdown: base staking APY, Jito MEV APY, total combined APY. |
| `getStakeAccounts` | List all stake accounts for a wallet delegated to Blueprint validator. |
| `checkWithdrawReady` | Check which stake accounts are ready for withdrawal after unstaking. |
| `simulateStake` | Project staking returns for a given amount and duration without transacting. |

## Security

- **Zero custody**: The plugin never handles private keys. All transactions are built as unsigned base64 payloads by the Solentic API and signed by the GOAT wallet client.
- **No key storage**: Private keys remain in the wallet client and are never sent to the Solentic API.
- **Verifiable**: The Solentic API provides a `verify_code_integrity` tool for auditing the server-side transaction building code.

## Staking Lifecycle

1. **Stake**: Call `stakeSol` with an amount. Returns a transaction signature and new stake account address. The stake activates at the next epoch boundary.
2. **Monitor**: Use `getStakeAccounts` to see status. Use `simulateStake` to project returns.
3. **Unstake**: Call `unstakeSol` with the stake account address. Begins the cooldown (deactivation) period.
4. **Withdraw**: After the epoch ends, call `checkWithdrawReady` to verify, then `withdrawStake` to reclaim SOL.

## Links

- [Solentic API](https://solentic.theblueprint.xyz)
- [API Documentation](https://solentic.theblueprint.xyz/docs)
- [GOAT SDK](https://github.com/goat-sdk/goat)

## License

MIT
32 changes: 32 additions & 0 deletions typescript/packages/plugins/solentic/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@goat-sdk/plugin-solentic",
"version": "0.1.0",
"files": ["dist/**/*", "README.md", "package.json"],
"scripts": {
"build": "tsup",
"clean": "rm -rf dist",
"test": "vitest run --passWithNoTests"
},
"sideEffects": false,
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"dependencies": {
"@goat-sdk/core": "workspace:*",
"@goat-sdk/wallet-solana": "workspace:*",
"zod": "catalog:"
},
"peerDependencies": {
"@goat-sdk/core": "workspace:*"
},
"homepage": "https://ohmygoat.dev",
"repository": {
"type": "git",
"url": "git+https://github.com/goat-sdk/goat.git"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/goat-sdk/goat/issues"
},
"keywords": ["ai", "agents", "web3", "solana", "staking", "defi", "solentic", "blueprint"]
}
12 changes: 12 additions & 0 deletions typescript/packages/plugins/solentic/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export { SolenticPlugin, solentic } from "./solentic.plugin";
export type { SolenticPluginOptions } from "./solentic.plugin";
export { SolenticService } from "./solentic.service";
export {
StakeSolParameters,
UnstakeSolParameters,
WithdrawStakeParameters,
GetStakeAccountsParameters,
CheckWithdrawReadyParameters,
SimulateStakeParameters,
EmptyParameters,
} from "./parameters";
72 changes: 72 additions & 0 deletions typescript/packages/plugins/solentic/src/parameters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { createToolParameters } from "@goat-sdk/core";
import { z } from "zod";

export class StakeSolParameters extends createToolParameters(
z.object({
amountInSol: z
.string()
.describe(
"Amount of SOL to stake, as a decimal string (e.g. '1.5'). Minimum ~0.01 SOL. A small reserve (~0.005 SOL) is kept for transaction fees."
),
})
) {}

export class UnstakeSolParameters extends createToolParameters(
z.object({
stakeAccountAddress: z
.string()
.describe(
"The Solana stake account address to deactivate. Must be an active stake account owned by the connected wallet. After deactivation, funds become withdrawable at the end of the current epoch (~2-3 days)."
),
})
) {}

export class WithdrawStakeParameters extends createToolParameters(
z.object({
stakeAccountAddress: z
.string()
.describe(
"The Solana stake account address to withdraw from. The stake must be fully deactivated (inactive) before withdrawal is possible. Use checkWithdrawReady to verify."
),
})
) {}

export class GetStakeAccountsParameters extends createToolParameters(
z.object({
walletAddress: z
.string()
.optional()
.describe(
"Wallet address to look up stake accounts for. If omitted, uses the connected wallet address."
),
})
) {}

export class CheckWithdrawReadyParameters extends createToolParameters(
z.object({
walletAddress: z
.string()
.optional()
.describe(
"Wallet address to check withdrawal readiness for. If omitted, uses the connected wallet address."
),
})
) {}

export class SimulateStakeParameters extends createToolParameters(
z.object({
amountInSol: z
.string()
.describe(
"Amount of SOL to simulate staking, as a decimal string (e.g. '100')."
),
durationDays: z
.number()
.optional()
.describe(
"Number of days to project staking returns for. Defaults to 365 if omitted."
),
})
) {}

export class EmptyParameters extends createToolParameters(z.object({})) {}
35 changes: 35 additions & 0 deletions typescript/packages/plugins/solentic/src/solentic.plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { type Chain, PluginBase } from "@goat-sdk/core";
import { SolenticService } from "./solentic.service";

export interface SolenticPluginOptions {
/**
* Base URL of the Solentic API.
* Defaults to "https://solentic.theblueprint.xyz"
*/
baseUrl?: string;
}

export class SolenticPlugin extends PluginBase {
constructor(options?: SolenticPluginOptions) {
super("solentic", [new SolenticService(options?.baseUrl)]);
}

supportsChain = (chain: Chain) => chain.type === "solana";
}

/**
* Create a Solentic plugin instance for GOAT.
*
* @example
* ```ts
* import { solentic } from "@goat-sdk/plugin-solentic";
*
* const tools = await getOnChainTools({
* wallet: solanaWallet,
* plugins: [solentic()],
* });
* ```
*/
export function solentic(options?: SolenticPluginOptions) {
return new SolenticPlugin(options);
}
Loading