What you will build.
Track DEMO-REMIT-01 from sender instructions to a fictional recipient payout. Funding has been observed, but the payout provider is still pending. Build a status view that tells support where the transfer is waiting instead of showing the recipient as paid.
Your working record
Create a private worksheet with columns for the source reference, observed state, responsible system, observation time, expected result and unresolved issue. Use the same fictional case throughout the steps; do not paste live personal or financial records into this exercise.
Run the example before changing it.
Inspect the baseline record below. Download and read the complete JavaScript file before running it. It uses only Node’s built-in test and assertion modules; there is no package installation, account connection or secret to configure.
{
"recipientAccepted": true,
"quoteValid": true,
"payoutState": "confirmed"
}Save it as global-remittance-platforms.mjs. Open a terminal in that folder and run:
node --version
node --test global-remittance-platforms.mjsExpected result: four passing tests and zero failures. These tests verify the teaching classifier only. They do not verify a production integration, security boundary or financial outcome.
File or test runner will not start?
Check that Node.js 22 or later is installed, the filename ends in .mjs rather than .mjs.txt, and your terminal is in the download folder. If a managed browser blocks scripts, open “Read the full exercise” and save that text locally under the same filename. Do not disable organizational security controls.
Read the full exercise
// Hybrid-Chain offline teaching model: global-remittance-platforms
// Fictional fields/states; NOT an API client, authorization system or production implementation.
// No network calls, credentials, payments or file writes. Review before running.
// Requires Node.js 22+. Run: node --test global-remittance-platforms.mjs
import test from 'node:test';
import assert from 'node:assert/strict';
export function inspect(record) {
if (!record.recipientAccepted) return 'RECIPIENT_REVIEW_REQUIRED';
if (!record.quoteValid) return 'REQUOTE_REQUIRED';
if (record.payoutState !== 'confirmed') return 'PAYOUT_UNRESOLVED';
return 'PAYOUT_RECORDED_FOR_REVIEW';
}
const baseline = {
"recipientAccepted": true,
"quoteValid": true,
"payoutState": "confirmed"
};
const cases = [
{
"name": "payout recorded",
"patch": {},
"expected": "PAYOUT_RECORDED_FOR_REVIEW"
},
{
"name": "recipient unresolved",
"patch": {
"recipientAccepted": false
},
"expected": "RECIPIENT_REVIEW_REQUIRED"
},
{
"name": "quote expired",
"patch": {
"quoteValid": false
},
"expected": "REQUOTE_REQUIRED"
},
{
"name": "payout pending",
"patch": {
"payoutState": "pending"
},
"expected": "PAYOUT_UNRESOLVED"
}
];
for (const example of cases) {
test(example.name, () => {
assert.equal(inspect({...baseline, ...example.patch}), example.expected);
});
}
Know what the tests demonstrate
- payout recorded
PAYOUT_RECORDED_FOR_REVIEW- recipient unresolved
RECIPIENT_REVIEW_REQUIRED- quote expired
REQUOTE_REQUIRED- payout pending
PAYOUT_UNRESOLVED
Now change one fixture at a time. If you change a case’s input without changing its expected result, the test should fail. Read the actual-versus-expected difference and use the walkthrough to decide whether your rule or your expectation needs correcting. Keep an unchanged copy for comparison.
Work through the case, step by step.
- 01
Describe one corridor precisely
Do this
- Write the source currency, destination currency, fee presentation, quote expiry and intended payout method.
- Name the funding, conversion and payout providers separately.
- Mark which system determines the delivered amount and final recipient status.
Expected resultThe worksheet describes one specific service arrangement rather than implying global coverage from a single API.
If your result is different
If payout availability or currency conversion is unconfirmed, keep it as an integration dependency.
- 02
Check recipient and quote conditions
Do this
- Run the baseline, then set recipientAccepted=false and expect RECIPIENT_REVIEW_REQUIRED.
- Restore the baseline and set quoteValid=false; expect REQUOTE_REQUIRED.
- Keep the recipient decision and quote status separate from the fact that funds may already have been observed.
Expected resultYour UI can explain a rejected recipient or expired quote without hiding the status of held or received funds.
If your result is different
Do not start a second funding request to solve a payout or recipient problem. Assign an owner to the existing funds.
- 03
Follow the payout reference
Do this
- Set payoutState=pending and confirm PAYOUT_UNRESOLVED.
- In the worksheet record the provider reference, observation time and escalation owner.
- Draft a customer message saying payout is pending; do not promise delivery based on an upstream funding event.
Expected resultSupport can locate the unresolved provider stage and avoid confusing funding confirmation with recipient receipt.
If your result is different
A callback timeout does not prove payout failure. Reconcile through the provider's actual status route before retrying.
- 04
Complete the reconciliation packet
Do this
- Restore payoutState=confirmed and record PAYOUT_RECORDED_FOR_REVIEW.
- List the actual evidence required to show delivered value, fees and any correction or refund.
- Use the funding walkthrough to map owner-scoped records while documenting the separate partner payout integration.
Expected resultYou have a bounded corridor design and tested incomplete states, not an implied payout network or banking permission.
If your result is different
If the providers disagree, leave the transfer under reconciliation and preserve the contradictory observations.
Review what you produced.
Save the worksheet, unmodified test output, one deliberately failing case and the explanation of its fix. A useful result includes an unresolved item with an owner; it is not just a screenshot of four green tests.
Map the model to actual systems.
Your business and approved partners own the corridor, liquidity, FX quote, local payout, licensing, fees, customer disclosures, and failed-payment handling.
For each worksheet field, name the owning system, exact current operation, permission and error behavior. Put “not available” next to any missing operation and assign a dependency owner. Do not substitute the teaching classifier for that missing integration.
Open the current API reference and inspect each operation’s request, response, scope and implementation status. Code examples on this page are local models only; they do not call those operations.
Take the next technical step.
Use your worksheet and failing-case notes in the next walkthrough. Keep the same reference trail so you can see which assumptions become actual observations—and which remain dependencies.
Trace the funding lifecycle