Skip to content
Closed
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
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ multiple operations into a single programmable and extensible toolkit.
- Liquidity pool (LP) deposits & withdrawals
- Querying pool reserves and share IDs
- Custom contract integrations (current)
- Claimable balances for conditional / time-locked payments (escrow & vesting)
- Designed for future LP provider integrations
- Supports Testnet & Mainnet

Expand Down Expand Up @@ -331,6 +332,58 @@ const shareId = await agent.lp.getShareId();

---

## 🔒 Claimable Balances (Conditional / Time-Locked Payments)

Stellar's native primitive for **escrow, vesting, and scheduled payouts** —
ideal for AI-agent workflows where funds must be released only when a
predicate is satisfied.

```typescript
import { AgentClient } from "stellartools";

const agent = new AgentClient({ network: "testnet" });

// 1. Lock 100 XLM for `recipient`, claimable any time within the next 24h
const created = await agent.claimable.create({
sourceSecret: process.env.SOURCE_SECRET!,
asset: { code: "XLM" },
amount: "100",
claimants: [
{
destination: "GRECIPIENT...",
predicate: { type: "beforeRelativeTime", seconds: 86400 },
},
],
});
console.log(created.transactionHash, created.balanceIds);

// 2. List claimable balances awaiting a specific account
const open = await agent.claimable.list({ claimant: "GRECIPIENT..." });

// 3. Claim a balance
await agent.claimable.claim({
claimerSecret: process.env.RECIPIENT_SECRET!,
balanceId: created.balanceIds[0],
});
```

**Supported predicates** (composable via `and` / `or` / `not`):

| Type | Meaning |
| --- | --- |
| `unconditional` | Always claimable |
| `beforeRelativeTime` | Claimable for N seconds after creation |
| `beforeAbsoluteTime` | Claimable until a Unix epoch timestamp |
| `not` | Negation of an inner predicate |
| `and` / `or` | Logical combination of two inner predicates |

Each input claimant becomes its own `CreateClaimableBalance` operation, so the
returned `balanceIds` map 1:1 with `claimants`. Up to **100 operations per
transaction** (Stellar protocol cap on operations per tx) — split larger batches
across multiple calls.

---

## 🌐 Supported Networks

- **Testnet** - Full support, no restrictions, safe for development
Expand Down
67 changes: 67 additions & 0 deletions agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ import {
type SwapBestRouteResult,
} from "./lib/dex";
import { bridgeTokenTool } from "./tools/bridge";
import {
createClaimableBalance as cbCreate,
claimClaimableBalance as cbClaim,
listClaimableBalances as cbList,
type CreateClaimableBalanceParams,
type CreateClaimableBalanceResult,
type ClaimClaimableBalanceParams,
type ClaimClaimableBalanceResult,
type ListClaimableBalancesParams,
type ClaimableBalanceRecord,
type ClaimPredicate,
type ClaimantInput,
} from "./lib/claimableBalance";
import {
Horizon,
Keypair,
Expand Down Expand Up @@ -66,6 +79,14 @@ export type {
RouteQuote,
SwapBestRouteParams,
SwapBestRouteResult,
CreateClaimableBalanceParams,
CreateClaimableBalanceResult,
ClaimClaimableBalanceParams,
ClaimClaimableBalanceResult,
ListClaimableBalancesParams,
ClaimableBalanceRecord,
ClaimPredicate,
ClaimantInput,
};

export class AgentClient {
Expand Down Expand Up @@ -238,6 +259,52 @@ export class AgentClient {
},
};

/**
* Claimable Balances — conditional / time-locked payments (escrow, vesting,
* scheduled payouts). Useful for AI-agent workflows where funds must be
* released only when a predicate evaluates to true.
*
* @example
* // Lock 100 XLM for `recipient`, claimable after 24h
* await agent.claimable.create({
* sourceSecret: process.env.SECRET!,
* asset: { code: "XLM" },
* amount: "100",
* claimants: [{
* destination: recipient,
* predicate: { type: "beforeRelativeTime", seconds: 86400 },
* }],
* });
*/
public claimable = {
create: async (
params: CreateClaimableBalanceParams
): Promise<CreateClaimableBalanceResult> => {
return await cbCreate(
{ network: this.network, horizonUrl: this.rpcUrl },
params
);
},

claim: async (
params: ClaimClaimableBalanceParams
): Promise<ClaimClaimableBalanceResult> => {
return await cbClaim(
{ network: this.network, horizonUrl: this.rpcUrl },
params
);
},

list: async (
params?: ListClaimableBalancesParams
): Promise<ClaimableBalanceRecord[]> => {
return await cbList(
{ network: this.network, horizonUrl: this.rpcUrl },
params ?? {}
);
},
};

/**
* Launch a new token on the Stellar network.
*
Expand Down
16 changes: 16 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ import type {
RouteQuote,
SwapBestRouteParams,
SwapBestRouteResult,
CreateClaimableBalanceParams,
CreateClaimableBalanceResult,
ClaimClaimableBalanceParams,
ClaimClaimableBalanceResult,
ListClaimableBalancesParams,
ClaimableBalanceRecord,
ClaimPredicate,
ClaimantInput,
} from "./agent";

export {
Expand All @@ -30,6 +38,14 @@ export type {
RouteQuote,
SwapBestRouteParams,
SwapBestRouteResult,
CreateClaimableBalanceParams,
CreateClaimableBalanceResult,
ClaimClaimableBalanceParams,
ClaimClaimableBalanceResult,
ListClaimableBalancesParams,
ClaimableBalanceRecord,
ClaimPredicate,
ClaimantInput,
};
export const stellarTools = [
bridgeTokenTool,
Expand Down
Loading
Loading