Public Specification

Web App & Payments Architecture

A detailed breakdown of Satolink's client-side runtime, cryptographic sessions, and non-custodial payment channels.

1. Non-Custodial Core Integration

The fundamental architecture of the Satolink client application (both Web App and Mobile Client) is built directly around the Breez Liquid SDK (@breeztech/breez-sdk-liquid). By utilizing this runtime locally on the user's browser or device, Satolink enforces a strict zero-custody model.

🔑

Private Key Sovereignty

Recovery seeds (12 words) and private keys are generated, encrypted, and kept exclusively in local memory. They are never sent to, read by, or stored on Satolink servers.

Local Signing

All Bitcoin Lightning and Liquid transactions are signed directly in the browser's sandbox environment before broadcasting, ensuring no external party can manipulate your funds.


2. Cryptographic Authentication: Challenge-Response

Traditional database passwords are vulnerable to leaks, breaches, and phishing. Satolink replaces central password databases with an asymmetric **Challenge-Response** protocol. To authenticate, the client signs a cryptographic challenge using the private key derived from the Breez Liquid SDK.

Challenge-Response Authentication Protocol
Client DeviceSatolink API GatewayRedis / Database1. POST /challenge { walletID }2. Save Challenge (TTL 5m)3. Return { challenge }sdk.signMessage(challenge)AuthHash = SHA256(pwd+ID)4. POST /access { signature, authhash }5. Delete challenge & Verify Sig6. Return JWT + HTTP-Only Cookie

Authentication Flow Breakdown

  1. Challenge Acquisition: The client presents their walletID (wallet fingerprint). The server replies with a secure, 32-byte cryptographically-random challenge buffer that remains valid for exactly 5 minutes.
  2. Client Signature: The client feeds the challenge intosdk.signMessage({ message: challenge }) within the Breez Liquid SDK. The SDK prefixes the buffer with standard Lightning signature metadata ("Lightning Signed Message:"), hashes it using SHA-256, and signs it via ECDSA. The signature is outputted in z-base32 encoding.
  3. Entropy Protection: To prove ownership of the password locally, the client derives:
    $$\text{AuthHash} = \text{SHA-256}(\text{password} + \text{walletID})$$
    Only this hash is sent to the server. The password is never transmitted or exposed.
  4. Server-Side Verification: The server checks the signature locally using curve secp256k1 and checks if the challenge was not reused or expired. If valid, the session is approved.
🔒 Security Assurance:Because the challenge is immediately purged from the server memory on verification (step 5), replay attacks are mathematically prevented even if an attacker intercepts the signature packet.

3. Session Management & RTR (Refresh Token Rotation)

To maintain a seamless and highly secure web session, Satolink uses a dual-token strategy combining short-lived JWT credentials with active Refresh Token Rotation (RTR).

Access Token (JWT)
  • Stored in: JS Memory (Volatile)
  • Lifespan: 15 Minutes
  • Usage: Sent in the HTTP Authorization: Bearer header
Refresh Token
  • Stored in: HttpOnly, Secure, SameSite Cookie
  • Lifespan: 7 Days
  • Usage: Used to request new access tokens implicitly

RTR Fraud Prevention Mechanism

When a client triggers a refresh request (POST /api/v1/user/refresh), the server issues a new Access Token and a fresh Refresh Token, while immediately invalidating the previous Refresh Token.

If a malicious actor intercepting traffic attempts to reuse a revoked Refresh Token:

🚨

System Action: The server recognizes a duplicate refresh attempt, triggers a security freeze, and instantly invalidates all active session sessions for that specific user ID. The true owner is safely prompted to re-authenticate.


4. Address Pool: Receiving Payments Offline

A persistent problem with non-custodial systems is that wallets cannot receive transactions if they are offline, since generating a deposit invoice or signature requires a private key. Satolink solves this with the **Offline Address Pool** mechanism.

01
Local Pre-generation

While the user is online, the app pre-generates 5 Liquid BTC and 5 Liquid USDT addresses from the local seed.

02
Encrypted Upload

Addresses are uploaded to Satolink's API linked to the user's public username handle (user@satolink.com).

03
Offline Resolution

When someone pays you, the server allocates an unused address from your pool to route the payment directly to your custody.

📈 Peer-to-Peer Settlement:Because payments route directly to Liquid network addresses, Satolink is never a custodian of the funds. We act only as a cryptographic router that maps your public handle to your next unused Liquid address.

5. Real-Time WebSockets & Sockets Security

To supply dynamic UI updates (payment notifications, instant chats, and pool depletion warnings), Satolink opens a persistent, encrypted WebSocket connection using **Socket.io**.

Event NameSourcePurpose
registerClient ➔ ServerSends JWT token to authenticate the WebSocket channel.
auth_errorServer ➔ ClientTriggers if the socket JWT expires, prompting the client to refresh its tokens.
check_address_pool_updatedClient ➔ ServerQueries the database state of the pre-generated addresses.
address_pool_statusServer ➔ ClientPushes real-time warnings when the pre-generated addresses fall below safety levels (e.g., < 2 addresses).
notificationServer ➔ ClientDelivers real-time notifications about incoming transaction statuses and chat messages.

6. Technical Glossary

Breez Liquid SDK

A mobile and web software development kit built in Rust and WebAssembly, enabling client devices to maintain a local, self-custodial node on the Liquid Network.

z-base32

A variant of Base32 encoding optimized for human readability and writing. It excludes confusing characters (like O, 0, l, 1) and places easier-to-read letters in higher-probability indices.

secp256k1

The standard elliptic curve parameters used by Bitcoin and Liquid to generate cryptographic key pairs. It permits high-speed signing and verification operations.

Refresh Token Rotation (RTR)

A security method where the server issues a brand new refresh token alongside a new access token at every request, immediately revoking the old refresh token to prevent replay hijacks.