Skip to content

Commit ada51dd

Browse files
authored
Merge branch 'master' into remix_cbor
2 parents d060391 + bd407c5 commit ada51dd

File tree

16 files changed

+388
-410
lines changed

16 files changed

+388
-410
lines changed

apps/contract-verification/src/app/Verifiers/BlockscoutVerifier.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,14 @@ export class BlockscoutVerifier extends EtherscanVerifier {
3838
const result: SourceFile[] = []
3939
const filePrefix = `/${this.LOOKUP_STORE_DIR}/${chainId}/${contractAddress}`
4040

41-
const targetFilePath = `${filePrefix}/${blockscoutSource.FileName}`
41+
let targetFilePath
42+
if (!blockscoutSource.FileName.startsWith('..')) targetFilePath = `${filePrefix}/${blockscoutSource.FileName}`
43+
else targetFilePath = `${filePrefix}/targetFile.sol`
44+
4245
result.push({ content: blockscoutSource.SourceCode, path: targetFilePath })
4346

4447
for (const additional of blockscoutSource.AdditionalSources ?? []) {
45-
result.push({ content: additional.SourceCode, path: `${filePrefix}/${additional.Filename}` })
48+
if (!additional.Filename.startsWith('..')) result.push({ content: additional.SourceCode, path: `${filePrefix}/${additional.Filename}` })
4649
}
4750

4851
return { sourceFiles: result, targetFilePath }

apps/contract-verification/src/app/Verifiers/EtherscanVerifier.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -273,22 +273,22 @@ export class EtherscanVerifier extends AbstractVerifier {
273273
parsedFiles = JSON.parse(source.SourceCode.substring(1, source.SourceCode.length - 1)).sources
274274
} catch (e) {}
275275
}
276-
277276
if (parsedFiles) {
278277
const result: SourceFile[] = []
279278
let targetFilePath = ''
280279
for (const [fileName, fileObj] of Object.entries<any>(parsedFiles)) {
280+
if (fileName.startsWith('..')) {
281+
if (fileName.endsWith(`/${source.ContractName}.sol`)) targetFilePath = `${filePrefix}/targetFile.sol`
282+
else continue
283+
}
281284
const path = `${filePrefix}/${fileName}`
282285

283286
result.push({ path, content: fileObj.content })
284287

285-
if (path.endsWith(`/${source.ContractName}.sol`)) {
286-
targetFilePath = path
287-
}
288+
if (path.endsWith(`/${source.ContractName}.sol`)) targetFilePath = path
288289
}
289290
return { sourceFiles: result, targetFilePath }
290291
}
291-
292292
// Parsing to JSON failed, SourceCode is the code itself
293293
const targetFilePath = `${filePrefix}/${source.ContractName}.sol`
294294
const sourceFiles: SourceFile[] = [{ content: source.SourceCode, path: targetFilePath }]

apps/contract-verification/src/app/Verifiers/SourcifyV1Verifier.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ export class SourcifyV1Verifier extends AbstractVerifier {
152152
}
153153
}
154154

155-
if (filePath) {
155+
if (filePath && !filePath.startsWith('..')) {
156156
result.push({ path: `${filePrefix}/${filePath}`, content: file.content })
157157
}
158158

apps/contract-verification/src/app/Verifiers/SourcifyVerifier.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,14 @@ export class SourcifyVerifier extends AbstractVerifier {
212212
// Extract contract path from fully qualified name (path can include colons)
213213
const splitIdentifier = fullyQualifiedName.split(':')
214214
const contractPath = splitIdentifier.slice(0, -1).join(':')
215-
216215
for (const [filePath, fileData] of Object.entries(sources)) {
216+
if (filePath.startsWith('..')) {
217+
if (filePath === contractPath) targetFilePath = `${filePrefix}/sources/targetFile.sol`
218+
else continue
219+
}
217220
const path = `${filePrefix}/sources/${filePath}`
218221
result.push({ path, content: fileData.content })
219-
if (filePath === contractPath) {
220-
targetFilePath = path
221-
}
222+
if (filePath === contractPath) targetFilePath = path
222223
}
223224

224225
return { sourceFiles: result, targetFilePath }

apps/remix-ide-e2e/src/tests/gist.test.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -113,18 +113,18 @@ module.exports = {
113113
.waitForElementVisible('*[data-shared="tooltipPopup"]', 60000)
114114
.assert.containsText('*[data-shared="tooltipPopup"]', 'Credentials removed')
115115
.click('*[data-id="github-dropdown-toggle"]')
116-
.click('*[data-id="github-dropdown-item-publish-to-gist"]')
117-
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
116+
.waitForElementNotPresent('*[data-id="github-dropdown-item-publish-to-gist"]')
117+
// .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
118118
// .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
119-
.perform((done) => {
120-
browser.getText('[data-id="fileSystemModalDialogModalBody-react"]', (result) => {
121-
console.log('result.value: ', result.value)
122-
browser.assert.ok(result.value === 'Remix requires an access token (which includes gists creation permission). Please go to the settings tab to create one.', 'Assert failed. Gist token error message not displayed.')
123-
done()
124-
})
125-
})
126-
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
127-
.click('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
119+
// .perform((done) => {
120+
// browser.getText('[data-id="fileSystemModalDialogModalBody-react"]', (result) => {
121+
// console.log('result.value: ', result.value)
122+
// browser.assert.ok(result.value === 'Remix requires an access token (which includes gists creation permission). Please go to the settings tab to create one.', 'Assert failed. Gist token error message not displayed.')
123+
// done()
124+
// })
125+
// })
126+
// .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
127+
// .click('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
128128
},
129129

130130
'Import From Gist For Valid Gist ID #group2': '' + function (browser: NightwatchBrowser) {

apps/remix-ide/src/app/plugins/git.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const profile = {
88
name: 'dgit',
99
displayName: 'Git',
1010
description: 'Git plugin for Remix',
11-
methods: ['open', 'init'],
11+
methods: ['open', 'init', 'login', 'logOut'],
1212
events: [''],
1313
version: packageJson.version,
1414
maintainedBy: 'Remix',
@@ -41,4 +41,12 @@ export class GitPlugin extends ViewPlugin {
4141
return <div id='gitTab'><GitUI plugin={this} /></div>
4242
}
4343

44+
async login(){
45+
this.emit('login')
46+
}
47+
48+
async logOut(){
49+
this.emit('disconnect')
50+
}
51+
4452
}

libs/remix-ui/git/src/components/github/devicecode.tsx

Lines changed: 41 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ import { sendToMatomo } from "../../lib/pluginActions";
77
import { gitMatomoEventTypes } from "../../types";
88
import { endpointUrls } from "@remix-endpoints-helper";
99
import isElectron from "is-electron";
10-
import { set } from "lodash";
11-
import { use } from "chai";
10+
import { startGitHubLogin, getDeviceCodeFromGitHub, connectWithDeviceCode, disconnectFromGitHub } from "../../lib/gitLoginActions";
1211

13-
export const GetDeviceCode = () => {
12+
export const ConnectToGitHub = () => {
1413
const context = React.useContext(gitPluginContext)
1514
const actions = React.useContext(gitActionsContext)
1615
const pluginActions = React.useContext(pluginActionsContext)
@@ -21,119 +20,48 @@ export const GetDeviceCode = () => {
2120

2221
const popupRef = useRef<Window | null>(null)
2322

24-
// Dynamically select the GitHub OAuth client ID based on the hostname
25-
const getClientId = async () => {
26-
const host = isElectron() ? 'desktop' : window.location.hostname
27-
// fetch it with axios from `${endpointUrls.gitHubLoginProxy}/client-id?host=${host}`
28-
try {
29-
const response = await axios.get(`${endpointUrls.gitHubLoginProxy}/client/${host}`, {
30-
headers: {
31-
'Content-Type': 'application/json',
32-
'Accept': 'application/json'
33-
}
34-
})
35-
return response.data.client_id
36-
}
37-
catch (error) {
38-
throw new Error('Failed to fetch GitHub client ID')
39-
}
40-
41-
}
42-
4323
const openPopupLogin = useCallback(async () => {
44-
45-
if (isElectron()) {
46-
setDesktopIsLoading(true)
47-
pluginActions.loginWithGitHub()
48-
return
49-
}
50-
51-
const clientId = await getClientId()
52-
const redirectUri = `${window.location.origin}/?source=github`
53-
const scope = 'repo gist user:email read:user'
54-
55-
const url = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scope)}&response_type=code`
56-
57-
const popup = window.open(url, '_blank', 'width=600,height=700')
58-
if (!popup) {
59-
console.warn('Popup blocked or failed to open, falling back to device code flow.')
60-
await getDeviceCodeFromGitHub()
61-
return
62-
}
63-
popupRef.current = popup
64-
65-
const messageListener = async (event: MessageEvent) => {
66-
if (event.origin !== window.location.origin) return
67-
68-
if (event.data.type === 'GITHUB_AUTH_SUCCESS') {
69-
const token = event.data.token
70-
await pluginActions.saveToken(token)
71-
await actions.loadGitHubUserFromToken()
24+
await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBBUTTON)
25+
try {
26+
if (isElectron()) {
27+
setDesktopIsLoading(true)
28+
}
29+
await startGitHubLogin()
30+
if (!isElectron()) {
7231
setAuthorized(true)
73-
await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBSUCCESS)
74-
window.removeEventListener('message', messageListener)
75-
popup?.close()
76-
} else if (event.data.type === 'GITHUB_AUTH_FAILURE') {
32+
}
33+
} catch (error) {
34+
console.error('GitHub login failed:', error)
35+
if (isElectron()) {
36+
setDesktopIsLoading(false)
37+
} else {
7738
setPopupError(true)
78-
window.removeEventListener('message', messageListener)
79-
popup?.close()
39+
// Fallback to device code flow
40+
await handleGetDeviceCode()
8041
}
8142
}
43+
}, [])
8244

83-
window.addEventListener('message', messageListener)
84-
}, [actions, pluginActions])
85-
86-
const getDeviceCodeFromGitHub = async () => {
45+
const handleGetDeviceCode = async () => {
8746
setDesktopIsLoading(false)
8847
setPopupError(false)
89-
await sendToMatomo(gitMatomoEventTypes.GETGITHUBDEVICECODE)
9048
setAuthorized(false)
91-
// Send a POST request
92-
const response = await axios({
93-
method: 'post',
94-
url: `${endpointUrls.github}/login/device/code`,
95-
data: {
96-
client_id: '2795b4e41e7197d6ea11',
97-
scope: 'repo gist user:email read:user'
98-
},
99-
headers: {
100-
'Content-Type': 'application/json',
101-
'Accept': 'application/json'
102-
},
103-
});
10449

105-
// convert response to json
106-
const githubrespone = await response.data;
107-
108-
setGitHubResponse(githubrespone)
50+
try {
51+
const githubResponse = await getDeviceCodeFromGitHub()
52+
setGitHubResponse(githubResponse)
53+
} catch (error) {
54+
console.error('Failed to get device code:', error)
55+
await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBFAIL)
56+
}
10957
}
11058

11159
const connectApp = async () => {
112-
await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUB)
113-
// poll https://github.com/login/oauth/access_token
114-
const accestokenresponse = await axios({
115-
method: 'post',
116-
url: `${endpointUrls.github}/login/oauth/access_token`,
117-
data: {
118-
client_id: '2795b4e41e7197d6ea11',
119-
device_code: gitHubResponse.device_code,
120-
grant_type: 'urn:ietf:params:oauth:grant-type:device_code'
121-
},
122-
headers: {
123-
'Content-Type': 'application/json',
124-
'Accept': 'application/json'
125-
},
126-
});
127-
128-
// convert response to json
129-
const response = await accestokenresponse.data;
130-
131-
if (response.access_token) {
60+
try {
61+
await connectWithDeviceCode(gitHubResponse.device_code)
13262
setAuthorized(true)
133-
await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBSUCCESS)
134-
await pluginActions.saveToken(response.access_token)
135-
await actions.loadGitHubUserFromToken()
136-
} else {
63+
} catch (error) {
64+
console.error('Failed to connect with device code:', error)
13765
await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBFAIL)
13866
}
13967
}
@@ -144,12 +72,14 @@ export const GetDeviceCode = () => {
14472
}
14573
},[context.gitHubUser])
14674

147-
const disconnect = async () => {
148-
await sendToMatomo(gitMatomoEventTypes.DISCONNECTFROMGITHUB)
149-
setAuthorized(false)
150-
setGitHubResponse(null)
151-
await pluginActions.saveToken(null)
152-
await actions.loadGitHubUserFromToken()
75+
const handleDisconnect = async () => {
76+
try {
77+
await disconnectFromGitHub()
78+
setAuthorized(false)
79+
setGitHubResponse(null)
80+
} catch (error) {
81+
console.error('Failed to disconnect from GitHub:', error)
82+
}
15383
}
15484

15585
return (
@@ -162,7 +92,7 @@ export const GetDeviceCode = () => {
16292
{popupError && !gitHubResponse && !authorized && (
16393
<div className="alert alert-warning mt-2" role="alert">
16494
GitHub login failed. You can continue using another method.
165-
<button className='btn btn-outline-primary btn-sm mt-2 w-100' onClick={getDeviceCodeFromGitHub}>
95+
<button className='btn btn-outline-primary btn-sm mt-2 w-100' onClick={handleGetDeviceCode}>
16696
Use another method
16797
</button>
16898
</div>
@@ -171,7 +101,7 @@ export const GetDeviceCode = () => {
171101
<i className="fas fa-spinner fa-spin fa-2x mt-1"></i>
172102
<div className="alert alert-warning mt-2" role="alert">
173103
In case of issues, you can try another method.
174-
<button className='btn btn-outline-primary btn-sm mt-2 w-100' onClick={getDeviceCodeFromGitHub}>
104+
<button className='btn btn-outline-primary btn-sm mt-2 w-100' onClick={handleGetDeviceCode}>
175105
Use another method
176106
</button>
177107
</div>
@@ -202,7 +132,7 @@ export const GetDeviceCode = () => {
202132
(context.gitHubUser && context.gitHubUser.isConnected) ?
203133
<div className="pt-2">
204134
<button data-id='disconnect-github' className='btn btn-primary mt-1 w-100' onClick={async () => {
205-
disconnect()
135+
handleDisconnect()
206136
}}>Disconnect</button>
207137
</div> : null
208138
}

libs/remix-ui/git/src/components/gitui.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { RemotesNavigation } from './navigation/remotes'
2121
import { Remotes } from './panels/remotes'
2222
import { GitHubNavigation } from './navigation/github'
2323
import { loaderReducer } from '../state/loaderReducer'
24-
import { GetDeviceCode } from './github/devicecode'
24+
import { ConnectToGitHub } from './github/devicecode'
2525
import { LogNavigation } from './navigation/log'
2626
import LogViewer from './panels/log'
2727
import { SourceControlBase } from './buttons/sourceControlBase'
@@ -241,7 +241,7 @@ export const GitUI = (props: IGitUi) => {
241241
<GitHubNavigation eventKey={gitUIPanels.GITHUB} activePanel={activePanel} callback={setActivePanel} />
242242
<Accordion.Collapse className='bg-light' eventKey={gitUIPanels.GITHUB}>
243243
<div className="px-2 py-2">
244-
<GetDeviceCode></GetDeviceCode>
244+
<ConnectToGitHub></ConnectToGitHub>
245245
<hr></hr>
246246
<GitHubCredentials></GitHubCredentials>
247247
</div>

0 commit comments

Comments
 (0)