Skip to content

fix(frontend): Soroban invocation encoding, contract targets, bounded tx timeout, create_market args - #1496

Merged
Ehonrie merged 5 commits into
Netwalls:mainfrom
liamscroxx-svg:fix/frontend-soroban-invocations-1419-1422
Oct 21, 2026
Merged

Ehonrie merged 5 commits into
Netwalls:mainfrom
liamscroxx-svg:fix/frontend-soroban-invocations-1419-1422

Conversation

@liamscroxx-svg

Copy link
Copy Markdown
Contributor

Fixes the frontend Soroban transaction path: invocations are now encoded correctly, target the right contract, expire after a bounded window, and create markets with the arguments the factory contract declares. Each issue is its own commit.

Commits

Behaviour changes

  • buildSorobanInvocation uses new Contract(contractId).call(method, ...args) and validates contractId is a C... address before touching the network.
  • Arguments that are already ScVals pass through unchanged; toU64ScVal encodes u64 timestamps.
  • The build used Timeout.INFINITE from an export the SDK does not have, so every build threw a TypeError. It now uses a 120 s window (TX_TIMEOUT_SECONDS).
  • The all-zero placeholder signature was rejected by the SDK as invalid. It is removed; the wallet signs the returned XDR.
  • A txTooLate rejection surfaces as TX_EXPIRED_MESSAGE ("please try again").
  • usePlaceBet takes the market's contractAddress as a second argument. useClaimWinnings, useClaimRefund and DisputeModal use market.contractAddress.
  • useCreateMarket reads NEXT_PUBLIC_MARKET_FACTORY_CONTRACT_ID from validated config and sends (caller, fighter_a, fighter_b, oracle, lock_time, end_time). Fighter metadata goes to POST /api/markets with the tx hash after confirmation.
  • zod is declared in frontend/package.json; lib/config.ts already imported it.

Testing

  • New: __tests__/lib/stellar.invocation.test.ts decodes the built XDR and asserts the contract id, function name, argument types, maxTime, and the expiry mapping.
  • New: __tests__/useClaimRefund.test.ts.
  • Updated: usePlaceBet, useClaimWinnings, useCreateMarket, DisputeModal tests assert the target contract and encoded arguments. Hook tests mock useWallet with a factory, because hooks/useWallet.ts contains JSX under a .ts extension and cannot be automocked.
  • npx jest: 5 suites that were failing on main now pass (useCreateMarket, usePlaceBet, useClaimWinnings, useClaimRefund, stellar.invocation). No suite that passed on main fails.

Not done here

Closes #1419
Closes #1420
Closes #1421
Closes #1422

liamscroxx-svg and others added 5 commits October 19, 2026 05:32
…iven contract

buildSorobanInvocation passed a plain object as the host function and
ignored params.contractId. It now builds the operation with
new Contract(contractId).call(method, ...args), and arguments that are
already ScVals pass through unchanged.

Also replaces the nonexistent Timeout.INFINITE with TimeoutInfinite and
drops the all-zero placeholder signature, which the SDK rejects as an
invalid signature. The wallet signs the returned XDR.
… txs

Built transactions used Timeout.INFINITE, so a signed XDR stayed valid
indefinitely. They now use TX_TIMEOUT_SECONDS (120). A txTooLate
rejection from submission is reported as TX_EXPIRED_MESSAGE, asking the
user to try again.
…laim calls

usePlaceBet, useClaimWinnings, useClaimRefund and DisputeModal passed the
market id (a 32-byte hash) as the invocation contract. They now use the
market's contractAddress; usePlaceBet takes it as a second argument.

buildSorobanInvocation rejects a contractId that is not a C-strkey before
building anything. Tests assert the target contract of each invocation.
… typed args

useCreateMarket sent a placeholder contract id and 11 arguments, while
create_market takes (caller, fighter_a, fighter_b, oracle, lock_time,
end_time). It now reads the factory id from the validated config
(NEXT_PUBLIC_MARKET_FACTORY_CONTRACT_ID), passes the connected address as
caller, and encodes both timestamps as u64 via toU64ScVal.

Fighter metadata the contract does not store (records, nationality, weight
class) is sent to the backend with the tx hash once the transaction is
confirmed. A failure there is logged and does not fail the creation, since
the market already exists on-chain.

zod is declared as a frontend dependency; lib/config.ts imports it but it
was only present through the backend.
Keep both config additions (factory id + site url), main's import and the
PR's Contract.call encoding with the secure RPC options helper, and the PR's
create_market args. Drop test files removed on main; keep the PR's
DisputeModal tests in a separate file.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@Ehonrie
Ehonrie merged commit 1fc8c3e into Netwalls:main Oct 21, 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

2 participants