Skip to content

Commit

Permalink
😄
Browse files Browse the repository at this point in the history
  • Loading branch information
nerderlyne committed Feb 25, 2024
1 parent f5c1b4f commit 05e05ec
Show file tree
Hide file tree
Showing 6 changed files with 767 additions and 657 deletions.
4 changes: 3 additions & 1 deletion ui/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { Version } from "./version";
export const Header = () => {
return (
<div className="mb-3">
<p>Nani Intents Shell <Version /></p>
<p>
Nani Intents Shell <Version />
</p>
<p className="mb-2">(c) 2024 Nani Kotoba DAO LLC. All rights reserved.</p>
<Account />
</div>
Expand Down
6 changes: 1 addition & 5 deletions ui/components/providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ const config = getDefaultConfig({
appName: siteConfig.name,
appDescription: siteConfig.description,
projectId: process.env.NEXT_PUBLIC_WC_ID!,
chains: [
mainnet,
sepolia,
arbitrum
],
chains: [mainnet, sepolia, arbitrum],
ssr: true,
});

Expand Down
290 changes: 203 additions & 87 deletions ui/components/shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
usePublicClient,
useWriteContract,
} from "wagmi";
import { IntentsEngineAbi } from "../lib/abi/IntentsEngineAbi";
import { ETH_ADDRESS, IE_ADDRESS } from "../lib/constants";
import {
erc20Abi,
Expand All @@ -19,10 +18,12 @@ import {
maxUint256,
zeroAddress,
} from "viem";
import { mainnet } from "viem/chains";
import { arbitrum, mainnet } from "viem/chains";
import useShellStore from "@/lib/use-shell-store";
import { ShellHistory } from "./shell-history";
import { cn } from "@/lib/utils";
import { IntentsEngineAbi } from "@/lib/abi/IntentsEngineAbi";
import { IntentsEngineAbiArb } from "@/lib/abi/IntentsEngineAbiArb";

const formSchema = z.object({
command: z.string().min(2),
Expand Down Expand Up @@ -57,7 +58,7 @@ export const Shell = () => {
chainId: mainnet.id,
});
const { writeContractAsync } = useWriteContract();

const client = usePublicClient({
chainId: chain ? chain.id : mainnet.id,
});
Expand Down Expand Up @@ -85,105 +86,217 @@ export const Shell = () => {
addLine(<p className="text-[red]">{error.message}</p>);
};

async function onSubmit({ command }: z.infer<typeof formSchema>) {
try {
form.reset();
addCommand({ chainId: chain?.id, user: name ?? address, command });
if (!client) throw new Error("No client available");
if (!address) throw new Error("No wallet connected");
if (!chain) throw new Error("No chain connected");
async function handleArbCommand(command: string) {
if (!client) throw new Error("No client available");
if (!address) throw new Error("No wallet connected");

const ieAddress = IE_ADDRESS[chain.id];
const ieAddress = IE_ADDRESS[arbitrum.id];

let value = 0n;
let value = 0n;

const preview = await client.readContract({
address: ieAddress,
abi: IntentsEngineAbi,
functionName: "previewCommand",
args: [command],
const preview = await client.readContract({
address: ieAddress,
abi: IntentsEngineAbiArb,
functionName: "previewCommand",
args: [command],
});
const previewedToken = preview[3];

addLine(<p>Preview: {serialize(preview)}</p>);

if (isAddressEqual(previewedToken, zeroAddress)) {
// invalid token
throw new Error(
"This token is not supported by the Intents Engine. Did you misspell the token symbol?",
);
}

if (isAddressEqual(previewedToken, ETH_ADDRESS)) {
// sending ether directly
value = preview[1];
} else {
// consent to spend tokens
const allowance = await client.readContract({
address: previewedToken,
abi: erc20Abi,
functionName: "allowance",
args: [address, ieAddress],
});

addLine(<p>Preview: {serialize(preview)}</p>);
if (allowance < preview[1]) {
// we do a lil approve dance
const approveTxHash = await writeContractAsync({
address: previewedToken,
abi: erc20Abi,
functionName: "approve",
args: [ieAddress, maxUint256],
});

addLine(
<p>
Approve TX Hash:{" "}
<a
href={`https://etherscan.io/tx/${approveTxHash}`}
target="_blank"
rel="noreferrer"
>
{approveTxHash}
</a>
</p>,
);

const allowanceReceipt = await client.waitForTransactionReceipt({
hash: approveTxHash,
confirmations: 1,
});

if (isAddressEqual(preview[2], zeroAddress)) {
// invalid token
throw new Error("This token is not supported by the Intents Engine. Did you misspell the token symbol?");
addLine(<p>Allowance Set. Receipt: {serialize(allowanceReceipt)}</p>);
}
}

const commandTxHash = await writeContractAsync({
address: ieAddress,
abi: IntentsEngineAbiArb,
functionName: "command",
value,
args: [command],
});

addLine(
<p>
Command TX Hash:{" "}
<a
href={`https://etherscan.io/tx/${commandTxHash}`}
target="_blank"
rel="noreferrer"
>
{commandTxHash}
</a>
</p>,
);

const commandReceipt = await client.waitForTransactionReceipt({
hash: commandTxHash,
confirmations: 1,
});

addLine(<p>Command Executed. Receipt: {JSON.stringify(commandReceipt)}</p>);
}

async function handleMainnetCommand(command: string) {
if (!client) throw new Error("No client available");
if (!address) throw new Error("No wallet connected");

const ieAddress = IE_ADDRESS[mainnet.id];

let value = 0n;

if (isAddressEqual(preview[2], ETH_ADDRESS)) {
// sending ether directly
value = preview[1];
} else {
// consent to spend tokens
const allowance = await client.readContract({
const preview = await client.readContract({
address: ieAddress,
abi: IntentsEngineAbi,
functionName: "previewCommand",
args: [command],
});

addLine(<p>Preview: {serialize(preview)}</p>);

if (isAddressEqual(preview[2], zeroAddress)) {
// invalid token
throw new Error(
"This token is not supported by the Intents Engine. Did you misspell the token symbol?",
);
}

if (isAddressEqual(preview[2], ETH_ADDRESS)) {
// sending ether directly
value = preview[1];
} else {
// consent to spend tokens
const allowance = await client.readContract({
address: preview[2],
abi: erc20Abi,
functionName: "allowance",
args: [address, ieAddress],
});

if (allowance < preview[1]) {
// we do a lil approve dance
const approveTxHash = await writeContractAsync({
address: preview[2],
abi: erc20Abi,
functionName: "allowance",
args: [address, ieAddress],
functionName: "approve",
args: [ieAddress, maxUint256],
});

if (allowance < preview[1]) {
// we do a lil approve dance
const approveTxHash = await writeContractAsync({
address: preview[2],
abi: erc20Abi,
functionName: "approve",
args: [ieAddress, maxUint256],
});

addLine(
<p>
Approve TX Hash:{" "}
<a
href={`https://etherscan.io/tx/${approveTxHash}`}
target="_blank"
rel="noreferrer"
>
{approveTxHash}
</a>
</p>,
);

const allowanceReceipt = await client.waitForTransactionReceipt({
hash: approveTxHash,
confirmations: 1,
});

addLine(<p>Allowance Set. Receipt: {serialize(allowanceReceipt)}</p>);
}

addLine(
<p>
Approve TX Hash:{" "}
<a
href={`https://etherscan.io/tx/${approveTxHash}`}
target="_blank"
rel="noreferrer"
>
{approveTxHash}
</a>
</p>,
);

const allowanceReceipt = await client.waitForTransactionReceipt({
hash: approveTxHash,
confirmations: 1,
});

addLine(<p>Allowance Set. Receipt: {serialize(allowanceReceipt)}</p>);
}
}

const commandTxHash = await writeContractAsync({
address: ieAddress,
abi: IntentsEngineAbi,
functionName: "command",
value,
args: [command],
});
const commandTxHash = await writeContractAsync({
address: ieAddress,
abi: IntentsEngineAbi,
functionName: "command",
value,
args: [command],
});

addLine(
<p>
Command TX Hash:{" "}
<a
href={`https://etherscan.io/tx/${commandTxHash}`}
target="_blank"
rel="noreferrer"
>
{commandTxHash}
</a>
</p>,
);
addLine(
<p>
Command TX Hash:{" "}
<a
href={`https://etherscan.io/tx/${commandTxHash}`}
target="_blank"
rel="noreferrer"
>
{commandTxHash}
</a>
</p>,
);

const commandReceipt = await client.waitForTransactionReceipt({
hash: commandTxHash,
confirmations: 1,

});
const commandReceipt = await client.waitForTransactionReceipt({
hash: commandTxHash,
confirmations: 1,
});

addLine(
<p>Command Executed. Receipt: {JSON.stringify(commandReceipt)}</p>,
);
addLine(<p>Command Executed. Receipt: {JSON.stringify(commandReceipt)}</p>);
}

async function onSubmit({ command }: z.infer<typeof formSchema>) {
try {
form.reset();
addCommand({ chainId: chain?.id, user: name ?? address, command });
if (!client) throw new Error("No client available");
if (!address) throw new Error("No wallet connected");
if (!chain) throw new Error("No chain connected");

switch (chain.id) {
case arbitrum.id:
await handleArbCommand(command);
break;
case mainnet.id:
await handleMainnetCommand(command);
break;
default:
throw new Error("Unsupported chain");
}
} catch (error) {
console.error(error);
error instanceof Error
Expand Down Expand Up @@ -212,7 +325,10 @@ export const Shell = () => {
{id}
<FormControl>
<input
className={cn("command-prompt-input", " min-w-3/4 focus:outline-none w-full")}
className={cn(
"command-prompt-input",
" min-w-3/4 focus:outline-none w-full",
)}
{...field}
/>
</FormControl>
Expand Down
21 changes: 9 additions & 12 deletions ui/components/version.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
'use client'
import { useAccount } from "wagmi"
"use client";
import { useAccount } from "wagmi";

const versions: {
[key: number]: string
[key: number]: string;
} = {
1: "1.0.0",
42161: "1.0.1 (nightly)",
}
1: "1.0.0",
42161: "1.0.1 (nightly)",
};

export const Version = () => {
const { chain } = useAccount();

return <span>
{`[ Version ${versions[chain ? chain.id : 1]} ]`}
</span>
}
const { chain } = useAccount();

return <span>{`[ Version ${versions[chain ? chain.id : 1]} ]`}</span>;
};
Loading

0 comments on commit 05e05ec

Please sign in to comment.