React Native DApp 开发全栈实战·从 0 到 1 系列(收益聚合器-前端部分)

  • 木西
  • 发布于 2小时前
  • 阅读 52

前言基于《ReactNativeDApp开发全栈实战·从0到1系列(收益聚合器-合约部分)》,本文进入“前端交互”环节,把已经部署在HardhatLocal上的多授权代币+收益聚合器搬到浏览器里:用MetaMask点火,用ethers.js操纵,完成存、取

前言

基于《 React Native DApp 开发全栈实战·从 0 到 1 系列(收益聚合器-合约部分)》,本文进入“前端交互”环节,把已经部署在 Hardhat Local 上的 多授权代币 + 收益聚合器 搬到浏览器里:用 MetaMask 点火,用 ethers.js 操纵,完成 存、取、份额、喂价、权限 五大核心场景的实时调用。

前期准备

  • hardhat启动网络节点:npx hardhat node
  • 合约编译:npx hardhat compile 生成对应的xxx.json用获取abi等相关信息
  • 合约部署:npx hardhat deploy --tags token3,token4,MockV3Aggregator,YieldAggregator 获取合约地址(资产代币、奖励代币、喂价和收益聚合器合约地址)
  • 节点的私钥导入钱包:用来与合约交互时支付对应的gas费

核心代码

  • 公共代码
    import { abi as MockV3AggregatorABI } from '@/abi/MockV3Aggregator.json';
    import { abi as MyTokenABI1 } from '@/abi/MyToken1.json';
    import { abi as MyTokenABI3 } from '@/abi/MyToken3.json';
    import { abi as YieldAggregatorABI } from '@/abi/YieldAggregator.json';
    import * as ethers from 'ethers';
  • 场景1(首次存入正确铸造份额=》二次存入按比例铸造份额 =》提取后份额与资产减少)
    const aggregatorFn=async ()=>{
        const provider = new ethers.providers.Web3Provider(window.ethereum);
        await provider.send('eth_requestAccounts', []); // 唤起钱包
        const signer = await provider.getSigner();
        const userAddr = await signer.getAddress();//当前用户地址
        const YieldAggregatorAddress="0x0E801D84Fa97b50751Dbf25036d067dCf18858bF"//聚合器地址
        const MockV3AggregatorAddress="0x998abeb3E57409262aE5b751f60747921B33613E"//MockV3Aggregator地址
        const MyAssetAddress="0x4826533B4897376654Bb4d4AD88B7faFD0C98528" //资产
        const MyAwardAddress="0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf"//奖励
        const YieldAggregatorContract = new ethers.Contract(YieldAggregatorAddress, YieldAggregatorABI, signer);
        const MockV3AggregatorContract = new ethers.Contract(MockV3AggregatorAddress, MockV3AggregatorABI, signer);
        const MyAssetContract = new ethers.Contract(MyAssetAddress, MyTokenABI1, signer);//资产
        const MyAwardContract = new ethers.Contract(MyAwardAddress, MyTokenABI3, signer);//奖励
    
        console.log(YieldAggregatorContract,MockV3AggregatorContract,MyAssetContract,MyAwardContract)
    
        const DEPOSIT_AMOUNT = ethers.utils.parseUnits("100", 18); // 100 个 token(18 位)
        const WITHDRAW_SHARES = ethers.utils.parseUnits("30", 18); // 100 个 token(18 位)
    
        /* ---------- 1. mint + approve ---------- */
    // 如果 asset 是 ERC20 且用户余额不足,我们先给他 mint(测试 token 才有)
    const mintTx = await MyAssetContract.mint(userAddr, DEPOSIT_AMOUNT);
    await mintTx.wait();
    
    const approveTx = await MyAssetContract.approve(YieldAggregatorAddress, DEPOSIT_AMOUNT);
    await approveTx.wait();
    
    /* ---------- 2. 首次 deposit ---------- */
    const depositTx = await YieldAggregatorContract.deposit(DEPOSIT_AMOUNT);
    await depositTx.wait();
    
    /* ---------- 3. 打印结果 ---------- */
    const userShares = await YieldAggregatorContract.shares(userAddr);
    const totalShares= await YieldAggregatorContract.totalShares();
    const totalAssets= await YieldAggregatorContract.totalAssetsDeposited();
    console.log("首次存入后用户份额 :", ethers.utils.formatUnits(userShares, 18));
    console.log("首次存入后份额总量 :", ethers.utils.formatUnits(totalShares, 18));
    console.log("首次存入后资产总量 :", ethers.utils.formatUnits(totalAssets, 18));  
    
    //提取资产
    const withdrawTx = await YieldAggregatorContract.withdraw(WITHDRAW_SHARES);
    await withdrawTx.wait();
    //验证
    const userSharesAfter = await YieldAggregatorContract.shares(userAddr);
    const totalSharesAfter= await YieldAggregatorContract.totalShares();
    const totalAssetsAfter= await YieldAggregatorContract.totalAssetsDeposited();
    console.log("提取资产后用户份额 :", ethers.utils.formatUnits(userSharesAfter, 18));
    console.log("提取资产后份额总量 :", ethers.utils.formatUnits(totalSharesAfter, 18));
    console.log("提取资产后资产总量 :", ethers.utils.formatUnits(totalAssetsAfter, 18));
    }
  • 场景2(无法提取超过自身份额、 rescue 只能 owner 调用 、getUserAssetValue 计算正确)
  • 场景3 获取喂价
    const ethPrice=await YieldAggregatorContract.getETHPrice()
    console.log("ethPrice:",ethers.utils.formatUnits(ethPrice,8))

    效果图

    <div style="display:flex; gap:8px;flex-wrap:wrap;"> <img src="https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/ec26e986cf574cd4b4e2ca0199bb54c7~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5pyo6KW_:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjQzNjE3MzQ5Njg0NTU0OSJ9&rk3s=e9ecf3d6&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1757941229&x-orig-sign=k6Dw%2Fuq10EDjAB8l%2B0usZxBYrX0%3D" alt="图1转存失败,建议直接上传图片文件" width="200"> <img src="https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/7c5c1819f59f4bd3bdf4f2309da8c0ee~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5pyo6KW_:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjQzNjE3MzQ5Njg0NTU0OSJ9&rk3s=e9ecf3d6&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1757941259&x-orig-sign=IjqtMGhRW2MqQ%2BkKs0zP5Gtzc9Q%3D" alt="图1转存失败,建议直接上传图片文件" width="200"> </div>

总结

  1. 一条命令跑通全流程
    npx hardhat nodecompiledeploy --tags → 私钥导入钱包,30 秒完成链端准备。

  2. 三大场景一次封装

    • 首次存入 1:1 铸造份额
    • 二次存入按比例增发
    • 提取后份额 & 资产同步减少
      外加 超额提取 revert、owner rescue、实时 ETH 价格 等边界校验,全部在前端用 Contract.method + wait() 实现,与单元测试断言一一对应。
  3. 直接可迁移到生产
    代码已抽离公共 signer/contract 初始化逻辑,只需把地址、ABI 换成正式网络,即可无缝接入 React / React Native 项目;UI 层只需包裹按钮与 Loading,即可完成「链上收益聚合器」的完整交互闭环。

至此,合约端 + 前端双端闭环全部打通,恭喜你拥有了一套可扩展、可复用、可上架的 DeFi 迷你收益聚合器 DApp!

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
木西
木西
0x5D5C...2dD7
江湖只有他的大名,没有他的介绍。