From 6b34e7d40bdfecf069fdff9fb224219a8a8cb6b6 Mon Sep 17 00:00:00 2001 From: Abdullahi-Code9 Date: Sat, 25 Jul 2026 23:31:12 +0100 Subject: [PATCH] style: format code with Prettier --- .github/workflows/frontend.yml | 33 +- .github/workflows/rust.yml | 29 +- AGENTS.md | 12 +- CONTRIBUTING.md | 21 +- Issues.md | 2 +- README.md | 18 +- SECURITY.md | 7 + TODO.md | 2 +- UIDesign.md | 2 +- code.md | 94 ++-- .../bench/bench_batch_charge_10_users.1.json | 2 +- .../test_snapshots/bench/bench_charge.1.json | 2 +- .../bench_charge_vs_subscribe_ratio.1.json | 2 +- .../bench/bench_pay_per_use.1.json | 2 +- .../bench/bench_subscribe.1.json | 2 +- ...ccept_admin_without_proposal_panics.1.json | 2 +- ...t_active_count_decrements_on_cancel.1.json | 2 +- ...oes_not_double_count_on_resubscribe.1.json | 2 +- ...ctive_count_increments_on_subscribe.1.json | 2 +- .../test_active_count_multiple_users.1.json | 2 +- ...criptions_freezes_multiple_accounts.1.json | 2 +- ...mes_paused_subscription_past_expiry.1.json | 2 +- ...st_batch_charge_charged_and_skipped.1.json | 2 +- .../test/test_batch_charge_empty.1.json | 2 +- ...t_batch_charge_grace_period_elapsed.1.json | 2 +- .../test/test_batch_charge_inactive.1.json | 2 +- .../test_batch_charge_no_subscription.1.json | 2 +- .../test/test_batch_charge_ordering.1.json | 2 +- ...ch_charge_over_default_limit_panics.1.json | 2 +- .../test/test_batch_charge_paused.1.json | 2 +- .../test/test_batch_charge_stress.1.json | 2 +- .../test/test_batch_charge_with_fee.1.json | 2 +- ...bscriptions_exceeds_max_size_panics.1.json | 2 +- ...lid_missing_and_pre_paused_accounts.1.json | 2 +- ...ch_pause_subscriptions_mixed_inputs.1.json | 2 +- ...ause_subscriptions_non_admin_panics.1.json | 2 +- ...ects_more_than_twenty_five_accounts.1.json | 2 +- ...e_subscriptions_requires_admin_auth.1.json | 7 +- .../test_snapshots/test/test_cancel.1.json | 2 +- ...d_at_interval_end_transfers_nothing.1.json | 2 +- ..._prorated_transfers_expected_amount.1.json | 2 +- ...arge_succeeds_after_merchant_frozen.1.json | 2 +- .../test/test_charge_too_early.1.json | 2 +- .../test_charge_updates_last_charged.1.json | 2 +- ...ith_zero_fee_bps_skips_fee_transfer.1.json | 2 +- ...charge_within_grace_window_succeeds.1.json | 2 +- ...rged_event_includes_ledger_sequence.1.json | 2 +- ...clear_charge_history_admin_succeeds.1.json | 2 +- ...ear_charge_history_non_admin_panics.1.json | 2 +- ...ge_history_nonexistent_key_no_panic.1.json | 2 +- ...chant_revenue_history_drops_history.1.json | 2 +- ...merchant_revenue_history_idempotent.1.json | 2 +- ...nt_revenue_history_non_admin_panics.1.json | 2 +- .../test_clear_metadata_removes_label.1.json | 2 +- .../test_contract_pause_events_emitted.1.json | 2 +- ...st_custom_sac_token_end_to_end_flow.1.json | 2 +- ...aily_limit_accumulates_across_calls.1.json | 2 +- ...ily_limit_allows_spend_within_limit.1.json | 2 +- ...y_limit_blocks_cumulative_overspend.1.json | 2 +- .../test_daily_limit_blocks_overspend.1.json | 2 +- ...test_daily_limit_day_start_boundary.1.json | 2 +- ...t_daily_limit_removed_event_emitted.1.json | 2 +- .../test_daily_limit_set_event_emitted.1.json | 2 +- ...limit_visibility_and_spend_tracking.1.json | 2 +- .../test/test_double_initialize.1.json | 2 +- .../test_freeze_merchant_idempotent.1.json | 2 +- ...e_merchant_independent_of_whitelist.1.json | 2 +- ...st_freeze_merchant_non_admin_panics.1.json | 2 +- ...charge_history_empty_for_no_history.1.json | 2 +- ...rge_history_page_limit_capped_at_12.1.json | 2 +- ...e_history_page_offset_beyond_length.1.json | 2 +- ...et_charge_history_page_offset_limit.1.json | 2 +- ...rge_history_three_charges_ascending.1.json | 2 +- .../test/test_get_daily_limit.1.json | 2 +- ...et_fee_returns_current_fee_settings.1.json | 2 +- .../test_get_grace_period_after_set.1.json | 2 +- .../test_get_grace_period_default_zero.1.json | 2 +- ...test_get_metadata_none_when_not_set.1.json | 2 +- .../test/test_get_min_interval_default.1.json | 2 +- ..._get_protocol_stats_after_subscribe.1.json | 2 +- ..._get_protocol_stats_contract_paused.1.json | 2 +- .../test_get_protocol_stats_initial.1.json | 2 +- .../test_get_protocol_stats_with_fee.1.json | 2 +- ...est_get_subscriber_at_returns_first.1.json | 2 +- ...ubscription_label_none_when_not_set.1.json | 2 +- ...ubscription_label_returns_set_value.1.json | 2 +- .../test_get_subscription_nonexistent.1.json | 2 +- ...get_token_returns_initialized_token.1.json | 2 +- ...n_returns_none_when_not_initialized.1.json | 6 +- ...est_get_trial_end_with_trial_period.1.json | 2 +- ..._get_trial_end_without_trial_period.1.json | 2 +- .../test_global_volume_exceeds_limit.1.json | 2 +- .../test_global_volume_window_reset.1.json | 2 +- .../test_global_volume_within_limit.1.json | 2 +- .../test_grace_period_ttl_extension.1.json | 2 +- ...lth_check_active_subscription_count.1.json | 2 +- ...t_health_check_initialized_unpaused.1.json | 2 +- .../test/test_health_check_paused.1.json | 2 +- .../test_health_check_pre_initialize.1.json | 6 +- .../test_initialize_backward_compat.1.json | 2 +- .../test_initialize_sets_instance_ttl.1.json | 2 +- ...test_initialize_without_valid_token.1.json | 2 +- .../test/test_interval_minimum_valid.1.json | 2 +- .../test/test_interval_too_short.1.json | 2 +- ...e_due_false_for_paused_subscription.1.json | 2 +- ...harge_due_false_for_unknown_address.1.json | 2 +- ..._charge_due_false_past_grace_window.1.json | 2 +- ...arge_due_transitions_after_interval.1.json | 2 +- ...t_is_merchant_frozen_reflects_state.1.json | 2 +- ...d_returns_false_for_non_whitelisted.1.json | 2 +- .../test_merchant_revenue_from_charge.1.json | 2 +- ...ub_count_double_cancel_no_underflow.1.json | 2 +- ...ount_resubscribe_different_merchant.1.json | 2 +- ...hant_sub_count_two_users_cancel_one.1.json | 2 +- ...pleted_event_with_version_and_count.1.json | 2 +- .../test/test_migrate_is_idempotent.1.json | 2 +- .../test/test_migrate_non_admin_panics.1.json | 2 +- .../test_migrate_sets_schema_version.1.json | 2 +- .../test/test_migrate_v1_to_v2.1.json | 2 +- ...lti_token_independent_subscriptions.1.json | 2 +- .../test/test_multiple_users.1.json | 2 +- ...st_next_charge_at_none_after_cancel.1.json | 2 +- ...rge_at_none_for_paused_subscription.1.json | 2 +- ..._charge_at_none_for_unknown_address.1.json | 2 +- ...charge_at_returns_correct_timestamp.1.json | 2 +- .../test/test_no_referral_returns_none.1.json | 2 +- ...dmin_add_and_remove_merchant_panics.1.json | 2 +- ...t_non_admin_set_grace_period_panics.1.json | 2 +- ...non_admin_set_max_batch_size_panics.1.json | 2 +- ...d_admin_loses_access_after_transfer.1.json | 2 +- ...use_on_inactive_subscription_panics.1.json | 2 +- .../test_pause_sets_indefinite_expiry.1.json | 2 +- .../test/test_pause_sets_paused_true.1.json | 2 +- ...til_auto_resume_clears_pause_expiry.1.json | 2 +- ..._pause_until_auto_resumes_on_charge.1.json | 2 +- ...t_pause_until_past_timestamp_panics.1.json | 2 +- .../test/test_pay_per_use.1.json | 2 +- ...rotocol_fee_and_records_net_revenue.1.json | 2 +- ...er_use_does_not_update_last_charged.1.json | 2 +- .../test/test_pay_per_use_exceeds_cap.1.json | 2 +- .../test/test_pay_per_use_inactive.1.json | 2 +- .../test/test_pay_per_use_nonexistent.1.json | 2 +- ...r_use_on_paused_subscription_panics.1.json | 2 +- ..._use_succeeds_after_merchant_frozen.1.json | 2 +- ...o_applies_protocol_fee_to_recipient.1.json | 2 +- ...daily_limit_shared_with_pay_per_use.1.json | 2 +- ...s_merchant_behaves_like_pay_per_use.1.json | 2 +- ...o_rejects_non_whitelisted_recipient.1.json | 2 +- ...transfers_to_recipient_not_merchant.1.json | 2 +- ..._zero_fee_bps_transfers_full_amount.1.json | 2 +- .../test/test_pay_per_use_zero_amount.1.json | 2 +- .../test_referral_cleared_on_cancel.1.json | 2 +- ...ral_clears_on_resubscribe_with_none.1.json | 2 +- .../test_referral_stored_on_subscribe.1.json | 2 +- ...est_referral_updates_on_resubscribe.1.json | 2 +- ...it_allows_pay_per_use_after_removal.1.json | 2 +- .../test/test_resubscribe.1.json | 2 +- ...ibe_active_does_not_duplicate_index.1.json | 2 +- ...t_resubscribe_zero_allowance_panics.1.json | 2 +- .../test_resume_clears_pause_expiry.1.json | 2 +- ...resume_unpauses_and_charge_succeeds.1.json | 2 +- ...referral_rejected_via_try_subscribe.1.json | 2 +- .../test/test_set_and_get_metadata.1.json | 2 +- .../test/test_set_fee_emits_event.1.json | 2 +- .../test_set_fee_invalid_bps_panics.1.json | 2 +- .../test_set_grace_period_emits_event.1.json | 2 +- ..._batch_size_rejects_value_above_200.1.json | 2 +- ...et_metadata_label_at_limit_succeeds.1.json | 2 +- ...etadata_label_exceeding_limit_fails.1.json | 2 +- ...test_set_metadata_wrong_user_panics.1.json | 2 +- ...t_set_min_interval_non_admin_panics.1.json | 2 +- .../test_set_min_interval_zero_panics.1.json | 2 +- ..._subscription_amount_admin_succeeds.1.json | 2 +- ...ption_amount_no_subscription_panics.1.json | 2 +- ...ubscription_amount_non_admin_panics.1.json | 2 +- ...ubscription_interval_admin_succeeds.1.json | 2 +- ...ion_interval_no_subscription_panics.1.json | 2 +- ...scription_interval_non_admin_panics.1.json | 2 +- ...t_subscription_interval_zero_panics.1.json | 2 +- ...t_enabled_false_allows_any_merchant.1.json | 2 +- ...ter_set_min_interval_lower_succeeds.1.json | 2 +- ...t_subscribe_amount_above_cap_panics.1.json | 2 +- ...st_subscribe_amount_at_cap_succeeds.1.json | 2 +- .../test/test_subscribe_and_charge.1.json | 2 +- ..._subscribe_exact_allowance_succeeds.1.json | 2 +- ...test_subscribe_extends_instance_ttl.1.json | 2 +- ...subscribe_interval_minimum_succeeds.1.json | 2 +- ...rval_too_short_panics_default_floor.1.json | 2 +- ..._subscribe_interval_under_60_panics.1.json | 2 +- ...test_subscribe_non_contract_address.1.json | 2 +- ...ibe_non_whitelisted_merchant_panics.1.json | 2 +- ...e_overwrites_cancelled_subscription.1.json | 2 +- ...subscribe_to_frozen_merchant_panics.1.json | 2 +- ...be_valid_sac_token_address_succeeds.1.json | 2 +- ...cribe_whitelisted_merchant_succeeds.1.json | 2 +- ...scribe_with_metadata_label_too_long.1.json | 2 +- ...ta_no_subscription_on_label_failure.1.json | 2 +- ...est_subscribe_with_metadata_success.1.json | 2 +- ...ro_allowance_does_not_write_storage.1.json | 2 +- ...est_subscribe_zero_allowance_panics.1.json | 2 +- ...subscriber_index_three_unique_users.1.json | 2 +- ..._subscriber_page_limit_capped_at_50.1.json | 2 +- ...e_offset_beyond_count_returns_empty.1.json | 2 +- ...scription_struct_fields_match_input.1.json | 2 +- .../test/test_transfer_admin.1.json | 2 +- .../test_transfer_admin_event_emitted.1.json | 2 +- .../test_transfer_admin_requires_auth.1.json | 2 +- ...test_transfer_subscription_succeeds.1.json | 2 +- ..._subscription_to_active_user_panics.1.json | 2 +- .../test/test_ttl_extension.1.json | 2 +- ..._unfreeze_merchant_non_admin_panics.1.json | 2 +- ...nfreeze_merchant_non_frozen_is_noop.1.json | 2 +- .../test/test_upgrade_event_emitted.1.json | 6 +- .../test/test_upgrade_event_emitted.2.json | 2 +- .../test/test_user_can_switch_token.1.json | 2 +- ...batch_add_duplicates_does_not_panic.1.json | 2 +- ...t_batch_add_exceeds_max_size_panics.1.json | 2 +- ...hitelist_batch_add_non_admin_panics.1.json | 2 +- ...whitelist_batch_add_three_merchants.1.json | 2 +- ...atch_remove_non_whitelisted_is_noop.1.json | 2 +- ...hitelist_batch_remove_two_merchants.1.json | 2 +- ..._withdraw_merchant_revenue_succeeds.1.json | 2 +- ...erchant_revenue_zero_balance_panics.1.json | 2 +- .../test/test_zero_amount.1.json | 2 +- .../test/test_zero_interval.1.json | 2 +- docs/ARCHITECTURE.md | 144 +++--- docs/COMPLIANCE.md | 126 +++--- docs/CONTRIBUTING-CONTRACT.md | 31 +- docs/CONTRIBUTING-FRONTEND.md | 27 +- docs/DAILY-LIMITS.md | 90 ++-- docs/DEPLOYMENT.md | 45 +- docs/ERROR-CODES.md | 380 ++++++++-------- docs/EVENT-DRIVEN-GUIDE.md | 103 ++--- docs/FRONTEND-COMPONENTS.md | 357 +++++++-------- docs/FRONTEND.md | 14 +- docs/GLOSSARY.md | 37 +- docs/INTEGRATION-GUIDE.md | 116 +++-- docs/KEEPER.md | 66 +-- docs/MAINNET-DEPLOYMENT.md | 68 +-- docs/MERCHANT-INTEGRATION.md | 126 +++--- docs/MULTI-TOKEN.md | 49 ++- docs/ONBOARDING.md | 17 +- docs/REFERRAL.md | 7 + docs/REFERRALS.md | 141 +++--- docs/SECURITY.md | 76 ++-- docs/STRUCTURE.md | 74 ++-- docs/SUBSCRIBER-LIFECYCLE.md | 34 +- docs/TESTING.md | 22 +- docs/architecture/storage_and_ttl.md | 102 ++--- docs/architecture/two-step-auth.md | 26 +- docs/development/performance-benchmarking.md | 33 +- docs/development/testing_runbook.md | 70 +-- docs/integrations/frontend_integration.md | 28 +- docs/operations/keeper_runbook.md | 81 ++-- docs/security/audit-preparation.md | 88 ++-- docs/security/threat_matrix.md | 19 +- docs/spec/lifecycle_spec.md | 90 +++- scripts/replay-dlq.ts | 414 ++++++++++++++++++ 258 files changed, 2202 insertions(+), 1566 deletions(-) create mode 100644 scripts/replay-dlq.ts diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 5a70b84b..8465f63f 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -2,9 +2,9 @@ name: Frontend on: push: - branches: [ "master" ] + branches: ["master"] pull_request: - branches: [ "master" ] + branches: ["master"] defaults: run: @@ -12,21 +12,20 @@ defaults: jobs: build: - runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: npm - cache-dependency-path: frontend/package-lock.json - - name: Install dependencies - run: npm ci - - name: Lint - run: npm run lint - - name: Format check - run: npx prettier --check . - - name: Build - run: npm run build + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: frontend/package-lock.json + - name: Install dependencies + run: npm ci + - name: Lint + run: npm run lint + - name: Format check + run: npx prettier --check . + - name: Build + run: npm run build diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d7e17ded..61fbe643 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,9 +2,9 @@ name: Backend (Rust) on: push: - branches: [ "master" ] + branches: ["master"] pull_request: - branches: [ "master" ] + branches: ["master"] env: CARGO_TERM_COLOR: always @@ -15,19 +15,18 @@ defaults: jobs: build: - runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Install Rust target - run: rustup target add wasm32-unknown-unknown - - name: Clippy - run: cargo clippy -- -D warnings - working-directory: contract - - name: Build - run: cargo build --verbose - working-directory: contract - - name: Run tests - run: cargo test --verbose - working-directory: contract + - uses: actions/checkout@v4 + - name: Install Rust target + run: rustup target add wasm32-unknown-unknown + - name: Clippy + run: cargo clippy -- -D warnings + working-directory: contract + - name: Build + run: cargo build --verbose + working-directory: contract + - name: Run tests + run: cargo test --verbose + working-directory: contract diff --git a/AGENTS.md b/AGENTS.md index eff86401..16c7f3f1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,7 +5,7 @@ PayFlow (also referred to as FlowPay) is a decentralized subscription and recurr ## Project Overview - **Core Technology:** Stellar Soroban (Rust), React + TypeScript (Frontend) -- **Architecture:** +- **Architecture:** - **Smart Contract (`/contract`):** Handles subscription logic, charging, cancellations, and pay-per-use microtransactions. - **Frontend (`/frontend`):** A React-based dashboard for users to manage subscriptions and for merchants to view revenue/subscribers. - **Documentation (`/docs`):** Comprehensive guides on API, architecture, deployment, and testing. @@ -13,6 +13,7 @@ PayFlow (also referred to as FlowPay) is a decentralized subscription and recurr ## Key Components & Technologies ### Smart Contract (Rust/Soroban) + - **Primary Contract:** `FlowPay` in `contract/src/lib.rs`. - **Key Functions:** - `initialize(token)`: Sets the primary SAC token (e.g., XLM). @@ -24,6 +25,7 @@ PayFlow (also referred to as FlowPay) is a decentralized subscription and recurr - **Features:** Grace periods, merchant whitelisting, protocol fees, referral tracking, and subscription metadata. ### Frontend (React/TypeScript) + - **Framework:** Vite + React + TypeScript. - **Blockchain Interaction:** `frontend/src/stellar.ts` uses `@stellar/stellar-sdk` and Soroban RPC. - **Wallet Support:** Freighter Wallet via `useWallet` hook. @@ -32,21 +34,25 @@ PayFlow (also referred to as FlowPay) is a decentralized subscription and recurr ## Building and Running ### Prerequisites + - Rust 1.70+ with `wasm32-unknown-unknown` target. - Soroban CLI. - Node.js 18+. ### Root Commands (using `package.json` scripts) + - **Typecheck Frontend:** `npm run typecheck` - **Build Frontend:** `npm run build:frontend` - **Test Contract:** `npm run backend:test` - **Check Contract:** `npm run backend:typecheck` ### Contract (`/contract`) + - **Build:** `cargo build --release --target wasm32-unknown-unknown` - **Test:** `cargo test` ### Frontend (`/frontend`) + - **Install Dependencies:** `npm install` - **Development Server:** `npm run dev` - **Build:** `npm run build` @@ -56,18 +62,22 @@ PayFlow (also referred to as FlowPay) is a decentralized subscription and recurr ## Development Conventions ### Coding Style + - **Contract:** Idiomatic Rust using `soroban-sdk`. Strict use of `no_std`. - **Frontend:** Functional React components with TypeScript. Prefer Vanilla CSS for styling (as seen in `index.css`). ### Testing Practices + - **Contract:** Comprehensive unit tests in `contract/src/test.rs`. Use `soroban-sdk`'s `testutils`. - **Frontend:** Vitest for unit and component testing. Smoke tests for main application entry points. ### Contribution Guidelines + - Refer to `CONTRIBUTING.md` for detailed instructions. - Husky is used for pre-commit/pre-push hooks (linting and type-checking). ## Important Files + - `contract/src/lib.rs`: Entry point for smart contract logic. - `frontend/src/stellar.ts`: Central hub for all Soroban/Stellar interactions. - `docs/API.md`: Detailed contract function documentation. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a33d58ba..0ad21baf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,15 +43,15 @@ Be respectful. We welcome contributors of all experience levels. Harassment, gat These are well-scoped tasks that don't require deep knowledge of the whole codebase: -| Task | Area | Difficulty | -| --- | --- | --- | -| Add USDC / custom SAC token support | Contract | Medium | -| Build a Node.js keeper service that calls `charge()` on a schedule | Backend | Medium | -| Add subscription pause/resume functions | Contract | Medium | -| Improve frontend error messages with human-readable contract panics | Frontend | Easy | -| Add `test_pay_per_use` unit test | Contract | Easy | -| Add `test_double_initialize` unit test | Contract | Easy | -| Display transaction history using contract events | Frontend | Hard | +| Task | Area | Difficulty | +| ------------------------------------------------------------------- | -------- | ---------- | +| Add USDC / custom SAC token support | Contract | Medium | +| Build a Node.js keeper service that calls `charge()` on a schedule | Backend | Medium | +| Add subscription pause/resume functions | Contract | Medium | +| Improve frontend error messages with human-readable contract panics | Frontend | Easy | +| Add `test_pay_per_use` unit test | Contract | Easy | +| Add `test_double_initialize` unit test | Contract | Easy | +| Display transaction history using contract events | Frontend | Hard | --- @@ -99,6 +99,7 @@ npm run dev 5. Push your branch and open a Pull Request against `main` Branch naming conventions: + - `feat/` — new feature - `fix/` — bug fix - `docs/` — documentation only @@ -131,7 +132,6 @@ See the full guide: [`docs/CONTRIBUTING-FRONTEND.md`](docs/CONTRIBUTING-FRONTEND - Run `npm run format` to auto-format all source files with Prettier - Run `npm run build` to confirm there are no TypeScript errors before submitting - --- ## Commit Style @@ -180,6 +180,7 @@ npm run generate:types ``` This invokes `scripts/generate-types.sh`, which requires either: + - `CONTRACT_ID` env var pointing to a deployed contract, or - A compiled WASM artifact at `contract/target/wasm32-unknown-unknown/release/payflow.wasm` diff --git a/Issues.md b/Issues.md index c82a8288..9a2caaf3 100644 --- a/Issues.md +++ b/Issues.md @@ -68,4 +68,4 @@ Acceptance criteria Countdown appears on the subscription card Overdue state is visually distinct -PR includes screenshot \ No newline at end of file +PR includes screenshot diff --git a/README.md b/README.md index fe786e95..233b304a 100644 --- a/README.md +++ b/README.md @@ -53,15 +53,16 @@ pub fn get_daily_limit(env: Env, user: Address) -> Option { get_daily_limit(env: Env, user: Address) -> Option ``` -| Parameter | Type | Description | -|-----------|------|-------------| -| `user` | `Address` | The subscriber address to query | +| Parameter | Type | Description | +| --------- | --------- | ------------------------------- | +| `user` | `Address` | The subscriber address to query | **Returns:** `Some(limit)` in stroops if a limit is set, `None` otherwise. **Auth:** None required. **Storage:** Reads `DataKey::DailyLimit(user)` from temporary storage. **CLI example:** + ```bash soroban contract invoke \ --id \ @@ -139,6 +140,7 @@ cargo test daily_limit ``` Expected output: + ``` test test::test_daily_limit_allows_spend_within_limit ... ok test test::test_daily_limit_accumulates_across_calls ... ok @@ -202,11 +204,11 @@ Stellar's Soroban platform uses state archiving — persistent storage entries h ## Prerequisites -| Tool | Version | Install | -|------|---------|---------| -| Rust | 1.70+ | `curl https://sh.rustup.rs -sSf \| sh` | -| wasm32 target | — | `rustup target add wasm32-unknown-unknown` | -| Soroban CLI | 21.x | `cargo install --locked soroban-cli` | +| Tool | Version | Install | +| ------------- | ------- | ------------------------------------------ | +| Rust | 1.70+ | `curl https://sh.rustup.rs -sSf \| sh` | +| wasm32 target | — | `rustup target add wasm32-unknown-unknown` | +| Soroban CLI | 21.x | `cargo install --locked soroban-cli` | --- diff --git a/SECURITY.md b/SECURITY.md index 830a5df0..ff141c54 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -5,23 +5,28 @@ If you discover a security vulnerability in PayFlow, please report it responsibly: ### Preferred Method + Use **GitHub Security Advisories** to report vulnerabilities privately: + 1. Go to the "Security" tab in this repository 2. Click "Report a vulnerability" 3. Fill out the advisory form ### Alternative Method + Email: **security@payflow.dev** Subject: `[PayFlow Security] Brief description` ### What to Include + - Description of the vulnerability - Steps to reproduce - Potential impact assessment - Suggested mitigations (if any) ### Response Timeline + - **Acknowledgment:** Within 48 hours - **Fix timeline:** Within 14 days for critical issues (depending on complexity) - **Credit:** We will credit researchers in release notes unless you prefer anonymity @@ -37,6 +42,7 @@ For the full threat model, auth matrix, and storage notes, see [docs/SECURITY.md ## Scope In scope for vulnerability reports: + - Smart contract logic vulnerabilities - Authorization bypass issues - Fund loss or theft scenarios @@ -44,6 +50,7 @@ In scope for vulnerability reports: - Integer overflow/underflow issues Out of scope: + - Issues in third-party dependencies (report to upstream) - Social engineering attacks - Physical security issues diff --git a/TODO.md b/TODO.md index bb3ddd60..af5f3833 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,7 @@ # TODO (PayFlow) ## Frontend DX: Hook JSDoc coverage + - [ ] Scan all files in `frontend/src/hooks/` and verify which exported hooks are missing/partial JSDoc. - [ ] Add/upgrade `/** ... */` JSDoc blocks for every hook to include: - purpose @@ -9,4 +10,3 @@ - side effects - `@example` usage - [ ] Run TypeScript compile/typecheck for `frontend` to ensure no errors. - diff --git a/UIDesign.md b/UIDesign.md index 95203571..ed114b9a 100644 --- a/UIDesign.md +++ b/UIDesign.md @@ -1 +1 @@ -https://www.figma.com/design/bhHlIX6xxmzhwcGga6ocmR/SiLioLabs-PayFlow?node-id=0-1&t=AcUOdKr2iI2eOxgC-1 \ No newline at end of file +https://www.figma.com/design/bhHlIX6xxmzhwcGga6ocmR/SiLioLabs-PayFlow?node-id=0-1&t=AcUOdKr2iI2eOxgC-1 diff --git a/code.md b/code.md index a06aed51..272b0b7b 100644 --- a/code.md +++ b/code.md @@ -1,81 +1,94 @@ -You are a senior Rust developer contributing to an open-source project built on the Stellar ecosystem. - +You are a senior Rust developer contributing to an open-source project built on the Stellar ecosystem. 1. Analyze Assigned Issues -Carefully read the below assigned issues. -Help solve each issues and map them to relevant parts of the codebase. + Carefully read the below assigned issues. + Help solve each issues and map them to relevant parts of the codebase. + +ISSUE #481 [CONTRACT-25] Add Event Index Metadata to All Published Events -ISSUE #481 [CONTRACT-25] Add Event Index Metadata to All Published Events ### Background + All events in `events.rs` are published with a two-element topic tuple `(Symbol, Address)` or `(Symbol,)`. Soroban events are indexed by topic on the RPC layer, but the current events carry no sequence or correlation metadata. When `batch_charge` processes 50 users and emits 50 charged events in one transaction, there is no way for an event consumer to reconstruct the original batch ordering or correlate a charge event back to a specific `batch_charge` invocation. Keeper bots and analytics pipelines that process events asynchronously must rely on ledger sequence numbers alone, which breaks when multiple `batch_charge` calls land in the same ledger. ### Task + Add a `ledger_sequence: u32` field to `ChargeEventData` (already a `#[contracttype]` struct). Populate it with `env.ledger().sequence()` in `publish_charged`. Add a consistent `sequence: u32` field to new event data structs for `publish_subscribed`, `publish_cancelled`, and `publish_pay_per_use` — wrap each in a new `#[contracttype]` struct (`SubscribedEventData`, `CancelledEventData`, `PayPerUseEventData`) rather than using bare tuples. This makes all major events strongly typed and carries ledger context. ### Key Files -* `contract/src/events.rs` — define `SubscribedEventData`, `CancelledEventData`, `PayPerUseEventData` structs; add `ledger_sequence: u32` to all; update all `publish_*` functions to use these structs -* `contract/src/lib.rs` — no changes needed if event functions are called correctly -* `contract/src/test.rs` — update any tests that assert on raw event tuples to match new struct shapes; add a test reading back charged event data and asserting `ledger_sequence` equals `env.ledger().sequence()` + +- `contract/src/events.rs` — define `SubscribedEventData`, `CancelledEventData`, `PayPerUseEventData` structs; add `ledger_sequence: u32` to all; update all `publish_*` functions to use these structs +- `contract/src/lib.rs` — no changes needed if event functions are called correctly +- `contract/src/test.rs` — update any tests that assert on raw event tuples to match new struct shapes; add a test reading back charged event data and asserting `ledger_sequence` equals `env.ledger().sequence()` ### Edge Cases -* `ChargeEventData` already exists as a struct — add `ledger_sequence` as a new field; existing snapshot tests will need regeneration -* Snapshot files in `contract/test_snapshots/` will change — delete and regenerate with `cargo test` (this is expected and must be noted in the PR) -* Do not add `ledger_sequence` to admin-only events (`publish_upgraded`, `publish_admin_transferred`) — those have different consumers + +- `ChargeEventData` already exists as a struct — add `ledger_sequence` as a new field; existing snapshot tests will need regeneration +- Snapshot files in `contract/test_snapshots/` will change — delete and regenerate with `cargo test` (this is expected and must be noted in the PR) +- Do not add `ledger_sequence` to admin-only events (`publish_upgraded`, `publish_admin_transferred`) — those have different consumers ### Acceptance Criteria + - [ ] `ChargeEventData`, `SubscribedEventData`, `CancelledEventData`, `PayPerUseEventData` all carry `ledger_sequence: u32` - [ ] All four `publish_*` functions populate `ledger_sequence` from `env.ledger().sequence()` - [ ] Test: assert charged event's `ledger_sequence` field equals the ledger sequence at charge time - [ ] All snapshot files regenerated and committed - [ ] `cargo test` passes with no regressions - -ISSUE #468 ## [CONTRACT-12] Implement validate_token_is_contract Using WASM-Safe XDR Inspection - +ISSUE #468 ## [CONTRACT-12] Implement validate_token_is_contract Using WASM-Safe XDR Inspection ### Background + `subscribe` in `lib.rs` contains an inline token validation using `token.clone().to_xdr(&env).get(7) == Some(0)` to detect non-contract addresses. This is an undocumented, fragile heuristic based on XDR byte layout — it has no test coverage explaining the magic byte index, it will silently break if Soroban's XDR serialization changes, and it lives inline in `subscribe` rather than in `validation.rs`. The existing `ContractError::InvalidTokenAddress` error is correct but the detection logic is brittle. The proper check is to attempt a `token::Client::new(env, &token).decimals()` call and catch the resulting host trap — or validate that the Address resolves to a contract via the `env.deployer()` API. ### Task + Move token validation into a `validate_token_address(env: &Env, token: &Address)` function in `validation.rs`. Replace the XDR byte hack with a call to `token::Client::new(env, token).decimals()` wrapped in a `try_` call (using soroban-sdk's `try_` invocation pattern for cross-contract calls). If the call returns an error, panic with `ContractError::InvalidTokenAddress`. Remove the inline XDR check from `subscribe` and replace it with `validation::validate_token_address`. Add the token module import to `validation.rs`. ### Key Files -* `contract/src/validation.rs` — add `validate_token_address(env, token)` -* `contract/src/lib.rs` — replace inline XDR check in `subscribe` with the new helper -* `contract/src/test.rs` — the existing `test_subscribe_non_contract_address` test must continue to pass; add a test for a valid contract token address succeeding + +- `contract/src/validation.rs` — add `validate_token_address(env, token)` +- `contract/src/lib.rs` — replace inline XDR check in `subscribe` with the new helper +- `contract/src/test.rs` — the existing `test_subscribe_non_contract_address` test must continue to pass; add a test for a valid contract token address succeeding ### Edge Cases -* In the test environment, soroban-sdk testutils register mock contracts — ensure the mock token used in `setup()` passes the new validation without changes to test infrastructure -* If `token::Client::try_decimals()` is not available in the current SDK version, use an alternative introspection method and document it clearly in a code comment -* The validation must occur after amount and interval checks to preserve existing error ordering in `subscribe` + +- In the test environment, soroban-sdk testutils register mock contracts — ensure the mock token used in `setup()` passes the new validation without changes to test infrastructure +- If `token::Client::try_decimals()` is not available in the current SDK version, use an alternative introspection method and document it clearly in a code comment +- The validation must occur after amount and interval checks to preserve existing error ordering in `subscribe` ### Acceptance Criteria + - [ ] `validate_token_address(env, token)` exists in `validation.rs` with a doc comment explaining the approach - [ ] `subscribe` no longer contains any XDR byte-index magic; calls `validate_token_address` instead - [ ] `test_subscribe_non_contract_address` passes without modification to test setup - [ ] New test: subscribing with a valid SAC token address succeeds - [ ] `cargo test` passes with no regression -ISSUE #472 ## [CONTRACT-16] Implement Configurable MAX_BATCH_SIZE Guard in batch_charge +ISSUE #472 ## [CONTRACT-16] Implement Configurable MAX_BATCH_SIZE Guard in batch_charge ### Background + `batch_charge` in `batch.rs` accepts an unbounded `Vec
` — a caller can pass thousands of addresses in a single transaction. Soroban enforces a per-transaction instruction budget, but the contract itself provides no explicit guard. A malicious or misconfigured keeper could submit a batch large enough to exhaust the instruction budget mid-execution, producing a partial batch result where some users are charged and others are not, with no way for the caller to distinguish charged-and-failed from not-yet-attempted. More critically, without a size cap the function's gas cost is unbounded and cannot be reliably estimated for keeper automation. ### Task + Add a `MAX_BATCH_SIZE: u32 = 50` constant in `batch.rs`. At the start of `batch_charge`, check if `users.len() > MAX_BATCH_SIZE` and panic with a new `ContractError::BatchTooLarge = 20`. Add `get_max_batch_size(env: Env) -> u32` as a public read-only function returning the constant. Expose an admin-configurable override via `DataKey::MaxBatchSize` instance storage — `set_max_batch_size(env, size)` (admin-only, max value 200) so the limit can be adjusted as Soroban's instruction budget evolves. If `DataKey::MaxBatchSize` is unset, fall back to the hardcoded `MAX_BATCH_SIZE` constant. ### Key Files -* `contract/src/batch.rs` — add `MAX_BATCH_SIZE` constant; add size guard using storage-or-default limit -* `contract/src/errors.rs` — add `BatchTooLarge = 20` -* `contract/src/lib.rs` — add `DataKey::MaxBatchSize`; add `get_max_batch_size` and `set_max_batch_size` public functions; `set_max_batch_size` requires admin auth -* `contract/src/test.rs` — test: batch of 51 addresses panics with `BatchTooLarge`; test: `set_max_batch_size(10)` then batch of 11 panics; test: non-admin `set_max_batch_size` panics + +- `contract/src/batch.rs` — add `MAX_BATCH_SIZE` constant; add size guard using storage-or-default limit +- `contract/src/errors.rs` — add `BatchTooLarge = 20` +- `contract/src/lib.rs` — add `DataKey::MaxBatchSize`; add `get_max_batch_size` and `set_max_batch_size` public functions; `set_max_batch_size` requires admin auth +- `contract/src/test.rs` — test: batch of 51 addresses panics with `BatchTooLarge`; test: `set_max_batch_size(10)` then batch of 11 panics; test: non-admin `set_max_batch_size` panics ### Edge Cases -* `set_max_batch_size` must reject values > 200 with `ContractError::InvalidFeeBps` — or add a new `ContractError::InvalidBatchSize = 21` for clarity -* An empty batch (`users.len() == 0`) must return an empty `Vec` without panicking -* The existing `test_batch_charge_stress` test uses a large batch — update it to use a size $\le$ `MAX_BATCH_SIZE` or call `set_max_batch_size` first + +- `set_max_batch_size` must reject values > 200 with `ContractError::InvalidFeeBps` — or add a new `ContractError::InvalidBatchSize = 21` for clarity +- An empty batch (`users.len() == 0`) must return an empty `Vec` without panicking +- The existing `test_batch_charge_stress` test uses a large batch — update it to use a size $\le$ `MAX_BATCH_SIZE` or call `set_max_batch_size` first ### Acceptance Criteria + - [ ] `ContractError::BatchTooLarge = 20` in `errors.rs` - [ ] `batch_charge` with `users.len() > max` panics with `BatchTooLarge` - [ ] `set_max_batch_size` requires admin auth and rejects values > 200 @@ -83,29 +96,34 @@ Add a `MAX_BATCH_SIZE: u32 = 50` constant in `batch.rs`. At the start of `batch_ - [ ] Test: batch of 51 with default limit panics; batch of 50 succeeds - [ ] `cargo test` passes, `test_batch_charge_stress` updated accordingly -ISSUE #474 ## [CONTRACT-18] Implement cancel_and_refund_prorated for Partial-Period Refunds +ISSUE #474 ## [CONTRACT-18] Implement cancel_and_refund_prorated for Partial-Period Refunds -* **Points:** 200 -* **Labels:** contract, subscriptions, token, ux +- **Points:** 200 +- **Labels:** contract, subscriptions, token, ux ### Background + `cancel` in `lib.rs` immediately deactivates the subscription without any refund mechanism. Users who cancel mid-period have paid for a full billing interval but cannot recoup the unused portion. While full refund logic is complex and out of scope, a prorated refund — where the contract transfers back $\text{amount} \times (\text{remaining\_seconds} / \text{interval})$ to the user — is both mathematically tractable and a significant UX differentiator. The contract already holds no funds directly (charges use `transfer_from` on the user's allowance), so a refund is a merchant-to-user transfer, requiring the merchant's authorization. ### Task + Add `cancel_and_refund_prorated(env: Env, user: Address, merchant: Address)` requiring both `user.require_auth()` and `merchant.require_auth()`. Compute $\text{elapsed} = \text{now} - \text{last\_charged}$, $\text{remaining} = \text{interval} - \text{elapsed}$ (clamped to 0 if $\text{elapsed} \ge \text{interval}$), $\text{refund} = \text{amount} \times \text{remaining} / \text{interval}$. If $\text{refund} > 0$, transfer refund from merchant to user using `token::Client::new(&env, &sub.token).transfer(&merchant, &user, &refund)`. Then cancel the subscription (set `active: false`, decrement counts). Emit a `subscription_cancelled_with_refund` event including the refund amount. ### Key Files -* `contract/src/lib.rs` — add `cancel_and_refund_prorated`; factor `cancel` bookkeeping into `cancel_inner(env, user)` to avoid duplication -* `contract/src/events.rs` — add `publish_cancelled_with_refund(env, user, refund_amount)` -* `contract/src/test.rs` — test: cancel 25% into a 100-second interval on a 1,000,000 stroop subscription yields a 750,000 refund; test: cancel at or after interval end yields 0 refund and no transfer; test: missing subscription panics + +- `contract/src/lib.rs` — add `cancel_and_refund_prorated`; factor `cancel` bookkeeping into `cancel_inner(env, user)` to avoid duplication +- `contract/src/events.rs` — add `publish_cancelled_with_refund(env, user, refund_amount)` +- `contract/src/test.rs` — test: cancel 25% into a 100-second interval on a 1,000,000 stroop subscription yields a 750,000 refund; test: cancel at or after interval end yields 0 refund and no transfer; test: missing subscription panics ### Edge Cases -* Both user and merchant must auth — a user cannot force a refund without merchant consent -* If $\text{elapsed} \ge \text{interval}$, $\text{remaining} = 0$ and $\text{refund} = 0$ — skip the transfer entirely -* Integer division truncation is acceptable (document in code comments); do not use floating point -* The function must still cancel the subscription even when `refund == 0` + +- Both user and merchant must auth — a user cannot force a refund without merchant consent +- If $\text{elapsed} \ge \text{interval}$, $\text{remaining} = 0$ and $\text{refund} = 0$ — skip the transfer entirely +- Integer division truncation is acceptable (document in code comments); do not use floating point +- The function must still cancel the subscription even when `refund == 0` ### Acceptance Criteria + - [ ] Both `user.require_auth()` and `merchant.require_auth()` are called - [ ] Prorated refund formula: $\text{refund} = \text{amount} \times \max(0, \text{interval} - \text{elapsed}) / \text{interval}$ - [ ] Token transfer only occurs when $\text{refund} > 0$ diff --git a/contract/test_snapshots/bench/bench_batch_charge_10_users.1.json b/contract/test_snapshots/bench/bench_batch_charge_10_users.1.json index 02ad1db8..777d2cf3 100644 --- a/contract/test_snapshots/bench/bench_batch_charge_10_users.1.json +++ b/contract/test_snapshots/bench/bench_batch_charge_10_users.1.json @@ -1080,4 +1080,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/bench/bench_charge.1.json b/contract/test_snapshots/bench/bench_charge.1.json index 23f74480..f2b961dc 100644 --- a/contract/test_snapshots/bench/bench_charge.1.json +++ b/contract/test_snapshots/bench/bench_charge.1.json @@ -1080,4 +1080,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/bench/bench_charge_vs_subscribe_ratio.1.json b/contract/test_snapshots/bench/bench_charge_vs_subscribe_ratio.1.json index 824994d3..8279cc45 100644 --- a/contract/test_snapshots/bench/bench_charge_vs_subscribe_ratio.1.json +++ b/contract/test_snapshots/bench/bench_charge_vs_subscribe_ratio.1.json @@ -1080,4 +1080,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/bench/bench_pay_per_use.1.json b/contract/test_snapshots/bench/bench_pay_per_use.1.json index 02ad1db8..777d2cf3 100644 --- a/contract/test_snapshots/bench/bench_pay_per_use.1.json +++ b/contract/test_snapshots/bench/bench_pay_per_use.1.json @@ -1080,4 +1080,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/bench/bench_subscribe.1.json b/contract/test_snapshots/bench/bench_subscribe.1.json index 23f74480..f2b961dc 100644 --- a/contract/test_snapshots/bench/bench_subscribe.1.json +++ b/contract/test_snapshots/bench/bench_subscribe.1.json @@ -1080,4 +1080,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_accept_admin_without_proposal_panics.1.json b/contract/test_snapshots/test/test_accept_admin_without_proposal_panics.1.json index 2c365676..cf93af38 100644 --- a/contract/test_snapshots/test/test_accept_admin_without_proposal_panics.1.json +++ b/contract/test_snapshots/test/test_accept_admin_without_proposal_panics.1.json @@ -1013,4 +1013,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_active_count_decrements_on_cancel.1.json b/contract/test_snapshots/test/test_active_count_decrements_on_cancel.1.json index 5a835644..5d6b3a41 100644 --- a/contract/test_snapshots/test/test_active_count_decrements_on_cancel.1.json +++ b/contract/test_snapshots/test/test_active_count_decrements_on_cancel.1.json @@ -1807,4 +1807,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_active_count_does_not_double_count_on_resubscribe.1.json b/contract/test_snapshots/test/test_active_count_does_not_double_count_on_resubscribe.1.json index 9495a0f0..d162e383 100644 --- a/contract/test_snapshots/test/test_active_count_does_not_double_count_on_resubscribe.1.json +++ b/contract/test_snapshots/test/test_active_count_does_not_double_count_on_resubscribe.1.json @@ -2198,4 +2198,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_active_count_increments_on_subscribe.1.json b/contract/test_snapshots/test/test_active_count_increments_on_subscribe.1.json index 3d428992..476b044b 100644 --- a/contract/test_snapshots/test/test_active_count_increments_on_subscribe.1.json +++ b/contract/test_snapshots/test/test_active_count_increments_on_subscribe.1.json @@ -1676,4 +1676,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_active_count_multiple_users.1.json b/contract/test_snapshots/test/test_active_count_multiple_users.1.json index f88b4d61..b3fa0531 100644 --- a/contract/test_snapshots/test/test_active_count_multiple_users.1.json +++ b/contract/test_snapshots/test/test_active_count_multiple_users.1.json @@ -2764,4 +2764,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_admin_batch_pause_subscriptions_freezes_multiple_accounts.1.json b/contract/test_snapshots/test/test_admin_batch_pause_subscriptions_freezes_multiple_accounts.1.json index 3db2b0c7..72f31dc8 100644 --- a/contract/test_snapshots/test/test_admin_batch_pause_subscriptions_freezes_multiple_accounts.1.json +++ b/contract/test_snapshots/test/test_admin_batch_pause_subscriptions_freezes_multiple_accounts.1.json @@ -2969,4 +2969,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_charge_auto_resumes_paused_subscription_past_expiry.1.json b/contract/test_snapshots/test/test_batch_charge_auto_resumes_paused_subscription_past_expiry.1.json index 74e9ad58..69c14ec7 100644 --- a/contract/test_snapshots/test/test_batch_charge_auto_resumes_paused_subscription_past_expiry.1.json +++ b/contract/test_snapshots/test/test_batch_charge_auto_resumes_paused_subscription_past_expiry.1.json @@ -1892,4 +1892,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_charge_charged_and_skipped.1.json b/contract/test_snapshots/test/test_batch_charge_charged_and_skipped.1.json index 48a7b2e5..b81c22e9 100644 --- a/contract/test_snapshots/test/test_batch_charge_charged_and_skipped.1.json +++ b/contract/test_snapshots/test/test_batch_charge_charged_and_skipped.1.json @@ -3397,4 +3397,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_charge_empty.1.json b/contract/test_snapshots/test/test_batch_charge_empty.1.json index cf7f4630..a8ce4934 100644 --- a/contract/test_snapshots/test/test_batch_charge_empty.1.json +++ b/contract/test_snapshots/test/test_batch_charge_empty.1.json @@ -933,4 +933,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_charge_grace_period_elapsed.1.json b/contract/test_snapshots/test/test_batch_charge_grace_period_elapsed.1.json index 2d196443..ffc384c2 100644 --- a/contract/test_snapshots/test/test_batch_charge_grace_period_elapsed.1.json +++ b/contract/test_snapshots/test/test_batch_charge_grace_period_elapsed.1.json @@ -1899,4 +1899,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_charge_inactive.1.json b/contract/test_snapshots/test/test_batch_charge_inactive.1.json index 3819d095..d52f9d80 100644 --- a/contract/test_snapshots/test/test_batch_charge_inactive.1.json +++ b/contract/test_snapshots/test/test_batch_charge_inactive.1.json @@ -1773,4 +1773,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_charge_no_subscription.1.json b/contract/test_snapshots/test/test_batch_charge_no_subscription.1.json index a143c9a2..4e19eb80 100644 --- a/contract/test_snapshots/test/test_batch_charge_no_subscription.1.json +++ b/contract/test_snapshots/test/test_batch_charge_no_subscription.1.json @@ -945,4 +945,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_charge_ordering.1.json b/contract/test_snapshots/test/test_batch_charge_ordering.1.json index edfbc45e..9641a75c 100644 --- a/contract/test_snapshots/test/test_batch_charge_ordering.1.json +++ b/contract/test_snapshots/test/test_batch_charge_ordering.1.json @@ -4350,4 +4350,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_charge_over_default_limit_panics.1.json b/contract/test_snapshots/test/test_batch_charge_over_default_limit_panics.1.json index ace39ae0..2f7a7363 100644 --- a/contract/test_snapshots/test/test_batch_charge_over_default_limit_panics.1.json +++ b/contract/test_snapshots/test/test_batch_charge_over_default_limit_panics.1.json @@ -1339,4 +1339,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_charge_paused.1.json b/contract/test_snapshots/test/test_batch_charge_paused.1.json index 7e874845..01e51c38 100644 --- a/contract/test_snapshots/test/test_batch_charge_paused.1.json +++ b/contract/test_snapshots/test/test_batch_charge_paused.1.json @@ -1807,4 +1807,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_charge_stress.1.json b/contract/test_snapshots/test/test_batch_charge_stress.1.json index 4fcc679d..664e047f 100644 --- a/contract/test_snapshots/test/test_batch_charge_stress.1.json +++ b/contract/test_snapshots/test/test_batch_charge_stress.1.json @@ -61362,4 +61362,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_charge_with_fee.1.json b/contract/test_snapshots/test/test_batch_charge_with_fee.1.json index f8955ed6..7900cb92 100644 --- a/contract/test_snapshots/test/test_batch_charge_with_fee.1.json +++ b/contract/test_snapshots/test/test_batch_charge_with_fee.1.json @@ -4368,4 +4368,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_pause_subscriptions_exceeds_max_size_panics.1.json b/contract/test_snapshots/test/test_batch_pause_subscriptions_exceeds_max_size_panics.1.json index 09f98215..e72faf35 100644 --- a/contract/test_snapshots/test/test_batch_pause_subscriptions_exceeds_max_size_panics.1.json +++ b/contract/test_snapshots/test/test_batch_pause_subscriptions_exceeds_max_size_panics.1.json @@ -1227,4 +1227,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_pause_subscriptions_handles_valid_missing_and_pre_paused_accounts.1.json b/contract/test_snapshots/test/test_batch_pause_subscriptions_handles_valid_missing_and_pre_paused_accounts.1.json index 45bfbf94..b1a24316 100644 --- a/contract/test_snapshots/test/test_batch_pause_subscriptions_handles_valid_missing_and_pre_paused_accounts.1.json +++ b/contract/test_snapshots/test/test_batch_pause_subscriptions_handles_valid_missing_and_pre_paused_accounts.1.json @@ -3167,4 +3167,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_pause_subscriptions_mixed_inputs.1.json b/contract/test_snapshots/test/test_batch_pause_subscriptions_mixed_inputs.1.json index fb41b4a8..fe0ee429 100644 --- a/contract/test_snapshots/test/test_batch_pause_subscriptions_mixed_inputs.1.json +++ b/contract/test_snapshots/test/test_batch_pause_subscriptions_mixed_inputs.1.json @@ -5927,4 +5927,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_pause_subscriptions_non_admin_panics.1.json b/contract/test_snapshots/test/test_batch_pause_subscriptions_non_admin_panics.1.json index e105825e..293e701d 100644 --- a/contract/test_snapshots/test/test_batch_pause_subscriptions_non_admin_panics.1.json +++ b/contract/test_snapshots/test/test_batch_pause_subscriptions_non_admin_panics.1.json @@ -1774,4 +1774,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_pause_subscriptions_rejects_more_than_twenty_five_accounts.1.json b/contract/test_snapshots/test/test_batch_pause_subscriptions_rejects_more_than_twenty_five_accounts.1.json index 667ea1c3..b8adb0ef 100644 --- a/contract/test_snapshots/test/test_batch_pause_subscriptions_rejects_more_than_twenty_five_accounts.1.json +++ b/contract/test_snapshots/test/test_batch_pause_subscriptions_rejects_more_than_twenty_five_accounts.1.json @@ -1227,4 +1227,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_batch_pause_subscriptions_requires_admin_auth.1.json b/contract/test_snapshots/test/test_batch_pause_subscriptions_requires_admin_auth.1.json index 2098fc25..66a741e2 100644 --- a/contract/test_snapshots/test/test_batch_pause_subscriptions_requires_admin_auth.1.json +++ b/contract/test_snapshots/test/test_batch_pause_subscriptions_requires_admin_auth.1.json @@ -3,10 +3,7 @@ "address": 3, "nonce": 0 }, - "auth": [ - [], - [] - ], + "auth": [[], []], "ledger": { "protocol_version": 21, "sequence_number": 0, @@ -267,4 +264,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_cancel.1.json b/contract/test_snapshots/test/test_cancel.1.json index 80cb736a..b147c8de 100644 --- a/contract/test_snapshots/test/test_cancel.1.json +++ b/contract/test_snapshots/test/test_cancel.1.json @@ -1843,4 +1843,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_cancel_and_refund_prorated_at_interval_end_transfers_nothing.1.json b/contract/test_snapshots/test/test_cancel_and_refund_prorated_at_interval_end_transfers_nothing.1.json index a376dc18..342c09ed 100644 --- a/contract/test_snapshots/test/test_cancel_and_refund_prorated_at_interval_end_transfers_nothing.1.json +++ b/contract/test_snapshots/test/test_cancel_and_refund_prorated_at_interval_end_transfers_nothing.1.json @@ -2349,4 +2349,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_cancel_and_refund_prorated_transfers_expected_amount.1.json b/contract/test_snapshots/test/test_cancel_and_refund_prorated_transfers_expected_amount.1.json index ab2712c4..2a429641 100644 --- a/contract/test_snapshots/test/test_cancel_and_refund_prorated_transfers_expected_amount.1.json +++ b/contract/test_snapshots/test/test_cancel_and_refund_prorated_transfers_expected_amount.1.json @@ -2465,4 +2465,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_charge_succeeds_after_merchant_frozen.1.json b/contract/test_snapshots/test/test_charge_succeeds_after_merchant_frozen.1.json index 29155eda..c4452b12 100644 --- a/contract/test_snapshots/test/test_charge_succeeds_after_merchant_frozen.1.json +++ b/contract/test_snapshots/test/test_charge_succeeds_after_merchant_frozen.1.json @@ -2527,4 +2527,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_charge_too_early.1.json b/contract/test_snapshots/test/test_charge_too_early.1.json index 5d6cd18d..8faec054 100644 --- a/contract/test_snapshots/test/test_charge_too_early.1.json +++ b/contract/test_snapshots/test/test_charge_too_early.1.json @@ -1753,4 +1753,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_charge_updates_last_charged.1.json b/contract/test_snapshots/test/test_charge_updates_last_charged.1.json index 4a943e64..c32a59fc 100644 --- a/contract/test_snapshots/test/test_charge_updates_last_charged.1.json +++ b/contract/test_snapshots/test/test_charge_updates_last_charged.1.json @@ -2293,4 +2293,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_charge_with_zero_fee_bps_skips_fee_transfer.1.json b/contract/test_snapshots/test/test_charge_with_zero_fee_bps_skips_fee_transfer.1.json index 0a416cfa..f9b5e26e 100644 --- a/contract/test_snapshots/test/test_charge_with_zero_fee_bps_skips_fee_transfer.1.json +++ b/contract/test_snapshots/test/test_charge_with_zero_fee_bps_skips_fee_transfer.1.json @@ -2666,4 +2666,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_charge_within_grace_window_succeeds.1.json b/contract/test_snapshots/test/test_charge_within_grace_window_succeeds.1.json index c5a889c0..5bd7309e 100644 --- a/contract/test_snapshots/test/test_charge_within_grace_window_succeeds.1.json +++ b/contract/test_snapshots/test/test_charge_within_grace_window_succeeds.1.json @@ -2550,4 +2550,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_charged_event_includes_ledger_sequence.1.json b/contract/test_snapshots/test/test_charged_event_includes_ledger_sequence.1.json index a869e495..f970ea94 100644 --- a/contract/test_snapshots/test/test_charged_event_includes_ledger_sequence.1.json +++ b/contract/test_snapshots/test/test_charged_event_includes_ledger_sequence.1.json @@ -2161,4 +2161,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_clear_charge_history_admin_succeeds.1.json b/contract/test_snapshots/test/test_clear_charge_history_admin_succeeds.1.json index d7f59c25..97d1eaed 100644 --- a/contract/test_snapshots/test/test_clear_charge_history_admin_succeeds.1.json +++ b/contract/test_snapshots/test/test_clear_charge_history_admin_succeeds.1.json @@ -2328,4 +2328,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_clear_charge_history_non_admin_panics.1.json b/contract/test_snapshots/test/test_clear_charge_history_non_admin_panics.1.json index 052fc2f7..d6cb26d1 100644 --- a/contract/test_snapshots/test/test_clear_charge_history_non_admin_panics.1.json +++ b/contract/test_snapshots/test/test_clear_charge_history_non_admin_panics.1.json @@ -1069,4 +1069,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_clear_charge_history_nonexistent_key_no_panic.1.json b/contract/test_snapshots/test/test_clear_charge_history_nonexistent_key_no_panic.1.json index 78f1b3f9..1e40206d 100644 --- a/contract/test_snapshots/test/test_clear_charge_history_nonexistent_key_no_panic.1.json +++ b/contract/test_snapshots/test/test_clear_charge_history_nonexistent_key_no_panic.1.json @@ -995,4 +995,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_clear_merchant_revenue_history_drops_history.1.json b/contract/test_snapshots/test/test_clear_merchant_revenue_history_drops_history.1.json index 64fa4442..7bf37357 100644 --- a/contract/test_snapshots/test/test_clear_merchant_revenue_history_drops_history.1.json +++ b/contract/test_snapshots/test/test_clear_merchant_revenue_history_drops_history.1.json @@ -2515,4 +2515,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_clear_merchant_revenue_history_idempotent.1.json b/contract/test_snapshots/test/test_clear_merchant_revenue_history_idempotent.1.json index c8829072..f4153543 100644 --- a/contract/test_snapshots/test/test_clear_merchant_revenue_history_idempotent.1.json +++ b/contract/test_snapshots/test/test_clear_merchant_revenue_history_idempotent.1.json @@ -1238,4 +1238,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_clear_merchant_revenue_history_non_admin_panics.1.json b/contract/test_snapshots/test/test_clear_merchant_revenue_history_non_admin_panics.1.json index 8c39a3a1..63293d9a 100644 --- a/contract/test_snapshots/test/test_clear_merchant_revenue_history_non_admin_panics.1.json +++ b/contract/test_snapshots/test/test_clear_merchant_revenue_history_non_admin_panics.1.json @@ -1026,4 +1026,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_clear_metadata_removes_label.1.json b/contract/test_snapshots/test/test_clear_metadata_removes_label.1.json index a9c4418a..c04b0f3c 100644 --- a/contract/test_snapshots/test/test_clear_metadata_removes_label.1.json +++ b/contract/test_snapshots/test/test_clear_metadata_removes_label.1.json @@ -1886,4 +1886,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_contract_pause_events_emitted.1.json b/contract/test_snapshots/test/test_contract_pause_events_emitted.1.json index 78a8955e..b6fe27e2 100644 --- a/contract/test_snapshots/test/test_contract_pause_events_emitted.1.json +++ b/contract/test_snapshots/test/test_contract_pause_events_emitted.1.json @@ -1226,4 +1226,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_custom_sac_token_end_to_end_flow.1.json b/contract/test_snapshots/test/test_custom_sac_token_end_to_end_flow.1.json index fde3ed9d..6cd982fc 100644 --- a/contract/test_snapshots/test/test_custom_sac_token_end_to_end_flow.1.json +++ b/contract/test_snapshots/test/test_custom_sac_token_end_to_end_flow.1.json @@ -4027,4 +4027,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_daily_limit_accumulates_across_calls.1.json b/contract/test_snapshots/test/test_daily_limit_accumulates_across_calls.1.json index a48e5297..7f6fdd57 100644 --- a/contract/test_snapshots/test/test_daily_limit_accumulates_across_calls.1.json +++ b/contract/test_snapshots/test/test_daily_limit_accumulates_across_calls.1.json @@ -2719,4 +2719,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_daily_limit_allows_spend_within_limit.1.json b/contract/test_snapshots/test/test_daily_limit_allows_spend_within_limit.1.json index 2ef0d75a..5398dd59 100644 --- a/contract/test_snapshots/test/test_daily_limit_allows_spend_within_limit.1.json +++ b/contract/test_snapshots/test/test_daily_limit_allows_spend_within_limit.1.json @@ -2452,4 +2452,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_daily_limit_blocks_cumulative_overspend.1.json b/contract/test_snapshots/test/test_daily_limit_blocks_cumulative_overspend.1.json index 6e482daf..b307a674 100644 --- a/contract/test_snapshots/test/test_daily_limit_blocks_cumulative_overspend.1.json +++ b/contract/test_snapshots/test/test_daily_limit_blocks_cumulative_overspend.1.json @@ -2641,4 +2641,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_daily_limit_blocks_overspend.1.json b/contract/test_snapshots/test/test_daily_limit_blocks_overspend.1.json index da212004..d7db0446 100644 --- a/contract/test_snapshots/test/test_daily_limit_blocks_overspend.1.json +++ b/contract/test_snapshots/test/test_daily_limit_blocks_overspend.1.json @@ -1958,4 +1958,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_daily_limit_day_start_boundary.1.json b/contract/test_snapshots/test/test_daily_limit_day_start_boundary.1.json index fadac38c..ae314e7e 100644 --- a/contract/test_snapshots/test/test_daily_limit_day_start_boundary.1.json +++ b/contract/test_snapshots/test/test_daily_limit_day_start_boundary.1.json @@ -3390,4 +3390,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_daily_limit_removed_event_emitted.1.json b/contract/test_snapshots/test/test_daily_limit_removed_event_emitted.1.json index 2a0bc6a3..f588881b 100644 --- a/contract/test_snapshots/test/test_daily_limit_removed_event_emitted.1.json +++ b/contract/test_snapshots/test/test_daily_limit_removed_event_emitted.1.json @@ -1192,4 +1192,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_daily_limit_set_event_emitted.1.json b/contract/test_snapshots/test/test_daily_limit_set_event_emitted.1.json index 818f95fe..797860d5 100644 --- a/contract/test_snapshots/test/test_daily_limit_set_event_emitted.1.json +++ b/contract/test_snapshots/test/test_daily_limit_set_event_emitted.1.json @@ -1072,4 +1072,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_daily_limit_visibility_and_spend_tracking.1.json b/contract/test_snapshots/test/test_daily_limit_visibility_and_spend_tracking.1.json index eaa03aab..e0340ee6 100644 --- a/contract/test_snapshots/test/test_daily_limit_visibility_and_spend_tracking.1.json +++ b/contract/test_snapshots/test/test_daily_limit_visibility_and_spend_tracking.1.json @@ -2712,4 +2712,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_double_initialize.1.json b/contract/test_snapshots/test/test_double_initialize.1.json index 45625c06..75b17496 100644 --- a/contract/test_snapshots/test/test_double_initialize.1.json +++ b/contract/test_snapshots/test/test_double_initialize.1.json @@ -1199,4 +1199,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_freeze_merchant_idempotent.1.json b/contract/test_snapshots/test/test_freeze_merchant_idempotent.1.json index 758fc102..481cee60 100644 --- a/contract/test_snapshots/test/test_freeze_merchant_idempotent.1.json +++ b/contract/test_snapshots/test/test_freeze_merchant_idempotent.1.json @@ -1372,4 +1372,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_freeze_merchant_independent_of_whitelist.1.json b/contract/test_snapshots/test/test_freeze_merchant_independent_of_whitelist.1.json index e3d6df7a..fde87a96 100644 --- a/contract/test_snapshots/test/test_freeze_merchant_independent_of_whitelist.1.json +++ b/contract/test_snapshots/test/test_freeze_merchant_independent_of_whitelist.1.json @@ -1346,4 +1346,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_freeze_merchant_non_admin_panics.1.json b/contract/test_snapshots/test/test_freeze_merchant_non_admin_panics.1.json index b0226087..eced3c48 100644 --- a/contract/test_snapshots/test/test_freeze_merchant_non_admin_panics.1.json +++ b/contract/test_snapshots/test/test_freeze_merchant_non_admin_panics.1.json @@ -1033,4 +1033,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_charge_history_empty_for_no_history.1.json b/contract/test_snapshots/test/test_get_charge_history_empty_for_no_history.1.json index 139febf6..9aae1485 100644 --- a/contract/test_snapshots/test/test_get_charge_history_empty_for_no_history.1.json +++ b/contract/test_snapshots/test/test_get_charge_history_empty_for_no_history.1.json @@ -933,4 +933,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_charge_history_page_limit_capped_at_12.1.json b/contract/test_snapshots/test/test_get_charge_history_page_limit_capped_at_12.1.json index b55cb300..ba44a151 100644 --- a/contract/test_snapshots/test/test_get_charge_history_page_limit_capped_at_12.1.json +++ b/contract/test_snapshots/test/test_get_charge_history_page_limit_capped_at_12.1.json @@ -6025,4 +6025,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_charge_history_page_offset_beyond_length.1.json b/contract/test_snapshots/test/test_get_charge_history_page_offset_beyond_length.1.json index edaed75a..a35c3e71 100644 --- a/contract/test_snapshots/test/test_get_charge_history_page_offset_beyond_length.1.json +++ b/contract/test_snapshots/test/test_get_charge_history_page_offset_beyond_length.1.json @@ -2224,4 +2224,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_charge_history_page_offset_limit.1.json b/contract/test_snapshots/test/test_get_charge_history_page_offset_limit.1.json index e47c97f0..6fa4d7f2 100644 --- a/contract/test_snapshots/test/test_get_charge_history_page_offset_limit.1.json +++ b/contract/test_snapshots/test/test_get_charge_history_page_offset_limit.1.json @@ -2811,4 +2811,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_charge_history_three_charges_ascending.1.json b/contract/test_snapshots/test/test_get_charge_history_three_charges_ascending.1.json index 36cf2c03..d162948b 100644 --- a/contract/test_snapshots/test/test_get_charge_history_three_charges_ascending.1.json +++ b/contract/test_snapshots/test/test_get_charge_history_three_charges_ascending.1.json @@ -2801,4 +2801,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_daily_limit.1.json b/contract/test_snapshots/test/test_get_daily_limit.1.json index 3385fc85..ca4a82dc 100644 --- a/contract/test_snapshots/test/test_get_daily_limit.1.json +++ b/contract/test_snapshots/test/test_get_daily_limit.1.json @@ -1173,4 +1173,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_fee_returns_current_fee_settings.1.json b/contract/test_snapshots/test/test_get_fee_returns_current_fee_settings.1.json index a0759bce..05668cdf 100644 --- a/contract/test_snapshots/test/test_get_fee_returns_current_fee_settings.1.json +++ b/contract/test_snapshots/test/test_get_fee_returns_current_fee_settings.1.json @@ -1231,4 +1231,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_grace_period_after_set.1.json b/contract/test_snapshots/test/test_get_grace_period_after_set.1.json index 4858175d..cde0eb8a 100644 --- a/contract/test_snapshots/test/test_get_grace_period_after_set.1.json +++ b/contract/test_snapshots/test/test_get_grace_period_after_set.1.json @@ -1188,4 +1188,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_grace_period_default_zero.1.json b/contract/test_snapshots/test/test_get_grace_period_default_zero.1.json index a5607a39..e513e0bc 100644 --- a/contract/test_snapshots/test/test_get_grace_period_default_zero.1.json +++ b/contract/test_snapshots/test/test_get_grace_period_default_zero.1.json @@ -931,4 +931,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_metadata_none_when_not_set.1.json b/contract/test_snapshots/test/test_get_metadata_none_when_not_set.1.json index ccde10e9..7a22c6c9 100644 --- a/contract/test_snapshots/test/test_get_metadata_none_when_not_set.1.json +++ b/contract/test_snapshots/test/test_get_metadata_none_when_not_set.1.json @@ -931,4 +931,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_min_interval_default.1.json b/contract/test_snapshots/test/test_get_min_interval_default.1.json index 0dd8f258..5c87d6fa 100644 --- a/contract/test_snapshots/test/test_get_min_interval_default.1.json +++ b/contract/test_snapshots/test/test_get_min_interval_default.1.json @@ -931,4 +931,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_protocol_stats_after_subscribe.1.json b/contract/test_snapshots/test/test_get_protocol_stats_after_subscribe.1.json index c8ed2180..f84c65c9 100644 --- a/contract/test_snapshots/test/test_get_protocol_stats_after_subscribe.1.json +++ b/contract/test_snapshots/test/test_get_protocol_stats_after_subscribe.1.json @@ -1683,4 +1683,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_protocol_stats_contract_paused.1.json b/contract/test_snapshots/test/test_get_protocol_stats_contract_paused.1.json index 1de020ac..bbde61e7 100644 --- a/contract/test_snapshots/test/test_get_protocol_stats_contract_paused.1.json +++ b/contract/test_snapshots/test/test_get_protocol_stats_contract_paused.1.json @@ -1336,4 +1336,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_protocol_stats_initial.1.json b/contract/test_snapshots/test/test_get_protocol_stats_initial.1.json index c916043e..ea01cd42 100644 --- a/contract/test_snapshots/test/test_get_protocol_stats_initial.1.json +++ b/contract/test_snapshots/test/test_get_protocol_stats_initial.1.json @@ -986,4 +986,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_protocol_stats_with_fee.1.json b/contract/test_snapshots/test/test_get_protocol_stats_with_fee.1.json index d52ff02c..78cc6dea 100644 --- a/contract/test_snapshots/test/test_get_protocol_stats_with_fee.1.json +++ b/contract/test_snapshots/test/test_get_protocol_stats_with_fee.1.json @@ -1281,4 +1281,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_subscriber_at_returns_first.1.json b/contract/test_snapshots/test/test_get_subscriber_at_returns_first.1.json index 63dc6596..17ea38bf 100644 --- a/contract/test_snapshots/test/test_get_subscriber_at_returns_first.1.json +++ b/contract/test_snapshots/test/test_get_subscriber_at_returns_first.1.json @@ -1678,4 +1678,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_subscription_label_none_when_not_set.1.json b/contract/test_snapshots/test/test_get_subscription_label_none_when_not_set.1.json index ec64cbb2..07304774 100644 --- a/contract/test_snapshots/test/test_get_subscription_label_none_when_not_set.1.json +++ b/contract/test_snapshots/test/test_get_subscription_label_none_when_not_set.1.json @@ -931,4 +931,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_subscription_label_returns_set_value.1.json b/contract/test_snapshots/test/test_get_subscription_label_returns_set_value.1.json index 828db7d1..0efb5a42 100644 --- a/contract/test_snapshots/test/test_get_subscription_label_returns_set_value.1.json +++ b/contract/test_snapshots/test/test_get_subscription_label_returns_set_value.1.json @@ -1784,4 +1784,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_subscription_nonexistent.1.json b/contract/test_snapshots/test/test_get_subscription_nonexistent.1.json index b865b48b..8c467aeb 100644 --- a/contract/test_snapshots/test/test_get_subscription_nonexistent.1.json +++ b/contract/test_snapshots/test/test_get_subscription_nonexistent.1.json @@ -931,4 +931,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_token_returns_initialized_token.1.json b/contract/test_snapshots/test/test_get_token_returns_initialized_token.1.json index 442cc4cd..39e9b717 100644 --- a/contract/test_snapshots/test/test_get_token_returns_initialized_token.1.json +++ b/contract/test_snapshots/test/test_get_token_returns_initialized_token.1.json @@ -1064,4 +1064,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_token_returns_none_when_not_initialized.1.json b/contract/test_snapshots/test/test_get_token_returns_none_when_not_initialized.1.json index 53ad479f..3baab2b6 100644 --- a/contract/test_snapshots/test/test_get_token_returns_none_when_not_initialized.1.json +++ b/contract/test_snapshots/test/test_get_token_returns_none_when_not_initialized.1.json @@ -3,9 +3,7 @@ "address": 1, "nonce": 0 }, - "auth": [ - [] - ], + "auth": [[]], "ledger": { "protocol_version": 21, "sequence_number": 0, @@ -118,4 +116,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_trial_end_with_trial_period.1.json b/contract/test_snapshots/test/test_get_trial_end_with_trial_period.1.json index 4d3d6766..4e108d54 100644 --- a/contract/test_snapshots/test/test_get_trial_end_with_trial_period.1.json +++ b/contract/test_snapshots/test/test_get_trial_end_with_trial_period.1.json @@ -1634,4 +1634,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_get_trial_end_without_trial_period.1.json b/contract/test_snapshots/test/test_get_trial_end_without_trial_period.1.json index 9ba9a442..fbf44800 100644 --- a/contract/test_snapshots/test/test_get_trial_end_without_trial_period.1.json +++ b/contract/test_snapshots/test/test_get_trial_end_without_trial_period.1.json @@ -1628,4 +1628,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_global_volume_exceeds_limit.1.json b/contract/test_snapshots/test/test_global_volume_exceeds_limit.1.json index a0296223..75a4501f 100644 --- a/contract/test_snapshots/test/test_global_volume_exceeds_limit.1.json +++ b/contract/test_snapshots/test/test_global_volume_exceeds_limit.1.json @@ -3871,4 +3871,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_global_volume_window_reset.1.json b/contract/test_snapshots/test/test_global_volume_window_reset.1.json index 66d01f64..033b318c 100644 --- a/contract/test_snapshots/test/test_global_volume_window_reset.1.json +++ b/contract/test_snapshots/test/test_global_volume_window_reset.1.json @@ -3939,4 +3939,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_global_volume_within_limit.1.json b/contract/test_snapshots/test/test_global_volume_within_limit.1.json index 08d69bc8..663b13d6 100644 --- a/contract/test_snapshots/test/test_global_volume_within_limit.1.json +++ b/contract/test_snapshots/test/test_global_volume_within_limit.1.json @@ -2161,4 +2161,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_grace_period_ttl_extension.1.json b/contract/test_snapshots/test/test_grace_period_ttl_extension.1.json index 40e6a94a..639663ab 100644 --- a/contract/test_snapshots/test/test_grace_period_ttl_extension.1.json +++ b/contract/test_snapshots/test/test_grace_period_ttl_extension.1.json @@ -1188,4 +1188,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_health_check_active_subscription_count.1.json b/contract/test_snapshots/test/test_health_check_active_subscription_count.1.json index 3e3550c1..6169c8f4 100644 --- a/contract/test_snapshots/test/test_health_check_active_subscription_count.1.json +++ b/contract/test_snapshots/test/test_health_check_active_subscription_count.1.json @@ -1710,4 +1710,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_health_check_initialized_unpaused.1.json b/contract/test_snapshots/test/test_health_check_initialized_unpaused.1.json index 62a47370..d1c8440d 100644 --- a/contract/test_snapshots/test/test_health_check_initialized_unpaused.1.json +++ b/contract/test_snapshots/test/test_health_check_initialized_unpaused.1.json @@ -1146,4 +1146,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_health_check_paused.1.json b/contract/test_snapshots/test/test_health_check_paused.1.json index bb0cb5dc..5e311a06 100644 --- a/contract/test_snapshots/test/test_health_check_paused.1.json +++ b/contract/test_snapshots/test/test_health_check_paused.1.json @@ -1269,4 +1269,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_health_check_pre_initialize.1.json b/contract/test_snapshots/test/test_health_check_pre_initialize.1.json index 83205d0d..c74eee31 100644 --- a/contract/test_snapshots/test/test_health_check_pre_initialize.1.json +++ b/contract/test_snapshots/test/test_health_check_pre_initialize.1.json @@ -3,9 +3,7 @@ "address": 1, "nonce": 0 }, - "auth": [ - [] - ], + "auth": [[]], "ledger": { "protocol_version": 21, "sequence_number": 0, @@ -202,4 +200,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_initialize_backward_compat.1.json b/contract/test_snapshots/test/test_initialize_backward_compat.1.json index e0971ed5..bf514906 100644 --- a/contract/test_snapshots/test/test_initialize_backward_compat.1.json +++ b/contract/test_snapshots/test/test_initialize_backward_compat.1.json @@ -2642,4 +2642,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_initialize_sets_instance_ttl.1.json b/contract/test_snapshots/test/test_initialize_sets_instance_ttl.1.json index c53e28f3..25a0bbf3 100644 --- a/contract/test_snapshots/test/test_initialize_sets_instance_ttl.1.json +++ b/contract/test_snapshots/test/test_initialize_sets_instance_ttl.1.json @@ -519,4 +519,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_initialize_without_valid_token.1.json b/contract/test_snapshots/test/test_initialize_without_valid_token.1.json index 576b1edb..ab9d2ee2 100644 --- a/contract/test_snapshots/test/test_initialize_without_valid_token.1.json +++ b/contract/test_snapshots/test/test_initialize_without_valid_token.1.json @@ -206,4 +206,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_interval_minimum_valid.1.json b/contract/test_snapshots/test/test_interval_minimum_valid.1.json index fbd60a24..216a633a 100644 --- a/contract/test_snapshots/test/test_interval_minimum_valid.1.json +++ b/contract/test_snapshots/test/test_interval_minimum_valid.1.json @@ -1993,4 +1993,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_interval_too_short.1.json b/contract/test_snapshots/test/test_interval_too_short.1.json index ca20ba8e..a0791866 100644 --- a/contract/test_snapshots/test/test_interval_too_short.1.json +++ b/contract/test_snapshots/test/test_interval_too_short.1.json @@ -1094,4 +1094,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_is_charge_due_false_for_paused_subscription.1.json b/contract/test_snapshots/test/test_is_charge_due_false_for_paused_subscription.1.json index 77b1dac5..df985e83 100644 --- a/contract/test_snapshots/test/test_is_charge_due_false_for_paused_subscription.1.json +++ b/contract/test_snapshots/test/test_is_charge_due_false_for_paused_subscription.1.json @@ -1795,4 +1795,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_is_charge_due_false_for_unknown_address.1.json b/contract/test_snapshots/test/test_is_charge_due_false_for_unknown_address.1.json index 96a883b2..1bbe6e8d 100644 --- a/contract/test_snapshots/test/test_is_charge_due_false_for_unknown_address.1.json +++ b/contract/test_snapshots/test/test_is_charge_due_false_for_unknown_address.1.json @@ -933,4 +933,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_is_charge_due_false_past_grace_window.1.json b/contract/test_snapshots/test/test_is_charge_due_false_past_grace_window.1.json index cefe113d..5d0bcfb5 100644 --- a/contract/test_snapshots/test/test_is_charge_due_false_past_grace_window.1.json +++ b/contract/test_snapshots/test/test_is_charge_due_false_past_grace_window.1.json @@ -1887,4 +1887,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_is_charge_due_transitions_after_interval.1.json b/contract/test_snapshots/test/test_is_charge_due_transitions_after_interval.1.json index d1836363..dc1398db 100644 --- a/contract/test_snapshots/test/test_is_charge_due_transitions_after_interval.1.json +++ b/contract/test_snapshots/test/test_is_charge_due_transitions_after_interval.1.json @@ -1680,4 +1680,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_is_merchant_frozen_reflects_state.1.json b/contract/test_snapshots/test/test_is_merchant_frozen_reflects_state.1.json index 2c6f49c0..e094424b 100644 --- a/contract/test_snapshots/test/test_is_merchant_frozen_reflects_state.1.json +++ b/contract/test_snapshots/test/test_is_merchant_frozen_reflects_state.1.json @@ -1421,4 +1421,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_is_merchant_whitelisted_returns_false_for_non_whitelisted.1.json b/contract/test_snapshots/test/test_is_merchant_whitelisted_returns_false_for_non_whitelisted.1.json index f20e0a41..50c126f4 100644 --- a/contract/test_snapshots/test/test_is_merchant_whitelisted_returns_false_for_non_whitelisted.1.json +++ b/contract/test_snapshots/test/test_is_merchant_whitelisted_returns_false_for_non_whitelisted.1.json @@ -1045,4 +1045,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_merchant_revenue_from_charge.1.json b/contract/test_snapshots/test/test_merchant_revenue_from_charge.1.json index 165cdfd2..3065c42c 100644 --- a/contract/test_snapshots/test/test_merchant_revenue_from_charge.1.json +++ b/contract/test_snapshots/test/test_merchant_revenue_from_charge.1.json @@ -2267,4 +2267,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_merchant_sub_count_double_cancel_no_underflow.1.json b/contract/test_snapshots/test/test_merchant_sub_count_double_cancel_no_underflow.1.json index beebdf1b..412134b5 100644 --- a/contract/test_snapshots/test/test_merchant_sub_count_double_cancel_no_underflow.1.json +++ b/contract/test_snapshots/test/test_merchant_sub_count_double_cancel_no_underflow.1.json @@ -1992,4 +1992,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_merchant_sub_count_resubscribe_different_merchant.1.json b/contract/test_snapshots/test/test_merchant_sub_count_resubscribe_different_merchant.1.json index 8910bf67..572f68fe 100644 --- a/contract/test_snapshots/test/test_merchant_sub_count_resubscribe_different_merchant.1.json +++ b/contract/test_snapshots/test/test_merchant_sub_count_resubscribe_different_merchant.1.json @@ -2170,4 +2170,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_merchant_sub_count_two_users_cancel_one.1.json b/contract/test_snapshots/test/test_merchant_sub_count_two_users_cancel_one.1.json index c56cefe6..7cc5f959 100644 --- a/contract/test_snapshots/test/test_merchant_sub_count_two_users_cancel_one.1.json +++ b/contract/test_snapshots/test/test_merchant_sub_count_two_users_cancel_one.1.json @@ -2818,4 +2818,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_migrate_emits_completed_event_with_version_and_count.1.json b/contract/test_snapshots/test/test_migrate_emits_completed_event_with_version_and_count.1.json index dbcc5d67..8dd43662 100644 --- a/contract/test_snapshots/test/test_migrate_emits_completed_event_with_version_and_count.1.json +++ b/contract/test_snapshots/test/test_migrate_emits_completed_event_with_version_and_count.1.json @@ -1740,4 +1740,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_migrate_is_idempotent.1.json b/contract/test_snapshots/test/test_migrate_is_idempotent.1.json index 766f38ba..2baf0893 100644 --- a/contract/test_snapshots/test/test_migrate_is_idempotent.1.json +++ b/contract/test_snapshots/test/test_migrate_is_idempotent.1.json @@ -1181,4 +1181,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_migrate_non_admin_panics.1.json b/contract/test_snapshots/test/test_migrate_non_admin_panics.1.json index f0ce8584..7770f1d6 100644 --- a/contract/test_snapshots/test/test_migrate_non_admin_panics.1.json +++ b/contract/test_snapshots/test/test_migrate_non_admin_panics.1.json @@ -1077,4 +1077,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_migrate_sets_schema_version.1.json b/contract/test_snapshots/test/test_migrate_sets_schema_version.1.json index 14d9458b..a8b99efe 100644 --- a/contract/test_snapshots/test/test_migrate_sets_schema_version.1.json +++ b/contract/test_snapshots/test/test_migrate_sets_schema_version.1.json @@ -1130,4 +1130,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_migrate_v1_to_v2.1.json b/contract/test_snapshots/test/test_migrate_v1_to_v2.1.json index 882498f8..6088a23c 100644 --- a/contract/test_snapshots/test/test_migrate_v1_to_v2.1.json +++ b/contract/test_snapshots/test/test_migrate_v1_to_v2.1.json @@ -1302,4 +1302,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_multi_token_independent_subscriptions.1.json b/contract/test_snapshots/test/test_multi_token_independent_subscriptions.1.json index 60841ed9..3706afde 100644 --- a/contract/test_snapshots/test/test_multi_token_independent_subscriptions.1.json +++ b/contract/test_snapshots/test/test_multi_token_independent_subscriptions.1.json @@ -4046,4 +4046,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_multiple_users.1.json b/contract/test_snapshots/test/test_multiple_users.1.json index c20eeb77..96b4897a 100644 --- a/contract/test_snapshots/test/test_multiple_users.1.json +++ b/contract/test_snapshots/test/test_multiple_users.1.json @@ -3253,4 +3253,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_next_charge_at_none_after_cancel.1.json b/contract/test_snapshots/test/test_next_charge_at_none_after_cancel.1.json index 1f533f75..27f3cb00 100644 --- a/contract/test_snapshots/test/test_next_charge_at_none_after_cancel.1.json +++ b/contract/test_snapshots/test/test_next_charge_at_none_after_cancel.1.json @@ -1759,4 +1759,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_next_charge_at_none_for_paused_subscription.1.json b/contract/test_snapshots/test/test_next_charge_at_none_for_paused_subscription.1.json index 9d5a1d90..79d3f9dc 100644 --- a/contract/test_snapshots/test/test_next_charge_at_none_for_paused_subscription.1.json +++ b/contract/test_snapshots/test/test_next_charge_at_none_for_paused_subscription.1.json @@ -1793,4 +1793,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_next_charge_at_none_for_unknown_address.1.json b/contract/test_snapshots/test/test_next_charge_at_none_for_unknown_address.1.json index d9015323..ac904012 100644 --- a/contract/test_snapshots/test/test_next_charge_at_none_for_unknown_address.1.json +++ b/contract/test_snapshots/test/test_next_charge_at_none_for_unknown_address.1.json @@ -931,4 +931,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_next_charge_at_returns_correct_timestamp.1.json b/contract/test_snapshots/test/test_next_charge_at_returns_correct_timestamp.1.json index 81139463..26f8c85e 100644 --- a/contract/test_snapshots/test/test_next_charge_at_returns_correct_timestamp.1.json +++ b/contract/test_snapshots/test/test_next_charge_at_returns_correct_timestamp.1.json @@ -1762,4 +1762,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_no_referral_returns_none.1.json b/contract/test_snapshots/test/test_no_referral_returns_none.1.json index 2a4b0068..8aff9efd 100644 --- a/contract/test_snapshots/test/test_no_referral_returns_none.1.json +++ b/contract/test_snapshots/test/test_no_referral_returns_none.1.json @@ -1628,4 +1628,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_non_admin_add_and_remove_merchant_panics.1.json b/contract/test_snapshots/test/test_non_admin_add_and_remove_merchant_panics.1.json index 6bb41960..e14bf70a 100644 --- a/contract/test_snapshots/test/test_non_admin_add_and_remove_merchant_panics.1.json +++ b/contract/test_snapshots/test/test_non_admin_add_and_remove_merchant_panics.1.json @@ -1069,4 +1069,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_non_admin_set_grace_period_panics.1.json b/contract/test_snapshots/test/test_non_admin_set_grace_period_panics.1.json index 6ef46910..6734e5d3 100644 --- a/contract/test_snapshots/test/test_non_admin_set_grace_period_panics.1.json +++ b/contract/test_snapshots/test/test_non_admin_set_grace_period_panics.1.json @@ -1069,4 +1069,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_non_admin_set_max_batch_size_panics.1.json b/contract/test_snapshots/test/test_non_admin_set_max_batch_size_panics.1.json index 8428b861..9b43cc2e 100644 --- a/contract/test_snapshots/test/test_non_admin_set_max_batch_size_panics.1.json +++ b/contract/test_snapshots/test/test_non_admin_set_max_batch_size_panics.1.json @@ -1026,4 +1026,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_old_admin_loses_access_after_transfer.1.json b/contract/test_snapshots/test/test_old_admin_loses_access_after_transfer.1.json index 70410d5c..921dfc29 100644 --- a/contract/test_snapshots/test/test_old_admin_loses_access_after_transfer.1.json +++ b/contract/test_snapshots/test/test_old_admin_loses_access_after_transfer.1.json @@ -1116,4 +1116,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pause_on_inactive_subscription_panics.1.json b/contract/test_snapshots/test/test_pause_on_inactive_subscription_panics.1.json index 095a9010..d47334c0 100644 --- a/contract/test_snapshots/test/test_pause_on_inactive_subscription_panics.1.json +++ b/contract/test_snapshots/test/test_pause_on_inactive_subscription_panics.1.json @@ -1884,4 +1884,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pause_sets_indefinite_expiry.1.json b/contract/test_snapshots/test/test_pause_sets_indefinite_expiry.1.json index 502895c4..0a3f0209 100644 --- a/contract/test_snapshots/test/test_pause_sets_indefinite_expiry.1.json +++ b/contract/test_snapshots/test/test_pause_sets_indefinite_expiry.1.json @@ -1407,4 +1407,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pause_sets_paused_true.1.json b/contract/test_snapshots/test/test_pause_sets_paused_true.1.json index efa3d4a4..788130e1 100644 --- a/contract/test_snapshots/test/test_pause_sets_paused_true.1.json +++ b/contract/test_snapshots/test/test_pause_sets_paused_true.1.json @@ -1877,4 +1877,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pause_until_auto_resume_clears_pause_expiry.1.json b/contract/test_snapshots/test/test_pause_until_auto_resume_clears_pause_expiry.1.json index e6fd9fdd..1be9b48e 100644 --- a/contract/test_snapshots/test/test_pause_until_auto_resume_clears_pause_expiry.1.json +++ b/contract/test_snapshots/test/test_pause_until_auto_resume_clears_pause_expiry.1.json @@ -1797,4 +1797,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pause_until_auto_resumes_on_charge.1.json b/contract/test_snapshots/test/test_pause_until_auto_resumes_on_charge.1.json index d35b8f0d..e5e3b558 100644 --- a/contract/test_snapshots/test/test_pause_until_auto_resumes_on_charge.1.json +++ b/contract/test_snapshots/test/test_pause_until_auto_resumes_on_charge.1.json @@ -2059,4 +2059,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pause_until_past_timestamp_panics.1.json b/contract/test_snapshots/test/test_pause_until_past_timestamp_panics.1.json index 7e7d4fcd..cd91545a 100644 --- a/contract/test_snapshots/test/test_pause_until_past_timestamp_panics.1.json +++ b/contract/test_snapshots/test/test_pause_until_past_timestamp_panics.1.json @@ -1424,4 +1424,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use.1.json b/contract/test_snapshots/test/test_pay_per_use.1.json index 2708b675..d32a1eb9 100644 --- a/contract/test_snapshots/test/test_pay_per_use.1.json +++ b/contract/test_snapshots/test/test_pay_per_use.1.json @@ -2369,4 +2369,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_applies_protocol_fee_and_records_net_revenue.1.json b/contract/test_snapshots/test/test_pay_per_use_applies_protocol_fee_and_records_net_revenue.1.json index 4e7b6299..79a31f5e 100644 --- a/contract/test_snapshots/test/test_pay_per_use_applies_protocol_fee_and_records_net_revenue.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_applies_protocol_fee_and_records_net_revenue.1.json @@ -3004,4 +3004,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_does_not_update_last_charged.1.json b/contract/test_snapshots/test/test_pay_per_use_does_not_update_last_charged.1.json index 88673a1b..dad11243 100644 --- a/contract/test_snapshots/test/test_pay_per_use_does_not_update_last_charged.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_does_not_update_last_charged.1.json @@ -2527,4 +2527,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_exceeds_cap.1.json b/contract/test_snapshots/test/test_pay_per_use_exceeds_cap.1.json index 3d197ae1..c68d15ae 100644 --- a/contract/test_snapshots/test/test_pay_per_use_exceeds_cap.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_exceeds_cap.1.json @@ -1769,4 +1769,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_inactive.1.json b/contract/test_snapshots/test/test_pay_per_use_inactive.1.json index 04a22fe2..75b4a830 100644 --- a/contract/test_snapshots/test/test_pay_per_use_inactive.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_inactive.1.json @@ -1900,4 +1900,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_nonexistent.1.json b/contract/test_snapshots/test/test_pay_per_use_nonexistent.1.json index f93a9a5f..7e18cd27 100644 --- a/contract/test_snapshots/test/test_pay_per_use_nonexistent.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_nonexistent.1.json @@ -1072,4 +1072,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_on_paused_subscription_panics.1.json b/contract/test_snapshots/test/test_pay_per_use_on_paused_subscription_panics.1.json index 2bd1dc53..2b03af5c 100644 --- a/contract/test_snapshots/test/test_pay_per_use_on_paused_subscription_panics.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_on_paused_subscription_panics.1.json @@ -1934,4 +1934,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_succeeds_after_merchant_frozen.1.json b/contract/test_snapshots/test/test_pay_per_use_succeeds_after_merchant_frozen.1.json index 4d7930d8..a83f83bf 100644 --- a/contract/test_snapshots/test/test_pay_per_use_succeeds_after_merchant_frozen.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_succeeds_after_merchant_frozen.1.json @@ -2500,4 +2500,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_to_applies_protocol_fee_to_recipient.1.json b/contract/test_snapshots/test/test_pay_per_use_to_applies_protocol_fee_to_recipient.1.json index 85263a00..f8ac9a14 100644 --- a/contract/test_snapshots/test/test_pay_per_use_to_applies_protocol_fee_to_recipient.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_to_applies_protocol_fee_to_recipient.1.json @@ -3010,4 +3010,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_to_daily_limit_shared_with_pay_per_use.1.json b/contract/test_snapshots/test/test_pay_per_use_to_daily_limit_shared_with_pay_per_use.1.json index 4a806abe..cbb078ba 100644 --- a/contract/test_snapshots/test/test_pay_per_use_to_daily_limit_shared_with_pay_per_use.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_to_daily_limit_shared_with_pay_per_use.1.json @@ -2647,4 +2647,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_to_recipient_equals_merchant_behaves_like_pay_per_use.1.json b/contract/test_snapshots/test/test_pay_per_use_to_recipient_equals_merchant_behaves_like_pay_per_use.1.json index 69d8fa85..562703e7 100644 --- a/contract/test_snapshots/test/test_pay_per_use_to_recipient_equals_merchant_behaves_like_pay_per_use.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_to_recipient_equals_merchant_behaves_like_pay_per_use.1.json @@ -2428,4 +2428,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_to_rejects_non_whitelisted_recipient.1.json b/contract/test_snapshots/test/test_pay_per_use_to_rejects_non_whitelisted_recipient.1.json index b4621693..30a3666a 100644 --- a/contract/test_snapshots/test/test_pay_per_use_to_rejects_non_whitelisted_recipient.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_to_rejects_non_whitelisted_recipient.1.json @@ -2136,4 +2136,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_to_transfers_to_recipient_not_merchant.1.json b/contract/test_snapshots/test/test_pay_per_use_to_transfers_to_recipient_not_merchant.1.json index cfa037a6..b8a019fb 100644 --- a/contract/test_snapshots/test/test_pay_per_use_to_transfers_to_recipient_not_merchant.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_to_transfers_to_recipient_not_merchant.1.json @@ -2587,4 +2587,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_with_zero_fee_bps_transfers_full_amount.1.json b/contract/test_snapshots/test/test_pay_per_use_with_zero_fee_bps_transfers_full_amount.1.json index f220c9af..4bf7cafb 100644 --- a/contract/test_snapshots/test/test_pay_per_use_with_zero_fee_bps_transfers_full_amount.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_with_zero_fee_bps_transfers_full_amount.1.json @@ -2768,4 +2768,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_pay_per_use_zero_amount.1.json b/contract/test_snapshots/test/test_pay_per_use_zero_amount.1.json index 5e84938b..f8a7631b 100644 --- a/contract/test_snapshots/test/test_pay_per_use_zero_amount.1.json +++ b/contract/test_snapshots/test/test_pay_per_use_zero_amount.1.json @@ -1769,4 +1769,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_referral_cleared_on_cancel.1.json b/contract/test_snapshots/test/test_referral_cleared_on_cancel.1.json index 68903f1a..2cb9bf23 100644 --- a/contract/test_snapshots/test/test_referral_cleared_on_cancel.1.json +++ b/contract/test_snapshots/test/test_referral_cleared_on_cancel.1.json @@ -1838,4 +1838,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_referral_clears_on_resubscribe_with_none.1.json b/contract/test_snapshots/test/test_referral_clears_on_resubscribe_with_none.1.json index ee6404e6..3692476c 100644 --- a/contract/test_snapshots/test/test_referral_clears_on_resubscribe_with_none.1.json +++ b/contract/test_snapshots/test/test_referral_clears_on_resubscribe_with_none.1.json @@ -1960,4 +1960,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_referral_stored_on_subscribe.1.json b/contract/test_snapshots/test/test_referral_stored_on_subscribe.1.json index 9be250b5..d437ad8d 100644 --- a/contract/test_snapshots/test/test_referral_stored_on_subscribe.1.json +++ b/contract/test_snapshots/test/test_referral_stored_on_subscribe.1.json @@ -1704,4 +1704,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_referral_updates_on_resubscribe.1.json b/contract/test_snapshots/test/test_referral_updates_on_resubscribe.1.json index 7f2fe533..be7c8341 100644 --- a/contract/test_snapshots/test/test_referral_updates_on_resubscribe.1.json +++ b/contract/test_snapshots/test/test_referral_updates_on_resubscribe.1.json @@ -2036,4 +2036,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_remove_daily_limit_allows_pay_per_use_after_removal.1.json b/contract/test_snapshots/test/test_remove_daily_limit_allows_pay_per_use_after_removal.1.json index f1bd91b0..62dff396 100644 --- a/contract/test_snapshots/test/test_remove_daily_limit_allows_pay_per_use_after_removal.1.json +++ b/contract/test_snapshots/test/test_remove_daily_limit_allows_pay_per_use_after_removal.1.json @@ -2812,4 +2812,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_resubscribe.1.json b/contract/test_snapshots/test/test_resubscribe.1.json index d449a57f..ecab1adb 100644 --- a/contract/test_snapshots/test/test_resubscribe.1.json +++ b/contract/test_snapshots/test/test_resubscribe.1.json @@ -2234,4 +2234,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_resubscribe_active_does_not_duplicate_index.1.json b/contract/test_snapshots/test/test_resubscribe_active_does_not_duplicate_index.1.json index 0cf8ef5f..739971c2 100644 --- a/contract/test_snapshots/test/test_resubscribe_active_does_not_duplicate_index.1.json +++ b/contract/test_snapshots/test/test_resubscribe_active_does_not_duplicate_index.1.json @@ -1992,4 +1992,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_resubscribe_zero_allowance_panics.1.json b/contract/test_snapshots/test/test_resubscribe_zero_allowance_panics.1.json index e8ef8140..86f288d9 100644 --- a/contract/test_snapshots/test/test_resubscribe_zero_allowance_panics.1.json +++ b/contract/test_snapshots/test/test_resubscribe_zero_allowance_panics.1.json @@ -1080,4 +1080,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_resume_clears_pause_expiry.1.json b/contract/test_snapshots/test/test_resume_clears_pause_expiry.1.json index 72fe9e8e..87c19620 100644 --- a/contract/test_snapshots/test/test_resume_clears_pause_expiry.1.json +++ b/contract/test_snapshots/test/test_resume_clears_pause_expiry.1.json @@ -1928,4 +1928,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_resume_unpauses_and_charge_succeeds.1.json b/contract/test_snapshots/test/test_resume_unpauses_and_charge_succeeds.1.json index 8a275009..25167d85 100644 --- a/contract/test_snapshots/test/test_resume_unpauses_and_charge_succeeds.1.json +++ b/contract/test_snapshots/test/test_resume_unpauses_and_charge_succeeds.1.json @@ -2533,4 +2533,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_self_referral_rejected_via_try_subscribe.1.json b/contract/test_snapshots/test/test_self_referral_rejected_via_try_subscribe.1.json index 31f26602..ea78f469 100644 --- a/contract/test_snapshots/test/test_self_referral_rejected_via_try_subscribe.1.json +++ b/contract/test_snapshots/test/test_self_referral_rejected_via_try_subscribe.1.json @@ -1132,4 +1132,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_and_get_metadata.1.json b/contract/test_snapshots/test/test_set_and_get_metadata.1.json index 8e06e0e6..d1468663 100644 --- a/contract/test_snapshots/test/test_set_and_get_metadata.1.json +++ b/contract/test_snapshots/test/test_set_and_get_metadata.1.json @@ -1784,4 +1784,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_fee_emits_event.1.json b/contract/test_snapshots/test/test_set_fee_emits_event.1.json index 2c594985..056180d3 100644 --- a/contract/test_snapshots/test/test_set_fee_emits_event.1.json +++ b/contract/test_snapshots/test/test_set_fee_emits_event.1.json @@ -1176,4 +1176,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_fee_invalid_bps_panics.1.json b/contract/test_snapshots/test/test_set_fee_invalid_bps_panics.1.json index 12251d6e..0020cc3c 100644 --- a/contract/test_snapshots/test/test_set_fee_invalid_bps_panics.1.json +++ b/contract/test_snapshots/test/test_set_fee_invalid_bps_panics.1.json @@ -1079,4 +1079,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_grace_period_emits_event.1.json b/contract/test_snapshots/test/test_set_grace_period_emits_event.1.json index 4a84dc4e..f8abf9c8 100644 --- a/contract/test_snapshots/test/test_set_grace_period_emits_event.1.json +++ b/contract/test_snapshots/test/test_set_grace_period_emits_event.1.json @@ -1140,4 +1140,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_max_batch_size_rejects_value_above_200.1.json b/contract/test_snapshots/test/test_set_max_batch_size_rejects_value_above_200.1.json index 6292118f..09c6d15b 100644 --- a/contract/test_snapshots/test/test_set_max_batch_size_rejects_value_above_200.1.json +++ b/contract/test_snapshots/test/test_set_max_batch_size_rejects_value_above_200.1.json @@ -1069,4 +1069,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_metadata_label_at_limit_succeeds.1.json b/contract/test_snapshots/test/test_set_metadata_label_at_limit_succeeds.1.json index 865ca45d..a04d0339 100644 --- a/contract/test_snapshots/test/test_set_metadata_label_at_limit_succeeds.1.json +++ b/contract/test_snapshots/test/test_set_metadata_label_at_limit_succeeds.1.json @@ -1087,4 +1087,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_metadata_label_exceeding_limit_fails.1.json b/contract/test_snapshots/test/test_set_metadata_label_exceeding_limit_fails.1.json index 040257f1..7f8d81cd 100644 --- a/contract/test_snapshots/test/test_set_metadata_label_exceeding_limit_fails.1.json +++ b/contract/test_snapshots/test/test_set_metadata_label_exceeding_limit_fails.1.json @@ -1066,4 +1066,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_metadata_wrong_user_panics.1.json b/contract/test_snapshots/test/test_set_metadata_wrong_user_panics.1.json index e47f5ad0..8e86dbc9 100644 --- a/contract/test_snapshots/test/test_set_metadata_wrong_user_panics.1.json +++ b/contract/test_snapshots/test/test_set_metadata_wrong_user_panics.1.json @@ -1734,4 +1734,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_min_interval_non_admin_panics.1.json b/contract/test_snapshots/test/test_set_min_interval_non_admin_panics.1.json index 6b5054a7..3cad6ad9 100644 --- a/contract/test_snapshots/test/test_set_min_interval_non_admin_panics.1.json +++ b/contract/test_snapshots/test/test_set_min_interval_non_admin_panics.1.json @@ -1026,4 +1026,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_min_interval_zero_panics.1.json b/contract/test_snapshots/test/test_set_min_interval_zero_panics.1.json index 9bb5730b..971cbfd8 100644 --- a/contract/test_snapshots/test/test_set_min_interval_zero_panics.1.json +++ b/contract/test_snapshots/test/test_set_min_interval_zero_panics.1.json @@ -1086,4 +1086,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_subscription_amount_admin_succeeds.1.json b/contract/test_snapshots/test/test_set_subscription_amount_admin_succeeds.1.json index f81abebd..bc13c32b 100644 --- a/contract/test_snapshots/test/test_set_subscription_amount_admin_succeeds.1.json +++ b/contract/test_snapshots/test/test_set_subscription_amount_admin_succeeds.1.json @@ -2008,4 +2008,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_subscription_amount_no_subscription_panics.1.json b/contract/test_snapshots/test/test_set_subscription_amount_no_subscription_panics.1.json index e3d568c9..60d636ee 100644 --- a/contract/test_snapshots/test/test_set_subscription_amount_no_subscription_panics.1.json +++ b/contract/test_snapshots/test/test_set_subscription_amount_no_subscription_panics.1.json @@ -1085,4 +1085,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_subscription_amount_non_admin_panics.1.json b/contract/test_snapshots/test/test_set_subscription_amount_non_admin_panics.1.json index 8b18f673..32f6f9f2 100644 --- a/contract/test_snapshots/test/test_set_subscription_amount_non_admin_panics.1.json +++ b/contract/test_snapshots/test/test_set_subscription_amount_non_admin_panics.1.json @@ -1782,4 +1782,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_subscription_interval_admin_succeeds.1.json b/contract/test_snapshots/test/test_set_subscription_interval_admin_succeeds.1.json index 57a23f7b..78c5bcf4 100644 --- a/contract/test_snapshots/test/test_set_subscription_interval_admin_succeeds.1.json +++ b/contract/test_snapshots/test/test_set_subscription_interval_admin_succeeds.1.json @@ -2046,4 +2046,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_subscription_interval_no_subscription_panics.1.json b/contract/test_snapshots/test/test_set_subscription_interval_no_subscription_panics.1.json index bda32605..b5c3034e 100644 --- a/contract/test_snapshots/test/test_set_subscription_interval_no_subscription_panics.1.json +++ b/contract/test_snapshots/test/test_set_subscription_interval_no_subscription_panics.1.json @@ -1079,4 +1079,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_subscription_interval_non_admin_panics.1.json b/contract/test_snapshots/test/test_set_subscription_interval_non_admin_panics.1.json index 79503b7f..4ea0ee66 100644 --- a/contract/test_snapshots/test/test_set_subscription_interval_non_admin_panics.1.json +++ b/contract/test_snapshots/test/test_set_subscription_interval_non_admin_panics.1.json @@ -1776,4 +1776,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_subscription_interval_zero_panics.1.json b/contract/test_snapshots/test/test_set_subscription_interval_zero_panics.1.json index 7fe20f66..e220636b 100644 --- a/contract/test_snapshots/test/test_set_subscription_interval_zero_panics.1.json +++ b/contract/test_snapshots/test/test_set_subscription_interval_zero_panics.1.json @@ -1776,4 +1776,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_set_whitelist_enabled_false_allows_any_merchant.1.json b/contract/test_snapshots/test/test_set_whitelist_enabled_false_allows_any_merchant.1.json index 0c27781a..c221cfcf 100644 --- a/contract/test_snapshots/test/test_set_whitelist_enabled_false_allows_any_merchant.1.json +++ b/contract/test_snapshots/test/test_set_whitelist_enabled_false_allows_any_merchant.1.json @@ -1923,4 +1923,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_after_set_min_interval_lower_succeeds.1.json b/contract/test_snapshots/test/test_subscribe_after_set_min_interval_lower_succeeds.1.json index 33c2da01..b3118c50 100644 --- a/contract/test_snapshots/test/test_subscribe_after_set_min_interval_lower_succeeds.1.json +++ b/contract/test_snapshots/test/test_subscribe_after_set_min_interval_lower_succeeds.1.json @@ -1968,4 +1968,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_amount_above_cap_panics.1.json b/contract/test_snapshots/test/test_subscribe_amount_above_cap_panics.1.json index cff431d6..817aeadf 100644 --- a/contract/test_snapshots/test/test_subscribe_amount_above_cap_panics.1.json +++ b/contract/test_snapshots/test/test_subscribe_amount_above_cap_panics.1.json @@ -1407,4 +1407,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_amount_at_cap_succeeds.1.json b/contract/test_snapshots/test/test_subscribe_amount_at_cap_succeeds.1.json index 0f645ceb..1e337b59 100644 --- a/contract/test_snapshots/test/test_subscribe_amount_at_cap_succeeds.1.json +++ b/contract/test_snapshots/test/test_subscribe_amount_at_cap_succeeds.1.json @@ -2280,4 +2280,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_and_charge.1.json b/contract/test_snapshots/test/test_subscribe_and_charge.1.json index 789641a9..fe08c8ea 100644 --- a/contract/test_snapshots/test/test_subscribe_and_charge.1.json +++ b/contract/test_snapshots/test/test_subscribe_and_charge.1.json @@ -2425,4 +2425,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_exact_allowance_succeeds.1.json b/contract/test_snapshots/test/test_subscribe_exact_allowance_succeeds.1.json index e3e63060..27b705af 100644 --- a/contract/test_snapshots/test/test_subscribe_exact_allowance_succeeds.1.json +++ b/contract/test_snapshots/test/test_subscribe_exact_allowance_succeeds.1.json @@ -1080,4 +1080,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_extends_instance_ttl.1.json b/contract/test_snapshots/test/test_subscribe_extends_instance_ttl.1.json index 41efee9f..b471ebda 100644 --- a/contract/test_snapshots/test/test_subscribe_extends_instance_ttl.1.json +++ b/contract/test_snapshots/test/test_subscribe_extends_instance_ttl.1.json @@ -1581,4 +1581,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_interval_minimum_succeeds.1.json b/contract/test_snapshots/test/test_subscribe_interval_minimum_succeeds.1.json index fbd60a24..216a633a 100644 --- a/contract/test_snapshots/test/test_subscribe_interval_minimum_succeeds.1.json +++ b/contract/test_snapshots/test/test_subscribe_interval_minimum_succeeds.1.json @@ -1993,4 +1993,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_interval_too_short_panics_default_floor.1.json b/contract/test_snapshots/test/test_subscribe_interval_too_short_panics_default_floor.1.json index d5f31dca..a0e0f64c 100644 --- a/contract/test_snapshots/test/test_subscribe_interval_too_short_panics_default_floor.1.json +++ b/contract/test_snapshots/test/test_subscribe_interval_too_short_panics_default_floor.1.json @@ -1094,4 +1094,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_interval_under_60_panics.1.json b/contract/test_snapshots/test/test_subscribe_interval_under_60_panics.1.json index e129ec78..14e54e45 100644 --- a/contract/test_snapshots/test/test_subscribe_interval_under_60_panics.1.json +++ b/contract/test_snapshots/test/test_subscribe_interval_under_60_panics.1.json @@ -1094,4 +1094,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_non_contract_address.1.json b/contract/test_snapshots/test/test_subscribe_non_contract_address.1.json index 95afe620..9010db2b 100644 --- a/contract/test_snapshots/test/test_subscribe_non_contract_address.1.json +++ b/contract/test_snapshots/test/test_subscribe_non_contract_address.1.json @@ -1094,4 +1094,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_non_whitelisted_merchant_panics.1.json b/contract/test_snapshots/test/test_subscribe_non_whitelisted_merchant_panics.1.json index 2e367781..70bf51b2 100644 --- a/contract/test_snapshots/test/test_subscribe_non_whitelisted_merchant_panics.1.json +++ b/contract/test_snapshots/test/test_subscribe_non_whitelisted_merchant_panics.1.json @@ -1206,4 +1206,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_overwrites_cancelled_subscription.1.json b/contract/test_snapshots/test/test_subscribe_overwrites_cancelled_subscription.1.json index f836f59c..a732c584 100644 --- a/contract/test_snapshots/test/test_subscribe_overwrites_cancelled_subscription.1.json +++ b/contract/test_snapshots/test/test_subscribe_overwrites_cancelled_subscription.1.json @@ -2320,4 +2320,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_to_frozen_merchant_panics.1.json b/contract/test_snapshots/test/test_subscribe_to_frozen_merchant_panics.1.json index cfd0ef13..bc8d1fc8 100644 --- a/contract/test_snapshots/test/test_subscribe_to_frozen_merchant_panics.1.json +++ b/contract/test_snapshots/test/test_subscribe_to_frozen_merchant_panics.1.json @@ -1407,4 +1407,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_valid_sac_token_address_succeeds.1.json b/contract/test_snapshots/test/test_subscribe_valid_sac_token_address_succeeds.1.json index 35c4a00a..f8387ba1 100644 --- a/contract/test_snapshots/test/test_subscribe_valid_sac_token_address_succeeds.1.json +++ b/contract/test_snapshots/test/test_subscribe_valid_sac_token_address_succeeds.1.json @@ -1712,4 +1712,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_whitelisted_merchant_succeeds.1.json b/contract/test_snapshots/test/test_subscribe_whitelisted_merchant_succeeds.1.json index 9af522d8..cb130613 100644 --- a/contract/test_snapshots/test/test_subscribe_whitelisted_merchant_succeeds.1.json +++ b/contract/test_snapshots/test/test_subscribe_whitelisted_merchant_succeeds.1.json @@ -2123,4 +2123,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_with_metadata_label_too_long.1.json b/contract/test_snapshots/test/test_subscribe_with_metadata_label_too_long.1.json index 9d6b9015..8a812900 100644 --- a/contract/test_snapshots/test/test_subscribe_with_metadata_label_too_long.1.json +++ b/contract/test_snapshots/test/test_subscribe_with_metadata_label_too_long.1.json @@ -1100,4 +1100,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_with_metadata_no_subscription_on_label_failure.1.json b/contract/test_snapshots/test/test_subscribe_with_metadata_no_subscription_on_label_failure.1.json index 9d6b9015..8a812900 100644 --- a/contract/test_snapshots/test/test_subscribe_with_metadata_no_subscription_on_label_failure.1.json +++ b/contract/test_snapshots/test/test_subscribe_with_metadata_no_subscription_on_label_failure.1.json @@ -1100,4 +1100,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_with_metadata_success.1.json b/contract/test_snapshots/test/test_subscribe_with_metadata_success.1.json index b3c0c853..9ba3b9e6 100644 --- a/contract/test_snapshots/test/test_subscribe_with_metadata_success.1.json +++ b/contract/test_snapshots/test/test_subscribe_with_metadata_success.1.json @@ -1813,4 +1813,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_zero_allowance_does_not_write_storage.1.json b/contract/test_snapshots/test/test_subscribe_zero_allowance_does_not_write_storage.1.json index 4f1539ac..4b33db8b 100644 --- a/contract/test_snapshots/test/test_subscribe_zero_allowance_does_not_write_storage.1.json +++ b/contract/test_snapshots/test/test_subscribe_zero_allowance_does_not_write_storage.1.json @@ -432,4 +432,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscribe_zero_allowance_panics.1.json b/contract/test_snapshots/test/test_subscribe_zero_allowance_panics.1.json index 14a76aed..fde93186 100644 --- a/contract/test_snapshots/test/test_subscribe_zero_allowance_panics.1.json +++ b/contract/test_snapshots/test/test_subscribe_zero_allowance_panics.1.json @@ -815,4 +815,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscriber_index_three_unique_users.1.json b/contract/test_snapshots/test/test_subscriber_index_three_unique_users.1.json index a939b90d..a3883dc6 100644 --- a/contract/test_snapshots/test/test_subscriber_index_three_unique_users.1.json +++ b/contract/test_snapshots/test/test_subscriber_index_three_unique_users.1.json @@ -3609,4 +3609,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscriber_page_limit_capped_at_50.1.json b/contract/test_snapshots/test/test_subscriber_page_limit_capped_at_50.1.json index a9be5f8b..973ec015 100644 --- a/contract/test_snapshots/test/test_subscriber_page_limit_capped_at_50.1.json +++ b/contract/test_snapshots/test/test_subscriber_page_limit_capped_at_50.1.json @@ -49073,4 +49073,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscriber_page_offset_beyond_count_returns_empty.1.json b/contract/test_snapshots/test/test_subscriber_page_offset_beyond_count_returns_empty.1.json index a9accdc0..21762f90 100644 --- a/contract/test_snapshots/test/test_subscriber_page_offset_beyond_count_returns_empty.1.json +++ b/contract/test_snapshots/test/test_subscriber_page_offset_beyond_count_returns_empty.1.json @@ -1742,4 +1742,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_subscription_struct_fields_match_input.1.json b/contract/test_snapshots/test/test_subscription_struct_fields_match_input.1.json index 1fc4ca5b..cb97c032 100644 --- a/contract/test_snapshots/test/test_subscription_struct_fields_match_input.1.json +++ b/contract/test_snapshots/test/test_subscription_struct_fields_match_input.1.json @@ -1712,4 +1712,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_transfer_admin.1.json b/contract/test_snapshots/test/test_transfer_admin.1.json index 70410d5c..921dfc29 100644 --- a/contract/test_snapshots/test/test_transfer_admin.1.json +++ b/contract/test_snapshots/test/test_transfer_admin.1.json @@ -1116,4 +1116,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_transfer_admin_event_emitted.1.json b/contract/test_snapshots/test/test_transfer_admin_event_emitted.1.json index 1c896f13..94f7e6bc 100644 --- a/contract/test_snapshots/test/test_transfer_admin_event_emitted.1.json +++ b/contract/test_snapshots/test/test_transfer_admin_event_emitted.1.json @@ -1115,4 +1115,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_transfer_admin_requires_auth.1.json b/contract/test_snapshots/test/test_transfer_admin_requires_auth.1.json index 70410d5c..921dfc29 100644 --- a/contract/test_snapshots/test/test_transfer_admin_requires_auth.1.json +++ b/contract/test_snapshots/test/test_transfer_admin_requires_auth.1.json @@ -1116,4 +1116,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_transfer_subscription_succeeds.1.json b/contract/test_snapshots/test/test_transfer_subscription_succeeds.1.json index 25dde8a5..7b921c15 100644 --- a/contract/test_snapshots/test/test_transfer_subscription_succeeds.1.json +++ b/contract/test_snapshots/test/test_transfer_subscription_succeeds.1.json @@ -2472,4 +2472,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_transfer_subscription_to_active_user_panics.1.json b/contract/test_snapshots/test/test_transfer_subscription_to_active_user_panics.1.json index 0e535dcd..565313c9 100644 --- a/contract/test_snapshots/test/test_transfer_subscription_to_active_user_panics.1.json +++ b/contract/test_snapshots/test/test_transfer_subscription_to_active_user_panics.1.json @@ -2720,4 +2720,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_ttl_extension.1.json b/contract/test_snapshots/test/test_ttl_extension.1.json index 9184641e..373de0ab 100644 --- a/contract/test_snapshots/test/test_ttl_extension.1.json +++ b/contract/test_snapshots/test/test_ttl_extension.1.json @@ -1761,4 +1761,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_unfreeze_merchant_non_admin_panics.1.json b/contract/test_snapshots/test/test_unfreeze_merchant_non_admin_panics.1.json index d0192576..694c18fd 100644 --- a/contract/test_snapshots/test/test_unfreeze_merchant_non_admin_panics.1.json +++ b/contract/test_snapshots/test/test_unfreeze_merchant_non_admin_panics.1.json @@ -1026,4 +1026,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_unfreeze_merchant_non_frozen_is_noop.1.json b/contract/test_snapshots/test/test_unfreeze_merchant_non_frozen_is_noop.1.json index e83fc2d8..be8554f8 100644 --- a/contract/test_snapshots/test/test_unfreeze_merchant_non_frozen_is_noop.1.json +++ b/contract/test_snapshots/test/test_unfreeze_merchant_non_frozen_is_noop.1.json @@ -1066,4 +1066,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_upgrade_event_emitted.1.json b/contract/test_snapshots/test/test_upgrade_event_emitted.1.json index 02f3d300..c0afb89c 100644 --- a/contract/test_snapshots/test/test_upgrade_event_emitted.1.json +++ b/contract/test_snapshots/test/test_upgrade_event_emitted.1.json @@ -3,9 +3,7 @@ "address": 1, "nonce": 0 }, - "auth": [ - [] - ], + "auth": [[]], "ledger": { "protocol_version": 21, "sequence_number": 0, @@ -91,4 +89,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_upgrade_event_emitted.2.json b/contract/test_snapshots/test/test_upgrade_event_emitted.2.json index 2dfb72e6..b85787a0 100644 --- a/contract/test_snapshots/test/test_upgrade_event_emitted.2.json +++ b/contract/test_snapshots/test/test_upgrade_event_emitted.2.json @@ -1082,4 +1082,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_user_can_switch_token.1.json b/contract/test_snapshots/test/test_user_can_switch_token.1.json index f5e34c9d..ce5e94a3 100644 --- a/contract/test_snapshots/test/test_user_can_switch_token.1.json +++ b/contract/test_snapshots/test/test_user_can_switch_token.1.json @@ -2764,4 +2764,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_whitelist_batch_add_duplicates_does_not_panic.1.json b/contract/test_snapshots/test/test_whitelist_batch_add_duplicates_does_not_panic.1.json index 1ab68c98..b3790370 100644 --- a/contract/test_snapshots/test/test_whitelist_batch_add_duplicates_does_not_panic.1.json +++ b/contract/test_snapshots/test/test_whitelist_batch_add_duplicates_does_not_panic.1.json @@ -1340,4 +1340,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_whitelist_batch_add_exceeds_max_size_panics.1.json b/contract/test_snapshots/test/test_whitelist_batch_add_exceeds_max_size_panics.1.json index 6028d162..def89e05 100644 --- a/contract/test_snapshots/test/test_whitelist_batch_add_exceeds_max_size_panics.1.json +++ b/contract/test_snapshots/test/test_whitelist_batch_add_exceeds_max_size_panics.1.json @@ -1377,4 +1377,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_whitelist_batch_add_non_admin_panics.1.json b/contract/test_snapshots/test/test_whitelist_batch_add_non_admin_panics.1.json index a34772e4..47dedddc 100644 --- a/contract/test_snapshots/test/test_whitelist_batch_add_non_admin_panics.1.json +++ b/contract/test_snapshots/test/test_whitelist_batch_add_non_admin_panics.1.json @@ -1077,4 +1077,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_whitelist_batch_add_three_merchants.1.json b/contract/test_snapshots/test/test_whitelist_batch_add_three_merchants.1.json index 1a6bcb9e..abc94b3a 100644 --- a/contract/test_snapshots/test/test_whitelist_batch_add_three_merchants.1.json +++ b/contract/test_snapshots/test/test_whitelist_batch_add_three_merchants.1.json @@ -1848,4 +1848,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_whitelist_batch_remove_non_whitelisted_is_noop.1.json b/contract/test_snapshots/test/test_whitelist_batch_remove_non_whitelisted_is_noop.1.json index 636a590a..12b52bf3 100644 --- a/contract/test_snapshots/test/test_whitelist_batch_remove_non_whitelisted_is_noop.1.json +++ b/contract/test_snapshots/test/test_whitelist_batch_remove_non_whitelisted_is_noop.1.json @@ -1055,4 +1055,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_whitelist_batch_remove_two_merchants.1.json b/contract/test_snapshots/test/test_whitelist_batch_remove_two_merchants.1.json index 82b7aaa6..f4f14e1e 100644 --- a/contract/test_snapshots/test/test_whitelist_batch_remove_two_merchants.1.json +++ b/contract/test_snapshots/test/test_whitelist_batch_remove_two_merchants.1.json @@ -1651,4 +1651,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_withdraw_merchant_revenue_succeeds.1.json b/contract/test_snapshots/test/test_withdraw_merchant_revenue_succeeds.1.json index b9d7c260..24b23b06 100644 --- a/contract/test_snapshots/test/test_withdraw_merchant_revenue_succeeds.1.json +++ b/contract/test_snapshots/test/test_withdraw_merchant_revenue_succeeds.1.json @@ -2944,4 +2944,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_withdraw_merchant_revenue_zero_balance_panics.1.json b/contract/test_snapshots/test/test_withdraw_merchant_revenue_zero_balance_panics.1.json index ecb5315c..401e8a29 100644 --- a/contract/test_snapshots/test/test_withdraw_merchant_revenue_zero_balance_panics.1.json +++ b/contract/test_snapshots/test/test_withdraw_merchant_revenue_zero_balance_panics.1.json @@ -1190,4 +1190,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_zero_amount.1.json b/contract/test_snapshots/test/test_zero_amount.1.json index 565ac69f..254f9a10 100644 --- a/contract/test_snapshots/test/test_zero_amount.1.json +++ b/contract/test_snapshots/test/test_zero_amount.1.json @@ -1094,4 +1094,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/contract/test_snapshots/test/test_zero_interval.1.json b/contract/test_snapshots/test/test_zero_interval.1.json index e129ec78..14e54e45 100644 --- a/contract/test_snapshots/test/test_zero_interval.1.json +++ b/contract/test_snapshots/test/test_zero_interval.1.json @@ -1094,4 +1094,4 @@ "failed_call": false } ] -} \ No newline at end of file +} diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index ce538de1..859ff497 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -32,31 +32,31 @@ graph TD ## Contract Modules -| Module | Responsibility | -| --- | --- | -| `lib.rs` | Public entry points, contract data types, storage keys, and cross-module orchestration. | -| `admin.rs` | Admin initialization, auth checks, and two-step admin transfer. | -| `batch.rs` | `batch_charge()` processing and per-user result reporting. | -| `bench.rs` | Benchmark-only instruction counting for core flows. | -| `charge_exec.rs` | Charge scheduling helpers and charge execution internals. | -| `errors.rs` | Contract error codes. | -| `events.rs` | All event emission helpers. | -| `fee.rs` | Protocol fee proposal, commit, and fee calculation logic. | -| `grace.rs` | Grace-period proposal, commit, and lookup helpers. | -| `merchant_stats.rs` | Merchant revenue, subscriber counts, and daily revenue buckets. | -| `migration.rs` | Schema version tracking and storage migration. | -| `min_interval.rs` | Minimum billing interval floor. | -| `referral.rs` | Referral storage and lookup. See [REFERRALS.md](./REFERRALS.md). | -| `spending_limit.rs` | Temporary daily spending limits for `pay_per_use()`. | -| `storage.rs` | Shared storage read/write helpers. | -| `subscription_count.rs` | Active subscription count and append-only subscriber index. | -| `subscription_history.rs` | Charge history recording and paging. | -| `subscription_metadata.rs` | Short subscription labels. | -| `test.rs` | Contract unit tests. | -| `trial.rs` | Trial end computation and trial helpers. | -| `upgrade.rs` | WASM upgrade wrapper and upgrade event emission. | -| `validation.rs` | Shared validation helpers for amounts, intervals, and allowance checks. | -| `whitelist.rs` | Merchant whitelist and freeze state helpers. | +| Module | Responsibility | +| -------------------------- | --------------------------------------------------------------------------------------- | +| `lib.rs` | Public entry points, contract data types, storage keys, and cross-module orchestration. | +| `admin.rs` | Admin initialization, auth checks, and two-step admin transfer. | +| `batch.rs` | `batch_charge()` processing and per-user result reporting. | +| `bench.rs` | Benchmark-only instruction counting for core flows. | +| `charge_exec.rs` | Charge scheduling helpers and charge execution internals. | +| `errors.rs` | Contract error codes. | +| `events.rs` | All event emission helpers. | +| `fee.rs` | Protocol fee proposal, commit, and fee calculation logic. | +| `grace.rs` | Grace-period proposal, commit, and lookup helpers. | +| `merchant_stats.rs` | Merchant revenue, subscriber counts, and daily revenue buckets. | +| `migration.rs` | Schema version tracking and storage migration. | +| `min_interval.rs` | Minimum billing interval floor. | +| `referral.rs` | Referral storage and lookup. See [REFERRALS.md](./REFERRALS.md). | +| `spending_limit.rs` | Temporary daily spending limits for `pay_per_use()`. | +| `storage.rs` | Shared storage read/write helpers. | +| `subscription_count.rs` | Active subscription count and append-only subscriber index. | +| `subscription_history.rs` | Charge history recording and paging. | +| `subscription_metadata.rs` | Short subscription labels. | +| `test.rs` | Contract unit tests. | +| `trial.rs` | Trial end computation and trial helpers. | +| `upgrade.rs` | WASM upgrade wrapper and upgrade event emission. | +| `validation.rs` | Shared validation helpers for amounts, intervals, and allowance checks. | +| `whitelist.rs` | Merchant whitelist and freeze state helpers. | --- @@ -104,35 +104,35 @@ graph TD FlowPay uses Soroban instance, persistent, and temporary storage deliberately. -| DataKey | Purpose | Storage type | -| --- | --- | --- | -| `Token` | Default payment token | instance | -| `Admin` | Current admin | instance | -| `PendingAdmin` | Two-step admin transfer target | instance | -| `ContractPaused` | Global pause flag | instance | -| `GracePeriod` | Charge grace window | instance | -| `WhitelistEnabled` | Merchant whitelist flag | instance | -| `FeeCollector` / `FeeBps` | Protocol fee configuration | instance | -| `PendingFee` | Pending fee proposal | temporary | -| `PendingGracePeriod` | Pending grace-period proposal | temporary | -| `MinInterval` | Minimum allowed subscription interval | instance | -| `SchemaVersion` | Storage schema version | instance | -| `ActiveCount` | Active subscription count | instance | -| `SubscriberIndexSize` | Append-only subscriber count | instance | -| `Subscription(user)` | Subscriber subscription record | persistent | -| `MerchantWhitelist(merchant)` | Whitelisted merchant flag | persistent | -| `MerchantFrozen(merchant)` | Frozen merchant flag | persistent | -| `MerchantRevenue(merchant)` | Cumulative merchant revenue | persistent | -| `MerchantRevenueDay(merchant, day)` | Daily revenue bucket | persistent | -| `MerchantRevenueHistory(merchant)` | History vector for revenue reads | persistent | -| `MerchantSubCount(merchant)` | Active subscriber count per merchant | persistent | -| `DailyLimit(user)` | Temporary pay-per-use limit | temporary | -| `DailySpent(user)` | Temporary pay-per-use spend counter | temporary | -| `Referral(user)` | Referrer for a subscriber ([REFERRALS.md](./REFERRALS.md)) | persistent | -| `SubscriptionMeta(user)` | Short subscription label | persistent | -| `ChargeHistory(user)` | Charge timestamps | persistent | -| `SubscriberIndex(i)` | Append-only subscriber list entry | persistent | -| `GlobalVolumeWindow` | Rolling volume cap state | instance | +| DataKey | Purpose | Storage type | +| ----------------------------------- | ---------------------------------------------------------- | ------------ | +| `Token` | Default payment token | instance | +| `Admin` | Current admin | instance | +| `PendingAdmin` | Two-step admin transfer target | instance | +| `ContractPaused` | Global pause flag | instance | +| `GracePeriod` | Charge grace window | instance | +| `WhitelistEnabled` | Merchant whitelist flag | instance | +| `FeeCollector` / `FeeBps` | Protocol fee configuration | instance | +| `PendingFee` | Pending fee proposal | temporary | +| `PendingGracePeriod` | Pending grace-period proposal | temporary | +| `MinInterval` | Minimum allowed subscription interval | instance | +| `SchemaVersion` | Storage schema version | instance | +| `ActiveCount` | Active subscription count | instance | +| `SubscriberIndexSize` | Append-only subscriber count | instance | +| `Subscription(user)` | Subscriber subscription record | persistent | +| `MerchantWhitelist(merchant)` | Whitelisted merchant flag | persistent | +| `MerchantFrozen(merchant)` | Frozen merchant flag | persistent | +| `MerchantRevenue(merchant)` | Cumulative merchant revenue | persistent | +| `MerchantRevenueDay(merchant, day)` | Daily revenue bucket | persistent | +| `MerchantRevenueHistory(merchant)` | History vector for revenue reads | persistent | +| `MerchantSubCount(merchant)` | Active subscriber count per merchant | persistent | +| `DailyLimit(user)` | Temporary pay-per-use limit | temporary | +| `DailySpent(user)` | Temporary pay-per-use spend counter | temporary | +| `Referral(user)` | Referrer for a subscriber ([REFERRALS.md](./REFERRALS.md)) | persistent | +| `SubscriptionMeta(user)` | Short subscription label | persistent | +| `ChargeHistory(user)` | Charge timestamps | persistent | +| `SubscriberIndex(i)` | Append-only subscriber list entry | persistent | +| `GlobalVolumeWindow` | Rolling volume cap state | instance | Persistent entries that must remain available are refreshed with TTL extensions where needed, most importantly subscription records and selected merchant-revenue data. Temporary entries are used for short-lived proposals and daily spending caps. @@ -145,24 +145,24 @@ Each `Subscription(user)` record carries its own `token` address rather than sha Events are emitted from `events.rs` and kept separate from storage mutation so the public contract methods remain small. -| Event | Trigger | -| --- | --- | -| `subscribed` | New or replaced subscription created | -| `referred` | Referrer stored on subscribe ([REFERRALS.md](./REFERRALS.md)) | -| `charged` | Successful recurring charge | -| `pay_per_use` | Successful one-time charge | -| `cancelled` | Subscription cancelled | -| `paused` / `resumed` | Subscription pause state changed | -| `admin_transferred` | Two-step admin transfer completed | -| `fee_proposed` / `fee_committed` | Fee configuration changed | -| `merchant_added` / `merchant_removed` | Whitelist updated | -| `merchant_frozen` / `merchant_unfrozen` | Merchant freeze state changed | -| `grace_period_proposed` / `grace_period_committed` | Grace period updated | -| `subscription_amount_updated` / `subscription_interval_updated` | Admin adjusted a subscription | -| `merchant_withdrawal` | Merchant withdrew revenue | -| `daily_limit_set` / `daily_limit_removed` | Daily limit updated | -| `subscription_transferred` | Subscription ownership moved | -| `upgraded` | Contract WASM upgraded | +| Event | Trigger | +| --------------------------------------------------------------- | ------------------------------------------------------------- | +| `subscribed` | New or replaced subscription created | +| `referred` | Referrer stored on subscribe ([REFERRALS.md](./REFERRALS.md)) | +| `charged` | Successful recurring charge | +| `pay_per_use` | Successful one-time charge | +| `cancelled` | Subscription cancelled | +| `paused` / `resumed` | Subscription pause state changed | +| `admin_transferred` | Two-step admin transfer completed | +| `fee_proposed` / `fee_committed` | Fee configuration changed | +| `merchant_added` / `merchant_removed` | Whitelist updated | +| `merchant_frozen` / `merchant_unfrozen` | Merchant freeze state changed | +| `grace_period_proposed` / `grace_period_committed` | Grace period updated | +| `subscription_amount_updated` / `subscription_interval_updated` | Admin adjusted a subscription | +| `merchant_withdrawal` | Merchant withdrew revenue | +| `daily_limit_set` / `daily_limit_removed` | Daily limit updated | +| `subscription_transferred` | Subscription ownership moved | +| `upgraded` | Contract WASM upgraded | Events are the main off-chain integration surface for analytics, indexers, and the keeper workflow. diff --git a/docs/COMPLIANCE.md b/docs/COMPLIANCE.md index dc70e796..adf7a16c 100644 --- a/docs/COMPLIANCE.md +++ b/docs/COMPLIANCE.md @@ -22,22 +22,22 @@ That means: ## What’s on-chain vs ephemeral -### Durable enough for audit *if you retain it* +### Durable enough for audit _if you retain it_ -| Artifact | Where it lives | What finance can use it for | -| --- | --- | --- | -| Contract events (`charged`, `subscribed`, `cancelled`, …) | Stellar ledger history | Complete billing journal: who paid whom, when, gross/fee/net | -| `Subscription` record | Persistent contract storage | Current terms: merchant, amount, interval, pause/active flags | -| Merchant revenue counters / day buckets / history | Persistent storage | Cumulative and daily revenue snapshots | -| Charge history timestamps | Persistent storage | Recent charge *times* only (see limits below) | -| Whitelist / freeze / referral / metadata | Persistent storage | Merchant directory and labels — not full payment proof | +| Artifact | Where it lives | What finance can use it for | +| --------------------------------------------------------- | --------------------------- | ------------------------------------------------------------- | +| Contract events (`charged`, `subscribed`, `cancelled`, …) | Stellar ledger history | Complete billing journal: who paid whom, when, gross/fee/net | +| `Subscription` record | Persistent contract storage | Current terms: merchant, amount, interval, pause/active flags | +| Merchant revenue counters / day buckets / history | Persistent storage | Cumulative and daily revenue snapshots | +| Charge history timestamps | Persistent storage | Recent charge _times_ only (see limits below) | +| Whitelist / freeze / referral / metadata | Persistent storage | Merchant directory and labels — not full payment proof | ### Ephemeral — do **not** treat as long-term evidence -| Artifact | Storage tier | Behavior | -| --- | --- | --- | -| Daily spend limit / daily spent / day-start markers | Temporary | Expire after ~24 hours (`17,280` ledgers). Permanently deleted; not restorable. | -| Pending fee / grace / upgrade proposals | Temporary | Short-lived propose → commit state (~1 day TTL). | +| Artifact | Storage tier | Behavior | +| --------------------------------------------------- | ------------ | ------------------------------------------------------------------------------- | +| Daily spend limit / daily spent / day-start markers | Temporary | Expire after ~24 hours (`17,280` ledgers). Permanently deleted; not restorable. | +| Pending fee / grace / upgrade proposals | Temporary | Short-lived propose → commit state (~1 day TTL). | See [architecture/storage_and_ttl.md](./architecture/storage_and_ttl.md) for storage tiers and TTL policy, and [ARCHITECTURE.md](./ARCHITECTURE.md#storage-strategy) for the high-level map. @@ -54,11 +54,11 @@ See [architecture/storage_and_ttl.md](./architecture/storage_and_ttl.md) for sto 1. Node.js 18+ and dependencies under `scripts/` (`cd scripts && npm install`). 2. Environment (Testnet defaults shown): -| Variable | Purpose | -| --- | --- | -| `VITE_CONTRACT_ID` or `CONTRACT_ID` | FlowPay contract ID | -| `VITE_RPC_URL` / `RPC_URL` | Soroban RPC endpoint | -| `VITE_NETWORK_PASSPHRASE` | Network passphrase (defaults to Testnet) | +| Variable | Purpose | +| ----------------------------------- | ---------------------------------------- | +| `VITE_CONTRACT_ID` or `CONTRACT_ID` | FlowPay contract ID | +| `VITE_RPC_URL` / `RPC_URL` | Soroban RPC endpoint | +| `VITE_NETWORK_PASSPHRASE` | Network passphrase (defaults to Testnet) | 3. Your merchant Stellar address (`G…`). 4. Optionally, an indexer database if you run continuous event ingestion (required for day-summary and churn scripts). @@ -115,7 +115,7 @@ CONTRACT_ID=C... node --experimental-require-module scripts/subscription-snapsho --addresses GABC...,GXYZ... --out snapshot.json ``` -Useful for proving *current* terms, not historical charges. +Useful for proving _current_ terms, not historical charges. ### Step 4 — Cross-check recent charge timestamps on-chain @@ -182,11 +182,11 @@ Full event schemas: [EVENTS.md](./EVENTS.md). Indexing patterns: [EVENT-DRIVEN-G If you already persist events to SQLite: -| Script | Purpose | -| --- | --- | -| `scripts/daily-revenue-summary.ts` | UTC-day charge / fee / subscription totals | -| `scripts/fee-revenue-report.ts` | Protocol fee totals from `charged.fee` | -| `scripts/subscriber-churn-report.ts` | Cancellation / churn rates | +| Script | Purpose | +| ------------------------------------ | ------------------------------------------ | +| `scripts/daily-revenue-summary.ts` | UTC-day charge / fee / subscription totals | +| `scripts/fee-revenue-report.ts` | Protocol fee totals from `charged.fee` | +| `scripts/subscriber-churn-report.ts` | Cancellation / churn rates | These do **not** replace a primary event archive; they summarize one. @@ -196,20 +196,20 @@ These do **not** replace a primary event archive; they summarize one. ### Billing events in finance language -| Event | Meaning for books | -| --- | --- | -| `subscribed` | Customer enrolled; recurring price (`amount`) and period (`interval` seconds) set | -| `charged` | Recurring invoice collected: **gross** charged to customer, **fee** to protocol, **net** to merchant, at `charged_at` | -| `pay_per_use` | One-off usage charge against an active subscription | -| `cancelled` / `cancelled_with_refund` | Subscription ended; no further recurring charges (refund amount only on the refund variant) | -| `paused` / `resumed` | Customer temporarily stopped / restarted billing | -| `sub_amount_updated` / `sub_interval_updated` | Price or billing period changed | -| `sub_transferred` | Subscription moved to another Stellar address | -| `merchant_withdrawal` | Merchant withdrew accrued protocol-tracked revenue (payout) | -| `daily_limit_set` / `daily_limit_removed` | Customer changed pay-per-use daily cap (control, not revenue) | -| `fee_proposed` / `fee_committed` | Protocol fee schedule change (policy audit) | -| `merchant_frozen` / `merchant_unfrozen` | Admin blocked / unblocked the merchant from new activity | -| `contract_paused` / `contract_unpaused` | Protocol-wide halt / resume | +| Event | Meaning for books | +| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| `subscribed` | Customer enrolled; recurring price (`amount`) and period (`interval` seconds) set | +| `charged` | Recurring invoice collected: **gross** charged to customer, **fee** to protocol, **net** to merchant, at `charged_at` | +| `pay_per_use` | One-off usage charge against an active subscription | +| `cancelled` / `cancelled_with_refund` | Subscription ended; no further recurring charges (refund amount only on the refund variant) | +| `paused` / `resumed` | Customer temporarily stopped / restarted billing | +| `sub_amount_updated` / `sub_interval_updated` | Price or billing period changed | +| `sub_transferred` | Subscription moved to another Stellar address | +| `merchant_withdrawal` | Merchant withdrew accrued protocol-tracked revenue (payout) | +| `daily_limit_set` / `daily_limit_removed` | Customer changed pay-per-use daily cap (control, not revenue) | +| `fee_proposed` / `fee_committed` | Protocol fee schedule change (policy audit) | +| `merchant_frozen` / `merchant_unfrozen` | Admin blocked / unblocked the merchant from new activity | +| `contract_paused` / `contract_unpaused` | Protocol-wide halt / resume | Amounts on `charged` are the structured source for revenue recognition splits (gross vs fee vs net). Prefer event payloads over reconstructing from token transfers alone. @@ -221,20 +221,20 @@ Amounts on `charged` are the structured source for revenue recognition splits (g 4. Expect **gross − fee = net**. Protocol fees go to the configured fee collector, not the merchant — do not book fee as merchant revenue. 5. Investigate gaps: missing events usually mean RPC retention lapsed without an indexer, or filters excluded the merchant. -Token transfers prove value movement; contract events prove *why* (subscription charge vs pay-per-use vs withdrawal). Keep both in the audit package when possible. +Token transfers prove value movement; contract events prove _why_ (subscription charge vs pay-per-use vs withdrawal). Keep both in the audit package when possible. --- ## Data retention -| Concern | Fact | Recommendation | -| --- | --- | --- | -| RPC event history | Short retention (~week order) | Run `watch-events` / indexer continuously; archive to your own storage | +| Concern | Fact | Recommendation | +| --------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| RPC event history | Short retention (~week order) | Run `watch-events` / indexer continuously; archive to your own storage | | Subscription / metadata TTL | Persistent keys target ~1 year (`6,307,200` ledgers) when bumped | Idle subscriptions may archive; call `extend_subscription_ttl` or restore if needed | -| Merchant revenue keys | Extended ~90 days on write in current code | Export reports regularly; do not rely on day buckets alone for multi-year books | -| Charge history storage | Max **12** timestamps; clearable by user | Never use as sole multi-year evidence | -| Temporary daily limits | Deleted after ~24h | Irrelevant for long-term audit | -| Admin clears | Admin can clear merchant revenue history / reset revenue | Treat admin actions as privileged; log them off-chain | +| Merchant revenue keys | Extended ~90 days on write in current code | Export reports regularly; do not rely on day buckets alone for multi-year books | +| Charge history storage | Max **12** timestamps; clearable by user | Never use as sole multi-year evidence | +| Temporary daily limits | Deleted after ~24h | Irrelevant for long-term audit | +| Admin clears | Admin can clear merchant revenue history / reset revenue | Treat admin actions as privileged; log them off-chain | **Retention recommendation:** Keep an off-chain append-only event store (and periodic merchant report exports) for as long as your accounting and tax rules require. The chain is the source of truth, but RPC nodes and temporary storage will not keep a multi-year merchant archive for you. @@ -244,15 +244,15 @@ Token transfers prove value movement; contract events prove *why* (subscription PayFlow / FlowPay does **not** provide: -| Expectation | Reality | -| --- | --- | -| KYC / identity verification | Addresses only — no identity documents or sanctions screening | -| Tax calculation or filing | No tax engine, jurisdiction rules, or Form exports | -| Legal dispute resolution | No on-chain arbitration for failed or disputed charges | -| Guaranteed charge timing | Recurring charges depend on an external [keeper](./GLOSSARY.md#keeper) calling `charge` / `batch_charge` | -| Complete on-chain invoice archive | Storage keeps only recent timestamps; full history requires indexed events | -| Production Mainnet assurance | Testnet deployment; no formal security audit yet ([SECURITY.md](./SECURITY.md)) | -| Custody or bank statements | Non-custodial protocol — bank-style statements are your responsibility off-chain | +| Expectation | Reality | +| --------------------------------- | -------------------------------------------------------------------------------------------------------- | +| KYC / identity verification | Addresses only — no identity documents or sanctions screening | +| Tax calculation or filing | No tax engine, jurisdiction rules, or Form exports | +| Legal dispute resolution | No on-chain arbitration for failed or disputed charges | +| Guaranteed charge timing | Recurring charges depend on an external [keeper](./GLOSSARY.md#keeper) calling `charge` / `batch_charge` | +| Complete on-chain invoice archive | Storage keeps only recent timestamps; full history requires indexed events | +| Production Mainnet assurance | Testnet deployment; no formal security audit yet ([SECURITY.md](./SECURITY.md)) | +| Custody or bank statements | Non-custodial protocol — bank-style statements are your responsibility off-chain | Broad admin powers (pause, freeze merchants, clear history, upgrade) exist. Treat admin key holders as highly trusted for any compliance narrative. @@ -260,12 +260,12 @@ Broad admin powers (pause, freeze merchants, clear history, upgrade) exist. Trea ## Related documentation -| Document | Topic | -| --- | --- | -| [SECURITY.md](./SECURITY.md) | Security model, auth table, known limitations, disclosure | -| [ARCHITECTURE.md](./ARCHITECTURE.md) | Modules, storage strategy, event architecture | -| [EVENTS.md](./EVENTS.md) | Full event payload reference | -| [EVENT-DRIVEN-GUIDE.md](./EVENT-DRIVEN-GUIDE.md) | Indexing, replay, RPC retention | -| [architecture/storage_and_ttl.md](./architecture/storage_and_ttl.md) | Storage tiers and TTL | -| [API.md](./API.md) | Charge and charge-history APIs | -| [GLOSSARY.md](./GLOSSARY.md) | Protocol terminology | +| Document | Topic | +| -------------------------------------------------------------------- | --------------------------------------------------------- | +| [SECURITY.md](./SECURITY.md) | Security model, auth table, known limitations, disclosure | +| [ARCHITECTURE.md](./ARCHITECTURE.md) | Modules, storage strategy, event architecture | +| [EVENTS.md](./EVENTS.md) | Full event payload reference | +| [EVENT-DRIVEN-GUIDE.md](./EVENT-DRIVEN-GUIDE.md) | Indexing, replay, RPC retention | +| [architecture/storage_and_ttl.md](./architecture/storage_and_ttl.md) | Storage tiers and TTL | +| [API.md](./API.md) | Charge and charge-history APIs | +| [GLOSSARY.md](./GLOSSARY.md) | Protocol terminology | diff --git a/docs/CONTRIBUTING-CONTRACT.md b/docs/CONTRIBUTING-CONTRACT.md index ebfe4f10..fb462521 100644 --- a/docs/CONTRIBUTING-CONTRACT.md +++ b/docs/CONTRIBUTING-CONTRACT.md @@ -51,6 +51,7 @@ contract/src/ ``` **Rules:** + - Business logic belongs in a focused module, not in `lib.rs`. - `lib.rs` only wires public contract functions to module helpers — no logic inline. - `bench.rs` and `test.rs` are gated with `#[cfg(test)]`. @@ -181,13 +182,13 @@ test_daily_limit_removed_event_emitted Every new public function needs at minimum: -| Test | What it verifies | -|------|-----------------| -| Happy path | Function succeeds under normal conditions | -| Precondition failure | Correct error when inputs are invalid | -| Auth enforcement | Panics when called without the required auth | -| State after | Storage reflects the expected change | -| Event emitted | The correct event was published (for state-changing functions) | +| Test | What it verifies | +| -------------------- | -------------------------------------------------------------- | +| Happy path | Function succeeds under normal conditions | +| Precondition failure | Correct error when inputs are invalid | +| Auth enforcement | Panics when called without the required auth | +| State after | Storage reflects the expected change | +| Event emitted | The correct event was published (for state-changing functions) | ### Asserting events @@ -230,12 +231,12 @@ Benchmark tests live in `contract/src/bench.rs` and measure CPU instruction coun ### Baselines -| Function | CPU instructions | Memory bytes | -|----------|-----------------|--------------| -| `subscribe()` | ~4 200 000 | ~200 000 | -| `charge()` | ~3 800 000 | ~180 000 | -| `pay_per_use()` | ~3 600 000 | ~170 000 | -| `batch_charge()` — 10 users | ~28 000 000 | ~1 200 000 | +| Function | CPU instructions | Memory bytes | +| --------------------------- | ---------------- | ------------ | +| `subscribe()` | ~4 200 000 | ~200 000 | +| `charge()` | ~3 800 000 | ~180 000 | +| `pay_per_use()` | ~3 600 000 | ~170 000 | +| `batch_charge()` — 10 users | ~28 000 000 | ~1 200 000 | Thresholds in `bench.rs` include ~10% headroom. If your change shifts a baseline by more than 5%, update the table and the constant. @@ -314,6 +315,7 @@ The full error reference is in [`docs/ERROR-CODES.md`](../docs/ERROR-CODES.md). Before opening a pull request against `main`: **Contract** + - [ ] `cargo test` passes with no failures - [ ] `cargo clippy -- -D warnings` passes with no warnings - [ ] `cargo check` passes @@ -326,16 +328,19 @@ Before opening a pull request against `main`: - [ ] `#![no_std]` is preserved — no `std::` imports anywhere **Benchmarks** + - [ ] If your change touches `subscribe`, `charge`, `pay_per_use`, or `batch_charge`, run `cargo test bench -- --nocapture` and confirm instruction counts are within the documented baselines - [ ] Update `bench.rs` constants and the baselines table if a deliberate change shifts a baseline **Documentation** + - [ ] New public functions are added to [`docs/API.md`](API.md) - [ ] New events are added to [`docs/EVENTS.md`](EVENTS.md) - [ ] New error codes are added to [`docs/ERROR-CODES.md`](ERROR-CODES.md) - [ ] PR description explains what changed, why, and links to the relevant issue **CI** + - [ ] The `Backend (Rust)` GitHub Actions workflow passes (`cargo build` + `cargo test`) --- diff --git a/docs/CONTRIBUTING-FRONTEND.md b/docs/CONTRIBUTING-FRONTEND.md index 911a9326..c4889f3a 100644 --- a/docs/CONTRIBUTING-FRONTEND.md +++ b/docs/CONTRIBUTING-FRONTEND.md @@ -47,6 +47,7 @@ export const MyComponent: FC = ({ title }) => { ``` **Rules of thumb** + - Prefer small components (one responsibility). - Prefer derived values via `useMemo`. - Avoid side effects in render (no async calls directly in the component body). @@ -60,10 +61,12 @@ export const MyComponent: FC = ({ title }) => { Hooks under `frontend/src/hooks/` should follow consistent conventions so contributors can compose them confidently. ### Naming + - Use the React hook naming convention: `useSomething`. - If a hook manages a resource, name it around the resource: `useWallet`, `useSubscriptions`, `useContractEvents`. ### Return shape + Prefer a clear, stable return object containing: - state values (e.g. `loading`, `error`, `data`) @@ -81,17 +84,20 @@ type UseXReturn = { ``` Guidelines: + - Keep return keys stable; avoid reordering or conditional return types. - For async actions, either: - return a Promise directly from the action function, or - expose `loading`/`error` updated by the action. ### Cleanup & effects + - If you attach listeners (window events, timers, subscriptions), always remove them in `useEffect` cleanup. - Avoid stale closures: put functions in dependency arrays or use `useCallback` when returning callbacks. - Do not start network requests in multiple places; centralize in hooks and expose `refresh`/`sync` actions. ### Side-effect boundary + - Components should be mostly presentational. - Hooks should own side effects: - `useEffect` for subscriptions/polling @@ -107,6 +113,7 @@ Frontend tests use Vitest configured with `jsdom` and RTL helpers. - RTL setup: `frontend/src/setupTests.ts` ### What to test + - Component behavior that depends on props/state - Hook behavior that exposes actions/state (prefer testing the resulting UI) - Accessibility-critical UI: buttons/inputs have labels and interactive elements are reachable @@ -126,7 +133,9 @@ describe("MyComponent", () => { it("renders the title", () => { render(); - expect(screen.getByRole("heading", { level: 2 })).toHaveTextContent("Hello"); + expect(screen.getByRole("heading", { level: 2 })).toHaveTextContent( + "Hello", + ); }); it("is keyboard operable (example)", async () => { @@ -141,6 +150,7 @@ describe("MyComponent", () => { ``` Notes: + - Prefer queries by role/label/text (`getByRole`, `getByLabelText`) rather than `getByTestId`. - For async UI, use `await screen.findBy*` or `await waitFor(...)`. @@ -160,6 +170,7 @@ npm test The app uses CSS custom properties (design tokens) defined in `frontend/src/index.css`. ### Required conventions + - Use tokens via `var(--token-name)` instead of hard-coded colors/sizes. - Prefer existing tokens (`--color-*`, `--space-*`, `--text-*`, `--radius-*`, `--transition-*`). - For theme-aware styling, ensure your CSS works with: @@ -167,10 +178,12 @@ The app uses CSS custom properties (design tokens) defined in `frontend/src/inde - `[data-theme="light"]` overrides ### Styling components + - Use existing utility classes/util patterns where possible. - If you introduce new styles, keep them token-based (no hard-coded theme-dependent values). ### Accessibility-related CSS utilities + - Use the `.sr-only` utility class for non-visual text when necessary (e.g., describing status changes). --- @@ -180,12 +193,14 @@ The app uses CSS custom properties (design tokens) defined in `frontend/src/inde Frontend changes must remain accessible. ### Interaction & keyboard navigation + - Every interactive element must be reachable and operable via keyboard: - Buttons should be `