Skip to content

Commit a64cbe8

Browse files
authored
[Tech] Refactor extension helper (#898)
* refactor extension helper * refactors for extension provider * prettier * fixes for extension provider * fixes for extension importer * fix ?? warnings * vite fixes * prettier * refactor pkg * ignore buildResetExtension * fix reset extension * update proxy server * fix provider request * update mm * update mm * update mm * update overlay submodule with main changes * fix mm links * fix send request * set main window on top when opening mm pages * fix mm links in browser game overlay (#905) * change maximize to restore * rm extension helper * pretty * rm classic level * refactor static hp ext importer imports to dynamic * add back classic level * use shell true to fix windows pkg build * merge hp overlay submodule
1 parent 6740455 commit a64cbe8

File tree

38 files changed

+607
-110
lines changed

38 files changed

+607
-110
lines changed

.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ flatpak/.flatpak-builder/
44
vite.config.ts
55
**/__mocks__/**
66
sign/**
7+
buildResetExtension.js

.github/workflows/submodules-are-merged.yml

-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ jobs:
2020
run: >
2121
git config --global url."https://github.com/".insteadOf
2222
ssh://git@github.com/
23-
- name: Check extension helper
24-
id: extDiff
25-
run: cd src/backend/hyperplay-extension-helper && echo "EXT_HELPER_DIFF=$(git log origin/main...HEAD)" >> "$GITHUB_OUTPUT"
2623
- name: Check overlay
2724
id: overlayDiff
2825
run: cd src/backend/hyperplay-overlay && echo "OVERLAY_DIFF=$(git log origin/main...HEAD)" >> "$GITHUB_OUTPUT"

.gitmodules

-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
[submodule "src/backend/hyperplay-extension-helper"]
2-
path = src/backend/hyperplay-extension-helper
3-
url = https://github.com/HyperPlay-Gaming/hyperplay-extension-helper.git
41
[submodule "src/backend/hyperplay-overlay"]
52
path = src/backend/hyperplay-overlay
63
url = https://github.com/HyperPlay-Gaming/hyperplay-overlay.git

LICENSE_ALL

-7
Original file line numberDiff line numberDiff line change
@@ -698,13 +698,6 @@ https://github.com/HyperPlay-Gaming/hyperplay-extension-helper
698698

699699
---
700700

701-
@hyperplay/hyperplay-extension-helper
702-
https://github.com/HyperPlay-Gaming/hyperplay-extension-helper
703-
704-
© 2022 - 2023 HyperPlay Labs, Inc. - All Rights Reserved.
705-
706-
---
707-
708701
@hyperplay/hyperplay-overlay
709702
https://github.com/HyperPlay-Gaming/hyperplay-overlay
710703

buildResetExtension.js

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const { spawnSync } = require('child_process')
2+
const { existsSync } = require('fs')
3+
const { platform } = require('os')
4+
const process = require('process')
5+
6+
const [nodeExe, scriptPath, ...args] = process.argv
7+
8+
const resetExtensionScript =
9+
'./node_modules/@hyperplay/extension-importer/src/resetExtension.js'
10+
if (existsSync(resetExtensionScript)) {
11+
console.log('spawning pkg', resetExtensionScript, args)
12+
const command = platform() === 'win32' ? 'yarn.cmd' : 'yarn'
13+
const result = spawnSync(
14+
command,
15+
[
16+
'pkg',
17+
resetExtensionScript,
18+
'--out-path',
19+
'./public/extensions/resetExecutables',
20+
...args
21+
],
22+
{ shell: true }
23+
)
24+
if (result.error) {
25+
console.error(result.error)
26+
} else {
27+
console.log('stdout: ', result.stdout.toString())
28+
console.error('stderr: ', result.stderr.toString())
29+
}
30+
} else {
31+
console.warn('Reset extension script could not be found')
32+
}

package.json

+8-4
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@
169169
"@fortawesome/react-fontawesome": "^0.1.18",
170170
"@hyperplay/check-disk-space": "^3.5.2",
171171
"@hyperplay/ui": "^1.2.32",
172+
"@hyperplay/utils": "^0.0.12",
172173
"@mantine/carousel": "^7.5.1",
173174
"@mantine/core": "^7.5.1",
174175
"@mantine/dropzone": "^7.5.1",
@@ -197,7 +198,7 @@
197198
"auto-launch": "^5.0.6",
198199
"axios": "^1.6.8",
199200
"bn.js": "^5.2.1",
200-
"classic-level": "1.2.0",
201+
"classic-level": "^1.4.1",
201202
"classnames": "^2.3.1",
202203
"compare-versions": "^6.0.0-rc.1",
203204
"crc": "^4.1.1",
@@ -293,7 +294,7 @@
293294
"prepare": "husky install",
294295
"prettier": "prettier --check .",
295296
"prettier-fix": "prettier --write .",
296-
"pkgResetExtension:base": "pkg ./src/backend/hyperplay-extension-helper/resetExtension.js --out-path ./public/extensions/resetExecutables",
297+
"pkgResetExtension:base": "node ./buildResetExtension.js",
297298
"pkgResetExtension:arm64:mac": "yarn pkgResetExtension:base -t node18-macos-arm64",
298299
"pkgResetExtension:x64:mac": "yarn pkgResetExtension:base -t node18-macos-x64",
299300
"pkgResetExtension:x64:win": "yarn pkgResetExtension:base -t node18-win-x64",
@@ -358,6 +359,8 @@
358359
"vite-plugin-svgr": "^2.2.2"
359360
},
360361
"optionalDependencies": {
362+
"@hyperplay/extension-importer": "^0.0.4",
363+
"@hyperplay/extension-provider": "^0.0.5",
361364
"@hyperplay/mock-backend": "^0.0.1",
362365
"@hyperplay/providers": "^0.0.5",
363366
"@hyperplay/proxy-server": "^0.0.9"
@@ -375,7 +378,6 @@
375378
"@rudderstack/rudder-sdk-node>bull>msgpackr>msgpackr-extract": true,
376379
"@testing-library/dom>aria-query>@babel/runtime-corejs3>core-js-pure": true,
377380
"@valist/sdk>files-from-path>ipfs-unixfs>protobufjs": true,
378-
"classic-level": true,
379381
"discord-rich-presence-typescript>discord-rpc>register-scheme": false,
380382
"electron": true,
381383
"electron-vite>esbuild": true,
@@ -385,7 +387,9 @@
385387
"postinstall-postinstall": true,
386388
"@rudderstack/rudder-sdk-node": true,
387389
"jsdom>ws>bufferutil": true,
388-
"jsdom>ws>utf-8-validate": true
390+
"jsdom>ws>utf-8-validate": true,
391+
"@hyperplay/extension-importer>classic-level": true,
392+
"classic-level": false
389393
}
390394
}
391395
}

src/backend/api/extensionImporter.ts

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { ipcRenderer } from 'electron'
2+
import { MetaMaskInitMethod, ImportableBrowser } from '@hyperplay/utils'
3+
import { MetamaskExtensionRequest } from 'common/types/proxy-types'
4+
import { WrapRendererCallback } from 'common/types'
5+
6+
/* eslint-disable @typescript-eslint/no-explicit-any */
7+
export const extensionOnEvent = (topic: string, ...args: any[]) => {
8+
ipcRenderer.send('extensionOnEvent', topic, ...args)
9+
}
10+
11+
export const handleMetamaskExtensionRequests = (
12+
callback: WrapRendererCallback<MetamaskExtensionRequest>
13+
) => {
14+
ipcRenderer.on('metamaskExtensionRequest', callback)
15+
return () => {
16+
ipcRenderer.removeListener('metamaskExtensionRequest', callback)
17+
}
18+
}
19+
20+
export const handleMetamaskExtensionSends = (
21+
callback: WrapRendererCallback<MetamaskExtensionRequest>
22+
) => {
23+
ipcRenderer.on('metamaskExtensionSend', callback)
24+
return () => {
25+
ipcRenderer.removeListener('metamaskExtensionSend', callback)
26+
}
27+
}
28+
29+
export const handleMetamaskExtensionSendAsyncs = (
30+
callback: WrapRendererCallback<MetamaskExtensionRequest>
31+
) => {
32+
ipcRenderer.on('metamaskExtensionSendAsync', callback)
33+
return () => {
34+
ipcRenderer.removeListener('metamaskExtensionSendAsync', callback)
35+
}
36+
}
37+
38+
export const returnExtensionRequest = (requestId: number, args: any) => {
39+
ipcRenderer.send('returnExtensionRequest', requestId, args)
40+
}
41+
42+
export const errorExtensionRequest = (requestId: number, error: any) => {
43+
ipcRenderer.send('errorExtensionRequest', requestId, error)
44+
}
45+
46+
export const handleSetBadgeTextInRenderer = (
47+
cb: WrapRendererCallback<(text: string) => void>
48+
) => {
49+
ipcRenderer.on('setBadgeTextInRenderer', cb)
50+
return () => {
51+
ipcRenderer.removeListener('setBadgeTextInRenderer', cb)
52+
}
53+
}
54+
55+
export const importMetaMask = async (
56+
mmInitMethod: MetaMaskInitMethod,
57+
dbPath?: string | null,
58+
browser?: ImportableBrowser
59+
) => ipcRenderer.invoke('importMetaMask', mmInitMethod, dbPath, browser)
60+
61+
export const getMetaMaskImportOptions = async () =>
62+
ipcRenderer.invoke('getMetaMaskImportOptions')
63+
64+
export const isExtensionInitialized = async () =>
65+
ipcRenderer.invoke('isExtensionInitialized')
66+
67+
export const handleMetaMaskImportError = (
68+
cb: WrapRendererCallback<(code: string) => void>
69+
) => {
70+
ipcRenderer.on('importMetaMaskError', cb)
71+
return () => {
72+
ipcRenderer.removeListener('importMetaMaskError', cb)
73+
}
74+
}
75+
76+
export const createNewMetaMaskWallet = (mmInitMethod: MetaMaskInitMethod) => {
77+
ipcRenderer.send('createNewMetaMaskWallet', mmInitMethod)
78+
}
79+
80+
export const handleOpenMetaMaskHomePage = (
81+
cb: WrapRendererCallback<(pathname: string) => void>
82+
) => {
83+
ipcRenderer.on('openMetaMaskHomePage', cb)
84+
return () => {
85+
ipcRenderer.removeListener('openMetaMaskHomePage', cb)
86+
}
87+
}
88+
89+
export const handleOpenMetaMaskSnapsPage = (
90+
cb: WrapRendererCallback<() => void>
91+
) => {
92+
ipcRenderer.on('openMetaMaskSnapsPage', cb)
93+
return () => {
94+
ipcRenderer.removeListener('openMetaMaskSnapsPage', cb)
95+
}
96+
}
97+
98+
export const handleOpenMetaMaskPortfolioPage = (
99+
cb: WrapRendererCallback<(pathname: string) => void>
100+
) => {
101+
ipcRenderer.on('openMetaMaskPortfolioPage', cb)
102+
return () => {
103+
ipcRenderer.removeListener('openMetaMaskPortfolioPage', cb)
104+
}
105+
}
106+
107+
export const getExtensionId = async () => ipcRenderer.invoke('getExtensionId')
108+
109+
export const getImportFolderPath = async () => {
110+
return ipcRenderer.invoke('getImportFolderPath')
111+
}

src/backend/api/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import * as Settings from './settings'
77
import * as Wine from './wine'
88
import * as Proxy from './proxy'
99
import * as DownloadManager from './downloadmanager'
10-
import * as Extensions from '../hyperplay-extension-helper/api/extensions'
10+
import * as Extensions from './extensionImporter'
1111
import * as Metrics from './metrics'
1212
import * as Overlay from 'backend/hyperplay-overlay/api'
1313
import * as Achievements from './questsAchievements'

src/backend/constants.ts

+9-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { spawnSync } from 'child_process'
22
import { homedir, platform } from 'os'
3-
import { join, resolve } from 'path'
3+
import { join } from 'path'
44
import { parse } from '@node-steam/vdf'
55

66
import { GameConfigVersion, GlobalConfigVersion } from 'common/types'
@@ -12,6 +12,14 @@ import { existsSync, mkdirSync, readFileSync } from 'graceful-fs'
1212
import { GlobalConfig } from './config'
1313
import { TypeCheckedStoreBackend } from './electron_store'
1414
import { DEV_PORTAL_URL } from 'common/constants'
15+
import {
16+
configFolder,
17+
appConfigFolder,
18+
publicDir,
19+
fixAsarPath,
20+
icon
21+
} from './constants/folders'
22+
export * from './constants/folders'
1523

1624
const configStore = new TypeCheckedStoreBackend('configStore', {
1725
cwd: 'store'
@@ -39,10 +47,8 @@ const currentGlobalConfigVersion: GlobalConfigVersion = 'v0'
3947

4048
const flatPakHome = env.XDG_DATA_HOME?.replace('/data', '') || homedir()
4149
const userHome = homedir()
42-
const configFolder = app.getPath('appData')
4350
const appFolder = join(configFolder, 'hyperplay')
4451
const legendaryConfigPath = join(appFolder, 'legendaryConfig', 'legendary')
45-
const appConfigFolder = join(configFolder, 'hyperplay')
4652
const configPath = join(appConfigFolder, 'config.json')
4753
const gamesConfigPath = join(appConfigFolder, 'GamesConfig')
4854

@@ -69,9 +75,7 @@ const cachedUbisoftInstallerPath = join(
6975
const { currentLogFile, lastLogFile, legendaryLogFile, gogdlLogFile } =
7076
createNewLogFileAndClearOldOnes()
7177

72-
const publicDir = resolve(__dirname, '..', app.isPackaged ? '' : '../public')
7378
const gogdlAuthConfig = join(app.getPath('userData'), 'gog_store', 'auth.json')
74-
const icon = fixAsarPath(join(publicDir, 'app_icon.png'))
7579
const iconDark = fixAsarPath(join(publicDir, 'trayIconDark24x24.png'))
7680
const iconLight = fixAsarPath(join(publicDir, 'trayIconLight24x24.png'))
7781
const vulkanHelperBin = fixAsarPath(
@@ -139,18 +143,6 @@ function getShell() {
139143
}
140144
}
141145

142-
/**
143-
* Fix path for packed files with asar, else will do nothing.
144-
* @param origin original path
145-
* @returns fixed path
146-
*/
147-
function fixAsarPath(origin: string): string {
148-
if (!origin.includes('app.asar.unpacked')) {
149-
return origin.replace('app.asar', 'app.asar.unpacked')
150-
}
151-
return origin
152-
}
153-
154146
export function getSteamCompatFolder() {
155147
// Paths are from https://savelocation.net/steam-game-folder
156148
if (isWindows) {

src/backend/constants/folders.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { app } from 'electron'
2+
import { join, resolve } from 'path'
3+
4+
export const configFolder = app.getPath('appData')
5+
export const appConfigFolder = join(configFolder, 'hyperplay')
6+
export const publicDir = resolve(
7+
__dirname,
8+
'..',
9+
app.isPackaged ? '' : '../public'
10+
)
11+
export function fixAsarPath(origin: string): string {
12+
if (!origin.includes('app.asar.unpacked')) {
13+
return origin.replace('app.asar', 'app.asar.unpacked')
14+
}
15+
return origin
16+
}
17+
export const icon = fixAsarPath(join(publicDir, 'app_icon.png'))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { backendEvents } from 'backend/backend_events'
2+
import { trackEvent } from 'backend/metrics/metrics'
3+
import defaultProviderStore from 'backend/proxy/provider_store'
4+
import { PROVIDERS } from 'common/types/proxy-types'
5+
import { app } from 'electron'
6+
import store from './store'
7+
import { initExtension } from '.'
8+
import { hpApi } from 'backend/utils/hyperplay_api'
9+
10+
backendEvents.on('currentWeb3Provider', (provider: PROVIDERS) => {
11+
defaultProviderStore.set('currentWeb3Provider', provider)
12+
})
13+
14+
backendEvents.on(
15+
'MetaMask Initialized',
16+
(mmInitMethod: string, browser: string) => {
17+
trackEvent({
18+
event: 'MetaMask Initialized',
19+
properties: { initMethod: mmInitMethod, browser }
20+
})
21+
}
22+
)
23+
24+
backendEvents.on('initExtension', async () => {
25+
store.set('isInitialized', true)
26+
await initExtension(hpApi)
27+
})
28+
29+
const openNewWindowListener = (
30+
ev: Electron.Event,
31+
contents: Electron.WebContents
32+
) => {
33+
backendEvents.emit('web-contents-created', ev, contents)
34+
}
35+
36+
app.on('web-contents-created', openNewWindowListener)
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { session } from 'electron'
2+
import store from './store'
3+
import { HyperPlayAPI } from '@hyperplay/utils'
4+
import './backendEventHandlers'
5+
import './ipcHandler'
6+
7+
export const initExtension = async function (api: HyperPlayAPI) {
8+
const extensionImporter = await import('@hyperplay/extension-importer')
9+
const isInitialized = store.get('isInitialized', false)
10+
extensionImporter.initExtension(api, session.defaultSession, isInitialized)
11+
}

0 commit comments

Comments
 (0)