Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Tikka SDK

NestJS library for Soroban contract interaction: transaction building, simulation, fee estimation, signing, and submission. The frontend and third-party integrators use this instead of calling Soroban directly.

Stack: NestJS, TypeScript, Stellar SDK. Published as @tikka/sdk.

Consumers: Frontend (client), third-party developers.

Compatibility: @tikka/sdk follows Semantic Versioning. Breaking changes are preceded by a documented deprecation window — see DEPRECATION.md.

Light vs full build

Choose the full SDK when you need NestJS modules, dependency injection, wallet services, or the higher-level contract helpers that assume the framework runtime. Choose the light build when you need a browser-friendly entry point for low-level RPC access and lightweight types without the NestJS overhead.

Build Import path Includes Excludes Measured size
Full @tikka/sdk all runtime modules, wallet adapters, contract services, and CLI helpers build output is available from the package entry point
Read-only @tikka/sdk/read the read-oriented helpers and types used by the CLI and lightweight consumers write/create helpers currently measured at 219 bytes gzipped in the workspace build output
Light @tikka/sdk/dist/light/index.light lightweight RPC client, raffle/network types, and shared helpers NestJS modules, decorators, DI providers, and high-level services currently measured at 183 bytes gzipped in the workspace build output

The light bundle is intended for browser and mobile integrations where bundle size matters most. Services must be instantiated manually, and NestJS module wiring is not available in this entry point.

Browser vs Node support matrix

Every public entry point and its runtime compatibility. Use this table when choosing an import path or planning bundler polyfills.

Module / entry Browser Node Notes
@tikka/sdk (full) NestJS modules (RaffleModule, TicketModule, etc.) target server-side DI; instantiate service classes directly in browser apps. Bundler required (buffer, crypto, stream polyfills may be needed).
@tikka/sdk/read Recommended for dashboards and SSR. No wallet or signing code bundled.
@tikka/sdk/write Write path: wallet adapters, ContractService, TransactionLifecycle, domain write services. Re-exports @tikka/sdk/read.
Light build (@tikka/sdk/dist/light/index.light) Smallest bundle; manual instantiation only. No NestJS, wallet adapters, or CLI.
RpcService Uses fetch; pass fetchClient in React Native or custom environments.
HorizonService Same fetch-based pattern as RpcService.
MockRpcService In-memory mock for tests, Storybook, and offline dev.
NetworkModule (NestJS) ⚠️ Requires NestJS runtime; use plain RpcService / HorizonService in browser.
ContractService Simulate/build/submit; signing delegated to a WalletAdapter.
TransactionLifecycle Four-phase invoke flow; needs a wallet adapter for the sign step.
ReadOnlyRaffleService Query-only; no wallet required.
ReadOnlyUserService Query-only; no wallet required.
RaffleService (write) Create/cancel need a browser wallet or MockWalletAdapter. Read methods work without signing.
TicketService Buy/refund need a wallet adapter; queries are simulate-only.
UserService (write) Participation queries are read-only; no wallet for reads.
AdminService Admin writes need a wallet; reads are simulate-only.
RaffleModule / TicketModule / UserModule / AdminModule ⚠️ NestJS DI wrappers; prefer direct service classes in browser bundles.
FeeEstimatorService RPC simulation only; no wallet or Node APIs.
FeeEstimatorModule (NestJS) ⚠️ NestJS DI wrapper around FeeEstimatorService.
buildChallenge / verifyResponse (SEP-10) ⚠️ Uses Node crypto.randomBytes; provide a crypto polyfill in browser or run server-side only.
FreighterAdapter Requires Freighter extension or @stellar/freighter-api.
XBullAdapter Requires xBull extension.
AlbedoAdapter Popup-based; requires @albedo-link/intent.
LobstrAdapter Requires LOBSTR extension.
RabetAdapter Requires Rabet extension (window.rabet).
MockWalletAdapter For tests, Storybook, and examples without a real wallet.
Utils (errors, validation, formatting, retry, BigNumber) Pure utilities; no environment-specific APIs.
CLI (tikka / bin/tikka.cjs) Node-only; uses commander, inquirer, and filesystem.

Legend: ✅ supported · ⚠️ works with bundler/polyfill or is not the primary target · ❌ not supported

Common polyfills for browser bundlers (Vite, Webpack, esbuild): buffer, crypto (for SEP-10 and Stellar SDK), and stream when your toolchain requires them. React Native consumers should pass an explicit fetchClient to RpcService (see React Native Notes below).

Core Features

  • Customizable RpcService: Support for custom fetch clients, headers, and automatic failover across multiple nodes.
  • Automatic RPC Retries: Built-in retry with exponential backoff for transient 429/5xx/timeout errors, with per-call opt-out.
  • Contract Interaction: Type-safe transaction building and simulation for Soroban contracts.
  • Wallet Integration: Unified WalletAdapter interface supporting Freighter, xBull, and Albedo.
  • Local Mocking Utilities: MockWalletAdapter and MockRpcService for Storybook, UI tests, and offline development.
  • Modular Design: Domain-specific modules for Raffles, Tickets, and Users.

Read-Only Entry Point (@tikka/sdk/read)

Consumers that only need to query raffle data (public dashboards, SSR pages, analytics) can import from the read-only sub-path. This avoids bundling wallet adapters and signing code, producing a significantly smaller bundle.

import { ReadOnlyRaffleService, ReadOnlyUserService, RpcService, resolveNetworkConfig } from '@tikka/sdk/read';

const networkConfig = resolveNetworkConfig('mainnet');
const rpcService = new RpcService(networkConfig);

const raffleService = new ReadOnlyRaffleService(rpcService, networkConfig);
const userService = new ReadOnlyUserService(rpcService, networkConfig);

// List all raffle IDs
const { value: allIds } = await raffleService.getAll();

// Fetch a single raffle
const { value: raffle } = await raffleService.getById(42);

// User participation profile
const { value: profile } = await userService.getProfile('GBIQ4VH3...');

// User raffle ID history
const { value: history } = await userService.getHistory('GBIQ4VH3...');

What is included

Export Description
ReadOnlyRaffleService getAll() — all raffle IDs; getById(id) — single raffle data
ReadOnlyUserService getProfile(addr) — participation stats; getHistory(addr) — raffle IDs
RpcService Soroban RPC client (simulate, getLedger)
HorizonService Horizon account/fee queries
resolveNetworkConfig, NetworkConfig Network configuration helpers
ContractFn, RaffleStatus Contract constants
ContractResponse Shared response envelope type
Read-only types RaffleData, UserParticipation, AssetDescriptor, etc.
Utils Formatting, validation, errors, retry, BigNumber

What is excluded

The read-only bundle intentionally excludes all signing-related code:

  • ContractService (requires wallet + TransactionBuilder)
  • TransactionLifecycle (requires wallet + signing)
  • All wallet adapters (Freighter, xBull, Albedo, LOBSTR, Rabet)
  • FeeEstimatorService
  • sep10 auth helpers
  • Write-side service classes (RaffleService, TicketService)
  • NestJS modules

Building the read-only bundle

cd sdk
pnpm run build:read   # outputs to dist/read/

Bundle size budget and size-check workflow

The SDK keeps browser-facing entry points small. Contributors whose PRs grow these bundles should know the limit and how to remediate before merging.

Budgets (enforced by size-limit)

Budgets are defined in sdk/package.json under the "size-limit" key. Sizes are minified + gzipped, with NestJS / Stellar / RxJS peer-style dependencies ignored so the check measures first-party SDK code (what consumers pay for on top of deps they already ship).

Entry Build output Budget Typical size (approx.)
@tikka/sdk/read dist/read/index.read.js 50 kB gzip ~7 kB
Light SDK (index.light) dist/light/index.light.js 25 kB gzip ~3 kB

The light entry also has a historical soft target of < 50 kB gzip documented in LIGHT_VERSION.md; the 25 kB limit above is the enforced budget based on current measured size with headroom for growth.

The full NestJS entry (@tikka/sdk) is not size-gated — prefer @tikka/sdk/read or the light entry for browser/mobile consumers.

Running the checks

cd sdk
pnpm install

# Build the entries under test (required before size-check)
pnpm run build:read
pnpm run build:light

# Enforced budgets (fails the process if over limit)
pnpm run size-check

# Legacy helper: prints the raw byte length of dist/light/index.light.js only
# (no budget assertion — useful for a quick local sanity check on Windows)
pnpm run size-check:legacy

CI currently runs SDK lint/test/build/docs; run size-check locally (or in a PR follow-up job) whenever you change SDK public exports, network/RPC code, or anything imported by the read/light entry points.

When size-check fails

  1. Confirm you rebuilt: pnpm run build:read and/or pnpm run build:light.
  2. Re-run pnpm run size-check and note which entry exceeded its budget.
  3. Audit imports on the failing entry:
    • Prefer @tikka/sdk/read or the light entry over the full @tikka/sdk barrel.
    • Do not pull wallet adapters, signing, SEP-10, fee estimation, or NestJS modules into the read/light graphs.
    • Avoid new heavy dependencies in files reachable from index.read.ts / index.light.ts.
  4. Split write-only helpers behind the main or ./write entry so tree-shaking can drop them from read/light consumers.
  5. If the growth is intentional and justified, update the matching "limit" in package.json "size-limit" in the same PR and explain why in the PR body.

Changing a budget

Edit the "size-limit" array in sdk/package.json, keep "gzip": true, and leave peer-style packages in "ignore" unless you intentionally want them counted. After changing a limit, run the build + size-check commands above and document the rationale in the PR.

Project Structure

  • src/network/ — Customizable Soroban RPC and Horizon services.
  • src/contract/ — Core transaction logic and Soroban bindings.
  • src/wallet/ — Multi-wallet adapter system.
  • src/modules/ — Feature modules (Raffle, Ticket, User).
  • src/utils/ — Shared utilities for formatting, validation, and error handling.
  • bin/tikka.cjs — Developer CLI for network testing and contract interaction.

CLI Commands

The Tikka SDK includes a command-line interface for smoke testing, network configuration, and contract interaction.

Installation

After building the SDK:

npm run build
npm run cli -- --help

Global Options

  • -n, --network <type> — Target network: testnet (default) or mainnet
  • -j, --json — Output results in JSON format (useful for scripting)
  • --help — Show help for a command
  • --version — Show CLI version

Read-Only Commands (no secrets required)

These commands don't require wallet signing and are safe for smoke testing:

config-check

Verify CLI configuration and SDK initialization.

tikka config-check                 # Check on testnet
tikka -n mainnet config-check      # Check on mainnet
tikka config-check --json          # Output as JSON

fee-quote <contractId>

Get estimated fees for a transaction.

tikka fee-quote CONTRACT_ABC123
tikka fee-quote CONTRACT_ABC123 --function transfer
tikka fee-quote CONTRACT_ABC123 --json
tikka -n mainnet fee-quote CONTRACT_ABC123

read <contractId>

Read contract data or state.

tikka read CONTRACT_ABC123
tikka read CONTRACT_ABC123 --key account_balance
tikka read CONTRACT_ABC123 --json
tikka -n mainnet read CONTRACT_ABC123

list

List active raffles on the network.

tikka list                    # List on testnet
tikka list --limit 20         # Limit results
tikka list --json             # Output as JSON
tikka -n mainnet list         # List on mainnet

info

Get contract status and network information.

tikka info                    # Get info on testnet
tikka info --json             # Output as JSON
tikka -n mainnet info         # Get info on mainnet

Interactive Commands (wallet signing required)

These commands require wallet integration for signing transactions:

create

Create a new raffle (interactive).

tikka create              # Guided setup on testnet
tikka -n mainnet create   # Guided setup on mainnet

buy

Purchase raffle tickets (interactive).

tikka buy                 # Purchase on testnet
tikka -n mainnet buy      # Purchase on mainnet

Examples

# Smoke test network configuration
cd sdk
npm run build
npm run cli -- config-check

# Get fee estimate for a contract (testnet)
npm run cli -- fee-quote CBVG2R3YLEDVGIQKHY6K2HGX55CPJMK5QX2YQE7WALLVIQG5IHVIGISQ

# Query contract state on mainnet
npm run cli -- -n mainnet read CBVG2R3YLEDVGIQKHY6K2HGX55CPJMK5QX2YQE7WALLVIQG5IHVIGISQ --json

# List raffles as JSON for automation
npm run cli -- list --json > raffles.json

# Get help for a specific command
npm run cli -- fee-quote --help

JSON Output

All commands support the --json flag for machine-readable output:

# Output as JSON
$ tikka config-check --json
{
  "version": "0.1.0",
  "network": "testnet",
  "rpcAvailable": true,
  "contractAvailable": true,
  "status": "OK"
}

# Errors also format as JSON
$ tikka fee-quote INVALID --json
{
  "error": "Invalid contract ID"
}

Error Handling

The CLI provides safe error messages that don't leak sensitive information:

  • Read-only commands fail gracefully with helpful error messages
  • Interactive commands confirm before executing wallet operations
  • JSON output includes error details in structured format
  • Invalid commands suggest the help flag for usage information

API Documentation

Full TypeDoc reference is auto-generated and hosted on GitHub Pages: crackedstudio.github.io/tikka

To build locally:

npm run docs        # generates sdk/docs/
npm run docs:watch  # rebuilds on file change

SEP-10 Backend Integration

The SDK includes SEP-10 helpers for building and verifying Stellar web authentication challenges.

Server-side challenge creation

import { buildChallenge } from '@tikka/sdk';
import { Networks } from '@stellar/stellar-sdk';

const challengeXdr = buildChallenge({
  serverSecret: process.env.SEP10_SERVER_SECRET!,
  clientAccount: clientPublicKey,
  anchorDomain: 'example.com',
  webAuthDomain: 'auth.example.com',
  timeout: 300,
  networkPassphrase: Networks.TESTNET,
});

return { xdr: challengeXdr };

Server-side response verification

import { Sep10VerificationError, Sep10VerificationErrorCode, verifyResponse } from '@tikka/sdk';
import { Networks } from '@stellar/stellar-sdk';

const verifiedClient = await verifyResponse({
  signedChallenge: responseXdr,
  serverAccount: serverPublicKey,
  clientAccount: clientPublicKey,
  anchorDomain: 'example.com',
  networkPassphrase: Networks.TESTNET,
  nonceValidator: async (nonceBase64) => {
    const key = `sep10:nonce:${nonceBase64}`;
    const added = await redis.set(key, '1', { NX: true, EX: 300 });
    return added === 'OK';
  },
});

console.log('Authenticated client:', verifiedClient);

Handling verification failures

try {
  await verifyResponse(...);
} catch (err) {
  if (err instanceof Sep10VerificationError) {
    if (err.code === Sep10VerificationErrorCode.ChallengeExpired) {
      // prompt client to request a new challenge
    }
  }
  throw err;
}

The docs are organized by module: Raffle · Ticket · Wallet · User · Network · Utils.

Error Reference

All SDK errors extend TikkaSdkError and carry a stable code property for predictable handling:

Code Class When thrown
NetworkError NetworkError All RPC endpoints unreachable, no fetch implementation
TIMEOUT RpcTimeoutError RPC request exceeded timeout
RATE_LIMIT RateLimitError RPC node returned 429
UNAVAILABLE UnavailableError RPC node returned 502/503/504
INVALID_RESPONSE InvalidResponseError Malformed or unparseable RPC response
TRANSACTION_REJECTED TransactionRejectedError Network explicitly rejected submitted transaction
SUBMISSION_FAILED TikkaSdkError (generic) Transaction submission failed (fallback)
SimulationFailed TikkaSdkError (generic) Transaction simulation failed
CONTRACT_FAILURE ContractFailureError Contract execution returned an error
CONTRACT_ERROR TikkaSdkError (generic) General contract error
AUTH_ERROR AuthError Authentication / SEP-10 verification failure
UNAUTHORIZED UnauthorizedError Caller lacks permission for admin-only operation
INSUFFICIENT_FUNDS InsufficientFundsError Caller's balance is too low
UserRejected TikkaSdkError (generic) User cancelled the wallet prompt
WALLET_NOT_CONNECTED TikkaSdkError (generic) Wallet not connected
WALLET_NOT_INSTALLED TikkaSdkError (generic) No wallet extension detected
INVALID_PARAMS TikkaSdkError (generic) Invalid function parameters
VALIDATION_ERROR TikkaSdkError (generic) Input validation failure
RAFFLE_NOT_FOUND RaffleNotFoundError Raffle ID does not exist on-chain
RAFFLE_ENDED RaffleEndedError Raffle is in DRAWING/FINALIZED/CANCELLED state
RAFFLE_FULL RaffleFullError Raffle has sold its maximum tickets
EXTERNAL_CONTRACT_ERROR TikkaSdkError (generic) Cross-contract call failed
UNKNOWN TikkaSdkError (generic) Catch-all for unexpected errors
try {
  await contractService.buyTicket(raffleId, quantity);
} catch (err) {
  if (err instanceof NetworkError) {
    // All RPC endpoints are down
  } else if (err instanceof TransactionRejectedError) {
    // Network rejected the submission
  } else if (err instanceof InsufficientFundsError) {
    // Top up before retrying
  } else if (err instanceof AuthError) {
    // Re-authenticate
  } else if (err instanceof TikkaSdkError) {
    // Fallback: check err.code
    switch (err.code) {
      case TikkaSdkErrorCode.RateLimit:
      case TikkaSdkErrorCode.Timeout:
        // Retry with backoff
    }
  }
}

Architecture

Full ecosystem spec: ../docs/ARCHITECTURE.md (section 2 — tikka-sdk).

Examples

All runnable examples live in examples/. They use MockWalletAdapter so they compile and run without a browser wallet — swap it for FreighterAdapter or another adapter when you need real signing.

Setup:

cp examples/.env.example examples/.env
# fill in TIKKA_PUBLIC_KEY and any other vars you need

Type-check all examples (no network required):

npm run examples:check

End-to-end walkthrough: bootstrap → create raffle → buy tickets → read state.

Env var Required Default Description
TIKKA_NETWORK no testnet testnet | mainnet | standalone
TIKKA_PUBLIC_KEY no mock key Stellar G… address
TIKKA_NETWORK=testnet npx ts-node examples/quickstart.ts

Create a new raffle on-chain with configurable price, asset, and duration.

Env var Required Default Description
TIKKA_NETWORK no testnet Network
TIKKA_PUBLIC_KEY yes Signer address
TIKKA_TICKET_PRICE no 1 Amount per ticket
TIKKA_ASSET_CODE no XLM Asset code
TIKKA_ASSET_ISSUER no "" Issuer for non-native assets
TIKKA_MAX_TICKETS no 50 Max tickets available
TIKKA_DURATION_HOURS no 24 Hours until raffle closes
TIKKA_METADATA_CID no "" IPFS CID for metadata
TIKKA_PUBLIC_KEY=G... npx ts-node examples/create-raffle.ts
# USDC example:
TIKKA_ASSET_CODE=USDC TIKKA_ASSET_ISSUER=GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN \
  TIKKA_PUBLIC_KEY=G... npx ts-node examples/create-raffle.ts

Purchase tickets for an existing raffle, with pre-flight status checks.

Env var Required Default Description
TIKKA_NETWORK no testnet Network
TIKKA_PUBLIC_KEY yes Buyer address
TIKKA_RAFFLE_ID yes Numeric raffle ID
TIKKA_QUANTITY no 1 Number of tickets
TIKKA_PUBLIC_KEY=G... TIKKA_RAFFLE_ID=1 npx ts-node examples/buy-tickets.ts

Poll Soroban contract events (RaffleCreated, TicketPurchased, RaffleFinalized) with optional raffle filter. Runs until Ctrl+C.

Network required — connects to the Soroban RPC to stream events.

Env var Required Default Description
TIKKA_NETWORK no testnet Network
TIKKA_RAFFLE_ID no all Filter events for one raffle
TIKKA_POLL_MS no 5000 Polling interval (ms)
TIKKA_CONTRACT_ID no built-in Override contract address
TIKKA_NETWORK=testnet npx ts-node examples/listen-events.ts
# filter to raffle #1:
TIKKA_RAFFLE_ID=1 npx ts-node examples/listen-events.ts

Cold-wallet / air-gapped signing flow. Step 1 builds an unsigned XDR; Step 3 submits a pre-signed XDR. Useful for multisig and hardware wallets.

Network required — Step 1 calls simulateTransaction; Step 3 submits to the network.

Env var Required Default Description
TIKKA_NETWORK no testnet Network
TIKKA_PUBLIC_KEY yes Source account address
TIKKA_SIGNED_XDR no Provide to skip to Step 3 (submit)
# Step 1 — build unsigned XDR:
TIKKA_PUBLIC_KEY=G... npx ts-node examples/offline-signing.ts

# Step 3 — submit after signing offline:
TIKKA_PUBLIC_KEY=G... TIKKA_SIGNED_XDR=<xdr> npx ts-node examples/offline-signing.ts

Browser-wallet integration demos. These require a browser environment (Albedo opens a popup; Rabet needs the extension installed).

Browser + wallet required — not runnable via ts-node in a plain terminal.

Minimal custom WalletAdapter implementation (local keypair stand-in). Documents the integrator contract and compiles via npm run examples:check.

npm run example:custom-wallet

Wallet Adapters

The SDK provides a unified interface for multiple Stellar wallets. All adapters implement the same WalletAdapter interface with getPublicKey() and signTransaction(xdr) methods.

Implementing a custom wallet? See the full integrator contract — methods, expected errors, and signing flow — in WALLET_ADAPTER.md, plus the runnable examples/custom-wallet.ts.

Supported Wallets

Wallet Installation Notes
Freighter Browser extension Most popular, requires extension
xBull Browser extension / PWA Mobile-friendly
Albedo Web-based No extension required, popup-based
LOBSTR Browser extension Large user base
Rabet Browser extension Lightweight, open-source
Custom Your bridge / custody / HSM Extend WalletAdapter — see docs above

Albedo Wallet

Albedo is a web-based wallet that doesn't require browser extensions. It opens a popup window for authentication and transaction signing, making it ideal for users who prefer not to install extensions.

Key Features:

  • No browser extension required
  • Works in any modern browser
  • Popup-based authentication
  • Supports message signing for SIWS (Sign In With Stellar)
  • Network switching support

Installation:

npm install @albedo-link/intent

Basic Usage:

import { AlbedoAdapter } from '@tikka/sdk';
import { Networks } from '@stellar/stellar-sdk';

// Create adapter with network configuration
const adapter = new AlbedoAdapter({
  networkPassphrase: Networks.TESTNET
});

// Check availability (always true in browser)
if (adapter.isAvailable()) {
  // Get public key (opens Albedo popup)
  const publicKey = await adapter.getPublicKey();
  console.log('User public key:', publicKey);
  
  // Sign transaction (opens Albedo popup)
  const { signedXdr } = await adapter.signTransaction(xdr, {
    networkPassphrase: Networks.TESTNET
  });
  
  // Sign message for authentication
  const signature = await adapter.signMessage('Sign in to MyApp');
}

Advanced Usage:

// Specify which account should sign (for multi-account users)
const { signedXdr } = await adapter.signTransaction(xdr, {
  networkPassphrase: Networks.TESTNET,
  accountToSign: 'GBQW4KLMRXIMSDWBEWX4AWQKWYW7R3E7SFPSHTUDTFFT22NNUC6COL72'
});

// Get configured network
const network = await adapter.getNetwork();
console.log('Network:', network);

Error Handling:

import { TikkaSdkError, TikkaSdkErrorCode } from '@tikka/sdk';

try {
  const publicKey = await adapter.getPublicKey();
} catch (err) {
  if (err instanceof TikkaSdkError) {
    switch (err.code) {
      case TikkaSdkErrorCode.UserRejected:
        console.log('User cancelled the request');
        break;
      case TikkaSdkErrorCode.WalletNotInstalled:
        console.log('@albedo-link/intent package not installed');
        break;
      default:
        console.log('Unknown error:', err.message);
    }
  }
}

Complete Example: See examples/albedo-wallet.ts for a full working example.

Rabet Wallet

Rabet is a lightweight, open-source browser extension wallet for Stellar. It provides a simple and secure way to manage Stellar assets and interact with dApps.

Key Features:

  • Lightweight browser extension
  • Open-source and community-driven
  • Simple and intuitive interface
  • Supports transaction signing
  • Network switching support

Installation: Rabet doesn't require an npm package - it uses the global window.rabet object injected by the browser extension.

Basic Usage:

import { RabetAdapter } from '@tikka/sdk';
import { Networks } from '@stellar/stellar-sdk';

// Create adapter with network configuration
const adapter = new RabetAdapter({
  networkPassphrase: Networks.TESTNET
});

// Check if Rabet extension is installed
if (adapter.isAvailable()) {
  // Get public key (prompts user to connect)
  const publicKey = await adapter.getPublicKey();
  console.log('User public key:', publicKey);
  
  // Sign transaction
  const { signedXdr } = await adapter.signTransaction(xdr, {
    networkPassphrase: Networks.TESTNET
  });
}

Advanced Usage:

// Use different network
const { signedXdr } = await adapter.signTransaction(xdr, {
  networkPassphrase: Networks.PUBLIC
});

// Get configured network
const network = await adapter.getNetwork();
console.log('Network:', network);

Error Handling:

import { TikkaSdkError, TikkaSdkErrorCode } from '@tikka/sdk';

try {
  const publicKey = await adapter.getPublicKey();
} catch (err) {
  if (err instanceof TikkaSdkError) {
    switch (err.code) {
      case TikkaSdkErrorCode.UserRejected:
        console.log('User cancelled the request');
        break;
      case TikkaSdkErrorCode.WalletNotInstalled:
        console.log('Rabet extension not installed. Get it at https://rabet.io');
        break;
      default:
        console.log('Unknown error:', err.message);
    }
  }
}

Important Notes:

  • Rabet requires a network passphrase for transaction signing
  • Message signing is not supported by Rabet
  • Users must have the Rabet browser extension installed from rabet.io

General Wallet Usage

import { FreighterAdapter, XBullAdapter, AlbedoAdapter, LobstrAdapter, RabetAdapter } from '@tikka/sdk';

// Create adapter instance
const adapter = new FreighterAdapter({
  networkPassphrase: Networks.TESTNET
});

// Check availability
if (adapter.isAvailable()) {
  // Get public key
  const publicKey = await adapter.getPublicKey();
  
  // Sign transaction
  const { signedXdr } = await adapter.signTransaction(xdr, {
    networkPassphrase: Networks.TESTNET
  });
}

Custom Wallet Adapter

Extend WalletAdapter to plug in hardware signers, custody APIs, or any other Stellar wallet:

import {
  WalletAdapter,
  WalletName,
  SignTransactionResult,
  WalletCapabilities,
  TikkaSdkError,
  TikkaSdkErrorCode,
} from '@tikka/sdk';

class MyWalletAdapter extends WalletAdapter {
  readonly name = WalletName.Custom; // or any string id

  isAvailable(): boolean {
    return typeof (globalThis as any).myWallet !== 'undefined';
  }

  async getPublicKey(): Promise<string> {
    if (!this.isAvailable()) {
      throw new TikkaSdkError(
        TikkaSdkErrorCode.WalletNotInstalled,
        'MyWallet is not installed',
      );
    }
    return (globalThis as any).myWallet.getPublicKey();
  }

  async signTransaction(
    xdr: string,
    opts?: { networkPassphrase?: string; accountToSign?: string },
  ): Promise<SignTransactionResult> {
    const networkPassphrase =
      opts?.networkPassphrase ?? this.options.networkPassphrase;
    const signedXdr = await (globalThis as any).myWallet.signTx(xdr, {
      networkPassphrase,
      accountToSign: opts?.accountToSign,
    });
    return { signedXdr };
  }

  getCapabilities(): WalletCapabilities {
    return {
      supportsGetPublicKey: true,
      supportsSignTransaction: true,
      supportsSignMessage: false,
      supportsGetNetwork: false,
    };
  }
}

Full contract (methods, error codes, signing flow): WALLET_ADAPTER.md.
Runnable demo: examples/custom-wallet.ts (npm run example:custom-wallet).

Selecting Adapters

You can select adapters by name or auto-detect available wallets:

const adapters = {
  freighter: new FreighterAdapter(),
  xbull: new XBullAdapter(),
  albedo: new AlbedoAdapter(),
  lobstr: new LobstrAdapter(),
};

// Check which are available
const availableAdapters = Object.entries(adapters)
  .filter(([, adapter]) => adapter.isAvailable())
  .map(([name]) => name);

// Auto-select first available
const selectedAdapter = availableAdapters[0] ? adapters[availableAdapters[0]] : null;

React Native Notes

  • Provide a fetch implementation explicitly when needed:
    • new RpcService(networkConfig, { endpoint, fetchClient: fetch })
  • Wallet adapters that rely on browser extension globals are not available in React Native; use app-native signing or the mock adapter for local prototyping.
  • Ensure required polyfills are present in your RN app entrypoint (buffer, crypto, and stream when your environment requires them).