/api/wallet/receipt
GETView 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:
- List Mode (no filename parameter): Returns a list of all receipt files available
- 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.
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
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.
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
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
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.).