Skip to content

Commit

Permalink
Merge branch 'main' into env/testnet
Browse files Browse the repository at this point in the history
  • Loading branch information
canhtrinh committed Jan 18, 2024
2 parents ccfe01e + 9058a45 commit 5d654ef
Show file tree
Hide file tree
Showing 15 changed files with 225 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export const ManageInterchainToken: FC<Props> = (props) => {
label: "Transfer Mintership",
value: "transferMintership",
icon: <GiftIcon className="h-7 w-7 md:h-8 md:w-8" />,
isVisible: () => false,
isVisible: (props) => props.isTokenMinter,
},
{
label: "Ownnership Pending Approval",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useCallback, useMemo, type FC } from "react";
import { useForm, type SubmitHandler } from "react-hook-form";

import { isAddress, TransactionExecutionError } from "viem";
import { useChainId, useWaitForTransaction } from "wagmi";
import { useAccount, useChainId, useWaitForTransaction } from "wagmi";

import { useInterchainTokenTransferMintership } from "~/lib/contracts/InterchainToken.hooks";
import { useTransactionState } from "~/lib/hooks/useTransactionState";
Expand All @@ -27,8 +27,9 @@ export const TransferInterchainTokenMintership: FC = () => {
const [txState, setTxState] = useTransactionState();
const [state] = useManageInterchainTokenContainer();
const chainId = useChainId();
const account = useAccount();

const { register, handleSubmit, formState, getValues } = useForm<FormState>({
const { register, handleSubmit, formState } = useForm<FormState>({
defaultValues: {
recipientAddress: undefined,
},
Expand All @@ -42,7 +43,7 @@ export const TransferInterchainTokenMintership: FC = () => {
data: transferResult,
} = useInterchainTokenTransferMintership({
address: state.tokenAddress,
account: getValues("recipientAddress"),
account: account.address,
});

const trpcContext = trpc.useUtils();
Expand Down Expand Up @@ -139,8 +140,7 @@ export const TransferInterchainTokenMintership: FC = () => {
</Dialog.Title>
{txState.status === "confirmed" ? (
<Alert status="success">
Token mintership has been successfully transferred. The recipient now
must accept the mintership transfer.
Token mintership has been successfully transferred.
</Alert>
) : (
<form
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useCallback, useMemo, type FC } from "react";
import { useForm, type SubmitHandler } from "react-hook-form";

import { isAddress, TransactionExecutionError } from "viem";
import { useChainId, useWaitForTransaction } from "wagmi";
import { useAccount, useChainId, useWaitForTransaction } from "wagmi";

import { useInterchainTokenServiceTransferOperatorship } from "~/lib/contracts/InterchainTokenService.hooks";
import { useTransactionState } from "~/lib/hooks/useTransactionState";
Expand All @@ -27,8 +27,9 @@ export const TransferInterchainTokenOperatorship: FC = () => {
const [txState, setTxState] = useTransactionState();
const [state] = useManageInterchainTokenContainer();
const chainId = useChainId();
const account = useAccount();

const { register, handleSubmit, formState, getValues } = useForm<FormState>({
const { register, handleSubmit, formState } = useForm<FormState>({
defaultValues: {
recipientAddress: undefined,
},
Expand All @@ -37,12 +38,12 @@ export const TransferInterchainTokenOperatorship: FC = () => {
});

const {
writeAsync: transferOwnershipAsync,
writeAsync: transferOperatorshipAsync,
isLoading: isTransfering,
data: transferResult,
} = useInterchainTokenServiceTransferOperatorship({
address: state.tokenAddress,
account: getValues("recipientAddress"),
account: account.address,
});

const trpcContext = trpc.useUtils();
Expand Down Expand Up @@ -70,7 +71,7 @@ export const TransferInterchainTokenOperatorship: FC = () => {
receipt,
});

toast.success("Successfully transferred token ownership");
toast.success("Successfully transferred token operatorship");
},
});

Expand All @@ -83,7 +84,7 @@ export const TransferInterchainTokenOperatorship: FC = () => {
});

try {
const txResult = await transferOwnershipAsync({
const txResult = await transferOperatorshipAsync({
args: [data.recipientAddress],
});

Expand All @@ -97,10 +98,10 @@ export const TransferInterchainTokenOperatorship: FC = () => {
} catch (error) {
if (error instanceof TransactionExecutionError) {
toast.error(
`Failed to transfer token ownership: ${error.cause.shortMessage}`
`Failed to transfer token operatorship: ${error.cause.shortMessage}`
);
logger.error(
`Failed to transfer token ownership: ${error.cause.message}`
`Failed to transfer token operatorship: ${error.cause.message}`
);

setTxState({
Expand All @@ -115,32 +116,31 @@ export const TransferInterchainTokenOperatorship: FC = () => {
});
}
},
[chainId, setTxState, transferOwnershipAsync]
[chainId, setTxState, transferOperatorshipAsync]
);

const buttonChildren = useMemo(() => {
switch (txState.status) {
case "idle":
case "confirmed":
return "Transfer token ownership";
return "Transfer token operatorship";
case "awaiting_approval":
return "Confirm on wallet";
case "submitted":
return "Transfering token ownership";
return "Transfering token operatorship";
case "reverted":
return "Failed to transfer ownership";
return "Failed to transfer operatorship";
}
}, [txState]);

return (
<>
<Dialog.Title className="flex">
<span>Transfer token ownership</span>
<span>Transfer rate-limit manager</span>
</Dialog.Title>
{txState.status === "confirmed" ? (
<Alert status="success">
Token ownership has been successfully transferred. The recipient now
must accept the ownership transfer.
Token operatorship has been successfully transferred.
</Alert>
) : (
<form
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,29 @@ export const RecentTransactionsTable: FC<Props> = ({
setPage(0);
}, [contractMethod]);

const { data: txns, isLoading } = trpc.gmp.getRecentTransactions.useQuery({
contractMethod,
senderAddress,
pageSize: maxTransactions,
page,
});
const { data: txns, isLoading } = trpc.gmp.getRecentTransactions.useQuery(
{
contractMethod,
senderAddress,
pageSize: maxTransactions,
page,
},
{
suspense: true,
}
);

const { data: prevPageTxns } = trpc.gmp.getRecentTransactions.useQuery({
contractMethod,
senderAddress,
pageSize: maxTransactions,
page: page > 0 ? page - 1 : 0,
});
const { data: prevPageTxns } = trpc.gmp.getRecentTransactions.useQuery(
{
contractMethod,
senderAddress,
pageSize: maxTransactions,
page: page > 0 ? page - 1 : 0,
},
{
suspense: true,
}
);

const { data: nextPageTxns } = trpc.gmp.getRecentTransactions.useQuery({
contractMethod,
Expand Down
88 changes: 87 additions & 1 deletion apps/maestro/src/pages/admin/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,97 @@
import { Button, Card, CopyToClipboardButton, Table } from "@axelarjs/ui";
import { useEffect, useState } from "react";

import { withRouteProtection } from "~/lib/auth";
import { trpc } from "~/lib/trpc";
import Page from "~/ui/layouts/Page";

const AdminIndexPage = () => {
return <Page>admin</Page>;
return (
<Page title="Admin" className="flex flex-1 flex-col gap-4" mustBeConnected>
<Page.Title>Admin Panel</Page.Title>
<Page.Content className="gap-4">
<GlobalMessageManager />
<AccountStatuses />
</Page.Content>
</Page>
);
};

export default withRouteProtection(AdminIndexPage, {
redirectTo: "/",
accountStatuses: ["privileged"],
});

const GlobalMessageManager = () => {
const { data: globalMessage } = trpc.messages.getGlobalMessage.useQuery();
const { mutateAsync: saveGlobalMessage, isLoading: isSavingGlobalMessage } =
trpc.messages.setGlobalMessage.useMutation();

const [newMessage, setNewMessage] = useState(globalMessage?.content || "");

useEffect(() => {
setNewMessage(globalMessage?.content || "");
}, [globalMessage]);

return (
<Card className="bg-base-200">
<Card.Body>
<Card.Title>Global Message</Card.Title>
<textarea
className="textarea"
value={newMessage}
onChange={(e) => {
setNewMessage(e.target.value);
}}
/>
<Card.Actions className="justify-end">
<Button
loading={isSavingGlobalMessage}
variant="primary"
onClick={async () => {
if (globalMessage) {
await saveGlobalMessage({
...globalMessage,
content: newMessage,
});
}
}}
>
Save global message
</Button>
</Card.Actions>
</Card.Body>
</Card>
);
};

const AccountStatuses = () => {
const { data: accountStatuses } = trpc.accounts.getAccountStatuses.useQuery();
return (
<Card className="bg-base-200">
<Card.Body>
<Card.Title>Account Statuses</Card.Title>
<Table>
<Table.Head>
<Table.Row>
<Table.Column>Address</Table.Column>
<Table.Column>Status</Table.Column>
</Table.Row>
</Table.Head>
<Table.Body>
{accountStatuses?.map((entry) => (
<Table.Row key={entry.accountAddress}>
<Table.Cell>
<CopyToClipboardButton>
{entry.accountAddress}
</CopyToClipboardButton>
</Table.Cell>
<Table.Cell>{entry.status}</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>
</Card.Body>
</Card>
);
};
45 changes: 26 additions & 19 deletions apps/maestro/src/pages/recent-transactions/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Tabs } from "@axelarjs/ui";
import { invert } from "@axelarjs/utils";
import { Suspense } from "react";

import { useAccount } from "wagmi";

Expand Down Expand Up @@ -36,25 +37,31 @@ const RecentTransactionsPage = () => {
>
<Page.Title>My Recent Transactions</Page.Title>
<div className="flex-1 space-y-4">
<Tabs boxed>
{CONTRACT_METHODS.map((method) => (
<Tabs.Tab
key={method}
onClick={(e) => {
e.preventDefault();
setTab(REVERSE_TAB_MAP[method]);
}}
active={contractMethod === method}
>
{CONTRACT_METHODS_LABELS[method]}
</Tabs.Tab>
))}
</Tabs>
<RecentTransactionsTable
contractMethod={contractMethod}
senderAddress={address}
maxTransactions={20}
/>
<Suspense
fallback={
<Page.FullScreenLoading loadingMessage="loading recent transactions..." />
}
>
<Tabs boxed>
{CONTRACT_METHODS.map((method) => (
<Tabs.Tab
key={method}
onClick={(e) => {
e.preventDefault();
setTab(REVERSE_TAB_MAP[method]);
}}
active={contractMethod === method}
>
{CONTRACT_METHODS_LABELS[method]}
</Tabs.Tab>
))}
</Tabs>
<RecentTransactionsTable
contractMethod={contractMethod}
senderAddress={address}
maxTransactions={20}
/>
</Suspense>
</div>
</Page>
);
Expand Down
2 changes: 2 additions & 0 deletions apps/maestro/src/server/routers/_app.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { publicProcedure, router } from "~/server/trpc";
import { accountsRouter } from "./accounts";
import { authRouter } from "./auth";
import { axelarConfigsRouter } from "./axelarConfigs";
import { axelarjsSDKRouter } from "./axelarjsSDK";
Expand All @@ -22,6 +23,7 @@ export const appRouter = router({
auth: authRouter,
openai: openaiRouter,
messages: messagesRouter,
accounts: accountsRouter,
});

export type AppRouter = typeof appRouter;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { publicProcedure } from "~/server/trpc";

export const getAccountStatuses = publicProcedure.query(async ({ ctx }) => {
return await ctx.persistence.kv.getAccounStatuses();
});
8 changes: 8 additions & 0 deletions apps/maestro/src/server/routers/accounts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { router } from "~/server/trpc";
import { getAccountStatuses } from "./getAccountStatuses";

export const accountsRouter = router({
getAccountStatuses,
});

export type AccountsRouter = typeof accountsRouter;
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ export const getERC20TokenBalanceForOwner = publicProcedure
chainConfig,
input.tokenAddress
);
const isTokenMinter = await itClient.reads
.isMinter({
addr: input.owner,
})
.catch(always(false));
const [isTokenMinter] = await Promise.all([
itClient.reads
.isMinter({
addr: input.owner,
})
.catch(always(false)),
]);

return {
isTokenMinter,
Expand Down
Loading

0 comments on commit 5d654ef

Please sign in to comment.