Skip to content

[RELEASE] fix batched USDC transactions - #623

Merged
rsproule merged 51 commits into
productionfrom
master
Oct 28, 2025
Merged

[RELEASE] fix batched USDC transactions #623
rsproule merged 51 commits into
productionfrom
master

Conversation

@zdql

@zdql zdql commented Oct 27, 2025

Copy link
Copy Markdown
Contributor

ETH_ADDRESS
ETH_WARNING_THRESHOLD
BASE_USDC_TRANSFER_THRESHOLD
MAX_COST_MARKUP

Should be added to the env var

@railway-app

railway-app Bot commented Oct 27, 2025

Copy link
Copy Markdown

🚅 Deployed to the echo-pr-623 environment in echo

Service Status Web Updated (UTC)
echo ◻️ Removed (View Logs) Web Oct 28, 2025 at 1:18 am

@vercel

vercel Bot commented Oct 27, 2025

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
assistant-ui-template Ready Ready Preview Comment Oct 28, 2025 1:15am
component-registry Ready Ready Preview Comment Oct 28, 2025 1:15am
echo-control (staging) Ready Ready Preview Comment Oct 28, 2025 1:15am
echo-next-boilerplate Ready Ready Preview Comment Oct 28, 2025 1:15am
echo-next-image Ready Ready Preview Comment Oct 28, 2025 1:15am
echo-next-sdk-example Ready Ready Preview Comment Oct 28, 2025 1:15am
echo-video-template Ready Ready Preview Comment Oct 28, 2025 1:15am
echo-vite-sdk-example Ready Ready Preview Comment Oct 28, 2025 1:15am
next-chat-template Ready Ready Preview Comment Oct 28, 2025 1:15am
react-boilerplate Ready Ready Preview Comment Oct 28, 2025 1:15am
react-chat Ready Ready Preview Comment Oct 28, 2025 1:15am
react-image Ready Ready Preview Comment Oct 28, 2025 1:15am

Comment thread packages/app/server/src/handlers.ts Outdated
fmhall and others added 5 commits October 27, 2025 17:57
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
@railway-app
railway-app Bot temporarily deployed to echo (echo / staging) October 27, 2025 22:55 Inactive
Comment thread packages/app/server/src/handlers.ts Outdated
Comment on lines 121 to 133
const transactionCostWithMarkup = applyMaxCostMarkup(transaction.rawTransactionCost);

// rawTransactionCost is what we pay to OpenAI
// transactionCostWithMarkup is what we charge the user
// markup is the difference between the two, and is sent with fundRepo (not every time, just when it is worthwhile to send a payment)

// The user should be refunded paymentAmountDecimal - transactionCostWithMarkup\


const refundAmount = calculateRefundAmount(
paymentAmountDecimal,
transaction.rawTransactionCost
transactionCostWithMarkup
);

@vercel vercel Bot Oct 27, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
const transactionCostWithMarkup = applyMaxCostMarkup(transaction.rawTransactionCost);
// rawTransactionCost is what we pay to OpenAI
// transactionCostWithMarkup is what we charge the user
// markup is the difference between the two, and is sent with fundRepo (not every time, just when it is worthwhile to send a payment)
// The user should be refunded paymentAmountDecimal - transactionCostWithMarkup\
const refundAmount = calculateRefundAmount(
paymentAmountDecimal,
transaction.rawTransactionCost
transactionCostWithMarkup
);
// The user was charged maxCostWithMarkup (applied in server.ts)
// They should only pay the actual transaction cost (rawTransactionCost)
// So refund = paymentAmount - actualCost (no additional markup needed)
const refundAmount = calculateRefundAmount(
paymentAmountDecimal,
transaction.rawTransactionCost
);
// Calculate markup for profit tracking (but don't apply it to refund calculation)
const transactionCostWithMarkup = applyMaxCostMarkup(transaction.rawTransactionCost);

The refund calculation incorrectly applies markup to the actual transaction cost, causing users to be overcharged when the actual cost is lower than the estimated maximum cost.

View Details

Analysis

Double markup application in finalize() causes user overcharges

What fails: finalize() function in /packages/app/server/src/handlers.ts applies markup twice - once to estimate (server.ts:111) then again to actual cost (handlers.ts:121), causing users to pay more than actual transaction cost + intended markup

How to reproduce:

// Scenario: Estimated cost 100 USD, actual cost 50 USD, markup 1.25x
// User charged: 125 USD (100 * 1.25)
// Buggy refund: 125 - (50 * 1.25) = 62.5 USD  
// User pays: 62.5 USD instead of 50 USD (12.5 USD overcharge)

Result: Users systematically overcharged when actual costs are below estimates. In test case: 12.5 USD overcharge (25% of actual cost).

Expected: Refund should be paymentAmount - rawTransactionCost so users pay exactly the actual cost, with markup profit tracked separately for fundRepo operations.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this is actually correct. The user should be refunded paymentAmountDecimal - transactionCostWithMarkup.
The final cost to the user should be raw tx cost + markup amount.

 Add xAI Grok model support
Add Documentation for Echo Shadcn Components Registry

export function applyMaxCostMarkup(maxCost: Decimal): Decimal {
const markup = process.env.MAX_COST_MARKUP || '1.25';
return maxCost.mul(new Decimal(markup));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
return maxCost.mul(new Decimal(markup));
try {
const markupDecimal = new Decimal(markup);
if (!markupDecimal.isFinite() || markupDecimal.isNaN()) {
throw new Error('Invalid markup value - not a finite number');
}
return maxCost.mul(markupDecimal);
} catch (error) {
// Log the error and fall back to default markup
console.error(`Invalid MAX_COST_MARKUP value "${markup}": ${error instanceof Error ? error.message : 'Unknown error'}. Using default markup 1.25.`);
return maxCost.mul(new Decimal('1.25'));
}

The applyMaxCostMarkup function passes the MAX_COST_MARKUP environment variable directly to the Decimal constructor without validating it's a valid number. If an invalid value is set, the application will crash when processing requests.

View Details

Analysis

Invalid MAX_COST_MARKUP environment variable crashes server

What fails: applyMaxCostMarkup() in packages/app/server/src/services/PricingService.ts passes process.env.MAX_COST_MARKUP directly to new Decimal() without validation, causing application crashes when the environment variable contains invalid values

How to reproduce:

# Set invalid environment variable and make a request:
MAX_COST_MARKUP="invalid" node -e "
const { applyMaxCostMarkup } = require('./dist/server.js');
const { Decimal } = require('@prisma/client/runtime/library');
applyMaxCostMarkup(new Decimal('100'));
"

Result: [DecimalError] Invalid argument: invalid exception crashes the server. Function is called in critical request paths in server.ts:111 and handlers.ts:121 without error handling.

Expected: Application should handle invalid environment variables gracefully and continue serving requests with fallback values.

Fix: Added try-catch validation in applyMaxCostMarkup() that validates the Decimal construction and falls back to default markup (1.25) when invalid values are encountered, with error logging for visibility.

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.

4 participants