/api/raida/locker/upload
GETUpload CloudCoins from your wallet to a RAIDA locker using a secure locker code.
Description
The /api/raida/locker/upload endpoint uploads CloudCoins from your wallet to the RAIDA cloud locker system. This is a secure way to store coins temporarily on the RAIDA network or to send coins to someone who knows the locker code.
The endpoint performs a two-phase operation:
- Coin Selection: Reads coins from Bank and Fracked folders, selects coins using a greedy algorithm to meet the requested amount.
- RAIDA Upload: Sends Locker Put (0x0852) requests to all 25 RAIDAs in parallel with the selected coins and derived locker key.
- Consensus Verification: Requires 13+ successful RAIDA responses (cloud consensus) to complete the upload.
- File Management: Successfully uploaded coins are moved to the Lockered folder.
- Secure Transfers: Send coins to someone by sharing the locker_code out-of-band (SMS, email, secure messaging)
- Cloud Storage: Temporarily store coins in the RAIDA cloud
- Cross-Wallet Transfers: Transfer coins between your own wallets
- Gift Coins: Gift coins using a shared secret code
The locker_code parameter is essentially a password. Anyone with this code can download the coins from the locker. Keep it secret and share it securely with the intended recipient only.
- Use strong, unique locker codes (mix of letters, numbers, symbols)
- Share codes through secure channels only
- The same locker_code always generates the same locker_key (deterministic)
Parameters
This endpoint requires two query parameters.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
locker_code |
string | Yes | Text string to hash into a 16-byte locker key. This is the "password" for the locker. Can be any text (letters, numbers, symbols). |
amount |
integer | Yes | Number of whole CloudCoin units to upload (e.g., 1, 5, 25, 100, 500). Must be greater than 0. |
Locker Key Generation
The locker key is a 16-byte value derived from the locker_code parameter using a simple XOR hash:
// Initialize locker_key to all zeros
uint8_t locker_key[16] = {0};
// XOR each character of locker_code into the key
for (size_t i = 0; i < strlen(locker_code); i++) {
locker_key[i % 16] ^= (uint8_t)locker_code[i];
}
// Set last 4 bytes to 0xFFFFFFFF (protocol requirement)
locker_key[12] = 0xFF;
locker_key[13] = 0xFF;
locker_key[14] = 0xFF;
locker_key[15] = 0xFF;
Important: The same locker_code always generates the same locker_key. This is by design - it allows the recipient to download coins by providing the same code.
RAIDA Protocol Details
This endpoint uses the RAIDA Locker Put command (0x0852).
Command Code
0x0852 (Command Group: 0x08 = Locker, Command: 0x52 = Put)
Request Format
Challenge(16 bytes)
+ LockerKey(16 bytes)
+ [DN(1) + SN(4) + AN(16)] × N coins
+ Terminator(0x3E3E)
Response Formats
- STATUS_ALL_PASS (241): All coins uploaded successfully
- STATUS_ALL_FAIL (242): All coins failed to upload
- STATUS_MIXED (243): Some coins succeeded, some failed - includes bitfield
- Error codes: Various error statuses for request/protocol errors
Consensus Requirement
Requires 13 or more out of 25 RAIDAs to successfully upload for cloud consensus. If fewer than 13 RAIDAs confirm the upload, the operation fails and coins remain in their original folders.
Response
Returns a JSON object with upload results.
Response Properties (Success)
Example Success Response
{
"status": "success",
"operation": "locker_upload",
"amount_requested": 500,
"amount_uploaded": 500,
"coins_uploaded": 3,
"locker_key": "0123456789abcdefffffffffffffff",
"successful_uploads": 24,
"message": "Coins uploaded to locker successfully"
}
Error Responses
The endpoint returns appropriate HTTP status codes with JSON error messages.
HTTP 400 - Bad Request
- No active wallet set
- Missing or empty
locker_codeparameter - Missing
amountparameter - Invalid amount (must be greater than 0)
- Insufficient balance in wallet
HTTP 500 - Internal Server Error
- Failed to read Bank folder
- Failed to read Fracked folder
- Failed to generate RAIDA requests
- Upload failed - insufficient RAIDA confirmations (fewer than 13)
Example Error Response
{
"status": "error",
"message": "Insufficient funds in wallet",
"code": 400
}
Coin Selection Algorithm
The endpoint uses a greedy algorithm to select coins for upload:
- Reads all coins from the Bank folder
- Reads all coins from the Fracked folder
- Sorts coins by denomination (largest first)
- Selects coins greedily until the requested amount is met or exceeded
- If insufficient funds, returns a 400 error with available balance
The actual amount uploaded may be slightly more than requested due to coin denominations. For example, if you request 100 units but only have denominations of 250, one 250 coin will be uploaded.
Post-Upload Process
After RAIDA responses are received:
Successful Upload (13+ RAIDAs confirm)
- Coins are moved from Bank/Fracked folders to the Lockered folder
- Original coin files are deleted from Bank/Fracked
- Lockered folder is created automatically if it doesn't exist
- Success response is returned with upload details
Failed Upload (Fewer than 13 RAIDAs confirm)
- Coins remain in their original folders (Bank/Fracked)
- No files are moved or deleted
- Error response is returned with failure reason
Examples
JavaScript (fetch)
const API_HOST = 'http://localhost:8080';
async function uploadToLocker(lockerCode, amount) {
try {
const url = `${API_HOST}/api/raida/locker/upload?` +
`locker_code=${encodeURIComponent(lockerCode)}&` +
`amount=${amount}`;
const response = await fetch(url);
const result = await response.json();
if (result.status === 'success') {
console.log('Upload Successful!');
console.log(`Coins uploaded: ${result.coins_uploaded}`);
console.log(`Amount uploaded: ${result.amount_uploaded} units`);
console.log(`RAIDAs confirmed: ${result.successful_uploads} / 25`);
console.log(`Locker key: ${result.locker_key}`);
console.log('\nShare this locker code with recipient:');
console.log(lockerCode);
} else {
console.error('Upload failed:', result.message);
}
} catch (error) {
console.error('Error uploading to locker:', error);
}
}
// Example: Upload 500 CloudCoins with secure code
uploadToLocker('MySecretCode2025!', 500);
cURL
# Upload 500 CloudCoins to locker
curl -X GET "http://localhost:8080/api/raida/locker/upload?locker_code=MySecretCode2025!&amount=500"
# Example with URL encoding for special characters
curl -X GET "http://localhost:8080/api/raida/locker/upload?locker_code=My%20Secret%20Code%202025%21&amount=100"
# Example with insufficient funds (will return 400 error)
curl -X GET "http://localhost:8080/api/raida/locker/upload?locker_code=test&amount=999999"
Go
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
const ApiHost = "http://localhost:8080"
type LockerUploadResponse struct {
Status string `json:"status"`
Operation string `json:"operation"`
AmountRequested int `json:"amount_requested"`
AmountUploaded int `json:"amount_uploaded"`
CoinsUploaded int `json:"coins_uploaded"`
LockerKey string `json:"locker_key"`
SuccessfulUploads int `json:"successful_uploads"`
Message string `json:"message"`
}
func uploadToLocker(lockerCode string, amount int) error {
// Build URL with query parameters
baseURL := fmt.Sprintf("%s/api/raida/locker/upload", ApiHost)
params := url.Values{}
params.Add("locker_code", lockerCode)
params.Add("amount", fmt.Sprintf("%d", amount))
fullURL := fmt.Sprintf("%s?%s", baseURL, params.Encode())
resp, err := http.Get(fullURL)
if err != nil {
return fmt.Errorf("HTTP request failed: %v", err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var result LockerUploadResponse
if err := json.Unmarshal(body, &result); err != nil {
return fmt.Errorf("JSON decode failed: %v", err)
}
if result.Status == "success" {
fmt.Println("Upload Successful!")
fmt.Printf("Coins uploaded: %d\n", result.CoinsUploaded)
fmt.Printf("Amount uploaded: %d units\n", result.AmountUploaded)
fmt.Printf("RAIDAs confirmed: %d / 25\n", result.SuccessfulUploads)
fmt.Printf("Locker key: %s\n", result.LockerKey)
fmt.Printf("\nShare this locker code with recipient:\n%s\n", lockerCode)
} else {
fmt.Printf("Upload failed: %s\n", result.Message)
}
return nil
}
func main() {
// Upload 500 CloudCoins with secure code
if err := uploadToLocker("MySecretCode2025!", 500); err != nil {
panic(err)
}
}
Related Endpoints
/api/raida/lockers/peek
View the contents of a locker without downloading the coins. Check balance before downloading.
/api/transactions/locker/download
Download coins from a locker to your wallet using the locker code or key.
/api/wallet/balance
Check your wallet balance before uploading coins to ensure sufficient funds.
Implementation Notes
This endpoint is fully implemented and production-ready (CloudCoinConsole v192+). All features are complete and tested:
- Parallel RAIDA execution (all 25 RAIDAs queried simultaneously)
- Greedy coin selection algorithm
- Cloud consensus (13/25 threshold)
- Automatic folder management (Lockered folder creation)
- Proper error handling and rollback on failure
- Test First: Use small amounts (1-5 units) when testing
- Check Balance: Call
/api/wallet/balancebefore uploading - Secure Codes: Use strong, random locker codes (12+ characters with mixed case, numbers, symbols)
- Share Safely: Only share locker codes through secure channels (encrypted messaging, in person, etc.)
- Verify Upload: Check the
successful_uploadsfield - should be 24-25 for optimal reliability - Timeout: RAIDA operations have a 10-second timeout - expect 1-3 second response times normally