前言基于《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';
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));
}
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>
一条命令跑通全流程
npx hardhat node
→ compile
→ deploy --tags
→ 私钥导入钱包,30 秒完成链端准备。
三大场景一次封装
Contract.method
+ wait()
实现,与单元测试断言一一对应。直接可迁移到生产
代码已抽离公共 signer/contract
初始化逻辑,只需把地址、ABI 换成正式网络,即可无缝接入 React / React Native 项目;UI 层只需包裹按钮与 Loading,即可完成「链上收益聚合器」的完整交互闭环。
至此,合约端 + 前端双端闭环全部打通,恭喜你拥有了一套可扩展、可复用、可上架的 DeFi 迷你收益聚合器 DApp!
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!