Skip to content

Develop #147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 351 commits into
base: main
Choose a base branch
from
Open

Develop #147

wants to merge 351 commits into from

Conversation

codingshot
Copy link
Member

@codingshot codingshot commented Sep 15, 2024

pushing to master

Summary by CodeRabbit

  • New Features

    • Updated contract IDs and added links for Staging and Testnet environments.
    • Expanded NEAR Grantpicks contract documentation with detailed architecture and methods.
    • Introduced comprehensive round, application, deposit, payout, and voting management in NEAR contract.
    • Added logging for key contract events to improve traceability.
    • Integrated whitelist and KYC list management via external list contract.
    • Added multi-chain support with Stellar and NEAR integration in frontend components.
    • Introduced new RoundMenu component for streamlined round interactions.
    • Added enhanced project pre-check and registration status features.
    • Added payout challenge management and compliance checks.
    • Enhanced wallet integration with additional wallet selectors and improved user profile handling.
    • Added local storage support for draft management in project creation forms.
    • Added video duration validation and YouTube embed title extraction for project media uploads.
  • Enhancements

    • Refined contract ownership transfer with two-step acceptance and cancellation.
    • Improved validation for voting and application periods, whitelist enforcement, and fee constraints.
    • Centralized contract configuration management for fees, page size, and whitelist IDs.
    • Streamlined contract storage management with modular persistence extensions.
    • Enhanced UI routing and navigation, redirecting application pages to rounds.
    • Updated UI components for dynamic blockchain-specific rendering and state management.
    • Improved error handling with detailed error codes and messages.
    • Simplified contract method signatures by removing redundant owner parameters.
    • Enhanced voting logic to prevent duplicate picks and enforce whitelist restrictions.
    • Improved payout processing with cooldowns, challenges, and compliance checks.
    • Updated frontend components to use new data models and support multi-chain logic.
    • Enhanced form validation and error feedback for member management and smart contract addresses.
    • Refined local storage usage for form drafts and application state persistence.
    • Improved UI elements including buttons, menus, and footers for better user experience.
  • Bug Fixes

    • Fixed typo in project funding history field name.
    • Corrected blacklist validation logic to prevent redundant entries.
    • Resolved issues with timing validations ensuring periods start in the future and meet minimum durations.
  • Documentation

    • Updated contract IDs in frontend client READMEs and CLI commands.
    • Clarified contract initialization parameters and configuration options.
    • Improved inline documentation for contract methods and data structures.

Copy link

vercel bot commented Sep 15, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
grantpicks ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 9, 2025 8:34am

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (9)
stellar/contract/round/src/test.rs (2)

2166-2283: Test for referrer fee calculations has commented assertions.

The test verifies referrer deposits work correctly, but contains commented-out assertions that should be either fixed and uncommented, or removed entirely.

     let deposit_without_referrer = round.get_deposits_for_round(&1, &None, &None);
     let deposit_without_referrer = deposit_without_referrer.first().unwrap();
     assert_eq!(deposit_without_referrer.referrer_fee, 0);
-    // assert_eq!(
-    //     deposit_without_referrer.net_amount as u128,
-    //     amount.saturating_sub(calculate_protocol_fee(&env, amount).unwrap())
-    // );
     assert_eq!(deposit_with_referrer.referrer_fee as u128, expected_referrer_fee);
-    // assert_eq!(
-    //     deposit_with_referrer.net_amount as u128,
-    //     amount.saturating_sub(calculate_protocol_fee(&env, amount).unwrap()).saturating_sub(expected_referrer_fee)
-    // );

2285-2380: ⚠️ Potential issue

Critical security feature lacks committed tests.

The commented-out two-step ownership transfer test is concerning. The comment "function names have to be shortened to test, did that locally" suggests that tests for this critical security feature have been run locally but not integrated into the continuous integration process.

Ownership transfer is a sensitive operation that should have automated tests in the repository. Please integrate the locally tested functionality into the codebase with proper test coverage.

stellar/contract/round/src/validation.rs (2)

142-144: Corrected voting period validation logic

The condition for checking if voting has started has been modified from > to >=.

This change fixes a critical edge case where voting would be allowed exactly at the start time. The previous implementation would have allowed voting before the official start time if a transaction was processed at exactly the start timestamp. This ensures the validation is precise.


223-232: 🛠️ Refactor suggestion

Check for mismatched _use_whitelist_voting vs function usage.

This function assumes round.voting_wl_list_id is always set. If the caller invokes validate_voting_whitelist without verifying use_whitelist_voting is enabled, .unwrap() could panic. Include a defensive check or ensure the function is only called when use_whitelist_voting is true.

+ if !round.use_whitelist_voting {
+     panic_with_error!(env, RoundError::WhitelistNotEnabled);
+ }
 let list_id = round.voting_wl_list_id.unwrap();
stellar/contract/round/src/internal.rs (5)

313-326: Error handling needed in KYC whitelist change function.

Just like in the initialization, the call to list_client.get_list() lacks proper error handling in the change_kyc_wl_list_id function.

Implement proper error handling similar to the suggestion for the initialization function:

let list_client = ListsClient::new(env, &config.list_contract);
-let valid_list = list_client.get_list(&list_id);
-assert!(valid_list.id == list_id, "Invalid voting whitelist list id");
+match list_client.try_get_list(&list_id) {
+    Ok(valid_list) => {
+        assert!(valid_list.id == list_id, "Invalid KYC whitelist list id");
+    },
+    Err(_) => panic_with_error!(env, Error::InvalidWhitelistId),
+}

1042-1054: ⚠️ Potential issue

Unsafe unwrap in whitelist_status function.

The whitelist_status function unwraps round.voting_wl_list_id without checking if it's None, which could cause a panic.

Handle the potential None case:

fn whitelist_status(env: &Env, round_id: u128, address: Address) -> bool {
    let round = read_round_info(env, round_id);
-    let list_id = round.voting_wl_list_id.unwrap();
+    if round.voting_wl_list_id.is_none() {
+        return false;
+    }
+    let list_id = round.voting_wl_list_id.unwrap();
    let list_contract = read_config(env).list_contract;
    let list_client = ListsClient::new(env, &list_contract);
    let is_whitelisted = list_client.is_registered(
        &Some(list_id),
        &address,
        &Some(RegistrationStatus::Approved),
    );

    is_whitelisted
}

107-114: 🛠️ Refactor suggestion

Whitelist validation needs error handling.

The call to list_client.get_list() lacks proper error handling. If the list doesn't exist or there are other issues, this will panic with a generic error instead of a specific error message.

Implement proper error handling:

if kyc_wl_list_id.is_some() {
    let list_client = ListsClient::new(env, &list_address);
-    let valid_list = list_client.get_list(&kyc_wl_list_id.unwrap());
-    assert!(
-        valid_list.id == kyc_wl_list_id.unwrap(),
-        "Invalid voting whitelist list id"
-    );
+    // Using a try-catch pattern with match to handle potential errors
+    match list_client.try_get_list(&kyc_wl_list_id.unwrap()) {
+        Ok(valid_list) => {
+            assert!(valid_list.id == kyc_wl_list_id.unwrap(), "Invalid KYC whitelist list id");
+        },
+        Err(_) => panic_with_error!(env, Error::InvalidWhitelistId),
+    }
}

855-859: 🛠️ Refactor suggestion

Add logging for skipped payments when project not found.

When a payout is skipped because the project is not found, there's no logging to indicate this happened.

Add explicit logging:

if project.is_none() {
+    log!("Skipping payment for project ID {} as it was not found in registry", project_id);
    payout.paid_at_ms = Some(get_ledger_second_as_millis(env));
    write_payout_info(env, payout_id, &payout);
    return;
}

870-877: 🛠️ Refactor suggestion

Add explicit logging for skipped KYC payments.

When a payout is skipped due to failed KYC verification, there's no logging to indicate this happened, which could lead to confusion and debugging difficulties.

Add explicit logging:

if !is_kyc_passed {
+    log!("Skipping payment to {} due to failed KYC verification", project_owner);
    if round.compliance_end_ms.unwrap_or(0) < get_ledger_second_as_millis(env) {
+        log!("Compliance period has ended, marking payment as processed without transfer");
        payout.paid_at_ms = Some(get_ledger_second_as_millis(env));
        write_payout_info(env, payout_id, &payout);
    }
    return;
}
🧹 Nitpick comments (4)
stellar/contract/round/src/internal.rs (4)

1294-1313: Duplicate whitelist validation code needs refactoring.

The validation code for both voting and application whitelist IDs is nearly identical and should be refactored into a shared function to avoid duplication.

Create a helper function for whitelist ID validation:

+fn validate_whitelist_id(env: &Env, list_contract: &Address, list_id: u128, error_message: &str) {
+    let list_client = ListsClient::new(env, list_contract);
+    match list_client.try_get_list(&list_id) {
+        Ok(valid_list) => {
+            assert!(valid_list.id == list_id, "{}", error_message);
+        },
+        Err(_) => panic_with_error!(env, Error::InvalidWhitelistId),
+    }
+}

// Then use it in the update_round function:
if let Some(voting_wl_list_id) = round_detail.voting_wl_list_id {
-    let list_client = ListsClient::new(env, &read_config(env).list_contract);
-    let valid_list = list_client.get_list(&voting_wl_list_id);
-    assert!(
-        valid_list.id == voting_wl_list_id,
-        "Invalid voting whitelist list id"
-    );
+    validate_whitelist_id(env, &read_config(env).list_contract, voting_wl_list_id, "Invalid voting whitelist list id");
    round.voting_wl_list_id = Some(voting_wl_list_id);
}

if let Some(application_wl_list_id) = round_detail.application_wl_list_id {
-    let list_client = ListsClient::new(env, &read_config(env).list_contract);
-    let valid_list = list_client.get_list(&application_wl_list_id);
-    assert!(
-        valid_list.id == application_wl_list_id,
-        "Invalid application whitelist list id"
-    );
+    validate_whitelist_id(env, &read_config(env).list_contract, application_wl_list_id, "Invalid application whitelist list id");
    round.application_wl_list_id = Some(application_wl_list_id);
}

701-713: Improved duplicate pick detection.

The code uses a vector to track seen pairs, which is fine for small numbers of picks, but could be inefficient for larger numbers.

Consider using a Map (or equivalent hash-based structure) for more efficient lookups:

-let mut seen_pairs: Vec<u32> = Vec::new(env);
+let mut seen_pairs: Map<u32, bool> = Map::new(env);

picks.iter().for_each(|picked_pair| {
    let picked_index = picked_pair.pair_id;

    if picked_index >= total_available_pairs {
        panic_with_error!(env, Error::IndexOutOfBound);
    }

-    if seen_pairs.contains(picked_index) {
+    if seen_pairs.contains_key(picked_index) {
        panic_with_error!(env, VoteError::DuplicatePick);
    }
-    seen_pairs.push_back(picked_pair.pair_id);
+    seen_pairs.set(picked_pair.pair_id, true);

1692-1700: Inefficient payout retrieval in get_payouts function.

The current implementation loops through sequential payout IDs and breaks when one is not found. This is inefficient for sparse payout IDs and could lead to incorrect results if IDs aren't sequential.

Consider using a more explicit storage method that maintains a list of valid payout IDs:

fn get_payouts(env: &Env, from_index: Option<u64>, limit: Option<u64>) -> Vec<Payout> {
    let default_page_size = read_config(env).default_page_size;
    let limit_internal: u64 = limit.unwrap_or(default_page_size);
    let from_index_internal: u64 = from_index.unwrap_or(0);

    let mut payouts_external: Vec<Payout> = Vec::new(env);

-    for i in from_index_internal..limit_internal {
-        let payout = read_payout_info(env, i as u32);
-
-        if payout.is_none() {
-            break;
-        }
-      
-        payouts_external.push_back(payout.unwrap().clone());
-    }
+    // Get all payout IDs
+    let payout_ids = read_all_payout_ids(env);
+    
+    // Apply pagination
+    payout_ids.iter()
+        .skip(from_index_internal as usize)
+        .take(limit_internal as usize)
+        .for_each(|payout_id| {
+            let payout = read_payout_info(env, *payout_id);
+            if let Some(payout_info) = payout {
+                payouts_external.push_back(payout_info.clone());
+            }
+        });

    payouts_external
}

This would require adding a new function to read all payout IDs from storage.


912-940: Improve error handling in can_vote function.

The can_vote function returns false in several scenarios (blacklisted, whitelist required but missing, user not on whitelist) without providing a way to distinguish between these cases.

Consider returning a structured result instead of a boolean:

-fn can_vote(env: &Env, round_id: u128, voter: Address) -> bool {
+fn can_vote(env: &Env, round_id: u128, voter: Address) -> (bool, Option<String>) {
    let round = read_round_info(env, round_id);
    let current_ms = get_ledger_second_as_millis(env);

    if round.voting_start_ms <= current_ms && current_ms <= round.voting_end_ms {
        let is_blacklisted = is_blacklisted(env, round_id, voter.clone());
        if is_blacklisted {
-            return false;
+            return (false, Some("Voter is blacklisted".into()));
        }
        if round.use_whitelist_voting {
            if round.voting_wl_list_id.is_none() {
-                return false;
+                return (false, Some("Whitelist ID not configured".into()));
            }
            let list_id = round.voting_wl_list_id.unwrap();
            let list_contract = read_config(env).list_contract;
            let list_client = ListsClient::new(env, &list_contract);
            let is_whitelisted = list_client.is_registered(
                &Some(list_id),
                &voter,
                &Some(RegistrationStatus::Approved),
            );
-            return is_whitelisted;
+            return (is_whitelisted, if is_whitelisted { None } else { Some("Voter not whitelisted".into()) });
        }

-        return true;
+        return (true, None);
    }

-    false
+    (false, Some("Voting period not active".into()))
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fefde29 and dec973e.

⛔ Files ignored due to path filters (2)
  • stellar/contract/build/round.wasm is excluded by !**/*.wasm
  • stellar/contract/build/round_opt.wasm is excluded by !**/*.wasm
📒 Files selected for processing (6)
  • stellar/contract/round/src/core.rs (1 hunks)
  • stellar/contract/round/src/data_type.rs (8 hunks)
  • stellar/contract/round/src/error.rs (4 hunks)
  • stellar/contract/round/src/internal.rs (52 hunks)
  • stellar/contract/round/src/test.rs (54 hunks)
  • stellar/contract/round/src/validation.rs (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • stellar/contract/round/src/data_type.rs
🧰 Additional context used
🧬 Code Graph Analysis (2)
stellar/contract/round/src/validation.rs (7)
stellar/contract/round/src/approval_writer.rs (2)
  • is_project_approved (18-21)
  • read_approved_projects (5-11)
stellar/contract/round/src/config_writer.rs (1)
  • read_config (10-13)
stellar/frontend/round-client/src/index.ts (4)
  • CreateRoundParams (90-114)
  • RoundDetail (55-87)
  • UpdateRoundParams (117-133)
  • RegistrationStatus (359-359)
stellar/frontend/lists-client/dist/index.d.ts (1)
  • RegistrationStatus (14-29)
stellar/contract/round/src/round_writer.rs (1)
  • read_round_info (10-13)
stellar/contract/round/src/utils.rs (1)
  • get_ledger_second_as_millis (24-26)
stellar/contract/round/src/voter_writer.rs (1)
  • is_blacklisted (29-38)
stellar/contract/round/src/core.rs (2)
stellar/contract/round/src/internal.rs (5)
  • set_applications_config (1190-1243)
  • set_voting_period (331-366)
  • set_number_of_votes (1074-1101)
  • set_expected_amount (368-382)
  • set_minimum_deposit (384-402)
stellar/frontend/round-client/src/index.ts (1)
  • RoundDetail (55-87)
🔇 Additional comments (14)
stellar/contract/round/src/core.rs (1)

12-16: API improvement with consolidated configuration methods.

The refactored method signatures provide a cleaner, more cohesive API. Consolidating related configuration aspects into single methods (set_applications_config, set_voting_period, etc.) makes the interface more maintainable and reduces the chance of inconsistent states that could occur with separate methods.

stellar/contract/round/src/test.rs (2)

47-74: Good addition of list contract deployment helper.

The helper functions for deploying and setting up the list contract provide clean test infrastructure and ensure consistent configuration across tests. Using a default KYC registration status of "Approved" is a pragmatic approach for test simplification.


156-163: Useful test period helper for consistent test configuration.

The create_test_period helper ensures consistent application and voting periods across tests, improving maintainability by centralizing timing logic. This reduces the chance of timing-related test errors and makes the test suite more robust.

stellar/contract/round/src/validation.rs (4)

6-8: Good addition of minimum duration constraints.

Adding minimum duration constants for voting and application periods (24 hours) prevents creation of rounds with impractically short periods. These constraints help ensure fair participation opportunities for all users.


13-16: Important validation that voting start is in the future.

Checking that the voting start timestamp is strictly in the future prevents creation of rounds that immediately begin voting, which could give unfair advantage to users who know about the round in advance.


26-31: Enhanced application period validation with future-time and minimum duration checks.

Validating that application periods start in the future and have a minimum duration improves round fairness and usability. The future-time check prevents retroactive application periods, while the minimum duration ensures participants have reasonable time to apply.


58-60: Enforcing minimum voting duration.

Adding validation that enforces a minimum voting period duration (24 hours) ensures users have adequate time to participate in the voting process. This is an important fairness constraint.

stellar/contract/round/src/error.rs (4)

14-18: Well-defined errors for ownership and initialization.

These new error variants improve contract security by providing specific errors for ownership management and initialization states. The NoPendingOwnershipTransfer error specifically supports the two-step ownership transfer process which is a security best practice.


58-68: Comprehensive timing and constraint errors.

The new timing constraint errors (VotingPeriodTooShort, ApplicationPeriodTooShort, etc.) directly support the enhanced validation logic. The deposit-related errors and whitelist errors improve clarity when operations fail due to specific conditions.


84-86: Improved voting validation errors.

The DuplicatePick and TooManyVotesForAvailablePairs errors provide better feedback for voting validation failures, helping users understand specifically why their vote was rejected.


104-107: Enhanced application period validation errors.

These new error variants align with the enhanced application period validation logic, providing specific feedback when application periods overlap with voting or are too short, helping round creators fix configuration issues.

stellar/contract/round/src/internal.rs (3)

1209-1233: Good improvements to application period validation.

The added validations for the application period are quite thorough, checking for future start times, minimum duration, and no overlap with voting periods.


149-154: Good validation of referrer fee basis points.

The validation ensures that the referrer fee cannot exceed the maximum allowed percentage (5%).


614-619: Clean conditional referrer fee calculation.

The code now properly handles the case when referrer_id is None by setting the fee to 0.

Comment on lines +2047 to +2164
let (application_start, application_end, voting_start, voting_end) = create_test_period(&env);

// Create round
let round_detail = &CreateRoundParams {
description: String::from_str(&env, "description"),
name: String::from_str(&env, "name"),
is_video_required: false,
contacts: Vec::new(&env),
voting_start_ms: voting_start,
voting_end_ms: voting_end,
application_start_ms: Some(application_start),
application_end_ms: Some(application_end),
expected_amount: 5,
minimum_deposit: 1,
admins: admins.clone(),
use_whitelist_voting: Some(false),
use_whitelist_application: Some(false),
voting_wl_list_id: None,
application_wl_list_id: None,
num_picks_per_voter: Some(2),
max_participants: Some(10),
allow_applications: true,
owner: admin.clone(),
cooldown_period_ms: None,
compliance_req_desc: String::from_str(&env, ""),
compliance_period_ms: None,
allow_remaining_dist: false,
remaining_dist_address: admin.clone(),
referrer_fee_basis_points: None,
use_vault: None,
};

round.initialize(
&admin,
&token_contract.address,
&project_contract.address,
&list_contract.address,
&Some(1),
&None,
&None,
&None,
);

let created_round = round.create_round(&admin, round_detail);

let reason1 = String::from_str(&env, "Challenge reason 1");

// Create three challenges
round.challenge_payouts(&created_round.id, &challenger1, &reason1);

// Resolve two of the challenges
// let admin_notes = String::from_str(&env, "Admin notes");
// round.update_payouts_challenge(
// &created_round.id,
// &admin,
// &challenger1,
// &Some(admin_notes.clone()),
// &Some(true), // Resolve this challenge
// );

// round.update_payouts_challenge(
// &created_round.id,
// &admin,
// &challenger2,
// &Some(admin_notes.clone()),
// &Some(true),
// );

// let challenges_before = round.get_challenges_payout(&created_round.id, &None, &None);
// assert_eq!(challenges_before.len(), 3);

// // Count resolved challenges
// let resolved_count = challenges_before.iter().filter(|c| c.resolved).count();
// assert_eq!(resolved_count, 2);

// // Remove resolved challenges
// round.remove_resolved_challenges(&created_round.id, &admin);

// let challenges_after = round.get_challenges_payout(&created_round.id, &None, &None);
// assert_eq!(challenges_after.len(), 1);

// assert_eq!(challenges_after.get(0).unwrap().challenger_id, challenger3);
// assert_eq!(challenges_after.get(0).unwrap().resolved, false);

// // Resolve the last challenge
// round.update_payouts_challenge(
// &created_round.id,
// &admin,
// &challenger3,
// &Some(admin_notes.clone()),
// &Some(true),
// );

// // Remove all resolved challenges
// round.remove_resolved_challenges(&created_round.id, &admin);

// // Verify no challenges remain
// let final_challenges = round.get_challenges_payout(&created_round.id, &None, &None);
// assert_eq!(final_challenges.len(), 0);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Incomplete test implementation for challenge functionality.

This test verifies that non-participants cannot challenge payouts, but most of the test logic is commented out. The test currently only validates the initial error condition but doesn't test the rest of the challenge management workflow.

Consider uncommenting and completing the test implementation to verify all aspects of the challenge lifecycle:

  • Creation of multiple challenges
  • Resolution of challenges by admin
  • Removal of resolved challenges
  • Verification of challenge count before and after operations

Comment on lines +234 to 242
pub fn validate_application_whitelist(env: &Env, round_id: u128, applicant: &Address) {
let round = read_round_info(env, round_id);
let list_id = round.application_wl_list_id.unwrap();
let list_contract = read_config(env).list_contract;
let list_client = ListsClient::new(env, &list_contract);
let is_whitelisted = list_client.is_registered(&Some(list_id), &applicant, &Some(RegistrationStatus::Approved));
if !is_whitelisted {
panic_with_error!(env, RoundError::UserNotWhitelisted);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Same defensive check needed for application whitelist validation.

Like the voting whitelist validation, this function should check if use_whitelist_application is true before attempting to unwrap the list ID.

pub fn validate_application_whitelist(env: &Env, round_id: u128, applicant: &Address) {
    let round = read_round_info(env, round_id);
+   if !round.use_whitelist_application {
+       panic_with_error!(env, RoundError::WhitelistNotEnabled);
+   }
    let list_id = round.application_wl_list_id.unwrap();
    let list_contract = read_config(env).list_contract;
    let list_client = ListsClient::new(env, &list_contract);
    let is_whitelisted = list_client.is_registered(&Some(list_id), &applicant, &Some(RegistrationStatus::Approved));
    if !is_whitelisted {
        panic_with_error!(env, RoundError::UserNotWhitelisted);
    }
}
📝 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
pub fn validate_application_whitelist(env: &Env, round_id: u128, applicant: &Address) {
let round = read_round_info(env, round_id);
let list_id = round.application_wl_list_id.unwrap();
let list_contract = read_config(env).list_contract;
let list_client = ListsClient::new(env, &list_contract);
let is_whitelisted = list_client.is_registered(&Some(list_id), &applicant, &Some(RegistrationStatus::Approved));
if !is_whitelisted {
panic_with_error!(env, RoundError::UserNotWhitelisted);
}
pub fn validate_application_whitelist(env: &Env, round_id: u128, applicant: &Address) {
let round = read_round_info(env, round_id);
if !round.use_whitelist_application {
panic_with_error!(env, RoundError::WhitelistNotEnabled);
}
let list_id = round.application_wl_list_id.unwrap();
let list_contract = read_config(env).list_contract;
let list_client = ListsClient::new(env, &list_contract);
let is_whitelisted = list_client.is_registered(&Some(list_id), &applicant, &Some(RegistrationStatus::Approved));
if !is_whitelisted {
panic_with_error!(env, RoundError::UserNotWhitelisted);
}
}

Comment on lines +762 to 764
validate_blacklist(env, round_id, &voter); // validate that user is not already blacklisted
add_to_blacklist(env, round_id, voter.clone());
log_update_user_flag(env, round.id, voter.clone(), true);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Logic issue in blacklist validation.

The validate_blacklist function is called to check if a user is not already blacklisted, but the function name suggests the opposite.

Either rename the function to better reflect its purpose or change the function call:

- validate_blacklist(env, round_id, &voter); // validate that user is not already blacklisted
+ // Option 1: Use a better named function
+ validate_not_already_blacklisted(env, round_id, &voter);

+ // Option 2: Invert the check in the existing function
+ if is_blacklisted(env, round_id, voter.clone()) {
+     panic_with_error!(env, Error::UserAlreadyBlacklisted);
+ }
📝 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
validate_blacklist(env, round_id, &voter); // validate that user is not already blacklisted
add_to_blacklist(env, round_id, voter.clone());
log_update_user_flag(env, round.id, voter.clone(), true);
if is_blacklisted(env, round_id, voter.clone()) {
panic_with_error!(env, Error::UserAlreadyBlacklisted);
}
add_to_blacklist(env, round_id, voter.clone());
log_update_user_flag(env, round.id, voter.clone(), true);
Suggested change
validate_blacklist(env, round_id, &voter); // validate that user is not already blacklisted
add_to_blacklist(env, round_id, voter.clone());
log_update_user_flag(env, round.id, voter.clone(), true);
validate_not_already_blacklisted(env, round_id, &voter);
add_to_blacklist(env, round_id, voter.clone());
log_update_user_flag(env, round.id, voter.clone(), true);

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
stellar/deploy.testnet.sh (1)

5-6: Use simple assignment instead of array assignment for contract IDs
Assigning the output of stellar contract deploy to an array and then expanding it can cause splitting issues (SC2207/SC2128). Since each command returns a single contract ID, prefer a quoted simple assignment.

- lists_contract_id=($(stellar contract deploy --wasm target/wasm32-unknown-unknown/release/lists_opt.wasm --source potlock-testnet --network testnet))
- registry_contract_id=($(stellar contract deploy --wasm target/wasm32-unknown-unknown/release/project_registry_opt.wasm --source potlock-testnet --network testnet))
+ lists_contract_id="$(stellar contract deploy --wasm target/wasm32-unknown-unknown/release/lists_opt.wasm --source potlock-testnet --network testnet)"
+ registry_contract_id="$(stellar contract deploy --wasm target/wasm32-unknown-unknown/release/project_registry_opt.wasm --source potlock-testnet --network testnet)"
🧰 Tools
🪛 Shellcheck (0.10.0)

[warning] 5-5: Prefer mapfile or read -a to split command output (or quote to avoid splitting).

(SC2207)


[warning] 6-6: Prefer mapfile or read -a to split command output (or quote to avoid splitting).

(SC2207)

🧹 Nitpick comments (1)
stellar/deploy.testnet.sh (1)

14-15: Quote variables in contract invocation commands
Wrapping interpolated variables in quotes prevents unintended word splitting if values ever contain spaces or special characters. For example:

- stellar contract invoke --source potlock-testnet --network testnet --id ${lists_contract_id} -- initialize --owner ${my_address}
- stellar contract invoke --source potlock-testnet --network testnet --id ${lists_contract_id} -- create_list --owner ${my_address} --name "Test List" --default_registration_status Approved
+ stellar contract invoke --source potlock-testnet --network testnet --id "${lists_contract_id}" -- initialize --owner "${my_address}"
+ stellar contract invoke --source potlock-testnet --network testnet --id "${lists_contract_id}" -- create_list --owner "${my_address}" --name "Test List" --default_registration_status Approved
🧰 Tools
🪛 Shellcheck (0.10.0)

[warning] 14-14: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 14-14: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 15-15: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 15-15: Expanding an array without an index only gives the first element.

(SC2128)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dec973e and 59cc4c3.

⛔ Files ignored due to path filters (6)
  • stellar/packages/lists-client/dist/index.d.ts is excluded by !**/dist/**
  • stellar/packages/lists-client/dist/index.js is excluded by !**/dist/**
  • stellar/packages/project-registry-client/dist/index.d.ts is excluded by !**/dist/**
  • stellar/packages/project-registry-client/dist/index.js is excluded by !**/dist/**
  • stellar/packages/round-client/dist/index.d.ts is excluded by !**/dist/**
  • stellar/packages/round-client/dist/index.js is excluded by !**/dist/**
📒 Files selected for processing (1)
  • stellar/deploy.testnet.sh (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
stellar/deploy.testnet.sh (6)
stellar/contract/lists/src/internal.rs (2)
  • initialize (48-55)
  • create_list (57-126)
stellar/contract/project-registry/src/internal.rs (1)
  • initialize (23-31)
stellar/contract/round/src/factory.rs (1)
  • initialize (6-15)
stellar/contract/lists/src/methods.rs (2)
  • initialize (6-6)
  • create_list (7-16)
stellar/contract/round/src/internal.rs (1)
  • initialize (90-136)
stellar/contract/project-registry/src/methods.rs (1)
  • initialize (6-6)
🪛 Shellcheck (0.10.0)
stellar/deploy.testnet.sh

[warning] 5-5: Prefer mapfile or read -a to split command output (or quote to avoid splitting).

(SC2207)


[warning] 6-6: Prefer mapfile or read -a to split command output (or quote to avoid splitting).

(SC2207)


[warning] 7-7: Prefer mapfile or read -a to split command output (or quote to avoid splitting).

(SC2207)


[warning] 9-9: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 10-10: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 11-11: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 12-12: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 14-14: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 14-14: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 15-15: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 15-15: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 16-16: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 16-16: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 17-17: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 17-17: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 17-17: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 17-17: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 17-17: Expanding an array without an index only gives the first element.

(SC2128)

🔇 Additional comments (1)
stellar/deploy.testnet.sh (1)

19-21: Validate commenting out TypeScript bindings generation
The three stellar contract bindings typescript commands have been commented out. If your CI or developer workflow relies on auto‑generated client bindings, ensure you update documentation or reintroduce these steps in a separate CI job.

Comment on lines +16 to +17
stellar contract invoke --source potlock-testnet --network testnet --id ${registry_contract_id} -- initialize --contract_owner ${my_address}
stellar contract invoke --source potlock-testnet --network testnet --id ${round_contract_id} -- initialize --registry_address ${registry_contract_id} --caller ${my_address} --token_address ${native_token} --protocol_fee_basis_points 200 --protocol_fee_recipient ${my_address} --default_page_size 5 --list_address ${lists_contract_id} --kyc_wl_list_id 1
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid hardcoding the KYC whitelist list ID
Right now you pass --kyc_wl_list_id 1, which assumes the newly created list will always have ID 1. This can break if the network already has existing lists. Consider capturing the list ID from the create_list invocation (e.g., parse stdout or use JSON output) and reusing that variable:

created_list_id=$(stellar contract invoke ... -- create_list ... | jq -r '.id')
stellar contract invoke --source potlock-testnet --network testnet --id "${round_contract_id}" \
  -- initialize \
  --registry_address "${registry_contract_id}" \
  --caller "${my_address}" \
  --token_address "${native_token}" \
  --protocol_fee_basis_points 200 \
  --protocol_fee_recipient "${my_address}" \
  --default_page_size 5 \
  --list_address "${lists_contract_id}" \
  --kyc_wl_list_id "${created_list_id}"
🧰 Tools
🪛 Shellcheck (0.10.0)

[warning] 16-16: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 16-16: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 17-17: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 17-17: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 17-17: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 17-17: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 17-17: Expanding an array without an index only gives the first element.

(SC2128)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
stellar/frontend/project-registry-client/src/index.ts (1)

433-433: Unsafe class-interface merging detected.

This issue was previously flagged by static analysis. The class merging with an interface can be unsafe in TypeScript as it doesn't guarantee that the class implements all interface members.

🧰 Tools
🪛 Biome (1.9.4)

[error] 433-433: This class is unsafely merged with an interface.

The interface is declared here.

The TypeScript compiler doesn't check whether properties defined in the interface are initialized in the class.

(lint/suspicious/noUnsafeDeclarationMerging)

🧹 Nitpick comments (1)
stellar/frontend/project-registry-client/src/index.ts (1)

148-148: Address static analysis warnings for void types.

Static analysis flags the use of void in the union type as confusing. Consider using undefined instead of void for better type clarity.

-export type ContractKey = {tag: "NumOfProjects", values: void} | {tag: "Projects", values: void} | {tag: "Project", values: readonly [u128]} | {tag: "RegistryAdmin", values: void} | {tag: "ApplicantToProjectID", values: readonly [string]};
+export type ContractKey = {tag: "NumOfProjects", values: undefined} | {tag: "Projects", values: undefined} | {tag: "Project", values: readonly [u128]} | {tag: "RegistryAdmin", values: undefined} | {tag: "ApplicantToProjectID", values: readonly [string]};
🧰 Tools
🪛 Biome (1.9.4)

[error] 148-148: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


[error] 148-148: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


[error] 148-148: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59cc4c3 and 2c21fdf.

⛔ Files ignored due to path filters (10)
  • stellar/frontend/lists-client/dist/index.d.ts is excluded by !**/dist/**
  • stellar/frontend/lists-client/dist/index.js is excluded by !**/dist/**
  • stellar/frontend/lists-client/package-lock.json is excluded by !**/package-lock.json
  • stellar/frontend/project-registry-client/dist/index.d.ts is excluded by !**/dist/**
  • stellar/frontend/project-registry-client/dist/index.js is excluded by !**/dist/**
  • stellar/frontend/project-registry-client/package-lock.json is excluded by !**/package-lock.json
  • stellar/frontend/round-client/dist/index.d.ts is excluded by !**/dist/**
  • stellar/frontend/round-client/dist/index.js is excluded by !**/dist/**
  • stellar/frontend/round-client/package-lock.json is excluded by !**/package-lock.json
  • stellar/frontend/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (5)
  • stellar/frontend/lists-client/README.md (2 hunks)
  • stellar/frontend/lists-client/src/index.ts (12 hunks)
  • stellar/frontend/project-registry-client/README.md (2 hunks)
  • stellar/frontend/project-registry-client/src/index.ts (8 hunks)
  • stellar/frontend/round-client/README.md (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • stellar/frontend/round-client/README.md
  • stellar/frontend/lists-client/README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • stellar/frontend/project-registry-client/README.md
🧰 Additional context used
🧬 Code Graph Analysis (1)
stellar/frontend/lists-client/src/index.ts (3)
stellar/frontend/lists-client/dist/index.d.ts (2)
  • ContractKey (84-120)
  • RegistrationStatus (14-29)
stellar/packages/lists-client/src/index.ts (3)
  • ContractKey (107-107)
  • Errors (109-147)
  • RegistrationStatus (41-41)
stellar/frontend/lists-client/dist/index.js (2)
  • Errors (16-36)
  • Errors (16-36)
🪛 Biome (1.9.4)
stellar/frontend/lists-client/src/index.ts

[error] 106-106: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


[error] 106-106: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


[error] 106-106: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

stellar/frontend/project-registry-client/src/index.ts

[error] 148-148: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


[error] 148-148: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


[error] 148-148: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


[error] 433-433: This class is unsafely merged with an interface.

The interface is declared here.

The TypeScript compiler doesn't check whether properties defined in the interface are initialized in the class.

(lint/suspicious/noUnsafeDeclarationMerging)

🔇 Additional comments (15)
stellar/frontend/project-registry-client/src/index.ts (10)

36-36: Contract ID updated for testnet deployment.

The contract ID has been updated to a new value, which aligns with the deployment changes mentioned in the AI summary.


112-112: Field type change from enum to string.

The denomination field has been changed from what was likely an enum to a string type, providing more flexibility for funding denomination specifications.


118-123: New RoundPreCheck interface added.

The new RoundPreCheck interface supports the pre-check functionality for projects and applicants, which aligns with the contract changes mentioned in the AI summary.


144-147: Enhanced error handling with new error codes.

The addition of error codes 10 (DataNotFound) and 11 (AlreadyInitialized) improves error handling capabilities and aligns with the contract's enhanced error management.


215-215: Method signature simplified by removing redundant parameters.

The add_admin method signature has been simplified by removing redundant admin/owner parameters, which aligns with the contract method signature changes mentioned in the AI summary.


235-235: Method signature simplified by removing redundant parameters.

The remove_admin method signature has been simplified by removing redundant admin/owner parameters, consistent with the streamlining of admin management methods.


335-335: Method signature simplified by removing redundant parameters.

The upgrade method signature has been simplified by removing redundant admin/owner parameters, which improves the API's consistency and simplicity.


372-431: New methods added for enhanced functionality.

The addition of owner, get_precheck, and get_precheck_by_id methods aligns with the contract's enhanced functionality for ownership management and pre-check operations.


436-460: Contract specifications updated to reflect interface changes.

The contract specifications have been properly updated to include the new RoundPreCheck interface, updated error codes, and modified method signatures, ensuring the client bindings match the contract implementation.


475-478: JSON mappings updated for new methods.

The fromJSON mappings have been correctly updated to include the new owner, get_precheck, and get_precheck_by_id methods with their appropriate return types.

stellar/frontend/lists-client/src/index.ts (5)

109-145: LGTM! Comprehensive error handling added.

The addition of detailed error messages for all error codes (1-19) significantly improves debugging and user experience. The error mapping is clear and descriptive.


212-212: LGTM! Consistent parameter removal across admin methods.

The removal of owner parameters from delete_list, transfer_ownership, add_admins, remove_admins, clear_admins, and upgrade methods is consistent with the security improvement of using stored authorization.

Also applies to: 272-272, 292-292, 312-312, 332-332, 632-632


592-592: LGTM! Improved method signature for is_registered.

Making list_id mandatory (removing Optional wrapper) improves the API design since checking registration status requires a specific list context.


681-706:

❓ Verification inconclusive

Verify contract specification alignment.

The base64-encoded contract specifications have been updated. Ensure these match the deployed contract's actual interface and that all method signatures are correctly represented.


🏁 Script executed:

#!/bin/bash
# Compare with the dist version to ensure consistency
diff <(grep -o '"[^"]*"' stellar/frontend/lists-client/src/index.ts | head -20) <(grep -o '"[^"]*"' stellar/frontend/lists-client/dist/index.js | head -20) || echo "Specifications may differ between source and dist"

Length of output: 378


🏁 Script executed:

#!/bin/bash
# Extract and sort base64-encoded specs from source and dist for comparison
grep -Eo '"AAAAAAAA[A-Za-z0-9+/=]+"' stellar/frontend/lists-client/src/index.ts \
  | sed 's/"//g' | sort > src_specs.txt

grep -Eo '"AAAAAAAA[A-Za-z0-9+/=]+"' stellar/frontend/lists-client/dist/index.js \
  | sed 's/"//g' | sort > dist_specs.txt

diff src_specs.txt dist_specs.txt || echo "Specifications differ between source and dist"

Length of output: 244


Specs Consistency Verified Locally; Please Confirm Against Deployed Contract

We ran a sorted diff of the base64-encoded specs in src/index.ts vs. dist/index.js and found no discrepancies. All method signatures are identical between source and build.

• src and dist payloads match exactly (no diff output)
• Next step: manually verify these specs against the live contract’s interface on chain to ensure every method signature is correctly represented


192-192:

✅ Verification successful

Verify consistency of owner parameter removal.

The owner parameter has been removed from update_list. This aligns with the broader pattern of using stored authorization rather than passed parameters, which is a security improvement.

Verify that all method signature changes are consistent with the backend contract:


🏁 Script executed:

#!/bin/bash
# Search for any remaining owner parameters in method signatures that might have been missed
rg -A 2 -B 2 "owner.*:" stellar/frontend/lists-client/src/index.ts

Length of output: 3441


Owner parameter removal in update_list confirmed
A ripgrep scan of stellar/frontend/lists-client/src/index.ts shows that update_list no longer destructures or expects an owner field, while other methods (e.g. initialize, create_list, get_lists_for_owner) continue to declare it where required. No unintended removals were detected.

@@ -33,7 +33,7 @@ if (typeof window !== 'undefined') {
export const networks = {
testnet: {
networkPassphrase: "Test SDF Network ; September 2015",
contractId: "CBAASQSA662PIZ26JQFRLDU2Q53WMJOHLUA2UGZE2RE2HZG2M7ZXV3ES",
contractId: "CBD4OK7KMJERD2HM775IXQGY4XE5G3QBV5BFBYMQ6LB4ONFCPBZAXENP",
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify the new contract ID is correct.

The contract ID has been updated for the testnet network. Ensure this corresponds to the correct deployed contract instance.


🏁 Script executed:

#!/bin/bash
# Verify the contract ID exists on Stellar testnet
curl -s "https://horizon-testnet.stellar.org/contracts/CBD4OK7KMJERD2HM775IXQGY4XE5G3QBV5BFBYMQ6LB4ONFCPBZAXENP" | jq '.type'

Length of output: 170


Contract ID Not Found on Stellar Testnet

The contract ID "CBD4OK7KMJERD2HM775IXQGY4XE5G3QBV5BFBYMQ6LB4ONFCPBZAXENP" does not exist according to the Horizon testnet API.

• File: stellar/frontend/lists-client/src/index.ts, line 36
• Action: Verify that the contract is deployed to testnet and update contractId to the correct, existing ID.

🤖 Prompt for AI Agents
In stellar/frontend/lists-client/src/index.ts at line 36, the contractId value
"CBD4OK7KMJERD2HM775IXQGY4XE5G3QBV5BFBYMQ6LB4ONFCPBZAXENP" does not exist on the
Stellar testnet. Verify that the contract has been properly deployed to the
testnet and obtain the correct contract ID. Update the contractId field with
this valid, existing contract ID to ensure the application references the
correct deployed contract.

@@ -103,10 +103,46 @@ export interface RegistrationInput {
updated_ms: Option<u64>;
}

export type ContractKey = {tag: "ContractOwner", values: void} | {tag: "ListsNumber", values: void} | {tag: "Lists", values: void} | {tag: "ListAdmins", values: void} | {tag: "OwnedList", values: void} | {tag: "RegistrantList", values: void} | {tag: "RegistrationsNumber", values: void} | {tag: "Registrations", values: void} | {tag: "ListRegistration", values: void} | {tag: "RegistrationsIDs", values: void} | {tag: "Upvotes", values: void} | {tag: "UserUpvotes", values: void};
export type ContractKey = {tag: "ContractOwner", values: void} | {tag: "ListsNumber", values: void} | {tag: "Lists", values: readonly [u128]} | {tag: "ListAdmins", values: readonly [u128]} | {tag: "OwnedList", values: readonly [string]} | {tag: "RegistrantList", values: readonly [string]} | {tag: "RegistrationsNumber", values: void} | {tag: "Registrations", values: readonly [u128]} | {tag: "ListRegistration", values: readonly [u128]} | {tag: "RegistrationsIDs", values: readonly [string]} | {tag: "Upvotes", values: readonly [u128]} | {tag: "UserUpvotes", values: readonly [string]};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix confusing void usage in union types.

The static analysis tool correctly identifies that using void in union types is confusing and should be avoided. Use undefined instead for better type clarity.

Apply this diff to fix the type definition:

-export type ContractKey = {tag: "ContractOwner", values: void} | {tag: "ListsNumber", values: void} | {tag: "Lists", values: readonly [u128]} | {tag: "ListAdmins", values: readonly [u128]} | {tag: "OwnedList", values: readonly [string]} | {tag: "RegistrantList", values: readonly [string]} | {tag: "RegistrationsNumber", values: void} | {tag: "Registrations", values: readonly [u128]} | {tag: "ListRegistration", values: readonly [u128]} | {tag: "RegistrationsIDs", values: readonly [string]} | {tag: "Upvotes", values: readonly [u128]} | {tag: "UserUpvotes", values: readonly [string]};
+export type ContractKey = {tag: "ContractOwner", values: undefined} | {tag: "ListsNumber", values: undefined} | {tag: "Lists", values: readonly [u128]} | {tag: "ListAdmins", values: readonly [u128]} | {tag: "OwnedList", values: readonly [string]} | {tag: "RegistrantList", values: readonly [string]} | {tag: "RegistrationsNumber", values: undefined} | {tag: "Registrations", values: readonly [u128]} | {tag: "ListRegistration", values: readonly [u128]} | {tag: "RegistrationsIDs", values: readonly [string]} | {tag: "Upvotes", values: readonly [u128]} | {tag: "UserUpvotes", values: readonly [string]};
📝 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
export type ContractKey = {tag: "ContractOwner", values: void} | {tag: "ListsNumber", values: void} | {tag: "Lists", values: readonly [u128]} | {tag: "ListAdmins", values: readonly [u128]} | {tag: "OwnedList", values: readonly [string]} | {tag: "RegistrantList", values: readonly [string]} | {tag: "RegistrationsNumber", values: void} | {tag: "Registrations", values: readonly [u128]} | {tag: "ListRegistration", values: readonly [u128]} | {tag: "RegistrationsIDs", values: readonly [string]} | {tag: "Upvotes", values: readonly [u128]} | {tag: "UserUpvotes", values: readonly [string]};
export type ContractKey =
| { tag: "ContractOwner"; values: undefined }
| { tag: "ListsNumber"; values: undefined }
| { tag: "Lists"; values: readonly [u128] }
| { tag: "ListAdmins"; values: readonly [u128] }
| { tag: "OwnedList"; values: readonly [string] }
| { tag: "RegistrantList"; values: readonly [string] }
| { tag: "RegistrationsNumber"; values: undefined }
| { tag: "Registrations"; values: readonly [u128] }
| { tag: "ListRegistration"; values: readonly [u128] }
| { tag: "RegistrationsIDs"; values: readonly [string] }
| { tag: "Upvotes"; values: readonly [u128] }
| { tag: "UserUpvotes"; values: readonly [string] };
🧰 Tools
🪛 Biome (1.9.4)

[error] 106-106: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


[error] 106-106: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


[error] 106-106: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

🤖 Prompt for AI Agents
In stellar/frontend/lists-client/src/index.ts at line 106, the ContractKey type
uses void in union types, which is confusing. Replace all occurrences of void
with undefined in the values field of the union types to improve type clarity
and satisfy static analysis.

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.

6 participants