Faucet Endpoints (Development)¶
Аудитория: разработчики, QA инженеры, интеграционные тестировщики Последнее обновление: 2025-11-17 Краткое содержание: Детальная документация Faucet endpoints для development окружения — request test USDC, check faucet status, monitor balance. Полное руководство по интеграции для тестирования и разработки.
⚠️ ВАЖНО: Faucet endpoints доступны ТОЛЬКО в development окружении. В production они отключены.
Обзор Endpoints¶
| Метод | Endpoint | Описание | Auth Required | Rate Limit |
|---|---|---|---|---|
| POST | /api/faucet/request |
Запрос test USDC | ❌ Нет | 1 req/24ч на адрес |
| GET | /api/faucet/status |
Конфигурация faucet | ❌ Нет | 100 req/час |
| GET | /api/faucet/balance |
Баланс faucet контракта | ❌ Нет | 100 req/час |
| GET | /api/faucet/history |
История распределения | ❌ Нет | 100 req/час |
💧 POST /api/faucet/request¶
Запросить test USDC токены для development и тестирования.
Запрос¶
POST /api/faucet/request
Content-Type: application/json
{
"walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
"amount": "1000.00",
"reason": "Testing investment flow"
}
Схема тела запроса:
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
walletAddress |
string | ✅ Да | Адрес кошелька получателя (0x..., 42 chars) |
amount |
string | ❌ Нет | Запрашиваемая сумма (по умолчанию: 1000 USDC, макс: 10000) |
reason |
string | ❌ Нет | Причина запроса (для логирования) |
Правила валидации:
- Адрес кошелька должен быть валидным Ethereum адресом (checksummed)
- Сумма должна быть ≥ 100 USDC и ≤ 10000 USDC
- Один запрос на кошелёк за 24 часа
- Faucet должен иметь достаточный баланс
Ответ¶
Успех (200 OK):
{
"success": true,
"data": {
"transactionHash": "0xabcd1234...",
"walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
"amount": "1000.00",
"currency": "USDC",
"status": "completed",
"blockNumber": 12345678,
"confirmations": 3,
"gasUsed": "50000",
"gasCost": "0.00125 ETH",
"timestamp": "2025-10-03T12:34:56Z",
"nextAllowedRequest": "2025-10-04T12:34:56Z",
"explorerUrl": "https://etherscan.io/tx/0xabcd1234..."
},
"timestamp": "2025-10-03T12:34:56Z"
}
Поля ответа:
| Поле | Тип | Описание |
|---|---|---|
data.transactionHash |
string | On-chain transaction hash |
data.amount |
string | Фактически выданная сумма (SafeDecimal) |
data.status |
string | Статус: pending, completed, failed |
data.blockNumber |
number | Блок где транзакция была майнена |
data.confirmations |
number | Количество подтверждений |
data.nextAllowedRequest |
string | Timestamp когда разрешен следующий запрос |
data.explorerUrl |
string | URL blockchain explorer |
Превышен лимит (429 Too Many Requests):
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Faucet can only be used once per 24 hours per address",
"details": {
"lastRequest": "2025-10-03T10:00:00Z",
"nextAllowedRequest": "2025-10-04T10:00:00Z",
"remainingTime": "22 hours 34 minutes"
}
},
"timestamp": "2025-10-03T12:34:56Z"
}
Недостаточный баланс (422 Unprocessable Entity):
{
"success": false,
"error": {
"code": "INSUFFICIENT_FAUCET_BALANCE",
"message": "Faucet has insufficient balance for this request",
"details": {
"requested": "1000.00",
"available": "500.00",
"suggestion": "Request a smaller amount or contact support to refill faucet"
}
}
}
Ошибки:
| Код статуса | Код ошибки | Описание |
|---|---|---|
| 400 | INVALID_WALLET_ADDRESS |
Невалидный формат адреса кошелька |
| 400 | INVALID_AMOUNT |
Сумма вне разрешенного диапазона (100-10000) |
| 422 | INSUFFICIENT_FAUCET_BALANCE |
Слишком низкий баланс faucet |
| 429 | RATE_LIMIT_EXCEEDED |
Слишком много запросов (1 за 24ч) |
| 503 | BLOCKCHAIN_ERROR |
Blockchain транзакция провалилась |
| 503 | FAUCET_DISABLED |
Faucet отключен (production окружение) |
Пример cURL¶
# Запрос test USDC
curl -X POST https://app.saga.surf/api/faucet/request \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
"amount": "1000.00",
"reason": "Testing investment flow"
}'
# Запрос суммы по умолчанию (1000 USDC)
curl -X POST https://app.saga.surf/api/faucet/request \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"
}'
Пример TypeScript¶
const requestTestUSDC = async (
walletAddress: string,
amount: string = '1000.00',
reason?: string
) => {
try {
const response = await fetch('/api/faucet/request', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
walletAddress,
amount,
reason
})
});
if (!response.ok) {
const error = await response.json();
if (error.error.code === 'RATE_LIMIT_EXCEEDED') {
console.log('⏱️ Rate limit exceeded');
console.log(` Next request: ${error.error.details.nextAllowedRequest}`);
console.log(` Wait: ${error.error.details.remainingTime}`);
return null;
}
throw new Error(error.error.message);
}
const { data } = await response.json();
console.log('💧 Test USDC Received:');
console.log(` Amount: $${data.amount}`);
console.log(` TX Hash: ${data.transactionHash}`);
console.log(` Status: ${data.status}`);
console.log(` Confirmations: ${data.confirmations}`);
console.log(` Gas Used: ${data.gasUsed} (${data.gasCost})`);
console.log(`\n🔗 Explorer: ${data.explorerUrl}`);
console.log(`⏰ Next Request: ${data.nextAllowedRequest}`);
return data;
} catch (error) {
console.error('❌ Faucet request failed:', error.message);
throw error;
}
};
// Usage
const wallet = await ethereum.request({ method: 'eth_requestAccounts' });
await requestTestUSDC(wallet[0], '1000.00', 'Testing deposits');
Пример React Hook¶
import { useState } from 'react';
import { useAccount } from 'wagmi';
interface FaucetResponse {
transactionHash: string;
amount: string;
nextAllowedRequest: string;
explorerUrl: string;
}
export const useFaucet = () => {
const { address } = useAccount();
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [lastRequest, setLastRequest] = useState<FaucetResponse | null>(null);
const requestUSDC = async (amount: string = '1000.00') => {
if (!address) {
setError('Wallet not connected');
return null;
}
setLoading(true);
setError(null);
try {
const response = await fetch('/api/faucet/request', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
walletAddress: address,
amount,
reason: 'Testing from dApp'
})
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error.message);
}
const { data } = await response.json();
setLastRequest(data);
return data;
} catch (err) {
setError(err.message);
return null;
} finally {
setLoading(false);
}
};
return { requestUSDC, loading, error, lastRequest };
};
// Component usage
const FaucetButton = () => {
const { requestUSDC, loading, error, lastRequest } = useFaucet();
return (
<div>
<button onClick={() => requestUSDC('1000.00')} disabled={loading}>
{loading ? 'Requesting...' : 'Get Test USDC'}
</button>
{error && <p className="error">{error}</p>}
{lastRequest && (
<div>
<p>✅ Received ${lastRequest.amount}</p>
<a href={lastRequest.explorerUrl} target="_blank">View TX</a>
</div>
)}
</div>
);
};
⚙️ GET /api/faucet/status¶
Получить конфигурацию faucet и текущий статус.
Запрос¶
Аутентификация не требуется.
Ответ¶
Успех (200 OK):
{
"success": true,
"data": {
"enabled": true,
"environment": "development",
"configuration": {
"usdcContractAddress": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
"defaultAmount": "1000.00",
"minAmount": "100.00",
"maxAmount": "10000.00",
"rateLimitPeriod": "24h",
"maxRequestsPerAddress": 1
},
"balance": {
"usdc": "500000.00",
"eth": "10.5",
"lowBalanceThreshold": "10000.00",
"needsRefill": false
},
"statistics": {
"totalDistributed": "125000.00",
"totalRequests": 125,
"uniqueAddresses": 87,
"lastDistribution": "2025-10-03T12:30:00Z",
"averageRequestAmount": "1000.00"
},
"limits": {
"dailyLimit": "50000.00",
"distributedToday": "12000.00",
"remainingToday": "38000.00"
},
"network": {
"chainId": 1337,
"blockNumber": 12345678,
"gasPrice": "25 gwei"
}
},
"timestamp": "2025-10-03T12:34:56Z"
}
Поля ответа:
| Поле | Тип | Описание |
|---|---|---|
data.enabled |
boolean | Статус включенности faucet |
data.configuration |
object | Настройки конфигурации faucet |
data.balance |
object | Текущие балансы faucet |
data.balance.needsRefill |
boolean | Флаг ниже порога |
data.statistics |
object | Статистика использования |
data.limits |
object | Дневные лимиты распределения |
data.network |
object | Информация о blockchain сети |
Отключен (503 Service Unavailable):
{
"success": false,
"error": {
"code": "FAUCET_DISABLED",
"message": "Faucet is disabled in production environment",
"details": {
"environment": "production",
"reason": "Faucet only available in development"
}
}
}
Пример cURL¶
# Получить статус faucet
curl -X GET https://app.saga.surf/api/faucet/status
# Проверить нужно ли пополнение
curl -s https://app.saga.surf/api/faucet/status | jq '.data.balance.needsRefill'
Пример TypeScript¶
const checkFaucetStatus = async () => {
const response = await fetch('/api/faucet/status');
if (!response.ok) {
const error = await response.json();
console.log('❌ Faucet unavailable:', error.error.message);
return null;
}
const { data } = await response.json();
console.log('💧 Faucet Status:');
console.log(` Enabled: ${data.enabled ? '✅' : '❌'}`);
console.log(` Environment: ${data.environment}`);
console.log('\n💰 Balance:');
console.log(` USDC: $${data.balance.usdc}`);
console.log(` ETH: ${data.balance.eth} ETH`);
console.log(` Needs Refill: ${data.balance.needsRefill ? '⚠️ YES' : '✅ NO'}`);
console.log('\n📊 Configuration:');
console.log(` Default Amount: $${data.configuration.defaultAmount}`);
console.log(` Range: $${data.configuration.minAmount} - $${data.configuration.maxAmount}`);
console.log(` Rate Limit: ${data.configuration.maxRequestsPerAddress} per ${data.configuration.rateLimitPeriod}`);
console.log('\n📈 Statistics:');
console.log(` Total Distributed: $${data.statistics.totalDistributed}`);
console.log(` Total Requests: ${data.statistics.totalRequests}`);
console.log(` Unique Addresses: ${data.statistics.uniqueAddresses}`);
console.log('\n📊 Daily Limits:');
console.log(` Limit: $${data.limits.dailyLimit}`);
console.log(` Distributed: $${data.limits.distributedToday}`);
console.log(` Remaining: $${data.limits.remainingToday}`);
return data;
};
💵 GET /api/faucet/balance¶
Получить текущий баланс faucet контракта.
Запрос¶
Аутентификация не требуется.
Ответ¶
Успех (200 OK):
{
"success": true,
"data": {
"contractAddress": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
"balances": {
"usdc": {
"balance": "500000.00",
"decimals": 6,
"symbol": "USDC"
},
"eth": {
"balance": "10.5",
"decimals": 18,
"symbol": "ETH"
}
},
"thresholds": {
"usdc": {
"low": "10000.00",
"critical": "1000.00",
"status": "healthy"
},
"eth": {
"low": "1.0",
"critical": "0.1",
"status": "healthy"
}
},
"lastRefill": {
"usdc": {
"amount": "100000.00",
"timestamp": "2025-10-01T10:00:00Z",
"txHash": "0xrefill1234..."
}
},
"estimatedRemaining": {
"requests": 500,
"days": 20
}
},
"timestamp": "2025-10-03T12:34:56Z"
}
Поля ответа:
| Поле | Тип | Описание |
|---|---|---|
data.balances |
object | Breakdown балансов токенов |
data.thresholds |
object | Пороги балансов и статус |
data.thresholds.*.status |
string | Статус: healthy, low, critical |
data.lastRefill |
object | Информация о последнем пополнении |
data.estimatedRemaining |
object | Оценка оставшейся ёмкости |
Пример cURL¶
# Получить баланс faucet
curl -X GET https://app.saga.surf/api/faucet/balance
# Мониторить баланс USDC
watch -n 10 'curl -s https://app.saga.surf/api/faucet/balance | jq .data.balances.usdc.balance'
Пример TypeScript¶
const checkFaucetBalance = async () => {
const response = await fetch('/api/faucet/balance');
const { data } = await response.json();
console.log('💵 Faucet Balance:');
console.log(` Contract: ${data.contractAddress}`);
console.log('\n💰 Balances:');
Object.entries(data.balances).forEach(([token, info]: [string, any]) => {
const status = data.thresholds[token].status;
const icon = status === 'healthy' ? '✅' : status === 'low' ? '⚠️' : '🚨';
console.log(` ${icon} ${info.symbol}: ${info.balance} (${status})`);
});
console.log('\n📊 Thresholds:');
Object.entries(data.thresholds).forEach(([token, threshold]: [string, any]) => {
console.log(` ${token.toUpperCase()}:`);
console.log(` Low: ${threshold.low}`);
console.log(` Critical: ${threshold.critical}`);
});
if (data.lastRefill.usdc) {
console.log('\n🔄 Last Refill:');
console.log(` Amount: $${data.lastRefill.usdc.amount}`);
console.log(` Time: ${data.lastRefill.usdc.timestamp}`);
console.log(` TX: ${data.lastRefill.usdc.txHash}`);
}
console.log('\n⏱️ Estimated Remaining:');
console.log(` Requests: ~${data.estimatedRemaining.requests}`);
console.log(` Days: ~${data.estimatedRemaining.days}`);
return data;
};
📜 GET /api/faucet/history¶
Получить историю распределения faucet.
Запрос¶
Query параметры:
| Параметр | Тип | Обязательно | Описание | По умолчанию |
|---|---|---|---|---|
limit |
number | ❌ Нет | Количество записей (макс: 100) | 50 |
walletAddress |
string | ❌ Нет | Фильтр по адресу кошелька | Все |
startDate |
string | ❌ Нет | Фильтр от даты (ISO 8601) | - |
endDate |
string | ❌ Нет | Фильтр до даты (ISO 8601) | - |
Ответ¶
Успех (200 OK):
{
"success": true,
"data": [
{
"id": "faucet_req_001",
"walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
"amount": "1000.00",
"transactionHash": "0xabcd1234...",
"status": "completed",
"requestedAt": "2025-10-03T12:00:00Z",
"completedAt": "2025-10-03T12:00:15Z",
"blockNumber": 12345678,
"gasUsed": "50000",
"reason": "Testing investment flow"
},
{
"id": "faucet_req_002",
"walletAddress": "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
"amount": "500.00",
"transactionHash": "0xef567890...",
"status": "completed",
"requestedAt": "2025-10-03T11:30:00Z",
"completedAt": "2025-10-03T11:30:20Z",
"blockNumber": 12345600,
"gasUsed": "50000"
}
],
"pagination": {
"limit": 50,
"total": 125,
"hasMore": true
},
"timestamp": "2025-10-03T12:34:56Z"
}
Пример cURL¶
# Получить недавнюю историю
curl -X GET https://app.saga.surf/api/faucet/history?limit=10
# Фильтр по кошельку
curl -X GET "https://app.saga.surf/api/faucet/history?walletAddress=0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"
Связанная документация¶
Публичные Endpoints:
- Health & Status - System health checks
- Blockchain Status - Blockchain операции
Разработка:
- Testing Guide - Тестирование с faucet
📋 Метаданные¶
Версия: 2.6.268
Обновлено: 2025-10-21
Статус: Published