Skip to content

Time-locked wallet library for Solana - Lock SOL/SPL tokens with timestamp-based release. Built with Rust/Anchor + TypeScript SDK + React components. πŸ† Superteam Earn Honorable Mention

hayaseta/time-locked-wallet-solana-lib

Repository files navigation

Time-Locked Wallet Solana Library

Build Status License Solana Anchor Superteam Earn

πŸ† Achievement

πŸ₯‰ Honorable Mention - Superteam Earn - Recognized for innovative time-locked wallet solution on Solana blockchain.

A comprehensive Solana library for creating time-locked wallets that allows users to lock SOL or SPL tokens with a predefined unlock timestamp. Perfect for vesting schedules, savings plans, or any time-based asset management.

alt text

🌟 Features

  • πŸ”’ Time-Locked Wallets: Lock SOL or SPL tokens until a specific timestamp
  • ⏰ Flexible Timing: Support for any future timestamp (minutes to years)
  • πŸ›‘οΈ Security: Built with reentrancy protection and comprehensive error handling
  • πŸ”— Solana Native: Full integration with Solana's architecture using Anchor framework
  • πŸ“¦ Developer Friendly: TypeScript SDK with full type safety
  • βš›οΈ React Ready: Pre-built hooks and components for frontend integration
  • πŸ§ͺ Well Tested: Comprehensive test suite for both devnet and localnet

πŸ“ Project Structure

time-locked-wallet-solana-lib/
β”œβ”€β”€ programs/
β”‚   └── time-locked-wallet/     # Rust/Anchor Solana program
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   β”œβ”€β”€ lib.rs          # Main program entry point
β”‚       β”‚   β”œβ”€β”€ state.rs        # Account structures
β”‚       β”‚   β”œβ”€β”€ instructions/   # Program instructions
β”‚       β”‚   β”œβ”€β”€ errors.rs       # Custom error definitions
β”‚       β”‚   └── events.rs       # Event definitions
β”‚       └── Cargo.toml
β”œβ”€β”€ packages/
β”‚   └── core/                   # TypeScript SDK
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   β”œβ”€β”€ client.ts       # Main client for production
β”‚       β”‚   β”œβ”€β”€ client-demo.ts  # Demo client for testing
β”‚       β”‚   β”œβ”€β”€ types.ts        # TypeScript definitions
β”‚       β”‚   β”œβ”€β”€ builders.ts     # Transaction builders
β”‚       β”‚   └── utils/          # Utility functions
β”‚       └── package.json
β”œβ”€β”€ target/
β”‚   β”œβ”€β”€ idl/                    # Generated IDL files
β”‚   └── types/                  # Generated TypeScript types
└── tests/                      # Test suites
    β”œβ”€β”€ localnet-test.ts        # Local development tests
    └── devnet-test.ts          # Devnet integration tests

πŸš€ Quick Start

Prerequisites

  • Node.js: Version 16+ required
  • Rust: Latest stable version
  • Solana CLI: Version 1.14+
  • Anchor CLI: Version 0.28+
  • Git: For cloning the repository

Installation

# Clone the repository
git clone https://github.com/your-org/time-locked-wallet-solana-lib.git
cd time-locked-wallet-solana-lib

# Install dependencies
npm install

# Build the Anchor program
anchor build

# Run tests (requires Solana test validator)
anchor test

πŸ’‘ How It Works

Core Concept

The Time-Locked Wallet uses Program Derived Addresses (PDAs) to create secure, deterministic wallet addresses that can only be unlocked after a specified timestamp. Here's the flow:

  1. Initialize: Create a time-locked wallet with an unlock timestamp
  2. Deposit: Lock SOL or SPL tokens into the wallet
  3. Wait: Funds remain locked until the unlock timestamp
  4. Withdraw: Once unlocked, only the owner can withdraw funds

Key Components

1. Solana Program (programs/time-locked-wallet/)

The on-chain Rust program handles:

  • Wallet initialization with unlock timestamps
  • Secure fund deposits (SOL and SPL tokens)
  • Time-based withdrawal validation
  • PDA-based security model

2. TypeScript SDK (packages/core/)

The client library provides:

  • Easy-to-use JavaScript/TypeScript API
  • Transaction building and signing
  • Account data fetching and parsing
  • Error handling and validation

3. Generated Types (target/types/)

Auto-generated TypeScript definitions from the Anchor IDL for type safety.

πŸ“– Usage Examples

Basic SOL Time-Lock

import { TimeLockClient, AssetType } from '@time-locked-wallet/core';
import { Connection, PublicKey } from '@solana/web3.js';

// Initialize client
const connection = new Connection('https://api.devnet.solana.com');
const client = new TimeLockClient(connection, wallet);

// Create a time-locked wallet (unlock in 1 hour)
const unlockTimestamp = Math.floor(Date.now() / 1000) + 3600;
const result = await client.createSolTimeLock({
  owner: wallet.publicKey,
  unlockTimestamp,
  assetType: AssetType.Sol,
  amount: 1000000000 // 1 SOL in lamports
});

console.log('Time-lock created:', result.timeLockAccount.toString());
console.log('Transaction signature:', result.signature);

Deposit Additional Funds

// Deposit more SOL to existing time-lock
await client.depositSol({
  timeLockAccount: result.timeLockAccount,
  amount: 500000000 // 0.5 SOL in lamports
});

Check Withdrawal Availability

// Check if funds can be withdrawn
const canWithdraw = await client.canWithdraw(result.timeLockAccount);
const remainingTime = await client.getRemainingLockTime(result.timeLockAccount);

console.log('Can withdraw:', canWithdraw);
console.log('Time remaining:', remainingTime, 'seconds');

Withdraw Funds

// Withdraw funds (only works after unlock time)
if (canWithdraw) {
  const signature = await client.withdrawSol({
    timeLockAccount: result.timeLockAccount,
    owner: wallet.publicKey
  });
  console.log('Withdrawal successful:', signature);
}

Working with SPL Tokens

// Create token time-lock
const tokenResult = await client.createTokenTimeLock({
  owner: wallet.publicKey,
  unlockTimestamp: Math.floor(Date.now() / 1000) + 86400, // 24 hours
  assetType: AssetType.Token
});

// Deposit tokens
await client.depositToken({
  timeLockAccount: tokenResult.timeLockAccount,
  amount: 1000000, // Token amount (adjust for decimals)
  tokenFromAta: userTokenAccount,
  tokenVault: vaultAccount,
  tokenProgramId: TOKEN_PROGRAM_ID
});

πŸ”§ Configuration

Program ID

The program is deployed with the following ID:

899SKikn1WiRBSurKhMZyNCNvYmWXVE6hZFYbFim293g

Network Configuration

// Devnet
const connection = new Connection('https://api.devnet.solana.com');

// Mainnet Beta
const connection = new Connection('https://api.mainnet-beta.solana.com');

// Localnet (for development)
const connection = new Connection('http://localhost:8899');

πŸ§ͺ Testing

The project includes a comprehensive testing suite for both development and production environments.

Quick Start

# Local development testing
npm run test:localnet

# Production-like testing  
npm run test:devnet

# Both environments
npm run test:all

# Show all available test commands
npm run test:help

Detailed Testing Documentation

Test Coverage

βœ… Initialize SOL time-locked wallets
βœ… Deposit SOL to time-locked accounts
βœ… Reject early withdrawal (time-lock mechanism)
βœ… Allow withdrawal after unlock time

Performance: 4/4 tests passing in ~11s (localnet) / ~25s (devnet)

Run Local Tests

# Start local Solana test validator
solana-test-validator

# In another terminal, run tests
anchor test --skip-deploy

Run Devnet Tests

# Configure Solana CLI for devnet
solana config set --url https://api.devnet.solana.com

# Run devnet integration tests
npm run test:devnet

πŸ”’ Security Features

Reentrancy Protection

  • Operations are protected against reentrancy attacks
  • Uses a processing flag to prevent concurrent operations

PDA Security

  • All wallets use Program Derived Addresses
  • Deterministic addresses based on owner + timestamp
  • No private key management required

Time Validation

  • Unlock timestamps must be in the future
  • Clock-based validation using Solana's on-chain clock
  • Protection against time manipulation

Error Handling

  • Comprehensive error types and messages
  • Input validation on all parameters
  • Clear error reporting for debugging

πŸ“š API Reference

TimeLockClient Methods

SOL Operations

  • createSolTimeLock(params) - Create new SOL time-lock
  • depositSol(params) - Deposit SOL to existing time-lock
  • withdrawSol(params) - Withdraw SOL (if unlocked)

Token Operations

  • createTokenTimeLock(params) - Create new token time-lock
  • depositToken(params) - Deposit tokens to existing time-lock
  • withdrawToken(params) - Withdraw tokens (if unlocked)

Query Operations

  • getTimeLockData(account) - Get time-lock account data
  • canWithdraw(account) - Check if withdrawal is available
  • getRemainingLockTime(account) - Get seconds until unlock

Utility Methods

  • findTimeLockPDA(owner, timestamp) - Calculate PDA address
  • validatePublicKey(key) - Validate public key format
  • validateTimestamp(timestamp) - Validate timestamp format
  • validateAmount(amount) - Validate amount format

Types

interface CreateTimeLockParams {
  owner: PublicKey;
  unlockTimestamp: number;
  assetType: AssetType;
  amount?: number;
}

interface DepositParams {
  timeLockAccount: PublicKey;
  amount: number;
  depositor?: PublicKey;
}

interface WithdrawParams {
  timeLockAccount: PublicKey;
  owner: PublicKey;
}

enum AssetType {
  Sol = "sol",
  Token = "token"
}

πŸ› Troubleshooting

Common Issues

1. InstructionDidNotDeserialize Error

Error Code: 102
  • Cause: Mismatch between instruction parameters
  • Solution: Ensure you're using the latest version and correct parameter types

2. Custom Program Error: 0x1771

Custom program error: 0x1771 (TimeLockNotExpired)
  • Cause: Attempting to withdraw before unlock time
  • Solution: Wait until unlock timestamp or check canWithdraw()

3. Account Not Found

Error: Account not found
  • Cause: Time-lock account doesn't exist or incorrect PDA calculation
  • Solution: Verify account was created and use correct owner/timestamp

Getting Help

  1. Check the Tests: Look at tests/ directory for working examples
  2. Enable Debug Logs: Use ANCHOR_LOG=debug for detailed logging
  3. Verify Network: Ensure you're connecting to the correct network
  4. Check Balance: Ensure sufficient SOL for transaction fees

🚧 Development

Building from Source

# Clone and setup
git clone <repository-url>
cd time-locked-wallet-solana-lib
npm install

# Build program
anchor build

# Generate types
anchor run test

# Run development server (if using examples)
cd examples/react-vite
npm run dev

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Commit changes: git commit -m 'Add amazing feature'
  4. Push to branch: git push origin feature/amazing-feature
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

  • Built with Anchor Framework
  • Inspired by the Solana ecosystem
  • Thanks to the Solana community for feedback and contributions

About

Time-locked wallet library for Solana - Lock SOL/SPL tokens with timestamp-based release. Built with Rust/Anchor + TypeScript SDK + React components. πŸ† Superteam Earn Honorable Mention

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •