Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

task6 #2157

Merged
merged 2 commits into from
Dec 13, 2024
Merged

task6 #2157

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions mover/Helen2022a/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/Helen2022a/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>
35 changes: 35 additions & 0 deletions mover/Helen2022a/code/task6/my-first-sui-dapp/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"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.42",
"@mysten/sui": "1.16.2",
"@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",
"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",
};
92 changes: 92 additions & 0 deletions mover/Helen2022a/code/task6/my-first-sui-dapp/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { useCurrentAccount, useSignAndExecuteTransaction, ConnectButton, useConnectWallet, useWallets } from "@mysten/dapp-kit";
import { Container, Flex, Heading, Text, Button } from "@radix-ui/themes";
import { wUSDC } from "navi-sdk/dist/address";
import { borrowAction } from "./borrowFromNavi.ts";

//根据月、日、小时计算借出的usdc的金额
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")}`;
//需要乘以wUSDC的精度: 10 ** wUSDC.decimal
return parseFloat(borrowAmountStr) * 10 ** wUSDC.decimal;
};

const App = () => {

const wallets = useWallets();
const { mutate: connect } = useConnectWallet();

const account = useCurrentAccount();
const { mutate: signAndExecute } = useSignAndExecuteTransaction();

// 获取当前日期生成借出usdc的金额
const date = new Date();
const usdcAmount = calculateBorrowAmount(date.getMonth() + 1, date.getDate(), date.getHours());

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

<div style={{ padding: 20 }}>
<ConnectButton />
<ul>
{wallets.map((wallet) => (
<li key={wallet.name}>
<button
onClick={() => {
connect(
{ wallet },
{
onSuccess: () => console.log('connected'),
},
);
}}
>
Connected to {wallet.name}
</button>
</li>
))}
</ul>
</div>

{account ? (
<Flex direction="column">
<Text>Wallet connected</Text>
<Text>Address: {account.address}</Text>
</Flex>
) : (
<Text>Wallet not connected</Text>
)}

<Text>========================================================================================</Text>
<Heading mb="2">Transaction Action</Heading>
{account ? (
<Flex direction="column">
<Heading mb="3">Execute the following steps in one transaction:</Heading>
<Flex direction="column">
<Text> 1. Deposit 1 SUI into Navi Protocol </Text>
<Text> {`2. Borrow ${usdcAmount} USDC from Navi Protocal`}</Text>
<Text> 3. Deposit the same amount of USDC</Text>
</Flex>
<Button
size="3"
onClick={() => {
borrowAction(account, {
signAndExecute, usdcAmount, onSuccess(result) {
console.log(result, 'Succeeded to execute the transaction!')
}, onError(error) {
console.log(error, 'Failed to execute the transaction!')
},
});
}}
style={{ cursor: 'pointer', width: '300px' }}
>
<Text>Execute this transaction</Text>
</Button>
</Flex>
) : null}
</Container>
);
}

export default App;

42 changes: 42 additions & 0 deletions mover/Helen2022a/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/Helen2022a/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>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Transaction } from '@mysten/sui/transactions';
import { depositCoin, borrowCoin, } from 'navi-sdk/dist/libs/PTB'
import { Sui, wUSDC } from "navi-sdk/dist/address";
import { Pool, PoolConfig } from "navi-sdk/dist/types";
import { pool } from 'navi-sdk/dist/address'


export const borrowAction = async (account: any, { signAndExecute, usdcAmount, onSuccess = () => { } }: {
signAndExecute: any;
usdcAmount: number;
onSuccess?: (result: any) => void;
onError?: (result: any) => void;
}) => {

if (!account) {
postMessage("Please connect your wallet first");
return;
}

// 创建交易对象
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");
}

// 设置gas
tx.setGasBudget(1e9);

try {
// 分离出1sui
const [sui] = tx.splitCoins(tx.gas, [1e9]);

console.log("Checking object existence...");
const suiObject = await tx.object(sui);
if (!suiObject) {
throw new Error(`Object ${sui} does not exist`);
}

// 存 1 SUI 进 Navi Protocal
await depositCoin(tx as any, SuiPool, sui, 1e9);

// 借出 usdc
const [usdc_coin] = await borrowCoin(tx as any, wUSDCPool, usdcAmount);

// 存入 usdc
await depositCoin(tx as any, wUSDCPool, usdc_coin, usdcAmount);

// 签名执行交易
await signAndExecute({
transaction: tx, chain: "sui:mainnet"
}, {
onSuccess,
onError: (error: any) => { // 为 error 参数指定类型
console.error("Transaction failed:", error);
postMessage(error.message || "Transaction failed");
},
});
} catch (error) {
console.error("Transaction failed:", error);
postMessage(error instanceof Error ? error.message : "An unknown error occurred");
}

}

26 changes: 26 additions & 0 deletions mover/Helen2022a/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>,
);
Loading
Loading