@chipi-stack/starknet-connector 0.3.0 → 0.4.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/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Connector } from '@starknet-react/core';
2
2
  import { ProviderInterface, AccountInterface } from 'starknet';
3
- import { StarknetWindowObject, RpcMessage, RequestFnCall, RpcTypeToMessageMap } from '@starknet-io/types-js';
3
+ import { StarknetWindowObject, RpcMessage, RequestFnCall, RpcTypeToMessageMap, RequestFn } from '@starknet-io/types-js';
4
4
 
5
5
  /**
6
6
  * Wire protocol between the "Connect with Chipi" connector (running in the dApp)
@@ -68,7 +68,9 @@ declare function isChipiDappMessage(data: unknown): data is ChipiDappMessage;
68
68
  * Client-side (dApp) transport: opens the Chipi hosted wallet in a popup,
69
69
  * performs the ready handshake, and forwards get-starknet `wallet_*` RPC calls
70
70
  * over `postMessage`, correlating responses by id. The popup is reused across
71
- * requests; if the user closed it, the next request reopens it.
71
+ * requests. If the user closes it, later requests reject with `POPUP_CLOSED`
72
+ * instead of reopening it: `window.open` outside a click is blocked by
73
+ * browsers, so the dApp must call `connect()` (or `open()`) again from a click.
72
74
  */
73
75
 
74
76
  interface ChipiTransportOptions {
@@ -89,9 +91,19 @@ interface ChipiTransportOptions {
89
91
  windowName?: string;
90
92
  /** Popup window features. */
91
93
  windowFeatures?: string;
92
- /** Ready-handshake timeout (ms). */
94
+ /** Ready-handshake timeout (ms). Defaults to 180_000. On timeout the popup is
95
+ * closed and the transport resets, so the next `open()` starts clean. */
93
96
  openTimeoutMs?: number;
97
+ /**
98
+ * Per-request timeout (ms), counted from when the request is posted to the
99
+ * wallet. Defaults to 120_000. A request that gets no answer in time rejects
100
+ * with an Error whose `code` (and `name`) is `"REQUEST_TIMEOUT"`. Pass `0` to
101
+ * disable.
102
+ */
103
+ requestTimeoutMs?: number;
94
104
  }
105
+ /** Error codes the transport attaches to `Error.code` (besides wallet codes). */
106
+ type ChipiTransportErrorCode = "REQUEST_TIMEOUT" | "POPUP_CLOSED";
95
107
  type EventName = "accountsChanged" | "networkChanged";
96
108
  type EventHandler = (data: unknown) => void;
97
109
  declare class ChipiPopupTransport {
@@ -107,6 +119,9 @@ declare class ChipiPopupTransport {
107
119
  private readyDeferred;
108
120
  private openPromise;
109
121
  private closeWatch;
122
+ /** True once this transport opened a popup. A later request with no live
123
+ * popup means the user closed it: reject instead of reopening off-gesture. */
124
+ private hadPopup;
110
125
  constructor(opts: ChipiTransportOptions);
111
126
  on(event: EventName, handler: EventHandler): void;
112
127
  off(event: EventName, handler: EventHandler): void;
@@ -118,6 +133,8 @@ declare class ChipiPopupTransport {
118
133
  * its ready handshake. Concurrent calls share ONE handshake. */
119
134
  open(): Promise<void>;
120
135
  private doOpen;
136
+ /** Close the popup (if we own one) and forget the target + ready state. */
137
+ private resetTarget;
121
138
  private awaitReady;
122
139
  /** Reject every in-flight request (popup closed / disconnected). */
123
140
  private rejectAllPending;
@@ -125,7 +142,15 @@ declare class ChipiPopupTransport {
125
142
  * reject them: otherwise the dApp's promise would hang forever. */
126
143
  private startCloseWatch;
127
144
  private stopCloseWatch;
128
- /** Forward a get-starknet RPC call to the wallet, awaiting its response. */
145
+ /**
146
+ * Forward a get-starknet RPC call to the wallet, awaiting its response.
147
+ *
148
+ * The first request may open the popup. Once a popup has been opened, a
149
+ * request made after it was closed rejects with `code: "POPUP_CLOSED"`
150
+ * instead of calling `window.open` again: requests usually run outside a
151
+ * click, where browsers block popups. Reopen via `connect()` / `open()`
152
+ * from a click.
153
+ */
129
154
  request(call: ChipiRpcCall): Promise<unknown>;
130
155
  /** Close the popup (if we own one) + reject in-flight requests. */
131
156
  close(): void;
@@ -147,6 +172,10 @@ type ConnectorData = {
147
172
  account?: string;
148
173
  chainId?: bigint;
149
174
  };
175
+ /** Mirrors starknet-react's `ConnectArgs` (not exported by every version). */
176
+ type ConnectArgs = {
177
+ chainIdHint?: bigint;
178
+ };
150
179
  interface ChipiConnectorOptions {
151
180
  /** Hosted wallet base URL. Defaults to `https://wallet.chipipay.com`. */
152
181
  walletUrl?: string;
@@ -173,6 +202,7 @@ declare class ChipiConnector extends Connector {
173
202
  private _account;
174
203
  private _swo;
175
204
  private _registration;
205
+ private readonly _autoRegister;
176
206
  constructor(options?: ChipiConnectorOptions);
177
207
  /**
178
208
  * Announce this wallet to scanning dApps (`window.starknet_chipi` +
@@ -191,8 +221,18 @@ declare class ChipiConnector extends Connector {
191
221
  ready(): Promise<boolean>;
192
222
  /** Lazily build the postMessage-backed get-starknet window object. */
193
223
  private swo;
194
- connect(): Promise<ConnectorData>;
224
+ /**
225
+ * Open the hosted wallet (call from a click: it opens a popup) and request
226
+ * the account. Chipi is mainnet-only: a `chainIdHint` other than SN_MAIN
227
+ * rejects before any popup opens.
228
+ */
229
+ connect(args?: ConnectArgs): Promise<ConnectorData>;
195
230
  disconnect(): Promise<void>;
231
+ /** Forward the wallet's account/network events as starknet-react events. */
232
+ private subscribe;
233
+ private unsubscribe;
234
+ private onAccountsChanged;
235
+ private onNetworkChanged;
196
236
  private emitEvent;
197
237
  account(provider: ProviderInterface): Promise<AccountInterface>;
198
238
  chainId(): Promise<bigint>;
@@ -233,4 +273,100 @@ interface ChipiRegistration {
233
273
  */
234
274
  declare function registerChipiWallet(wallet: StarknetWindowObject, target?: (Window & typeof globalThis) | undefined): ChipiRegistration;
235
275
 
236
- export { CHIPI_WC, CHIPI_WINDOW_KEY, ChipiConnector, type ChipiConnectorOptions, type ChipiDappMessage, type ChipiEventMessage, ChipiPopupTransport, type ChipiReadyMessage, type ChipiRegistration, type ChipiRpcCall, type ChipiRpcRequestMessage, type ChipiRpcResultMessage, type ChipiTransportOptions, type ChipiWalletMessage, chipi, isChipiDappMessage, isChipiWalletMessage, registerChipiWallet };
276
+ /**
277
+ * Chipi as a Wallet Standard wallet with Starknet features
278
+ * (`WalletWithStarknetFeatures` from `@starknet-io/get-starknet-wallet-standard`),
279
+ * so dApps on get-starknet v5+/v6 discovery (`@starknet-io/get-starknet-discovery`,
280
+ * `@starknet-start/react`, anything that listens for
281
+ * `wallet-standard:register-wallet`) list "Chipi" without importing this
282
+ * package's connector.
283
+ *
284
+ * Backed by the same popup transport as {@link ChipiConnector}. The types
285
+ * below mirror the upstream interfaces structurally so this package keeps no
286
+ * runtime (or type) dependency on `@wallet-standard/*`.
287
+ */
288
+
289
+ /** Wallet Standard chain id for Starknet mainnet: `starknet:` + hex of "SN_MAIN"
290
+ * (same as `WELL_KNOWN_STARKNET_CHAINS[0]` in get-starknet-wallet-standard). */
291
+ declare const CHIPI_STARKNET_MAINNET_CHAIN: "starknet:0x534e5f4d41494e";
292
+ /** `starknet:0x...` chain identifier. */
293
+ type ChipiStarknetChain = `starknet:0x${string}`;
294
+ /** Data-URI icon, as Wallet Standard requires. */
295
+ type ChipiWalletIcon = `data:image/${"svg+xml" | "webp" | "png" | "gif"};base64,${string}`;
296
+ /** Mirrors `@wallet-standard/base` `WalletAccount`. */
297
+ interface ChipiStandardWalletAccount {
298
+ readonly address: string;
299
+ readonly publicKey: Uint8Array;
300
+ readonly chains: readonly ChipiStarknetChain[];
301
+ readonly features: readonly `${string}:${string}`[];
302
+ }
303
+ /** Mirrors `@wallet-standard/features` `StandardEventsChangeProperties`. */
304
+ interface ChipiStandardChangeProperties {
305
+ readonly chains?: readonly ChipiStarknetChain[];
306
+ readonly accounts?: readonly ChipiStandardWalletAccount[];
307
+ }
308
+ /** Mirrors `StarknetFeatures` from `@starknet-io/get-starknet-wallet-standard`.
309
+ * (A type alias, not an interface, so it satisfies Wallet Standard's
310
+ * `IdentifierRecord` index signature.) */
311
+ type ChipiStandardWalletFeatures = {
312
+ readonly "starknet:walletApi": {
313
+ readonly version: "1.0.0";
314
+ readonly request: RequestFn;
315
+ readonly walletVersion: string;
316
+ readonly id: string;
317
+ };
318
+ readonly "standard:connect": {
319
+ readonly version: "1.0.0";
320
+ readonly connect: (input?: {
321
+ readonly silent?: boolean;
322
+ }) => Promise<{
323
+ readonly accounts: readonly ChipiStandardWalletAccount[];
324
+ }>;
325
+ };
326
+ readonly "standard:disconnect": {
327
+ readonly version: "1.0.0";
328
+ readonly disconnect: () => Promise<void>;
329
+ };
330
+ readonly "standard:events": {
331
+ readonly version: "1.0.0";
332
+ readonly on: <E extends "change">(event: E, listener: (properties: ChipiStandardChangeProperties) => void) => () => void;
333
+ };
334
+ };
335
+ /** Structurally a `WalletWithStarknetFeatures`. */
336
+ interface ChipiStandardWallet {
337
+ readonly version: "1.0.0";
338
+ readonly name: string;
339
+ readonly icon: ChipiWalletIcon;
340
+ readonly chains: readonly ChipiStarknetChain[];
341
+ readonly accounts: readonly ChipiStandardWalletAccount[];
342
+ readonly features: ChipiStandardWalletFeatures;
343
+ }
344
+ interface ChipiStandardWalletOptions {
345
+ /** Hosted wallet base URL. Defaults to `https://wallet.chipipay.com`. */
346
+ walletUrl?: string;
347
+ /** Display name. Defaults to `"Chipi"`. */
348
+ name?: string;
349
+ /** Data-URI icon. Defaults to the Chipi icon. */
350
+ icon?: ChipiWalletIcon;
351
+ /** Popup transport tuning (window name/features, timeouts). */
352
+ transport?: Omit<ChipiTransportOptions, "walletUrl" | "mode">;
353
+ }
354
+ /**
355
+ * Build the Chipi Wallet Standard wallet (without registering it). `connect`
356
+ * opens the popup, so dApps call it from a click; `connect({ silent: true })`
357
+ * never opens a popup and returns the current accounts (empty if not
358
+ * connected).
359
+ */
360
+ declare function createChipiStandardWallet(options?: ChipiStandardWalletOptions): ChipiStandardWallet;
361
+ /**
362
+ * Register Chipi with every Wallet Standard app on the page: dispatches
363
+ * `wallet-standard:register-wallet` now and answers later
364
+ * `wallet-standard:app-ready` events (the `@wallet-standard/wallet`
365
+ * `registerWallet` protocol, implemented here without the dependency).
366
+ *
367
+ * Returns an unregister function that removes the listener and unregisters
368
+ * from every app that accepted the wallet. SSR-safe: a no-op without `window`.
369
+ */
370
+ declare function registerChipiStandardWallet(options?: ChipiStandardWalletOptions, target?: (Window & typeof globalThis) | undefined): () => void;
371
+
372
+ export { CHIPI_STARKNET_MAINNET_CHAIN, CHIPI_WC, CHIPI_WINDOW_KEY, ChipiConnector, type ChipiConnectorOptions, type ChipiDappMessage, type ChipiEventMessage, ChipiPopupTransport, type ChipiReadyMessage, type ChipiRegistration, type ChipiRpcCall, type ChipiRpcRequestMessage, type ChipiRpcResultMessage, type ChipiStandardChangeProperties, type ChipiStandardWallet, type ChipiStandardWalletAccount, type ChipiStandardWalletFeatures, type ChipiStandardWalletOptions, type ChipiStarknetChain, type ChipiTransportErrorCode, type ChipiTransportOptions, type ChipiWalletIcon, type ChipiWalletMessage, chipi, createChipiStandardWallet, isChipiDappMessage, isChipiWalletMessage, registerChipiStandardWallet, registerChipiWallet };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Connector } from '@starknet-react/core';
2
- import { WalletAccount } from 'starknet';
2
+ import { constants, WalletAccount } from 'starknet';
3
3
 
4
4
  // src/connector.ts
5
5
 
@@ -13,6 +13,22 @@ function isChipiDappMessage(data) {
13
13
  }
14
14
 
15
15
  // src/transport.ts
16
+ function transportError(code, message) {
17
+ const err = Object.assign(new Error(message), { code });
18
+ err.name = code;
19
+ return err;
20
+ }
21
+ function stripUndefined(value) {
22
+ if (Array.isArray(value)) return value.map((v) => stripUndefined(v));
23
+ if (value === null || typeof value !== "object") return value;
24
+ const proto = Object.getPrototypeOf(value);
25
+ if (proto !== Object.prototype && proto !== null) return value;
26
+ const out = {};
27
+ for (const [k, v] of Object.entries(value)) {
28
+ if (v !== void 0) out[k] = stripUndefined(v);
29
+ }
30
+ return out;
31
+ }
16
32
  function deferred() {
17
33
  let resolve;
18
34
  let reject;
@@ -37,18 +53,19 @@ var ChipiPopupTransport = class {
37
53
  this.readyDeferred = null;
38
54
  this.openPromise = null;
39
55
  this.closeWatch = null;
56
+ /** True once this transport opened a popup. A later request with no live
57
+ * popup means the user closed it: reject instead of reopening off-gesture. */
58
+ this.hadPopup = false;
40
59
  this.onMessage = (e) => {
41
60
  if (e.origin !== this.walletOrigin || !isChipiWalletMessage(e.data)) return;
42
- if (this.target && e.source !== this.target) return;
61
+ if (!this.target || e.source !== this.target) return;
43
62
  const msg = e.data;
44
63
  if (msg.type === "ready") {
45
64
  this.ready = true;
46
65
  this.readyDeferred?.resolve();
47
66
  this.readyDeferred = null;
48
- if (this.target) {
49
- for (const p of this.pending.values()) {
50
- this.target.postMessage(p.message, this.walletOrigin);
51
- }
67
+ for (const p of this.pending.values()) {
68
+ this.target.postMessage(p.message, this.walletOrigin);
52
69
  }
53
70
  return;
54
71
  }
@@ -56,6 +73,7 @@ var ChipiPopupTransport = class {
56
73
  const p = this.pending.get(msg.id);
57
74
  if (!p) return;
58
75
  this.pending.delete(msg.id);
76
+ if (p.timer) clearTimeout(p.timer);
59
77
  if (msg.ok) p.resolve(msg.result);
60
78
  else p.reject(Object.assign(new Error(msg.error.message), { code: msg.error.code }));
61
79
  return;
@@ -114,9 +132,26 @@ var ChipiPopupTransport = class {
114
132
  );
115
133
  this.ownsTarget = true;
116
134
  if (!this.target) throw Object.assign(new Error("Popup blocked"), { code: "popup_blocked" });
135
+ this.hadPopup = true;
117
136
  }
137
+ const opened = this.target;
118
138
  this.readyDeferred = deferred();
119
- await this.awaitReady();
139
+ try {
140
+ await this.awaitReady();
141
+ } catch (err) {
142
+ if (this.target === opened) this.resetTarget();
143
+ throw err;
144
+ }
145
+ }
146
+ /** Close the popup (if we own one) and forget the target + ready state. */
147
+ resetTarget() {
148
+ try {
149
+ if (this.ownsTarget) this.target?.close();
150
+ } catch {
151
+ }
152
+ this.target = null;
153
+ this.ready = false;
154
+ this.readyDeferred = null;
120
155
  }
121
156
  async awaitReady() {
122
157
  const timeoutMs = this.opts.openTimeoutMs ?? 18e4;
@@ -132,7 +167,10 @@ var ChipiPopupTransport = class {
132
167
  }
133
168
  /** Reject every in-flight request (popup closed / disconnected). */
134
169
  rejectAllPending(message) {
135
- for (const [, p] of this.pending) p.reject(Object.assign(new Error(message), { code: 4001 }));
170
+ for (const [, p] of this.pending) {
171
+ if (p.timer) clearTimeout(p.timer);
172
+ p.reject(Object.assign(new Error(message), { code: 4001 }));
173
+ }
136
174
  this.pending.clear();
137
175
  }
138
176
  /** While requests are in flight, watch for the user closing the popup and
@@ -156,8 +194,22 @@ var ChipiPopupTransport = class {
156
194
  this.closeWatch = null;
157
195
  }
158
196
  }
159
- /** Forward a get-starknet RPC call to the wallet, awaiting its response. */
197
+ /**
198
+ * Forward a get-starknet RPC call to the wallet, awaiting its response.
199
+ *
200
+ * The first request may open the popup. Once a popup has been opened, a
201
+ * request made after it was closed rejects with `code: "POPUP_CLOSED"`
202
+ * instead of calling `window.open` again: requests usually run outside a
203
+ * click, where browsers block popups. Reopen via `connect()` / `open()`
204
+ * from a click.
205
+ */
160
206
  async request(call) {
207
+ if (this.hadPopup && this.resolveMode() === "popup" && (!this.target || this.target.closed)) {
208
+ throw transportError(
209
+ "POPUP_CLOSED",
210
+ "The Chipi wallet window was closed. Call connect() again from a click."
211
+ );
212
+ }
161
213
  await this.open();
162
214
  if (this.ownsTarget) this.target?.focus();
163
215
  const id = randomId();
@@ -166,10 +218,24 @@ var ChipiPopupTransport = class {
166
218
  type: "rpc",
167
219
  id,
168
220
  origin: window.location.origin,
169
- call
221
+ call: stripUndefined(call)
170
222
  };
223
+ const timeoutMs = this.opts.requestTimeoutMs ?? 12e4;
171
224
  return new Promise((resolve, reject) => {
172
- this.pending.set(id, { resolve, reject, message });
225
+ const entry = { resolve, reject, message };
226
+ if (timeoutMs > 0 && Number.isFinite(timeoutMs)) {
227
+ entry.timer = setTimeout(() => {
228
+ if (this.pending.get(id) !== entry) return;
229
+ this.pending.delete(id);
230
+ reject(
231
+ transportError(
232
+ "REQUEST_TIMEOUT",
233
+ `The Chipi wallet did not answer "${call.type}" within ${timeoutMs} ms.`
234
+ )
235
+ );
236
+ }, timeoutMs);
237
+ }
238
+ this.pending.set(id, entry);
173
239
  this.target.postMessage(message, this.walletOrigin);
174
240
  this.startCloseWatch();
175
241
  });
@@ -177,12 +243,8 @@ var ChipiPopupTransport = class {
177
243
  /** Close the popup (if we own one) + reject in-flight requests. */
178
244
  close() {
179
245
  this.stopCloseWatch();
180
- try {
181
- if (this.ownsTarget) this.target?.close();
182
- } catch {
183
- }
184
- this.target = null;
185
- this.ready = false;
246
+ this.readyDeferred?.reject(Object.assign(new Error("disconnected"), { code: 4001 }));
247
+ this.resetTarget();
186
248
  this.rejectAllPending("disconnected");
187
249
  if (this.listening && typeof window !== "undefined") {
188
250
  window.removeEventListener("message", this.onMessage);
@@ -213,13 +275,46 @@ function registerChipiWallet(wallet, target = typeof window !== "undefined" ? wi
213
275
  var CHIPI_ICON = "data:image/png;base64,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";
214
276
 
215
277
  // src/connector.ts
216
- var SN_MAIN = BigInt("0x534e5f4d41494e");
278
+ var SN_MAIN = BigInt(constants.StarknetChainId.SN_MAIN);
279
+ function toChainId(value) {
280
+ if (typeof value === "bigint") return value;
281
+ if (typeof value === "number" || typeof value === "string") {
282
+ try {
283
+ return BigInt(value);
284
+ } catch {
285
+ return void 0;
286
+ }
287
+ }
288
+ return void 0;
289
+ }
217
290
  var ChipiConnector = class extends Connector {
218
291
  constructor(options = {}) {
219
292
  super();
220
293
  this._account = null;
221
294
  this._swo = null;
222
295
  this._registration = null;
296
+ this.onAccountsChanged = (data) => {
297
+ const accounts = Array.isArray(data) ? data : [];
298
+ const account = accounts[0];
299
+ if (typeof account === "string" && account) {
300
+ this._account = account;
301
+ this.emitEvent("change", { account, chainId: SN_MAIN });
302
+ } else {
303
+ this._account = null;
304
+ this.emitEvent("disconnect");
305
+ }
306
+ };
307
+ this.onNetworkChanged = (data) => {
308
+ const payload = typeof data === "object" && data !== null && !Array.isArray(data) ? data : { chainId: data };
309
+ const chainId = toChainId(payload.chainId);
310
+ const accounts = Array.isArray(payload.accounts) ? payload.accounts : [];
311
+ const next = typeof accounts[0] === "string" && accounts[0] ? accounts[0] : this._account;
312
+ if (next) this._account = next;
313
+ const change = {};
314
+ if (chainId !== void 0) change.chainId = chainId;
315
+ if (next) change.account = next;
316
+ this.emitEvent("change", change);
317
+ };
223
318
  const walletUrl = options.walletUrl ?? options.transport?.walletUrl ?? "https://wallet.chipipay.com";
224
319
  this.transport = new ChipiPopupTransport({
225
320
  ...options.transport,
@@ -230,7 +325,8 @@ var ChipiConnector = class extends Connector {
230
325
  this._id = options.id ?? "chipi";
231
326
  this._name = options.name ?? "Connect with Chipi";
232
327
  this._icon = options.icon ?? CHIPI_ICON;
233
- if (options.register !== false) this.register();
328
+ this._autoRegister = options.register !== false;
329
+ if (this._autoRegister) this.register();
234
330
  }
235
331
  /**
236
332
  * Announce this wallet to scanning dApps (`window.starknet_chipi` +
@@ -284,7 +380,22 @@ var ChipiConnector = class extends Connector {
284
380
  };
285
381
  return this._swo;
286
382
  }
287
- async connect() {
383
+ /**
384
+ * Open the hosted wallet (call from a click: it opens a popup) and request
385
+ * the account. Chipi is mainnet-only: a `chainIdHint` other than SN_MAIN
386
+ * rejects before any popup opens.
387
+ */
388
+ async connect(args = {}) {
389
+ if (args.chainIdHint !== void 0 && BigInt(args.chainIdHint) !== SN_MAIN) {
390
+ throw Object.assign(
391
+ new Error(
392
+ `Chipi is mainnet-only: chainIdHint 0x${BigInt(args.chainIdHint).toString(16)} is not SN_MAIN.`
393
+ ),
394
+ { code: "UNSUPPORTED_CHAIN" }
395
+ );
396
+ }
397
+ if (this._autoRegister) this.register();
398
+ this.subscribe();
288
399
  await this.transport.open();
289
400
  const accounts = await this.transport.request({ type: "wallet_requestAccounts" });
290
401
  const account = accounts?.[0];
@@ -295,16 +406,27 @@ var ChipiConnector = class extends Connector {
295
406
  return data;
296
407
  }
297
408
  async disconnect() {
409
+ this.unsubscribe();
298
410
  this.transport.close();
299
411
  this._account = null;
412
+ this.unregister();
300
413
  this._swo = null;
301
414
  this.emitEvent("disconnect");
302
415
  }
303
- // `Connector` extends eventemitter3's EventEmitter, but the bundled .d.ts
304
- // doesn't surface `emit` cleanly through the abstract class: reach it via a
305
- // narrow cast rather than fight the upstream typing.
416
+ /** Forward the wallet's account/network events as starknet-react events. */
417
+ subscribe() {
418
+ this.unsubscribe();
419
+ this.transport.on("accountsChanged", this.onAccountsChanged);
420
+ this.transport.on("networkChanged", this.onNetworkChanged);
421
+ }
422
+ unsubscribe() {
423
+ this.transport.off("accountsChanged", this.onAccountsChanged);
424
+ this.transport.off("networkChanged", this.onNetworkChanged);
425
+ }
306
426
  emitEvent(event, data) {
307
- this.emit(event, data);
427
+ const emitter = this;
428
+ if (data === void 0) emitter.emit(event);
429
+ else emitter.emit(event, data);
308
430
  }
309
431
  async account(provider) {
310
432
  if (!this._account) throw new Error("chipi_not_connected");
@@ -323,6 +445,144 @@ function chipi(options) {
323
445
  return new ChipiConnector(options);
324
446
  }
325
447
 
326
- export { CHIPI_WC, CHIPI_WINDOW_KEY, ChipiConnector, ChipiPopupTransport, chipi, isChipiDappMessage, isChipiWalletMessage, registerChipiWallet };
448
+ // src/standard.ts
449
+ var CHIPI_STARKNET_MAINNET_CHAIN = "starknet:0x534e5f4d41494e";
450
+ function toStarknetChain(value) {
451
+ if (typeof value !== "string" && typeof value !== "bigint" && typeof value !== "number") {
452
+ return void 0;
453
+ }
454
+ try {
455
+ return `starknet:0x${BigInt(value).toString(16)}`;
456
+ } catch {
457
+ return void 0;
458
+ }
459
+ }
460
+ function createChipiStandardWallet(options = {}) {
461
+ const transport = new ChipiPopupTransport({
462
+ ...options.transport,
463
+ walletUrl: options.walletUrl ?? "https://wallet.chipipay.com",
464
+ mode: "popup"
465
+ });
466
+ const listeners = /* @__PURE__ */ new Set();
467
+ let current = null;
468
+ const accounts = () => current ? [
469
+ {
470
+ address: current.address,
471
+ publicKey: new Uint8Array(),
472
+ chains: [current.chain],
473
+ features: []
474
+ }
475
+ ] : [];
476
+ const emitChange = () => {
477
+ const properties = { accounts: accounts() };
478
+ for (const listener of [...listeners]) listener(properties);
479
+ };
480
+ const setDisconnected = () => {
481
+ if (!current) return;
482
+ current = null;
483
+ emitChange();
484
+ };
485
+ const onAccountsChanged = (data) => {
486
+ const list = Array.isArray(data) ? data : [];
487
+ const address = list[0];
488
+ if (typeof address !== "string" || !address) return setDisconnected();
489
+ if (!current) return;
490
+ current = { ...current, address };
491
+ emitChange();
492
+ };
493
+ const onNetworkChanged = (data) => {
494
+ const payload = typeof data === "object" && data !== null && !Array.isArray(data) ? data : { chainId: data };
495
+ const chain = toStarknetChain(payload.chainId);
496
+ if (!chain) return setDisconnected();
497
+ if (!current) return;
498
+ const list = Array.isArray(payload.accounts) ? payload.accounts : [];
499
+ const address = typeof list[0] === "string" && list[0] ? list[0] : current.address;
500
+ current = { address, chain };
501
+ emitChange();
502
+ };
503
+ transport.on("accountsChanged", onAccountsChanged);
504
+ transport.on("networkChanged", onNetworkChanged);
505
+ const request = ((call) => transport.request(call));
506
+ const features = {
507
+ "starknet:walletApi": {
508
+ version: "1.0.0",
509
+ request,
510
+ walletVersion: "1.0.0",
511
+ id: "chipi"
512
+ },
513
+ "standard:connect": {
514
+ version: "1.0.0",
515
+ connect: async (input) => {
516
+ if (current || input?.silent) return { accounts: accounts() };
517
+ await transport.open();
518
+ const result = await transport.request({ type: "wallet_requestAccounts" });
519
+ const list = Array.isArray(result) ? result : [];
520
+ const address = list[0];
521
+ if (typeof address !== "string" || !address) return { accounts: [] };
522
+ current = { address, chain: CHIPI_STARKNET_MAINNET_CHAIN };
523
+ emitChange();
524
+ return { accounts: accounts() };
525
+ }
526
+ },
527
+ "standard:disconnect": {
528
+ version: "1.0.0",
529
+ disconnect: async () => {
530
+ transport.close();
531
+ setDisconnected();
532
+ }
533
+ },
534
+ "standard:events": {
535
+ version: "1.0.0",
536
+ on: (_event, listener) => {
537
+ listeners.add(listener);
538
+ return () => {
539
+ listeners.delete(listener);
540
+ };
541
+ }
542
+ }
543
+ };
544
+ return {
545
+ version: "1.0.0",
546
+ name: options.name ?? "Chipi",
547
+ icon: options.icon ?? CHIPI_ICON,
548
+ chains: [CHIPI_STARKNET_MAINNET_CHAIN],
549
+ get accounts() {
550
+ return accounts();
551
+ },
552
+ features
553
+ };
554
+ }
555
+ function registerChipiStandardWallet(options = {}, target = typeof window !== "undefined" ? window : void 0) {
556
+ if (!target) return () => {
557
+ };
558
+ const wallet = createChipiStandardWallet(options);
559
+ const unregisters = [];
560
+ const callback = ({ register }) => {
561
+ unregisters.push(register(wallet));
562
+ };
563
+ const onAppReady = (event) => {
564
+ const api = event.detail;
565
+ if (api && typeof api.register === "function") callback(api);
566
+ };
567
+ try {
568
+ target.dispatchEvent(
569
+ new CustomEvent("wallet-standard:register-wallet", {
570
+ detail: callback,
571
+ bubbles: false,
572
+ cancelable: false,
573
+ composed: false
574
+ })
575
+ );
576
+ } catch (error) {
577
+ console.error("wallet-standard:register-wallet event could not be dispatched\n", error);
578
+ }
579
+ target.addEventListener("wallet-standard:app-ready", onAppReady);
580
+ return () => {
581
+ target.removeEventListener("wallet-standard:app-ready", onAppReady);
582
+ for (const unregister of unregisters.splice(0)) unregister();
583
+ };
584
+ }
585
+
586
+ export { CHIPI_STARKNET_MAINNET_CHAIN, CHIPI_WC, CHIPI_WINDOW_KEY, ChipiConnector, ChipiPopupTransport, chipi, createChipiStandardWallet, isChipiDappMessage, isChipiWalletMessage, registerChipiStandardWallet, registerChipiWallet };
327
587
  //# sourceMappingURL=index.js.map
328
588
  //# sourceMappingURL=index.js.map