# Quickstart with `Sign in` button

This quick-start shows the minimum code required to add `Sign in with {yourbrand}` to any React app using the Ecosystem SDK.

## 1. Create a new React app

If you’re starting fresh, create a new React app:

```bash
npx create-react-app . --template typescript
```

## 2. Install the SDK

```bash
npm install @rapidfire/id
```

:::warning
To make these instructions concrete, we have created a sample global wallet called **Rapidfire ID**. To interact with it, you can find its SDK in the NPM package directory: [@rapidfire/id](https://www.npmjs.com/package/@rapidfire/id).

You can check out the GitHub [repository for Rapidfire Wallet](https://github.com/openfort-xyz/ecosystem-sample) to learn how to create your own wallet.
:::

<details>
  <summary style={{ margin: '12px 0' }}>Check the recommended project structure for this example project</summary>

  ```txt
  my-app/
    .env.local
    package.json
    tsconfig.json
    src/
      App.tsx
      index.tsx
      components/
        wallet/
          CreateWalletButton.tsx
          WalletLogo.tsx
      lib/
        provider.ts
        sdk.ts
  ```

  <p style={{ margin: '16px 0' }}>If starting with `create-react-app`, create the folders:</p>

  ```bash
  mkdir -p src/lib/
  mkdir -p src/components/wallet/
  ```
</details>

## 3. Initialize the SDK, Provider, and Components

You'll handle all wallet interactions through the standard `EIP-1193` provider interface, giving you complete flexibility in implementing wallet creation, connection flows, and transaction handling. While this approach requires more custom development work, it's ideal for applications that need specialized wallet interactions or want to minimize dependencies.

:::code-group

```ts [src/lib/sdk.ts]
import EcosystemWallet from '@rapidfire/id';

// Initialize the SDK with required parameters
export const sdk = new EcosystemWallet({
  appChainIds: [80002],
  appLogoUrl: 'https://a.rgbimg.com/users/b/ba/barunpatro/600/mf6B5Gq.jpg',
  appName: 'Example App',
});
```

```ts [src/lib/provider.ts]
import { sdk } from './sdk';

// Configure the provider with chain and policy
type EIP1193Provider = {
  request: (args: { method: string; params?: unknown[] }) => Promise<any>;
};

export const provider = (sdk as any).getEthereumProvider({
  policy: process.env.NEXT_PUBLIC_POLICY_ID
}) as EIP1193Provider;
```

:::

## 4. Implement the `Sign in` button

Create the wallet components that use the configured provider.

::::code-group

```tsx [src/components/wallet/WalletLogo.tsx]
import React from 'react';

const defaultContainerStyles = {
  paddingTop: 2,
  display: 'flex',
  alignItems: 'center',
};

export function WalletLogo({
  size = 24,
  containerStyles = defaultContainerStyles,
}) {
  return (
    <div style={containerStyles}>
      <svg
        width={size}
        height={size}
        viewBox="0 0 24 24"
        fill="none"
        xmlns="http://www.w3.org/2000/svg"
      >
        <rect
          x="2"
          y="4"
          width="20"
          height="16"
          rx="3"
          stroke="currentColor"
          strokeWidth="2"
        />
        <path
          d="M16 12C16 10.8954 16.8954 10 18 10H22V14H18C16.8954 14 16 13.1046 16 12Z"
          fill="currentColor"
        />
        <circle cx="12" cy="12" r="2" fill="currentColor" />
      </svg>
    </div>
  );
}
```

```tsx [src/components/wallet/CreateWalletButton.tsx]
import React, { useCallback } from 'react';
import { WalletLogo } from './WalletLogo';
import { provider } from '../../lib/provider';

const buttonStyles = {
  background: 'linear-gradient(135deg, #2D3436 0%, #000000 100%)',
  border: '1px solid rgba(255, 255, 255, 0.1)',
  boxSizing: 'border-box' as const,
  display: 'flex',
  alignItems: 'center',
  gap: '12px',
  width: 'auto',
  minWidth: '200px',
  fontFamily: 'Inter, system-ui, sans-serif',
  fontWeight: '600',
  fontSize: '16px',
  color: '#FFFFFF',
  padding: '12px 20px',
  borderRadius: '12px',
  cursor: 'pointer',
  transition: 'all 0.2s ease-in-out',
  boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
  ':hover': {
    transform: 'translateY(-1px)',
    boxShadow: '0 6px 8px -1px rgba(0, 0, 0, 0.1), 0 4px 6px -1px rgba(0, 0, 0, 0.06)',
  },
};

type CreateWalletButtonProps = {
  handleSuccess: (address: string) => void;
  handleError: (error: unknown) => void;
};

export function CreateWalletButton({ handleSuccess, handleError }: CreateWalletButtonProps) {
  const createWallet = useCallback(async () => {
    try {
      const [address] = await provider.request({
        method: 'eth_requestAccounts',
      });
      handleSuccess(address);
    } catch (error) {
      handleError(error);
    }
  }, [handleSuccess, handleError]);

  return (
    <button style={buttonStyles} onClick={createWallet}>
      <WalletLogo />
      Create Wallet
    </button>
  );
}
```

::::

## 5. Set up the main app

Configure your main App component and environment variables.

:::tip
Make sure to set up your `NEXT_PUBLIC_POLICY_ID` in your environment variables to sponsor transactions.
:::

:::code-group

```tsx [src/App.tsx]
import React, { useState } from 'react';
import { CreateWalletButton } from './components/wallet/CreateWalletButton';

export default function App() {
  const [address, setAddress] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  return (
    <div style={{ display: 'grid', placeItems: 'center', minHeight: '100vh' }}>
      <div style={{ display: 'grid', gap: 16, textAlign: 'center' }}>
        <h1>Sign in with your Global Wallet</h1>
        {address ? (
          <div>
            <p>Signed in as</p>
            <code>{address}</code>
          </div>
        ) : (
          <CreateWalletButton
            handleSuccess={(addr: string) => {
              setError(null);
              setAddress(addr);
            }}
            handleError={(e: unknown) => {
              const message = e instanceof Error ? e.message : String(e);
              setError(message);
            }}
          />
        )}
        {error && <p style={{ color: 'tomato' }}>{error}</p>}
      </div>
    </div>
  );
}
```

```dotenv [.env.local]
NEXT_PUBLIC_POLICY_ID=
```

:::

## 6. Start your app

```bash
npm start
```
