Skip to content

🥅 server: skip retries for replay reverts#757

Closed
nfmelendez wants to merge 1 commit intomainfrom
nicolas
Closed

🥅 server: skip retries for replay reverts#757
nfmelendez wants to merge 1 commit intomainfrom
nicolas

Conversation

@nfmelendez
Copy link
Copy Markdown
Contributor

@nfmelendez nfmelendez commented Feb 11, 2026

Panda sometimes doesn't care that we return 200 and the webhook retries again flooding our instrumetation so the PR is about preventing those retries to happen returning 200 only for Replay reverts

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved handling of contract replay scenarios to prevent unnecessary error escalation, ensuring idempotent request processing and enhanced reliability in transaction operations.
  • Tests

    • Added test coverage validating idempotent behavior for replayed requests in card creation, reversal, and refund flows.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Feb 11, 2026

🦋 Changeset detected

Latest commit: c9d1d65

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@exactly/server Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 11, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

The PR adds specialized handling for contract replay errors in the panda hook, treating them as non-fatal operations. It includes a changeset entry documenting the patch release and three new test cases validating the replay error handling behavior.

Changes

Cohort / File(s) Summary
Changeset Metadata
.changeset/silent-streets-jump.md
New changeset entry declaring a patch release for @exactly/server with a note about skipping retries for replay reverts.
Replay Error Handling
server/hooks/panda.ts, server/test/hooks/panda.test.ts
Adds specialized catch block logic to treat ContractFunctionRevertedError with errorName "Replay" as non-fatal, marking spans with panda.replay and panda.transaction attributes and returning ok status. Includes three test cases validating replay handling for card creation, reversal, and refund flows.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • cruzdanilo
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch nicolas

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown

gemini-code-assist bot commented Feb 11, 2026

Summary of Changes

Hello @nfmelendez, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the platform's backend infrastructure and user-facing features by overhauling webhook processing for greater reliability and introducing robust KYC and risk assessment integrations. It also streamlines development workflows with updated Node.js versions and new E2E testing pipelines, while enriching the mobile application with a new benefits section and improved asset display. The changes collectively aim to improve security, compliance, and user experience.

Highlights

  • Enhanced Webhook Management & Reliability: Implemented a new API for managing webhooks, including secure HMAC SHA256 signing, robust retry policies with exponential backoff, and mutex-based concurrency control. Crucially, the system now intelligently skips retries for 'Replay reverts' from Panda, preventing unnecessary instrumentation flooding and improving system efficiency. New HTTP status codes (558, 559) were introduced for high-risk transactions and refunds.
  • Comprehensive KYC Refactor and API: Introduced a refactored KYC API with dedicated endpoints for submitting, updating, and retrieving the status of KYC applications. This includes support for encrypted payloads, organization-based permissions, and a mechanism to identify and handle legacy KYC flows. Persona webhook integration was enhanced to include Sardine customer risk assessment and Pax Assistance onboarding.
  • Third-Party Integrations (Pax & Sardine): Integrated Pax Assistance with a new API endpoint to retrieve associate data and a backfill script for existing users. Sardine's risk assessment and feedback mechanisms were integrated into Panda webhooks for real-time transaction monitoring and fraud prevention.
  • Infrastructure & Development Workflow Improvements: Upgraded the Node.js runtime to 24.12.0 across the Dockerfile, package.json, and eas.json. New EAS workflows were added for local and production E2E testing, incorporating Maestro for UI automation. A new BullMQ queue was introduced for asynchronous handling of Alchemy webhook subscriber updates, improving performance and reliability.
  • Expanded Documentation: Added extensive new documentation covering organization authentication (including SIWE, organization creation, and invite management), key integration resources (Exa server IPs, Panda RSA public keys), and detailed webhook setup, security, flows, and event references.
  • Mobile UI/UX & Feature Enhancements: Introduced a new 'Benefits' section on the Home screen, featuring a carousel of partner benefits (e.g., Pax Assistance, Airalo, Visa Signature) with detailed modal sheets. The AssetLogo component was refactored to leverage expo-image for improved caching and performance. Card API responses now include cardId, and weak PIN error handling was improved.
  • Database & Authentication System Updates: Integrated better-auth with a new Drizzle adapter, expanding the database schema to include tables for users, sessions, organizations, members, and invitations. The authentication middleware was updated to support better-auth sessions.
  • PDF Statement Generation: Added functionality to generate PDF statements for user activity, allowing users to retrieve a printable summary of their transactions for a given maturity period.
Changelog
  • .changeset/chubby-comics-mix.md
    • Added a changeset file for @exactly/mobile related to adding a benefits section.
  • .changeset/common-carrots-think.md
    • Added a changeset file for @exactly/server related to KYC refactor.
  • .changeset/cool-snakes-reply.md
    • Added a changeset file for @exactly/server related to setting up better-auth database tables.
  • .changeset/cute-buttons-roll.md
    • Added a changeset file for @exactly/docs related to adding configuration resources.
  • .changeset/flat-books-mix.md
    • Added a changeset file for @exactly/mobile related to implementing asset logo caching.
  • .changeset/forty-ads-lie.md
    • Added a changeset file for @exactly/server related to adding Sardine integration.
  • .changeset/four-numbers-worry.md
    • Added a changeset file for @exactly/server related to implementing KYC data submission.
  • .changeset/fresh-kings-buy.md
    • Added a changeset file for @exactly/server related to standardizing card status.
  • .changeset/gold-ties-tan.md
    • Added a changeset file for @exactly/server related to returning correct card status.
  • .changeset/long-moons-brake.md
    • Added a changeset file for @exactly/server related to fixing webhook retries.
  • .changeset/long-nails-doubt.md
    • Added a changeset file for @exactly/server related to adding sandbox dedicated IPs.
  • .changeset/olive-onions-tan.md
    • Added a changeset file for @exactly/server related to adding webhook API.
  • .changeset/quick-ants-write.md
    • Added a changeset file for @exactly/server related to adding transaction receipt to webhook.
  • .changeset/quiet-bars-walk.md
    • Added a changeset file for @exactly/server related to adding Panda merchant category code.
  • .changeset/sharp-squids-push.md
    • Added a changeset file for @exactly/server related to adding role to organization database table.
  • .changeset/short-cars-return.md
    • Added a changeset file for @exactly/server related to adding queue on user creation.
  • .changeset/slick-hairs-relax.md
    • Added a changeset file for @exactly/server related to supporting Pax's assistance.
  • .changeset/soft-eggs-count.md
    • Added a changeset file for @exactly/server related to adding create card docs.
  • .changeset/stale-owls-work.md
    • Added a changeset file for @exactly/server related to adding card statement.
  • .changeset/tame-times-warn.md
    • Added a changeset file for @exactly/server related to supporting Pax's assistance.
  • .changeset/tidy-worms-sin.md
    • Added a changeset file for @exactly/server related to fixing patch response validation.
  • .changeset/upset-seas-sink.md
    • Added a changeset file for @exactly/server related to adding KYC role to organizations.
  • .changeset/violet-plums-move.md
    • Added a changeset file for @exactly/server related to forwarding webhooks to source.
  • .changeset/wet-games-relate.md
    • Added a changeset file for @exactly/server related to assessing transaction risk.
  • .changeset/wicked-lies-invent.md
    • Added a changeset file for @exactly/server related to returning card ID.
  • .changeset/wild-points-lose.md
    • Added a changeset file for @exactly/server related to improving weak PIN error handling.
  • .changeset/wise-knives-glow.md
    • Added a changeset file for @exactly/server related to preventing array overlap errors when no hashes.
  • .do/app.yaml
    • Updated environment variables for Pax and Sardine API keys and URLs.
  • .eas/workflows/local.yaml
    • Added a new EAS workflow for local E2E testing.
  • .eas/workflows/production.yaml
    • Added a new EAS workflow for production E2E testing.
  • .maestro/flows/production.yaml
    • Added a new Maestro flow for production E2E testing.
  • .ncurc.json
    • Added expo-image to the ignored updates list.
  • Dockerfile
    • Updated the base Node.js image from 22.14.0-slim to 24.12.0-slim.
  • common/package.json
    • Updated the required Node.js version from >=22.14.0 to >=24.12.0.
  • common/wagmi.config.ts
    • Added baseSepolia.id to exaAccountFactory configuration.
  • cspell.json
    • Added 'ciphertext' and 'hmac' to the CSpell dictionary.
  • docs/astro.config.ts
    • Modified the sidebar configuration to include new documentation sections.
  • docs/src/content/docs/organization-authentication.md
    • Added new documentation for organization authentication and invite management.
  • docs/src/content/docs/resources.md
    • Added new documentation for key integration resources.
  • docs/src/content/docs/webhooks.md
    • Added new documentation detailing webhook setup, security, retry policy, flows, and event references.
  • eas.json
    • Updated Node.js version to 24.12.0, added E2E build profiles, and modified submit configurations.
  • package.json
    • Updated the required Node.js version to >=24.12.0 and added new mobile dependencies.
  • server/api/activity.ts
    • Modified the /activity endpoint to support PDF statement generation.
  • server/api/card.ts
    • Enhanced card API to include cardId in responses, added KYC approval check, integrated Sardine customer tracking, and improved weak PIN error handling.
  • server/api/index.ts
    • Integrated new /webhook and /pax API routes.
  • server/api/kyc.ts
    • Refactored KYC API to support new /application endpoints for submitting, updating, and getting status of KYC applications.
  • server/api/pax.ts
    • Added a new API endpoint /pax to retrieve associate data.
  • server/api/webhook.ts
    • Added a new API endpoint /webhook for managing webhooks.
  • server/database/index.ts
    • Integrated better-auth drizzle adapter and defined schema for authentication-related tables.
  • server/database/schema.ts
    • Extended the database schema to include source in credentials table, and added new tables for better-auth integration.
  • server/hooks/panda.ts
    • Modified Panda webhook handler to integrate Sardine for transaction risk assessment and feedback, and to publish webhooks to configured endpoints.
  • server/hooks/persona.ts
    • Enhanced Persona webhook handler to integrate Sardine customer risk assessment and Pax Assistance addCapita for new user onboarding.
  • server/index.ts
    • Integrated better-auth handler for /api/auth/* routes.
  • server/middleware/auth.ts
    • Modified authentication middleware to check better-auth session if credential_id cookie is missing.
  • server/package.json
    • Updated Node.js version to >=24.12.0 and added new server dependencies.
  • server/queues/alchemyQueue.ts
    • Added a new BullMQ queue (alchemyQueue) for managing Alchemy webhook subscriber updates asynchronously.
  • server/queues/constants.ts
    • Defined constants for queue names and Alchemy job types.
  • server/script/backfillPax.ts
    • Added a new script to backfill Pax Assistance data for existing users.
  • server/script/openapi.ts
    • Updated environment variables for Pax and Sardine, and added siweAuth security scheme.
  • server/test/api/card.test.ts
    • Updated card API tests to include KYC approval check, cardId in response, and weak PIN error handling.
  • server/test/api/kyc.test.ts
    • Added comprehensive tests for the new KYC API endpoints.
  • server/test/api/pax.test.ts
    • Added tests for the new Pax API endpoint to retrieve associate ID.
  • server/test/api/webhook.test.ts
    • Added tests for the new webhook API endpoints.
  • server/test/hooks/panda.test.ts
    • Updated Panda webhook tests to include Sardine risk assessment and new HTTP status codes for high-risk transactions/refunds.
  • server/test/hooks/persona.test.ts
    • Updated Persona webhook tests to include Sardine customer integration and Pax addCapita calls.
  • server/test/mocks/database.ts
    • Modified database mock to integrate better-auth drizzle adapter for testing.
  • server/test/mocks/sardine.ts
    • Added mocks for Sardine API calls.
  • server/test/queues/alchemyQueue.test.ts
    • Added tests for the new Alchemy queue processor.
  • server/test/script/backfillPax.test.ts
    • Added tests for the new Pax backfill script.
  • server/test/utils/createCredential.test.ts
    • Added tests to verify that createCredential enqueues an Alchemy job.
  • server/test/utils/deriveAssociateId.test.ts
    • Added tests for the new deriveAssociateId utility.
  • server/test/utils/pax.test.ts
    • Added tests for the new Pax API utility functions.
  • server/test/utils/persona.test.ts
    • Added tests for new Persona utility functions.
  • server/tsconfig.json
    • Added "jsx": "react" to compiler options.
  • server/utils/Statement.tsx
    • Added a new React component for generating PDF statements.
  • server/utils/auth.ts
    • Added a new better-auth configuration file.
  • server/utils/createCredential.ts
    • Modified createCredential to enqueue an Alchemy job for webhook subscriber updates.
  • server/utils/deriveAssociateId.ts
    • Added a new utility function to deterministically derive a 7-character associate ID.
  • server/utils/keeper.ts
    • Extended keeper.exaSend to include an onReceipt callback for post-transaction processing.
  • server/utils/kyc.ts
    • Added new utility functions for interacting with Panda's KYC application API.
  • server/utils/panda.ts
    • Updated createCard logic to use a different virtualCardArt based on baseURL.
  • server/utils/pax.ts
    • Added new utility functions for interacting with Pax Assistance API.
  • server/utils/paxAssociateIdSecret.ts
    • Added a new utility to load Pax associate ID secret from environment variables.
  • server/utils/persona.ts
    • Refactored Persona utility functions, including new getAccounts and getPendingInquiryTemplate for different account scopes.
  • server/utils/ramps/bridge.ts
    • Removed Persona-related logic from getProvider and onboarding functions, effectively disabling Bridge ramp functionality.
  • server/utils/ramps/manteca.ts
    • Removed Persona-related logic from getProvider and mantecaOnboarding functions, effectively disabling Manteca ramp functionality.
  • server/utils/ramps/shared.ts
    • Added DevelopmentChainId constant.
  • server/utils/sardine.ts
    • Added new utility functions for integrating with Sardine API.
  • server/vitest.config.mts
    • Updated AUTH_SECRET and added new environment variables for Pax and Sardine.
  • src/assets/images/airalo.svg
    • Added new SVG asset for Airalo logo.
  • src/assets/images/pax.svg
    • Added new SVG asset for Pax logo.
  • src/assets/images/visa.svg
    • Added new SVG asset for Visa logo.
  • src/components/activity/details/ReceivedActivity.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/activity/details/RepayActivity.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/activity/details/SentActivity.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/add-funds/AddCrypto.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/add-funds/Bridge.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/add-funds/SupportedAssetsSheet.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/benefits/BenefitCard.tsx
    • Added new React component for displaying a single benefit card.
  • src/components/benefits/BenefitSheet.tsx
    • Added new React component for displaying benefit details in a modal sheet.
  • src/components/benefits/BenefitsSection.tsx
    • Added new React component for displaying a carousel of benefits.
  • src/components/home/AssetList.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/home/CardLimits.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/home/Home.tsx
    • Integrated BenefitsSection into the Home screen.
  • src/components/loans/AmountSelector.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/loans/Asset.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/loans/CreditLine.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/loans/LoanSummary.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/loans/Review.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/pay-mode/OverduePayments.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/pay-mode/Pay.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/pay-mode/PaySelector.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/pay-mode/RepayAmountSelector.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/pay-mode/UpcomingPayments.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/send-funds/Amount.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/send-funds/ReviewSheet.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/shared/AssetLogo.tsx
    • Refactored AssetLogo component to use expo-image for improved caching and performance.
  • src/components/shared/AssetSelector.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/shared/CopyAddressSheet.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/shared/Failure.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/shared/InstallmentSelector.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/shared/PaymentScheduleSheet.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/shared/Pending.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/shared/Success.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/shared/WeightedRate.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/components/swaps/TokenInput.tsx
    • Updated AssetLogo component usage to pass source prop.
  • src/utils/server.ts
    • Modified getActivity to correctly parse array responses and added getPaxId function for fetching Pax associate ID.
Ignored Files
  • Ignored by pattern: .github/workflows/** (5)
    • .github/workflows/docs.yaml
    • .github/workflows/mobile-beta.yaml
    • .github/workflows/server-deploy.yaml
    • .github/workflows/test.yaml
    • .github/workflows/version.yaml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a very large number of changes that go far beyond the scope implied by its title, "🥅 server: skip retries for replay reverts". While it includes a fix for webhook retries, it also brings in major new features like Pax and Sardine integrations, a new "Benefits" section in the mobile app, PDF statement generation, and a full Webhook management API. Additionally, it contains significant architectural changes, such as a complete refactoring of the KYC flow and the introduction of better-auth for authentication and organization management.

Such a large and diverse set of changes in a single PR makes it extremely difficult to review thoroughly and significantly increases the risk of introducing unintended bugs. In the future, please break down large features and refactors into smaller, more focused pull requests.

Despite the size, I've reviewed the changes and have a few points of feedback. The most notable is a duplication of environment variables in the deployment configuration, and there's also deprecated logic that could be removed.

I am having trouble creating individual review comments. Click here to see my feedback.

.do/app.yaml (162-168)

medium

These environment variables for Pax (PAX_API_KEY and PAX_API_URL) are already defined on lines 118-124. This duplication should be removed to avoid confusion and potential configuration issues.

server/api/kyc.ts (89-112)

medium

This block of code handles a deprecated templateId parameter and is marked for future deletion. Leaving deprecated logic in the codebase increases complexity and can lead to confusion. It would be cleaner to remove this in a separate, dedicated pull request to manage technical debt, rather than keeping it in the main branch.

@sentry
Copy link
Copy Markdown

sentry bot commented Feb 11, 2026

Codecov Report

❌ Patch coverage is 87.50000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 67.10%. Comparing base (a27029d) to head (c9d1d65).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
server/hooks/panda.ts 87.50% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #757      +/-   ##
==========================================
- Coverage   67.67%   67.10%   -0.57%     
==========================================
  Files         206      206              
  Lines        6932     6940       +8     
  Branches     2171     2175       +4     
==========================================
- Hits         4691     4657      -34     
- Misses       2052     2093      +41     
- Partials      189      190       +1     
Flag Coverage Δ
e2e 51.11% <0.00%> (-0.73%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cruzdanilo cruzdanilo closed this Feb 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants