# Quickstart

### 1. Create a React + Typescript Project

Let's create a simple vite project with React and Typescript:

```bash
npm create vite@latest sdk-test -- --template react-ts
```

### 2. Install Dependencies

Install `shielder-sdk` and additional dependencies:

```bash
npm install @cardinal-cryptography/shielder-sdk@0.3.0-rc.3
npm install @cardinal-cryptography/shielder-sdk-crypto@0.3.0-rc.1
npm install @cardinal-cryptography/shielder-sdk-crypto-wasm-light@0.3.0-rc.2
npm install viem @types/node @vitejs/plugin-react
```

### 3. Configure Vite

Add following code to `vite.config.ts` :

{% code title="vite.config.ts" %}

```typescript
import * as path from "path";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

// https://vite.dev/config/
export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
  optimizeDeps: {
    exclude: ["@cardinal-cryptography/shielder-sdk-crypto-wasm-light"],
  },
});

```

{% endcode %}

### 4. Set Up WASM Cryptography Client

Create a file `src/shielderWasm.ts` , where we'll set up the wasm engine loading.

Note, that in quickstart guide we use a light wasm client, which is simple to set up, but currently is in alpha stage. Refer to [cryptography-client](https://docs.blanksquare.io/integration-guides/cryptography-client "mention") for production-ready setup details.

PCR values can be found at [Github Releases](https://github.com/Cardinal-Cryptography/blanksquare-monorepo/releases), for example [pcr-92cd84c.json](https://github.com/Cardinal-Cryptography/blanksquare-monorepo/releases/tag/prover-server-v0.2.0)

{% code title="src/shielderWasm.ts" %}

```typescript
import { initWasmWorker } from "@cardinal-cryptography/shielder-sdk-crypto-wasm-light";

// values from releases page
const pcrs = new Map<string, string>(
  Object.entries({
    "0": "94b74422daddb8f503fcd69df064c7cde5d053001b9cd153c75ec34484283496a37e89c7287a00f467759a6863362b60",
    "1": "927e084e583f5c2d60a39e2b9cd9728bfb390aa9f83dee4b6ac768509850ba273ea8b019ccfbf3180eb18a2dd0c4a678",
    "2": "07c20c057d5c10cb732b273b7fa26a2b67e333344ccda49be939a6b7c5bed5e46f0b0703386dd2d0f6104a13a4894cb2",
  })
);

// WASM crypto client
export const wasmCryptoClientRead = (async () => {
  return initWasmWorker("https://prover-server.test.blanksquare.dev", pcrs);
})();

```

{% endcode %}

### 5. Initialize the Shielder SDK Client

Create `src/shielder.ts:`

{% code title="src/shielder.ts:" %}

```typescript
import {
  createShielderClient,
  type ShielderOperation,
} from "@cardinal-cryptography/shielder-sdk";
import { createPublicClient, http } from "viem";
import { baseSepolia } from "viem/chains";
import { wasmCryptoClientRead } from "./shielderWasm";

const chain = baseSepolia;

const shielderContractAddress =
  "0x2098a5f59DAB63F1a2aB7C0715DA437D1efB012B" as `0x${string}`;

const relayerUrl = "https://base-testnet-shielder-relayer-v3.test.blanksquare.dev";

export const publicClient = createPublicClient({
  chain,
  transport: http(),
});

// Simple in-memory key-value storage
const shielderStorage: Map<string, string> = new Map();

// 66-character (0x prefix + 64 hex symbols) of account private key
const shieldedAccountPrivateKey = "0x..." as `0x${string}`;

export async function initializeShielderClient() {
  return createShielderClient({
    shielderSeedPrivateKey,
    chainId: BigInt(chain.id),
    // Note: cast publicClient to 'any' for compatibility
    publicClient: publicClient as any,
    contractAddress: shielderContractAddress,
    relayerUrl,
    storage: {
      getItem: async (key: string) => {
        return shielderStorage.get(key) || null;
      },
      setItem: async (key: string, value: string) => {
        shielderStorage.set(key, value);
      },
    },
    cryptoClient: await wasmCryptoClientRead,
    callbacks: {
      onAccountNotOnChain: async (
        error: unknown,
        stage: string,
        operation: ShielderOperation
      ) => {
        console.error("Account not on chain:", error, stage, operation);
      },
      onSdkOutdated: async (
        error: unknown,
        stage: string,
        operation: ShielderOperation
      ) => {
        console.error("SDK outdated:", error, stage, operation);
      },
    },
  });
}
```

{% endcode %}

### 6. Verify the Setup

In your main file (e.g. `src/main.tsx` or `src/App.tsx`):

```typescript
import { initializeShielderClient } from "./shielder";
import { nativeToken } from "@cardinal-cryptography/shielder-sdk";

(async () => {
  // Initialize the SDK client
  const shielder = await initializeShielderClient();
  // Sync the account state from chain
  await shielder.syncShielder();
  
  // Get the native token representation
  const token = nativeToken();
  
  // Query your current account state (balance, nonce.)
  const accountState = await shielder.accountState(token);

  // Log the result to console (should be null at this point)
  console.log("Account:", accountState);
})();
```

At this point, your app is connected to the Shielder network, has synced the private account, and can query its state.\\

Next steps:

* To shield tokens (i.e. deposit), see: [shielding-tokens](https://docs.blanksquare.io/integration-guides/shielding-tokens "mention")
* To withdraw tokens back to a public address, see: [withdrawing-tokens](https://docs.blanksquare.io/integration-guides/withdrawing-tokens "mention")

Both operations require working with token approvals, gas fees, and relayer coordination. For a comprehensive understanding of all fee structures and costs involved, see [Understanding Fees](https://docs.blanksquare.io/integration-guides/fees).

We recommend you handle those through user-facing components in your app UI.

Explore the guides to implement full privacy flow.
