/api/transactions/export

GET

Export CloudCoins from a specified wallet to a destination folder for sharing or transfer.

⚠️ IMPLEMENTATION STATUS: PARAMETER VALIDATION ONLY

This endpoint is currently NOT FULLY IMPLEMENTED. It performs parameter validation and returns success, but does not actually export coins from the wallet.

  • Current behavior: Validates the amount parameter and returns success with validated parameters
  • Missing functionality: Does not read coins from Bank/Fracked folders, does not copy coins to Export folder, does not update transactions.csv
  • TODO: Call cmd_export_coins() and capture actual export results

This documentation describes the intended functionality once fully implemented.

Description

The `/api/transactions/export` endpoint exports CloudCoins from a specified wallet's Bank and Fracked folders to a destination folder (typically "Export"). Exported coins can be shared with others or transferred to a different wallet.

Backward Compatibility: If no wallet_path parameter is provided, the endpoint uses the active wallet. This ensures existing integrations continue to work without modification.

The endpoint will select coins from available authenticated (Bank) and partially-authenticated (Fracked) coins to meet the requested amount. Coins are copied, not moved, so they remain in the original folders after export.

💡 Use Cases

This endpoint is useful for:

  • Transferring CloudCoins to another user
  • Creating backups of specific amounts
  • Preparing coins for sending via email or file transfer
  • Splitting wallet holdings across multiple locations
⚠️ Important Notes
  • Exported coins are COPIED, not moved - they remain in Bank/Fracked folders
  • Amount is specified in whole units (1, 5, 25, 100, 250, etc.), not individual coin serial numbers
  • The system will select appropriate denomination coins to meet the requested amount
  • Export operations are logged in transactions.csv for audit purposes (when fully implemented)
  • wallet_path parameter: Specify a wallet path to export from a non-active wallet. If omitted, the active wallet is used for backward compatibility
  • Path formats supported: Absolute paths (e.g., C:\Wallets\MyWallet) or relative paths from the program directory

Parameters

All parameters are passed as URL query parameters.

Parameter Type Required Description
amount integer Yes Number of whole CloudCoin units to export. Must be a positive integer (e.g., 100, 250, 1000). The system will select appropriate denomination coins to meet this amount.
destination string No Destination folder name within the wallet directory. Defaults to "Export" if not specified. Common values: "Export", "Shared", "Backup".
wallet_path string No Path to the wallet to export from. Can be absolute (e.g., C:\Wallets\MyWallet) or relative to program directory. If not specified, uses the currently active wallet. This parameter enables exporting from non-active wallets without changing the active wallet.

Response

Returns a JSON object with export operation results.

Success Response Properties

status string
Always "success" for successful export operations.
operation string
Always "export".
amount integer
The requested amount to export (validated parameter).
destination string
The destination folder name (validated parameter or default "Export").
message string
Currently: "Export endpoint - implementation pending". When fully implemented, this will contain export confirmation details.
exported integer
Number of coins actually exported. Currently always 0 (not implemented). When implemented, will show the count of coins copied to destination.
wallet_path string
The wallet path used for the export operation. Will be the specified wallet_path if provided, or the active wallet path if wallet_path was not specified.

Future Implementation Properties

When fully implemented, the response will also include:

exported_value integer
Total value of exported coins in whole units.
filename string
Generated export filename containing the exported coins.
file_path string
Full path to the exported file.
transaction_id string
Transaction ID logged in transactions.csv.

Current Example Response (Parameter Validation Only)

{
  "status": "success",
  "operation": "export",
  "amount": 100,
  "destination": "Export",
  "wallet_path": "C:\\MyWallets\\Default",
  "message": "Export endpoint - implementation pending",
  "exported": 0
}

Future Example Response (When Fully Implemented)

{
  "status": "success",
  "operation": "export",
  "amount": 100,
  "destination": "Export",
  "wallet_path": "C:\\MyWallets\\Default",
  "exported": 2,
  "exported_value": 100,
  "filename": "export_100cc_2025-01-31_15-30-45.stack",
  "file_path": "C:\\MyWallets\\Default\\Export\\export_100cc_2025-01-31_15-30-45.stack",
  "transaction_id": "2025-01-31_15-30-45",
  "message": "Successfully exported 100 CloudCoins (2 coins) to Export folder"
}

Error Responses

400 Bad Request

Returned when the amount parameter is invalid.

{
  "status": "error",
  "operation": "export",
  "error_code": 400,
  "message": "Invalid amount parameter"
}

Common causes:

  • Missing amount parameter
  • Non-numeric amount value
  • Negative or zero amount
500 Internal Server Error (Future)

When fully implemented, may be returned for various operational errors:

  • Insufficient balance to export requested amount
  • No wallet currently active
  • Unable to create destination folder
  • File I/O errors during export
  • Transaction logging failures

Examples

JavaScript (fetch)

const API_HOST = 'http://localhost:8080';

// Export coins from active wallet (backward compatible)
async function exportCoins(amount, destination = 'Export', walletPath = null) {
    try {
        const params = new URLSearchParams({
            amount: amount,
            destination: destination
        });

        // Add wallet_path if specified (enables exporting from non-active wallets)
        if (walletPath) {
            params.append('wallet_path', walletPath);
        }

        const response = await fetch(`${API_HOST}/api/transactions/export?${params}`);
        const result = await response.json();

        if (result.status === 'success') {
            console.log(`Export initiated: ${result.amount} coins`);
            console.log(`Destination: ${result.destination}`);
            console.log(`Wallet: ${result.wallet_path}`);
            console.log(`Message: ${result.message}`);

            // When fully implemented:
            // console.log(`Exported ${result.exported} coins worth ${result.exported_value} units`);
            // console.log(`File: ${result.filename}`);
        } else {
            console.error('Export failed:', result.message);
        }

        return result;
    } catch (error) {
        console.error('Error exporting coins:', error);
        throw error;
    }
}

// Example 1: Export from active wallet (backward compatible)
await exportCoins(100, 'Export');

// Example 2: Export from active wallet with custom destination
await exportCoins(250, 'Backup');

// Example 3: Export from non-active wallet (new functionality)
await exportCoins(50, 'Export', 'C:\\Wallets\\MyWallet');

// Example 4: Export from non-active wallet with custom destination
await exportCoins(500, 'Shared', 'Wallets/ArchiveWallet');

cURL

># Example 1: Export from active wallet (backward compatible) curl -X GET "http://localhost:8080/api/transactions/export?amount=100" # Example 2: Export from active wallet to custom destination curl -X GET "http://localhost:8080/api/transactions/export?amount=250&destination=Backup" # Example 3: Export with wallet_path parameter (Windows) curl -X GET "http://localhost:8080/api/transactions/export?amount=100&destination=E:\coins&wallet_path=E:/Data/Wallets/Default" # Example 4: Export with custom destination curl -X GET "http://localhost:8080/api/transactions/export?amount=500&destination=E:\export&wallet_path=E:/Data/Wallets/Default" # Example 5: Export with formatted output (jq) curl -X GET "http://localhost:8080/api/transactions/export?amount=100&destination=E:\coins&wallet_path=E:/Data/Wallets/Default" | jq .

Go

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "net/url"
)

const ApiHost = "http://localhost:8080"

type ExportResponse struct {
    Status      string `json:"status"`
    Operation   string `json:"operation"`
    Amount      int    `json:"amount"`
    Destination string `json:"destination"`
    WalletPath  string `json:"wallet_path"`
    Message     string `json:"message"`
    Exported    int    `json:"exported"`

    // Future implementation fields
    ExportedValue int    `json:"exported_value,omitempty"`
    Filename      string `json:"filename,omitempty"`
    FilePath      string `json:"file_path,omitempty"`
    TransactionID string `json:"transaction_id,omitempty"`
}

func exportCoins(amount int, destination string, walletPath string) (*ExportResponse, error) {
    // Build URL with parameters
    params := url.Values{}
    params.Add("amount", fmt.Sprintf("%d", amount))
    params.Add("destination", destination)

    // Add wallet_path only if specified (maintains backward compatibility)
    if walletPath != "" {
        params.Add("wallet_path", walletPath)
    }

    url := fmt.Sprintf("%s/api/transactions/export?%s", ApiHost, params.Encode())

    resp, err := http.Get(url)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    var result ExportResponse
    if err := json.Unmarshal(body, &result); err != nil {
        return nil, err
    }

    return &result, nil
}

func main() {
    // Example 1: Export from active wallet (backward compatible)
    result1, err := exportCoins(100, "Export", "")
    if err != nil {
        panic(err)
    }
    fmt.Println("Example 1: Active wallet export")
    fmt.Printf("  Wallet: %s\n", result1.WalletPath)
    fmt.Printf("  Amount: %d\n", result1.Amount)
    fmt.Printf("  Destination: %s\n\n", result1.Destination)

    // Example 2: Export from non-active wallet
    result2, err := exportCoins(50, "Export", "C:\\Wallets\\MyWallet")
    if err != nil {
        panic(err)
    }
    fmt.Println("Example 2: Non-active wallet export")
    fmt.Printf("  Wallet: %s\n", result2.WalletPath)
    fmt.Printf("  Amount: %d\n", result2.Amount)
    fmt.Printf("  Destination: %s\n\n", result2.Destination)

    // Example 3: Export from relative path
    result3, err := exportCoins(250, "Backup", "Wallets/ArchiveWallet")
    if err != nil {
        panic(err)
    }
    fmt.Println("Example 3: Relative path wallet export")
    fmt.Printf("  Wallet: %s\n", result3.WalletPath)
    fmt.Printf("  Amount: %d\n", result3.Amount)
    fmt.Printf("  Destination: %s\n", result3.Destination)

    // When fully implemented, also show:
    // if result1.Filename != "" {
    //     fmt.Printf("Export file: %s\n", result1.Filename)
    //     fmt.Printf("Transaction ID: %s\n", result1.TransactionID)
    // }
}

Implementation Details

Current Implementation Status

The endpoint is defined in api_handlers.c (lines 667-690) and currently:

  • ✓ Validates the amount parameter (must be present and numeric)
  • ✓ Accepts optional destination parameter (defaults to "Export")
  • ✓ Accepts optional wallet_path parameter (defaults to active wallet for backward compatibility)
  • ✓ Returns structured JSON response with wallet_path information
  • ✗ Does NOT read coins from Bank/Fracked folders
  • ✗ Does NOT select coins to meet requested amount
  • ✗ Does NOT copy coins to destination folder
  • ✗ Does NOT generate export filenames
  • ✗ Does NOT update transactions.csv

Planned Full Implementation

When fully implemented (via cmd_export_coins() in commands.c), the endpoint will:

  1. Resolve the wallet path:
    • If wallet_path is provided: Use that wallet's Bank and Fracked folders
    • If wallet_path is omitted: Use the active wallet (backward compatible)
    • Support both absolute paths (e.g., C:\Wallets\MyWallet) and relative paths
  2. Read all coins from the specified wallet's Bank and Fracked folders
  3. Select coins whose total value meets or exceeds the requested amount
  4. Generate a timestamp-based filename (e.g., export_100cc_2025-01-31_15-30-45.stack)
  5. Copy selected coins to the destination folder within the specified wallet
  6. Create binary format (.stack) or JSON format files based on configuration
  7. Log the transaction in transactions.csv with:
    • Transaction ID (timestamp)
    • Operation type ("export")
    • Wallet path used
    • Amount requested vs amount exported
    • Number of coins exported
    • Destination folder path
  8. Return detailed results including exported coin count, file paths, and wallet path used

Coin Selection Algorithm

The system will use a denomination-based selection strategy:

  • Prefer larger denominations first to minimize coin count
  • Include fracked coins if needed to meet the amount
  • May export slightly more than requested if exact change isn't available

Backward Compatibility

✓ Fully Backward Compatible

The wallet_path parameter is entirely optional and maintains 100% backward compatibility:

  • Existing code without wallet_path: Works exactly as before - uses the active wallet
  • No breaking changes: All existing integrations continue to function without modification
  • Gradual migration: Add wallet_path to your code only when you need to export from non-active wallets
  • Response field: The new wallet_path field in responses is always present (showing which wallet was actually used)

Migration Path

If you have existing code, you can gradually adopt the wallet_path parameter:

// Old code (still works without any changes)
const result1 = await fetch('http://localhost:8080/api/transactions/export?amount=100');

// New code with wallet_path support
const result2 = await fetch('http://localhost:8080/api/transactions/export?amount=100&wallet_path=C%3A%5CWallets%5CArchive');

// Response always includes wallet_path (showing which wallet was used)
// Old code: wallet_path will show the active wallet
// New code: wallet_path will show the specified wallet

Workflow Example

💡 Typical Export Workflow (Future)
  1. Check wallet balance: GET /api/wallet/balance
  2. Verify sufficient funds available
  3. Export desired amount: GET /api/transactions/export?amount=100
  4. Verify export in Export folder
  5. Share exported file with recipient
  6. Recipient imports using: POST /api/transactions/import

Related Endpoints

/api/transactions/import

Import CloudCoins from external files into the active wallet's Import folder for authentication.

/api/wallet/balance

Check current wallet balance before exporting to verify sufficient funds.

/api/coins/export

Alternative export endpoint with additional format options (JSON, PNG, JPEG).

File Format Information

When fully implemented, exported files will use CloudCoin Version 3, File Format 9:

  • File extension: .stack (binary format) or .json (JSON format)
  • File header: 32 bytes containing format version, coin ID, encryption type, and coin count
  • Per-coin data: 407 bytes (7-byte header + 400-byte body with 25 Authenticity Numbers)
  • Encryption: Optional AES-128-CTR or AES-256-CTR encryption