frontier field notes · no. 04 ↩ back to the index
A field note on Utexo's wallet stack — read from the source

How native USDT reaches your wallet.

Where it settles was the question of No. 03. This note answers the next one: how a Bitcoin-native dollar actually climbs out of rgb-lib and LDK, through a Rust FFI, into the app on your phone. The map below is drawn from the source of @utexo/wdk-rgb-lightning - the module that wires RGB-over-Lightning into Tether's Wallet Development Kit.

repo: UTEXO-Protocol/wdk-rgb-lightning version read: 0.1.0-beta.13 status: beta · on npm license: Apache-2.0
§ 00

The dollar that came home.

USDT was born on Bitcoin, left for faster chains, and is finding its way back - this time as an RGB asset settling over Lightning. The module in this note is the road home.

2014

Born on Bitcoin

Tether launches on the Omni Layer - USDT's first home, anchored to Bitcoin.

2019 →

Left for speed

Volume migrates to Ethereum and Tron. Cheaper, faster - and fully public.

2023

Omni sunset

Tether ends Omni support. The original Bitcoin rail goes quiet.

2026

Home, via RGB

Native USDT returns to Bitcoin - client-side validated, Lightning-fast, settlement-anchored.

§ 01

Four floors between the chain and the app.

Tap a floor to read it. Or press trace a payment and watch an invoice fall through the whole building - from the wallet's one-line call down to the Rust node that signs against Bitcoin.

the stack · top = your code
below L4: ⌂ Bitcoin - the settlement anchor

One package, two runtimes. exports in package.json picks the binding at module-load: Node resolves index-node.js, a bare worklet resolves bare.js. Same classes either way.

§ 02

A wallet integrates, in seven moves.

The README's usage example, annotated move by move. This is the whole journey from "npm install" to a paid Lightning invoice carrying an RGB asset - with the seed never leaving the host.


          
§ 03

The part that earns the word "wallet".

Three design decisions in the security model, as documented in the repo. They are the difference between "an SDK that moves money" and one a wallet team can actually ship.

keys

The seed never leaves the host

The mnemonic is owned by the WDK secret manager. The binding derives a 32-byte BIP-32 entropy (seedHex), hands it once to NativeExternalSigner.create, and the node persists only public material - xpubs, node id, master fingerprint. Same mnemonic, same node identity, every restart.

signing

Channel crypto runs in-process

All channel-state signing goes through vls-protocol-signer - the Validating Lightning Signer - whose lifecycle is tied to the binding and destroyed on manager.dispose(). No external signing daemon to misconfigure.

backup

Cloud backup that sees nothing

With vssUrl set, channel state and RGB wallet data mirror to a VSS endpoint encrypted client-side with XChaCha20-Poly1305, keyed via HKDF from the BIP-39 mnemonic (path m/535'/1'). The server stores ciphertext; recovery requires the original seed. Plain http:// is rejected by default.

seed → seedHex → signer, once persists public material only VLS dies with dispose() backup key m/535'/1' http:// rejected by default server holds ciphertext only
§ 03b

The module, by the numbers.

A wallet integration has a shape you can count. Here's the one this module asks for - read straight off the repo at the version above.

4
floors from app to chain
L0 → L4, then Bitcoin
7
moves to a paid invoice
install → construct → pay
2
runtimes, one codebase
Node host · Bare / RN
1
Rust FFI chokepoint
one security-review surface
12
platform prebuilds
7 bare · 5 napi
0
times the seed leaves the host
public material persisted only
§ 03c

Two roads to USDT on Bitcoin - this one takes RGB.

USDT already moves over Lightning via Taproot Assets. This module bets on RGB instead. The difference is where asset data lives - and who can see it.

this module

RGBclient-side validation

data livesOff-chain, in the holder's rgb-lib store. The chain sees commitments, not amounts.
privacyTransfer history is shared peer-to-peer, not broadcast. Default-private.
on LightningAsset channels via rgb-lightning-node (LDK + rgb-lib).
maturityYounger tooling, smaller validator surface, heavier client.
the other road

Taproot Assetsuniverse / proof courier

data livesProofs anchored to Taproot outputs; universes distribute proof state.
privacyBetter than a public token ledger, but proof distribution differs in posture.
on LightningAlready live - USDT shipped over LN via Taproot Assets in 2026.
maturityMore deployed today; backed by Lightning Labs' stack.

The honest read: Taproot Assets has the head start. RGB's pitch is stronger client-side privacy and validation that never touches a shared ledger. This module is a bet that the second property is worth the younger toolchain - a bet worth its own field note.

§ 05

Anatomy of a native USDT transfer.

What actually happens when one wallet pays another, end to end - the five beats this module orchestrates.

01
Invoice
payee creates a BOLT11 carrying an RGB asset id
02
Route
LDK finds a path across asset channels
03
Validate
rgb-lib checks the transfer client-side, off-chain
04
Settle
HTLC resolves; balances move along the channel
05
Anchor
correctness traces back to Bitcoin, on close
§ 04

What the footnotes say.

Things you only find by reading the repo, not the press release. Beta software is allowed rough edges - naming them is how it hardens.

FN·1

Now on npm - it wasn't when this note was filed

At the time of writing the native bindings shipped only as GitHub-tagged prebuilds, installed via a github:#v<tag> spec. As of 0.1.0-beta.10 they are published: @utexo/rgb-lightning-node-nodejs@0.1.0-beta.9 and -bare@0.1.0-beta.13. The README install steps are now plain npm install.

resolved · now on npm
FN·2

README and package.json disagreed on versions - fixed

When filed, the README pinned the bindings at beta.8 / beta.12 while package.json floored both at ^0.5.2-beta.1 - ranges that didn't overlap, so the documented install threw EBADPEER. Flagged it; 0.1.0-beta.10 realigned the floors to ^0.1.0-beta.9 / ^0.1.0-beta.13, on the same 0.1.0 base as the published prereleases. Maintainer confirmed the diagnosis.

resolved · diagnosis confirmed
FN·3

Five "not exposed" ops are, in fact, exposed

The README says issueAssetNia / Ifa / Cfa / Uda and inflate aren't exposed here and points at wdk-wallet-rgb. The account class in src/wallet-account-rgb-lightning.js forwards all five straight to the node. Either the code should drop them or the README should own them.

contribution surface: code/doc reconciliation
FN·4

The good kind of footnote: APay and hodl are already in

Async payments (apayNew, plus a one-shot bootstrapLsp that replaced a manual three-call dance), hodl invoices, atomic swaps and a hardened LSP client with retry/backoff and structured errors - all present in beta. The surface is wider than the headline suggests.