Skip to content

feat: event schema versioning, creator invoice cap, recipient validation - #552

Merged
Kingsman-99 merged 2 commits into
Stellar-split:mainfrom
Favourejiro:feat/502-503-505-event-versioning-invoice-cap-recipient-validation
Jul 29, 2026
Merged

feat: event schema versioning, creator invoice cap, recipient validation#552
Kingsman-99 merged 2 commits into
Stellar-split:mainfrom
Favourejiro:feat/502-503-505-event-versioning-invoice-cap-recipient-validation

Conversation

@Favourejiro

Copy link
Copy Markdown
Contributor

Summary

Implements three issues in a single coherent change-set. All three touch events.rs, error.rs, lib.rs, storage_keys.rs, storage_snapshot.rs, and the snapshot JSON.


Issue #502 — Soroban Event Schema Versioning

What changed

  • Added pub const *_V: u32 = 1 version constants for every event type at the top of events.rs, with a migration guide comment block explaining the policy.
  • Each new event function (invoice_limit_updated, recipient_account_missing) includes the version constant as the first topic element.

Migration guide (see top of events.rs): bump the relevant _V constant and add a note to the version-history comment whenever a topic list or data payload shape changes.


Issue #503 — Invoice Count Per Creator Cap

What changed

  • ContractError::CreatorInvoiceLimitReached = 36 added.
  • New storage keys: open_invoice_count_key(creator) (persistent u32), max_open_invoices_key() (instance u32, default 100).
  • _create_invoice_inner: checks open_count >= max and panics with CreatorInvoiceLimitReached before creating. Increments counter on success.
  • _release_full: decrements counter once all payouts complete (gated on no failed payouts — see Recipient Account Existence Validation #505).
  • cancel_invoice: decrements counter on Cancelled transition.
  • New admin entry point set_max_open_invoices(env, admin, new_limit) — requires AdminRole::Operator, stores cap, emits InvoiceLimitUpdated(new_limit).

Issue #505 — Recipient Account Existence Validation

What changed

  • ContractError::RecipientAccountMissing = 37 added.
  • New storage key: failed_payouts_key(invoice_id) (persistent Vec<Address>).
  • _release_full payout loop: before each transfer calls env.try_invoke_contract(balance) on the funding token. If that returns Err, the recipient is appended to FailedPayouts, RecipientAccountMissing is emitted, and the loop continues — no panic.
  • Invoice only transitions to Released (and the open-invoice counter only decrements) when FailedPayouts is empty.
  • New entry point retry_failed_payout(env, invoice_id, recipient): re-validates account existence, executes the transfer, removes from the failed list, and finalises the invoice when the list empties.

Storage Snapshot

Three new keys registered in storage_snapshot.rs and tests/snapshots/storage_keys.json:

Key name Tier Type
open_invoice_count_key persistent (Symbol, Address) → u32
max_open_invoices_key instance Symbol → u32
failed_payouts_key persistent (Symbol, u64) → Vec<Address>

Closes #502
Closes #503
Closes #505

…ion (Stellar-split#502 Stellar-split#503 Stellar-split#505)

Issue Stellar-split#502 — Soroban Event Schema Versioning
- Add pub const *_V: u32 = 1 version constants for every event type in events.rs
- Include migration guide comment block describing version history policy
- Add invoice_limit_updated and recipient_account_missing event functions with
  version constant as first topic element

Issue Stellar-split#503 — Invoice Count Per Creator Cap
- Add CreatorInvoiceLimitReached = 36 to ContractError
- Add open_invoice_count_key (persistent) and max_open_invoices_key (instance)
  to storage_keys.rs and lib.rs inline helpers
- Enforce cap in _create_invoice_inner: panics with CreatorInvoiceLimitReached
  when open_count >= max (default 100 via DEFAULT_MAX_OPEN_INVOICES)
- Decrement counter in _release_full (when no failed payouts) and cancel_invoice
- Add set_max_open_invoices(env, admin, new_limit) admin function that stores
  the cap and emits InvoiceLimitUpdated(new_limit)

Issue Stellar-split#505 — Recipient Account Existence Validation
- Add RecipientAccountMissing = 37 to ContractError
- Add failed_payouts_key (persistent Vec<Address>) to storage_keys.rs and lib.rs
- In _release_full payout loop: call try_invoke_contract(balance) before each
  transfer; on failure store recipient in failed_payouts_key and emit
  RecipientAccountMissing, skip the transfer, continue
- Gate invoice status -> Released and counter decrement on failed_payouts empty
- Add retry_failed_payout(env, invoice_id, recipient): re-validates existence,
  executes transfer, removes from failed list, finalises when list empties

Storage snapshot
- Register open_invoice_count_key, max_open_invoices_key, failed_payouts_key
  in storage_snapshot.rs
- Add corresponding XDR entries to tests/snapshots/storage_keys.json

Closes Stellar-split#502
Closes Stellar-split#503
Closes Stellar-split#505
@drips-wave

drips-wave Bot commented Jul 28, 2026

Copy link
Copy Markdown

@Favourejiro Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Kingsman-99
Kingsman-99 merged commit 24165cf into Stellar-split:main Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Recipient Account Existence Validation Invoice Count Per Creator Cap Soroban Event Schema Versioning

2 participants