What you will build.
A fictional player purchases item DEMO-ITEM-01. The payment is confirmed but the game inventory grant may be missing or already applied. Trace payment, asset ownership and game inventory as related but independent records.
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.
{
"paymentConfirmed": true,
"inventoryGranted": false,
"ownershipDisputed": false
}Save it as web3-gaming-economy.mjs. Open a terminal in that folder and run:
node --version
node --test web3-gaming-economy.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: web3-gaming-economy
// 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 web3-gaming-economy.mjs
import test from 'node:test';
import assert from 'node:assert/strict';
export function inspect(record) {
if (!record.paymentConfirmed) return 'WAIT_FOR_PAYMENT';
if (record.ownershipDisputed) return 'OWNERSHIP_REVIEW_REQUIRED';
if (record.inventoryGranted) return 'ALREADY_GRANTED';
return 'READY_FOR_INVENTORY_REVIEW';
}
const baseline = {
"paymentConfirmed": true,
"inventoryGranted": false,
"ownershipDisputed": false
};
const cases = [
{
"name": "paid order needs inventory review",
"patch": {},
"expected": "READY_FOR_INVENTORY_REVIEW"
},
{
"name": "payment unresolved",
"patch": {
"paymentConfirmed": false
},
"expected": "WAIT_FOR_PAYMENT"
},
{
"name": "duplicate delivery",
"patch": {
"inventoryGranted": true
},
"expected": "ALREADY_GRANTED"
},
{
"name": "ownership dispute",
"patch": {
"ownershipDisputed": true
},
"expected": "OWNERSHIP_REVIEW_REQUIRED"
}
];
for (const example of cases) {
test(example.name, () => {
assert.equal(inspect({...baseline, ...example.patch}), example.expected);
});
}
Know what the tests demonstrate
- paid order needs inventory review
READY_FOR_INVENTORY_REVIEW- payment unresolved
WAIT_FOR_PAYMENT- duplicate delivery
ALREADY_GRANTED- ownership dispute
OWNERSHIP_REVIEW_REQUIRED
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
Define the item and its utility
Do this
- Describe what DEMO-ITEM-01 does in this game and who can change that behavior.
- Record supply, transfer rules and inventory-delivery owner separately from the asset identifier.
- Avoid suggesting cross-game compatibility merely because ownership is represented digitally.
Expected resultThe entitlement has a clear game-specific meaning rather than an assumed universal utility.
If your result is different
If the game cannot resolve the item's definition, hold delivery for review instead of creating an arbitrary inventory entry.
- 02
Wait for authoritative payment
Do this
- Run the baseline with paymentConfirmed=true.
- Change it to false and expect WAIT_FOR_PAYMENT.
- Record the actual payment reference and keep browser return/notification receipt separate from its authoritative state.
Expected resultThe game does not grant a purchased item on an unverified checkout signal.
If your result is different
If the provider status is unavailable, keep the order unresolved; do not both refund and grant while guessing what happened.
- 03
Handle repeat delivery and disputed ownership
Do this
- Set inventoryGranted=true and expect ALREADY_GRANTED.
- Restore the baseline, set ownershipDisputed=true and expect OWNERSHIP_REVIEW_REQUIRED.
- Specify a durable order-to-grant key and a support view showing both asset and inventory references.
Expected resultRepeated messages and ownership disagreements have distinct explanations and responsible owners.
If your result is different
A local flag is not atomic inventory delivery. Test the real game service under concurrent retries.
- 04
Reconcile a paid-but-undelivered order
Do this
- Keep paymentConfirmed=true and inventoryGranted=false; the model returns READY_FOR_INVENTORY_REVIEW, not delivered.
- Assign the failed grant to the game operator and preserve the original payment reference.
- Add anti-cheat, player-safety and rollback requirements to the studio backlog rather than treating asset evidence as those controls.
Expected resultYou finish with a traceable support case and a narrow implementation plan for delivery and reconciliation.
If your result is different
Do not mint or charge again to hide an inventory mismatch. Reconcile the existing order first.
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.
The studio owns the game server, entitlement utility, player safety, fraud response, inventory synchronization, and any marketplace rules.
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.
Practice the checkout handoff