Skip to content

bountiful ergo bounty platform - #23

Open
aryan1715 wants to merge 1 commit into
StabilityNexus:mainfrom
aryan1715:Bountiful-Ergo-Bounty-Platform
Open

bountiful ergo bounty platform#23
aryan1715 wants to merge 1 commit into
StabilityNexus:mainfrom
aryan1715:Bountiful-Ergo-Bounty-Platform

Conversation

@aryan1715

@aryan1715 aryan1715 commented Dec 14, 2025

Copy link
Copy Markdown

Issue
Tests + contract compile were failing on Windows because Jest couldn’t load *.es?raw contract templates correctly (it treated them as non-strings), and the test script used non-Windows env syntax.
Fix
Made Jest scripts Windows-compatible.
Added a Jest transformer + mapper so *.es?raw loads as raw contract source string (so fleet-sdk/compiler can compile it).
Added wallet guards to avoid blank screen when Nautilus/window.ergo isn’t available.

Summary by CodeRabbit

  • New Features

    • Introduced Judge System phase for proposal dispute resolution and escalation
    • New "Send to Judge System" button enables escalation of disputed proposals to external judges
    • Added judge system status to proposal lifecycle tracking
  • Improvements

    • Enhanced Ergo wallet API resilience with improved error handling and connection verification

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Dec 14, 2025

Copy link
Copy Markdown

Walkthrough

The PR introduces a new Judge System feature for proposal contract management on the Ergo blockchain. It adds a new contract variant (v1_1) with dispute escalation capabilities, extends status handling to recognize "judge_system" as a distinct proposal state (value 4), reinforces platform API resilience, and updates corresponding UI and test infrastructure.

Changes

Cohort / File(s) Summary
New Judge System Contract
contracts/proposal_v1_1.es
New Ergo Sigma contract implementing Bountiful Proposal v1.4.0 with dispute resolution and judge system escalation. Defines input box fields (proposerPK, bountyId, metadataJson, bountyCreatorProp, status), status predicates, and action predicates for dispute (R8==3), judge escalation (R8==4), maintenance (R8==0), rejection (R8==2), and approval (R8==1). Top-level sigmaProp constraint aggregates validSetup and actions.
Contract Infrastructure
contracts/proposal_v1_0.es, src/lib/ergo/proposal_contract.ts
Minor formatting in v1_0; expanded v1_1 support by adding internal v1_1 generator, importing template, and extending version type from "v1_0" to "v1_0" | "v1_1".
Status & Action Handling
src/lib/common/proposal.ts, src/lib/ergo/actions/update_proposal_status.ts
Added parsing for status value 4 ("judge_system") in proposal parsing. Extended updateProposalStatus parameter type from 0 | 3 to 0 | 1 | 2 | 3 | 4 to support all lifecycle transitions.
Platform Utilities
src/lib/ergo/platform.ts
Introduced private getErgoApi() helper for API resilience; updated wallet methods (connect, get_address, get_current_height, get_balance) to use the helper with guards and fallback logic. Extended status handling to recognize "judge_system". Added genesis timestamp utilities (calculateGenesisTimestamp, blockHeightToDate) for date computations.
UI & User Interactions
src/routes/ProposalManager.svelte
Added support for status value 4 ("judge_system"). Introduced handleJudgeSystem async function to escalate disputed proposals. Updated UI logic to render "Send to Judge System" button for disputed proposals, gated by isCurrentUserJudge.
Test Configuration & Infrastructure
jest.config.mjs, package.json, test/fileMock.cjs, test/rawEsTransform.cjs
Updated Jest transform target from fileMock.cjs to rawEsTransform.cjs for .es files; added raw query string mapping. Modified test scripts to use explicit node execution path instead of NODE_OPTIONS environment variable. Added fileMock.cjs export helper and rawEsTransform.cjs to inline raw .es file contents for tests.
Contract Tests
test/proposal-contract.test.ts
Added JUDGE_SYSTEM status (value 4) to status definitions; updated test assertions to exclude 4 from canDisputeFrom (cannot dispute from judge system).

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as ProposalManager UI
    participant Platform as ErgoPlatform
    participant Ergo as Ergo Wallet/API
    participant Blockchain as Ergo Blockchain

    User->>UI: Click "Send to Judge System"<br/>(Disputed Proposal)
    UI->>UI: handleJudgeSystem(proposalId)
    UI->>Platform: updateProposalStatus(proposalBox,<br/>status: 4 [judge_system])
    Platform->>Platform: Construct transaction<br/>(copy assets, encode R8=4)
    Platform->>Ergo: Sign transaction
    Ergo->>Blockchain: Submit transaction
    Blockchain->>Blockchain: Validate: isEscalateToJudgeSystemAction<br/>(R8==4, bounty creator auth)
    Blockchain-->>Ergo: Tx confirmed
    Ergo-->>Platform: Return txId
    Platform->>Platform: Store txId
    Platform->>Platform: Wait & reload proposals
    Platform->>UI: Update status to "judge_system"
    UI->>User: Display Judge panel<br/>(Approve/Reject buttons)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Areas requiring extra attention:

  • Contract logic validation: Verify the new v1_1 contract predicates (isEscalateToJudgeSystemAction, isMaintenanceAction, etc.) correctly enforce the dispute escalation flow and authorization requirements.
  • Status enum consistency: Ensure the new status value 4 ("judge_system") is correctly propagated through all parsing, type definitions, and UI logic paths.
  • Platform API resilience: Review the getErgoApi() helper and its integration into wallet methods to confirm proper error handling and fallback behavior when Ergo API is unavailable.
  • Jest transform changes: Verify the rawEsTransform.cjs correctly inlines .es file contents and that the transform configuration properly maps to it via the ?raw query string.

Possibly related PRs

Poem

🐰 A judge system hops into sight,
Disputes now escalate to set things right,
From pending to judged, the contracts align,
With status four dancing in register R8 fine,
The bounty platform blooms—a feature divine! 🌿

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'bountiful ergo bounty platform' is vague and generic. It reads like a product name rather than a description of the specific changes in this PR. The PR actually adds a new v1.1 contract, fixes Jest/Windows compatibility, adds wallet guards, and extends status handling—none of which is conveyed by the title. Revise the title to be specific and descriptive of the main changes, such as 'Add v1.1 proposal contract with judge system and fix Windows Jest compatibility' or 'Support judge system status and improve platform stability.'
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/lib/ergo/actions/update_proposal_status.ts (1)

33-42: Update the JSDoc comment to reflect all status codes.

The function now accepts status codes 0, 1, 2, 3, and 4, but the JSDoc comment only documents 0 and 3. Please update the comment to include all valid status values for clarity.

Apply this diff:

 /**
  * Updates the status of a proposal.
- * This is used by the bounty creator to mark a proposal as "Disputed" or to resolve a dispute.
  * @param proposalBox The proposal box to update.
- * @param newStatus The new status code (0 for Pending, 3 for Disputed).
+ * @param newStatus The new status code (0: Pending, 1: Approved, 2: Rejected, 3: Disputed, 4: Judge System).
  * @param creatorAddress The address of the bounty creator.
  */
 export async function updateProposalStatus(
     proposalBox: ProposalBox,
     newStatus: 0 | 1 | 2 | 3 | 4,
     creatorAddress: string
 ): Promise<string | null> {
src/routes/ProposalManager.svelte (1)

841-866: Missing CSS style for status-judge_system badge.

The UI correctly adds the "Send to Judge System" button for disputed proposals and allows approve/reject actions for judge_system status. However, there's no CSS class .status-judge_system defined in the styles section (only .status-approved, .status-rejected, .status-pending, .status-disputed exist).

Add a style for the judge_system status badge:

.status-judge_system {
    background-color: #cce5ff;
    color: #004085;
}
🧹 Nitpick comments (3)
test/rawEsTransform.cjs (1)

1-10: Consider adding error handling for file read failures.

The implementation correctly reads and exports file content as a string for Jest. However, adding error handling around fs.readFileSync would provide clearer error messages if a file is missing or unreadable.

Apply this diff to add error handling:

 module.exports = {
   process(_src, filename) {
+    try {
       const content = fs.readFileSync(filename, 'utf8');
       return {
         code: `module.exports = ${JSON.stringify(content)};`
       };
+    } catch (error) {
+      throw new Error(`Failed to read contract file ${filename}: ${error.message}`);
+    }
   }
 };
contracts/proposal_v1_1.es (1)

21-33: Unused helper function.

The isSigmaPropEqualToBoxProp helper is defined but never used in any action predicate. Consider removing it to reduce contract complexity and script size, or document its intended use for future actions.

src/lib/ergo/platform.ts (1)

66-72: Consider providing clearer user feedback when Ergo API is unavailable.

The guard correctly prevents issues when the API is unavailable after Nautilus connection, but the user only sees a console warning. Consider showing an alert or a UI notification similar to other failure paths (lines 77, 80).

           const ergoApi = this.getErgoApi();
           if (!ergoApi) {
             console.warn('Connected to Nautilus, but ergo API is not available on window');
+            alert('Wallet connection incomplete - Ergo API not available');
             connected.set(false);
             return;
           }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 63fb5c3 and aacefc5.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (12)
  • contracts/proposal_v1_0.es (1 hunks)
  • contracts/proposal_v1_1.es (1 hunks)
  • jest.config.mjs (1 hunks)
  • package.json (1 hunks)
  • src/lib/common/proposal.ts (1 hunks)
  • src/lib/ergo/actions/update_proposal_status.ts (1 hunks)
  • src/lib/ergo/platform.ts (7 hunks)
  • src/lib/ergo/proposal_contract.ts (2 hunks)
  • src/routes/ProposalManager.svelte (4 hunks)
  • test/fileMock.cjs (1 hunks)
  • test/proposal-contract.test.ts (2 hunks)
  • test/rawEsTransform.cjs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/lib/ergo/platform.ts (2)
src/lib/common/store.ts (2)
  • connected (10-10)
  • address (8-8)
src/lib/ergo/actions/approve_proposal.ts (1)
  • ProposalBox (26-33)
🔇 Additional comments (17)
contracts/proposal_v1_0.es (1)

23-23: LGTM!

The blank line improves readability by separating variable declarations from the logic below.

jest.config.mjs (2)

11-11: LGTM!

Switching to rawEsTransform.cjs enables loading .es contract files as raw string content, which is required for fleet-sdk/compiler to compile them. This aligns with the PR's objective of fixing Windows compatibility issues where Jest previously couldn't load these files correctly.


14-14: LGTM!

The ?raw query string mapper works in conjunction with the raw ES transformer to enable explicit raw imports like import contract from './contract.es?raw'. This is a common pattern for loading file content as strings.

package.json (1)

6-8: LGTM!

Excellent fix for Windows compatibility. The NODE_OPTIONS=... syntax doesn't work in Windows CMD/PowerShell. Calling the node binary explicitly with the --experimental-vm-modules flag works cross-platform.

test/proposal-contract.test.ts (2)

28-29: LGTM!

Adding the JUDGE_SYSTEM status with value 4 correctly extends the status model to include the new judge system phase introduced in this PR.


43-43: LGTM!

Correctly verifies that proposals in the Judge System state (4) cannot be disputed, which makes sense as the Judge System is an escalation mechanism beyond the normal dispute flow.

src/lib/common/proposal.ts (1)

177-179: LGTM!

The new status case correctly parses value 4 from the R8 register to the "judge_system" status string, maintaining consistency with the status model introduced across the PR.

src/lib/ergo/proposal_contract.ts (3)

7-9: LGTM!

The v1_1 template import and type extension follow the established pattern for v1_0 cleanly.


22-25: LGTM!

The generator function for v1_1 follows the same structure as v1_0, maintaining consistency.


32-33: LGTM!

The version switcher correctly handles the new v1_1 case. The exhaustive switch with a default error throw ensures type safety.

src/routes/ProposalManager.svelte (2)

309-311: LGTM!

Status parsing correctly maps R8 value "4" to "judge_system", consistent with the contract definition.


665-690: LGTM!

The handleJudgeSystem function follows the same pattern as handleDispute and handleReject, with proper error handling and state management.

contracts/proposal_v1_1.es (2)

35-48: Verify: Dispute from approved state is intentional.

The isDisputeAction allows transitioning from isApproved to disputed status. This is unusual since approved proposals typically represent a finalized state. Please confirm this is the intended behavior for allowing post-approval disputes.


107-120: LGTM!

The action aggregation and validSetup logic correctly combine all predicates. The contract structure is clean and follows the expected pattern for Ergo contracts.

src/lib/ergo/platform.ts (3)

53-57: LGTM!

The getErgoApi() helper cleanly centralizes the Ergo API resolution logic, checking both global ergo and window.ergo with proper guards. This addresses the PR objective of preventing blank screens when Nautilus is unavailable.


89-91: LGTM!

The wallet methods (get_address, get_current_height, get_balance) correctly use the centralized getErgoApi() helper with appropriate guards and error messages.

Also applies to: 100-102, 122-127


241-250: LGTM!

The status parsing in fetchProposals correctly handles all five status values (0-4), matching the contract definition and UI expectations.

Comment on lines +65 to +75
val isMaintenanceAction = {
allOf(Coll(
isPending,
OUTPUTS(0).R4[GroupElement].get == proposerPK,
OUTPUTS(0).R5[Coll[Byte]].get == bountyId,
OUTPUTS(0).R7[SigmaProp].get == bountyCreatorProp,
OUTPUTS(0).value == SELF.value,
OUTPUTS(0).propositionBytes == SELF.propositionBytes,
OUTPUTS(0).R8[Int].get == 0
))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing R6 (metadataJson) preservation in isMaintenanceAction.

Unlike other action predicates (isDisputeAction, isRejectAction, isApprovalAction, isEscalateToJudgeSystemAction) which all verify OUTPUTS(0).R6[Coll[Byte]].get == metadataJson, this action does not check R6. This could allow the metadata to be modified during maintenance.

Apply this diff to ensure metadata is preserved:

 val isMaintenanceAction = {
   allOf(Coll(
     isPending,
     OUTPUTS(0).R4[GroupElement].get == proposerPK,
     OUTPUTS(0).R5[Coll[Byte]].get == bountyId,
+    OUTPUTS(0).R6[Coll[Byte]].get == metadataJson,
     OUTPUTS(0).R7[SigmaProp].get == bountyCreatorProp,
     OUTPUTS(0).value == SELF.value,
     OUTPUTS(0).propositionBytes == SELF.propositionBytes,
     OUTPUTS(0).R8[Int].get == 0
   ))
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
val isMaintenanceAction = {
allOf(Coll(
isPending,
OUTPUTS(0).R4[GroupElement].get == proposerPK,
OUTPUTS(0).R5[Coll[Byte]].get == bountyId,
OUTPUTS(0).R7[SigmaProp].get == bountyCreatorProp,
OUTPUTS(0).value == SELF.value,
OUTPUTS(0).propositionBytes == SELF.propositionBytes,
OUTPUTS(0).R8[Int].get == 0
))
}
val isMaintenanceAction = {
allOf(Coll(
isPending,
OUTPUTS(0).R4[GroupElement].get == proposerPK,
OUTPUTS(0).R5[Coll[Byte]].get == bountyId,
OUTPUTS(0).R6[Coll[Byte]].get == metadataJson,
OUTPUTS(0).R7[SigmaProp].get == bountyCreatorProp,
OUTPUTS(0).value == SELF.value,
OUTPUTS(0).propositionBytes == SELF.propositionBytes,
OUTPUTS(0).R8[Int].get == 0
))
}
🤖 Prompt for AI Agents
In contracts/proposal_v1_1.es around lines 65 to 75, the isMaintenanceAction
predicate is missing a check to preserve R6 (metadataJson); add a clause to the
allOf that asserts OUTPUTS(0).R6[Coll[Byte]].get == metadataJson so the
maintenance action validates that metadataJson is unchanged, matching the other
action predicates.

Comment thread src/lib/ergo/platform.ts
Comment on lines +198 to 200
async updateProposalStatus(proposalBox: ProposalBox, newStatus: 0 | 1 | 2 | 3 | 4, creatorAddress: string): Promise<string | null> {
return await updateProposalStatus(proposalBox, newStatus, creatorAddress);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify updateProposalStatus action signature and ProposalBox interface
echo "=== Checking updateProposalStatus signature ==="
rg -n "updateProposalStatus" src/lib/ergo/actions/update_proposal_status.ts -A 3

echo ""
echo "=== Checking ProposalBox R8 comment ==="
rg -n "R8.*status" src/lib/ergo/actions/approve_proposal.ts

Repository: StabilityNexus/Bountiful-BountyPlatform-Ergo

Length of output: 410


LGTM, but ProposalBox interface comment needs updating.

The updateProposalStatus signature is correctly expanded to accept the new judge_system status (4), and the underlying action in src/lib/ergo/actions/update_proposal_status.ts (line 40-42) properly accepts the expanded status type. However, the ProposalBox interface comment at src/lib/ergo/actions/approve_proposal.ts line 32 still lists only statuses 0-3 and must be updated to include "4: Judge System":

R8: string; // Int - status (0: Pending, 1: Approved, 2: Rejected, 3: Disputed, 4: Judge System)
🤖 Prompt for AI Agents
In src/lib/ergo/actions/approve_proposal.ts around line 32, update the
ProposalBox interface comment for the R8 field to include the new status value 4
by changing the status list to: "Int - status (0: Pending, 1: Approved, 2:
Rejected, 3: Disputed, 4: Judge System)"; ensure the comment remains on the R8
line and matches the same format as other comments.

Comment thread test/fileMock.cjs
Comment on lines +1 to +7
module.exports = {
process() {
return {
code: 'module.exports = {};'
};
},
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for references to fileMock.cjs in the codebase
rg "fileMock\.cjs" -n

Repository: StabilityNexus/Bountiful-BountyPlatform-Ergo

Length of output: 70


🏁 Script executed:

#!/bin/bash
# Also search for variations and imports of fileMock
rg "fileMock" -n --type js --type cjs --type mjs --type json

Repository: StabilityNexus/Bountiful-BountyPlatform-Ergo

Length of output: 115


🏁 Script executed:

#!/bin/bash
# Check the jest configuration to see what mocks are actually configured
cat -n jest.config.mjs

Repository: StabilityNexus/Bountiful-BountyPlatform-Ergo

Length of output: 709


🏁 Script executed:

#!/bin/bash
# Search for moduleNameMapper or transform configurations that might reference this file
rg "moduleNameMapper|transform" jest.config.mjs -A 5 -B 5

Repository: StabilityNexus/Bountiful-BountyPlatform-Ergo

Length of output: 569


Remove the unused fileMock.cjs file.

This file is not referenced anywhere in the codebase and is not configured in jest.config.mjs. The jest configuration only uses rawEsTransform.cjs for .es file transformations. Delete it to reduce clutter.

🤖 Prompt for AI Agents
In test/fileMock.cjs lines 1-7: this file is unused and not referenced by the
codebase or jest.config.mjs; delete test/fileMock.cjs from the repository to
remove dead/unused test fixture and update any tests if they depended on it (no
code changes required elsewhere since jest config only uses rawEsTransform.cjs).

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.

2 participants