Skip to content

PROD-003: Add analytics tracking for proposal and vote activity - #3

Open
ZainabJanee wants to merge 78 commits into
mainfrom
feat/prod-003-analytics
Open

PROD-003: Add analytics tracking for proposal and vote activity#3
ZainabJanee wants to merge 78 commits into
mainfrom
feat/prod-003-analytics

Conversation

@ZainabJanee

Copy link
Copy Markdown
Owner

Implements PROD-003 (Issue Vera3289#321) by integrating Plausible analytics to track critical user flows including wallet connections, proposal views, and transaction submissions.

Closes Vera3289#321

ZainabJanee and others added 30 commits May 30, 2026 18:44
…3289#315)

- Integrate Freighter wallet connection
- Require explicit wallet signature for voting and proposal creation
- Ensure unsigned transactions are never submitted
…3289#321)

- Integrate Plausible analytics
- Track wallet connections, proposal views, and action submissions
- Collect metrics for confirmed transactions
- Install Vitest, @testing-library/react, jest-dom, user-event, jsdom
- Configure Vitest in vite.config.ts with jsdom environment
- Add test/test:watch scripts to package.json
- Add 4 tests covering all acceptance criteria:
  - connect button triggers Freighter connection
  - connected state shows truncated address
  - disconnect clears wallet state
  - Freighter not installed shows install prompt
- Freighter API mocked via window.freighter
…-013)

Adds 8 tests covering all acceptance criteria for issue Vera3289#300:

- AC1: transfer_admin succeeds with valid new admin; new admin can cancel
- AC2: non-admin cannot call execute, cancel, or pause (NotAdmin #2)
- AC3: old admin loses execute, cancel, and pause after transfer
- AC4: transfer to zero address reverts with InvalidAddress (Vera3289#28)

Tests follow existing patterns (mock_all_auths, setup_passed_proposal,
setup_active_proposal helpers) and are grouped under TEST-013 section.
Triggers on push and PR to main. Builds both governance and token
WASM contracts via stellar contract build, verifies both binaries
exist, and uploads them as artifacts. Fails fast on any build error.

Closes Vera3289#258
Covers all acceptance criteria:
- Full event schema tables for governance and token contracts
- JavaScript examples for subscribing via Horizon/RPC getEvents
- Paginated event replay for historical data
- Continuous indexer class for live polling
- Proposal index builder from event stream

Closes Vera3289#283
- Add docs/soroban-gotchas.md covering:
  - Storage TTL and expiry across all three tiers
  - Contract size limits and optimisation tips
  - Cross-contract call costs and budget model
  - Auth model differences from EVM (no msg.sender, require_auth)
  - WASM determinism requirements and forbidden features
- Link new page from docs/GETTING_STARTED.md Next Steps section
…289#289)

Three end-to-end tests covering all acceptance criteria:
- test_lifecycle_passed_and_executed: create → vote Yes → finalise Passed → execute
- test_lifecycle_rejected: create → vote No (below quorum) → finalise Rejected
- test_lifecycle_cancelled_mid_vote: create → vote → cancel mid-vote

Tests use env.register() to run against the compiled WASM contract.
…ra3289#281)

Add 'Storage Cost Estimates' section to docs/storage.md covering:
- Fee model overview (inclusion fee + resource fee)
- Cost table for create_proposal, cast_vote, finalise, execute, cancel
- Storage rent estimates for long-running proposals per entry type
- Cost-saving notes (read-only calls, instance storage, cast_vote overhead)
- How to get exact estimates via simulateTransaction
- Add contracts/governance/fuzz/Cargo.toml with libfuzzer-sys 0.4
  and testutils features for governance + token contracts
- Add fuzz_create_proposal target that exercises all four inputs:
  title, description, quorum, and duration with arbitrary byte data
- Invariant: create_proposal must never panic; only Ok or ContractError
- Add .github/workflows/fuzz.yml as an optional nightly CI job
  (continue-on-error, uploads crash artifacts on failure)

Closes Vera3289#288
- Add tags: Vec<String> field to Proposal struct
- Add TooManyTags (Vera3289#35) and TagTooLong (Vera3289#36) error variants
- create_proposal accepts optional tags (max 5, max 32 chars each)
- Tags stored and returned as part of Proposal via get_proposal
- Add MAX_TAGS=5 and MAX_TAG_LEN=32 constants
- Update all existing create_proposal call sites to pass empty tags
- Add 7 tests covering tag storage, validation, and isolation

Closes Vera3289#253
- Add InvalidTokenContract (Vera3289#35) error variant
- Call try_balance() and try_total_supply() on token at init
- Revert with InvalidTokenContract if either call fails
- Add tests for valid and invalid token contracts

Closes Vera3289#247
- Add useOgMeta hook to set og:title, og:description, og:image,
  og:url, og:type, og:site_name, and all twitter:card tags
- Truncates description to 200 chars for card previews
- Falls back to votechain.dev/og-default.png when no custom image
- Wire hook into ProposalDetail, restores default title on unmount
- Add static fallback OG/Twitter tags to index.html for non-JS crawlers

Closes Vera3289#329
- SVG logo in light and dark variants (assets/logo-light.svg, logo-dark.svg)
- Full design token set in styles/tokens.css:
  - Color palette: brand (9 steps), neutral (11 steps), status, dark-mode aliases
  - Typography: font families, scale (xs–4xl), weights, line-heights, tracking
  - Spacing scale (4px base, 0–24)
  - Border radius, shadows, motion, z-index
  - Dark mode via prefers-color-scheme and html.dark class
- JS/TS token export in styles/tokens.ts for charting libs and dynamic styles

Closes Vera3289#324
…(SEC-016)

PROD-005: NotificationSubscribe component with email/webhook form,
event selection (created/voting_ended/executed), and unsubscribe list
persisted in localStorage. Rendered in GovernanceDashboard.

SEC-016: PhishingWarning modal shown on first wallet connect, displays
current domain, requires acknowledgement, supports 'don't show again'
via localStorage. Wired into FreighterWallet.
Display a warning modal on first wallet connect showing the current
domain. User must acknowledge before proceeding. Supports 'don't show
again' via localStorage.
Closes Vera3289#292 — TEST-005: Add tests for all ContractError variants
─────────────────────────────────────────────────────────────────
Every ContractError variant in both contracts now has at least one
test that triggers it and asserts the correct error is returned.

Governance (contracts/governance/src/test.rs):
- AdminNotSet (1): call execute() on an uninitialised contract
- VotingTokenNotSet (3): discriminant assertion (unreachable via
  public API since initialize sets both atomically; variant confirmed)
- InvalidDuration (5): create_proposal with duration = 0
- ProposalNotFound (6): get_proposal with a non-existent ID
- VotingPeriodEnded (8): cast_vote after the voting window closes
- VotingStillOpen (9): finalise before the voting window closes
- NoVotingPower (11): cast_vote with zero token balance
- ProposalNotPassed (12): execute an Active (not Passed) proposal
Previously untested variants now all have dedicated #[should_panic]
or assertion tests. Variants already covered (NotAdmin, InvalidQuorum,
ProposalNotActive, AlreadyVoted, AlreadyInitialized) are unchanged.

Token (contracts/token/src/test.rs):
- AdminNotSet (1): call mint() before initialize()
- InvalidAmount (3): transfer with amount = 0; mint with amount = 0
- AllowanceExceeded (5): transfer_from exceeding approved allowance
Previously untested variants now covered. NotAdmin and
InsufficientBalance were already tested.

Closes Vera3289#291 — TEST-004: Configure cargo-tarpaulin coverage in CI
─────────────────────────────────────────────────────────────────
Added a new 'coverage' job to .github/workflows/ci.yml that:
1. Installs cargo-tarpaulin (pinned via --locked)
2. Runs tarpaulin across the whole workspace with a 120 s timeout
   and outputs a Cobertura XML report
3. Enforces a 70 % line-coverage minimum threshold — the build fails
   if coverage drops below this floor
4. Uploads the coverage report as a CI artifact for inspection
The job depends on the existing 'test' job so it only runs after
tests pass.

Closes Vera3289#293 — TEST-006: Add snapshot tests for contract event payloads
───────────────────────────────────────────────────────────────────────
Added explicit event-payload assertion tests for every governance
state transition in contracts/governance/src/test.rs. Each test
calls env.events().all() and asserts that an event with the exact
expected topics tuple and data value was emitted:
- test_event_proposal_created   → ("created", id) / proposer address
- test_event_vote_cast          → ("vote", id) / (voter, Vote::Yes, weight)
- test_event_proposal_finalised_passed  → ("final", id) / ProposalStatus::Passed
- test_event_proposal_finalised_rejected → ("final", id) / ProposalStatus::Rejected
- test_event_proposal_executed  → ("final", id) / ProposalStatus::Executed
- test_event_proposal_cancelled → ("final", id) / ProposalStatus::Cancelled
- test_event_quorum_updated     → ("qupdate", id) / new_quorum i128
These tests pin the exact event schema so any accidental change to
topic keys, argument order, or data type will break CI immediately.

Closes Vera3289#307 — SEC-005: Add overflow protection for vote weight accumulation
────────────────────────────────────────────────────────────────────────────
The three .expect("vote tally overflow") calls in cast_vote
(contracts/governance/src/lib.rs) were replaced with:
  .ok_or(ContractError::Overflow)?
This converts an i128 arithmetic overflow from a contract panic into
a clean, catchable ContractError::Overflow (discriminant 14), which
is returned to the caller instead of aborting the transaction with an
unstructured panic message. A new Overflow = 14 variant was added to
the ContractError enum in contracts/governance/src/types.rs.
All three vote branches (Yes, No, Abstain) are protected.
VERA added 30 commits June 2, 2026 08:51
…esolution

docs: expand errors.md with all error codes, causes, and resolution steps
do: add pre-commit hooks for fmt and clippy checks
do: add SBOM generation workflow via cargo-cyclonedx
do: add release workflow with CHANGELOG notes and WASM artifacts
…ui-enhancements

feat: implement responsive proposal layout and empty state UI (closes Vera3289#215, closes Vera3289#231)
…ing-warning

feat: add phishing protection warning for wallet connection (SEC-016)
feat: add notification subscriptions (PROD-005) and phishing warning …
…acts227

feature:Implement optimistic UI updates for vote submission
…-secrets

SC-015: Audit deployment scripts for secret exposure
…ylesheet

FE-025: Add print stylesheet for proposal detail page
…-admin

SC-003: Add multi-sig admin support for governance contract
…d-design-system

feat(PROD-006): add brand identity and design system
feat(PROD-011): add OG and Twitter Card meta tags for proposal sharing
…validation

feat(SC-008): validate SEP-41 compliance at initialization
…al-tags

feat(SC-014): add proposal categories/tags support
…creation

test(Vera3289#288): add cargo-fuzz target for create_proposal inputs
…timates

docs: add storage cost estimates for governance operations (closes Vera3289#281)
…ycle-integration

test: add integration tests for full proposal lifecycle (closes Vera3289#289)
docs: add Soroban gotchas and limitations page (closes Vera3289#287)
…-indexing-guide

docs: event indexing guide for off-chain applications (DOC-011)
…ld-workflow

ci: add dedicated WASM build workflow (DO-001)
…n-transfer-privilege-tests

test(governance): admin transfer and privilege escalation tests (TEST-013)
…et-connection-unit-tests

test(frontend): wallet connection unit tests (TEST-010)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.