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