Skip to content

Commit

Permalink
feat: sim replace frontend rpc calls with genlayerjs (#600)
Browse files Browse the repository at this point in the history
* install genlayer js

* contract queries OK

* get transaction with genlayer client

* update transaction unit tests

* accounts and client working

* extract shorten address hook, update unit tests

* cleanup todos

* cleanup

* cleanup comments

* fix pkg lock

* allow returning null tx

* update params for leader only

* update genlayer-js and use new contract schema methods

* bump genlayer-js version to include support for leaderOnly param

* fix typing with genlayer-js/genvm

* update genlayer-js

* fix cleanup local tx logic

* fix unit test

* remove redundant typing and use genlayer-js types as truth

* fix precommit

* bump genlayer-js version

* update leaderOnly casing in contract queries

* regen package lock

* bumb genlayer-js version

---------

Co-authored-by: Den <[email protected]>
Co-authored-by: Cristiam Da Silva <[email protected]>
  • Loading branch information
3 people authored Dec 4, 2024
1 parent 78ff5cf commit ff5fcb7
Show file tree
Hide file tree
Showing 27 changed files with 1,657 additions and 504 deletions.
1,636 changes: 1,466 additions & 170 deletions frontend/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"defu": "^6.1.4",
"dexie": "^4.0.4",
"floating-vue": "^5.2.2",
"genlayer-js": "^0.4.6",
"hash-sum": "^2.0.0",
"jump.js": "^1.0.2",
"lodash-es": "^4.17.21",
Expand Down
59 changes: 0 additions & 59 deletions frontend/src/clients/web3.ts

This file was deleted.

10 changes: 4 additions & 6 deletions frontend/src/components/Simulator/AccountItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { PowerCircle } from 'lucide-vue-next';
import { ref } from 'vue';
import CopyTextButton from '../global/CopyTextButton.vue';
import { TrashIcon, CheckCircleIcon } from '@heroicons/vue/16/solid';
import type { Account } from 'genlayer-js/types';
const store = useAccountsStore();
const setCurentAddress = () => {
Expand Down Expand Up @@ -35,6 +35,7 @@ const deleteAddress = () => {
const props = defineProps<{
active?: Boolean;
account: Account;
privateKey: `0x${string}`;
canDelete?: Boolean;
}>();
Expand All @@ -61,16 +62,13 @@ const showConfirmDelete = ref(false);
class="flex grow flex-row truncate font-mono text-xs font-semibold"
:class="[!active && 'opacity-50']"
>
{{ store.accountFromPrivateKey(privateKey).address }}
{{ account.address }}
</span>

<div
class="flex flex-row items-center gap-1 opacity-0 group-hover:opacity-100"
>
<CopyTextButton
:text="store.accountFromPrivateKey(privateKey).address"
v-tooltip="'Copy Address'"
/>
<CopyTextButton :text="account.address" v-tooltip="'Copy Address'" />

<Transition mode="out-in" v-if="canDelete">
<button
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/Simulator/AccountSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Wallet } from 'lucide-vue-next';
import { PlusIcon } from '@heroicons/vue/16/solid';
import { notify } from '@kyvg/vue3-notification';
import { useEventTracking } from '@/hooks';
import { createAccount } from 'genlayer-js';
const store = useAccountsStore();
const { trackEvent } = useEventTracking();
Expand Down Expand Up @@ -42,6 +42,7 @@ const handleCreateNewAccount = async () => {
v-for="privateKey in store.privateKeys"
:key="privateKey"
:privateKey="privateKey"
:account="createAccount(privateKey)"
:active="privateKey === store.currentPrivateKey"
:canDelete="true"
v-close-popper
Expand Down
5 changes: 1 addition & 4 deletions frontend/src/components/Simulator/ConstructorParameters.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useContractQueries } from '@/hooks';
import { ref, computed } from 'vue';
import PageSection from '@/components/Simulator/PageSection.vue';
import { ArrowUpTrayIcon } from '@heroicons/vue/16/solid';
import type { ContractMethodBase } from '@/types';
import ContractParams from './ContractParams.vue';
import { type ArgData, unfoldArgsData } from './ContractParams';
Expand All @@ -18,9 +17,7 @@ const { data, isPending, isRefetching, isError } = contractSchemaQuery;
const calldataArguments = ref<ArgData>({ args: [], kwargs: {} });
const ctorMethod = computed(
() => data.value?.ctor as ContractMethodBase | undefined,
);
const ctorMethod = computed(() => data.value.ctor);
const emit = defineEmits(['deployed-contract']);
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/Simulator/ContractInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import PageSection from '@/components/Simulator/PageSection.vue';
import { CheckCircleIcon } from '@heroicons/vue/24/outline';
import EmptyListPlaceholder from '@/components/Simulator/EmptyListPlaceholder.vue';
import { useNodeStore } from '@/stores';
import { useWallet, useContractQueries } from '@/hooks';
import { useContractQueries, useShortAddress } from '@/hooks';
import { UploadIcon } from 'lucide-vue-next';
const nodeStore = useNodeStore();
const { shortenAddress } = useWallet();
const { shorten } = useShortAddress();
defineProps<{
showNewDeploymentButton: boolean;
Expand Down Expand Up @@ -36,7 +36,7 @@ const { isDeployed, address, contract } = useContractQueries();
Deployed at

<div class="font-semibold">
{{ shortenAddress(address) }}
{{ shorten(address) }}
</div>

<CopyTextButton :text="address" />
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Simulator/ContractMethodItem.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import type { ContractMethod } from '@/types';
import type { ContractMethod } from 'genlayer-js/types';
import { ref } from 'vue';
import { Collapse } from 'vue-collapsed';
import { notify } from '@kyvg/vue3-notification';
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/components/Simulator/ContractParams.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<script setup lang="ts">
import { useInputMap } from '@/hooks';
import type { ContractMethodBase, ContractParamsSchema } from '@/types';
import type {
ContractMethodBase,
ContractParamsSchema,
} from 'genlayer-js/types';
import { onMounted, ref, watch } from 'vue';
import { AnyFieldValue } from '../global/fields/AnyFieldValue';
import EmptyListPlaceholder from '@/components/Simulator/EmptyListPlaceholder.vue';
Expand Down
7 changes: 3 additions & 4 deletions frontend/src/components/Simulator/ContractReadMethods.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import { useContractQueries } from '@/hooks';
import { computed } from 'vue';
import PageSection from '@/components/Simulator/PageSection.vue';
import { type ContractMethod } from '@/types';
import ContractMethodItem from '@/components/Simulator/ContractMethodItem.vue';
import EmptyListPlaceholder from '@/components/Simulator/EmptyListPlaceholder.vue';
import type { ContractSchema } from 'genlayer-js/types';
const props = defineProps<{
leaderOnly: boolean;
Expand All @@ -15,9 +15,8 @@ const { contractAbiQuery } = useContractQueries();
const { data, isPending, isError, error, isRefetching } = contractAbiQuery;
const readMethods = computed(() => {
return Object.entries(
data.value.methods as { [key: string]: ContractMethod },
).filter((x) => x[1].readonly);
const methods = (data.value as ContractSchema).methods;
return Object.entries(methods).filter((x) => x[1].readonly);
});
</script>

Expand Down
8 changes: 3 additions & 5 deletions frontend/src/components/Simulator/ContractWriteMethods.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
import { useContractQueries } from '@/hooks';
import { computed } from 'vue';
import PageSection from '@/components/Simulator/PageSection.vue';
import { type ContractMethod } from '@/types';
import ContractMethodItem from '@/components/Simulator/ContractMethodItem.vue';
import EmptyListPlaceholder from '@/components/Simulator/EmptyListPlaceholder.vue';
import type { ContractSchema } from 'genlayer-js/types';
const props = defineProps<{
leaderOnly: boolean;
}>();
Expand All @@ -15,9 +14,8 @@ const { contractAbiQuery } = useContractQueries();
const { data, isPending, isError, error, isRefetching } = contractAbiQuery;
const writeMethods = computed(() => {
return Object.entries(
data.value.methods as { [key: string]: ContractMethod },
).filter((x) => !x[1].readonly);
const methods = (data.value as ContractSchema).methods;
return Object.entries(methods).filter((x) => !x[1].readonly);
});
</script>

Expand Down
3 changes: 2 additions & 1 deletion frontend/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
export * from './useUniqueId';
export * from './useEventTracking';
export * from './useRpcClient';
export * from './useWallet';
export * from './useDb';
export * from './useWebSocketClient';
export * from './useInputMap';
export * from './useContractQueries';
export * from './useFileName';
export * from './useSetupStores';
export * from './useGenlayer';
export * from './useShortAddress';
export * from './useConfig';
export * from './useTransactionListener';
73 changes: 32 additions & 41 deletions frontend/src/hooks/useContractQueries.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { watch, ref, computed } from 'vue';
import { useQuery, useQueryClient } from '@tanstack/vue-query';
import type { Address, TransactionItem } from '@/types';
import type { TransactionItem } from '@/types';
import {
useContractsStore,
useTransactionsStore,
Expand All @@ -9,19 +9,23 @@ import {
import { useDebounceFn } from '@vueuse/core';
import { notify } from '@kyvg/vue3-notification';
import { useMockContractData } from './useMockContractData';
import { useEventTracking, useRpcClient, useWallet } from '@/hooks';
import { useEventTracking, useGenlayer } from '@/hooks';
import * as calldata from '@/calldata';
import type {
Address,
TransactionHash,
ContractSchema,
} from 'genlayer-js/types';

const schema = ref<any>();

export function useContractQueries() {
const rpcClient = useRpcClient();
const genlayer = useGenlayer();
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 @@ -63,9 +67,9 @@ export function useContractQueries() {
return mockContractSchema;
}

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

schema.value = result;

Expand All @@ -87,24 +91,17 @@ export function useContractQueries() {
if (!contract.value || !accountsStore.currentPrivateKey) {
throw new Error('Error Deploying the contract');
}
const data = [
contract.value?.content ?? '',
calldata.encode(args),
leaderOnly,
];

const nonce = await accountsStore.getCurrentNonce();

const signed = await wallet.signTransaction({
privateKey: accountsStore.currentPrivateKey,
data,
nonce,
const result = await genlayer.client?.deployContract({
code: contract.value?.content ?? '',
args: args.args,
leaderOnly,
});
const result = await rpcClient.sendTransaction(signed);

const tx: TransactionItem = {
contractAddress: '',
localContractId: contract.value?.id ?? '',
hash: result,
hash: result as TransactionHash,
type: 'deploy',
status: 'PENDING',
data: {},
Expand Down Expand Up @@ -154,9 +151,9 @@ export function useContractQueries() {
return mockContractSchema;
}

const result = await rpcClient.getDeployedContractSchema({
address: deployedContract.value?.address ?? '',
});
const result = await genlayer.client?.getContractSchema(
deployedContract.value?.address ?? '',
);

return result;
}
Expand All @@ -169,13 +166,10 @@ export function useContractQueries() {
},
) {
try {
const data = [calldata.encode({ method, ...args })];
const encodedData = wallet.encodeTransactionData(data);

const result = await rpcClient.getContractState({
to: address.value || '',
from: accountsStore.currentUserAddress,
data: encodedData,
const result = await genlayer.client?.readContract({
address: address.value as Address,
functionName: method,
args: args.args,
});

return result;
Expand All @@ -199,21 +193,17 @@ export function useContractQueries() {
}) {
try {
if (!accountsStore.currentPrivateKey) {
throw new Error('Error Deploying the contract');
throw new Error('Error writing to contract');
}
const data = [calldata.encode({ method, ...args }), leaderOnly];
const to = (address.value as Address) || null;

const nonce = await accountsStore.getCurrentNonce();

const signed = await wallet.signTransaction({
privateKey: accountsStore.currentPrivateKey,
data,
nonce,
to,
const result = await genlayer.client?.writeContract({
address: address.value as Address,
functionName: method,
args: args.args,
value: BigInt(0),
leaderOnly,
});

const result = await rpcClient.sendTransaction(signed);
transactionsStore.addTransaction({
contractAddress: address.value || '',
localContractId: contract.value?.id || '',
Expand All @@ -228,6 +218,7 @@ export function useContractQueries() {
});
return true;
} catch (error) {
console.error(error);
throw new Error('Error writing to contract');
}
}
Expand Down
Loading

0 comments on commit ff5fcb7

Please sign in to comment.