# @dynamic-labs/spark

A Spark wallet connector package for the Dynamic SDK that enables seamless integration with Spark network wallets.

## Features

- **Magic Eden Wallet Support** - Full integration with Magic Eden's Spark wallet
- **Flexible Provider Interface** - Easy to add support for additional Spark wallets
- **Bitcoin Transfers** - Send Bitcoin to Spark addresses with optional Taproot support
- **Token Transfers** - Transfer tokens between Spark addresses
- **Message Signing** - Sign messages for authentication with optional Taproot support
- **Mainnet Support** - Currently supports Spark mainnet (chain ID 301)

## Installation

```bash
npm install @dynamic-labs/spark
```

## 🔌 Supported Wallets

### Magic Eden

The package includes full support for Magic Eden's Spark wallet implementation, which provides:

- **Connection Management** - Seamless wallet connection and disconnection
- **Address Retrieval** - Get current wallet address
- **Message Signing** - Sign messages for authentication with optional Taproot support
- **Bitcoin Transfers** - Send Bitcoin to other Spark addresses
- **Token Transfers** - Transfer tokens between Spark addresses

## Architecture

### Base Connector Class

The `SparkWalletConnector` provides a robust foundation for all Spark wallet integrations:

- **Abstract Implementation** - Handles common wallet operations
- **Error Handling** - Comprehensive error handling and logging
- **Mainnet Focus** - Currently optimized for mainnet usage

### Provider Interface

All Spark wallet providers must implement the `ISparkProvider` interface:

```typescript
interface ISparkProvider {
  isConnected: boolean;
  chainId?: string;
  network?: string;

  connect(): Promise<SparkConnectionResult | string>;
  disconnect(): Promise<void>;
  getAddress(): Promise<SparkAddressResult>;
  signMessage(
    message: string | SparkSignMessageRequest,
  ): Promise<SparkSignatureResult>;
  signMessageWithTaproot(message: string): Promise<SparkSignatureResult>;
  transferBitcoin(params: {
    receiverSparkAddress: string;
    amountSats: bigint;
    isTaproot?: boolean;
  }): Promise<string>;
  transferTokens(params: {
    tokenPublicKey: string;
    receiverSparkAddress: string;
    tokenAmount: number;
    isTaproot?: boolean;
  }): Promise<string>;
  request(method: string, params?: unknown): Promise<unknown>;

  [key: string]: unknown; // Extensible for additional properties
}
```

## 🌐 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.

## 📖 Usage

### Basic Integration

```typescript
import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core';
import { SparkWalletConnectors } from '@dynamic-labs/spark';

function App() {
  return (
    <DynamicContextProvider
      settings={{
        environmentId: 'your-environment-id',
        walletConnectors: [SparkWalletConnectors()],
      }}
    >
      {/* Your app content */}
    </DynamicContextProvider>
  );
}
```

### Using the SparkWallet

```typescript
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
import { SparkWallet } from '@dynamic-labs/spark';

function MyComponent() {
  const { primaryWallet } = useDynamicContext();

  const handleSendBitcoin = async () => {
    if (primaryWallet instanceof SparkWallet) {
      // Send Bitcoin
      const txHash = await primaryWallet.sendBalance({
        amount: '100000', // 100,000 satoshis
        toAddress: 'sp1recipient123456789abcdef',
        isTaproot: false,
      });

      // Or use the direct transferBitcoin method
      const txHash2 = await primaryWallet.transferBitcoin({
        amount: '50000',
        toAddress: 'sp1recipient123456789abcdef',
        isTaproot: true,
      });
    }
  };

  const handleSendTokens = async () => {
    if (primaryWallet instanceof SparkWallet) {
      const txHash = await primaryWallet.transferTokens({
        tokenPublicKey: 'token123',
        receiverSparkAddress: 'sp1recipient123456789abcdef',
        tokenAmount: 1000,
        isTaproot: false,
      });
    }
  };

  return (
    <div>
      <button onClick={handleSendBitcoin}>Send Bitcoin</button>
      <button onClick={handleSendTokens}>Send Tokens</button>
    </div>
  );
}
```

### Custom Connector Implementation

To add support for a new Spark wallet:

```typescript
import { SparkWalletConnector } from '@dynamic-labs/spark';

export class YourSparkConnector extends SparkWalletConnector {
  override name = 'Your Spark Wallet';
  override overrideKey = 'yourspark';

  public override getProvider(): ISparkProvider | undefined {
    return window.yourProvider;
  }
}
```

### Type Checking

Use the `isSparkWallet` type guard to safely work with Spark wallets:

```typescript
import { isSparkWallet } from '@dynamic-labs/spark';

function handleWallet(wallet: Wallet) {
  if (isSparkWallet(wallet)) {
    // TypeScript now knows this is a SparkWallet
    wallet.transferBitcoin({
      amount: '100000',
      toAddress: 'sp1recipient123456789abcdef',
    });
  }
}
```

## 🧪 Testing

### Run Tests

```bash
npx nx test spark
```

### Build Package

```bash
npx nx build spark
```

### Test in Demo App

1. Start the demo app: `npm run start`
2. Navigate to the Spark wallet section
3. Test connection, address retrieval, and message signing

## 📚 API Reference

### Core Exports

- `SparkWalletConnectors()` - Factory function returning all available connectors
- `SparkWalletConnector` - Base class for custom implementations
- `SparkWallet` - Wallet class with Bitcoin and token transfer methods
- `ISparkProvider` - Interface for wallet providers
- `isSparkWallet` - Type guard for Spark wallets

### SparkWallet Methods

- `sendBalance(params)` - Send Bitcoin (alias for transferBitcoin)
- `transferBitcoin(params)` - Send Bitcoin to a Spark address
- `transferTokens(params)` - Send tokens to a Spark address

### Type Definitions

- `SparkConnectionResult` - Result from wallet connection
- `SparkAddressResult` - Result from address retrieval
- `SparkSignMessageRequest` - Message signing request options
- `SparkSignatureResult` - Result from message signing

## 🔗 Related Packages

- **@dynamic-labs/sdk-react-core** - React SDK core functionality
- **@dynamic-labs/wallet-connector-core** - Base wallet connector classes
- **@dynamic-labs/types** - Common type definitions

## 🤝 Contributing

We welcome contributions! Please see our [contributing guidelines](https://github.com/dynamic-labs/dynamic-sdk/blob/main/CONTRIBUTING.md) for details.

### Development Setup

1. Clone the repository
2. Install dependencies: `npm install`
3. Run tests: `npx nx test spark`
4. Build package: `npx nx build spark`

### Adding New Wallets

1. Create a new connector class extending `SparkWalletConnector`
2. Implement the `getProvider()` method
3. Add comprehensive tests
4. Update the `SparkWalletConnectors()` factory function

## 📄 License

This package is part of the Dynamic SDK and follows the same licensing terms. See [LICENSE](https://github.com/dynamic-labs/dynamic-sdk/blob/main/LICENSE) for details.

## 🆘 Support

- **Documentation**: [docs.dynamic.xyz](https://docs.dynamic.xyz)
- **GitHub Issues**: [Report bugs or request features](https://github.com/dynamic-labs/dynamic-sdk/issues)
- **Discord**: [Join our community](https://discord.gg/dynamic)

---

**Built with ❤️ by the Dynamic Labs team**
