Skip to content

Installment windows, partial-payment quanta, shared targets, exact split-payout arithmetic, and the distinction between transaction caps and cumulative targets.

Use separate obligations when payments have different schedules or responsible people. Use receipt units when one obligation can be satisfied through smaller contributions with a fixed payout ratio.

Installments

Create independent obligations for the same named payer. Each installment has its own reference, amounts, opening time, inclusive cutoff, and optional due date. The amounts may differ while keeping the same recipient/denomination payout shape.

An installment is payable only in its own window. The standard does not require payment of installment 1 before installment 2 unless the actual windows prevent the undesired ordering. Overlapping windows allow either installment to be paid first. An informational due date does not create a conditional milestone or proof of delivery.

Every installment retains separate progress. One completed installment does not make the collection fully paid, and an expired installment does not erase prior payments. Use the collection's obligation list when explaining its overall state.

Partial Payments

For one named payer, set partial: { "targetUnits": "N" }. Each payout amount is the exact amount per receipt unit, also called a quantum. A payment of U units transfers U times every payout leg and consumes U units of the cumulative target.

For example, an obligation with two payout legs of 3 and 2 base units and targetUnits: "10" requests 30 and 20 base units in total. Paying --units 4 transfers 12 and 8 base units, leaving 6 receipt units. It does not transfer 4 display coins or four independently counted fixed payments.

The quantum determines the smallest supported increment and preserves split ratios. If a desired split cannot be expressed using integer base units, choose a different quantum or change the requested split. Do not round each recipient independently.

Shared Target

Use the same partial target with a public payer. Eligible people collectively consume its capacity; each contribution pays the recipients immediately. A named multi-payer partial target is also expressible through valid custom terms, but it is not an all-of guarantee.

The target is a cap on cumulative receipt units. It does not hold funds until the goal is reached, and it does not refund earlier contributors when the cutoff arrives with units remaining. Use a separate funding design if those conditions are required.

Caps and Concurrency

The cumulative approval amount enforces the target. A per-transaction scaling limit alone would only cap one transaction and would not prevent repeated overpayment. The builder configures the cumulative cap and the parser verifies it.

Two contributors may read the same remaining amount. If both attempt to consume all of it, only a transaction still within the current chain cap can execute. Refetch and explain changed capacity after a failed attempt; do not automatically increase the target or change payout ratios.

--units must be a positive integer and must not exceed remaining capacity. A fixed-payment obligation uses exactly one receipt unit per payment. Payment links do not support finite partial targets.

Time Boundaries

startTime and endTime are inclusive. The obligation opens at its start timestamp and remains within its payment window through the cutoff timestamp. Chain block time determines execution eligibility. A browser countdown or local clock does not override the chain.

dueAt is informational. An unpaid obligation past its due date can be overdue and still payable until its cutoff. Describe these separately in forms and dashboards: Payment Opens, Due Date, and Payment Cutoff represent different facts.

JSON Recipes

The following obligations arrays replace the array in the complete invoice JSON, with kind: "invoice". They are fragments, not standalone builder inputs. Replace demo addresses and timestamps. Each recipe can also be generated as a complete input with bb build payment-request-v2 --example <name>.

Installments

json
{
  "obligations": [
    {
      "id": "payment-1",
      "payer": {
        "kind": "addresses",
        "addresses": [
          "bb1zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zql3w7"
        ]
      },
      "payouts": [
        {
          "recipient": "bb1xvenxvenxvenxvenxvenxvenxvenxvenlrd2nm",
          "denom": "ubadge",
          "amount": "1000000"
        }
      ],
      "startTime": "1",
      "endTime": "1893456000000"
    },
    {
      "id": "payment-2",
      "payer": {
        "kind": "addresses",
        "addresses": [
          "bb1zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zql3w7"
        ]
      },
      "payouts": [
        {
          "recipient": "bb1xvenxvenxvenxvenxvenxvenxvenxvenlrd2nm",
          "denom": "ubadge",
          "amount": "1000000"
        }
      ],
      "startTime": "1893456000000",
      "endTime": "1896048000000"
    }
  ]
}

Generate the complete installments input, edit its demo values, and build it:

bash
bb build payment-request-v2 --example installments | jq '.data' > installments.json
# Edit installments.json before building.
bb build payment-request-v2 --json installments.json --creator "$CREATOR" --output-file installments-proposal.json

Partial

json
{
  "obligations": [
    {
      "id": "payment-1",
      "payer": {
        "kind": "addresses",
        "addresses": [
          "bb1zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zql3w7"
        ]
      },
      "payouts": [
        {
          "recipient": "bb1xvenxvenxvenxvenxvenxvenxvenxvenlrd2nm",
          "denom": "ubadge",
          "amount": "1000000"
        }
      ],
      "startTime": "1",
      "endTime": "1893456000000",
      "partial": {
        "targetUnits": "10"
      }
    }
  ]
}

Generate the complete partial input, edit its demo values, and build it:

bash
bb build payment-request-v2 --example partial | jq '.data' > partial.json
# Edit partial.json before building.
bb build payment-request-v2 --json partial.json --creator "$CREATOR" --output-file partial-proposal.json

Target

json
{
  "obligations": [
    {
      "id": "payment-1",
      "payer": {
        "kind": "anyone"
      },
      "payouts": [
        {
          "recipient": "bb1xvenxvenxvenxvenxvenxvenxvenxvenlrd2nm",
          "denom": "ubadge",
          "amount": "1000000"
        }
      ],
      "startTime": "1",
      "endTime": "1893456000000",
      "partial": {
        "targetUnits": "10"
      }
    }
  ]
}

Generate the complete target input, edit its demo values, and build it:

bash
bb build payment-request-v2 --example target | jq '.data' > target.json
# Edit target.json before building.
bb build payment-request-v2 --json target.json --creator "$CREATOR" --output-file target-proposal.json

Edit this page on GitHub