Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: refactor services and clients #419

Merged
merged 32 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
63f6efa
refactor: convert rpc client to a hook instead of provide/inject
Aug 20, 2024
cf7e1c4
refactor: web3 hook
Aug 22, 2024
f45bbb2
refactor: short address hook
Aug 22, 2024
815e558
refactor: db hook
Aug 23, 2024
5e82a4f
fix: remove db version redundancy
Aug 23, 2024
b960a93
refactor: ws hook
Aug 23, 2024
2c0267b
refactor: rpc client/hook
Aug 23, 2024
971fcb2
refactor: input map hook, move useContractQueries to hooks index
Aug 23, 2024
c600c2e
refactor: python syntax hook
Aug 23, 2024
f4cbd86
refactor: filename hook
Aug 23, 2024
c52b1fb
refactor: setup stores
Aug 23, 2024
a4fb5f3
refactor: rename eth to wallet
Aug 23, 2024
356f102
fix: wrong input mapping
Aug 23, 2024
58c7241
build: Merge branch 'staging' into 408-sim-fe-refactor-services-and-c…
Aug 23, 2024
d4e16be
build: Merge branch 'staging' into 408-sim-fe-refactor-services-and-c…
Aug 27, 2024
371c31c
refactor: normalize naming for wallet methods
Aug 27, 2024
1634a6e
fix: update omitted replace
Aug 26, 2024
8660d95
fix: replace updated method
Aug 28, 2024
a408403
fix: consistently delete example contracts on reset storage
Aug 28, 2024
bcdc69d
fix: don't reload all example files when they already exist with a ch…
Aug 28, 2024
1f8ef07
fix: remove comment
Aug 28, 2024
15bc623
fix: allow id param on tx items
Aug 28, 2024
84c5a7d
fix: load opened files correctly from storage, remove some legacy code
Aug 29, 2024
9fcd5cb
fix: Merge branch 'staging' into 408-sim-fe-refactor-services-and-cli…
Aug 29, 2024
d023136
refactor: move shortenAddress to useWallet hook and simplify it's def…
Aug 30, 2024
5fa951c
refactor: move python syntax to a constant
Aug 30, 2024
5a5ecd7
refactor: web client
Aug 30, 2024
74bb000
refactor: wrap web3 methods
Aug 30, 2024
9edde1a
fix: adapt implementations after web3 wallet wrapping
Aug 30, 2024
f0d8f3f
fix: use lodash debounce instead of vue-debounce because of breaking …
Aug 28, 2024
601d078
fix: wrong typing
Aug 30, 2024
c005c59
Merge branch 'staging' into 408-sim-fe-refactor-services-and-clients
Aug 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import Notification from '@/components/Notification.vue';
import TutorialContainer from '@/components/Tutorial/TutorialContainer.vue';
import { useUIStore } from '@/stores/ui';
import { onBeforeMount } from 'vue';
import { setupStores } from './utils';
import { useSetupStores } from '@/hooks';

const uiStore = useUIStore();
const { setupStores } = useSetupStores();

onBeforeMount(() => {
uiStore.initialize();
Expand Down
File renamed without changes.
5 changes: 3 additions & 2 deletions frontend/src/components/Simulator/CodeEditor.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
<script setup lang="ts">
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { pythonSyntaxDefinition } from '@/utils';
import { ref, shallowRef, watch, computed, onMounted } from 'vue';
import { useContractsStore, useUIStore } from '@/stores';
import { type ContractFile } from '@/types';
import { usePythonSyntax } from '@/hooks';

const uiStore = useUIStore();
const contractStore = useContractsStore();
const props = defineProps<{
contract: ContractFile;
}>();
const pythonSyntax = usePythonSyntax();

const editorElement = ref<HTMLDivElement | null>(null);
const containerElement = ref<HTMLElement | null | undefined>(null);
Expand All @@ -19,7 +20,7 @@ const theme = computed(() => (uiStore.mode === 'light' ? 'vs' : 'vs-dark'));
function initEditor() {
containerElement.value = editorElement.value?.parentElement;
monaco.languages.register({ id: 'python' });
monaco.languages.setMonarchTokensProvider('python', pythonSyntaxDefinition);
monaco.languages.setMonarchTokensProvider('python', pythonSyntax);
editorRef.value = monaco.editor.create(editorElement.value!, {
value: props.contract.content || '',
language: 'python',
Expand Down
12 changes: 8 additions & 4 deletions frontend/src/components/Simulator/ConstructorParameters.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
<script setup lang="ts">
import { useContractQueries } from '@/hooks/useContractQueries';
import { useContractQueries, useInputMap } from '@/hooks';
import { ref, computed, watch, onMounted } from 'vue';
import PageSection from '@/components/Simulator/PageSection.vue';
import { ArrowUpTrayIcon } from '@heroicons/vue/16/solid';
import { InputTypesMap } from '@/utils';
import EmptyListPlaceholder from '@/components/Simulator/EmptyListPlaceholder.vue';
import GhostBtn from '../global/GhostBtn.vue';
import { notify } from '@kyvg/vue3-notification';
Expand All @@ -13,6 +12,7 @@ import { type ContractMethod } from '@/types';

const { contract, contractSchemaQuery, deployContract, isDeploying } =
useContractQueries();
const inputMap = useInputMap();

const { data, isPending, isRefetching, isError } = contractSchemaQuery;
const inputParams = ref<{ [k: string]: any }>({});
Expand Down Expand Up @@ -105,7 +105,11 @@ const toggleMode = () => {

const mapInputs = (inputs: { [k: string]: string }) =>
Object.keys(inputs || {})
.map((key) => ({ name: key, type: InputTypesMap[key], value: inputs[key] }))
.map((key) => ({
name: key,
type: inputs[key],
value: inputs[key],
}))
.reduce((prev, curr) => {
if (typeof curr.value === 'boolean') {
prev = { ...prev, [curr.name]: curr.value ? 'True' : 'False' };
Expand Down Expand Up @@ -175,7 +179,7 @@ const hasConstructorInputs = computed(
<template v-if="mode === 'form'">
<div v-for="input in constructorInputs" :key="input">
<component
:is="InputTypesMap[input.type]"
:is="inputMap.getComponent(input.type)"
v-model="inputParams[input.name]"
:name="input.name"
:placeholder="input.name"
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Simulator/ContractInfo.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<script setup lang="ts">
import { useContractQueries } from '@/hooks/useContractQueries';
import PageSection from '@/components/Simulator/PageSection.vue';
import { CheckCircleIcon } from '@heroicons/vue/24/outline';
import EmptyListPlaceholder from '@/components/Simulator/EmptyListPlaceholder.vue';
import { PlusIcon } from '@heroicons/vue/16/solid';
import { shortenAddress } from '@/utils';
import { useNodeStore } from '@/stores';
import { useShortAddress, useContractQueries } from '@/hooks';

const nodeStore = useNodeStore();
const { shortenAddress } = useShortAddress();

defineProps<{
showNewDeploymentButton: boolean;
Expand Down
9 changes: 5 additions & 4 deletions frontend/src/components/Simulator/ContractMethodItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
import type { ContractMethod } from '@/types';
import { onMounted, ref } from 'vue';
import { Collapse } from 'vue-collapsed';
import { InputTypesMap } from '@/utils';
import { useContractQueries } from '@/hooks/useContractQueries';
import { useInputMap } from '@/hooks';
import { notify } from '@kyvg/vue3-notification';
import { ChevronDownIcon } from '@heroicons/vue/16/solid';
import { useEventTracking } from '@/hooks';
import { useEventTracking, useContractQueries } from '@/hooks';

const { callWriteMethod, callReadMethod, contract } = useContractQueries();
const { trackEvent } = useEventTracking();

const inputMap = useInputMap();

const props = defineProps<{
method: ContractMethod;
methodType: 'read' | 'write';
Expand Down Expand Up @@ -116,7 +117,7 @@ onMounted(() => {
<component
v-for="input in method.inputs"
:key="input.name"
:is="InputTypesMap[input.type]"
:is="inputMap.getComponent(input.type)"
v-model="inputs[input.name]"
:name="String(input.name)"
:label="String(input.name)"
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Simulator/ContractReadMethods.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { useContractQueries } from '@/hooks/useContractQueries';
import { useContractQueries } from '@/hooks';
import { computed } from 'vue';
import PageSection from '@/components/Simulator/PageSection.vue';
import { type ContractMethod } from '@/types';
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Simulator/ContractWriteMethods.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { useContractQueries } from '@/hooks/useContractQueries';
import { useContractQueries } from '@/hooks';
import { computed } from 'vue';
import PageSection from '@/components/Simulator/PageSection.vue';
import { type ContractMethod } from '@/types';
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Simulator/ContractsPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useContractsStore } from '@/stores';
import { computed } from 'vue';
import HomeTab from './HomeTab.vue';
import { useRouter, useRoute } from 'vue-router';
import { useContractQueries } from '@/hooks/useContractQueries';
import { useContractQueries } from '@/hooks';

const store = useContractsStore();
const router = useRouter();
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/components/Tutorial/TutorialContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ const tutorialStore = useTutorialStore();
const uiStore = useUIStore();
const router = useRouter();

tutorialStore.resetTutorialState();

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

const steps = ref([
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
export * from './useUniqueId';
export * from './useEventTracking';
export * from './useRpcClient';
export * from './useWallet';
export * from './useShortAddress';
export * from './useDb';
export * from './useWebSocketClient';
export * from './useInputMap';
export * from './useContractQueries';
export * from './usePythonSyntax';
export * from './useFileName';
export * from './useSetupStores';
34 changes: 14 additions & 20 deletions frontend/src/hooks/useContractQueries.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import { watch, ref, inject, computed } from 'vue';
import { toHex, toRlp } from 'viem';
import type { IJsonRpcService } from '@/services';
import { watch, ref, computed } from 'vue';
import { useQuery, useQueryClient } from '@tanstack/vue-query';
import type { Address, TransactionItem } from '@/types';
import {
useContractsStore,
useTransactionsStore,
useAccountsStore,
} from '@/stores';
import { signTransaction } from '@/utils';
import { useDebounceFn } from '@vueuse/core';
import { notify } from '@kyvg/vue3-notification';
import { useMockContractData } from './useMockContractData';
import { useEventTracking } from '@/hooks';
import { useEventTracking, useRpcClient, useWallet } from '@/hooks';

const schema = ref<any>();

export function useContractQueries() {
const $jsonRpc = inject<IJsonRpcService>('$jsonRpc'); // This could be done without inject/provide
const rpcClient = useRpcClient();
const accountsStore = useAccountsStore();
const transactionsStore = useTransactionsStore();
const contractsStore = useContractsStore();
const queryClient = useQueryClient();
const { trackEvent } = useEventTracking();
const wallet = useWallet();
const contract = computed(() => contractsStore.currentContract);

const { mockContractId, mockContractSchema } = useMockContractData();
Expand Down Expand Up @@ -64,7 +62,7 @@ export function useContractQueries() {
return mockContractSchema;
}

const result = await $jsonRpc?.getContractSchema({
const result = await rpcClient.getContractSchema({
code: contract.value?.content ?? '',
});

Expand All @@ -91,16 +89,12 @@ export function useContractQueries() {
throw new Error('Error Deploying the contract');
}
const constructorParamsAsString = JSON.stringify(constructorParams);
const data = toRlp([
toHex(contract.value?.content ?? ''),
toHex(constructorParamsAsString),
]);

const signed = await signTransaction(
const data = [contract.value?.content ?? '', constructorParamsAsString];
const signed = await wallet.signTransaction(
accountsStore.currentPrivateKey,
data,
);
const result = await $jsonRpc?.sendTransaction(signed);
const result = await rpcClient.sendTransaction(signed);

if (result?.status === 'success') {
const tx: TransactionItem = {
Expand Down Expand Up @@ -166,7 +160,7 @@ export function useContractQueries() {
return mockContractSchema;
}

const result = await $jsonRpc?.getDeployedContractSchema({
const result = await rpcClient.getDeployedContractSchema({
address: deployedContract.value?.address ?? '',
});

Expand All @@ -180,7 +174,7 @@ export function useContractQueries() {

async function callReadMethod(method: string, methodArguments: string[]) {
try {
const result = await $jsonRpc?.getContractState({
const result = await rpcClient.getContractState({
contractAddress: address.value || '',
method,
methodArguments,
Expand Down Expand Up @@ -210,15 +204,15 @@ export function useContractQueries() {
throw new Error('Error Deploying the contract');
}
const methodParamsAsString = JSON.stringify(params);
const data = toRlp([toHex(method), toHex(methodParamsAsString)]);

const data = [method, methodParamsAsString];
const to = (address.value as Address) || null;
const signed = await signTransaction(

const signed = await wallet.signTransaction(
accountsStore.currentPrivateKey,
data,
to,
);
const result = await $jsonRpc?.sendTransaction(signed);
const result = await rpcClient.sendTransaction(signed);

if (result?.status === 'success') {
transactionsStore.addTransaction({
Expand Down
14 changes: 5 additions & 9 deletions frontend/src/utils/db.ts → frontend/src/hooks/useDb.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
import type { ContractFile, DeployedContract, TransactionItem } from '@/types';
import Dexie, { type Table } from 'dexie';

export class GenLayerSimulatorDB extends Dexie {
class GenLayerSimulatorDB extends Dexie {
contractFiles!: Table<ContractFile>;
deployedContracts!: Table<DeployedContract>;
transactions!: Table<TransactionItem>;

constructor() {
super('genLayerSimulatorDB');
this.version(2).stores({
contractFiles: 'id, name, content, example, updatedAt',
deployedContracts: '[contractId+address]',
defaultContractStates: '[contractId+address]',
});

this.version(2).stores({
contractFiles: 'id', // Primary key and indexed props
contractFiles: 'id',
deployedContracts: '[contractId+address]',
defaultContractStates: null,
transactions:
'++id, type, status, contractAddress, localContractId, txId',
});
}
}

export const db = new GenLayerSimulatorDB();
export const useDb = () => {
return new GenLayerSimulatorDB();
};
13 changes: 13 additions & 0 deletions frontend/src/hooks/useFileName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const useFileName = () => {
function cleanupFileName(name: string) {
const tokens = name.split('.');
if (tokens.length > 0) {
return `${tokens[0]}.gpy`;
}
return `${name}.gpy`;
}

return {
cleanupFileName,
};
};
14 changes: 14 additions & 0 deletions frontend/src/utils/inputs.ts → frontend/src/hooks/useInputMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,17 @@ export const InputTypesMap: { [k: string]: any } = {
float: FloatField,
bool: BooleanField,
};

export const useInputMap = () => {
const getComponent = (type: string) => {
const component = InputTypesMap[type];

if (!component) {
throw new Error(`Component not found for input type: ${type}`);
}

return component;
};

return { getComponent };
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-useless-escape */
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';

export const pythonSyntaxDefinition: monaco.languages.IMonarchLanguage = {
const pythonSyntaxDefinition: monaco.languages.IMonarchLanguage = {
denishacquin marked this conversation as resolved.
Show resolved Hide resolved
defaultToken: '',
tokenPostfix: '.python',

Expand Down Expand Up @@ -213,3 +213,7 @@ export const pythonSyntaxDefinition: monaco.languages.IMonarchLanguage = {
],
},
};

export const usePythonSyntax = () => {
return pythonSyntaxDefinition;
};
6 changes: 6 additions & 0 deletions frontend/src/hooks/useRpcClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { RpcClient } from '@/clients/rpc';
import { JsonRpcService } from '@/services/JsonRpcService';

export function useRpcClient() {
cristiam86 marked this conversation as resolved.
Show resolved Hide resolved
return new JsonRpcService(new RpcClient());
}
Loading
Loading