-
-
Notifications
You must be signed in to change notification settings - Fork 1
chore(backend): deploy to sepolia #92
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
Conversation
✅ Deploy Preview for web3-sponsors ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
WalkthroughUpdated Hardhat RPC URLs; recompiled and replaced multiple smart-contract artifacts (SponsorshipQueue, DistributionQueue, DistributionVerifier), added a new QueueHandler artifact, updated deployed addresses and ignition journal entries, and adapted frontend components/pages to the revised ABIs and 1-based queue-numbering. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant UI as Frontend UI
participant SQ as SponsorshipQueue
participant DQ as DistributionQueue
participant QH as QueueHandler
participant DV as DistributionVerifier
rect rgba(230,240,255,0.4)
note over UI: Reads use getLength() and queue(uint24)
User->>UI: View queues
UI->>SQ: getLength()
UI->>DQ: getLength()
UI->>SQ: queue(queueNumber)
UI->>DQ: queue(queueNumber)
end
rect rgba(230,255,230,0.4)
note over UI,QH: Queue processing via QueueHandler
User->>UI: Trigger processQueuePair
UI->>QH: processQueuePair()
QH->>DQ: dequeue() -- returns Distribution tuple
QH->>SQ: dequeue() -- returns Sponsorship tuple
QH->>DV: verifyDistribution(queueNumber, approved?)
alt approved
DV-->>QH: DistributionApproved
QH-->>UI: QueuePairProcessed(distribution, sponsorship)
else rejected
DV-->>QH: DistributionRejected
QH->>QH: removeRejectedDistribution()
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 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.
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 (10)
backend/hardhat.config.ts (1)
22-29
: Switch to env-driven RPC with safe fallbacks; keep empty-accounts pattern only for non-prod.Good move to 0xRPC. To reduce blast radius and keep CI happy while aligning with elimu.ai’s mission to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months, prefer env-driven URLs with 0xRPC as fallback, and avoid accidental mainnet usage with empty accounts.
Apply:
require("dotenv").config(); -const privateKeys = process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [] +const privateKeys = process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : []; +const sepoliaUrl = process.env.SEPOLIA_RPC_URL ?? "https://0xrpc.io/sep"; +const mainnetUrl = process.env.MAINNET_RPC_URL ?? "https://0xrpc.io/eth"; ... networks: { sepolia: { // Chain ID 11155111 - url: "https://0xrpc.io/sep", + url: sepoliaUrl, accounts: privateKeys }, mainnet: { // Chain ID 1 - url: "https://0xrpc.io/eth", + url: mainnetUrl, accounts: privateKeys } },Confirm:
- PRIVATE_KEY is unset in CI runs that only lint/compile.
- When deploying to mainnet, PRIVATE_KEY is present and points to a funded address.
backend/ignition/deployments/chain-11155111/journal.jsonl (1)
3-8
: Constructor arg change on SponsorshipQueue—confirm units and front-end expectations.
constructorArgs: 100000000000000
suggests 0.0001 ETH (1e14 wei). Verify the UI/QueueHandler uses the same unit and does not assume gwei/ether.Add a unit test asserting expected value in wei and end-to-end flow through QueueHandler.
backend/README.md (2)
31-33
: Great: pre-deploy artifact cleanup. Add a caution.Add a one-liner warning that this purges only cached deployment artifacts, not source code, to avoid accidental path edits.
45-47
: Mirror the Sepolia cleanup note for mainnet and require explicit consent.Consider adding a short “Are you sure?” prompt (via a wrapper script) before mainnet cleanup/deploy to prevent accidental mainnet redeploys.
backend/ignition/deployments/chain-11155111/artifacts/DistributionVerifierModule#DistributionVerifier.json (2)
82-99
: New counters: approvalCount/rejectionCount—expose in frontend.Surface these read-only endpoints in the UI to improve moderator visibility.
21-35
: queueIndex → queueNumber rename—update all callers.Events and function params switched to
queueNumber
. Ensure off-chain code, tests, and subgraphs use the new name.#!/bin/bash # Find old API usages across repo rg -nP -C2 '\bqueueIndex\b|isDistributionApproved\s*\(|verifyDistribution\s*\(|getQueueCount\b|languages\s*\(\)' -g '!**/node_modules/**'backend/ignition/deployments/chain-11155111/artifacts/QueueHandlerModule#QueueHandler.json (1)
209-220
: updateDistributionVerifier event + method—wire hot-swap logic.Confirm QueueHandler validates the new verifier address (non-zero, code size > 0) and emits DistributionVerifierUpdated.
backend/ignition/deployments/chain-11155111/artifacts/DistributionQueueModule#DistributionQueue.json (1)
235-260
: Expose queueNumberFront/Next—validate monotonicity and overflow.Using uint24 is fine; add tests for wrap-around (very long run) and for length computation using Next−Front.
backend/ignition/deployments/chain-11155111/artifacts/SponsorshipQueueModule#SponsorshipQueue.json (2)
18-21
: Orphaned error: InvalidLanguageCode remains but no language input.This error seems unused now—remove to avoid confusion and reduce bytecode.
245-269
: New queueNumberFront/Next—align with DistributionQueue semantics.Add cross-contract tests: enqueue on SponsorshipQueue then process via QueueHandler to confirm indices move in lockstep with DistributionQueue.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
backend/README.md
(2 hunks)backend/hardhat.config.ts
(1 hunks)backend/ignition/deployments/chain-11155111/artifacts/DistributionQueueModule#DistributionQueue.json
(5 hunks)backend/ignition/deployments/chain-11155111/artifacts/DistributionVerifierModule#DistributionVerifier.json
(7 hunks)backend/ignition/deployments/chain-11155111/artifacts/QueueHandlerModule#QueueHandler.json
(1 hunks)backend/ignition/deployments/chain-11155111/artifacts/SponsorshipQueueModule#SponsorshipQueue.json
(10 hunks)backend/ignition/deployments/chain-11155111/deployed_addresses.json
(1 hunks)backend/ignition/deployments/chain-11155111/journal.jsonl
(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-08-12T06:22:30.517Z
Learnt from: jo-elimu
PR: elimu-ai/web3-sponsors#74
File: backend/ignition/modules/SponsorshipQueue.ts:9-17
Timestamp: 2025-08-12T06:22:30.517Z
Learning: The web3-sponsors project has not deployed to Ethereum Mainnet yet. The placeholder "0x addr mainnet" in backend/ignition/modules/SponsorshipQueue.ts is intentional and appropriate for the current deployment state.
Applied to files:
backend/README.md
backend/ignition/deployments/chain-11155111/deployed_addresses.json
📚 Learning: 2024-10-20T07:26:44.861Z
Learnt from: jo-elimu
PR: elimu-ai/web3-sponsors#0
File: :0-0
Timestamp: 2024-10-20T07:26:44.861Z
Learning: User `jo-elimu` resolved an issue with missing `WALLET_KEY` by using an empty array `[]` in the `networks` configuration in `hardhat.config.ts` to avoid errors during the `npx hardhat clean` command. This is not suitable for production environments where real transactions occur.
Applied to files:
backend/hardhat.config.ts
📚 Learning: 2025-08-22T12:52:32.267Z
Learnt from: jo-elimu
PR: elimu-ai/web3-sponsors#81
File: backend/contracts/DistributionQueue.sol:0-0
Timestamp: 2025-08-22T12:52:32.267Z
Learning: In DistributionQueue.sol, the queue uses a mapping-based implementation where the first item is stored at index 0. The enqueue() function writes to queue[queueNumberNext] before incrementing queueNumberNext, and dequeue() reads from queue[queueNumberFront] before incrementing queueNumberFront. This creates a proper FIFO queue where items are enqueued starting at index 0.
Applied to files:
backend/ignition/deployments/chain-11155111/artifacts/DistributionQueueModule#DistributionQueue.json
📚 Learning: 2025-08-22T12:52:32.267Z
Learnt from: jo-elimu
PR: elimu-ai/web3-sponsors#81
File: backend/contracts/DistributionQueue.sol:0-0
Timestamp: 2025-08-22T12:52:32.267Z
Learning: In DistributionQueue.sol, the queue uses a mapping-based implementation where the first item is stored at index 0. The enqueue() function writes to queue[queueNumberNext] before incrementing queueNumberNext, and dequeue() reads from queue[queueNumberFront] before incrementing queueNumberFront. This creates a proper FIFO queue where items are enqueued starting at index 0, and the implementation is correct as-is.
Applied to files:
backend/ignition/deployments/chain-11155111/artifacts/DistributionQueueModule#DistributionQueue.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: build (windows-latest, 20.x)
- GitHub Check: build (ubuntu-latest, 20.x)
- GitHub Check: build (ubuntu-latest, 18.x)
- GitHub Check: build (windows-latest, 18.x)
🔇 Additional comments (6)
backend/ignition/deployments/chain-11155111/journal.jsonl (1)
21-26
: Deployment flow OK; sanity-check fees/nonces.Nonces 27–30 and very low maxFeePerGas values are recorded. Confirm these are from Sepolia at the deployment time and not mocked, to avoid misleading future operators.
backend/ignition/deployments/chain-11155111/artifacts/DistributionQueueModule#DistributionQueue.json (1)
114-148
: dequeue now returns a Distribution tuple—API break.Ensure all consumers migrated from prior getters to
dequeue()
and handle empty-queue errors properly.backend/ignition/deployments/chain-11155111/artifacts/SponsorshipQueueModule#SponsorshipQueue.json (2)
9-16
: Constructor simplified—double-check that Languages dependency removal is intentional.If language validation moved elsewhere, great; otherwise, confirm no missing checks.
92-127
: ```shell
#!/bin/bash
set -euo pipefailecho "PWD: $(pwd)"
echo "Git HEAD (if available):"
git rev-parse --abbrev-ref HEAD 2>/dev/null || trueecho
echo "1) Searching for occurrences of 'addSponsorship'..."
rg -n --hidden -S "addSponsorship" -g '!/node_modules/' -g '!/dist/' -g '!/.git/' -C5 || trueecho
echo "2) Searching for Solidity function declarations 'function addSponsorship'..."
rg -n --hidden -S --type-add 'sol:*.sol' -t sol "function addSponsorship" -g '!/node_modules/' -g '!/dist/' -g '!/.git/' -C10 || trueecho
echo "3) Searching for struct/type 'Sponsorship' and 'dequeue' usages..."
rg -n --hidden -S "struct Sponsorship" -g '!/node_modules/' -C5 || true
rg -n --hidden -S "\bdequeue\b" -g '!/node_modules/' -C5 || trueecho
echo "4) Show the deployment artifact mentioned in the review (if present)..."
artifact="backend/ignition/deployments/chain-11155111/artifacts/SponsorshipQueueModule#SponsorshipQueue.json"
if [ -f "$artifact" ]; then
echo "== Found artifact: $artifact =="
sed -n '1,240p' "$artifact" || true
else
echo "Artifact not found at: $artifact"
echo "List matching artifact files under backend/ignition/deployments (if any):"
find backend/ignition/deployments -maxdepth 6 -type f -name 'Sponsorship' -print 2>/dev/null || true
fiecho
echo "5) If any .sol file containing 'addSponsorship' was found, print its surrounding lines (up to 120 lines)."
matches=$(rg -n --hidden -S --type-add 'sol:.sol' -t sol "addSponsorship" -g '!/node_modules/' -g '!/.git/' --no-line-number || true)
if [ -n "$matches" ]; then
echo "Printing matched files and contexts:"
rg -n --hidden -S --type-add 'sol:.sol' -t sol "addSponsorship" -g '!/node_modules/' -g '!/.git/' -C60 || true
else
echo "No direct Solidity matches for 'addSponsorship' found."
fiecho
echo "Script completed."</blockquote></details> <details> <summary>backend/ignition/deployments/chain-11155111/deployed_addresses.json (1)</summary><blockquote> `2-6`: **Addresses updated; add lightweight validation before publishing.** Looks fine. Add a quick check to ensure all addresses are valid EOA/contract addresses and deployed code size > 0. ```shell #!/bin/bash # Validate Sepolia addresses have code set -euo pipefail ADDRS=( 0x646A5550af30f5340AF218C9aE375A4C7Bb740BF 0xD7744d3Cc62748fcDc8f53e202C804488D9e85A8 0xC3313d6BB50C081AE07B6B097700eC2ED0568377 0x0B96769D277D8b7EaED38d2e269101615fB3e237 ) for a in "${ADDRS[@]}"; do echo -n "$a: " cast code --rpc-url "${SEPOLIA_RPC_URL:-https://0xrpc.io/sep}" "$a" | awk '{print (length($0)>2)?"OK:code":"ERR:no code"}' done
backend/ignition/deployments/chain-11155111/artifacts/QueueHandlerModule#QueueHandler.json (1)
169-181
: ```shell
#!/bin/bash
set -euo pipefail
echo "PWD: $(pwd)"
echo
echo "Find occurrences of the function names and contract name in the repo..."
rg -n --hidden --no-ignore -S "processQueuePair|removeRejectedDistribution|processQueuePair\s*(|removeRejectedDistribution\s*(|contract\s+QueueHandler" -g '!/node_modules/' -g '!/dist/' -g '!/build/' || trueART="backend/ignition/deployments/chain-11155111/artifacts/QueueHandlerModule#QueueHandler.json"
echo
if [ -f "$ART" ]; then
echo "Artifact found: $ART"
echo
echo "Showing lines 150-200 from artifact (to include the snippet lines referenced in the review):"
sed -n '150,200p' "$ART" || true
echo
echo "Showing ABI entries for the two target functions (if present):"
jq -c '.abi[] | select(.type=="function" and (.name=="processQueuePair" or .name=="removeRejectedDistribution"))' "$ART" 2>/dev/null || true
else
echo "Artifact not found at $ART"
fiecho
echo "Search for function definitions with context (to locate Solidity source):"
rg -n --hidden --no-ignore -S -C3 "function\s+processQueuePair|function\s+removeRejectedDistribution" -g '!/node_modules/' -g '!/dist/' -g '!/build/' || trueecho
echo "Search for common access-control and reentrancy patterns (onlyOwner, onlyRole, hasRole, nonReentrant, ReentrancyGuard):"
rg -n --hidden --no-ignore -S "onlyOwner|onlyRole|hasRole|nonReentrant|ReentrancyGuard" -g '!/node_modules/' -g '!/dist/' -g '!/build/' || true</blockquote></details> </blockquote></details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
"inputs": [ | ||
{ | ||
"internalType": "uint256", | ||
"internalType": "address", | ||
"name": "distributor", | ||
"type": "address" | ||
}, | ||
{ | ||
"components": [ | ||
{ | ||
"internalType": "uint256", | ||
"name": "estimatedCost", | ||
"type": "uint256" | ||
}, | ||
{ | ||
"internalType": "uint256", | ||
"name": "timestamp", | ||
"type": "uint256" | ||
}, | ||
{ | ||
"internalType": "address", | ||
"name": "sponsor", | ||
"type": "address" | ||
} | ||
], | ||
"internalType": "struct Sponsorship", | ||
"name": "sponsorship", | ||
"type": "tuple" | ||
} | ||
], | ||
"name": "payDistributor", | ||
"outputs": [], | ||
"stateMutability": "nonpayable", | ||
"type": "function" | ||
}, |
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.
payDistributor(distributor, Sponsorship) risks mismatch.
Ensure the function verifies the tuple matches the current front-of-queue item (not caller-provided arbitrary data) before paying, and uses nonReentrant + pull pattern if feasible.
🤖 Prompt for AI Agents
In
backend/ignition/deployments/chain-11155111/artifacts/SponsorshipQueueModule#SponsorshipQueue.json
around lines 168-201, the payDistributor(distributor, Sponsorship) ABI indicates
the function accepts a caller-supplied tuple which risks paying based on
arbitrary data; change the implementation to read the current front-of-queue
sponsorship from contract storage and verify the tuple fields (estimatedCost,
timestamp, sponsor) match that stored item instead of trusting the
caller-provided struct, refuse to proceed if they differ, and then mark the item
as paid/removed; additionally, protect the function with a nonReentrant modifier
(or equivalent reentrancy guard) and switch to a pull-payment pattern (record
payable balances for distributors and let them withdraw) rather than sending
funds directly within payDistributor to mitigate reentrancy and gas/transfer
failures.
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
frontend/src/pages/sponsorships/add.tsx (2)
71-81
: Send ETH when simulating addSponsorship + pin Sepolia (11155111)File: frontend/src/pages/sponsorships/add.tsx (around lines 71–81)
- ABI shows addSponsorship is payable (stateMutability = "payable") — current simulation sending 0 ETH will revert. Pass the sponsorship amount (in wei) via the value option to useSimulateContract.
- Pin chainId to 11155111 to avoid accidental mainnet/wrong‑chain calls.
- Add a runtime guard for a missing deployment address (disable/hide button if deploymentAddress is falsy).
Apply (example):
const { isPending, isError, error, isSuccess } = useSimulateContract({ abi, address: deploymentAddress, - functionName: "addSponsorship" + functionName: "addSponsorship", + chainId: 11155111, + // pass sponsorship amount in wei (BigInt or ethers.parseEther(amountEth)) + value: sponsorshipValueWei })elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.
100-121
: Button says “Send 0.0001 ETH” but transaction sends 0 ETH — fix the mismatchelimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.
File: frontend/src/pages/sponsorships/add.tsx
Lines: 100-121Pick ONE:
- Option A (no payment now): update label (and pin chainId).
const { writeContract } = useWriteContract(); return ( <button className="mt-4 p-8 text-2xl bg-purple-200 dark:bg-purple-950 rounded-lg border-purple-400 border-r-4 border-b-4 hover:border-r-8 hover:border-b-8 hover:-translate-y-1 active:border-r-2 active:border-b-2" onClick={() => writeContract({ abi, address: deploymentAddress, - functionName: "addSponsorship" + functionName: "addSponsorship", + chainId: 11155111 }) } > - Send 0.0001 ETH ⟠ + Add Sponsorship 💜 </button>
- Option B (still payable): re-add value consistently to simulate + write.
const { isPending, isError, error, isSuccess } = useSimulateContract({ abi, address: deploymentAddress, - functionName: "addSponsorship", - chainId: 11155111 + functionName: "addSponsorship", + value: parseEther("0.0001"), + chainId: 11155111 })writeContract({ abi, address: deploymentAddress, - functionName: "addSponsorship", - chainId: 11155111 + functionName: "addSponsorship", + value: parseEther("0.0001"), + chainId: 11155111 })
🧹 Nitpick comments (2)
frontend/src/components/Sponsorships.tsx (1)
35-37
: Minor: strict equality and cleaner list constructionUse
===
and avoid filling an array only to ignore the element.- if (queueCount == 0) { + if (queueCount === 0) { return <div>None yet</div>; } @@ - {Array(queueCount).fill(1).map((el, i) => + {[...Array(queueCount).keys()].map((i) => <Link key={i} href={`/sponsorships/${i + 1}`}> <div className="skew-y-3 p-4 text-2xl bg-purple-200 dark:bg-purple-950 rounded-lg border-purple-400 border-r-4 border-b-4 hover:border-r-8 hover:border-b-8 hover:-translate-y-1"> <SponsorshipSummary queueIndex={i} /> </div> </Link> )}Quick check: confirm the route is 1‑based (
i+1
) whilequeueIndex
is 0‑based by design. If not intentional, align both.Also applies to: 41-47
frontend/src/components/Distributions.tsx (1)
35-37
: Minor: prefer===
and a simpler index listTighten equality and remove the unused
el
.- if (queueCount == 0) { + if (queueCount === 0) { return <div>None yet</div>; } @@ - {Array(queueCount).fill(1).map((el, i) => + {[...Array(queueCount).keys()].map((i) => <Link key={i} href={`/distributions/${i + 1}`}> <div className="skew-y-3 p-4 text-2xl bg-indigo-200 dark:bg-indigo-950 rounded-lg border-indigo-400 border-r-4 border-b-4 hover:border-r-8 hover:border-b-8 hover:-translate-y-1"> <DistributionSummary queueIndex={i} /> </div> </Link> )}Also confirm 1‑based route (
i+1
) vs 0‑basedqueueIndex
is intentional.Also applies to: 41-47
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
frontend/src/components/Distributions.tsx
(1 hunks)frontend/src/components/Sponsorships.tsx
(1 hunks)frontend/src/pages/sponsorships/add.tsx
(4 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: jo-elimu
PR: elimu-ai/web3-sponsors#74
File: backend/ignition/modules/SponsorshipQueue.ts:9-17
Timestamp: 2025-08-12T06:22:30.517Z
Learning: The web3-sponsors project has not deployed to Ethereum Mainnet yet. The placeholder "0x addr mainnet" in backend/ignition/modules/SponsorshipQueue.ts is intentional and appropriate for the current deployment state.
📚 Learning: 2025-08-12T06:22:30.517Z
Learnt from: jo-elimu
PR: elimu-ai/web3-sponsors#74
File: backend/ignition/modules/SponsorshipQueue.ts:9-17
Timestamp: 2025-08-12T06:22:30.517Z
Learning: The web3-sponsors project has not deployed to Ethereum Mainnet yet. The placeholder "0x addr mainnet" in backend/ignition/modules/SponsorshipQueue.ts is intentional and appropriate for the current deployment state.
Applied to files:
frontend/src/pages/sponsorships/add.tsx
🧬 Code graph analysis (1)
frontend/src/pages/sponsorships/add.tsx (1)
frontend/src/pages/distributions/add.tsx (2)
SimulateContractButton
(109-141)WriteContractButton
(143-165)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: Redirect rules - web3-sponsors
- GitHub Check: Header rules - web3-sponsors
- GitHub Check: Pages changed - web3-sponsors
- GitHub Check: build (windows-latest, 20.x)
- GitHub Check: build (ubuntu-latest, 18.x)
- GitHub Check: build (windows-latest, 18.x)
- GitHub Check: build (ubuntu-latest, 20.x)
- GitHub Check: build (windows-latest, 18.x)
🔇 Additional comments (2)
frontend/src/components/Sponsorships.tsx (1)
15-19
: Pin chainId=11155111 for deterministic reads; verify no stale getQueueCount calls remain
- Add chainId to the useReadContract call in frontend/src/components/Sponsorships.tsx:
const { isLoading, isError, error, data } = useReadContract({ abi, address: deploymentAddress, - functionName: "getLength" + functionName: "getLength", + chainId: 11155111, });
- Repo search for '\bgetQueueCount\b' returned no matches — unable to confirm absence of stale calls; re-run the search or manually verify the codebase.
elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.
frontend/src/components/Distributions.tsx (1)
15-19
: Pin chainId=11155111 for Sepolia reads in frontend/src/components/Distributions.tsxSame as Sponsorships — pin the chain for Sepolia reads and verify there are no remaining
getQueueCount
references in distributions paths.const { isLoading, isError, error, data } = useReadContract({ abi, address: deploymentAddress, - functionName: "getLength" + functionName: "getLength", + chainId: 11155111, });Verification:
rg
produced no matches; manual confirmation required.elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.
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 (6)
frontend/src/components/SponsorshipSummary.tsx (5)
15-20
: Guard the read until the route param is valid (avoid NaN/undefined invocation).On first render, router.query.queueNumber is often undefined → Number(...) becomes NaN. Calling useReadContract with NaN can error. Gate the query.
const { isLoading, isError, error, data } = useReadContract({ abi, address: deploymentAddress, functionName: "queue", - args: [queueNumber] + args: [BigInt(queueNumber - 1)], + // wagmi v2 style; confirm your version + query: { enabled: Number.isInteger(queueNumber) && queueNumber > 0 } });If you’re on wagmi v1, switch to the equivalent enabled flag for useContractRead.
Would you like me to adjust this to your exact wagmi version once you confirm it?
8-12
: Type the props and dropany
.Make the intent explicit and catch invalid inputs early.
-export default function SponsorshipSummary({ queueNumber }: any) { +export default function SponsorshipSummary({ queueNumber }: { queueNumber: number }) {
34-37
: Avoid re-wrapping BigInt and destructure with types for safety.sponsorship[0] is already bigint from viem; BigInt(…) around a bigint is unnecessary and can bite during refactors. Destructure with explicit tuple typing.
- const sponsorship: any = data; - const estimatedCost = BigInt(sponsorship[0]); - const timestamp = Number(sponsorship[1]); - const sponsor = sponsorship[2]; + const [estimatedCost, timestampBn, sponsor] = + data as readonly [bigint, bigint, Address]; + const timestamp = Number(timestampBn);
41-43
: Tiny nit: compute Date once to avoid duplicate work.Precompute and reuse.
- {new Date(timestamp * 1_000).toISOString().substring(0,10)} {new Date(timestamp * 1_000).toISOString().substring(11,16)} + {(() => { + const d = new Date(timestamp * 1_000); + const iso = d.toISOString(); + return `${iso.substring(0,10)} ${iso.substring(11,16)}`; + })()}
9-24
: Trim debug logs or gate behind an env flag.Spammy console output in production hurts UX. Consider a small debug util gated by NEXT_PUBLIC_DEBUG.
If helpful, I can add a
debug()
helper and replace these calls.frontend/src/pages/sponsorships/[queueNumber].tsx (1)
31-31
: Validate route param before rendering and keep 1‑based UX consistent.Ensure the param is present and valid (positive integer). This prevents NaN from propagating and aligns with the component’s 1‑based prop.
- <SponsorshipSummary queueNumber={queueNumber} /> + <SponsorshipSummary queueNumber={queueNumber} />Add guards above (outside this hunk):
// after const router = useRouter(); const queueNumber = Number(router.query.queueNumber); const isValid = Number.isInteger(queueNumber) && queueNumber > 0; if (!router.isReady) return null; // or <LoadingIndicator /> if (!isValid) return <div className="mt-8 p-4">Invalid queue number.</div>;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
frontend/src/components/SponsorshipSummary.tsx
(2 hunks)frontend/src/components/Sponsorships.tsx
(2 hunks)frontend/src/pages/sponsorships/[queueNumber].tsx
(1 hunks)frontend/src/pages/sponsorships/add.tsx
(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- frontend/src/components/Sponsorships.tsx
- frontend/src/pages/sponsorships/add.tsx
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: jo-elimu
PR: elimu-ai/web3-sponsors#74
File: backend/ignition/modules/SponsorshipQueue.ts:9-17
Timestamp: 2025-08-12T06:22:30.517Z
Learning: The web3-sponsors project has not deployed to Ethereum Mainnet yet. The placeholder "0x addr mainnet" in backend/ignition/modules/SponsorshipQueue.ts is intentional and appropriate for the current deployment state.
📚 Learning: 2025-08-12T06:22:30.517Z
Learnt from: jo-elimu
PR: elimu-ai/web3-sponsors#74
File: backend/ignition/modules/SponsorshipQueue.ts:9-17
Timestamp: 2025-08-12T06:22:30.517Z
Learning: The web3-sponsors project has not deployed to Ethereum Mainnet yet. The placeholder "0x addr mainnet" in backend/ignition/modules/SponsorshipQueue.ts is intentional and appropriate for the current deployment state.
Applied to files:
frontend/src/components/SponsorshipSummary.tsx
🧬 Code graph analysis (1)
frontend/src/pages/sponsorships/[queueNumber].tsx (1)
frontend/src/components/SponsorshipSummary.tsx (1)
SponsorshipSummary
(8-50)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Redirect rules - web3-sponsors
- GitHub Check: Header rules - web3-sponsors
- GitHub Check: Pages changed - web3-sponsors
- GitHub Check: build (windows-latest, 18.x)
- GitHub Check: build (windows-latest, 20.x)
🔇 Additional comments (2)
frontend/src/components/SponsorshipSummary.tsx (1)
15-20
: Confirmed: ABI tuple order matches (estimatedCost, timestamp, sponsor).
Verified queue() ABI in backend/ignition/deployments/chain-11155111/artifacts/SponsorshipQueueModule#SponsorshipQueue.json — outputs are [estimatedCost, timestamp, sponsor]; no change required.
elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.frontend/src/pages/sponsorships/[queueNumber].tsx (1)
31-31
: Confirm 1‑based queueNumber usage in SponsorshipSummary and callersIf SponsorshipSummary now expects a 1‑based queueNumber for UX, verify all call sites (e.g., Sponsorships.tsx) pass i + 1 and that SponsorshipSummary converts to 0‑based only for contract reads. Automated search failed here (rg reported unrecognized tsx); please run locally: rg -nC2 'SponsorshipSummary' and check indexing at each call site.
elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.
args: [queueNumber] | ||
}); |
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.
Fix off‑by‑one: contract index vs. human display is inconsistent (likely wrong item fetched).
The page now passes a 1‑based queueNumber from the route, but:
- You call the contract with args: [queueNumber] (1‑based),
- Then display Queue number: #{queueNumber + 1} (effectively 2‑based).
This will read the wrong queue entry on-chain and display an incorrect number. Align to a single convention: treat props as 1‑based for UX, convert to 0‑based only for the contract call.
Apply:
- functionName: "queue",
- args: [queueNumber]
+ functionName: "queue",
+ args: [BigInt(queueNumber - 1)]
- Queue number: #{queueNumber + 1}
+ Queue number: #{queueNumber}
Context: Getting this right is key for trust—elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.
Also applies to: 40-41
🤖 Prompt for AI Agents
In frontend/src/components/SponsorshipSummary.tsx around lines 19-20 (and also
apply the same fix at lines 40-41): the component is using a 1-based queueNumber
from the route but calling the contract with the raw 1-based value and then
displaying queueNumber + 1, causing an off-by-one error and wrong on-chain read;
convert the UX 1-based prop to 0-based only for the contract call (pass
queueNumber - 1 in args) and stop adding 1 when rendering the displayed "Queue
number" (render queueNumber directly), and make the same change for the other
occurrence on lines 40-41 so both contract calls and displays follow the single
1-based-for-UI / 0-based-for-contract convention.
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/src/pages/distributions/add.tsx (1)
5-5
: Guard against wrong-chain writes (import hooks)You’re using Sepolia artifacts (chain 11155111). Add chain guards to prevent wrong‑network submissions.
Apply this diff to extend the wagmi imports:
-import { useAccount, useSimulateContract, useWriteContract } from "wagmi"; +import { useAccount, useSimulateContract, useWriteContract, useChainId, useSwitchChain } from "wagmi";
🧹 Nitpick comments (14)
frontend/src/pages/distributions/add.tsx (10)
15-19
: Add chain hooks in component scopeRetrieve chain info and a switch helper.
Apply this diff:
const { address, isConnecting, isReconnecting } = useAccount(); + const chainId = useChainId(); + const { switchChain } = useSwitchChain();
45-54
: Gate UI on Sepolia; offer a “Switch to Sepolia” actionPrevents user confusion and failed txs when connected to the wrong network.
Apply this diff:
- {!address ? ( + {!address ? ( <button disabled={true} className="p-8 text-2xl text-zinc-400 bg-zinc-300 rounded-lg"> <div className="text-6xl rotate-12 mb-4">☝🏽</div> Connect wallet first </button> - ) : ( + ) : chainId !== 11155111 ? ( + <button + className="p-8 text-2xl bg-amber-200 dark:bg-amber-900 rounded-lg border-amber-400 border-r-4 border-b-4 hover:border-r-8 hover:border-b-8 hover:-translate-y-1 active:border-r-2 active:border-b-2" + onClick={() => switchChain({ chainId: 11155111 })} + > + Switch to Sepolia (11155111) + </button> + ) : ( <InputAndroidId /> )}
109-114
: Simulate with the actual accountIncluding the caller account makes the simulation reflect permissions/allowances precisely.
Apply this diff:
export function SimulateContractButton({ languageCode, androidId}: any) { console.debug("SimulateContractButton"); + const { address } = useAccount(); const deploymentAddress: Address = deployed_addresses["DistributionQueueModule#DistributionQueue"] as `0x${string}`; console.debug("deploymentAddress:", deploymentAddress);
10-10
: Type import for cleaner handler signaturesAvoid
any
by importing the event type.Apply this diff:
-import { useState } from "react"; +import { useState, type ChangeEvent } from "react";
65-68
: Type the onChange handlers (drop any)Improves IntelliSense and prevents accidental misuse.
Apply this diff:
- const handleLanguageCodeChange = (event: any) => { + const handleLanguageCodeChange = (event: ChangeEvent<HTMLSelectElement>) => { console.debug('handleLanguageCodeChange'); setLanguageCode(event.target.value); } ... - const handleAndroidIdChange = (event: any) => { + const handleAndroidIdChange = (event: ChangeEvent<HTMLInputElement>) => { console.debug('handleAndroidIdChange'); setAndroidId(event.target.value); }Also applies to: 72-75
98-104
: Stronger input validation (regex) and stricter checksValidate format, not just length. Android ID is typically hex; language codes are 3 letters.
Apply this diff:
- {((languageCode.length != 3) || (androidId.length != 16)) ? ( + {!isValid ? ( <button disabled={true} className="mt-4 p-8 text-2xl text-zinc-400 bg-zinc-300 rounded-lg"> Add Distribution 📦 </button> ) : ( <SimulateContractButton languageCode={languageCode} androidId={androidId} /> )}Add this just before the
return
inInputAndroidId
:const isValid = /^[A-Z]{3}$/.test(languageCode.trim()) && /^[0-9a-fA-F]{16}$/.test(androidId.trim());
136-138
: Surface clearer error details from simulationShow
shortMessage
ormessage
when available for actionable feedback.Apply this diff:
- if (isError) { - return <ErrorIndicator description={error.name} /> - } + if (isError) { + // wagmi BaseError often includes a helpful shortMessage + const desc = + (error as any)?.shortMessage || + (error as any)?.message || + error.name; + return <ErrorIndicator description={desc} /> + }
149-164
: Disable “Add Distribution” button while sending; optional tx feedbackPrevents duplicate clicks and improves UX. If desired, wire a receipt toast after
writeContract
.Apply this diff:
- const { writeContract } = useWriteContract(); + const { writeContract, isPending } = useWriteContract(); return ( <button - className="mt-4 p-8 text-2xl bg-indigo-200 dark:bg-indigo-950 rounded-lg border-indigo-400 border-r-4 border-b-4 hover:border-r-8 hover:border-b-8 hover:-translate-y-1 active:border-r-2 active:border-b-2" + disabled={isPending} + className="mt-4 p-8 text-2xl bg-indigo-200 dark:bg-indigo-950 rounded-lg border-indigo-400 border-r-4 border-b-4 hover:border-r-8 hover:border-b-8 hover:-translate-y-1 active:border-r-2 active:border-b-2 disabled:opacity-60" onClick={() => writeContract({ abi, address: deploymentAddress, functionName: "addDistribution", args: [languageCode, androidId] }) } > - Add Distribution 📦 + {isPending ? "Sending..." : "Add Distribution 📦"} </button>
80-89
: Add labels/aria for a11yAssociate labels with the select/input for keyboard and screen-reader users.
Example:
<label className="block mb-2 text-sm" htmlFor="lang">Language</label> <select id="lang" aria-label="Language" ... /> <label className="block mt-4 mb-2 text-sm" htmlFor="androidId">Android ID</label> <input id="androidId" aria-label="Android ID" ... />Also applies to: 91-96
115-120
: Pass account into useSimulateContract; ABI verified (2 string inputs)ABI for addDistribution is (languageCode: string, androidId: string) — args are correct; add the connected EOA to the simulate call.
File: frontend/src/pages/distributions/add.tsx (lines 115–120)
const { isPending, isError, error, isSuccess } = useSimulateContract({ abi, address: deploymentAddress, functionName: "addDistribution", - args: [languageCode, androidId] + account: address as Address, + args: [languageCode, androidId] })elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.
frontend/src/components/DistributionSummary.tsx (4)
8-12
: Tighten types for safer propsUse an explicit props type to prevent accidental non‑integers making it into the hook.
-export default function DistributionSummary({ queueNumber }: any) { +type Props = { queueNumber: number }; +export default function DistributionSummary({ queueNumber }: Props) {
35-38
: Validate tuple field order against ABI and type the resultEnsure the tuple order matches the contract (languageCode, androidId, timestamp, distributor). Typing this eliminates silent misreads if the ABI changes.
- const distribution: any = data; - const languageCode = distribution[0]; - const androidId = distribution[1]; - const timestamp = Number(distribution[2]); - const distributor = distribution[3]; + type Distribution = readonly [string, string, bigint, Address]; + const [languageCode, androidId, ts, distributor] = data as Distribution; + const timestamp = Number(ts);
46-53
: Handle empty/uninitialized slots to avoid “1970‑01‑01”Uninitialized queue entries return zeroed structs; rendering them shows epoch time and empty strings. Add a lightweight guard.
- <div className="mt-2"> - {new Date(timestamp * 1_000).toISOString().substring(0,10)} {new Date(timestamp * 1_000).toISOString().substring(11,16)} - </div> + {timestamp > 0 ? ( + <div className="mt-2"> + {new Date(timestamp * 1_000).toISOString().substring(0,10)} {new Date(timestamp * 1_000).toISOString().substring(11,16)} + </div> + ) : ( + <div className="mt-2 text-zinc-500">Empty slot</div> + )}
11-11
: Optional: gate debug logs behind env flagReduce noisy logs in production builds.
if (process.env.NEXT_PUBLIC_DEBUG === "true") { console.debug("queueNumber:", queueNumber); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
frontend/src/components/DistributionSummary.tsx
(2 hunks)frontend/src/components/Distributions.tsx
(2 hunks)frontend/src/components/SponsorshipSummary.tsx
(2 hunks)frontend/src/pages/distributions/[queueNumber].tsx
(1 hunks)frontend/src/pages/distributions/add.tsx
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- frontend/src/components/Distributions.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/src/components/SponsorshipSummary.tsx
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-22T12:52:32.267Z
Learnt from: jo-elimu
PR: elimu-ai/web3-sponsors#81
File: backend/contracts/DistributionQueue.sol:0-0
Timestamp: 2025-08-22T12:52:32.267Z
Learning: In DistributionQueue.sol, the queue uses a mapping-based implementation where the first item is stored at index 0. The enqueue() function writes to queue[queueNumberNext] before incrementing queueNumberNext, and dequeue() reads from queue[queueNumberFront] before incrementing queueNumberFront. This creates a proper FIFO queue where items are enqueued starting at index 0, and the implementation is correct as-is.
Applied to files:
frontend/src/pages/distributions/[queueNumber].tsx
frontend/src/components/DistributionSummary.tsx
📚 Learning: 2025-08-22T12:52:32.267Z
Learnt from: jo-elimu
PR: elimu-ai/web3-sponsors#81
File: backend/contracts/DistributionQueue.sol:0-0
Timestamp: 2025-08-22T12:52:32.267Z
Learning: In DistributionQueue.sol, the queue uses a mapping-based implementation where the first item is stored at index 0. The enqueue() function writes to queue[queueNumberNext] before incrementing queueNumberNext, and dequeue() reads from queue[queueNumberFront] before incrementing queueNumberFront. This creates a proper FIFO queue where items are enqueued starting at index 0.
Applied to files:
frontend/src/pages/distributions/[queueNumber].tsx
frontend/src/components/DistributionSummary.tsx
🧬 Code graph analysis (2)
frontend/src/pages/distributions/add.tsx (1)
frontend/src/pages/sponsorships/add.tsx (1)
WriteContractButton
(101-123)
frontend/src/pages/distributions/[queueNumber].tsx (1)
frontend/src/components/DistributionSummary.tsx (1)
DistributionSummary
(8-56)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: build (windows-latest, 18.x)
- GitHub Check: build (ubuntu-latest, 20.x)
- GitHub Check: build (windows-latest, 20.x)
- GitHub Check: build (ubuntu-latest, 18.x)
- GitHub Check: build (windows-latest, 20.x)
- GitHub Check: build (windows-latest, 18.x)
- GitHub Check: Redirect rules - web3-sponsors
- GitHub Check: Header rules - web3-sponsors
- GitHub Check: Pages changed - web3-sponsors
🔇 Additional comments (2)
frontend/src/pages/distributions/add.tsx (1)
140-140
: LGTM: props now correctly forwarded to the write stepForwarding
languageCode
andandroidId
ensures parity between simulation and the actual on-chain call. This tightens the Add Distribution flow and helps us ship reliable UX toward our mission: elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.frontend/src/components/DistributionSummary.tsx (1)
19-20
: Incorrect off‑by‑one — contract is 1‑based; no UI index subtraction required.Backend (backend/contracts/DistributionQueue.sol) initializes queueNumberFront = 1 and queueNumberNext = 1 and uses those keys; frontend (frontend/src/components/DistributionSummary.tsx) passes args: [queueNumber] and Distributions passes i + 1 — do not convert to 0‑based. Optional: gate the contract read until queueNumber is an integer >= 1 to avoid invalid reads.
elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.
Likely an incorrect or invalid review comment.
|
||
<div className="mt-8 p-4 text-2xl bg-zinc-50 dark:bg-zinc-900 rounded-lg"> | ||
<DistributionSummary queueIndex={queueIndex} /> | ||
<DistributionSummary queueNumber={queueNumber} /> |
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.
🧩 Analysis chain
Guard rendering and validate route param before hitting the chain
Passing queueNumber
straight through is fine only if the child converts 1‑based UI → 0‑based contract index. Also prevent NaN
/invalid values during the initial render (Next.js router not ready) to avoid spurious contract reads.
Apply this minimal guard at the call site:
- <DistributionSummary queueNumber={queueNumber} />
+ {Number.isInteger(queueNumber) && queueNumber >= 1 ? (
+ <DistributionSummary queueNumber={queueNumber} />
+ ) : null}
Optional follow‑up (helps our mission’s reliability): run this to ensure no stale queueIndex
props remain:
Eliminating off‑by‑one pitfalls here keeps the Distributions UI trustworthy—important as elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.
🏁 Script executed:
#!/bin/bash
# Find any remaining queueIndex usages
rg -n --type=ts --type=tsx -C1 '\bqueueIndex\b'
Length of output: 27
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "1) locate files named [queueNumber].tsx"
find . -type f -name '[queueNumber].tsx' -print || true
echo "----"
echo "2) if found, print first 200 lines"
for f in $(find . -type f -name '[queueNumber].tsx' -print); do
echo ">>> $f"
sed -n '1,200p' "$f"
done
echo "----"
echo "3) search for queueIndex occurrences (no --type flags)"
rg -n -C1 '\bqueueIndex\b' || true
echo "----"
echo "4) search for DistributionSummary usages"
rg -n -C3 'DistributionSummary' || true
echo "----"
echo "5) list files in frontend/src/pages/distributions (if present)"
ls -la frontend/src/pages/distributions 2>/dev/null || true
Length of output: 3717
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== pages/distributions/[queueNumber].tsx ==="
sed -n '1,240p' frontend/src/pages/distributions/[queueNumber].tsx || true
echo
echo "=== components/DistributionSummary.tsx ==="
sed -n '1,240p' frontend/src/components/DistributionSummary.tsx || true
echo
echo "=== search for queueIndex occurrences ==="
rg -n '\bqueueIndex\b' -S || true
echo
echo "=== search for queueNumber occurrences ==="
rg -n '\bqueueNumber\b' -S || true
echo
echo "=== search for router.query references ==="
rg -n "router\.query" -S || true
echo
echo "=== search for parseInt or Number around queueNumber ==="
rg -n -C1 "parseInt|Number\(" -S || true
Length of output: 9672
Guard route param before calling DistributionSummary
router.query can be undefined on initial render; Number(router.query.queueNumber) can be NaN — validate before passing to DistributionSummary (it calls useReadContract with args: [queueNumber]).
- <DistributionSummary queueNumber={queueNumber} />
+ {Number.isInteger(queueNumber) && queueNumber >= 1 ? (
+ <DistributionSummary queueNumber={queueNumber} />
+ ) : null}
Also apply the same guard in frontend/src/pages/sponsorships/[queueNumber].tsx.
elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.
📝 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.
<DistributionSummary queueNumber={queueNumber} /> | |
{Number.isInteger(queueNumber) && queueNumber >= 1 ? ( | |
<DistributionSummary queueNumber={queueNumber} /> | |
) : null} |
🤖 Prompt for AI Agents
In frontend/src/pages/distributions/[queueNumber].tsx around line 31,
router.query.queueNumber may be undefined or non-numeric on initial render so
Number(router.query.queueNumber) can yield NaN; guard and validate the param
before passing it to <DistributionSummary /> (which ultimately calls
useReadContract). Fix by extracting queueNumber from router.query, check that it
exists and that Number(queueNumber) is a finite integer (or use parseInt +
isFinite) and only render <DistributionSummary queueNumber={...}/> when valid;
otherwise render a loading/null fallback or redirect. Apply the same guard and
pattern in frontend/src/pages/sponsorships/[queueNumber].tsx.
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: 0
🧹 Nitpick comments (2)
frontend/src/components/Distributions.tsx (2)
33-36
: Safely normalize contract return to number; use strict equality.Prevents accidental NaN and avoids loose equality.
- const queueLength = Number(data); - console.debug("queueLength:", queueLength); - if (queueLength == 0) { + const queueLength = typeof data === "bigint" ? Number(data) : Number(data ?? 0); + console.debug("queueLength:", queueLength); + if (queueLength === 0) {
41-47
: Prefer Array.from and stable keys; keep 1‑based queueNumber.More idiomatic, avoids an unnecessary fill, and keys won’t collide.
- {Array(queueLength).fill(1).map((el, i) => - <Link key={i} href={`/distributions/${i + 1}`}> - <div className="skew-y-3 p-4 text-2xl bg-indigo-200 dark:bg-indigo-950 rounded-lg border-indigo-400 border-r-4 border-b-4 hover:border-r-8 hover:border-b-8 hover:-translate-y-1"> - <DistributionSummary queueNumber={i + 1} /> - </div> - </Link> - )} + {Array.from({ length: queueLength }, (_, i) => i + 1).map((queueNumber) => ( + <Link key={queueNumber} href={`/distributions/${queueNumber}`}> + <div className="skew-y-3 p-4 text-2xl bg-indigo-200 dark:bg-indigo-950 rounded-lg border-indigo-400 border-r-4 border-b-4 hover:border-r-8 hover:border-b-8 hover:-translate-y-1"> + <DistributionSummary queueNumber={queueNumber} /> + </div> + </Link> + ))}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
frontend/src/components/Distributions.tsx
(2 hunks)frontend/src/components/Sponsorships.tsx
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/src/components/Sponsorships.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/components/Distributions.tsx (1)
frontend/src/components/DistributionSummary.tsx (1)
DistributionSummary
(8-56)
🔇 Additional comments (1)
frontend/src/components/Distributions.tsx (1)
16-19
: Approve — ABI exposes getLength; no stale getQueueCount in frontend.backend/ignition/deployments/chain-11155111/artifacts/*SponsorshipQueue.json and *DistributionQueue.json contain "getLength"; no matches for getQueueCount in frontend; DistributionSummary passes queueNumber as the queue arg. Aligning this keeps us moving fast toward elimu.ai's mission: to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.
#65
Summary by CodeRabbit
New Features
Refactor
Chores