> ## 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

<Steps>
  <Step title="Configure your Authentication" titleSize="h2">
    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.
    </Tip>

    ### Common auth providers

    <Tabs>
      <Tab title="Clerk">
        The dashboard auto-configures JWKS when you provide your Clerk Secret Key.
      </Tab>

      <Tab title="Firebase">
        See our tutorial on how to set up Chipi with [Firebase](/sdk/nextjs/gasless-firebase-setup).
      </Tab>

      <Tab title="Supabase">
        See our tutorial on how to set up Chipi with [Supabase](/sdk/react/gasless-supabase-setup).
      </Tab>
    </Tabs>
  </Step>

  <Step title="Get your API Keys" titleSize="h2">
    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`
  </Step>

  <Step title="Frontend Code to create a wallet" titleSize="h2">
    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.

    <Info>
      Chipi supports two wallet types:

      * **CHIPI** (default): OpenZeppelin account with SNIP-9 session keys support
      * **READY**: Argent X Account v0.4.0
    </Info>

    ```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"
          }`
        );
      }
    };
    ```
  </Step>

  <Step title="Create a Wallet" titleSize="h2">
    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.
    </Tip>

    ### 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.
    </Note>
  </Step>
</Steps>
