> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chipipay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Quick setup guide for gasless transactions using only the Chipi API

## 1. Configure your Authentication

You'll need to configure your auth provider's JWKS endpoint in the [Chipi Dashboard](https://dashboard.chipipay.com). The dashboard quickstart detects your auth provider and walks you through the setup.

> [!TIP]
>
> With this JWKS Endpoint setup, you can now run secure code in your frontend
> using a rotating JWT token.

### Common auth providers

**Clerk**

The dashboard auto-configures JWKS when you provide your Clerk Secret Key.

**Firebase**

See our tutorial on how to set up Chipi with [Firebase](/sdk/nextjs/gasless-firebase-setup).

**Supabase**

See our tutorial on how to set up Chipi with [Supabase](/sdk/react/gasless-supabase-setup).

## 2. Get your API Keys

Go to the [Chipi Dashboard](https://dashboard.chipipay.com) and open your project. The quickstart shows your `.env` snippet with both keys ready to copy.

You'll need:

* **Public Key** (`pk_prod_xxxx`) — used client-side
* **Secret Key** (`sk_prod_xxxx`) — used by the server-side `ChipiProvider`

## 3. Frontend Code to create a wallet

Since this wallet is self-custodial, there are many steps that need to be done in the frontend.

Here is the code to create a wallet for your user.

> [!NOTE]
>
> Chipi supports two wallet types:
>
> * **CHIPI** (default): OpenZeppelin account with SNIP-9 session keys support
> * **READY**: Argent X Account v0.4.0

```typescript theme={null}
// External dependencies (you'll need to install these)
import CryptoJS from "crypto-js";
import {
  Account,
  CairoCustomEnum,
  CairoOption,
  CairoOptionVariant,
  CallData,
  ec,
  hash,
  num,
  RpcProvider,
  stark,
} from "starknet";

// Wallet type configuration
type WalletType = "CHIPI" | "READY";

// Class hashes for each wallet type
const WALLET_CLASS_HASHES = {
  CHIPI: "0x53f4f8791ed5bed0fddaa553d180c664e32cfaf8316bb232ae77bb08f459f2a",
  READY: "0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f",
};

// RPC endpoints per wallet type
const WALLET_RPC_ENDPOINTS = {
  CHIPI: "https://starknet-mainnet.public.blastapi.io/rpc/v0_7",
  READY: "https://cloud.argent-api.com/v1/starknet/mainnet/rpc/v0.7",
};

// Deployment data type
interface DeploymentData {
  class_hash: string;
  salt: string;
  unique: string;
  calldata: string[];
}

// Encryption utility
const encryptPrivateKey = (
  privateKey: string,
  password: string,
): string => {
  if (!privateKey || !password) {
    throw new Error("Private key and password are required");
  }
  return CryptoJS.AES.encrypt(privateKey, password).toString();
};

// Types (included inline)
interface WalletData {
  publicKey: string;
  encryptedPrivateKey: string;
}

interface CreateWalletParams {
  encryptKey: string;
  externalUserId: string;
  apiPublicKey: string;
  bearerToken: string;
  chain: string; // Currently only "STARKNET" is supported
  walletType?: WalletType; // Optional, defaults to "CHIPI"
}

// Backend URL constant
const BACKEND_URL = "https://api.chipipay.com/v1";

// Build constructor calldata based on wallet type
const buildConstructorCallData = (
  walletType: WalletType,
  starkKeyPubAX: string
): string[] => {
  if (walletType === "READY") {
    // Argent X Account: owner (CairoCustomEnum) + guardian (CairoOption None)
    const axSigner = new CairoCustomEnum({
      Starknet: { pubkey: starkKeyPubAX },
    });
    const axGuardian = new CairoOption<unknown>(CairoOptionVariant.None);
    return CallData.compile({
      owner: axSigner,
      guardian: axGuardian,
    });
  }

  // ChipiWallet (default): Simple OpenZeppelin account with just public_key
  return CallData.compile({
    public_key: starkKeyPubAX,
  });
};

// Main function
export const createWallet = async (
  params: CreateWalletParams
): Promise<CreateWalletResponse> => {
  try {
    const {
      encryptKey,
      apiPublicKey,
      bearerToken,
      walletType = "CHIPI" // Default to CHIPI wallet
    } = params;

    // Select RPC endpoint based on wallet type
    const rpcUrl = WALLET_RPC_ENDPOINTS[walletType];
    const provider = new RpcProvider({ nodeUrl: rpcUrl });

    // Generating the private key with Stark Curve
    const privateKeyAX = stark.randomAddress();
    const starkKeyPubAX = ec.starkCurve.getStarkKey(privateKeyAX);

    // Select class hash based on wallet type
    const accountClassHash = WALLET_CLASS_HASHES[walletType];

    // Build constructor calldata based on wallet type
    const constructorCallData = buildConstructorCallData(walletType, starkKeyPubAX);

    // Calculate future address of the account
    const publicKey = hash.calculateContractAddressFromHash(
      starkKeyPubAX,
      accountClassHash,
      constructorCallData,
      0
    );

    // Initiating Account
    const account = new Account(provider, publicKey, privateKeyAX);

    // Backend Call API to create the wallet
    const typeDataResponse = await fetch(`${BACKEND_URL}/chipi-wallets/prepare-creation`, {
      method: "POST",
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${bearerToken}`,
        'x-api-key': apiPublicKey,
      },
      body: JSON.stringify({
        publicKey,
        walletType,
      }),
    });
    const { typeData, accountClassHash: accountClassHashResponse } = await typeDataResponse.json();

    // Sign the message
    const userSignature = await account.signMessage(typeData);

    const deploymentData: DeploymentData = {
      class_hash: accountClassHashResponse,
      salt: starkKeyPubAX,
      unique: `${num.toHex(0)}`,
      calldata: constructorCallData.map((value: any) => num.toHex(value)),
    };

    const encryptedPrivateKey = encryptPrivateKey(privateKeyAX, encryptKey);

    // Call the API to save the wallet in dashboard
    const executeTransactionResponse = await fetch(`${BACKEND_URL}/chipi-wallets`, {
      method: "POST",
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${bearerToken}`,
        'x-api-key': apiPublicKey,
      },
      body: JSON.stringify({
        apiPublicKey,
        publicKey,
        walletType,
        userSignature: {
          r: (userSignature as any).r.toString(),
          s: (userSignature as any).s.toString(),
          recovery: (userSignature as any).recovery
        },
        typeData,
        encryptedPrivateKey,
        deploymentData: {
          ...deploymentData,
          salt: `${deploymentData.salt}`,
          calldata: deploymentData.calldata.map((data: any) => `${data}`),
        }
      }),
    });
    const executeTransaction = await executeTransactionResponse.json();
    console.log("Execute transaction: ", executeTransaction);

    if (executeTransaction.success) {
      return {
        success: true,
        txHash: executeTransaction.txHash,
        wallet: {
          publicKey: executeTransaction.walletPublicKey,
          encryptedPrivateKey: encryptedPrivateKey,
        } as WalletData,
      };
    } else {
      return {
        success: false,
        txHash: "",
        wallet: {
          publicKey: "",
          encryptedPrivateKey: "",
        } as WalletData,
      };
    }
  } catch (error: unknown) {
    console.error("Error detallado:", error);

    if (error instanceof Error && error.message.includes("SSL")) {
      throw new Error(
        "SSL connection error. Try using NODE_TLS_REJECT_UNAUTHORIZED=0 or verify the RPC URL"
      );
    }

    throw new Error(
      `Error creating wallet: ${
        error instanceof Error ? error.message : "Unknown error"
      }`
    );
  }
};
```

## 4. Create a Wallet

Now you can create a wallet for your user.

> [!TIP]
>
> For the bearerToken you need to pass a valid JWT token from your auth provider.

### Create a ChipiWallet (Default)

ChipiWallet is an OpenZeppelin account with SNIP-9 session keys support, perfect for gasless transactions and delegated access.

```typescript theme={null}
// Example usage with ChipiWallet (default):
const params: CreateWalletParams = {
  encryptKey: "user-secure-pin", // Encryption key for the private key
  externalUserId: "user-123", // Your user's unique identifier
  apiPublicKey: "pk_prod_***", // Your Chipi Pay public key
  bearerToken: "your-bearer-token", // Valid JWT token from your Auth Provider
  chain: "STARKNET", // Currently only STARKNET is supported
  // walletType: "CHIPI", // Optional - CHIPI is the default
};

createWallet(params)
  .then(response => console.log("Wallet created:", response))
  .catch(error => console.error("Error:", error));
```

### Create a Ready Wallet

If you need Argent X compatibility:

```typescript theme={null}
// Example usage with Ready wallet:
const params: CreateWalletParams = {
  encryptKey: "user-secure-pin",
  externalUserId: "user-123",
  apiPublicKey: "pk_prod_***",
  bearerToken: "your-bearer-token",
  chain: "STARKNET", // Currently only STARKNET is supported
  walletType: "READY", // Explicitly use Argent X Account
};

createWallet(params)
  .then(response => console.log("Wallet created:", response))
  .catch(error => console.error("Error:", error));
```

> [!NOTE]
>
> **Backward Compatibility**: If you don't specify `walletType`, the SDK will create a ChipiWallet by default. Existing integrations will continue to work without changes.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.