From 6b9a7c527b72d4687f740c24f9948e81962b3a0e Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Tue, 10 Sep 2024 12:55:24 +0100 Subject: [PATCH 1/7] add regex for pragma --- .../src/app/components/CompilerButton.tsx | 4 +-- apps/vyper/src/app/utils/compiler.tsx | 29 ++++++++++++------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/apps/vyper/src/app/components/CompilerButton.tsx b/apps/vyper/src/app/components/CompilerButton.tsx index cf06790c4e6..d661416dbc9 100644 --- a/apps/vyper/src/app/components/CompilerButton.tsx +++ b/apps/vyper/src/app/components/CompilerButton.tsx @@ -1,5 +1,5 @@ import React, { Fragment, useEffect, useState } from 'react' -import {isVyper, compile, toStandardOutput, isCompilationError, remixClient, normalizeContractPath, compileContract, RemixClient} from '../utils' +import { isVyper, compile, toStandardOutput, isCompilationError, remixClient, normalizeContractPath, compileContract, RemixClient } from '../utils' import Button from 'react-bootstrap/Button' interface Props { @@ -11,7 +11,7 @@ interface Props { remixClient: RemixClient } -function CompilerButton({contract, setOutput, compilerUrl, resetCompilerState, output, remixClient}: Props) { +function CompilerButton({ contract, setOutput, compilerUrl, resetCompilerState, output, remixClient }: Props) { const [loadingSpinner, setLoadingSpinnerState] = useState(false) if (!contract || !contract) { diff --git a/apps/vyper/src/app/utils/compiler.tsx b/apps/vyper/src/app/utils/compiler.tsx index 7fdf99e4568..a1d4916f0e1 100644 --- a/apps/vyper/src/app/utils/compiler.tsx +++ b/apps/vyper/src/app/utils/compiler.tsx @@ -47,6 +47,7 @@ export function normalizeContractPath(contractPath: string): string[] { function parseErrorString(errorString) { // Split the string into lines + console.log(errorString) let lines = errorString.trim().split('\n') // Extract the line number and message let message = errorString.trim() @@ -141,20 +142,21 @@ const compileReturnType = (output, contract) => { } const fixContractContent = (content: string) => { + const pragmaRegex = /#\s*pragma\s+[@]*version\s+([\^~<>!=^]+)\s*(\d+\.\d+\.\d+)/ if (content.length === 0) return - const pragmaFound = content.includes('#pragma version ^0.3.10') + const pragmaFound = content.match(pragmaRegex) const wrongpragmaFound = content.includes('# pragma version ^0.3.10') - const evmVerFound = content.includes('#pragma evm-version shanghai') - const pragma = '#pragma version ^0.3.10' - const evmVer = '#pragma evm-version shanghai' + const evmVerFound = content.includes('#pragma evm-version cancun') + const pragma = '# pragma version ~=0.4.0' + const evmVer = '# pragma evm-version cancun' - if (evmVerFound === false) { - content = `${evmVer}\n${content}` - } + // if (evmVerFound === false) { + // content = `${evmVer}\n${content}` + // } if (wrongpragmaFound === true) { content = content.replace('# pragma version ^0.3.10', '') } - if (pragmaFound === false ) { + if (!pragmaFound) { content = `${pragma}\n${content}` } return content @@ -174,13 +176,17 @@ export async function compile(url: string, contract: Contract): Promise { throw new Error('Use extension .vy for Vyper.') } + const cleanedUpContent = fixContractContent(contract.content) + console.log('cleanedUp', cleanedUpContent) + let contractName = contract['name'] const compilePackage = { manifest: 'ethpm/3', sources: { - [contractName] : { content : fixContractContent(contract.content) } + [contractName] : { content : cleanedUpContent } } } + console.log(compilePackage) let response = await axios.post(`${url}compile`, compilePackage ) if (response.status === 404) { @@ -204,11 +210,12 @@ export async function compile(url: string, contract: Contract): Promise { })).data return result - } else if (status === 'FAILED') { + } else if (status !== 'SUCCESS') { const intermediate = await(await axios.get(url + 'exceptions/' + compileCode , { method: 'Get' })).data - result = parseErrorString(intermediate[0]) + result = parseErrorString(intermediate) + console.log('Errors found', intermediate) return result } await new Promise((resolve) => setTimeout(() => resolve({}), 3000)) From cbb5dfe01db53c0b417f745e1e9afd9d0c887b41 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 12 Sep 2024 02:12:22 +0100 Subject: [PATCH 2/7] updates for v0.4.0 --- apps/vyper/src/app/utils/compiler.tsx | 40 ++++++++++++++--------- apps/vyper/src/app/utils/remix-client.tsx | 6 ++-- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/apps/vyper/src/app/utils/compiler.tsx b/apps/vyper/src/app/utils/compiler.tsx index a1d4916f0e1..1b196050c82 100644 --- a/apps/vyper/src/app/utils/compiler.tsx +++ b/apps/vyper/src/app/utils/compiler.tsx @@ -48,6 +48,7 @@ export function normalizeContractPath(contractPath: string): string[] { function parseErrorString(errorString) { // Split the string into lines console.log(errorString) + return let lines = errorString.trim().split('\n') // Extract the line number and message let message = errorString.trim() @@ -141,27 +142,32 @@ const compileReturnType = (output, contract) => { return result } -const fixContractContent = (content: string) => { - const pragmaRegex = /#\s*pragma\s+[@]*version\s+([\^~<>!=^]+)\s*(\d+\.\d+\.\d+)/ - if (content.length === 0) return +const updatePragmaDeclaration = (content: string) => { + const pragmaRegex = /#\s*pragma\s+[@]*version\s+([~<>!=^]+)\s*(\d+\.\d+\.\d+)/ + const oldPragmaRegex = /#\s*pragma\s+[@]*version\s+([\^^]+)\s*(\d+\.\d+\.\d+)/ + const oldPragmaDeclaration = ['# pragma version ^0.2.16', '# pragma version ^0.3.10', '#pragma version ^0.2.16', '#pragma version ^0.3.10'] const pragmaFound = content.match(pragmaRegex) - const wrongpragmaFound = content.includes('# pragma version ^0.3.10') - const evmVerFound = content.includes('#pragma evm-version cancun') + const oldPragmaFound = content.match(oldPragmaRegex) + const pragma = '# pragma version ~=0.4.0' - const evmVer = '# pragma evm-version cancun' - // if (evmVerFound === false) { - // content = `${evmVer}\n${content}` - // } - if (wrongpragmaFound === true) { - content = content.replace('# pragma version ^0.3.10', '') + if (oldPragmaFound) { + console.log('found old pragma') + // oldPragmaDeclaration.forEach(declaration => { + // content = content.replace(declaration, '# pragma version ~=0.4.0') + // }) } if (!pragmaFound) { - content = `${pragma}\n${content}` + content = `${pragma}\n\n${content}` } return content } +const fixContractContent = (content: string) => { + if (content.length === 0) return + return updatePragmaDeclaration(content) +} + /** * Compile the a contract * @param url The url of the compiler @@ -177,7 +183,7 @@ export async function compile(url: string, contract: Contract): Promise { } const cleanedUpContent = fixContractContent(contract.content) - console.log('cleanedUp', cleanedUpContent) + // console.log('cleanedUp', cleanedUpContent) let contractName = contract['name'] const compilePackage = { @@ -187,6 +193,7 @@ export async function compile(url: string, contract: Contract): Promise { } } console.log(compilePackage) + let response = await axios.post(`${url}compile`, compilePackage ) if (response.status === 404) { @@ -197,9 +204,11 @@ export async function compile(url: string, contract: Contract): Promise { } const compileCode = response.data + console.log('compileCode', compileCode) contractName = null response = null let result: any + let intermediateError const status = await (await axios.get(url + 'status/' + compileCode , { method: 'Get' @@ -210,12 +219,13 @@ export async function compile(url: string, contract: Contract): Promise { })).data return result - } else if (status !== 'SUCCESS') { + } else if (status === 'FAILED') { const intermediate = await(await axios.get(url + 'exceptions/' + compileCode , { method: 'Get' })).data - result = parseErrorString(intermediate) console.log('Errors found', intermediate) + result = parseErrorString(intermediate) + intermediateError = intermediate return result } await new Promise((resolve) => setTimeout(() => resolve({}), 3000)) diff --git a/apps/vyper/src/app/utils/remix-client.tsx b/apps/vyper/src/app/utils/remix-client.tsx index c2d57f64f69..2c534a8cc71 100644 --- a/apps/vyper/src/app/utils/remix-client.tsx +++ b/apps/vyper/src/app/utils/remix-client.tsx @@ -83,11 +83,11 @@ export class RemixClient extends PluginClient { try { // @ts-ignore - this.call('notification', 'toast', 'cloning Snekmate Vyper repository...') + this.call('notification', 'toast', 'cloning Snekmate Vyper repository...') await this.call( 'dgitApi', 'clone', - {url: 'https://github.com/pcaversaccio/snekmate', token: null, branch: 'main', singleBranch: false, workspaceName: 'snekmate'}, + { url: 'https://github.com/vyperlang/vyper', token: null, branch: 'master', singleBranch: false, workspaceName: 'vyper' }, ) await this.call( @@ -99,7 +99,7 @@ export class RemixClient extends PluginClient { refresh: true, } ) - + this.call( // @ts-ignore 'notification', From f4d70d4a09f60b0347e201cd36076cc89f32260d Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 16 Sep 2024 14:55:18 +0100 Subject: [PATCH 3/7] update default versions. clone from vyperlang --- apps/vyper/src/app/utils/compiler.tsx | 6 +++--- apps/vyper/src/app/utils/remix-client.tsx | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/vyper/src/app/utils/compiler.tsx b/apps/vyper/src/app/utils/compiler.tsx index 1b196050c82..834eb3a18ae 100644 --- a/apps/vyper/src/app/utils/compiler.tsx +++ b/apps/vyper/src/app/utils/compiler.tsx @@ -111,10 +111,10 @@ const compileReturnType = (output, contract) => { const normal = normalizeContractPath(contract)[2] const abi = temp[normal]['abi'] const evm = _.merge(temp[normal]['evm']) - const dpb = evm.deployedBytecode + const depByteCode = evm.deployedBytecode const runtimeBytecode = evm.bytecode const methodIdentifiers = evm.methodIdentifiers - const version = output?.compilers[0]?.version ?? '0.3.10' + const version = output?.compilers[0]?.version ?? '0.4.0' const optimized = output?.compilers[0]?.settings?.optimize ?? true const evmVersion = '' @@ -131,7 +131,7 @@ const compileReturnType = (output, contract) => { } = { contractName: normal, abi, - bytecode: dpb, + bytecode: depByteCode, runtimeBytecode, ir: '', methodIdentifiers, diff --git a/apps/vyper/src/app/utils/remix-client.tsx b/apps/vyper/src/app/utils/remix-client.tsx index 2c534a8cc71..0557149b1e7 100644 --- a/apps/vyper/src/app/utils/remix-client.tsx +++ b/apps/vyper/src/app/utils/remix-client.tsx @@ -90,15 +90,15 @@ export class RemixClient extends PluginClient { { url: 'https://github.com/vyperlang/vyper', token: null, branch: 'master', singleBranch: false, workspaceName: 'vyper' }, ) - await this.call( - 'dgitApi', - 'checkout', - { - ref:'v0.0.5', - force: true, - refresh: true, - } - ) + // await this.call( + // 'dgitApi', + // 'checkout', + // { + // ref:'v0.0.5', + // force: true, + // refresh: true, + // } + // ) this.call( // @ts-ignore From b44fd089a369c5ebfb2d61b31133a60af871d8ea Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 16 Sep 2024 15:43:25 +0100 Subject: [PATCH 4/7] fix vyper test --- .../remix-ide-e2e/src/tests/vyper_api.test.ts | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/vyper_api.test.ts b/apps/remix-ide-e2e/src/tests/vyper_api.test.ts index 717edd43c9a..ca6810a6ade 100644 --- a/apps/remix-ide-e2e/src/tests/vyper_api.test.ts +++ b/apps/remix-ide-e2e/src/tests/vyper_api.test.ts @@ -27,7 +27,7 @@ module.exports = { .frameParent() .clickLaunchIcon('filePanel') .waitForElementVisible({ - selector: "//*[@data-id='workspacesSelect' and contains(.,'snekmate')]", + selector: "//*[@data-id='workspacesSelect' and contains(.,'vyper')]", locateStrategy: 'xpath', timeout: 120000 }) @@ -36,33 +36,33 @@ module.exports = { locateStrategy: 'xpath', timeout: 120000 }) + .openFile('examples') + .openFile('examples/auctions') + .openFile('examples/auctions/blind_auction.vy') }, - // 'Add vyper file to run tests #group1': function (browser: NightwatchBrowser) { - // browser.addFile('TestBallot.sol', sources[0]['TestBallot.sol']) + + // '@sources': () => sources, + // 'Context menu click to compile blind_auction should succeed #group1': function (browser: NightwatchBrowser) { + // browser + // // .click('*[data-id="treeViewLitreeViewItemblind_auction.vy"]') + // // .rightClick('*[data-id="treeViewLitreeViewItemblind_auction.vy"]') + // // .waitForElementPresent('[data-id="contextMenuItemvyper"]') + // // .click('[data-id="contextMenuItemvyper"]') + // .clickLaunchIcon('vyper') + // // @ts-ignore + // .frame(0) + // .waitForElementVisible({ + // selector:'[data-id="compilation-details"]', + // timeout: 120000 + // }) + // .click('[data-id="compilation-details"]') + // .frameParent() + // .waitForElementVisible('[data-id="copy-abi"]') + // .waitForElementVisible({ + // selector: "//*[@class='variable-value' and contains(.,'highestBidder')]", + // locateStrategy: 'xpath', + // }) // }, - '@sources': () => sources, - 'Context menu click to compile blind_auction should succeed #group1': function (browser: NightwatchBrowser) { - browser - .addFileSnekmate('blind_auction.vy', sources[0]['blindAuction']) - .click('*[data-id="treeViewLitreeViewItemblind_auction.vy"]') - .rightClick('*[data-id="treeViewLitreeViewItemblind_auction.vy"]') - .waitForElementPresent('[data-id="contextMenuItemvyper"]') - .click('[data-id="contextMenuItemvyper"]') - .clickLaunchIcon('vyper') - // @ts-ignore - .frame(0) - .waitForElementVisible({ - selector:'[data-id="compilation-details"]', - timeout: 120000 - }) - .click('[data-id="compilation-details"]') - .frameParent() - .waitForElementVisible('[data-id="copy-abi"]') - .waitForElementVisible({ - selector: "//*[@class='variable-value' and contains(.,'highestBidder')]", - locateStrategy: 'xpath', - }) - }, 'Compile blind_auction should success #group1': function (browser: NightwatchBrowser) { browser @@ -145,32 +145,32 @@ module.exports = { }) }, - 'Compile Ownable contract from snekmate #group1': function (browser: NightwatchBrowser) { - let contractAddress - browser - .frameParent() - .clickLaunchIcon('filePanel') - .switchWorkspace('snekmate') - .openFile('src') - .openFile('src/snekmate') - .openFile('src/snekmate/auth') - .openFile('src/snekmate/auth/Ownable.vy') - .rightClick('*[data-id="treeViewLitreeViewItemsrc/snekmate/auth/Ownable.vy"]') - .waitForElementVisible('*[data-id="contextMenuItemvyper"]') - .click('*[data-id="contextMenuItemvyper"]') - .clickLaunchIcon('vyper') - // @ts-ignore - .frame(0) - .click('[data-id="compile"]') - .waitForElementVisible({ - selector:'[data-id="compilation-details"]', - timeout: 60000 - }) - .click('[data-id="compilation-details"]') - .frameParent() - .waitForElementVisible('[data-id="copy-abi"]') - .end() - } + // 'Compile Ownable contract from snekmate #group1': function (browser: NightwatchBrowser) { + // let contractAddress + // browser + // .frameParent() + // .clickLaunchIcon('filePanel') + // .switchWorkspace('vyper') + // .openFile('src') + // .openFile('src/snekmate') + // .openFile('src/snekmate/auth') + // .openFile('src/snekmate/auth/Ownable.vy') + // .rightClick('*[data-id="treeViewLitreeViewItemsrc/snekmate/auth/Ownable.vy"]') + // .waitForElementVisible('*[data-id="contextMenuItemvyper"]') + // .click('*[data-id="contextMenuItemvyper"]') + // .clickLaunchIcon('vyper') + // // @ts-ignore + // .frame(0) + // .click('[data-id="compile"]') + // .waitForElementVisible({ + // selector:'[data-id="compilation-details"]', + // timeout: 60000 + // }) + // .click('[data-id="compilation-details"]') + // .frameParent() + // .waitForElementVisible('[data-id="copy-abi"]') + // .end() + // } } const testContract = ` @@ -384,6 +384,6 @@ def auctionEnd(): # Transfer funds to beneficiary send(self.beneficiary, self.highestBid) -`} +` } } ] From f1c6b388738a3f6c9f16fd4efb0c198ddfc0503d Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 19 Sep 2024 11:45:49 +0100 Subject: [PATCH 5/7] temp fix for error cards --- apps/vyper/src/app/utils/compiler.tsx | 37 +++++++++++++++------------ 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/apps/vyper/src/app/utils/compiler.tsx b/apps/vyper/src/app/utils/compiler.tsx index 834eb3a18ae..ad204dc4076 100644 --- a/apps/vyper/src/app/utils/compiler.tsx +++ b/apps/vyper/src/app/utils/compiler.tsx @@ -45,24 +45,31 @@ export function normalizeContractPath(contractPath: string): string[] { return [folders,resultingPath, filename] } -function parseErrorString(errorString) { +function parseErrorString(errorStructure: string[]) { // Split the string into lines - console.log(errorString) - return - let lines = errorString.trim().split('\n') - // Extract the line number and message - let message = errorString.trim() - let targetLine = lines[2].split(',') - let tline = lines[2].trim().split(' ')[1].split(':') + console.log(errorStructure) + let errorType = '' + let message = '' + let tline = '' + errorStructure.forEach(errorMsg => { + const choppedup = errorMsg.split(': ') + errorType = choppedup[0].trim().split('\n')[1] + message = choppedup[1] + if (errorStructure.length > 2) { + console.log(choppedup[2].split(',')[1]) + } + console.log(choppedup) + }) + let lines = errorStructure[0].trim().split('\n') const errorObject = { status: 'failed', - message: message, - column: tline[1], - line: tline[0] + message: `${errorType} - ${message}`, + column: '', + line: '' } message = null - targetLine = null + // targetLine = null lines = null tline = null return errorObject @@ -152,10 +159,10 @@ const updatePragmaDeclaration = (content: string) => { const pragma = '# pragma version ~=0.4.0' if (oldPragmaFound) { - console.log('found old pragma') // oldPragmaDeclaration.forEach(declaration => { - // content = content.replace(declaration, '# pragma version ~=0.4.0') + // content = content.replace(declaration, '# pragma version >0.3.10') // }) + return content } if (!pragmaFound) { content = `${pragma}\n\n${content}` @@ -183,7 +190,6 @@ export async function compile(url: string, contract: Contract): Promise { } const cleanedUpContent = fixContractContent(contract.content) - // console.log('cleanedUp', cleanedUpContent) let contractName = contract['name'] const compilePackage = { @@ -204,7 +210,6 @@ export async function compile(url: string, contract: Contract): Promise { } const compileCode = response.data - console.log('compileCode', compileCode) contractName = null response = null let result: any From e2caa29579efdc18ad05f6dd86e6c4c2eaf5cc0d Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 19 Sep 2024 12:59:40 +0100 Subject: [PATCH 6/7] fix vyper e2e --- apps/remix-ide-e2e/src/tests/vyper_api.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/remix-ide-e2e/src/tests/vyper_api.test.ts b/apps/remix-ide-e2e/src/tests/vyper_api.test.ts index ca6810a6ade..e38583a9ae2 100644 --- a/apps/remix-ide-e2e/src/tests/vyper_api.test.ts +++ b/apps/remix-ide-e2e/src/tests/vyper_api.test.ts @@ -67,6 +67,7 @@ module.exports = { 'Compile blind_auction should success #group1': function (browser: NightwatchBrowser) { browser // @ts-ignore + .clickLaunchIcon('vyper') .frame(0) .click('[data-id="compile"]') .waitForElementVisible({ @@ -209,7 +210,7 @@ const sources = [{ 'blindAuction' : { content: ` # Blind Auction. Adapted to Vyper from [Solidity by Example](https://github.com/ethereum/solidity/blob/develop/docs/solidity-by-example.rst#blind-auction-1) -#pragma version ^0.3.10 +#pragma version >0.3.10 struct Bid: blindedBid: bytes32 From fc19b90e46f965ae5b442b1774b793c291a48650 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 19 Sep 2024 16:53:59 +0100 Subject: [PATCH 7/7] cleanup --- apps/vyper/src/app/utils/compiler.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/apps/vyper/src/app/utils/compiler.tsx b/apps/vyper/src/app/utils/compiler.tsx index ad204dc4076..e48d41e3b52 100644 --- a/apps/vyper/src/app/utils/compiler.tsx +++ b/apps/vyper/src/app/utils/compiler.tsx @@ -47,7 +47,6 @@ export function normalizeContractPath(contractPath: string): string[] { function parseErrorString(errorStructure: string[]) { // Split the string into lines - console.log(errorStructure) let errorType = '' let message = '' let tline = '' @@ -55,10 +54,10 @@ function parseErrorString(errorStructure: string[]) { const choppedup = errorMsg.split(': ') errorType = choppedup[0].trim().split('\n')[1] message = choppedup[1] - if (errorStructure.length > 2) { - console.log(choppedup[2].split(',')[1]) - } - console.log(choppedup) + // if (errorStructure.length > 2) { + // console.log(choppedup[2].split(',')[1]) + // } + // console.log(choppedup) }) let lines = errorStructure[0].trim().split('\n') @@ -198,7 +197,6 @@ export async function compile(url: string, contract: Contract): Promise { [contractName] : { content : cleanedUpContent } } } - console.log(compilePackage) let response = await axios.post(`${url}compile`, compilePackage ) @@ -228,7 +226,7 @@ export async function compile(url: string, contract: Contract): Promise { const intermediate = await(await axios.get(url + 'exceptions/' + compileCode , { method: 'Get' })).data - console.log('Errors found', intermediate) + // console.log('Errors found', intermediate) result = parseErrorString(intermediate) intermediateError = intermediate return result