/api/transactions/locker/put-one-coin

GET

Upload 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.

Single Coin with Serial Number

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:

  1. Wallet Lock: Acquires a wallet lock to prevent concurrent modifications.
  2. Coin Selection: Finds one coin matching the requested denomination from Bank, then Fracked if not found in Bank.
  3. RAIDA Upload: Sends Locker Put (0x0852) requests to all 25 RAIDAs in parallel with XOR-sum verification.
  4. Consensus Verification: Requires 13+ successful RAIDA responses to complete the upload.
  5. File Management: Moves the coin file from Bank/Fracked to the Locker folder on success.
  6. Wallet Unlock: Releases the wallet lock.
Security Warning

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.
Metric Denomination Values

Denominations are metric (powers of 10). Pass the actual value, not a code:

Denomination ParameterNameDescription
0.00000001Nanno10-8 CloudCoin (smallest unit)
0.0000001Micro-Cent10-7 CloudCoin
0.000001Milli-Cent10-6 CloudCoin
0.00001Centi-Cent10-5 CloudCoin
0.0001Deci-Cent10-4 CloudCoin
0.001Cent10-3 CloudCoin (1/1000)
0.01Deci10-2 CloudCoin (1/100)
0.1One-Tenth10-1 CloudCoin (1/10)
1One1 CloudCoin
10Ten10 CloudCoins
100Hundred100 CloudCoins
1000Thousand1,000 CloudCoins
10000Ten-K10,000 CloudCoins
100000Hundred-K100,000 CloudCoins
1000000Million1,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

status string
"success" or "error"
operation string
Always "locker_upload".
denomination number
The denomination of the coin that was uploaded (e.g., 1, 100, 0.01).
serial_number integer
The serial number of the coin that was uploaded. This uniquely identifies the coin on the RAIDA.
amount_uploaded integer
The value of the uploaded coin in whole CloudCoin units.
coins_uploaded integer
Always 1 for this endpoint.
locker_key string
The locker key used for the upload.
successful_uploads integer
Number of RAIDAs that successfully confirmed the upload (out of 25). Should be 13+ for success.
message string
Always "Single coin uploaded to locker" on success.
task_id string
Transaction ID for tracking in wallet transaction log.

Error Responses

The endpoint returns appropriate HTTP status codes with JSON error messages.

HTTP 400 - Bad Request

  • Missing or empty locker_key parameter
  • Missing denomination parameter
  • 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

Best Practices
  • Test First: Use small denominations (denomination=0.00000001) when testing
  • Save the Serial Number: The serial_number in 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
Common Issues
  • 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.