@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/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;
|
|
@@ -22,6 +38,21 @@ function deferred() {
|
|
|
22
38
|
});
|
|
23
39
|
return { promise, resolve, reject };
|
|
24
40
|
}
|
|
41
|
+
var SN_MAIN_HEX = "0x534e5f4d41494e";
|
|
42
|
+
function passiveAnswer(call) {
|
|
43
|
+
switch (call.type) {
|
|
44
|
+
case "wallet_getPermissions":
|
|
45
|
+
return { value: [] };
|
|
46
|
+
case "wallet_requestAccounts": {
|
|
47
|
+
const params = call.params;
|
|
48
|
+
return params?.silent_mode === true ? { value: [] } : void 0;
|
|
49
|
+
}
|
|
50
|
+
case "wallet_requestChainId":
|
|
51
|
+
return { value: SN_MAIN_HEX };
|
|
52
|
+
default:
|
|
53
|
+
return void 0;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
25
56
|
function randomId() {
|
|
26
57
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
27
58
|
}
|
|
@@ -37,18 +68,19 @@ var ChipiPopupTransport = class {
|
|
|
37
68
|
this.readyDeferred = null;
|
|
38
69
|
this.openPromise = null;
|
|
39
70
|
this.closeWatch = null;
|
|
71
|
+
/** True once this transport opened a popup. A later request with no live
|
|
72
|
+
* popup means the user closed it: reject instead of reopening off-gesture. */
|
|
73
|
+
this.hadPopup = false;
|
|
40
74
|
this.onMessage = (e) => {
|
|
41
75
|
if (e.origin !== this.walletOrigin || !isChipiWalletMessage(e.data)) return;
|
|
42
|
-
if (this.target
|
|
76
|
+
if (!this.target || e.source !== this.target) return;
|
|
43
77
|
const msg = e.data;
|
|
44
78
|
if (msg.type === "ready") {
|
|
45
79
|
this.ready = true;
|
|
46
80
|
this.readyDeferred?.resolve();
|
|
47
81
|
this.readyDeferred = null;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.target.postMessage(p.message, this.walletOrigin);
|
|
51
|
-
}
|
|
82
|
+
for (const p of this.pending.values()) {
|
|
83
|
+
this.target.postMessage(p.message, this.walletOrigin);
|
|
52
84
|
}
|
|
53
85
|
return;
|
|
54
86
|
}
|
|
@@ -56,6 +88,7 @@ var ChipiPopupTransport = class {
|
|
|
56
88
|
const p = this.pending.get(msg.id);
|
|
57
89
|
if (!p) return;
|
|
58
90
|
this.pending.delete(msg.id);
|
|
91
|
+
if (p.timer) clearTimeout(p.timer);
|
|
59
92
|
if (msg.ok) p.resolve(msg.result);
|
|
60
93
|
else p.reject(Object.assign(new Error(msg.error.message), { code: msg.error.code }));
|
|
61
94
|
return;
|
|
@@ -114,9 +147,26 @@ var ChipiPopupTransport = class {
|
|
|
114
147
|
);
|
|
115
148
|
this.ownsTarget = true;
|
|
116
149
|
if (!this.target) throw Object.assign(new Error("Popup blocked"), { code: "popup_blocked" });
|
|
150
|
+
this.hadPopup = true;
|
|
117
151
|
}
|
|
152
|
+
const opened = this.target;
|
|
118
153
|
this.readyDeferred = deferred();
|
|
119
|
-
|
|
154
|
+
try {
|
|
155
|
+
await this.awaitReady();
|
|
156
|
+
} catch (err) {
|
|
157
|
+
if (this.target === opened) this.resetTarget();
|
|
158
|
+
throw err;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/** Close the popup (if we own one) and forget the target + ready state. */
|
|
162
|
+
resetTarget() {
|
|
163
|
+
try {
|
|
164
|
+
if (this.ownsTarget) this.target?.close();
|
|
165
|
+
} catch {
|
|
166
|
+
}
|
|
167
|
+
this.target = null;
|
|
168
|
+
this.ready = false;
|
|
169
|
+
this.readyDeferred = null;
|
|
120
170
|
}
|
|
121
171
|
async awaitReady() {
|
|
122
172
|
const timeoutMs = this.opts.openTimeoutMs ?? 18e4;
|
|
@@ -132,7 +182,10 @@ var ChipiPopupTransport = class {
|
|
|
132
182
|
}
|
|
133
183
|
/** Reject every in-flight request (popup closed / disconnected). */
|
|
134
184
|
rejectAllPending(message) {
|
|
135
|
-
for (const [, p] of this.pending)
|
|
185
|
+
for (const [, p] of this.pending) {
|
|
186
|
+
if (p.timer) clearTimeout(p.timer);
|
|
187
|
+
p.reject(Object.assign(new Error(message), { code: 4001 }));
|
|
188
|
+
}
|
|
136
189
|
this.pending.clear();
|
|
137
190
|
}
|
|
138
191
|
/** While requests are in flight, watch for the user closing the popup and
|
|
@@ -156,8 +209,30 @@ var ChipiPopupTransport = class {
|
|
|
156
209
|
this.closeWatch = null;
|
|
157
210
|
}
|
|
158
211
|
}
|
|
159
|
-
/**
|
|
212
|
+
/**
|
|
213
|
+
* Forward a get-starknet RPC call to the wallet, awaiting its response.
|
|
214
|
+
*
|
|
215
|
+
* With no wallet window open, passive calls are answered locally and never
|
|
216
|
+
* open it: `wallet_getPermissions` → `[]`, `wallet_requestAccounts` with
|
|
217
|
+
* `silent_mode: true` → `[]`, `wallet_requestChainId` → SN_MAIN.
|
|
218
|
+
*
|
|
219
|
+
* The first request may open the popup. Once a popup has been opened, a
|
|
220
|
+
* request made after it was closed rejects with `code: "POPUP_CLOSED"`
|
|
221
|
+
* instead of calling `window.open` again: requests usually run outside a
|
|
222
|
+
* click, where browsers block popups. Reopen via `connect()` / `open()`
|
|
223
|
+
* from a click.
|
|
224
|
+
*/
|
|
160
225
|
async request(call) {
|
|
226
|
+
if (this.resolveMode() === "popup" && (!this.target || this.target.closed)) {
|
|
227
|
+
const passive = passiveAnswer(call);
|
|
228
|
+
if (passive) return passive.value;
|
|
229
|
+
}
|
|
230
|
+
if (this.hadPopup && this.resolveMode() === "popup" && (!this.target || this.target.closed)) {
|
|
231
|
+
throw transportError(
|
|
232
|
+
"POPUP_CLOSED",
|
|
233
|
+
"The Chipi wallet window was closed. Call connect() again from a click."
|
|
234
|
+
);
|
|
235
|
+
}
|
|
161
236
|
await this.open();
|
|
162
237
|
if (this.ownsTarget) this.target?.focus();
|
|
163
238
|
const id = randomId();
|
|
@@ -166,10 +241,24 @@ var ChipiPopupTransport = class {
|
|
|
166
241
|
type: "rpc",
|
|
167
242
|
id,
|
|
168
243
|
origin: window.location.origin,
|
|
169
|
-
call
|
|
244
|
+
call: stripUndefined(call)
|
|
170
245
|
};
|
|
246
|
+
const timeoutMs = this.opts.requestTimeoutMs ?? 12e4;
|
|
171
247
|
return new Promise((resolve, reject) => {
|
|
172
|
-
|
|
248
|
+
const entry = { resolve, reject, message };
|
|
249
|
+
if (timeoutMs > 0 && Number.isFinite(timeoutMs)) {
|
|
250
|
+
entry.timer = setTimeout(() => {
|
|
251
|
+
if (this.pending.get(id) !== entry) return;
|
|
252
|
+
this.pending.delete(id);
|
|
253
|
+
reject(
|
|
254
|
+
transportError(
|
|
255
|
+
"REQUEST_TIMEOUT",
|
|
256
|
+
`The Chipi wallet did not answer "${call.type}" within ${timeoutMs} ms.`
|
|
257
|
+
)
|
|
258
|
+
);
|
|
259
|
+
}, timeoutMs);
|
|
260
|
+
}
|
|
261
|
+
this.pending.set(id, entry);
|
|
173
262
|
this.target.postMessage(message, this.walletOrigin);
|
|
174
263
|
this.startCloseWatch();
|
|
175
264
|
});
|
|
@@ -177,12 +266,8 @@ var ChipiPopupTransport = class {
|
|
|
177
266
|
/** Close the popup (if we own one) + reject in-flight requests. */
|
|
178
267
|
close() {
|
|
179
268
|
this.stopCloseWatch();
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
} catch {
|
|
183
|
-
}
|
|
184
|
-
this.target = null;
|
|
185
|
-
this.ready = false;
|
|
269
|
+
this.readyDeferred?.reject(Object.assign(new Error("disconnected"), { code: 4001 }));
|
|
270
|
+
this.resetTarget();
|
|
186
271
|
this.rejectAllPending("disconnected");
|
|
187
272
|
if (this.listening && typeof window !== "undefined") {
|
|
188
273
|
window.removeEventListener("message", this.onMessage);
|
|
@@ -213,13 +298,46 @@ function registerChipiWallet(wallet, target = typeof window !== "undefined" ? wi
|
|
|
213
298
|
var CHIPI_ICON = "data:image/png;base64,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";
|
|
214
299
|
|
|
215
300
|
// src/connector.ts
|
|
216
|
-
var SN_MAIN = BigInt(
|
|
301
|
+
var SN_MAIN = BigInt(constants.StarknetChainId.SN_MAIN);
|
|
302
|
+
function toChainId(value) {
|
|
303
|
+
if (typeof value === "bigint") return value;
|
|
304
|
+
if (typeof value === "number" || typeof value === "string") {
|
|
305
|
+
try {
|
|
306
|
+
return BigInt(value);
|
|
307
|
+
} catch {
|
|
308
|
+
return void 0;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return void 0;
|
|
312
|
+
}
|
|
217
313
|
var ChipiConnector = class extends Connector {
|
|
218
314
|
constructor(options = {}) {
|
|
219
315
|
super();
|
|
220
316
|
this._account = null;
|
|
221
317
|
this._swo = null;
|
|
222
318
|
this._registration = null;
|
|
319
|
+
this.onAccountsChanged = (data) => {
|
|
320
|
+
const accounts = Array.isArray(data) ? data : [];
|
|
321
|
+
const account = accounts[0];
|
|
322
|
+
if (typeof account === "string" && account) {
|
|
323
|
+
this._account = account;
|
|
324
|
+
this.emitEvent("change", { account, chainId: SN_MAIN });
|
|
325
|
+
} else {
|
|
326
|
+
this._account = null;
|
|
327
|
+
this.emitEvent("disconnect");
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
this.onNetworkChanged = (data) => {
|
|
331
|
+
const payload = typeof data === "object" && data !== null && !Array.isArray(data) ? data : { chainId: data };
|
|
332
|
+
const chainId = toChainId(payload.chainId);
|
|
333
|
+
const accounts = Array.isArray(payload.accounts) ? payload.accounts : [];
|
|
334
|
+
const next = typeof accounts[0] === "string" && accounts[0] ? accounts[0] : this._account;
|
|
335
|
+
if (next) this._account = next;
|
|
336
|
+
const change = {};
|
|
337
|
+
if (chainId !== void 0) change.chainId = chainId;
|
|
338
|
+
if (next) change.account = next;
|
|
339
|
+
this.emitEvent("change", change);
|
|
340
|
+
};
|
|
223
341
|
const walletUrl = options.walletUrl ?? options.transport?.walletUrl ?? "https://wallet.chipipay.com";
|
|
224
342
|
this.transport = new ChipiPopupTransport({
|
|
225
343
|
...options.transport,
|
|
@@ -230,7 +348,8 @@ var ChipiConnector = class extends Connector {
|
|
|
230
348
|
this._id = options.id ?? "chipi";
|
|
231
349
|
this._name = options.name ?? "Connect with Chipi";
|
|
232
350
|
this._icon = options.icon ?? CHIPI_ICON;
|
|
233
|
-
|
|
351
|
+
this._autoRegister = options.register !== false;
|
|
352
|
+
if (this._autoRegister) this.register();
|
|
234
353
|
}
|
|
235
354
|
/**
|
|
236
355
|
* Announce this wallet to scanning dApps (`window.starknet_chipi` +
|
|
@@ -284,7 +403,22 @@ var ChipiConnector = class extends Connector {
|
|
|
284
403
|
};
|
|
285
404
|
return this._swo;
|
|
286
405
|
}
|
|
287
|
-
|
|
406
|
+
/**
|
|
407
|
+
* Open the hosted wallet (call from a click: it opens a popup) and request
|
|
408
|
+
* the account. Chipi is mainnet-only: a `chainIdHint` other than SN_MAIN
|
|
409
|
+
* rejects before any popup opens.
|
|
410
|
+
*/
|
|
411
|
+
async connect(args = {}) {
|
|
412
|
+
if (args.chainIdHint !== void 0 && BigInt(args.chainIdHint) !== SN_MAIN) {
|
|
413
|
+
throw Object.assign(
|
|
414
|
+
new Error(
|
|
415
|
+
`Chipi is mainnet-only: chainIdHint 0x${BigInt(args.chainIdHint).toString(16)} is not SN_MAIN.`
|
|
416
|
+
),
|
|
417
|
+
{ code: "UNSUPPORTED_CHAIN" }
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
if (this._autoRegister) this.register();
|
|
421
|
+
this.subscribe();
|
|
288
422
|
await this.transport.open();
|
|
289
423
|
const accounts = await this.transport.request({ type: "wallet_requestAccounts" });
|
|
290
424
|
const account = accounts?.[0];
|
|
@@ -295,16 +429,27 @@ var ChipiConnector = class extends Connector {
|
|
|
295
429
|
return data;
|
|
296
430
|
}
|
|
297
431
|
async disconnect() {
|
|
432
|
+
this.unsubscribe();
|
|
298
433
|
this.transport.close();
|
|
299
434
|
this._account = null;
|
|
435
|
+
this.unregister();
|
|
300
436
|
this._swo = null;
|
|
301
437
|
this.emitEvent("disconnect");
|
|
302
438
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
439
|
+
/** Forward the wallet's account/network events as starknet-react events. */
|
|
440
|
+
subscribe() {
|
|
441
|
+
this.unsubscribe();
|
|
442
|
+
this.transport.on("accountsChanged", this.onAccountsChanged);
|
|
443
|
+
this.transport.on("networkChanged", this.onNetworkChanged);
|
|
444
|
+
}
|
|
445
|
+
unsubscribe() {
|
|
446
|
+
this.transport.off("accountsChanged", this.onAccountsChanged);
|
|
447
|
+
this.transport.off("networkChanged", this.onNetworkChanged);
|
|
448
|
+
}
|
|
306
449
|
emitEvent(event, data) {
|
|
307
|
-
this
|
|
450
|
+
const emitter = this;
|
|
451
|
+
if (data === void 0) emitter.emit(event);
|
|
452
|
+
else emitter.emit(event, data);
|
|
308
453
|
}
|
|
309
454
|
async account(provider) {
|
|
310
455
|
if (!this._account) throw new Error("chipi_not_connected");
|
|
@@ -323,6 +468,144 @@ function chipi(options) {
|
|
|
323
468
|
return new ChipiConnector(options);
|
|
324
469
|
}
|
|
325
470
|
|
|
326
|
-
|
|
471
|
+
// src/standard.ts
|
|
472
|
+
var CHIPI_STARKNET_MAINNET_CHAIN = "starknet:0x534e5f4d41494e";
|
|
473
|
+
function toStarknetChain(value) {
|
|
474
|
+
if (typeof value !== "string" && typeof value !== "bigint" && typeof value !== "number") {
|
|
475
|
+
return void 0;
|
|
476
|
+
}
|
|
477
|
+
try {
|
|
478
|
+
return `starknet:0x${BigInt(value).toString(16)}`;
|
|
479
|
+
} catch {
|
|
480
|
+
return void 0;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
function createChipiStandardWallet(options = {}) {
|
|
484
|
+
const transport = new ChipiPopupTransport({
|
|
485
|
+
...options.transport,
|
|
486
|
+
walletUrl: options.walletUrl ?? "https://wallet.chipipay.com",
|
|
487
|
+
mode: "popup"
|
|
488
|
+
});
|
|
489
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
490
|
+
let current = null;
|
|
491
|
+
const accounts = () => current ? [
|
|
492
|
+
{
|
|
493
|
+
address: current.address,
|
|
494
|
+
publicKey: new Uint8Array(),
|
|
495
|
+
chains: [current.chain],
|
|
496
|
+
features: []
|
|
497
|
+
}
|
|
498
|
+
] : [];
|
|
499
|
+
const emitChange = () => {
|
|
500
|
+
const properties = { accounts: accounts() };
|
|
501
|
+
for (const listener of [...listeners]) listener(properties);
|
|
502
|
+
};
|
|
503
|
+
const setDisconnected = () => {
|
|
504
|
+
if (!current) return;
|
|
505
|
+
current = null;
|
|
506
|
+
emitChange();
|
|
507
|
+
};
|
|
508
|
+
const onAccountsChanged = (data) => {
|
|
509
|
+
const list = Array.isArray(data) ? data : [];
|
|
510
|
+
const address = list[0];
|
|
511
|
+
if (typeof address !== "string" || !address) return setDisconnected();
|
|
512
|
+
if (!current) return;
|
|
513
|
+
current = { ...current, address };
|
|
514
|
+
emitChange();
|
|
515
|
+
};
|
|
516
|
+
const onNetworkChanged = (data) => {
|
|
517
|
+
const payload = typeof data === "object" && data !== null && !Array.isArray(data) ? data : { chainId: data };
|
|
518
|
+
const chain = toStarknetChain(payload.chainId);
|
|
519
|
+
if (!chain) return setDisconnected();
|
|
520
|
+
if (!current) return;
|
|
521
|
+
const list = Array.isArray(payload.accounts) ? payload.accounts : [];
|
|
522
|
+
const address = typeof list[0] === "string" && list[0] ? list[0] : current.address;
|
|
523
|
+
current = { address, chain };
|
|
524
|
+
emitChange();
|
|
525
|
+
};
|
|
526
|
+
transport.on("accountsChanged", onAccountsChanged);
|
|
527
|
+
transport.on("networkChanged", onNetworkChanged);
|
|
528
|
+
const request = ((call) => transport.request(call));
|
|
529
|
+
const features = {
|
|
530
|
+
"starknet:walletApi": {
|
|
531
|
+
version: "1.0.0",
|
|
532
|
+
request,
|
|
533
|
+
walletVersion: "1.0.0",
|
|
534
|
+
id: "chipi"
|
|
535
|
+
},
|
|
536
|
+
"standard:connect": {
|
|
537
|
+
version: "1.0.0",
|
|
538
|
+
connect: async (input) => {
|
|
539
|
+
if (current || input?.silent) return { accounts: accounts() };
|
|
540
|
+
await transport.open();
|
|
541
|
+
const result = await transport.request({ type: "wallet_requestAccounts" });
|
|
542
|
+
const list = Array.isArray(result) ? result : [];
|
|
543
|
+
const address = list[0];
|
|
544
|
+
if (typeof address !== "string" || !address) return { accounts: [] };
|
|
545
|
+
current = { address, chain: CHIPI_STARKNET_MAINNET_CHAIN };
|
|
546
|
+
emitChange();
|
|
547
|
+
return { accounts: accounts() };
|
|
548
|
+
}
|
|
549
|
+
},
|
|
550
|
+
"standard:disconnect": {
|
|
551
|
+
version: "1.0.0",
|
|
552
|
+
disconnect: async () => {
|
|
553
|
+
transport.close();
|
|
554
|
+
setDisconnected();
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
"standard:events": {
|
|
558
|
+
version: "1.0.0",
|
|
559
|
+
on: (_event, listener) => {
|
|
560
|
+
listeners.add(listener);
|
|
561
|
+
return () => {
|
|
562
|
+
listeners.delete(listener);
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
return {
|
|
568
|
+
version: "1.0.0",
|
|
569
|
+
name: options.name ?? "Chipi",
|
|
570
|
+
icon: options.icon ?? CHIPI_ICON,
|
|
571
|
+
chains: [CHIPI_STARKNET_MAINNET_CHAIN],
|
|
572
|
+
get accounts() {
|
|
573
|
+
return accounts();
|
|
574
|
+
},
|
|
575
|
+
features
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
function registerChipiStandardWallet(options = {}, target = typeof window !== "undefined" ? window : void 0) {
|
|
579
|
+
if (!target) return () => {
|
|
580
|
+
};
|
|
581
|
+
const wallet = createChipiStandardWallet(options);
|
|
582
|
+
const unregisters = [];
|
|
583
|
+
const callback = ({ register }) => {
|
|
584
|
+
unregisters.push(register(wallet));
|
|
585
|
+
};
|
|
586
|
+
const onAppReady = (event) => {
|
|
587
|
+
const api = event.detail;
|
|
588
|
+
if (api && typeof api.register === "function") callback(api);
|
|
589
|
+
};
|
|
590
|
+
try {
|
|
591
|
+
target.dispatchEvent(
|
|
592
|
+
new CustomEvent("wallet-standard:register-wallet", {
|
|
593
|
+
detail: callback,
|
|
594
|
+
bubbles: false,
|
|
595
|
+
cancelable: false,
|
|
596
|
+
composed: false
|
|
597
|
+
})
|
|
598
|
+
);
|
|
599
|
+
} catch (error) {
|
|
600
|
+
console.error("wallet-standard:register-wallet event could not be dispatched\n", error);
|
|
601
|
+
}
|
|
602
|
+
target.addEventListener("wallet-standard:app-ready", onAppReady);
|
|
603
|
+
return () => {
|
|
604
|
+
target.removeEventListener("wallet-standard:app-ready", onAppReady);
|
|
605
|
+
for (const unregister of unregisters.splice(0)) unregister();
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
export { CHIPI_STARKNET_MAINNET_CHAIN, CHIPI_WC, CHIPI_WINDOW_KEY, ChipiConnector, ChipiPopupTransport, chipi, createChipiStandardWallet, isChipiDappMessage, isChipiWalletMessage, registerChipiStandardWallet, registerChipiWallet };
|
|
327
610
|
//# sourceMappingURL=index.js.map
|
|
328
611
|
//# sourceMappingURL=index.js.map
|