Skip to content

updated create-pool and implemented bulk addMember#318

Open
iYukay wants to merge 9 commits intoGoodDollar:masterfrom
iYukay:create-pool-flow
Open

updated create-pool and implemented bulk addMember#318
iYukay wants to merge 9 commits intoGoodDollar:masterfrom
iYukay:create-pool-flow

Conversation

@iYukay
Copy link
Copy Markdown

@iYukay iYukay commented Mar 11, 2026

Title: Create‑pool copy refresh + bulk add members

Summary:

  • Updated create‑pool screens with Figma copy.
  • Added initial members input and bulk add via SDK in create‑pool flow
  • Terms of Use is now clickable

Testing:

  • yarn workspace @gooddollar/goodcollective-contracts compile
  • yarn workspace @gooddollar/goodcollective-sdk build

Summary by Sourcery

Refresh the create-pool flow copy and add support for specifying and bulk-adding initial pool members.

New Features:

  • Allow pool creators to optionally input initial member wallet addresses when configuring a pool.
  • Bulk-add initial pool members to the newly created pool via the GoodCollective SDK.
  • Make the Terms of Use in the welcome screen clickable, including a direct link to the terms URL.

Enhancements:

  • Update welcome and pool type selection copy to match current product messaging and clarify available pool types.
  • Add validation for initial member wallet addresses, including format checks and maximum member count constraints.
  • Adjust pool configuration logic so closed pools are treated as members-only when creating UBI settings.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • In Welcome.tsx, the terms of use are rendered as two separate clickable Text elements with identical onPress handlers; consider consolidating this into a single clearly-labeled touch target to reduce duplication and improve accessibility/UX.
  • The projectId generation in CreatePoolProvider uses replace(' ', '/'), which only replaces the first space; if multiple spaces are expected, consider using a global regex or split/join to normalize the name consistently.
  • In usePoolConfigurationValidation, the comparison members.length > maximumMembers will silently do nothing when maximumMembers is undefined; if this check should only run when a max is explicitly set, consider guarding it with an explicit maximumMembers != null to make the intent clearer.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `Welcome.tsx`, the terms of use are rendered as two separate clickable `Text` elements with identical `onPress` handlers; consider consolidating this into a single clearly-labeled touch target to reduce duplication and improve accessibility/UX.
- The `projectId` generation in `CreatePoolProvider` uses `replace(' ', '/')`, which only replaces the first space; if multiple spaces are expected, consider using a global regex or `split/join` to normalize the name consistently.
- In `usePoolConfigurationValidation`, the comparison `members.length > maximumMembers` will silently do nothing when `maximumMembers` is undefined; if this check should only run when a max is explicitly set, consider guarding it with an explicit `maximumMembers != null` to make the intent clearer.

## Individual Comments

### Comment 1
<location path="packages/app/src/hooks/useCreatePool/CreatePoolContext.tsx" line_range="105-113" />
<code_context>
       return false;
     }

+    const rawRecipients = form.poolRecipients?.trim() ?? '';
+    const memberAddresses = rawRecipients ? parseMemberAddresses(rawRecipients) : [];
+    if (rawRecipients) {
+      const memberError = validateMemberAddresses(memberAddresses);
+      if (memberError) {
+        console.error(memberError);
+        return false;
+      }
+      if (form.maximumMembers && memberAddresses.length > form.maximumMembers) {
+        console.error(`Members count (${memberAddresses.length}) exceeds maximum (${form.maximumMembers}).`);
+        return false;
</code_context>
<issue_to_address>
**suggestion:** Recipient validation logic is duplicated here and in `usePoolConfigurationValidation`, which risks drift.

Parsing and validating recipient addresses (including the `maximumMembers` length check) now happens both in this context and in `usePoolConfigurationValidation`. This duplication makes it easy for rules (regex, formatting, limits) to diverge. Consider centralizing this in a shared utility—building on `parseMemberAddresses`/`validateMemberAddresses`—and having both the hook and context call the same higher-level validator.

Suggested implementation:

```typescript
    const sdk = new GoodCollectiveSDK(chainIdString, signer.provider as ethers.providers.Provider, { network });

    const validatePoolRecipients = (
      rawRecipients: string | undefined,
      maximumMembers?: number,
    ): {
      isValid: boolean;
      memberAddresses: string[];
      error?: string;
    } => {
      const trimmedRecipients = rawRecipients?.trim() ?? '';

      if (!trimmedRecipients) {
        return { isValid: true, memberAddresses: [] };
      }

      const memberAddresses = parseMemberAddresses(trimmedRecipients);
      const memberError = validateMemberAddresses(memberAddresses);

      if (memberError) {
        return { isValid: false, memberAddresses, error: memberError };
      }

      if (maximumMembers && memberAddresses.length > maximumMembers) {
        return {
          isValid: false,
          memberAddresses,
          error: `Members count (${memberAddresses.length}) exceeds maximum (${maximumMembers}).`,
        };
      }

      return { isValid: true, memberAddresses };
    };

    // Final form validation

```

```typescript
    const recipientsValidation = validatePoolRecipients(form.poolRecipients, form.maximumMembers);

    if (!recipientsValidation.isValid) {
      if (recipientsValidation.error) {
        console.error(recipientsValidation.error);
      }
      return false;
    }

    const { memberAddresses } = recipientsValidation;

```

To fully address the duplication with `usePoolConfigurationValidation`, you should:
1. Move `validatePoolRecipients` into a shared utility module (for example, `packages/app/src/utils/poolRecipients.ts`) so it is not tied to this context.
2. Update this file to import `validatePoolRecipients` from that shared module instead of defining it inline.
3. Update `usePoolConfigurationValidation` to call the shared `validatePoolRecipients` helper (and remove its local recipient parsing/validation logic), ensuring both the hook and this context share the same rules and error messages.
</issue_to_address>

### Comment 2
<location path="packages/app/src/hooks/useCreatePool/CreatePoolContext.tsx" line_range="150-156" />
<code_context>
     // Calculate cycle length based on claim frequency
     const cycleLengthDays = form.claimFrequency && form.claimFrequency <= 7 ? 7 : form.claimFrequency || 1;

+    const onlyMembers = form.joinStatus === 'closed';
     const ubiSettings: UBISettings = {
       claimPeriodDays: ethers.BigNumber.from(form.claimFrequency || 1),
       minActiveUsers: ethers.BigNumber.from(1),
       maxClaimAmount: ethers.utils.parseEther(String(form.claimAmountPerWeek || 0)),
       maxMembers: form.maximumMembers || form.expectedMembers || 100,
-      onlyMembers: form.poolRecipients ? form.canNewMembersJoin ?? false : false,
+      onlyMembers,
       cycleLengthDays: ethers.BigNumber.from(cycleLengthDays),
       claimForEnabled: false,
</code_context>
<issue_to_address>
**question:** Revisiting the `onlyMembers` logic now that it’s based solely on `joinStatus`.

Previously, `onlyMembers` also depended on `form.poolRecipients` being set, but now it’s purely `joinStatus === 'closed'`. With this change, a pool that is `closed` and has no initial members will still have `onlyMembers = true`, which may prevent anyone from ever joining. If that’s not the intended behavior, consider conditioning `onlyMembers` on both `joinStatus` and the presence of initial members, or clearly define and enforce the expected behavior for empty-member pools.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@iYukay
Copy link
Copy Markdown
Author

iYukay commented Mar 11, 2026

Hi @L03TJ3 , I just made a video walkthrough showing the functional fixes
Video Demo

@iYukay iYukay deployed to external March 11, 2026 21:48 — with GitHub Actions Active
@L03TJ3 L03TJ3 linked an issue Mar 13, 2026 that may be closed by this pull request
3 tasks
Copy link
Copy Markdown
Collaborator

@L03TJ3 L03TJ3 left a comment

Choose a reason for hiding this comment

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

Homepage

  1. homepage styles are not aligned with figma (no emphasising with bold text). also, test on mobile screens. the spacing of the words is weird.

  2. the confirm terms of use should be a clickable link, not include the link (figma was just showing where the link should lead to. So: terms of use itself should be clickable, redirecting to > url

  3. the checkbox should be confirmed before able to click on get started

create a pool screen

  1. the link is not clickable

@iYukay
Copy link
Copy Markdown
Author

iYukay commented Mar 20, 2026

Hi @L03TJ3 ,,,,
I have resolved the homepage and create‑pool feedback, updated the mobile view to match the styles on, made Telegram link clickable, and enforced checkbox gating before Get Started.

@iYukay iYukay requested a review from L03TJ3 March 20, 2026 10:27
@L03TJ3
Copy link
Copy Markdown
Collaborator

L03TJ3 commented Mar 26, 2026

Hey, sorry that I see this so late. but you produced a demo-video but not actually launched the pool?
how has it been verified that the bulkAdd members worked?
@iYukay

@iYukay
Copy link
Copy Markdown
Author

iYukay commented Mar 27, 2026

Hi @L03TJ3. I attempted to launch with multiple initial members, but the flow fails at bulk‑add with addMembers is not a function. It looks like the SDK contract instance is using an ABI that doesn’t include addMembers, so I can’t verify. I want to clarify if am supposed to work on the sdk too?

@L03TJ3
Copy link
Copy Markdown
Collaborator

L03TJ3 commented Mar 27, 2026

Okay. Lets do it like this.
The main bulk of this work has been confirmed to be changed accordingly. (the copy updates)

So we just have to test the bulk-add.

you can pull in the changes of this pull-request (your other assigned item): #315

and include the changes here.
And test both creating a pool with using a list of members + testing the member admin area and bulkAdd members.
this will be the final pull-request and we will close the other. (you will get your reward as has been assigned)
@iYukay

@iYukay
Copy link
Copy Markdown
Author

iYukay commented Mar 27, 2026

Alright @L03TJ3

Makes sense

@iYukay
Copy link
Copy Markdown
Author

iYukay commented Mar 28, 2026

Test Summary – PR #318 / #314

I tested both bulk-add flows related to #314:

  • Adding multiple members during pool creation
  • Bulk adding members after pool deployment from the Member Management tab

Important Note on UBI Pools
For UBI pools, added addresses must pass the pool’s uniqueness validator. Random wallet addresses were rejected. So I used eligible addresses for successful tests. Ineligible addresses now show clear error messages in the UI.

Results

  • Bulk add works from the UI after a pool is deployed
  • Multiple addresses can be submitted in one action
  • Address parsing and validation work correctly
  • The UI now gives clearer loading, success, and error feedback
  • Manager action visibility is more stable during refresh
  • Member data refresh behavior is improved after add/remove actions

Demo Video
https://www.loom.com/share/83d52b659d024f638223d219aec1e1ca

@L03TJ3

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.

Update: Create a UBI Pool

2 participants