TagwiseTagwiseDevnet
Integration Guides

Wallet Authentication (SIWS)

Non-custodial ed25519 signature challenge authentication and session management.

TIP uses Sign-In With Solana (SIWS) authentication. To perform protected actions, users sign a single-use text challenge message generated by the server.


High-Level connect() Flow

The TipClient SDK handles challenge requesting, byte encoding, and signature verification automatically via connect(signer):

import { TipClient } from "@tagwise/tip-sdk";

const client = new TipClient();

// Connect with any wallet adapter matching the Signer interface
const authenticatedPubkey = await client.connect({
  publicKey: walletAdapter.publicKey.toBase58(),
  signMessage: async (messageBytes: Uint8Array) => {
    return await walletAdapter.signMessage(messageBytes);
  },
});

console.log("Authenticated as:", authenticatedPubkey);
console.log("JWT Session Token:", client.token);

Session Persistence Across Page Reloads

The SDK keeps the JWT session token in memory by default. In web or mobile apps, you can store the JWT in localStorage or secure enclave storage and restore it when your app loads:

// On login: Save token & pubkey
const pubkey = await client.connect(signer);
localStorage.setItem("tip_token", client.token!);
localStorage.setItem("tip_pubkey", pubkey);

// On app initialization / refresh: Restore session
const savedToken = localStorage.getItem("tip_token");
const savedPubkey = localStorage.getItem("tip_pubkey");

if (savedToken && savedPubkey) {
  client.setSession(savedToken, savedPubkey);
  console.log("Restored session for:", client.connectedPubkey);
}

Manual Challenge/Verify (Advanced Control)

If you are implementing custom auth pipelines without connect(), call challenge() and verify() explicitly:

// 1. Fetch challenge string
const message = await client.challenge(userPubkey);

// 2. Sign message bytes with ed25519 keypair / wallet
const messageBytes = new TextEncoder().encode(message);
const signatureBytes = await walletAdapter.signMessage(messageBytes);

// 3. Convert signature bytes to base58
import { getBase58Decoder } from "@solana/kit";
const signatureBase58 = getBase58Decoder().decode(signatureBytes);

// 4. Verify signature and retrieve JWT token
const jwtToken = await client.verify(userPubkey, message, signatureBase58);

On this page