Skip to content
Merged
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
3 changes: 0 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,3 @@ jobs:
working-directory: packages/actions
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}



8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Thank you for your interest in contributing to Pipeit! This document provides gu
This is a monorepo managed with Turbo and pnpm workspaces:

- `packages/core/` - Main transaction builder with execution strategies, Flow API, and Kit integration
- `packages/actions/` - High-level DeFi actions with pluggable protocol adapters
- `packages/actions/` - InstructionPlan factories for DeFi (Titan, Metis)
- `packages/fastlane/` - Native Rust QUIC client for direct TPU submission (NAPI)
- `examples/next-js/` - Next.js example application demonstrating usage

Expand Down Expand Up @@ -103,9 +103,9 @@ pnpm test

### @pipeit/actions

- Follow adapter pattern for protocol integrations
- Ensure adapters are pluggable and testable
- Document adapter interfaces and requirements
- Build Kit-compatible InstructionPlans
- Follow existing Titan/Metis patterns for new integrations
- Document quote/route/plan building pipeline
- Consider API rate limits and error handling

### @pipeit/fastlane
Expand Down
91 changes: 53 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Pipeit is a comprehensive TypeScript SDK for building and executing Solana trans
Built on modern Solana libraries (@solana/kit) with a focus on type safety, developer experience, and production readiness.

**Key Features:**

- Type-safe transaction building with compile-time validation
- Multiple execution strategies (Standard RPC, Jito Bundles, Parallel Execution, TPU direct)
- Multi-step flows with dynamic context between steps
Expand All @@ -19,31 +20,37 @@ Built on modern Solana libraries (@solana/kit) with a focus on type safety, deve

## Packages

| Package | Description | Docs |
|---------|-------------|------|
| [@pipeit/core](./packages/core) | Transaction builder with smart defaults, flows, and execution strategies | [README](./packages/core/README.md) |
| [@pipeit/actions](./packages/actions) | High-level DeFi actions with pluggable adapters | [README](./packages/actions/README.md) |
| [@pipeit/fastlane](./packages/fastlane) | Native Rust QUIC client for direct TPU submission | [Package](./packages/fastlane) |
| Package | Description | Docs |
| --------------------------------------- | ------------------------------------------------------------------------ | -------------------------------------- |
| [@pipeit/core](./packages/core) | Transaction builder with smart defaults, flows, and execution strategies | [README](./packages/core/README.md) |
| [@pipeit/actions](./packages/actions) | InstructionPlan factories for DeFi (Titan, Metis) | [README](./packages/actions/README.md) |
| [@pipeit/fastlane](./packages/fastlane) | Native Rust QUIC client for direct TPU submission | [Package](./packages/fastlane) |

## Package Overview

### @pipeit/core

The foundation package for transaction building:

- TransactionBuilder with auto-blockhash, auto-retry, and priority fees
- Flow API for multi-step workflows with dynamic context
- Multiple execution strategies (RPC, Jito bundles, parallel execution, TPU direct)
- Kit instruction-plans integration
- Server exports for server components based TPU handlers

### @pipeit/actions (WIP)
High-level DeFi operations:
- Simple, composable API for swaps and other DeFi actions
- Pluggable adapters (Jupiter, with more coming)
- Automatic address lookup table handling
- Lifecycle hooks for monitoring execution
### @pipeit/actions

Composable InstructionPlan factories for DeFi:

- Kit-compatible InstructionPlans for swap operations
- Titan and Metis aggregator integration
- Address lookup table support
- Composable with Kit's plan combinators

### @pipeit/fastlane

Ultra-fast transaction submission:

- Native Rust QUIC implementation via NAPI
- Direct TPU submission bypassing RPC nodes
- Continuous resubmission until confirmation
Expand All @@ -57,13 +64,14 @@ Ultra-fast transaction submission:
pipeit/
├── packages/
│ ├── @pipeit/core # Transaction builder, flows, execution
│ ├── @pipeit/actions # High-level DeFi actions
│ ├── @pipeit/actions # InstructionPlan factories for DeFi
│ └── @pipeit/fastlane # Native QUIC TPU client
└── examples/
└── next-js/ # Example application
```

**Choosing a Package:**

- Building transactions? → `@pipeit/core`
- DeFi operations (swaps)? → `@pipeit/actions` + `@pipeit/core`
- Ultra-fast submission? → `@pipeit/fastlane` + `@pipeit/core`
Expand All @@ -74,7 +82,7 @@ pipeit/
# Transaction builder (recommended starting point)
pnpm install @pipeit/core @solana/kit

# High-level DeFi actions
# DeFi operations (swaps via Titan/Metis)
pnpm install @pipeit/actions @pipeit/core @solana/kit

# TPU direct submission (server-side only)
Expand Down Expand Up @@ -126,43 +134,47 @@ const result = await createFlow({ rpc, rpcSubscriptions, signer })
### DeFi Swap

```typescript
import { pipe } from '@pipeit/actions';
import { jupiter } from '@pipeit/actions/adapters';
import { getTitanSwapPlan } from '@pipeit/actions/titan';
import { executePlan } from '@pipeit/core';

const result = await pipe({
rpc,
rpcSubscriptions,
signer,
adapters: { swap: jupiter() },
})
.swap({
// Get a swap plan from Titan
const { plan, lookupTableAddresses, quote } = await getTitanSwapPlan({
swap: {
inputMint: 'So11111111111111111111111111111111111111112', // SOL
outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
amount: 100_000_000n, // 0.1 SOL
slippageBps: 50,
})
.execute();
},
transaction: {
userPublicKey: signer.address,
},
});

// Execute with ALT support
await executePlan(plan, {
rpc,
rpcSubscriptions,
signer,
lookupTableAddresses,
});
```

## Execution Strategies

Pipeit supports multiple execution strategies for different use cases:

| Preset | Description | Use Case |
|--------|-------------|----------|
| `'standard'` | Default RPC submission | General transactions |
| `'economical'` | Jito bundle only | MEV-sensitive swaps |
| `'fast'` | Jito + parallel RPC race | Time-sensitive operations |
| `'ultra'` | TPU direct + Jito race | Fastest possible (requires `@pipeit/fastlane`) |
| Preset | Description | Use Case |
| -------------- | ------------------------ | ---------------------------------------------- |
| `'standard'` | Default RPC submission | General transactions |
| `'economical'` | Jito bundle only | MEV-sensitive swaps |
| `'fast'` | Jito + parallel RPC race | Time-sensitive operations |
| `'ultra'` | TPU direct + Jito race | Fastest possible (requires `@pipeit/fastlane`) |

```typescript
const signature = await new TransactionBuilder({ rpc })
.setFeePayerSigner(signer)
.addInstruction(instruction)
.execute({
rpcSubscriptions,
execution: 'fast', // or 'standard', 'economical', 'ultra'
});
const signature = await new TransactionBuilder({ rpc }).setFeePayerSigner(signer).addInstruction(instruction).execute({
rpcSubscriptions,
execution: 'fast', // or 'standard', 'economical', 'ultra'
});
```

For custom configuration, see the [@pipeit/core README](./packages/core/README.md).
Expand Down Expand Up @@ -225,18 +237,21 @@ export { tpuHandler as POST } from '@pipeit/core/server';
## Development

### Prerequisites

- Node.js 20+
- pnpm 10+
- Rust (for @pipeit/fastlane development)

### Setup

```bash
git clone https://github.com/stevesarmiento/pipeit.git
cd pipeit
pnpm install
```

### Commands

```bash
pnpm build # Build all packages
pnpm test # Run all tests
Expand All @@ -250,5 +265,5 @@ Contributions are welcome. Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for

## License

MIT
MIT
[LICENSE.md](.LICENSE.md)
20 changes: 10 additions & 10 deletions examples/next-js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ Demonstrates the value proposition of Pipeit with:

Interactive demos of various pipeline patterns with real mainnet transactions:

| Example | Description |
|---------|-------------|
| **Simple Transfer** | Single instruction, single transaction - baseline example |
| **Batched Transfers** | Multiple transfers batched into one atomic transaction |
| **Mixed Pipeline** | Instruction and transaction steps - shows when batching breaks |
| **Jupiter Swap** | Token swap using Jupiter aggregator |
| **Pipe Multi-Swap** | SOL → USDC → BONK sequential swaps with Flow orchestration |
| **Jito Bundle** | MEV-protected bundle submission with Jito tip instructions |
| **TPU Direct** | Direct QUIC submission to validator TPU - bypass RPC for max speed |
| Example | Description |
| --------------------- | ------------------------------------------------------------------ |
| **Simple Transfer** | Single instruction, single transaction - baseline example |
| **Batched Transfers** | Multiple transfers batched into one atomic transaction |
| **Mixed Pipeline** | Instruction and transaction steps - shows when batching breaks |
| **Jupiter Swap** | Token swap using Jupiter aggregator |
| **Titan Swap** | Token swap using Titan aggregator |
| **Jito Bundle** | MEV-protected bundle submission with Jito tip instructions |
| **TPU Direct** | Direct QUIC submission to validator TPU - bypass RPC for max speed |

Each example includes:

Expand Down Expand Up @@ -102,7 +102,7 @@ Multi-step examples demonstrate:
## Dependencies

- `@pipeit/core` - Transaction builder
- `@pipeit/actions` - DeFi actions (Jupiter swaps)
- `@pipeit/actions` - DeFi actions (Titan, Metis swaps)
- `@pipeit/fastlane` - TPU direct submission
- `@solana/kit` - Solana primitives
- `@solana/connector` - Wallet connection
Expand Down
79 changes: 64 additions & 15 deletions examples/next-js/app/api/jupiter/quote/route.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,79 @@
import { NextRequest, NextResponse } from 'next/server';

const JUPITER_API_BASE = 'https://api.jup.ag/swap/v1';

/**
* Next.js API route proxy for Jupiter quote API.
* Proxies requests to Jupiter's quote API to work around network/DNS restrictions.
* Next.js API route proxy for Jupiter Metis quote API.
* Proxies requests to Jupiter's quote API with API key authentication.
*/
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;

const params = new URLSearchParams({
inputMint: searchParams.get('inputMint') || '',
outputMint: searchParams.get('outputMint') || '',
amount: searchParams.get('amount') || '',
slippageBps: searchParams.get('slippageBps') || '50',
onlyDirectRoutes: searchParams.get('onlyDirectRoutes') || 'false',
asLegacyTransaction: searchParams.get('asLegacyTransaction') || 'false',
});
const params = new URLSearchParams();

// Required params
const inputMint = searchParams.get('inputMint');
const outputMint = searchParams.get('outputMint');
const amount = searchParams.get('amount');

if (!inputMint || !outputMint || !amount) {
return NextResponse.json(
{ error: 'Missing required parameters: inputMint, outputMint, amount' },
{ status: 400 },
);
}

params.set('inputMint', inputMint);
params.set('outputMint', outputMint);
params.set('amount', amount);

// Optional params
const slippageBps = searchParams.get('slippageBps');
if (slippageBps) params.set('slippageBps', slippageBps);

const swapMode = searchParams.get('swapMode');
if (swapMode) params.set('swapMode', swapMode);

const dexes = searchParams.get('dexes');
if (dexes) params.set('dexes', dexes);

const excludeDexes = searchParams.get('excludeDexes');
if (excludeDexes) params.set('excludeDexes', excludeDexes);

const restrictIntermediateTokens = searchParams.get('restrictIntermediateTokens');
if (restrictIntermediateTokens) params.set('restrictIntermediateTokens', restrictIntermediateTokens);

const onlyDirectRoutes = searchParams.get('onlyDirectRoutes');
if (onlyDirectRoutes) params.set('onlyDirectRoutes', onlyDirectRoutes);

const asLegacyTransaction = searchParams.get('asLegacyTransaction');
if (asLegacyTransaction) params.set('asLegacyTransaction', asLegacyTransaction);

const platformFeeBps = searchParams.get('platformFeeBps');
if (platformFeeBps) params.set('platformFeeBps', platformFeeBps);

const maxAccounts = searchParams.get('maxAccounts');
if (maxAccounts) params.set('maxAccounts', maxAccounts);

try {
const response = await fetch(`https://lite-api.jup.ag/swap/v1/quote?${params}`, {
headers: {
Accept: 'application/json',
},
const headers: Record<string, string> = {
Accept: 'application/json',
};

// Add API key if available
if (process.env.JUPITER_API_KEY) {
headers['x-api-key'] = process.env.JUPITER_API_KEY;
}

const response = await fetch(`${JUPITER_API_BASE}/quote?${params}`, {
headers,
cache: 'no-store',
});

if (!response.ok) {
throw new Error(`Jupiter API error: ${response.status}`);
const errorText = await response.text();
console.error('Jupiter quote API error:', response.status, errorText);
throw new Error(`Jupiter API error: ${response.status} - ${errorText.substring(0, 200)}`);
}

const data = await response.json();
Expand Down
26 changes: 18 additions & 8 deletions examples/next-js/app/api/jupiter/swap-instructions/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { NextRequest, NextResponse } from 'next/server';

const JUPITER_API_BASE = 'https://api.jup.ag/swap/v1';

/**
* Next.js API route proxy for Jupiter swap-instructions API.
* Proxies requests to Jupiter's swap-instructions API to work around network/DNS restrictions.
* Next.js API route proxy for Jupiter Metis swap-instructions API.
* Proxies requests to Jupiter's swap-instructions API with API key authentication.
*/
export async function POST(request: NextRequest) {
try {
Expand All @@ -17,18 +19,26 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ error: 'Missing required field: userPublicKey' }, { status: 400 });
}

const response = await fetch('https://lite-api.jup.ag/swap/v1/swap-instructions', {
const headers: Record<string, string> = {
'Content-Type': 'application/json',
Accept: 'application/json',
};

// Add API key if available
if (process.env.JUPITER_API_KEY) {
headers['x-api-key'] = process.env.JUPITER_API_KEY;
}

const response = await fetch(`${JUPITER_API_BASE}/swap-instructions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
headers,
cache: 'no-store',
body: JSON.stringify(body),
});

if (!response.ok) {
const errorText = await response.text();
console.error('Jupiter API error response:', response.status, errorText);
console.error('Jupiter swap-instructions API error:', response.status, errorText);
throw new Error(`Jupiter API error: ${response.status} - ${errorText.substring(0, 200)}`);
}

Expand Down
Loading