NIMmesh, a Bluetooth mesh wallet for Nimiq, goes to alpha today. Sign a payment on a phone with no connection. It hops phone to phone until one of them is online and puts it on the chain.
Every phone running NIMmesh is a node. The internet is needed at the final hop only.
A node signs, carries and relays. A relay never reads what it carries. It holds a payment until another node appears, so the mesh can be sparse.
Every field is fixed width. The biggest payment ever and the smallest are the same size.
Not on average. Every single one.
That matters more than being small. A radio either fits it or it does not, once, forever.
Tap a field. 96 of the 139 bytes are the public key and the signature. The payment itself is 40. The three slivers are single-byte fields: format, proof type, network id.
Attach a note to the payment and it stops fitting in a text message.
SMS is the tight one: a bare payment fits with one byte to spare. Attach a note (a memo, in Nimiq terms) and it grows to roughly 205 bytes, which no single SMS can carry.
Both existing Bitcoin bridges split the transaction and rebuild it at the far end. NIMmesh never does.
| Project | How it goes on the air | What that forces |
|---|---|---|
| btcmesh | Chunked hexadecimal strings over LoRa direct messages. | A reassembler on the receiving end, and a configurable reassembly timeout for when a chunk never lands. |
| MeshtasticBitcoinCore_Bridge | You divide the raw hex yourself into portions of 200 characters or less. | A + before every portion and a == to terminate. Its README notes that Bitcoin hex may run past 1,000 characters against a 228-byte buffer. |
Both bridges send hex, which doubles the bytes, then chunk it. A NIM payment goes on the air as 139 raw bytes and its size is fixed: no reassembly, no partial state, no timeout to tune.
Four mainnet payments totalling 19 NIM, each one on the block explorer.
| Block | When | Value | What it proved |
|---|---|---|---|
| 55488525 | 7 Jul 2026, 00:38 UTC | 1 NIM | Airplane mode phone, over Bluetooth, to a Mac gateway. The first real money. |
| 56054933 | 13 Jul 2026, 11:39 UTC | 1 NIM | Phone to phone, no computer in the path. |
| 56055090 | 13 Jul 2026, 11:42 UTC | 15 NIM | Same path, two and a half minutes later, fifteen times the amount. |
| 56055105 | 13 Jul 2026, 11:42 UTC | 2 NIM | Once more, fifteen seconds after that. |
Bluetooth, end to end, with real funds. Nothing about LoRa or SMS, which have never carried a payment.
The measurement is done. The radio work is not.
| Claim | Status | What is true today |
|---|---|---|
| A payment over LoRa | Unproven | No radio has ever carried one. The Meshtastic frame codec is written and checked byte by byte against the published protobuf schema by hand, but no LoRa hardware has been bought and nothing has been on the air. |
| A payment over SMS | Unproven | The one byte of headroom is arithmetic, not a delivery receipt. No transaction has been sent through a carrier. |
| 1.35 seconds on air | Computed | Derived from Semtech's time-on-air formula for a 155-byte frame at the LongFast preset. Not measured on a device. |
| Android relaying | Unproven | Both Bluetooth roles come up on a real stack and the wallet signs correctly on device. No byte has yet crossed the air between two Android phones. |
| Cross-chain swaps | Testnet | NIM to USDC runs end to end and settles, on Nimiq testnet and Polygon Amoy only. The mainnet phone-to-phone swap has never been run. Do not read the swap code as mainnet proven. |
The two meshes already carry each other's messages, phone to phone.
NIMmesh is a Nimiq take on Bitchat, Jack Dorsey's Bluetooth mesh messenger from July 2025. Same mesh, a signed transaction instead of a chat message.
A mesh is only worth anything if other people's software is on it.
Reported, not verified here: the demo ran phone to phone with no computer in the path. Two phones in a room are the only real proof.
Three months of work, then the radios.
The clock starts when the first tranche lands. The app is scored on the Mini Apps Competition rubric, three ways, at nimiq.tech/scored.
Not by building a network. Meshtastic communities already run open meshes across many cities. One $35 radio puts a NIMmesh gateway on one.
An earlier post found 143 million crypto owners where no exchange sells NIM. A payment that fits one SMS does not care which exchanges serve your country.
The milestone that matters next: a payment crossing a phone that belongs to somebody I have never met.
Open source, Apache 2.0, at github.com/Andjroo111/nimmesh. The 139-byte tests run in its CI.
The Android app is signed with one permanent key, so a phone can verify every update comes from the same author. The first testers come from the Nimiq community, on their own phones.
The size is asserted in CI, in a file called transport_mtu_tests. A change to the wire format turns the build red. Five tests, all passing when this post was written:
| Test | What it asserts |
|---|---|
| a_real_signed_transfer_is_exactly_the_advertised_139_bytes | A fully formed, signed transfer serialises to 139 bytes. |
| a_transaction_fits_one_meshtastic_packet_with_room_to_spare | It fits, and the margin is at least 64 bytes, so a slow creep toward the ceiling is caught early rather than at the edge. |
| a_transaction_fits_a_single_binary_sms | It fits inside 140 bytes with no concatenation header. |
| a_transaction_fits_the_transports_we_already_ship_or_plan | It fits the Bluetooth padding block and a raw LoRa frame. |
| the_sms_headroom_is_exactly_one_byte_and_that_is_documented | The headroom is one byte, so if it ever loosens or tightens the documentation is wrong and has to be corrected. |
The transaction under test is built with the largest values its fields can hold: the maximum amount, the maximum fee, the highest block height. If any integer were serialised short, the test would measure a smaller number and the claim would quietly shrink. It is measured from a real serialised transaction, not compared against a stored constant.
The Meshtastic ceiling is quoted three different ways, and the post takes the smallest.
| Reading | Payload | Room left |
|---|---|---|
| Meshtastic's own mesh.proto, DATA_PAYLOAD_LEN, with the 16-byte header outside the envelope | 233 | 94 |
| Our test, a 237-byte packet with the 16-byte header subtracted anyway | 221 | 82 |
The honest range is 82 to 94 bytes. This post uses 82.