入门 Sui Move 开发:9. 一个 Sui dApp 前端项目

发布于:2025-03-19 ⋅ 阅读:(22) ⋅ 点赞:(0)

内容概览

接下来一起通过 PTB 和 Navi SDK 实现一个一键存入借出的简单 DApp

本节分为两部分:

  • 创建一个 DApp 前端项目以及 Sui dApp Kit 的使用;
  • 了解 Navi SDK,主要包含的功能以及如何实现存入和借出功能;

最终完成我们的项目。

前端项目部分

创建项目

项目使用 Next.js 框架,创建新项目:npx create-next-app@latest 按提示输入项目名及配置(配置按习惯选择),然后等待安装完成。

添加 Sui dApp Kit 依赖

Sui dApp Kit 是一组 React 组件,可以帮助我们快速构建 dApp

首先需要安装它,进入到项目目录,执行命令:
npm i --save @mysten/dapp-kit @mysten/sui @tanstack/react-query

你也可以使用官方提供的 @mysten/dapp cli命令创建项目。

运行项目:npm run dev,如何可以打开页面说明已经成功创建工程。

配置项目,编写相关代码

接下来在 src 中新建文件 providers.tsx 和 utils/sui.ts

providers.tsx 用来设置使用 sdk 中提供的组件和钩子函数需要的 provider ,内容如下:

'use client';

import { QueryClientProvider } from "@tanstack/react-query";
import React from "react";
import { networkConfig, queryClient } from "./utils/sui";
import { SuiClientProvider, WalletProvider } from "@mysten/dapp-kit";

export default function SuiProviders({ children }: { children: React.ReactNode }) {

  return (
    <QueryClientProvider client={queryClient}>
      <SuiClientProvider networks={networkConfig} defaultNetwork="mainnet">
        <WalletProvider>
          {children}
        </WalletProvider>
      </SuiClientProvider>
    </QueryClientProvider>
  );
}

utils/sui.ts 提供 providers 中需要的对象,内容如下:

import { createNetworkConfig } from "@mysten/dapp-kit";
import { getFullnodeUrl } from "@mysten/sui/client";
import { QueryClient } from "@tanstack/react-query";

const { networkConfig } = createNetworkConfig({
  mainnet: {
    url: getFullnodeUrl('mainnet'),
  }
});

const queryClient = new QueryClient();

export { networkConfig, queryClient };

layout.tsx 中的修改如下:

import SuiProviders from "./providers";
import '@mysten/dapp-kit/dist/index.css'; // 导入 sui dapp kit sdk 样式

...
// 使用 SuiProviders 包裹 children
<SuiProviders>
    {children}
</SuiProviders>

page.tsx 就是展示的默认页面,修改内容如下包含:一个标题,一个链接钱包的按钮,一个可以实现存入/借出的按钮,内容如下:

'use client';

import { ConnectButton, } from "@mysten/dapp-kit";

export default function Home() {

  function handleClick() {
    // todo: 点击显示一个 alert
    alert('click button');
  }

  return (
    <div className="container mx-auto p-4">
      <div className="flex justify-between">
        <p className="text-2xl font-bold">Hello SUI dApp</p>
        <ConnectButton />
      </div>
      <button
        onClick={handleClick}
        className="mt-4 border border-blue-500 rounded-md p-2 font-bold text-blue-500">
        存入/借出/存入
      </button>
    </div>
  );
}
页面效果

此时页面效果如下:

image.png

navi-sdk 提供了与 navi 协议交互的封装,方便存款/借款等功能。

首先安装:npm i --save navi-sdk

接下来补充上面按钮的逻辑

导包
import { ConnectButton, useCurrentAccount, useSignAndExecuteTransaction } from "@mysten/dapp-kit";
import { Transaction } from "@mysten/sui/transactions";
import { borrowCoin, depositCoin, nUSDC, Pool, pool, Sui } from "navi-sdk";
import { useState } from "react";
按钮逻辑
// 当前链接的钱包
const currentAddress = useCurrentAccount();

// 执行交易
const { mutate: signAndExecuteTransaction } = useSignAndExecuteTransaction();

// 交易hash
const [digest, setDigest] = useState('');

// 发生错误时提示信息
const [noticeInfo, setNoticeInfo] = useState('');


const handleClick = async () => {
    if (!currentAddress) {
      alert("请先连接钱包");
      return;
    }
    // 存入 1 SUI,借出当前日期对应的 USDC,并将 USDC 存入协议中
    // 数量
    const suiAmount = 1 * 10 ** Sui.decimal;
    console.log("suiAmount = ", suiAmount);

    const date = new Date();
    const month = date.getMonth() + 1;
    const day = date.getDate();
    const hours = date.getHours();

    const usdcAmount = parseInt((parseFloat(`0.${month.toString().padStart(2, '0')}${day.toString().padStart(2, '0')}${hours.toString().padStart(2, '0')}`) * 10 ** nUSDC.decimal).toString());
    console.log("usdcAmount = ", usdcAmount);

    // 创建交易对象
    const tx = new Transaction();

    // 分割 sui
    const [suiCoin] = tx.splitCoins(tx.gas, [suiAmount]);
    console.log(suiCoin);

    if (!suiCoin) {
      setNoticeInfo("分割 SUI 失败");
      return;
    }

    // 操作池
    const suiPool = pool[Sui.symbol as keyof Pool];
    const usdcPool = pool[nUSDC.symbol as keyof Pool];
    if (!suiPool || !usdcPool) {
      setNoticeInfo("pool 配置失败");
      return;
    }

    // 存 sui
    await depositCoin(tx, suiPool, suiCoin, suiAmount);

    // 借 usdc
    const [borrowedCoin] = await borrowCoin(tx, usdcPool, usdcAmount);

    // 存 usdc
    await depositCoin(tx, usdcPool, borrowedCoin, usdcAmount);

    signAndExecuteTransaction(
      {
        transaction: tx,
      },
      {
        onSuccess: (result) => {
          setDigest(result.digest);
          setNoticeInfo("交易已发送");
        },
        onError: (error) => {
          setNoticeInfo(error.message);
        }
      });
  }
页面 UI 添加
{noticeInfo && <p>{noticeInfo}</p>}
{digest && <p>交易 hash {digest}</p>}

如果觉得本节内容对你有所帮助,可以点赞鼓励下,更多信息,,https://t.me/+_QibemQqIIg1OTY1