Hoscoo
Sandbox

Deterministic fixtures

Every magic value below always produces the same outcome. This table is rendered directly from lib/sandbox/fixtures.ts — the same source the simulation engine and tests read from, so this page can never drift from actual behavior.

Wallet to wallet

M-Pesa — success

Designated MSISDN for M-Pesa that always completes successfully.

+255700000200
COMPLETED

Mixx by Yas — success

Designated MSISDN for Mixx by Yas that always completes successfully.

+255700000201
COMPLETED

Airtel Money — success

Designated MSISDN for Airtel Money that always completes successfully.

+255700000202
COMPLETED

HaloPesa — success

Designated MSISDN for HaloPesa that always completes successfully.

+255700000203
COMPLETED

T-Pesa — success

Designated MSISDN for T-Pesa that always completes successfully.

+255700000204
COMPLETED

Selcom Pesa — success

Designated MSISDN for Selcom Pesa that always completes successfully.

+255700000205
COMPLETED

Insufficient funds

Source wallet balance is too low.

+255700000101
FAILED: INSUFFICIENT_FUNDS

Timeout

Destination provider never responds within the SLA window.

+255700000102
FAILED: TIMEOUT

Authorization expiry

Customer never completes authorization before the window closes.

+255700000103
EXPIRED

Alias unmapped

Destination identifier has no resolvable account.

+255700000104
FAILED: ALIAS_UNMAPPED

3-DS challenge

Forces a step-up authorization challenge (app-push/USSD PIN prompt).

+255700000105
CHALLENGE_ISSUED

3-DS challenge failure

Customer fails the step-up challenge.

+255700000106
FAILED: THREE_DS_CHALLENGE_FAILED

Rail unavailable

Simulates the MNO interconnect being down for this instruction.

+255700000107
FAILED: RAIL_UNAVAILABLE

Debit succeeded, credit failed

Source debit clears, destination credit fails — the exact case merchant reconciliation must catch.

+255700000108
FAILED: DEBIT_SUCCEEDED_CREDIT_FAILED

Same-provider transfer rejected

Two M-Pesa numbers on a MNO_TO_MNO instruction. This is an on-us book transfer, never a cross-network route — must be rejected with SAME_PROVIDER_ON_US before any routing decision.

+255740000001 -> +255740000002 (both MPESA_TZ)
REJECTED: SAME_PROVIDER_ON_US

Ported number: prefix disagrees with declared provider

MSISDN +255650009999 carries a TIGO_PESA prefix (65) but the request declares providerCode AIRTEL_MONEY (the number ported). detectMnoFromMsisdn returns TIGO_PESA; the instruction must still route on the declared AIRTEL_MONEY code, proving prefix is never used as a correctness control.

+255650009999 declared as AIRTEL_MONEY
COMPLETED (routed on declared provider, not detected prefix)

MSISDN resolves at two providers

MSISDN +255740005555 matches MPESA_TZ by prefix (74) and can also be legitimately declared as SELCOM_PESA (which owns no prefix range and therefore never conflicts by construction). Both requests are valid; the declared providerCode alone decides.

+255740005555 declared as MPESA_TZ or SELCOM_PESA
COMPLETED (either provider, per declared providerCode)

Unregistered destination

Destination MSISDN has no wallet account with the declared provider at all.

+255760009999
FAILED: ALIAS_UNMAPPED

Non-USSD authorization

Selcom Pesa cannot authorize via USSD — Test Bank must render its app-push/agent-assisted variant, never a generic PIN prompt.

+255700000300 declared as SELCOM_PESA
COMPLETED (via app-push authorization variant)

Bank to bank

TIPS alias resolves

Resolves via the CRDB Bank TIPS directory entry.

+255700000001
COMPLETED

TIPS alias unmapped

No TIPS directory entry for this alias.

+255700099999
FAILED: ALIAS_UNMAPPED

Card / gateway checkout

Visa success

Passes Luhn and authorizes cleanly.

4242424242424242
COMPLETED

3-DS challenge

Card requires step-up authentication.

4000000000003220
CHALLENGE_ISSUED

3-DS failure

Card fails step-up authentication.

4000000000003063
FAILED: THREE_DS_CHALLENGE_FAILED

Insufficient funds

Issuer declines for insufficient funds.

4000000000009995
FAILED: INSUFFICIENT_FUNDS

Cross-border corridors

TZ -> KE success

Standard corridor settlement, two-decimal currencies on both sides.

corridor=TZ-KE, quoteId=<normal>
COMPLETED

Originating market not LIVE

Instruction declares market=KE as the originating market. Only TZ is LIVE — rejected before any quote, alias lookup, or ledger posting.

market=KE
REJECTED: MARKET_NOT_LIVE

Zero-decimal destination (UGX)

Exercises CURRENCY_META.UGX exponent=0 — no fractional units, no naive /100.

corridor=TZ-UG, amountMinor=1250000
COMPLETED

Zero-decimal destination (RWF)

Exercises CURRENCY_META.RWF exponent=0.

corridor=TZ-RW, amountMinor=980000
COMPLETED

Quote expired mid-flight

Execution attempted after the quote's expiresAt.

quoteId=hsc_quote_expired
REJECTED: QUOTE_EXPIRED

Adverse rate movement

Rate moved against the customer between quote and execution — reversed rather than silently re-quoted.

quoteId=hsc_quote_adverse
REJECTED: RATE_MOVED

Corridor liquidity exhausted

Corridor's settlement-window liquidity cap has been used up.

quoteId=hsc_quote_illiquid
REJECTED: CORRIDOR_LIQUIDITY_EXHAUSTED

Outside cut-off

Request arrives after the corridor's daily cut-off hour.

quoteId=hsc_quote_after_cutoff
REJECTED: OUTSIDE_CUTOFF

Rounding-residual amount

amountMinor chosen so the raw rate multiplication does not divide evenly (e.g. 333333 minor units at a TZ-KE rate of 555/100000). quoteFx must round exactly once and leave no unexplained minor unit — see the money property tests.

corridor=TZ-KE, amountMinor=333333
COMPLETED (creditedMinor rounds once, no residual)