@starknet-io/get-starknet-discovery 5.0.0-beta.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/LICENSE +20 -0
- package/dist/index.cjs +187 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +16 -0
- package/dist/index.d.mts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.mjs +185 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +50 -0
- package/src/eip1193-wallet.ts +26 -0
- package/src/index.ts +6 -0
- package/src/injected-wallet.ts +62 -0
- package/src/standard-wallet.ts +58 -0
- package/src/store.ts +126 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 avimak
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const features = require('@starknet-io/get-starknet-wallet-standard/features');
|
|
4
|
+
const metamask = require('@starknet-io/get-starknet-virtual-wallet/metamask');
|
|
5
|
+
const getStarknetWalletStandard = require('@starknet-io/get-starknet-wallet-standard');
|
|
6
|
+
|
|
7
|
+
function registerStandardWalletDiscovery(register) {
|
|
8
|
+
if (typeof window === "undefined")
|
|
9
|
+
return;
|
|
10
|
+
const api = Object.freeze({ register });
|
|
11
|
+
const handler = ({ detail: callback }) => {
|
|
12
|
+
callback(api);
|
|
13
|
+
};
|
|
14
|
+
window.addEventListener(
|
|
15
|
+
"wallet-standard:register-wallet",
|
|
16
|
+
handler
|
|
17
|
+
);
|
|
18
|
+
window.dispatchEvent(new AppReadyEvent(api));
|
|
19
|
+
return () => window.removeEventListener(
|
|
20
|
+
"wallet-standard:register-wallet",
|
|
21
|
+
handler
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
class AppReadyEvent extends Event {
|
|
25
|
+
constructor(detail) {
|
|
26
|
+
super("wallet-standard:app-ready", {
|
|
27
|
+
bubbles: false,
|
|
28
|
+
cancelable: false,
|
|
29
|
+
composed: false
|
|
30
|
+
});
|
|
31
|
+
this.detail = detail;
|
|
32
|
+
}
|
|
33
|
+
get type() {
|
|
34
|
+
return "wallet-standard:app-ready";
|
|
35
|
+
}
|
|
36
|
+
preventDefault() {
|
|
37
|
+
throw new Error("preventDefault is deprecated");
|
|
38
|
+
}
|
|
39
|
+
stopImmediatePropagation() {
|
|
40
|
+
throw new Error("stopImmediatePropagation is deprecated");
|
|
41
|
+
}
|
|
42
|
+
stopPropagation() {
|
|
43
|
+
throw new Error("stopPropagation is deprecated");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function registerInjectedWalletDiscovery(register) {
|
|
48
|
+
if (typeof window === "undefined")
|
|
49
|
+
return {
|
|
50
|
+
unregister: () => {
|
|
51
|
+
},
|
|
52
|
+
refresh: () => {
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
function refresh() {
|
|
56
|
+
const injectedWallets = scanWindowForWallets(window);
|
|
57
|
+
for (const wallet of injectedWallets) {
|
|
58
|
+
register(new getStarknetWalletStandard.StarknetInjectedWallet(wallet));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
refresh();
|
|
62
|
+
return {
|
|
63
|
+
unregister: () => {
|
|
64
|
+
},
|
|
65
|
+
refresh
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function scanWindowForWallets(window2) {
|
|
69
|
+
return Object.getOwnPropertyNames(window2).reduce((wallets, key) => {
|
|
70
|
+
if (key.startsWith("starknet")) {
|
|
71
|
+
const wallet = window2[key];
|
|
72
|
+
if (isStarknetWindowObject(wallet)) {
|
|
73
|
+
wallets.push(wallet);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return wallets;
|
|
77
|
+
}, []);
|
|
78
|
+
}
|
|
79
|
+
const STARKNET_WALLET_KEYS = [
|
|
80
|
+
"id",
|
|
81
|
+
"name",
|
|
82
|
+
"version",
|
|
83
|
+
"icon",
|
|
84
|
+
"request",
|
|
85
|
+
"on",
|
|
86
|
+
"off"
|
|
87
|
+
];
|
|
88
|
+
function isStarknetWindowObject(wallet) {
|
|
89
|
+
if (typeof wallet !== "object" || wallet === null)
|
|
90
|
+
return false;
|
|
91
|
+
return STARKNET_WALLET_KEYS.every((key) => key in wallet);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function registerEIP1193WalletFromEIP6963Discovery(eip1193Adapters, register) {
|
|
95
|
+
if (typeof window === "undefined")
|
|
96
|
+
return;
|
|
97
|
+
const handler = (event) => {
|
|
98
|
+
const { info, provider } = event.detail;
|
|
99
|
+
for (const adapter of eip1193Adapters) {
|
|
100
|
+
const wallet = adapter(info, provider);
|
|
101
|
+
if (wallet) {
|
|
102
|
+
register(wallet);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
window.addEventListener("eip6963:announceProvider", handler);
|
|
108
|
+
window.dispatchEvent(new Event("eip6963:requestProvider"));
|
|
109
|
+
return () => window.removeEventListener("eip6963:announceProvider", handler);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const DEFAULT_EIP1193_ADAPTERS = [metamask.metaMaskVirtualWallet];
|
|
113
|
+
function createStore({
|
|
114
|
+
eip1193Adapters = DEFAULT_EIP1193_ADAPTERS
|
|
115
|
+
} = {}) {
|
|
116
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
117
|
+
let wallets = [];
|
|
118
|
+
function emitChanges() {
|
|
119
|
+
for (const listener of listeners) {
|
|
120
|
+
listener(wallets.map(({ wallet }) => wallet).slice());
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
registerStandardWalletDiscovery((wallet) => {
|
|
124
|
+
if (!features.isStarknetWallet(wallet))
|
|
125
|
+
return;
|
|
126
|
+
const existing = wallets.find((w) => w.wallet.name === wallet.name);
|
|
127
|
+
if (existing) {
|
|
128
|
+
if (existing.discoverer !== "standard") {
|
|
129
|
+
wallets = [
|
|
130
|
+
{ discoverer: "standard", wallet },
|
|
131
|
+
...wallets.filter((w) => w.wallet.name !== wallet.name)
|
|
132
|
+
];
|
|
133
|
+
emitChanges();
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
wallets = [{ discoverer: "standard", wallet }, ...wallets];
|
|
137
|
+
emitChanges();
|
|
138
|
+
}
|
|
139
|
+
return () => {
|
|
140
|
+
wallets = wallets.filter((w) => w.wallet.name !== wallet.name);
|
|
141
|
+
emitChanges();
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
registerEIP1193WalletFromEIP6963Discovery(eip1193Adapters, (wallet) => {
|
|
145
|
+
if (!features.isStarknetWallet(wallet))
|
|
146
|
+
return;
|
|
147
|
+
const existing = wallets.find((w) => w.wallet.name === wallet.name);
|
|
148
|
+
if (!existing) {
|
|
149
|
+
wallets = [{ discoverer: "eip6963", wallet }, ...wallets];
|
|
150
|
+
emitChanges();
|
|
151
|
+
}
|
|
152
|
+
return () => {
|
|
153
|
+
wallets = wallets.filter((w) => w.wallet.name !== wallet.name);
|
|
154
|
+
emitChanges();
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
const { refresh: refreshInjectedWallets } = registerInjectedWalletDiscovery(
|
|
158
|
+
(wallet) => {
|
|
159
|
+
if (!features.isStarknetWallet(wallet))
|
|
160
|
+
return;
|
|
161
|
+
const existing = wallets.find((w) => w.wallet.name === wallet.name);
|
|
162
|
+
if (!existing) {
|
|
163
|
+
wallets = [{ discoverer: "injected", wallet }, ...wallets];
|
|
164
|
+
emitChanges();
|
|
165
|
+
}
|
|
166
|
+
return () => {
|
|
167
|
+
wallets = wallets.filter((w) => w.wallet.name !== wallet.name);
|
|
168
|
+
emitChanges();
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
return {
|
|
173
|
+
_refreshInjectedWallets: refreshInjectedWallets,
|
|
174
|
+
getWallets() {
|
|
175
|
+
return wallets.map(({ wallet }) => wallet).slice();
|
|
176
|
+
},
|
|
177
|
+
subscribe(listener) {
|
|
178
|
+
listeners.add(listener);
|
|
179
|
+
return () => {
|
|
180
|
+
listeners.delete(listener);
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
exports.createStore = createStore;
|
|
187
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/standard-wallet.ts","../src/injected-wallet.ts","../src/eip1193-wallet.ts","../src/store.ts"],"sourcesContent":["import type {\n WalletEventsWindow,\n WindowRegisterWalletEvent,\n WindowAppReadyEvent,\n WindowAppReadyEventAPI,\n Wallet,\n} from \"@wallet-standard/base\";\n\nexport function registerStandardWalletDiscovery(\n register: (wallet: Wallet) => () => void,\n) {\n if (typeof window === \"undefined\") return;\n\n const api = Object.freeze({ register });\n\n const handler = ({ detail: callback }: WindowRegisterWalletEvent) => {\n callback(api);\n };\n\n (window as WalletEventsWindow).addEventListener(\n \"wallet-standard:register-wallet\",\n handler,\n );\n\n (window as WalletEventsWindow).dispatchEvent(new AppReadyEvent(api));\n\n return () =>\n (window as WalletEventsWindow).removeEventListener(\n \"wallet-standard:register-wallet\",\n handler,\n );\n}\n\nclass AppReadyEvent extends Event implements WindowAppReadyEvent {\n constructor(public readonly detail: WindowAppReadyEventAPI) {\n super(\"wallet-standard:app-ready\", {\n bubbles: false,\n cancelable: false,\n composed: false,\n });\n }\n\n get type() {\n return \"wallet-standard:app-ready\" as const;\n }\n\n preventDefault(): never {\n throw new Error(\"preventDefault is deprecated\");\n }\n\n stopImmediatePropagation(): never {\n throw new Error(\"stopImmediatePropagation is deprecated\");\n }\n\n stopPropagation(): never {\n throw new Error(\"stopPropagation is deprecated\");\n }\n}\n","import { StarknetInjectedWallet } from \"@starknet-io/get-starknet-wallet-standard\";\nimport type { StarknetWindowObject } from \"@starknet-io/types-js\";\nimport type { Wallet } from \"@wallet-standard/base\";\n\nexport function registerInjectedWalletDiscovery(\n register: (wallet: Wallet) => () => void,\n): {\n unregister: () => void;\n refresh: () => void;\n} {\n if (typeof window === \"undefined\")\n return {\n unregister: () => {},\n refresh: () => {},\n };\n\n function refresh() {\n const injectedWallets = scanWindowForWallets(window);\n\n for (const wallet of injectedWallets) {\n register(new StarknetInjectedWallet(wallet));\n }\n }\n\n refresh();\n\n return {\n unregister: () => {},\n refresh,\n };\n}\n\nfunction scanWindowForWallets(window: Window): StarknetWindowObject[] {\n return Object.getOwnPropertyNames(window).reduce((wallets, key) => {\n if (key.startsWith(\"starknet\")) {\n const wallet = window[key];\n\n if (isStarknetWindowObject(wallet)) {\n wallets.push(wallet);\n }\n }\n\n return wallets;\n }, []);\n}\n\nconst STARKNET_WALLET_KEYS = [\n \"id\",\n \"name\",\n \"version\",\n \"icon\",\n \"request\",\n \"on\",\n \"off\",\n];\n\nfunction isStarknetWindowObject(\n wallet: unknown,\n): wallet is StarknetWindowObject {\n if (typeof wallet !== \"object\" || wallet === null) return false;\n return STARKNET_WALLET_KEYS.every((key) => key in wallet);\n}\n","import type { EIP1193Adapter } from \"@starknet-io/get-starknet-virtual-wallet\";\nimport type { Wallet } from \"@wallet-standard/base\";\n\nexport function registerEIP1193WalletFromEIP6963Discovery(\n eip1193Adapters: EIP1193Adapter[],\n register: (wallet: Wallet) => () => void,\n) {\n if (typeof window === \"undefined\") return;\n\n const handler = (event: CustomEvent) => {\n const { info, provider } = event.detail;\n for (const adapter of eip1193Adapters) {\n const wallet = adapter(info, provider);\n if (wallet) {\n register(wallet);\n return;\n }\n }\n };\n\n window.addEventListener(\"eip6963:announceProvider\", handler);\n\n window.dispatchEvent(new Event(\"eip6963:requestProvider\"));\n\n return () => window.removeEventListener(\"eip6963:announceProvider\", handler);\n}\n","import {\n type WalletWithStarknetFeatures,\n isStarknetWallet,\n} from \"@starknet-io/get-starknet-wallet-standard/features\";\nimport type { EIP1193Adapter } from \"@starknet-io/get-starknet-virtual-wallet\";\nimport { metaMaskVirtualWallet } from \"@starknet-io/get-starknet-virtual-wallet/metamask\";\n\nimport { registerStandardWalletDiscovery } from \"./standard-wallet\";\nimport { registerInjectedWalletDiscovery } from \"./injected-wallet\";\nimport { registerEIP1193WalletFromEIP6963Discovery } from \"./eip1193-wallet\";\n\nexport type CleanupListener = () => void;\nexport type Listener = (wallets: readonly WalletWithStarknetFeatures[]) => void;\n\nexport type Store = {\n getWallets: () => WalletWithStarknetFeatures[];\n subscribe: (listener: Listener) => CleanupListener;\n _refreshInjectedWallets: () => void;\n};\n\n// Track how a wallet was discovered to prefer standard wallets over (legacy) injected wallets\ntype DiscoveredStarknetWallet = {\n discoverer: \"standard\" | \"injected\" | \"eip6963\";\n wallet: WalletWithStarknetFeatures;\n};\n\nexport type CreateStoreOptions = {\n eip1193Adapters?: EIP1193Adapter[];\n};\n\nconst DEFAULT_EIP1193_ADAPTERS: EIP1193Adapter[] = [metaMaskVirtualWallet];\n\nexport function createStore({\n eip1193Adapters = DEFAULT_EIP1193_ADAPTERS,\n}: CreateStoreOptions = {}): Store {\n const listeners = new Set<Listener>();\n let wallets: DiscoveredStarknetWallet[] = [];\n\n function emitChanges() {\n for (const listener of listeners) {\n listener(wallets.map(({ wallet }) => wallet).slice());\n }\n }\n\n registerStandardWalletDiscovery((wallet) => {\n if (!isStarknetWallet(wallet)) return;\n\n const existing = wallets.find((w) => w.wallet.name === wallet.name);\n\n if (existing) {\n // If the wallet exists but is an injected wallet this library registered,\n // replace it with the standard wallet registered by the wallet itself.\n if (existing.discoverer !== \"standard\") {\n wallets = [\n { discoverer: \"standard\", wallet },\n ...wallets.filter((w) => w.wallet.name !== wallet.name),\n ];\n\n emitChanges();\n }\n } else {\n wallets = [{ discoverer: \"standard\", wallet }, ...wallets];\n\n emitChanges();\n }\n\n return () => {\n wallets = wallets.filter((w) => w.wallet.name !== wallet.name);\n\n emitChanges();\n };\n });\n\n registerEIP1193WalletFromEIP6963Discovery(eip1193Adapters, (wallet) => {\n if (!isStarknetWallet(wallet)) return;\n\n const existing = wallets.find((w) => w.wallet.name === wallet.name);\n\n if (!existing) {\n wallets = [{ discoverer: \"eip6963\", wallet }, ...wallets];\n\n emitChanges();\n }\n\n return () => {\n wallets = wallets.filter((w) => w.wallet.name !== wallet.name);\n\n emitChanges();\n };\n });\n\n const { refresh: refreshInjectedWallets } = registerInjectedWalletDiscovery(\n (wallet) => {\n if (!isStarknetWallet(wallet)) return;\n\n const existing = wallets.find((w) => w.wallet.name === wallet.name);\n\n // Only register injected wallets if they are not already registered.\n // We should not override standard wallets with injected wallets.\n if (!existing) {\n wallets = [{ discoverer: \"injected\", wallet }, ...wallets];\n\n emitChanges();\n }\n\n return () => {\n wallets = wallets.filter((w) => w.wallet.name !== wallet.name);\n\n emitChanges();\n };\n },\n );\n\n return {\n _refreshInjectedWallets: refreshInjectedWallets,\n getWallets() {\n return wallets.map(({ wallet }) => wallet).slice();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n"],"names":["StarknetInjectedWallet","window","metaMaskVirtualWallet","isStarknetWallet"],"mappings":";;;;;;AAQO,SAAS,gCACd,QACA,EAAA;AACA,EAAA,IAAI,OAAO,MAAW,KAAA,WAAA;AAAa,IAAA,OAAA;AAEnC,EAAA,MAAM,GAAM,GAAA,MAAA,CAAO,MAAO,CAAA,EAAE,UAAU,CAAA,CAAA;AAEtC,EAAA,MAAM,OAAU,GAAA,CAAC,EAAE,MAAA,EAAQ,UAA0C,KAAA;AACnE,IAAA,QAAA,CAAS,GAAG,CAAA,CAAA;AAAA,GACd,CAAA;AAEA,EAAC,MAA8B,CAAA,gBAAA;AAAA,IAC7B,iCAAA;AAAA,IACA,OAAA;AAAA,GACF,CAAA;AAEA,EAAC,MAA8B,CAAA,aAAA,CAAc,IAAI,aAAA,CAAc,GAAG,CAAC,CAAA,CAAA;AAEnE,EAAA,OAAO,MACJ,MAA8B,CAAA,mBAAA;AAAA,IAC7B,iCAAA;AAAA,IACA,OAAA;AAAA,GACF,CAAA;AACJ,CAAA;AAEA,MAAM,sBAAsB,KAAqC,CAAA;AAAA,EAC/D,YAA4B,MAAgC,EAAA;AAC1D,IAAA,KAAA,CAAM,2BAA6B,EAAA;AAAA,MACjC,OAAS,EAAA,KAAA;AAAA,MACT,UAAY,EAAA,KAAA;AAAA,MACZ,QAAU,EAAA,KAAA;AAAA,KACX,CAAA,CAAA;AALyB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AAAA,GAM5B;AAAA,EAEA,IAAI,IAAO,GAAA;AACT,IAAO,OAAA,2BAAA,CAAA;AAAA,GACT;AAAA,EAEA,cAAwB,GAAA;AACtB,IAAM,MAAA,IAAI,MAAM,8BAA8B,CAAA,CAAA;AAAA,GAChD;AAAA,EAEA,wBAAkC,GAAA;AAChC,IAAM,MAAA,IAAI,MAAM,wCAAwC,CAAA,CAAA;AAAA,GAC1D;AAAA,EAEA,eAAyB,GAAA;AACvB,IAAM,MAAA,IAAI,MAAM,+BAA+B,CAAA,CAAA;AAAA,GACjD;AACF;;ACrDO,SAAS,gCACd,QAIA,EAAA;AACA,EAAA,IAAI,OAAO,MAAW,KAAA,WAAA;AACpB,IAAO,OAAA;AAAA,MACL,YAAY,MAAM;AAAA,OAAC;AAAA,MACnB,SAAS,MAAM;AAAA,OAAC;AAAA,KAClB,CAAA;AAEF,EAAA,SAAS,OAAU,GAAA;AACjB,IAAM,MAAA,eAAA,GAAkB,qBAAqB,MAAM,CAAA,CAAA;AAEnD,IAAA,KAAA,MAAW,UAAU,eAAiB,EAAA;AACpC,MAAS,QAAA,CAAA,IAAIA,gDAAuB,CAAA,MAAM,CAAC,CAAA,CAAA;AAAA,KAC7C;AAAA,GACF;AAEA,EAAQ,OAAA,EAAA,CAAA;AAER,EAAO,OAAA;AAAA,IACL,YAAY,MAAM;AAAA,KAAC;AAAA,IACnB,OAAA;AAAA,GACF,CAAA;AACF,CAAA;AAEA,SAAS,qBAAqBC,OAAwC,EAAA;AACpE,EAAA,OAAO,OAAO,mBAAoBA,CAAAA,OAAM,EAAE,MAAO,CAAA,CAAC,SAAS,GAAQ,KAAA;AACjE,IAAI,IAAA,GAAA,CAAI,UAAW,CAAA,UAAU,CAAG,EAAA;AAC9B,MAAM,MAAA,MAAA,GAASA,QAAO,GAAG,CAAA,CAAA;AAEzB,MAAI,IAAA,sBAAA,CAAuB,MAAM,CAAG,EAAA;AAClC,QAAA,OAAA,CAAQ,KAAK,MAAM,CAAA,CAAA;AAAA,OACrB;AAAA,KACF;AAEA,IAAO,OAAA,OAAA,CAAA;AAAA,GACT,EAAG,EAAE,CAAA,CAAA;AACP,CAAA;AAEA,MAAM,oBAAuB,GAAA;AAAA,EAC3B,IAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AACF,CAAA,CAAA;AAEA,SAAS,uBACP,MACgC,EAAA;AAChC,EAAI,IAAA,OAAO,MAAW,KAAA,QAAA,IAAY,MAAW,KAAA,IAAA;AAAM,IAAO,OAAA,KAAA,CAAA;AAC1D,EAAA,OAAO,oBAAqB,CAAA,KAAA,CAAM,CAAC,GAAA,KAAQ,OAAO,MAAM,CAAA,CAAA;AAC1D;;AC1DgB,SAAA,yCAAA,CACd,iBACA,QACA,EAAA;AACA,EAAA,IAAI,OAAO,MAAW,KAAA,WAAA;AAAa,IAAA,OAAA;AAEnC,EAAM,MAAA,OAAA,GAAU,CAAC,KAAuB,KAAA;AACtC,IAAA,MAAM,EAAE,IAAA,EAAM,QAAS,EAAA,GAAI,KAAM,CAAA,MAAA,CAAA;AACjC,IAAA,KAAA,MAAW,WAAW,eAAiB,EAAA;AACrC,MAAM,MAAA,MAAA,GAAS,OAAQ,CAAA,IAAA,EAAM,QAAQ,CAAA,CAAA;AACrC,MAAA,IAAI,MAAQ,EAAA;AACV,QAAA,QAAA,CAAS,MAAM,CAAA,CAAA;AACf,QAAA,OAAA;AAAA,OACF;AAAA,KACF;AAAA,GACF,CAAA;AAEA,EAAO,MAAA,CAAA,gBAAA,CAAiB,4BAA4B,OAAO,CAAA,CAAA;AAE3D,EAAA,MAAA,CAAO,aAAc,CAAA,IAAI,KAAM,CAAA,yBAAyB,CAAC,CAAA,CAAA;AAEzD,EAAA,OAAO,MAAM,MAAA,CAAO,mBAAoB,CAAA,0BAAA,EAA4B,OAAO,CAAA,CAAA;AAC7E;;ACKA,MAAM,wBAAA,GAA6C,CAACC,8BAAqB,CAAA,CAAA;AAElE,SAAS,WAAY,CAAA;AAAA,EAC1B,eAAkB,GAAA,wBAAA;AACpB,CAAA,GAAwB,EAAW,EAAA;AACjC,EAAM,MAAA,SAAA,uBAAgB,GAAc,EAAA,CAAA;AACpC,EAAA,IAAI,UAAsC,EAAC,CAAA;AAE3C,EAAA,SAAS,WAAc,GAAA;AACrB,IAAA,KAAA,MAAW,YAAY,SAAW,EAAA;AAChC,MAAS,QAAA,CAAA,OAAA,CAAQ,IAAI,CAAC,EAAE,QAAa,KAAA,MAAM,CAAE,CAAA,KAAA,EAAO,CAAA,CAAA;AAAA,KACtD;AAAA,GACF;AAEA,EAAA,+BAAA,CAAgC,CAAC,MAAW,KAAA;AAC1C,IAAI,IAAA,CAACC,0BAAiB,MAAM,CAAA;AAAG,MAAA,OAAA;AAE/B,IAAM,MAAA,QAAA,GAAW,QAAQ,IAAK,CAAA,CAAC,MAAM,CAAE,CAAA,MAAA,CAAO,IAAS,KAAA,MAAA,CAAO,IAAI,CAAA,CAAA;AAElE,IAAA,IAAI,QAAU,EAAA;AAGZ,MAAI,IAAA,QAAA,CAAS,eAAe,UAAY,EAAA;AACtC,QAAU,OAAA,GAAA;AAAA,UACR,EAAE,UAAY,EAAA,UAAA,EAAY,MAAO,EAAA;AAAA,UACjC,GAAG,QAAQ,MAAO,CAAA,CAAC,MAAM,CAAE,CAAA,MAAA,CAAO,IAAS,KAAA,MAAA,CAAO,IAAI,CAAA;AAAA,SACxD,CAAA;AAEA,QAAY,WAAA,EAAA,CAAA;AAAA,OACd;AAAA,KACK,MAAA;AACL,MAAA,OAAA,GAAU,CAAC,EAAE,UAAA,EAAY,YAAY,MAAO,EAAA,EAAG,GAAG,OAAO,CAAA,CAAA;AAEzD,MAAY,WAAA,EAAA,CAAA;AAAA,KACd;AAEA,IAAA,OAAO,MAAM;AACX,MAAU,OAAA,GAAA,OAAA,CAAQ,OAAO,CAAC,CAAA,KAAM,EAAE,MAAO,CAAA,IAAA,KAAS,OAAO,IAAI,CAAA,CAAA;AAE7D,MAAY,WAAA,EAAA,CAAA;AAAA,KACd,CAAA;AAAA,GACD,CAAA,CAAA;AAED,EAA0C,yCAAA,CAAA,eAAA,EAAiB,CAAC,MAAW,KAAA;AACrE,IAAI,IAAA,CAACA,0BAAiB,MAAM,CAAA;AAAG,MAAA,OAAA;AAE/B,IAAM,MAAA,QAAA,GAAW,QAAQ,IAAK,CAAA,CAAC,MAAM,CAAE,CAAA,MAAA,CAAO,IAAS,KAAA,MAAA,CAAO,IAAI,CAAA,CAAA;AAElE,IAAA,IAAI,CAAC,QAAU,EAAA;AACb,MAAA,OAAA,GAAU,CAAC,EAAE,UAAA,EAAY,WAAW,MAAO,EAAA,EAAG,GAAG,OAAO,CAAA,CAAA;AAExD,MAAY,WAAA,EAAA,CAAA;AAAA,KACd;AAEA,IAAA,OAAO,MAAM;AACX,MAAU,OAAA,GAAA,OAAA,CAAQ,OAAO,CAAC,CAAA,KAAM,EAAE,MAAO,CAAA,IAAA,KAAS,OAAO,IAAI,CAAA,CAAA;AAE7D,MAAY,WAAA,EAAA,CAAA;AAAA,KACd,CAAA;AAAA,GACD,CAAA,CAAA;AAED,EAAM,MAAA,EAAE,OAAS,EAAA,sBAAA,EAA2B,GAAA,+BAAA;AAAA,IAC1C,CAAC,MAAW,KAAA;AACV,MAAI,IAAA,CAACA,0BAAiB,MAAM,CAAA;AAAG,QAAA,OAAA;AAE/B,MAAM,MAAA,QAAA,GAAW,QAAQ,IAAK,CAAA,CAAC,MAAM,CAAE,CAAA,MAAA,CAAO,IAAS,KAAA,MAAA,CAAO,IAAI,CAAA,CAAA;AAIlE,MAAA,IAAI,CAAC,QAAU,EAAA;AACb,QAAA,OAAA,GAAU,CAAC,EAAE,UAAA,EAAY,YAAY,MAAO,EAAA,EAAG,GAAG,OAAO,CAAA,CAAA;AAEzD,QAAY,WAAA,EAAA,CAAA;AAAA,OACd;AAEA,MAAA,OAAO,MAAM;AACX,QAAU,OAAA,GAAA,OAAA,CAAQ,OAAO,CAAC,CAAA,KAAM,EAAE,MAAO,CAAA,IAAA,KAAS,OAAO,IAAI,CAAA,CAAA;AAE7D,QAAY,WAAA,EAAA,CAAA;AAAA,OACd,CAAA;AAAA,KACF;AAAA,GACF,CAAA;AAEA,EAAO,OAAA;AAAA,IACL,uBAAyB,EAAA,sBAAA;AAAA,IACzB,UAAa,GAAA;AACX,MAAO,OAAA,OAAA,CAAQ,IAAI,CAAC,EAAE,QAAa,KAAA,MAAM,EAAE,KAAM,EAAA,CAAA;AAAA,KACnD;AAAA,IACA,UAAU,QAAU,EAAA;AAClB,MAAA,SAAA,CAAU,IAAI,QAAQ,CAAA,CAAA;AACtB,MAAA,OAAO,MAAM;AACX,QAAA,SAAA,CAAU,OAAO,QAAQ,CAAA,CAAA;AAAA,OAC3B,CAAA;AAAA,KACF;AAAA,GACF,CAAA;AACF;;;;"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { WalletWithStarknetFeatures } from '@starknet-io/get-starknet-wallet-standard/features';
|
|
2
|
+
import { EIP1193Adapter } from '@starknet-io/get-starknet-virtual-wallet';
|
|
3
|
+
|
|
4
|
+
type CleanupListener = () => void;
|
|
5
|
+
type Listener = (wallets: readonly WalletWithStarknetFeatures[]) => void;
|
|
6
|
+
type Store = {
|
|
7
|
+
getWallets: () => WalletWithStarknetFeatures[];
|
|
8
|
+
subscribe: (listener: Listener) => CleanupListener;
|
|
9
|
+
_refreshInjectedWallets: () => void;
|
|
10
|
+
};
|
|
11
|
+
type CreateStoreOptions = {
|
|
12
|
+
eip1193Adapters?: EIP1193Adapter[];
|
|
13
|
+
};
|
|
14
|
+
declare function createStore({ eip1193Adapters, }?: CreateStoreOptions): Store;
|
|
15
|
+
|
|
16
|
+
export { type CleanupListener, type Listener, type Store, createStore };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { WalletWithStarknetFeatures } from '@starknet-io/get-starknet-wallet-standard/features';
|
|
2
|
+
import { EIP1193Adapter } from '@starknet-io/get-starknet-virtual-wallet';
|
|
3
|
+
|
|
4
|
+
type CleanupListener = () => void;
|
|
5
|
+
type Listener = (wallets: readonly WalletWithStarknetFeatures[]) => void;
|
|
6
|
+
type Store = {
|
|
7
|
+
getWallets: () => WalletWithStarknetFeatures[];
|
|
8
|
+
subscribe: (listener: Listener) => CleanupListener;
|
|
9
|
+
_refreshInjectedWallets: () => void;
|
|
10
|
+
};
|
|
11
|
+
type CreateStoreOptions = {
|
|
12
|
+
eip1193Adapters?: EIP1193Adapter[];
|
|
13
|
+
};
|
|
14
|
+
declare function createStore({ eip1193Adapters, }?: CreateStoreOptions): Store;
|
|
15
|
+
|
|
16
|
+
export { type CleanupListener, type Listener, type Store, createStore };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { WalletWithStarknetFeatures } from '@starknet-io/get-starknet-wallet-standard/features';
|
|
2
|
+
import { EIP1193Adapter } from '@starknet-io/get-starknet-virtual-wallet';
|
|
3
|
+
|
|
4
|
+
type CleanupListener = () => void;
|
|
5
|
+
type Listener = (wallets: readonly WalletWithStarknetFeatures[]) => void;
|
|
6
|
+
type Store = {
|
|
7
|
+
getWallets: () => WalletWithStarknetFeatures[];
|
|
8
|
+
subscribe: (listener: Listener) => CleanupListener;
|
|
9
|
+
_refreshInjectedWallets: () => void;
|
|
10
|
+
};
|
|
11
|
+
type CreateStoreOptions = {
|
|
12
|
+
eip1193Adapters?: EIP1193Adapter[];
|
|
13
|
+
};
|
|
14
|
+
declare function createStore({ eip1193Adapters, }?: CreateStoreOptions): Store;
|
|
15
|
+
|
|
16
|
+
export { type CleanupListener, type Listener, type Store, createStore };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { isStarknetWallet } from '@starknet-io/get-starknet-wallet-standard/features';
|
|
2
|
+
import { metaMaskVirtualWallet } from '@starknet-io/get-starknet-virtual-wallet/metamask';
|
|
3
|
+
import { StarknetInjectedWallet } from '@starknet-io/get-starknet-wallet-standard';
|
|
4
|
+
|
|
5
|
+
function registerStandardWalletDiscovery(register) {
|
|
6
|
+
if (typeof window === "undefined")
|
|
7
|
+
return;
|
|
8
|
+
const api = Object.freeze({ register });
|
|
9
|
+
const handler = ({ detail: callback }) => {
|
|
10
|
+
callback(api);
|
|
11
|
+
};
|
|
12
|
+
window.addEventListener(
|
|
13
|
+
"wallet-standard:register-wallet",
|
|
14
|
+
handler
|
|
15
|
+
);
|
|
16
|
+
window.dispatchEvent(new AppReadyEvent(api));
|
|
17
|
+
return () => window.removeEventListener(
|
|
18
|
+
"wallet-standard:register-wallet",
|
|
19
|
+
handler
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
class AppReadyEvent extends Event {
|
|
23
|
+
constructor(detail) {
|
|
24
|
+
super("wallet-standard:app-ready", {
|
|
25
|
+
bubbles: false,
|
|
26
|
+
cancelable: false,
|
|
27
|
+
composed: false
|
|
28
|
+
});
|
|
29
|
+
this.detail = detail;
|
|
30
|
+
}
|
|
31
|
+
get type() {
|
|
32
|
+
return "wallet-standard:app-ready";
|
|
33
|
+
}
|
|
34
|
+
preventDefault() {
|
|
35
|
+
throw new Error("preventDefault is deprecated");
|
|
36
|
+
}
|
|
37
|
+
stopImmediatePropagation() {
|
|
38
|
+
throw new Error("stopImmediatePropagation is deprecated");
|
|
39
|
+
}
|
|
40
|
+
stopPropagation() {
|
|
41
|
+
throw new Error("stopPropagation is deprecated");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function registerInjectedWalletDiscovery(register) {
|
|
46
|
+
if (typeof window === "undefined")
|
|
47
|
+
return {
|
|
48
|
+
unregister: () => {
|
|
49
|
+
},
|
|
50
|
+
refresh: () => {
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
function refresh() {
|
|
54
|
+
const injectedWallets = scanWindowForWallets(window);
|
|
55
|
+
for (const wallet of injectedWallets) {
|
|
56
|
+
register(new StarknetInjectedWallet(wallet));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
refresh();
|
|
60
|
+
return {
|
|
61
|
+
unregister: () => {
|
|
62
|
+
},
|
|
63
|
+
refresh
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function scanWindowForWallets(window2) {
|
|
67
|
+
return Object.getOwnPropertyNames(window2).reduce((wallets, key) => {
|
|
68
|
+
if (key.startsWith("starknet")) {
|
|
69
|
+
const wallet = window2[key];
|
|
70
|
+
if (isStarknetWindowObject(wallet)) {
|
|
71
|
+
wallets.push(wallet);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return wallets;
|
|
75
|
+
}, []);
|
|
76
|
+
}
|
|
77
|
+
const STARKNET_WALLET_KEYS = [
|
|
78
|
+
"id",
|
|
79
|
+
"name",
|
|
80
|
+
"version",
|
|
81
|
+
"icon",
|
|
82
|
+
"request",
|
|
83
|
+
"on",
|
|
84
|
+
"off"
|
|
85
|
+
];
|
|
86
|
+
function isStarknetWindowObject(wallet) {
|
|
87
|
+
if (typeof wallet !== "object" || wallet === null)
|
|
88
|
+
return false;
|
|
89
|
+
return STARKNET_WALLET_KEYS.every((key) => key in wallet);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function registerEIP1193WalletFromEIP6963Discovery(eip1193Adapters, register) {
|
|
93
|
+
if (typeof window === "undefined")
|
|
94
|
+
return;
|
|
95
|
+
const handler = (event) => {
|
|
96
|
+
const { info, provider } = event.detail;
|
|
97
|
+
for (const adapter of eip1193Adapters) {
|
|
98
|
+
const wallet = adapter(info, provider);
|
|
99
|
+
if (wallet) {
|
|
100
|
+
register(wallet);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
window.addEventListener("eip6963:announceProvider", handler);
|
|
106
|
+
window.dispatchEvent(new Event("eip6963:requestProvider"));
|
|
107
|
+
return () => window.removeEventListener("eip6963:announceProvider", handler);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const DEFAULT_EIP1193_ADAPTERS = [metaMaskVirtualWallet];
|
|
111
|
+
function createStore({
|
|
112
|
+
eip1193Adapters = DEFAULT_EIP1193_ADAPTERS
|
|
113
|
+
} = {}) {
|
|
114
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
115
|
+
let wallets = [];
|
|
116
|
+
function emitChanges() {
|
|
117
|
+
for (const listener of listeners) {
|
|
118
|
+
listener(wallets.map(({ wallet }) => wallet).slice());
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
registerStandardWalletDiscovery((wallet) => {
|
|
122
|
+
if (!isStarknetWallet(wallet))
|
|
123
|
+
return;
|
|
124
|
+
const existing = wallets.find((w) => w.wallet.name === wallet.name);
|
|
125
|
+
if (existing) {
|
|
126
|
+
if (existing.discoverer !== "standard") {
|
|
127
|
+
wallets = [
|
|
128
|
+
{ discoverer: "standard", wallet },
|
|
129
|
+
...wallets.filter((w) => w.wallet.name !== wallet.name)
|
|
130
|
+
];
|
|
131
|
+
emitChanges();
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
wallets = [{ discoverer: "standard", wallet }, ...wallets];
|
|
135
|
+
emitChanges();
|
|
136
|
+
}
|
|
137
|
+
return () => {
|
|
138
|
+
wallets = wallets.filter((w) => w.wallet.name !== wallet.name);
|
|
139
|
+
emitChanges();
|
|
140
|
+
};
|
|
141
|
+
});
|
|
142
|
+
registerEIP1193WalletFromEIP6963Discovery(eip1193Adapters, (wallet) => {
|
|
143
|
+
if (!isStarknetWallet(wallet))
|
|
144
|
+
return;
|
|
145
|
+
const existing = wallets.find((w) => w.wallet.name === wallet.name);
|
|
146
|
+
if (!existing) {
|
|
147
|
+
wallets = [{ discoverer: "eip6963", wallet }, ...wallets];
|
|
148
|
+
emitChanges();
|
|
149
|
+
}
|
|
150
|
+
return () => {
|
|
151
|
+
wallets = wallets.filter((w) => w.wallet.name !== wallet.name);
|
|
152
|
+
emitChanges();
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
const { refresh: refreshInjectedWallets } = registerInjectedWalletDiscovery(
|
|
156
|
+
(wallet) => {
|
|
157
|
+
if (!isStarknetWallet(wallet))
|
|
158
|
+
return;
|
|
159
|
+
const existing = wallets.find((w) => w.wallet.name === wallet.name);
|
|
160
|
+
if (!existing) {
|
|
161
|
+
wallets = [{ discoverer: "injected", wallet }, ...wallets];
|
|
162
|
+
emitChanges();
|
|
163
|
+
}
|
|
164
|
+
return () => {
|
|
165
|
+
wallets = wallets.filter((w) => w.wallet.name !== wallet.name);
|
|
166
|
+
emitChanges();
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
return {
|
|
171
|
+
_refreshInjectedWallets: refreshInjectedWallets,
|
|
172
|
+
getWallets() {
|
|
173
|
+
return wallets.map(({ wallet }) => wallet).slice();
|
|
174
|
+
},
|
|
175
|
+
subscribe(listener) {
|
|
176
|
+
listeners.add(listener);
|
|
177
|
+
return () => {
|
|
178
|
+
listeners.delete(listener);
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export { createStore };
|
|
185
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/standard-wallet.ts","../src/injected-wallet.ts","../src/eip1193-wallet.ts","../src/store.ts"],"sourcesContent":["import type {\n WalletEventsWindow,\n WindowRegisterWalletEvent,\n WindowAppReadyEvent,\n WindowAppReadyEventAPI,\n Wallet,\n} from \"@wallet-standard/base\";\n\nexport function registerStandardWalletDiscovery(\n register: (wallet: Wallet) => () => void,\n) {\n if (typeof window === \"undefined\") return;\n\n const api = Object.freeze({ register });\n\n const handler = ({ detail: callback }: WindowRegisterWalletEvent) => {\n callback(api);\n };\n\n (window as WalletEventsWindow).addEventListener(\n \"wallet-standard:register-wallet\",\n handler,\n );\n\n (window as WalletEventsWindow).dispatchEvent(new AppReadyEvent(api));\n\n return () =>\n (window as WalletEventsWindow).removeEventListener(\n \"wallet-standard:register-wallet\",\n handler,\n );\n}\n\nclass AppReadyEvent extends Event implements WindowAppReadyEvent {\n constructor(public readonly detail: WindowAppReadyEventAPI) {\n super(\"wallet-standard:app-ready\", {\n bubbles: false,\n cancelable: false,\n composed: false,\n });\n }\n\n get type() {\n return \"wallet-standard:app-ready\" as const;\n }\n\n preventDefault(): never {\n throw new Error(\"preventDefault is deprecated\");\n }\n\n stopImmediatePropagation(): never {\n throw new Error(\"stopImmediatePropagation is deprecated\");\n }\n\n stopPropagation(): never {\n throw new Error(\"stopPropagation is deprecated\");\n }\n}\n","import { StarknetInjectedWallet } from \"@starknet-io/get-starknet-wallet-standard\";\nimport type { StarknetWindowObject } from \"@starknet-io/types-js\";\nimport type { Wallet } from \"@wallet-standard/base\";\n\nexport function registerInjectedWalletDiscovery(\n register: (wallet: Wallet) => () => void,\n): {\n unregister: () => void;\n refresh: () => void;\n} {\n if (typeof window === \"undefined\")\n return {\n unregister: () => {},\n refresh: () => {},\n };\n\n function refresh() {\n const injectedWallets = scanWindowForWallets(window);\n\n for (const wallet of injectedWallets) {\n register(new StarknetInjectedWallet(wallet));\n }\n }\n\n refresh();\n\n return {\n unregister: () => {},\n refresh,\n };\n}\n\nfunction scanWindowForWallets(window: Window): StarknetWindowObject[] {\n return Object.getOwnPropertyNames(window).reduce((wallets, key) => {\n if (key.startsWith(\"starknet\")) {\n const wallet = window[key];\n\n if (isStarknetWindowObject(wallet)) {\n wallets.push(wallet);\n }\n }\n\n return wallets;\n }, []);\n}\n\nconst STARKNET_WALLET_KEYS = [\n \"id\",\n \"name\",\n \"version\",\n \"icon\",\n \"request\",\n \"on\",\n \"off\",\n];\n\nfunction isStarknetWindowObject(\n wallet: unknown,\n): wallet is StarknetWindowObject {\n if (typeof wallet !== \"object\" || wallet === null) return false;\n return STARKNET_WALLET_KEYS.every((key) => key in wallet);\n}\n","import type { EIP1193Adapter } from \"@starknet-io/get-starknet-virtual-wallet\";\nimport type { Wallet } from \"@wallet-standard/base\";\n\nexport function registerEIP1193WalletFromEIP6963Discovery(\n eip1193Adapters: EIP1193Adapter[],\n register: (wallet: Wallet) => () => void,\n) {\n if (typeof window === \"undefined\") return;\n\n const handler = (event: CustomEvent) => {\n const { info, provider } = event.detail;\n for (const adapter of eip1193Adapters) {\n const wallet = adapter(info, provider);\n if (wallet) {\n register(wallet);\n return;\n }\n }\n };\n\n window.addEventListener(\"eip6963:announceProvider\", handler);\n\n window.dispatchEvent(new Event(\"eip6963:requestProvider\"));\n\n return () => window.removeEventListener(\"eip6963:announceProvider\", handler);\n}\n","import {\n type WalletWithStarknetFeatures,\n isStarknetWallet,\n} from \"@starknet-io/get-starknet-wallet-standard/features\";\nimport type { EIP1193Adapter } from \"@starknet-io/get-starknet-virtual-wallet\";\nimport { metaMaskVirtualWallet } from \"@starknet-io/get-starknet-virtual-wallet/metamask\";\n\nimport { registerStandardWalletDiscovery } from \"./standard-wallet\";\nimport { registerInjectedWalletDiscovery } from \"./injected-wallet\";\nimport { registerEIP1193WalletFromEIP6963Discovery } from \"./eip1193-wallet\";\n\nexport type CleanupListener = () => void;\nexport type Listener = (wallets: readonly WalletWithStarknetFeatures[]) => void;\n\nexport type Store = {\n getWallets: () => WalletWithStarknetFeatures[];\n subscribe: (listener: Listener) => CleanupListener;\n _refreshInjectedWallets: () => void;\n};\n\n// Track how a wallet was discovered to prefer standard wallets over (legacy) injected wallets\ntype DiscoveredStarknetWallet = {\n discoverer: \"standard\" | \"injected\" | \"eip6963\";\n wallet: WalletWithStarknetFeatures;\n};\n\nexport type CreateStoreOptions = {\n eip1193Adapters?: EIP1193Adapter[];\n};\n\nconst DEFAULT_EIP1193_ADAPTERS: EIP1193Adapter[] = [metaMaskVirtualWallet];\n\nexport function createStore({\n eip1193Adapters = DEFAULT_EIP1193_ADAPTERS,\n}: CreateStoreOptions = {}): Store {\n const listeners = new Set<Listener>();\n let wallets: DiscoveredStarknetWallet[] = [];\n\n function emitChanges() {\n for (const listener of listeners) {\n listener(wallets.map(({ wallet }) => wallet).slice());\n }\n }\n\n registerStandardWalletDiscovery((wallet) => {\n if (!isStarknetWallet(wallet)) return;\n\n const existing = wallets.find((w) => w.wallet.name === wallet.name);\n\n if (existing) {\n // If the wallet exists but is an injected wallet this library registered,\n // replace it with the standard wallet registered by the wallet itself.\n if (existing.discoverer !== \"standard\") {\n wallets = [\n { discoverer: \"standard\", wallet },\n ...wallets.filter((w) => w.wallet.name !== wallet.name),\n ];\n\n emitChanges();\n }\n } else {\n wallets = [{ discoverer: \"standard\", wallet }, ...wallets];\n\n emitChanges();\n }\n\n return () => {\n wallets = wallets.filter((w) => w.wallet.name !== wallet.name);\n\n emitChanges();\n };\n });\n\n registerEIP1193WalletFromEIP6963Discovery(eip1193Adapters, (wallet) => {\n if (!isStarknetWallet(wallet)) return;\n\n const existing = wallets.find((w) => w.wallet.name === wallet.name);\n\n if (!existing) {\n wallets = [{ discoverer: \"eip6963\", wallet }, ...wallets];\n\n emitChanges();\n }\n\n return () => {\n wallets = wallets.filter((w) => w.wallet.name !== wallet.name);\n\n emitChanges();\n };\n });\n\n const { refresh: refreshInjectedWallets } = registerInjectedWalletDiscovery(\n (wallet) => {\n if (!isStarknetWallet(wallet)) return;\n\n const existing = wallets.find((w) => w.wallet.name === wallet.name);\n\n // Only register injected wallets if they are not already registered.\n // We should not override standard wallets with injected wallets.\n if (!existing) {\n wallets = [{ discoverer: \"injected\", wallet }, ...wallets];\n\n emitChanges();\n }\n\n return () => {\n wallets = wallets.filter((w) => w.wallet.name !== wallet.name);\n\n emitChanges();\n };\n },\n );\n\n return {\n _refreshInjectedWallets: refreshInjectedWallets,\n getWallets() {\n return wallets.map(({ wallet }) => wallet).slice();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n"],"names":["window"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@starknet-io/get-starknet-discovery",
|
|
3
|
+
"version": "5.0.0-beta.0",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"starknet",
|
|
6
|
+
"starkware",
|
|
7
|
+
"l2",
|
|
8
|
+
"zk",
|
|
9
|
+
"rollup",
|
|
10
|
+
"wallet",
|
|
11
|
+
"dapp"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "./dist/index.mjs",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"import": "./dist/index.mjs",
|
|
21
|
+
"require": "./dist/index.cjs",
|
|
22
|
+
"default": "./dist/index.mjs"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"src"
|
|
28
|
+
],
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@wallet-standard/core": "^1.1.0",
|
|
31
|
+
"happy-dom": "^17.4.4",
|
|
32
|
+
"typescript": "^5.8.3",
|
|
33
|
+
"unbuild": "^2.0.0",
|
|
34
|
+
"vitest": "^3.1.1"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@starknet-io/types-js": "^0.7.10",
|
|
38
|
+
"@wallet-standard/base": "^1.1.0",
|
|
39
|
+
"@starknet-io/get-starknet-virtual-wallet": "^5.0.0-beta.0",
|
|
40
|
+
"@starknet-io/get-starknet-wallet-standard": "^5.0.0-beta.0"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "unbuild",
|
|
44
|
+
"format:check": "biome format .",
|
|
45
|
+
"format": "biome format --write .",
|
|
46
|
+
"lint:check": "biome lint .",
|
|
47
|
+
"lint": "biome lint --write .",
|
|
48
|
+
"test": "vitest"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { EIP1193Adapter } from "@starknet-io/get-starknet-virtual-wallet";
|
|
2
|
+
import type { Wallet } from "@wallet-standard/base";
|
|
3
|
+
|
|
4
|
+
export function registerEIP1193WalletFromEIP6963Discovery(
|
|
5
|
+
eip1193Adapters: EIP1193Adapter[],
|
|
6
|
+
register: (wallet: Wallet) => () => void,
|
|
7
|
+
) {
|
|
8
|
+
if (typeof window === "undefined") return;
|
|
9
|
+
|
|
10
|
+
const handler = (event: CustomEvent) => {
|
|
11
|
+
const { info, provider } = event.detail;
|
|
12
|
+
for (const adapter of eip1193Adapters) {
|
|
13
|
+
const wallet = adapter(info, provider);
|
|
14
|
+
if (wallet) {
|
|
15
|
+
register(wallet);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
window.addEventListener("eip6963:announceProvider", handler);
|
|
22
|
+
|
|
23
|
+
window.dispatchEvent(new Event("eip6963:requestProvider"));
|
|
24
|
+
|
|
25
|
+
return () => window.removeEventListener("eip6963:announceProvider", handler);
|
|
26
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { StarknetInjectedWallet } from "@starknet-io/get-starknet-wallet-standard";
|
|
2
|
+
import type { StarknetWindowObject } from "@starknet-io/types-js";
|
|
3
|
+
import type { Wallet } from "@wallet-standard/base";
|
|
4
|
+
|
|
5
|
+
export function registerInjectedWalletDiscovery(
|
|
6
|
+
register: (wallet: Wallet) => () => void,
|
|
7
|
+
): {
|
|
8
|
+
unregister: () => void;
|
|
9
|
+
refresh: () => void;
|
|
10
|
+
} {
|
|
11
|
+
if (typeof window === "undefined")
|
|
12
|
+
return {
|
|
13
|
+
unregister: () => {},
|
|
14
|
+
refresh: () => {},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function refresh() {
|
|
18
|
+
const injectedWallets = scanWindowForWallets(window);
|
|
19
|
+
|
|
20
|
+
for (const wallet of injectedWallets) {
|
|
21
|
+
register(new StarknetInjectedWallet(wallet));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
refresh();
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
unregister: () => {},
|
|
29
|
+
refresh,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function scanWindowForWallets(window: Window): StarknetWindowObject[] {
|
|
34
|
+
return Object.getOwnPropertyNames(window).reduce((wallets, key) => {
|
|
35
|
+
if (key.startsWith("starknet")) {
|
|
36
|
+
const wallet = window[key];
|
|
37
|
+
|
|
38
|
+
if (isStarknetWindowObject(wallet)) {
|
|
39
|
+
wallets.push(wallet);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return wallets;
|
|
44
|
+
}, []);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const STARKNET_WALLET_KEYS = [
|
|
48
|
+
"id",
|
|
49
|
+
"name",
|
|
50
|
+
"version",
|
|
51
|
+
"icon",
|
|
52
|
+
"request",
|
|
53
|
+
"on",
|
|
54
|
+
"off",
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
function isStarknetWindowObject(
|
|
58
|
+
wallet: unknown,
|
|
59
|
+
): wallet is StarknetWindowObject {
|
|
60
|
+
if (typeof wallet !== "object" || wallet === null) return false;
|
|
61
|
+
return STARKNET_WALLET_KEYS.every((key) => key in wallet);
|
|
62
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
WalletEventsWindow,
|
|
3
|
+
WindowRegisterWalletEvent,
|
|
4
|
+
WindowAppReadyEvent,
|
|
5
|
+
WindowAppReadyEventAPI,
|
|
6
|
+
Wallet,
|
|
7
|
+
} from "@wallet-standard/base";
|
|
8
|
+
|
|
9
|
+
export function registerStandardWalletDiscovery(
|
|
10
|
+
register: (wallet: Wallet) => () => void,
|
|
11
|
+
) {
|
|
12
|
+
if (typeof window === "undefined") return;
|
|
13
|
+
|
|
14
|
+
const api = Object.freeze({ register });
|
|
15
|
+
|
|
16
|
+
const handler = ({ detail: callback }: WindowRegisterWalletEvent) => {
|
|
17
|
+
callback(api);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
(window as WalletEventsWindow).addEventListener(
|
|
21
|
+
"wallet-standard:register-wallet",
|
|
22
|
+
handler,
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
(window as WalletEventsWindow).dispatchEvent(new AppReadyEvent(api));
|
|
26
|
+
|
|
27
|
+
return () =>
|
|
28
|
+
(window as WalletEventsWindow).removeEventListener(
|
|
29
|
+
"wallet-standard:register-wallet",
|
|
30
|
+
handler,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
class AppReadyEvent extends Event implements WindowAppReadyEvent {
|
|
35
|
+
constructor(public readonly detail: WindowAppReadyEventAPI) {
|
|
36
|
+
super("wallet-standard:app-ready", {
|
|
37
|
+
bubbles: false,
|
|
38
|
+
cancelable: false,
|
|
39
|
+
composed: false,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get type() {
|
|
44
|
+
return "wallet-standard:app-ready" as const;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
preventDefault(): never {
|
|
48
|
+
throw new Error("preventDefault is deprecated");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
stopImmediatePropagation(): never {
|
|
52
|
+
throw new Error("stopImmediatePropagation is deprecated");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
stopPropagation(): never {
|
|
56
|
+
throw new Error("stopPropagation is deprecated");
|
|
57
|
+
}
|
|
58
|
+
}
|
package/src/store.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type WalletWithStarknetFeatures,
|
|
3
|
+
isStarknetWallet,
|
|
4
|
+
} from "@starknet-io/get-starknet-wallet-standard/features";
|
|
5
|
+
import type { EIP1193Adapter } from "@starknet-io/get-starknet-virtual-wallet";
|
|
6
|
+
import { metaMaskVirtualWallet } from "@starknet-io/get-starknet-virtual-wallet/metamask";
|
|
7
|
+
|
|
8
|
+
import { registerStandardWalletDiscovery } from "./standard-wallet";
|
|
9
|
+
import { registerInjectedWalletDiscovery } from "./injected-wallet";
|
|
10
|
+
import { registerEIP1193WalletFromEIP6963Discovery } from "./eip1193-wallet";
|
|
11
|
+
|
|
12
|
+
export type CleanupListener = () => void;
|
|
13
|
+
export type Listener = (wallets: readonly WalletWithStarknetFeatures[]) => void;
|
|
14
|
+
|
|
15
|
+
export type Store = {
|
|
16
|
+
getWallets: () => WalletWithStarknetFeatures[];
|
|
17
|
+
subscribe: (listener: Listener) => CleanupListener;
|
|
18
|
+
_refreshInjectedWallets: () => void;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Track how a wallet was discovered to prefer standard wallets over (legacy) injected wallets
|
|
22
|
+
type DiscoveredStarknetWallet = {
|
|
23
|
+
discoverer: "standard" | "injected" | "eip6963";
|
|
24
|
+
wallet: WalletWithStarknetFeatures;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type CreateStoreOptions = {
|
|
28
|
+
eip1193Adapters?: EIP1193Adapter[];
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const DEFAULT_EIP1193_ADAPTERS: EIP1193Adapter[] = [metaMaskVirtualWallet];
|
|
32
|
+
|
|
33
|
+
export function createStore({
|
|
34
|
+
eip1193Adapters = DEFAULT_EIP1193_ADAPTERS,
|
|
35
|
+
}: CreateStoreOptions = {}): Store {
|
|
36
|
+
const listeners = new Set<Listener>();
|
|
37
|
+
let wallets: DiscoveredStarknetWallet[] = [];
|
|
38
|
+
|
|
39
|
+
function emitChanges() {
|
|
40
|
+
for (const listener of listeners) {
|
|
41
|
+
listener(wallets.map(({ wallet }) => wallet).slice());
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
registerStandardWalletDiscovery((wallet) => {
|
|
46
|
+
if (!isStarknetWallet(wallet)) return;
|
|
47
|
+
|
|
48
|
+
const existing = wallets.find((w) => w.wallet.name === wallet.name);
|
|
49
|
+
|
|
50
|
+
if (existing) {
|
|
51
|
+
// If the wallet exists but is an injected wallet this library registered,
|
|
52
|
+
// replace it with the standard wallet registered by the wallet itself.
|
|
53
|
+
if (existing.discoverer !== "standard") {
|
|
54
|
+
wallets = [
|
|
55
|
+
{ discoverer: "standard", wallet },
|
|
56
|
+
...wallets.filter((w) => w.wallet.name !== wallet.name),
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
emitChanges();
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
wallets = [{ discoverer: "standard", wallet }, ...wallets];
|
|
63
|
+
|
|
64
|
+
emitChanges();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return () => {
|
|
68
|
+
wallets = wallets.filter((w) => w.wallet.name !== wallet.name);
|
|
69
|
+
|
|
70
|
+
emitChanges();
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
registerEIP1193WalletFromEIP6963Discovery(eip1193Adapters, (wallet) => {
|
|
75
|
+
if (!isStarknetWallet(wallet)) return;
|
|
76
|
+
|
|
77
|
+
const existing = wallets.find((w) => w.wallet.name === wallet.name);
|
|
78
|
+
|
|
79
|
+
if (!existing) {
|
|
80
|
+
wallets = [{ discoverer: "eip6963", wallet }, ...wallets];
|
|
81
|
+
|
|
82
|
+
emitChanges();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return () => {
|
|
86
|
+
wallets = wallets.filter((w) => w.wallet.name !== wallet.name);
|
|
87
|
+
|
|
88
|
+
emitChanges();
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const { refresh: refreshInjectedWallets } = registerInjectedWalletDiscovery(
|
|
93
|
+
(wallet) => {
|
|
94
|
+
if (!isStarknetWallet(wallet)) return;
|
|
95
|
+
|
|
96
|
+
const existing = wallets.find((w) => w.wallet.name === wallet.name);
|
|
97
|
+
|
|
98
|
+
// Only register injected wallets if they are not already registered.
|
|
99
|
+
// We should not override standard wallets with injected wallets.
|
|
100
|
+
if (!existing) {
|
|
101
|
+
wallets = [{ discoverer: "injected", wallet }, ...wallets];
|
|
102
|
+
|
|
103
|
+
emitChanges();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return () => {
|
|
107
|
+
wallets = wallets.filter((w) => w.wallet.name !== wallet.name);
|
|
108
|
+
|
|
109
|
+
emitChanges();
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
_refreshInjectedWallets: refreshInjectedWallets,
|
|
116
|
+
getWallets() {
|
|
117
|
+
return wallets.map(({ wallet }) => wallet).slice();
|
|
118
|
+
},
|
|
119
|
+
subscribe(listener) {
|
|
120
|
+
listeners.add(listener);
|
|
121
|
+
return () => {
|
|
122
|
+
listeners.delete(listener);
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|