HomeDocumentation

Payments Extension

A payment claim is a signed authorization that allows spending from a payer along a specific trustline ("line"). The claim does not track usage itself — instead, spending is enforced cumulatively on the line.


Overview

Payment claims enable:

  • trustline-based spending
  • delegated payment authorization
  • cross-system settlement
  • reusable payment capacity

These claims can be:

  • submitted to smart contracts on blockchains
  • processed by off-chain systems (e.g. Qbix communities)

The signed claim itself acts as authorization, removing the need for separate approval transactions.


Structure

json
"payments": [ claims ]

Each entry is a full OpenClaim.


Claim Shape

json
{
  "ocp": 1,
  "iss": "payer identifier",
  "sub": "asset identifier",
  "stm": {
    "recipients": ["recipient identifier", "..."],
    "max": "3000000",
    "line": 7
  },
  "key": ...,
  "sig": ["BASE64_SIGNATURE", ...]
}

Field Semantics

iss (Payer)

The entity authorizing the payment.

Examples:

json
"iss": "evm:53:address:0x...payer"
"iss": "qbix:community:SomeCommunity"

sub (Asset)

The asset or token being transferred.

Examples:

json
"sub": "evm:53:address:0x...token"
"sub": "qbix:token:SomeCommunity"

recipients

Array of allowed recipients.

json
"recipients": ["evm:53:address:0x...recipient"]
  • may contain one or many recipients
  • order MUST be preserved for deterministic hashing

max

Maximum total spend allowed on the line.

json
"max": "3000000"

Important: max represents the maximum total spend allowed on the line, evaluated against the line's current spent amount.

  • encoded as string in JSON
  • interpreted as uint256 in execution layer

line

Trustline identifier for cumulative spending tracking.

json
"line": 7
  • line = uint256
  • line 0 is valid
  • lines persist on-chain

Examples

Example 1 — EVM Payment

json
{
  "ocp": 1,
  "iss": "evm:53:address:0x...payer",
  "sub": "evm:53:address:0x...token",
  "stm": {
    "recipients": ["evm:53:address:0x...recipient"],
    "max": "3000000",
    "line": "7"
  },
  "key": [
    "data:key/es256;base64,MIIB..."
  ],
  "sig": ["BASE64_SIGNATURE"]
}

Example 2 — Qbix Payment

json
{
  "ocp": 1,
  "iss": "qbix:community:SomeCommunity",
  "sub": "qbix:token:SomeCommunity",
  "stm": {
    "recipients": ["qbix:user:someUserId"],
    "max": "133.50",
    "line": "7"
  },
  "key": [
    "https://community.example/.well-known/openclaiming.json#payerKey"
  ],
  "sig": ["BASE64_SIGNATURE"]
}

Lines (Trustlines)

Each payment is executed against a line:

text
payer → line → max → spent

Line State

Lines are persistent state defined per (address, lineId):

  • max — maximum capacity
  • spent — current cumulative spending
  • open/closed — line status

Remaining Capacity

javascript
remaining = min(claim.max, line.max) - line.spent

Line Lifecycle

Open

solidity
lineOpen(account, line, max)

Close

solidity
lineClose(account, line)

Access Control

Lines can be managed by:

  • account itself
  • or account.owner() (for managed accounts)

Unlimited Lines

max = 0 → unlimited capacity


Delegation

Payment claims enable delegated spending:

  • ERC20 — uses transferFrom (requires approval)
  • native token — must be sent by payer directly

Replay Protection

Replay protection is enforced through cumulative spending on each line.

Claims are reusable until line capacity is exhausted.


Multi-line Execution

Multiple claims can combine for larger payments:

  • multiple claims can combine
  • same payer + token required
  • behaves like routing liquidity

Canonical Defaults

For deterministic processing, omitted fields are treated as:

json
nbf: 0
exp: 0
recipients: []

This ensures consistent hashing and EIP-712 compatibility.


Canonical EIP-712 Mapping

Payments are designed to map deterministically into EIP-712 for on-chain verification. For complete EVM-compatible encoding and EIP-712 details, see EVM Blockchains.

Domain (inferred)

  • name = "OpenClaiming.payments"
  • version = "1"
  • chainId = extracted from iss

Canonical Struct

solidity
Payment(
  address payer,
  address token,
  bytes32 recipientsHash,
  uint256 max,
  uint256 line,
  uint256 nbf,
  uint256 exp
)

Hashing Rules

recipientsHash

solidity
keccak256(
  abi.encodePacked(
    keccak256(bytes(recipient1)),
    keccak256(bytes(recipient2))
  )
)

Rules:

  • order MUST be preserved
  • empty array must hash deterministically
  • each element is hashed individually

Value Conversion

  • iss → parsed as address (payer)
  • sub → parsed as address (token)
  • max → uint256
  • line → uint256

Execution Model

A payment claim may be:

  • submitted to a smart contract
  • processed by a backend
  • used in a trustline settlement system

The verifier checks:

  • signature validity
  • issuer identity
  • expiration constraints
  • trustline constraints (line)
  • recipient inclusion
  • maximum amount

If valid, the payment may be:

  • executed (token transfer)
  • recorded (ledger update)
  • partially consumed (remaining allowance tracked)

Design Notes

  • payments are authorization primitives, not transactions
  • execution is handled by the verifier system
  • compatible with:
    • EVM contracts
    • Qbix trustlines
    • hybrid systems
  • canonical structure enables:
    • deterministic EIP-712 hashing
    • shared verifier contracts
    • cross-system interoperability

Summary

The payments extension provides:

  • a minimal but powerful spending authorization model
  • compatibility with both on-chain and off-chain systems
  • deterministic encoding for smart contract verification
  • a foundation for trustline-based economies