Conversation
…action (#660) * Update TransactionStatus to handle "refunded" status for onramp transactions alongside "expired" status, improving user feedback on transaction availability. * Refactor TransactionStatus to conditionally display onchain receipt based on transaction status, enhancing clarity for users on receipt availability.
* Update `useSwapButton` to prevent enabling the "Fund wallet" button for corridors with no liquidity when the balance is sufficient, ensuring clearer user guidance. * Modify `TransactionForm` to handle insufficient balance scenarios more effectively, pausing market limits when the amount exceeds the connected wallet balance. * Refactor balance calculations to determine the active wallet and its corresponding balance based on the user's wallet type, improving accuracy in transaction handling. * Adjust tests for `useSwapButton` to reflect the new logic, ensuring comprehensive coverage of edge cases related to liquidity and balance checks.
* Introduce `rateRequestSeqRef` to manage request sequences in `MainPageContent`, ensuring that only the latest request updates the state. * Update `useSwapButton` to accept a pre-computed `hasInsufficientBalance` flag, optimizing balance checks and maintaining compatibility with legacy callers. * Modify `TransactionForm` to pass the `hasInsufficientBalance` flag, enhancing the handling of insufficient balance scenarios during transactions.
* Enhance `MainPageContent` to ensure that the fetching state is correctly updated based on the request sequence, preventing stale state updates when conditions are not met. * Update `useSwapButton` to streamline the handling of insufficient balance scenarios, ensuring that the button's state reflects the user's wallet status more accurately without redundant checks.
…664) * fix: add liquidity band checks and toast suppression for no-provider scenarios * Introduced `isSendAmountOutsideLiquidityBand` to determine if a send amount exceeds the defined liquidity corridor limits. * Added `shouldSuppressNoProviderForLiquidity` to suppress legacy no-provider messages when the form already communicates the limits. * Updated tests to validate the new functionality, ensuring correct behavior for amounts above and below the liquidity band. * Enhanced `MainPageContent` to utilize the new checks for improved user experience during rate requests. * refactor: enhance rate fetching logic with active state management
* fix: add swap refund skipping logic to Moralis deposit processing - Introduced a check to skip processing deposits that are identified as swap refunds, enhancing the handling of transactions. - Added logging for development environment to indicate when a deposit is skipped due to being a swap refund. - Updated both native and ERC20 deposit processing functions to include this new logic, ensuring consistent behavior across transaction types. * refactor: streamline swap refund detection logic in Moralis deposit processing * test: add unit tests for isPaycrestGatewayAddress and refactor existing tests - Introduced new tests for the isPaycrestGatewayAddress function to validate its behavior with known and arbitrary wallet addresses, including edge cases for missing addresses. - Refactored calculateCorrectedTotalBalance tests to improve clarity and maintainability. - Removed outdated tests for isPaycrestGatewayAddress from moralis-skip-swap-refund.test.ts as they are now covered in the new test suite.
Resolved conflicts in MainPageContent.tsx: - Kept main's active/invalidate pattern for effect cleanup - Preserved branch's skipMarketForInsufficientBalance logic - Integrated main's liquidity band checks and error suppression - Removed unused rateRequestSeqRef (replaced by active/invalidate)
…#663) * feat: enhance Earn feature with EVM support and LayerSwap integration - Added configuration options for EVM Earn and LayerSwap API in .env.example and config.ts. - Introduced new components and hooks to manage EVM Earn flows, including EarnBridgeTracker and useEvmEarnHandler. - Updated existing components (e.g., EarnActivityPanel, EarnWalletForm) to support EVM-specific logic and display. - Implemented filtering for earn activity based on the source chain, allowing for better user experience across different networks. - Enhanced UI elements to indicate when Earn is unavailable on certain networks, improving clarity for users. - Refactored related types and utility functions to accommodate new EVM features and ensure type safety. * refactor: enhance LayerSwap integration and error handling - Updated .env.example to include optional LayerSwap API base URL configuration. - Refactored LayerSwap API routes to improve error handling, including timeout responses for transaction confirmations. - Introduced validation functions for parsing amounts in LayerSwap requests, ensuring robust input handling. - Enhanced the Earn bridge status tracking to include wallet ID in API calls, improving user-specific data retrieval. - Updated hooks and utility functions to support new validation and error handling logic, ensuring a smoother user experience. * feat: enhance earnPositionStore with new formatting and claim handling. * refactor: update USDC formatting constants for improved clarity * feat: enhance Earn feature with EVM wallet support
…e-available-balance-check Enhance swap button behavior and transaction form logic
…g logic - Introduced a new test suite for the useBridgeQuote hook, covering various scenarios including fallback mechanisms between NEAR and LI.FI. - Updated BridgeForm component to improve quote handling and distinguish between fetched and non-fetched states. - Refactored bridge.ts to streamline quote fetching logic, ensuring better handling of unsupported asset pairs and slippage configurations. - Enhanced error handling and user feedback for scenarios where no routing options are available.
…or-on-usdc-base-convert-transactions feat: enhance quote routing logic to avoid no route available errors for Base
* feat: update contribution guidelines and issue templates to integrate Jira tracking - Revised README.md to include instructions for filing engineering work in Jira and updated the developer Telegram link. - Enhanced pull request template to specify linking Jira issues and clarified the handling of GitHub issues. - Updated bug report and feature request templates to direct users to create tickets in Jira instead of GitHub Issues, including specific instructions for linking GitHub PRs to Jira tickets. - Added a new contact link in the issue template configuration for engineering issues related to Jira KAN. * KAN-743: Address CodeRabbit review — required Jira field, branch naming Co-authored-by: Cursor <cursoragent@cursor.com> * KAN-743: Use config.yml, mailto security link, remove submittable issue templates Co-authored-by: Cursor <cursoragent@cursor.com> * chore: enhance documentation for Jira ticketing and PR processes - Updated AGENTS.md to include links to the ticket specification and PR template for better clarity on filing new work. - Revised pull request template to emphasize that spec and acceptance criteria should be referenced from the linked Jira ticket. - Added guidance in issue-tracker.md regarding the use of ticket and PR templates, ensuring consistency in issue filing and tracking. * Use reponame Jira labels without repo- prefix. Align agent docs, AGENTS.md, and issue template config with KAN label convention. Co-authored-by: Cursor <cursoragent@cursor.com> * Use reponame Jira labels without repo- prefix. Update ticket-spec-template and README where applicable. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor: update EarnConsentModal styles and structure - Adjusted the modal's layout and styling for improved visual consistency, including changes to border radius and padding. - Enhanced checkbox styling for better user interaction and clarity. - Updated button classes to ensure proper background and text color handling across themes. * refactor: update button classes in EarnConsentModal for consistency
… tests - Added comprehensive unit tests for auto-substitution rules, covering various scenarios including goalkeeper replacements and bench priority. - Introduced tests for Noblocks Match Bonus (NMB) eligibility and scoring, ensuring correct handling of tie rules and winning goal ordinals. - Implemented validation tests for fantasy challenges, focusing on gameweek constraints and prize budget enforcement. - Added pagination helper tests to ensure correct chunking of arrays and adherence to PostgREST limits. - Removed outdated referral sweep tests to streamline the codebase. These changes improve the robustness of the fantasy module by ensuring critical functionalities are well-tested and validated.
- Added unit tests for handling terminal postponed and cancelled statuses in the hasActiveFixtures function, ensuring accurate game state evaluation. - Updated the API route to improve error handling for matchday scores, profiles, and fixtures, ensuring robust data retrieval and error management. - Refactored the MatchdayPanel component to accept matchdayId as a prop, enhancing its flexibility and reusability. - Improved identity deduplication logic in KYC processing, ensuring accurate handling of identity keys and profiles. - Enhanced rate limiting logic to better manage user and IP-based requests, improving overall system reliability. These changes improve the accuracy of fixture status evaluations and enhance the robustness of the API and user experience in the fantasy module.
- Updated the authorization middleware to strip client-supplied identity headers (x-user-id, x-wallet-address) for enhanced security against forged requests. - Refactored rate limiting logic to use x-wallet-address as the identity key, ensuring that only verified wallets are considered, while removing reliance on x-user-id to prevent forgery. - Enhanced overall request handling to improve system reliability and security. These changes strengthen the integrity of user identity verification and rate limiting mechanisms in the application.
The EPL season migration declares fantasy_worker_release(p_token UUID) but revokes fantasy_worker_release(TIMESTAMPTZ) — a signature that does not exist. The function originally took the started_at timestamp and was refactored to a uuid ownership token; the REVOKE was not updated with it. Postgres raises 42883 on REVOKE against a non-existent signature, so the statement aborts and, inside the migration transaction, rolls the whole file back: no EPL settings, no mini-leagues, no challenges, no worker lock. CI did not catch it because the migrate job was skipped on the PR run. The line must be corrected rather than deleted: functions grant EXECUTE to PUBLIC by default, so dropping it would leave a SECURITY DEFINER function that clears the worker run-lock callable by anon/authenticated. Verified against PostgreSQL 16 by applying the full fantasy migration chain end to end: all five files apply, PUBLIC holds no EXECUTE on either worker lock function, and acquire → blocked-reacquire → release → reacquire behaves as designed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017yHcQR6Cg2ej49PmSEqQzD
…ke-signature fix(fantasy): correct REVOKE signature that aborts the EPL season migration
The scoring worker is driven by an external Cloudflare cron, so neither browser RUM nor the Mixpanel API-analytics path observes it. Its WorkerReport already carries what on-call needs — work done per tick, remaining API-Football budget, and internal failures — but it was only returned to the caller and dropped. A dead cron or a failing rollover was invisible: scores simply stop updating with no error anywhere. Adds a server-side Datadog log shipper and emits one structured line per tick, flattened into @worker.* facets so Datadog can generate metrics and monitors from them (notably a "no tick in 10 minutes" page). - app/lib/datadog.server.ts: posts to the HTTP logs intake, reusing the RUM client's site/service/env config. Gated on DD_API_KEY (a server secret, deliberately not NEXT_PUBLIC_), off in dev unless NEXT_PUBLIC_DD_ENABLE_IN_DEV=true. Never throws, bounded at 2s via AbortController — AbortSignal.timeout is absent on some runtimes, and an unbounded intake call is the failure this guard exists to prevent. - app/lib/fantasy/telemetry.ts: WorkerReport -> facets. Ticks carrying alerts log at warn even though they returned 200, since rollover and score recompute can fail inside an otherwise successful tick. Failure logs share the @worker.* namespace with ok:false so a heartbeat query counts crashed ticks and a crash loop can't read as healthy. - Worker route emits on both success and catch paths. The call is awaited rather than fire-and-forget: serverless runtimes freeze the invocation on return and would drop the request.
Restores provider headshots across the Play surfaces. Faces were swapped for stylized club kits in 80932b4; this turns them back on while keeping the kit as the fallback rather than replacing it outright. Two things independently suppressed photos, so flipping the setting alone would not have been enough: - PitchView's PlayerPhoto still carried its name but rendered ClubJersey unconditionally, ignoring photo_url. It is the single choke point for all four render sites (pitch, both TeamManager sheets, PlayerPicker), so restoring it there covers every list and card at once. Preference order is now headshot -> club kit -> caller fallback, so a missing or broken photo degrades to the kit instead of a hole. - ManagerTeamView hardcoded photo_url: null when mapping the public team, discarding what the API already sent. No flag is threaded into the components: the APIs already null photo_url unless photos_enabled is on, so the setting alone decides whether faces appear. That flag is flipped in the EPL season migration, which is a full config overwrite and has never applied successfully anywhere yet. PlayerPhoto remembers the URL that failed rather than a boolean, because these components are reused across players in scrolling lists and a boolean would keep suppressing the next player's perfectly good photo. The OG squad card fetches headshots up front and inlines them as data URIs instead of handing Satori remote URLs. Satori would fetch them during render, where one dead provider URL throws and takes the whole card down; pre-fetching lets a bad URL fall back to that single player's kit. Requests run in parallel, each bounded at 2.5s. Share URL version bumped to bust CDN and social-scraper caches. No CSP change needed — the app sets only frame-ancestors, so there is no img-src to widen for the provider host.
Three findings from the CodeRabbit review on #671. 1. OG headshot fetch accepted any 200 as an image. A provider returning an HTML error page was inlined as a data: URI and marked isPhoto, skipping the kit fallback and handing Satori something it cannot decode — the whole-card failure the pre-fetch exists to prevent. The media type is now matched against a strict image/* pattern, which also keeps anything odd in the header out of the URI built from it. 2. Failure-log message and stack were unbounded. Provider and Postgres errors can build their message from the data that caused them, so this was both a payload-size and an accidental-disclosure risk, and it was inconsistent with the 300-char cap already applied to alerts. Both are now bounded via a shared truncate helper. The review suggested dropping the stack. It is capped at 2000 chars instead: the frames are our own code paths and are the main reason to ship an error log at all, so removing them would defeat the purpose while adding little privacy beyond the cap. 3. The FANTASY_WORKER_SECRET row in the Cloudflare variables table was left with one cell, tripping markdownlint MD056. This came in when an in-flight edit to that line was swept into 8fcccfa.
Replaces the direct HTTP log shipper with the same observability stack the
aggregator runs: dd-trace for APM, JSON logs with trace correlation, and a
Datadog Agent sidecar. app/lib/datadog.server.ts is deleted — logs now go
to stdout for the agent to collect rather than being POSTed from app code,
so the app no longer needs a Datadog API key at all.
The finding that motivated this: next.config.mjs set
removeConsole: process.env.NODE_ENV === "production"
which applies to server code, not just the browser bundle. Verified against
a production build — the console.error strings from the API routes appeared
only in .js.map, never in the emitted chunks. Every server-side console call
was being stripped, so no agent or log drain could ever have collected one.
Now { exclude: ["warn", "error", "info"] }; console.log is still stripped.
Confirmed by rebuild: those strings now appear in the server chunks.
- instrumentation.ts: dd-trace init, Node runtime only (dd-trace cannot load
on Edge, so middleware is not traced). No experimental.instrumentationHook
— instrumentation.ts is stable in Next 15 and that flag no longer exists.
- app/lib/logger.ts: pino with dd.trace_id/dd.span_id injection, Datadog's
`status` level key and ms `timestamp`, and redaction of auth/cookie/token
fields.
- fantasy telemetry now emits through the logger. The @worker.* attribute
shape is unchanged, so the dashboard widgets and monitors built on it
stay valid. Emission is synchronous now — pino writes to a stream, so
there is no in-flight request for the runtime to drop and nothing to
await.
- dd-trace and pino added to serverExternalPackages: dd-trace patches
modules at require time and pino resolves transports through worker
threads, so bundling either breaks it.
- @datadog/native-metrics added to pnpm.onlyBuiltDependencies. pnpm blocks
install scripts by default, which would silently leave runtimeMetrics
inert.
- docker-compose.datadog.yml + .env.datadog.example for the DigitalOcean
Docker host. Agent ports bind to 127.0.0.1 only. .env.datadog added to
.gitignore, which covered .env and .env*.local but would not have caught
it.
- OBSERVABILITY.md documents the pipeline, the worker attributes, the four
monitors, and verification steps.
service.datadog.yaml carries TODO placeholders for team handle, contact and
dashboard URL rather than invented values.
Five findings from the CodeRabbit review of f0501c1. 1. Logger redaction missed root-level fields. Every path was the "*.token" form, which fast-redact treats as "iterate the root object's children and redact `token` in each" — it does not match a root-level { token: ... }, which is the shape most call sites use. Verified: with the old paths, logger.info({ token: "SECRET" }) wrote SECRET in clear. Bare paths added alongside the wildcards; fast-redact has no recursive wildcard so each depth must be listed. Covered by a new test that captures what the logger actually writes rather than asserting on config. 2. Monitor queries in OBSERVABILITY.md were not scoped to an environment. Staging shares the Datadog org, so the absence monitor would have been satisfied by staging ticks and a production outage would never have paged — the monitor inverted into a liability. All four now carry service:noblocks env:production, with a note not to drop the scope. 3. DD_TRACE_ENABLED was documented as taking effect "without a redeploy". It is read once in register() at process startup, so it needs a restart. Corrected in the env docs, .env.example and at the point of use in instrumentation.ts. 4. The env docs described traces and logs as both talking to the agent. They take different routes — traces over :8126, logs via stdout that the agent collects — which matters when debugging one of them, since logs survive with no agent running and traces do not. Now a table. 5. Architecture diagram fence had no language (markdownlint MD040). service.datadog.yaml still carries TODO placeholders for team handle, contact alias and dashboard URL. Left open deliberately rather than inventing values.
…emetry feat: Datadog server-side observability (APM + structured logs) and player faces
…up) (#673) * docs(agents): map Bug/Task tickets to Jira custom fields Use typed KAN fields for Bug vs Task (mutually exclusive); document field ids for Atlassian MCP; never Story/Feature. * docs(agents): address CodeRabbit review on KAN-743 follow-up Align flowchart scope, drop stale Working Agreement wording, and document Money-safety select option encoding for MCP. * docs(agents): require ADF for Jira rich-text fields
…nEnded component - Added countdown functionality to display time remaining until the Premier League season launch. - Updated CampaignEnded component to show a prelaunch announcement when the campaign is not yet ended. - Modified PlayShell and PlayFooter components to handle prelaunch state, ensuring proper display of navigation and footer elements. - Adjusted layout metadata to reflect upcoming campaign details.
…sy-on-noblocks feat(play): implement countdown and prelaunch announcement
Contributor
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
* Implement identity-scoped referral and cashback claim checks - Introduced `resolveOwnIdentityFingerprint` and `resolveIdentityScope` functions to ensure referral and cashback claims are validated against a user's verified identity across multiple wallets. - Updated referral and cashback claim routes to utilize these new identity checks, preventing multiple claims from the same identity. - Added new columns for identity phone and ID key in the referrals and referral claims tables, along with unique indexes to enforce identity-scoped constraints. - Enhanced error handling for identity verification failures during claim processes, ensuring users receive appropriate feedback. This update strengthens the integrity of the referral and cashback systems by enforcing identity-based limits on claims. * Enhance cashback claim processing by integrating EOA and smart wallet address resolution - Added new functions to map embedded/EOA wallet addresses to their corresponding smart wallet addresses, facilitating accurate cashback claims. - Updated the cashback claim route to utilize these new mappings, ensuring claims are processed against the correct identity scope. - Improved error handling for identity resolution failures during cashback claims, enhancing user feedback and system reliability. This update strengthens the cashback claim process by bridging the gap between EOA and smart wallet address spaces. * Refactor cashback claim processing to improve identity scope resolution - Moved identity scope resolution logic to occur after checking for existing claims, ensuring that retries on processed transactions do not incur additional costs or errors. - Enhanced error handling for identity resolution failures, providing clearer feedback to users in case of issues during cashback claim verification. - Updated comments for clarity and to reflect the new order of operations in the cashback claim process. This update optimizes the cashback claim workflow by ensuring efficient identity resolution while maintaining user experience during claim retries. * fix: apply CodeRabbit auto-fixes Fixed 1 file(s) based on 1 unresolved review comment. Co-authored-by: CodeRabbit <noreply@coderabbit.ai> * Enhance cashback claim processing and identity verification - Updated the cashback claim route to handle numeric fields as strings to preserve precision during serialization. - Improved error handling for duplicate transactions, providing clearer feedback to users when a claim already exists. - Enhanced messaging for maximum claims and cashback limits, clarifying that limits apply across all wallets linked to a verified identity. - Added logic to delete any pending claims if a malformed response is received, ensuring no allowance is consumed unnecessarily. This update optimizes the cashback claim workflow and improves user experience by providing clearer error messages and handling edge cases more effectively. * Enhance cashback claim validation and error handling - Added checks for invalid transaction amounts in the cashback claim route to prevent NaN values from affecting the quota function. - Implemented error responses for cases where the transaction amount is too small to earn cashback, ensuring users receive clear feedback. - Updated the cashback claim quota function in the database to handle malformed amounts and prevent unnecessary claim slot consumption. These improvements strengthen the integrity of the cashback claim process and enhance user experience by providing clearer error messages and handling edge cases effectively. * Enhance validation for cashback claim amounts - Updated the cashback claim quota function to include additional checks for invalid amounts, specifically handling NaN and Infinity values. - Improved error handling to ensure that malformed amounts do not affect the claim process, providing clearer feedback to users. These changes strengthen the robustness of the cashback claim system by preventing invalid inputs from causing issues during processing. * Close referrer-side identity gap and reclaim stranded cashback quota Addresses the review feedback on #659. Identity-level self-referral guard (app/api/referral/claim/route.ts): the fingerprint indexes stop a sibling wallet collecting a second referee reward, but the referrer side stamps no fingerprint — by design, since a referrer legitimately earns on many referrals. That left one person able to refer their own sibling wallets and collect a referrer reward per wallet, which address-equality in submit/route.ts cannot see. Both sides now reject when the two parties resolve to the same identity scope, fail closed on lookup error, and map SELF_REFERRAL to 403. Placed after the completed-claim short-circuit so already-paid claims stay idempotent. Stranded pending reservations (20260804120100): 'pending' rows count against the pooled caps, and only the route's catch block releases them. An invocation killed mid-flight stranded its reservation permanently across every wallet sharing that identity. A pg_cron sweep now fails rows older than 30 minutes that never recorded a tx_hash. Also: CHECK constraint (NOT VALID) so an unparseable amount cannot make the quota function's amount::NUMERIC cast fail every claim for an identity; bounded the smart-wallet cache with TTL eviction on read and a size cap; corrected the search_path comment, which described pg_temp as excluded when listing it last is what demotes it behind public; and softened the 'failed' quota note, which implied a retry that Step 8's idempotency lookup does not allow. Tests: resolveOwnIdentityFingerprint was untested — added coverage for the normalization that must stay in sync with the migration backfill, plus the fail-closed contract. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Canonicalize identity ID matching and prove no broadcast before reaping Addresses both CodeRabbit findings on the previous commit. Canonical ID key (20260805120000, app/lib/kyc-identity.ts): the id_* columns hold raw input — smile-id/route.ts falls back to the client-supplied number — but resolveIdentityScope matched them with exact equality, so one document stored two ways ("NG:PASSPORT:A123456" vs "ng:passport:a 123 456") failed to pool. Everything downstream inherited it: separate monthly allowances, separate cashback allowances, siblings serializing on different advisory locks (reopening the race the quota function exists to close), and the new self-referral guard missing a referrer that is really the referee's own wallet. Sibling lookups and lock keys now go through a generated identity_id_key column, with the single TS copy of the expression extracted as buildIdentityIdKey. Generated rather than written so it cannot drift and needs no backfill. Phone was already E.164-canonical on write and is unchanged. The KYC write path's own per-document uniqueness checks still compare the raw triple; retargeting those would tighten enrollment, which is a KYC behaviour change that does not belong here. Noted in the migration. Pre-broadcast marker (20260804120100, cashback route): tx_hash is only persisted after writeContract returns, so a null hash did not prove the transfer never happened — the reaper could release quota for a claim that was actually paid. The route now stamps transfer_attempted_at immediately before broadcasting and aborts if that write fails; the sweep reaps only unstamped rows. Stamped-but-hashless rows keep their reservation for manual reconciliation, which is the conservative side to err on. Note for deploy: 20260805120000 must be applied BEFORE the code ships — resolveIdentityScope filters on the new column. Old code is fine against the new schema, so migrate-then-deploy is the safe order. Tests: divergent-spelling coverage for resolveIdentityScope (asserting the query uses the canonical column and no raw-triple filter survives) plus buildIdentityIdKey units. 344 pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Keep broadcast-attempted claims reserved and align SQL/TS canonicalization Addresses the three findings on fdac43f. Indeterminate broadcast (cashback route): the marker stopped the *reaper* releasing quota for a possibly-paid claim, but the route's own catch still set 'failed' unconditionally — which releases the same reservation. A node can accept and broadcast a transfer while the client loses the response, so an error out of writeContract proves nothing. The catch now only marks 'failed' for errors thrown before the broadcast (token lookup, RPC config, key validation, the marker write itself); once writeContract is entered the claim stays 'pending' with its reservation and is logged for manual review. Consistent with how the reaper already treats stamped rows. Pre-marker rows (20260804120100): adding the column leaves every existing pending claim NULL, and for those NULL means "unknown", not "never broadcast" — the marker did not exist when they ran. The sweep would have treated exactly the unknowable rows as safe. They are now stamped with their created_at at migration time, excluding them until a human clears them. SQL/TS whitespace parity (20260805120000, 20260730120000, kyc-identity): btrim() with no second argument strips spaces only, so "\tng\t" canonicalized to NG in the app and to a tab-padded key in the generated column — one identity, two keys, defeating the point. All three copies now strip exactly [[:space:]] (the six ASCII whitespace characters), applied throughout rather than at the ends so internal spacing collapses too. The class is spelled out rather than using \s or trim(), which in JS also match NBSP and the Unicode separators that Postgres leaves alone. Tests: tab/newline/vertical-tab parity regression. 345 pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: CodeRabbit <noreply@coderabbit.ai> Co-authored-by: Chibuotu Amadi <chibuotu@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Dprof-in-tech
had a problem deploying
to
production
August 17, 2026 10:22 — with
GitHub Actions
Failure
Production already has 20260811120000_epl_fantasy_season applied. Identity-scoped referral/cashback migrations from #659 and the refund-accounts migration from #667 (stable-only) used earlier timestamps, so `supabase db push` refused to insert them before the remote head without --include-all. Rename those five files to 20260817180x so they apply in order after EPL and unblock main migrate / the main→stable promotion. Co-authored-by: Francis Ocholi <5ran6@users.noreply.github.com>
8 tasks
Match buildIdentityIdKey: NULLIF after [[:space:]] strip so empty or whitespace-only id_country/id_type/id_number do not produce keys with empty components. Align the generated column and TS helper the same way. Co-authored-by: Francis Ocholi <5ran6@users.noreply.github.com>
…-epl-bc42 fix(db): retimestamp migrations blocked behind applied EPL season
Production already has currency + refund_accounts_one_per_wallet_currency from the stable-only #667 apply, but the retimestamped 20260817180000 was not in the migrate ledger. Guard the unique constraint with a pg_constraint check so db push can record the version and continue to the identity migrations. Co-authored-by: Francis Ocholi <5ran6@users.noreply.github.com>
8 tasks
…potent-bc42 fix(db): idempotent refund_accounts currency migration for re-apply
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Promoting
main→stableThis PR promotes all features currently on
mainthat have not yet been released tostable. It is a rollup of merged PRs — no new code changes, just a branch promotion with a consolidated description for the deploy.Features being promoted
1. Transaction & swap reliability (KAN-733, KAN-739)
TransactionStatusnow treats"refunded"the same as"expired"for onramp transactions, and conditionally hides the onchain receipt when it is not yet available.useSwapButtonno longer enables "Fund wallet" for corridors with no liquidity when the balance is sufficient.TransactionFormpauses market limits when the amount exceeds the connected wallet balance.isSendAmountOutsideLiquidityBandcheck suppresses the legacy "no provider" toast when the form already communicates limits.2. Earn: EVM support & LayerSwap integration
/api/earn/layerswap/quote,swap,swap/status,starknet-deposit,withdraw-quote,withdraw-swap).EarnWalletFormhandles EVM-specific flows,EarnActivityPanelfilters by source chain,EarnSourcePositionCardadded for EVM positions.useBridgeQuotehook tests covering NEAR ↔ LI.FI fallback.3. Noblocks Play — EPL season launch prep (Fantasy)
fantasy_worker_releaseREVOKE signature (was referencing a droppedTIMESTAMPTZoverload).LeagueCardcomponent./api/play/admin/challengesroute for ops management.CampaignEndedcomponent now shows a countdown to the EPL season launch when the previous campaign has ended but the new one has not started.hasActiveFixtureshandles postponed/cancelled statuses; API routes improved for matchday scores, profiles, and fixtures.x-user-id/x-wallet-addressheaders; rate limiting now keyed on verified wallet address only.4. Datadog observability
dd-traceinitialized ininstrumentation.ts(Node runtime only; Edge middleware is not traced).dd.trace_id/dd.span_idinjection, Datadogstatuslevel key, redaction of auth/cookie/token fields (including root-level).docker-compose.datadog.ymlfor the DigitalOcean Docker host; agent ports bind to127.0.0.1only.@worker.*facets per tick for Datadog monitors (heartbeat, API budget, failures).consolestrip fix —next.config.mjswas stripping all server-sideconsole.*calls (includingwarn/error), making logs invisible to the agent. Now excludeswarn,error,info.OBSERVABILITY.md— documents the pipeline, worker attributes, four monitors, and verification steps.5. Jira migration (KAN-743)
AGENTS.mddocuments conventions, ticket spec template, and PR process.bug_report.md,feature_request.md) removed; replaced withconfig.ymlpointing to Jira.6. Swap refund detection (Moralis)
isPaycrestGatewayAddresstests.Deployment notes
Environment variables — new or changed
DD_SERVICEDD_ENVproduction,stagingDD_AGENT_HOST127.0.0.1)DD_TRACE_ENABLEDfalseto disable APM. Requires restart — read once at process startup, not hot-reloadableDD_API_KEYNEXT_PUBLIC_NEXT_PUBLIC_DD_ENABLE_IN_DEVNEXT_PUBLIC_EVM_EARN_ENABLEDNEXT_PUBLIC_LAYERSWAP_API_KEYNEXT_PUBLIC_LAYERSWAP_API_BASE_URLNEXT_PUBLIC_FANTASY_ENABLEDNEXT_PUBLIC_FANTASY_CAMPAIGN_ENDEDtrue, /play shows prelaunch countdown instead of live gameDatabase migration
fantasy_worker_release(p_token UUID)and revokes the oldfantasy_worker_release(TIMESTAMPTZ)signature — verify the migration chain applies cleanly against the current stable schema before merging.42883errors.Infrastructure
docker-compose.datadog.ymlto the DigitalOcean Docker host before enablingDD_TRACE_ENABLED. The app sends traces to:8126and logs via stdout (agent collects). Without the agent, traces are lost but logs still work..env.datadogis now in.gitignore— ensure the production host has this file with the realDD_API_KEY(if using direct log shipping) or agent config.Runtime behavior changes
removeConsoleinnext.config.mjsnow preservesconsole.warn,console.error, andconsole.infoon the server. This means server-side error logs are now visible to the Datadog agent — previously they were all stripped. No action needed, but be aware log volume may increase.dd-traceandpinoare inserverExternalPackages— they must not be bundled by Next.js. If the build fails on these, checknext.config.mjscarried over correctly.@datadog/native-metricsis inpnpm.onlyBuiltDependencies— pnpm blocks install scripts by default; without this the runtime metrics collector is silently inert.Feature flags for stable
NEXT_PUBLIC_FANTASY_ENABLEDandNEXT_PUBLIC_FANTASY_CAMPAIGN_ENDEDon stable. On main they are bothtrue(prelaunch countdown visible). If stable should show the live game, setFANTASY_CAMPAIGN_ENDED=false.NEXT_PUBLIC_EVM_EARN_ENABLED— confirm whether EVM Earn should be enabled on stable immediately or gated behind a later toggle.Monitoring
OBSERVABILITY.md. All are scoped toservice:noblocks env:production— do not drop the env scope or staging ticks will satisfy production monitors.