Skip to content

fix(checkout): submit real batch purchase transaction - #972

Merged
nanaf6203-bit merged 1 commit into
MettaChain:mainfrom
nasalehj:fix/issue-813-submit-real-batch-purchase
Aug 29, 2026
Merged

fix(checkout): submit real batch purchase transaction#972
nanaf6203-bit merged 1 commit into
MettaChain:mainfrom
nasalehj:fix/issue-813-submit-real-batch-purchase

Conversation

@nasalehj

Copy link
Copy Markdown
Contributor

Summary

Closes #813

The cart checkout path now submits a real batch purchase transaction instead of fabricating a result. BatchTransactionService.executeBatchPurchase resolves a wagmi/viem executor backed by the connected wallet: it validates the cart and wallet first, submits the batchPurchase contract call with the per-item slippage-protected minimum amounts, and only reports success: true after the transaction receipt is observed on chain.

Why

Previously (before #960) checkout waited on a timer, rolled Math.random() to pick success/failure, and returned a generated 0x... hash without touching a wallet or chain — users saw a "confirmed" purchase that never happened. #960 removed the simulation and added an executor seam, but deferred the actual submission. This PR completes the seam: when a deployed batch-purchase contract address is configured (NEXT_PUBLIC_BATCH_PURCHASE_ADDRESS), checkout really submits; when it is not configured, checkout fails closed with an explicit configuration error. There is no code path that returns a fabricated hash.

What was built

File What it contains
src/lib/batchTransaction.ts executeBatchPurchase now defaults to the configured real executor (injected executor still supported for tests), includes the property token address in the request, and keeps receipt-gated success, decoded revert/user-rejection handling, and fail-closed behavior.
src/lib/batchPurchaseExecutor.ts Real executor: resolves the wallet client for the connected account (throws before submission if not connected), calls writeContract with batchPurchase(propertyTokens[], quantities[], minAmounts[], deadline) and the quoted total as value, then waitForTransactionReceipt — success is only reported after the receipt.
src/config/batchPurchase.ts BATCH_PURCHASE_ABI and getBatchPurchaseContractAddress(), which reads NEXT_PUBLIC_BATCH_PURCHASE_ADDRESS and returns null when unset/malformed so checkout fails closed.
src/lib/__tests__/batchTransaction.test.ts Existing suite retained; new suite mocks @wagmi/core/actions (wagmi/viem) and asserts: the real hash is returned only after a successful receipt; a reverted receipt is not reported as success; a disconnected wallet is rejected before any submission; a user rejection (4001) returns success: false with the decoded reason.
.env.example, docs/smart-contract-integration.md Documents NEXT_PUBLIC_BATCH_PURCHASE_ADDRESS.

Integration changes outside src/lib/

  • .env.example — documents the new optional NEXT_PUBLIC_BATCH_PURCHASE_ADDRESS.
  • docs/smart-contract-integration.md — documents the batch purchase contract address and checkout flow.

Acceptance criteria coverage

  • executeBatchPurchase submits a real transaction for the connected account and resolves success: true only after on-chain confirmation (receipt observed); no code path returns a fabricated hash. (batchPurchaseExecutor.tswriteContract + waitForTransactionReceipt; success gated on receipt status === "success")
  • The 20% Math.random() failure branch and the setTimeout simulation are gone. (removed in fix(checkout): remove fabricated batch transaction results #960; no timer/random path exists in the current code)
  • The per-item slippage math is documented as an estimate with real values computed from the quote: calculateMinimumAmount feeds minAmounts (in wei) into the batchPurchase call; the contract is documented to reject purchases below those minimums. (batchTransaction.ts, batchPurchaseExecutor.ts, src/config/batchPurchase.ts)
  • src/lib/__tests__/batchTransaction.test.ts rewritten to mock wagmi/viem and assert: success returns the real hash; user rejection returns success: false with a decoded reason; disconnected wallet is rejected before any submission. (13/13 tests pass)
  • npm run typecheck, npm test, and npm run lint pass. — Repository-wide gates remain blocked by pre-existing issues unrelated to this change (syntax errors in src/app/compare/page.tsx, src/components/PropertyCard.tsx, src/components/TransactionConfirmation.tsx, src/lib/toast.ts, src/stories/ResponsiveContainerExample.stories.ts, src/components/CartSidebar.tsx, plus the missing eslint-plugin-jsdoc dependency). The issue-specific suite passes and the changed files are clean of type errors.

Deliberately deferred

  • Dynamic volatility-based slippage and EIP-712 typed-data slippage intent — explicitly out of scope in the issue.
  • Per-chain contract address maps — a single network-agnostic env var is used for now; src/config/batchPurchase.ts notes where a per-chain map belongs once deployments exist.

Test plan

  • npx jest src/lib/__tests__/batchTransaction.test.ts — 13/13 passing.
  • npx prettier --check src/lib/batchTransaction.ts src/lib/batchPurchaseExecutor.ts src/config/batchPurchase.ts src/lib/__tests__/batchTransaction.test.ts — all matched files pass.
  • npm run typecheck — blocked by the pre-existing unrelated syntax errors listed above; none of the errors are in the changed files.
  • npm run lint — blocked because the checked-out dependencies do not include eslint-plugin-jsdoc (pre-existing tooling gap, same as fix(checkout): remove fabricated batch transaction results #960-fix(security): remove orphaned pages router file #963).
  • npm test -- --runInBand — repository-wide run is blocked by pre-existing failures; the batchTransaction suite passes.

Env vars / Notes

New optional variable: NEXT_PUBLIC_BATCH_PURCHASE_ADDRESS. No other env vars, migrations, or API changes.

Completes the batch checkout integration started in MettaChain#960 by wiring a real
wagmi/viem executor. When a batch-purchase contract address is configured,
executeBatchPurchase now resolves the connected wallet client, submits the
batchPurchase call with per-item slippage-protected minimum amounts, and
only reports success after the transaction receipt is observed on chain.

The default path fails closed with a configuration error when no contract
address is set, and disconnected wallets are rejected before any submission.
The timeout/Math.random simulation is not reintroduced anywhere.

Closes MettaChain#813
@nanaf6203-bit
nanaf6203-bit merged commit 9d37fc8 into MettaChain:main Aug 29, 2026
2 of 5 checks passed
@github-actions

Copy link
Copy Markdown

🔒 Preview Environment Destroyed

The preview environment for this PR has been torn down.

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.

Cart checkout fabricates transaction results: executeBatchPurchase never submits to the chain

2 participants