-
Notifications
You must be signed in to change notification settings - Fork 8
FT support for campaigns #388
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
FT support for campaigns #388
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Caution Review failedThe pull request is closed. WalkthroughThis update introduces full support for fungible token (FT) donations to campaigns, including a new multicall function for campaign FT donations, enhanced contract client APIs, and comprehensive refactoring of token handling across campaign and donation components. It also generalizes token display, selection, and validation, and updates related types, schemas, and UI logic. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI
participant DonationForm
participant CampaignsContract
participant FTContract
User->>UI: Selects campaign and token, enters amount
UI->>DonationForm: Submits donation with token info
DonationForm->>FTContract: Check storage balance, deposit if needed
DonationForm->>CampaignsContract: Get config (for protocol fee recipient)
DonationForm->>FTContract: ft_transfer_call (send donation to campaign)
FTContract-->>CampaignsContract: Triggers on_transfer with donation details
CampaignsContract-->>DonationForm: Returns donation receipt
DonationForm-->>UI: Show donation success and updated campaign progress
Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
Note ⚡️ AI Code Reviews for VS Code, Cursor, WindsurfCodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback. 📜 Recent review detailsConfiguration used: .coderabbit.yaml 📒 Files selected for processing (1)
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
…375-campaigns-campaign-ft-donation-support
…375-campaigns-campaign-ft-donation-support
…375-campaigns-campaign-ft-donation-support
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🔭 Outside diff range comments (1)
src/common/contracts/core/donation/client.ts (1)
47-71
: 🛠️ Refactor suggestion
⚠️ Potential issueGood type safety improvement, but address the empty object type.
The use of
IndivisibleUnits
type for deposit amounts improves type safety. However, the static analysis correctly flags an issue with the empty object type.Apply this diff to fix the empty object type:
-export const storage_deposit = (depositAmountYocto: IndivisibleUnits) => - contractApi.call<{}, IndivisibleUnits>("storage_deposit", { +export const storage_deposit = (depositAmountYocto: IndivisibleUnits) => + contractApi.call<Record<string, never>, IndivisibleUnits>("storage_deposit", { deposit: depositAmountYocto, args: {}, gas: "100000000000000", });Using
Record<string, never>
explicitly indicates an empty object with no properties, which is more precise than the{}
type.🧰 Tools
🪛 Biome (1.9.4)
[error] 67-67: Don't use '{}' as a type.
Prefer explicitly define the object shape. '{}' means "any non-nullable value".
(lint/complexity/noBannedTypes)
🧹 Nitpick comments (7)
src/entities/campaign/components/CampaignSettings.tsx (1)
94-97
: Optimize the memoized token icon.The
tokenIcon
creates a new React element on every render, which defeats the purpose of memoization. Consider memoizing just the token ID and rendering the icon inline.- const tokenIcon = useMemo( - () => <TokenIcon tokenId={campaign?.ft_id ?? NATIVE_TOKEN_ID} />, - [campaign?.ft_id], - ); + const tokenId = campaign?.ft_id ?? NATIVE_TOKEN_ID;Then use
<TokenIcon tokenId={tokenId} />
directly in the JSX where needed.src/entities/campaign/components/CampaignForm.tsx (1)
135-145
: Remove unnecessary memoization.The
selectedTokenIndicator
is always disabled and doesn't depend on any changing values. This memoization adds complexity without benefit.- const selectedTokenIndicator = useMemo( - () => ( - <FormField - control={form.control} - name="ft_id" - render={() => <TokenSelector disabled value={ftId} />} - /> - ), - - [form.control, ftId], - );Then inline the JSX directly where it's used:
- inputExtension={selectedTokenIndicator} + inputExtension={<TokenSelector disabled value={ftId} />}src/features/donation/models/effects/index.ts (1)
145-146
: Address TODO: bypass_creator_fee functionalityThe
bypass_creator_fee
is hardcoded tofalse
with TODOs indicating the functionality might be required. This could impact fee collection for campaign creators.Would you like me to help implement the bypass_creator_fee functionality or create an issue to track this requirement?
Also applies to: 163-164
src/entities/campaign/hooks/forms.ts (1)
183-183
: Remove outdated TODO comment.The TODO comment is no longer relevant as the implementation below correctly uses token metadata for amount conversion.
- // TODO: Use token metadata to convert amounts const onSubmit: SubmitHandler<Values> = useCallback(
src/entities/campaign/components/CampaignProgressBar.tsx (1)
181-192
: Optimize memoization dependencies to avoid redundancy.The dependency array includes both
amountDisplay
and its constituent values (tokenId
,raisedAmountFloat
,targetAmountFloat
,token?.metadata.symbol
), which creates redundancy.}, [ amountDisplay, isTimeUp, isTargetMet, - raisedAmountFloat, minAmountFLoat, isEscrowBalanceEmpty, color, - tokenId, - targetAmountFloat, - token?.metadata.symbol, ]);src/entities/_shared/token/components/selector.tsx (1)
31-31
: Optimize balance fetching logic.Consider simplifying the boolean logic for better readability.
- balanceCheckAccountId: showBalance || skipIfZeroBalance ? viewer?.accountId : undefined, + balanceCheckAccountId: (showBalance || skipIfZeroBalance) ? viewer?.accountId : undefined,src/features/donation/models/effects/campaign-ft-donation.ts (1)
226-232
: Enhance error handling for receipt parsing.Consider adding more specific error handling for JSON parsing failures.
try { return [JSON.parse(decodedReceipt) as CampaignDonation]; - } catch { + } catch (error) { + console.warn("Failed to parse donation receipt:", error); return acc; }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (37)
.vscode/settings.json
(3 hunks)src/common/contracts/core/campaigns/client.ts
(2 hunks)src/common/contracts/core/campaigns/interfaces.ts
(2 hunks)src/common/contracts/core/donation/client.ts
(4 hunks)src/common/ui/form/components/select.tsx
(1 hunks)src/entities/_shared/token/components/inputs.tsx
(0 hunks)src/entities/_shared/token/components/selector.tsx
(2 hunks)src/entities/_shared/token/hooks/data.ts
(1 hunks)src/entities/_shared/token/index.ts
(0 hunks)src/entities/campaign/components/CampaignBanner.tsx
(6 hunks)src/entities/campaign/components/CampaignCard.tsx
(4 hunks)src/entities/campaign/components/CampaignCarouselItem.tsx
(2 hunks)src/entities/campaign/components/CampaignDonationItem.tsx
(0 hunks)src/entities/campaign/components/CampaignDonorsTable.tsx
(3 hunks)src/entities/campaign/components/CampaignForm.tsx
(15 hunks)src/entities/campaign/components/CampaignProgressBar.tsx
(3 hunks)src/entities/campaign/components/CampaignSettings.tsx
(6 hunks)src/entities/campaign/hooks/forms.ts
(7 hunks)src/entities/campaign/models/schema.ts
(2 hunks)src/entities/voting-round/hooks/vote-weight.ts
(1 hunks)src/entities/voting-round/utils/weight.ts
(1 hunks)src/features/donation/components/group-allocation.tsx
(1 hunks)src/features/donation/components/modal-confirmation-screen.tsx
(4 hunks)src/features/donation/components/modal-content.tsx
(2 hunks)src/features/donation/components/modal.tsx
(1 hunks)src/features/donation/components/single-recipient-allocation.tsx
(5 hunks)src/features/donation/components/single-recipient-success.tsx
(2 hunks)src/features/donation/components/user-entrypoints.tsx
(2 hunks)src/features/donation/hooks/form.ts
(6 hunks)src/features/donation/hooks/user-flow.ts
(1 hunks)src/features/donation/models/effects/campaign-ft-donation.ts
(1 hunks)src/features/donation/models/effects/direct-ft-donation.ts
(1 hunks)src/features/donation/models/effects/group-list-donation.ts
(1 hunks)src/features/donation/models/effects/group-pot-donation.ts
(2 hunks)src/features/donation/models/effects/index.ts
(6 hunks)src/features/donation/models/schemas.ts
(1 hunks)uno.config.ts
(1 hunks)
💤 Files with no reviewable changes (3)
- src/entities/_shared/token/index.ts
- src/entities/campaign/components/CampaignDonationItem.tsx
- src/entities/_shared/token/components/inputs.tsx
🧰 Additional context used
🧠 Learnings (1)
src/features/donation/models/effects/campaign-ft-donation.ts (1)
Learnt from: akaia-shadowfox
PR: PotLock/potlock-nextjs-app#366
File: src/features/donation/models/effects/ft.ts:206-239
Timestamp: 2025-04-27T20:33:00.401Z
Learning: The donation FT multicall function in src/features/donation/models/effects/ft.ts is designed to be executed only in browser environments, making browser-only globals like `atob()` acceptable to use.
🧬 Code Graph Analysis (18)
src/features/donation/models/schemas.ts (1)
src/common/types.ts (1)
AccountId
(40-40)
src/features/donation/components/modal-content.tsx (1)
src/features/donation/hooks/form.ts (1)
DonationFormParams
(31-36)
src/common/contracts/core/campaigns/client.ts (3)
src/common/contracts/core/donation/client.ts (1)
storage_deposit
(66-71)src/common/contracts/core/campaigns/interfaces.ts (1)
CampaignsContractConfig
(3-12)src/common/types.ts (1)
IndivisibleUnits
(82-82)
src/features/donation/components/modal.tsx (1)
src/features/donation/components/modal-content.tsx (1)
DonationModalContentProps
(23-27)
src/entities/campaign/models/schema.ts (1)
src/common/constants.ts (1)
NATIVE_TOKEN_ID
(114-114)
src/features/donation/hooks/user-flow.ts (2)
src/features/donation/types.ts (1)
DonationAllocationKey
(13-13)src/features/donation/components/modal.tsx (1)
DonationModalProps
(16-17)
src/features/donation/components/single-recipient-success.tsx (3)
src/common/contracts/core/donation/interfaces.ts (1)
DirectDonation
(15-26)src/common/contracts/core/campaigns/interfaces.ts (1)
CampaignDonation
(53-69)src/common/constants.ts (1)
NATIVE_TOKEN_ID
(114-114)
src/features/donation/models/effects/group-list-donation.ts (2)
src/features/donation/models/schemas.ts (1)
DonationSubmitParams
(71-74)src/common/contracts/core/donation/interfaces.ts (1)
DirectDonation
(15-26)
src/entities/campaign/components/CampaignDonorsTable.tsx (6)
src/common/types.ts (1)
ByCampaignId
(118-120)src/common/contracts/core/campaigns/index.ts (1)
campaignsContractHooks
(7-7)src/entities/_shared/token/hooks/data.ts (1)
useToken
(35-192)src/common/constants.ts (2)
NATIVE_TOKEN_ID
(114-114)NATIVE_TOKEN_DECIMALS
(115-115)src/entities/_shared/token/components/icons.tsx (1)
TokenIcon
(31-57)src/common/lib/format.ts (1)
indivisibleUnitsToFloat
(16-20)
src/features/donation/models/effects/direct-ft-donation.ts (2)
src/features/donation/models/schemas.ts (1)
DonationSubmitParams
(71-74)src/common/contracts/core/donation/interfaces.ts (1)
DirectDonation
(15-26)
src/entities/campaign/components/CampaignCarouselItem.tsx (3)
src/common/constants.ts (1)
NATIVE_TOKEN_ID
(114-114)src/common/lib/string.ts (1)
truncate
(14-22)src/features/donation/components/user-entrypoints.tsx (1)
DonateToCampaign
(76-98)
src/features/donation/components/user-entrypoints.tsx (2)
src/common/types.ts (1)
ByCampaignId
(118-120)src/features/donation/hooks/user-flow.ts (2)
DonationUserFlowProps
(12-13)useDonationUserFlow
(15-44)
src/entities/campaign/components/CampaignCard.tsx (3)
src/entities/campaign/components/CampaignProgressBar.tsx (1)
CampaignProgressBar
(24-235)src/common/constants.ts (1)
NATIVE_TOKEN_ID
(114-114)src/features/donation/components/user-entrypoints.tsx (1)
DonateToCampaign
(76-98)
src/common/contracts/core/campaigns/interfaces.ts (1)
src/common/types.ts (2)
IndivisibleUnits
(82-82)TokenId
(101-101)
src/common/contracts/core/donation/client.ts (3)
src/common/contracts/core/donation/interfaces.ts (2)
DirectDonation
(15-26)DirectDonationArgs
(28-33)src/common/contracts/core/campaigns/client.ts (2)
donate
(70-76)storage_deposit
(107-112)src/common/types.ts (1)
IndivisibleUnits
(82-82)
src/entities/_shared/token/components/selector.tsx (5)
src/common/types.ts (1)
ByTokenId
(103-108)src/common/wallet/hooks.ts (1)
useWalletUserSession
(14-95)src/entities/_shared/token/hooks/data.ts (1)
useToken
(35-192)src/common/ui/form/components/select.tsx (4)
SelectFieldOption
(18-18)SelectFieldProps
(27-38)ControlledSelectFieldProps
(20-23)UncontrolledSelectFieldProps
(25-25)src/common/constants.ts (1)
NATIVE_TOKEN_ID
(114-114)
src/features/donation/hooks/form.ts (2)
src/common/types.ts (1)
TokenId
(101-101)src/common/constants.ts (1)
NATIVE_TOKEN_ID
(114-114)
src/features/donation/models/effects/campaign-ft-donation.ts (10)
src/features/donation/models/schemas.ts (1)
DonationSubmitParams
(71-74)src/common/types.ts (1)
CampaignId
(116-116)src/common/contracts/core/campaigns/interfaces.ts (1)
CampaignDonation
(53-69)src/common/contracts/core/campaigns/index.ts (1)
campaignsContractClient
(7-7)src/common/blockchains/near-protocol/index.ts (1)
nearProtocolClient
(6-6)src/features/donation/constants.ts (1)
DONATION_BASE_STORAGE_DEPOSIT_FLOAT
(17-17)src/common/contracts/tokens/fungible/interfaces.ts (2)
FungibleTokenStorageBalance
(11-11)FungibleTokenMetadata
(1-9)src/common/lib/format.ts (3)
indivisibleUnitsToBigNum
(9-10)bigNumToIndivisible
(12-13)floatToIndivisible
(22-23)src/common/constants.ts (2)
NATIVE_TOKEN_DECIMALS
(115-115)FULL_TGAS
(134-134)src/common/blockchains/near-protocol/types.ts (1)
InformativeSuccessfulExecutionOutcome
(3-5)
🪛 Biome (1.9.4)
src/common/contracts/core/campaigns/client.ts
[error] 22-22: Don't use '{}' as a type.
Prefer explicitly define the object shape. '{}' means "any non-nullable value".
(lint/complexity/noBannedTypes)
[error] 108-108: Don't use '{}' as a type.
Prefer explicitly define the object shape. '{}' means "any non-nullable value".
(lint/complexity/noBannedTypes)
src/common/contracts/core/donation/client.ts
[error] 67-67: Don't use '{}' as a type.
Prefer explicitly define the object shape. '{}' means "any non-nullable value".
(lint/complexity/noBannedTypes)
src/features/donation/models/effects/campaign-ft-donation.ts
[error] 134-135: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 56-56: Don't use '{}' as a type.
Prefer explicitly define the object shape. '{}' means "any non-nullable value".
(lint/complexity/noBannedTypes)
[error] 59-59: Don't use '{}' as a type.
Prefer explicitly define the object shape. '{}' means "any non-nullable value".
(lint/complexity/noBannedTypes)
🔇 Additional comments (62)
src/entities/voting-round/utils/weight.ts (1)
88-88
:✅ Verification successful
Potential breaking change: Verify if
basicWeight
of 0 is a valid value.The change from nullish coalescing (
??
) to logical OR (||
) means that abasicWeight
of0
will now be treated as1
. This could significantly alter voting weight calculations if0
was intended to mean "no amplification" or "disabled voting power."Please verify if
basicWeight
can legitimately be0
and whether this change is intentional:
🏁 Script executed:
#!/bin/bash # Search for basicWeight usage and configurations to understand valid values echo "=== Searching for basicWeight definitions and usage ===" rg -A 3 -B 3 "basicWeight" echo "=== Searching for VotingMechanismConfig type definition ===" ast-grep --pattern 'interface VotingMechanismConfig { $$$ }' echo "=== Searching for voting round configurations ===" rg -A 5 -B 5 "VOTING_ROUND_CONFIG"Length of output: 9000
No behavior change:
basicWeight = 0
not usedWe’ve verified that:
- In
src/entities/voting-round/types.ts
,basicWeight
is defined as optional (basicWeight?: number
).- The only hardcoded config (
VOTING_ROUND_CONFIG_MPDAO
inmodel/config.hardcoded.ts
) setsbasicWeight: 1
.- There are no occurrences of
basicWeight = 0
anywhere in the codebase.As a result, changing
.mul(basicWeight ?? 1)to
.mul(basicWeight || 1)does not alter current behavior. If you later need to allow
basicWeight = 0
(to explicitly disable amplification), you can revert to nullish coalescing (basicWeight ?? 1
). Otherwise, this change is safe to ship.src/entities/voting-round/hooks/vote-weight.ts (1)
58-58
:✅ Verification successful
Consistent with utility change but verify the impact on voting logic.
This change mirrors the same operator replacement in the utility file. While consistency is good, the same concern applies: if
basicWeight
can legitimately be0
, this change could affect voting calculations.Since this hook is likely used in the UI, please verify:
- Whether any existing voting round configurations use
basicWeight: 0
- The expected behavior when
basicWeight
is0
- Whether this change aligns with the intended voting mechanism design
🏁 Script executed:
#!/bin/bash # Check for any hardcoded voting configurations that might use basicWeight: 0 echo "=== Searching for hardcoded voting configurations ===" rg -A 10 -B 5 "basicWeight.*:.*0" echo "=== Searching for test cases related to vote weight calculation ===" rg -A 5 -B 5 "basicWeight.*0|weight.*0" --type ts --type tsxLength of output: 388
🏁 Script executed:
#!/bin/bash echo "=== Searching for hardcoded basicWeight: 0 across all files ===" rg -A5 -B5 'basicWeight.*0' echo "=== Searching for JSON configs with \"basicWeight\": 0 ===" rg -A5 -B5 '"basicWeight"\s*:\s*0' -g '*.json' echo "=== Listing every occurrence of basicWeight ===" rg -n 'basicWeight' echo "=== Listing every occurrence of votingRoundConfig ===" rg -n 'votingRoundConfig'Length of output: 1948
No existing
basicWeight = 0
usage; change is safe
- Verified across codebase (including JSON and TS files) that no voting configuration sets
basicWeight
to0
.- The only hardcoded default is
basicWeight: 1
insrc/entities/voting-round/model/config.hardcoded.ts
.Since there are currently no scenarios where
basicWeight
is0
, switching from?? 1
to|| 1
does not alter any existing behavior.If in the future you intend to use a
basicWeight
of0
to disable vote amplification, you should either revert to?? 1
or add an explicit check for0
..vscode/settings.json (1)
85-85
: LGTM: Spell check additions are appropriate.The new spell check words align well with the project's blockchain focus:
- "Multicall" for contract call batching
- "remeda" for the functional programming utility library
- "TGAS" for tera gas units in NEAR blockchain
Also applies to: 102-102, 113-113
uno.config.ts (1)
200-200
: Good UI enhancement for combobox components.The CSS rule effectively hides appendix elements in combobox contexts, which should improve the user experience in token selectors and similar dropdown components.
src/common/contracts/core/campaigns/interfaces.ts (4)
3-12
: Well-structured contract configuration type.The
CampaignsContractConfig
type comprehensively captures contract metadata including fees, counts, and administrative details. The type structure aligns well with blockchain contract patterns.
43-43
: Field reordering is acceptable.Moving
escrow_balance
aftermax_amount
doesn't affect functionality and may improve logical grouping of related fields.
20-22
:✅ Verification successful
Type change improves blockchain precision but verify compatibility.
Changing amount fields from
number
toIndivisibleUnits
is necessary for accurate token handling in blockchain contexts, as JavaScript numbers lose precision with large values.Verify that all existing code using these fields has been updated to handle
IndivisibleUnits
(string) instead ofnumber
:
🏁 Script executed:
#!/bin/bash # Description: Find usages of campaign amount fields to verify type compatibility # Expected: All usages should handle IndivisibleUnits (string) type echo "Searching for target_amount usages..." rg -A 3 -B 3 "target_amount" --type ts --type tsx echo "Searching for min_amount usages..." rg -A 3 -B 3 "min_amount" --type ts --type tsx echo "Searching for max_amount usages..." rg -A 3 -B 3 "max_amount" --type ts --type tsxLength of output: 470
Let’s broaden the search to include both
.ts
and.tsx
files (the sandbox’srg --type tsx
isn’t available):
🏁 Script executed:
#!/bin/bash # Description: Find usages of campaign amount fields using glob patterns echo "Searching for target_amount usages..." rg -n --glob '*.ts' --glob '*.tsx' -A 3 -B 3 "target_amount" echo "Searching for min_amount usages..." rg -n --glob '*.ts' --glob '*.tsx' -A 3 -B 3 "min_amount" echo "Searching for max_amount usages..." rg -n --glob '*.ts' --glob '*.tsx' -A 3 -B 3 "max_amount"Length of output: 42492
All amount fields updated to use
IndivisibleUnits
correctlyWe’ve verified every reference to
target_amount
,min_amount
, andmax_amount
now uses the string-basedIndivisibleUnits
type with the appropriate conversion utilities:
- Form handling:
–floatToIndivisible(...)
inhooks/forms.ts
when submitting
–yoctoNearToFloat(...)
inCampaignForm.tsx
for populating fields- Display components:
–indivisibleUnitsToFloat(...)
inCampaignSettings.tsx
,CampaignBanner.tsx
, andCampaignProgressBar.tsx
- Props and comparisons:
– All UI components accept the string values (e.g.data?.target_amount ?? "0"
) and only compare or render after parsing or conversionNo raw numeric operations remain on the contract-level fields.
39-39
:✅ Verification successful
Field rename improves consistency but verify all references updated.
The rename from
ftId
toft_id
aligns with the snake_case convention used throughout the contract interfaces.Verify that all code references to
ftId
have been updated to useft_id
:
🏁 Script executed:
#!/bin/bash # Description: Check for any remaining ftId references that should be ft_id # Expected: No references to old ftId field name echo "Checking for old ftId references..." rg -i "ftId" --type ts --type tsx echo "Verifying new ft_id usage..." rg -A 2 -B 2 "ft_id" --type ts --type tsxLength of output: 279
🏁 Script executed:
#!/bin/bash # Re-run without relying on rg’s built-in types to avoid the “unrecognized file type” error echo "Checking for any remaining ftId references (searching .ts and .tsx files)..." rg -i "ftId" -g '*.ts' -g '*.tsx' echo "Verifying all instances use ft_id (searching .ts and .tsx files)..." rg "ft_id" -g '*.ts' -g '*.tsx'Length of output: 4542
No remaining
ftId
property references detected
All contract‐level fields have been renamed toft_id
. The onlyftId
hits are in:
- Deprecated components (e.g.
src/layout/profile/_deprecated/DonationItem.tsx
,PotDonationEntry.tsx
)- Local bindings or schema helpers (
const ftIdSchema
, form‐destructuredftId
)None of these refer to the interface field name, so no further changes are needed.
src/features/donation/models/schemas.ts (1)
73-73
: Good addition for FT campaign donation support.The optional
campaignRecipientAccountId
field appropriately extends the donation parameters to support fungible token campaign donations while maintaining backward compatibility.src/features/donation/components/group-allocation.tsx (1)
166-166
: LGTM! Good UX improvement for token selection.Adding
hideZeroBalanceOptions
to the TokenSelector improves the user experience by filtering out tokens with zero balance, making it easier for users to select from available tokens for donations.src/entities/_shared/token/hooks/data.ts (1)
12-12
: LGTM! Good cleanup of deprecated token utilities.The removal of
useTokenUsdDisplayValue
and related imports aligns with the broader refactor to consolidate token handling using the comprehensiveuseToken
hook. This reduces code duplication and provides a more consistent API for token operations.src/features/donation/components/modal-content.tsx (1)
24-24
: LGTM! Proper extension of props for token-aware donations.Adding
cachedTokenId
to the modal props interface enables support for token-aware donation flows where the token ID is provided by the indexer. The optional nature of this property maintains backward compatibility while enabling the new FT donation functionality.src/features/donation/models/effects/group-list-donation.ts (2)
12-12
: LGTM! Consistent naming improvement.Renaming
ListDonationMulticallInputs
toGroupListDonationMulticallInputs
improves consistency with the naming pattern used across other donation effect modules, making the codebase more coherent.
17-22
: LGTM! Function renaming aligns with module consistency.Renaming
listDonationMulticall
togroupListDonationMulticall
maintains consistency with other group donation functions in the module while preserving all existing functionality. The function implementation correctly handles batch donations with proper error handling and receipt parsing.src/features/donation/components/modal.tsx (1)
16-17
: LGTM! Type extension for FT support.The addition of
cachedTokenId
toDonationModalProps
correctly extends the interface to support token-aware donation flows. This change aligns well with the broader FT support implementation.src/features/donation/components/modal-confirmation-screen.tsx (3)
29-29
: LGTM! Appropriate import for allocation strategy.The import of
DonationAllocationStrategyEnum
is necessary for the updated logic that determines donation type based on allocation strategy.
41-49
: Excellent refactor to use allocation strategy.The change from watching
recipientAccountId
toallocationStrategy
and updating the logic to useDonationAllocationStrategyEnum.full
is a more robust approach. This determines donation type based on the actual allocation strategy rather than derived state, which improves maintainability and correctness.
92-106
: LGTM! Consistent updates to conditional rendering.The updates to use
isSingleRecipientDonation
instead ofisSingleProjectDonation
are consistent with the logic refactoring and maintain the same UI behavior while being based on more reliable state.Also applies to: 157-192
src/features/donation/hooks/user-flow.ts (2)
9-9
: LGTM! Appropriate import extension.Adding
DonationModalProps
to the import is necessary for the new type definition.
12-15
: Excellent type design for FT support.The new
DonationUserFlowProps
type effectively combines the existingDonationAllocationKey
with an optionalcachedTokenId
fromDonationModalProps
. This approach:
- Maintains backwards compatibility
- Uses TypeScript's
Pick
utility type appropriately- Enables token-aware donation flows
The updated hook parameter type properly supports the enhanced functionality.
src/features/donation/components/single-recipient-success.tsx (2)
83-89
: Excellent refactor with improved token ID logic.The
useMemo
refactor provides several benefits:
- Performance: Memoizes the computation to prevent unnecessary recalculations
- Readability: More explicit logic flow compared to the previous inline conditional
- Correctness: Properly uses
ft_id
property which aligns with the contract interfaces (as seen inDirectDonation
andCampaignDonation
interfaces from relevant snippets)The logic correctly handles different donation types and falls back to
NATIVE_TOKEN_ID
appropriately.
169-169
: LGTM! Minor CSS improvement.The addition of
items-center
class improves the flex container alignment for the donation recipient information.src/entities/campaign/models/schema.ts (2)
56-59
: Well-designed FT token validation schema.The
ftIdSchema
properly validates fungible token IDs by accepting either the native NEAR token or contract account IDs with a minimum length requirement. The default toNATIVE_TOKEN_ID
ensures backward compatibility.
68-68
: Good integration of FT ID into campaign schema.Adding
ft_id
as a required field with proper validation aligns well with the broader FT support implementation across the codebase.src/features/donation/models/effects/group-pot-donation.ts (1)
9-9
: Good refactoring for naming consistency.The rename from
PotDonationMulticallInputs
toGroupPotDonationMulticallInputs
andpotGroupDonationMulticall
togroupPotDonationMulticall
improves naming consistency across the donation effects modules.Also applies to: 18-25
src/entities/campaign/components/CampaignCard.tsx (3)
4-4
: Excellent integration of FT token support.The addition of
NATIVE_TOKEN_ID
fallback fordata.ft_id
provides good backward compatibility while enabling fungible token support. Passing thetokenId
toCampaignProgressBar
andcachedTokenId
toDonateToCampaign
allows these components to handle token-specific logic appropriately.Also applies to: 68-68, 79-79
70-72
: Good approach: passing raw amounts for token-aware conversion.Passing raw string amounts (
total_raised_amount
,min_amount
,target_amount
) instead of pre-converted values allows theCampaignProgressBar
component to perform conversions based on the specific token's decimal precision, which is more accurate and flexible.
25-25
: Improved layout flexibility.Changing from fixed height
h-144
to minimum heightmin-h-144
provides better responsive behavior for cards with varying content lengths.src/entities/campaign/components/CampaignDonorsTable.tsx (2)
6-6
: LGTM! Clean import additions for token generalization.The new imports support the migration from NEAR-specific handling to generic token support, which aligns perfectly with the PR's FT support objectives.
Also applies to: 8-8, 12-12
56-65
: Excellent token-aware amount display implementation.The dynamic token handling is well-implemented:
- Proper fallback to
NATIVE_TOKEN_ID
whencampaign?.ft_id
is undefined- Correct use of token decimals with fallback to
NATIVE_TOKEN_DECIMALS
- Clean integration of
TokenIcon
componentThe vertical alignment styling with
pb-1.5
on the icon ensures consistent visual presentation.src/features/donation/models/effects/direct-ft-donation.ts (1)
19-19
: LGTM! Clear and consistent renaming for better code organization.The renaming from
FtDonationMulticallInputs
toDirectFtDonationMulticallInputs
andftDonationMulticall
todirectFtDonationMulticall
improves clarity by explicitly indicating this handles direct FT donations. This aligns with the broader refactor mentioned in the AI summary to distinguish different donation flow types.Also applies to: 24-24, 31-31
src/features/donation/components/single-recipient-allocation.tsx (4)
8-8
: LGTM! Consistent variable naming and safer number parsing.Good improvements:
- Adding
parseNumber
import for safer number parsing- Renaming
viewer
towalletUser
for consistency across the codebase- Updating all references to use the new variable name
Also applies to: 39-39, 50-50
70-72
: Verify the FT selector disabling logic for campaign donations.The logic now always disables FT selection for campaign donations (
isCampaignDonation ? false
). This seems intentional but differs from the previous behavior mentioned in the AI summary.Could you clarify the reasoning for always disabling FT selection for campaign donations? Is this because campaigns have a predefined token (via
ft_id
) that shouldn't be changeable during donation?
74-81
: Excellent memoized USD value calculation with safe parsing.The implementation correctly:
- Uses
useMemo
for performance optimization- Safely parses the amount with
parseNumber
before calculation- Handles undefined USD price gracefully
- Provides proper dependency array
This is a significant improvement over direct calculations.
178-215
: Great UX improvement with loading skeleton and enhanced token selector.The conditional rendering provides better user experience:
- Loading skeleton prevents layout shift during campaign data loading
hideZeroBalanceOptions
prop improves token selection UX- Proper form field structure maintained
The implementation is clean and follows React patterns well.
src/features/donation/components/user-entrypoints.tsx (1)
69-74
: LGTM! Clean refactor to support cached token IDs in donation flow.The changes are well-structured:
- Type renaming from
DonationToCampaignProjectsProps
toDonationToCampaignProps
is more concise- Addition of
cachedTokenId
support via proper type picking fromDonationUserFlowProps
- Component renaming and prop destructuring updated consistently
- Hook call properly passes both
campaignId
andcachedTokenId
This integrates well with the broader token-aware donation flow enhancements mentioned in the AI summary.
Also applies to: 76-77, 83-83
src/entities/campaign/components/CampaignCarouselItem.tsx (2)
4-11
: Import changes look good!The migration to use
NATIVE_TOKEN_ID
constant and the updated donation component import align well with the FT support objectives.
65-82
: Token handling implementation is correct.The changes properly implement:
- Token ID propagation with appropriate fallback to
NATIVE_TOKEN_ID
- Raw amount values as strings, consistent with
IndivisibleUnits
type usage- Proper prop passing to both
CampaignProgressBar
andDonateToCampaign
src/common/ui/form/components/select.tsx (1)
20-38
: Excellent type safety improvement!The separation of controlled and uncontrolled prop types using a discriminated union prevents common React anti-patterns where controlled and uncontrolled props are mixed. This will help catch errors at compile time.
src/common/contracts/core/donation/client.ts (1)
30-36
: Naming convention update aligns with contract standards.The change from camelCase to snake_case for function names matches NEAR contract conventions, ensuring consistency between the client and contract APIs.
src/entities/campaign/components/CampaignSettings.tsx (1)
67-92
:✅ Verification successful
Consider potential floating-point precision issues.
The floating-point conversions might lose precision for very large token amounts. While
indivisibleUnitsToFloat
likely handles this internally, ensure that the display values are accurate for tokens with high decimal places.
🏁 Script executed:
#!/bin/bash # Description: Check if indivisibleUnitsToFloat handles precision correctly # Look for the implementation to verify precision handling ast-grep --pattern 'function indivisibleUnitsToFloat($_) { $$$ }' rg -A 10 'export.*indivisibleUnitsToFloat'Length of output: 875
Consider JavaScript number precision limits for large token amounts.
The
indivisibleUnitsToFloat
helper uses Big’stoFixed(fracDigits ?? 2, 3)
to round accurately, but then returns a native JS number viaparseFloat
. Values with integer parts ≥Number.MAX_SAFE_INTEGER
(≈ 9e15) can’t be represented exactly in a JSnumber
, leading to precision loss for very large balances. If you anticipate amounts that large:
- Display the string output from
toFixed
directly instead of converting to a number.- Or keep the value as a Big instance until rendering.
This ensures correct display even for tokens with high decimal places and extremely large amounts.
src/features/donation/hooks/form.ts (2)
31-36
: LGTM! Well-documented parameter addition.The
cachedTokenId
parameter is properly documented and provides a clean way to pre-populate the token selection from external sources like the indexer.
228-239
: Token synchronization logic looks solid.The effect correctly ensures that campaign donations use the campaign's specified token and prevents unnecessary re-renders by checking if the token differs before updating.
src/entities/campaign/components/CampaignForm.tsx (1)
271-295
: Token selector integration looks good.The implementation properly integrates token selection with the amount input field, providing a clean UX for selecting tokens while entering amounts.
src/features/donation/models/effects/index.ts (3)
12-17
: LGTM! Import names are more descriptive.The updated import names clearly indicate the specific donation type each multicall handles, improving code maintainability.
133-137
: Good validation for required campaign recipient.The early validation ensures that FT donations to campaigns have the required recipient account ID, preventing runtime errors.
139-154
: Campaign FT donation implementation looks good.The implementation correctly handles FT donations to campaigns with proper error handling and follows the established pattern.
src/entities/campaign/hooks/forms.ts (4)
38-51
: Good use of memoization for parsed amounts.The memoized parsing ensures consistent number handling and prevents unnecessary recalculations, improving performance.
53-72
: Robust token handling in form state.The disabled state correctly accounts for token loading and validates token availability only for non-native tokens, preventing form submission with invalid token selections.
189-214
: Excellent token-aware amount conversion.The implementation correctly handles amount conversion using token decimals with appropriate fallbacks and conditional inclusion of optional fields.
305-305
: Clean simplification of return value.Returning only
self
as theform
property is cleaner and avoids redundant spreading since the form object already contains all necessary state.src/entities/campaign/components/CampaignProgressBar.tsx (2)
34-53
: Robust token data handling with safe conversions.The implementation correctly handles undefined token data and consistently converts indivisible units to float values with proper decimal handling.
65-68
: Good defensive programming against division by zero.The code correctly guards against division by zero by using
(targetAmountFloat || 1)
, preventing runtime errors when the target amount is not set.Also applies to: 206-209
src/entities/_shared/token/components/selector.tsx (2)
17-26
: LGTM! Well-designed component enhancement.The new props for conditional balance display and zero-balance filtering are well-thought-out and provide good UX control.
38-38
: Clever UX enhancement with CSS ordering.The use of CSS
order
property to prioritize tokens with positive balances is an elegant solution that improves user experience by surfacing available tokens first.src/features/donation/models/effects/campaign-ft-donation.ts (2)
219-221
: Browser-only function usage is acceptable.The use of
atob()
is appropriate here as this function is designed to run in browser environments only, consistent with other donation effects.
24-243
: Complex but well-structured multicall function.The function correctly handles all the necessary steps for FT campaign donations:
- Fetches protocol config and token metadata
- Calculates storage requirements
- Ensures adequate storage deposits for all parties
- Executes the FT transfer with proper parameters
- Extracts and validates the donation receipt
The logic flow is comprehensive and handles edge cases appropriately.
🧰 Tools
🪛 Biome (1.9.4)
[error] 134-135: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 56-56: Don't use '{}' as a type.
Prefer explicitly define the object shape. '{}' means "any non-nullable value".
(lint/complexity/noBannedTypes)
[error] 59-59: Don't use '{}' as a type.
Prefer explicitly define the object shape. '{}' means "any non-nullable value".
(lint/complexity/noBannedTypes)
src/entities/campaign/components/CampaignBanner.tsx (5)
36-36
: Good fallback to native token.The fallback to
NATIVE_TOKEN_ID
whencampaign?.ft_id
is undefined ensures the component works correctly for both FT and native token campaigns.
38-54
: Excellent memoization of calculated values.The memoized calculations for
raisedAmountFloat
andminAmountFLoat
are well-implemented with proper dependencies. This prevents unnecessary recalculations and improves performance.
73-80
: Improved USD approximation calculation.The replacement of the deprecated
useTokenUsdDisplayValue
hook with a direct memoized calculation is a good improvement that provides more control and clarity.
148-148
: Dynamic token symbol display.The updated amount display using
token?.metadata.symbol
correctly adapts to different token types, enhancing the user experience for FT campaigns.
214-221
: Updated donation component integration.The replacement of
DonateToCampaignProjects
withDonateToCampaign
and the addition ofcachedTokenId
prop properly integrates with the enhanced token selection functionality.
There was a problem hiding this 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
🧹 Nitpick comments (2)
src/features/donation/components/campaign-success-share.tsx (2)
66-74
: Consider breaking down the useMemo dependencies.The dependency array is quite long, which suggests the memoized logic might be doing too much. Consider splitting this into smaller, more focused useMemo hooks.
Example approach:
+ const recipientReference = useMemo(() => { + // Extract recipient reference logic here + }, [recipientSocialProfile?.linktree?.twitter, recipientSocialProfile?.name, recipientAccountId]); + + const shareUrl = useMemo(() => { + // Extract URL construction logic here + }, [campaignId, viewer.accountId, viewer.isSignedIn]); + const intent = useMemo(() => { - // Move text and final URL construction here + // Simplified intent construction using the above values - }, [ - campaignId, - campaignName, - // ... all current dependencies - ]); + }, [campaignName, recipientReference, shareUrl]);
79-84
: Enhance accessibility for the share button.Consider adding accessibility attributes to improve screen reader support.
- <Button asChild variant="standard-filled" className="bg-neutral-950 py-1.5 shadow-none"> - <Link href={intent} target="_blank"> + <Button asChild variant="standard-filled" className="bg-neutral-950 py-1.5 shadow-none"> + <Link + href={intent} + target="_blank" + rel="noopener noreferrer" + aria-label={`Share ${campaignName} campaign on X`} + >
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/entities/campaign/components/CampaignProgressBar.tsx
(3 hunks)src/features/donation/components/campaign-success-share.tsx
(1 hunks)src/features/donation/components/single-recipient-success.tsx
(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/features/donation/components/single-recipient-success.tsx
- src/entities/campaign/components/CampaignProgressBar.tsx
🔇 Additional comments (4)
src/features/donation/components/campaign-success-share.tsx (4)
1-18
: LGTM! Clean import structure.The imports are well-organized with appropriate groupings and all necessary dependencies are included.
19-27
: LGTM! Well-typed component interface.The props type definition is clear and uses proper type extraction with
Campaign["name"]
. The component declaration follows React best practices.
28-31
: LGTM! Proper hook usage.The wallet session and social profile hooks are used correctly with appropriate destructuring and variable naming.
44-65
: LGTM! Proper URL construction and encoding.The share intent URL is constructed correctly with proper encoding of all parameters. The logic for conditional referrer parameter is well-implemented.
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Refactor
Chores