Lane Lite · Phone Node Contributor spec Live on devnet

Solinkify DePIN · Android contribution

Build the Lane Lite phone node.

A phone becomes a relay node: connect, forward signed transactions, earn USDC. Here is the exact protocol and a path from MVP to a live devnet test.

01

What a phone node does

A Lite node is a pure transport relay. It opens an outbound WebSocket to the coordinator, receives a Solana transaction that is already signed, submits it to an RPC, and reports back the signature. The node never builds or changes a transaction (ADR-006), so it holds no funds and carries almost no trust: the worst a coordinator can do is withhold a job.

Outbound-only is deliberate. Phones sit behind carrier NAT and have no public IP, so the node dials out to the coordinator rather than the other way around.

How the node earns

02

Prerequisites

Before a node can go online, its wallet must be a registered, active Lite node.

Register first, order matters. Even a perfectly correct signature is rejected with denied: "wallet is not an active Lite node" until the wallet has staked and is Lite tier on-chain. Registration is a one-time step: run register.js from the reference repo once on any PC using the same keypair the app will use. The Android app itself never needs to build a transaction.

Devnet parameters

Coordinator WSwss://api.solinkify.com/coordinator/ws
Status (GET)https://api.solinkify.com/coordinator/status
Solana RPChttps://api.devnet.solana.com
Program IDA8qSJCS2uxxnEMdCcpjX2L8hUUMydoeCi5xq5qvzS22B
$SINKY mintEAMRKocV7wTrj2S7CwYQVAbBqB4xa51TV1Akdp9FKa8R
Auth domainsolinkify-lite-v1:
Lite stake25 SINKY · on-chain tier byte = 3
03

The WebSocket protocol

This is the contract, one JSON object per text frame. It is identical to the reference Node.js runner already relaying on devnet, so the Android app can port it 1:1.

  1. server → sends a one-time challenge with a random nonce.
  2. client → ed25519-signs "solinkify-lite-v1:" + nonce and returns auth with the wallet pubkey and base58 signature.
  3. server → checks the signature and the on-chain node, then sends ready (or denied with a reason).
  4. server → pushes a job: a job_id and a base64 already-signed transaction.
  5. client → submits the tx to the RPC, then replies result with the signature (or error with a message).
// 1. server → client
{"type":"challenge", "nonce":"<uuid>"}

// 2. client → server   (sig = base58 of ed25519 over the UTF-8 bytes below)
{"type":"auth", "wallet":"<base58 pubkey>",
 "signature":"<base58 ed25519( 'solinkify-lite-v1:' + nonce )>"}

// 3. server → client
{"type":"ready"}
{"type":"denied", "reason":"wallet is not an active Lite node (register 25 SINKY first)"}

// 4. server → client
{"type":"job", "job_id":"<id>", "tx":"<base64 signed tx>"}

// 5. client → server
{"type":"result", "job_id":"<id>", "signature":"<sig>"}
{"type":"error",  "job_id":"<id>", "message":"<err>"}
Submitting a job is cheap. The tx is already signed, so the node just calls Solana RPC sendTransaction with encoding base64 and returns the signature. That is a plain JSON-RPC POST, no full Solana SDK is needed for the runner core. Also reply to WebSocket ping with pong.
Signing details that matter. The nonce is a 32-character hex string (no dashes); use it exactly as received. The message to sign is the raw UTF-8 bytes of "solinkify-lite-v1:" + nonce (the colon is part of the prefix; sign the message itself, not a hash of it). The signature is a 64-byte ed25519 detached signature encoded as base58 (not base64, not hex). Keypair format pitfall on the JVM: a Solana keypair JSON array is 64 bytes, the first 32 are the ed25519 seed and the last 32 the public key. BouncyCastle and Tink expect the 32-byte seed only; tweetnacl-style APIs expect the full 64 bytes. Passing the wrong slice is the most common cause of denied: "signature invalid". To confirm you are online after ready: GET the status endpoint from the table above, your wallet should appear in the list.
04

Timeouts & session rules

These match the coordinator, keep them exact.

05

What the app must implement

06

Android-specific notes

Most of the runner is light. The two real challenges are Android platform behavior, not the protocol:

Suggested stack: Kotlin + OkHttp (WebSocket) + an ed25519 library, with a foreground service. The Solana Mobile SDK / a Kotlin Solana RPC client helps if you later add in-app registration.
07

Milestones: MVP to devnet test

A build path in four phases. Phase 3 is the proof: a real payment relayed by the phone, verifiable on-chain. (Ticks are a reading aid and do not save.)

P0

Setup & access

Prep
P1

Core runner

MVP
P2

Android runtime

Hardening
P3

Devnet validation

Proof
P4

Next, post-MVP

Optional