feat: add email field to transaction inputs and update related components.#398
feat: add email field to transaction inputs and update related components.#398onahprosper merged 4 commits intomainfrom
Conversation
…ents * Introduced an email field in TransactionCreateInput to capture user email during transaction creation. * Updated the transaction route to handle the new email field, ensuring it is trimmed and set to null if not provided. * Modified useSmartWalletTransfer and TransactionPreview components to include the user's email address when saving transactions, enhancing user data capture.
📝 WalkthroughWalkthroughAdds optional Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/api/v1/transactions/route.ts`:
- Line 160: Guard against non-string email values before calling .trim() by
converting or checking the type like you do for walletAddress: replace direct
body.email?.trim() usage with a safe conversion/check (e.g., if (body.email ==
null) resultEmail = null else resultEmail = String(body.email).trim()) so that
email becomes null when absent and never throws when body.email is a
number/object; update the code that sets email to use this safe result
(reference body.email, .trim(), and the walletAddress String() conversion
approach).
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
app/api/v1/transactions/route.tsapp/hooks/useSmartWalletTransfer.tsapp/pages/TransactionPreview.tsxapp/types.ts
* Added normalization for the email field in the transaction route to ensure it is trimmed and set to null if not provided, improving data integrity during transaction creation.
* Introduced an optional explorer_link field in the TransactionHistory interface to store links to transaction explorers. * Updated the POST and PUT transaction routes to generate and include the explorer link based on the network and transaction hash, enhancing transaction visibility and user experience.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
app/api/v1/transactions/route.ts (1)
147-150: Minor inconsistency in default value between POST and PUT handlers.Here the default is
""(empty string), while[id]/route.tsusesundefined. Both are falsy and work correctly with the conditional spread, but for consistency consider using the same default:Optional: Align with PUT handler pattern
const explorerLink = body.network && body.txHash ? getExplorerLink(body.network, body.txHash) - : ""; + : undefined;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/v1/transactions/route.ts` around lines 147 - 150, The POST handler sets explorerLink to an empty string while the PUT handler uses undefined; change the POST assignment of explorerLink (where getExplorerLink(body.network, body.txHash) is called) to use undefined as the default when body.network or body.txHash are missing so it matches the PUT handler pattern (keep the same conditional logic using body.network and body.txHash and the getExplorerLink call).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/api/v1/transactions/`[id]/route.ts:
- Line 80: The transactions table is missing columns referenced by the updater
(explorer_link via explorerLink, plus network, order_id, and email), which will
cause Supabase "column does not exist" errors; update the DB migration that
creates the transactions table to add columns network, order_id, email, and
explorer_link with appropriate SQL types and nullability (e.g., text/varchar for
network and explorer_link, varchar/uuid for order_id if applicable, and
text/varchar for email), include corresponding DOWN/rollback removal, run the
migration, and then re-run the handler that writes those keys so the conditional
spread (...(explorerLink && { explorer_link: explorerLink })) will no longer
trigger missing-column errors.
---
Nitpick comments:
In `@app/api/v1/transactions/route.ts`:
- Around line 147-150: The POST handler sets explorerLink to an empty string
while the PUT handler uses undefined; change the POST assignment of explorerLink
(where getExplorerLink(body.network, body.txHash) is called) to use undefined as
the default when body.network or body.txHash are missing so it matches the PUT
handler pattern (keep the same conditional logic using body.network and
body.txHash and the getExplorerLink call).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 5fc59e8d-179d-4d79-99e5-24af63c1ddea
📒 Files selected for processing (3)
app/api/v1/transactions/[id]/route.tsapp/api/v1/transactions/route.tsapp/types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- app/types.ts
* Added email, order_id, network, email_sent_at, and explorer_link fields to the transactions table for enhanced transaction tracking and user data capture. * Updated the created_at field to ensure proper timestamp handling.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
supabase/migrations/create_transactions_table.sql (2)
17-17: Prefer DB-managedupdated_atto avoid drift.
updated_atcurrently has only an insert default at Line 17. Even thoughapp/api/v1/transactions/[id]/route.ts(Line 73-87) sets it manually, DB-level trigger protection is safer and consistent with existing pattern insupabase/migrations/create_wallet_migrations.sql:35-48.Proposed trigger
+CREATE OR REPLACE FUNCTION public.update_transactions_updated_at() +RETURNS trigger LANGUAGE plpgsql AS $$ +BEGIN + NEW.updated_at = now(); + RETURN NEW; +END; +$$; + +DROP TRIGGER IF EXISTS transactions_update_updated_at ON public.transactions; +CREATE TRIGGER transactions_update_updated_at +BEFORE UPDATE ON public.transactions +FOR EACH ROW EXECUTE FUNCTION public.update_transactions_updated_at();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@supabase/migrations/create_transactions_table.sql` at line 17, The transactions table defines updated_at with only an insert default, which allows application-level updates to drift; add a DB trigger+trigger function that sets NEW.updated_at = timezone('utc'::text, now()) on UPDATE (and/or INSERT) to ensure DB-managed timestamps, modeled after the pattern used in create_wallet_migrations.sql (see the trigger function and trigger installation around lines 35-48); update create_transactions_table.sql to create the plpgsql trigger function (e.g., transactions_set_updated_at()) and attach it to the transactions table for BEFORE UPDATE (and optionally BEFORE INSERT) so updated_at is always maintained by the database.
19-24: Add an index for the email dispatch selector.PR objective relies on filtering by
email IS NOT NULL AND email_sent_at IS NULL, but current indexes (Line 21, Line 24) won’t optimize that path.Proposed index
CREATE INDEX idx_transactions_created_at ON transactions(created_at DESC); +CREATE INDEX idx_transactions_email_pending + ON transactions (created_at DESC) + WHERE email IS NOT NULL AND email_sent_at IS NULL;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@supabase/migrations/create_transactions_table.sql` around lines 19 - 24, The current indexes (idx_transactions_wallet_address, idx_transactions_created_at) don't cover the email-dispatch filter; add a partial index to speed up queries filtering WHERE email IS NOT NULL AND email_sent_at IS NULL by creating an index targeting the email dispatch selector (e.g., name it idx_transactions_email_pending) on the transactions table with the matching WHERE predicate so the planner can use the index for those queries.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@supabase/migrations/create_transactions_table.sql`:
- Around line 16-17: The current CREATE TABLE may already have been applied, so
add a new additive migration that ALTER TABLE public.transactions and runs ADD
COLUMN IF NOT EXISTS for the five missing columns (email, order_id, network,
email_sent_at TIMESTAMP WITH TIME ZONE, explorer_link) so existing databases
gain these columns; ensure the migration uses IF NOT EXISTS for each column and
matches the types used by the transactions insert logic in the transactions
route handler that writes to email, order_id, network, email_sent_at, and
explorer_link.
---
Nitpick comments:
In `@supabase/migrations/create_transactions_table.sql`:
- Line 17: The transactions table defines updated_at with only an insert
default, which allows application-level updates to drift; add a DB
trigger+trigger function that sets NEW.updated_at = timezone('utc'::text, now())
on UPDATE (and/or INSERT) to ensure DB-managed timestamps, modeled after the
pattern used in create_wallet_migrations.sql (see the trigger function and
trigger installation around lines 35-48); update create_transactions_table.sql
to create the plpgsql trigger function (e.g., transactions_set_updated_at()) and
attach it to the transactions table for BEFORE UPDATE (and optionally BEFORE
INSERT) so updated_at is always maintained by the database.
- Around line 19-24: The current indexes (idx_transactions_wallet_address,
idx_transactions_created_at) don't cover the email-dispatch filter; add a
partial index to speed up queries filtering WHERE email IS NOT NULL AND
email_sent_at IS NULL by creating an index targeting the email dispatch selector
(e.g., name it idx_transactions_email_pending) on the transactions table with
the matching WHERE predicate so the planner can use the index for those queries.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f5c6cce7-2071-4468-a894-0887a09ef853
📒 Files selected for processing (1)
supabase/migrations/create_transactions_table.sql
Description
This PR adds optional email support to transaction creation so that when a user completes a swap or transfer in Noblocks, their Privy email (when present) is stored on the transaction record. Downstream automation (e.g. Activepieces → Brevo) can then send transaction confirmation emails only to users who have an email, and use
email_sent_atto avoid duplicate sends.Background: The
transactionstable already had (or was extended with) anemailcolumn. The app was not sending the user's email when creating swap/transfer records, so automation could not target users by email. This change wires the existing Privy user email into the transaction payload for both flows.Changes:
TransactionCreateInputnow includes optionalemail?: string./api/v1/transactionspersistsemail(trimmed or null) on insert.TransactionPreview.tsxpassesuser?.email?.addressinto the transaction object insaveTransactionData.useSmartWalletTransfer.tspassesuser?.email?.addressinto the transaction object when callingsaveTransaction.Impacts: No breaking changes. Email is optional; existing callers and rows are unchanged. Rows without email continue to work; only users with a Privy email have it stored. Activepieces (or similar) can filter with
email IS NOT NULLandemail_sent_at IS NULLand setemail_sent_atafter sending to prevent duplicate emails.Database: run this migration in Supabase SQL.
-- Add columns used by the app and by Activepieces
ALTER TABLE transactions
ADD COLUMN IF NOT EXISTS email TEXT,
ADD COLUMN IF NOT EXISTS order_id TEXT,
ADD COLUMN IF NOT EXISTS network TEXT,
ADD COLUMN IF NOT EXISTS email_sent_at TIMESTAMP WITH TIME ZONE;
ADD COLUMN IF NOT EXISTS explorer_link TEXT;
Checklist
mainBy submitting a PR, I agree to Paycrest's Contributor Code of Conduct and Contribution Guide.
Summary by CodeRabbit