@chipi-stack/starknet-connector 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +203 -51
- package/dist/index.cjs +309 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +157 -10
- package/dist/index.d.ts +157 -10
- package/dist/index.js +308 -25
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,35 +1,41 @@
|
|
|
1
1
|
# @chipi-stack/starknet-connector
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[get-starknet](https://github.com/starknet-io/get-starknet) connector that
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
just add the package to your own dApp and it works.
|
|
3
|
+
"Connect with Chipi" for Starknet dApps. A [starknet-react](https://starknet-react.com) /
|
|
4
|
+
[get-starknet](https://github.com/starknet-io/get-starknet) connector that opens the user's
|
|
5
|
+
Chipi wallet (passkey, gasless) in a popup. No browser extension, no WalletConnect, no
|
|
6
|
+
whitelisting. It works next to injected wallets such as Bramble, Ready and Braavos.
|
|
8
7
|
|
|
9
8
|
```bash
|
|
10
9
|
npm install @chipi-stack/starknet-connector
|
|
11
10
|
```
|
|
12
11
|
|
|
13
|
-
Ships
|
|
14
|
-
|
|
15
|
-
`ERR_PACKAGE_PATH_NOT_EXPORTED`. Bundlers were never affected.
|
|
12
|
+
Ships ESM and CommonJS. Versions before 0.3.0 were ESM-only and failed under CommonJS
|
|
13
|
+
resolvers (plain Node, `tsx`, `ts-node`, Jest) with `ERR_PACKAGE_PATH_NOT_EXPORTED`.
|
|
16
14
|
|
|
17
|
-
## Use it
|
|
15
|
+
## Use it with starknet-react
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
Offer Chipi next to Bramble, Ready and Braavos:
|
|
20
18
|
|
|
21
19
|
```tsx
|
|
22
|
-
import {
|
|
20
|
+
import type { ReactNode } from "react";
|
|
21
|
+
import {
|
|
22
|
+
StarknetConfig,
|
|
23
|
+
InjectedConnector,
|
|
24
|
+
publicProvider,
|
|
25
|
+
ready,
|
|
26
|
+
braavos,
|
|
27
|
+
} from "@starknet-react/core";
|
|
23
28
|
import { mainnet } from "@starknet-react/chains";
|
|
24
29
|
import { chipi } from "@chipi-stack/starknet-connector";
|
|
25
30
|
|
|
26
31
|
const connectors = [
|
|
27
32
|
chipi(), // "Connect with Chipi"
|
|
28
|
-
|
|
33
|
+
new InjectedConnector({ options: { id: "bramble", name: "Bramble" } }),
|
|
34
|
+
ready(), // Ready (formerly Argent X)
|
|
29
35
|
braavos(),
|
|
30
36
|
];
|
|
31
37
|
|
|
32
|
-
export function
|
|
38
|
+
export function Providers({ children }: { children: ReactNode }) {
|
|
33
39
|
return (
|
|
34
40
|
<StarknetConfig chains={[mainnet]} provider={publicProvider()} connectors={connectors}>
|
|
35
41
|
{children}
|
|
@@ -38,9 +44,122 @@ export function App({ children }) {
|
|
|
38
44
|
}
|
|
39
45
|
```
|
|
40
46
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
Your `useConnect` / `useAccount` flow now offers all four. With Chipi, `account.execute(...)`
|
|
48
|
+
and `account.signMessage(...)` go to the user's Chipi wallet: gasless, signed with their
|
|
49
|
+
passkey.
|
|
50
|
+
|
|
51
|
+
Notes for `@starknet-react/core` 5:
|
|
52
|
+
|
|
53
|
+
- List every wallet yourself. `useInjectedConnectors` only picks up objects with the legacy keys
|
|
54
|
+
(`provider`, `isConnected`, `enable`, `isPreauthorized`). Neither `window.starknet_chipi` nor
|
|
55
|
+
`window.starknet_bramble` has all of them, so it finds neither.
|
|
56
|
+
- `injected({ id: "bramble" })` also works, but in 5.0.3 `injected()` takes only `id`. The label
|
|
57
|
+
is then the wallet's own name once Bramble has injected, and `"bramble"` before that.
|
|
58
|
+
- `argent()` is an alias of `ready()`. Use `ready()`.
|
|
59
|
+
- `InjectedConnector` looks up `window.starknet_bramble` each time it is used, so Bramble's late
|
|
60
|
+
injection is fine. `autoConnect` runs once on mount, though: if Bramble has not injected by
|
|
61
|
+
then, the last Bramble session is not restored.
|
|
62
|
+
|
|
63
|
+
## Use it with get-starknet v4
|
|
64
|
+
|
|
65
|
+
get-starknet v4 (`@starknet-io/get-starknet-core`) lists every `window.starknet*` object that
|
|
66
|
+
has `id`, `name`, `version`, `icon`, `request`, `on` and `off`. Creating a Chipi connector puts
|
|
67
|
+
`window.starknet_chipi` on the page, so both wallets show up:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { getStarknet } from "@starknet-io/get-starknet-core";
|
|
71
|
+
import { chipi } from "@chipi-stack/starknet-connector";
|
|
72
|
+
|
|
73
|
+
declare const connectButton: HTMLButtonElement;
|
|
74
|
+
declare function pickedWalletId(): "chipi" | "bramble"; // from your wallet picker
|
|
75
|
+
|
|
76
|
+
// Puts window.starknet_chipi on the page.
|
|
77
|
+
chipi();
|
|
78
|
+
|
|
79
|
+
// Bramble injects window.starknet_bramble after page load, then fires
|
|
80
|
+
// "starknet#initialized". Scan after that, or after a short timeout.
|
|
81
|
+
function waitForInjectedWallets(timeoutMs = 3000): Promise<void> {
|
|
82
|
+
return new Promise((resolve) => {
|
|
83
|
+
if ("starknet_bramble" in window) return resolve();
|
|
84
|
+
const done = () => {
|
|
85
|
+
clearTimeout(timer);
|
|
86
|
+
window.removeEventListener("starknet#initialized", done);
|
|
87
|
+
resolve();
|
|
88
|
+
};
|
|
89
|
+
const timer = setTimeout(done, timeoutMs);
|
|
90
|
+
window.addEventListener("starknet#initialized", done);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
await waitForInjectedWallets();
|
|
95
|
+
const gsc = getStarknet();
|
|
96
|
+
const wallets = await gsc.getAvailableWallets();
|
|
97
|
+
// Both are listed: wallets.map((w) => w.id) includes "chipi" and "bramble".
|
|
98
|
+
|
|
99
|
+
// Prompts only from a click: Chipi opens its popup, Bramble its side panel.
|
|
100
|
+
connectButton.onclick = async () => {
|
|
101
|
+
const wallet = wallets.find((w) => w.id === pickedWalletId());
|
|
102
|
+
if (wallet) await gsc.enable(wallet);
|
|
103
|
+
};
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`getAuthorizedWallets()` and `getLastConnectedWallet()` send `wallet_getPermissions` to every
|
|
107
|
+
wallet at page load. Chipi answers that locally with `[]` and does not open its popup (see
|
|
108
|
+
[Passive calls](#passive-calls)). There is no silent reconnect: the user clicks connect again
|
|
109
|
+
on each page load.
|
|
110
|
+
|
|
111
|
+
Bramble's guide notes that get-starknet v3 also requires a `provider` key, which Bramble lacks.
|
|
112
|
+
Chipi's object lacks it too.
|
|
113
|
+
|
|
114
|
+
## Wallet Standard (get-starknet v5 and v6)
|
|
115
|
+
|
|
116
|
+
`@starknet-io/get-starknet-discovery` (5.0.0 and 6.0.6 ship the same code) builds its list in
|
|
117
|
+
`createStore()`:
|
|
118
|
+
|
|
119
|
+
- Wallet Standard wallets register through `wallet-standard:register-wallet`, at any time.
|
|
120
|
+
- `window.starknet*` objects are scanned once, when `createStore()` runs, and wrapped as
|
|
121
|
+
injected wallets. Entries are de-duplicated by name, and a Wallet Standard entry wins.
|
|
122
|
+
|
|
123
|
+
Bramble has no Wallet Standard registration, so get-starknet v5/v6 lists it only if
|
|
124
|
+
`window.starknet_bramble` exists when `createStore()` runs. Register Chipi as a Wallet Standard
|
|
125
|
+
wallet so the order does not matter:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import { registerChipiStandardWallet } from "@chipi-stack/starknet-connector";
|
|
129
|
+
|
|
130
|
+
const unregister = registerChipiStandardWallet({
|
|
131
|
+
walletUrl: "https://wallet.chipipay.com", // default
|
|
132
|
+
});
|
|
133
|
+
// later: unregister();
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
It dispatches `wallet-standard:register-wallet` and answers `wallet-standard:app-ready`, with no
|
|
137
|
+
extra dependency. It exposes `starknet:walletApi`, `standard:connect`, `standard:disconnect` and
|
|
138
|
+
`standard:events` on `starknet:0x534e5f4d41494e` (mainnet), backed by the same popup.
|
|
139
|
+
`connect({ silent: true })` never opens the popup. Its default name is `"Chipi"`; the
|
|
140
|
+
connector's is `"Connect with Chipi"`. If `window.starknet_chipi` also exists when the store is
|
|
141
|
+
created, the store lists two Chipi entries: pass `register: false` to the connector, or give both
|
|
142
|
+
the same `name`. `createChipiStandardWallet(options)` builds the wallet
|
|
143
|
+
without registering it.
|
|
144
|
+
|
|
145
|
+
## Works next to Bramble
|
|
146
|
+
|
|
147
|
+
- **No id collision.** Chipi is `window.starknet_chipi` with id `"chipi"`. Bramble is
|
|
148
|
+
`window.starknet_bramble` with id `"bramble"`. get-starknet v4 and starknet-react key wallets
|
|
149
|
+
by id, so both are listed.
|
|
150
|
+
- **Neither writes `window.starknet`.**
|
|
151
|
+
- **When each object exists.** `window.starknet_chipi` exists only after a `ChipiConnector` is
|
|
152
|
+
created (unless `register: false`). `disconnect()` removes it until the next `connect()`.
|
|
153
|
+
`window.starknet_bramble` appears after page load, followed by a `starknet#initialized` event.
|
|
154
|
+
- **A wallet scan never opens Chipi.** Since 0.5.0, the calls scanners send at page load are
|
|
155
|
+
answered without opening the popup (see [Passive calls](#passive-calls)).
|
|
156
|
+
- **Bramble's own rules apply to Bramble.** Prompts only from a click, at most 5 pending prompts
|
|
157
|
+
per site, strict params (an extra key fails with `114`), a typed-data `chainId` equal to its
|
|
158
|
+
active network, no `wallet_disconnect` (`114`), one account per site. Signatures are `[r, s]`
|
|
159
|
+
for OpenZeppelin and Braavos accounts and `["1", "0", pub, r, s]` for Argent accounts: verify
|
|
160
|
+
them with the account's `is_valid_signature`, not by length. starknet-react's
|
|
161
|
+
`InjectedConnector.disconnect()` does not send `wallet_disconnect`. See
|
|
162
|
+
[Bramble rules to follow](https://docs.chipipay.com/sdk/guides/trusted-wallets#bramble-rules-to-follow).
|
|
44
163
|
|
|
45
164
|
## How it works
|
|
46
165
|
|
|
@@ -54,55 +173,88 @@ account.execute(calls)
|
|
|
54
173
|
└─ wallet_addInvokeTransaction ─► user approves ─► sponsored tx ─► tx hash
|
|
55
174
|
```
|
|
56
175
|
|
|
57
|
-
- The connector
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- `
|
|
64
|
-
|
|
176
|
+
- The connector only carries messages. It opens the hosted wallet in a popup and forwards
|
|
177
|
+
get-starknet `wallet_*` calls over `postMessage`. It holds no keys and signs nothing.
|
|
178
|
+
- Each request is posted right away and matched to its answer by id. Several can be in flight at
|
|
179
|
+
once; the connector neither queues nor rejects them.
|
|
180
|
+
- `account()` wraps the channel in a starknet.js `WalletAccount`, so the dApp gets a standard
|
|
181
|
+
`AccountInterface`.
|
|
182
|
+
- There is no silent reconnect. `ready()` is `true` only after `connect()` succeeded on this
|
|
183
|
+
page. Call `connect()` from a click: it opens a popup.
|
|
184
|
+
- Chipi is mainnet-only. `chainId()` always returns `SN_MAIN`.
|
|
185
|
+
|
|
186
|
+
## Passive calls
|
|
187
|
+
|
|
188
|
+
While no wallet window is open (before `connect()`, or after the user closed it), the connector
|
|
189
|
+
answers these calls itself and does not open the popup. Once the window is open, they go to the
|
|
190
|
+
wallet.
|
|
191
|
+
|
|
192
|
+
| Call | Answer with no wallet window open |
|
|
193
|
+
| ------------------------------------------------- | --------------------------------- |
|
|
194
|
+
| `wallet_getPermissions` | `[]` |
|
|
195
|
+
| `wallet_requestAccounts` with `silent_mode: true` | `[]` |
|
|
196
|
+
| `wallet_requestChainId` | `"0x534e5f4d41494e"` (`SN_MAIN`) |
|
|
197
|
+
|
|
198
|
+
`wallet_requestAccounts` without `silent_mode: true` opens the popup, so send it from a click.
|
|
65
199
|
|
|
66
200
|
## Options
|
|
67
201
|
|
|
68
202
|
```ts
|
|
203
|
+
import { chipi } from "@chipi-stack/starknet-connector";
|
|
204
|
+
|
|
69
205
|
chipi({
|
|
70
206
|
walletUrl: "https://wallet.chipipay.com", // hosted wallet base URL (default)
|
|
71
|
-
id: "chipi", // connector id
|
|
72
|
-
name: "Connect with Chipi", // display name
|
|
73
|
-
icon: "data:image/
|
|
74
|
-
register: true, //
|
|
207
|
+
id: "chipi", // connector id (default); the window key stays starknet_chipi
|
|
208
|
+
name: "Connect with Chipi", // display name (default)
|
|
209
|
+
icon: "data:image/png;base64,...", // default: a 48x48 PNG data URI
|
|
210
|
+
register: true, // put window.starknet_chipi on the page (default; no-op in SSR)
|
|
211
|
+
transport: {
|
|
212
|
+
windowName: "chipi-wallet", // default: a new random name per open
|
|
213
|
+
windowFeatures: "popup=yes,width=420,height=680", // default
|
|
214
|
+
openTimeoutMs: 180_000, // wait for the wallet page to load (default)
|
|
215
|
+
requestTimeoutMs: 120_000, // per request; 0 disables (default)
|
|
216
|
+
},
|
|
75
217
|
});
|
|
76
218
|
```
|
|
77
219
|
|
|
78
|
-
`chipi(options)` is
|
|
79
|
-
identically if you prefer instantiating the class directly.
|
|
220
|
+
`chipi(options)` is the same as `new ChipiConnector(options)`.
|
|
80
221
|
|
|
81
|
-
##
|
|
222
|
+
## Errors
|
|
223
|
+
|
|
224
|
+
The connector rejects with an `Error`. Check `err.code` first, then `err.message`.
|
|
82
225
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
226
|
+
| `code` or message | When |
|
|
227
|
+
| ----------------------------------------------- | ---------------------------------------------------------------------------------------- |
|
|
228
|
+
| code `"UNSUPPORTED_CHAIN"` | `connect({ chainIdHint })` with a chain other than `SN_MAIN`. No popup opens. |
|
|
229
|
+
| code `"popup_blocked"` | The browser blocked the popup: `connect()` did not run from a click. |
|
|
230
|
+
| message `"wallet_open_timeout"` | The wallet page did not load within `transport.openTimeoutMs` (180 s). The popup closes. |
|
|
231
|
+
| code `"REQUEST_TIMEOUT"` | No answer within `transport.requestTimeoutMs` (120 s). |
|
|
232
|
+
| code `"POPUP_CLOSED"` | A request after the user closed the wallet window. Call `connect()` again from a click. |
|
|
233
|
+
| code `4001`, message `"User closed the wallet"` | The user closed the wallet window while a request was waiting. |
|
|
234
|
+
| code `4001`, message `"disconnected"` | `disconnect()` ran while a request, or the wallet page load, was waiting. |
|
|
235
|
+
| message `"chipi_no_account"` | The wallet returned no account on connect. |
|
|
236
|
+
| message `"chipi_not_connected"` | `account()` before `connect()`. |
|
|
237
|
+
| message `"chipi_connector_requires_browser"` | The popup was requested without `window` (SSR). |
|
|
238
|
+
| numeric code from the wallet (`113` … `163`) | The wallet's own error, passed through with its message (see below). |
|
|
86
239
|
|
|
87
|
-
|
|
240
|
+
Wallets built on `createChipiWindowObject` from `@chipi-stack/chipi-react` answer `113` (the
|
|
241
|
+
user refused), `114` (no calls, or typed data with no `chainId` or one for another chain), `115` (account
|
|
242
|
+
already deployed), `116` (deployment data not available) and `163` (unsupported method,
|
|
243
|
+
including `wallet_disconnect` and `wallet_switchStarknetChain`, or another failure).
|
|
88
244
|
|
|
89
|
-
|
|
90
|
-
(`window.starknet_chipi` + a `starknet:announceWallet` event, the get-starknet /
|
|
91
|
-
Starknet-Wallet-Standard discovery path), so dApps that _scan_ for wallets find
|
|
92
|
-
"Connect with Chipi" even if they don't import this package, no whitelisting,
|
|
93
|
-
no coordination with us required. Pass `register: false` to opt out (e.g. to
|
|
94
|
-
avoid a duplicate entry in a picker that already lists the connector
|
|
95
|
-
explicitly). It's a no-op during SSR. You can also call
|
|
96
|
-
`registerChipiWallet(swo)` directly.
|
|
245
|
+
## Events
|
|
97
246
|
|
|
98
|
-
|
|
247
|
+
- The wallet's `accountsChanged` / `networkChanged` become starknet-react `change` events
|
|
248
|
+
(`{ account, chainId }`). An empty account list emits `disconnect`.
|
|
249
|
+
- `disconnect()` closes the popup and removes `window.starknet_chipi`. The next `connect()` puts
|
|
250
|
+
it back.
|
|
251
|
+
|
|
252
|
+
## Compatibility
|
|
99
253
|
|
|
100
|
-
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
-
|
|
104
|
-
- One approval at a time; a dApp that fires two prompts truly simultaneously has
|
|
105
|
-
its second request rejected (most dApps serialize).
|
|
254
|
+
- `@starknet-react/core` >= 3 (peer), tested against 5.0.3.
|
|
255
|
+
- `starknet` >= 8.1.2 (peer). `WalletAccount.connect` is the same in 8 and 9.
|
|
256
|
+
- Starknet mainnet only.
|
|
257
|
+
- Popup only. The in-app-browser ("parent") mode is in the transport but not exposed.
|
|
106
258
|
|
|
107
|
-
MIT · [docs.chipipay.com](https://docs.chipipay.com) ·
|
|
259
|
+
MIT · [docs.chipipay.com](https://docs.chipipay.com/sdk/connector/overview) ·
|
|
108
260
|
[example](https://github.com/chipi-pay/build-with-chipi/tree/main/tutorials/03-connect-with-chipi)
|