116 lines
2.9 KiB
TypeScript
116 lines
2.9 KiB
TypeScript
|
import { getFaviconUrl } from '~lib/get-favicon-url'
|
||
|
import { ProviderMessage } from '~messages/provider-message'
|
||
|
|
||
|
import { DesktopClient } from '../lib/desktop-client'
|
||
|
|
||
|
import type { ProxyMessage } from '~messages/proxy-message'
|
||
|
import type { EthersError } from 'ethers'
|
||
|
import type { PlasmoCSConfig } from 'plasmo'
|
||
|
|
||
|
export const config: PlasmoCSConfig = {
|
||
|
run_at: 'document_start',
|
||
|
}
|
||
|
|
||
|
const desktopClient = new DesktopClient()
|
||
|
|
||
|
const handleMessage = async (event: MessageEvent) => {
|
||
|
if (event.origin !== window.origin) {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
let message: ProviderMessage
|
||
|
try {
|
||
|
message = ProviderMessage.parse(event.data)
|
||
|
} catch {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (message.type === 'status:provider:disconnect') {
|
||
|
desktopClient.stop()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (message.type !== 'status:provider') {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (!event.ports.length) {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
console.log('request::', message.data)
|
||
|
|
||
|
const response = await desktopClient.send({
|
||
|
...message.data,
|
||
|
name: window.location.hostname,
|
||
|
url: window.origin,
|
||
|
iconUrl: getFaviconUrl() ?? '',
|
||
|
})
|
||
|
|
||
|
console.log('response::', response)
|
||
|
|
||
|
event.ports[0].postMessage({
|
||
|
type: 'status:proxy:success',
|
||
|
data: response,
|
||
|
} satisfies ProxyMessage)
|
||
|
} catch (error) {
|
||
|
let proxyError = {
|
||
|
code: -32603,
|
||
|
message: isError(error) ? error.message : 'Internal error',
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ethers.js library has a custom error detection mechanism.
|
||
|
* - Detected errors are stored in the `info` object:
|
||
|
* @see https://github.com/ethers-io/ethers.js/blob/72c2182d01afa855d131e82635dca3da063cfb31/src.ts/providers/provider-jsonrpc.ts#L976-L1057
|
||
|
* - Undetected errors are stored in the `error` field:
|
||
|
* @see https://github.com/ethers-io/ethers.js/blob/72c2182d01afa855d131e82635dca3da063cfb31/src.ts/providers/provider-jsonrpc.ts#L1059
|
||
|
*/
|
||
|
if (isEthersError(error)) {
|
||
|
if (isRpcError(error.error)) {
|
||
|
proxyError = error.error
|
||
|
} else if (isRpcError(error.info?.error)) {
|
||
|
proxyError = error.info.error
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const proxyMessage: ProxyMessage = {
|
||
|
type: 'status:proxy:error',
|
||
|
error: proxyError,
|
||
|
}
|
||
|
|
||
|
event.ports[0].postMessage(proxyMessage)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function isError(error: unknown): error is Error {
|
||
|
return !!error && typeof error === 'object' && 'message' in error
|
||
|
}
|
||
|
|
||
|
function isEthersError(error: unknown): error is EthersError & {
|
||
|
info?: { error?: { code: number; message: string } }
|
||
|
} {
|
||
|
return (
|
||
|
!!error &&
|
||
|
typeof error === 'object' &&
|
||
|
'error' in error &&
|
||
|
error.error !== null &&
|
||
|
typeof error.error === 'object' &&
|
||
|
'code' in error.error
|
||
|
)
|
||
|
}
|
||
|
|
||
|
function isRpcError(
|
||
|
error: unknown,
|
||
|
): error is { code: number; message: string } {
|
||
|
return (
|
||
|
!!error &&
|
||
|
typeof error === 'object' &&
|
||
|
'code' in error &&
|
||
|
'message' in error
|
||
|
)
|
||
|
}
|
||
|
|
||
|
window.addEventListener('message', handleMessage)
|