---
title: Signed Receipts
description: >-
  Learn how LayerX signed receipts, domain-separated Merkle leaves, and
  inclusion proofs let anyone verify transfers without trusting the sequencer.
---

> **For AI agents:** the complete documentation index is at [llms.txt](/llms.txt). Append `.md` to any page URL for its markdown version.

## Signed receipts

Every transfer on LayerX produces a signed receipt - a cryptographically verifiable record that the transfer occurred, was accepted by the sequencer, and was included in a committed batch. Receipts are the foundation of LayerX's trust model: they let any party verify transfers without relying on the sequencer's honesty.

## Receipt structure

A receipt contains:

| Field | Description |
|-------|-------------|
| `seq` | Monotonically increasing sequence number |
| `sender` | Sender's DID |
| `recipient` | Recipient's DID |
| `amount` | Transfer amount in USDX |
| `timestamp` | Sequencer-accepted time (RFC 3339) |
| `batch_seq` | Batch sequence number (set after batch closes) |
| `merkle_leaf` | Domain-separated hash of the transfer |
| `signature` | Sequencer's Ed25519 signature over the receipt |

The sequencer signs every receipt at transfer time. The `batch_seq` and `merkle_leaf` fields are populated once the transfer is included in a closed batch.

## Domain-separated Merkle leaves

Each transfer is hashed into a Merkle leaf using a domain separator to prevent cross-chain and cross-domain replay:

```
leaf = keccak256(
  "LAYERX_TRANSFER_V1" ||
  sender_did_bytes ||
  recipient_did_bytes ||
  amount_bytes ||
  seq_bytes ||
  timestamp_bytes
)
```

The domain separator `"LAYERX_TRANSFER_V1"` is a fixed string. If LayerX ever introduces a second domain (e.g., for a different asset), it will use a distinct separator.

## Inclusion proofs

After a batch is anchored to Paxeer L1, anyone can verify that a specific transfer was included in that batch using a Merkle inclusion proof.

An inclusion proof consists of:

- The transfer's Merkle leaf.
- The sibling hashes along the path from the leaf to the root.
- The expected Merkle root (published on L1).

To verify:

1. Hash the leaf with its sibling at each level, moving up the tree.
2. Compare the computed root with the on-chain Merkle root.
3. If they match, the transfer was included in the batch.

```typescript
import { verifyInclusion } from "@paxeer/merkle";

const valid = verifyInclusion({
  leaf: transfer.merkle_leaf,
  proof: transfer.merkle_proof,
  root: batch.merkle_root
});
// valid === true means the transfer was committed to L1
```

## Public receipt access

Receipts are publicly readable. Any party can fetch a receipt by its sequence number:

```bash
curl https://layerx.paxeer.network/v1/receipt/12345
```

**Response:**

```json
{
  "seq": 12345,
  "sender": "did:ed25519:agent.scanner.v1",
  "recipient": "did:ed25519:service.weather.v2",
  "amount": "0.001",
  "timestamp": "2026-01-15T10:03:42Z",
  "batch_seq": 987,
  "merkle_leaf": "0xa3f9...",
  "merkle_proof": ["0xb2c1...", "0xd4e5..."],
  "signature": "base64url-encoded-sequencer-signature"
}
```

This endpoint is unauthenticated - no DID challenge or principal token required. Receipts are public records.

## Independent verifiability

The receipt system is designed so that no party needs to trust the sequencer:

- **Recipients** verify that their incoming transfer was signed by the sequencer and included in a committed batch.
- **Senders** verify that their outgoing transfer was recorded correctly.
- **Third parties** (auditors, regulators, other agents) can verify any transfer's inclusion by checking the Merkle proof against the on-chain root.
- **The sequencer** cannot forge transfers - the Merkle root on L1 is immutable once anchored, and any discrepancy between the API's receipts and the on-chain root would be immediately detectable.

This model ensures that LayerX's off-chain speed does not compromise on-chain verifiability.
