/api/transactions/locker/put-one-coin
GETUpload exactly one CloudCoin of a specified denomination to a RAIDA locker and return its serial number.
Description
The /api/transactions/locker/put-one-coin endpoint uploads exactly one CloudCoin of a specified denomination from your wallet to the RAIDA cloud locker system. Unlike LockerStore which uploads coins totaling an amount, this endpoint selects a single coin matching the requested denomination and returns its serial number in the response.
This endpoint is designed for cases where you need to know the exact serial number of the coin placed in the locker. It always uploads exactly one coin and includes the serial_number and denomination in the success response.
The endpoint performs a multi-phase operation:
- Wallet Lock: Acquires a wallet lock to prevent concurrent modifications.
- Coin Selection: Finds one coin matching the requested denomination from Bank, then Fracked if not found in Bank.
- RAIDA Upload: Sends Locker Put (0x0852) requests to all 25 RAIDAs in parallel with XOR-sum verification.
- Consensus Verification: Requires 13+ successful RAIDA responses to complete the upload.
- File Management: Moves the coin file from Bank/Fracked to the Locker folder on success.
- Wallet Unlock: Releases the wallet lock.
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 both locker_key and denomination.
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 | Yes | The denomination of the coin to upload. Must be a valid metric denomination value (see table below). |
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
1 x [DN(1 byte) + SN(4 bytes)] // Single coin record
+ XOR_SUM(16 bytes) // The coin's AN for this RAIDA (single coin = no XOR needed)
+ LOCKER_CODE(16 bytes) // Per-RAIDA derived locker code (ends with 0xFFFFFFFF)
Body size = 5 + 16 + 16 = 37 bytes (always exactly one coin).
Response Status Codes
- 241 (Sum Was Correct): Coin 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 the uploaded coin's serial number and denomination.
Example: Success
{
"status": "success",
"operation": "locker_upload",
"denomination": 100,
"serial_number": 4589231,
"amount_uploaded": 100,
"coins_uploaded": 1,
"locker_key": "CUP-1974",
"successful_uploads": 24,
"message": "Single coin uploaded to locker",
"task_id": "a1b2c3d4"
}
Example: Fractional Denomination Success
{
"status": "success",
"operation": "locker_upload",
"denomination": 0.01,
"serial_number": 12345678,
"amount_uploaded": 0,
"coins_uploaded": 1,
"locker_key": "PENNY-JAR",
"successful_uploads": 25,
"message": "Single coin uploaded to locker",
"task_id": "e5f6g7h8"
}
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
denominationparameter - Invalid denomination (not a valid metric value)
- Invalid wallet path
HTTP 404 - Not Found
- No coins in Bank folder
- No coin of requested denomination found in Bank or Fracked
HTTP 500 - Internal Server Error
- Upload failed — insufficient RAIDA confirmations (fewer than 13)
- Transport not initialized
Example: Invalid Denomination
{
"success": false,
"message": "Invalid denomination. Valid values: 0.00000001, 0.0000001, 0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 1000, 10000, 100000, 1000000",
"denomination_requested": "50",
"locker_key": "MY-KEY"
}
Example: Coin Not Found
{
"success": false,
"message": "No coin of requested denomination found in Bank or Fracked",
"denomination": 1000,
"locker_key": "MY-KEY"
}
Example: Upload Failed
{
"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
# Upload one 1 CC coin to locker
curl "http://localhost:8080/api/transactions/locker/put-one-coin?locker_key=CUP-1974&denomination=1"
# Upload one 100 CC coin
curl "http://localhost:8080/api/transactions/locker/put-one-coin?locker_key=GIFT-CODE&denomination=100"
# Upload one 0.01 CC (1 cent) coin
curl "http://localhost:8080/api/transactions/locker/put-one-coin?locker_key=PENNY&denomination=0.01"
# Upload one coin from a specific wallet
curl "http://localhost:8080/api/transactions/locker/put-one-coin?locker_key=MY-KEY&denomination=10&wallet_path=/path/to/wallet"
# Upload smallest denomination (nanno)
curl "http://localhost:8080/api/transactions/locker/put-one-coin?locker_key=TINY&denomination=0.00000001"
JavaScript (fetch)
const API_HOST = 'http://localhost:8080';
// Upload exactly one coin of a given denomination and get its serial number
async function lockerPutOneCoin(lockerKey, denomination, walletPath = null) {
let url = `${API_HOST}/api/transactions/locker/put-one-coin?` +
`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 ${result.denomination})`);
console.log(`Serial Number: ${result.serial_number}`);
console.log(`RAIDAs confirmed: ${result.successful_uploads}/25`);
} else {
console.error('Upload failed:', result.message);
}
return result;
}
// Examples:
// Upload one 1 CC coin and get its serial number
lockerPutOneCoin('CUP-1974', 1);
// Upload one 100 CC coin
lockerPutOneCoin('GIFT-CODE', 100);
// Upload one 0.01 CC coin (1 cent)
lockerPutOneCoin('PENNY', 0.01);
// Upload one 1000 CC coin from specific wallet
lockerPutOneCoin('BIG-ONE', 1000, 'E:/Wallets/MyWallet');
Go
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
const ApiHost = "http://localhost:8080"
type PutOneCoinResponse struct {
Status string `json:"status"`
Operation string `json:"operation"`
Denomination float64 `json:"denomination"`
SerialNumber int `json:"serial_number"`
AmountUploaded int `json:"amount_uploaded"`
CoinsUploaded int `json:"coins_uploaded"`
LockerKey string `json:"locker_key"`
SuccessfulUploads int `json:"successful_uploads"`
Message string `json:"message"`
TaskID string `json:"task_id"`
}
// Upload exactly one coin by denomination and get its serial number
func putOneCoin(lockerKey string, denomination float64, walletPath string) (*PutOneCoinResponse, 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/put-one-coin?%s",
ApiHost, params.Encode())
resp, err := http.Get(fullURL)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var result PutOneCoinResponse
json.Unmarshal(body, &result)
return &result, nil
}
func main() {
// Upload one 1 CC coin
result, err := putOneCoin("CUP-1974", 1.0, "")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Status: %s\n", result.Status)
fmt.Printf("Denomination: %g CC\n", result.Denomination)
fmt.Printf("Serial Number: %d\n", result.SerialNumber)
fmt.Printf("RAIDAs confirmed: %d/25\n", result.SuccessfulUploads)
// Upload one 100 CC coin
result, _ = putOneCoin("GIFT-CODE", 100.0, "")
fmt.Printf("100 CC coin SN: %d (%d/25 RAIDAs)\n",
result.SerialNumber, result.SuccessfulUploads)
// Upload one 0.01 CC coin (1 cent)
result, _ = putOneCoin("PENNY", 0.01, "")
fmt.Printf("Cent coin SN: %d (%d/25 RAIDAs)\n",
result.SerialNumber, result.SuccessfulUploads)
}
Comparison with Other Locker Endpoints
| Feature | Put One Coin | LockerStore (put-no-sum) | Locker Upload |
|---|---|---|---|
| Input | denomination (single coin) |
amount (total value) |
denomination or amount |
| Coins uploaded | Always exactly 1 | Multiple (greedy selection) | 1 or multiple |
| Returns serial number | Yes | Per-coin results array | Only in single coin mode |
| Wallet locking | Yes (thread-safe) | No | No |
| Authentication | XOR-sum (0x0852) | Per-coin AN (0x0850) | XOR-sum (0x0852) |
| Best for | When you need the serial number of the specific coin placed in locker | Bulk uploads with per-coin results | General-purpose locker uploads |
Related Endpoints
/api/transactions/locker/put-no-sum
Upload coins totaling an amount using per-coin authentication. Best for bulk uploads with per-coin results.
/api/transactions/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.
Implementation Notes
- Test First: Use small denominations (denomination=0.00000001) when testing
- Save the Serial Number: The
serial_numberin the response uniquely identifies the coin — save it if you need to track the coin later - Check Balance: Ensure wallet has a coin of the requested denomination before calling
- 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.
- Coin Not Found: Ensure the wallet has at least one coin of the requested denomination in Bank or Fracked.
- 0/25 Success: Coin may already be in a locker, or ANs are out of sync. Run frack fix first.
- Same Key Reuse: Using the same locker_key adds coins to the existing locker — recipient gets all coins uploaded with that key.