Skip to content

fix(quotes): harden quote -> rank -> pay pipeline across all providers#37

Merged
Shreyassp002 merged 34 commits into
HoomanBuilds:mainfrom
Shreyassp002:main
May 31, 2026
Merged

fix(quotes): harden quote -> rank -> pay pipeline across all providers#37
Shreyassp002 merged 34 commits into
HoomanBuilds:mainfrom
Shreyassp002:main

Conversation

@Shreyassp002

Copy link
Copy Markdown
Contributor

This audits and fixes the quote -> rank -> pay pipeline across all six providers (LiFi, Rango, Rubic, Symbiosis, NEAR, CCTP). Each provider fix was verified against the live provider APIs, not just by reading code, and everything is unit-tested. Gates on the final commit: tsc 0 errors, vitest 185 passing, build compiles.

What this changes

  • Ranking now compares the real net output (amount normalized by the token's actual decimals, minus on-top fees) instead of raw integers, and it trusts the authoritative destination decimals from the request — so a provider that mislabels decimals can no longer win the ranking.
  • The NEAR deposit memo is now carried through the entire flow (deposit submit + status polling), and non-EVM/Solana/Bitcoin deposit sources are blocked with a clear error instead of being misrouted to the EVM signer.
  • Added a real Solana execution path for non-NEAR providers, and quotes that come back with no executable transaction data are dropped instead of winning the ranking and then failing at pay time.
  • Requests are now validated before fan-out: source/destination addresses are checked against the chain's address space, and unsupported chains return an explicit "not supported yet" reason (shown in the UI) instead of a silent empty result. Missing source-token decimals are resolved up front so amounts aren't mis-scaled.
  • Symbiosis now uses the real fee and destination decimals from its response; CCTP fails closed when the fee can't be fetched, uses the correct fee label, and reports a realistic settlement time.
  • Fixed Rubic deposit trades end to end: parse the deposit route shape, send the required refundAddress, and store the deposit amount in raw base units (it was being sent in human units, which would have caused a massive underpayment).
  • Removed dead code: the browser supabase client, the wallet store, the Dither component, and the UpdatePaymentLinkInput type. Also de-duplicated same-symbol tokens so the payment selector shows one row per token.

@vercel

vercel Bot commented May 31, 2026

Copy link
Copy Markdown

@Shreyassp002 is attempting to deploy a commit to the Shreyas' projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

Copy link
Copy Markdown

⚡ Flash Review

Metric Value
Files Reviewed 6
Risk Level 🔴 High
Issues Found 🚨 2 Critical · ⚠️ 3 Warnings · 💡 2 Suggestions

See inline comments for details.


⚡ Powered by Flash Review

⚠️ Note: 9 file(s) could not be reviewed due to API errors.

{ event: 'transaction/poll' },
async ({ event, step }) => {
const { transactionId, txHash, fromChainId, toChainId, bridge, provider: providerName, requestId, depositAddress, attempt = 1 } = event.data
const { transactionId, txHash, fromChainId, toChainId, bridge, provider: providerName, requestId, depositAddress, depositMemo, attempt = 1 } = event.data

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Flash Review

🚨 Security: The new depositMemo field is destructured from event.data and subsequently passed to a cross-chain provider. If this data originates from user input (e.g., during payment link creation or customer payment initiation), it must be thoroughly validated to prevent potential injection attacks or unexpected behavior when interacting with external provider APIs.

Fix: Ensure depositMemo is explicitly defined and validated within the Zod schema for the transaction/poll Inngest event. For instance, use z.string().max(256).optional() if it's an optional string memo, or z.string().min(1).max(256) if required.

import { PublicKey } from '@solana/web3.js'
import { resolveExecutionPath, isCrossChainSwap } from '@/lib/execution-path'
import { PublicKey, VersionedTransaction, Transaction } from '@solana/web3.js'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Flash Review

🚨 Security: Hardcoding a fallback API key directly in the client-side bundle is a severe security risk. This key can be easily extracted by anyone inspecting the client-side code, potentially leading to abuse of the Rango API or rate limit exhaustion.

Fix: Remove the hardcoded fallback. The NEXT_PUBLIC_RANGO_API_KEY should only be sourced from environment variables. If it's missing, the application should fail gracefully or prompt for configuration, not expose a default key.

} else {
// Fallback if SDK doesn't return explicit hash in expected place
setStatus('completed')
return '0x'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Flash Review

🐛 Bug: Adding memo to submitDepositTx is a critical improvement. For certain chains (e.g., Cosmos, XRP, Stellar), a deposit memo is essential for correctly attributing funds to the user's account. Without it, funds could be lost or significantly delayed.

Fix: This change is a fix. Ensure quote.metadata?.depositMemo is correctly populated by the quote aggregator when required.

// 1. Extract Deposit Address
const depositAddress =
quote.transactionRequest?.depositAddress || quote.metadata?.depositAddress
if (!depositAddress) throw new Error('Deposit address missing for Near Intents')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Flash Review

🧹 Code Quality: The 1.0 slippage value is a magic number. While it's a common default, it's better to define it as a named constant (e.g., DEFAULT_RANGO_SLIPPAGE_PERCENT) for clarity and easier modification.

Fix: Define const DEFAULT_RANGO_SLIPPAGE_PERCENT = 1.0 and use it here.

disableEstimate: false
}
// 2. Call Swap API (Step 1)
// We pass the full request to get the tx data

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Flash Review

🧹 Code Quality: The // @ts-ignore comment indicates a type safety issue. Relying on @ts-ignore can hide potential bugs and makes the code harder to maintain. The statusRes object should have a properly defined type that accurately reflects its structure, including the status property.

Fix: Define a proper TypeScript interface or type for statusRes that accurately reflects its structure, including the status property, and remove the @ts-ignore.

@Shreyassp002 Shreyassp002 merged commit 2bdc411 into HoomanBuilds:main May 31, 2026
2 of 3 checks passed
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.

1 participant