Skip to content

Commit 1d85931

Browse files
committed
Added filter to EIP6963 discovery API.
1 parent 374d301 commit 1d85931

File tree

1 file changed

+66
-10
lines changed

1 file changed

+66
-10
lines changed

src.ts/providers/provider-browser.ts

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { assertArgument } from "../utils/index.js";
1+
2+
import { assertArgument, makeError } from "../utils/index.js";
23

34
import { JsonRpcApiPollingProvider } from "./provider-jsonrpc.js";
45

@@ -93,10 +94,13 @@ export interface BrowserDiscoverOptions {
9394
* environments or to hijack where a provider comes from.
9495
*/
9596
window?: any;
96-
}
9797

98-
// @TODO: Future, provide some sort of filter mechansm callback along
99-
// with exposing the following types
98+
/**
99+
* Explicitly choose which provider to used once scanning is complete.
100+
*/
101+
filter?: (found: Array<Eip6963ProviderInfo>) => null | BrowserProvider |
102+
Eip6963ProviderInfo;
103+
}
100104

101105

102106
/**
@@ -242,11 +246,16 @@ export class BrowserProvider extends JsonRpcApiPollingProvider {
242246
return new BrowserProvider(context.ethereum);
243247
}
244248

249+
if (!("addEventListener" in context && "dispatchEvent" in context
250+
&& "removeEventListener" in context)) {
251+
return null;
252+
}
253+
245254
const timeout = options.timeout ? options.timeout: 300;
246255
if (timeout === 0) { return null; }
247256

248-
return await (new Promise((resolve) => {
249-
let found: Array<any> = [ ];
257+
return await (new Promise((resolve, reject) => {
258+
let found: Array<Eip6963ProviderDetail> = [ ];
250259

251260
const addProvider = (event: Eip6963Announcement) => {
252261
found.push(event.detail);
@@ -255,14 +264,61 @@ export class BrowserProvider extends JsonRpcApiPollingProvider {
255264

256265
const finalize = () => {
257266
clearTimeout(timer);
267+
258268
if (found.length) {
259-
const { provider, info } = found[0];
260-
resolve(new BrowserProvider(provider, undefined, {
261-
providerInfo: info
262-
}));
269+
270+
// If filtering is provided:
271+
if (options && options.filter) {
272+
273+
// Call filter, with a copies of found provider infos
274+
const filtered = options.filter(found.map(i =>
275+
Object.assign({ }, (i.info))));
276+
277+
if (filtered == null) {
278+
// No provider selected
279+
resolve(null);
280+
281+
} else if (filtered instanceof BrowserProvider) {
282+
// Custom provider created
283+
resolve(filtered);
284+
285+
} else {
286+
// Find the matching provider
287+
let match: null | Eip6963ProviderDetail = null;
288+
if (filtered.uuid) {
289+
const matches = found.filter(f =>
290+
(filtered.uuid === f.info.uuid));
291+
// @TODO: What should happen if multiple values
292+
// for the same UUID?
293+
match = matches[0];
294+
}
295+
296+
if (match) {
297+
const { provider, info } = match;
298+
resolve(new BrowserProvider(provider, undefined, {
299+
providerInfo: info
300+
}));
301+
} else {
302+
reject(makeError("filter returned unknown info", "UNSUPPORTED_OPERATION", {
303+
value: filtered
304+
}));
305+
}
306+
}
307+
308+
} else {
309+
310+
// Pick the first found provider
311+
const { provider, info } = found[0];
312+
resolve(new BrowserProvider(provider, undefined, {
313+
providerInfo: info
314+
}));
315+
}
316+
263317
} else {
318+
// Nothing found
264319
resolve(null);
265320
}
321+
266322
context.removeEventListener(<any>"eip6963:announceProvider",
267323
addProvider);
268324
};

0 commit comments

Comments
 (0)