Skip to content

Commit d8c204f

Browse files
committed
feat: providers loading ready
1 parent 4fd8b31 commit d8c204f

File tree

4 files changed

+51
-42
lines changed

4 files changed

+51
-42
lines changed

src/background/providers/ChainAgnosticProvider.ts

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import EventEmitter from 'events';
22
import {
3+
DAppProviderRequest,
34
JsonRpcRequest,
45
JsonRpcRequestPayload,
56
} from '../connections/dAppConnection/models';
@@ -8,9 +9,18 @@ import { ethErrors, serializeError } from 'eth-rpc-errors';
89
import AbstractConnection from '../utils/messaging/AbstractConnection';
910
import { ChainId } from '@avalabs/core-chains-sdk';
1011
import RequestRatelimiter from './utils/RequestRatelimiter';
12+
import {
13+
InitializationStep,
14+
ProviderReadyPromise,
15+
} from './utils/ProviderReadyPromise';
16+
import onDomReady from './utils/onDomReady';
17+
import { getSiteMetadata } from './utils/getSiteMetadata';
1118

1219
export class ChainAgnosticProvider extends EventEmitter {
1320
#contentScriptConnection: AbstractConnection;
21+
#providerReadyPromise = new ProviderReadyPromise([
22+
InitializationStep.DOMAIN_METADATA_SENT,
23+
]);
1424

1525
#requestRateLimiter = new RequestRatelimiter([
1626
'eth_requestAccounts',
@@ -19,12 +29,26 @@ export class ChainAgnosticProvider extends EventEmitter {
1929

2030
constructor(connection) {
2131
super();
32+
connection.connect();
2233
this.#contentScriptConnection = connection;
2334
this.#init();
2435
}
2536

2637
async #init() {
2738
await this.#contentScriptConnection.connect();
39+
40+
onDomReady(async () => {
41+
const domainMetadata = await getSiteMetadata();
42+
43+
this.#request({
44+
data: {
45+
method: DAppProviderRequest.DOMAIN_METADATA_METHOD,
46+
params: domainMetadata,
47+
},
48+
});
49+
50+
this.#providerReadyPromise.check(InitializationStep.DOMAIN_METADATA_SENT);
51+
});
2852
}
2953

3054
#request = async ({
@@ -73,12 +97,14 @@ export class ChainAgnosticProvider extends EventEmitter {
7397
chainId,
7498
}: {
7599
data: PartialBy<JsonRpcRequestPayload, 'id' | 'params'>;
76-
sessionId: string;
77-
chainId: string | null;
100+
sessionId?: string;
101+
chainId?: string | null;
78102
}) => {
79-
return this.#requestRateLimiter.call(data.method, () =>
80-
this.#request({ data, chainId, sessionId })
81-
);
103+
return this.#providerReadyPromise.call(() => {
104+
return this.#requestRateLimiter.call(data.method, () =>
105+
this.#request({ data, chainId, sessionId })
106+
);
107+
});
82108
};
83109

84110
subscribeToMessage = (callback) => {

src/background/providers/CoreProvider.ts

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { ethErrors } from 'eth-rpc-errors';
22
import EventEmitter from 'events';
3-
import { getSiteMetadata } from './utils/getSiteMetadata';
4-
import onDomReady from './utils/onDomReady';
53
import {
64
EventNames,
75
type AccountsChangedEventData,
@@ -18,7 +16,6 @@ import {
1816
} from '../connections/dAppConnection/models';
1917
import type { PartialBy, ProviderInfo } from '../models';
2018
import { ChainAgnosticProvider } from './ChainAgnosticProvider';
21-
import AbstractConnection from '../utils/messaging/AbstractConnection';
2219

2320
interface ProviderState {
2421
accounts: string[] | null;
@@ -28,8 +25,9 @@ interface ProviderState {
2825
}
2926

3027
export class CoreProvider extends EventEmitter {
31-
#providerReadyPromise = new ProviderReadyPromise();
32-
#contentScriptConnection: AbstractConnection;
28+
#providerReadyPromise = new ProviderReadyPromise([
29+
InitializationStep.PROVIDER_STATE_LOADED,
30+
]);
3331
#chainagnosticProvider?: ChainAgnosticProvider;
3432

3533
readonly info: ProviderInfo = {
@@ -68,16 +66,9 @@ export class CoreProvider extends EventEmitter {
6866
isUnlocked: () => Promise.resolve(this._isUnlocked),
6967
};
7068

71-
constructor({
72-
connection,
73-
maxListeners = 100,
74-
}: {
75-
connection: AbstractConnection;
76-
maxListeners?: number;
77-
}) {
69+
constructor({ maxListeners = 100 }: { maxListeners?: number }) {
7870
super();
7971
this.setMaxListeners(maxListeners);
80-
this.#contentScriptConnection = connection;
8172
this.#subscribe();
8273
}
8374

@@ -104,19 +95,6 @@ export class CoreProvider extends EventEmitter {
10495
* Initializes provider state, and collects dApp information
10596
*/
10697
#init = async () => {
107-
await this.#contentScriptConnection.connect();
108-
109-
onDomReady(async () => {
110-
const domainMetadata = await getSiteMetadata();
111-
112-
this.#request({
113-
method: DAppProviderRequest.DOMAIN_METADATA_METHOD,
114-
params: domainMetadata,
115-
});
116-
117-
this.#providerReadyPromise.check(InitializationStep.DOMAIN_METADATA_SENT);
118-
});
119-
12098
try {
12199
const response = await this.#request({
122100
method: DAppProviderRequest.INIT_DAPP_STATE,

src/background/providers/initializeInpageProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function initializeProvider(
2424
}
2525
);
2626

27-
const provider = new Proxy(new CoreProvider({ maxListeners, connection }), {
27+
const provider = new Proxy(new CoreProvider({ maxListeners }), {
2828
// some common libraries, e.g. [email protected], mess with our API
2929
deleteProperty: () => true,
3030
});

src/background/providers/utils/ProviderReadyPromise.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,37 @@
11
export enum InitializationStep {
2-
DOMAIN_METADATA_SENT,
3-
PROVIDER_STATE_LOADED,
2+
DOMAIN_METADATA_SENT = 'domain_metadata_sent',
3+
PROVIDER_STATE_LOADED = 'provider_state_loaded',
44
}
55

66
export class ProviderReadyPromise {
7-
#steps: boolean[] = [];
7+
#unpreparedSteps: InitializationStep[] = [];
88
#inflightRequests: {
99
resolve(value: unknown): void;
1010
fn(): Promise<any>;
1111
}[] = [];
1212

13-
constructor() {
14-
// length / 2 is required since InitializationStep is an enum
15-
// enums generate objects like this: { key0: 0, key1: 1, 0: key0, 1: key1 }
16-
this.#steps = Array(Object.keys(InitializationStep).length / 2).fill(false);
13+
constructor(steps: InitializationStep[]) {
14+
this.#unpreparedSteps = Object.values(steps);
1715
}
1816

1917
check = (step: InitializationStep) => {
20-
this.#steps[step] = true;
18+
const stepIndex = this.#unpreparedSteps.findIndex(
19+
(currentStep) => step === currentStep
20+
);
21+
22+
if (stepIndex > -1) {
23+
this.#unpreparedSteps.splice(stepIndex, 1);
24+
}
25+
2126
this._proceed();
2227
};
2328

2429
uncheck = (step: InitializationStep) => {
25-
this.#steps[step] = false;
30+
this.#unpreparedSteps[step] = step;
2631
};
2732

2833
private _proceed = () => {
29-
if (this.#steps.some((step) => !step)) {
34+
if (this.#unpreparedSteps.length) {
3035
return;
3136
}
3237

0 commit comments

Comments
 (0)