Skip to main content
Wallet integration is the bridge between your application’s users and the SURCHI protocol. By connecting a Solana wallet, users can authenticate directly with their on-chain identity — no username or password required — and optionally grant your application permission to query their portfolio or submit execution strategies on their behalf via Execution Sentinel. This guide covers supported wallets, the wallet authentication flow, and the permission model for execution access.

Supported Wallets

SURCHI supports all major Solana wallet adapters. The following wallets are officially tested and recommended:
WalletTypeNotes
PhantomBrowser extension / MobileRecommended for most users
SolflareBrowser extension / MobileFull feature support including staking
BackpackBrowser extensionxNFT and advanced dApp support
LedgerHardwareVia the Solana Ledger adapter; requires Solana app v1.3.1+
Any wallet that implements the Solana Wallet Adapter standard is compatible. Hardware wallets connected through Phantom or Solflare are also supported.

Wallet Authentication Flow

SURCHI uses a sign-message authentication pattern — no transaction fees required. The user signs a challenge message with their wallet private key, and your application exchanges that signature for a SURCHI API access token scoped to that wallet identity.
1

Generate a nonce

Request a one-time nonce from the SURCHI API to prevent replay attacks. Nonces expire after 5 minutes.
curl -X POST https://api.surchi.io/v1/auth/nonce \
  -H 'Content-Type: application/json' \
  -d '{"wallet_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"}'
2

Construct and sign the message

Build a human-readable message incorporating the nonce and timestamp, then prompt the user to sign it with their wallet.
wallet-auth.ts
import { useWallet } from '@solana/wallet-adapter-react';

const { publicKey, signMessage } = useWallet();

// Construct a human-readable authentication message
const message = `Authenticate with SURCHI\nNonce: ${nonce}\nTimestamp: ${Date.now()}`;
const encodedMessage = new TextEncoder().encode(message);

// Prompt the user to sign — this opens their wallet UI
const signature = await signMessage(encodedMessage);

// Exchange the signature for a SURCHI API access token
const response = await fetch('https://api.surchi.io/v1/auth/wallet', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    wallet_address: publicKey.toString(),
    signature: Buffer.from(signature).toString('base64'),
    message
  })
});

const { access_token, expires_in } = await response.json();
3

Use the wallet-scoped token

The returned access token is scoped to the authenticated wallet address. Use it in the Authorization header for all subsequent API requests, including portfolio queries and execution submissions.

Portfolio Query

Once a user has authenticated with their wallet, query their portfolio using the wallet-scoped token. This returns the full token holdings and position analytics for the authenticated address:
portfolio.ts
async function getWalletPortfolio(accessToken: string, walletAddress: string) {
  const response = await fetch(
    `https://api.surchi.io/v1/wallet/portfolio?address=${walletAddress}`,
    {
      headers: {
        Authorization: `Bearer ${accessToken}`,
      },
    }
  );

  if (!response.ok) {
    throw new Error(`Portfolio fetch failed: ${response.status}`);
  }

  return response.json();
}
See the Market Data API page for the full portfolio response schema.

Execution Permissions

Execution Sentinel can perform on-chain actions — swaps, limit orders, liquidity adjustments — on behalf of a wallet, but only when the wallet owner has explicitly granted permission. Permissions are scoped, revocable, and recorded on-chain.

Permission Scopes

ScopeDescription
read:portfolioRead token balances and transaction history
execute:swapSubmit token swap instructions within user-defined slippage limits
execute:limit_orderPlace and cancel limit orders on behalf of the wallet
execute:liquidityAdd or remove liquidity from approved pools

Requesting Permissions

Permissions are requested through a signed on-chain transaction that records the grant in the SURCHI program. Present this to your user as a transparent permission dialog:
request-permissions.ts
import { useWallet } from '@solana/wallet-adapter-react';

const { publicKey, sendTransaction } = useWallet();

const response = await fetch('https://api.surchi.io/v1/execution/permissions', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${accessToken}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    wallet_address: publicKey.toString(),
    scopes: ['read:portfolio', 'execute:swap'],
    // Optional: maximum position size per execution in USD
    constraints: {
      max_position_usd: 500,
      allowed_assets: ['SOL', 'USDC', 'JTO'],
    },
  }),
});

// Returns a serialized transaction for the user to sign and submit
const { transaction } = await response.json();

Revoking Permissions

Users can revoke execution permissions at any time through the SURCHI app at app.surchi.io/settings/permissions, or programmatically via the API:
curl -X DELETE https://api.surchi.io/v1/execution/permissions \
  -H 'Authorization: Bearer {token}' \
  -H 'Content-Type: application/json' \
  -d '{"wallet_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "scopes": ["execute:swap"]}'
Never request more permissions than your application genuinely needs. Users should understand exactly what your application is authorized to do before granting execution access. Always present permission scopes in plain language in your UI, and make the revocation process easy to find. Misuse of execution permissions may result in your API key being permanently revoked.