Repository navigation
Seat subscriptions, counter-offer reject, child upgrades - #862
Merged
fati-Onchain merged 2 commits intoOct 23, 2026
Merged
Conversation
Resolves Facil-Pay#753. Resolves Facil-Pay#813. Resolves Facil-Pay#819. Resolves Facil-Pay#829.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #753, closes #813, closes #819, closes #829.
#753: Seat-based subscriptions with prorated quantity changes (payment)
SubscriptionSeats { quantity: u32, unit_amount: i128 }, stored underSubscriptionKey::Seats(id). The billedSubscription::amountis alwaysunit_amount * quantity.Subscription, so stored subscriptions still decode. A subscription with no seat record is read asquantity = 1, unit_amount = amount, so no migration call is needed.update_subscription_quantity(customer, subscription_id, new_quantity):new_quantity == 0is rejected with the newSubscriptionError::InvalidQuantity(328). TheTryFrom<soroban_sdk::Error>range now includes 328.set_subscription_prorationflag and uses the same formula asresume_subscription:(new_amount - old_amount) * (next_payment_at - now) / interval. Nothing is prorated while proration is off or during a trial.SubscriptionKey::SeatCredit), andexecute_recurring_paymentdeducts it from the next charges. This applies on both the normal path and the dunning path.SubscriptionQuantityChanged.get_subscription_seatsandget_subscription_seat_credit.#813: Reject a counter-offer and escalate (refund)
reject_counter_offer(customer, refund_id)discards the pending offer. The refund staysRequestedat its original amount, which puts it back in review.reject_counter_offer_escalate(customer, refund_id, fee_token, fee_amount) -> u64covers the optional escalation in a single call. It rejects the offer, moves the refund toPendingAppeal(rejected_by= the offering merchant), then opens an arbitration case. The name is shortened because Soroban caps function names at 32 characters.escalate_to_arbitration's body moved into a privateescalate_to_arbitration_internalso it can be reused without a secondrequire_auth. Any failure reverts the whole call.expired: true.CounterOfferRejected { refund_id, customer, requested_amount, offered_amount, expired, escalated }.#819: Coordinated upgrade of child contracts (admin)
upgrade_children(admin, payment_hash, escrow_hash, refund_hash)works in three steps: it pauses each child, callsupgradeon each, then unpauses them. The coordinator calls the children as itself (current_contract_address()), so it must be an admin on each child. The README describes the setup.ChildContractUpgradedper child.AdminAction::UpgradeChildren(..)lets multisig deployments (threshold > 1) do the same through propose/approve/execute. The direct call follows the same single-admin rule asupgrade.ChildContractUpdatedevent struct. A merge had dropped it while theset_*_contractsetters still emitted it, so the admin crate did not compile.#829: Document scheduled policy changes, auto-approve ceiling and cooldown config (refund, docs only)
The refund README now documents:
schedule_refund_policy_change,cancel_scheduled_refund_policy,get_scheduled_refund_policyandactivate_scheduled_refund_policy. The section covers parameters, auth, the lazy-activation rules, a timeline example, errors (69/70/71/12) and events.set_auto_approve_below_ceilingandget_auto_approve_below_ceiling, and how the ceiling limits a merchant'sset_auto_approve_below(min(threshold, ceiling)at request time, error 32).set_refund_cooldown_configandget_refund_cooldown_config, theRefundCooldownConfigfields,RefundCooldownActive(33) andRefundCooldownEnforced.The examples use the real signatures from
lib.rs. The policy events were added to the events table.Notes
Per the task rules, nothing was built, formatted or tested locally.
cargo fmt,cargo clippyandcargo testshould be run in CI.Closes #753
Closes #813
Closes #819
Closes #829