前言基于《ReactNativeDApp开发全栈实战·从0到1系列(兑换-合约部分)》,本文进入“前端交互”环节,用ReactNative+ethers.js完成一次“1ETH换BTK”的完整用户旅程:唤起钱包→读取实时报价→一键兑换→余额即时刷新。前
基于《 React Native DApp 开发全栈实战·从 0 到 1 系列(兑换-合约部分)》,本文进入“前端交互”环节,用 React Native + ethers.js 完成一次“1 ETH 换 BTK”的完整用户旅程:唤起钱包 → 读取实时报价 → 一键兑换 → 余额即时刷新。
import { abi as MockV3AggregatorABI } from '@/abi/MockV3Aggregator.json';
import { abi as MyTokenABI } from '@/abi/MyToken4.json';
import { abi as SwapTokenABI } from '@/abi/SwapToken.json';
import * as ethers from 'ethers';
说明:“预言机读价 → 给 swap 合约打币 → 用户把 1 ETH 打进去 → 合约按价放 BTK → 用户余额增加” 。
const SwapTokenFn=async ()=>{
const provider = new ethers.providers.Web3Provider(window.ethereum);
await provider.send('eth_requestAccounts', []); // 唤起钱包
const signer = await provider.getSigner();
const userAddr = await signer.getAddress();//当前用户地址
console.log('当前用户地址',userAddr)
const MyTokenAddress="0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf" //代币
const MockV3AggregatorAddress="0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf"//MockV3Aggregator地址
const SwapTokenAddress="0x9d4454B023096f34B160D6B654540c56A1F81688"//兑换地址
const MyTokenContract = new ethers.Contract(MyTokenAddress, MyTokenABI, signer);
const MockV3AggregatorContract = new ethers.Contract(MockV3AggregatorAddress, MockV3AggregatorABI, signer);
const SwapTokenContract = new ethers.Contract(SwapTokenAddress, SwapTokenABI, signer);
//验证
const price = await MockV3AggregatorContract.latestAnswer();
console.log("ETH/USD price", price.toString()); // 期望 2000 * 1e8
const usdEquiv = await SwapTokenContract.getEthInUsd(ethers.utils.parseEther("1"));
console.log("1 ETH 对应 USD 数量", usdEquiv.toString()); // 期望 2000
//铸造代币
const tx = await MyTokenContract.mint(SwapTokenAddress, ethers.utils.parseEther("4000000"));
const rcpt = await tx.wait();
console.log('mint status', rcpt.status);
console.log("兑换余额",ethers.utils.formatEther(await MyTokenContract.balanceOf(SwapTokenAddress)))
const usd = await SwapTokenContract.getEthInUsd(ethers.utils.parseEther("1")); // 2000
const btkWei = usd.mul(1000).mul(ethers.utils.parseEther("1")); // 2000*1000*1e18
console.log("应得 BTK(wei)", btkWei.toString());
/* 6. 发起兑换:1 ETH -> BTK */
const ethAmount = ethers.utils.parseEther("1");
const txSwap = await SwapTokenContract.swap({ value: ethAmount });
await txSwap.wait();
/* 7. 查询结果 */
const btkBalance = await MyTokenContract.balanceOf(userAddr);
console.log(btkBalance)
const dec = await MyTokenContract.decimals();
console.log("💰 兑换后 BTK 余额:", ethers.utils.formatUnits(btkBalance,0));
}
<div style="display:flex; gap:8px;flex-wrap:wrap;"> <img src="https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/e136012c471c4df7a079a4e72ad14edc~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5pyo6KW_:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjQzNjE3MzQ5Njg0NTU0OSJ9&rk3s=e9ecf3d6&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1758281528&x-orig-sign=WA0BFd2c6PS%2BWISULx%2FdxqpxdCA%3D" alt="图1转存失败,建议直接上传图片文件" width="200"> <img src="https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/ac10668536094f38b74d7e46608ab9cc~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5pyo6KW_:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjQzNjE3MzQ5Njg0NTU0OSJ9&rk3s=e9ecf3d6&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1758281662&x-orig-sign=gRf7Hz8%2FRjNHsLK5sLyrHFqkEEk%3D" alt="图1转存失败,建议直接上传图片文件" width="200"> </div>
三步跑通移动端 swap
npx hardhat node
一键启动,私钥导入 MetaMask 即可秒连。npx hardhat deploy --tags token4,MockV3Aggregator,SwapToken
拿到三个核心地址,前端直接引用。Web3Provider
把 MetaMask 变成签名器,完成合约实例化,完成 swap。关键路径拆解
预言机读价 → 预铸流动性 → 用户输入 1 ETH → 合约按价放 BTK → 余额实时回显,整条链路在 10 秒内闭环。
下一步优化
latestAnswer
换成 latestRoundData
并加价格过期校验,满足生产级安全。useContractEvent
监听 Swap
事件,实现“交易成功即弹 Toast + 自动刷新余额”。至此,合约 + 前端 + 钱包 的完整 DeFi 小闭环已经在你的手机里跑通。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!