Skip to content

Commit

Permalink
task6
Browse files Browse the repository at this point in the history
  • Loading branch information
flatflax committed Dec 6, 2024
1 parent 755c954 commit 00834b4
Show file tree
Hide file tree
Showing 15 changed files with 424 additions and 1 deletion.
35 changes: 35 additions & 0 deletions mover/flatflax/code/task6/my-first-sui-dapp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Sui dApp Starter Template

This dApp was created using `@mysten/create-dapp` that sets up a basic React
Client dApp using the following tools:

- [React](https://react.dev/) as the UI framework
- [TypeScript](https://www.typescriptlang.org/) for type checking
- [Vite](https://vitejs.dev/) for build tooling
- [Radix UI](https://www.radix-ui.com/) for pre-built UI components
- [ESLint](https://eslint.org/)
- [`@mysten/dapp-kit`](https://sdk.mystenlabs.com/dapp-kit) for connecting to
wallets and loading data
- [pnpm](https://pnpm.io/) for package management

## Starting your dApp

To install dependencies you can run

```bash
pnpm install
```

To start your dApp in development mode run

```bash
pnpm dev
```

## Building

To build your app for deployment you can run

```bash
pnpm build
```
59 changes: 59 additions & 0 deletions mover/flatflax/code/task6/my-first-sui-dapp/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<!doctype html>
<html lang="en" class="dark-theme" style="color-scheme: dark">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sui dApp Starter</title>

<style>
/*
Josh's Custom CSS Reset
https://www.joshwcomeau.com/css/custom-css-reset/
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
* {
margin: 0;
}
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}
input,
button,
textarea,
select {
font: inherit;
}
p,
h1,
h2,
h3,
h4,
h5,
h6 {
overflow-wrap: break-word;
}
#root,
#__next {
isolation: isolate;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
36 changes: 36 additions & 0 deletions mover/flatflax/code/task6/my-first-sui-dapp/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "my-first-sui-dapp",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@mysten/dapp-kit": "0.14.40",
"@mysten/sui": "1.16.0",
"@radix-ui/colors": "^3.0.0",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/themes": "^3.1.1",
"@tanstack/react-query": "^5.50.1",
"navi-sdk": "^1.4.7",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.16.0",
"@typescript-eslint/parser": "^7.16.0",
"@vitejs/plugin-react-swc": "^3.7.0",
"eslint": "^9.6.0",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.7",
"prettier": "^3.3.2",
"typescript": "^5.5.3",
"vite": "^5.3.3"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// eslint-disable-next-line no-undef
module.exports = {
proseWrap: "always",
};
132 changes: 132 additions & 0 deletions mover/flatflax/code/task6/my-first-sui-dapp/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { ConnectButton } from "@mysten/dapp-kit";
import { WalletStatus } from "./WalletStatus";
import { Button, Container, Flex, Text, Box, Heading } from "@radix-ui/themes"; // 导入 Radix UI 组件
import { useCurrentAccount, useSignAndExecuteTransaction } from "@mysten/dapp-kit"; // 导入 Mysten DApp Kit 钩子
import { Transaction } from "@mysten/sui/transactions"; // 导入 Sui 交易类
import { Pool, PoolConfig } from "navi-sdk/dist/types"; // 导入 Navi SDK 中的池和池配置类型
import { pool, Sui, wUSDC } from "navi-sdk/dist/address"; // 导入 Navi SDK 中的池地址和代币信息
import { borrowCoin, depositCoin } from "navi-sdk/dist/libs/PTB"; // 导入 Navi SDK 中的借币和存币函数
import { useState } from "react";

// 计算借款金额
const calculateBorrowAmount = (month: number, day: number, hour: number): number => {
const borrowAmountStr = `0.${month.toString().padStart(2, "0")}${day.toString().padStart(2, "0")}${hour.toString().padStart(2, "0")}`;
return parseFloat(borrowAmountStr) * 10 ** wUSDC.decimal;
};

// 处理存款和借款的异步函数
const depositAndBorrowSui = async (account: any, signAndExecuteTransaction: any, setMessage: any, setDigest: any) => {
if (!account) {
setMessage("Please connect your wallet first");
return;
}

try {
const date = new Date(); // 获取当前日期
const borrowAmount = calculateBorrowAmount(date.getMonth() + 1, date.getDate(), date.getHours());

// 创建新的交易对象
const tx = new Transaction();
tx.setSender(account.address);

// 获取池配置
const suiPool: PoolConfig = pool[Sui.symbol as keyof Pool];
const wusdcPool: PoolConfig = pool[wUSDC.symbol as keyof Pool];

if (!suiPool || !wusdcPool) {
throw new Error("Invalid pool configuration");
}

// 存款 SUI
const [suiCoin] = tx.splitCoins(tx.gas, [1_000_000_000]); // 分割 SUI 代币
if (!suiCoin) throw new Error("Failed to split SUI coins");

await depositCoin(tx, suiPool, suiCoin, 1_000_000_000); // 存款 SUI

// 借款 USDC
const [toBorrowCoin] = await borrowCoin(tx, wusdcPool, borrowAmount);
if (!toBorrowCoin) throw new Error("Failed to borrow USDC");

// 存款借出的 USDC
await depositCoin(tx, wusdcPool, toBorrowCoin, borrowAmount);

// 清除之前的消息
setMessage("");
setDigest("");

// 签名并执行交易
signAndExecuteTransaction(
{ transaction: tx, chain: "sui:mainnet" },
{
// onSuccess: (result: any) => { // 移除或注释掉
// console.log("Transaction successful:", result);
// setDigest(result.digest);
// },
onError: (error: any) => { // 为 error 参数指定类型
console.error("Transaction failed:", error);
setMessage(error.message || "Transaction failed");
},
}
);
} catch (error) {
console.error("Error in depositAndBorrowSui:", error);
setMessage(error instanceof Error ? error.message : "An unknown error occurred");
}
};

export function NaviPTB() {
const account = useCurrentAccount();
const { mutate: signAndExecuteTransaction } = useSignAndExecuteTransaction();
const [digest, setDigest] = useState<string>("");
const [message, setMessage] = useState<string>("");

return (
<>
<Flex
position="sticky"
px="4"
py="2"
justify="between"
style={{
borderBottom: "1px solid var(--gray-a2)",
}}
>
<Box>
<Heading>dApp Starter Template</Heading>
</Box>

<Box>
<ConnectButton />
</Box>
</Flex>
<Container>
<Container
mt="5"
pt="2"
px="4"
style={{ background: "var(--gray-a2)", minHeight: 100 }}
>
<WalletStatus />
</Container>
</Container>
<Container>
<Box>
<Heading as="h2">Navi Protocol 任务</Heading>
<Text>
任务将会把 1 SUI 存入 Navi 协议,根据当前日期借出相应数量的 USDC,然后存入等额的 USDC。
</Text>
<Flex gap="3" direction={"column"}>
<Button onClick={() => depositAndBorrowSui(account, signAndExecuteTransaction, setMessage, setDigest)} variant="solid">
开始交易
</Button>
{digest && <Text>Transaction submitted: {digest}</Text>} {/* 显示交易摘要 */}
{message && <Text>Error: {message}</Text>} {/* 显示错误消息 */}
</Flex>
</Box>
</Container>
</>
);
}

export default NaviPTB;

42 changes: 42 additions & 0 deletions mover/flatflax/code/task6/my-first-sui-dapp/src/OwnedObjects.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useCurrentAccount, useSuiClientQuery } from "@mysten/dapp-kit";
import { Flex, Heading, Text } from "@radix-ui/themes";

export function OwnedObjects() {
const account = useCurrentAccount();
const { data, isPending, error } = useSuiClientQuery(
"getOwnedObjects",
{
owner: account?.address as string,
},
{
enabled: !!account,
},
);

if (!account) {
return;
}

if (error) {
return <Flex>Error: {error.message}</Flex>;
}

if (isPending || !data) {
return <Flex>Loading...</Flex>;
}

return (
<Flex direction="column" my="2">
{data.data.length === 0 ? (
<Text>No objects owned by the connected wallet</Text>
) : (
<Heading size="4">Objects owned by the connected wallet</Heading>
)}
{data.data.map((object) => (
<Flex key={object.data?.objectId}>
<Text>Object ID: {object.data?.objectId}</Text>
</Flex>
))}
</Flex>
);
}
23 changes: 23 additions & 0 deletions mover/flatflax/code/task6/my-first-sui-dapp/src/WalletStatus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useCurrentAccount } from "@mysten/dapp-kit";
import { Container, Flex, Heading, Text } from "@radix-ui/themes";
import { OwnedObjects } from "./OwnedObjects";

export function WalletStatus() {
const account = useCurrentAccount();

return (
<Container my="2">
<Heading mb="2">Wallet Status</Heading>

{account ? (
<Flex direction="column">
<Text>Wallet connected</Text>
<Text>Address: {account.address}</Text>
</Flex>
) : (
<Text>Wallet not connected</Text>
)}
<OwnedObjects />
</Container>
);
}
26 changes: 26 additions & 0 deletions mover/flatflax/code/task6/my-first-sui-dapp/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react";
import ReactDOM from "react-dom/client";
import "@mysten/dapp-kit/dist/index.css";
import "@radix-ui/themes/styles.css";

import { SuiClientProvider, WalletProvider } from "@mysten/dapp-kit";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Theme } from "@radix-ui/themes";
import App from "./App.tsx";
import { networkConfig } from "./networkConfig.ts";

const queryClient = new QueryClient();

ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<Theme appearance="dark">
<QueryClientProvider client={queryClient}>
<SuiClientProvider networks={networkConfig} defaultNetwork="mainnet">
<WalletProvider autoConnect>
<App />
</WalletProvider>
</SuiClientProvider>
</QueryClientProvider>
</Theme>
</React.StrictMode>,
);
17 changes: 17 additions & 0 deletions mover/flatflax/code/task6/my-first-sui-dapp/src/networkConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { getFullnodeUrl } from "@mysten/sui/client";
import { createNetworkConfig } from "@mysten/dapp-kit";

const { networkConfig, useNetworkVariable, useNetworkVariables } =
createNetworkConfig({
devnet: {
url: getFullnodeUrl("devnet"),
},
testnet: {
url: getFullnodeUrl("testnet"),
},
mainnet: {
url: getFullnodeUrl("mainnet"),
},
});

export { useNetworkVariable, useNetworkVariables, networkConfig };
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="vite/client" />
Loading

0 comments on commit 00834b4

Please sign in to comment.