Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >web3钱包接入之viem

web3钱包接入之viem

作者头像
Maic
发布于 2025-02-12 06:11:37
发布于 2025-02-12 06:11:37
17500
代码可运行
举报
文章被收录于专栏:Web技术学苑Web技术学苑
运行总次数:0
代码可运行

过去一年,接入了很多第三方钱包,有solana,rainbow,web3Modal【现在是reown】了、aptos相关区块链钱包,第三方钱包接入已经相对非常成熟,API通常来讲非常简易,基本不用考虑更底层的API,常用的hook也会更高效,但通常接入钱包过程中,似乎总有种,知其然而不知所以然的感觉,本文是一篇钱包偏底层的接入流程。

本文主要以evm钱包为例子

首先我们要初步了解viem,我们在项目中,你也许会看到大量的wagmi,实际上这是对viem更上层的封装,wagmi是以太坊交互官方封装便捷好用的react库,让你非常快捷方便的与钱包以及以太坊交互,但本质上所有与以太坊交互的hook依赖于viem

在开始本文之前,你的浏览器得提前安装一个metaMask插件钱包

查看区块block

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 
// test.js
import { createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";
const client = createPublicClient({
  chain: mainnet,
  transport: http(),
});
console.log(client);
const getBlock = async () => {
  const blockNumber = await client.getBlockNumber();
  console.log(blockNumber);
};
getBlock();

当我们运行node test.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 
{
  account: undefined,
  batch: undefined,
  cacheTime: 4000,
  ccipRead: undefined,
  chain: {
    formatters: undefined,
    fees: undefined,
    serializers: undefined,
    id: 1,
    name: 'Ethereum',
    nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
    rpcUrls: { default: [Object] },
    blockExplorers: { default: [Object] },
    contracts: {
      ensRegistry: [Object],
      ensUniversalResolver: [Object],
      multicall3: [Object]
    }
  },
  key: 'public',
  name: 'Public Client',
  pollingInterval: 4000,
  request: [AsyncFunction (anonymous)],
  transport: {
    key: 'http',
    name: 'HTTP JSON-RPC',
    request: [AsyncFunction: request],
    retryCount: 3,
    retryDelay: 150,
    timeout: 10000,
    type: 'http',
    fetchOptions: undefined,
    url: 'https://cloudflare-eth.com'
  },
  type: 'publicClient',
  uid: '2523e6fdcf6',
  extend: [Function (anonymous)],
  call: [Function: call],
  createBlockFilter: [Function: createBlockFilter],
  createContractEventFilter: [Function: createContractEventFilter],
  createEventFilter: [Function: createEventFilter],
  createPendingTransactionFilter: [Function: createPendingTransactionFilter],
  estimateContractGas: [Function: estimateContractGas],
  estimateGas: [Function: estimateGas],
  getBalance: [Function: getBalance],
  getBlobBaseFee: [Function: getBlobBaseFee],
  getBlock: [Function: getBlock],
  getBlockNumber: [Function: getBlockNumber],
  getBlockTransactionCount: [Function: getBlockTransactionCount],
  getBytecode: [Function: getBytecode],
  getChainId: [Function: getChainId],
  getCode: [Function: getCode],
  getContractEvents: [Function: getContractEvents],
  getEip712Domain: [Function: getEip712Domain],
  getEnsAddress: [Function: getEnsAddress],
  getEnsAvatar: [Function: getEnsAvatar],
  getEnsName: [Function: getEnsName],
  getEnsResolver: [Function: getEnsResolver],
  getEnsText: [Function: getEnsText],
  getFeeHistory: [Function: getFeeHistory],
  estimateFeesPerGas: [Function: estimateFeesPerGas],
  getFilterChanges: [Function: getFilterChanges],
  getFilterLogs: [Function: getFilterLogs],
  getGasPrice: [Function: getGasPrice],
  getLogs: [Function: getLogs],
  getProof: [Function: getProof],
  estimateMaxPriorityFeePerGas: [Function: estimateMaxPriorityFeePerGas],
  getStorageAt: [Function: getStorageAt],
  getTransaction: [Function: getTransaction],
  getTransactionConfirmations: [Function: getTransactionConfirmations],
  getTransactionCount: [Function: getTransactionCount],
  getTransactionReceipt: [Function: getTransactionReceipt],
  multicall: [Function: multicall],
  prepareTransactionRequest: [Function: prepareTransactionRequest],
  readContract: [Function: readContract],
  sendRawTransaction: [Function: sendRawTransaction],
  simulateContract: [Function: simulateContract],
  verifyMessage: [Function: verifyMessage],
  verifySiweMessage: [Function: verifySiweMessage],
  verifyTypedData: [Function: verifyTypedData],
  uninstallFilter: [Function: uninstallFilter],
  waitForTransactionReceipt: [Function: waitForTransactionReceipt],
  watchBlocks: [Function: watchBlocks],
  watchBlockNumber: [Function: watchBlockNumber],
  watchContractEvent: [Function: watchContractEvent],
  watchEvent: [Function: watchEvent],
  watchPendingTransactions: [Function: watchPendingTransactions]
}

21074983n

我们发现client这个对象返回出了很多与以太坊交互的接口

http()其实会默认选择rpc就是cloudflare-eth.comcontracts也提供了一个默认的address,默认的交易对就是ETH,精度18

连接钱包

我们知道与以太坊交互去中心化,所有的交易账户需要一个账号与链上产生交互,所以需要链接钱包,当我们插件安装了metaMask后,浏览器的window对象就已经绑定了ethereum这个对象,所以基本上所有与钱包交互的接口的前提是你必须在插件商店安装对应的一个钱包才行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 
   function App() {
        const handleConnetWallet = async () => {
        const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' });
        console.log(account, '==account')
      }
  
   return (<div>
            <h1 onClick={handleConnetWallet}>Content Wallet</h1>
      </div>);
   }

当前的web端唤起小狐狸钱包或者其他钱包,基本就是依靠这个window.ethereum.request这个接口

我们注意到一个钱包有很多个账号,而且我们默认的就是ETH主网,因为我们的钱包会默认选择一个ETH主网,当你选择确认对应钱包后,此时的account就是我们选择的钱包地址

SignMessage

通常我们在连接钱包后,我们需要做一个签名,这个签名一般由客户端主动发起,当签名成功后,就会获取一个hash,然后这个hash一般会是通过一个后端登录的接口进行验证这个账户

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 
import  {memo, useRef} from "react";
...
function App() {
     const accountRef = useRef(null);
    const handleSignMessage = async () => {
    const walletClient = createWalletClient({
        account: accountRef.current,
        chain: mainnet,
        transport:custom(window.ethereum),
    });
    const hash = await walletClient.signMessage({
        message: "hello world"
    });
    console.log(hash);
  }
  const handleConnetWallet = async () => {
    const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' });
    accountRef.current = account;
  }
  return (<div>
     <h1 onClick={handleConnetWallet}>Content Wallet</h1>
     <h1 onClick={handleSignMessage}>SignMessage</h1>
  </div>)
}

注意签名的前提必须是你已经链接钱包

返回的hash是这这样的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 
0xaeedca0a7745ee7dbbabdf69226dd7c27aa0f17c8bdcf58616ced8f1b9fe7bc60da3fcdb850af23d1379c2a0b57349862db2010ceb50f8a33322aed68119b14b1c

我们会发现签名值的变化与message这个传入的字符串有关,如果这个字符串发生变化,那么签名后的hash就不回一样,反之当message不发生变化时,产生的hash是不会变化的

isAddress

主要是判断这个钱包地址是否是eth地址

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 
import {isAddress} from "viem";
...
function App() {
       const [address, setIsAddress] = useState("");
      const [isEthAddress, setIsEthAddress] = useState(false);
     const handleVerifyAddress = () => {
            const isEthAddress = isAddress(address);
            setIsEthAddress(isEthAddress);
      }
    return <>
        <div>
            <input type="text" onChange={(e) => setIsAddress(e.target.value)} />
            <button onClick={handleVerifyAddress}>Verify address</button>
            <p>{address} {isEthAddress ? 'is': 'is not'} eth address</p>
        </div>
    <>
}

sendTransaction

可以理解成一个钱包地址向另外一个地址转账,在操作前,必须有SignMessage操作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 
  ...
  const handleSendTransaction = async () => {
    const res = await wallect.current.sendTransaction({
        to: "0x5A39756bAE97685917a292B33ddFb2B54DF1e806",
        value: parseEther("0.001"), // 0.001ETH
    });
    console.log(res);
  }
  return (<>
      <h1 onClick={handleSendTransaction}>sendTransaction</h1>
  </>)

你会发现,我发送2.66$,所需要的gas费用就是0.67$,所以实际上你在钱包中发起的一笔转账,大概总计就需要3.33$

如果你把实际转账的参数改成这样

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 
  const handleSendTransaction = async () => {
    const res = await wallect.current.sendTransaction({
        to: "0x5A39756bAE97685917a292B33ddFb2B54DF1e806",
        value: parseEther("1"), // 1 ETH
    });
    console.log(res);
  }
  return (<>
       <h1 onClick={handleSendTransaction}>sendTransaction</h1>
  </>)

你会发现gas费用是动态变化的,但是跟你当下交易的笔数的大小无关,gas费每次都会变化,如果多笔转账合并,那么会减少不少的gas费用

获取公共操作

主要是查询用户账户余额、检索当前区块号,或者检索当前的交易信息,查询这些并不需要签名等权限

  • getBalance
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 
import {createPublicClient, http, createWalletClient, custom, isAddress, parseEther, formatUnits } from "viem"

import { mainnet, bsc } from "viem/chains";

const client = createPublicClient({
    chain: bsc, // bsc链
    transport: http(),
 })
 
 function App() {
      const handleGetBlance = async () => {
          const res = await client.getBalance({
              address: "0x6c85e349A70791e95fD6D9D5e066C6Ec136E0a92"
          });
           console.log(`余额:${formatUnits(res, 18)} BNB`);
      }
     return <div>
         <div onClick={handleGetBlance}>get Blance</div>
     </div>
 }

我们发现对于获取后的余额实际上精度是18位的,最终我们使用viem中的formatUnits帮我们处理成了与钱包余额一样的余额数值

  • getTransactionReceipt 主要是根本交易hash能查询当前的交易状态,比如
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 
 ...
 const handleGetTranstion = async () => {
    const res = await client.getTransactionReceipt({
        hash: "0xf6914af778b18ca1be98adead61af6351862fe26faad7e64d631df30fe925cd4"
    });
 console.log(res);
 function App() {
     return <>
             <h1 onClick={handleGetTranstion}>get transition hash</h1>
     </>
 }
  

我们会查询这个这交易hash的在区块链的实际交易状态,实际上你在https://bscscan.com/ 中根据交易hash也可查询看到对应的状态

至此一个从一个连接钱包登录,到签名,再到sendTransition的基础功能就基本结束,viem也提供了如何与以太坊合约交互的接口,这些都会有一个ABI的数据相关联,后续也会写个测试网合约进行调试,更多的详细的与以太坊交互的参考viem 文档

总结

  • 了解学习到使用更低层的viem官方接口唤起钱包,进行钱包连接签名sendTranstion操作
  • viem开放出来的公用区块查询,比如钱包余额,区块,以及交易状态
  • code example
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-10-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Web技术学苑 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
响铃:美团滴滴大战:消失的业务边界与迷失的竞争战略
新华网用“今日头条的幡然醒悟值得肯定”对今日头条做了概括性总结,可关于美团和滴滴的争议还没有答案。
曾响铃
2018/08/21
3490
响铃:美团滴滴大战:消失的业务边界与迷失的竞争战略
美团打车VS滴滴外卖:尔要战便战,却谁也干不掉谁
近日根据《财经》报道,滴滴外卖将进入全国九大城市,包括无锡、南京、长沙、福州、济南、宁波、温州、成都和厦门。这是滴滴外卖的首批上线城市,商户招募已同步启动,但具体上线时间未定。据了解,滴滴外卖将通过降
罗超频道
2018/04/17
7500
美团打车VS滴滴外卖:尔要战便战,却谁也干不掉谁
你卸载滴滴了吗?
2015年2月14日情人节,在柳传志坐庄调停下,烧钱烧到疲惫的滴滴、快的宣布合并。
IT派
2018/07/30
8340
你卸载滴滴了吗?
滴滴CEO程维:创业是一条没有尽头的路,路上是不完的仗
口述文章来源于程维在小饭桌创业课堂上的演讲 滴滴和快的,在2014年掀起了中国互联网史上前所未有的烧钱大战,然后又在2015年出闪电般的合并。在外人看来,就如做梦一般的不可思议。但是在滴滴CEO程维看
用户1756920
2018/06/20
6200
情人节美团上线打车业务怼滴滴,故事不错但挑战也很多
在去年11月的乌镇互联网大会上,被媒体视作“新三巨头”的“TMD”即今日头条、美团点评和滴滴创始人有一次会面,彼时谈笑风生的三个创始人中的两位,在三个月后的今天成为竞争对手:美团开始在南京地区低调试运
罗超频道
2018/04/26
8430
情人节美团上线打车业务怼滴滴,故事不错但挑战也很多
共享单车风云再起!美团和滴滴明争暗斗,到底谁会成为单车之王
自从摩拜卖给美团以后,共享单车的大战暂告一段落。最近,传出了滴滴收购ofo的消息,引发了媒体和互联网人的广泛关注。当然,滴滴收购ofo是非常合理的。原本滴滴就是ofo的大股东,而且滴滴是全国最大的出行平台,通过收购ofo来完善业务布局,对于滴滴来说是非常有价值的。一旦消息坐实,我想共享单车市场又无法平静了,一场大战难以避免。美团和滴滴不仅在网约车领域打得火热,而且即将在单车市场进行激烈的竞争,到底谁会成为共享单车的王者?
光荣与梦想1987
2018/09/11
3820
出行巨头历经九年沉浮,未来的滴滴将驶向何方?
国内的互联网企业,从阿里走出去的高管几乎占据了半壁江山,滴滴创始人兼CEO程维便是其中之一。
敖丙
2021/04/16
5150
出行巨头历经九年沉浮,未来的滴滴将驶向何方?
网约车江湖群雄并起!美团、京东先后入局,程维已经睡不着觉了吧
2018年,对于滴滴来说注定是不平静的一年。先是在年初,美团高调进入网约车市场,想跟滴滴一争高低。接着,先后发生了郑州空姐遇害案、温州女孩遇害案,网络上骂声一片。最终,滴滴的程维和柳青联名发布了道歉声明,公众的怒火才暂时行以平息。不过,程维和柳青还没有缓过气,就出现了另外一件事情。近日,京东集团下属一家公司日前更新了工商资料,在经营范围一栏新增了网约车服务。莫非京东也要开展网约车服务了?在国内,京东可是仅次于BAT的互联网公司,实力非常雄厚。现在巨头也要过来抢生意了,滴滴应该怎么办?
光荣与梦想1987
2018/09/11
5840
滴滴的第二次反围剿,不在外卖
“围魏,不能救赵”。 当所有人都认为滴滴已经“吃定”网约车市场时,2018年形势陡然生变。24日,美团宣布上海出行市场日订单量已达到30万,五成用户成回头客。在美团打车上线后,程维问王兴为什么搞打车,
罗超频道
2018/04/17
7700
滴滴的第二次反围剿,不在外卖
美团滴滴,互为掣肘
文|孟永辉 最终,美团还是开启了打车的端口。美团与滴滴之间的打车之战一触即发,当前人们比较关心的问题就是谁会是最后的胜利者?谁又将能够主导未来的打车市场?从目前整个市场的反应情况来看,希望美团能够在这场战役中胜利的人占据了大多数。滴滴一家独大的局面无论是对于司机还是乘客来讲都是他们不愿意见到的。 对于乘客来讲,他们希望能够有更多的入局者参与其中,这样他们能够获得更多的选择性,甚至还有可能获得竞争者之间的价格战带来的红利。对于司机来讲,一家巨大的局面对于他们来讲更多地是任人宰割,而无法有太多的自主性。因此,无
孟永辉
2018/05/15
5710
美团再出幺蛾子,启动美团打车项目,滴滴感到威胁了吗?
要说今年最火的项目及概念,那就一定是人工智能项目了,不管是从国内还是国外,整个地球都被人工智能所包裹。如果,你说自己是互联网公司的,但却不知道什么是人工智能,那真是秀逗了。 可是,说起前两年,那就一定是O2O了,而O2O的典型代表,那就是美团了,其不管是到店的团购业务,还是到家的外卖业务,都打出了一片天。而且其还全面纵向发展,酒店旅游,打车业务相继启动,俨然要成为BAT外的第三极,可以说野心极大。 但是,正是因为其全面发展,树立了无数的敌人 团购业务一家独大,美团外卖对标饿了么,酒店旅游对标携程,随着打
企鹅号小编
2018/01/16
7000
美团再出幺蛾子,启动美团打车项目,滴滴感到威胁了吗?
滴滴打车CTO张博:生死战役,技术和时间赛跑
2012年成立的滴滴打车,仅用了三年时间就书写了:覆盖300个城市,用户数从2200万增到1.5亿,月活跃用户增长了600多倍(2014年平安夜当天,全国用滴滴打车出行人数超过了3000万人),打车成功率高于90%……这些永远会被铭记在移动互联网历史中的神奇记录。而不为人知的是,支撑滴滴打车如此庞大用户数量的架构,以及那些曾无数次不眠不休应对挑战的技术伙伴们。 人称“博师傅”的滴滴打车CTO张博这样描述:“三年来,基本天天都在‘打仗’。每天一睁眼就要想生和死的问题。比谁能最先稳定,能将用户留住,谁就是胜利者
CSDN技术头条
2018/02/09
1.2K0
滴滴打车CTO张博:生死战役,技术和时间赛跑
滴滴如何用八十万成为百亿美金公司?
福布斯中文网授权转载 网站: forbeschina.com 微信: forbeschinaonline 如需转载请联系editor@forbeschina.com 阿里巴巴前高管、滴滴打车天使投资人王刚近日在杭州接受了《福布斯》独家专访,讲述了集齐“阿里的人、百度的技术、腾讯的钱”的滴滴如何从八十万启动资金,在三年内成长为百亿美金级移动互联网公司。滴滴创始人程维此前曾把创业历程比喻为“桥段丰富的韩剧”,王刚在采访时也把滴滴的故事形容为“跌宕起伏,天天都是高潮”,他描述了眼中的程维和柳青,并分享了BAT力
大数据文摘
2018/05/23
5200
希望滴滴再也不会道歉。
几天前,乐清女孩被滴滴顺风车司机杀害的消息爆出,一石激起千层浪,滴滴陷入巨大的舆论之中。
昱良
2018/09/29
3770
大数据杀熟?那分明是滴滴最后的希望
不知道大家关注新闻没有,前几天有一个知名大学的教授公布了一个报告。他花费50000余元打车800余次,总结出了滴滴打车杀熟的报告。比如说,除了苹果手机之外,手机越便宜叫车的费用越便宜,手机越贵,叫车越贵。网友们纷纷义愤填膺,高呼停止大数据杀熟!
TechFlow-承志
2021/03/25
7660
历经9981难,王兴的斗战胜佛修炼史
天赋异禀的孙悟空经历九九八十一难,磨去了顽劣,才终成斗战胜佛,纵观王兴的创业史也是这般,虽挫折连连,但通过打怪升级、搬救兵,最终逆袭成王。
挖数
2019/07/09
8890
历经9981难,王兴的斗战胜佛修炼史
美团点评融资40亿美元!程维能睡着了,今夜谁无眠?
今天,美团点评宣布完成新一轮40亿美元融资,投后估值300亿美元,传了半年的美团融资,终于尘埃落定。美团的300亿美元估值,第一次落了实锤。 从市值/估值来看,美团成为仅次于BAT、京东、蚂蚁、滴滴和网易的第八大互联网公司——蚂蚁和滴滴的估值已分别超过600亿美元和500亿美元,“MMD”,中国互联网未上市新三巨头浮出水面。阿里孵化出了蚂蚁和菜鸟两大百亿美金级巨头,腾讯则花钱买出了美团和滴滴两个,两者不分仲伯。 美团此次融资由腾讯领投,引入了新的战略投资方The Priceline Group,其他主要投资
罗超频道
2018/04/25
7480
美团点评融资40亿美元!程维能睡着了,今夜谁无眠?
被逼出海,滴滴:我太难了
7 月 28 日,长城战略咨询发布了《2019 年中国独角兽企业研究报告》,滴滴出行以 580 亿的估值排名第三。
深度学习与Python
2020/08/11
9160
被逼出海,滴滴:我太难了
打车大战一周年:从“炮灰”到下一波BAT
2013年,二十几个打车软件创业公司“摸黑”前行。12月,快的打车率先与支付宝钱包联手推广打车移动支付,在北京出门打车用支付宝钱包付款,乘客和司机每人可以获得5元返现。 随后,滴滴打车与微信支付合作,并宣布从1月20日开始打车立减10元。之后快的和支付宝迅速跟进,并喊出“永远比对手多一块”来压制滴滴。 自此,堪称互联网最疯狂补贴大战拉开帷幕。成交每个订单,用户和司机都可以得到10元以上的高额补贴和奖励。而且双方都希望在补贴上压对方一头,导致补贴数额越来越高。据媒体公开数据,截至5月,快的和滴滴用于乘客和司机
罗超频道
2018/04/28
6430
滴滴柳青:算法和数据才是核武器
点击标题下「大数据文摘」可快捷关注 柳青——有太多光环的人:柳传志的女儿,高盛亚洲区的董事总经理,滴滴打车的 COO。但见面聊过之后,这些光环淡了下去,她在我眼中的形象换成了一个温和、思维敏捷而且很有梦想的女性创业者。 采访约在滴滴的办公室,从外面的呜呜冷风中逃出来,突然进到他们的办公室,很暖,进门是滴滴的标志橙色,转了一圈,从气场上能明显感觉到这是一家年轻并且处在快速上升期的公司。 我和柳青在滴滴的图书室里坐了下来,简单几句之后就直入主题了。 36氪:现在滴滴是个什么状态? 柳青:发展挺快的。两年时间,
大数据文摘
2018/05/23
4570
推荐阅读
相关推荐
响铃:美团滴滴大战:消失的业务边界与迷失的竞争战略
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验