{"content":{"title":"0基础从前端到Web3 —— Vite + React + TS moveCall a + b","body":"# 一：初始化项目\r\n\r\n$\\mathit {Vite}$ 作为近几年前端开发中常用的构建工具之一，具有**启动速度快**、**更快的冷启动与热更新**、**按需加载**等优势，极高提升了开发效率和体验，想要初始化一个项目也十分简单，本篇以 $\\mathit {pnpm}$ 为例：\r\n\r\n1. `pnpm create vite`<br>根据提示输入想要创建的项目名，再选择 $\\mathit {React}$ 框架和 $\\mathit {TypeScript}$ 模板（请根据具体的开发需求选择合适的框架和模板）。\r\n2. `cd`进入你新建的项目，通过`pnpm install`安装必要的依赖，等待一会儿后即可通过`pnpm run dev`进行启动，这里可以选择打开浏览器预览初始化的页面（中央有一个点击计数的按钮）。\r\n3. 本篇还需要使用到 $\\mathit {Sui\\ Move}$​ 的相关功能（例如通过浏览器连接钱包，链上调用等），所以还需要通过如下命令添加依赖：<br>`pnpm add -D @mysten/sui.js @mysten/dapp-kit @tanstack/react-query`\r\n\r\n至此，基础的内容都已经初始化完毕，让我们将功能进行拆解进行实现。\r\n\r\n# 二：功能实现\r\n\r\n## 2.1 基础组件\r\n\r\n在项目中进入`src`文件夹，打开并修改`main.tsx`文件。\r\n\r\n```tsx\r\nimport React from 'react'\r\nimport ReactDOM from 'react-dom/client'\r\nimport App from './App.tsx'\r\n\r\nimport '@mysten/dapp-kit/dist/index.css';\r\n\r\nimport { SuiClientProvider, WalletProvider } from '@mysten/dapp-kit';\r\nimport { getFullnodeUrl } from '@mysten/sui.js/client';\r\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\r\n\r\nconst queryClient = new QueryClient();\r\nconst networks = {\r\n\ttestnet: { url: getFullnodeUrl('testnet') },\r\n\tmainnet: { url: getFullnodeUrl('mainnet') },\r\n};\r\n\r\nReactDOM.createRoot(document.getElementById('root')!).render(\r\n\t<React.StrictMode>\r\n\t\t<QueryClientProvider client={queryClient}>\r\n\t\t\t<SuiClientProvider networks={networks} defaultNetwork='testnet'>\r\n\t\t\t\t<WalletProvider>\r\n\t\t\t\t\t<App />\r\n\t\t\t\t</WalletProvider>\r\n\t\t\t</SuiClientProvider>\r\n\t\t</QueryClientProvider>\r\n\t</React.StrictMode>,\r\n);\r\n```\r\n\r\n`QueryClientProvider, SuiClientProvider, WalletProvider`是 $\\mathit {Sui\\ Client},\\ \\mathit {Sui\\ Networks},\\ \\mathit {Wallet}$  的组件设置，格式相对固定，这里以连接 $\\mathit {testnet}$ 为例，具体的界面和相关的功能都在同目录下的`App.tsx`当中编写。\r\n\r\n## 2.2 界面布局\r\n\r\n### 2.2.1 连接钱包\r\n\r\n在`@mysten/dapp-kit`当中可以导入`ConnectButton`这一按钮，只需要通过`<ConnectButton />`调用，就可以返回一个点击连接浏览器钱包功能的按钮，为了设置其布局，我们在外面套一层`<div></div>`，通过`className`编写`css`文件调整位置布局。\r\n\r\n```tsx\r\n<div className='ConnectButton'>\r\n    <ConnectButton />\r\n</div>\r\n```\r\n\r\n```css\r\n.ConnectButton {\r\n    text-align: center;\r\n    padding: 15%;\r\n}\r\n```\r\n\r\n### 2.2.2 输入输出\r\n\r\n这里使用 $\\mathit {UI}$ 组件：$\\mathit {Material\\ UI}$ 来进行后续界面布局，它是世上最流行的 $\\mathit {React\\ UI}$ 框架，基础的格式和组件使用可以[点击](https://mui.com/material-ui/getting-started/)查看。\r\n\r\n依赖安装很简单，也是通过 $\\mathit {pnpm}$ 一行命令搞定：`pnpm add -D @mui/material @emotion/react @emotion/styled`，如有特殊的需求可以通过上面的链接点击进入查看。\r\n\r\n用`Box`来框定范围、间距等，内部通过`TextField`来设置文本框，两个用来输入的，一个用来输出的，输出答案的文本框不可编辑，内容将根据调用进程实时变更。\r\n\r\n```tsx\r\n<Box\r\n    component=\"form\"\r\n    sx={{\r\n        '& > :not(style)': { m: 1, width: '15ch', left: \"33%\"},\r\n    }}\r\n    noValidate\r\n    autoComplete=\"off\"\r\n    >\r\n    <TextField id=\"a\" label=\"a\" variant=\"standard\" onChange={readNumberA}/>\r\n    <p className='Symbol'>+</p>\r\n    <TextField id=\"b\" label=\"b\" variant=\"standard\" onChange={readNumberB}/>\r\n    <p className='Symbol'>=</p>\r\n    <TextField id=\"sum\" label=\"sum\" variant=\"standard\" disabled={true} value={sum}/>\r\n\r\n    <Button variant=\"outlined\" size=\"large\" className=\"CalButton\" onClick={calculate}>Calculate</Button>\r\n</Box>\r\n```\r\n\r\n具体的格式设置都可以通过 $\\mathit {Material\\ UI}$ 的详情页查看，这里也就不再赘述，关键是几个点击事件的监听。\r\n\r\n```tsx\r\nconst { mutate: signAndExecuteTransactionBlock } = useSignAndExecuteTransactionBlock();\r\nconst account = useCurrentAccount();\r\n\r\nconst [numberA, setNumberA] = React.useState(\"\");\r\nconst readNumberA = (event: any) => {\r\n    setNumberA(event.target.value);\r\n};\r\n// console.log(numberA);\r\nconst [numberB, setNumberB] = React.useState(\"\");\r\nconst readNumberB = (event: any) => {\r\n    setNumberB(event.target.value);\r\n};\r\n// console.log(numberB);\r\nconst [sum, setSum] = React.useState(\"\");\r\nconst calculate = () => {\r\n    moveCall(Number(numberA), Number(numberB), account, signAndExecuteTransactionBlock, setSum);\r\n};\r\n```\r\n\r\n`readNumberA`和`readNumberB`都是获取用户输入的内容，分别存储到`numberA, numberB`当中。\r\n\r\n`Calculate`按钮实际功能是链上调用，将得到的两个数字作为参数传入（得到的是字符串，传入时转换成数字类型），后面的`account`用来判断用户是否已经连接了钱包，`signAndExecuteTransactionBlock`用来进行链上交易调用，`setSum`不必多说，用来将计算所得（通过读取交易后的事件）来改变`sum`，而我们的答案文本框的内容会根据`sum`值改变而改变。\r\n\r\n## 2.3 链上调用\r\n\r\n首先，通过`account`判断是否已经连接了钱包。\r\n\r\n```tsx\r\nif (!account) {\r\n    setSum(\"Connect First!!!\");\r\n    return;\r\n}\r\n```\r\n\r\n然后，创建交易块并且填写交易信息，内容与直接通过 $\\mathit {TypeScript}$ 调用 $\\mathit {Sui\\ Move\\ SDK}$ 时大差不差。\r\n\r\n```tsx\r\nconst txb = new TransactionBlock();\r\ntxb.moveCall({\r\n    target: \"0xc20b020f8bf81400cc6c1d63ac37a4802ef873df35abd754ffd37992655b25e4::add::add\",\r\n    arguments: [txb.pure(a), txb.pure(b)],\r\n});\r\n```\r\n\r\n最后，通过传入的`signAndExecuteTransactionBlock`进行签名并交易。\r\n\r\n```tsx\r\nsignAndExecuteTransactionBlock(\r\n{\r\n    transactionBlock: txb,\r\n    chain: \"sui:testnet\",\r\n    options: {\r\n        showEvents: true,\r\n    },\r\n},\r\n{\r\n    onSuccess: (result: any) => {\r\n        setSum(result.events[0].parsedJson.res);\r\n    },\r\n});\r\n```\r\n\r\n其中，`chain`选择的是网络环境，本篇使用的是测试网（$\\mathit {testnet}$​），`options`当中的`showEvents`则是令成功交易后返回的`result`当中显示事件信息，`onSuccess`则是处理成功交易后的逻辑，这里很简单，将`event`当中存储的`res`赋值给`sum`。\r\n\r\n## 2.4 简单演示\r\n\r\n\r\n![main.png](https://img.learnblockchain.cn/attachments/2024/05/xrUqfV2C664ae0603a74d.png)\r\n\r\n\r\n\r\n![calc.png](https://img.learnblockchain.cn/attachments/2024/05/hP5xkMCP664ae067dea13.png)\r\n\r\n\r\n\r\n![res.png](https://img.learnblockchain.cn/attachments/2024/05/oFtiE3W1664ae06e824d7.png)\r\n\r\n\r\n## 2.5 其它\r\n\r\n额外提一点，如果已知链上的 $\\mathit {objectId}$，该如何查询其内容：在`@mysten/dapp-kit`当中有`useSuiClientQuery, useSuiClientQueries`等一系列函数，这里以查询单一的对象为例：<br>`const { data } = useSuiClientQuery(\"getObject\", { id: objectId, options: { showContent: true } });`<br>可以通过`console.log(data)`来查看结构，再通过`.`来一层一层取用。\r\n\r\n本篇完整的代码（包括 $\\mathit {a\\ +\\ b}$ 的 $\\mathit {move}$ 代码）可以[点击](https://github.com/zcy1024/SuiStudy/tree/main/react_a_add_b)查看。\r\n\r\n[$\\mathit {letsmove}$ 学习激励计划](https://github.com/move-cn/letsmove)的 $\\mathit {task6}$ 新增要求必须使用 $\\mathit {dapp}$-$\\mathit {kit}$ 在浏览器进行交易，可结合本篇以及前面的文章内容稍加修改后达成。\r\n\r\n# 三：加入组织，共同进步！\r\n\r\n- [Sui 中文开发群(TG)](https://t.me/move_cn)\r\n- $\\mathit{Move}$ 语言学习交流群: 79489587"},"author":{"user":"https://learnblockchain.cn/people/19165","address":"0xa74501E5BdAad0Ec0752AB09c7183C794D0DFe19"},"history":null,"timestamp":1716183214,"version":1}