【Sui】 前端共学笔记(3)

sui前端共学week_3笔记

88f9d4b7250a724489ed6e23ff6ea7f.jpg 请关注 sui 前端共学营及其社区,在这里你可以学到前端和 move 合约语言的知识。 Dapp,Next.js 与合约的交互

项目搭建

使用npx create-nextjs-sui-dapp-template搭建nextjs框架的suiDapp(我这里使用的是测试网)然后安装依赖后使用npm run dev启动项目。

网络合约设置

进入文件contracts/index.ts

    testnet: {
        url: getFullnodeUrl("testnet"),
        variables: {
            package: "youPackageID",
            state: "youObjectID",
        }
    },

以这样的形式设置合约和对象。

合约调用

我这里使用的是3讲_2视频中的demo合约:

    module demo::demo;
    public struct State has key, store {
        id: UID,
        acount: u64,
    }

    fun init (ctx: &mut TxContext) {
        let state = State {
            id: object::new(ctx),
            acount: 0,
        };
        transfer::public_share_object(state);
    }

    public entry fun deposit (state: &mut State, amount: u64) {
        state.acount = state.acount + amount;
    }

他是一个简单的对object内数值进行累加的合约,我们在contracts文件下创建一个同名ts文件来对合约调用:

 import { createBetterTxFactory } from ".";

export const deposit = createBetterTxFactory<{amount:number}>((tx, networkVariables, params) => {
    tx.moveCall({
        package: networkVariables.package,
        module: "demo",
        function: "deposit",
        arguments: [
            tx.object(networkVariables.state),
            tx.pure.u64(params.amount),
        ],
    })
    return tx;
})

这段代码是用来创建一个交易函数(deposit),并通过 createBetterTxFactory 包装它,从而简化与 Sui 区块链的交互。

1. createBetterTxFactory<{amount:number}>

  • createBetterTxFactory 是一个用于创建交易的工厂函数,用来生成具有特定结构和行为的事务。<{amount: number}> 表明这是一个带有 amount 参数的函数。

2. tx.moveCall

  • tx.moveCall 用于调用一个 Move 合约函数。在这里,它调用的是名为 deposit 的 Move 合约函数。moveCall 是一种交易类型,用于在 Sui 区块链上执行 Move 程序。

3. tx.object(networkVariables.state)

  • 这行代码指定了交易中所需的 Sui 对象。networkVariables.state 一个对象,它会作为参数传递到 Move 合约函数中。

4. tx.pure.u64(params.amount)

  • tx.pure.u64(params.amount)amount 参数转换为一个纯数据值,并指定其类型为 u64(64位无符号整数)。
  • 这意味着 amount 是以 64 位整数的形式传递到 Move 合约中。

5. return tx

  • 返回处理后的 tx 对象,表示构建好的交易。

context

context用于组件之间共享和管理状态,当需要在应用中访问和共享“用户数据”时,就可以用context 来实现。我们在创建一个文件context下面用来实现context: (这里有一个getState的方法写在了contracts/query.ts中下面有)

import { getState } from "../contracts/query"
import { useState, useCallback, useContext, createContext } from "react"

interface StateContextType {
    acount: number
    refresh:()=>Promise<void>
}

const StateContext = createContext<StateContextType | undefined>(undefined)

interface StateProviderProps {
    children: React.ReactNode
}

export const StateProvider: React.FC<StateProviderProps> = ({ children }) => {
    const [acount, setAccount] = useState<number>(0)
    const refresh = useCallback(async () => {
        const state = await getState()
        const data = state.data?.content as unknown as {fields: {acount: number}}
        const acount = data.fields.acount
        setAccount(acount)
    }, [])

    return (
        <StateContext.Provider value={{ acount, refresh }}>{children}</StateContext.Provider>
    )
}

export function useStateContext() {
    const context = useContext(StateContext)
    if (!context) {
        throw new Error("useContext must be used within a StateProvider")
    }
    return context
}

这段代码用于共享和管理应用中的acount。它通过创建一个 StateContext 和提供一个 StateProvider 组件,使得应用中的其他组件能够访问和更新这个状态。这个 StateContext 主要用于存储和更新 acount,并提供了一个 refresh 方法来刷新该值。 注意之后要将这里的</StateProvider>使用在app/providers

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <QueryClientProvider client={queryClient}>
      <SuiClientProvider networks={networkConfig} defaultNetwork={network}>
        <WalletProvider>
          <StateProvider>
            {children}
          </StateProvider>
        </WalletProvider>
      </SuiClientProvider>
    </QueryClientProvider>
  );
}

getState()

export const getState = async ()=>{
  const state = await suiClient.getObject({
    id: networkConfig[network].variables.state,
    options: {
      showContent: true,
    },
  });
  return state;
}

page页面调用

使用 useBetterSignAndExecuteTransaction 自定义 hook 来执行一个交易(deposit),并获取一个 handleSignAndExecuteTransaction 函数,用于处理交易签名和执行。

  const { handleSignAndExecuteTransaction: depositHandler } = useBetterSignAndExecuteTransaction({
    tx: deposit,
  });

还需要而外加一个hook去使用context的内容

  const {acount, refresh} = useStateContext();

下面是完整调用:

  const account = useCurrentAccount();
  const [userObjects, setUserObjects] = useState<CategorizedObjects | null>(null);
  const { handleSignAndExecuteTransaction: depositHandler } = useBetterSignAndExecuteTransaction({
    tx: deposit,
  });
  const {acount, refresh} = useStateContext();

  const handleIncrement = async () => {
    await depositHandler({ amount: 1}).onSuccess(async () => {
      await refresh();
      console.log('onSuccess')
    }).onError(async (error) => {
      console.log('onError', error)
    }).execute()
  }

  useEffect(() => {
    async function fetchUserProfile() {
      if (account?.address) {
        try {
          const profile = await getUserProfile(account.address);
          await refresh();
          setUserObjects(profile);
        } catch (error) {
          console.error('Error fetching user profile:', error);
        }
      }
    }
    console.log(acount);
    fetchUserProfile();
  }, [account, refresh, acount]);

 return(
     <button onClick={ handleIncrement} >Increment</button>
 )
}
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
yuanchengjiayu
yuanchengjiayu
江湖只有他的大名,没有他的介绍。