Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TW-1498 [EVM] Connect wallet to dapps #1235

Merged
merged 22 commits into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2bea1de
TW-1498 Implement connection to EVM dApps (raw version)
keshan3262 Nov 28, 2024
104d05e
TW-1498 Fix connection to dApps
keshan3262 Nov 29, 2024
24c6214
TW-1498 Fix signing
keshan3262 Dec 2, 2024
4bc19f8
TW-1498 Change UI for connection page
keshan3262 Dec 4, 2024
b3fb426
TW-1498 Add UI for signing EVM messages and data
keshan3262 Dec 5, 2024
2c63b26
TW-1498 Display active EVM connection on extension home page
keshan3262 Dec 5, 2024
5f3844e
TW-1498 Resolve merge conflicts
keshan3262 Dec 6, 2024
850c8ea
TW-1498 Display EVM DApps in settings
keshan3262 Dec 6, 2024
aca9cc4
TW-1498 Fix types errors
keshan3262 Dec 6, 2024
5d7a1a4
TW-1498 Fix behavior after a network that has a connection is disabled
keshan3262 Dec 6, 2024
de67fa9
TW-1498 Some refactoring
keshan3262 Dec 6, 2024
b7b4213
TW-1498 Fix 'Testnet mode' label
keshan3262 Dec 6, 2024
fec918f
TW-1498 Move EVM RPC requests to the background
keshan3262 Dec 9, 2024
a1f04fb
TW-1498 Resolve merge conflicts
keshan3262 Dec 9, 2024
e2262ba
TW-1498 Minor refactoring
keshan3262 Dec 9, 2024
904a6e0
TW-1498 Refactoring according to comments
keshan3262 Dec 13, 2024
634597d
TW-1498 Unhardcode 'All Networks' label
keshan3262 Dec 13, 2024
3c47d1b
Merge branch 'development-2' of https://github.com/madfish-solutions/…
keshan3262 Dec 16, 2024
74dd931
TW-1498 Fix connectivity for Firefox
keshan3262 Dec 16, 2024
3f812be
TW-1498 UI fixes
keshan3262 Dec 19, 2024
5dbca74
TW-1498 Fix requests freezing
keshan3262 Dec 19, 2024
d83d5a7
TW-1498 Remove an unused export
keshan3262 Dec 19, 2024
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
12 changes: 6 additions & 6 deletions src/content-scripts/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import browser from 'webextension-polyfill';
import {
APP_TITLE,
ContentScriptType,
DISCONNECT_DAPP_EVENT,
DISCONNECT_DAPP_MSG_TYPE,
PASS_TO_BG_EVENT,
RESPONSE_FROM_BG_EVENT,
SWITCH_CHAIN_EVENT,
RESPONSE_FROM_BG_MSG_TYPE,
SWITCH_CHAIN_MSG_TYPE,
WEBSITES_ANALYTICS_ENABLED
} from 'lib/constants';
import { serealizeError } from 'lib/intercom/helpers';
Expand Down Expand Up @@ -78,13 +78,13 @@ getIntercom().subscribe((msg?: TempleNotification) => {
const { origins } = msg;

if (origins.some(origin => window.origin === origin)) {
window.dispatchEvent(new CustomEvent(DISCONNECT_DAPP_EVENT));
window.postMessage({ type: DISCONNECT_DAPP_MSG_TYPE }, window.origin);
}
break;
case TempleMessageType.TempleEvmChainSwitched:
const { origin, type, ...chainSwitchPayload } = msg;
if (origin === window.origin) {
window.dispatchEvent(new CustomEvent(SWITCH_CHAIN_EVENT, { detail: chainSwitchPayload }));
window.postMessage({ type: SWITCH_CHAIN_MSG_TYPE, ...chainSwitchPayload }, window.origin);
}
}
});
Expand All @@ -102,7 +102,7 @@ window.addEventListener(PASS_TO_BG_EVENT, evt => {
})
.then((res: TempleResponse) => {
if (res?.type === TempleMessageType.PageResponse && res.payload) {
window.dispatchEvent(new CustomEvent(RESPONSE_FROM_BG_EVENT, { detail: { ...res.payload, requestId } }));
window.postMessage({ type: RESPONSE_FROM_BG_MSG_TYPE, payload: res.payload, requestId }, window.origin);
keshan3262 marked this conversation as resolved.
Show resolved Hide resolved
}
})
.catch(err => console.error(err));
Expand Down
6 changes: 3 additions & 3 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ export const MAIN_CHAINS_IDS = [

export const PASS_TO_BG_EVENT = 'templePassToBackground';

export const RESPONSE_FROM_BG_EVENT = 'templeResponseFromBackground';
export const RESPONSE_FROM_BG_MSG_TYPE = 'templeResponseFromBackground';

export const DISCONNECT_DAPP_EVENT = 'templeDisconnectDApp';
export const DISCONNECT_DAPP_MSG_TYPE = 'templeDisconnectDApp';

export const SWITCH_CHAIN_EVENT = 'templeSwitchChain';
export const SWITCH_CHAIN_MSG_TYPE = 'templeSwitchChain';
69 changes: 53 additions & 16 deletions src/temple/evm/web3-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import type {
RpcSchemaOverride
} from 'viem';

import { DISCONNECT_DAPP_EVENT, PASS_TO_BG_EVENT, RESPONSE_FROM_BG_EVENT, SWITCH_CHAIN_EVENT } from 'lib/constants';
import {
DISCONNECT_DAPP_MSG_TYPE,
PASS_TO_BG_EVENT,
RESPONSE_FROM_BG_MSG_TYPE,
SWITCH_CHAIN_MSG_TYPE
} from 'lib/constants';
import { ETHEREUM_MAINNET_CHAIN_ID } from 'lib/temple/types';

import {
Expand Down Expand Up @@ -95,7 +100,6 @@ interface BackgroundErrorResponse {

interface BackgroundSuccessResponse<M extends RequestParameters['method']> {
data: BackgroundResponseData<M>;
requestId: string;
}

type BackgroundResponse<M extends RequestParameters['method']> = BackgroundSuccessResponse<M> | BackgroundErrorResponse;
Expand All @@ -111,6 +115,29 @@ const identity = <T>(x: T) => x;
const noop = () => {};
const toHex = (value: number): HexString => `0x${value.toString(16)}`;

interface DisconnectDAppMessage {
type: typeof DISCONNECT_DAPP_MSG_TYPE;
}

interface SwitchChainMessage {
type: typeof SWITCH_CHAIN_MSG_TYPE;
chainId: number;
}

interface ResponseFromBgMessage {
type: typeof RESPONSE_FROM_BG_MSG_TYPE;
payload: any;
requestId: string;
}

const isTypedMessage = (msg: any): msg is { type: string } => typeof msg === 'object' && msg && 'type' in msg;
const isDisconnectDAppMessage = (msg: any): msg is DisconnectDAppMessage =>
isTypedMessage(msg) && msg.type === DISCONNECT_DAPP_MSG_TYPE;
const isSwitchChainMessage = (msg: any): msg is SwitchChainMessage =>
isTypedMessage(msg) && msg.type === SWITCH_CHAIN_MSG_TYPE;
const isResponseFromBgMessage = (msg: any): msg is ResponseFromBgMessage =>
isTypedMessage(msg) && msg.type === RESPONSE_FROM_BG_MSG_TYPE;

export class TempleWeb3Provider extends EventEmitter {
private accounts: HexString[];
private chainId: HexString;
Expand All @@ -136,12 +163,8 @@ export class TempleWeb3Provider extends EventEmitter {
identity,
undefined
).catch(error => console.error(error));
window.addEventListener(DISCONNECT_DAPP_EVENT, this.handleDisconnect);
window.addEventListener(SWITCH_CHAIN_EVENT, e => {
const { chainId } = (e as CustomEvent<{ chainId: number }>).detail;

this.updateChainId(toHex(chainId));
});
this.listenToTypedMessage(isDisconnectDAppMessage, this.handleDisconnect);
this.listenToTypedMessage(isSwitchChainMessage, ({ chainId }) => this.updateChainId(toHex(chainId)));
}

// @ts-expect-error
Expand Down Expand Up @@ -304,32 +327,46 @@ export class TempleWeb3Provider extends EventEmitter {
);

return new Promise<ProviderResponse<M>>((resolve, reject) => {
const listener = (evt: Event) => {
const { requestId: reqIdFromEvent, ...responseContent } = (evt as CustomEvent<BackgroundResponse<M>>).detail;
const listener = (msg: ResponseFromBgMessage) => {
const reqIdFromEvent = msg.requestId;
const payload: BackgroundResponse<M> = msg.payload;

if (reqIdFromEvent !== requestId) {
return;
}

window.removeEventListener(RESPONSE_FROM_BG_EVENT, listener);
removeListener();

if ('error' in responseContent) {
console.error('inpage got error from bg', responseContent);
reject(new ErrorWithCode(responseContent.error.code, responseContent.error.message));
if ('error' in payload) {
console.error('inpage got error from bg', payload);
reject(new ErrorWithCode(payload.error.code, payload.error.message));

return;
}

const { data } = responseContent;
const { data } = payload;

effectFn(data);
// @ts-expect-error
resolve(toProviderResponse(data));
};
window.addEventListener(RESPONSE_FROM_BG_EVENT, listener);
const removeListener = this.listenToTypedMessage(isResponseFromBgMessage, listener);
});
}

private listenToTypedMessage<T>(typeguard: (msg: any) => msg is T, callback: SyncFn<T>) {
const listener = (evt: MessageEvent<any>) => {
if (evt.origin === window.origin && typeguard(evt.data)) {
callback(evt.data);
}
};
const removeListener = () => window.removeEventListener('message', listener);

window.addEventListener('message', listener);

return removeListener;
}

private getIconUrl = memoizee(
// A page may not have a head element
async (head: HTMLHeadElement | undefined) => {
Expand Down
Loading