614 lines
16 KiB
Markdown
614 lines
16 KiB
Markdown
# Wallet Funds API Documentation
|
|
|
|
## Overview
|
|
|
|
The Wallet Funds API provides red packet functionality for the DysonNetwork platform, allowing users to create and distribute funds among multiple recipients with expiration and claiming mechanisms.
|
|
|
|
## Authentication
|
|
|
|
All endpoints require Bearer token authentication:
|
|
|
|
```
|
|
Authorization: Bearer {jwt_token}
|
|
```
|
|
|
|
## Data Types
|
|
|
|
### Enums
|
|
|
|
#### FundSplitType
|
|
```typescript
|
|
enum FundSplitType {
|
|
Even = 0, // Equal distribution
|
|
Random = 1 // Lucky draw distribution
|
|
}
|
|
```
|
|
|
|
#### FundStatus
|
|
```typescript
|
|
enum FundStatus {
|
|
Created = 0, // Fund created, waiting for claims
|
|
PartiallyReceived = 1, // Some recipients claimed
|
|
FullyReceived = 2, // All recipients claimed
|
|
Expired = 3, // Fund expired, unclaimed amounts refunded
|
|
Refunded = 4 // Legacy status
|
|
}
|
|
```
|
|
|
|
### Request/Response Models
|
|
|
|
#### CreateFundRequest
|
|
```typescript
|
|
interface CreateFundRequest {
|
|
recipientAccountIds: string[]; // UUIDs of recipients
|
|
currency: string; // e.g., "points", "golds"
|
|
totalAmount: number; // Total amount to distribute
|
|
splitType: FundSplitType; // Even or Random
|
|
message?: string; // Optional message
|
|
expirationHours?: number; // Optional: hours until expiration (default: 24)
|
|
pinCode: string; // Required: 6-digit PIN code for security
|
|
}
|
|
```
|
|
|
|
#### SnWalletFund
|
|
```typescript
|
|
interface SnWalletFund {
|
|
id: string; // UUID
|
|
currency: string;
|
|
totalAmount: number;
|
|
splitType: FundSplitType;
|
|
status: FundStatus;
|
|
message?: string;
|
|
creatorAccountId: string; // UUID
|
|
creatorAccount: SnAccount; // Creator account details (includes profile)
|
|
recipients: SnWalletFundRecipient[];
|
|
expiredAt: string; // ISO 8601 timestamp
|
|
createdAt: string; // ISO 8601 timestamp
|
|
updatedAt: string; // ISO 8601 timestamp
|
|
}
|
|
```
|
|
|
|
#### SnWalletFundRecipient
|
|
```typescript
|
|
interface SnWalletFundRecipient {
|
|
id: string; // UUID
|
|
fundId: string; // UUID
|
|
recipientAccountId: string; // UUID
|
|
recipientAccount: SnAccount; // Recipient account details (includes profile)
|
|
amount: number; // Allocated amount
|
|
isReceived: boolean;
|
|
receivedAt?: string; // ISO 8601 timestamp (if claimed)
|
|
createdAt: string; // ISO 8601 timestamp
|
|
updatedAt: string; // ISO 8601 timestamp
|
|
}
|
|
```
|
|
|
|
#### SnWalletTransaction
|
|
```typescript
|
|
interface SnWalletTransaction {
|
|
id: string; // UUID
|
|
payerWalletId?: string; // UUID (null for system transfers)
|
|
payeeWalletId?: string; // UUID (null for system transfers)
|
|
currency: string;
|
|
amount: number;
|
|
remarks?: string;
|
|
type: TransactionType;
|
|
createdAt: string; // ISO 8601 timestamp
|
|
updatedAt: string; // ISO 8601 timestamp
|
|
}
|
|
```
|
|
|
|
#### Error Response
|
|
```typescript
|
|
interface ErrorResponse {
|
|
type: string; // Error type
|
|
title: string; // Error title
|
|
status: number; // HTTP status code
|
|
detail: string; // Error details
|
|
instance?: string; // Request instance
|
|
}
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
### 1. Create Fund
|
|
|
|
Creates a new fund (red packet) for distribution among recipients.
|
|
|
|
**Endpoint:** `POST /api/wallets/funds`
|
|
|
|
**Request Body:** `CreateFundRequest`
|
|
|
|
**Response:** `SnWalletFund` (201 Created)
|
|
|
|
**Example Request:**
|
|
```bash
|
|
curl -X POST "/api/wallets/funds" \
|
|
-H "Authorization: Bearer {token}" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"recipientAccountIds": [
|
|
"550e8400-e29b-41d4-a716-446655440000",
|
|
"550e8400-e29b-41d4-a716-446655440001",
|
|
"550e8400-e29b-41d4-a716-446655440002"
|
|
],
|
|
"currency": "points",
|
|
"totalAmount": 100.00,
|
|
"splitType": "Even",
|
|
"message": "Happy New Year! 🎉",
|
|
"expirationHours": 48,
|
|
"pinCode": "123456"
|
|
}'
|
|
```
|
|
|
|
**Example Response:**
|
|
```json
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440003",
|
|
"currency": "points",
|
|
"totalAmount": 100.00,
|
|
"splitType": 0,
|
|
"status": 0,
|
|
"message": "Happy New Year! 🎉",
|
|
"creatorAccountId": "550e8400-e29b-41d4-a716-446655440004",
|
|
"creatorAccount": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440004",
|
|
"username": "creator_user"
|
|
},
|
|
"recipients": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440005",
|
|
"fundId": "550e8400-e29b-41d4-a716-446655440003",
|
|
"recipientAccountId": "550e8400-e29b-41d4-a716-446655440000",
|
|
"amount": 33.34,
|
|
"isReceived": false,
|
|
"createdAt": "2025-10-03T22:00:00Z",
|
|
"updatedAt": "2025-10-03T22:00:00Z"
|
|
},
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440006",
|
|
"fundId": "550e8400-e29b-41d4-a716-446655440003",
|
|
"recipientAccountId": "550e8400-e29b-41d4-a716-446655440001",
|
|
"amount": 33.33,
|
|
"isReceived": false,
|
|
"createdAt": "2025-10-03T22:00:00Z",
|
|
"updatedAt": "2025-10-03T22:00:00Z"
|
|
},
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440007",
|
|
"fundId": "550e8400-e29b-41d4-a716-446655440003",
|
|
"recipientAccountId": "550e8400-e29b-41d4-a716-446655440002",
|
|
"amount": 33.33,
|
|
"isReceived": false,
|
|
"createdAt": "2025-10-03T22:00:00Z",
|
|
"updatedAt": "2025-10-03T22:00:00Z"
|
|
}
|
|
],
|
|
"expiredAt": "2025-10-05T22:00:00Z",
|
|
"createdAt": "2025-10-03T22:00:00Z",
|
|
"updatedAt": "2025-10-03T22:00:00Z"
|
|
}
|
|
```
|
|
|
|
**Error Responses:**
|
|
- `400 Bad Request`: Invalid parameters, insufficient funds, invalid recipients
|
|
- `401 Unauthorized`: Missing or invalid authentication
|
|
- `403 Forbidden`: Invalid PIN code
|
|
- `422 Unprocessable Entity`: Business logic violations
|
|
|
|
---
|
|
|
|
### 2. Get Funds
|
|
|
|
Retrieves funds that the authenticated user is involved in (as creator or recipient).
|
|
|
|
**Endpoint:** `GET /api/wallets/funds`
|
|
|
|
**Query Parameters:**
|
|
- `offset` (number, optional): Pagination offset (default: 0)
|
|
- `take` (number, optional): Number of items to return (default: 20, max: 100)
|
|
- `status` (FundStatus, optional): Filter by fund status
|
|
|
|
**Response:** `SnWalletFund[]` (200 OK)
|
|
|
|
**Headers:**
|
|
- `X-Total`: Total number of funds matching the criteria
|
|
|
|
**Example Request:**
|
|
```bash
|
|
curl -X GET "/api/wallets/funds?offset=0&take=10&status=0" \
|
|
-H "Authorization: Bearer {token}"
|
|
```
|
|
|
|
**Example Response:**
|
|
```json
|
|
[
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440003",
|
|
"currency": "points",
|
|
"totalAmount": 100.00,
|
|
"splitType": 0,
|
|
"status": 0,
|
|
"message": "Happy New Year! 🎉",
|
|
"creatorAccountId": "550e8400-e29b-41d4-a716-446655440004",
|
|
"creatorAccount": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440004",
|
|
"username": "creator_user"
|
|
},
|
|
"recipients": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440005",
|
|
"fundId": "550e8400-e29b-41d4-a716-446655440003",
|
|
"recipientAccountId": "550e8400-e29b-41d4-a716-446655440000",
|
|
"amount": 33.34,
|
|
"isReceived": false
|
|
}
|
|
],
|
|
"expiredAt": "2025-10-05T22:00:00Z",
|
|
"createdAt": "2025-10-03T22:00:00Z",
|
|
"updatedAt": "2025-10-03T22:00:00Z"
|
|
}
|
|
]
|
|
```
|
|
|
|
**Error Responses:**
|
|
- `401 Unauthorized`: Missing or invalid authentication
|
|
|
|
---
|
|
|
|
### 3. Get Fund
|
|
|
|
Retrieves details of a specific fund.
|
|
|
|
**Endpoint:** `GET /api/wallets/funds/{id}`
|
|
|
|
**Path Parameters:**
|
|
- `id` (string): Fund UUID
|
|
|
|
**Response:** `SnWalletFund` (200 OK)
|
|
|
|
**Example Request:**
|
|
```bash
|
|
curl -X GET "/api/wallets/funds/550e8400-e29b-41d4-a716-446655440003" \
|
|
-H "Authorization: Bearer {token}"
|
|
```
|
|
|
|
**Example Response:** (Same as create fund response)
|
|
|
|
**Error Responses:**
|
|
- `401 Unauthorized`: Missing or invalid authentication
|
|
- `403 Forbidden`: User doesn't have permission to view this fund
|
|
- `404 Not Found`: Fund not found
|
|
|
|
---
|
|
|
|
### 4. Receive Fund
|
|
|
|
Claims the authenticated user's portion of a fund.
|
|
|
|
**Endpoint:** `POST /api/wallets/funds/{id}/receive`
|
|
|
|
**Path Parameters:**
|
|
- `id` (string): Fund UUID
|
|
|
|
**Response:** `SnWalletTransaction` (200 OK)
|
|
|
|
**Example Request:**
|
|
```bash
|
|
curl -X POST "/api/wallets/funds/550e8400-e29b-41d4-a716-446655440003/receive" \
|
|
-H "Authorization: Bearer {token}"
|
|
```
|
|
|
|
**Example Response:**
|
|
```json
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440008",
|
|
"payerWalletId": null,
|
|
"payeeWalletId": "550e8400-e29b-41d4-a716-446655440009",
|
|
"currency": "points",
|
|
"amount": 33.34,
|
|
"remarks": "Received fund portion from 550e8400-e29b-41d4-a716-446655440004",
|
|
"type": 1,
|
|
"createdAt": "2025-10-03T22:05:00Z",
|
|
"updatedAt": "2025-10-03T22:05:00Z"
|
|
}
|
|
```
|
|
|
|
**Error Responses:**
|
|
- `400 Bad Request`: Fund expired, already claimed, not a recipient
|
|
- `401 Unauthorized`: Missing or invalid authentication
|
|
- `404 Not Found`: Fund not found
|
|
|
|
---
|
|
|
|
### 5. Get Wallet Overview
|
|
|
|
Retrieves a summarized overview of wallet transactions grouped by type for graphing/charting purposes.
|
|
|
|
**Endpoint:** `GET /api/wallets/overview`
|
|
|
|
**Query Parameters:**
|
|
- `startDate` (string, optional): Start date in ISO 8601 format (e.g., "2025-01-01T00:00:00Z")
|
|
- `endDate` (string, optional): End date in ISO 8601 format (e.g., "2025-12-31T23:59:59Z")
|
|
|
|
**Response:** `WalletOverview` (200 OK)
|
|
|
|
**Example Request:**
|
|
```bash
|
|
curl -X GET "/api/wallets/overview?startDate=2025-01-01T00:00:00Z&endDate=2025-12-31T23:59:59Z" \
|
|
-H "Authorization: Bearer {token}"
|
|
```
|
|
|
|
**Example Response:**
|
|
```json
|
|
{
|
|
"accountId": "550e8400-e29b-41d4-a716-446655440000",
|
|
"startDate": "2025-01-01T00:00:00.0000000Z",
|
|
"endDate": "2025-12-31T23:59:59.0000000Z",
|
|
"summary": {
|
|
"System": {
|
|
"type": "System",
|
|
"currencies": {
|
|
"points": {
|
|
"currency": "points",
|
|
"income": 150.00,
|
|
"spending": 0.00,
|
|
"net": 150.00
|
|
}
|
|
}
|
|
},
|
|
"Transfer": {
|
|
"type": "Transfer",
|
|
"currencies": {
|
|
"points": {
|
|
"currency": "points",
|
|
"income": 25.00,
|
|
"spending": 75.00,
|
|
"net": -50.00
|
|
},
|
|
"golds": {
|
|
"currency": "golds",
|
|
"income": 0.00,
|
|
"spending": 10.00,
|
|
"net": -10.00
|
|
}
|
|
}
|
|
},
|
|
"Order": {
|
|
"type": "Order",
|
|
"currencies": {
|
|
"points": {
|
|
"currency": "points",
|
|
"income": 0.00,
|
|
"spending": 200.00,
|
|
"net": -200.00
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"totalIncome": 175.00,
|
|
"totalSpending": 285.00,
|
|
"netTotal": -110.00
|
|
}
|
|
```
|
|
|
|
**Response Fields:**
|
|
- `accountId`: User's account UUID
|
|
- `startDate`/`endDate`: Date range applied (ISO 8601 format)
|
|
- `summary`: Object keyed by transaction type
|
|
- `type`: Transaction type name
|
|
- `currencies`: Object keyed by currency code
|
|
- `currency`: Currency name
|
|
- `income`: Total money received
|
|
- `spending`: Total money spent
|
|
- `net`: Income minus spending
|
|
- `totalIncome`: Sum of all income across all types/currencies
|
|
- `totalSpending`: Sum of all spending across all types/currencies
|
|
- `netTotal`: Overall net (totalIncome - totalSpending)
|
|
|
|
**Error Responses:**
|
|
- `401 Unauthorized`: Missing or invalid authentication
|
|
|
|
## Error Codes
|
|
|
|
### Common Error Types
|
|
|
|
#### Validation Errors
|
|
```json
|
|
{
|
|
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
|
|
"title": "Bad Request",
|
|
"status": 400,
|
|
"detail": "At least one recipient is required",
|
|
"instance": "/api/wallets/funds"
|
|
}
|
|
```
|
|
|
|
#### Insufficient Funds
|
|
```json
|
|
{
|
|
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
|
|
"title": "Bad Request",
|
|
"status": 400,
|
|
"detail": "Insufficient funds",
|
|
"instance": "/api/wallets/funds"
|
|
}
|
|
```
|
|
|
|
#### Fund Not Available
|
|
```json
|
|
{
|
|
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
|
|
"title": "Bad Request",
|
|
"status": 400,
|
|
"detail": "Fund is no longer available",
|
|
"instance": "/api/wallets/funds/550e8400-e29b-41d4-a716-446655440003/receive"
|
|
}
|
|
```
|
|
|
|
#### Already Claimed
|
|
```json
|
|
{
|
|
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
|
|
"title": "Bad Request",
|
|
"status": 400,
|
|
"detail": "You have already received this fund",
|
|
"instance": "/api/wallets/funds/550e8400-e29b-41d4-a716-446655440003/receive"
|
|
}
|
|
```
|
|
|
|
## Rate Limiting
|
|
|
|
- **Create Fund**: 10 requests per minute per user
|
|
- **Get Funds**: 60 requests per minute per user
|
|
- **Get Fund**: 60 requests per minute per user
|
|
- **Receive Fund**: 30 requests per minute per user
|
|
|
|
## Webhooks/Notifications
|
|
|
|
The system integrates with the platform's notification system:
|
|
|
|
- **Fund Created**: Creator receives confirmation
|
|
- **Fund Claimed**: Creator receives notification when someone claims
|
|
- **Fund Expired**: Creator receives refund notification
|
|
|
|
## SDK Examples
|
|
|
|
### JavaScript/TypeScript
|
|
|
|
```typescript
|
|
// Create a fund
|
|
const createFund = async (fundData: CreateFundRequest): Promise<SnWalletFund> => {
|
|
const response = await fetch('/api/wallets/funds', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`,
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(fundData)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
return response.json();
|
|
};
|
|
|
|
// Get user's funds
|
|
const getFunds = async (params?: {
|
|
offset?: number;
|
|
take?: number;
|
|
status?: FundStatus;
|
|
}): Promise<SnWalletFund[]> => {
|
|
const queryParams = new URLSearchParams();
|
|
if (params?.offset) queryParams.set('offset', params.offset.toString());
|
|
if (params?.take) queryParams.set('take', params.take.toString());
|
|
if (params?.status !== undefined) queryParams.set('status', params.status.toString());
|
|
|
|
const response = await fetch(`/api/wallets/funds?${queryParams}`, {
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`
|
|
}
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
return response.json();
|
|
};
|
|
|
|
// Claim a fund
|
|
const receiveFund = async (fundId: string): Promise<SnWalletTransaction> => {
|
|
const response = await fetch(`/api/wallets/funds/${fundId}/receive`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`
|
|
}
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
return response.json();
|
|
};
|
|
```
|
|
|
|
### Python
|
|
|
|
```python
|
|
import requests
|
|
from typing import List, Optional
|
|
from enum import Enum
|
|
|
|
class FundSplitType(Enum):
|
|
EVEN = 0
|
|
RANDOM = 1
|
|
|
|
class FundStatus(Enum):
|
|
CREATED = 0
|
|
PARTIALLY_RECEIVED = 1
|
|
FULLY_RECEIVED = 2
|
|
EXPIRED = 3
|
|
REFUNDED = 4
|
|
|
|
def create_fund(token: str, fund_data: dict) -> dict:
|
|
"""Create a new fund"""
|
|
response = requests.post(
|
|
'/api/wallets/funds',
|
|
json=fund_data,
|
|
headers={
|
|
'Authorization': f'Bearer {token}',
|
|
'Content-Type': 'application/json'
|
|
}
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
|
|
def get_funds(
|
|
token: str,
|
|
offset: int = 0,
|
|
take: int = 20,
|
|
status: Optional[FundStatus] = None
|
|
) -> List[dict]:
|
|
"""Get user's funds"""
|
|
params = {'offset': offset, 'take': take}
|
|
if status is not None:
|
|
params['status'] = status.value
|
|
|
|
response = requests.get(
|
|
'/api/wallets/funds',
|
|
params=params,
|
|
headers={'Authorization': f'Bearer {token}'}
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
|
|
def receive_fund(token: str, fund_id: str) -> dict:
|
|
"""Claim a fund portion"""
|
|
response = requests.post(
|
|
f'/api/wallets/funds/{fund_id}/receive',
|
|
headers={'Authorization': f'Bearer {token}'}
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
```
|
|
|
|
## Changelog
|
|
|
|
### Version 1.0.0
|
|
- Initial release with basic red packet functionality
|
|
- Support for even and random split types
|
|
- 24-hour expiration with automatic refunds
|
|
- RESTful API endpoints
|
|
- Comprehensive error handling
|
|
|
|
## Support
|
|
|
|
For API support or questions:
|
|
- Check the main documentation at `README_WALLET_FUNDS.md`
|
|
- Review error messages for specific guidance
|
|
- Contact the development team for technical issues
|