Back to list

Development Update — August 6

Today the mobile app took center stage. The phone got a real Wallet — SKY, the fiber coins, BTC, and now native Ethereum with ERC-20 tokens and USDT built in — a redesign that gives every screen one visual language, and several passes of polish driven by using it on a device. Underneath, two periodic jobs the phone had been paying for got trimmed, and the phone stopped shipping the deployment’s survey whitelist it had no business carrying. On the browser side, the Services-Health tab is now populated and bounded on a wasm hypervisor, guarded against silent DTO drift; and a dmsg server can finally reach its own co-located transit client so its version stops showing blank.

Skywire: The Mobile Wallet Grows a Second Chain

The phone’s Wallet now holds SKY, the fiber coins, and BTC with keys that never leave the device, and today it gained a second chain: Ethereum — native ETH and ERC-20 tokens, with USDT built in. Around it, a full redesign gives every screen one language — “the cloud in the middle” — so SkyChat wears the Wallet’s design and every tab wears one header, and a hardening pass drew the line on what leaves the phone and what is readable on it. SkyVPN got a second pass from real use: rates that move, a route-length control, and an honest address readout. A polish pass and a six-item test-pass pull followed — the app icon, lighter cards, battery handling, coin logos, contrast, the nav cloud, back behavior, hang-up, the first message — plus a second pass adding a hub jump, a hero exit line, live tile numbers, chat file verbs with upload progress, a DEX list view, and heartbeats moved out of the room. Country names now come off a guarded Locale.Builder. On the build side, make android-apk takes a version and owns the versionCode, and CI gates app checks on android/ and releases the APK from a mobile-v tag.

Skywire: Trimming What the Phone Pays For

Two fixes cut work the phone shouldn’t have been doing. fix(dmsg,visor): two periodic jobs the phone was paying for removes background jobs a phone-hosted visor was running needlessly — one of them fleet-wide in effect — so a battery-constrained device isn’t spending cycles and radio on periodic work that doesn’t serve it. fix(visor): the phone stops shipping the deployment’s survey whitelist stops the phone build from carrying the deployment survey-collection whitelist it has no role in; the survey machinery is a deployment-node concern, not something a phone visor should be distributing.

Skywire: Services-Health on a Browser Visor

The HV Services-Health tab was blank on a browser wasm hypervisor because pkg/wasmhv served no /api/service-health route, so the Angular component short-circuited to a “not available on a browser visor” notice. 3779 feat(wasmhv): populate the Services-Health tab adds SelfProvider.SelfServiceHealth(), which probes each deployment service’s /health over the wasm visor’s own dmsg client (net/http-free, via dmsgclient.FetchOverDmsg on dmsg port 80), reads build_info.version + latency + status, and returns the native []visor.ServiceHealthEntry shape — the same pattern as SelfNetworkView. Only the route-setup-node stats section, a native-hypervisor role a browser edge has none of, stays gated off on wasm. 3787 fix(wasm-visor): bound the Services-Health probe stops one dead service from hanging the tab: SelfServiceHealth was waiting on all seven probes via wg.Wait(), and the decommissioned standalone uptime tracker never answers, so the table could sit on “Checking deployment services…” for 30s+. A hard 9s overall deadline with partial results now pre-seeds rows (configured-but-unreachable → TIMEOUT, unconfigured → N/A) and overwrites them as each probe returns under a mutex — reachable services answer in <1s over dmsg, so 9s never truncates a healthy one. Because the fetch is now unconditional, a stale blob without the route would 404, so both committed blobs (wasmgo + wasmtinygo) were rebuilt — and 3778 test(visor): guard against wasm-HV mirror DTO drift pins that surface: pkg/wasmhv can’t import pkg/visor, so it hand-mirrors Overview/Summary/TransportSummary/About/HealthInfo as a comment-only contract, and a new reflection test (in an external visor_test package that can import both without a cycle) asserts mirror ⊆ native — every mirrored field must exist in the native original with the same Go field name (gob identity) and json key (wire identity). The tour caught up too: 3786 spotlights the live dmsg/transport counts instead of the column headers, and 3780 corrects the services step and names the .dmsg aliases in the browse demo.

Skywire: A dmsg Server That Can Reach Itself

3776 fix(dmsg-server): transit client reaches its own server via loopback closes a self-reachability gap. A dmsg server runs a co-located transit dmsg client under the same PK, serving /health, pprof, and route-setup on dmsg port 80; that client is an unregistered deployment service reached via seeded delegated-servers, and with MinSessions:0 it connects to all servers including itself — but its self-entry used the server’s public address, making the self-dial a NAT hairpin (a container dialing its own external IP back into itself), which fails on typical Docker/NAT hosts. So the server held no session for its own transit client, and a remote dial to dmsg://<serverPK>:80 routed through the server’s own sessionless entry and timed out — which is exactly why svc health showed a blank version for such servers despite them being current and healthy. Pointing the transit client’s own entry at the loopback listener (127.0.0.1:<local port>) makes the self-session form in-kernel with no NAT, adding the local path without changing reachability via the other servers. A new TestSelfSession_SameKeyClientReachesOwnServer proves a client sharing the server’s keypair forms a session with its own server (Noise-XK with initiator==responder static key is valid) and relays a third client’s stream through it. Version populates for every server directly once the fleet redeploys.