Skip to main content

Wallet Creation API

Overview​

Create new cryptocurrency wallets for authenticated users.

Endpoint​

  • URL: /api/wallet/create
  • Method: POST
  • Auth: Required (SUBSCRIBER+ role)

Request​

{
"label": "My Wallet" // Optional
}

Response​

{
"wallet": {
"id": "wallet_123",
"address": "0x742d35Cc...",
"label": "My Wallet",
"balance": "0",
"isActive": true
}
}

Errors​

  • 401 - Unauthorized
  • 403 - Insufficient permissions (VISITOR role)
  • 500 - Server error

Example​

const response = await fetch('/api/wallet/create', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ label: 'My Wallet' })
});

const { wallet } = await response.json();

Endpoint Details​

  • URL: /api/wallet/create
  • Method: POST
  • Authentication: Required (JWT Token)
  • Rate Limit: 10 requests per minute
  • Content-Type: application/json

Authentication Requirements​

This endpoint requires authentication with minimum role:

  • SUBSCRIBER - Can create basic wallets
  • MEMBER - Can create standard wallets
  • CONFIDENTIAL - Can create advanced wallets
  • ADMIN - Full wallet creation access

Note: VISITOR role cannot create wallets.

Request Format​

Headers​

POST /api/wallet/create
Content-Type: application/json
Authorization: Bearer <jwt_token>

Request Body Schema​

interface CreateWalletRequest {
label?: string; // Optional wallet label/name
}

Example Request Body​

{
"label": "My Primary Wallet"
}

Response Format​

Success Response (200 OK)​

{
"wallet": {
"id": "wallet_123456789",
"address": "0x742d35Cc6634C0532925a3b8D4C2C4e4C4C4C4C4",
"label": "My Primary Wallet",
"balance": "0",
"currency": "ETH",
"network": "ethereum",
"isActive": true,
"isPrimary": false,
"createdAt": "2025-01-14T17:30:00Z",
"updatedAt": "2025-01-14T17:30:00Z",
"userId": "user_987654321"
}
}

Error Responses​

401 Unauthorized​

{
"error": "Unauthorized"
}

403 Forbidden​

{
"error": "Forbidden: Insufficient permissions"
}

500 Internal Server Error​

{
"error": "Failed to create wallet"
}
{
"error": "Server configuration error"
}

Code Examples​

JavaScript/TypeScript​

async function createWallet(label?: string): Promise<Wallet> {
const response = await fetch('/api/wallet/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({ label })
});

if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Failed to create wallet');
}

const result = await response.json();
return result.wallet;
}

// Usage examples
const wallet1 = await createWallet('My Trading Wallet');
const wallet2 = await createWallet(); // No label

React Hook Example​

import { useState } from 'react';

function useCreateWallet() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

const createWallet = async (label?: string) => {
setLoading(true);
setError(null);

try {
const response = await fetch('/api/wallet/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ label }),
});

if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error);
}

const result = await response.json();
return result.wallet;
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error');
throw err;
} finally {
setLoading(false);
}
};

return { createWallet, loading, error };
}

// Usage in component
function WalletCreator() {
const { createWallet, loading, error } = useCreateWallet();
const [label, setLabel] = useState('');

const handleCreate = async () => {
try {
const newWallet = await createWallet(label);
console.log('Wallet created:', newWallet);
} catch (error) {
console.error('Failed to create wallet:', error);
}
};

return (
<div>
<input
value={label}
onChange={(e) => setLabel(e.target.value)}
placeholder="Wallet label (optional)"
/>
<button onClick={handleCreate} disabled={loading}>
{loading ? 'Creating...' : 'Create Wallet'}
</button>
{error && <div>Error: {error}</div>}
</div>
);
}

cURL Example​

# Create wallet with label
curl -X POST https://ring.ck.ua/api/wallet/create \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"label": "My Primary Wallet"
}'

# Create wallet without label
curl -X POST https://ring.ck.ua/api/wallet/create \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{}'

Python Example​

import requests

def create_wallet(token: str, label: str = None) -> dict:
"""Create a new wallet"""
url = "https://ring.ck.ua/api/wallet/create"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}

data = {}
if label:
data["label"] = label

response = requests.post(url, headers=headers, json=data)

if response.status_code == 200:
return response.json()["wallet"]
elif response.status_code == 401:
raise PermissionError("Unauthorized")
elif response.status_code == 403:
raise PermissionError("Insufficient permissions")
else:
response.raise_for_status()

# Usage
try:
wallet = create_wallet("your_jwt_token", "My Trading Wallet")
print(f"Created wallet: {wallet['address']}")
except Exception as e:
print(f"Error: {e}")

Response Schema​

interface Wallet {
id: string; // Unique wallet identifier
address: string; // Blockchain wallet address
label?: string; // User-defined wallet label
balance: string; // Current balance (as string for precision)
currency: string; // Currency type (e.g., "ETH", "BTC")
network: string; // Blockchain network
isActive: boolean; // Whether wallet is active
isPrimary: boolean; // Whether this is the primary wallet
createdAt: string; // Creation timestamp (ISO 8601)
updatedAt: string; // Last update timestamp (ISO 8601)
userId: string; // ID of wallet owner
}

Security Considerations​

  1. Role-Based Access: Only authenticated users with appropriate roles can create wallets
  2. Encryption: All wallet private keys are encrypted using server-side encryption
  3. Rate Limiting: Prevents abuse with 10 requests per minute limit
  4. Audit Logging: All wallet creation events are logged for security monitoring
  5. Key Management: Private keys are never exposed in API responses

Business Logic​

  1. Automatic Fields: id, address, balance, isActive, isPrimary, createdAt, updatedAt, and userId are automatically generated
  2. Address Generation: Secure blockchain address generation using cryptographic libraries
  3. Default Settings: New wallets start with zero balance and inactive primary status
  4. Label Validation: Optional labels are validated for length and content
  5. User Association: Wallets are automatically associated with the authenticated user

Validation Rules​

Optional Fields​

  • label: Maximum 50 characters, alphanumeric and spaces allowed
  • No special characters except hyphens and underscores

Automatic Validation​

  • User must be authenticated
  • User role must be SUBSCRIBER or higher
  • Server encryption key must be configured

Error Handling​

Common Error Scenarios​

  1. Unauthenticated User

    • Status: 401
    • Message: "Unauthorized"
    • Solution: Ensure valid JWT token is provided
  2. Insufficient Permissions

    • Status: 403
    • Message: "Forbidden: Insufficient permissions"
    • Solution: User needs minimum SUBSCRIBER role
  3. Server Configuration Error

    • Status: 500
    • Message: "Server configuration error"
    • Solution: Contact system administrator
  4. General Creation Failure

    • Status: 500
    • Message: "Failed to create wallet"
    • Solution: Retry request or contact support

Testing Examples​

Unit Test Example​

describe('POST /api/wallet/create', () => {
it('should create wallet successfully with label', async () => {
const response = await request(app)
.post('/api/wallet/create')
.set('Authorization', `Bearer ${validToken}`)
.send({ label: 'Test Wallet' })
.expect(200);

expect(response.body).toHaveProperty('wallet');
expect(response.body.wallet).toHaveProperty('id');
expect(response.body.wallet).toHaveProperty('address');
expect(response.body.wallet.label).toBe('Test Wallet');
});

it('should create wallet without label', async () => {
const response = await request(app)
.post('/api/wallet/create')
.set('Authorization', `Bearer ${validToken}`)
.send({})
.expect(200);

expect(response.body.wallet.label).toBeUndefined();
});

it('should return 401 for unauthenticated requests', async () => {
const response = await request(app)
.post('/api/wallet/create')
.send({ label: 'Test' })
.expect(401);

expect(response.body.error).toBe('Unauthorized');
});

it('should return 403 for visitor role', async () => {
const response = await request(app)
.post('/api/wallet/create')
.set('Authorization', `Bearer ${visitorToken}`)
.send({})
.expect(403);

expect(response.body.error).toContain('Insufficient permissions');
});
});

Changelog​

  • v1.0.0 - Initial implementation with basic wallet creation
  • v1.1.0 - Added label support and enhanced validation
  • v1.2.0 - Improved error handling and security
  • v1.3.0 - Added role-based access control
  • v1.4.0 - Enhanced encryption and key management