@keplr-wallet/provider 0.12.131 → 0.12.133-rc.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/build/core.d.ts +49 -1
- package/build/core.js +161 -7
- package/build/core.js.map +1 -1
- package/build/inject.d.ts +55 -7
- package/build/inject.js +280 -5
- package/build/inject.js.map +1 -1
- package/package.json +7 -4
- package/src/core.ts +255 -7
- package/src/inject.ts +437 -6
package/src/inject.ts
CHANGED
@@ -24,6 +24,10 @@ import {
|
|
24
24
|
EIP6963EventNames,
|
25
25
|
EIP6963ProviderInfo,
|
26
26
|
EIP6963ProviderDetail,
|
27
|
+
IStarknetProvider,
|
28
|
+
WalletEvents,
|
29
|
+
AccountChangeEventHandler,
|
30
|
+
NetworkChangeEventHandler,
|
27
31
|
} from "@keplr-wallet/types";
|
28
32
|
import {
|
29
33
|
Result,
|
@@ -36,6 +40,13 @@ import deepmerge from "deepmerge";
|
|
36
40
|
import Long from "long";
|
37
41
|
import { KeplrCoreTypes } from "./core-types";
|
38
42
|
import EventEmitter from "events";
|
43
|
+
import {
|
44
|
+
AccountInterface,
|
45
|
+
Call,
|
46
|
+
DeployAccountSignerDetails,
|
47
|
+
InvocationsSignerDetails,
|
48
|
+
ProviderInterface,
|
49
|
+
} from "starknet";
|
39
50
|
|
40
51
|
export interface ProxyRequest {
|
41
52
|
type: "proxy-request";
|
@@ -43,6 +54,7 @@ export interface ProxyRequest {
|
|
43
54
|
method: keyof (Keplr & KeplrCoreTypes);
|
44
55
|
args: any[];
|
45
56
|
ethereumProviderMethod?: keyof IEthereumProvider;
|
57
|
+
starknetProviderMethod?: keyof IStarknetProvider;
|
46
58
|
}
|
47
59
|
|
48
60
|
export interface ProxyRequestResponse {
|
@@ -91,6 +103,12 @@ export function injectKeplrToWindow(keplr: IKeplr): void {
|
|
91
103
|
"getEnigmaUtils",
|
92
104
|
keplr.getEnigmaUtils
|
93
105
|
);
|
106
|
+
|
107
|
+
defineUnwritablePropertyIfPossible(
|
108
|
+
window,
|
109
|
+
"starknet_braavos",
|
110
|
+
keplr.starknet
|
111
|
+
);
|
94
112
|
}
|
95
113
|
|
96
114
|
/**
|
@@ -148,6 +166,7 @@ export class InjectedKeplr implements IKeplr, KeplrCoreTypes {
|
|
148
166
|
if (
|
149
167
|
!keplr[message.method] ||
|
150
168
|
(message.method !== "ethereum" &&
|
169
|
+
message.method !== "starknet" &&
|
151
170
|
typeof keplr[message.method] !== "function")
|
152
171
|
) {
|
153
172
|
throw new Error(`Invalid method: ${message.method}`);
|
@@ -305,6 +324,76 @@ export class InjectedKeplr implements IKeplr, KeplrCoreTypes {
|
|
305
324
|
);
|
306
325
|
}
|
307
326
|
|
327
|
+
if (method === "starknet") {
|
328
|
+
const starknetProviderMethod = message.starknetProviderMethod;
|
329
|
+
|
330
|
+
if (starknetProviderMethod?.startsWith("protected")) {
|
331
|
+
throw new Error("Rejected");
|
332
|
+
}
|
333
|
+
|
334
|
+
if (starknetProviderMethod === "id") {
|
335
|
+
throw new Error("id is not function");
|
336
|
+
}
|
337
|
+
|
338
|
+
if (starknetProviderMethod === "name") {
|
339
|
+
throw new Error("name is not function");
|
340
|
+
}
|
341
|
+
|
342
|
+
if (starknetProviderMethod === "version") {
|
343
|
+
throw new Error("version is not function");
|
344
|
+
}
|
345
|
+
|
346
|
+
if (starknetProviderMethod === "icon") {
|
347
|
+
throw new Error("icon is not function");
|
348
|
+
}
|
349
|
+
|
350
|
+
if (starknetProviderMethod === "chainId") {
|
351
|
+
throw new Error("chainId is not function");
|
352
|
+
}
|
353
|
+
|
354
|
+
if (starknetProviderMethod === "selectedAddress") {
|
355
|
+
throw new Error("selectedAddress is not function");
|
356
|
+
}
|
357
|
+
|
358
|
+
if (starknetProviderMethod === "isConnected") {
|
359
|
+
throw new Error("isConnected is not function");
|
360
|
+
}
|
361
|
+
|
362
|
+
if (starknetProviderMethod === "account") {
|
363
|
+
throw new Error("account is not function");
|
364
|
+
}
|
365
|
+
|
366
|
+
if (starknetProviderMethod === "provider") {
|
367
|
+
throw new Error("provider is not function");
|
368
|
+
}
|
369
|
+
|
370
|
+
if (
|
371
|
+
starknetProviderMethod === undefined ||
|
372
|
+
typeof keplr.starknet?.[starknetProviderMethod] !== "function"
|
373
|
+
) {
|
374
|
+
throw new Error(
|
375
|
+
`${message.starknetProviderMethod} is not function or invalid Starknet provider method`
|
376
|
+
);
|
377
|
+
}
|
378
|
+
|
379
|
+
const messageArgs = JSONUint8Array.unwrap(message.args);
|
380
|
+
if (starknetProviderMethod === "request") {
|
381
|
+
return await keplr.starknet.request(
|
382
|
+
typeof messageArgs === "string"
|
383
|
+
? JSON.parse(messageArgs)
|
384
|
+
: messageArgs
|
385
|
+
);
|
386
|
+
}
|
387
|
+
|
388
|
+
return await keplr.starknet[starknetProviderMethod](
|
389
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
390
|
+
// @ts-ignore
|
391
|
+
...(typeof messageArgs === "string"
|
392
|
+
? JSON.parse(messageArgs)
|
393
|
+
: messageArgs)
|
394
|
+
);
|
395
|
+
}
|
396
|
+
|
308
397
|
return await keplr[method](
|
309
398
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
310
399
|
// @ts-ignore
|
@@ -410,6 +499,14 @@ export class InjectedKeplr implements IKeplr, KeplrCoreTypes {
|
|
410
499
|
constructor(
|
411
500
|
public readonly version: string,
|
412
501
|
public readonly mode: KeplrMode,
|
502
|
+
protected readonly onStarknetStateChange: (state: {
|
503
|
+
selectedAddress: string | null;
|
504
|
+
chainId: string | null;
|
505
|
+
rpc: string | null;
|
506
|
+
}) => void,
|
507
|
+
protected readonly onStarknetAccountChange: (state: {
|
508
|
+
selectedAddress: string | null;
|
509
|
+
}) => void,
|
413
510
|
protected readonly eventListener: {
|
414
511
|
addMessageListener: (fn: (e: any) => void) => void;
|
415
512
|
removeMessageListener: (fn: (e: any) => void) => void;
|
@@ -422,8 +519,13 @@ export class InjectedKeplr implements IKeplr, KeplrCoreTypes {
|
|
422
519
|
postMessage: (message) =>
|
423
520
|
window.postMessage(message, window.location.origin),
|
424
521
|
},
|
425
|
-
protected readonly parseMessage
|
426
|
-
protected readonly eip6963ProviderInfo
|
522
|
+
protected readonly parseMessage: ((message: any) => any) | undefined,
|
523
|
+
protected readonly eip6963ProviderInfo: EIP6963ProviderInfo | undefined,
|
524
|
+
protected readonly starknetProviderInfo: {
|
525
|
+
id: string;
|
526
|
+
name: string;
|
527
|
+
icon: string;
|
528
|
+
}
|
427
529
|
) {
|
428
530
|
// Freeze fields/method except for "defaultOptions"
|
429
531
|
// Intentionally, "defaultOptions" can be mutated to allow a webpage to change the options with cosmjs usage.
|
@@ -870,12 +972,77 @@ export class InjectedKeplr implements IKeplr, KeplrCoreTypes {
|
|
870
972
|
return await this.requestMethod("__core__webpageClosed", []);
|
871
973
|
}
|
872
974
|
|
975
|
+
async getStarknetKey(chainId: string): Promise<{
|
976
|
+
name: string;
|
977
|
+
hexAddress: string;
|
978
|
+
pubKey: Uint8Array;
|
979
|
+
address: Uint8Array;
|
980
|
+
}> {
|
981
|
+
return await this.requestMethod("getStarknetKey", [chainId]);
|
982
|
+
}
|
983
|
+
|
984
|
+
async getStarknetKeysSettled(chainIds: string[]): Promise<
|
985
|
+
SettledResponses<{
|
986
|
+
name: string;
|
987
|
+
hexAddress: string;
|
988
|
+
pubKey: Uint8Array;
|
989
|
+
address: Uint8Array;
|
990
|
+
}>
|
991
|
+
> {
|
992
|
+
return await this.requestMethod("getStarknetKeysSettled", [chainIds]);
|
993
|
+
}
|
994
|
+
|
995
|
+
async signStarknetTx(
|
996
|
+
chainId: string,
|
997
|
+
transactions: Call[],
|
998
|
+
details: InvocationsSignerDetails
|
999
|
+
): Promise<{
|
1000
|
+
transactions: Call[];
|
1001
|
+
details: InvocationsSignerDetails;
|
1002
|
+
signature: string[];
|
1003
|
+
}> {
|
1004
|
+
return await this.requestMethod("signStarknetTx", [
|
1005
|
+
chainId,
|
1006
|
+
transactions,
|
1007
|
+
details,
|
1008
|
+
]);
|
1009
|
+
}
|
1010
|
+
|
1011
|
+
async signStarknetDeployAccountTransaction(
|
1012
|
+
chainId: string,
|
1013
|
+
transaction: DeployAccountSignerDetails
|
1014
|
+
): Promise<{
|
1015
|
+
transaction: DeployAccountSignerDetails;
|
1016
|
+
signature: string[];
|
1017
|
+
}> {
|
1018
|
+
return await this.requestMethod("signStarknetDeployAccountTransaction", [
|
1019
|
+
chainId,
|
1020
|
+
transaction,
|
1021
|
+
]);
|
1022
|
+
}
|
1023
|
+
|
1024
|
+
generateStarknetProvider(): IStarknetProvider {
|
1025
|
+
return new StarknetProvider(
|
1026
|
+
this.starknetProviderInfo.id,
|
1027
|
+
this.starknetProviderInfo.name,
|
1028
|
+
this.version,
|
1029
|
+
this.starknetProviderInfo.icon,
|
1030
|
+
() => this,
|
1031
|
+
this.onStarknetStateChange,
|
1032
|
+
this.onStarknetAccountChange,
|
1033
|
+
this.eventListener,
|
1034
|
+
this.parseMessage
|
1035
|
+
);
|
1036
|
+
}
|
1037
|
+
|
873
1038
|
public readonly ethereum = new EthereumProvider(
|
874
|
-
this,
|
1039
|
+
() => this,
|
875
1040
|
this.eventListener,
|
876
1041
|
this.parseMessage,
|
877
1042
|
this.eip6963ProviderInfo
|
878
1043
|
);
|
1044
|
+
|
1045
|
+
public readonly starknet = this.generateStarknetProvider();
|
879
1046
|
}
|
880
1047
|
|
881
1048
|
class EthereumProvider extends EventEmitter implements IEthereumProvider {
|
@@ -893,7 +1060,7 @@ class EthereumProvider extends EventEmitter implements IEthereumProvider {
|
|
893
1060
|
protected _currentChainId: string | null = null;
|
894
1061
|
|
895
1062
|
constructor(
|
896
|
-
protected readonly injectedKeplr: InjectedKeplr,
|
1063
|
+
protected readonly injectedKeplr: () => InjectedKeplr,
|
897
1064
|
protected readonly eventListener: {
|
898
1065
|
addMessageListener: (fn: (e: any) => void) => void;
|
899
1066
|
removeMessageListener: (fn: (e: any) => void) => void;
|
@@ -915,13 +1082,13 @@ class EthereumProvider extends EventEmitter implements IEthereumProvider {
|
|
915
1082
|
|
916
1083
|
window.addEventListener("keplr_keystorechange", async () => {
|
917
1084
|
if (this._currentChainId) {
|
918
|
-
const chainInfo = await injectedKeplr.getChainInfoWithoutEndpoints(
|
1085
|
+
const chainInfo = await injectedKeplr().getChainInfoWithoutEndpoints(
|
919
1086
|
this._currentChainId
|
920
1087
|
);
|
921
1088
|
|
922
1089
|
if (chainInfo) {
|
923
1090
|
const selectedAddress = (
|
924
|
-
await injectedKeplr.getKey(this._currentChainId)
|
1091
|
+
await injectedKeplr().getKey(this._currentChainId)
|
925
1092
|
).ethereumHexAddress;
|
926
1093
|
this._handleAccountsChanged(selectedAddress);
|
927
1094
|
}
|
@@ -1145,3 +1312,267 @@ class EthereumProvider extends EventEmitter implements IEthereumProvider {
|
|
1145
1312
|
})) as string;
|
1146
1313
|
};
|
1147
1314
|
}
|
1315
|
+
|
1316
|
+
class StarknetProvider implements IStarknetProvider {
|
1317
|
+
isConnected: boolean = false;
|
1318
|
+
|
1319
|
+
// It must be in plain text format not hexadecimal string. e.g. "SN_MAIN"
|
1320
|
+
chainId?: string = undefined;
|
1321
|
+
|
1322
|
+
selectedAddress?: string = undefined;
|
1323
|
+
|
1324
|
+
account?: AccountInterface = undefined;
|
1325
|
+
|
1326
|
+
provider?: ProviderInterface = undefined;
|
1327
|
+
|
1328
|
+
// It must be in the CAIP-2 chain ID format. e.g. "starknet:SN_MAIN"
|
1329
|
+
protected _currentChainId?: string = undefined;
|
1330
|
+
|
1331
|
+
protected _userWalletEvents: WalletEvents[] = [];
|
1332
|
+
|
1333
|
+
constructor(
|
1334
|
+
public readonly id: string,
|
1335
|
+
public readonly name: string,
|
1336
|
+
public readonly version: string,
|
1337
|
+
public readonly icon: string,
|
1338
|
+
|
1339
|
+
protected readonly _injectedKeplr: () => InjectedKeplr,
|
1340
|
+
protected readonly onStateChange: (state: {
|
1341
|
+
selectedAddress: string | null;
|
1342
|
+
chainId: string | null;
|
1343
|
+
rpc: string | null;
|
1344
|
+
}) => void,
|
1345
|
+
protected readonly onAccountChange: (state: {
|
1346
|
+
selectedAddress: string | null;
|
1347
|
+
}) => void,
|
1348
|
+
protected readonly _eventListener: {
|
1349
|
+
addMessageListener: (fn: (e: any) => void) => void;
|
1350
|
+
removeMessageListener: (fn: (e: any) => void) => void;
|
1351
|
+
postMessage: (message: any) => void;
|
1352
|
+
} = {
|
1353
|
+
addMessageListener: (fn: (e: any) => void) =>
|
1354
|
+
window.addEventListener("message", fn),
|
1355
|
+
removeMessageListener: (fn: (e: any) => void) =>
|
1356
|
+
window.removeEventListener("message", fn),
|
1357
|
+
postMessage: (message) =>
|
1358
|
+
window.postMessage(message, window.location.origin),
|
1359
|
+
},
|
1360
|
+
|
1361
|
+
protected readonly _parseMessage?: (message: any) => any
|
1362
|
+
) {
|
1363
|
+
this._initProviderState();
|
1364
|
+
|
1365
|
+
window.addEventListener("keplr_keystorechange", async () => {
|
1366
|
+
if (this._currentChainId) {
|
1367
|
+
const selectedAddress = (
|
1368
|
+
await this._injectedKeplr().getStarknetKey(this._currentChainId)
|
1369
|
+
).hexAddress;
|
1370
|
+
|
1371
|
+
this.selectedAddress = selectedAddress;
|
1372
|
+
|
1373
|
+
this.onAccountChange({
|
1374
|
+
selectedAddress,
|
1375
|
+
});
|
1376
|
+
|
1377
|
+
this._userWalletEvents.forEach((userWalletEvent) => {
|
1378
|
+
if (userWalletEvent.type === "accountsChanged") {
|
1379
|
+
userWalletEvent.handler([selectedAddress]);
|
1380
|
+
}
|
1381
|
+
});
|
1382
|
+
}
|
1383
|
+
});
|
1384
|
+
|
1385
|
+
window.addEventListener("keplr_starknetChainChanged", (event) => {
|
1386
|
+
const origin = (event as CustomEvent).detail.origin;
|
1387
|
+
const starknetChainId = (event as CustomEvent).detail.starknetChainId;
|
1388
|
+
|
1389
|
+
this.chainId = starknetChainId;
|
1390
|
+
|
1391
|
+
if (origin === window.location.origin) {
|
1392
|
+
this._userWalletEvents.forEach((userWalletEvent) => {
|
1393
|
+
if (userWalletEvent.type === "networkChanged") {
|
1394
|
+
userWalletEvent.handler(starknetChainId);
|
1395
|
+
}
|
1396
|
+
});
|
1397
|
+
}
|
1398
|
+
});
|
1399
|
+
}
|
1400
|
+
|
1401
|
+
protected async _requestMethod<T = unknown>(
|
1402
|
+
method: keyof IStarknetProvider,
|
1403
|
+
args: Record<string, any>
|
1404
|
+
): Promise<T> {
|
1405
|
+
const bytes = new Uint8Array(8);
|
1406
|
+
const id: string = Array.from(crypto.getRandomValues(bytes))
|
1407
|
+
.map((value) => {
|
1408
|
+
return value.toString(16);
|
1409
|
+
})
|
1410
|
+
.join("");
|
1411
|
+
|
1412
|
+
const proxyMessage: ProxyRequest = {
|
1413
|
+
type: "proxy-request",
|
1414
|
+
id,
|
1415
|
+
method: "starknet",
|
1416
|
+
args: JSONUint8Array.wrap(args),
|
1417
|
+
starknetProviderMethod: method,
|
1418
|
+
};
|
1419
|
+
|
1420
|
+
return new Promise<T>((resolve, reject) => {
|
1421
|
+
const receiveResponse = (e: any) => {
|
1422
|
+
const proxyResponse: ProxyRequestResponse = this._parseMessage
|
1423
|
+
? this._parseMessage(e.data)
|
1424
|
+
: e.data;
|
1425
|
+
|
1426
|
+
if (!proxyResponse || proxyResponse.type !== "proxy-request-response") {
|
1427
|
+
return;
|
1428
|
+
}
|
1429
|
+
|
1430
|
+
if (proxyResponse.id !== id) {
|
1431
|
+
return;
|
1432
|
+
}
|
1433
|
+
|
1434
|
+
this._eventListener.removeMessageListener(receiveResponse);
|
1435
|
+
|
1436
|
+
const result = JSONUint8Array.unwrap(proxyResponse.result);
|
1437
|
+
|
1438
|
+
if (!result) {
|
1439
|
+
reject(new Error("Result is null"));
|
1440
|
+
return;
|
1441
|
+
}
|
1442
|
+
|
1443
|
+
if (result.error) {
|
1444
|
+
const error = result.error;
|
1445
|
+
reject(
|
1446
|
+
error.code && !error.module
|
1447
|
+
? new EthereumProviderRpcError(
|
1448
|
+
error.code,
|
1449
|
+
error.message,
|
1450
|
+
error.data
|
1451
|
+
)
|
1452
|
+
: new Error(error)
|
1453
|
+
);
|
1454
|
+
return;
|
1455
|
+
}
|
1456
|
+
|
1457
|
+
resolve(result.return as T);
|
1458
|
+
};
|
1459
|
+
|
1460
|
+
this._eventListener.addMessageListener(receiveResponse);
|
1461
|
+
|
1462
|
+
this._eventListener.postMessage(proxyMessage);
|
1463
|
+
});
|
1464
|
+
}
|
1465
|
+
|
1466
|
+
protected async _initProviderState() {
|
1467
|
+
const { currentChainId, selectedAddress, rpc } = await this.request<{
|
1468
|
+
currentChainId: string | null;
|
1469
|
+
selectedAddress: string | null;
|
1470
|
+
rpc: string | null;
|
1471
|
+
}>({
|
1472
|
+
type: "keplr_initStarknetProviderState",
|
1473
|
+
});
|
1474
|
+
|
1475
|
+
if (currentChainId != null && selectedAddress != null && rpc != null) {
|
1476
|
+
this.onStateChange({
|
1477
|
+
selectedAddress,
|
1478
|
+
chainId: currentChainId,
|
1479
|
+
rpc,
|
1480
|
+
});
|
1481
|
+
|
1482
|
+
this._currentChainId = currentChainId;
|
1483
|
+
this.chainId = currentChainId.replace("starknet:", "");
|
1484
|
+
this.selectedAddress = selectedAddress;
|
1485
|
+
this.isConnected = true;
|
1486
|
+
} else {
|
1487
|
+
this.onStateChange({
|
1488
|
+
selectedAddress: null,
|
1489
|
+
chainId: null,
|
1490
|
+
rpc: null,
|
1491
|
+
});
|
1492
|
+
}
|
1493
|
+
}
|
1494
|
+
|
1495
|
+
async request<T = unknown>({
|
1496
|
+
type,
|
1497
|
+
params,
|
1498
|
+
}: {
|
1499
|
+
type: string;
|
1500
|
+
params?: unknown[] | Record<string, unknown>;
|
1501
|
+
}): Promise<T> {
|
1502
|
+
if (typeof type !== "string") {
|
1503
|
+
throw new Error("Invalid parameter: `type` must be a string");
|
1504
|
+
}
|
1505
|
+
|
1506
|
+
return await this._requestMethod<T>("request", {
|
1507
|
+
type,
|
1508
|
+
params,
|
1509
|
+
});
|
1510
|
+
}
|
1511
|
+
async enable(_options?: {
|
1512
|
+
starknetVersion?: "v4" | "v5";
|
1513
|
+
}): Promise<string[]> {
|
1514
|
+
const { currentChainId, selectedAddress, rpc } = await this.request<{
|
1515
|
+
currentChainId: string;
|
1516
|
+
selectedAddress: string;
|
1517
|
+
rpc: string;
|
1518
|
+
}>({
|
1519
|
+
type: "keplr_enableStarknetProvider",
|
1520
|
+
});
|
1521
|
+
|
1522
|
+
this.onStateChange({
|
1523
|
+
selectedAddress,
|
1524
|
+
chainId: currentChainId,
|
1525
|
+
rpc,
|
1526
|
+
});
|
1527
|
+
|
1528
|
+
this._currentChainId = currentChainId;
|
1529
|
+
this.chainId = currentChainId.replace("starknet:", "");
|
1530
|
+
this.selectedAddress = selectedAddress;
|
1531
|
+
this.isConnected = true;
|
1532
|
+
|
1533
|
+
return [selectedAddress];
|
1534
|
+
}
|
1535
|
+
async isPreauthorized(): Promise<boolean> {
|
1536
|
+
const { currentChainId, selectedAddress } = await this.request<{
|
1537
|
+
currentChainId: string | null;
|
1538
|
+
selectedAddress: string | null;
|
1539
|
+
}>({
|
1540
|
+
type: "keplr_initStarknetProviderState",
|
1541
|
+
});
|
1542
|
+
|
1543
|
+
if (currentChainId != null && selectedAddress != null) {
|
1544
|
+
return true;
|
1545
|
+
}
|
1546
|
+
|
1547
|
+
return false;
|
1548
|
+
}
|
1549
|
+
on<E extends WalletEvents>(event: E["type"], handleEvent: E["handler"]) {
|
1550
|
+
if (event === "accountsChanged") {
|
1551
|
+
this._userWalletEvents.push({
|
1552
|
+
type: "accountsChanged",
|
1553
|
+
handler: handleEvent as AccountChangeEventHandler,
|
1554
|
+
});
|
1555
|
+
} else if (event === "networkChanged") {
|
1556
|
+
this._userWalletEvents.push({
|
1557
|
+
type: "networkChanged",
|
1558
|
+
handler: handleEvent as NetworkChangeEventHandler,
|
1559
|
+
});
|
1560
|
+
} else {
|
1561
|
+
throw new Error("Invalid event type");
|
1562
|
+
}
|
1563
|
+
}
|
1564
|
+
off<E extends WalletEvents>(event: E["type"], handleEvent: E["handler"]) {
|
1565
|
+
if (event !== "accountsChanged" && event !== "networkChanged") {
|
1566
|
+
throw new Error("Invalid event type");
|
1567
|
+
}
|
1568
|
+
|
1569
|
+
const eventIndex = this._userWalletEvents.findIndex(
|
1570
|
+
(userEvent) =>
|
1571
|
+
userEvent.type === event && userEvent.handler === handleEvent
|
1572
|
+
);
|
1573
|
+
|
1574
|
+
if (eventIndex >= 0) {
|
1575
|
+
this._userWalletEvents.splice(eventIndex, 1);
|
1576
|
+
}
|
1577
|
+
}
|
1578
|
+
}
|