# 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.2.0-beta.10
npm install @cardinal-cryptography/shielder-sdk-crypto@0.2.0-beta.4
npm install @cardinal-cryptography/shielder-sdk-crypto-wasm@0.2.0-beta.4
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";

function crossOriginIsolationMiddleware(_, res, next) {
  res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
  res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
  next();
}

const setCors = () => ({
  name: "configure-server",
  configureServer: (server) => {
    server.middlewares.use(crossOriginIsolationMiddleware);
  },
  configurePreviewServer: (server) => {
    server.middlewares.use(crossOriginIsolationMiddleware);
  },
});

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

```

{% endcode %}

### 4. Set Up WASM Cryptography Client

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

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

```typescript
import newAccountParamsUrl from "@cardinal-cryptography/shielder-sdk-crypto-wasm/keys/new_account/params.bin?url";
import newAccountPkUrl from "@cardinal-cryptography/shielder-sdk-crypto-wasm/keys/new_account/pk.bin?url";
import depositParamsUrl from "@cardinal-cryptography/shielder-sdk-crypto-wasm/keys/deposit/params.bin?url";
import depositPkUrl from "@cardinal-cryptography/shielder-sdk-crypto-wasm/keys/deposit/pk.bin?url";
import withdrawParamsUrl from "@cardinal-cryptography/shielder-sdk-crypto-wasm/keys/withdraw/params.bin?url";
import withdrawPkUrl from "@cardinal-cryptography/shielder-sdk-crypto-wasm/keys/withdraw/pk.bin?url";
import { initWasmWorker } from "@cardinal-cryptography/shielder-sdk-crypto-wasm";

// Helper function to fetch proving/verifying keys
async function fetchArrayBuffer(url: string): Promise<Uint8Array> {
  return fetch(url)
    .then((r) => r.arrayBuffer())
    .then((b) => new Uint8Array(b));
}

// Lazy-loaded WASM crypto client
export const wasmCryptoClientRead = (async () => {
  const newAccountParams = await fetchArrayBuffer(newAccountParamsUrl);
  const newAccountPk = await fetchArrayBuffer(newAccountPkUrl);
  const depositParams = await fetchArrayBuffer(depositParamsUrl);
  const depositPk = await fetchArrayBuffer(depositPkUrl);
  const withdrawParams = await fetchArrayBuffer(withdrawParamsUrl);
  const withdrawPk = await fetchArrayBuffer(withdrawPkUrl);
  return initWasmWorker(
    navigator.hardwareConcurrency,
    {
      paramsBuf: newAccountParams,
      pkBuf: newAccountPk,
    },
    {
      paramsBuf: depositParams,
      pkBuf: depositPk,
    },
    {
      paramsBuf: withdrawParams,
      pkBuf: withdrawPk,
    }
  );
})();

```

{% 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://shielder-relayer-v2.test.azero.dev/base-testnet";

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.<br>

Next steps:

* To shield tokens (i.e. deposit), see: [Shielding Tokens](/knowledge-base/shielding-tokens.md)
* To withdraw tokens back to a public address, see: [Withdrawing Tokens](/knowledge-base/withdrawing-tokens.md)

Both operations require working with token approvals, gas fees, and relayer coordination.

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

Explore the guides to implement full privacy flow.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.common.fi/knowledge-base/shielder-sdk/quickstart.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
