diff --git a/components/workspace/cli.tsx b/components/workspace/cli.tsx index 1ef9c73..a720c51 100644 --- a/components/workspace/cli.tsx +++ b/components/workspace/cli.tsx @@ -2,12 +2,7 @@ import { build } from "@/data/build"; import { db } from "@/data/db"; -import { - getProposalInfo, - useDeploy, - useLogs, - useTransactionResult, -} from "@/data/wallet"; +import { useWallet } from "@/data/wallet"; import { useTheme } from "next-themes"; import { useParams } from "next/navigation"; import { ReactTerminal } from "react-terminal"; @@ -15,9 +10,7 @@ import { z } from "zod"; export default function Cli() { const { id } = useParams(); - const deploy = useDeploy(); - const getResult = useTransactionResult(); - const getLogs = useLogs(); + const wallet = useWallet(); const commands = { help: () => (
@@ -54,10 +47,13 @@ export default function Cli() { if (typeof id !== "string") return "Workspace id not found."; const { dll } = (await db.workspaces.get(id)) || {}; if (!dll) return "Contract not built. Please build first."; - const { TransactionId } = await deploy(dll); + if (!wallet) return "Wallet not ready."; try { - const result: { TransactionId: string; Status: string } = - await getResult(TransactionId); + await wallet.faucet(); + } catch (err) {} + const { TransactionId } = await wallet.deploy(dll); + try { + const result = await wallet.getTxResult(TransactionId); return `TransactionId: ${TransactionId}, Status: ${result.Status}`; } catch (err) { return JSON.stringify(err, undefined, 2); @@ -65,14 +61,16 @@ export default function Cli() { }, check: async (id: string) => { if (!id) return `Please enter the Transaction ID.`; + if (!wallet) return "Wallet not ready."; try { - const result = await getResult(id); - const logs = await getLogs(id); + const result = await wallet.getTxResult(id); + const logs = await wallet.getLogs(id); const { data } = z.object({ proposalId: z.string() }).safeParse(logs); - const proposalInfo = await getProposalInfo(data?.proposalId); + if (!data?.proposalId) return "Missing proposalId."; + const proposalInfo = await wallet.getProposalInfo(data?.proposalId); const releasedTxId = proposalInfo?.data.proposal.releasedTxId; const releasedTxLogs = releasedTxId - ? await getLogs(releasedTxId) + ? await wallet.getLogs(releasedTxId) : undefined; const { data: contractAddressData } = z .object({ address: z.string() }) diff --git a/data/wallet.ts b/data/wallet.ts index 2216fd1..0f4000b 100644 --- a/data/wallet.ts +++ b/data/wallet.ts @@ -32,142 +32,110 @@ export function useWallet() { if (!privateKey) return; - const wallet = AElf.wallet.getWalletByPrivateKey(privateKey); - - return wallet; + return new Wallet(privateKey); } -function useChainStatus() { - const { data } = useSWR("chainstatus", async () => { - return await aelf.chain.getChainStatus(); - }); +class Wallet { + privateKey; + wallet; + cached: Record = {}; - return data as { GenesisContractAddress: string }; -} + constructor(privateKey: string) { + this.privateKey = privateKey; + this.wallet = AElf.wallet.getWalletByPrivateKey(privateKey); + } -function useContract(address: string) { - const wallet = useWallet(); - const { data } = useSWR( - wallet && address ? `contract-${address}` : null, - async () => { - return await aelf.chain.contractAt(address, wallet); - } - ); + async faucet() { + const res = await fetch( + `https://faucet.aelf.dev/api/claim?walletAddress=${this.wallet.address}`, + { method: "POST" } + ); - return data; -} + const data = await res.json(); + console.log(data); + } -function useContractAddressByName(name: string) { - const chainStatus = useChainStatus(); - const genesisContract = useContract(chainStatus.GenesisContractAddress); + private async getChainStatus() { + return await aelf.chain.getChainStatus(); + } - const { data } = useSWR( - genesisContract ? `${name}-address` : null, - async () => { - return await genesisContract.GetContractAddressByName.call( - AElf.utils.sha256(name) - ); - } - ); + private getContract(address: string) { + return aelf.chain.contractAt(address, this.wallet); + } - return data; -} + private async getGenesisContract() { + const chainStatus = await this.getChainStatus(); + return await this.getContract(chainStatus.GenesisContractAddress); + } -function useTokenContractAddress() { - return useContractAddressByName(`AElf.ContractNames.Token`); -} + private async getContractAddressByName(name: string) { + const genesisContract = await this.getGenesisContract(); + return await genesisContract.GetContractAddressByName.call( + AElf.utils.sha256(name) + ); + } -export function useTokenContract() { - const tokenContractAddress = useTokenContractAddress(); - return useContract(tokenContractAddress); -} + private async getTokenContractAddress() { + return await this.getContractAddressByName(`AElf.ContractNames.Token`); + } -function useBalance() { - const tokenContract = useTokenContract(); - const wallet = useWallet(); - const { data } = useSWR( - tokenContract && wallet ? `balance` : null, - async () => { - return await tokenContract.GetBalance.call({ - symbol: "ELF", - owner: wallet.address, - }); - } - ); + private async getTokenContract() { + const tokenContractAddress = await this.getTokenContractAddress(); - return data as { - symbol: string; - owner: string; - balance: string; - }; -} + return this.getContract(tokenContractAddress); + } -export function useBalanceInELF() { - const balance = useBalance(); - return new BigNumber(balance.balance).dividedBy(10 ** 8).toFixed(5); -} + async getBalance() { + const tokenContract = await this.getTokenContract(); + const res = await tokenContract.GetBalance.call({ + symbol: "ELF", + owner: this.wallet.address, + }); -function useGenesisContract() { - const chainstatus = useChainStatus(); - return useContract(chainstatus?.GenesisContractAddress); -} + return new BigNumber(res.balance).dividedBy(10 ** 8).toFixed(5); + } -export function useDeploy() { - const genesisContract = useGenesisContract(); + async deploy(code: string): Promise<{ TransactionId: string }> { + const genesisContract = await this.getGenesisContract(); - const deploy = async (code: string) => { - return (await genesisContract.DeployUserSmartContract({ + return await genesisContract.DeployUserSmartContract({ category: 0, code, - })) as { TransactionId: string }; - }; - - return deploy; -} + }); + } -export function useTransactionResult() { - return async (id: string) => { + async getTxResult( + id: string + ): Promise<{ TransactionId: string; Status: string }> { return await aelf.chain.getTxResult(id); - }; -} + } -let cached: Record = {}; + private async getProto(address: string) { + const key = aelf.currentProvider.host + "_" + address; + if (!this.cached[key]) + this.cached[key] = await aelf.chain.getContractFileDescriptorSet(address); + return AElf.pbjs.Root.fromDescriptor(this.cached[key]); + } -async function getProto(address: string) { - const key = aelf.currentProvider.host + "_" + address; - if (!cached[key]) - cached[key] = await aelf.chain.getContractFileDescriptorSet(address); - return AElf.pbjs.Root.fromDescriptor(cached[key]); -} + async getLogs(txId: string) { + const txResult = await aelf.chain.getTxResult(txId); -export function useLogs() { - return async (txId: string) => { - try { - const txResult = await aelf.chain.getTxResult(txId); + const services = await Promise.all( + txResult.Logs.map( + async ({ Address }: { Address: string }) => await this.getProto(Address) + ) + ); - const deserializeLogs = async () => { - const services = await Promise.all( - txResult.Logs.map( - async ({ Address }: { Address: string }) => await getProto(Address) - ) - ); + const deserializedLogs: Array<{ proposalId: string }> = + await deserializeLog(txResult.Logs, services); - const deserializedLogs: Array<{ proposalId: string }> = - await deserializeLog(txResult.Logs, services); + return deserializedLogs.reduce((acc, cur) => ({ ...acc, ...cur }), {}); + } - return deserializedLogs.reduce((acc, cur) => ({ ...acc, ...cur }), {}); - }; + async getProposalInfo(proposalId: string) { + const res = await fetch(`/api/get-proposal-info?id=${proposalId}`); + const data: ProposalInfo = await res.json(); - return await deserializeLogs(); - } catch (err: unknown) { - return err; - } - }; + return data; + } } - -export async function getProposalInfo(proposalId?: string) { - const res = await fetch(`/api/get-proposal-info?id=${proposalId}`); - const data: ProposalInfo = await res.json(); - - return data; -} \ No newline at end of file