1- import { assertArgument } from "../utils/index.js" ;
1+
2+ import { assertArgument , makeError } from "../utils/index.js" ;
23
34import { 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