@chipi-stack/starknet-connector 0.2.0 → 0.3.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 CHANGED
@@ -1,15 +1,19 @@
1
1
  # @chipi-stack/starknet-connector
2
2
 
3
- **"Connect with Chipi"** — a [starknet-react](https://starknet-react.com) /
3
+ **"Connect with Chipi"**, a [starknet-react](https://starknet-react.com) /
4
4
  [get-starknet](https://github.com/starknet-io/get-starknet) connector that lets
5
5
  any Starknet dApp connect to a **Chipi hosted smart-account wallet** (passkey,
6
- gasless via paymaster). No browser extension, no WalletConnect, no whitelisting
7
- — add the package to your own dApp and it just works.
6
+ gasless via paymaster). No browser extension, no WalletConnect, no whitelisting,
7
+ just add the package to your own dApp and it works.
8
8
 
9
9
  ```bash
10
10
  npm install @chipi-stack/starknet-connector
11
11
  ```
12
12
 
13
+ Ships both ESM and CommonJS. Versions before 0.3.0 were ESM-only and failed
14
+ under any CommonJS resolver (plain Node, `tsx`, `ts-node`, Jest) with
15
+ `ERR_PACKAGE_PATH_NOT_EXPORTED`. Bundlers were never affected.
16
+
13
17
  ## Use it
14
18
 
15
19
  Add one connector to your `StarknetConfig`:
@@ -36,7 +40,7 @@ export function App({ children }) {
36
40
 
37
41
  That's it. Your existing `useConnect` / `useAccount` flow now offers "Connect
38
42
  with Chipi", and `account.signMessage(...)` / `account.execute(...)` route to the
39
- user's Chipi wallet — **gasless**, signed with their passkey.
43
+ user's Chipi wallet, **gasless**, signed with their passkey.
40
44
 
41
45
  ## How it works
42
46
 
@@ -50,11 +54,11 @@ account.execute(calls)
50
54
  └─ wallet_addInvokeTransaction ─► user approves ─► sponsored tx ─► tx hash
51
55
  ```
52
56
 
53
- - The connector is **transport only** — it opens the hosted wallet in a popup and
57
+ - The connector is **transport only**: it opens the hosted wallet in a popup and
54
58
  forwards get-starknet `wallet_*` RPC calls over `postMessage`. It holds no
55
59
  keys and signs nothing itself.
56
60
  - The hosted wallet renders a **decoded approval** for every sign/execute (it
57
- shows the actual intent — token, amount, spender — and hard-blocks typed data
61
+ shows the actual intent, token, amount, spender, and hard-blocks typed data
58
62
  it can't read), then runs the real passkey + paymaster path.
59
63
  - `account()` wraps the channel in a `starknet.js` `WalletAccount`, so the dApp
60
64
  uses a standard `AccountInterface`.
@@ -71,21 +75,21 @@ chipi({
71
75
  });
72
76
  ```
73
77
 
74
- `chipi(options)` is a thin wrapper — `new ChipiConnector(options)` still works
78
+ `chipi(options)` is a thin wrapper: `new ChipiConnector(options)` still works
75
79
  identically if you prefer instantiating the class directly.
76
80
 
77
81
  ## Compatibility
78
82
 
79
83
  - `@starknet-react/core` **>= 3** (peer) · tested against `5.x`
80
- - `starknet` **>= 8.1.2** (peer) — `WalletAccount.connect` is identical across 8/9
84
+ - `starknet` **>= 8.1.2** (peer); `WalletAccount.connect` is identical across 8/9
81
85
  - **Starknet mainnet** (v1). The wallet is mainnet-only.
82
86
 
83
87
  ## Discovery
84
88
 
85
89
  Instantiating the connector also **self-registers** the wallet on `window`
86
- (`window.starknet_chipi` + a `starknet:announceWallet` event — the get-starknet /
90
+ (`window.starknet_chipi` + a `starknet:announceWallet` event, the get-starknet /
87
91
  Starknet-Wallet-Standard discovery path), so dApps that _scan_ for wallets find
88
- "Connect with Chipi" even if they don't import this package — no whitelisting,
92
+ "Connect with Chipi" even if they don't import this package, no whitelisting,
89
93
  no coordination with us required. Pass `register: false` to opt out (e.g. to
90
94
  avoid a duplicate entry in a picker that already lists the connector
91
95
  explicitly). It's a no-op during SSR. You can also call
@@ -94,12 +98,11 @@ explicitly). It's a no-op during SSR. You can also call
94
98
  ## Notes / limits (v1)
95
99
 
96
100
  - **Popup-based** (external dApps). The in-app-browser ("parent") mode is in the
97
- transport but not exposed yet — the hosted wallet side handles it in a later
101
+ transport but not exposed yet; the hosted wallet side handles it in a later
98
102
  release.
99
- - Mainnet only — pass a mainnet `provider`.
103
+ - Mainnet only, pass a mainnet `provider`.
100
104
  - One approval at a time; a dApp that fires two prompts truly simultaneously has
101
105
  its second request rejected (most dApps serialize).
102
106
 
103
107
  MIT · [docs.chipipay.com](https://docs.chipipay.com) ·
104
- [example](https://github.com/chipi-pay/build-with-chipi/tree/feat/connect-with-chipi-tutorial/tutorials/03-connect-with-chipi)
105
- (pending merge — [PR #22](https://github.com/chipi-pay/build-with-chipi/pull/22))
108
+ [example](https://github.com/chipi-pay/build-with-chipi/tree/main/tutorials/03-connect-with-chipi)
package/dist/index.cjs ADDED
@@ -0,0 +1,337 @@
1
+ 'use strict';
2
+
3
+ var core = require('@starknet-react/core');
4
+ var starknet = require('starknet');
5
+
6
+ // src/connector.ts
7
+
8
+ // src/protocol.ts
9
+ var CHIPI_WC = "chipi-connect/v1";
10
+ function isChipiWalletMessage(data) {
11
+ return typeof data === "object" && data !== null && data.channel === CHIPI_WC;
12
+ }
13
+ function isChipiDappMessage(data) {
14
+ return typeof data === "object" && data !== null && data.channel === CHIPI_WC && data.type === "rpc";
15
+ }
16
+
17
+ // src/transport.ts
18
+ function deferred() {
19
+ let resolve;
20
+ let reject;
21
+ const promise = new Promise((res, rej) => {
22
+ resolve = res;
23
+ reject = rej;
24
+ });
25
+ return { promise, resolve, reject };
26
+ }
27
+ function randomId() {
28
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
29
+ }
30
+ var ChipiPopupTransport = class {
31
+ constructor(opts) {
32
+ this.opts = opts;
33
+ this.target = null;
34
+ this.ownsTarget = false;
35
+ this.ready = false;
36
+ this.listening = false;
37
+ this.pending = /* @__PURE__ */ new Map();
38
+ this.handlers = /* @__PURE__ */ new Map();
39
+ this.readyDeferred = null;
40
+ this.openPromise = null;
41
+ this.closeWatch = null;
42
+ this.onMessage = (e) => {
43
+ if (e.origin !== this.walletOrigin || !isChipiWalletMessage(e.data)) return;
44
+ if (this.target && e.source !== this.target) return;
45
+ const msg = e.data;
46
+ if (msg.type === "ready") {
47
+ this.ready = true;
48
+ this.readyDeferred?.resolve();
49
+ this.readyDeferred = null;
50
+ if (this.target) {
51
+ for (const p of this.pending.values()) {
52
+ this.target.postMessage(p.message, this.walletOrigin);
53
+ }
54
+ }
55
+ return;
56
+ }
57
+ if (msg.type === "rpc-result") {
58
+ const p = this.pending.get(msg.id);
59
+ if (!p) return;
60
+ this.pending.delete(msg.id);
61
+ if (msg.ok) p.resolve(msg.result);
62
+ else p.reject(Object.assign(new Error(msg.error.message), { code: msg.error.code }));
63
+ return;
64
+ }
65
+ if (msg.type === "event") {
66
+ this.handlers.get(msg.event)?.forEach((h) => h(msg.data));
67
+ }
68
+ };
69
+ this.url = opts.walletUrl.replace(/\/$/, "") + "/connect";
70
+ this.walletOrigin = new URL(opts.walletUrl).origin;
71
+ }
72
+ on(event, handler) {
73
+ (this.handlers.get(event) ?? this.handlers.set(event, /* @__PURE__ */ new Set()).get(event)).add(handler);
74
+ }
75
+ off(event, handler) {
76
+ this.handlers.get(event)?.delete(handler);
77
+ }
78
+ ensureListener() {
79
+ if (this.listening || typeof window === "undefined") return;
80
+ window.addEventListener("message", this.onMessage);
81
+ this.listening = true;
82
+ }
83
+ /** Resolve "auto" → "parent" when iframed, else "popup". */
84
+ resolveMode() {
85
+ const mode = this.opts.mode ?? "popup";
86
+ if (mode !== "auto") return mode;
87
+ return typeof window !== "undefined" && window.parent !== window ? "parent" : "popup";
88
+ }
89
+ /** Open (or reuse) the wallet (popup window OR the parent frame) and wait for
90
+ * its ready handshake. Concurrent calls share ONE handshake. */
91
+ async open() {
92
+ if (typeof window === "undefined") throw new Error("chipi_connector_requires_browser");
93
+ this.ensureListener();
94
+ const isParent = this.resolveMode() === "parent";
95
+ if (this.ready && this.target && (isParent || !this.target.closed)) return;
96
+ if (this.openPromise) return this.openPromise;
97
+ this.openPromise = this.doOpen(isParent);
98
+ try {
99
+ await this.openPromise;
100
+ } finally {
101
+ this.openPromise = null;
102
+ }
103
+ }
104
+ async doOpen(isParent) {
105
+ if (isParent) {
106
+ if (window.parent === window) throw new Error("chipi_not_in_iframe");
107
+ this.target = window.parent;
108
+ this.ownsTarget = false;
109
+ } else {
110
+ this.ready = false;
111
+ const name = this.opts.windowName ?? `chipi-wallet-${randomId()}`;
112
+ this.target = window.open(
113
+ this.url,
114
+ name,
115
+ this.opts.windowFeatures ?? "popup=yes,width=420,height=680"
116
+ );
117
+ this.ownsTarget = true;
118
+ if (!this.target) throw Object.assign(new Error("Popup blocked"), { code: "popup_blocked" });
119
+ }
120
+ this.readyDeferred = deferred();
121
+ await this.awaitReady();
122
+ }
123
+ async awaitReady() {
124
+ const timeoutMs = this.opts.openTimeoutMs ?? 18e4;
125
+ let timer;
126
+ const timeout = new Promise((_, reject) => {
127
+ timer = setTimeout(() => reject(new Error("wallet_open_timeout")), timeoutMs);
128
+ });
129
+ try {
130
+ await Promise.race([this.readyDeferred.promise, timeout]);
131
+ } finally {
132
+ if (timer) clearTimeout(timer);
133
+ }
134
+ }
135
+ /** Reject every in-flight request (popup closed / disconnected). */
136
+ rejectAllPending(message) {
137
+ for (const [, p] of this.pending) p.reject(Object.assign(new Error(message), { code: 4001 }));
138
+ this.pending.clear();
139
+ }
140
+ /** While requests are in flight, watch for the user closing the popup and
141
+ * reject them: otherwise the dApp's promise would hang forever. */
142
+ startCloseWatch() {
143
+ if (this.closeWatch || !this.ownsTarget) return;
144
+ this.closeWatch = setInterval(() => {
145
+ if (this.target?.closed) {
146
+ this.ready = false;
147
+ this.target = null;
148
+ this.rejectAllPending("User closed the wallet");
149
+ this.stopCloseWatch();
150
+ } else if (this.pending.size === 0) {
151
+ this.stopCloseWatch();
152
+ }
153
+ }, 500);
154
+ }
155
+ stopCloseWatch() {
156
+ if (this.closeWatch) {
157
+ clearInterval(this.closeWatch);
158
+ this.closeWatch = null;
159
+ }
160
+ }
161
+ /** Forward a get-starknet RPC call to the wallet, awaiting its response. */
162
+ async request(call) {
163
+ await this.open();
164
+ if (this.ownsTarget) this.target?.focus();
165
+ const id = randomId();
166
+ const message = {
167
+ channel: CHIPI_WC,
168
+ type: "rpc",
169
+ id,
170
+ origin: window.location.origin,
171
+ call
172
+ };
173
+ return new Promise((resolve, reject) => {
174
+ this.pending.set(id, { resolve, reject, message });
175
+ this.target.postMessage(message, this.walletOrigin);
176
+ this.startCloseWatch();
177
+ });
178
+ }
179
+ /** Close the popup (if we own one) + reject in-flight requests. */
180
+ close() {
181
+ this.stopCloseWatch();
182
+ try {
183
+ if (this.ownsTarget) this.target?.close();
184
+ } catch {
185
+ }
186
+ this.target = null;
187
+ this.ready = false;
188
+ this.rejectAllPending("disconnected");
189
+ if (this.listening && typeof window !== "undefined") {
190
+ window.removeEventListener("message", this.onMessage);
191
+ this.listening = false;
192
+ }
193
+ }
194
+ };
195
+
196
+ // src/register.ts
197
+ var CHIPI_WINDOW_KEY = "starknet_chipi";
198
+ function registerChipiWallet(wallet, target = typeof window !== "undefined" ? window : void 0) {
199
+ if (!target) return { dispose: () => {
200
+ } };
201
+ const store = target;
202
+ store[CHIPI_WINDOW_KEY] = wallet;
203
+ const announce = () => target.dispatchEvent(new CustomEvent("starknet:announceWallet", { detail: wallet }));
204
+ target.addEventListener("starknet:requestWallets", announce);
205
+ announce();
206
+ return {
207
+ dispose: () => {
208
+ target.removeEventListener("starknet:requestWallets", announce);
209
+ if (store[CHIPI_WINDOW_KEY] === wallet) delete store[CHIPI_WINDOW_KEY];
210
+ }
211
+ };
212
+ }
213
+
214
+ // src/icon.ts
215
+ var CHIPI_ICON = "data:image/png;base64,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";
216
+
217
+ // src/connector.ts
218
+ var SN_MAIN = BigInt("0x534e5f4d41494e");
219
+ var ChipiConnector = class extends core.Connector {
220
+ constructor(options = {}) {
221
+ super();
222
+ this._account = null;
223
+ this._swo = null;
224
+ this._registration = null;
225
+ const walletUrl = options.walletUrl ?? options.transport?.walletUrl ?? "https://wallet.chipipay.com";
226
+ this.transport = new ChipiPopupTransport({
227
+ ...options.transport,
228
+ walletUrl,
229
+ mode: "popup"
230
+ // v1: external-dApp popup only (parent host not yet built)
231
+ });
232
+ this._id = options.id ?? "chipi";
233
+ this._name = options.name ?? "Connect with Chipi";
234
+ this._icon = options.icon ?? CHIPI_ICON;
235
+ if (options.register !== false) this.register();
236
+ }
237
+ /**
238
+ * Announce this wallet to scanning dApps (`window.starknet_chipi` +
239
+ * `starknet:announceWallet`). Called automatically from the constructor
240
+ * unless `register: false`. Idempotent and SSR-safe.
241
+ */
242
+ register() {
243
+ if (this._registration) return;
244
+ this._registration = registerChipiWallet(this.swo());
245
+ }
246
+ /** Undo {@link register}: remove the window object + announce listener. */
247
+ unregister() {
248
+ this._registration?.dispose();
249
+ this._registration = null;
250
+ }
251
+ get id() {
252
+ return this._id;
253
+ }
254
+ get name() {
255
+ return this._name;
256
+ }
257
+ get icon() {
258
+ return this._icon;
259
+ }
260
+ /** Hosted wallet: always available (no extension to detect). */
261
+ available() {
262
+ return true;
263
+ }
264
+ /** No silent reconnect in v1: the user re-approves the popup each session. */
265
+ async ready() {
266
+ return this._account !== null;
267
+ }
268
+ /** Lazily build the postMessage-backed get-starknet window object. */
269
+ swo() {
270
+ if (this._swo) return this._swo;
271
+ const transport = this.transport;
272
+ const request = (async (call) => transport.request(call));
273
+ this._swo = {
274
+ id: this._id,
275
+ name: this._name,
276
+ version: "1.0.0",
277
+ icon: typeof this._icon === "string" ? this._icon : this._icon?.dark ?? "",
278
+ request,
279
+ on: ((event, handler) => {
280
+ if (event === "accountsChanged" || event === "networkChanged") transport.on(event, handler);
281
+ }),
282
+ off: ((event, handler) => {
283
+ if (event === "accountsChanged" || event === "networkChanged")
284
+ transport.off(event, handler);
285
+ })
286
+ };
287
+ return this._swo;
288
+ }
289
+ async connect() {
290
+ await this.transport.open();
291
+ const accounts = await this.transport.request({ type: "wallet_requestAccounts" });
292
+ const account = accounts?.[0];
293
+ if (!account) throw new Error("chipi_no_account");
294
+ this._account = account;
295
+ const data = { account, chainId: SN_MAIN };
296
+ this.emitEvent("connect", data);
297
+ return data;
298
+ }
299
+ async disconnect() {
300
+ this.transport.close();
301
+ this._account = null;
302
+ this._swo = null;
303
+ this.emitEvent("disconnect");
304
+ }
305
+ // `Connector` extends eventemitter3's EventEmitter, but the bundled .d.ts
306
+ // doesn't surface `emit` cleanly through the abstract class: reach it via a
307
+ // narrow cast rather than fight the upstream typing.
308
+ emitEvent(event, data) {
309
+ this.emit(event, data);
310
+ }
311
+ async account(provider) {
312
+ if (!this._account) throw new Error("chipi_not_connected");
313
+ return starknet.WalletAccount.connect(provider, this.swo());
314
+ }
315
+ async chainId() {
316
+ return SN_MAIN;
317
+ }
318
+ async request(call) {
319
+ return this.transport.request(call);
320
+ }
321
+ };
322
+
323
+ // src/factory.ts
324
+ function chipi(options) {
325
+ return new ChipiConnector(options);
326
+ }
327
+
328
+ exports.CHIPI_WC = CHIPI_WC;
329
+ exports.CHIPI_WINDOW_KEY = CHIPI_WINDOW_KEY;
330
+ exports.ChipiConnector = ChipiConnector;
331
+ exports.ChipiPopupTransport = ChipiPopupTransport;
332
+ exports.chipi = chipi;
333
+ exports.isChipiDappMessage = isChipiDappMessage;
334
+ exports.isChipiWalletMessage = isChipiWalletMessage;
335
+ exports.registerChipiWallet = registerChipiWallet;
336
+ //# sourceMappingURL=index.cjs.map
337
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/protocol.ts","../src/transport.ts","../src/register.ts","../src/icon.ts","../src/connector.ts","../src/factory.ts"],"names":["Connector","WalletAccount"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Wire protocol between the \"Connect with Chipi\" connector (running in the dApp)\n * and the Chipi hosted wallet (running at `wallet.chipipay.com` in a popup).\n *\n * Both sides import these shapes so the contract stays in lock-step. The\n * transport is `window.postMessage`: the dApp opens the wallet in a popup,\n * forwards get-starknet `wallet_*` RPC calls over the channel, and the wallet\n * answers after the user approves in its own (already-built) approval UI.\n */\n/** A get-starknet RPC call as sent over the wire: just the discriminant +\n * optional params (the full typed `RpcMessage` carries result/errors we don't\n * serialize). */\nexport interface ChipiRpcCall {\n type: string;\n params?: unknown;\n}\n\n/** Namespace tag on every message so we ignore unrelated postMessages. */\nexport const CHIPI_WC = \"chipi-connect/v1\" as const;\n\n/** wallet → dApp: the hosted wallet page finished loading and is listening. */\nexport interface ChipiReadyMessage {\n channel: typeof CHIPI_WC;\n type: \"ready\";\n}\n\n/** dApp → wallet: forward a get-starknet `wallet_*` RPC call. */\nexport interface ChipiRpcRequestMessage {\n channel: typeof CHIPI_WC;\n type: \"rpc\";\n id: string;\n /** The dApp origin, so the wallet can show it + enforce Verify checks. */\n origin: string;\n call: ChipiRpcCall;\n}\n\n/** wallet → dApp: the result (or error) for a given request id. */\nexport type ChipiRpcResultMessage =\n | { channel: typeof CHIPI_WC; type: \"rpc-result\"; id: string; ok: true; result: unknown }\n | {\n channel: typeof CHIPI_WC;\n type: \"rpc-result\";\n id: string;\n ok: false;\n error: { code: number; message: string };\n };\n\n/** wallet → dApp: an account/network change to propagate to the dApp. */\nexport interface ChipiEventMessage {\n channel: typeof CHIPI_WC;\n type: \"event\";\n event: \"accountsChanged\" | \"networkChanged\";\n data: unknown;\n}\n\nexport type ChipiWalletMessage = ChipiReadyMessage | ChipiRpcResultMessage | ChipiEventMessage;\nexport type ChipiDappMessage = ChipiRpcRequestMessage;\n\nexport function isChipiWalletMessage(data: unknown): data is ChipiWalletMessage {\n return (\n typeof data === \"object\" &&\n data !== null &&\n (data as { channel?: unknown }).channel === CHIPI_WC\n );\n}\n\n/** Type guard for a dApp→wallet message (used by the hosted wallet side). */\nexport function isChipiDappMessage(data: unknown): data is ChipiDappMessage {\n return (\n typeof data === \"object\" &&\n data !== null &&\n (data as { channel?: unknown }).channel === CHIPI_WC &&\n (data as { type?: unknown }).type === \"rpc\"\n );\n}\n","/**\n * Client-side (dApp) transport: opens the Chipi hosted wallet in a popup,\n * performs the ready handshake, and forwards get-starknet `wallet_*` RPC calls\n * over `postMessage`, correlating responses by id. The popup is reused across\n * requests; if the user closed it, the next request reopens it.\n */\nimport {\n CHIPI_WC,\n isChipiWalletMessage,\n type ChipiRpcCall,\n type ChipiRpcRequestMessage,\n type ChipiWalletMessage,\n} from \"./protocol.js\";\n\nexport interface ChipiTransportOptions {\n /** Hosted wallet base URL, e.g. `https://wallet.chipipay.com`. */\n walletUrl: string;\n /**\n * Transport mode:\n * - `\"popup\"` (default): open the hosted wallet in a popup window: the\n * universal model, works for any external dApp.\n * - `\"parent\"`: the dApp is embedded in an iframe INSIDE the Chipi wallet\n * (in-app browser); talk to `window.parent` instead of opening a popup, so\n * approval renders inline in the wallet. Only works when the dApp is\n * actually iframed by the Chipi host.\n * - `\"auto\"`: use `\"parent\"` when running inside an iframe, else `\"popup\"`.\n */\n mode?: \"popup\" | \"parent\" | \"auto\";\n /** Popup window name. */\n windowName?: string;\n /** Popup window features. */\n windowFeatures?: string;\n /** Ready-handshake timeout (ms). */\n openTimeoutMs?: number;\n}\n\ntype EventName = \"accountsChanged\" | \"networkChanged\";\ntype EventHandler = (data: unknown) => void;\n\nfunction deferred<T>() {\n let resolve!: (v: T) => void;\n let reject!: (e: unknown) => void;\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n}\n\nfunction randomId(): string {\n // App-runtime ids; uniqueness only needs to hold within one open popup.\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport class ChipiPopupTransport {\n private readonly walletOrigin: string;\n private readonly url: string;\n private target: Window | null = null;\n private ownsTarget = false;\n private ready = false;\n private listening = false;\n private readonly pending = new Map<\n string,\n {\n resolve: (v: unknown) => void;\n reject: (e: unknown) => void;\n message: ChipiRpcRequestMessage;\n }\n >();\n private readonly handlers = new Map<EventName, Set<EventHandler>>();\n private readyDeferred: ReturnType<typeof deferred<void>> | null = null;\n private openPromise: Promise<void> | null = null;\n private closeWatch: ReturnType<typeof setInterval> | null = null;\n\n constructor(private readonly opts: ChipiTransportOptions) {\n this.url = opts.walletUrl.replace(/\\/$/, \"\") + \"/connect\";\n this.walletOrigin = new URL(opts.walletUrl).origin;\n }\n\n on(event: EventName, handler: EventHandler): void {\n (this.handlers.get(event) ?? this.handlers.set(event, new Set()).get(event)!).add(handler);\n }\n\n off(event: EventName, handler: EventHandler): void {\n this.handlers.get(event)?.delete(handler);\n }\n\n private ensureListener(): void {\n if (this.listening || typeof window === \"undefined\") return;\n window.addEventListener(\"message\", this.onMessage);\n this.listening = true;\n }\n\n private onMessage = (e: MessageEvent): void => {\n if (e.origin !== this.walletOrigin || !isChipiWalletMessage(e.data)) return;\n // Isolate to OUR wallet window: without this, a second Chipi popup (another\n // dApp, same origin) could leak its `ready`/`event` into this transport.\n if (this.target && e.source !== this.target) return;\n const msg = e.data as ChipiWalletMessage;\n if (msg.type === \"ready\") {\n this.ready = true;\n this.readyDeferred?.resolve();\n this.readyDeferred = null;\n // A fresh /connect re-announces \"ready\": e.g. after the user signs in,\n // which reloads the popup onto a new page. The request we already sent went\n // to the previous page, which is gone. Re-send any in-flight requests so\n // they reach the new page. The hosted wallet de-dupes by request id, so a\n // repeat (e.g. from the popup's multi-post ready) is harmless.\n if (this.target) {\n for (const p of this.pending.values()) {\n this.target.postMessage(p.message, this.walletOrigin);\n }\n }\n return;\n }\n if (msg.type === \"rpc-result\") {\n const p = this.pending.get(msg.id);\n if (!p) return;\n this.pending.delete(msg.id);\n if (msg.ok) p.resolve(msg.result);\n else p.reject(Object.assign(new Error(msg.error.message), { code: msg.error.code }));\n return;\n }\n if (msg.type === \"event\") {\n this.handlers.get(msg.event)?.forEach((h) => h(msg.data));\n }\n };\n\n /** Resolve \"auto\" → \"parent\" when iframed, else \"popup\". */\n private resolveMode(): \"popup\" | \"parent\" {\n const mode = this.opts.mode ?? \"popup\";\n if (mode !== \"auto\") return mode;\n return typeof window !== \"undefined\" && window.parent !== window ? \"parent\" : \"popup\";\n }\n\n /** Open (or reuse) the wallet (popup window OR the parent frame) and wait for\n * its ready handshake. Concurrent calls share ONE handshake. */\n async open(): Promise<void> {\n if (typeof window === \"undefined\") throw new Error(\"chipi_connector_requires_browser\");\n this.ensureListener();\n const isParent = this.resolveMode() === \"parent\";\n if (this.ready && this.target && (isParent || !this.target.closed)) return;\n if (this.openPromise) return this.openPromise;\n this.openPromise = this.doOpen(isParent);\n try {\n await this.openPromise;\n } finally {\n this.openPromise = null;\n }\n }\n\n private async doOpen(isParent: boolean): Promise<void> {\n if (isParent) {\n if (window.parent === window) throw new Error(\"chipi_not_in_iframe\");\n this.target = window.parent;\n this.ownsTarget = false;\n } else {\n this.ready = false;\n // Unique per-open window name so a reconnect can never reuse a stale popup\n // that still holds a previous session's pending approval.\n const name = this.opts.windowName ?? `chipi-wallet-${randomId()}`;\n this.target = window.open(\n this.url,\n name,\n this.opts.windowFeatures ?? \"popup=yes,width=420,height=680\"\n );\n this.ownsTarget = true;\n if (!this.target) throw Object.assign(new Error(\"Popup blocked\"), { code: \"popup_blocked\" });\n }\n this.readyDeferred = deferred<void>();\n await this.awaitReady();\n }\n\n private async awaitReady(): Promise<void> {\n // Generous: a cold login (Clerk / passkey) can take a while. We only reject\n // here on an outright stall: the popup-closed watcher handles the real\n // \"user gave up / closed it\" case quickly.\n const timeoutMs = this.opts.openTimeoutMs ?? 180_000;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(\"wallet_open_timeout\")), timeoutMs);\n });\n try {\n await Promise.race([this.readyDeferred!.promise, timeout]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n\n /** Reject every in-flight request (popup closed / disconnected). */\n private rejectAllPending(message: string): void {\n for (const [, p] of this.pending) p.reject(Object.assign(new Error(message), { code: 4001 }));\n this.pending.clear();\n }\n\n /** While requests are in flight, watch for the user closing the popup and\n * reject them: otherwise the dApp's promise would hang forever. */\n private startCloseWatch(): void {\n if (this.closeWatch || !this.ownsTarget) return;\n this.closeWatch = setInterval(() => {\n if (this.target?.closed) {\n this.ready = false;\n this.target = null;\n this.rejectAllPending(\"User closed the wallet\");\n this.stopCloseWatch();\n } else if (this.pending.size === 0) {\n this.stopCloseWatch();\n }\n }, 500);\n }\n\n private stopCloseWatch(): void {\n if (this.closeWatch) {\n clearInterval(this.closeWatch);\n this.closeWatch = null;\n }\n }\n\n /** Forward a get-starknet RPC call to the wallet, awaiting its response. */\n async request(call: ChipiRpcCall): Promise<unknown> {\n await this.open();\n if (this.ownsTarget) this.target?.focus();\n const id = randomId();\n const message: ChipiRpcRequestMessage = {\n channel: CHIPI_WC,\n type: \"rpc\",\n id,\n origin: window.location.origin,\n call,\n };\n return new Promise<unknown>((resolve, reject) => {\n this.pending.set(id, { resolve, reject, message });\n this.target!.postMessage(message, this.walletOrigin);\n this.startCloseWatch();\n });\n }\n\n /** Close the popup (if we own one) + reject in-flight requests. */\n close(): void {\n this.stopCloseWatch();\n try {\n if (this.ownsTarget) this.target?.close();\n } catch {\n // ignore\n }\n this.target = null;\n this.ready = false;\n this.rejectAllPending(\"disconnected\");\n if (this.listening && typeof window !== \"undefined\") {\n window.removeEventListener(\"message\", this.onMessage);\n this.listening = false;\n }\n }\n}\n","import type { StarknetWindowObject } from \"@starknet-io/types-js\";\n\n/** Window key get-starknet discovers by scanning for `starknet*` properties. */\nexport const CHIPI_WINDOW_KEY = \"starknet_chipi\";\n\nexport interface ChipiRegistration {\n /** Remove `window.starknet_chipi` + the announce listener. */\n dispose: () => void;\n}\n\n/**\n * Make a Chipi `StarknetWindowObject` discoverable to any get-starknet /\n * starknet-react / starknetkit dApp on the page: WITHOUT an upstream PR and\n * WITHOUT whitelisting. This self-registration covers the apps that scan for\n * wallets rather than importing our connector explicitly.\n *\n * Discovery is announced two ways for maximum reach:\n * 1. **window scan**: set `window.starknet_chipi`. get-starknet v4's\n * `getAvailableWallets()` finds every `window` key starting with `starknet`.\n * 2. **event announce**: dispatch `starknet:announceWallet` now and again on\n * the dApp's `starknet:requestWallets` (the EIP-6963-style, timing-robust\n * Starknet Wallet Standard discovery path).\n *\n * SSR-safe (no-ops when there's no `window`) and idempotent per (target, wallet).\n */\nexport function registerChipiWallet(\n wallet: StarknetWindowObject,\n target: (Window & typeof globalThis) | undefined = typeof window !== \"undefined\"\n ? window\n : undefined\n): ChipiRegistration {\n if (!target) return { dispose: () => {} };\n\n const store = target as unknown as Record<string, unknown>;\n // 1. Classic window-scan discovery.\n store[CHIPI_WINDOW_KEY] = wallet;\n\n // 2. Event-based discovery (announce now + whenever a dApp asks).\n const announce = () =>\n target.dispatchEvent(new CustomEvent(\"starknet:announceWallet\", { detail: wallet }));\n target.addEventListener(\"starknet:requestWallets\", announce);\n announce();\n\n return {\n dispose: () => {\n target.removeEventListener(\"starknet:requestWallets\", announce);\n // Only remove our own object: never clobber a newer injector's wallet.\n if (store[CHIPI_WINDOW_KEY] === wallet) delete store[CHIPI_WINDOW_KEY];\n },\n };\n}\n","// Chipi brand wallet icon: the current luchador mark on a transparent\n// background, 48x48 PNG (same asset used by the browser extension's\n// toolbar icon). A data-URI is what get-starknet / wallet pickers render.\nexport const CHIPI_ICON = \"data:image/png;base64,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\";\n","/**\n * `ChipiConnector`: a starknet-react / get-starknet connector for the Chipi\n * hosted smart-account wallet. A self-contained connector package any dApp\n * adds to its `connectors` array (`new ChipiConnector()`) directly: no\n * whitelisting, no dependency on a third-party wallet kit, and NO browser\n * extension required. Clicking \"Connect with Chipi\" opens our hosted wallet\n * (passkey + gasless paymaster) in a popup; the dApp's `wallet_*` RPC calls are\n * forwarded over postMessage and answered after the user approves in Chipi's\n * own (already-built) approval UI.\n */\nimport { Connector } from \"@starknet-react/core\";\nimport { WalletAccount } from \"starknet\";\nimport type { AccountInterface, ProviderInterface } from \"starknet\";\nimport type {\n RpcMessage,\n RequestFnCall,\n RpcTypeToMessageMap,\n StarknetWindowObject,\n} from \"@starknet-io/types-js\";\nimport { ChipiPopupTransport, type ChipiTransportOptions } from \"./transport.js\";\nimport { registerChipiWallet, type ChipiRegistration } from \"./register.js\";\nimport { CHIPI_ICON } from \"./icon.js\";\n\n// @starknet-react/core declares these internally but doesn't export them; mirror\n// the shapes (ConnectorIcons === get-starknet's StarknetWindowObject[\"icon\"]).\ntype ConnectorIcons = StarknetWindowObject[\"icon\"];\ntype ConnectorData = { account?: string; chainId?: bigint };\n\n/** Starknet mainnet chain id (felt of the shortstring \"SN_MAIN\"). */\nconst SN_MAIN = BigInt(\"0x534e5f4d41494e\");\n\nexport interface ChipiConnectorOptions {\n /** Hosted wallet base URL. Defaults to `https://wallet.chipipay.com`. */\n walletUrl?: string;\n /** Override the connector id / display name / icon if embedding. */\n id?: string;\n name?: string;\n icon?: ConnectorIcons;\n transport?: ChipiTransportOptions;\n /**\n * Self-register the wallet on `window` (set `window.starknet_chipi` + announce\n * via `starknet:announceWallet`) so dApps that *scan* for wallets, raw\n * get-starknet / Wallet-Standard consumers that don't import this connector,\n * also discover \"Connect with Chipi\". Defaults to `true` in a browser; pass\n * `false` to opt out (e.g. to avoid a double entry in a picker that already\n * lists the connector explicitly). No-op during SSR.\n */\n register?: boolean;\n // NOTE: the in-app-browser (\"parent\") transport mode is implemented in the\n // transport but NOT yet supported by the hosted wallet side, so it's not\n // exposed here in v1. Use popup (external dApps) only.\n}\n\nexport class ChipiConnector extends Connector {\n private readonly transport: ChipiPopupTransport;\n private readonly _id: string;\n private readonly _name: string;\n private readonly _icon: ConnectorIcons;\n private _account: string | null = null;\n private _swo: StarknetWindowObject | null = null;\n private _registration: ChipiRegistration | null = null;\n\n constructor(options: ChipiConnectorOptions = {}) {\n super();\n const walletUrl =\n options.walletUrl ?? options.transport?.walletUrl ?? \"https://wallet.chipipay.com\";\n this.transport = new ChipiPopupTransport({\n ...options.transport,\n walletUrl,\n mode: \"popup\", // v1: external-dApp popup only (parent host not yet built)\n });\n this._id = options.id ?? \"chipi\";\n this._name = options.name ?? \"Connect with Chipi\";\n this._icon = options.icon ?? CHIPI_ICON;\n if (options.register !== false) this.register();\n }\n\n /**\n * Announce this wallet to scanning dApps (`window.starknet_chipi` +\n * `starknet:announceWallet`). Called automatically from the constructor\n * unless `register: false`. Idempotent and SSR-safe.\n */\n register(): void {\n if (this._registration) return;\n this._registration = registerChipiWallet(this.swo());\n }\n\n /** Undo {@link register}: remove the window object + announce listener. */\n unregister(): void {\n this._registration?.dispose();\n this._registration = null;\n }\n\n get id(): string {\n return this._id;\n }\n\n get name(): string {\n return this._name;\n }\n\n get icon(): ConnectorIcons {\n return this._icon;\n }\n\n /** Hosted wallet: always available (no extension to detect). */\n available(): boolean {\n return true;\n }\n\n /** No silent reconnect in v1: the user re-approves the popup each session. */\n async ready(): Promise<boolean> {\n return this._account !== null;\n }\n\n /** Lazily build the postMessage-backed get-starknet window object. */\n private swo(): StarknetWindowObject {\n if (this._swo) return this._swo;\n const transport = this.transport;\n const request = (async (call: RpcMessage) =>\n transport.request(call)) as StarknetWindowObject[\"request\"];\n this._swo = {\n id: this._id,\n name: this._name,\n version: \"1.0.0\",\n icon: typeof this._icon === \"string\" ? this._icon : (this._icon?.dark ?? \"\"),\n request,\n on: ((event: string, handler: (data: unknown) => void) => {\n if (event === \"accountsChanged\" || event === \"networkChanged\") transport.on(event, handler);\n }) as StarknetWindowObject[\"on\"],\n off: ((event: string, handler: (data: unknown) => void) => {\n if (event === \"accountsChanged\" || event === \"networkChanged\")\n transport.off(event, handler);\n }) as StarknetWindowObject[\"off\"],\n };\n return this._swo;\n }\n\n async connect(): Promise<ConnectorData> {\n await this.transport.open();\n const accounts = (await this.transport.request({ type: \"wallet_requestAccounts\" })) as string[];\n const account = accounts?.[0];\n if (!account) throw new Error(\"chipi_no_account\");\n this._account = account;\n const data: ConnectorData = { account, chainId: SN_MAIN };\n this.emitEvent(\"connect\", data);\n return data;\n }\n\n async disconnect(): Promise<void> {\n this.transport.close();\n this._account = null;\n this._swo = null;\n this.emitEvent(\"disconnect\");\n }\n\n // `Connector` extends eventemitter3's EventEmitter, but the bundled .d.ts\n // doesn't surface `emit` cleanly through the abstract class: reach it via a\n // narrow cast rather than fight the upstream typing.\n private emitEvent(event: \"connect\" | \"disconnect\", data?: ConnectorData): void {\n (this as unknown as { emit: (e: string, d?: ConnectorData) => void }).emit(event, data);\n }\n\n async account(provider: ProviderInterface): Promise<AccountInterface> {\n if (!this._account) throw new Error(\"chipi_not_connected\");\n // WalletAccount routes execute()/signMessage() through the SWO's request(),\n // i.e. over our postMessage channel to the hosted wallet.\n return WalletAccount.connect(provider, this.swo());\n }\n\n async chainId(): Promise<bigint> {\n return SN_MAIN;\n }\n\n async request<T extends RpcMessage[\"type\"]>(\n call: RequestFnCall<T>\n ): Promise<RpcTypeToMessageMap[T][\"result\"]> {\n return this.transport.request(call) as Promise<RpcTypeToMessageMap[T][\"result\"]>;\n }\n}\n","import { ChipiConnector, type ChipiConnectorOptions } from \"./connector.js\";\n\n/**\n * Plain-function form of {@link ChipiConnector}, for parity with\n * `@starknet-react/core`'s built-in factories (`ready()`, `braavos()`):\n *\n * const connectors = [chipi(), ready(), braavos()];\n *\n * Equivalent to `new ChipiConnector(options)`: use whichever reads better\n * in your `connectors` array.\n */\nexport function chipi(options?: ChipiConnectorOptions): ChipiConnector {\n return new ChipiConnector(options);\n}\n"]}