> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Spark Wallet Integration Guide

> Step-by-step guide for integrating your Spark wallet with Dynamic

> [card] Recommended: JavaScript SDK with React Hooks
>
> For new React apps, we recommend the JavaScript SDK with React Hooks (`@dynamic-labs-sdk/react-hooks`) instead of the legacy React SDK documented here. The JS SDK comes with many benefits such as a much smaller bundle size and other optimizations. Use the [React quickstart (JavaScript SDK)](https://docs.dynamic.xyz/docs/javascript/reference/react-quickstart.md) to get started.

This guide walks you through integrating your Spark wallet with the Dynamic SDK. By implementing the `ISparkProvider` interface, your wallet will be compatible with Dynamic's Spark network support.

## Overview

To integrate your Spark wallet with Dynamic, you'll need to follow these steps:

For general information about custom wallet connectors, see our [Integrate your Wallet](https://docs.dynamic.xyz/docs/external-wallets/supported-wallets.md#custom-wallet-connectors) guide.

**1. Implement the ISparkProvider Interface**

Your wallet must implement the `ISparkProvider` interface. This interface defines all the methods Dynamic expects from a Spark wallet.

### Required Methods

* `connect()` - Establishes connection and returns the public key
* `disconnect()` - Disconnects from the wallet
* `getAddress()` - Retrieves the current wallet address
* `signMessage()` - Signs messages for authentication
* `signMessageWithTaproot()` - Signs messages using Taproot protocol
* `transferBitcoin()` - Sends Bitcoin to other Spark addresses
* `transferTokens()` - Transfers tokens between Spark addresses
* `request()` - Handles generic RPC requests

### Example Implementation

```typescript title="Your Wallet Provider Implementation" theme={"system"}
// This is what your wallet should implement
class YourWalletProvider implements ISparkProvider {
  async connect(): Promise<string> {
    // Your wallet's connection logic
    const publicKey = await this.connectToWallet();
    this.isConnected = true;
    return publicKey;
  }

  async disconnect(): Promise<void> {
    await this.disconnectFromWallet();
    this.isConnected = false;
  }

  async getAddress(): Promise<string> {
    return await this.getWalletAddress();
  }

  async signMessage(message: string | SparkSignMessageRequest): Promise<SparkSignatureResult> {
    const messageText = typeof message === 'string' ? message : message.message;
    const isTaproot = typeof message === 'object' ? message.isTaproot : false;
    
    if (isTaproot) {
      const signature = await this.signMessageWithTaproot(messageText);
      return { signature };
    } else {
      const signature = await this.signMessageRegular(messageText);
      return { signature };
    }
  }

  async signMessageWithTaproot(message: string): Promise<SparkSignatureResult> {
    const signature = await this.signMessageWithTaproot(message);
    return { signature };
  }

  async transferBitcoin(params: {
    receiverSparkAddress: string;
    amountSats: bigint;
    isTaproot?: boolean;
  }): Promise<string> {
    return await this.sendBitcoin({
      to: params.receiverSparkAddress,
      amount: params.amountSats,
      useTaproot: params.isTaproot || false
    });
  }

  async transferTokens(params: {
    tokenPublicKey: string;
    receiverSparkAddress: string;
    tokenAmount: number;
    isTaproot?: boolean;
  }): Promise<string> {
    return await this.sendToken({
      tokenPublicKey: params.tokenPublicKey,
      to: params.receiverSparkAddress,
      amount: params.tokenAmount,
      useTaproot: params.isTaproot || false
    });
  }

  async request(method: string, params?: unknown): Promise<unknown> {
    return await this.handleRequest(method, params);
  }

  // Your wallet's internal methods
  private async connectToWallet(): Promise<string> { /* ... */ }
  private async disconnectFromWallet(): Promise<void> { /* ... */ }
  private async getWalletAddress(): Promise<string> { /* ... */ }
  private async signMessageRegular(message: string): Promise<string> { /* ... */ }
  private async sendBitcoin(params: any): Promise<string> { /* ... */ }
  private async sendToken(params: any): Promise<string> { /* ... */ }
  private async handleRequest(method: string, params?: unknown): Promise<unknown> { /* ... */ }
}
```

**2. Create a Custom Wallet Connector**

Follow the process outlined in our [Custom Wallet Connectors](https://docs.dynamic.xyz/docs/external-wallets/supported-wallets.md#custom-wallet-connectors) guide:

1. Visit the [Dynamic Public Wallet Connectors repository](https://github.com/dynamic-labs/public-wallet-connectors)
2. Follow the guidelines in the [CONTRIBUTING.md](https://github.com/dynamic-labs/public-wallet-connectors/blob/main/CONTRIBUTING.md) file
3. Create your connector package following the established patterns

### Connector Structure

Your connector should extend `SparkWalletConnector` and implement the required overrides:

```typescript title="YourSparkConnector Implementation" theme={"system"}
import { SparkWalletConnector, type ISparkProvider } from '@dynamic-labs/spark';

export class YourSparkConnector extends SparkWalletConnector {
  /**
   * The name of the wallet connector
   * @override Required override from the base connector class
   */
  override name = 'Your Wallet Name';

  /**
   * Unique identifier for your wallet
   * @override Required override from the base connector class
   */
  override overrideKey = 'yourwallet';

  /**
   * Whether the wallet can connect via custodial service
   * @override Optional override
   */
  override canConnectViaCustodialService = false;

  /**
   * The constructor for the connector, with the relevant metadata
   * @param props The options for the connector
   */
  constructor(props: any) {
    super({
      ...props,
      metadata: {
        id: 'yourwallet',
        name: 'Your Wallet Name',
        icon: 'https://your-wallet.com/icon.png',
      },
    });
  }

  /**
   * Returns the wallet provider instance
   * @override Required override from the base connector class
   */
  public override getProvider(): ISparkProvider | undefined {
    return window.yourWalletProvider;
  }
}
```

**3. Test Your Integration**

Before submitting, thoroughly test your integration:

1. **Connection Testing** - Verify wallet connects and disconnects properly
2. **Address Retrieval** - Ensure addresses are returned correctly
3. **Message Signing** - Test both regular and Taproot message signing
4. **Transaction Testing** - Test Bitcoin and token transfers
5. **Error Handling** - Verify proper error handling for all methods

**4. Submit Your Connector**

Once your implementation is complete and tested:

1. Submit your connector following the [Custom Wallet Connectors](https://docs.dynamic.xyz/docs/external-wallets/supported-wallets.md#custom-wallet-connectors) process
2. Fill out the submission form to get allowlisted
3. Our team will review and integrate your connector

## Supported Networks

| Network | Chain ID | Description | Block Explorer |
| - | - | - | - |
| **Mainnet** | 301 | Production network | [mempool.space](https://mempool.space) |

> **Note**: Currently only mainnet is supported. Testnet, signet, and regtest support may be added in future versions.

## Reference: ISparkProvider Interface

The complete `ISparkProvider` interface specification:

```typescript title="ISparkProvider Interface" theme={"system"}
interface ISparkProvider {
  /** Whether the wallet is currently connected */
  isConnected: boolean;

  /** The current network chain ID (e.g., '301' for mainnet) */
  chainId?: string;

  /** The current network name (e.g., 'mainnet', 'testnet') */
  network?: string;

  /**
   * Establishes a connection to the wallet
   * @returns Promise resolving to the public key (string)
   */
  connect(): Promise<string>;

  /**
   * Disconnects from the wallet
   * @returns Promise that resolves when disconnected
   */
  disconnect(): Promise<void>;

  /**
   * Retrieves the current wallet address
   * @returns Promise resolving to address information
   */
  getAddress(): Promise<SparkAddressResult>;

  /**
   * Signs a message for authentication
   * @param message - Message to sign or signing request object
   * @returns Promise resolving to signature result
   */
  signMessage(
    message: string | SparkSignMessageRequest,
  ): Promise<SparkSignatureResult>;

  /**
   * Signs a message using Taproot protocol
   * @param message - Message to sign
   * @returns Promise resolving to signature result
   */
  signMessageWithTaproot(message: string): Promise<SparkSignatureResult>;

  /**
   * Transfers Bitcoin to another Spark address
   * @param params - Transfer parameters
   * @param params.receiverSparkAddress - The recipient's Spark address
   * @param params.amountSats - Amount to transfer in satoshis
   * @param params.isTaproot - Whether to use Taproot (defaults to false)
   * @returns Promise resolving to transaction hash
   */
  transferBitcoin(params: {
    receiverSparkAddress: string;
    amountSats: bigint;
    isTaproot?: boolean;
  }): Promise<string>;

  /**
   * Transfers tokens to another Spark address
   * @param params - Transfer parameters
   * @param params.tokenPublicKey - The token's public key
   * @param params.receiverSparkAddress - The recipient's Spark address
   * @param params.tokenAmount - Amount of tokens to transfer
   * @param params.isTaproot - Whether to use Taproot (defaults to false)
   * @returns Promise resolving to transaction hash
   */
  transferTokens(params: {
    tokenPublicKey: string;
    receiverSparkAddress: string;
    tokenAmount: number;
    isTaproot?: boolean;
  }): Promise<string>;

  /**
   * Generic RPC method for custom requests
   * @param method - The RPC method name
   * @param params - Optional parameters for the method
   * @returns Promise resolving to the method result
   */
  request(method: string, params?: unknown): Promise<unknown>;

  // Allow any additional properties for flexibility
  /** Additional properties that providers may implement */
  [key: string]: unknown;
}
```

## Reference: Type Definitions

```typescript title="Spark Type Definitions" theme={"system"}
/**
 * Result from address retrieval, supporting different formats
 */
type SparkAddressResult = string;

/**
 * Message signing request, supporting both simple and advanced options
 */
type SparkSignMessageRequest =
  | {
      message: string;
      isTaproot?: boolean; // defaults to false
    }
  | string;

/**
 * Result from message signing, supporting different return formats
 */
type SparkSignatureResult =
  | {
      signature: string;
    }
  | string;
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.