Lynk Core — Getting Started

Lynk Core — Getting Started

P2P sync engine for offline-first applications.
One binary. Connect. Sync. No server needed.

5-Minute Quick Start

Choose your language:

Language Package Import
Rust lynk-core crate cargo add lynk-core
Node.js @lynk/core npm npm install @lynk/core
Python lynk-core pip pip install lynk-core
C/C++ lynk_c.h header #include "lynk_c.h"

Getting Your Lic Token

Every node needs a Lic JWT to connect. It’s a signed token that tells the signaling server who you are and which peers you can reach.

You (developer B) → POST /api/v1/lic/provision → get Lic JWT
                  → pass to LynkEngine::new(lic_token)

Via API (one line):

curl -X POST https://api.lynkcore.dev/api/v1/lic/provision \
  -H "Authorization: Bearer *** \
  -H "Content-Type: application/json" \
  -d '{"node_id":"my-node","expires_at":"2027-06-10T00:00:00Z","signaling_mode":"http"}'

Via USB bootstrap (offline):
POS operators never see this — plug in a USB stick with bootstrap.poskey, the app reads lic.jwt from it automatically.

📖 Full provisioning guide: docs.lynkcore.dev/license


Rust

# Cargo.toml
[dependencies]
lynk-core = "0.1"
tokio = { version = "1", features = ["full"] }
use lynk_core::{PosyncEngine, SyncEngine, SyncCallback, LicContext, Transaction};
use std::sync::Arc;

struct MyApp;
impl SyncCallback for MyApp {
    fn on_transaction_received(&self, tx: Transaction) {
        println!("New tx: {} — {}", tx.tx_id, tx.amount);
    }
    fn on_peer_status_changed(&self, node: &str, online: bool) {
        println!("Peer {} is {}", node, if online { "online" } else { "offline" });
    }
    fn on_sync_completed(&self, n: usize) { println!("Synced {} items", n); }
    fn on_master_changed(&self, master: &str) { println!("Master: {}", master); }
    // ... implement remaining callbacks with todo!()
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. Parse your Lic token (from USB bootstrap or API)
    let lic: LicContext = serde_json::from_str(r#"{
        "lic_id":"lic-001","node_id":"pos-cashier-1","b_id":"b-001",
        "expires_at":"2027-06-09T00:00:00Z","signaling_mode":"http"
    }")?;

    // 2. Create engine with your Lic JWT
    let engine = PosyncEngine::new(
        lic,
        "your-lic-jwt-token".into(),        // JWT from provision API
        Arc::new(MyApp),
        Some("https://api.lynkcore.dev"),    // Signaling server URL
    )?;

    // 3. Connect — engine handles election, discovery, P2P, sync
    engine.connect().await?;

    // 4. Your POS is now live
    println!("I am master: {}", engine.is_master());

    // 5. Push transactions — engine routes to master automatically
    let tx = Transaction { /* your data */ };
    engine.push_transaction(tx)?;

    Ok(())
}

What happens when you call connect():

connect()
├── Start LAN master election (UDP broadcast)
├── Wait → become master → register with Signaling
├── Discover peers → establish P2P TCP (AES-256-GCM)
├── Start heartbeat loop (30s)
└── Start queue drainer (10s) → sync pending items

Node.js

npm install @lynk/core
const { createLynkEngine } = require('@lynk/core');

async function main() {
    // Create engine with Lic JWT + signaling URL
    const engine = createLynkEngine(
        'your-lic-jwt-token',
        'https://api.lynkcore.dev'
    );

    // Connect — automatic election + P2P
    await engine.connect();

    console.log('Master:', engine.isMaster());

    // Push data
    const tx = { txId: 'tx-001', amount: 29900, items: [...] };
    engine.pushTransaction(JSON.stringify(tx));

    // Poll status
    setInterval(() => {
        console.log('Peers:', engine.peerStatus());
        console.log('Pending sync:', engine.getPending().length);
    }, 5000);
}

main().catch(console.error);

Python

pip install lynk-core
from lynk_core import LynkEngine

def main():
    # Create engine
    engine = LynkEngine(
        lic_token="your-lic-jwt-token",
        signaling_url="https://api.lynkcore.dev"
    )

    # Connect — automatic election + P2P
    engine.connect()

    print(f"Master: {engine.is_master()}")

    # Push data
    tx = {"tx_id": "tx-001", "amount": 29900}
    engine.push_transaction(tx)

    # Query
    peers = engine.peer_status()
    pending = engine.get_pending()
    print(f"Peers: {len(peers)}, Pending: {len(pending)}")

if __name__ == "__main__":
    main()

C / C++

#include "lynk_c.h"
#include <stdio.h>

void on_tx_received(void* ctx, const lynk_transaction_t* tx) {
    printf("New tx: %s%lld\n", tx->tx_id, tx->amount);
}

int main() {
    // Parse Lic context from JSON
    lynk_lic_t lic;
    lynk_parse_lic("{\"lic_id\":\"lic-001\",...}", &lic);

    // Create engine
    lynk_engine_t* engine = lynk_engine_new(
        &lic,
        "your-lic-jwt-token",
        "https://api.lynkcore.dev"
    );

    // Register callback
    lynk_on_transaction(engine, on_tx_received, NULL);

    // Connect
    lynk_connect(engine);

    printf("Master: %d\n", lynk_is_master(engine));

    // Push transaction
    lynk_transaction_t tx = { .tx_id = "tx-001", .amount = 29900 };
    lynk_push_transaction(engine, &tx);

    // Cleanup
    lynk_engine_free(engine);
    return 0;
}

Compile:

gcc -o myapp myapp.c -llynk_c -lpthread -ldl

Signaling Modes

Lic token controls how your node discovers peers (Section 6.9):

Mode Best for Transport
http POS, batch sync REST heartbeat (30s)
mqtt Always-on, real-time Persistent MQTT (port 8883)
both Hybrid fallback MQTT first → HTTP backup
// Provision Lic with MQTT mode (via API)
POST /api/v1/lic/provision
{
    "node_id": "pos-1",
    "expires_at": "2027-06-10T00:00:00Z",
    "signaling_mode": "mqtt"
}

Architecture

┌──────────┐  master election   ┌──────────┐
│  POS 1   │◄──── UDP LAN ────►│  POS 2   │
│ (Master) │                    │(Follower)│
└────┬─────┘                    └──────────┘
     │  heartbeat + peer hints
     ▼
┌──────────┐
│ Signaling │   lynkcore.dev (REST + MQTT)
└──────────┘
     │
     ▼  AES-256-GCM over TCP
  Peer-to-peer data sync
  (A not involved after handshake)

Key principles: - Data belongs to the shop owner, never passes through A - Offline-first — POS works even without internet - 1 binary — License unlocks features, no reinstall - Master election automatic within LAN branches


Next Steps


Built by A Platform — P2P infrastructure for developers.
📧 hello@lynkcore.dev