fix abi and bytecode copy and presentation

pull/4182/head
Joseph Izang 1 year ago
parent ae91d82a78
commit 218b69709d
  1. 8
      apps/vyper/src/app/app.tsx
  2. 28
      apps/vyper/src/app/components/CompilerButton.tsx
  3. 27
      apps/vyper/src/app/components/VyperResult.tsx
  4. 4
      apps/vyper/src/app/utils/compiler.tsx
  5. 8
      apps/vyper/src/app/utils/remix-client.tsx

@ -1,6 +1,6 @@
import React, {useState, useEffect} from 'react' import React, {useState, useEffect} from 'react'
import {VyperCompilationOutput, remixClient, toStandardOutput} from './utils' import {VyperCompilationOutput, normalizeContractPath, remixClient, toStandardOutput} from './utils'
import {CompilationResult} from '@remixproject/plugin-api' import {CompilationResult} from '@remixproject/plugin-api'
// Components // Components
@ -13,7 +13,6 @@ import ToggleButton from 'react-bootstrap/ToggleButton'
import Button from 'react-bootstrap/Button' import Button from 'react-bootstrap/Button'
import './app.css' import './app.css'
import { VyperCompilationResultType } from './utils/types'
interface AppState { interface AppState {
status: 'idle' | 'inProgress' status: 'idle' | 'inProgress'
@ -34,7 +33,7 @@ const App: React.FC = () => {
environment: 'local', environment: 'local',
localUrl: 'http://localhost:8000/' localUrl: 'http://localhost:8000/'
}) })
const [compilerResponse, setCompilerResponse] = useState<any>({})
useEffect(() => { useEffect(() => {
async function start() { async function start() {
@ -100,8 +99,9 @@ const App: React.FC = () => {
setOutput={(name, update) => setOutput({...output, [name]: update})} setOutput={(name, update) => setOutput({...output, [name]: update})}
/> />
</div> </div>
<article id="result" className="px-2"> <article id="result" className="px-2">
<VyperResult output={contract ? output[contract] : undefined} /> {Object.keys(output).length > 0 ? <VyperResult output={ output} themeColor={remixClient.checkActiveTheme()} /> : null}
</article> </article>
</section> </section>
</main> </main>

@ -1,11 +1,13 @@
import React from 'react' import React from 'react'
import {isVyper, compile, toStandardOutput, VyperCompilationOutput, isCompilationError, remixClient} from '../utils' import {isVyper, compile, toStandardOutput, VyperCompilationOutput, isCompilationError, remixClient, normalizeContractPath} from '../utils'
import Button from 'react-bootstrap/Button' import Button from 'react-bootstrap/Button'
import _ from 'lodash'
import { runtime } from 'webpack'
interface Props { interface Props {
compilerUrl: string compilerUrl: string
contract?: string contract?: string
setOutput: (name: string, output: VyperCompilationOutput) => void setOutput: (name: string, output: any) => void
} }
function CompilerButton({contract, setOutput, compilerUrl}: Props) { function CompilerButton({contract, setOutput, compilerUrl}: Props) {
@ -40,8 +42,26 @@ function CompilerButton({contract, setOutput, compilerUrl}: Props) {
setOutput(_contract.name, {status: 'failed', message: e.message}) setOutput(_contract.name, {status: 'failed', message: e.message})
return return
} }
setOutput(_contract.name, output) const compileReturnType = () => {
// setCompilerResponse(output) const t: any = toStandardOutput(contract, output)
const temp = _.merge(t['contracts'][contract])
const normal = normalizeContractPath(contract)[2]
console.log(normal)
const abi = temp[normal]['abi']
const evm = _.merge(temp[normal]['evm'])
const dpb = evm.deployedBytecode
const runtimeBytecode = evm.bytecode
const result = {
contractName: normal,
abi: abi,
bytecode: dpb,
runtimeBytecode: runtimeBytecode,
ir: ''
}
return result
}
setOutput(_contract.name, compileReturnType())
// ERROR // ERROR
if (isCompilationError(output)) { if (isCompilationError(output)) {

@ -3,13 +3,14 @@ import {VyperCompilationOutput, isCompilationError} from '../utils'
import Tabs from 'react-bootstrap/Tabs' import Tabs from 'react-bootstrap/Tabs'
import Tab from 'react-bootstrap/Tab' import Tab from 'react-bootstrap/Tab'
import Button from 'react-bootstrap/Button' import Button from 'react-bootstrap/Button'
import JSONTree from 'react-json-view' import JSONTree, { ThemeKeys } from 'react-json-view'
import ReactJson from 'react-json-view' import ReactJson from 'react-json-view'
import {CopyToClipboard} from '@remix-ui/clipboard' import {CopyToClipboard} from '@remix-ui/clipboard'
import { VyperCompilationResult } from '../utils/types' import { VyperCompilationResult } from '../utils/types'
interface VyperResultProps { interface VyperResultProps {
output?: VyperCompilationOutput output?: any
themeColor?: string
} }
export type ExampleContract = { export type ExampleContract = {
@ -17,7 +18,7 @@ export type ExampleContract = {
address: string address: string
} }
function VyperResult({ output }: VyperResultProps) { function VyperResult({ output, themeColor }: VyperResultProps) {
const [active, setActive] = useState<keyof VyperCompilationResult>('abi') const [active, setActive] = useState<keyof VyperCompilationResult>('abi')
if (!output) if (!output)
@ -49,36 +50,36 @@ function VyperResult({ output }: VyperResultProps) {
return ( return (
<Tabs id="result" activeKey={active} onSelect={(key: any) => setActive(key)}> <Tabs id="result" activeKey={active} onSelect={(key: any) => setActive(key)}>
<Tab eventKey="abi" title="ABI"> <Tab eventKey="abi" title="ABI">
<CopyToClipboard getContent={() => JSON.stringify(output.abi)}> <CopyToClipboard getContent={() => JSON.stringify(Object.values(output)[0]['abi'])}>
<Button variant="info" className="copy" data-id="copy-abi"> <Button variant="info" className="copy" data-id="copy-abi">
Copy ABI Copy ABI
</Button> </Button>
</CopyToClipboard> </CopyToClipboard>
<JSONTree src={output.abi} /> <JSONTree src={Object.values(output)[0]['abi']} theme={themeColor as any}/>
</Tab> </Tab>
<Tab eventKey="bytecode" title="Bytecode"> <Tab eventKey="bytecode" title="Bytecode">
<CopyToClipboard getContent={() => output.bytecode}> <CopyToClipboard getContent={() => JSON.stringify(Object.values(output)[0]['bytecode'].object.toString())}>
<Button variant="info" className="copy"> <Button variant="info" className="copy">
Copy Bytecode Copy Bytecode
</Button> </Button>
</CopyToClipboard> </CopyToClipboard>
<textarea defaultValue={output.bytecode}></textarea> <textarea defaultValue={Object.values(output)[0]['bytecode'].object.toString()}></textarea>
</Tab> </Tab>
<Tab eventKey="bytecode_runtime" title="Runtime Bytecode"> <Tab eventKey="bytecode_runtime" title="Runtime Bytecode">
<CopyToClipboard getContent={() => output.bytecode_runtime}> <CopyToClipboard getContent={() => JSON.stringify(Object.values(output)[0]['runtimeBytecode'].object.toString())}>
<Button variant="info" className="copy"> <Button variant="info" className="copy">
Copy Runtime Bytecode Copy Runtime Bytecode
</Button> </Button>
</CopyToClipboard> </CopyToClipboard>
<textarea defaultValue={output.bytecode_runtime}></textarea> <textarea defaultValue={Object.values(output)[0]['runtimeBytecode'].object.toString()}></textarea>
</Tab> </Tab>
<Tab eventKey="ir" title="LLL"> <Tab eventKey="ir" title="LLL">
<CopyToClipboard getContent={() => output.ir}> <CopyToClipboard getContent={() => JSON.stringify(Object.values(output)[0]['ir'])}>
<Button variant="info" className="copy"> <Button disabled={Object.values(output)[0]['ir'].length <= 1} variant="info" className="copy">
Copy LLL Code {Object.values(output)[0]['ir'].length > 1 ? 'Copy LLL Code' : 'Nothing to copy yet'}
</Button> </Button>
</CopyToClipboard> </CopyToClipboard>
<textarea defaultValue={output.ir}></textarea> <textarea defaultValue={Object.values(output)[0]['ir'].toString()}></textarea>
</Tab> </Tab>
</Tabs> </Tabs>
) )

@ -10,6 +10,7 @@ export interface Contract {
export interface VyperCompilationResult { export interface VyperCompilationResult {
status: 'success' status: 'success'
bytecode: string bytecode: string
contractName?: string
bytecode_runtime: string bytecode_runtime: string
abi: ABIDescription[] abi: ABIDescription[]
ir: string ir: string
@ -102,7 +103,7 @@ export async function compile(url: string, contract: Contract): Promise<VyperCom
* @param compilationResult Result returned by the compiler * @param compilationResult Result returned by the compiler
*/ */
export function toStandardOutput(fileName: string, compilationResult: VyperCompilationResultType): CompilationResult { export function toStandardOutput(fileName: string, compilationResult: VyperCompilationResultType): CompilationResult {
const contractName = fileName.split('/').slice(-1)[0].split('.')[0] const contractName = normalizeContractPath(fileName)[2]
const compiledAbi = compilationResult['contractTypes'][contractName].abi const compiledAbi = compilationResult['contractTypes'][contractName].abi
const deployedBytecode = compilationResult['contractTypes'][contractName].deploymentBytecode.bytecode.replace('0x', '') const deployedBytecode = compilationResult['contractTypes'][contractName].deploymentBytecode.bytecode.replace('0x', '')
const bytecode = compilationResult['contractTypes'][contractName].runtimeBytecode.bytecode.replace('0x', '') const bytecode = compilationResult['contractTypes'][contractName].runtimeBytecode.bytecode.replace('0x', '')
@ -123,6 +124,7 @@ export function toStandardOutput(fileName: string, compilationResult: VyperCompi
// The Ethereum Contract ABI. If empty, it is represented as an empty array. // The Ethereum Contract ABI. If empty, it is represented as an empty array.
// See https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI // See https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
abi: compiledAbi, abi: compiledAbi,
contractName: contractName,
evm: { evm: {
bytecode: { bytecode: {
linkReferences: {}, linkReferences: {},

@ -4,6 +4,7 @@ import {createClient} from '@remixproject/plugin-webview'
import {PluginClient} from '@remixproject/plugin' import {PluginClient} from '@remixproject/plugin'
import {Contract} from './compiler' import {Contract} from './compiler'
import {ExampleContract} from '../components/VyperResult' import {ExampleContract} from '../components/VyperResult'
import { ThemeKeys } from 'react-json-view'
export class RemixClient extends PluginClient { export class RemixClient extends PluginClient {
private client = createClient<Api, Readonly<RemixApi>>(this) private client = createClient<Api, Readonly<RemixApi>>(this)
@ -66,6 +67,13 @@ export class RemixClient extends PluginClient {
this.client.emit('statusChanged', status) this.client.emit('statusChanged', status)
} }
checkActiveTheme() {
const active = this.client.call('theme', 'currentTheme')
if (active === 'dark') {
return 'monokai' as any
}
}
/** Highlight a part of the editor */ /** Highlight a part of the editor */
async highlight(lineColumnPos: HighlightPosition, name: string, message: string) { async highlight(lineColumnPos: HighlightPosition, name: string, message: string) {
await this.client.call('editor', 'highlight', lineColumnPos, name) await this.client.call('editor', 'highlight', lineColumnPos, name)

Loading…
Cancel
Save