Merge branch 'dev' of gitlab.com:ligolang/ligo into rinderknecht@contracts
This commit is contained in:
commit
604330eab6
@ -7,6 +7,7 @@ import { AppState } from '../redux/app';
|
|||||||
import { CommandState } from '../redux/command';
|
import { CommandState } from '../redux/command';
|
||||||
import { DoneLoadingAction, LoadingState } from '../redux/loading';
|
import { DoneLoadingAction, LoadingState } from '../redux/loading';
|
||||||
import { ResultState } from '../redux/result';
|
import { ResultState } from '../redux/result';
|
||||||
|
import { Command } from '../redux/types';
|
||||||
import { OutputToolbarComponent } from './output-toolbar';
|
import { OutputToolbarComponent } from './output-toolbar';
|
||||||
|
|
||||||
const Container = styled.div<{ visible?: boolean }>`
|
const Container = styled.div<{ visible?: boolean }>`
|
||||||
@ -43,7 +44,7 @@ const CancelButton = styled.div`
|
|||||||
|
|
||||||
const Output = styled.div`
|
const Output = styled.div`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 0 0.5em 0.5em 0.5em;
|
padding: 0.5em;
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
/* This font size is used to calcuate spinner size */
|
/* This font size is used to calcuate spinner size */
|
||||||
@ -81,20 +82,18 @@ function copyOutput(el: HTMLElement | null) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function downloadOutput(el: HTMLElement | null) {
|
function downloadOutput(output: string) {
|
||||||
if (el) {
|
const anchor = document.createElement('a');
|
||||||
const anchor = document.createElement('a');
|
anchor.setAttribute(
|
||||||
anchor.setAttribute(
|
'href',
|
||||||
'href',
|
`data:text/plain;charset=utf-8,${encodeURIComponent(output)}`
|
||||||
'data:text/plain;charset=utf-8,' + encodeURIComponent(el.innerHTML)
|
);
|
||||||
);
|
anchor.setAttribute('download', 'output.txt');
|
||||||
anchor.setAttribute('download', 'output.txt');
|
|
||||||
|
|
||||||
anchor.style.display = 'none';
|
anchor.style.display = 'none';
|
||||||
document.body.appendChild(anchor);
|
document.body.appendChild(anchor);
|
||||||
anchor.click();
|
anchor.click();
|
||||||
document.body.removeChild(anchor);
|
document.body.removeChild(anchor);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const OutputTabComponent = (props: {
|
export const OutputTabComponent = (props: {
|
||||||
@ -107,6 +106,9 @@ export const OutputTabComponent = (props: {
|
|||||||
const contract = useSelector<AppState, ResultState['contract']>(
|
const contract = useSelector<AppState, ResultState['contract']>(
|
||||||
state => state.result.contract
|
state => state.result.contract
|
||||||
);
|
);
|
||||||
|
const command = useSelector<AppState, ResultState['command']>(
|
||||||
|
state => state.result.command
|
||||||
|
);
|
||||||
|
|
||||||
const loading = useSelector<AppState, LoadingState>(state => state.loading);
|
const loading = useSelector<AppState, LoadingState>(state => state.loading);
|
||||||
|
|
||||||
@ -132,10 +134,14 @@ export const OutputTabComponent = (props: {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container visible={props.selected}>
|
<Container visible={props.selected}>
|
||||||
{output.length !== 0 && (
|
{!(
|
||||||
|
loading.loading ||
|
||||||
|
output.length === 0 ||
|
||||||
|
command !== Command.Compile
|
||||||
|
) && (
|
||||||
<OutputToolbarComponent
|
<OutputToolbarComponent
|
||||||
onCopy={() => copyOutput(preRef.current)}
|
onCopy={() => copyOutput(preRef.current)}
|
||||||
onDownload={() => downloadOutput(preRef.current)}
|
onDownload={() => downloadOutput(output)}
|
||||||
></OutputToolbarComponent>
|
></OutputToolbarComponent>
|
||||||
)}
|
)}
|
||||||
<Output id="output" ref={outputRef}>
|
<Output id="output" ref={outputRef}>
|
||||||
|
@ -1,78 +1,58 @@
|
|||||||
import { faCopy, faDownload } from '@fortawesome/free-solid-svg-icons';
|
import { faCopy, faDownload } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import { AppState } from '../redux/app';
|
||||||
|
import { ResultState } from '../redux/result';
|
||||||
|
import { Item, Toolbar } from './toolbar';
|
||||||
import { Tooltip } from './tooltip';
|
import { Tooltip } from './tooltip';
|
||||||
|
|
||||||
const Container = styled.div`
|
const Divider = styled.div`
|
||||||
display: flex;
|
display: block;
|
||||||
justify-content: flex-start;
|
background-color: rgba(0, 0, 0, 0.12);
|
||||||
padding: 0.2em 0.5em;
|
height: 20px;
|
||||||
z-index: 3;
|
width: 1px;
|
||||||
|
margin: 0 3px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Action = styled.div`
|
const Link = styled.a`
|
||||||
z-index: 3;
|
font-size: 0.8em;
|
||||||
position: relative;
|
color: var(--blue);
|
||||||
margin: 4px 6px;
|
opacity: 1;
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
opacity: 0.5;
|
|
||||||
color: #444;
|
|
||||||
|
|
||||||
::before {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
z-index: -1;
|
|
||||||
bottom: -4px;
|
|
||||||
left: -4px;
|
|
||||||
right: -4px;
|
|
||||||
top: -4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: none;
|
|
||||||
box-sizing: border-box;
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0);
|
|
||||||
transition-property: transform, opacity;
|
|
||||||
transition-duration: 0.15s;
|
|
||||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
:hover::before {
|
|
||||||
background-color: rgba(32, 33, 36, 0.059);
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
:hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const OutputToolbarComponent = (props: {
|
export const OutputToolbarComponent = (props: {
|
||||||
onCopy?: () => void;
|
onCopy?: () => void;
|
||||||
onDownload?: () => void;
|
onDownload?: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
|
const output = useSelector<AppState, ResultState['output']>(
|
||||||
|
state => state.result.output
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Toolbar>
|
||||||
<Action onClick={() => props.onCopy && props.onCopy()}>
|
<Item onClick={() => props.onCopy && props.onCopy()}>
|
||||||
<FontAwesomeIcon icon={faCopy}></FontAwesomeIcon>
|
<FontAwesomeIcon icon={faCopy}></FontAwesomeIcon>
|
||||||
<Tooltip>Copy</Tooltip>
|
<Tooltip>Copy</Tooltip>
|
||||||
</Action>
|
</Item>
|
||||||
<Action onClick={() => props.onDownload && props.onDownload()}>
|
<Item onClick={() => props.onDownload && props.onDownload()}>
|
||||||
<FontAwesomeIcon icon={faDownload}></FontAwesomeIcon>
|
<FontAwesomeIcon icon={faDownload}></FontAwesomeIcon>
|
||||||
<Tooltip>Download</Tooltip>
|
<Tooltip>Download</Tooltip>
|
||||||
</Action>
|
</Item>
|
||||||
</Container>
|
<Divider></Divider>
|
||||||
|
<Item>
|
||||||
|
<Link
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href={`https://try-michelson.tzalpha.net/?source=${encodeURIComponent(
|
||||||
|
output
|
||||||
|
)}`}
|
||||||
|
>
|
||||||
|
View in Try-Michelson IDE
|
||||||
|
</Link>
|
||||||
|
</Item>
|
||||||
|
</Toolbar>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
65
tools/webide/packages/client/src/components/toolbar.tsx
Normal file
65
tools/webide/packages/client/src/components/toolbar.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.2em 0.5em;
|
||||||
|
z-index: 3;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Group = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Item = styled.div`
|
||||||
|
z-index: 3;
|
||||||
|
position: relative;
|
||||||
|
margin: 4px 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
opacity: 0.5;
|
||||||
|
color: #444;
|
||||||
|
|
||||||
|
::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
bottom: -4px;
|
||||||
|
left: -4px;
|
||||||
|
right: -4px;
|
||||||
|
top: -4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0);
|
||||||
|
transition-property: transform, opacity;
|
||||||
|
transition-duration: 0.15s;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
:hover::before {
|
||||||
|
background-color: rgba(32, 33, 36, 0.059);
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Toolbar = (props: any) => {
|
||||||
|
return <Container>{props.children}</Container>;
|
||||||
|
};
|
@ -48,7 +48,7 @@
|
|||||||
--font_ghost_weight: 700;
|
--font_ghost_weight: 700;
|
||||||
--font_ghost_color: rgba(153, 153, 153, 0.5); /* or #CFCFCF */
|
--font_ghost_color: rgba(153, 153, 153, 0.5); /* or #CFCFCF */
|
||||||
|
|
||||||
--content_height: 85vh;
|
--content_height: 84vh;
|
||||||
|
|
||||||
--tooltip_foreground: white;
|
--tooltip_foreground: white;
|
||||||
--tooltip_background: rgba(0, 0, 0, 0.75) /*#404040*/;
|
--tooltip_background: rgba(0, 0, 0, 0.75) /*#404040*/;
|
||||||
|
@ -4,6 +4,7 @@ import { compileContract, getErrorMessage } from '../../services/api';
|
|||||||
import { AppState } from '../app';
|
import { AppState } from '../app';
|
||||||
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||||
import { ChangeOutputAction } from '../result';
|
import { ChangeOutputAction } from '../result';
|
||||||
|
import { Command } from '../types';
|
||||||
import { CancellableAction } from './cancellable';
|
import { CancellableAction } from './cancellable';
|
||||||
|
|
||||||
export class CompileAction extends CancellableAction {
|
export class CompileAction extends CancellableAction {
|
||||||
@ -24,13 +25,18 @@ export class CompileAction extends CancellableAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({ ...new ChangeOutputAction(michelsonCode.result) });
|
dispatch({
|
||||||
|
...new ChangeOutputAction(michelsonCode.result, Command.Compile)
|
||||||
|
});
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
...new ChangeOutputAction(`Error: ${getErrorMessage(ex)}`)
|
...new ChangeOutputAction(
|
||||||
|
`Error: ${getErrorMessage(ex)}`,
|
||||||
|
Command.Compile
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,12 @@ import { Tezos } from '@taquito/taquito';
|
|||||||
import { TezBridgeSigner } from '@taquito/tezbridge-signer';
|
import { TezBridgeSigner } from '@taquito/tezbridge-signer';
|
||||||
import { Dispatch } from 'redux';
|
import { Dispatch } from 'redux';
|
||||||
|
|
||||||
import { compileContract, compileExpression, deploy, getErrorMessage } from '../../services/api';
|
import { compileContract, compileStorage, deploy, getErrorMessage } from '../../services/api';
|
||||||
import { AppState } from '../app';
|
import { AppState } from '../app';
|
||||||
import { MichelsonFormat } from '../compile';
|
import { MichelsonFormat } from '../compile';
|
||||||
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||||
import { ChangeContractAction, ChangeOutputAction } from '../result';
|
import { ChangeContractAction, ChangeOutputAction } from '../result';
|
||||||
|
import { Command } from '../types';
|
||||||
import { CancellableAction } from './cancellable';
|
import { CancellableAction } from './cancellable';
|
||||||
|
|
||||||
Tezos.setProvider({
|
Tezos.setProvider({
|
||||||
@ -32,8 +33,10 @@ export class DeployAction extends CancellableAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch({ ...new UpdateLoadingAction('Compiling storage...') });
|
dispatch({ ...new UpdateLoadingAction('Compiling storage...') });
|
||||||
const michelsonStorage = await compileExpression(
|
const michelsonStorage = await compileStorage(
|
||||||
editorState.language,
|
editorState.language,
|
||||||
|
editorState.code,
|
||||||
|
deployState.entrypoint,
|
||||||
deployState.storage,
|
deployState.storage,
|
||||||
MichelsonFormat.Json
|
MichelsonFormat.Json
|
||||||
);
|
);
|
||||||
@ -83,13 +86,18 @@ export class DeployAction extends CancellableAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({ ...new ChangeContractAction(contract.address) });
|
dispatch({
|
||||||
|
...new ChangeContractAction(contract.address, Command.Deploy)
|
||||||
|
});
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
...new ChangeOutputAction(`Error: ${getErrorMessage(ex)}`)
|
...new ChangeOutputAction(
|
||||||
|
`Error: ${getErrorMessage(ex)}`,
|
||||||
|
Command.Deploy
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { dryRun, getErrorMessage } from '../../services/api';
|
|||||||
import { AppState } from '../app';
|
import { AppState } from '../app';
|
||||||
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||||
import { ChangeOutputAction } from '../result';
|
import { ChangeOutputAction } from '../result';
|
||||||
|
import { Command } from '../types';
|
||||||
import { CancellableAction } from './cancellable';
|
import { CancellableAction } from './cancellable';
|
||||||
|
|
||||||
export class DryRunAction extends CancellableAction {
|
export class DryRunAction extends CancellableAction {
|
||||||
@ -25,13 +26,16 @@ export class DryRunAction extends CancellableAction {
|
|||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({ ...new ChangeOutputAction(result.output) });
|
dispatch({ ...new ChangeOutputAction(result.output, Command.DryRun) });
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
...new ChangeOutputAction(`Error: ${getErrorMessage(ex)}`)
|
...new ChangeOutputAction(
|
||||||
|
`Error: ${getErrorMessage(ex)}`,
|
||||||
|
Command.DryRun
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { getErrorMessage, runFunction } from '../../services/api';
|
|||||||
import { AppState } from '../app';
|
import { AppState } from '../app';
|
||||||
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||||
import { ChangeOutputAction } from '../result';
|
import { ChangeOutputAction } from '../result';
|
||||||
|
import { Command } from '../types';
|
||||||
import { CancellableAction } from './cancellable';
|
import { CancellableAction } from './cancellable';
|
||||||
|
|
||||||
export class EvaluateFunctionAction extends CancellableAction {
|
export class EvaluateFunctionAction extends CancellableAction {
|
||||||
@ -27,13 +28,18 @@ export class EvaluateFunctionAction extends CancellableAction {
|
|||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({ ...new ChangeOutputAction(result.output) });
|
dispatch({
|
||||||
|
...new ChangeOutputAction(result.output, Command.EvaluateFunction)
|
||||||
|
});
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
...new ChangeOutputAction(`Error: ${getErrorMessage(ex)}`)
|
...new ChangeOutputAction(
|
||||||
|
`Error: ${getErrorMessage(ex)}`,
|
||||||
|
Command.EvaluateFunction
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { evaluateValue, getErrorMessage } from '../../services/api';
|
|||||||
import { AppState } from '../app';
|
import { AppState } from '../app';
|
||||||
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||||
import { ChangeOutputAction } from '../result';
|
import { ChangeOutputAction } from '../result';
|
||||||
|
import { Command } from '../types';
|
||||||
import { CancellableAction } from './cancellable';
|
import { CancellableAction } from './cancellable';
|
||||||
|
|
||||||
export class EvaluateValueAction extends CancellableAction {
|
export class EvaluateValueAction extends CancellableAction {
|
||||||
@ -28,13 +29,18 @@ export class EvaluateValueAction extends CancellableAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({ ...new ChangeOutputAction(result.code) });
|
dispatch({
|
||||||
|
...new ChangeOutputAction(result.code, Command.EvaluateValue)
|
||||||
|
});
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
...new ChangeOutputAction(`Error: ${getErrorMessage(ex)}`)
|
...new ChangeOutputAction(
|
||||||
|
`Error: ${getErrorMessage(ex)}`,
|
||||||
|
Command.EvaluateValue
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,26 +1,36 @@
|
|||||||
|
import { Command } from './types';
|
||||||
|
|
||||||
export enum ActionType {
|
export enum ActionType {
|
||||||
ChangeOutput = 'result-change-output',
|
ChangeOutput = 'result-change-output',
|
||||||
ChangeContract = 'result-change-contract'
|
ChangeContract = 'result-change-contract'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResultState {
|
export interface ResultState {
|
||||||
|
command: Command;
|
||||||
output: string;
|
output: string;
|
||||||
contract: string;
|
contract: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChangeOutputAction {
|
export class ChangeOutputAction {
|
||||||
public readonly type = ActionType.ChangeOutput;
|
public readonly type = ActionType.ChangeOutput;
|
||||||
constructor(public payload: ResultState['output']) {}
|
constructor(
|
||||||
|
public output: ResultState['output'],
|
||||||
|
public command: ResultState['command']
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChangeContractAction {
|
export class ChangeContractAction {
|
||||||
public readonly type = ActionType.ChangeContract;
|
public readonly type = ActionType.ChangeContract;
|
||||||
constructor(public payload: ResultState['contract']) {}
|
constructor(
|
||||||
|
public contract: ResultState['contract'],
|
||||||
|
public command: ResultState['command']
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Action = ChangeOutputAction | ChangeContractAction;
|
type Action = ChangeOutputAction | ChangeContractAction;
|
||||||
|
|
||||||
const DEFAULT_STATE: ResultState = {
|
const DEFAULT_STATE: ResultState = {
|
||||||
|
command: Command.Compile,
|
||||||
output: '',
|
output: '',
|
||||||
contract: ''
|
contract: ''
|
||||||
};
|
};
|
||||||
@ -30,13 +40,15 @@ export default (state = DEFAULT_STATE, action: Action): ResultState => {
|
|||||||
case ActionType.ChangeOutput:
|
case ActionType.ChangeOutput:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
output: action.payload
|
output: action.output,
|
||||||
|
command: action.command
|
||||||
};
|
};
|
||||||
case ActionType.ChangeContract:
|
case ActionType.ChangeContract:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
output: DEFAULT_STATE.output,
|
output: DEFAULT_STATE.output,
|
||||||
contract: action.payload
|
contract: action.contract,
|
||||||
|
command: action.command
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
|
@ -36,6 +36,23 @@ export async function compileExpression(
|
|||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function compileStorage(
|
||||||
|
syntax: Language,
|
||||||
|
code: string,
|
||||||
|
entrypoint: string,
|
||||||
|
storage: string,
|
||||||
|
format?: string
|
||||||
|
) {
|
||||||
|
const response = await axios.post('/api/compile-storage', {
|
||||||
|
syntax,
|
||||||
|
code,
|
||||||
|
entrypoint,
|
||||||
|
storage,
|
||||||
|
format
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
export async function dryRun(
|
export async function dryRun(
|
||||||
syntax: Language,
|
syntax: Language,
|
||||||
code: string,
|
code: string,
|
||||||
|
@ -79,6 +79,19 @@ exports.verifyAllExamples = async (action, done) => {
|
|||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.verifyWithParameter = async (command, parameter, value, action, done) => {
|
||||||
|
await page.click('#command-select');
|
||||||
|
await page.click(`#${command}`);
|
||||||
|
|
||||||
|
await page.click(`#${parameter}`);
|
||||||
|
await exports.clearText(page.keyboard);
|
||||||
|
await page.keyboard.type(value);
|
||||||
|
|
||||||
|
expect(await action()).toEqual(`Error: "${parameter}" is not allowed to be empty`);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
|
||||||
exports.verifyWithBlankParameter = async (command, parameter, action, done) => {
|
exports.verifyWithBlankParameter = async (command, parameter, action, done) => {
|
||||||
await page.click('#command-select');
|
await page.click('#command-select');
|
||||||
await page.click(`#${command}`);
|
await page.click(`#${command}`);
|
||||||
|
38
tools/webide/packages/e2e/test/deploy.spec.js
Normal file
38
tools/webide/packages/e2e/test/deploy.spec.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
const commonUtils = require('./common-utils');
|
||||||
|
|
||||||
|
const API_HOST = commonUtils.API_HOST;
|
||||||
|
|
||||||
|
const runCommandAndGetOutputFor = commonUtils.runCommandAndGetOutputFor;
|
||||||
|
const clearText = commonUtils.clearText;
|
||||||
|
|
||||||
|
const COMMAND = 'deploy';
|
||||||
|
const COMMAND_ENDPOINT = 'deploy';
|
||||||
|
|
||||||
|
async function deploy() {
|
||||||
|
return await runCommandAndGetOutputFor(COMMAND, COMMAND_ENDPOINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Deploy contract', () => {
|
||||||
|
beforeAll(() => jest.setTimeout(60000));
|
||||||
|
|
||||||
|
beforeEach(async () => await page.goto(API_HOST));
|
||||||
|
|
||||||
|
it('should deploy', async done => {
|
||||||
|
expect(await deploy()).toContain('The contract was successfully deployed to the babylonnet test network.');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail to deploy contract with invalid storage', async done => {
|
||||||
|
await page.click('#command-select');
|
||||||
|
await page.click(`#deploy`);
|
||||||
|
|
||||||
|
await page.click(`#storage`);
|
||||||
|
await clearText(page.keyboard);
|
||||||
|
await page.keyboard.type('asdf');
|
||||||
|
|
||||||
|
expect(await deploy()).toContain('Error: ');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
@ -40,10 +40,12 @@ export async function deployHandler(req: Request, res: Response) {
|
|||||||
'json'
|
'json'
|
||||||
);
|
);
|
||||||
|
|
||||||
const michelsonStorage = await new LigoCompiler().compileExpression(
|
const michelsonStorage = await new LigoCompiler().compileStorage(
|
||||||
body.syntax,
|
body.syntax,
|
||||||
body.storage,
|
body.code,
|
||||||
'json'
|
body.entrypoint,
|
||||||
|
'json',
|
||||||
|
body.storage
|
||||||
);
|
);
|
||||||
|
|
||||||
await Tezos.importKey(await fetchRandomPrivateKey());
|
await Tezos.importKey(await fetchRandomPrivateKey());
|
||||||
|
@ -120,6 +120,7 @@ export class LigoCompiler {
|
|||||||
format: string
|
format: string
|
||||||
) {
|
) {
|
||||||
const { name, remove } = await this.createTemporaryFile(code);
|
const { name, remove } = await this.createTemporaryFile(code);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await this.execPromise(this.ligoCmd, [
|
const result = await this.execPromise(this.ligoCmd, [
|
||||||
'compile-contract',
|
'compile-contract',
|
||||||
@ -148,6 +149,33 @@ export class LigoCompiler {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async compileStorage(
|
||||||
|
syntax: string,
|
||||||
|
code: string,
|
||||||
|
entrypoint: string,
|
||||||
|
format: string,
|
||||||
|
storage: string
|
||||||
|
) {
|
||||||
|
const { name, remove } = await this.createTemporaryFile(code);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await this.execPromise(this.ligoCmd, [
|
||||||
|
'compile-storage',
|
||||||
|
'--michelson-format',
|
||||||
|
format,
|
||||||
|
'-s',
|
||||||
|
syntax,
|
||||||
|
name,
|
||||||
|
entrypoint,
|
||||||
|
storage
|
||||||
|
]);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} finally {
|
||||||
|
remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async dryRun(
|
async dryRun(
|
||||||
syntax: string,
|
syntax: string,
|
||||||
code: string,
|
code: string,
|
||||||
|
37
tools/webide/packages/server/test/ligo-compiler.spec.ts
Normal file
37
tools/webide/packages/server/test/ligo-compiler.spec.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { LigoCompiler } from '../src/ligo-compiler';
|
||||||
|
|
||||||
|
const PASCALIGO_CODE = `
|
||||||
|
type action is
|
||||||
|
| Increment of int
|
||||||
|
| Decrement of int
|
||||||
|
|
||||||
|
function add (const a : int ; const b : int) : int is
|
||||||
|
block { skip } with a + b
|
||||||
|
|
||||||
|
function subtract (const a : int ; const b : int) : int is
|
||||||
|
block { skip } with a - b
|
||||||
|
|
||||||
|
function main (const p : action ; const s : int) :
|
||||||
|
(list(operation) * int) is
|
||||||
|
block { skip } with ((nil : list(operation)),
|
||||||
|
case p of
|
||||||
|
| Increment(n) -> add(s, n)
|
||||||
|
| Decrement(n) -> subtract(s, n)
|
||||||
|
end)
|
||||||
|
`;
|
||||||
|
|
||||||
|
describe('Ligo compiler', () => {
|
||||||
|
it('should compile storage', async done => {
|
||||||
|
const michelsonCode = await new LigoCompiler().compileStorage(
|
||||||
|
'pascaligo',
|
||||||
|
PASCALIGO_CODE,
|
||||||
|
'main',
|
||||||
|
'json',
|
||||||
|
'0'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(michelsonCode.trim()).toEqual('{ "int": "0" }');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user