/api/transactions/locker/upload
GETUpload CloudCoins from your wallet to a RAIDA locker using a secure locker key.
Description
The /api/transactions/locker/upload endpoint uploads CloudCoins from your wallet to the RAIDA cloud locker system. This endpoint supports two modes of operation:
- Single Coin Mode: Use the
denominationparameter to upload exactly one coin of a specific denomination. - Amount Mode: Use the
amountparameter to upload coins totaling a specific value (uses greedy selection).
The endpoint performs a multi-phase operation:
- Coin Selection: Reads coins from the Bank folder and selects based on mode (single denomination or amount).
- RAIDA Upload: Sends Locker Put (0x0852) requests to all 25 RAIDAs in parallel with XOR-sum verification.
- Consensus Verification: Requires 13+ successful RAIDA responses (cloud consensus) to complete the upload.
The locker_key parameter is essentially a password. Anyone with this key can download the coins from the locker. Keep it secret and share it securely with the intended recipient only.
Parameters
This endpoint requires locker_key plus either denomination (single coin) or amount (multiple coins).
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
locker_key |
string | Yes | Any string of characters (e.g., "ABC-1234"). This becomes the password to access the locker. |
denomination |
number | No* | Single Coin Mode. Upload exactly one coin of this denomination. Values are metric (powers of 10) including fractional: 0.00000001, 0.0000001, ..., 0.1, 1, 10, 100, ..., 1000000. *Required if amount not provided. |
amount |
integer | No* | Amount Mode. Upload coins totaling this many whole CloudCoin units. Uses greedy selection (largest denominations first). *Required if denomination not provided. |
wallet_path |
string | No | Full path to the wallet directory containing the coins. If omitted, uses the default wallet. |
wallet |
string | No | Wallet name (alternative to wallet_path). Looks up wallet in standard locations. |
Denominations are metric (powers of 10). Pass the actual value, not a code:
| Denomination Parameter | Name | Description |
|---|---|---|
| 0.00000001 | Nanno | 10-8 CloudCoin (smallest unit) |
| 0.0000001 | Micro-Cent | 10-7 CloudCoin |
| 0.000001 | Milli-Cent | 10-6 CloudCoin |
| 0.00001 | Centi-Cent | 10-5 CloudCoin |
| 0.0001 | Deci-Cent | 10-4 CloudCoin |
| 0.001 | Cent | 10-3 CloudCoin (1/1000) |
| 0.01 | Deci | 10-2 CloudCoin (1/100) |
| 0.1 | One-Tenth | 10-1 CloudCoin (1/10) |
| 1 | One | 1 CloudCoin |
| 10 | Ten | 10 CloudCoins |
| 100 | Hundred | 100 CloudCoins |
| 1000 | Thousand | 1,000 CloudCoins |
| 10000 | Ten-K | 10,000 CloudCoins |
| 100000 | Hundred-K | 100,000 CloudCoins |
| 1000000 | Million | 1,000,000 CloudCoins |
Locker Key Format
The locker_key can be any string. We recommend a format like "ABC-1234" for easy sharing, but any characters work.
Example locker_key values:
CUP-1974
MySecret2025
ABC-DEFG-1234
gift-for-alice
Important: The same locker_key always accesses the same locker. Keep your locker_key secret and share it securely with the intended recipient only. Anyone with the locker_key can download the coins.
RAIDA Protocol Details
This endpoint uses the RAIDA Locker Put command (0x0852).
Command Code
0x0852 (Command Group: 0x08 = Locker, Command: 0x52 = Put)
Request Body Format
N x [DN(1 byte) + SN(4 bytes)] // Token records
+ XOR_SUM(16 bytes) // XOR of all ANs for this RAIDA
+ LOCKER_CODE(16 bytes) // Per-RAIDA derived locker code (ends with 0xFFFFFFFF)
Body size = (N x 5) + 16 + 16 = (N x 5) + 32 bytes, where N is the number of coins.
XOR Sum Calculation
Each coin's AN (16 bytes) is treated as four little-endian 32-bit integers. All coins' ANs are XORed together to produce the 16-byte sum. The RAIDA verifies this sum matches its stored ANs.
Response Status Codes
- 241 (Sum Was Correct): All coins uploaded successfully
- 242 (Sum Was Not Correct): XOR sum mismatch - coin may be counterfeit or already in a locker
Consensus Requirement
Requires 13 or more out of 25 RAIDAs to return status 241 for success.
Response
Returns a JSON object with upload results. Response format varies slightly between single coin and amount modes.
Example: Single Coin Mode Success
{
"status": "success",
"operation": "locker_upload",
"denomination": 1,
"amount_uploaded": 1,
"coins_uploaded": 1,
"locker_key": "NEW-KEY1",
"successful_uploads": 24,
"message": "Single coin uploaded to locker"
}
Example: Amount Mode Success
{
"status": "success",
"operation": "locker_upload",
"amount_requested": 500,
"amount_uploaded": 500,
"coins_uploaded": 3,
"locker_key": "CUP-1974",
"successful_uploads": 24,
"message": "Coins uploaded to locker successfully"
}
Response Properties
Error Responses
The endpoint returns appropriate HTTP status codes with JSON error messages.
HTTP 400 - Bad Request
- Missing or empty
locker_keyparameter - Missing both
amountanddenominationparameters - Invalid amount (must be greater than 0)
- Insufficient balance in wallet
- Invalid wallet path
HTTP 404 - Not Found
- No coins in Bank folder
- No coin of requested denomination found (single coin mode)
- Wallet not found
HTTP 500 - Internal Server Error
- Upload failed - insufficient RAIDA confirmations (fewer than 13)
- Failed to get encryption keys
Example Error Response
{
"status": "error",
"operation": "locker_upload",
"message": "Upload failed - insufficient RAIDA confirmations",
"error": "Success",
"locker_key": "MY-KEY",
"successful_uploads": 0,
"failed_uploads": 25
}
Examples
cURL
# Single Coin Mode: Upload one 1 CC coin
curl "http://localhost:8080/api/transactions/locker/upload?locker_key=MY-KEY&denomination=1"
# Single Coin Mode: Upload one 0.01 CC (1 cent) coin
curl "http://localhost:8080/api/transactions/locker/upload?locker_key=PENNY&denomination=0.01"
# Single Coin Mode: Upload one 100 CC coin from specific wallet
curl "http://localhost:8080/api/transactions/locker/upload?locker_key=GIFT-CODE&denomination=100&wallet_path=/path/to/wallet"
# Single Coin Mode: Upload one 1000 CC coin
curl "http://localhost:8080/api/transactions/locker/upload?locker_key=BIG-ONE&denomination=1000"
# Single Coin Mode: Upload smallest denomination (nanno)
curl "http://localhost:8080/api/transactions/locker/upload?locker_key=TINY-COIN&denomination=0.00000001"
# Amount Mode: Upload 500 CloudCoins worth of coins
curl "http://localhost:8080/api/transactions/locker/upload?locker_key=CUP-1974&amount=500"
# Amount Mode: Upload 100 CloudCoins from a named wallet
curl "http://localhost:8080/api/transactions/locker/upload?locker_key=ABC-1234&amount=100&wallet=MyWallet"
JavaScript (fetch)
const API_HOST = 'http://localhost:8080';
// Upload a single coin by denomination
async function uploadSingleCoin(lockerKey, denomination, walletPath = null) {
let url = `${API_HOST}/api/transactions/locker/upload?` +
`locker_key=${encodeURIComponent(lockerKey)}&` +
`denomination=${denomination}`;
if (walletPath) {
url += `&wallet_path=${encodeURIComponent(walletPath)}`;
}
const response = await fetch(url);
const result = await response.json();
if (result.status === 'success') {
console.log(`Uploaded 1 coin (denom ${denomination}) to locker`);
console.log(`RAIDAs confirmed: ${result.successful_uploads}/25`);
} else {
console.error('Upload failed:', result.message);
}
return result;
}
// Upload coins by amount
async function uploadByAmount(lockerKey, amount, walletPath = null) {
let url = `${API_HOST}/api/transactions/locker/upload?` +
`locker_key=${encodeURIComponent(lockerKey)}&` +
`amount=${amount}`;
if (walletPath) {
url += `&wallet_path=${encodeURIComponent(walletPath)}`;
}
const response = await fetch(url);
const result = await response.json();
if (result.status === 'success') {
console.log(`Uploaded ${result.coins_uploaded} coins (${result.amount_uploaded} CC)`);
console.log(`RAIDAs confirmed: ${result.successful_uploads}/25`);
} else {
console.error('Upload failed:', result.message);
}
return result;
}
// Examples:
// Upload one 1 CC coin
uploadSingleCoin('GIFT-CODE', 1);
// Upload one 0.01 CC coin (1 cent)
uploadSingleCoin('PENNY', 0.01);
// Upload one 100 CC coin
uploadSingleCoin('MY-KEY', 100);
// Upload one 1000 CC coin from specific wallet
uploadSingleCoin('BIG-ONE', 1000, 'E:/Wallets/MyWallet');
// Upload smallest denomination (nanno)
uploadSingleCoin('TINY', 0.00000001);
// Upload 500 CloudCoins worth (amount mode)
uploadByAmount('CUP-1974', 500);
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"`
Denomination float64 `json:"denomination,omitempty"`
AmountRequested int `json:"amount_requested,omitempty"`
AmountUploaded int `json:"amount_uploaded"`
CoinsUploaded int `json:"coins_uploaded"`
LockerKey string `json:"locker_key"`
SuccessfulUploads int `json:"successful_uploads"`
Message string `json:"message"`
}
// Upload a single coin by denomination (supports fractional: 0.00000001 to 1000000)
func uploadSingleCoin(lockerKey string, denomination float64, walletPath string) (*LockerUploadResponse, error) {
params := url.Values{}
params.Add("locker_key", lockerKey)
params.Add("denomination", fmt.Sprintf("%g", denomination))
if walletPath != "" {
params.Add("wallet_path", walletPath)
}
fullURL := fmt.Sprintf("%s/api/transactions/locker/upload?%s", ApiHost, params.Encode())
return doRequest(fullURL)
}
// Upload coins by amount
func uploadByAmount(lockerKey string, amount int, walletPath string) (*LockerUploadResponse, error) {
params := url.Values{}
params.Add("locker_key", lockerKey)
params.Add("amount", fmt.Sprintf("%d", amount))
if walletPath != "" {
params.Add("wallet_path", walletPath)
}
fullURL := fmt.Sprintf("%s/api/transactions/locker/upload?%s", ApiHost, params.Encode())
return doRequest(fullURL)
}
func doRequest(url string) (*LockerUploadResponse, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var result LockerUploadResponse
json.Unmarshal(body, &result)
return &result, nil
}
func main() {
// Upload one 1 CC coin
result, _ := uploadSingleCoin("GIFT-CODE", 1.0, "")
fmt.Printf("Single coin: %s (%d/25 RAIDAs)\n", result.Status, result.SuccessfulUploads)
// Upload one 0.01 CC coin (1 cent)
result, _ = uploadSingleCoin("PENNY", 0.01, "")
fmt.Printf("Cent coin: %s (%d/25 RAIDAs)\n", result.Status, result.SuccessfulUploads)
// Upload one 1000 CC coin
result, _ = uploadSingleCoin("BIG-ONE", 1000.0, "")
fmt.Printf("1000 CC coin: %s (%d/25 RAIDAs)\n", result.Status, result.SuccessfulUploads)
// Upload 500 CloudCoins worth (amount mode)
result, _ = uploadByAmount("CUP-1974", 500, "")
fmt.Printf("Amount mode: %s (%d coins, %d/25 RAIDAs)\n",
result.Status, result.CoinsUploaded, result.SuccessfulUploads)
}
Related Endpoints
/api/locker/peek
View the contents of a locker without downloading the coins. Check what's inside before downloading.
/api/transactions/locker/download
Download coins from a locker to your wallet using the locker key.
/api/wallet/balance
Check your wallet balance before uploading coins to ensure sufficient funds.
Implementation Notes
- Test First: Use small denominations (denomination=0.00000001) when testing
- Check Balance: Ensure wallet has coins before uploading
- Secure Keys: Use memorable but unpredictable locker keys
- Share Safely: Only share locker keys through secure channels
- Verify Upload: Check
successful_uploads- should be 13+ for success, 24-25 for optimal reliability
- Invalid Denomination: Must be a metric value (power of 10): 0.00000001 through 1000000. Values like 5, 25, 50 are not valid.
- 0/25 Success: Coin may already be in a locker, or ANs are out of sync. Run frack fix first.
- Coin Not Found: Ensure the coin is in the Bank folder, not Fracked or other folders.
- Same Key Reuse: Using the same locker_key creates a new locker or overwrites - recipient gets all coins uploaded with that key.