Skip to content

App

The App class connects to wish-core and gives you direct access to the p2p network. It's the foundation — RpcApp is built on top of it.

Creating an App

typescript
import { App } from '@wishcore/wish-sdk';

const app = new App({
    name: 'MyApp',
    protocols: ['myprotocol'],
});

Auto-connects to wish-core via Unix socket (macOS: ~/Library/Application Support/Wish/core.sock, Linux: ~/.wish/core.sock).

Options

OptionTypeDescription
namestringApp name shown in Dashboard
protocolsstring[]Protocol names this app speaks
coreUnixSocketstringOverride Unix socket path (auto-detected by default)
corePortnumberTCP port (legacy, prefer unix socket)
coreHoststringTCP host (default: 127.0.0.1)
permissionsobject{ admin: true } for admin access

Events

ready

Fired when connected to wish-core and ready to operate.

typescript
app.on('ready', () => {
    console.log('Connected');
});

online(peer)

A peer with a matching protocol came online.

typescript
app.on('online', (peer) => {
    console.log(peer.toString());  // "André@hp/myprotocol"
    app.peer.send(peer, Buffer.from('hello'));
});

offline(peer)

A peer went offline.

typescript
app.on('offline', (peer) => {
    console.log(peer.toString(), 'disconnected');
});

frame(peer, data)

Received a raw frame from a peer.

typescript
app.on('frame', (peer, data) => {
    // data is a Buffer
    console.log(peer.toString(), ':', data.toString());
});

disconnected

Lost connection to wish-core. The SDK reconnects automatically.

Peer

The Peer object identifies who you're talking to.

typescript
peer.luid     // Buffer — local identity UID
peer.ruid     // Buffer — remote identity UID
peer.rhid     // Buffer — remote host ID
peer.rsid     // Buffer — remote service/app ID
peer.protocol // string — protocol name

Display

peer.toString() returns a human-readable string following peer notation:

typescript
peer.toString()  // "André@hp/myprotocol"

Names are resolved from wish-core's identity list. Falls back to 6-char hex when names aren't available:

typescript
peer.toString()  // "a3f2e1@965907/myprotocol"

Identity

peer.toUrl() returns the full peer URL used as a unique key:

<luid-hex>><ruid-hex>@<rhid-hex>/<rsid-hex>/<protocol>

Identity API

app.identity.list()

List all identities visible to this app (own + contacts).

typescript
const identities = await app.identity.list();

// [{ uid: Buffer, name: 'André', privkey: true }, ...]

Non-admin apps only see identities explicitly granted via the Wish app.

app.identity.get(uid)

Get full identity details including signers and hosts.

typescript
const identity = await app.identity.get(uid);
// { uid, name, privkey, signers: [...], contacts: [...], hosts: [...] }

app.identity.sign(uid, document, claim)

Sign a document with an identity's key. The claim is an arbitrary buffer that becomes part of the signed statement.

app.identity.verify(document)

Verify a signed document. Returns the document with verification result.

Sending data

app.peer.send(peer, frame)

Send a frame to a peer. Retries automatically on buffer-full (up to 15 seconds).

typescript
await app.peer.send(peer, Buffer.from('hello'));

Frames are raw bytes — you decide the encoding. Most apps use CBOR:

typescript
import { encodeOne, decodeFirstSync } from 'cbor';

// Send
await app.peer.send(peer, encodeOne({ type: 'message', text: 'hello' }));

// Receive
app.on('frame', (peer, data) => {
    const msg = decodeFirstSync(data);
    console.log(msg.type, msg.text);
});

Peer Pins

Declare that your app wants wish-core to maintain a connection to a specific peer.

app.peer.pin(luid, ruid, rhid, policy, priority?)

typescript
const ANY_HOST = Buffer.alloc(32); // all zeros = any host

await app.peer.pin(
    myUid,       // local identity
    bobUid,      // remote identity
    ANY_HOST,    // any host
    'eager',     // connect when possible
    0            // highest priority
);

Policies:

  • 'always' — maintain connection persistently
  • 'eager' — connect when possible, allow disconnect

app.peer.unpin(luid, ruid, rhid)

Remove a peer pin.

app.peer.pins()

List this app's peer pins.

typescript
const pins = await app.peer.pins();
// [{ luid, ruid, rhid, policy: 'eager', priority: 0 }, ...]

Identity name cache

App automatically caches identity names and host names from wish-core, used by peer.toString(). The cache is refreshed on identity changes.

typescript
// Look up names directly
app.identityCache.getName(uid)          // "André" or undefined
app.identityCache.getHostName(uid, hid) // "hp" or undefined

Signals

Subscribe to real-time events from wish-core. Everything is event-driven — identities change, connections come and go, contacts are added.

typescript
app.requestBare('signals', [], (msg) => {
    if (msg.data === 'ok') return; // subscription confirmed
    const [name, data] = msg.data;
    console.log('Signal:', name, data);
});
SignalFires when
identityIdentity list changed — new identity, name update, contact added
connectionsConnection established or lost
nearbyNearby peer discovered or lost (admin only)

Use signals to keep your app reactive. For example, re-fetch app.identity.list() when the identity signal fires, or update your UI when connections changes.

Low-level requests

For endpoints not yet wrapped by the SDK, use app.request() directly. See the Identity and Peers API pages for the full reference.

typescript
await app.request('admin.request', ['identity', 'Need identity for sync']);

Connection lifecycle

┌──────────┐     ┌───────────┐     ┌──────────┐
│connecting│────→│ connected │────→│  ready   │
└──────────┘     └───────────┘     └──────────┘
                       │                 │
                       │   ┌─────────────┘
                       ▼   ▼
                 ┌──────────────┐
                 │disconnected  │──→ auto-reconnect
                 └──────────────┘

The App auto-reconnects on disconnect (2 second delay). All pending requests are rejected with DISCONNECTED. All peers are marked offline.

App permissions

Apps are sandboxed by wish-core. By default, an app:

  • Has no identities (must be granted via the Wish app)
  • Sees no contacts
  • Cannot make admin API calls

Grant identities and configure contact visibility through the Wish tray app (Dashboard).