参数
接收空投的账户公钥(base-58 编码)
请求的 lamports 数量(1 SOL = 1,000,000,000 lamports)
响应
空投的交易签名(base-58 编码)
代码示例
基本请求
复制
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "requestAirdrop",
"params": [
"83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri",
1000000000
]
}'
使用 web3.js
复制
import { Connection, PublicKey } from '@solana/web3.js';
const connection = new Connection('https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY');
// Request airdrop
const signature = await connection.requestAirdrop(
new PublicKey('83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri'),
1000000000 // 1 SOL
);
console.log('Airdrop signature:', signature);
// Request airdrop with confirmation
async function requestAirdropWithConfirmation(
pubkey: string,
lamports: number,
config: { commitment?: string }
) {
const signature = await connection.requestAirdrop(
new PublicKey(pubkey),
lamports,
config
);
// Wait for confirmation
const confirmation = await connection.confirmTransaction(signature);
return {
signature,
confirmation: {
status: confirmation.value.err ? 'failed' : 'success',
slot: confirmation.context.slot
},
request: {
pubkey,
lamports,
formatted: lamports / 1e9 + ' SOL'
},
metadata: {
timestamp: Date.now(),
commitment: config.commitment
}
};
}
注意事项
- 向 Solana 账户请求空投 SOL
- 仅在测试网络(devnet、testnet)上可用
- 响应是交易签名
- 交易必须被确认后资金才可用
- 金额根据网络配置有限制
最佳实践
- 根据需求使用适当的 commitment 级别
- 在继续之前等待交易确认
- 处理速率限制和网络错误
- 考虑使用水龙头服务获取更大金额
- 监控交易状态以检测失败
常见错误
| 错误码 | 消息 | 解决方案 |
|---|---|---|
| -32601 | Method not found | 验证是否连接到测试网络 |
| -32602 | Invalid params | 检查公钥格式和 lamports 数量 |
| -32003 | Transaction simulation failed | 金额可能超出限制或账户可能无效 |
用例
-
空投管理
复制
interface AirdropRequest { request: { pubkey: string; lamports: number; formatted: string; }; transaction: { signature: string; status: 'pending' | 'success' | 'failed'; confirmations: number; }; metadata: { timestamp: number; network: string; commitment?: string; }; } class AirdropManager { private readonly maxRetries = 3; private readonly confirmationTimeout = 30000; // 30 seconds async requestAirdrop( pubkey: string, lamports: number, config: { commitment?: string } ): Promise<AirdropRequest> { let retries = 0; let signature: string; while (retries < this.maxRetries) { try { signature = await connection.requestAirdrop( new PublicKey(pubkey), lamports, config ); // Wait for confirmation const confirmation = await connection.confirmTransaction(signature, config.commitment); if (!confirmation.value.err) { return { request: { pubkey, lamports, formatted: lamports / 1e9 + ' SOL' }, transaction: { signature, status: 'success', confirmations: 1 }, metadata: { timestamp: Date.now(), network: connection.rpcEndpoint, commitment: config.commitment } }; } } catch (error) { retries++; if (retries === this.maxRetries) { throw error; } await new Promise(resolve => setTimeout(resolve, 1000)); } } } } -
空投监控
复制
interface AirdropStatus { request: { pubkey: string; lamports: number; }; status: { signature: string; confirmations: number; slot: number; }; history: Array<{ timestamp: number; status: string; confirmations: number; }>; } class AirdropMonitor { private requests: Map<string, AirdropStatus> = new Map(); async monitorAirdrop( signature: string, request: { pubkey: string; lamports: number; } ): Promise<AirdropStatus> { let status = this.requests.get(signature); const now = Date.now(); const confirmation = await connection.getSignatureStatus(signature); if (!status) { status = { request, status: { signature, confirmations: confirmation?.confirmations || 0, slot: confirmation?.slot || 0 }, history: [{ timestamp: now, status: confirmation ? 'confirmed' : 'pending', confirmations: confirmation?.confirmations || 0 }] }; } else { status.status.confirmations = confirmation?.confirmations || 0; status.status.slot = confirmation?.slot || 0; status.history.push({ timestamp: now, status: confirmation ? 'confirmed' : 'pending', confirmations: confirmation?.confirmations || 0 }); } this.requests.set(signature, status); return status; } } -
空投规划
复制
interface AirdropPlan { request: { pubkey: string; lamports: number; formatted: string; }; recommendations: Array<{ type: 'proceed' | 'split' | 'abort'; reason: string; }>; metadata: { timestamp: number; }; } class AirdropPlanner { private readonly maxAirdrop = 2000000000; // 2 SOL private readonly minAirdrop = 100000; // 0.0001 SOL async planAirdrop( pubkey: string, lamports: number ): Promise<AirdropPlan> { const recommendations: Array<{ type: 'proceed' | 'split' | 'abort'; reason: string; }> = []; if (lamports > this.maxAirdrop) { recommendations.push({ type: 'split', reason: `Amount ${lamports} exceeds maximum airdrop of ${this.maxAirdrop}` }); } else if (lamports < this.minAirdrop) { recommendations.push({ type: 'abort', reason: `Amount ${lamports} is below minimum airdrop of ${this.minAirdrop}` }); } else { recommendations.push({ type: 'proceed', reason: 'Amount is within valid range' }); } return { request: { pubkey, lamports, formatted: lamports / 1e9 + ' SOL' }, recommendations, metadata: { timestamp: Date.now() } }; } async splitAirdrop( pubkey: string, totalLamports: number ): Promise<Array<{ lamports: number; delay: number; }>> { const chunks: Array<{ lamports: number; delay: number; }> = []; let remaining = totalLamports; let delay = 0; while (remaining > 0) { const chunk = Math.min(remaining, this.maxAirdrop); chunks.push({ lamports: chunk, delay }); remaining -= chunk; delay += 2000; // 2 seconds between requests } return chunks; } }