A collection of DeFi primitives for Solana, starting with Dollar Cost Averaging (DCA) functionality.
MPL DeFi Tools provides on-chain infrastructure for automated trading strategies. The flagship feature is a DCA (Dollar Cost Averaging) program that enables users to automatically execute periodic token purchases via Raydium AMM.
Dollar Cost Averaging is an investment strategy where you invest a fixed amount at regular intervals, regardless of price. This approach:
- Reduces the impact of volatility on your overall purchase
- Removes emotional decision-making from investing
- Allows you to accumulate assets over time without timing the market
- Automated Periodic Swaps: Set up recurring token purchases at configurable intervals (minimum 60 seconds)
- Raydium AMM Integration: Executes swaps through Raydium's AMM for deep liquidity
- Slippage Protection: Configure minimum output amounts to protect against unfavorable prices
- Permissionless Execution: Anyone can "crank" (execute) DCA orders when timing conditions are met
- Crank Incentives: Built-in SOL tip system rewards crankers for executing orders
- Flexible Management: Deposit more funds, withdraw partially, or close positions at any time
- Multiple Positions: Create multiple DCA positions for the same token pair using nonces
-
Create Position: User deposits input tokens (e.g., USDC) and configures:
- Amount per cycle (how much to swap each time)
- Cycle frequency (how often to swap)
- Minimum output amount (slippage protection)
- Crank tip settings (incentive for executors)
-
Automated Execution: When the cycle time arrives, any cranker can execute the swap:
- Swaps
amount_per_cycleof input tokens for output tokens via Raydium - Output tokens are sent directly to the user's wallet
- Cranker receives SOL tip as reward
- Next cycle timestamp is updated
- Swaps
-
Position Management: Users can:
- Deposit more input tokens
- Add more SOL for crank tips
- Withdraw input tokens (partial or full)
- Close the position entirely
| Instruction | Description |
|---|---|
CreateDca |
Create a new DCA position with initial deposit and configuration |
DepositDca |
Add more input tokens to an existing position |
DepositTip |
Add more SOL for crank incentives |
WithdrawDca |
Withdraw input tokens from a position |
ExecuteDca |
Execute a swap cycle (permissionless, called by crankers) |
CloseDca |
Close position and return all remaining funds |
This project contains the following programs:
- MPL DeFi Tools
DEF1eGLKcDDn7cE4quJ3UYBoVaWho3AqUHXszZUQvRYs
Auto-generated clients are available for:
- JavaScript - TypeScript/JavaScript client using Umi framework
- Rust - Native Rust client
- Rust 1.83.0 or compatible
- Solana CLI 2.2.1
- Node.js and pnpm
# Install dependencies
pnpm install
# Build the program
pnpm programs:build
# Generate clients
pnpm generate# Run program tests
pnpm programs:test
# Run JavaScript client tests
pnpm clients:js:test
# Run Rust client tests
pnpm clients:rust:test# Start local validator with program deployed
pnpm validator
# View validator logs
pnpm validator:logs
# Stop validator
pnpm validator:stopEach DCA position is stored in a PDA with the following seeds:
["dca", authority, input_mint, output_mint, nonce]
The nonce allows users to create multiple positions for the same token pair.
| Field | Type | Description |
|---|---|---|
authority |
Pubkey | Owner who can modify/close the position |
input_mint |
Pubkey | Token being sold (e.g., USDC) |
output_mint |
Pubkey | Token being bought |
amount_per_cycle |
u64 | Input tokens swapped per cycle |
cycle_frequency |
i64 | Seconds between swaps |
next_cycle_at |
i64 | Unix timestamp of next execution |
total_deposited |
u64 | Lifetime input token deposits |
total_spent |
u64 | Input tokens spent on swaps |
total_received |
u64 | Output tokens received |
cycles_executed |
u64 | Number of successful swaps |
min_output_amount |
u64 | Slippage protection threshold |
crank_tip_lamports |
u64 | SOL balance for tips |
tip_per_execution |
u64 | SOL paid per crank |
- Only the authority can modify or close a DCA position
- ExecuteDca is permissionless but validates timing and state
- State updates occur before CPI calls to prevent reentrancy
- Slippage protection validates output amounts post-swap
Check out the Contributing Guide to learn more about how to contribute to this project.