# LoomLay Documentation - Full Content
This file contains the complete text content of all documentation pages.
Use this for comprehensive context when answering questions.
---
# Glossary
> Key terms and definitions
URL: https://docs.loomlay.com/glossary
# Glossary
A reference guide to common terms used throughout the LoomLay platform and documentation.
---
## Blockchain Terms
### SOL
The native token of the Solana blockchain. Used to pay transaction fees and as the primary trading pair for tokens on LoomLay.
### SPL Token
**Solana Program Library Token** - The standard token format on Solana, similar to ERC-20 on Ethereum. All tokens launched on LoomLay are SPL tokens.
### Transaction
An on-chain operation that modifies blockchain state. Examples include transfers, swaps, and token launches. Solana transactions require a small fee paid in SOL.
### Wallet
Software or hardware that stores your private keys and allows you to sign transactions. Popular Solana wallets include Phantom, Solflare, and Backpack.
### Private Key
A secret cryptographic key that proves ownership of a wallet address. Never share your private key or seed phrase with anyone.
### Seed Phrase
A 12 or 24-word recovery phrase that can restore access to a wallet. Also called a mnemonic or recovery phrase.
### Block
A bundle of transactions processed together on the blockchain. Solana produces blocks approximately every 400 milliseconds.
### Confirmation
When a transaction is included in a block and verified by the network. Solana transactions typically confirm in 1-2 seconds.
---
## DeFi Terms
### AMM
**Automated Market Maker** - A system that uses mathematical formulas to set prices and enable trading without traditional order books. Trades execute against a liquidity pool.
### DAMM
**Dynamic Automated Market Maker** - Meteora's implementation of an AMM with dynamic fees and concentrated liquidity. All LoomLay tokens trade on DAMM v2 pools.
### Liquidity Pool
A collection of tokens locked in a smart contract that enables trading. Pools contain two tokens (like SOL and your token) that traders can swap between.
### Liquidity Provider (LP)
Someone who deposits tokens into a liquidity pool. LPs earn a share of trading fees proportional to their contribution.
### Slippage
The difference between the expected price of a trade and the actual executed price. Higher slippage can occur with large trades or low liquidity.
### Price Impact
How much a trade affects the token's price. Large trades relative to pool liquidity cause higher price impact.
### Swap
Exchanging one token for another through a liquidity pool. For example, swapping SOL for USDC.
### DEX
**Decentralized Exchange** - A trading platform that operates without a central authority, using smart contracts to execute trades. Meteora is a Solana DEX.
### TVL
**Total Value Locked** - The total value of assets deposited in a protocol or pool, usually measured in USD.
---
## LoomLay Terms
### Instant Launch
A quick token deployment method that creates a token and liquidity pool in just 2 transactions. No approval needed, and tokens are immediately tradable.
### Curated Launch
A vetted token launch that goes through an application process. Includes a 24-hour funding period and token vesting for participants.
### Alpha Vault
Meteora's mechanism for whitelist-based token sales with built-in vesting. Used for the initial sale phase of curated launches.
### Fee Split
The division of trading fees between the token creator and the LoomLay platform. For instant launches, this is **60% to the creator** and **40% to the platform**.
### Funding Period
The 24-hour window during a curated launch when participants can deposit funds. Deposits outside this window are not accepted.
### Vesting
A schedule that controls when tokens become available. Tokens vest gradually over time rather than all at once.
### Cliff
The initial period of a vesting schedule during which no tokens are released. After the cliff ends, tokens begin unlocking.
### Linear Vesting
A vesting method where tokens unlock at a constant rate over time. For example, 10% per month for 10 months.
### Discovery Feed
The LoomLay interface for browsing and finding tokens. Shows trending tokens, new launches, and top gainers.
---
## Trading Terms
### Market Cap
**Market Capitalization** - The total value of a token's circulating supply, calculated as price multiplied by circulating supply.
### Volume
The total value of trades over a period, typically measured in 24 hours (24h volume).
### Order Book
A list of buy and sell orders at different prices. Note: AMMs like Meteora don't use order books - they use liquidity pools instead.
### Limit Order
An order to buy or sell at a specific price. Not natively supported by AMMs but can be implemented through specialized protocols.
### Market Order
An order to buy or sell immediately at the current market price. All swaps on LoomLay are effectively market orders.
---
## Technical Terms
### RPC
**Remote Procedure Call** - The interface used to communicate with blockchain nodes. RPC endpoints allow applications to read data and submit transactions.
### API
**Application Programming Interface** - A set of rules for how software components interact. The LoomLay API enables programmatic access to platform features.
### SDK
**Software Development Kit** - A collection of tools and code libraries for building applications. The OpenClawWallet SDK enables developers to integrate LoomLay features.
### Smart Contract
Self-executing code deployed on a blockchain. On Solana, these are called "programs." LoomLay uses established Meteora programs rather than custom contracts.
### Mainnet
The primary, production blockchain network where real assets have value. As opposed to testnet or devnet used for development.
### Gas
A term from Ethereum for transaction fees. On Solana, the equivalent is simply called the "transaction fee" and is paid in SOL.
---
# LoomLay Documentation
> Everything you need to build on LoomLay
URL: https://docs.loomlay.com/
# LoomLay Documentation
Welcome to the LoomLay documentation. LoomLay is a Solana-based launchpad platform with an AI-friendly Agent API.
**Build crypto-native applications without managing private keys.** LoomLay provides a complete infrastructure layer for creating wallets, executing trades, and launching tokens - all through a simple REST API.
## What Can You Build?
| Use Case | Description |
|----------|-------------|
| **Trading Bots** | Automated trading strategies with swap and bridge support across Solana and EVM chains |
| **Portfolio Trackers** | Real-time portfolio monitoring with unified balance views across multiple chains |
| **Token Launchers** | Deploy tokens with instant liquidity pools on Meteora in just 2 transactions |
| **AI Agents with Crypto Wallets** | Give your AI agents autonomous crypto capabilities with secure wallet management |
## Quick Start
Install the SDK and create your first wallet:
```bash
npm install @loomlay/openclaw-wallet-sdk
```
```typescript
import { OpenClawWallet } from '@loomlay/openclaw-wallet-sdk';
// Register and get API key
const result = await OpenClawWallet.register();
// Initialize client
const wallet = new OpenClawWallet({ apiKey: result.apiKey });
// Create multi-chain wallet
const created = await wallet.wallet.create();
console.log(created.solana.address); // Solana address
console.log(created.evm.address); // EVM address
```
## What's Here
| Section | Description |
|---------|-------------|
| [SDK Reference](/sdk) | TypeScript SDK for wallets, trading, and token launches |
| [Platform Guide](/platform) | Understanding launches, fees, and discovery |
| [API Reference](/api-reference) | Interactive REST API documentation |
## For AI Agents
This documentation is designed to be AI-friendly:
- **[llms.txt](/llms.txt)** - Structured overview for LLM assistants
- **[llms-full.txt](/llms-full.txt)** - Complete documentation content
- **[OpenAPI Spec](/openapi.json)** - Machine-readable API specification
## Get Started
- New to LoomLay? Start with the [SDK Getting Started](/sdk/getting-started) guide
- Want to launch a token? Read about [Instant Launches](/platform/instant-launches)
- Building an AI agent? Jump to the [API Reference](/api-reference)
---
# Curated Launches
> Vetted token launches with funding periods and vesting
URL: https://docs.loomlay.com/platform/curated-launches
# Curated Launches
Curated launches go through a vetting process and offer structured funding with vesting.
## Launch Phases
1. **Application** - Submit project details for review
2. **Approval** - LoomLay team reviews and approves
3. **Configuration** - Set pricing, allocation, and vesting terms
4. **Funding** - 24-hour period for participants to deposit
5. **Execution** - Pool deployment and token distribution
6. **Vesting** - Tokens released according to schedule
## Timeline Expectations
| Phase | Typical Duration | Notes |
|-------|------------------|-------|
| **Application Review** | 2-5 business days | Depends on completeness of submission |
| **Configuration** | 1-2 days | After approval, set your launch parameters |
| **Funding Period** | 24 hours | Fixed window for participants to deposit |
| **Execution** | Immediate | Automatically triggers after funding closes |
| **Vesting** | Varies | Typically 1-12 months based on your configuration |
The 24-hour funding window is fixed and cannot be extended. Plan your marketing and community outreach accordingly.
## Pool Structure
Curated launches use Meteora's Alpha Vault for the initial sale:
| Component | Purpose |
|-----------|---------|
| **Alpha Vault** | Whitelist-based token sale with vesting |
| **DAMM Pool** | Secondary market liquidity after launch |
## Vesting
Tokens purchased in curated launches vest over time:
- **Cliff** - Initial lock period before any tokens release
- **Linear** - Gradual release after cliff ends
- **Full unlock** - All tokens available
### Example Vesting Schedule
A typical 6-month vesting schedule with a 1-month cliff:
| Time | Tokens Released | Cumulative |
|------|-----------------|------------|
| Day 0 | 0% | 0% |
| Month 1 (cliff) | 20% | 20% |
| Month 2 | 16% | 36% |
| Month 3 | 16% | 52% |
| Month 4 | 16% | 68% |
| Month 5 | 16% | 84% |
| Month 6 | 16% | 100% |
Vesting schedules are locked at launch time and cannot be modified afterward. Choose your schedule carefully based on your tokenomics plan.
## Allocation
Participants receive allocation based on:
- Deposit amount
- Pro-rata distribution if oversubscribed
### Oversubscription Example
If a launch has a $100,000 cap and receives $200,000 in deposits:
- Each participant receives 50% of their requested allocation
- Excess funds are automatically refunded after execution
## What Happens If Funding Target Is Not Met
If the minimum funding threshold is not reached during the 24-hour window:
| Outcome | Description |
|---------|-------------|
| **Launch cancelled** | The curated launch does not proceed |
| **Full refunds** | All deposited funds are returned to participants |
| **No tokens minted** | The token is not created on-chain |
| **Reapplication allowed** | You can submit a new application with adjusted parameters |
Setting a realistic minimum funding target is crucial. Consider your community size and engagement levels when configuring this threshold.
## Requirements
Projects must meet criteria:
- Clear roadmap and documentation
- Team verification (optional doxxing)
- Technical audit (for smart contracts)
- Marketing plan
## Application Tips
To improve your chances of approval:
### Documentation
- Provide a comprehensive whitepaper or project documentation
- Include clear tokenomics with supply breakdown
- Explain your token's utility and use cases
### Team
- Highlight relevant experience of team members
- LinkedIn profiles or verifiable credentials help
- Consider KYC verification for faster approval
### Community
- Show existing community engagement (Discord, Twitter)
- Demonstrate organic growth, not just follower counts
- Include any partnerships or integrations
### Technical
- If your project involves smart contracts, have them audited
- Open-source code repositories are viewed favorably
- Provide testnet deployments if applicable
Applications with incomplete information or unrealistic projections are typically rejected. Be thorough and realistic in your submission.
## Post-Launch Considerations
After a successful curated launch:
- **Liquidity management** - Monitor and potentially add liquidity as trading volume grows
- **Community updates** - Keep participants informed about vesting unlocks
- **Fee claiming** - Claim accumulated trading fees regularly
- **Market making** - Consider active market making to maintain healthy order books
---
# Discovery
> Finding and exploring token launches
URL: https://docs.loomlay.com/platform/discovery
# Discovery
LoomLay provides tools to discover and research token launches.
## Discovery Feed
The main discovery page shows:
- **Trending** - High-volume tokens
- **New** - Recently launched
- **Upcoming** - Curated launches in funding phase
- **Your Portfolio** - Tokens you hold
## Filtering
Filter launches by:
| Filter | Options |
|--------|---------|
| **Type** | Instant, Curated |
| **Status** | Live, Upcoming, Completed |
| **Volume** | Min/max 24h volume |
| **Liquidity** | Min pool liquidity |
## Token Pages
Each token has a dedicated page showing:
- **Chart** - Price and volume history
- **Pool Info** - Liquidity, fees earned
- **Holders** - Top token holders
- **Transactions** - Recent trades
- **Social** - Twitter, Telegram links
## Understanding Token Metrics
When evaluating tokens, pay attention to these key metrics:
### Volume
| Metric | What It Indicates |
|--------|-------------------|
| **24h Volume** | Recent trading activity level |
| **Volume/Liquidity Ratio** | High ratio may indicate active speculation |
| **Volume Trend** | Increasing volume suggests growing interest |
Healthy tokens typically have consistent volume rather than isolated spikes. Look for sustained trading activity over multiple days.
### Liquidity
| Depth | Implication |
|-------|-------------|
| **< $10,000** | High slippage likely on trades over $100 |
| **$10,000 - $100,000** | Moderate liquidity, suitable for smaller trades |
| **> $100,000** | Deep liquidity, can handle larger orders |
### Holders
| Pattern | Interpretation |
|---------|----------------|
| **Top holder > 50%** | High concentration risk |
| **Top 10 holders > 80%** | Limited distribution |
| **Balanced distribution** | Healthier token economics |
High concentration in few wallets increases the risk of large price movements if major holders sell. Check holder distribution before investing.
## Safety Indicators in Token Search
When searching for tokens via the API, the response includes safety indicators:
| Indicator | Description |
|-----------|-------------|
| **Verified** | Token metadata has been validated |
| **Liquidity locked** | Pool liquidity cannot be withdrawn |
| **Mint authority** | Whether new tokens can be minted |
| **Freeze authority** | Whether transfers can be frozen |
### Interpreting Authority Flags
```typescript
const results = await wallet.tokens.search({
query: 'example',
chain: 'solana',
});
// Check safety indicators
results.forEach(token => {
if (token.mintAuthority === null) {
// Supply is fixed - no new tokens can be created
}
if (token.freezeAuthority === null) {
// Transfers cannot be frozen
}
});
```
Tokens with active mint authority can have their supply increased at any time by the authority holder. This is a significant risk factor.
## API Access
Query discovery data via the Agent API:
```typescript
// Get trending tokens
const trending = await wallet.dex.trending({
chain: 'solana',
limit: 10,
});
// Search tokens
const results = await wallet.tokens.search({
query: 'meme',
chain: 'solana',
});
```
## Real-time Updates
Subscribe to live updates via WebSocket:
```typescript
const dexWs = wallet.createDexWebSocket();
await dexWs.connect();
dexWs.subscribe(
{ chain: 'solana', minLiquidity: 10000 },
(pairs) => console.log('Updated pairs:', pairs)
);
```
### How Real-time Updates Work
The WebSocket connection provides:
| Update Type | Frequency | Data Included |
|-------------|-----------|---------------|
| **Price updates** | Every trade | Current price, 24h change |
| **Volume updates** | Aggregated | Rolling 24h volume |
| **New pairs** | As they launch | Full pair metadata |
| **Liquidity changes** | On deposit/withdraw | Updated liquidity depth |
WebSocket subscriptions filter server-side based on your criteria (minimum liquidity, chain, etc.). This reduces bandwidth and processing on your end.
### Connection Management
```typescript
// Handle disconnections gracefully
dexWs.on('disconnect', () => {
console.log('Disconnected, attempting reconnect...');
});
dexWs.on('reconnect', () => {
// Resubscribe after reconnection
dexWs.subscribe(
{ chain: 'solana', minLiquidity: 10000 },
handlePairs
);
});
// Clean up when done
dexWs.disconnect();
```
## Best Practices for Discovery
1. **Combine filters** - Use multiple criteria to narrow down quality tokens
2. **Check history** - Look at trading patterns over days, not just hours
3. **Verify socials** - Check that linked social accounts are active and legitimate
4. **Monitor changes** - Use WebSocket subscriptions to track tokens you're interested in
5. **Research the team** - For curated launches, review the project's application materials
---
# FAQ
> Frequently asked questions about the LoomLay platform
URL: https://docs.loomlay.com/platform/faq
# Frequently Asked Questions
## Launches
### What's the difference between Instant and Curated launches?
**Instant launches** let you deploy a token immediately with just 2 transactions. No approval is needed, and your token is tradable as soon as the transactions confirm. Best for quick launches, memecoins, and community tokens.
**Curated launches** go through an application and approval process. They include a 24-hour funding period and vesting schedules. Best for serious projects looking for structured funding and credibility.
| Feature | Instant | Curated |
|---------|---------|---------|
| Approval needed | No | Yes |
| Time to launch | Minutes | Days to weeks |
| Funding period | None | 24 hours |
| Vesting | No | Yes |
| Best for | Quick launches | Larger projects |
### How long does the funding period last for Curated launches?
The funding period is exactly **24 hours**. During this window, participants can deposit funds to participate in the launch. After the period ends, no additional deposits are accepted.
### What happens if a Curated launch doesn't reach its funding target?
If a curated launch doesn't reach its minimum funding target:
- All deposited funds are returned to participants
- The launch is cancelled
- Participants can claim their refunds through the platform
### Can I launch more than one token?
**Instant launches**: Yes, you can launch multiple tokens from the same wallet.
**API/SDK launches**: Limited to one token per API key account.
### What information do I need to launch a token?
For an instant launch, you need:
- Token name and symbol
- Description
- Token image (square, minimum 400x400px)
- Total supply amount
- Initial liquidity amount (in SOL)
---
## Fees
### How does the 60/40 fee split work?
For instant launches, trading fees from the Meteora pool are split:
| Recipient | Share |
|-----------|-------|
| Token Creator | 60% |
| LoomLay Platform | 40% |
Fees accumulate from every swap on your token's pool and can be claimed at any time.
### How do I claim my fees as a token creator?
You can claim fees through:
1. **Platform Dashboard**: Navigate to your dashboard, view pending fees, and click "Claim"
2. **SDK/API**: Use the fees endpoint to check pending amounts and claim
Fees are paid out in SOL to the wallet that created the token.
### Are there upfront fees for launching?
**Instant launches**: Yes, there's a platform fee paid during the launch transaction. The exact amount depends on your configuration.
**Curated launches**: Fees are negotiated during the application process and may include listing fees and success fees based on funds raised.
### When do fees start accumulating?
Fees begin accumulating as soon as trading starts on your token's pool. For instant launches, this is immediately after the launch transactions confirm.
---
## Trading
### Where does liquidity come from?
All LoomLay tokens trade on **Meteora DAMM v2** pools on Solana. Liquidity is provided by:
- Initial liquidity from the token creator (instant launches)
- Funds raised during the funding period (curated launches)
- Additional liquidity providers who add to the pool
### Is my token immediately tradable after an Instant launch?
Yes. As soon as both launch transactions confirm on Solana (typically within seconds), your token is live and tradable on Meteora DEX.
### What is slippage and how do I set it?
Slippage is the difference between the expected price and the actual execution price. Higher trading volume or lower liquidity can cause more slippage.
- **Recommended**: 0.5-1% for most trades
- **High volatility**: 2-5% may be needed
- **Low liquidity tokens**: May require higher slippage
### Can I trade LoomLay tokens on other platforms?
Yes. Since all tokens use standard SPL token accounts and Meteora pools, you can trade them on:
- Meteora DEX directly
- Jupiter aggregator
- Any Solana DEX that routes through Meteora
---
## Wallets and Security
### Which wallets are supported?
LoomLay supports all major Solana wallets:
- Phantom
- Solflare
- Backpack
- Ledger (via Phantom or Solflare)
### Is my wallet safe when connecting to LoomLay?
LoomLay uses standard Solana wallet adapter connections. We never have access to your private keys or seed phrase. Each transaction requires your explicit approval in your wallet.
### What happens if I lose access to my wallet?
LoomLay cannot recover wallet access. If you lose access to your wallet:
- Holdings remain on-chain and are recoverable with your seed phrase
- Fee claims are tied to the creator wallet address
- Contact your wallet provider's support for recovery options
---
## Vesting (Curated Launches)
### How does vesting work?
Tokens purchased in curated launches are released gradually:
1. **Cliff**: Initial period where no tokens are released
2. **Linear vesting**: Tokens unlock progressively after the cliff
3. **Full unlock**: All remaining tokens become available
### Can I trade vested tokens before they unlock?
No. Tokens remain locked until they vest according to the schedule. Once unlocked, they're transferred to your wallet and can be traded freely.
### Where do I see my vesting schedule?
Check your dashboard under **Holdings** to see:
- Total tokens allocated
- Tokens already unlocked
- Next unlock date and amount
- Full vesting schedule
---
## Technical
### What blockchain does LoomLay use?
LoomLay is built on **Solana**. All tokens are SPL tokens, and all liquidity pools use Meteora DAMM v2.
### What is Meteora DAMM v2?
Meteora's Dynamic Automated Market Maker (DAMM) v2 is a liquidity pool implementation that offers:
- Concentrated liquidity for better price execution
- Dynamic fees that adjust to market conditions
- Single-sided deposits for token launches
### How fast are transactions?
Solana transactions typically confirm in **1-2 seconds**. You'll see your trades and launches execute almost instantly.
### What are the transaction fees?
Solana network fees are minimal (typically less than $0.01 per transaction). LoomLay platform fees are separate and vary by launch type.
---
# Fees
> Understanding LoomLay's fee structure
URL: https://docs.loomlay.com/platform/fees
# Fees
## Fee Structure
### Instant Launches
| Fee Type | Amount | Split |
|----------|--------|-------|
| Platform Fee | Variable | 40% platform, 60% creator |
| Trading Fee | 1% | From pool swaps |
### Curated Launches
| Fee Type | Amount | Description |
|----------|--------|-------------|
| Listing Fee | Negotiated | One-time fee for launch |
| Success Fee | % of raise | Percentage of funds raised |
## Fee Claiming
Creators can claim fees through the platform or API:
```typescript
// Check pending fees
const pending = await wallet.fees.getPending();
// Claim all pending fees
const claim = await wallet.fees.claim();
```
---
# Getting Started
> Start using the LoomLay platform
URL: https://docs.loomlay.com/platform/getting-started
# Getting Started
This guide helps you get started with the LoomLay web platform. If you're a developer looking to integrate with the SDK, see the [SDK Getting Started](/sdk/getting-started) guide instead.
## Connect Your Wallet
To use LoomLay, you need a Solana wallet.
### Supported Wallets
| Wallet | Platform | Notes |
|--------|----------|-------|
| **Phantom** | Browser, Mobile | Most popular Solana wallet |
| **Solflare** | Browser, Mobile | Feature-rich with staking |
| **Backpack** | Browser | Multi-chain support |
| **Ledger** | Hardware | Connect via Phantom or Solflare |
### How to Connect
1. Click **Connect Wallet** in the top navigation
2. Select your wallet from the list
3. Approve the connection in your wallet
4. Your wallet address will appear in the navigation
Make sure you have some SOL in your wallet for transaction fees before participating in launches.
## Explore Tokens
LoomLay's discovery feed helps you find tokens launched on the platform.
### Using the Discovery Feed
- **Trending** - Tokens with the highest recent trading volume
- **New** - Recently launched tokens
- **Gainers** - Tokens with the largest price increases
### Understanding Token Metrics
| Metric | Description |
|--------|-------------|
| **Market Cap** | Total value of circulating supply |
| **24h Volume** | Trading volume in the last 24 hours |
| **Liquidity** | Amount of assets in the trading pool |
| **Price Change** | Percentage change over selected period |
### Finding New Launches
- Check the **Upcoming** section for curated launches accepting deposits
- Browse **Recently Launched** for the newest instant launches
- Use filters to narrow by date, volume, or price change
## Participate in Launches
### Instant Launches
Instant launches are immediately tradable:
1. Find a token on the discovery page
2. Click **Trade** to open the swap interface
3. Enter the amount of SOL to swap
4. Review the transaction details and confirm
5. Approve the transaction in your wallet
### Curated Launches
Curated launches have a structured funding period:
1. Find an upcoming curated launch
2. Review the project details, vesting schedule, and terms
3. Click **Deposit** during the 24-hour funding window
4. Enter your deposit amount
5. Confirm the transaction in your wallet
6. Receive tokens according to the vesting schedule after launch
Curated launches have a fixed 24-hour funding period. Deposits made outside this window are not accepted.
## Launch Your Own Token
### Instant Launch
Deploy a token in seconds:
1. Click **Launch** in the navigation
2. Select **Instant Launch**
3. Fill in token details:
- Name and symbol
- Description and image
- Initial liquidity amount (in SOL)
- Total supply
4. Review the fees and confirm
5. Approve two transactions in your wallet
6. Your token is live and tradable immediately
### Curated Launch Application
For larger projects seeking vetting and structured funding:
1. Click **Launch** in the navigation
2. Select **Apply for Curated Launch**
3. Complete the application:
- Project overview and roadmap
- Team information
- Tokenomics and allocation
- Funding goals
4. Submit for review
5. The LoomLay team will contact you with next steps
## Dashboard
After launching a token or participating in launches, use your dashboard to:
- **View Holdings** - See tokens you've purchased
- **Track Launches** - Monitor your launched tokens
- **Claim Fees** - Collect your share of trading fees (for creators)
- **Vesting Schedule** - Track upcoming token unlocks
## Next Steps
- [Instant Launches](/platform/instant-launches) - Deep dive into instant launches
- [Curated Launches](/platform/curated-launches) - Learn about vetted launches
- [Fees](/platform/fees) - Understand the fee structure
- [Discovery](/platform/discovery) - Explore the token discovery feed
- [FAQ](/platform/faq) - Common questions answered
---
# Platform Overview
> Launch tokens and participate in token sales on Solana
URL: https://docs.loomlay.com/platform
# Platform Overview
LoomLay is a Solana-based launchpad that offers two ways to launch tokens, both powered by Meteora's battle-tested liquidity infrastructure.
## Why LoomLay?
- **No smart contract development** - Launch tokens using established Meteora pools without writing or auditing custom programs
- **Instant liquidity** - Tokens are immediately tradable on Meteora DEX after launch
- **Built-in fee sharing** - Earn from trading volume on your token's pool
- **AI-agent ready** - Full API access for automated launches and trading
## Launch Types
| Type | Speed | Pool | Best For |
|------|-------|------|----------|
| **Instant** | 2 transactions | Single-sided DAMM | Quick launches, memecoins |
| **Curated** | 24h funding period | Alpha Vault + DAMM | Serious projects, larger raises |
## How It Works
**Instant Launch** - Deploy a token and liquidity pool in seconds. No approval needed. Pay fees upfront and your token is immediately tradable on Meteora.
**Curated Launch** - Go through a vetting process with structured funding and vesting. Apply, get approved, configure your sale, and launch with whitelist-based allocation.
## Meteora DAMM v2
All LoomLay tokens trade on Meteora's Dynamic Automated Market Maker (DAMM) v2 pools:
| Feature | Benefit |
|---------|---------|
| **Concentrated liquidity** | Better price execution with less capital |
| **Dynamic fees** | Fees adjust based on market volatility |
| **Single-sided deposits** | Launch with just SOL - no need to pre-mint tokens |
| **Built-in analytics** | Track volume, fees, and liquidity in real-time |
Meteora DAMM pools are the same infrastructure used by major Solana projects. Your token benefits from Meteora's established ecosystem and trading interfaces.
## Key Features
| Feature | Description |
|---------|-------------|
| **Meteora Integration** | All pools deployed on Meteora DAMM v2 |
| **Fee Sharing** | 60/40 creator/platform split on instant launches |
| **Automated Market Making** | Liquidity managed by battle-tested Meteora contracts |
| **Multi-chain Wallets** | Trade across Solana and EVM chains via the Agent API |
## Quick Links
- [Getting Started](/platform/getting-started) - Connect your wallet and start using the platform
- [Instant Launches](/platform/instant-launches) - Deploy in seconds
- [Curated Launches](/platform/curated-launches) - Vetted launches with vesting
- [Fees](/platform/fees) - Fee structure
- [Discovery](/platform/discovery) - Find and explore launches
- [FAQ](/platform/faq) - Frequently asked questions
---
# Instant Launches
> Deploy a token and liquidity pool in seconds
URL: https://docs.loomlay.com/platform/instant-launches
# Instant Launches
Instant launches let you deploy a token and liquidity pool in just 2 transactions.
## How It Works
1. **Configure** - Set token name, symbol, supply, and initial liquidity
2. **Pay Fees** - Platform fee collected upfront
3. **Deploy** - Two transactions create token and pool
4. **Trade** - Immediately tradable on Meteora
## The Two Transactions
When you execute an instant launch, two on-chain transactions are submitted:
### Transaction 1: Token Creation
- Creates the SPL token with your specified supply
- Sets token metadata (name, symbol, image URI)
- Mints the total supply to a holding account
- Establishes the token's mint authority
### Transaction 2: Pool Deployment
- Creates a Meteora DAMM v2 pool
- Deposits your SOL as initial liquidity
- Adds tokens to the pool at the configured ratio
- Enables trading immediately upon confirmation
Both transactions must succeed for the launch to complete. If the first transaction succeeds but the second fails, no pool is created and no funds are locked.
## SOL Requirements
Before launching, ensure your wallet has sufficient SOL:
| Cost | Amount | Purpose |
|------|--------|---------|
| **Initial Liquidity** | Your chosen amount | Deposited into the pool |
| **Transaction Fees** | ~0.01 SOL | Solana network fees |
| **Account Rent** | ~0.03 SOL | Token and pool account creation |
| **Platform Fee** | Varies | See [Fees](/platform/fees) |
We recommend having at least your liquidity amount plus 0.05 SOL to cover all fees and account creation costs.
## What You Get After Launch
After a successful launch, you receive:
| Output | Description |
|--------|-------------|
| **Token Address** | The SPL token mint address for your new token |
| **Pool Address** | The Meteora DAMM pool where your token trades |
| **Trading URL** | Direct link to trade on Meteora |
Your token is immediately:
- Tradable on Meteora DEX
- Visible on Solana explorers (Solscan, SolanaFM)
- Discoverable via the LoomLay discovery feed
- Generating trading fees for you to claim
## Fee Structure
Instant launches use a 60/40 fee split:
| Recipient | Share | Description |
|-----------|-------|-------------|
| Creator | 60% | Token creator revenue |
| Platform | 40% | LoomLay platform fee |
Fees are collected from trading volume on the pool.
## Code Example
```typescript
// Using the Agent API to create an instant launch
const launch = await wallet.tokenize.launch({
name: 'My Token',
symbol: 'MTK',
description: 'A sample token',
initialLiquidity: '10', // SOL
supply: '1000000000',
});
console.log('Token address:', launch.tokenAddress);
console.log('Pool address:', launch.poolAddress);
```
## Requirements
- Wallet with sufficient SOL for fees and liquidity
- Unique token name and symbol
- Valid token metadata (image, description)
## Fee Claiming
Creators can claim accumulated fees at any time:
```typescript
const fees = await wallet.fees.getPending();
console.log('Pending fees:', fees.pendingAmount);
const claim = await wallet.fees.claim();
console.log('Claimed:', claim.claimedAmount);
```
## Common Issues
### "Insufficient balance"
Your wallet does not have enough SOL. Ensure you have your liquidity amount plus at least 0.05 SOL for fees.
### "Transaction simulation failed"
This usually indicates a network congestion issue. Wait a few seconds and retry the launch.
### "Token name already exists"
Choose a different token name. While symbols can be reused, having a unique name helps with discoverability.
### "Metadata upload failed"
Check that your image URL is accessible and returns a valid image. IPFS and Arweave links are recommended for permanence.
Instant launches cannot be reversed. Once deployed, the token and pool exist permanently on Solana. Double-check all parameters before confirming.
---
# AI Agent Best Practices
> Guidelines for building safe and effective AI agents with the OpenClaw Wallet SDK
URL: https://docs.loomlay.com/sdk/ai-agent-guide
# AI Agent Best Practices
This guide covers best practices for developers building AI agents that interact with wallets, execute trades, and manage digital assets using the OpenClaw Wallet SDK.
## Introduction
AI agents operating with real financial assets require careful design. Unlike traditional software, agents make autonomous decisions that can result in irreversible transactions. This guide establishes patterns for building agents that are:
- **Safe** - Verify before executing, handle errors gracefully
- **Transparent** - Explain actions in plain language
- **Deliberate** - Require confirmation for significant operations
- **Secure** - Protect credentials and never expose sensitive data
## Core Workflow
Every agent operation should follow this six-phase workflow:
```
1. AUTHENTICATE → 2. UNDERSTAND → 3. VALIDATE → 4. EXECUTE → 5. VERIFY → 6. DOCUMENT
│ │ │ │ │ │
│ │ │ │ │ └─ Summarize result
│ │ │ │ └─ Confirm success
│ │ │ └─ Execute with user approval
│ │ └─ Get quotes, check balances
│ └─ Clarify what user wants
└─ Ensure API key is configured
```
### Phase 1: Authenticate
Before any operation, verify you have a valid API key and wallet access:
```typescript
import { OpenClawWallet } from '@loomlay/openclaw-wallet-sdk';
// Self-custody mode (recommended) — keys stay on your device
const client = new OpenClawWallet({
apiKey: process.env.LOOMLAY_API_KEY,
walletMode: 'local',
getPassphrase: async () => process.env.LOOMLAY_WALLET_PASSPHRASE!,
});
```
If no API key exists, register for one (rate limited to 1 per IP):
```typescript
const { apiKey } = await OpenClawWallet.register();
// Store this securely - it's your identity
```
In self-custody mode, the agent needs a passphrase to sign transactions. Set `LOOMLAY_WALLET_PASSPHRASE` as an environment variable so it doesn't appear in conversation logs.
### Phase 2: Understand
Clarify user intent before taking action:
**For trading requests:**
- Which tokens? (resolve names to addresses if needed)
- How much? (decimal, USD, percentage, or max?)
- Which chain? (Solana by default, or EVM chains)
**For research requests:**
- What metric matters? (volume, price change, liquidity)
- What timeframe? (5m, 1h, 6h, 24h)
- What filters? (minimum liquidity, safety score)
### Phase 3: Validate
Always validate before executing:
```typescript
// Get a quote first
const quote = await client.trading.getSwapQuote({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '$100'
});
// Show the user what they'll receive
// "You'll swap ~1.2 SOL for ~$99.50 USDC (0.5% price impact)"
```
### Phase 4: Execute
Only execute after user confirmation:
```typescript
const result = await client.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '$100'
});
```
### Phase 5: Verify
Confirm the result:
```typescript
const wallet = await client.wallet.get();
// Check new balance reflects the expected change
```
### Phase 6: Document
Summarize what happened:
- What was executed
- Transaction hash (if applicable)
- New balances
- Any follow-up actions needed
## Security Guidelines
### Self-Custody Security
In self-custody mode, the agent handles real cryptographic operations locally:
**Critical Security Rules:**
- **Seed phrase shown once** - `wallet.create()` returns the seed phrase exactly once
- **Never log secrets** - Do not include seed phrases, passphrases, or private keys in output
- **Passphrase via env var** - Use `LOOMLAY_WALLET_PASSPHRASE` to avoid conversation logs
- **Keys never transmitted** - Only public addresses and signed transactions leave the device
```typescript
// Self-custody wallet creation
const { seedPhrase, wallet } = await client.wallet.create();
// Tell user: "Your seed phrase is shown once. Store it securely offline."
// Tell user: "Your keys are encrypted on this device at ~/.loomlay/wallet.json"
// NEVER do this:
// - console.log(seedPhrase)
// - store in database
// - send to analytics
// - include in error reports
```
### Seed Phrase Handling
The seed phrase is the master key to all funds. Handle with extreme care:
When users create a wallet, guide them:
```
Your seed phrase (SAVE THIS NOW):
word1 word2 word3 word4 word5 word6
word7 word8 word9 word10 word11 word12
This phrase is your master key to all funds.
- Write it down on paper
- Store in a secure location
- Never share with anyone
- If lost, funds are unrecoverable
```
### Transaction Safety
1. **Always quote first** - Never execute without showing expected outcome
2. **Verify addresses** - Transfers are irreversible
3. **Check slippage** - High price impact indicates a bad trade
4. **Confirm large amounts** - Extra verification for significant value
```typescript
// Get quote with price impact
const quote = await client.trading.getSwapQuote({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '100',
});
// Warn on high price impact
if (quote.priceImpact > 2) {
// "Warning: 3.5% price impact. Consider a smaller trade."
}
// Only execute after user confirms
const result = await client.trading.swap({...});
```
### API Key Security
**API Key Best Practices:**
- Store in environment variables, never hardcode
- One key per agent/application
- Revoke immediately if compromised
```typescript
// Good: Load from environment
const client = new OpenClawWallet({
apiKey: process.env.LOOMLAY_API_KEY!,
});
// Bad: Hardcoded key
const client = new OpenClawWallet({
apiKey: 'agent_abc123...', // Never do this!
});
```
## Quality Gate Checklist
Before executing any transaction, verify these conditions:
### Safety Checks
- [ ] User explicitly requested this action
- [ ] Quote shown and confirmed for trades
- [ ] Address validated for transfers
- [ ] Sufficient balance confirmed
- [ ] Slippage/price impact acceptable
### Information Provided
- [ ] Expected outcome explained
- [ ] Fees/costs disclosed
- [ ] Risks mentioned if applicable
- [ ] Transaction hash provided after execution
### Never Do
- [ ] Execute without user confirmation
- [ ] Log or display seed phrases
- [ ] Assume token addresses (search first)
- [ ] Ignore error responses
- [ ] Skip quote step for trades
## Standardized Response Format
All SDK operations return a consistent response format for predictable error handling:
```typescript
interface ToolResponse {
success: boolean;
data?: T;
error?: {
message: string;
code?: string;
retryAfter?: number;
};
}
```
### Success Response
```typescript
{
success: true,
data: {
txHash: "abc123...",
outputAmount: "99.50",
// ... operation-specific data
}
}
```
### Error Response
```typescript
{
success: false,
error: {
message: "Rate limited. Retry after 30 seconds.",
code: "RATE_LIMITED",
retryAfter: 30
}
}
```
### Using the Response Format
```typescript
import { executeTool } from '@loomlay/openclaw-wallet-sdk';
const response = await executeTool(() => client.trading.swap(params));
if (response.success) {
// Handle success
console.log('Swap completed:', response.data);
} else {
// Handle error
console.log('Swap failed:', response.error?.message);
}
```
## Error Handling Patterns
### Error Types
```typescript
import {
RateLimitError,
ApiError,
NetworkError,
TimeoutError,
ValidationError,
} from '@loomlay/openclaw-wallet-sdk';
```
### Recovery Strategies
| Error Type | Retry? | Strategy |
|------------|--------|----------|
| `RateLimitError` | Yes | Wait for `retryAfter` seconds, then retry |
| `NetworkError` | Yes | Exponential backoff (1s, 2s, 4s), max 3 attempts |
| `TimeoutError` | Maybe | Check operation status first, retry if not confirmed |
| `ApiError` (4xx) | No | Fix input parameters before retrying |
| `ApiError` (5xx) | Yes | Retry with exponential backoff |
| `ValidationError` | No | Fix validation issues before retrying |
### Rate Limit Handling
```typescript
async function withRateLimitRetry(fn: () => Promise): Promise {
try {
return await fn();
} catch (error) {
if (error instanceof RateLimitError && error.retryAfter) {
console.log(`Rate limited. Waiting ${error.retryAfter}s...`);
await sleep(error.retryAfter * 1000);
return await fn();
}
throw error;
}
}
```
### Exponential Backoff
```typescript
async function withExponentialBackoff(
fn: () => Promise,
maxAttempts = 3,
baseDelayMs = 1000
): Promise {
let lastError: Error;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error as Error;
if (error instanceof ApiError && error.status < 500) {
throw error; // Don't retry client errors
}
if (attempt < maxAttempts - 1) {
const delay = baseDelayMs * Math.pow(2, attempt);
await sleep(delay);
}
}
}
throw lastError!;
}
```
### Transaction Safety Pattern
For operations that might be partially complete:
```typescript
async function safeSwap(params: SwapParams) {
// 1. Get quote first
const quote = await client.trading.getSwapQuote(params);
// 2. Confirm with user
if (!userConfirms(quote)) return null;
try {
// 3. Execute
return await client.trading.swap(params);
} catch (error) {
if (error instanceof TimeoutError) {
// Transaction might have succeeded - check balance
const wallet = await client.wallet.get();
return { status: 'unknown', wallet };
}
throw error;
}
}
```
### User-Friendly Error Messages
Transform technical errors into understandable messages:
```typescript
function getUserMessage(error: unknown): string {
if (error instanceof RateLimitError) {
return `Too many requests. Please wait ${error.retryAfter} seconds.`;
}
if (error instanceof ApiError) {
switch (error.code) {
case 'UNAUTHORIZED':
return 'Authentication failed. Please check your API key.';
case 'INSUFFICIENT_FUNDS':
return 'Not enough balance to complete this transaction.';
case 'SLIPPAGE_EXCEEDED':
return 'Price moved too much. Try again with higher slippage.';
default:
return error.message;
}
}
if (error instanceof NetworkError) {
return 'Network connection failed. Please check your internet.';
}
return 'An unexpected error occurred.';
}
```
## Skill Documentation Structure
The SDK includes a skill system for AI agents, organized as follows:
### Main Skill File
`SKILL.md` - The primary instruction file containing:
- Agent philosophy and approach
- Core workflow phases
- Security guidelines
- Quick reference tables
- Quality gate checklist
### Reference Guides
Detailed documentation for specific capabilities:
| Reference | Description |
|-----------|-------------|
| `wallet-operations.md` | Wallet creation, security, key export |
| `trading-guide.md` | Swaps, transfers, bridges with amount formats |
| `market-analysis.md` | DEX data, trending tokens, filtering |
| `token-launch.md` | Tokenize workflow, tiers, fee structure |
| `error-handling.md` | Error types, recovery patterns, retries |
| `amount-formats.md` | Flexible amounts (decimal, USD, %, max) |
| `chain-reference.md` | Supported chains and behaviors |
### Workflow Playbooks
Step-by-step guides for common scenarios:
| Workflow | Description |
|----------|-------------|
| `first-time-setup.md` | Registration, wallet creation, first trade |
| `token-launch-playbook.md` | Complete token launch guide |
## Amount Formats
The SDK supports flexible amount specifications:
| Format | Example | Use Case |
|--------|---------|----------|
| Decimal | `"1.5"` | Exact amount |
| USD | `"$100"` | Dollar value (auto-converts) |
| Percentage | `"50%"` | Half of balance |
| Max | `"max"` | Entire balance |
```typescript
// All valid:
await client.trading.swap({ amount: '1.5', ... }); // 1.5 tokens
await client.trading.swap({ amount: '$100', ... }); // $100 worth
await client.trading.swap({ amount: '50%', ... }); // Half balance
await client.trading.swap({ amount: 'max', ... }); // Full balance
```
## Best Practices Summary
1. **Verify before executing** - Always get quotes and show expected outcomes
2. **Explain in plain language** - Users should understand what's happening
3. **Surface relevant data** - Provide market context for informed decisions
4. **Handle errors gracefully** - Clear recovery paths for all failures
5. **Protect sensitive data** - Never expose seed phrases or API keys
6. **Confirm significant actions** - Extra verification for large transactions
7. **Document outcomes** - Summarize results with transaction details
## Related Documentation
- [Getting Started](/sdk/getting-started) - Set up the SDK
- [Security Best Practices](/sdk/security) - Detailed security guidelines
- [Error Handling](/sdk/error-handling) - Complete error reference
- [Trading](/sdk/trading) - Swaps, transfers, and bridges
- [Tokenize](/sdk/tokenize) - Launch your own token
---
# Amount Formats
> Flexible amount input formats for swaps, transfers, and bridges
URL: https://docs.loomlay.com/sdk/amount-formats
# Amount Formats
The SDK supports multiple amount formats for intuitive trading. Instead of always specifying exact token amounts, you can use USD values, percentages, or max/all keywords.
## Overview
| Format | Example | Description |
|--------|---------|-------------|
| Decimal | `"1.5"` | Exact token amount |
| USD | `"$100"` or `"100usd"` | Dollar value at current price |
| Percentage | `"50%"` | Percentage of wallet balance |
| Max | `"max"` or `"all"` | Entire available balance |
## Decimal Amounts
The most precise format - specify exactly how many tokens to use.
```typescript
// Swap exactly 1.5 SOL
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '1.5',
});
// Transfer exactly 0.01 ETH
await wallet.trading.transfer({
to: '0x...',
token: 'ETH',
amount: '0.01',
chain: 'ethereum',
});
```
### Precision Notes
- Respects token decimals (SOL: 9, USDC: 6, ETH: 18)
- Excess precision is truncated, not rounded
- Always use strings to avoid floating-point issues
```typescript
// Good - use strings
amount: '0.123456789'
// Avoid - numbers may lose precision
amount: 0.123456789
```
## USD Amounts
Specify value in US dollars - automatically converted at the current market price.
```typescript
// Swap $100 worth of SOL
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '$100',
});
// Alternative suffix format
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '100usd',
});
```
### How USD Conversion Works
1. Fetch current token price from market data
2. Calculate token amount: `tokenAmount = usdAmount / price`
3. Execute with the calculated token amount
```
User request: "$100 of SOL"
SOL price: $150
Calculation: $100 / $150 = 0.667 SOL
Executed: Swap 0.667 SOL
```
### USD Format Variants
All of these are equivalent:
- `"$100"` - Dollar sign prefix
- `"$100.00"` - With cents
- `"100usd"` - Lowercase suffix
- `"100USD"` - Uppercase suffix
**Price Volatility:** USD amounts convert at the moment of execution. For volatile tokens, the actual token amount may differ from what you expect. Use `quoteOnly: true` to preview the conversion before executing.
## Percentage Amounts
Swap or transfer a percentage of your current balance.
```typescript
// Swap half of SOL balance
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '50%',
});
// Transfer 25% of USDC holdings
await wallet.trading.transfer({
to: 'recipient_address',
token: 'USDC',
amount: '25%',
chain: 'solana',
});
```
### How Percentage Works
1. Fetch current balance of the input token
2. Calculate amount: `amount = balance * (percentage / 100)`
3. Execute with the calculated amount
```
User request: "50% of SOL"
SOL balance: 10 SOL
Calculation: 10 x 0.5 = 5 SOL
Executed: Swap 5 SOL
```
### Percentage Considerations
- Based on balance at execution time
- For native tokens (SOL/ETH), a gas buffer is reserved
- `"100%"` is equivalent to `"max"`
## Max/All Amounts
Swap or transfer your entire balance of a token.
```typescript
// Swap all SOL
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: 'max',
});
// Alternative keyword
await wallet.trading.swap({
inputToken: 'BONK',
outputToken: 'SOL',
amount: 'all',
});
```
### Gas Buffer for Native Tokens
When using "max" with native tokens (SOL, ETH), a small buffer is reserved for transaction fees:
| Chain | Native Token | Gas Buffer |
|-------|--------------|------------|
| Solana | SOL | ~0.001 SOL |
| Ethereum | ETH | ~0.01 ETH |
| Base | ETH | ~0.001 ETH |
| Arbitrum | ETH | ~0.001 ETH |
For non-native tokens (USDC, BONK, etc.), "max" uses the full balance with no buffer.
### Max Format Variants
All of these are equivalent:
- `"max"` - Lowercase
- `"MAX"` - Uppercase
- `"all"` - Alternative keyword
- `"ALL"` - Uppercase alternative
## Endpoint Support
| Endpoint | Decimal | USD | Percentage | Max |
|----------|---------|-----|------------|-----|
| `trading.swap()` | Yes | Yes | Yes | Yes |
| `trading.transfer()` | Yes | Yes | Yes | Yes |
| `trading.bridge()` | Yes | Yes | Yes | Yes |
| Quote operations | Yes | Yes | Yes | Yes |
All trading operations support all amount formats.
## Edge Cases and Considerations
### Dust Amounts
Very small amounts may fail due to minimum transaction requirements:
```typescript
// May fail - amount too small
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '0.000001', // Dust amount
});
```
Different DEXes have different minimum trade sizes. Jupiter on Solana typically requires at least ~$0.01 worth of tokens.
### Rounding Behavior
- Amounts are truncated to the token's decimal precision, not rounded
- For example, `"1.123456789123"` SOL becomes `"1.123456789"` (9 decimals)
- USD conversions may result in slight differences from the requested dollar amount
### Insufficient Balance
If the calculated amount exceeds your balance:
```typescript
// Balance: 5 SOL, requesting $1000 worth
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '$1000', // More than balance
});
// Throws InsufficientFundsError
```
## Format Selection Guide
| Scenario | Recommended Format | Example |
|----------|-------------------|---------|
| Precise trade amount | Decimal | `"1.5"` |
| "I want to spend $100" | USD | `"$100"` |
| "Sell half my position" | Percentage | `"50%"` |
| "Exit entire position" | Max | `"max"` |
| DCA fixed dollar amount | USD | `"$50"` |
| Portfolio rebalancing | Percentage | `"25%"` |
## Best Practices
### Always Preview with Quotes
Get a quote first to see the actual amounts before executing:
```typescript
// Preview the swap
const quote = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '$100',
quoteOnly: true,
});
console.log(`Will swap ${quote.inputAmount} SOL for ~${quote.outputAmount} USDC`);
// Then execute
const result = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '$100',
});
```
### Confirm Large Operations
For max or high percentage amounts, always confirm with the user:
```typescript
const info = await wallet.wallet.get();
const solBalance = info.balances.solana.native;
// Show user what "max" means
console.log(`This will swap your entire balance of ${solBalance} SOL`);
// Then execute after confirmation
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: 'max',
});
```
### Use Strings for Precision
Always pass amounts as strings to avoid JavaScript floating-point issues:
```typescript
// Correct
amount: '0.1'
// Avoid - may have precision issues
amount: 0.1
amount: String(0.1)
```
## Error Cases
| Input | Error |
|-------|-------|
| `"0"` | Zero amount not allowed |
| `"-1"` | Negative amounts not allowed |
| `"101%"` | Percentage over 100% not allowed |
| `"abc"` | Invalid format |
| `""` | Empty amount not allowed |
| `"$"` | Missing value after dollar sign |
## Type Definition
```typescript
type FlexibleAmount = string;
// Valid patterns:
// /^\d+\.?\d*$/ - Decimal (1.5, 100)
// /^\$\d+\.?\d*$/ - USD prefix ($100, $100.50)
// /^\d+\.?\d*usd$/i - USD suffix (100usd, 100USD)
// /^\d+\.?\d*%$/ - Percentage (50%, 100%)
// /^(max|all)$/i - Max (max, MAX, all, ALL)
```
---
# Supported Chains
> Blockchain networks supported by the SDK
URL: https://docs.loomlay.com/sdk/chains
# Supported Chains
The SDK supports multiple blockchain networks through a unified interface.
## Chain Overview
| Chain | Type | Native Token | Chain ID | Swap | Transfer | Bridge |
|-------|------|--------------|----------|------|----------|--------|
| Solana | Non-EVM | SOL | - | Yes | Yes | No |
| Ethereum | EVM | ETH | 1 | Yes | Yes | Yes |
| Base | EVM | ETH | 8453 | Yes | Yes | Yes |
| Arbitrum | EVM | ETH | 42161 | Yes | Yes | Yes |
## Chain Details
### Solana
Full trading support via Jupiter aggregator.
```typescript
// Swap on Solana (default chain)
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '1',
});
// Transfer SOL
await wallet.trading.transfer({
to: 'recipient_solana_address',
token: 'SOL',
amount: '1',
chain: 'solana',
});
// Launch tokens (Solana only)
await wallet.tokenize.launch({
name: 'My Token',
symbol: 'MTK',
description: 'A new token',
image: 'https://...',
initialLiquidity: '10',
});
```
**Features:**
- Token swaps via Jupiter Ultra
- Native SOL and SPL token transfers
- Token launches with instant liquidity
- Sub-second transaction finality
### Ethereum
EVM support via Relay aggregator.
```typescript
// Swap on Ethereum
await wallet.trading.swap({
inputToken: 'ETH',
outputToken: 'USDC',
amount: '0.1',
chain: 'ethereum',
});
// Transfer ETH
await wallet.trading.transfer({
to: '0x...',
token: 'ETH',
amount: '0.1',
chain: 'ethereum',
});
```
**Features:**
- Token swaps via Relay
- Native ETH and ERC-20 transfers
- Bridge source and destination
### Base
L2 with low fees via Relay.
```typescript
// Swap on Base
await wallet.trading.swap({
inputToken: 'ETH',
outputToken: 'USDC',
amount: '0.1',
chain: 'base',
});
// Bridge from Ethereum to Base
await wallet.trading.bridge({
fromChain: 'ethereum',
toChain: 'base',
token: 'USDC',
amount: '100',
});
```
**Features:**
- Low transaction fees
- Fast confirmation times
- Bridge from/to other EVM chains
### Arbitrum
L2 with Ethereum security via Relay.
```typescript
// Swap on Arbitrum
await wallet.trading.swap({
inputToken: 'ETH',
outputToken: 'USDC',
amount: '0.1',
chain: 'arbitrum',
});
```
**Features:**
- Low transaction fees
- Ethereum-level security
- Bridge from/to other EVM chains
## Bridges
Bridges are only available between EVM chains. Solana bridges are not yet supported.
### Supported Bridge Routes
| From | To | Supported |
|------|-----|-----------|
| Ethereum | Base | Yes |
| Ethereum | Arbitrum | Yes |
| Base | Ethereum | Yes |
| Base | Arbitrum | Yes |
| Arbitrum | Ethereum | Yes |
| Arbitrum | Base | Yes |
| Solana | Any EVM | No |
| Any EVM | Solana | No |
### Bridge Example
```typescript
// Bridge USDC from Ethereum to Base
const result = await wallet.trading.bridge({
fromChain: 'ethereum',
toChain: 'base',
token: 'USDC',
amount: '100',
});
console.log('Source tx:', result.sourceTxHash);
console.log('Estimated time:', result.estimatedTime);
```
## Wallet Addresses
One seed phrase generates addresses for all chains:
```typescript
const created = await wallet.wallet.create();
// Single seed phrase
console.log('Seed phrase:', created.seedPhrase);
// Generates both addresses
console.log('Solana:', created.solanaAddress); // Base58
console.log('EVM:', created.evmAddress); // 0x... (same for all EVM chains)
```
The EVM address is shared across Ethereum, Base, and Arbitrum.
## Balances
Check balances across all chains:
```typescript
const info = await wallet.wallet.get();
// Solana
console.log('SOL:', info.balances.solana.native);
// EVM chains
console.log('ETH (Ethereum):', info.balances.ethereum.native);
console.log('ETH (Base):', info.balances.base.native);
console.log('ETH (Arbitrum):', info.balances.arbitrum.native);
```
## Token Resolution
The SDK resolves token symbols to addresses automatically:
```typescript
// These all work
await wallet.trading.swap({ inputToken: 'SOL', ... });
await wallet.trading.swap({ inputToken: 'ETH', chain: 'ethereum', ... });
await wallet.trading.swap({ inputToken: 'USDC', chain: 'base', ... });
// Or use contract addresses directly
await wallet.trading.swap({
inputToken: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC on Solana
...
});
```
## Coming Soon
- Solana to EVM bridges
- Additional EVM chains (Polygon, Optimism)
- Cross-chain swap in single transaction
---
# Market Data
> Access DexScreener data with the SDK
URL: https://docs.loomlay.com/sdk/dex
# Market Data
The `dex` resource provides access to DexScreener market data.
## Trending Pairs
```typescript
const trending = await wallet.dex.trending({
chain: 'solana',
limit: 10,
});
for (const pair of trending.pairs) {
console.log(`${pair.baseToken.symbol}/${pair.quoteToken.symbol}`);
console.log(` Price: $${pair.priceUsd}`);
console.log(` 24h Volume: $${pair.volume24h}`);
console.log(` 24h Change: ${pair.priceChange24h}%`);
}
```
## Market Movers
```typescript
// Top gainers
const gainers = await wallet.dex.gainers({ chain: 'solana', limit: 10 });
// Top losers
const losers = await wallet.dex.losers({ chain: 'solana', limit: 10 });
// Highest volume
const volume = await wallet.dex.volume({ chain: 'solana', limit: 10 });
// New pairs
const newPairs = await wallet.dex.new({ chain: 'solana', limit: 10 });
```
## Custom Queries
Search with specific filters:
```typescript
const results = await wallet.dex.query({
query: 'meme',
chain: 'solana',
filters: {
minLiquidity: 10000,
minVolume: 50000,
priceChange24h: { min: 0 }, // Only gainers
},
});
```
## Token Search
Search for specific tokens:
```typescript
const tokens = await wallet.tokens.search({
query: 'bonk',
chain: 'solana',
});
for (const token of tokens.tokens) {
console.log(`${token.name} (${token.symbol})`);
console.log(` Address: ${token.address}`);
console.log(` Safety score: ${token.safety.score}`);
console.log(` Verified: ${token.safety.verified}`);
}
```
## Pump.fun Tokens
Get Pump.fun specific data:
```typescript
const pumpfun = await wallet.dex.pumpfun({ limit: 20 });
for (const token of pumpfun.tokens) {
console.log(`${token.name}: ${token.marketCap}`);
}
```
## Pair Details
Get detailed info for a specific pair:
```typescript
const pair = await wallet.dex.getPair({
chain: 'solana',
pairAddress: 'pair_address_here',
});
console.log('Base token:', pair.baseToken.symbol);
console.log('Quote token:', pair.quoteToken.symbol);
console.log('Liquidity:', pair.liquidity);
console.log('Created:', pair.createdAt);
```
## Type Definitions
```typescript
interface DexPair {
pairAddress: string;
baseToken: TokenInfo;
quoteToken: TokenInfo;
priceUsd: string;
priceNative: string;
volume24h: string;
liquidity: string;
priceChange24h: number;
priceChange1h: number;
txCount24h: number;
}
interface TokenInfo {
address: string;
name: string;
symbol: string;
}
interface TokenSafety {
score: number;
flags: string[];
verified: boolean;
}
```
---
# Error Handling
> Handle errors gracefully with the SDK
URL: https://docs.loomlay.com/sdk/error-handling
# Error Handling
The SDK provides typed errors for robust error handling.
## Error Types
```typescript
import {
OpenClawWalletError,
ConfigurationError,
AuthenticationError,
RateLimitError,
ValidationError,
NetworkError,
InsufficientFundsError,
} from '@loomlay/openclaw-wallet-sdk';
```
## Basic Error Handling
```typescript
try {
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '100',
});
} catch (error) {
if (error instanceof InsufficientFundsError) {
console.log('Not enough SOL:', error.message);
console.log('Required:', error.required);
console.log('Available:', error.available);
} else if (error instanceof RateLimitError) {
console.log('Rate limited. Retry after:', error.retryAfter, 'seconds');
} else if (error instanceof ValidationError) {
console.log('Invalid input:', error.field, error.message);
} else {
throw error;
}
}
```
## Error Properties
All errors extend `OpenClawWalletError`:
```typescript
interface OpenClawWalletError extends Error {
code: string; // Machine-readable error code
statusCode?: number; // HTTP status if applicable
details?: unknown; // Additional error details
}
```
### Specific Error Types
```typescript
// Configuration issues
class ConfigurationError extends OpenClawWalletError {
code: 'CONFIGURATION_ERROR';
}
// Auth failures
class AuthenticationError extends OpenClawWalletError {
code: 'UNAUTHORIZED' | 'INVALID_API_KEY';
}
// Rate limiting
class RateLimitError extends OpenClawWalletError {
code: 'RATE_LIMITED';
retryAfter: number; // Seconds until retry allowed
}
// Input validation
class ValidationError extends OpenClawWalletError {
code: 'VALIDATION_ERROR';
field: string;
}
// Network issues
class NetworkError extends OpenClawWalletError {
code: 'NETWORK_ERROR' | 'TIMEOUT';
}
// Insufficient balance
class InsufficientFundsError extends OpenClawWalletError {
code: 'INSUFFICIENT_FUNDS';
required: string;
available: string;
token: string;
}
// Transaction failed
class TransactionError extends OpenClawWalletError {
code: 'TRANSACTION_FAILED' | 'TRANSACTION_TIMEOUT';
txHash?: string;
}
// Token launch errors
class TokenizeError extends OpenClawWalletError {
code: 'ALREADY_LAUNCHED' | 'SYMBOL_TAKEN' | 'INVALID_IMAGE';
}
```
## Error Code Reference
| Error Code | HTTP Status | Error Class | Description |
|------------|-------------|-------------|-------------|
| `CONFIGURATION_ERROR` | - | `ConfigurationError` | SDK misconfigured (missing API key, invalid options) |
| `UNAUTHORIZED` | 401 | `AuthenticationError` | Missing or invalid API key |
| `INVALID_API_KEY` | 401 | `AuthenticationError` | API key format is invalid |
| `RATE_LIMITED` | 429 | `RateLimitError` | Too many requests, retry after `retryAfter` seconds |
| `VALIDATION_ERROR` | 400 | `ValidationError` | Invalid input parameters |
| `NETWORK_ERROR` | - | `NetworkError` | Connection failed or request timed out |
| `TIMEOUT` | - | `NetworkError` | Request exceeded timeout limit |
| `INSUFFICIENT_FUNDS` | 400 | `InsufficientFundsError` | Not enough balance for operation |
| `TRANSACTION_FAILED` | 500 | `TransactionError` | On-chain transaction failed |
| `TRANSACTION_TIMEOUT` | 500 | `TransactionError` | Transaction confirmation timed out |
| `ALREADY_LAUNCHED` | 400 | `TokenizeError` | Account already launched a token |
| `SYMBOL_TAKEN` | 400 | `TokenizeError` | Token symbol already exists |
| `INVALID_IMAGE` | 400 | `TokenizeError` | Image URL invalid or inaccessible |
| `WALLET_NOT_FOUND` | 404 | `OpenClawWalletError` | No wallet exists for this account |
| `TOKEN_NOT_FOUND` | 404 | `OpenClawWalletError` | Token address or symbol not found |
| `SLIPPAGE_EXCEEDED` | 400 | `OpenClawWalletError` | Price moved beyond slippage tolerance |
## Retry Logic
The SDK has built-in retry for transient failures:
```typescript
const wallet = new OpenClawWallet({
apiKey: 'agent_xxx',
maxRetries: 3, // Retry up to 3 times
retryDelay: 1000, // Start with 1s delay
});
```
### Custom Retry
```typescript
async function swapWithRetry(params: SwapParams, maxAttempts = 3) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await wallet.trading.swap(params);
} catch (error) {
if (error instanceof RateLimitError) {
if (attempt < maxAttempts) {
await sleep(error.retryAfter * 1000);
continue;
}
}
throw error;
}
}
}
```
## Retry Strategy by Error Type
| Error Type | Retry? | Strategy |
|------------|--------|----------|
| `RateLimitError` | Yes | Wait for `retryAfter` seconds, then retry |
| `NetworkError` | Yes | Exponential backoff (1s, 2s, 4s), max 3 attempts |
| `TransactionError` (TIMEOUT) | Maybe | Check transaction status first, retry if not confirmed |
| `TransactionError` (FAILED) | No | Transaction was rejected, fix params and retry |
| `InsufficientFundsError` | No | Add funds before retrying |
| `ValidationError` | No | Fix input parameters before retrying |
| `AuthenticationError` | No | Check API key, do not retry |
| `ConfigurationError` | No | Fix SDK configuration, do not retry |
| `TokenizeError` | No | Address the specific issue (symbol, image, etc.) |
| `SLIPPAGE_EXCEEDED` | Yes | Increase slippage or retry with fresh quote |
**Pro Tip:** For `SLIPPAGE_EXCEEDED` errors, fetch a fresh quote with `quoteOnly: true` before retrying. Market conditions may have changed significantly.
## WebSocket Errors
```typescript
const dexWs = wallet.createDexWebSocket();
dexWs.on('error', (error) => {
if (error instanceof AuthenticationError) {
console.log('Invalid API key');
} else if (error instanceof NetworkError) {
console.log('Connection lost');
}
});
```
## Logging
Enable debug logging:
```typescript
import { setLogLevel } from '@loomlay/openclaw-wallet-sdk';
setLogLevel('debug'); // 'debug' | 'info' | 'warn' | 'error' | 'none'
```
---
# FAQ
> Frequently asked questions about the SDK
URL: https://docs.loomlay.com/sdk/faq
# Frequently Asked Questions
Common questions and answers about the OpenClawWallet SDK.
## Registration
### Why can I only launch one token per API key?
Each API key is tied to one agent account to prevent spam and ensure quality token launches. This limit:
- Prevents bot-driven token spam
- Ensures creators are invested in their token's success
- Maintains platform quality
If you need to launch multiple tokens, you'll need separate agent accounts.
### How do I get a new API key if I lost mine?
Registration is IP-limited. Your options:
1. **Check your code** - Search for `agent_` in your codebase or environment files
2. **Check registration response** - If you try to register again, you'll see your key prefix
3. **Contact support** - Email [support@loomlay.io](mailto:support@loomlay.io) with verification of ownership
```typescript
// Registration attempt shows your existing key prefix
const result = await OpenClawWallet.register();
if (!result.success) {
console.log('Already registered. Key prefix:', result.keyPrefix);
// Use this to help identify your key
}
```
### Can I have multiple API keys?
Yes, you can create additional keys for your existing account:
```typescript
// Create new key
const newKey = await wallet.auth.createKey();
// List all keys
const keys = await wallet.auth.listKeys();
// Revoke if needed
await wallet.auth.revokeKey({ keyId: 'key_id' });
```
## Trading
### Why is my swap failing?
Common causes:
**Insufficient balance**
```typescript
import { InsufficientFundsError } from '@loomlay/openclaw-wallet-sdk';
try {
await wallet.trading.swap({ ... });
} catch (error) {
if (error instanceof InsufficientFundsError) {
console.log('Required:', error.required);
console.log('Available:', error.available);
}
}
```
**Slippage too low**
```typescript
// Try higher slippage for volatile tokens
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'MEMECOIN',
amount: '1',
slippage: 3, // 3% instead of default 0.5%
});
```
**Token not found**
```typescript
// Ensure token exists and use correct symbol or address
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC address
amount: '1',
});
```
**Liquidity issues**
```typescript
// Check price impact first
const quote = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'LOW_LIQ_TOKEN',
amount: '100',
quoteOnly: true,
});
if (quote.priceImpact > 5) {
console.warn('High price impact - consider smaller amount');
}
```
### Why is my bridge taking so long?
Bridge times vary by network congestion:
| Route | Typical Time |
|-------|-------------|
| Ethereum to Base | 1-5 minutes |
| Ethereum to Arbitrum | 1-5 minutes |
| Base to Ethereum | 5-15 minutes |
| Arbitrum to Ethereum | 5-15 minutes |
The SDK returns estimated time:
```typescript
const result = await wallet.trading.bridge({ ... });
console.log('Estimated time:', result.estimatedTime);
```
### What chains are supported for bridges?
EVM chains only. Solana bridges are not yet supported.
| From | To | Supported |
|------|-----|-----------|
| Ethereum | Base, Arbitrum | Yes |
| Base | Ethereum, Arbitrum | Yes |
| Arbitrum | Ethereum, Base | Yes |
| Solana | Any | No |
| Any | Solana | No |
## Wallet
### How do I check my wallet balance?
Two options depending on what you need:
```typescript
// Option 1: Basic wallet info
const info = await wallet.wallet.get();
console.log('SOL:', info.balances.solana.native);
console.log('ETH:', info.balances.ethereum.native);
// Option 2: Full portfolio with USD values
const portfolio = await wallet.portfolio.get();
console.log('Total value:', portfolio.totalValueUsd);
for (const holding of portfolio.holdings) {
console.log(`${holding.symbol}: ${holding.balance} ($${holding.valueUsd})`);
}
```
### Can I import an existing wallet?
Yes, in self-custody mode you can import an existing BIP39 seed phrase:
```typescript
// SDK
const imported = await wallet.wallet.importSeed(
'your twelve word seed phrase here ...',
'my-secure-passphrase'
);
```
```typescript
// Plugin
const imported = await wallet_import({
seedPhrase: 'your twelve word seed phrase here ...',
passphrase: 'my-secure-passphrase'
});
```
The seed phrase is encrypted locally and public addresses are registered with the API for balance lookups.
### Where are my private keys stored?
Private keys are derived from your seed phrase using:
- **Solana**: SLIP-0010 derivation (m/44'/501'/0'/0')
- **EVM**: BIP32 derivation (m/44'/60'/0'/0/0)
Storage depends on your wallet mode:
| Mode | Where Keys Live | Encryption |
|------|----------------|------------|
| **Self-custody** (`local`) | `~/.loomlay/wallet.json` on your device | PBKDF2-SHA512 + AES-256-GCM |
| **Custodial** | Server-side (PostgreSQL) | AES-256-GCM with server key |
In self-custody mode, private keys never leave your device. Only public addresses and signed transactions are sent to the API.
### How do I unlock my wallet for signing?
In self-custody mode, you need to provide your passphrase before signing transactions. Three options:
1. **Environment variable** (recommended): `export LOOMLAY_WALLET_PASSPHRASE=your-passphrase`
2. **Plugin tool**: Call `wallet_unlock({ passphrase: 'your-passphrase' })`
3. **SDK callback**: Pass `getPassphrase` when creating the client
## Token Launch
### Why did my token launch fail?
Common issues:
**Insufficient SOL**
```typescript
// Need SOL for: liquidity + transaction fees
// Example: 10 SOL liquidity + ~0.1 SOL fees
const info = await wallet.wallet.get();
console.log('SOL balance:', info.balances.solana.native);
```
**Invalid image**
```typescript
// Image requirements:
// - Valid URL (https://)
// - PNG, JPG, or GIF format
// - Minimum 200x200 pixels
// - Accessible publicly
```
**Symbol already used**
```typescript
// Each symbol must be unique on LoomLay
// Try a different symbol if yours is taken
```
### How do I claim fees from my token?
```typescript
// Check pending fees
const fees = await wallet.fees.getPending();
console.log('Pending:', fees.pendingAmount, 'SOL');
// Claim fees (rate limited to 1 per hour)
if (parseFloat(fees.pendingAmount) > 0) {
const claim = await wallet.fees.claim();
console.log('Claimed:', claim.claimedAmount, 'SOL');
}
```
Fee claims are rate limited to 1 per hour. The platform pays gas, so this prevents abuse.
## WebSockets
### Why am I getting disconnected?
Common causes:
**Inactivity timeout**
```typescript
// Send heartbeats to stay connected
const dexWs = wallet.createDexWebSocket();
// SDK handles heartbeats automatically, but you can listen:
dexWs.on('heartbeat', () => {
console.log('Connection alive');
});
```
**Too many subscriptions**
```typescript
// Maximum 10 subscriptions per connection
// Create multiple connections if needed
```
**Network issues**
```typescript
dexWs.on('disconnect', (reason) => {
console.log('Disconnected:', reason);
// SDK auto-reconnects with exponential backoff
});
```
### How do I subscribe to multiple pairs?
```typescript
const dexWs = wallet.createDexWebSocket();
// Subscribe to multiple pairs (max 10)
const pairs = ['SOL/USDC', 'ETH/USDC', 'BONK/SOL'];
for (const pair of pairs) {
dexWs.subscribePair(pair);
}
dexWs.on('update', (data) => {
console.log(`${data.pair}: $${data.price}`);
});
```
## General
### Is the SDK browser-compatible?
No. The SDK is designed for server-side use only:
- API keys should never be exposed to browsers
- Seed phrases must stay server-side
- Use a backend API to proxy requests if needed
### What's the difference between quote and execute?
```typescript
// Quote: Get price without executing (no funds needed)
const quote = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '100',
quoteOnly: true, // Just get the price
});
// Execute: Actually perform the swap (needs funds)
const result = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '100',
// quoteOnly defaults to false
});
```
### How do I handle errors?
```typescript
import {
OpenClawWalletError,
AuthenticationError,
RateLimitError,
InsufficientFundsError,
ValidationError,
} from '@loomlay/openclaw-wallet-sdk';
try {
await wallet.trading.swap({ ... });
} catch (error) {
if (error instanceof AuthenticationError) {
// Invalid or revoked API key
} else if (error instanceof RateLimitError) {
// Wait and retry
await sleep(error.retryAfter * 1000);
} else if (error instanceof InsufficientFundsError) {
// Not enough balance
} else if (error instanceof ValidationError) {
// Invalid parameters
} else if (error instanceof OpenClawWalletError) {
// Other SDK error
console.log('Error code:', error.code);
} else {
throw error;
}
}
```
See [Error Handling](/sdk/error-handling) for more details.
---
# Getting Started
> Set up the OpenClawWallet SDK or OpenClaw Plugin in your project
URL: https://docs.loomlay.com/sdk/getting-started
# Getting Started
This guide walks you through setting up the OpenClawWallet SDK or OpenClaw Plugin.
## Prerequisites
Before you begin, ensure you have:
- **Node.js 18+** or **Bun 1.0+**
- A package manager: npm, yarn, pnpm, or bun
- A server-side environment (the SDK is not designed for browser use)
## Installation
```bash
npm install @loomlay/openclaw-wallet-sdk
```
```bash
yarn add @loomlay/openclaw-wallet-sdk
```
```bash
pnpm add @loomlay/openclaw-wallet-sdk
```
```bash
bun add @loomlay/openclaw-wallet-sdk
```
## Quick Start (Auto-Registration)
The easiest way to get started is with automatic registration:
```typescript
import { OpenClawWallet } from '@loomlay/openclaw-wallet-sdk';
// Auto-register if no key found, saves to ~/.loomlay/credentials.json
const { client, registration } = await OpenClawWallet.create({ autoRegister: true });
if (registration) {
console.log('New account created!');
console.log('API Key:', registration.apiKey);
console.log('Saved to:', registration.savedTo);
}
// Use the client
const wallet = await client.wallet.create();
```
The `create()` method checks for API keys in this order:
1. `apiKey` option (if provided)
2. `LOOMLAY_API_KEY` environment variable
3. Stored credentials (`~/.loomlay/credentials.json`)
4. Auto-register (if `autoRegister: true`)
## Manual Registration
If you prefer to register manually:
```typescript
import { OpenClawWallet } from '@loomlay/openclaw-wallet-sdk';
// This is rate-limited to 1 per IP
const result = await OpenClawWallet.register();
console.log('API Key:', result.apiKey);
// Save this key securely!
```
Save your API key immediately - it's only shown once during registration.
### Registration Failed (409)?
If your IP already has an account:
1. **Check stored credentials** - `cat ~/.loomlay/credentials.json`
2. **Set environment variable** - `export LOOMLAY_API_KEY=agent_your_key`
3. **Contact support** - [support@loomlay.io](mailto:support@loomlay.io) for key recovery
## Initialize the Client
### Option 1: With auto-registration (recommended)
```typescript
const { client } = await OpenClawWallet.create({ autoRegister: true });
```
### Option 2: With self-custody mode
```typescript
const wallet = new OpenClawWallet({
apiKey: process.env.LOOMLAY_API_KEY!,
walletMode: 'local',
getPassphrase: async () => process.env.LOOMLAY_WALLET_PASSPHRASE!,
});
```
In self-custody mode, private keys are generated and stored locally on your device. The API only receives public addresses. See [Wallet Management](/sdk/wallet) for details.
### Option 3: With environment variable (custodial)
```typescript
const wallet = new OpenClawWallet({
apiKey: process.env.LOOMLAY_API_KEY!,
});
```
### Option 4: With explicit key
```typescript
const wallet = new OpenClawWallet({
apiKey: 'agent_your_key_here',
});
```
## Create Your First Wallet
```typescript
// Create a new wallet
const created = await wallet.wallet.create();
console.log('Seed phrase:', created.seedPhrase);
console.log('Solana:', created.solanaAddress);
console.log('EVM:', created.evmAddress);
// Save the seed phrase securely!
```
## Check Balances
```typescript
const info = await wallet.wallet.get();
console.log('Solana balance:', info.balances.solana.native, 'SOL');
console.log('Ethereum balance:', info.balances.ethereum.native, 'ETH');
```
## Make Your First Swap
```typescript
import { InsufficientFundsError, RateLimitError } from '@loomlay/openclaw-wallet-sdk';
try {
// Swap 1 SOL for USDC
const swap = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '1',
});
console.log('Swapped for:', swap.outputAmount, 'USDC');
console.log('Transaction:', swap.txHash);
} catch (error) {
if (error instanceof InsufficientFundsError) {
console.error('Not enough funds:', error.message);
console.error('Required:', error.required, '| Available:', error.available);
} else if (error instanceof RateLimitError) {
console.error('Rate limited. Retry in', error.retryAfter, 'seconds');
} else {
throw error;
}
}
```
## Environment Variables
We recommend storing your API key in environment variables:
```bash
# .env
LOOMLAY_API_KEY=agent_your_key_here
```
```typescript
// Load from environment
const wallet = new OpenClawWallet({
apiKey: process.env.LOOMLAY_API_KEY!,
});
```
## TypeScript Support
The SDK is written in TypeScript and provides full type definitions:
```typescript
import type {
SwapParams,
SwapResult,
WalletInfo
} from '@loomlay/openclaw-wallet-sdk';
const params: SwapParams = {
inputToken: 'SOL',
outputToken: 'USDC',
amount: '1.5',
slippage: 0.5,
};
const result: SwapResult = await wallet.trading.swap(params);
```
## Next Steps
- [Wallet Management](/sdk/wallet) - Create and manage wallets
- [Trading](/sdk/trading) - Swaps, transfers, and bridges
- [Market Data](/sdk/dex) - Access DexScreener data
- [Real-time Updates](/sdk/websockets) - WebSocket subscriptions
If you're using an AI coding assistant like Claude Code, you can use the OpenClaw Plugin instead of integrating the SDK directly. The plugin provides 29 tools for wallet management, trading, and market data that the AI can use on your behalf. The plugin defaults to **self-custody mode** — private keys stay on your device.
## Installation
```bash
npm install @loomlay/openclaw-wallet-plugin
```
## Configuration
No configuration required! The plugin auto-registers an API key and creates a local wallet on first use.
Optionally set environment variables:
```bash
# Override auto-registration
export LOOMLAY_API_KEY=agent_your_key_here
# Set wallet passphrase (recommended — avoids passphrase in conversation logs)
export LOOMLAY_WALLET_PASSPHRASE=your-secure-passphrase
```
## What's Included
The plugin provides **29 tools** across these categories:
| Category | Tools | Description |
|----------|-------|-------------|
| **Wallet** | 5 | Create wallets, check balances, export keys, unlock, import |
| **Trading** | 5 | Swaps, transfers, bridges with quotes |
| **Tokens** | 4 | Search, price, details, charts |
| **Portfolio** | 2 | Holdings and transaction history |
| **DEX** | 7 | Trending, gainers, losers, new pairs |
| **Tokenize** | 2 | Launch tokens and check status |
| **Fees** | 2 | Check and claim trading fees |
| **RPC** | 2 | Direct chain RPC access |
## Skill System
The plugin includes a skill system that teaches Claude:
- Wallet security best practices
- Quote-before-trade workflow
- Error handling patterns
- Chain-specific behaviors
## Example Usage
Once configured, Claude can execute commands like:
- "Create a new wallet"
- "Swap 1 SOL for USDC"
- "Show me trending tokens on Solana"
- "What's the price of BONK?"
Always review swap quotes before confirming trades. The plugin will show you expected output amounts and price impact.
## Next Steps
- [OpenClaw Plugin](/sdk/openclaw-plugin) - Full plugin documentation
- [Wallet Management](/sdk/wallet) - Wallet operations reference
- [Trading](/sdk/trading) - Trading operations reference
---
# SDK Overview
> TypeScript SDK for the LoomLay Agent API
URL: https://docs.loomlay.com/sdk
# SDK Overview
The official TypeScript SDK for the LoomLay Agent API. Build AI agents that can trade, manage wallets, and launch tokens across multiple blockchains.
## Choose Your Integration
**Package:** `@loomlay/openclaw-wallet-sdk`
For TypeScript/JavaScript applications that need programmatic access to the LoomLay Agent API.
```bash
npm install @loomlay/openclaw-wallet-sdk
```
```typescript
import { OpenClawWallet } from '@loomlay/openclaw-wallet-sdk';
const wallet = new OpenClawWallet({
apiKey: process.env.LOOMLAY_API_KEY!,
});
// Swap tokens
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '1',
});
```
[Get Started with the SDK](/sdk/getting-started)
**Package:** `@loomlay/openclaw-wallet-plugin`
For AI agents and coding assistants. Provides a skill-based interface with 29 tools for wallet management, trading, and market data. Defaults to **self-custody** — private keys stay on your device.
```bash
npm install -g @loomlay/openclaw-wallet-plugin
```
Then use the `/wallet` skill in your AI coding assistant:
```
/wallet swap 1 SOL to USDC
/wallet check balance
/wallet transfer 0.5 ETH to 0x...
```
[OpenClaw Plugin Guide](/sdk/openclaw-plugin)
**Building an AI Agent?** Check out the [AI Agent Development Guide](/sdk/ai-agent-guide) for best practices on amount formatting, error handling, and transaction confirmations.
## How It Works
**Register** - Get an API key with a single call. One key per IP address.
**Create Wallet** - Generate a multi-chain wallet with Solana and EVM addresses from a single seed phrase.
**Trade** - Swap tokens, transfer funds, and bridge across chains with simple method calls.
## Supported Chains
| Chain | Type | Native Token | Chain ID | Swap | Transfer | Bridge |
|-------|------|--------------|----------|------|----------|--------|
| Solana | Non-EVM | SOL | - | Yes | Yes | No |
| Ethereum | EVM | ETH | 1 | Yes | Yes | Yes |
| Base | EVM | ETH | 8453 | Yes | Yes | Yes |
| Arbitrum | EVM | ETH | 42161 | Yes | Yes | Yes |
| Optimism | EVM | ETH | 10 | Yes | Yes | Yes |
| Polygon | EVM | MATIC | 137 | Yes | Yes | Yes |
| BSC | EVM | BNB | 56 | Yes | Yes | Yes |
All EVM chains share the same wallet address. See [Supported Chains](/sdk/chains) for detailed chain information.
## Key Features
| Feature | Description |
|---------|-------------|
| **Self-custody** | Private keys encrypted locally, never sent to server |
| **Type-safe** | Full TypeScript support with generated types |
| **Multi-chain** | Solana + EVM from single interface |
| **WebSockets** | Real-time market data subscriptions |
| **Auto-retry** | Configurable retry logic for transient failures |
| **AI-ready** | OpenClaw Plugin with 29 tools |
API requests are rate-limited to prevent abuse. See [Rate Limits](/api-reference/rate-limits) for details on limits per endpoint.
Each API key is tied to one agent account, which can only launch **one token**. Choose your token launch carefully as this cannot be undone.
## Resources
| Resource | Purpose |
|----------|---------|
| `wallet.auth` | API key management |
| `wallet.wallet` | Wallet creation and info |
| `wallet.trading` | Swaps, transfers, bridges |
| `wallet.dex` | Market data |
| `wallet.tokenize` | Token launches |
## Quick Links
### Getting Started
- [Getting Started](/sdk/getting-started) - Set up the SDK
- [Wallet Management](/sdk/wallet) - Create and manage wallets
- [Trading](/sdk/trading) - Swaps, transfers, bridges
- [WebSockets](/sdk/websockets) - Real-time subscriptions
### AI Agent Development
- [OpenClaw Plugin](/sdk/openclaw-plugin) - Skill-based interface for AI agents
- [Tools Reference](/sdk/tools-reference) - All 27 available tools
- [AI Agent Guide](/sdk/ai-agent-guide) - Best practices for AI agents
- [Amount Formats](/sdk/amount-formats) - Human-readable vs raw amounts
### Reference
- [Supported Chains](/sdk/chains) - Chain details and capabilities
- [Error Handling](/sdk/error-handling) - Error types and recovery
- [Security](/sdk/security) - API key and wallet security
---
# OpenClaw Plugin
> Native tools for AI agents with multi-chain wallet and trading capabilities
URL: https://docs.loomlay.com/sdk/openclaw-plugin
# OpenClaw Plugin
The OpenClaw Plugin provides 29 native tools for multi-chain wallet management, trading, and market data directly within AI coding assistants like Claude Code. The plugin defaults to **self-custody mode** — private keys are generated and encrypted locally on your device, never sent to any server.
## Architecture Overview
The OpenClaw ecosystem has a dual-layer architecture:
| Layer | Package | Purpose |
|-------|---------|---------|
| **SDK** | `@loomlay/openclaw-wallet-sdk` | Programmatic TypeScript interface for building applications |
| **Plugin** | `@loomlay/openclaw-wallet-plugin` | Native tools for AI agents |
The SDK is designed for developers building applications. The Plugin wraps the SDK and exposes its functionality as discrete tools that AI agents can invoke directly.
The Plugin depends on the SDK internally. When you install the plugin, the SDK is included as a peer dependency.
## Installation
```bash
npm install @loomlay/openclaw-wallet-plugin
```
```bash
yarn add @loomlay/openclaw-wallet-plugin
```
```bash
pnpm add @loomlay/openclaw-wallet-plugin
```
```bash
bun add @loomlay/openclaw-wallet-plugin
```
## Configuration
### Zero Configuration (Recommended)
The plugin works out of the box with **no configuration required**. On first use, it automatically:
1. Registers for a new API key (saved to `~/.loomlay/credentials.json`)
2. Generates wallet keys **locally** on your device
3. Encrypts keys with your passphrase (saved to `~/.loomlay/wallet.json`)
4. Registers only public addresses with the API
```typescript
import { wallet_create, wallet_unlock } from '@loomlay/openclaw-wallet-plugin';
// First use: auto-registers API key, creates local wallet
const wallet = await wallet_create();
// → Keys generated on YOUR device, encrypted with passphrase
// → Public addresses registered with API for balance lookups
// Unlock wallet for signing operations
await wallet_unlock({ passphrase: 'your-passphrase' });
// All trades sign locally — private key never sent to server
```
### API Key Resolution Order
The plugin checks for API keys in this order:
1. `LOOMLAY_API_KEY` environment variable (highest priority)
2. Stored credentials (`~/.loomlay/credentials.json`)
3. Auto-register new account (if no key found)
### Passphrase Resolution Order
For signing operations (swaps, transfers), the passphrase is resolved:
1. `LOOMLAY_WALLET_PASSPHRASE` environment variable (highest priority, recommended)
2. In-memory cache (set via `wallet_unlock`)
3. Error thrown with instructions
### Environment Variables (Optional)
```bash
# Override auto-registration
export LOOMLAY_API_KEY=agent_your_key_here
# Set wallet passphrase (avoids passphrase appearing in conversation logs)
export LOOMLAY_WALLET_PASSPHRASE=your-secure-passphrase
# Optional: Custom API base URL
export LOOMLAY_BASE_URL=https://api.loomlay.com
```
### Programmatic Configuration (Optional)
```typescript
import { initPlugin, initPluginAsync } from '@loomlay/openclaw-wallet-plugin';
// Sync: Requires existing key from env or stored credentials
initPlugin({
apiKey: 'agent_your_key_here',
baseUrl: 'https://api.loomlay.com' // Optional
});
// Async: Supports auto-registration
const { client, registration } = await initPluginAsync();
```
### Disable Auto-Registration
If you want to require explicit API key configuration:
```typescript
import { initPluginAsync } from '@loomlay/openclaw-wallet-plugin';
// Throws error if no key found instead of auto-registering
const { client } = await initPluginAsync({ autoRegister: false });
```
Store your API key in environment variables or let the plugin manage it automatically. API keys start with `agent_` prefix.
## Available Tools (29)
The plugin provides 29 tools organized into 8 categories:
### Wallet (5 tools)
| Tool | Description |
|------|-------------|
| `wallet_create` | Create a new multi-chain wallet (keys stored locally in self-custody mode). Returns Solana and EVM addresses plus a 12-word seed phrase shown only once. |
| `wallet_get` | Get wallet addresses and current balances across all chains. |
| `wallet_export_keys` | Export private keys. In self-custody mode, decrypts locally using passphrase. In custodial mode, requires seed phrase. |
| `wallet_unlock` | Cache passphrase in memory for signing operations. Required before swaps/transfers in self-custody mode. |
| `wallet_import` | Import an existing seed phrase into a local self-custody wallet. Encrypts locally and registers addresses with API. |
### Trading (5 tools)
| Tool | Description |
|------|-------------|
| `swap` | Execute a token swap. Supports flexible amounts: `"1.5"`, `"$100"`, `"50%"`, or `"max"`. |
| `swap_quote` | Get a swap quote without executing. Shows expected output, minimum received, and price impact. |
| `transfer` | Transfer tokens to another address on any supported chain. |
| `bridge` | Bridge tokens between different chains (e.g., Solana to Base). |
| `bridge_quote` | Get a bridge quote showing fees and estimated completion time. |
### Tokens (4 tools)
| Tool | Description |
|------|-------------|
| `token_search` | Search for tokens by name, symbol, or address. Returns matches with safety scores. |
| `token_price` | Get current USD price for any token. |
| `token_details` | Get detailed token information including market data and safety analysis. |
| `token_chart` | Get OHLCV chart data for technical analysis. |
### Portfolio (2 tools)
| Tool | Description |
|------|-------------|
| `portfolio_get` | Get combined portfolio across all chains with total USD value. |
| `portfolio_history` | Get transaction history with optional chain filtering. |
### DEX (7 tools)
| Tool | Description |
|------|-------------|
| `dex_trending` | Get trending trading pairs sorted by trending score. |
| `dex_volume` | Get top trading pairs by 24h volume. |
| `dex_gainers` | Get top price gainers (24h). |
| `dex_losers` | Get top price losers (24h). |
| `dex_new` | Get newly created pairs (< 24 hours old). |
| `dex_pumpfun` | Get Pumpfun trending pairs (Solana only, bonding curve tokens). |
| `dex_query` | Advanced DEX query with custom filters, ranking, and timeframes. |
### Tokenize (2 tools)
| Tool | Description |
|------|-------------|
| `tokenize_launch` | Launch a new token on Solana with automatic pool creation. One token per account. |
| `tokenize_info` | Get information about your launched token including mint and pool addresses. |
### Fees (2 tools)
| Tool | Description |
|------|-------------|
| `fees_status` | Get fee status including generated, claimed, and unclaimed amounts. |
| `fees_claim` | Claim accumulated trading fees from your launched token (platform pays gas). |
### RPC (2 tools)
| Tool | Description |
|------|-------------|
| `rpc_call` | Make a direct RPC call to any supported chain. |
| `rpc_chains` | Get list of supported chains for RPC access. |
## Skill System
The plugin includes a skill file (`SKILL.md`) that teaches AI agents how to use the tools safely and effectively.
### What the Skill Teaches
The skill provides guidance on:
1. **Core Workflow** - A structured approach: Authenticate, Understand, Validate, Execute, Verify, Document
2. **Security Best Practices** - Seed phrase handling, transaction safety, API key management
3. **Quote-Before-Trade Pattern** - Always get quotes and show expected outcomes before executing
4. **Error Handling** - Recovery patterns for rate limits, insufficient funds, and network errors
5. **Chain-Specific Behaviors** - Differences between Solana and EVM chains
### Key Safety Principles
The skill enforces these safety principles for AI agents:
```
Security comes first. Wallets contain real value.
Every action involving funds should be deliberate,
verified, and explained to the user before execution.
```
**Quality Gate Checklist:**
- User explicitly requested this action
- Quote shown and confirmed for trades
- Address validated for transfers
- Sufficient balance confirmed
- Slippage/price impact acceptable
- Transaction hash provided after execution
### Accessing the Skill
```typescript
// Import from the package
import skillContent from '@loomlay/openclaw-wallet-plugin/skill';
// Or read the file directly
// node_modules/@loomlay/openclaw-wallet-plugin/skill/SKILL.md
```
## Usage Example
### Self-Custody Workflow
```typescript
import {
wallet_create,
wallet_unlock,
wallet_get,
swap,
swap_quote,
dex_trending
} from '@loomlay/openclaw-wallet-plugin';
// 1. Create wallet (keys generated and encrypted locally)
const wallet = await wallet_create();
if (wallet.success) {
console.log('Solana Address:', wallet.data.wallet.solanaAddress);
console.log('EVM Address:', wallet.data.wallet.evmAddress);
// IMPORTANT: Save the seed phrase securely - shown only once
console.log('Seed Phrase:', wallet.data.seedPhrase);
}
// 2. Unlock wallet for signing (or set LOOMLAY_WALLET_PASSPHRASE env var)
await wallet_unlock({ passphrase: 'my-secure-passphrase' });
// Check balance
const balance = await wallet_get();
if (balance.success) {
console.log('SOL Balance:', balance.data.balances.solana.sol);
}
// Get a quote before trading
const quote = await swap_quote({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '$100'
});
if (quote.success) {
console.log('Expected Output:', quote.data.outputAmount, 'USDC');
console.log('Price Impact:', quote.data.priceImpact, '%');
}
// Execute the swap after confirming the quote
const result = await swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '$100'
});
// Get trending tokens
const trending = await dex_trending({
chain: 'solana',
minLiquidity: 10000,
limit: 20
});
```
### Using the Tools Registry
```typescript
import { tools } from '@loomlay/openclaw-wallet-plugin';
// Call tools by name
const wallet = await tools.wallet_get();
const trending = await tools.dex_trending({ chain: 'solana' });
```
## Response Format
All tools return a standardized response:
```typescript
interface ToolResponse {
success: boolean;
data?: T; // Present when success is true
error?: {
message: string;
code?: string;
retryAfter?: number; // For rate limit errors
};
}
```
### Success Response
```typescript
{
success: true,
data: {
// Tool-specific data
}
}
```
### Error Response
```typescript
{
success: false,
error: {
message: "Rate limited",
code: "RATE_LIMITED",
retryAfter: 30
}
}
```
## Amount Formats
Trading tools accept flexible amount formats:
| Format | Example | Description |
|--------|---------|-------------|
| Decimal | `"1.5"` | Exact token amount |
| USD | `"$100"` | Dollar value (auto-converts) |
| Percentage | `"50%"` | Percentage of balance |
| Max | `"max"` | Entire balance |
## Supported Chains
| Chain | Swaps | Bridges | RPC |
|-------|:-----:|:-------:|:---:|
| Solana | Yes | Yes | Yes |
| Ethereum | Yes | Yes | Yes |
| Base | Yes | Yes | Yes |
| Arbitrum | Yes | Yes | Yes |
| Optimism | Yes | Yes | Yes |
| Polygon | Yes | Yes | Yes |
| BSC | Yes | Yes | Yes |
## Plugin Manifest
The `openclaw.plugin.json` file describes all tools in a machine-readable format:
```json
{
"name": "@loomlay/openclaw-wallet-plugin",
"tools": [
{
"name": "swap",
"description": "Execute a token swap...",
"parameters": { ... },
"returns": { ... }
}
]
}
```
This manifest enables plugin systems and AI agents to discover and understand available tools programmatically.
## Security Notes
**Seed Phrase Security:** The seed phrase is returned only once when creating a wallet. It cannot be retrieved later. Store it securely offline. Never log it, include it in error messages, or store it in databases.
### Self-Custody Security
In self-custody mode (default), your keys are protected by:
- **Local encryption**: PBKDF2-SHA512 (600k iterations) + AES-256-GCM
- **File permissions**: `~/.loomlay/wallet.json` with `0600` (owner read/write only)
- **No key transmission**: Private keys never sent to any server
- **Transaction validation**: Fee payer verified before signing
- **Key zeroing**: Private key buffers zeroed after signing
Set `LOOMLAY_WALLET_PASSPHRASE` as an environment variable to keep your passphrase out of conversation logs.
### General
1. **API Key** - Store in environment variables, never hardcode
2. **Seed Phrase** - Returned once from `wallet_create`, store offline securely
3. **Quotes First** - Always get quotes before executing trades
4. **Verify Addresses** - Double-check recipient addresses for transfers
5. **Check Price Impact** - High price impact (>1%) indicates significant market movement
## Related Pages
- [SDK Overview](/sdk) - Full TypeScript SDK documentation
- [Getting Started](/sdk/getting-started) - SDK setup and first steps
- [Trading](/sdk/trading) - Detailed swap, transfer, and bridge documentation
- [Market Data](/sdk/dex) - DEX data and market analysis tools
- [Error Handling](/sdk/error-handling) - Error types and recovery patterns
- [Rate Limits](/sdk/rate-limits) - API rate limit information
---
# Rate Limits
> API rate limits and best practices
URL: https://docs.loomlay.com/sdk/rate-limits
# Rate Limits
The API enforces rate limits to ensure fair usage and platform stability.
## Rate Limit Overview
| Endpoint | Limit | Window |
|----------|-------|--------|
| Registration | 5 requests | 24 hours |
| Wallet operations | 30 requests | 1 minute |
| Trading (swap/transfer/bridge) | 30 requests | 1 minute |
| Portfolio | 60 requests | 1 minute |
| Token search | 100 requests | 1 minute |
| DEX data | 60 requests | 1 minute |
| RPC proxy | 100 requests | 1 minute |
| Token launch | 1 request | 24 hours |
| Fee claims | 1 request | 1 hour |
## Rate Limit Headers
All API responses include rate limit headers:
```
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 25
X-RateLimit-Reset: 1699574400
```
## Handling 429 Responses
When you exceed rate limits, the API returns HTTP 429:
```typescript
import { RateLimitError } from '@loomlay/openclaw-wallet-sdk';
try {
await wallet.trading.swap({ ... });
} catch (error) {
if (error instanceof RateLimitError) {
console.log('Rate limited. Retry after:', error.retryAfter, 'seconds');
}
}
```
## Exponential Backoff
Implement exponential backoff for robust retry logic:
```typescript
async function withRetry(
fn: () => Promise,
maxAttempts = 5
): Promise {
let lastError: Error | undefined;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
if (error instanceof RateLimitError) {
// Use server-provided retry time, or calculate backoff
const delay = error.retryAfter
? error.retryAfter * 1000
: Math.min(1000 * Math.pow(2, attempt), 30000);
console.log(`Rate limited. Retrying in ${delay}ms...`);
await sleep(delay);
lastError = error;
} else {
throw error;
}
}
}
throw lastError;
}
function sleep(ms: number): Promise {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Usage
const result = await withRetry(() =>
wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '1',
})
);
```
## Built-in Retry
The SDK includes built-in retry for transient failures:
```typescript
const wallet = new OpenClawWallet({
apiKey: process.env.LOOMLAY_API_KEY!,
maxRetries: 3, // Retry up to 3 times
retryDelay: 1000, // Start with 1s delay
});
```
Built-in retry uses exponential backoff automatically. Each retry waits 2x longer than the previous.
## WebSocket Limits
WebSocket connections have separate limits:
| Limit | Value |
|-------|-------|
| Subscriptions per client | 10 |
| Max upstream connections | 20 |
| Heartbeat interval | 30 seconds |
```typescript
const dexWs = wallet.createDexWebSocket();
// Maximum 10 subscriptions per connection
dexWs.subscribePair('SOL/USDC');
dexWs.subscribePair('ETH/USDC');
// ... up to 10 pairs
```
## Best Practices
### Batch When Possible
Instead of multiple individual calls:
```typescript
// Less efficient: 3 API calls
const sol = await wallet.wallet.get();
const portfolio = await wallet.portfolio.get();
const status = await wallet.tokenize.status();
```
Use a single portfolio call when you need holdings:
```typescript
// More efficient: 1 API call
const portfolio = await wallet.portfolio.get();
// Contains balances across all chains
```
### Cache Responses
Cache data that doesn't change frequently:
```typescript
let cachedPortfolio: PortfolioResult | null = null;
let cacheTime = 0;
const CACHE_TTL = 60000; // 1 minute
async function getPortfolio() {
const now = Date.now();
if (cachedPortfolio && now - cacheTime < CACHE_TTL) {
return cachedPortfolio;
}
cachedPortfolio = await wallet.portfolio.get();
cacheTime = now;
return cachedPortfolio;
}
```
### Use WebSockets for Real-time Data
For frequently updating data, use WebSockets instead of polling:
```typescript
// Instead of polling
setInterval(async () => {
const data = await wallet.dex.getPair('SOL/USDC'); // Uses rate limit
}, 1000);
// Use WebSocket
const dexWs = wallet.createDexWebSocket();
dexWs.subscribePair('SOL/USDC');
dexWs.on('update', (data) => {
console.log('Real-time update:', data);
});
```
### Spread Out Requests
If you need to make many requests, spread them out:
```typescript
const tokens = ['SOL', 'ETH', 'USDC', 'BONK', 'WIF'];
const results = [];
for (const token of tokens) {
const data = await wallet.dex.getToken(token);
results.push(data);
// Small delay between requests
await sleep(100);
}
```
## Registration Limits
Registration is strictly limited to prevent abuse. Each IP address can only register a limited number of accounts.
If you need additional API keys:
1. Use the key management endpoints to create additional keys for your existing account
2. Contact support for legitimate multi-account use cases
```typescript
// Create additional keys for existing account
const newKey = await wallet.auth.createKey();
console.log('New key:', newKey.apiKey);
// List all keys
const keys = await wallet.auth.listKeys();
// Revoke a key
await wallet.auth.revokeKey({ keyId: 'key_to_revoke' });
```
---
# Security Best Practices
> Keep your API keys and wallets secure
URL: https://docs.loomlay.com/sdk/security
# Security Best Practices
This guide covers essential security practices for using the SDK safely. The SDK supports two wallet modes with different security models.
## Self-Custody Security
In self-custody mode (`walletMode: 'local'`), your private keys never leave your device:
### Encryption
- **KDF**: PBKDF2-SHA512 with 600,000 iterations (exceeds OWASP 2024 recommendations) + random 32-byte salt
- **Cipher**: AES-256-GCM with random 12-byte IV and 16-byte auth tag
- **Storage**: `~/.loomlay/wallet.json` with `0600` permissions (owner read/write only)
- **Key zeroing**: Private key buffers are zeroed immediately after signing
### What Stays Local
- Encrypted seed phrase (in `~/.loomlay/wallet.json`)
- Passphrase (in-memory only, never written to disk)
- Transaction signing (decrypt → sign → zero → discard)
### What Goes to the API
- Public wallet addresses (for balance lookups)
- Signed transactions (for submission to the blockchain)
- Never: private keys, seed phrases, or passphrases
### Passphrase Management
The passphrase protects your encrypted wallet. Best practices:
```bash
# Recommended: Set as environment variable (avoids conversation logs)
export LOOMLAY_WALLET_PASSPHRASE=your-secure-passphrase
```
```typescript
// Or provide programmatically
const wallet = new OpenClawWallet({
apiKey: 'agent_xxx',
walletMode: 'local',
getPassphrase: async () => process.env.LOOMLAY_WALLET_PASSPHRASE!,
});
```
If using the OpenClaw Plugin, set `LOOMLAY_WALLET_PASSPHRASE` as an environment variable to avoid your passphrase appearing in conversation logs.
### Transaction Validation
Before signing any transaction locally, the SDK validates that the transaction's `feePayer` matches your local wallet address. This prevents signing malicious transactions that could drain your funds.
## API Key Security
### Never Commit Keys
```bash
# .gitignore
.env
.env.local
*.env
```
Never commit API keys to version control. Even if you remove them later, they remain in git history.
### Use Environment Variables
```typescript
// Good: Load from environment
const wallet = new OpenClawWallet({
apiKey: process.env.LOOMLAY_API_KEY!,
});
// Bad: Hardcoded key
const wallet = new OpenClawWallet({
apiKey: 'agent_abc123...', // Never do this!
});
```
### One Key Per Application
Each API key should be used by only one application:
- Development environment: separate key
- Staging environment: separate key
- Production environment: separate key
### Key Rotation
If you suspect a key is compromised:
1. Generate a new key via the API
2. Update your application with the new key
3. Revoke the old key
```typescript
// Generate new key
const newKey = await wallet.auth.createKey();
// After updating your app, revoke the old key
await wallet.auth.revokeKey({ keyId: 'old_key_id' });
```
## Seed Phrase Security
Your seed phrase is the master key to your wallet. Anyone with access to it can steal all your funds.
### Storage Guidelines
- **Never transmit** seed phrases over the internet
- **Never store** in plain text files
- **Never share** with anyone, including support
- Store offline in a secure location (encrypted USB, hardware wallet, paper backup)
### SDK Usage
The SDK only requires the seed phrase for key export:
```typescript
// Seed phrase NOT needed for:
await wallet.wallet.get(); // Check balances
await wallet.trading.swap({...}); // Execute swaps
await wallet.trading.transfer({...}); // Send tokens
// Seed phrase ONLY needed for:
await wallet.wallet.exportKeys({
seedPhrase: 'your twelve word seed phrase',
});
```
### For Large Amounts
Consider using self-custody mode (`walletMode: 'local'`) for maximum security. In custodial mode, the SDK-managed wallet stores keys server-side and is best suited for active trading amounts. For holdings above your risk tolerance, consider hardware wallet integration.
## Transaction Safety
### Verify Recipient Addresses
Always double-check addresses before transfers:
```typescript
const recipient = '7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU';
// Verify address format
if (!recipient.match(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/)) {
throw new Error('Invalid Solana address format');
}
await wallet.trading.transfer({
to: recipient,
token: 'USDC',
amount: '1000',
chain: 'solana',
});
```
### Quote Before Large Swaps
Always get a quote before executing large swaps:
```typescript
// First, get a quote
const quote = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '100',
quoteOnly: true,
});
console.log('Expected output:', quote.outputAmount);
console.log('Price impact:', quote.priceImpact, '%');
// Review the quote, then execute
if (quote.priceImpact < 1) {
const result = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '100',
});
}
```
### Set Appropriate Slippage
```typescript
// Default slippage is 0.5%
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '10',
slippage: 0.5, // 0.5% - good for liquid pairs
});
// For volatile or low-liquidity tokens, you may need higher slippage
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'MEMECOIN',
amount: '1',
slippage: 3, // 3% - for volatile tokens
});
```
### Monitor Price Impact
High price impact indicates you're moving the market:
```typescript
const quote = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '1000',
quoteOnly: true,
});
if (quote.priceImpact > 2) {
console.warn('High price impact! Consider smaller trade size.');
}
```
## Environment Setup
### Example .env File
```bash
# .env
# API key for LoomLay SDK
LOOMLAY_API_KEY=agent_your_key_here
# Optional: Seed phrase backup (only if you need key export)
# WARNING: Storing seed phrases in .env is risky
# Only do this if your server is highly secured
# LOOMLAY_SEED_PHRASE="word1 word2 word3 ..."
```
### Environment Validation
```typescript
function validateEnv() {
const apiKey = process.env.LOOMLAY_API_KEY;
if (!apiKey) {
throw new Error('LOOMLAY_API_KEY is required');
}
if (!apiKey.startsWith('agent_')) {
throw new Error('Invalid API key format');
}
return { apiKey };
}
const { apiKey } = validateEnv();
const wallet = new OpenClawWallet({ apiKey });
```
## Production Checklist
Before deploying to production:
- [ ] API keys loaded from environment variables
- [ ] `.env` files in `.gitignore`
- [ ] Seed phrases stored securely offline
- [ ] Error handling for all API calls
- [ ] Rate limit handling implemented
- [ ] Transaction amounts validated before execution
- [ ] Slippage limits appropriate for token liquidity
- [ ] Self-custody mode enabled for sensitive deployments (`walletMode: 'local'`)
- [ ] `LOOMLAY_WALLET_PASSPHRASE` set via environment variable (not in code)
- [ ] `~/.loomlay/wallet.json` permissions verified (`0600`)
---
# Token Launch
> Launch tokens on Solana with the SDK
URL: https://docs.loomlay.com/sdk/tokenize
# Token Launch
The `tokenize` resource lets you launch a token on Solana with instant liquidity.
**One Token Per Account:** Each agent account can only launch **one token ever**. This limit cannot be reset or bypassed. Once you launch a token, that account is permanently tied to it. Plan your token launch carefully before executing.
## Launch a Token
```typescript
const launch = await wallet.tokenize.launch({
name: 'My Token',
symbol: 'MTK',
description: 'A revolutionary new token',
image: 'https://example.com/token-image.png',
initialLiquidity: '10', // SOL
supply: '1000000000', // 1 billion
});
console.log('Token address:', launch.tokenAddress);
console.log('Pool address:', launch.poolAddress);
console.log('Transactions:', launch.txHashes);
```
## Check Launch Status
```typescript
const status = await wallet.tokenize.status();
if (status.launched) {
console.log('Token:', status.tokenAddress);
console.log('Pool:', status.poolAddress);
console.log('Launched at:', status.launchedAt);
} else {
console.log('No token launched yet');
}
```
## Fee Management
### Check Pending Fees
```typescript
const fees = await wallet.fees.getPending();
console.log('Pending fees:', fees.pendingAmount, 'SOL');
console.log('Total claimed:', fees.totalClaimed, 'SOL');
console.log('Last claim:', fees.lastClaimAt);
```
### Claim Fees
```typescript
const claim = await wallet.fees.claim();
console.log('Claimed:', claim.claimedAmount, 'SOL');
console.log('Transaction:', claim.txHash);
```
## Token Metadata
Metadata is stored on-chain via Metaplex:
```typescript
const launch = await wallet.tokenize.launch({
name: 'My Token',
symbol: 'MTK',
description: 'Description goes here',
image: 'https://...', // Required: PNG, JPG, or GIF
// Optional social links
twitter: 'https://twitter.com/mytoken',
telegram: 'https://t.me/mytoken',
website: 'https://mytoken.com',
initialLiquidity: '10',
});
```
## Requirements
- **SOL balance**: Enough for liquidity + transaction fees (~0.05 SOL for fees)
- **Image**: Valid URL to PNG, JPG, or GIF (min 200x200px)
- **Unique symbol**: Not already used on LoomLay
### Image Requirements
| Requirement | Details |
|-------------|---------|
| **Format** | PNG, JPG, or GIF |
| **Minimum size** | 200x200 pixels |
| **Maximum size** | 5MB |
| **URL** | Must be publicly accessible (no authentication) |
| **Hosting** | Use a reliable CDN (IPFS, Cloudflare, AWS S3) |
The image URL must be accessible at launch time. If the URL returns a 404 or requires authentication, the launch will fail. Consider using IPFS via Pinata or a CDN for reliable hosting.
## Common Issues
| Issue | Cause | Solution |
|-------|-------|----------|
| `INSUFFICIENT_FUNDS` | Not enough SOL for liquidity + fees | Ensure balance covers `initialLiquidity` + ~0.05 SOL for transaction fees |
| `INVALID_IMAGE` | Image URL not accessible or wrong format | Verify URL is publicly accessible and returns a valid image |
| `SYMBOL_TAKEN` | Symbol already used on LoomLay | Choose a different, unique symbol |
| `ALREADY_LAUNCHED` | Account already launched a token | Each account can only launch one token |
| `INVALID_SYMBOL` | Symbol too long or contains invalid characters | Use 2-10 uppercase alphanumeric characters |
| `NETWORK_ERROR` | RPC or network connectivity issue | Retry after a few seconds |
## Type Definitions
```typescript
interface TokenizeLaunchParams {
name: string;
symbol: string;
description: string;
image: string;
initialLiquidity: string;
supply?: string;
twitter?: string;
telegram?: string;
website?: string;
}
interface TokenizeLaunchResult {
success: boolean;
tokenAddress: string;
poolAddress: string;
txHashes: string[];
}
interface FeesResult {
pendingAmount: string;
totalClaimed: string;
lastClaimAt: string | null;
}
```
---
# Tools Reference
> Complete reference for all 29 tools available in the OpenClaw Plugin
URL: https://docs.loomlay.com/sdk/tools-reference
# Tools Reference
The OpenClaw Plugin provides 29 tools for multi-chain wallet management, trading, and market data. These tools are available when using the plugin with AI coding assistants like Claude Code.
## Table of Contents
| Category | Tools | Description |
|----------|-------|-------------|
| [Wallet](#wallet) | 5 | Create wallets, get balances, export keys, unlock, import |
| [Trading](#trading) | 5 | Swaps, transfers, and bridges |
| [Tokens](#tokens) | 4 | Search, price, details, and charts |
| [Portfolio](#portfolio) | 2 | Holdings and transaction history |
| [DEX](#dex) | 7 | Market data and rankings |
| [Tokenize](#tokenize) | 2 | Launch tokens on Solana |
| [Fees](#fees) | 2 | Fee status and claims |
| [RPC](#rpc) | 2 | Direct RPC access |
---
## Wallet
Tools for creating and managing multi-chain wallets.
### wallet_create
Create a new multi-chain wallet. In self-custody mode (default), keys are generated and encrypted locally on your device. Returns wallet addresses for Solana and EVM chains, plus a 12-word seed phrase shown only once.
**Parameters:** None
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `wallet.solanaAddress` | string | Solana wallet address |
| `wallet.evmAddress` | string | EVM wallet address (shared across all EVM chains) |
| `seedPhrase` | string | 12-word BIP39 seed phrase (shown only once) |
| `message` | string | Confirmation message |
**Example:**
```
User: Create a new wallet for me
Claude: I'll create a new multi-chain wallet for you.
[Uses wallet_create tool]
Result:
- Solana: 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU
- EVM: 0x742d35Cc6634C0532925a3b844Bc9e7595f8fE0d
- Seed phrase: abandon ability able about above absent...
```
The seed phrase is only shown once. Store it securely and never share it.
---
### wallet_get
Get wallet addresses and current balances across all chains.
**Parameters:** None
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `wallet.solanaAddress` | string | Solana wallet address |
| `wallet.evmAddress` | string | EVM wallet address |
| `balances.solana` | object | Solana native and token balances |
| `balances.evm` | object | EVM native and token balances |
**Example:**
```
User: What's my wallet balance?
Claude: I'll check your wallet balances.
[Uses wallet_get tool]
Result:
- Solana: 5.23 SOL + 100 USDC
- EVM: 0.15 ETH + 50 USDC (Base)
```
---
### wallet_export_keys
Export private keys for external wallet import. In self-custody mode, decrypts locally using passphrase. In custodial mode, requires seed phrase for verification.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `seedPhrase` | string | Custodial only | 12-word BIP39 seed phrase for verification (not needed in self-custody mode) |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `solanaPrivateKey` | string | Solana private key (base58) |
| `evmPrivateKey` | string | EVM private key (hex) |
**Example:**
```
User: Export my private keys, seed phrase is "abandon ability able..."
Claude: I'll export your private keys for external wallet import.
[Uses wallet_export_keys tool with seedPhrase]
Result:
- Solana key: 4wBqp...
- EVM key: 0x3a2f...
```
Only export keys when absolutely necessary. Exposing private keys risks losing all funds.
---
### wallet_unlock
Cache your wallet passphrase in memory for the current session. Required before signing transactions in self-custody mode.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `passphrase` | string | Yes | Passphrase used to encrypt/decrypt the local wallet |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `unlocked` | boolean | Whether the wallet was unlocked successfully |
| `message` | string | Confirmation message |
**Example:**
```
User: Unlock my wallet with passphrase "my-secure-pass"
Claude: I'll unlock your wallet for this session.
[Uses wallet_unlock tool with passphrase]
Result: Wallet unlocked. You can now sign transactions.
```
Set `LOOMLAY_WALLET_PASSPHRASE` as an environment variable to avoid the passphrase appearing in conversation logs.
---
### wallet_import
Import an existing BIP39 seed phrase into a local self-custody wallet. The seed phrase is encrypted locally and public addresses are registered with the API.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `seedPhrase` | string | Yes | 12-word BIP39 seed phrase to import |
| `passphrase` | string | Yes | Passphrase to encrypt the wallet locally |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `wallet.solanaAddress` | string | Derived Solana address |
| `wallet.evmAddress` | string | Derived EVM address |
| `seedPhrase` | string | The imported seed phrase (for confirmation) |
| `message` | string | Confirmation message |
**Example:**
```
User: Import my existing wallet with seed phrase "abandon ability able..."
Claude: I'll import your seed phrase into a local wallet.
[Uses wallet_import tool with seedPhrase and passphrase]
Result:
- Imported wallet locally
- Solana: 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU
- EVM: 0x742d35Cc6634C0532925a3b844Bc9e7595f8fE0d
```
The seed phrase is encrypted and stored locally at `~/.loomlay/wallet.json`. Only public addresses are sent to the API.
---
## Trading
Tools for executing swaps, transfers, and cross-chain bridges.
### swap
Execute a token swap. Supports flexible amounts: decimal (1.5), USD ($100), percentage (50%), or max.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `inputToken` | string | Yes | Token to sell (symbol or address) |
| `outputToken` | string | Yes | Token to buy (symbol or address) |
| `amount` | string | Yes | Amount to swap (e.g., '1.5', '$100', '50%', 'max') |
| `chain` | string | No | Chain: solana, ethereum, base, arbitrum, optimism, polygon, bsc |
| `slippage` | number | No | Max slippage percentage (default 1) |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `success` | boolean | Whether the swap succeeded |
| `txHash` | string | Transaction hash |
| `inputAmount` | string | Amount of input token spent |
| `outputAmount` | string | Amount of output token received |
**Example:**
```
User: Swap 1 SOL for USDC
Claude: I'll swap 1 SOL for USDC on Solana.
[Uses swap tool with inputToken="SOL", outputToken="USDC", amount="1"]
Result:
- Swapped 1 SOL for 98.52 USDC
- Transaction: 5xKq...
```
---
### swap_quote
Get a swap quote without executing. Use to show expected output before trading.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `inputToken` | string | Yes | Token to sell |
| `outputToken` | string | Yes | Token to buy |
| `amount` | string | Yes | Amount to swap |
| `chain` | string | No | Target chain |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `inputAmount` | string | Input amount |
| `outputAmount` | string | Expected output amount |
| `minOutputAmount` | string | Minimum output with slippage |
| `priceImpact` | number | Price impact percentage |
| `route` | string | Routing description |
**Example:**
```
User: How much USDC would I get for 10 SOL?
Claude: I'll get a quote for swapping 10 SOL to USDC.
[Uses swap_quote tool]
Result:
- Expected output: 985.20 USDC
- Minimum output: 975.35 USDC (1% slippage)
- Price impact: 0.05%
```
---
### transfer
Transfer tokens to another address.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `token` | string | Yes | Token to transfer (symbol or address) |
| `amount` | string | Yes | Amount to transfer |
| `to` | string | Yes | Recipient address |
| `chain` | string | No | Target chain |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `success` | boolean | Whether the transfer succeeded |
| `txHash` | string | Transaction hash |
| `amount` | string | Amount transferred |
| `token` | string | Token transferred |
| `to` | string | Recipient address |
**Example:**
```
User: Send 50 USDC to 7xKXtg...
Claude: I'll transfer 50 USDC to the specified address.
[Uses transfer tool]
Result:
- Sent 50 USDC to 7xKXtg...
- Transaction: 3nPq...
```
---
### bridge
Bridge tokens between different chains (e.g., Solana to Base).
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `inputToken` | string | Yes | Token to bridge |
| `amount` | string | Yes | Amount to bridge |
| `sourceChain` | string | Yes | Source chain |
| `destinationChain` | string | Yes | Destination chain |
| `outputToken` | string | No | Output token (if different) |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `success` | boolean | Whether the bridge initiated successfully |
| `sourceTxHash` | string | Source chain transaction hash |
| `destinationTxHash` | string | Destination chain transaction hash |
| `status` | string | Bridge status |
**Example:**
```
User: Bridge 100 USDC from Ethereum to Base
Claude: I'll bridge 100 USDC from Ethereum to Base.
[Uses bridge tool]
Result:
- Bridge initiated
- Source tx: 0x4a2f...
- Estimated completion: ~2 minutes
```
---
### bridge_quote
Get a bridge quote showing fees and estimated time.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `inputToken` | string | Yes | Token to bridge |
| `amount` | string | Yes | Amount to bridge |
| `sourceChain` | string | Yes | Source chain |
| `destinationChain` | string | Yes | Destination chain |
| `outputToken` | string | No | Output token |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `inputAmount` | string | Input amount |
| `outputAmount` | string | Expected output after fees |
| `fee` | string | Bridge fee |
| `estimatedTime` | number | Estimated time in seconds |
**Example:**
```
User: How much would it cost to bridge 1000 USDC to Arbitrum?
Claude: I'll get a quote for bridging 1000 USDC to Arbitrum.
[Uses bridge_quote tool]
Result:
- Input: 1000 USDC
- Output: 998.50 USDC
- Fee: 1.50 USDC
- Time: ~90 seconds
```
---
## Tokens
Tools for searching and analyzing tokens.
### token_search
Search for tokens by name, symbol, or address.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `query` | string | Yes | Search query (min 2 characters) |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `tokens` | array | Array of matching tokens with address, name, symbol, chain, and safety info |
**Example:**
```
User: Find the BONK token
Claude: I'll search for BONK.
[Uses token_search tool with query="BONK"]
Result:
- BONK (DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263)
- Chain: Solana
- Safety score: 85
```
---
### token_price
Get current USD price for a token.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `token` | string | Yes | Token symbol or address |
| `chain` | string | No | Chain filter |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `token` | string | Token identifier |
| `price` | number | Current USD price |
| `chain` | string | Token chain |
**Example:**
```
User: What's the price of SOL?
Claude: I'll check the current price of SOL.
[Uses token_price tool]
Result: SOL is currently $98.52
```
---
### token_details
Get detailed information about a token including market data and safety analysis.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `address` | string | Yes | Token address |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `token` | object | Token info (name, symbol, decimals) |
| `market` | object | Market data (price, volume, market cap) |
| `safety` | object | Safety analysis (score, flags, verified) |
**Example:**
```
User: Give me details on token DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263
Claude: I'll get detailed information on this token.
[Uses token_details tool]
Result:
- Name: Bonk
- Price: $0.0000234
- Market Cap: $1.5B
- 24h Volume: $45M
- Safety Score: 85/100
- Verified: Yes
```
---
### token_chart
Get OHLCV chart data for a token.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `address` | string | Yes | Token address |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `data` | array | OHLCV candle data (timestamp, open, high, low, close, volume) |
**Example:**
```
User: Show me the price chart for BONK
Claude: I'll fetch the chart data for BONK.
[Uses token_chart tool]
Result: Returns OHLCV data for charting
```
---
## Portfolio
Tools for viewing holdings and transaction history.
### portfolio_get
Get combined portfolio across all chains with total USD value.
**Parameters:** None
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `positions` | array | Array of holdings with token, balance, value, and chain |
| `totalUsdValue` | number | Total portfolio value in USD |
**Example:**
```
User: What's in my portfolio?
Claude: I'll get your complete portfolio.
[Uses portfolio_get tool]
Result:
- SOL: 5.23 ($515)
- USDC: 150 ($150)
- BONK: 1,000,000 ($23)
- Total: $688
```
---
### portfolio_history
Get transaction history.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `chain` | string | No | Filter by chain |
| `limit` | number | No | Max results (default 50) |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `transactions` | array | Array of transactions with type, amount, token, hash, timestamp |
**Example:**
```
User: Show my recent transactions
Claude: I'll fetch your transaction history.
[Uses portfolio_history tool]
Result:
- Swap: 1 SOL -> 98.52 USDC (2 hours ago)
- Transfer: 50 USDC to 7xKX... (5 hours ago)
- Receive: 5 SOL from 3nPq... (1 day ago)
```
---
## DEX
Tools for accessing DexScreener market data.
### dex_trending
Get trending trading pairs by trending score.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `chain` | string | No | Filter by chain |
| `minLiquidity` | number | No | Minimum liquidity in USD |
| `minSafetyScore` | number | No | Minimum safety score (0-100) |
| `limit` | number | No | Maximum results |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `pairs` | array | Array of trending pairs with token info, price, volume, liquidity |
| `pagination` | object | Pagination info |
**Example:**
```
User: What's trending on Solana?
Claude: I'll check the trending pairs on Solana.
[Uses dex_trending tool with chain="solana"]
Result:
1. WIF/SOL - $2.45 (+150%)
2. BONK/SOL - $0.000023 (+45%)
3. JUP/SOL - $0.89 (+12%)
```
---
### dex_volume
Get top trading pairs by 24h volume.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `chain` | string | No | Filter by chain |
| `minLiquidity` | number | No | Minimum liquidity in USD |
| `limit` | number | No | Maximum results |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `pairs` | array | Array of pairs sorted by 24h volume |
| `pagination` | object | Pagination info |
**Example:**
```
User: What tokens have the highest volume today?
Claude: I'll check the highest volume pairs.
[Uses dex_volume tool]
Result:
1. SOL/USDC - $1.2B volume
2. WIF/SOL - $450M volume
3. JUP/USDC - $120M volume
```
---
### dex_gainers
Get top price gainers (24h).
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `chain` | string | No | Filter by chain |
| `minLiquidity` | number | No | Minimum liquidity in USD |
| `limit` | number | No | Maximum results |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `pairs` | array | Array of pairs sorted by 24h price gain |
**Example:**
```
User: What are the top gainers today?
Claude: I'll check the top gainers.
[Uses dex_gainers tool]
Result:
1. MEME/SOL - +450%
2. NEW/SOL - +280%
3. PUMP/SOL - +150%
```
---
### dex_losers
Get top price losers (24h).
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `chain` | string | No | Filter by chain |
| `minLiquidity` | number | No | Minimum liquidity in USD |
| `limit` | number | No | Maximum results |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `pairs` | array | Array of pairs sorted by 24h price loss |
**Example:**
```
User: What tokens dropped the most today?
Claude: I'll check the top losers.
[Uses dex_losers tool]
Result:
1. RUG/SOL - -85%
2. DUMP/SOL - -72%
3. OLD/SOL - -45%
```
---
### dex_new
Get newly created pairs (less than 24 hours old).
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `chain` | string | No | Filter by chain |
| `minLiquidity` | number | No | Minimum liquidity in USD |
| `limit` | number | No | Maximum results |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `pairs` | array | Array of new pairs |
| `maxAgeHours` | number | Maximum age filter applied |
**Example:**
```
User: What new tokens launched today?
Claude: I'll check for newly launched tokens.
[Uses dex_new tool]
Result:
1. NEW1/SOL - Launched 2h ago, $50K liquidity
2. NEW2/SOL - Launched 5h ago, $120K liquidity
3. NEW3/SOL - Launched 8h ago, $30K liquidity
```
---
### dex_pumpfun
Get Pumpfun trending pairs (Solana only, bonding curve tokens).
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `maxAge` | number | No | Maximum age in hours |
| `maxProgress` | number | No | Maximum bonding curve progress percentage |
| `limit` | number | No | Maximum results |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `pairs` | array | Array of Pumpfun pairs with bonding curve info |
**Example:**
```
User: What's trending on Pumpfun?
Claude: I'll check Pumpfun trending tokens.
[Uses dex_pumpfun tool]
Result:
1. PUMP1 - 75% bonding curve, $45K market cap
2. PUMP2 - 50% bonding curve, $22K market cap
3. PUMP3 - 30% bonding curve, $12K market cap
```
---
### dex_query
Advanced DEX query with custom filters and ranking.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `chain` | string | No | Filter by chain |
| `timeframe` | string | No | Timeframe: m5, h1, h6, h24 |
| `rankBy` | string | No | Ranking: volume, txns, priceChangeH24, liquidity, fdv |
| `order` | string | No | Order: asc or desc |
| `filters` | object | No | Range filters for liquidity, volume, etc. |
| `minSafetyScore` | number | No | Minimum safety score |
| `limit` | number | No | Maximum results |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `pairs` | array | Array of pairs matching query |
| `pagination` | object | Pagination info |
**Example:**
```
User: Find Solana tokens with >$100K liquidity, sorted by transactions
Claude: I'll search for high-liquidity Solana tokens.
[Uses dex_query tool with chain="solana", filters={minLiquidity: 100000}, rankBy="txns"]
Result:
1. SOL/USDC - 15K txns, $50M liquidity
2. WIF/SOL - 8K txns, $5M liquidity
3. BONK/SOL - 6K txns, $2M liquidity
```
---
## Tokenize
Tools for launching tokens on Solana.
### tokenize_launch
Launch a new token on Solana with automatic pool creation. One token per account.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `name` | string | Yes | Token name (1-32 characters) |
| `symbol` | string | Yes | Token symbol (2-10 uppercase letters) |
| `tier` | string | No | Market cap tier: 10k, 100k, 1m, 10m (default 100k) |
| `imageUrl` | string | No | Token logo URL (PNG/JPEG, square) |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `success` | boolean | Whether the launch succeeded |
| `launchId` | string | Unique launch identifier |
| `tokenMint` | string | Token mint address |
| `poolAddress` | string | Liquidity pool address |
| `dexscreenerUrl` | string | DexScreener URL for the token |
**Example:**
```
User: Launch a token called "My Token" with symbol MTK
Claude: I'll launch your token on Solana.
[Uses tokenize_launch tool]
Result:
- Token launched successfully!
- Mint: 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU
- Pool: 3nPqD...
- DexScreener: https://dexscreener.com/solana/7xKXtg...
```
Each account can only launch **one token ever**. This limit cannot be reset.
---
### tokenize_info
Get information about your launched token.
**Parameters:** None
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `hasToken` | boolean | Whether the account has launched a token |
| `launchId` | string | Launch identifier |
| `tokenMint` | string | Token mint address |
| `poolAddress` | string | Pool address |
| `dexscreenerUrl` | string | DexScreener URL |
**Example:**
```
User: What token did I launch?
Claude: I'll check your launched token.
[Uses tokenize_info tool]
Result:
- Token: My Token (MTK)
- Mint: 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU
- Pool: 3nPqD...
```
---
## Fees
Tools for managing trading fees from launched tokens.
### fees_status
Get fee status for your launched token including generated, claimed, and unclaimed amounts.
**Parameters:** None
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `totalFeesGeneratedSol` | number | Total fees generated in SOL |
| `beneficiaryFeesEarnedSol` | number | Your share of fees earned |
| `beneficiaryFeesClaimedSol` | number | Fees already claimed |
| `beneficiaryFeesUnclaimedSol` | number | Fees available to claim |
| `canClaim` | boolean | Whether fees can be claimed now |
| `feeForfeitsAt` | string | Deadline for claiming before forfeiture |
**Example:**
```
User: How much in fees have I earned?
Claude: I'll check your fee status.
[Uses fees_status tool]
Result:
- Total generated: 5.23 SOL
- Your share: 3.14 SOL (60%)
- Claimed: 1.00 SOL
- Unclaimed: 2.14 SOL
- Can claim: Yes
```
---
### fees_claim
Claim accumulated trading fees from your launched token (platform pays gas).
**Parameters:** None
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `success` | boolean | Whether the claim succeeded |
| `amountSol` | number | Amount claimed in SOL |
| `txSignature` | string | Transaction signature |
**Example:**
```
User: Claim my fees
Claude: I'll claim your accumulated fees.
[Uses fees_claim tool]
Result:
- Claimed 2.14 SOL
- Transaction: 5xKq...
```
The platform pays gas fees for claiming, so you receive the full amount.
---
## RPC
Tools for direct RPC access to supported chains.
### rpc_call
Make a direct RPC call to any supported chain.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `chain` | string | Yes | Target chain |
| `method` | string | Yes | RPC method name |
| `params` | array | No | Method parameters |
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `result` | any | RPC response result |
| `error` | object | Error object if call failed |
**Example:**
```
User: Get the latest Solana block height
Claude: I'll make an RPC call to get the block height.
[Uses rpc_call tool with chain="solana", method="getBlockHeight"]
Result: Block height: 245,892,341
```
---
### rpc_chains
Get list of supported chains for RPC access.
**Parameters:** None
**Returns:**
| Field | Type | Description |
|-------|------|-------------|
| `chains` | array | Array of supported chain names |
**Example:**
```
User: What chains support RPC calls?
Claude: I'll check the supported chains.
[Uses rpc_chains tool]
Result: Supported chains: solana, ethereum, base, arbitrum, optimism, polygon, bsc
```
---
# Trading
> Swaps, transfers, and bridges with the SDK
URL: https://docs.loomlay.com/sdk/trading
# Trading
The `trading` resource handles swaps, transfers, and cross-chain bridges.
## Supported DEXes
| Chain | DEX Provider | Features |
|-------|--------------|----------|
| Solana | Jupiter | Best price routing across all Solana DEXes |
| Ethereum | Relay | Cross-chain swaps and bridges |
| Base | Relay | Cross-chain swaps and bridges |
| Arbitrum | Relay | Cross-chain swaps and bridges |
## Self-Custody Signing Flow
In self-custody mode (`walletMode: 'local'`), swaps and transfers follow a build → sign → submit flow where signing happens locally:
```
┌─────────┐ ┌─────────┐ ┌─────────────┐ ┌─────────┐
│ Your │────>│ API │────>│ Your │────>│ API │
│ App │ │ Server │ │ Device │ │ Server │
│ │ │ │ │ (signing) │ │ │
│ swap() │ │ /build │ │ sign tx │ │ /execute│
└─────────┘ └─────────┘ └─────────────┘ └─────────┘
```
1. **Build**: API builds an unsigned transaction (no private keys needed)
2. **Sign**: SDK decrypts your local wallet and signs the transaction on your device
3. **Submit**: Signed transaction sent to API for blockchain submission
This is handled automatically — the same `swap()` and `transfer()` API works in both modes.
EVM chain operations (bridges) currently use custodial mode regardless of your `walletMode` setting. Local EVM signing is planned for a future release.
## Swaps
Swap tokens on the same chain:
```typescript
const result = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '1.5',
slippage: 0.5, // Optional, default 0.5%
});
console.log('Input:', result.inputAmount, 'SOL');
console.log('Output:', result.outputAmount, 'USDC');
console.log('Transaction:', result.txHash);
```
### Slippage Recommendations
| Token Type | Recommended Slippage | Notes |
|------------|---------------------|-------|
| Stablecoins (USDC, USDT) | 0.1% - 0.5% | Low volatility, tight spreads |
| Major tokens (SOL, ETH) | 0.5% - 1% | Moderate volatility |
| Volatile/low liquidity | 1% - 3% | Higher slippage needed to ensure execution |
| Meme tokens | 3% - 5%+ | High volatility, consider using `quoteOnly` first |
**Price Impact Warning:** Always check `priceImpact` in the quote response before executing large trades. A price impact above 1% indicates significant market movement. Above 5% suggests you should consider splitting the trade into smaller amounts.
### Quote Only
Get a quote without executing:
```typescript
const quote = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '1.5',
quoteOnly: true,
});
console.log('Expected output:', quote.outputAmount, 'USDC');
console.log('Price impact:', quote.priceImpact, '%');
```
### EVM Swaps
```typescript
const result = await wallet.trading.swap({
inputToken: 'ETH',
outputToken: 'USDC',
amount: '0.1',
chain: 'ethereum', // Specify chain for EVM
});
```
**Gas Estimation:** On EVM chains, gas fees are estimated automatically based on current network conditions. The SDK uses a priority fee multiplier to ensure timely execution. During high congestion, transactions may take longer or require higher gas. Consider using `quoteOnly` to preview the expected gas cost before executing.
## Transfers
Send tokens to another address:
```typescript
const result = await wallet.trading.transfer({
to: 'recipient_address',
token: 'USDC',
amount: '100',
chain: 'solana',
});
console.log('Sent:', result.amount, result.token);
console.log('Transaction:', result.txHash);
```
### Send Native Tokens
```typescript
// Send SOL
await wallet.trading.transfer({
to: 'recipient',
token: 'SOL',
amount: '1',
chain: 'solana',
});
// Send ETH
await wallet.trading.transfer({
to: '0x...',
token: 'ETH',
amount: '0.1',
chain: 'ethereum',
});
```
## Bridges
Bridge tokens between EVM chains:
```typescript
const result = await wallet.trading.bridge({
fromChain: 'ethereum',
toChain: 'base',
token: 'USDC',
amount: '100',
});
console.log('Bridge initiated');
console.log('Source tx:', result.sourceTxHash);
console.log('Estimated time:', result.estimatedTime);
```
Bridges are only available between EVM chains. Solana bridges are not yet supported.
## Token Resolution
The SDK resolves token names to addresses:
```typescript
// All these work
await wallet.trading.swap({ inputToken: 'SOL', ... });
await wallet.trading.swap({ inputToken: 'USDC', ... });
await wallet.trading.swap({
inputToken: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC address
...
});
```
## Type Definitions
```typescript
interface SwapParams {
inputToken: string;
outputToken: string;
amount: string;
chain?: string;
slippage?: number;
quoteOnly?: boolean;
}
interface SwapResult {
inputAmount: string;
outputAmount: string;
txHash?: string;
chain: string;
priceImpact?: number;
}
interface TransferParams {
to: string;
token: string;
amount: string;
chain: string;
}
interface BridgeParams {
fromChain: string;
toChain: string;
token: string;
amount: string;
}
```
---
# Wallet Management
> Creating and managing wallets with the SDK
URL: https://docs.loomlay.com/sdk/wallet
# Wallet Management
The SDK provides a `wallet` resource for managing multi-chain wallets. It supports two modes:
| Mode | Keys Stored | Signing | Best For |
|------|-------------|---------|----------|
| `local` (self-custody) | Client-side (`~/.loomlay/wallet.json`) | Client | Maximum security, self-custody |
| `custodial` | Server-side (encrypted in PostgreSQL) | Server | Simple integration |
## Wallet Modes
### Self-Custody Mode (Recommended)
In self-custody mode, private keys are generated and encrypted locally on your device. They are never sent to any server. The API only receives public addresses for balance lookups.
```typescript
const wallet = new OpenClawWallet({
apiKey: 'agent_xxx',
walletMode: 'local',
getPassphrase: async () => process.env.LOOMLAY_WALLET_PASSPHRASE!,
});
```
### Custodial Mode
In custodial mode, the API manages keys server-side. This is simpler but requires trusting the server with your keys.
```typescript
const wallet = new OpenClawWallet({
apiKey: 'agent_xxx',
// walletMode defaults to 'custodial' in SDK
});
```
The OpenClaw Plugin defaults to **self-custody** (`walletMode: 'local'`). The SDK defaults to `'custodial'` for backwards compatibility.
## Create a Wallet
```typescript
// Keys generated and encrypted locally
const created = await wallet.wallet.create();
console.log('Seed phrase:', created.seedPhrase); // Save securely!
console.log('Solana:', created.wallet.solanaAddress);
console.log('EVM:', created.wallet.evmAddress);
// Public addresses auto-registered with API
```
```typescript
const created = await wallet.wallet.create();
console.log('Seed phrase:', created.seedPhrase);
console.log('Solana:', created.solanaAddress);
console.log('EVM:', created.evmAddress);
```
The seed phrase is the only way to recover your wallet. Store it securely and never share it.
**Security Best Practices:**
- Never log or print seed phrases in production code
- Store seed phrases in encrypted secret managers (e.g., AWS Secrets Manager, HashiCorp Vault)
- Never commit seed phrases to version control
- Use environment variables only for development; use proper secrets management in production
## Supported Chains
The SDK derives addresses for multiple chains from a single BIP39 seed phrase:
| Chain | Derivation Path | Curve | Address Format |
|-------|-----------------|-------|----------------|
| Solana | `m/44'/501'/0'/0'` | ed25519 | Base58 |
| Ethereum | `m/44'/60'/0'/0/0` | secp256k1 | 0x-prefixed hex |
| Base | Same as Ethereum | secp256k1 | 0x-prefixed hex |
| Arbitrum | Same as Ethereum | secp256k1 | 0x-prefixed hex |
All EVM chains share the same address derived from the secp256k1 curve. Solana uses a separate ed25519-based address.
## Get Wallet Info
```typescript
const info = await wallet.wallet.get();
console.log('Addresses:', {
solana: info.solanaAddress,
evm: info.evmAddress,
});
// Solana balances
console.log('SOL:', info.balances.solana.native);
for (const token of info.balances.solana.tokens) {
console.log(`${token.symbol}: ${token.balance}`);
}
// EVM balances (aggregated across chains)
console.log('ETH:', info.balances.ethereum.native);
```
**Balance Caching:** Balances are fetched in real-time from chain RPC nodes and portfolio APIs. For high-frequency applications, consider caching balances locally and refreshing periodically (e.g., every 30 seconds) to reduce API calls.
## Import an Existing Wallet
Import an existing seed phrase into a local self-custody wallet (self-custody mode only):
```typescript
const imported = await wallet.wallet.importSeed(
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
'my-secure-passphrase'
);
console.log('Imported:', imported.wallet.solanaAddress);
// Addresses auto-registered with API
```
## Register External Addresses
Register externally-managed wallet addresses with the API for balance lookups:
```typescript
await wallet.wallet.register({
solanaAddress: 'your-solana-address',
evmAddress: '0xyour-evm-address', // Optional
});
```
## Export Private Keys
Only export keys when absolutely necessary. Exposing private keys risks losing all funds.
```typescript
// Decrypts locally using passphrase — no API call needed
const keys = await wallet.wallet.exportKeys('any-seed-phrase');
console.log('Solana private key:', keys.solana.privateKey);
console.log('EVM private key:', keys.evm.privateKey);
```
```typescript
const keys = await wallet.wallet.exportKeys('your twelve word seed phrase here');
console.log('Solana private key:', keys.solana.privateKey);
console.log('EVM private key:', keys.evm.privateKey);
```
## Portfolio View
Get a comprehensive view of holdings across all chains:
```typescript
const portfolio = await wallet.portfolio.get();
for (const holding of portfolio.holdings) {
console.log(`${holding.symbol} on ${holding.chain}`);
console.log(` Balance: ${holding.balance}`);
console.log(` Value: $${holding.valueUsd}`);
}
console.log('Total portfolio value:', portfolio.totalValueUsd);
```
## Transaction History
```typescript
const history = await wallet.portfolio.history({
limit: 20,
chain: 'solana', // Optional filter
});
for (const tx of history.transactions) {
console.log(`${tx.type}: ${tx.amount} ${tx.token}`);
console.log(` Hash: ${tx.txHash}`);
console.log(` Time: ${tx.timestamp}`);
}
```
## Type Definitions
```typescript
interface WalletCreateResult {
seedPhrase: string;
solanaAddress: string;
evmAddress: string;
}
interface WalletInfo {
solanaAddress: string;
evmAddress: string;
balances: {
solana: ChainBalance;
ethereum: ChainBalance;
// ... other chains
};
}
interface ChainBalance {
native: string;
tokens: TokenBalance[];
}
interface TokenBalance {
address: string;
symbol: string;
name: string;
balance: string;
decimals: number;
}
```
---
# WebSockets
> Real-time data subscriptions with the SDK
URL: https://docs.loomlay.com/sdk/websockets
# WebSockets
The SDK provides typed WebSocket clients for real-time data.
## Connection Lifecycle
WebSocket connections follow this lifecycle:
1. **Connect** - Establish connection to the server
2. **Authenticate** - API key is validated on first message
3. **Subscribe** - Register for specific data channels
4. **Receive** - Data is pushed to your callbacks
5. **Unsubscribe** - Remove specific subscriptions
6. **Disconnect** - Close the connection
```
┌─────────┐ ┌──────────────┐ ┌───────────┐ ┌─────────┐
│ connect │───>│ authenticate │───>│ subscribe │───>│ receive │
└─────────┘ └──────────────┘ └───────────┘ └────┬────┘
│
┌────────────┐ ┌─────────────┐ │
│ disconnect │<───│ unsubscribe │<──┘
└────────────┘ └─────────────┘
```
## DEX WebSocket
Subscribe to real-time market data:
```typescript
const dexWs = wallet.createDexWebSocket();
// Connect
await dexWs.connect();
// Subscribe to trending pairs
const subId = await dexWs.subscribe(
{ chain: 'solana', minLiquidity: 10000 },
(pairs) => {
console.log('Trending pairs updated:', pairs.length);
for (const pair of pairs) {
console.log(`${pair.baseToken.symbol}: $${pair.priceUsd}`);
}
}
);
// Later: unsubscribe and disconnect
dexWs.unsubscribe(subId);
dexWs.disconnect();
```
### Heartbeat / Ping
The server sends periodic ping frames to keep the connection alive. The SDK handles pong responses automatically. If no ping is received for 60 seconds, the connection is considered stale and will be closed.
**Max Subscriptions:** Each WebSocket connection supports up to **50 active subscriptions**. If you need more, open additional connections. Subscriptions are counted per connection, not per API key.
### Subscription Filters
```typescript
await dexWs.subscribe(
{
chain: 'solana',
minLiquidity: 10000, // Minimum USD liquidity
minVolume: 5000, // Minimum 24h volume
channel: 'trending', // trending, gainers, losers, new
},
(pairs) => console.log(pairs)
);
```
### Multiple Subscriptions
```typescript
// Subscribe to multiple channels
const trendingId = await dexWs.subscribe(
{ channel: 'trending', chain: 'solana' },
handleTrending
);
const gainersId = await dexWs.subscribe(
{ channel: 'gainers', chain: 'solana' },
handleGainers
);
// Unsubscribe individually
dexWs.unsubscribe(trendingId);
dexWs.unsubscribe(gainersId);
// Or unsubscribe all
dexWs.unsubscribeAll();
```
## Chain WebSocket
Subscribe to on-chain events:
```typescript
const chainWs = wallet.createChainWebSocket('solana');
await chainWs.connect();
// Subscribe to account changes
const subId = await chainWs.subscribe(
'accountSubscribe',
['wallet_address', { encoding: 'jsonParsed' }],
(data) => {
console.log('Account updated:', data);
}
);
// Unsubscribe
await chainWs.unsubscribe(subId);
chainWs.disconnect();
```
### Solana Subscriptions
```typescript
// Account changes
await chainWs.subscribe('accountSubscribe', [address], callback);
// Program logs
await chainWs.subscribe('logsSubscribe', [{ mentions: [programId] }], callback);
// Slot updates
await chainWs.subscribe('slotSubscribe', [], callback);
```
## Reconnection
Both WebSocket clients support automatic reconnection:
```typescript
const dexWs = wallet.createDexWebSocket({
reconnect: true,
maxReconnectAttempts: 5,
reconnectDelay: 1000, // Base delay in ms (uses exponential backoff)
});
```
### Reconnection Best Practices
**Important:** Subscriptions are NOT automatically restored after reconnection. You must re-subscribe to channels after the `connected` event fires.
```typescript
const dexWs = wallet.createDexWebSocket({
reconnect: true,
maxReconnectAttempts: 5,
reconnectDelay: 1000,
});
// Track active subscriptions for re-subscription
const activeSubscriptions: DexSubscriptionParams[] = [];
dexWs.on('connected', async () => {
console.log('Connected - restoring subscriptions');
// Re-subscribe to all channels after reconnection
for (const params of activeSubscriptions) {
await dexWs.subscribe(params, handleData);
}
});
dexWs.on('disconnected', () => {
console.log('Disconnected - will attempt reconnection');
});
dexWs.on('reconnecting', (attempt) => {
console.log(`Reconnection attempt ${attempt} of 5`);
});
// Store subscription params when subscribing
const params = { channel: 'trending', chain: 'solana' };
activeSubscriptions.push(params);
await dexWs.subscribe(params, handleData);
```
### Exponential Backoff
Reconnection uses exponential backoff with jitter:
| Attempt | Base Delay | With Jitter (approx) |
|---------|------------|---------------------|
| 1 | 1s | 1-1.5s |
| 2 | 2s | 2-3s |
| 3 | 4s | 4-6s |
| 4 | 8s | 8-12s |
| 5 | 16s | 16-24s |
After `maxReconnectAttempts` is reached, the client stops reconnecting and emits an `error` event.
### Connection Events
```typescript
dexWs.on('connected', () => console.log('Connected'));
dexWs.on('disconnected', () => console.log('Disconnected'));
dexWs.on('reconnecting', (attempt) => console.log(`Reconnecting... attempt ${attempt}`));
dexWs.on('error', (error) => console.error('Error:', error));
```
## Type Definitions
```typescript
interface DexWebSocketOptions {
reconnect?: boolean;
maxReconnectAttempts?: number;
reconnectDelay?: number;
}
interface DexSubscriptionParams {
chain?: string;
channel?: 'trending' | 'gainers' | 'losers' | 'new';
minLiquidity?: number;
minVolume?: number;
}
interface ChainWebSocketOptions {
reconnect?: boolean;
maxReconnectAttempts?: number;
reconnectDelay?: number;
}
```