Skip to content

Commit 04c3b12

Browse files
committed
fix: wip
1 parent eca31bf commit 04c3b12

7 files changed

Lines changed: 7095 additions & 162 deletions

File tree

packages/sdk-multichain/src/connect.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ function testSuite<T extends MultichainOptions>({ platform, createSDK, options:
170170
t.expect(sdk.state).toBe('connected');
171171
t.expect(sdk.storage).toBeDefined();
172172
t.expect(sdk.transport).toBeDefined();
173+
t.expect(sdk.provider).toBeDefined();
173174

174175
const { sessionScopes, expiry: _, ...rest } = mockSessionData;
175176
const expectedSessionResponse = {
@@ -198,6 +199,7 @@ function testSuite<T extends MultichainOptions>({ platform, createSDK, options:
198199
sdk = await createSDK(testOptions);
199200
t.expect(sdk.state).toBe('connected');
200201
t.expect(sdk.transport).toBeDefined();
202+
t.expect(sdk.provider).toBeDefined();
201203
t.expect(sdk.storage).toBeDefined();
202204

203205
await t.expect(sdk.storage.getTransport()).resolves.toBe(transportString);
@@ -219,6 +221,7 @@ function testSuite<T extends MultichainOptions>({ platform, createSDK, options:
219221

220222
sdk = await createSDK(testOptions);
221223
t.expect(sdk.transport).toBeDefined();
224+
t.expect(sdk.provider).toBeDefined();
222225
t.expect(sdk.storage).toBeDefined();
223226
t.expect(sdk.state).toBe('connected');
224227

@@ -410,6 +413,10 @@ function testSuite<T extends MultichainOptions>({ platform, createSDK, options:
410413

411414
sdk = await createSDK(testOptions);
412415
await sdk.connect(scopes, caipAccountIds);
416+
t.expect(sdk.state).toBe('connected');
417+
t.expect(sdk.provider).toBeDefined();
418+
t.expect(sdk.transport).toBeDefined();
419+
413420
await t.expect(sdk.disconnect()).rejects.toThrow('Failed to disconnect transport');
414421
});
415422

@@ -423,6 +430,8 @@ function testSuite<T extends MultichainOptions>({ platform, createSDK, options:
423430
sdk = await createSDK(testOptions);
424431

425432
t.expect(sdk.state).toBe('connected');
433+
t.expect(sdk.provider).toBeDefined();
434+
t.expect(sdk.transport).toBeDefined();
426435

427436
t.expect(mockedData.mockDappClient.state).toBe('CONNECTED');
428437
await mockedData.mockDappClient.disconnect();

packages/sdk-multichain/src/domain/multichain/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ export abstract class MultichainCore extends EventEmitter<SDKEvents> {
2525
abstract provider: MultichainApiClient<RPCAPI>;
2626
abstract transport: Transport;
2727

28-
abstract getCurrentSession(): Promise<SessionData | undefined>;
2928
/**
3029
* Establishes a connection to the multichain provider, or re-use existing session
3130
*

packages/sdk-multichain/src/multichain/index.ts

Lines changed: 39 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -124,24 +124,19 @@ export class MultichainSDK extends MultichainCore {
124124
analytics.enable();
125125
}
126126

127-
private async onTransportNotification(payload: unknown) {
128-
if (typeof payload === 'object' && payload !== null && 'data' in payload) {
129-
const data = payload.data as Record<string, unknown>;
130-
if ('method' in data && data.method === 'wallet_sessionChanged') {
131-
const session = data.params as SessionData;
132-
this.emit('wallet_sessionChanged', Object.keys(session?.sessionScopes ?? {}).length > 0 ? session : undefined);
133-
} else {
134-
this.emit(data.method as string, data.params);
135-
}
127+
private async onTransportNotification(payload: any) {
128+
if (typeof payload === 'object' && payload !== null && 'method' in payload) {
129+
this.emit(payload.method as string, payload.params || payload.result);
136130
}
137131
}
138132

139133
private async getStoredTransport() {
140134
const { ui } = this.options;
141135
const { preferExtension = true, headless: _headless = false } = ui;
142-
136+
logger(`Fetching the stored transport`);
143137
const transportType = await this.storage.getTransport();
144138
if (transportType) {
139+
logger(`Transport found: ${transportType}`);
145140
if (transportType === TransportType.Browser) {
146141
//Check if the user still have the extension or not return the transport
147142
if (hasExtension() && preferExtension) {
@@ -162,35 +157,22 @@ export class MultichainSDK extends MultichainCore {
162157
await this.storage.removeTransport();
163158
}
164159

160+
logger(`No transport found`);
165161
return undefined;
166162
}
167163

168-
private async getActiveSession() {
169-
const request = await this.transport.request({ method: 'wallet_getSession' });
170-
const response = request.result as SessionData;
171-
return response;
172-
}
173-
174164
private async setupTransport() {
175165
const transport = await this.getStoredTransport();
176166
if (transport) {
167+
logger(`Transport returned, connecting to transport`);
177168
if (!this.transport.isConnected()) {
178169
this.state = 'connecting';
179170
await this.transport.connect();
180171
this.state = 'connected';
172+
logger(`Transport connected`);
181173
}
182-
183-
const session = await this.getActiveSession();
174+
logger(`Transport provider create`);
184175
this.__provider = getMultichainClient({ transport });
185-
//Add event listeners to the transport
186-
if (session && Object.keys(session.sessionScopes ?? {}).length > 0) {
187-
// No listeners can exist in here so we need onResumeSession event on constructor
188-
this.options.transport?.onNotification?.({
189-
method: 'wallet_sessionChanged',
190-
params: session,
191-
});
192-
this.state = 'connected';
193-
}
194176
} else {
195177
this.state = 'loaded';
196178
}
@@ -207,86 +189,27 @@ export class MultichainSDK extends MultichainCore {
207189
if (typeof window !== 'undefined') {
208190
window.mmsdk = this;
209191
}
192+
logger(`SDK initialized`);
210193
}
211194
} catch (error) {
212-
debugger;
213195
logger('MetaMaskSDK error during initialization', error);
214196
}
215197
}
216198

217-
async getCurrentSession(): Promise<SessionData | undefined> {
218-
try {
219-
//TODO: We should report to the multichain api team that when there's no extension installed
220-
// getSession timeouts and should be just undefined
221-
// Thats why we need this function, to compensate that
222-
let validSession: SessionData | undefined;
223-
const session = await this.getActiveSession();
224-
225-
if (Object.keys(session?.sessionScopes ?? {}).length > 0) {
226-
validSession = session;
227-
}
228-
return validSession;
229-
} catch (err) {
230-
logger('MetaMaskSDK error during getCurrentSession', err);
231-
return undefined;
232-
}
233-
}
234-
235-
/**
236-
* Once Connection to transport is successfull, we will fetch the
237-
*/
238-
private async onConnectionSuccess(params: ModalFactoryConnectOptions) {
239-
try {
240-
if (!this.transport.isConnected()) {
241-
await this.transport.connect(params);
242-
}
243-
244-
debugger;
245-
this.state = 'connected';
246-
this.__provider ??= getMultichainClient({ transport: this.transport });
247-
const session = await this.getCurrentSession();
248-
249-
if (session) {
250-
const currentScopes = Object.keys(session?.sessionScopes ?? {}) as Scope[];
251-
const proposedScopes = params.scopes;
252-
const isSameScopes = currentScopes.every((scope) => proposedScopes.includes(scope)) && proposedScopes.every((scope) => currentScopes.includes(scope));
253-
if (isSameScopes) {
254-
this.emit('wallet_sessionChanged', session);
255-
return;
256-
}
257-
await this.transport.request({ method: 'wallet_revokeSession', params: session });
258-
}
259-
260-
const { scopes, caipAccountIds } = params;
261-
const optionalScopes = addValidAccounts(getOptionalScopes(scopes), getValidAccounts(caipAccountIds));
262-
const sessionRequest: CreateSessionParams<RPCAPI> = { optionalScopes };
263-
const newSessionRequest = await this.transport.request({ method: 'wallet_createSession', params: sessionRequest });
264-
const newSession = newSessionRequest.result as SessionData;
265-
this.options.transport?.onNotification?.({
266-
method: 'wallet_sessionChanged',
267-
params: newSession,
268-
});
269-
this.emit('wallet_sessionChanged', newSession);
270-
} catch (err) {
271-
logger('MetaMaskSDK error during onConnectionSuccess', err);
272-
throw err;
273-
} finally {
274-
this.state = this.transport.isConnected() ? 'connected' : 'disconnected';
275-
}
276-
}
277-
278199
private async showInstallModal(desktopPreferred: boolean, scopes: Scope[], caipAccountIds: CaipAccountId[]) {
279200
return new Promise<void>((resolve, reject) => {
280201
this.dappClient.once('connected', () => {
202+
logger(`DappClient connected on showInstallModal`);
281203
this.options.ui.factory.unload();
282204
});
283205
// Use Connection Modal
284206
this.options.ui.factory.renderInstallModal(
285207
desktopPreferred,
286208
async () => {
209+
logger(`Creating session request for QRCode`);
287210
return new Promise<ConnectionRequest>((resolveConnectionRequest) => {
288-
debugger;
289211
this.dappClient.on('session_request', (sessionRequest: SessionRequest) => {
212+
logger(`Session request received on showInstallModal`);
290213
resolveConnectionRequest({
291214
sessionRequest,
292215
metadata: {
@@ -312,12 +235,18 @@ export class MultichainSDK extends MultichainCore {
312235
});
313236
},
314237
async (error?: Error) => {
238+
logger(`Unmounting install modal on showInstallModal`);
315239
this.options.ui.factory.modal?.unmount();
316240
if (!error) {
317-
this.storage.setTransport(TransportType.MPW);
318-
this.onConnectionSuccess({ scopes, caipAccountIds }).then(resolve).catch(reject);
241+
await this.storage.setTransport(TransportType.MPW);
242+
logger(`Setting transport to MPW on showInstallModal`);
243+
this.__provider = getMultichainClient({ transport: this.transport });
244+
this.state = 'connected';
245+
resolve();
319246
} else {
247+
logger(`Setting state to disconnected on showInstallModal`);
320248
this.state = 'disconnected';
249+
await this.storage.removeTransport();
321250
reject(error);
322251
}
323252
},
@@ -335,6 +264,10 @@ export class MultichainSDK extends MultichainCore {
335264
}
336265

337266
private async setupMWP() {
267+
if (this.__transport instanceof MWPTransport) {
268+
return;
269+
}
270+
//Only setup MWP if it is not already mwp
338271
const { adapter: kvstore } = this.options.storage;
339272
const dappClient = await this.createDappClient();
340273
this.__dappClient = dappClient;
@@ -371,13 +304,13 @@ export class MultichainSDK extends MultichainCore {
371304
}
372305
}
373306

374-
private async extensionConnect(scopes: Scope[], caipAccountIds: CaipAccountId[]) {
307+
private async extensionConnect() {
375308
this.state = 'connecting';
376309
await this.storage.setTransport(TransportType.Browser);
377310
const transport = getDefaultTransport();
378311
this.listener = transport.onNotification(this.onTransportNotification.bind(this));
379312
this.__transport = transport;
380-
return this.onConnectionSuccess({ scopes, caipAccountIds });
313+
return Promise.resolve();
381314
}
382315

383316
private async deeplinkConnect(scopes: Scope[], caipAccountIds: CaipAccountId[]) {
@@ -417,7 +350,6 @@ export class MultichainSDK extends MultichainCore {
417350
this.openDeeplink(deeplink, universalLink);
418351
}
419352
});
420-
debugger;
421353
this.state = 'connecting';
422354
this.transport.connect({ scopes, caipAccountIds }).catch(reject);
423355
});
@@ -432,14 +364,19 @@ export class MultichainSDK extends MultichainCore {
432364
const isWeb = platformType === PlatformType.MetaMaskMobileWebview || platformType === PlatformType.DesktopWeb;
433365
const { preferExtension = true, preferDesktop = false, headless: _headless = false } = ui;
434366

435-
if (this.__transport?.isConnected()) {
436-
//If transport was loaded by sdk init, re-use session
437-
return this.onConnectionSuccess({ scopes, caipAccountIds });
367+
if (this.transport?.isConnected()) {
368+
if (!(this.transport instanceof MWPTransport)) {
369+
logger(`Transport already connected`);
370+
return Promise.resolve();
371+
}
372+
logger(`MWP Transport already connected, reconnecting`);
373+
return this.transport.connect({ scopes, caipAccountIds });
438374
}
439375

440376
if (isWeb && hasExtension() && preferExtension) {
377+
logger(`Metamask extension is available, connecting to extension`);
441378
//If metamask extension is available, connect to it
442-
return this.extensionConnect(scopes, caipAccountIds);
379+
return this.extensionConnect();
443380
}
444381

445382
// Connection will now be InstallModal + QRCodes or Deeplinks, both require mwp
@@ -455,10 +392,12 @@ export class MultichainSDK extends MultichainCore {
455392

456393
const secure = isSecure();
457394
if (secure && !isDesktopPreferred) {
395+
logger(`Desktop is not preferred option, using deeplinks`);
458396
// Desktop is not preferred option, so we use deeplinks (mobile web)
459397
return this.deeplinkConnect(scopes, caipAccountIds);
460398
}
461399

400+
logger(`Showing install modal`);
462401
// Show install modal for RN, Web + Node
463402
return this.showInstallModal(isDesktopPreferred, scopes, caipAccountIds);
464403
}
@@ -495,13 +434,12 @@ export class MultichainSDK extends MultichainCore {
495434
const secure = isSecure();
496435

497436
if (secure && !preferDesktop) {
498-
const response = client.invokeMethod(request);
499437
if (this.options.mobile?.preferredOpenLink) {
500438
this.options.mobile.preferredOpenLink(METAMASK_DEEPLINK_BASE, '_self');
501439
} else {
502440
this.openDeeplink(METAMASK_DEEPLINK_BASE, METAMASK_CONNECT_BASE_URL);
503441
}
504-
return response;
442+
return client.invokeMethod(request);
505443
} else {
506444
return client.invokeMethod(request);
507445
}

0 commit comments

Comments
 (0)