# Swapzy: A Custodial Multi-Chain Wallet for Chat Platforms

**Version 1.0 — September 2026**
swapzy.cc

## Abstract

Self-custodial cryptocurrency wallets ask every user to hold a seed phrase, to
keep a native coin on each chain in order to move any other asset on it, and to
know which of six networks a given dollar is sitting on before they can spend
it. The result is that crypto is used for holding and trading far more than it
is used for paying anyone. Swapzy takes the opposite trade deliberately: it is a
custodial wallet that runs inside a chat platform, where the user's existing
account is the account, transfers between users are ledger entries rather than
transactions, and the platform pays gas at both ends. This paper describes the
system — the per-chain ledger, the many-to-one deposit sweep, the one-to-many
withdrawal path, the swap pricing and settlement model, the treasury that keeps
six chains solvent, and the event stream that lets a chat client stay a thin
client. It also states plainly what the design costs: users trust Swapzy the way
they trust an exchange, not the way they trust a hardware wallet.

---

## 1. Introduction

A person who wants to send a friend twenty dollars of USDT today must: install a
wallet, record a seed phrase, fund the wallet with the native coin of whichever
chain they intend to use, confirm that the friend's address is on that same
chain, and pay a gas fee that may be a meaningful fraction of the amount. Every
one of those steps is a place to stop, and most people stop.

None of that friction is inherent to the payment. It is the cost of the wallet
being self-custodial, chain-agnostic in name but chain-specific in practice, and
disconnected from any identity the two parties already share.

Swapzy removes the friction by accepting the trade-off the friction exists to
avoid. It holds the keys. In exchange:

- **Identity is already solved.** A Discord account is the account. There is no
  signup, no seed phrase, and no address to copy between two people who are
  already talking to each other.
- **Transfers between users are free and immediate**, because they are ledger
  writes and never touch a chain.
- **Gas is the platform's problem.** A user holding only USDT can send USDT. They
  are never asked to acquire a native coin first.
- **Six chains present as one balance sheet**, with a swap — not a bridge the
  user has to find, fund and trust — as the way across.

Section 3 states the custody model without softening it, because a user who
discovers custody later discovers it badly.

## 2. Design goals

1. **The chat client stays thin.** Everything that is money — parsing an amount,
   pricing it, holding it, moving it, deciding when a timer expires — happens on
   the backend. A client is a renderer with a socket.
2. **A balance is a statement of fact, not a claim on inventory.** What the
   ledger says a user holds on a chain is what is there.
3. **Fail closed on price.** No transaction denominated in dollars settles
   against a stale or guessed rate.
4. **Idempotence at every chain boundary.** A redelivered webhook, a retried
   sweep or a duplicated callback must not move money twice.
5. **Publish the fee schedule in full.** Every charge in Section 13 is the whole
   charge. There is no percentage taken from transfers, no spread inside a
   deposit and no monthly fee.

Explicit non-goals: Swapzy does not pay yield, does not lend user balances, does
not offer leverage, and does not present itself as insured, regulated or
licensed.

## 3. Custody model

**Swapzy holds the keys.** Balances are credited to a chat-platform account and
settled from wallets Swapzy controls.

This is what makes the rest of the system possible. An instant, free transfer
between two users is only instant and free because no chain is involved, and no
chain can be involved unless one party controls both sides. Gas can only be paid
by the platform if the platform is the one signing.

The honest framing is that using Swapzy is like using an exchange: a user trusts
an operator to hold funds and honour withdrawals. It is not like using a
hardware wallet. Long-term savings belong somewhere the holder keeps the keys.

Three structural properties bound the risk:

- **User deposit addresses are not spending wallets.** Each user's derived
  address per chain is emptied into the master wallet as soon as a deposit
  confirms. Nothing is ever signed from it afterwards.
- **Everything that leaves the platform leaves from the master wallet**, through
  one path, with one set of controls.
- **The ledger is the record of what is owed**, independent of where the funds
  happen to be sitting, and it is reconciled against on-chain holdings.

## 4. Accounts and identity

A Swapzy account is a chat-platform identity. Discord accounts are addressed by
their snowflake; Telegram accounts are namespaced (`tg:` prefixed) so the two
can never collide. Identity is canonicalised in one place, and the platform a
user belongs to is derived from the identifier rather than passed alongside it.

Cross-platform transfers are refused. A Discord user cannot tip a Telegram user,
because the two identifiers name different people in different namespaces and
guessing that they are the same person is not a guess a payment system should
make.

Clients authenticate with an API key that *is* a tenant identity: the key
determines which users a request may act for and which events a socket receives.
Administrative access is a separate credential entirely — a different table, a
different header, a different minting path — so that no amount of client
compromise yields operator reads.

## 5. The ledger

Every balance in Swapzy is a `(user, chain, asset)` triple. USDT on Solana and
USDT on Ethereum are two holdings, not one. The balance endpoint returns them
keyed by chain and then by token, and deliberately publishes no cross-chain
total, because that sum is not a number anyone can spend.

This was not the original design, and the change is instructive. Stablecoins
used to be pooled: a deposit on any chain could be withdrawn on any other, with
the treasury quietly bridging behind the scenes. That worked until the house was
short on the chain someone withdrew to — at which point the user's balance had
quietly become a claim on inventory rather than a statement of what they held.
Per-chain balances make the constraint visible at the moment it matters, and a
refusal names where the money actually is:

> Insufficient USDT balance on eth. You hold 50 on sol — balances do not cross
> chains, so swap it to eth first.

The way across is an explicit swap, priced and shown before it is agreed to.

Ledger primitives are credit, debit, hold, settle and revert. A withdrawal
debits into a hold and settles when the chain confirms, so funds are never
spendable twice and a failure path has something to return. Per-account advisory
locks are keyed by `user:chain:asset`, so two chains of one stablecoin do not
serialise against each other. Amounts have one canonical stored spelling;
trailing zeros are trimmed only at the display boundary, so what the balance
check validated and what the row stores are the same string.

## 6. Deposits

Each user is issued a derived address per chain, and it stays theirs.

Deposits are detected by chain-appropriate means — provider webhooks on EVM
chains and Solana, and ZeroMQ subscriptions to our own Litecoin and Bitcoin
nodes that capture transactions for registered addresses only. Litecoin credits
after six confirmations and Bitcoin after two; other chains credit on
confirmation of the depositing transaction.

A sweeper then moves funds from the user's address into the master wallet and
credits the ledger. There are six sweep paths — EVM token, EVM native, SOL,
SPL, LTC, BTC — and every one credits idempotently, keyed on the transaction hash, so
a redelivered webhook cannot double-credit. A sweep that fails retries with
exponential backoff for twenty-four hours.

**Deposits are charged at cost, and often at nothing.** When a stablecoin
deposit lands, Swapzy pays gas to collect it and charges back exactly that —
measured from the sweep transaction itself (`gasUsed × gasPrice` on EVM, the
signature fee in lamports on Solana), with nothing added. Native deposits on EVM
chains are free, because the sweep is sent by the depositing address and pays its
own gas. Litecoin deposits are free, because the miner fee comes out before the
coins land. A Bitcoin deposit pays the miner fee of the sweep that collects it,
out of the deposit, and nothing more; because that fee is larger, a Bitcoin
deposit below 0.00005 BTC waits on its address until the deposits there reach
that, and they are collected and credited together. If the cost cannot be measured or priced, nothing is charged — a
deposit is never held up over a fee.

## 7. Internal transfers

A payment from one Swapzy user to another is a ledger write. Nothing touches a
chain, no gas is burned, and the transfer is free and immediate. This holds for
native coins as much as for stablecoins.

The decision is made by *who the recipient is*, not by what is being moved — so a
raw address that turns out to be one of Swapzy's own deposit wallets settles
internally too, rather than paying a network to move funds between two accounts
the platform already controls.

A tip to several recipients is a single ledger debit covering all of them, which
makes it all-or-nothing: if any recipient is an outside address, the whole tip
goes on-chain.

## 8. Withdrawals

A withdrawal is signed by the master wallet, never by the sender's derived
address.

The path is: parse the amount (a USD figure requires a live price, and a dead
price feed yields a retryable error rather than a guess), hold the balance, check
that the chain has the liquidity, queue, sign, broadcast, and settle the hold
when the transaction confirms. In the current configuration a queued withdrawal
is picked up within seconds rather than waiting on a fixed batch window; EVM
payouts are still packed into a single `multiTransfer` call, so one transaction
can settle many users' payouts at once.

**Fees are charged in one of two modes, chosen by balance rather than
configuration:**

| | user is debited | recipient receives |
|---|---|---|
| fees on top | amount + fees | the whole amount |
| fees under | exactly the amount | amount − fees |

In both cases `debited = received + fees`. That invariant is what makes
"withdraw my entire balance" work without the user pre-computing a fee.

**Held withdrawals.** When a chain is temporarily short of a stablecoin, the
withdrawal is held rather than rejected: the balance is already debited into a
hold, a cross-chain top-up is sourced, and the user is told they are waiting.
Three events narrate it — pending, resumed, and expired — and an expiry refunds.
Handing a user a retryable error against a chain that will stay empty for minutes
is not an answer, so the system does not give one.

## 9. Swaps

Any supported asset can be swapped for any other, including across chains, in one
command.

**Litecoin is the first exception.** Any supported asset buys it, and it sells
only into USDT or USDC, on any supported chain. A Litecoin swap is not filled on
the spot: it completes when the other side delivers, which takes minutes rather
than seconds, and the user is told by direct message. Each Litecoin pair has a
minimum and a maximum size, and the quote names both. Its quote is an estimate —
what is credited is what is delivered, less the costs the quote named — and if
the swap cannot be completed, the full amount sold returns to the balance.

**Bitcoin is the second.** It swaps both ways with every supported asset except
Litecoin; the two cannot be swapped with each other. A Bitcoin swap waits on the
Bitcoin network, so it too takes minutes rather than seconds, and the user is
told by direct message when it completes.

**Pricing has two components.** A base rate, which is the cost of taking the
other side of the trade, and a size component, which reflects that larger trades
move the market more. Both are computed at quote time from the pair, the amount
and what the market is doing at that moment.

The rate is therefore a property of the trade rather than a figure on a page.
The quote states it, alongside the exact amount that will be received, and **a
user is never charged a rate they were not shown**. A small floor keeps trivial
swaps worth executing, and a ceiling expressed as a share of the trade stops
that floor from ever dominating one: below that point the swap is declined with
a reason rather than filled at a rate nobody would agree to if they read it.

**Quotes.** Every quote states exactly what will be received. A quote expires
shortly after it is given. It is indicative: the rate is recomputed at execution, and if the market
has moved past tolerance the swap is refused rather than filled worse. Prices
come from live market data with a 15-second staleness limit — a price older than
that is not used for anything.

**Routing** compares external execution venues on the only figure that matters to
the person trading:

```
effective output = venue output − platform fee − gas − other explicit costs
score            = effective output − execution risk − quote staleness
```

The best user output wins. Routing is scored per trade rather than pinned per
corridor, and multi-hop routes are taken when they deliver more than a direct
one. The cost of the route is already inside the quoted number.

## 10. Treasury and liquidity

Six chains must each be solvent enough to serve withdrawals on demand. The
treasury tracks per-chain inventory and rebalances between chains when one runs
short.

Rebalance routes are constructed backwards from the amount needed, because the
*output* is the constraint: a top-up that arrives 3% light has not solved the
problem it was dispatched to solve. One planner runs at a time, under a lock, so
two rebalances cannot claim the same funds.

Two ideas are kept strictly separate, and the separation is load-bearing:

> **A cap is a hard permission boundary. Inventory skew is an economic incentive
> within that boundary.**

Caps say what is allowed. Skew makes an allowed trade cheaper or dearer to steer
inventory back toward balance. Skew must never quietly become a second exposure
limit, because then the real limit is one nobody wrote down.

## 11. Airdrops

An airdrop distributes one sender's pot across many recipients as ledger writes.

Timed rounds run entirely on the backend. A host opens a round with a pot and a
duration; participants enter by pressing a button in chat; the round closes on
the backend's clock and pays out in the same database transaction that marks it
closed, so a crash between the draw and the payment is not a state the system
can be in. Two shapes are supported, and the difference is one optional field:

- **A winner count is given** — that many entrants are drawn at random.
- **No winner count is given** — everyone who entered splits the pot equally.

All four outcomes are reported back to the chat client: settled, empty (nobody
entered), void (the pot will not divide into a share worth sending), and failed.
A countdown that ends in silence reads like lost money, so no ending is left
unannounced.

## 12. Event delivery

Chat clients hold a WebSocket. Deposits credited, withdrawals completed,
rebalances pending, resumed or expired, and airdrop rounds closed are pushed to
the client that owns the user in question, with an HTTP callback as a fallback
transport. Events are sliced per tenant: a bot receives only what concerns its
own users.

This is what keeps the client thin. A round that closes while a bot is being
restarted still settles, and the result arrives on the socket when the bot comes
back — there is no resume path in the client to get wrong, because there is no
state in the client to resume.

## 13. Fee schedule

The whole of it.

| What you do | What it costs |
|---|---|
| Send to another Swapzy user | **Free** (0%) |
| Tip another Swapzy user | **Free** (0%) |
| Deposit LTC, or native ETH / BNB / POL | **Free** |
| Deposit BTC | The network fee to collect it, taken from the deposit |
| Deposit stablecoins | Exactly the gas spent collecting it. No markup. |
| Withdraw on Ethereum | $1.00 |
| Withdraw on BNB Smart Chain | $0.05 |
| Withdraw on Polygon | $0.01 |
| Withdraw stablecoins on Solana | $0.20 |
| Withdraw SOL | $0.01 |
| Withdraw LTC | $0.01 |
| Withdraw BTC | $1.00 |
| Swap | A percentage of the trade, built into the quote |

Withdrawal fees are flat, not percentages: the same whether the amount is $20 or
$20,000. Stablecoin fees are taken in the stablecoin being sent; native-coin fees
are quoted in dollars and converted at the live rate when the withdrawal
executes. The fee always comes from the sender — the recipient receives the full
amount that was typed.

**One Solana surcharge.** Sending USDT or USDC to a Solana address that has never
held that token requires opening a token account on-chain, and Solana charges
rent for it. That is **about $0.20**, charged only the first time that address
receives that token and never again. It is computed live from the network's rent
minimum and the SOL price, and is never less than $0.05.

Ethereum costs a hundred times what Polygon does because Ethereum gas costs a
hundred times what Polygon gas does. Every one of these fees covers the cost of
the transaction it pays for; none of them is a margin on the difference.

## 14. Security posture

- **Keys.** User addresses are derived; the master wallet signs everything that
  leaves. Deposit addresses are swept empty and never spent from.
- **Two credential systems.** Client API keys carry tenant identity and can act
  only for their own users. Administrative tokens are a separate credential with
  their own scopes, and every administrative route is read-only.
- **Fail-closed pricing.** The price feed throws rather than returning a stale or
  default figure, and the error surfaces as a retryable service error. There is
  no fallback constant anywhere in the money path.
- **Idempotence.** Deposit credits are keyed on transaction hash. Sweeps,
  webhooks and callbacks are all safe to redeliver.
- **Locks.** Per-account advisory locks on the ledger, a distributed lock on the
  treasury planner, and source locks that stop two writers claiming one pot of
  funds.
- **Rate limiting** per user and per key, with velocity controls on the paths
  that move money.
- **Reconciliation** between ledger liabilities and on-chain holdings, with
  operator alerts on mismatch.
- **Tests.** The backend carries a unit suite and a suite that runs against a real
  embedded PostgreSQL; both run on every change.

## 15. Limitations and risks

Stated plainly, because a whitepaper that omits them is marketing.

- **Custodial risk is the principal risk.** An operator that is compromised,
  insolvent or coerced is a risk to user balances. Swapzy is not insured,
  regulated or licensed, and makes no claim to be.
- **A transfer sent on the wrong network cannot be recovered.** USDT on Ethereum
  and USDT on BNB Smart Chain are different tokens on different networks.
- **Deposits take as long as the network takes.** Litecoin waits for six
  confirmations and Bitcoin for two, and a Bitcoin deposit below 0.00005 BTC
  waits on its address until the deposits there reach that. "Instant" applies
  only to transfers between Swapzy users, which never touch a chain.
- **Swaps are priced against live market data.** A quote is indicative; if the
  market moves past tolerance between quote and execution, the swap is refused
  rather than filled at a worse rate.
- **Very small swaps are declined** when the minimum fee would take too large a
  share of the trade.
- **Litecoin sells only into USDT or USDC**, and a Litecoin swap takes minutes
  rather than seconds. Its quote is an estimate, not a fixed amount.
- **Bitcoin cannot be swapped into or out of Litecoin**, and a Bitcoin swap
  takes minutes rather than seconds.
- **No yield.** Balances earn nothing. Swapzy does not lend, stake or rehypothecate
  user funds.

## 16. Future work

Directions under consideration, none of them promised: additional chat platforms
on the existing identity namespacing (Telegram is already addressable in the
identity layer); further chains and assets, each of which must earn its place by
carrying its own liquidity; a published attestation of ledger liabilities against
on-chain holdings, so the reconciliation that runs internally can be checked
externally; and per-server configuration for communities that want their own
fee or feature posture.

## 17. Conclusion

Most crypto wallets optimise for sovereignty and pay for it in usage. Swapzy
optimises for usage and is explicit about what that costs. Inside a chat client,
where two people are already in the same place with the same identities,
a payment should be a sentence — and the machinery that makes it one is a
per-chain ledger, a master wallet at both ends of every chain interaction, a
swap desk that quotes before it fills, and a treasury that keeps six chains
solvent so no user has to think about which one their dollars are on.

The honest summary is a trade: keys for convenience, stated up front rather than
discovered later.

---

## References

1. S. Nakamoto, *Bitcoin: A Peer-to-Peer Electronic Cash System*, 2008.
2. Ethereum Foundation, *Ethereum Development Documentation*. https://ethereum.org/developers
3. Solana Foundation, *Solana Documentation* — Associated Token Accounts and rent. https://solana.com/docs
4. Bitcoin Core project, *Bitcoin Core Documentation*. https://bitcoincore.org
5. Litecoin Project, *Litecoin Core Documentation*. https://litecoin.org
6. Circle, *USDC: Multi-chain Deployments*. https://circle.com/usdc
7. Discord Inc., *Discord Developer Documentation*. https://discord.com/developers/docs

---

*Swapzy is a custodial service. Nothing in this document is financial advice, an
offer of a security, or a promise of return. Fees and parameters stated here are
current as of the version date and may change; the live schedule is published on
swapzy.cc.*
