Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion packages/network-controller/src/NetworkController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,11 @@ export type NetworkControllerGetNetworkClientByIdAction = {
handler: NetworkController['getNetworkClientById'];
};

export type NetworkControllerGetSelectedNetworkClientAction = {
type: `NetworkController:getSelectedNetworkClient`;
handler: NetworkController['getSelectedNetworkClient'];
};

export type NetworkControllerGetEIP1559CompatibilityAction = {
type: `NetworkController:getEIP1559Compatibility`;
handler: NetworkController['getEIP1559Compatibility'];
Expand Down Expand Up @@ -462,6 +467,7 @@ export type NetworkControllerActions =
| NetworkControllerGetProviderConfigAction
| NetworkControllerGetEthQueryAction
| NetworkControllerGetNetworkClientByIdAction
| NetworkControllerGetSelectedNetworkClientAction
| NetworkControllerGetEIP1559CompatibilityAction
| NetworkControllerFindNetworkClientIdByChainIdAction
| NetworkControllerSetActiveNetworkAction
Expand Down Expand Up @@ -634,13 +640,18 @@ export class NetworkController extends BaseController<
this.getNetworkConfigurationByNetworkClientId.bind(this),
);

this.messagingSystem.registerActionHandler(
`${this.name}:getSelectedNetworkClient`,
this.getSelectedNetworkClient.bind(this),
);

this.#previousProviderConfig = this.state.providerConfig;
}

/**
* Accesses the provider and block tracker for the currently selected network.
*
* @returns The proxy and block tracker proxies.
* @deprecated This method has been replaced by `getSelectedNetworkClient` (which has a more easily used return type) and will be removed in a future release.
*/
getProviderAndBlockTracker(): {
provider: SwappableProxy<ProxyWithAccessibleTarget<Provider>> | undefined;
Expand All @@ -654,6 +665,26 @@ export class NetworkController extends BaseController<
};
}

/**
* Accesses the provider and block tracker for the currently selected network.
*
* @returns an object with the provider and block tracker proxies for the currently selected network.
*/
getSelectedNetworkClient():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method should have a JSDoc description.

Maybe also worth adding a @deprecated tag on getProviderAndBlockTracker (it's equivalent to this, except more difficult to work with because of the return type)

Copy link
Contributor Author

@adonesky1 adonesky1 Mar 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done here: b0f1670

| {
provider: SwappableProxy<ProxyWithAccessibleTarget<Provider>>;
blockTracker: SwappableProxy<ProxyWithAccessibleTarget<BlockTracker>>;
}
| undefined {
if (this.#providerProxy && this.#blockTrackerProxy) {
return {
provider: this.#providerProxy,
blockTracker: this.#blockTrackerProxy,
};
}
return undefined;
}

/**
* Returns all of the network clients that have been created so far, keyed by
* their identifier in the network client registry. This collection represents
Expand Down
27 changes: 27 additions & 0 deletions packages/network-controller/tests/NetworkController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7426,6 +7426,33 @@ function lookupNetworkTests({
);
});
});

describe('getSelectedNetworkClient', () => {
it('returns the selected network provider and blockTracker proxy when initialized', async () => {
await withController(async ({ controller }) => {
const fakeProvider = buildFakeProvider();
const fakeNetworkClient = buildFakeClient(fakeProvider);
mockCreateNetworkClient().mockReturnValue(fakeNetworkClient);
await controller.initializeProvider();
const defaultNetworkClient = controller.getProviderAndBlockTracker();

const selectedNetworkClient = controller.getSelectedNetworkClient();
expect(defaultNetworkClient.provider).toBe(
selectedNetworkClient?.provider,
);
expect(defaultNetworkClient.blockTracker).toBe(
selectedNetworkClient?.blockTracker,
);
});
});

it('returns undefined when the selected network provider and blockTracker proxy are not initialized', async () => {
await withController(async ({ controller }) => {
const selectedNetworkClient = controller.getSelectedNetworkClient();
expect(selectedNetworkClient).toBeUndefined();
});
});
});
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
BlockTrackerProxy,
NetworkClientId,
NetworkControllerGetNetworkClientByIdAction,
NetworkControllerGetSelectedNetworkClientAction,
NetworkControllerGetStateAction,
NetworkControllerStateChangeEvent,
ProviderProxy,
Expand Down Expand Up @@ -71,6 +72,7 @@ export type SelectedNetworkControllerActions =

export type AllowedActions =
| NetworkControllerGetNetworkClientByIdAction
| NetworkControllerGetSelectedNetworkClientAction
| NetworkControllerGetStateAction
| PermissionControllerHasPermissions
| PermissionControllerGetSubjectsAction;
Expand Down Expand Up @@ -171,9 +173,7 @@ export class SelectedNetworkController extends BaseController<
op === 'remove' &&
this.state.domains[domain] !== undefined
) {
this.update(({ domains }) => {
delete domains[domain];
});
this.#unsetNetworkClientIdForDomain(domain);
}
}
});
Expand Down Expand Up @@ -222,24 +222,39 @@ export class SelectedNetworkController extends BaseController<
'NetworkController:getNetworkClientById',
networkClientId,
);
const networkProxy = this.#domainProxyMap.get(domain);
if (networkProxy === undefined) {
this.#domainProxyMap.set(domain, {
provider: createEventEmitterProxy(networkClient.provider),
blockTracker: createEventEmitterProxy(networkClient.blockTracker, {
eventFilter: 'skipInternal',
}),
});
} else {
networkProxy.provider.setTarget(networkClient.provider);
networkProxy.blockTracker.setTarget(networkClient.blockTracker);
}
const networkProxy = this.getProviderAndBlockTracker(domain);
networkProxy.provider.setTarget(networkClient.provider);
networkProxy.blockTracker.setTarget(networkClient.blockTracker);

this.update((state) => {
state.domains[domain] = networkClientId;
});
}

/**
* This method is used when a domain is removed from the PermissionsController.
* It will remove re-point the network proxy to the globally selected network in the domainProxyMap or, if no globally selected network client is available, delete the proxy.
*
* @param domain - The domain for which to unset the network client ID.
*/
#unsetNetworkClientIdForDomain(domain: Domain) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Could use a JSDoc description here as well

Copy link
Contributor Author

@adonesky1 adonesky1 Mar 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done here: b0f1670

const globallySelectedNetworkClient = this.messagingSystem.call(
'NetworkController:getSelectedNetworkClient',
);
const networkProxy = this.#domainProxyMap.get(domain);
if (networkProxy && globallySelectedNetworkClient) {
networkProxy.provider.setTarget(globallySelectedNetworkClient.provider);
networkProxy.blockTracker.setTarget(
globallySelectedNetworkClient.blockTracker,
);
} else if (networkProxy) {
this.#domainProxyMap.delete(domain);
}
this.update((state) => {
delete state.domains[domain];
});
}

#domainHasPermissions(domain: Domain): boolean {
return this.messagingSystem.call(
'PermissionController:hasPermissions',
Expand Down Expand Up @@ -282,23 +297,23 @@ export class SelectedNetworkController extends BaseController<
* @returns The proxy and block tracker proxies.
*/
getProviderAndBlockTracker(domain: Domain): NetworkProxy {
if (!this.#getUseRequestQueue()) {
throw new Error(
'Provider and BlockTracker should be fetched from NetworkController when useRequestQueue is false',
);
}
const networkClientId = this.state.domains[domain];
if (!networkClientId) {
throw new Error(
'NetworkClientId has not been set for the requested domain',
);
}
let networkProxy = this.#domainProxyMap.get(domain);
if (networkProxy === undefined) {
const networkClient = this.messagingSystem.call(
'NetworkController:getNetworkClientById',
networkClientId,
);
let networkClient;
if (networkClientId === undefined) {
networkClient = this.messagingSystem.call(
'NetworkController:getSelectedNetworkClient',
);
if (networkClient === undefined) {
throw new Error('Selected network not initialized');
}
} else {
networkClient = this.messagingSystem.call(
'NetworkController:getNetworkClientById',
networkClientId,
);
}
networkProxy = {
provider: createEventEmitterProxy(networkClient.provider),
blockTracker: createEventEmitterProxy(networkClient.blockTracker, {
Expand Down
Loading