diff --git a/src/api/apollo/generated/graphql.tsx b/src/api/apollo/generated/graphql.tsx index df869866..f0b064d4 100644 --- a/src/api/apollo/generated/graphql.tsx +++ b/src/api/apollo/generated/graphql.tsx @@ -10,18 +10,55 @@ export type Scalars = { Boolean: boolean; Int: number; Float: number; + UUID: any; Version: any; Address: any; - UUID: any; ExecutionResultValue: any; RawExecutionResult: any; }; -export type ProgramError = { - __typename?: 'ProgramError'; - message: Scalars['String']; - startPosition?: Maybe; - endPosition?: Maybe; +export type Project = { + __typename?: 'Project'; + id: Scalars['UUID']; + publicId: Scalars['UUID']; + parentId?: Maybe; + title: Scalars['String']; + seed: Scalars['Int']; + version: Scalars['Version']; + persist?: Maybe; + mutable?: Maybe; + accounts?: Maybe>; + transactionTemplates?: Maybe>; + transactionExecutions?: Maybe>; + scriptTemplates?: Maybe>; + scriptExecutions?: Maybe>; +}; + +export type NewProject = { + parentId?: Maybe; + title: Scalars['String']; + seed: Scalars['Int']; + accounts?: Maybe>; + transactionTemplates?: Maybe>; + scriptTemplates?: Maybe>; +}; + +export type NewProjectTransactionTemplate = { + title: Scalars['String']; + script: Scalars['String']; +}; + +export type NewScriptExecution = { + projectId: Scalars['UUID']; + script: Scalars['String']; + arguments?: Maybe>; +}; + +export type ProgramPosition = { + __typename?: 'ProgramPosition'; + offset: Scalars['Int']; + line: Scalars['Int']; + column: Scalars['Int']; }; export type Query = { @@ -61,16 +98,27 @@ export type QueryTransactionTemplateArgs = { projectId: Scalars['UUID']; }; -export type NewProject = { - parentId?: Maybe; +export type TransactionTemplate = { + __typename?: 'TransactionTemplate'; + id: Scalars['UUID']; + index: Scalars['Int']; title: Scalars['String']; - seed: Scalars['Int']; - accounts?: Maybe>; - transactionTemplates?: Maybe>; - scriptTemplates?: Maybe>; + script: Scalars['String']; }; -export type NewProjectScriptTemplate = { +export type TransactionExecution = { + __typename?: 'TransactionExecution'; + id: Scalars['UUID']; + script: Scalars['String']; + arguments?: Maybe>; + signers: Array; + errors?: Maybe>; + events: Array>; + logs: Array; +}; + +export type NewTransactionTemplate = { + projectId: Scalars['UUID']; title: Scalars['String']; script: Scalars['String']; }; @@ -83,11 +131,36 @@ export type UpdateTransactionTemplate = { script?: Maybe; }; -export type NewTransactionExecution = { - projectId: Scalars['UUID']; + + +export type ProgramError = { + __typename?: 'ProgramError'; + message: Scalars['String']; + startPosition?: Maybe; + endPosition?: Maybe; +}; + +export type ScriptExecution = { + __typename?: 'ScriptExecution'; + id: Scalars['UUID']; script: Scalars['String']; - signers?: Maybe>; arguments?: Maybe>; + errors?: Maybe>; + value: Scalars['String']; + logs: Array; +}; + +export type NewProjectScriptTemplate = { + title: Scalars['String']; + script: Scalars['String']; +}; + +export type UpdateScriptTemplate = { + id: Scalars['UUID']; + title?: Maybe; + projectId: Scalars['UUID']; + index?: Maybe; + script?: Maybe; }; export type Mutation = { @@ -182,18 +255,10 @@ export type MutationUpdateTransactionTemplateArgs = { input: UpdateTransactionTemplate; }; -export type TransactionTemplate = { - __typename?: 'TransactionTemplate'; - id: Scalars['UUID']; - index: Scalars['Int']; - title: Scalars['String']; - script: Scalars['String']; -}; - -export type NewTransactionTemplate = { - projectId: Scalars['UUID']; - title: Scalars['String']; - script: Scalars['String']; +export type PlaygroundInfo = { + __typename?: 'PlaygroundInfo'; + apiVersion: Scalars['Version']; + cadenceVersion: Scalars['Version']; }; export type Event = { @@ -223,7 +288,6 @@ export type UpdateAccount = { deployedCode?: Maybe; }; - export type Account = { __typename?: 'Account'; id: Scalars['UUID']; @@ -234,84 +298,20 @@ export type Account = { state: Scalars['String']; }; -export type NewScriptExecution = { + +export type NewTransactionExecution = { projectId: Scalars['UUID']; script: Scalars['String']; + signers?: Maybe>; arguments?: Maybe>; }; - -export type ProgramPosition = { - __typename?: 'ProgramPosition'; - offset: Scalars['Int']; - line: Scalars['Int']; - column: Scalars['Int']; -}; - export type NewScriptTemplate = { projectId: Scalars['UUID']; title: Scalars['String']; script: Scalars['String']; }; -export type PlaygroundInfo = { - __typename?: 'PlaygroundInfo'; - apiVersion: Scalars['Version']; - cadenceVersion: Scalars['Version']; -}; - -export type Project = { - __typename?: 'Project'; - id: Scalars['UUID']; - publicId: Scalars['UUID']; - parentId?: Maybe; - title: Scalars['String']; - seed: Scalars['Int']; - version: Scalars['Version']; - persist?: Maybe; - mutable?: Maybe; - accounts?: Maybe>; - transactionTemplates?: Maybe>; - transactionExecutions?: Maybe>; - scriptTemplates?: Maybe>; - scriptExecutions?: Maybe>; -}; - -export type TransactionExecution = { - __typename?: 'TransactionExecution'; - id: Scalars['UUID']; - script: Scalars['String']; - arguments?: Maybe>; - signers: Array; - errors?: Maybe>; - events: Array>; - logs: Array; -}; - -export type NewProjectTransactionTemplate = { - title: Scalars['String']; - script: Scalars['String']; -}; - -export type UpdateScriptTemplate = { - id: Scalars['UUID']; - title?: Maybe; - projectId: Scalars['UUID']; - index?: Maybe; - script?: Maybe; -}; - - -export type ScriptExecution = { - __typename?: 'ScriptExecution'; - id: Scalars['UUID']; - script: Scalars['String']; - arguments?: Maybe>; - errors?: Maybe>; - value: Scalars['String']; - logs: Array; -}; - export enum ResultType { diff --git a/src/components/Arguments/index.tsx b/src/components/Arguments/index.tsx index bc225a59..1d02cb7f 100644 --- a/src/components/Arguments/index.tsx +++ b/src/components/Arguments/index.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { FaRegCheckCircle, FaRegTimesCircle, FaSpinner } from 'react-icons/fa'; import { motion } from 'framer-motion'; import { EntityType } from 'providers/Project'; @@ -6,25 +6,47 @@ import { useProject } from 'providers/Project/projectHooks'; import { Account, ResultType, - useSetExecutionResultsMutation + useSetExecutionResultsMutation, } from 'api/apollo/generated/graphql'; -import { ArgumentsProps } from "components/Arguments/types"; +import { ArgumentsProps } from 'components/Arguments/types'; +import { ExecuteCommandRequest } from 'monaco-languageclient'; -import { - ControlContainer, - HoverPanel, - StatusMessage -} from './styles'; +import { ControlContainer, HoverPanel, StatusMessage } from './styles'; import { ActionButton, ArgumentsList, - ArgumentsTitle, ErrorsList, Hints, + ArgumentsTitle, + ErrorsList, + Hints, Signers, } from './components'; -const validateByType = (value: any, type: string) => { +const isDictionaary = (type:string) => type.includes("{") +const isArray = (type:string) => type.includes("[") +const isImportedType = (type:string) => type.includes(".") +const isComplexType = (type:string)=> isDictionaary(type) + || isArray(type) + || isImportedType(type) + +const startsWith = (value : string, prefix: string) => { + return value.startsWith(prefix) || value.startsWith("U"+prefix) +} + +const checkJSON = (value: any, type: string) => { + try{ + JSON.parse(value) + return null + } catch (e){ + return `Not a valid argument of type ${type}` + } +} + +const validateByType = ( + value: any, + type: string, +) => { if (value.length === 0) { return "Value can't be empty"; } @@ -36,29 +58,34 @@ const validateByType = (value: any, type: string) => { } // Integers - case type.includes('Int'): { - if (isNaN(value) || value === "") { + case startsWith(type,'Int'): { + if (isNaN(value) || value === '') { return 'Should be a valid Integer number'; } return null; } // Words - case type.includes('Word'): { - if (isNaN(value) || value === "") { + case startsWith(type,'Word'): { + if (isNaN(value) || value === '') { return 'Should be a valid Word number'; } return null; } // Fixed Point - case type.includes('Fix'): { - if (isNaN(value) || value === "") { + case startsWith(type, 'Fix'): { + if (isNaN(value) || value === '') { return 'Should be a valid fixed point number'; } return null; } + case isComplexType(type): { + // This case it to catch complex arguments like Dictionaries + return checkJSON(value, type); + } + // Address case type === 'Address': { if (!value.match(/(^0x[\w\d]{16})|(^0x[\w\d]{1,4})/)) { @@ -75,28 +102,12 @@ const validateByType = (value: any, type: string) => { return null; } - default: + default: { return null; + } } }; -const validate = (list: any, values: any) => { - return list.reduce((acc: any, item: any) => { - const { name, type } = item; - const value = values[name]; - if (value) { - const error = validateByType(value, type); - if (error) { - acc[name] = error; - } - } else { - if (type !== "String"){ - acc[name] = "Value can't be empty" - } - } - return acc; - }, {}); -}; const getLabel = ( resultType: ResultType, @@ -141,7 +152,6 @@ const useTemplateType = (): ProcessingArgs => { contractDeployment: updateAccountDeployedCode, }; }; - interface IValue { [key: string]: string; } @@ -149,19 +159,45 @@ interface IValue { const Arguments: React.FC = (props) => { const { type, list, signers } = props; const { goTo, hover, hideDecorations, problems } = props; - const validCode = problems.error.length === 0 + const validCode = problems.error.length === 0; const needSigners = type == EntityType.TransactionTemplate && signers > 0; const [selected, updateSelectedAccounts] = useState([]); + const [errors, setErrors] = useState({}) const [expanded, setExpanded] = useState(true); const [values, setValue] = useState({}); const constraintsRef = useRef(); - const errors = validate(list, values); + // const errors = validate(list, values); const numberOfErrors = Object.keys(errors).length; const notEnoughSigners = needSigners && selected.length < signers; const haveErrors = numberOfErrors > 0 || notEnoughSigners; + const validate = (list: any, values: any) => { + const errors = list.reduce((acc: any, item: any) => { + const { name, type } = item; + const value = values[name]; + if (value) { + const error = validateByType(value, type); + if (error) { + acc[name] = error; + } + } else { + if (type !== 'String') { + acc[name] = "Value can't be empty"; + } + } + return acc; + }, {}); + + console.log({errors}); + setErrors(errors); + }; + + useEffect(()=>{ + validate(list, values) + }, [list, values]); + const [processingStatus, setProcessingStatus] = useState(false); const [setResult] = useSetExecutionResultsMutation(); @@ -180,17 +216,41 @@ const Arguments: React.FC = (props) => { setProcessingStatus(true); } - // Map values to strings that will be passed to backend - const args = list.map((arg) => { + // TODO: implement algorithm for drilling down dictionaries + + const fixed = list.map((arg) => { const { name, type } = arg; let value = values[name]; // We probably better fix this on server side... - if (type === "UFix64"){ - if (value.indexOf('.') < 0 ){ - value = `${value}.0` + if (type === 'UFix64') { + if (value.indexOf('.') < 0) { + value = `${value}.0`; } } + return value; + }); + + const formatted = await props.languageClient.sendRequest( + ExecuteCommandRequest.type, + { + command: 'cadence.server.parseEntryPointArguments', + arguments: [ + props.editor.getModel().uri.toString(), + fixed + ], + }, + ); + + // Map values to strings that will be passed to backend + const args:any = list.map((arg, index) => { + const { type } = arg; + const value = fixed[index] + + // If we have a complex type - return value formatted by language server + if ( isComplexType(type)){ + return JSON.stringify(formatted[index]) + } return JSON.stringify({ value, type }); }); @@ -255,7 +315,7 @@ const Arguments: React.FC = (props) => { statusMessage = 'Please, wait...'; } - const actions = { goTo, hover, hideDecorations} + const actions = { goTo, hover, hideDecorations }; return ( <> @@ -299,8 +359,8 @@ const Arguments: React.FC = (props) => { )} - - + + diff --git a/src/components/Arguments/types.tsx b/src/components/Arguments/types.tsx index 6281fc4f..33a2deca 100644 --- a/src/components/Arguments/types.tsx +++ b/src/components/Arguments/types.tsx @@ -1,17 +1,22 @@ -import * as monaco from "monaco-editor"; -import {EntityType} from "providers/Project"; -import {CadenceProblem, Highlight, ProblemsList} from "../../util/language-syntax-errors"; +import * as monaco from 'monaco-editor'; +import { EntityType } from 'providers/Project'; +import { + CadenceProblem, + Highlight, + ProblemsList, +} from '../../util/language-syntax-errors'; +import { MonacoLanguageClient } from 'monaco-languageclient'; export type InteractionButtonProps = { - onClick: () => void, - active?: boolean, - type: EntityType -} + onClick: () => void; + active?: boolean; + type: EntityType; +}; export type Argument = { - name: string, - type: string -} + name: string; + type: string; +}; export type ArgumentsProps = { type: EntityType; @@ -21,36 +26,38 @@ export type ArgumentsProps = { goTo: (position: monaco.IPosition) => void; hover: (highlight: Highlight) => void; hideDecorations: () => void; + editor: any; + languageClient: MonacoLanguageClient; }; export type ArgumentsTitleProps = { - type: EntityType, - expanded: boolean, - setExpanded: (value: boolean) => void, - errors?: number -} + type: EntityType; + expanded: boolean; + setExpanded: (value: boolean) => void; + errors?: number; +}; export type ArgumentsListProps = { - list: Argument[], - hidden: boolean, - onChange: (name: String, value: any) => void, - errors: any, -} + list: Argument[]; + hidden: boolean; + onChange: (name: String, value: any) => void; + errors: any; +}; export type ErrorListProps = { - list: CadenceProblem[], + list: CadenceProblem[]; goTo: (position: monaco.IPosition) => void; hover: (highlight: Highlight) => void; hideDecorations: () => void; -} +}; export type HintsProps = { - problems: ProblemsList, - goTo: (position: monaco.IPosition) => void, - hover: (highlight: Highlight) => void, - hideDecorations: () => void, -} + problems: ProblemsList; + goTo: (position: monaco.IPosition) => void; + hover: (highlight: Highlight) => void; + hideDecorations: () => void; +}; export type HintsState = { - expanded: boolean -} + expanded: boolean; +}; diff --git a/src/components/CadenceEditor.tsx b/src/components/CadenceEditor.tsx index 0597c65d..0073c298 100644 --- a/src/components/CadenceEditor.tsx +++ b/src/components/CadenceEditor.tsx @@ -1,20 +1,30 @@ -import React from "react" -import styled from "@emotion/styled" -import { keyframes } from "@emotion/core"; -import configureCadence, {CADENCE_LANGUAGE_ID} from "../util/cadence" -import {CadenceCheckCompleted, CadenceLanguageServer, Callbacks} from "../util/language-server" -import {createCadenceLanguageClient} from "../util/language-client" -import * as monaco from "monaco-editor/esm/vs/editor/editor.api" -import {EntityType} from "providers/Project"; -import Arguments from "components/Arguments"; -import { Argument } from "components/Arguments/types"; -import {CadenceProblem, formatMarker, goTo, Highlight, ProblemsList} from "../util/language-syntax-errors"; +import React from 'react'; +import styled from '@emotion/styled'; +import { keyframes } from '@emotion/core'; +import configureCadence, { CADENCE_LANGUAGE_ID } from '../util/cadence'; +import { + CadenceCheckCompleted, + CadenceLanguageServer, + Callbacks, +} from '../util/language-server'; +import { createCadenceLanguageClient } from '../util/language-client'; +import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; +import { EntityType } from 'providers/Project'; +import Arguments from 'components/Arguments'; +import { Argument } from 'components/Arguments/types'; +import { + CadenceProblem, + formatMarker, + goTo, + Highlight, + ProblemsList, +} from '../util/language-syntax-errors'; import { MonacoLanguageClient, ExecuteCommandRequest, -} from "monaco-languageclient" +} from 'monaco-languageclient'; -const {MonacoServices} = require("monaco-languageclient/lib/monaco-services"); +const { MonacoServices } = require('monaco-languageclient/lib/monaco-services'); const blink = keyframes` 50% { @@ -97,7 +107,7 @@ type EditorState = { let monacoServicesInstalled = false; -type CodeGetter = (index: number) => string | undefined +type CodeGetter = (index: number) => string | undefined; type CadenceEditorProps = { code: string; @@ -106,14 +116,17 @@ type CadenceEditorProps = { activeId: string; type: EntityType; getCode: CodeGetter; -} +}; type CadenceEditorState = { - args: {[key: string]: Argument[]} - problems: {[key: string]: ProblemsList} -} + args: { [key: string]: Argument[] }; + problems: { [key: string]: ProblemsList }; +}; -class CadenceEditor extends React.Component { +class CadenceEditor extends React.Component< + CadenceEditorProps, + CadenceEditorState +> { editor: monaco.editor.ICodeEditor; languageClient?: MonacoLanguageClient; _subscription: any; @@ -132,13 +145,13 @@ class CadenceEditor extends React.Component { this.props.onChange(this.editor.getValue(), event); @@ -164,18 +177,22 @@ class CadenceEditor extends React.Component this.props.getCode(index)) + await this.loadLanguageServer(editor, (index) => + this.props.getCode(index), + ); } } - private async loadLanguageServer(editor: monaco.editor.ICodeEditor, getCode: CodeGetter) { - + private async loadLanguageServer( + editor: monaco.editor.ICodeEditor, + getCode: CodeGetter, + ) { this.callbacks = { // The actual callback will be set as soon as the language server is initialized toServer: null, @@ -190,20 +207,20 @@ class CadenceEditor extends React.Component { - this.languageClient.onNotification(CadenceCheckCompleted.methodName, async (result: CadenceCheckCompleted.Params) => { - if (result.valid) { - const params = await this.getParameters() - this.setExecutionArguments(params) - } - this.processMarkers() - }) - }) + this.languageClient.onNotification( + CadenceCheckCompleted.methodName, + async (result: CadenceCheckCompleted.Params) => { + if (result.valid) { + const params = await this.getParameters(); + this.setExecutionArguments(params); + } + this.processMarkers(); + }, + ); + }); } private async getParameters() { - await this.languageClient.onReady() + await this.languageClient.onReady(); try { - const args = await this.languageClient.sendRequest(ExecuteCommandRequest.type, { - command: "cadence.server.getEntryPointParameters", - arguments: [this.editor.getModel().uri.toString()] - }) - return args || [] + const args = await this.languageClient.sendRequest( + ExecuteCommandRequest.type, + { + command: 'cadence.server.getEntryPointParameters', + arguments: [this.editor.getModel().uri.toString()], + }, + ); + return args || []; } catch (error) { - console.error(error) + console.error(error); } } - processMarkers(){ + processMarkers() { const model = this.editor.getModel(); - const modelMarkers = monaco.editor.getModelMarkers({resource: model.uri}) - const errors = modelMarkers - .reduce((acc: {[key:string]: CadenceProblem[]}, marker) => { - const mappedMarker:CadenceProblem = formatMarker(marker); - acc[mappedMarker.type].push(mappedMarker) - return acc - },{ - "error": [], - "warning": [], - "info": [], - "hint": [] - }) + const modelMarkers = monaco.editor.getModelMarkers({ resource: model.uri }); + const errors = modelMarkers.reduce( + (acc: { [key: string]: CadenceProblem[] }, marker) => { + const mappedMarker: CadenceProblem = formatMarker(marker); + acc[mappedMarker.type].push(mappedMarker); + return acc; + }, + { + error: [], + warning: [], + info: [], + hint: [], + }, + ); - const {activeId} = this.props; + const { activeId } = this.props; this.setState({ problems: { - [activeId]: errors - } - }) + [activeId]: errors, + }, + }); } - setExecutionArguments(args: Argument[]){ - const {activeId} = this.props; + setExecutionArguments(args: Argument[]) { + const { activeId } = this.props; this.setState({ args: { - [activeId]: args - } - }) + [activeId]: args, + }, + }); } getOrCreateEditorState(id: string, code: string): EditorState { @@ -281,12 +306,12 @@ class CadenceEditor extends React.Component line.includes(keyWord)) - - if (target){ - const match = target.match(/(?:\()(.*)(?:\))/) - if (match){ - return match[1] - .split(",") - .map(item => item.replace(/\s*/g,'')) + .find((line) => line.includes(keyWord)); + + if (target) { + const match = target.match(/(?:\()(.*)(?:\))/); + if (match) { + return match[1].split(',').map((item) => item.replace(/\s*/g, '')); } } - return [] + return []; } - extractSigners(code: string):number{ - return this - .extract(code, "prepare") - .filter(item => !!item) - .length + extractSigners(code: string): number { + return this.extract(code, 'prepare').filter((item) => !!item).length; } hover(highlight: Highlight): void { - const { startLine, startColumn, endLine, endColumn, color } = highlight - const model = this.editor.getModel() + const { startLine, startColumn, endLine, endColumn, color } = highlight; + const model = this.editor.getModel(); - const selection = model - .getAllDecorations() - .find((item: any) => { - return ( - item.range.startLineNumber === startLine && - item.range.startColumn === startColumn - ) - }) + const selection = model.getAllDecorations().find((item: any) => { + return ( + item.range.startLineNumber === startLine && + item.range.startColumn === startColumn + ); + }); - const selectionEndLine = selection ? selection.range.endLineNumber : endLine - const selectionEndColumn = selection ? selection.range.endColumn : endColumn + const selectionEndLine = selection + ? selection.range.endLineNumber + : endLine; + const selectionEndColumn = selection + ? selection.range.endColumn + : endColumn; const highlightLine = [ { @@ -389,27 +411,33 @@ class CadenceEditor extends React.Component { - const { className } = item.options - return className?.includes("playground-syntax") - }).map(item => item.id) + .getAllDecorations() + .filter((item) => { + const { className } = item.options; + return className?.includes('playground-syntax'); + }) + .map((item) => item.id); - model.deltaDecorations(current, []) + model.deltaDecorations(current, []); } render() { @@ -418,16 +446,16 @@ class CadenceEditor extends React.Component this.hover(highlight)} - hideDecorations={()=>this.hideDecorations()} - goTo={(position: monaco.IPosition)=> goTo(this.editor, position)} + hover={(highlight) => this.hover(highlight)} + hideDecorations={() => this.hideDecorations()} + goTo={(position: monaco.IPosition) => goTo(this.editor, position)} + editor={this.editor} + languageClient={this.languageClient} /> ); diff --git a/src/components/RenderResponse/Line/index.tsx b/src/components/RenderResponse/Line/index.tsx index f18488b7..e66bd16f 100644 --- a/src/components/RenderResponse/Line/index.tsx +++ b/src/components/RenderResponse/Line/index.tsx @@ -74,7 +74,7 @@ const Label = styled.strong<{ tag: Tag }>` `} `; -const Value = styled.span<{ tag: Tag }>` +const StringValue = styled.pre<{ tag: Tag }>` ${p => p.tag === Tag.ERROR && css` @@ -82,7 +82,7 @@ const Value = styled.span<{ tag: Tag }>` `} `; -const Pre = styled.pre` +const ObjectValue = styled.pre` border-radius: 3px; padding: 13px; background: ${theme.colors.muted}; @@ -99,13 +99,11 @@ export const Line: React.FC = ({ timestamp, tag, value, label }) => { - {typeof value === "string" ? ( - <> - {value} - - ) : ( -
{JSON.stringify(value, null, 2)}
- )} + { + typeof value === "string" + ? {value} + : {JSON.stringify(value, null, 2)} + } ); }; diff --git a/src/providers/Project/projectMutator.ts b/src/providers/Project/projectMutator.ts index 898325ac..c4937a29 100644 --- a/src/providers/Project/projectMutator.ts +++ b/src/providers/Project/projectMutator.ts @@ -1,6 +1,6 @@ -import ApolloClient from "apollo-client"; -import { navigate } from "@reach/router"; -import Mixpanel from "../../util/mixpanel"; +import { navigate } from '@reach/router'; + +import ApolloClient from 'apollo-client'; import { CREATE_PROJECT, @@ -15,16 +15,16 @@ import { UPDATE_SCRIPT_TEMPLATE, CREATE_SCRIPT_TEMPLATE, DELETE_SCRIPT_TEMPLATE, - DELETE_TRANSACTION_TEMPLATE -} from "api/apollo/mutations"; - -import { Project, Account } from "api/apollo/generated/graphql"; -import { GET_LOCAL_PROJECT, GET_PROJECT } from "api/apollo/queries"; + DELETE_TRANSACTION_TEMPLATE, +} from 'api/apollo/mutations'; +import { Project, Account } from 'api/apollo/generated/graphql'; +import { GET_LOCAL_PROJECT, GET_PROJECT } from 'api/apollo/queries'; +import Mixpanel from '../../util/mixpanel'; import { registerOnCloseSaveMessage, - unregisterOnCloseSaveMessage -} from "../../util/onclose"; + unregisterOnCloseSaveMessage, +} from '../../util/onclose'; export default class ProjectMutator { client: ApolloClient; @@ -35,7 +35,7 @@ export default class ProjectMutator { constructor( client: ApolloClient, projectId: string | null, - isLocal: boolean + isLocal: boolean, ) { this.client = client; this.projectId = projectId; @@ -44,18 +44,18 @@ export default class ProjectMutator { async createProject(): Promise { const { project: localProject } = this.client.readQuery({ - query: GET_LOCAL_PROJECT + query: GET_LOCAL_PROJECT, }); const parentId = localProject.parentId; const accounts = localProject.accounts.map((acc: Account) => acc.draftCode); const seed = localProject.seed; const transactionTemplates = localProject.transactionTemplates.map( - (tpl: any) => ({ script: tpl.script, title: tpl.title }) + (tpl: any) => ({ script: tpl.script, title: tpl.title }), ); const scriptTemplates = localProject.scriptTemplates.map((tpl: any) => ({ script: tpl.script, - title: tpl.title + title: tpl.title, })); const { data } = await this.client.mutate({ @@ -64,10 +64,10 @@ export default class ProjectMutator { parentId: parentId, accounts: accounts, seed: seed, - title: "", + title: '', transactionTemplates: transactionTemplates, - scriptTemplates: scriptTemplates - } + scriptTemplates: scriptTemplates, + }, }); const project = data.project; @@ -78,13 +78,13 @@ export default class ProjectMutator { this.client.mutate({ mutation: SET_ACTIVE_PROJECT, variables: { - id: this.projectId - } + id: this.projectId, + }, }); Mixpanel.people.set({ - projectId: project.id + projectId: project.id, }); - Mixpanel.track("Project created", { projectId: project.id, project }); + Mixpanel.track('Project created', { projectId: project.id, project }); return project; } @@ -97,14 +97,14 @@ export default class ProjectMutator { await this.client.mutate({ mutation: PERSIST_PROJECT, variables: { - projectId: this.projectId - } + projectId: this.projectId, + }, }); if (isFork) { - Mixpanel.track("Project forked", { projectId: this.projectId }); + Mixpanel.track('Project forked', { projectId: this.projectId }); } else { - Mixpanel.track("Project saved", { projectId: this.projectId }); + Mixpanel.track('Project saved', { projectId: this.projectId }); } navigate(`/${this.projectId}`, { replace: true }); @@ -115,9 +115,9 @@ export default class ProjectMutator { this.client.writeData({ id: `Account:${account.id}`, data: { - __typename: "Account", - draftCode: code - } + __typename: 'Account', + draftCode: code, + }, }); registerOnCloseSaveMessage(); @@ -129,8 +129,8 @@ export default class ProjectMutator { variables: { projectId: this.projectId, accountId: account.id, - code - } + code, + }, }); } @@ -146,16 +146,16 @@ export default class ProjectMutator { variables: { projectId: this.projectId, accountId: account.id, - code: account.draftCode + code: account.draftCode, }, refetchQueries: [ - { query: GET_PROJECT, variables: { projectId: this.projectId } } - ] + { query: GET_PROJECT, variables: { projectId: this.projectId } }, + ], }); - Mixpanel.track("Contract deployed", { + Mixpanel.track('Contract deployed', { projectId: this.projectId, accountId: account.id, - code: account.draftCode + code: account.draftCode, }); return res; } @@ -163,15 +163,15 @@ export default class ProjectMutator { async updateTransactionTemplate( templateId: string, script: string, - title: string + title: string, ) { if (this.isLocal) { this.client.writeData({ id: `TransactionTemplate:${templateId}`, data: { script: script, - title: title - } + title: title, + }, }); registerOnCloseSaveMessage(); return; @@ -183,21 +183,25 @@ export default class ProjectMutator { projectId: this.projectId, templateId: templateId, script: script, - title: title + title: title, }, refetchQueries: [ - { query: GET_PROJECT, variables: { projectId: this.projectId } } - ] + { query: GET_PROJECT, variables: { projectId: this.projectId } }, + ], }); } - async createTransactionExecution(script: string, signers: Account[], args: string[]) { + async createTransactionExecution( + script: string, + signers: Account[], + args: string[], + ) { if (this.isLocal) { await this.createProject(); } const signerAddresses: string[] = signers.map( - (account: Account) => account.address + (account: Account) => account.address, ); const res = await this.client.mutate({ @@ -206,15 +210,15 @@ export default class ProjectMutator { projectId: this.projectId, signers: signerAddresses, arguments: args, - script + script, }, refetchQueries: [ - { query: GET_PROJECT, variables: { projectId: this.projectId } } - ] + { query: GET_PROJECT, variables: { projectId: this.projectId } }, + ], }); - Mixpanel.track("Transaction template executed", { + Mixpanel.track('Transaction template executed', { projectId: this.projectId, - script + script, }); return res; @@ -230,34 +234,34 @@ export default class ProjectMutator { variables: { projectId: this.projectId, script, - title + title, }, refetchQueries: [ - { query: GET_PROJECT, variables: { projectId: this.projectId } } + { query: GET_PROJECT, variables: { projectId: this.projectId } }, ], - awaitRefetchQueries: true + awaitRefetchQueries: true, }); - Mixpanel.track("Transaction template created", { + Mixpanel.track('Transaction template created', { projectId: this.projectId, - script + script, }); - return res + return res; } async updateScriptTemplate( templateId: string, script: string, - title: string + title: string, ) { if (this.isLocal) { this.client.writeData({ id: `ScriptTemplate:${templateId}`, data: { script: script, - title: title - } + title: title, + }, }); registerOnCloseSaveMessage(); return; @@ -269,11 +273,11 @@ export default class ProjectMutator { projectId: this.projectId, templateId: templateId, script: script, - title: title + title: title, }, refetchQueries: [ - { query: GET_PROJECT, variables: { projectId: this.projectId } } - ] + { query: GET_PROJECT, variables: { projectId: this.projectId } }, + ], }); } @@ -286,11 +290,11 @@ export default class ProjectMutator { mutation: DELETE_TRANSACTION_TEMPLATE, variables: { projectId: this.projectId, - templateId + templateId, }, refetchQueries: [ - { query: GET_PROJECT, variables: { projectId: this.projectId } } - ] + { query: GET_PROJECT, variables: { projectId: this.projectId } }, + ], }); return res; @@ -305,18 +309,17 @@ export default class ProjectMutator { mutation: DELETE_SCRIPT_TEMPLATE, variables: { projectId: this.projectId, - templateId + templateId, }, refetchQueries: [ - { query: GET_PROJECT, variables: { projectId: this.projectId } } - ] + { query: GET_PROJECT, variables: { projectId: this.projectId } }, + ], }); return res; } async createScriptExecution(script: string, args: string[]) { - if (this.isLocal) { await this.createProject(); } @@ -326,12 +329,12 @@ export default class ProjectMutator { variables: { projectId: this.projectId, script, - arguments: args - } + arguments: args, + }, }); - Mixpanel.track("Script template executed", { + Mixpanel.track('Script template executed', { projectId: this.projectId, - script + script, }); return res; } @@ -346,19 +349,19 @@ export default class ProjectMutator { variables: { projectId: this.projectId, script, - title + title, }, refetchQueries: [ - { query: GET_PROJECT, variables: { projectId: this.projectId } } + { query: GET_PROJECT, variables: { projectId: this.projectId } }, ], - awaitRefetchQueries: true + awaitRefetchQueries: true, }); - Mixpanel.track("Script template created", { + Mixpanel.track('Script template created', { projectId: this.projectId, - script + script, }); - return res + return res; } }