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

# Connector

> Let any Starknet dApp offer a Chipi wallet (passkey, gasless) next to Bramble, Ready and Braavos. No extension, no WalletConnect, no whitelisting.

`@chipi-stack/starknet-connector` is a [starknet-react](https://starknet-react.com) /
[get-starknet](https://github.com/starknet-io/get-starknet) connector. It opens the user's
Chipi wallet, a passkey smart account that signs **gasless** through the paymaster, in a popup.
No browser extension, no WalletConnect, and no whitelisting on our side: any Starknet dApp can
add it. It works next to injected wallets such as Bramble, Ready and Braavos.

## Install

```bash theme={null}
npm install @chipi-stack/starknet-connector
```

## Add it with starknet-react

Offer Chipi next to Bramble, Ready and Braavos:

```tsx theme={null}
import type { ReactNode } from "react";
import {
  StarknetConfig,
  InjectedConnector,
  publicProvider,
  ready,
  braavos,
} from "@starknet-react/core";
import { mainnet } from "@starknet-react/chains";
import { chipi } from "@chipi-stack/starknet-connector";

const connectors = [
  chipi(), // "Connect with Chipi"
  new InjectedConnector({ options: { id: "bramble", name: "Bramble" } }),
  ready(), // Ready (formerly Argent X)
  braavos(),
];

export function Providers({ children }: { children: ReactNode }) {
  return (
    <StarknetConfig chains={[mainnet]} provider={publicProvider()} connectors={connectors}>
      {children}
    </StarknetConfig>
  );
}
```

Your `useConnect` / `useAccount` flow now offers all four. With Chipi, `account.execute(...)`
and `account.signMessage(...)` go to the user's Chipi wallet: gasless, signed with their passkey.

With `@starknet-react/core` 5:

* **List every wallet yourself.** `useInjectedConnectors` only picks up objects with the legacy
  keys (`provider`, `isConnected`, `enable`, `isPreauthorized`). Neither `window.starknet_chipi`
  nor `window.starknet_bramble` has all of them, so it finds neither.
* `injected({ id: "bramble" })` also works, but in 5.0.3 `injected()` takes only `id`: the label
  is Bramble's own name once it has injected, and `"bramble"` before that.
* `argent()` is an alias of `ready()`. Use `ready()`.
* `InjectedConnector` looks up `window.starknet_bramble` each time it is used, so Bramble's late
  injection is fine. `autoConnect` runs once on mount: if Bramble has not injected by then, its
  last session is not restored.

## Add it with get-starknet v4

get-starknet v4 lists every `window.starknet*` object that has `id`, `name`, `version`, `icon`,
`request`, `on` and `off`. Chipi and Bramble both qualify. Bramble injects late, so scan after
its `starknet#initialized` event:

```ts theme={null}
import { getStarknet } from "@starknet-io/get-starknet-core";
import { chipi } from "@chipi-stack/starknet-connector";

declare const connectButton: HTMLButtonElement;
declare function pickedWalletId(): "chipi" | "bramble"; // from your wallet picker

// Puts window.starknet_chipi on the page.
chipi();

// Bramble injects window.starknet_bramble after page load, then fires
// "starknet#initialized". Scan after that, or after a short timeout.
function waitForInjectedWallets(timeoutMs = 3000): Promise<void> {
  return new Promise((resolve) => {
    if ("starknet_bramble" in window) return resolve();
    const done = () => {
      clearTimeout(timer);
      window.removeEventListener("starknet#initialized", done);
      resolve();
    };
    const timer = setTimeout(done, timeoutMs);
    window.addEventListener("starknet#initialized", done);
  });
}

await waitForInjectedWallets();
const gsc = getStarknet();
const wallets = await gsc.getAvailableWallets();
// Both are listed: wallets.map((w) => w.id) includes "chipi" and "bramble".

// Prompts only from a click: Chipi opens its popup, Bramble its side panel.
connectButton.onclick = async () => {
  const wallet = wallets.find((w) => w.id === pickedWalletId());
  if (wallet) await gsc.enable(wallet);
};
```

For get-starknet v5 and v6 (Wallet Standard), see [Wallet Standard](/sdk/connector/api#wallet-standard).

## Works next to Bramble

* **No id collision.** Chipi is `window.starknet_chipi` with id `"chipi"`. Bramble is
  `window.starknet_bramble` with id `"bramble"`. get-starknet v4 and starknet-react key wallets
  by id, so both are listed.
* **Neither writes `window.starknet`.**
* **When each object exists.** `window.starknet_chipi` exists only after a `ChipiConnector` is
  created (unless `register: false`). `disconnect()` removes it until the next `connect()`.
  `window.starknet_bramble` appears after page load, followed by `starknet#initialized`.
* **A wallet scan never opens Chipi.** get-starknet v4's `getAuthorizedWallets()` and
  `getLastConnectedWallet()` send `wallet_getPermissions` to every wallet at page load. Since
  0.5.0, Chipi answers that and the other [passive calls](/sdk/connector/api#passive-calls)
  itself (`[]` before the user connects) and does not try to open its popup.
* **Bramble's rules apply to Bramble.** Prompts only from a click, at most 5 pending prompts per
  site, strict params (an extra key fails with `114`), a typed-data `chainId` equal to its active
  network, no `wallet_disconnect` (`114`), one account per site. starknet-react's
  `InjectedConnector.disconnect()` does not send `wallet_disconnect`. Signatures are `[r, s]` for
  OpenZeppelin and Braavos accounts and `["1", "0", pub, r, s]` for Argent accounts: verify them
  with the account's `is_valid_signature` (or [Sign in with Starknet](/sdk/guides/sign-in-with-starknet)),
  not by length. Full list: [Bramble rules to follow](/sdk/guides/trusted-wallets#bramble-rules-to-follow).

## How it works

```
your dApp                          Chipi hosted wallet (wallet.chipipay.com)
─────────                          ──────────────────────────────────────────
ChipiConnector.connect()
  ├─ opens a popup ──────────────►  /connect  (the user's authenticated wallet)
  └─ postMessage  ◄────────────►    approval UI (passkey + gasless paymaster)
account.execute(calls)
  └─ wallet_addInvokeTransaction ─►  user approves ─► sponsored tx ─► tx hash
```

1. `ChipiConnector` only carries messages. It opens the hosted wallet in a popup and forwards
   get-starknet `wallet_*` calls over `postMessage`. It holds no keys and signs nothing.
2. The **hosted wallet** (`/connect`) signs the user in, shows an approval for each connect,
   sign and execute, then runs the passkey + paymaster path and posts the result back.
3. `connector.account(provider)` wraps the channel in a starknet.js `WalletAccount`, so the
   dApp gets a standard `AccountInterface`.

There is no silent reconnect: `ready()` is `true` only after `connect()` succeeded on the same
page. Call `connect()` from a click, since it opens a popup.

## Also on the extension

The same hosted-wallet approval path is reachable from the **Chipi Wallet browser extension**,
which injects a get-starknet provider so dApps that scan for installed wallets list Chipi. See
the [Chrome Web Store listing](https://chromewebstore.google.com/detail/oaaommjokjjclmkgldlooihpfhbigejl).
Both paths end in the same hosted wallet and the same [security model](/sdk/connector/security).

## Try the example

A runnable starknet-react example lives in
[`build-with-chipi` → Tutorial 03](https://github.com/chipi-pay/build-with-chipi/tree/main/tutorials/03-connect-with-chipi).
It puts Chipi in the same `connectors` array as any other connector, then connects, signs typed
data and runs a gasless execute.

> ✅ Verified against the SDK source on **2026-10-12**.


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