Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds a Pot apply flow: new pot client apply(...) and calculateCallDeposit util, DAO proposal submission support, base64 JSON helpers, refactored Pot application UI/hooks/effects to use applyToPot with toast feedback, and minor encoding and label updates across related features. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant UI as PotApplicationModal
participant Hook as usePotApplicationForm
participant Effect as applyToPot
participant Pot as potContractClient
participant DAO as sputnikdao2.client
User->>UI: Submit application
UI->>Hook: onSubmit(message)
Hook->>Effect: applyToPot({ applicantAccountId, asDao, message, potConfig })
alt Direct application (asDao = false)
Effect->>Pot: apply({ potId, args:{message}, deposit, gas, callbackUrl })
Pot-->>Effect: Application result
else DAO proposal (asDao = true)
Effect->>DAO: get_policy(daoAccountId)
DAO-->>Effect: policy
Effect->>DAO: add_proposal({ proposal:{ description, kind: FunctionCall(method:"apply", args: base64Json, deposit, gas) }, proposalBond, callbackUrl })
DAO-->>Effect: ProposalId
end
Effect-->>Hook: success / failure
Hook-->>UI: invoke onSuccess / onFailure
UI-->>User: show toast (success / error)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
src/common/lib/object.ts (1)
58-59: Add error handling for JSON serialization.
JSON.stringifycan throw when encountering circular references or non-serializable values (e.g., functions, symbols). Consider wrapping the serialization in try-catch or documenting the expectation that inputs must be serializable.Apply this diff to add error handling:
-export const objectToBase64Json = (obj: object | Record<string, unknown>): string => - utf8StringToBase64(JSON.stringify(obj)); +export const objectToBase64Json = (obj: object | Record<string, unknown>): string => { + try { + return utf8StringToBase64(JSON.stringify(obj)); + } catch (error) { + throw new Error(`Failed to serialize object to base64 JSON: ${error}`); + } +};
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
src/common/contracts/core/pot/client.ts(3 hunks)src/common/contracts/core/pot/index.ts(1 hunks)src/common/contracts/core/pot/utils.ts(1 hunks)src/common/contracts/sputnikdao2/client.ts(2 hunks)src/common/contracts/sputnikdao2/types.ts(2 hunks)src/common/lib/object.ts(2 hunks)src/common/lib/string.ts(1 hunks)src/features/donation/components/user-entrypoints.tsx(1 hunks)src/features/matching-pool-contribution/hooks/forms.ts(2 hunks)src/features/pot-application/components/PotApplicationModal.tsx(1 hunks)src/features/pot-application/hooks/forms.ts(1 hunks)src/features/pot-application/model/effects.ts(1 hunks)src/features/profile-configuration/models/effects.ts(2 hunks)src/layout/pot/components/layout.tsx(5 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-02-14T13:55:21.902Z
Learnt from: carina-akaia
PR: PotLock/potlock-nextjs-app#341
File: src/entities/campaign/hooks/forms.ts:94-116
Timestamp: 2025-02-14T13:55:21.902Z
Learning: The toast component from shadcn/ui is imported from "@/hooks/use-toast". For success messages, use a simple toast with description. For error states, use the "destructive" variant.
Applied to files:
src/layout/pot/components/layout.tsx
🧬 Code graph analysis (12)
src/features/donation/components/user-entrypoints.tsx (1)
src/common/ui/layout/components/atoms/button.tsx (1)
Button(111-111)
src/features/profile-configuration/models/effects.ts (1)
src/common/lib/object.ts (1)
objectToBase64Json(58-59)
src/features/matching-pool-contribution/hooks/forms.ts (1)
src/common/lib/object.ts (1)
objectToBase64Json(58-59)
src/features/pot-application/model/effects.ts (5)
src/common/contracts/core/pot/client.ts (1)
ApplyArgs(112-114)src/common/api/indexer/internal/client.generated.ts (1)
Pot(857-977)src/common/contracts/sputnikdao2/types.ts (1)
ActionCall(81-91)src/common/lib/object.ts (1)
objectToBase64Json(58-59)src/common/constants.ts (1)
ONE_TGAS(152-152)
src/common/contracts/core/pot/client.ts (4)
src/common/api/indexer/types.ts (1)
ByPotId(11-13)src/common/contracts/core/pot/interfaces.ts (1)
Application(16-23)src/common/contracts/core/pot/utils.ts (1)
calculateCallDeposit(14-30)src/common/constants.ts (1)
ONE_TGAS(152-152)
src/common/lib/object.ts (1)
src/common/lib/string.ts (1)
utf8StringToBase64(39-40)
src/common/contracts/sputnikdao2/client.ts (3)
src/common/contracts/sputnikdao2/types.ts (2)
ProposalInput(152-155)ProposalId(189-189)src/common/types.ts (1)
IndivisibleUnits(92-92)src/common/constants.ts (1)
FULL_TGAS(145-145)
src/common/contracts/core/pot/utils.ts (4)
src/common/contracts/core/pot/client.ts (1)
ApplyArgs(112-114)src/common/types.ts (1)
IndivisibleUnits(92-92)src/common/lib/format.ts (1)
parseNearAmount(7-7)src/common/constants.ts (1)
ONE_HUNDREDTH_NEAR(141-141)
src/layout/pot/components/layout.tsx (2)
src/layout/pot/hooks/tab-navigation.ts (1)
usePotLayoutTabNavigation(157-225)src/common/ui/layout/components/templates/page-with-banner.tsx (1)
PageWithBanner(8-12)
src/features/pot-application/hooks/forms.ts (3)
src/common/types.ts (1)
AccountId(45-45)src/common/api/indexer/internal/client.generated.ts (1)
Pot(857-977)src/features/pot-application/model/effects.ts (1)
applyToPot(15-57)
src/common/contracts/sputnikdao2/types.ts (1)
src/common/types.ts (1)
IndivisibleUnits(92-92)
src/features/pot-application/components/PotApplicationModal.tsx (2)
src/features/pot-application/hooks/forms.ts (2)
PotApplicationFormParams(18-24)usePotApplicationForm(26-57)src/common/ui/form/components/textarea.tsx (1)
TextAreaField(20-66)
🔇 Additional comments (21)
src/features/donation/components/user-entrypoints.tsx (1)
75-75: LGTM! Consistent label across donation entry points.The label now matches the one used in
DonateToPotProjects(Line 67), improving UI consistency.src/common/contracts/sputnikdao2/types.ts (2)
90-90: LGTM! Correct type for gas values.Changing
gasfromnumbertoIndivisibleUnits(string) aligns with NEAR protocol standards, where gas values can exceed JavaScript's safe integer range.
152-155: LGTM! Clean input type for proposals.The new
ProposalInputtype provides a focused interface for proposal creation, separating input concerns from the fullProposaltype that includes runtime state.src/features/matching-pool-contribution/hooks/forms.ts (1)
41-41: No UTF-8 encoding issues in objectToBase64Json
utf8StringToBase64leveragesBuffer.from(value, "utf8").toString("base64"), which correctly encodes UTF-8 strings. No changes required.src/common/contracts/core/pot/utils.ts (1)
14-30: Verify calculateDepositByDataSize units and multiplier
- Does calculateDepositByDataSize (from @wpdas/naxios) return a value in NEAR or yoctoNEAR?
- Is the 0.01× factor intended for the “apply” deposit formula?
- Are there edge cases (very small/large data) where this produces under- or oversized deposits?
Location: src/common/contracts/core/pot/utils.ts:21
src/common/contracts/sputnikdao2/client.ts (1)
29-44: Verify gas allocation for add_proposalAll calls to add_proposal currently attach FULL_TGAS (300 Tgas per transaction, NEAR’s maximum) (docs.near.org). If your proposals consistently consume ≤200 Tgas, reduce the attachment to save fees (e.g.
"200000000000000"for 200 Tgas) and confirm no “Exceeded prepaid gas” errors. Only retain FULL_TGAS if specific proposal kinds genuinely require >200 Tgas.src/common/contracts/core/pot/index.ts (1)
3-3: LGTM!Clean addition of the utility export to the pot contract barrel, enabling access to deposit calculation helpers.
Also applies to: 8-8
src/features/profile-configuration/models/effects.ts (1)
23-23: LGTM! Standardized base64 encoding for DAO proposals.The replacement of direct Buffer usage with
objectToBase64Jsonimproves consistency. The?? {}fallback ensures undefined args are handled gracefully. Error handling is covered by the outer.catchblocks.Also applies to: 123-123
src/features/pot-application/model/effects.ts (2)
47-53: Error handling delegated to caller.The promise chain returns unhandled rejections to the caller. Ensure the calling code (likely in the form hook or modal) has appropriate error handling and user feedback for both policy retrieval and proposal submission failures.
15-57: Well-structured dual-path application flow.The implementation cleanly separates DAO proposal submission from direct application. The DAO path correctly constructs a Sputnik DAO v2 proposal with base64-encoded args and calculated deposit.
src/common/contracts/core/pot/client.ts (3)
112-114: LGTM!The type definition correctly defines the application arguments with an optional message field.
2-2: Fix the import syntax for big.js.The library exports
Bigas the default export, not a named export. This will cause a runtime error.Apply this diff:
-import { Big } from "big.js"; +import Big from "big.js";⛔ Skipped due to learnings
Learnt from: akaia-shadowfox PR: PotLock/potlock-nextjs-app#451 File: src/features/profile-configuration/models/effects.ts:2-2 Timestamp: 2025-09-29T11:23:41.179Z Learning: In big.js, both import patterns work: `import { Big } from "big.js"` (named import) and `import Big from "big.js"` (default import) are functionally equivalent due to TypeScript's CommonJS interoperability with the library's `export = Big` pattern.Learnt from: akaia-shadowfox PR: PotLock/potlock-nextjs-app#451 File: src/features/profile-configuration/models/effects.ts:2-2 Timestamp: 2025-09-29T11:23:41.179Z Learning: In big.js, both import patterns work: `import { Big } from "big.js"` (named import) and `import Big from "big.js"` (default import) are functionally equivalent due to TypeScript's module interoperability features.
116-126: Confirm apply gas allocation
Theapplycall usesONE_TGAS.mul(100)(100 TGas) while all other pot operations useFULL_TGAS(300 TGas). Ensure 100 TGas is sufficient for the apply operation, or switch toFULL_TGASif not.src/layout/pot/components/layout.tsx (3)
29-29: LGTM!The toast hook and data fetching are correctly implemented.
Also applies to: 47-48
50-60: LGTM!The success callback correctly closes the modal and displays an appropriate success toast message that distinguishes between DAO and direct application flows.
105-113: LGTM!The modal props are correctly updated to use the new
potConfigprop and wire the success/failure callbacks.src/features/pot-application/hooks/forms.ts (2)
18-24: LGTM!The type definition correctly captures all parameters needed for the unified application flow.
26-56: LGTM!The refactored hook correctly delegates to
applyToPotand handles success/failure flows appropriately. The form reset on success ensures a clean state for subsequent submissions.src/features/pot-application/components/PotApplicationModal.tsx (3)
16-23: LGTM!The props type correctly leverages
Pickto maintain type consistency withPotApplicationFormParams.
36-42: LGTM!The form hook is correctly invoked with all required parameters.
51-83: Disable logic is correct: message is required by schema.
ThepotApplicationSchemamandates amessagewith at least 3 characters, so blocking submission untilform.formState.isValidis true is intentional and should remain.Likely an incorrect or invalid review comment.
| args: applyArgs, | ||
| }), | ||
|
|
||
| gas: ONE_TGAS.toString(), |
There was a problem hiding this comment.
🧩 Analysis chain
Verify gas allocation is sufficient for pot application.
The gas is set to ONE_TGAS (1 TGas). Ensure this is adequate for the apply method on the pot contract, as insufficient gas will cause the proposal execution to fail.
Run the following script to check the pot contract's apply method implementation and gas usage patterns:
🏁 Script executed:
#!/bin/bash
# Search for pot contract apply method and gas patterns
echo "Searching for apply method gas requirements:"
rg -n "apply.*gas|gas.*apply" --type ts -C3
echo "---"
echo "Other pot contract gas allocations:"
rg -n "potContract.*gas|ONE_TGAS|FIFTY_TGAS|FULL_TGAS" --type ts -C2Length of output: 20489
🏁 Script executed:
#!/bin/bash
# Show pot-application effects code context
rg -n "potContract" -C4 src/features/pot-application/model/effects.ts
# Show apply usage in pot-application effects
rg -n "apply" -C4 src/features/pot-application/model/effects.tsLength of output: 2011
Increase DAO apply action gas to 100 TGas. In applyToPot (src/features/pot-application/model/effects.ts:32), replace
gas: ONE_TGAS.toString(),with
gas: ONE_TGAS.mul(100).toString(),so that DAO-submitted proposals use the same 100 TGas default as potContractClient.apply and avoid execution failures.
🤖 Prompt for AI Agents
In src/features/pot-application/model/effects.ts around line 32, the gas for the
DAO apply action is set to ONE_TGAS.toString() which is too low; update the gas
value to use 100 TGas by replacing that assignment with
ONE_TGAS.mul(100).toString() so DAO-submitted proposals use the same 100 TGas
default as potContractClient.apply and avoid execution failures.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/layout/pot/components/layout.tsx (1)
62-74: Fixed: Destructive variant now present.The error toast now correctly includes
variant: "destructive"as per project conventions. The issue raised in the previous review has been resolved.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/common/lib/string.ts(1 hunks)src/layout/pot/components/layout.tsx(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/common/lib/string.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-02-14T13:55:21.902Z
Learnt from: carina-akaia
PR: PotLock/potlock-nextjs-app#341
File: src/entities/campaign/hooks/forms.ts:94-116
Timestamp: 2025-02-14T13:55:21.902Z
Learning: The toast component from shadcn/ui is imported from "@/hooks/use-toast". For success messages, use a simple toast with description. For error states, use the "destructive" variant.
Applied to files:
src/layout/pot/components/layout.tsx
🧬 Code graph analysis (1)
src/layout/pot/components/layout.tsx (2)
src/layout/pot/hooks/tab-navigation.ts (1)
usePotLayoutTabNavigation(157-225)src/common/ui/layout/components/templates/page-with-banner.tsx (1)
PageWithBanner(8-12)
🔇 Additional comments (6)
src/layout/pot/components/layout.tsx (6)
8-8: LGTM: useToast import added.The import is correctly placed and supports the new toast-based feedback mechanism.
29-29: LGTM: useToast hook properly initialized.The hook is correctly destructured to access the toast function.
50-60: LGTM: Success callback properly implemented.The success handler correctly closes the modal and shows contextual feedback based on whether the user is a DAO representative. The toast follows project conventions for success messages.
79-82: LGTM: Clear technical debt marker.The FIXME comment appropriately flags that this modal should be replaced with toast calls, aligning with the PR's direction toward toast-based feedback.
90-93: LGTM: Consistent technical debt documentation.The FIXME comment matches the pattern established above and clearly marks the need to replace this modal with toast calls.
108-116: No action needed; types align. TheusePothook returnsdataof typePot, which exactly matches thePotApplicationModal’spotConfig: Potprop.
| const { activeTab, orderedTabList } = usePotLayoutTabNavigation({ potId }); | ||
| const { data: pot } = indexer.usePot({ potId }); |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Verify error handling for pot data query.
The component now fetches pot data using indexer.usePot, but there's no visible error or loading state handling. If the query fails or is loading, the modals at line 100 won't render (due to the pot && condition), but users won't see any feedback about what's happening.
Consider adding loading and error states:
const { data: pot, isLoading, error } = indexer.usePot({ potId });
// Show loading state
if (isLoading) {
return <PageWithBanner><LoadingSpinner /></PageWithBanner>;
}
// Show error state
if (error) {
return <PageWithBanner><ErrorMessage error={error} /></PageWithBanner>;
}Run this script to check if error handling exists elsewhere in the component or related hooks:
🏁 Script executed:
#!/bin/bash
# Check if indexer.usePot returns error/loading states and if they're handled
ast-grep --pattern 'indexer.usePot'
# Check for error handling patterns in the file
rg -n "isLoading|isError|error" src/layout/pot/components/layout.tsxLength of output: 1847
🏁 Script executed:
#!/bin/bash
sed -n '1,120p' src/layout/pot/components/layout.tsxLength of output: 4256
Handle loading and error for usePot in PotLayout (src/layout/pot/components/layout.tsx:47-48)
Destructure isLoading and error from indexer.usePot and early-return a spinner or error banner to ensure users see fetch status before rendering the layout.
🤖 Prompt for AI Agents
In src/layout/pot/components/layout.tsx around lines 47-48, the call to
indexer.usePot only destructures data and doesn't handle loading or error
states; update the hook call to also destructure isLoading and error, then add
early returns: if isLoading return a Spinner (or loading component) centered
where the layout would render, and if error return an ErrorBanner (or simple
error message) with context (e.g., "Failed to load pot"). Keep the existing
activeTab and orderedTabList logic intact and only render the full PotLayout
when isLoading is false and error is null.
Summary by CodeRabbit
New Features
UI
Refactor