Designing a Non-Custodial Multichain Wallet Hub for a Web3 Marketplace
Building a marketplace that supports cryptocurrency payments creates an architectural decision very early:
Who controls the keys?
While developing the open-source MyZubster ecosystem, I decided that the Marketplace and virtual world should be able to interact with multiple blockchain networks without turning the platform into a custodian.
The result is an experimental multichain Wallet Hub designed around four external settlement rails:
- Ethereum (ETH)
- Bitcoin (BTC)
- Monero (XMR)
- Tari
alongside MYZ, which remains a separate internal ecosystem accounting/reward layer.
The core rule: never put private keys in the application
A web application does not need a user's seed phrase to display a receiving address.
It does not need private keys to create marketplace settlement intent.
And it should not automatically gain authority over someone's cryptocurrency simply because they use the Marketplace.
The architecture therefore follows a simple boundary:
Marketplace → Settlement Intent → Public Address → User Wallet → Blockchain
The wallet owner remains responsible for signing the transaction.
The blockchain remains responsible for settlement.
The Marketplace coordinates the interaction.
Public configuration, private authorization
The frontend can receive public wallet configuration through environment variables:
REACT_APP_WALLET_ETH=
REACT_APP_WALLET_BTC=
REACT_APP_WALLET_XMR=
REACT_APP_WALLET_TARI=
These variables are intended for public receiving addresses only.
They must never contain:
seed phrases
private keys
extended private keys
wallet passwords
signing secrets
This distinction sounds obvious, but it becomes extremely important once a project starts supporting several blockchain networks.
Extending the Marketplace
The MyZubster Marketplace already supported multiple exchange modes and currencies.
The current work extends the settlement model with Bitcoin and Ethereum so listings can identify their intended rail.
Conceptually, a listing can look like this:
{
"title": "Community gardening service",
"price": 0.0001,
"currency": "BTC",
"exchangeMode": "payment"
}
But this object represents commercial intent, not proof of payment.
Creating the listing does not move Bitcoin.
Creating an order should not automatically move Bitcoin either.
Actual settlement happens independently.
Settlement is a state machine
One of the useful lessons from building this architecture is that application state and blockchain state should not be confused.
A transaction flow can be modeled as:
ORDER CREATED
↓
SETTLEMENT REQUESTED
↓
TRANSACTION AUTHORIZED
↓
TRANSACTION BROADCAST
↓
SEEN BY NETWORK
↓
CONFIRMED
↓
SETTLED
The Marketplace should only mark an external cryptocurrency payment as settled after obtaining appropriate evidence from the corresponding network.
This becomes particularly important in a multichain environment because confirmation semantics are not identical across Bitcoin, Ethereum, Monero and Tari.
The Wallet Hub
Inside MyZubster, the Wallet Hub acts as the interface between the Marketplace/virtual world and the supported settlement rails.
The intended architecture is:
MyZubster World
│
▼
Marketplace
│
▼
Wallet Hub
/ | \
/ | \
ETH BTC XMR TARI
│ │ │ │
▼ ▼ ▼ ▼
Network Network Network Network
The important part is what is not inside that diagram:
private-key custody.
Different chains, different adapters
A multichain system should also avoid pretending every blockchain behaves like Ethereum.
A cleaner implementation uses network-specific adapters behind a common settlement interface.
Conceptually:
const settlementAdapters = {
ETH: ethereumAdapter,
BTC: bitcoinAdapter,
XMR: moneroAdapter,
TARI: tariAdapter
};
Each adapter can eventually implement operations such as:
getReceivingAddress()
validateAddress()
getTransactionStatus()
verifyPayment()
Signing can remain outside the Marketplace boundary.
This gives the application a common interface without erasing the differences between networks.
Bitcoin
Bitcoin integration can use an Electrum-based workflow for wallet/network interaction.
The important separation remains:
Marketplace
↓
public Bitcoin address
↓
external/user-controlled signing
↓
Bitcoin network
↓
confirmation verification
A transaction ID alone should not automatically mean "paid."
Confirmation status matters.
Monero
Monero requires its own integration model.
A Monero daemon and wallet RPC can provide the infrastructure needed for verification and wallet operations without exposing sensitive wallet material to the browser.
Again, the browser should never receive:
private spend key
private view key
seed
wallet password
Only the minimum information required by the application should cross the boundary.
Ethereum and Tari
ETH and Tari are exposed through the same Wallet Hub abstraction, while their network-specific adapters can evolve independently.
This is useful because the UI doesn't need to understand every protocol detail.
It only needs to understand something like:
asset
network
public destination
amount
transaction reference
status
confirmations/evidence
The backend adapter handles the chain-specific interpretation.
Security before convenience
It is tempting to build a "Pay" button that owns everything:
click
→ sign
→ send
→ confirm
That is convenient, but it dramatically changes the threat model if the server or frontend controls the keys.
For MyZubster, the safer initial architecture is deliberately less magical:
✓ public receiving addresses
✓ user-controlled authorization
✓ network-specific verification
✓ explicit settlement state
✓ separation of internal and external assets
✗ seed storage in frontend
✗ private keys in Git
✗ automatic custody
✗ assuming an order equals payment
✗ assuming a broadcast transaction equals confirmed settlement
Connecting the Marketplace to the virtual world
This work becomes more interesting because MyZubster isn't only a conventional marketplace.
The ecosystem is also experimenting with an interactive digital world containing community spaces, characters, chat, missions and other modules.
The longer-term architecture becomes:
Identity
│
├── Community
│
├── Missions
│
├── Marketplace
│ │
│ └── Wallet Hub
│ ├── ETH
│ ├── BTC
│ ├── XMR
│ └── TARI
│
└── MyZubster World
That creates the possibility of virtual-world interactions that lead to real settlement rails while maintaining a clear security boundary.
Open-source implementation
The Wallet Hub work is being developed publicly in the MyZubster repository.
The current implementation is tracked in:
PR #811 — Connect metaverse market to multichain wallet hub
At this stage, it should be treated as active development rather than a claim of a production-ready financial system.
CI, security testing, deployment configuration and transaction-verification workflows are all part of moving from architecture to production.
What comes next
The next steps are particularly interesting from an engineering perspective:
complete CI and security validation;
finish deployment configuration for each public wallet rail;
implement network-specific transaction verification;
connect marketplace orders to settlement evidence;
define confirmation policies per network;
improve auditability without exposing sensitive wallet information;
keep internal MYZ accounting clearly separated from external cryptocurrency settlement.
The bigger lesson is simple:
Multichain doesn't have to mean multi-custodial.
A marketplace can coordinate several blockchain networks while keeping transaction authorization where it belongs:
with the wallet owner.
MyZubster is an open-source project under active development.
GitHub:
https://github.com/MyZubster-Ecosystem/myzubster
Wallet Hub implementation:
https://github.com/MyZubster-Ecosystem/myzubster/pull/811