/api/wallet/receipt

GET

View transaction receipts or list all receipts for the active wallet.

Description

The `/api/wallet/receipt` endpoint provides access to transaction receipts stored in the active wallet's Receipts folder. It operates in two modes:

  1. List Mode (no filename parameter): Returns a list of all receipt files available
  2. Read Mode (filename provided): Returns the full content of a specific receipt file

Receipts are auto-generated by CloudCoin operations (POWN, Detect, Fix, etc.) and contain detailed information about each operation including task ID, summary statistics, and per-coin authentication results with POWN strings.

💡 Use Case

This endpoint is perfect for:

  • Auditing transaction history and authentication results
  • Troubleshooting failed coin authentications
  • Reviewing detailed POWN strings for specific coins
  • Linking task IDs from transactions.csv to detailed receipts
  • Generating reports on wallet operations
📁 Receipt Storage

Receipts are stored in: [wallet]/Receipts/

Filename format: YYYY-MM-DD_HH-MM-SS.operation-type.txt

Example: 2025-01-30_15-30-45.pown.txt

Parameters

All parameters are optional. Omitting the filename parameter triggers List Mode.

filename optional
string

The exact filename of the receipt to read (e.g., "2025-01-30_15-30-45.pown.txt").

If omitted: Returns list of all receipts.

If provided: Returns full content of the specified receipt file.

Response

Returns different JSON structures depending on the mode.

Mode 1: List All Receipts (No Filename)

Response Properties

status string
Always "success" when operation completes successfully.
operation string
Always "wallet-receipt-list" for list mode.
wallet string
Name of the active wallet.
receipts array
Array of receipt objects, each containing a "filename" property. Returns all .txt files found in the Receipts folder.

Example Response (List Mode)

{
  "status": "success",
  "operation": "wallet-receipt-list",
  "wallet": "Default",
  "receipts": [
    {"filename": "2025-01-30_15-30-45.pown.txt"},
    {"filename": "2025-01-30_16-15-22.detect.txt"},
    {"filename": "2025-01-31_09-05-10.fix.txt"},
    {"filename": "2025-01-31_14-22-33.pown.txt"}
  ]
}

Mode 2: Read Specific Receipt (Filename Provided)

Response Properties

status string
Always "success" when operation completes successfully.
operation string
Always "wallet-receipt" for read mode.
wallet string
Name of the active wallet.
filename string
The filename that was requested.
content string
Full content of the receipt file (up to 16KB). Contains task ID, summary statistics, and per-coin results with POWN strings. Newlines are preserved.

Example Response (Read Mode)

{
  "status": "success",
  "operation": "wallet-receipt",
  "wallet": "Default",
  "filename": "2025-01-30_15-30-45.pown.txt",
  "content": "=== Receipt ===\nType: POWN Authentication\nDate: 2025-01-30 15:30:45\nTask ID: Jan-30-25_03-30-45-PM\n\nSummary:\n- Total coins: 5\n- Authenticated: 4\n- Fracked: 1\n- Counterfeit: 0\n\nCoin Results:\nSN 12345 (250): ppppppppppppppppppppppppp (25/25 Pass)\nSN 67890 (100): pppppppppppppnfppppppppp (22/25 Pass - Fracked)\nSN 23456 (25): ppppppppppppppppppppppppp (25/25 Pass)\nSN 34567 (5): ppppppppppppppppppppppppp (25/25 Pass)\nSN 45678 (1): ppppppppppppppppppppppppp (25/25 Pass)\n"
}

Receipt File Format

Receipt files contain detailed transaction information in a human-readable text format.

Typical Receipt Structure

=== Receipt ===
Type: POWN Authentication
Date: 2025-01-30 15:30:45
Task ID: Jan-30-25_03-30-45-PM

Summary:
- Total coins: 5
- Authenticated: 4
- Fracked: 1
- Counterfeit: 0

Coin Results:
SN 12345 (250): ppppppppppppppppppppppppp (25/25 Pass)
SN 67890 (100): pppppppppppppnfppppppppp (22/25 Pass - Fracked)
SN 23456 (25): ppppppppppppppppppppppppp (25/25 Pass)
SN 34567 (5): ppppppppppppppppppppppppp (25/25 Pass)
SN 45678 (1): ppppppppppppppppppppppppp (25/25 Pass)

Receipt Filename Patterns

Receipt filenames follow a strict naming convention:

  • Format: YYYY-MM-DD_HH-MM-SS.operation-type.txt
  • POWN receipts: 2025-01-30_15-30-45.pown.txt
  • Detect receipts: 2025-01-31_09-05-10.detect.txt
  • Fix receipts: 2025-01-31_14-22-33.fix.txt

POWN String Interpretation

Each POWN string contains 25 characters representing authentication status from each RAIDA server:

  • p (0x0A): Pass - Coin authenticated successfully
  • f (0x0F): Fail - Coin rejected as counterfeit
  • n (0x0C): No reply - RAIDA server timeout
  • e (0x0E): Error - Server error occurred
  • u (0x00): Untried - Not yet tested
  • b (0x0B): Broken encryption key
  • d (0x0D): Network dropped

Authentication threshold: 13+ passes (out of 25) required for authenticity.

Error Responses

No Active Wallet (HTTP 400)

{
  "status": "error",
  "message": "No active wallet"
}

Receipt File Not Found (HTTP 404)

{
  "status": "error",
  "message": "Receipt file not found"
}

Examples

JavaScript (fetch)

Example 1: List All Receipts

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

async function listAllReceipts() {
    try {
        const response = await fetch(`${API_HOST}/api/wallet/receipt`);
        const result = await response.json();

        console.log(`Wallet: ${result.wallet}`);
        console.log(`Total receipts: ${result.receipts.length}`);

        result.receipts.forEach(receipt => {
            console.log(`- ${receipt.filename}`);
        });
    } catch (error) {
        console.error('Error listing receipts:', error);
    }
}

listAllReceipts();

Example 2: Read Specific Receipt

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

async function readReceipt(filename) {
    try {
        const url = `${API_HOST}/api/wallet/receipt?filename=${encodeURIComponent(filename)}`;
        const response = await fetch(url);
        const result = await response.json();

        if (result.status === 'success') {
            console.log(`Receipt: ${result.filename}`);
            console.log('Content:');
            console.log(result.content);
        } else {
            console.error(`Error: ${result.message}`);
        }
    } catch (error) {
        console.error('Error reading receipt:', error);
    }
}

readReceipt('2025-01-30_15-30-45.pown.txt');

Example 3: Parse Receipt Content

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

async function analyzeReceipt(filename) {
    try {
        const url = `${API_HOST}/api/wallet/receipt?filename=${encodeURIComponent(filename)}`;
        const response = await fetch(url);
        const result = await response.json();

        if (result.status !== 'success') {
            console.error(`Error: ${result.message}`);
            return;
        }

        const lines = result.content.split('\n');

        // Parse summary section
        const totalMatch = lines.find(l => l.includes('Total coins:'));
        const authMatch = lines.find(l => l.includes('Authenticated:'));
        const frackedMatch = lines.find(l => l.includes('Fracked:'));

        if (totalMatch && authMatch && frackedMatch) {
            const total = parseInt(totalMatch.split(':')[1].trim());
            const authenticated = parseInt(authMatch.split(':')[1].trim());
            const fracked = parseInt(frackedMatch.split(':')[1].trim());

            console.log(`Analysis of ${filename}:`);
            console.log(`- Success rate: ${((authenticated / total) * 100).toFixed(1)}%`);
            console.log(`- Fracked: ${fracked}`);
        }

        // Extract POWN strings
        const coinResults = lines.filter(l => l.includes('SN '));
        console.log('\nCoin Details:');
        coinResults.forEach(line => {
            const match = line.match(/SN (\d+) \((\d+)\): ([pufnebd]+)/);
            if (match) {
                const [, sn, denom, pown] = match;
                const passCount = (pown.match(/p/g) || []).length;
                console.log(`  SN ${sn}: ${passCount}/25 passes`);
            }
        });
    } catch (error) {
        console.error('Error analyzing receipt:', error);
    }
}

analyzeReceipt('2025-01-30_15-30-45.pown.txt');

cURL

Example 1: List All Receipts

# List all receipt files
curl -X GET "http://localhost:8080/api/wallet/receipt"

Example 2: Read Specific Receipt

# Read a specific receipt file
curl -X GET "http://localhost:8080/api/wallet/receipt?filename=2025-01-30_15-30-45.pown.txt"

Example 3: Pretty Print Receipt Content

# Read receipt and extract just the content field
curl -X GET "http://localhost:8080/api/wallet/receipt?filename=2025-01-30_15-30-45.pown.txt" | \
  jq -r '.content'

Go

Example 1: List All Receipts

package main

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

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

type Receipt struct {
    Filename string `json:"filename"`
}

type ReceiptListResponse struct {
    Status    string    `json:"status"`
    Operation string    `json:"operation"`
    Wallet    string    `json:"wallet"`
    Receipts  []Receipt `json:"receipts"`
}

func main() {
    resp, err := http.Get(fmt.Sprintf("%s/api/wallet/receipt", ApiHost))
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)

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

    fmt.Printf("Wallet: %s\n", result.Wallet)
    fmt.Printf("Total receipts: %d\n", len(result.Receipts))

    for _, receipt := range result.Receipts {
        fmt.Printf("- %s\n", receipt.Filename)
    }
}

Example 2: Read Specific Receipt

package main

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

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

type ReceiptResponse struct {
    Status    string `json:"status"`
    Operation string `json:"operation"`
    Wallet    string `json:"wallet"`
    Filename  string `json:"filename"`
    Content   string `json:"content"`
}

func main() {
    filename := "2025-01-30_15-30-45.pown.txt"

    u, _ := url.Parse(fmt.Sprintf("%s/api/wallet/receipt", ApiHost))
    q := u.Query()
    q.Set("filename", filename)
    u.RawQuery = q.Encode()

    resp, err := http.Get(u.String())
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)

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

    if result.Status == "success" {
        fmt.Printf("Receipt: %s\n", result.Filename)
        fmt.Println("Content:")
        fmt.Println(result.Content)
    } else {
        fmt.Printf("Error reading receipt\n")
    }
}

Example 3: Parse Receipt Statistics

package main

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

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

type ReceiptResponse struct {
    Status    string `json:"status"`
    Operation string `json:"operation"`
    Wallet    string `json:"wallet"`
    Filename  string `json:"filename"`
    Content   string `json:"content"`
}

func analyzeReceipt(filename string) {
    u, _ := url.Parse(fmt.Sprintf("%s/api/wallet/receipt", ApiHost))
    q := u.Query()
    q.Set("filename", filename)
    u.RawQuery = q.Encode()

    resp, err := http.Get(u.String())
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)

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

    if result.Status != "success" {
        fmt.Println("Error reading receipt")
        return
    }

    lines := strings.Split(result.Content, "\n")

    // Parse summary
    for _, line := range lines {
        if strings.Contains(line, "Total coins:") {
            parts := strings.Split(line, ":")
            if len(parts) == 2 {
                fmt.Printf("Total coins: %s\n", strings.TrimSpace(parts[1]))
            }
        } else if strings.Contains(line, "Authenticated:") {
            parts := strings.Split(line, ":")
            if len(parts) == 2 {
                fmt.Printf("Authenticated: %s\n", strings.TrimSpace(parts[1]))
            }
        }
    }

    // Extract POWN strings
    re := regexp.MustCompile(`SN (\d+) \((\d+)\): ([pufnebd]+)`)
    fmt.Println("\nCoin Details:")
    for _, line := range lines {
        matches := re.FindStringSubmatch(line)
        if len(matches) == 4 {
            sn := matches[1]
            pown := matches[3]
            passCount := strings.Count(pown, "p")
            fmt.Printf("  SN %s: %d/25 passes\n", sn, passCount)
        }
    }
}

func main() {
    analyzeReceipt("2025-01-30_15-30-45.pown.txt")
}

Related Endpoints

/api/wallet/transactions

View transaction history from transactions.csv. Task IDs link to receipt files.

/api/wallet/show-coins

View coins in wallet folders (Bank, Fracked, Counterfeit, etc.).

/api/coin/pown

Authenticate coins and generate POWN receipts automatically.