# @swing.xyz/wallets

Multi-chain wallet connection manager.

## Installation

Install the package using your favorite package manager.

```bash
yarn add @swing.xyz/wallets

# OR

npm i @swing.xyz/wallets
```

## Setup

The `@swing.xyz/wallets` package is designed to work with the [@swing.xyz/sdk](https://www.npmjs.com/package/@swing.xyz/sdk) and [@swing.xyz/ui](https://www.npmjs.com/package/@swing.xyz/ui) packages.

### Use with @swing.xyz/sdk

To use with [@swing.xyz/sdk](https://www.npmjs.com/package/@swing.xyz/sdk), you should provide the `swingSDK` instance to the `WalletProvider`.

```tsx
import { SwingSDK } from '@swing.xyz/sdk';
import { WalletProvider } from '@swing.xyz/wallets/provider';

const swingSDK = new SwingSDK({
  // Include your SwingSDK config
});

export default function App() {
  return <WalletProvider swingSDK={swingSDK}>{/* The rest of your app code */}</WalletProvider>;
}
```

### Use with @swing.xyz/ui

To use with [@swing.xyz/ui](https://www.npmjs.com/package/@swing.xyz/ui), you should wrap the `WalletProvider` in a `SwingSdkProvider`. This ensures that the same `swingSDK` instance is available to the `WalletProvider`.

```tsx
import { Swap, SwingSdkProvider, useSwingSdk } from '@swing.xyz/ui';
import { WalletProvider } from '@swing.xyz/wallets/provider';

export default function App() {
  return (
    <SwingSdkProvider>
      <WalletProviderWrapper />
    </SwingSdkProvider>
  );
}

function WalletProviderWrapper() {
  const swingSDK = useSwingSdk();

  return (
    <WalletProvider swingSDK={swingSDK}>
      {/* The rest of your app code, such as the one of the @swing.xyz/ui widgets */}
      <Swap />
    </WalletProvider>
  );
}
```

### Use with Wagmi

The `@swing.xyz/wallets` package is built on top of [Wagmi](https://wagmi.sh/). It will automatically inherit any connectors you have configured in your Wagmi config.

To use with Wagmi, you need to wrap your `WagmiProvider` around the `WalletProvider`.

```tsx
import { WagmiProvider } from 'wagmi';
import { WalletProvider } from '@swing.xyz/wallets/provider';

export default function App() {
  return (
    <WagmiProvider config={wagmiConfig}>
      <WalletProvider swingSDK={swingSDK}>{/* The rest of your app code */}</WalletProvider>
    </WagmiProvider>
  );
}
```

## Connectors

Connectors are a small abstraction layer over different wallet providers.

You can add your own custom connectors by implementing the `WalletConnector` interface.

```ts
// import { type WalletConnector } from '@swing.xyz/wallets/connectors';
interface WalletConnector {
  /**
   * Unquie identifier for the wallet
   */
  id: string;

  /**
   * Wallet name
   */
  name: string;

  /**
   * Wallet logo
   */
  logo: string;

  /**
   * Type of the connector such as injected, walletconnect, etc.
   */
  type: string;

  /**
   * Protocols supported by the wallet such as evm, ibc, solana, bitcoin, etc
   */
  protocols: ProtocolType[];

  /**
   * Get the provider for the connector.
   */
  getProvider: (chain?: Chain) => Promise<WalletProvider | undefined> | WalletProvider | undefined;

  /**
   * Connect to the wallet. If a chain is provided, the wallet will switch to the chain.
   */
  connect: (chain?: Chain) => Promise<{ accounts: string[]; chainId: string | number }>;

  /**
   * Disconnect from the wallet
   */
  disconnect?: () => Promise<void> | void;

  /**
   * Switch the current chain of the wallet
   */
  switchChain?: (chain: Chain) => Promise<string[]> | Promise<void>;
}
```

### getConnectors()

The `getConnectors` function returns an array of all the connectors.

```ts
import { getConnectors } from '@swing.xyz/wallets/connectors';

const connectors = getConnectors();

/**
 * [
 *  {
 *    id: 'metamask',
 *    name: 'MetaMask',
 *    logo: 'https://metamask.io/favicon.ico',
 *    type: 'injected',
 *    protocols: ['evm'],
 *  }
 * ]
 **/
```

### getConnector()

The `getConnector` function returns a connector by ID.

```ts
import { getConnector } from '@swing.xyz/wallets/connectors';

const connector = getConnector('metamask');

/**
 *  {
 *    id: 'metamask',
 *    name: 'MetaMask',
 *    logo: 'https://metamask.io/favicon.ico',
 *    type: 'injected',
 *    protocols: ['evm'],
 *  }
 **/
```

### Custom Connector Example

```tsx
import type { WalletConnector } from '@swing.xyz/wallets/connectors';
import { WalletProvider } from '@swing.xyz/wallets/provider';

const customConnector: WalletConnector = {
  id: 'custom',
  name: 'Custom',
  logo: 'custom-logo.png',
  type: 'injected',
  protocols: ['evm'], // Include the protocols supported by your custom wallet
  getProvider: (chain) => window.ethereum,
  connect: async (chain) => {
    // Connect to the custom wallet
  },
  disconnect: async () => {
    // (Optional) Disconnect from the custom wallet
  },
  switchChain: async (chain) => {
    // (Optional) Switch the current chain of the custom wallet
  },
};

export default function App() {
  return <WalletProvider connectors={[customConnector]}>{/* The rest of your app code */}</WalletProvider>;
}
```

## Connections

Connections are a representation of a wallet's connection to a chain.

```ts
// import { type WalletConnection } from '@swing.xyz/wallets/connections';
interface WalletConnection {
  connector: WalletConnector;
  chain: Chain;
  accounts: string[];
}
```

### connect()

The `connect` function prompts the user to connect their wallet. If a chain is provided, the wallet will switch to the chain.

```ts
import { connect } from '@swing.xyz/wallets/connections';

// Connect using the wallet's current chain
const walletAddress = await connect({ connector });

// Connect to a specific chain using the chain's slug
const walletAddress = await connect({ connector, chainId: 'ethereum' });

// Connect to a specific chain using the chain's ID
const walletAddress = await connect({ connector, chainId: 1 });
```

### disconnect()

The `disconnect` function removes a wallet connection.

```ts
import { disconnect } from '@swing.xyz/wallets/connections';

await disconnect({ connector });
```

### getConnections()

The `getConnections` function returns an array of all the connections.

```ts
import { getConnections } from '@swing.xyz/wallets/connections';

const connections = getConnections();

/**
 * [
 *  {
 *    accounts: ['0x123...', '0x456...'],
 *    chain: {
 *      id: 1,
 *      slug: 'ethereum',
 *      ...
 *    },
 *    connector: {
 *      id: 'metamask',
 *      ...,
 *    }
 *  }
 * ]
 **/
```

### getConnection()

The `getConnection` function returns a connection by wallet address.

```ts
import { getConnection } from '@swing.xyz/wallets/connections';

const connection = getConnection('0x123...');

/**
 *  {
 *    accounts: ['0x123...', '0x456...'],
 *    chain: {
 *      id: 1,
 *      slug: 'ethereum',
 *      ...
 *    },
 *    connector: {
 *      id: 'metamask',
 *      ...,
 *    }
 *  }
 ** /
```

### getConnectionForChain()

The `getConnectionForChain` function returns a connection for a given chain.

```ts
import { getConnectionForChain } from '@swing.xyz/wallets/connections';

const connection = getConnectionForChain('ethereum');

/**
 *  {
 *    accounts: ['0x123...', '0x456...'],
 *    chain: {
 *      id: 1,
 *      slug: 'ethereum',
 *      ...
 *    },
 *    connector: {
 *      id: 'metamask',
 *      ...,
 *    }
 *  }
 **/
```

## Hooks

### useConnect()

The `useConnect` hook provides the [connect()](#connect) function to connect to a wallet. See the [connect()](#connect) function for more information.

```tsx
import { useConnect } from '@swing.xyz/wallets/hooks/useConnect';

const connect = useConnect();

// Connect using the wallet's current chain
const walletAddress = await connect({ connector });

// Connect to a specific chain using the chain's slug
const walletAddress = await connect({ connector, chainId: 'ethereum' });

// Connect to a specific chain using the chain's ID
const walletAddress = await connect({ connector, chainId: 1 });
```

### useConnection()

The `useConnection` hook provides a function to get the current connection by wallet address.

```tsx
import { useConnection } from '@swing.xyz/wallets/hooks/useConnection';

const connection = useConnection('0x123...');
```

### useConnections()

The `useConnections` hook provides a function to get all the connections.

```tsx
import { useConnections } from '@swing.xyz/wallets/hooks/useConnections';

const connections = useConnections();
```

### useConnector()

The `useConnector` hook provides a function to get a connector by ID.

```tsx
import { useConnector } from '@swing.xyz/wallets/hooks/useConnector';

const connector = useConnector('metamask');
```

### useConnectors()

The `useConnectors` hook provides a function to get all the connectors.

```tsx
import { useConnectors } from '@swing.xyz/wallets/hooks/useConnectors';

const connectors = useConnectors();
```

## Default Wallets

The following wallets are supported by default:

- MetaMask
- Coinbase Wallet
- WalletConnect
- Rabby
- Rainbow
- Trust Wallet
- Safe
- Keplr
- Phantom
- TonConnect
- MultiversX

You can also add your own [custom connectors](#custom-connector-example) to the `WalletProvider`, and they will be available to all of the connector helpers such as the [useConnectors()](#useconnectors) hook and [getConnectors()](#getconnectors) functions.

If you would like your wallet to be added to our default wallet list, please open a PR adding your wallet to the `src/connectors` folder.
