From f1b91bc5db7aceb5bcf7e8567cbc3aa49ddfbd13 Mon Sep 17 00:00:00 2001 From: onoja24cash-code Date: Thu, 25 Jun 2026 09:26:03 +0000 Subject: [PATCH] chore: branch protection docs, treasury pagination, ABI explorer, CODEOWNERS - CONTRIBUTING.md: add Branch Protection section documenting required CI checks (contract-build, contract-tests, abi-snapshot-hygiene, markdown-lint, frontend-build), 1-approval rule and 2-approval rule for mainnet-related changes, and no direct pushes to main - treasury/src/lib.rs: replace stub get_pending_settlements with paginated version accepting offset/limit (default cap 100), filters on SettlementStatus::Pending - frontend: add ABIExplorer component (read-only, collapsible per contract) and wire /abi route in App.tsx - .github/CODEOWNERS: assign @dreamgeneX to contracts/, scripts/, docs/, frontend/, and comebackhere-frontend/ --- .github/CODEOWNERS | 9 ++ .../contracts/treasury/src/lib.rs | 37 +++++- CONTRIBUTING.md | 22 ++++ frontend/src/App.tsx | 2 + frontend/src/components/ABIExplorer.tsx | 114 ++++++++++++++++++ 5 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 frontend/src/components/ABIExplorer.tsx diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..7f0f298 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,9 @@ +# CODEOWNERS +# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + +contracts/ @dreamgeneX +scripts/ @dreamgeneX +docs/ @dreamgeneX + +comebackhere-frontend/ @dreamgeneX +frontend/ @dreamgeneX diff --git a/COMEBACKHERE-contracts/contracts/treasury/src/lib.rs b/COMEBACKHERE-contracts/contracts/treasury/src/lib.rs index cc852a2..68a0d7f 100644 --- a/COMEBACKHERE-contracts/contracts/treasury/src/lib.rs +++ b/COMEBACKHERE-contracts/contracts/treasury/src/lib.rs @@ -103,8 +103,41 @@ impl TreasuryContract { } } - pub fn get_pending_settlements(e: Env) -> Vec { - Vec::new(&e) + pub fn get_pending_settlements( + e: Env, + offset: Option, + limit: Option, + ) -> Vec { + let cap: u64 = limit.unwrap_or(100).min(100); + let skip: u64 = offset.unwrap_or(0); + let next_id: u64 = e + .storage() + .instance() + .get(&DataKey::NextSettlementId) + .unwrap_or(1u64); + + let mut result: Vec = Vec::new(&e); + let mut matched: u64 = 0; + let mut collected: u64 = 0; + + let mut id: u64 = 1; + while id < next_id && collected < cap { + if let Some(s) = e + .storage() + .instance() + .get::(&DataKey::Settlement(id)) + { + if matches!(s.status, SettlementStatus::Pending) { + if matched >= skip { + result.push_back(id); + collected += 1; + } + matched += 1; + } + } + id += 1; + } + result } pub fn pause(e: Env, admin: Address) { diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 56e8919..3d913e1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,6 +23,28 @@ Run all hooks manually: pre-commit run --all-files ``` +## Branch Protection + +The `main` branch is protected. Direct pushes are not allowed; all changes must +go through a pull request. + +### Required status checks + +All of the following CI checks must pass before a PR can be merged: + +- `contract-build` — Soroban contracts compile without errors +- `contract-tests` — contract unit and integration tests pass +- `abi-snapshot-hygiene` — ABI snapshots in `abis/` are consistent with contract sources +- `markdown-lint` — documentation passes markdownlint rules +- `frontend-build` — frontend builds without errors + +### Required reviews + +- At least **1 approving review** is required for all PRs targeting `main`. +- At least **2 approving reviews** are required for PRs that touch mainnet-related + paths (`docs/MAINNET_DEPLOYMENT.md`, mainnet deployment scripts, or governance + configuration). + ## ABI snapshots After changing contract interfaces (in `COMEBACKHERE-contracts/`), regenerate and verify ABI metadata: diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 162fd13..188e088 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,6 +1,7 @@ import { Navigate, Route, Routes } from "react-router-dom"; import DashboardLayout from "./components/Dashboard/DashboardLayout"; import SettlementProposalForm from "./components/SettlementProposal/SettlementProposalForm"; +import ABIExplorer from "./components/ABIExplorer"; function InvoicesPage() { return

Invoices list will appear here.

; @@ -27,6 +28,7 @@ export default function App() { } /> } /> } /> + } /> ); diff --git a/frontend/src/components/ABIExplorer.tsx b/frontend/src/components/ABIExplorer.tsx new file mode 100644 index 0000000..efbbfab --- /dev/null +++ b/frontend/src/components/ABIExplorer.tsx @@ -0,0 +1,114 @@ +import { useState } from 'react' + +interface ABIContract { + contract: string + version: string + functions: string[] +} + +const contracts: ABIContract[] = [ + { + contract: 'invoice', + version: '1.1.0', + functions: [ + 'initialize', + 'create_invoice', + 'mark_paid', + 'get_invoice', + 'get_invoice_status', + 'cancel_invoice', + 'request_refund', + 'batch_expire(offset: u32, limit: u32, returns: u32)', + 'pause', + 'unpause', + 'set_grace_window', + 'get_grace_window', + 'release_escrow', + ], + }, + { + contract: 'treasury', + version: '1.0.0', + functions: [ + 'initialize', + 'set_signer', + 'propose_settlement', + 'propose_partial_settlement', + 'approve_settlement', + 'approve_partial_settlement', + 'execute_settlement', + 'partially_execute_settlement', + 'cancel_settlement', + 'get_pending_settlements', + 'get_pending_settlements_page', + 'get_settlement', + 'update_threshold', + 'pause', + 'unpause', + 'raise_dispute', + 'resolve_dispute', + 'vote_dispute_resolution', + 'deposit', + 'withdraw', + 'add_allowed_token', + 'remove_allowed_token', + 'get_allowed_tokens', + 'propose_signer_rotation', + 'approve_signer_rotation', + 'update_merchant_payout_address', + 'get_merchant_payout_address', + 'hold_settlement', + 'release_hold', + ], + }, + { + contract: 'compliance', + version: '1.0.0', + functions: [ + 'initialize', + 'is_allowed', + 'allow_address', + 'block_address', + 'allow_address_until', + 'transfer_admin', + 'accept_admin', + 'clear_address', + 'pause', + 'unpause', + ], + }, +] + +export default function ABIExplorer() { + const [expanded, setExpanded] = useState>({}) + + const toggle = (contract: string) => { + setExpanded(prev => ({ ...prev, [contract]: !prev[contract] })) + } + + return ( +
+

ABI Explorer

+

Deployed contract functions reference

+ {contracts.map(c => ( +
+
toggle(c.contract)} + style={{ padding: '12px', cursor: 'pointer', background: '#f9f9f9', fontWeight: 'bold' }} + > + {c.contract} (v{c.version}) — {c.functions.length} functions +
+ {expanded[c.contract] && ( +
    + {c.functions.map((fn, i) => ( +
  • + {fn} +
  • + ))} +
+ )} +
+ ))} +
+ ) +}