专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

全栈以太坊和EVM开发的完整指南

  使用React、Ethers。js、Solidity和Hardhat构建全栈dApp
  在本教程中,您将学习一个web3技术栈,它允许您利用以太坊虚拟机(EVM)在包括以太坊、Polygon、Avalanche、Celo等在内的数十个区块链网络上构建全栈应用程序。
  该项目的代码位于此处〔1〕。本教程的视频课程位于此处〔2〕。另请查看定义web3堆栈〔3〕
  自从我开始在区块链领域工作以来,我一直在深入研究Solidity和EVM的智能合约开发。我已经确定了我认为是开始使用Solidity构建全栈dApp的技术栈:
  客户端框架React
  以太坊开发环境Hardhat〔4〕
  以太坊Web客户端库Ethers。js〔5〕
  API层TheGraphProtocol〔6〕
  我在学习这个的过程中遇到的问题是,虽然对于这些东西中的每一个都有相当好的文档,但实际上没有关于如何将所有这些东西放在一起并理解它们如何相互工作的东西。有一些非常好的样板,例如scaffoldeth〔7〕(其中还包括Ethers、Hardhat和TheGraph),但对于刚入门的人来说可能太多了。
  我想要一个端到端的指南来向我展示如何使用最新的资源、库和工具构建完整的以太坊应用程序。
  我感兴趣的是:1。如何创建、部署和测试以太坊智能合约到本地、测试和主网2。如何在本地、测试和生产环境网络之间切换3。如何使用React、Vue、Svelte或Angular等前端的各种环境连接到合约并与之交互
  在花了一些时间弄清楚所有这些并开始使用我感到非常满意的堆栈之后,我认为写出如何使用这个堆栈构建和测试一个完整的以太坊应用程序会很好,而不仅仅是为了其他人还有谁可能对这个栈感兴趣,也供自己以后参考。这就是那个参考。碎片
  让我们回顾一下我们将使用的主要部分以及它们如何适应堆栈。一、以太坊开发环境
  在构建智能合约时,您需要一种无需处理实时环境即可部署合约、运行测试和调试Solidity代码的方法。
  您还需要一种方法将您的Solidity代码编译成可以在客户端应用程序中运行的代码在我们的例子中,是一个React应用程序。稍后我们将详细了解其工作原理。
  Hardhat是专为全栈开发而设计的以太坊开发环境和框架,也是我将在本教程中使用的框架。
  生态系统中的其他类似工具是Ganache〔8〕、Truffle〔9〕和Foundry〔10〕。2。以太坊Web客户端库
  在我们的React应用程序中,我们需要一种方法来与已部署的智能合约进行交互。我们将需要一种方法来读取数据以及发送新交易。
  ethers。js〔11〕旨在成为一个完整而紧凑的库,用于从React、Vue、Angular或Svelte等客户端JavaScript应用程序与以太坊区块链及其生态系统进行交互。这是我们将要使用的库。
  生态系统中另一个流行的选择是web3。js〔12〕3。MetaMask
  Metamask〔13〕有助于处理帐户管理并将当前用户连接到区块链。MetaMask使用户能够以几种不同的方式管理他们的帐户和密钥,同时将他们与站点上下文隔离开来。
  一旦用户连接了他们的MetaMask钱包,您作为开发人员就可以与全球可用的以太坊API(window。ethereum)交互,该API可以识别web3兼容浏览器的用户(例如MetaMask用户),并且每当您请求交易签名时,MetaMask都会提示以尽可能易于理解的方式向用户展示。4。React
  React是一个前端JavaScript库,用于构建Web应用程序、用户界面和UI组件。它由Facebook和许多个人开发人员和公司维护。
  React及其庞大的元框架生态系统(如Next。js〔14〕、Gatsby〔15〕、Redwood〔16〕、Blitz。js〔17〕等)支持所有类型的部署目标,包括传统SPA、静态站点生成器、服务器端渲染以及这三者的组合。React似乎继续在前端领域占据主导地位,我认为至少在不久的将来会继续这样做。5。Graph
  对于大多数构建在以太坊等区块链上的应用程序,直接从链上读取数据既困难又费时,因此您过去经常看到人们和公司构建自己的集中式索引服务器并为来自这些服务器的API请求提供服务。这需要大量的工程和硬件资源,并破坏了去中心化所需的安全属性。
  Graph是一种用于查询区块链数据的索引协议,它支持创建完全去中心化的应用程序并解决了这个问题,暴露了应用程序可以使用的丰富的GraphQL查询层。在本指南中,我们不会为我们的应用程序构建子图,但会在以后的教程中这样做。
  要了解如何使用TheGraph构建区块链API,请查看在以太坊上构建GraphQLAPI〔18〕。我们将建造什么
  在本教程中,我们将构建、部署和连接到几个基本的智能合约:1。在以太坊区块链上创建和更新消息的合约2。铸造代币的合同,然后允许合同的所有者将代币发送给其他人并读取代币余额,并且新代币的所有者也可以将它们发送给其他人。
  我们还将构建一个React前端,允许用户:1。从部署到区块链的合约中读取问候语2。更新问候语3。将新铸造的代币从他们的地址发送到另一个地址4。一旦有人收到代币,允许他们也将代币发送给其他人5。从部署到区块链的合约中读取代币余额先决条件1。本地机器上安装的Node。js2。MetaMask〔19〕Chrome扩展安装在您的浏览器中
  您不需要为本指南拥有任何以太坊,因为我们将在整个教程的测试网络上使用假测试以太币。入门
  首先,我们将创建一个新的React应用程序:npxcreatereactappreactdapp
  接下来,切换到新目录并使用NPM或Yarnethers。js〔20〕安装和hardhat〔21〕使用:npminstallethershardhatnomiclabshardhatwaffleethereumwafflechainomiclabshardhatethers安装和配置以太坊开发环境
  接下来,使用Hardhat初始化一个新的以太坊开发环境:npxhardhat?Whatdoyouwanttodo?CreateaJavaScriptproject?Hardhatprojectroot:Choosedefaultpath
  如果您遇到有关README。md文件的错误,请删除README。md文件并重新运行该命令。
  现在您应该会在根目录中看到为您创建的以下工件:
  hardhat。config。js您的整个Hardhat设置(即您的配置、插件和自定义任务)都包含在此文件中。scripts一个包含名为samplescript。js的脚本的文件夹,该脚本将在执行时部署你的智能合约test一个包含示例测试脚本的文件夹contracts一个包含示例Solidity智能合约的文件夹
  由于MetaMask配置问题〔22〕,我们需要将HardHat配置上的链ID更新为1337。我们还需要更新已编译合约的工件〔23〕位置,使其位于React应用程序的src目录中。
  要进行这些更新,请打开hardhat。config。js并将module。exports更新为如下所示:module。exports{solidity:0。8。9,paths:{artifacts:。srcartifacts,},networks:{hardhat:{chainId:1337}}};我们的智能合约
  接下来,让我们看一下在contractsGreeter。sol中提供给我们的示例合约:SPDXLicenseIdentifier:MITpragmasolidity0。8。9;importhardhatconsole。sol;contractGreeter{stringgreeting;constructor(stringmemorygreeting){console。log(DeployingaGreeterwithgreeting:,greeting);greetinggreeting;}functiongreet()publicviewreturns(stringmemory){returngreeting;}functionsetGreeting(stringmemorygreeting)public{console。log(Changinggreetingfromstos,greeting,greeting);greetinggreeting;}}
  这是一个非常基本的智能合约。部署时,它会设置一个Greeting变量并公开一个可以调用以返回问候语的函数(greet)。
  它还公开了一个允许用户更新问候语(setGreeting)的函数。当部署到以太坊区块链时,这些方法将可供用户进行交互。读写以太坊区块链
  与智能合约交互的方式有两种,读取或写入交易。在我们的合约中,greet可以认为是读,而setGreeting可以认为是写交易。
  在写入或初始化交易时,您必须为要写入区块链的交易付费。为了使这项工作成功,您需要支付〔gas〕(https:www。investopedia。comtermsggasethereum。asp::textWhatIsGas(Ethereum)3F,ontheEthereumblockchainplatform),这是在以太坊区块链上成功进行交易和执行合同所需的费用或价格。
  只要您只是从区块链中读取数据而不更改或更新任何内容,您就不需要进行交易,也不会产生任何gas或成本。然后,您调用的函数将仅由您连接的节点执行,因此您无需支付任何气体,并且读取是免费的。
  ethers。js在我们的React应用程序中,我们与智能合约交互的方式是使用库、合约地址和Hardhat从合约创建的ABI〔24〕的组合。
  什么是ABI?ABI代表应用程序二进制接口。您可以将其视为您的客户端应用程序与部署您将与之交互的智能合约的以太坊区块链之间的接口。
  ABI通常由HardHat等开发框架从Solidity智能合约编译而成。您还可以经常在Etherscan〔25〕上找到智能合约的ABI编译ABI
  现在我们已经了解了基本的智能合约并了解了ABI是什么,让我们为我们的项目编译一个ABI。
  为此,请转到命令行并运行以下命令:npxhardhatcompile
  如果您有任何依赖性错误问题hardhattoolbox,请查看此处的〔26〕安装说明。
  现在,您应该会在src目录中看到一个名为artifacts的新文件夹。artifactscontractsGreeter。json文件包含ABI作为属性之一。当我们需要使用ABI时,我们可以从我们的JavaScript文件中导入它:importGreeterfrom。artifactscontractsGreeter。solGreeter。json
  然后我们可以像这样引用ABI:console。log(GreeterABI:,Greeter。abi)
  请注意,Ethers。js还支持人类可读的ABI〔27〕,但在本教程中不会涉及到这一点。部署和使用本地网络区块链
  接下来,让我们将智能合约部署到本地区块链,以便我们对其进行测试。
  要部署到本地网络,首先需要启动本地测试节点。为此,请打开CLI并运行以下命令:npxhardhatnode
  当我们运行此命令时,您应该会看到一个地址和私钥列表。
  这些是为我们创建的20个测试帐户和地址,我们可以使用它们来部署和测试我们的智能合约。每个账户还装有10,000个假以太币。稍后,我们将学习如何将测试帐户导入MetaMask,以便我们使用它。
  接下来,使用以下代码更新scriptsdeploy。js以部署Greeter合约:consthrerequire(hardhat);asyncfunctionmain(){constGreeterawaithre。ethers。getContractFactory(Greeter);constgreeterawaitGreeter。deploy(HelloWorld);awaitgreeter。deployed();console。log(contractsuccessfullydeployedto{greeter。address});}main()。catch((error){console。error(error);process。exitCode1;});
  现在我们可以运行部署脚本并为我们想要部署到本地网络的CLI提供一个标志:npxhardhatrunscriptsdeploy。jsnetworklocalhost
  执行此脚本后,智能合约应部署到本地测试网络,然后我们应该能够开始与其交互。
  部署合约时,它使用了我们启动本地网络时创建的第一个帐户。
  如果您查看CLI的输出,您应该能够看到如下内容:Greeterdeployedto:0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
  这个地址是我们将在我们的客户端应用程序中用来与智能合约对话的地址。保持此地址可用,因为我们在从客户端应用程序连接到它时需要使用它。
  要将交易发送到智能合约,我们需要使用运行npxhardhatnode时创建的帐户之一连接我们的MetaMask钱包。在CLI注销的合约列表中,您应该会看到帐号和私钥:reactdappgit:(main)npxhardhatnodeStartedHTTPandWebSocketJSONRPCserverathttp:127。0。0。1:8545AccountsAccount0:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266(10000ETH)PrivateKey:0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80。。。
  我们可以将此帐户导入MetaMask,以便开始使用那里可用的一些假Eth。
  为此,首先打开MetaMask并启用测试网络:
  接下来,将网络更新为Localhost8545:
  接下来,在MetaMask中点击账户菜单中的导入账户:
  复制然后粘贴由CLI注销的私钥之一,然后单击导入。导入帐户后,您应该会在帐户中看到Eth:
  现在我们已经部署了智能合约并准备好使用帐户,我们可以开始从React应用程序与其交互。连接React客户端
  在本教程中,我们不会担心使用CSS构建漂亮的UI以及所有这些,我们100专注于核心功能,以帮助您启动和运行。从那里,你可以把它拿走,如果你愿意的话,让它看起来不错。
  话虽如此,让我们回顾一下我们希望从React应用程序中实现的两个目标:1。从智能合约中获取greeting当前值2。允许用户更新greeting的值
  了解了这些事情后,我们如何做到这一点?以下是我们需要做的事情来实现这一点:1。创建一个输入字段和一些本地状态来管理输入的值(更新greeting)2。允许应用程序连接到用户的MetaMask帐户以签署交易3。创建用于读取和写入智能合约的函数
  为此,使用以下代码打开srcApp。js并更新它,将greeterAddress的值设置为您的智能合约的地址:import。App。css;import{useState}fromreact;import{ethers}fromethersimportGreeterfrom。artifactscontractsGreeter。solGreeter。jsonUpdatewiththecontractaddressloggedouttotheCLIwhenitwasdeployedconstgreeterAddressyourcontractaddressfunctionApp(){storegreetinginlocalstateconst〔greeting,setGreetingValue〕useState()requestaccesstotheusersMetaMaskaccountasyncfunctionrequestAccount(){awaitwindow。ethereum。request({method:ethrequestAccounts});}callthesmartcontract,readthecurrentgreetingvalueasyncfunctionfetchGreeting(){if(typeofwindow。ethereum!undefined){constprovidernewethers。providers。Web3Provider(window。ethereum)constcontractnewethers。Contract(greeterAddress,Greeter。abi,provider)try{constdataawaitcontract。greet()console。log(data:,data)}catch(err){console。log(Error:,err)}}}callthesmartcontract,sendanupdateasyncfunctionsetGreeting(){if(!greeting)returnif(typeofwindow。ethereum!undefined){awaitrequestAccount()constprovidernewethers。providers。Web3Provider(window。ethereum);constsignerprovider。getSigner()constcontractnewethers。Contract(greeterAddress,Greeter。abi,signer)consttransactionawaitcontract。setGreeting(greeting)awaittransaction。wait()fetchGreeting()}}return(headerclassNameAppheaderbuttononClick{fetchGreeting}FetchGreetingbuttonbuttononClick{setGreeting}SetGreetingbuttoninputonChange{esetGreetingValue(e。target。value)}placeholderSetgreetingheader);}exportdefaultApp;
  要测试它,请启动React服务器:npmstart
  当应用程序加载时,您应该能够获取当前问候语并将其注销到控制台。您还应该能够通过使用您的MetaMask钱包签署合同并花费假Ether来更新问候语。
  部署和使用实时测试网络
  我们还可以部署几个以太坊测试网络,如Ropsten、Rinkeby或Kovan,以便在无需将其部署到主网的情况下获得可公开访问的合约版本。在本教程中,我们将部署到Ropsten测试网络。
  首先,请先更新您的MetaMask钱包以连接到Ropsten网络。
  接下来,通过访问这个〔28〕或另一个测试水龙头,给自己发送一些测试以太币,以便在本教程的其余部分使用。
  我们可以通过注册Infura〔29〕或Alchemy〔30〕(我在本教程中使用Infura)等服务来访问Ropsten(或任何其他测试网络)。
  在Infura或Alchemy中创建应用程序后,您将获得一个如下所示的端点:https:ropsten。infura。iov3yourprojectid
  请务必在Infura或Alchemy应用程序配置中设置ALLOWLISTETHEREUMADDRESSES,以包含您将从中进行部署的帐户的钱包地址。
  要部署到测试网络,我们需要使用一些额外的网络信息更新我们的hardhat配置。我们需要设置的一件事是我们将从中部署的钱包的私钥。
  要获取私钥,您可以从MetaMask导出它。
  我建议不要在您的应用程序中对这个值进行硬编码,而是将其设置为环境变量。
  接下来,添加具有以下配置的networks属性:module。exports{defaultNetwork:hardhat,paths:{artifacts:。srcartifacts,},networks:{hardhat:{},ropsten:{url:https:ropsten。infura。iov3yourprojectid,accounts:〔0x{yourprivatekey}〕}},solidity:0。8。9,};
  要部署,请运行以下脚本:npxhardhatrunscriptsdeploy。jsnetworkropsten
  部署合约后,您应该能够开始与其交互。您现在应该能够在EtherscanRopstenTestnetExplorer〔31〕上查看实时合约。铸造代币
  智能合约最常见的用例之一是创建代币,让我们看看我们如何做到这一点。由于我们对所有这些工作原理了解得更多一些,所以我们会走得更快一些。
  在主contracts目录中创建一个名为Token。sol的新文件。
  接下来,使用以下智能合约更新Token。sol:SPDXLicenseIdentifier:MITpragmasolidity0。8。9;importhardhatconsole。sol;contractToken{stringpublicnameNaderDabitToken;stringpublicsymbolNDT;uintpublictotalSupply1000000;mapping(addressuint)balances;constructor(){balances〔msg。sender〕totalSupply;}functiontransfer(addressto,uintamount)external{require(balances〔msg。sender〕amount,Notenoughtokens);balances〔msg。sender〕amount;balances〔to〕amount;}functionbalanceOf(addressaccount)externalviewreturns(uint){returnbalances〔account〕;}}
  请注意,此代币合约仅用于演示目的,不符合ERC20〔32〕标准。我们将在这里〔33〕介绍ERC20代币
  该合约将创建一个名为NaderDabitToken的新代币,并将供应量设置为1000000。
  接下来,编译这个合约:npxhardhatcompile
  现在,更新scriptsdeploy。js中的部署脚本以包含这个新的Token合约:consthrerequire(hardhat);asyncfunctionmain(){const〔deployer〕awaithre。ethers。getSigners();console。log(Deployingcontractswiththeaccount:,deployer。address);constGreeterawaithre。ethers。getContractFactory(Greeter);constgreeterawaitGreeter。deploy(Hello,World!);constTokenawaithre。ethers。getContractFactory(Token);consttokenawaitToken。deploy();awaitgreeter。deployed();awaittoken。deployed();console。log(Greeterdeployedto:,greeter。address);console。log(Tokendeployedto:,token。address);}main()。then(()process。exit(0))。catch(error{console。error(error);process。exit(1);});
  现在,我们可以将这个新合约部署到本地或Ropsten网络:npxhardhatrunscriptsdeploy。jsnetworklocalhost
  部署合约后,您可以开始将这些代币发送到其他地址。
  为此,让我们更新完成这项工作所需的客户端代码:import。App。css;import{useState}fromreact;import{ethers}fromethersimportGreeterfrom。artifactscontractsGreeter。solGreeter。jsonimportTokenfrom。artifactscontractsToken。solToken。jsonconstgreeterAddressyourcontractaddressconsttokenAddressyourcontractaddressfunctionApp(){const〔greeting,setGreetingValue〕useState()const〔userAccount,setUserAccount〕useState()const〔amount,setAmount〕useState()asyncfunctionrequestAccount(){awaitwindow。ethereum。request({method:ethrequestAccounts});}asyncfunctionfetchGreeting(){if(typeofwindow。ethereum!undefined){constprovidernewethers。providers。Web3Provider(window。ethereum)console。log({provider})constcontractnewethers。Contract(greeterAddress,Greeter。abi,provider)try{constdataawaitcontract。greet()console。log(data:,data)}catch(err){console。log(Error:,err)}}}asyncfunctiongetBalance(){if(typeofwindow。ethereum!undefined){const〔account〕awaitwindow。ethereum。request({method:ethrequestAccounts})constprovidernewethers。providers。Web3Provider(window。ethereum);constcontractnewethers。Contract(tokenAddress,Token。abi,provider)constbalanceawaitcontract。balanceOf(account);console。log(Balance:,balance。toString());}}asyncfunctionsetGreeting(){if(!greeting)returnif(typeofwindow。ethereum!undefined){awaitrequestAccount()constprovidernewethers。providers。Web3Provider(window。ethereum);console。log({provider})constsignerprovider。getSigner()constcontractnewethers。Contract(greeterAddress,Greeter。abi,signer)consttransactionawaitcontract。setGreeting(greeting)awaittransaction。wait()fetchGreeting()}}asyncfunctionsendCoins(){if(typeofwindow。ethereum!undefined){awaitrequestAccount()constprovidernewethers。providers。Web3Provider(window。ethereum);constsignerprovider。getSigner();constcontractnewethers。Contract(tokenAddress,Token。abi,signer);consttransationawaitcontract。transfer(userAccount,amount);awaittransation。wait();console。log({amount}Coinssuccessfullysentto{userAccount});}}return(headerclassNameAppheaderbuttononClick{fetchGreeting}FetchGreetingbuttonbuttononClick{setGreeting}SetGreetingbuttoninputonChange{esetGreetingValue(e。target。value)}placeholderSetgreetingbrbuttononClick{getBalance}GetBalancebuttonbuttononClick{sendCoins}SendCoinsbuttoninputonChange{esetUserAccount(e。target。value)}placeholderAccountIDinputonChange{esetAmount(e。target。value)}placeholderAmountheader);}exportdefaultApp;
  接下来,运行应用程序:npmstart
  我们应该能够点击GetBalance并看到我们登录到控制台的帐户中有1,000,000个代币。
  您还应该能够通过单击导入令牌在MetaMask中查看它们:
  接下来单击CustomToken并输入令牌合约地址,然后单击AddCustomToken。(如果询问代币小数,请选择0)现在代币应该在您的钱包中可用:
  接下来,让我们尝试将这些硬币发送到另一个地址。
  为此,请复制另一个帐户的地址,并使用更新后的ReactUI将它们发送到该地址。当您检查令牌数量时,它应该等于原始数量减去您发送到该地址的数量。ERC20代币
  ERC20代币标准〔34〕定义了一套适用于所有ERC20代币的规则,使它们能够轻松地相互交互。ERC20使得人们可以很容易地铸造自己的代币,这些代币将与以太坊区块链上的其他代币具有互操作性。
  让我们看看如何使用ERC20标准构建我们自己的代币。
  首先,安装OpenZepplin〔35〕智能合约库,我们将在其中导入基础ERC20令牌:npminstallopenzeppelincontracts
  接下来,我们将通过扩展(或继承)合约来创建我们的代币ERC20:SPDXLicenseIdentifier:MITpragmasolidity0。8。9;importopenzeppelincontractstokenERC20ERC20。sol;contractNDTokenisERC20{constructor(stringmemoryname,stringmemorysymbol)ERC20(name,symbol){mint(msg。sender,100000(1018));}}
  构造函数允许您设置代币名称和符号,mint函数允许您铸造代币并设置数量。
  默认情况下,ERC20将小数位数设置为18,因此在我们的mint函数中,我们将100,000乘以10的18次方来铸造总共100,000个代币,每个代币有18个小数位(类似于1Eth由10到18wei〔36〕。
  要部署,我们需要传入构造函数值(name和symbol),因此我们可能会在部署脚本中执行如下操作:constNDTokenawaithre。ethers。getContractFactory(NDToken);constndTokenawaitNDToken。deploy(NaderDabitToken,NDT);
  通过扩展原始的ERC20代币,您的代币将继承以下所有功能和功能:functionname()publicviewreturns(string)functionsymbol()publicviewreturns(string)functiondecimals()publicviewreturns(uint8)functiontotalSupply()publicviewreturns(uint256)functionbalanceOf(addressowner)publicviewreturns(uint256balance)functiontransfer(addressto,uint256value)publicreturns(boolsuccess)functiontransferFrom(addressfrom,addressto,uint256value)publicreturns(boolsuccess)functionapprove(addressspender,uint256value)publicreturns(boolsuccess)functionallowance(addressowner,addressspender)publicviewreturns(uint256remaining)
  部署后,您可以使用这些功能中的任何一个与新的智能合约进行交互。有关ERC20代币的另一个示例,请查看Soliditybyexample〔37〕结论
  好吧,我们在这里涵盖了很多,但对我来说,这是开始使用这个堆栈的面包和黄油核心,也是我想要拥有的东西,不仅是作为一个正在学习所有这些东西的人,而且也是未来如果我需要参考我将来可能需要的任何东西。我希望你学到了很多。
  如果除了MetaMask之外你还想支持多个钱包,请查看Web3Modal〔38〕,它可以通过相当简单和可自定义的配置轻松地在你的应用程序中实现对多个提供商的支持。
  在我未来的教程和指南中,我将深入研究更复杂的智能合约开发,以及如何将它们部署为subgraphs〔39〕以在它们之上公开GraphQLAPI并实现分页和全文搜索等功能。
  我还将探讨如何使用IPFS和Web3数据库等技术以分散的方式存储数据。
  原文:https:web3。careerlearnweb3web3interviewquestions
  引用链接
  〔1〕此处:https:github。comdabit3fullstackethereum
  〔2〕此处:https:www。youtube。comwatch?va0osIaAOFSE
  〔3〕定义web3堆栈:https:edgeandnode。comblogdefiningtheweb3stack
  〔4〕Hardhat:https:hardhat。org
  〔5〕Ethers。js:https:docs。ethers。iov5
  〔6〕TheGraphProtocol:https:thegraph。com
  〔7〕scaffoldeth:https:github。comaustintgriffithscaffoldeth
  〔8〕Ganache:https:www。trufflesuite。comganache
  〔9〕Truffle:https:www。trufflesuite。com
  〔10〕Foundry:https:www。paradigm。xyz202112introducingthefoundryethereumdevelopmenttoolbox
  〔11〕ethers。js:https:docs。ethers。iov5
  〔12〕web3。js:https:web3js。readthedocs。ioenv1。3。4
  〔13〕Metamask:https:metamask。iodownload。html
  〔14〕Next。js:https:nextjs。org
  〔15〕Gatsby:https:www。gatsbyjs。com
  〔16〕Redwood:https:redwoodjs。com
  〔17〕Blitz。js:https:blitzjs。com
  〔18〕在以太坊上构建GraphQLAPI:https:dev。todabit3buildinggraphqlapisonethereum4poa
  〔19〕MetaMask:https:metamask。io
  〔20〕ethers。js:https:docs。ethers。iov5
  〔21〕hardhat:https:github。comnomiclabshardhat
  〔22〕MetaMask配置问题:https:hardhat。orgmetamaskissue。html
  〔23〕我们还需要更新已编译合约的工件:https:hardhat。orgguidescompilecontracts。htmlartifacts
  〔24〕ABI:https:docs。soliditylang。orgenv0。5。3abispec。html
  〔25〕您还可以经常在Etherscan:https:etherscan。io
  〔26〕此处的:https:hardhat。orghardhatrunnerpluginsnomicfoundationhardhattoolbox
  〔27〕人类可读的ABI:https:blog。ricmoo。comhumanreadablecontractabisinethersjs141902f4d917
  〔28〕接下来,通过访问这个:https:faucet。egorfine。com
  〔29〕我们可以通过注册Infura:https:infura。iodashboardethereumcbdf7c5eee8b4e2b91e76b77ffd34533settings
  〔30〕Alchemy:https:www。alchemyapi。io
  〔31〕您现在应该能够在EtherscanRopstenTestnetExplorer:https:ropsten。etherscan。io
  〔32〕ERC20:https:eips。ethereum。orgEIPSeip20
  〔33〕我们将在这里:https:dev。todabit3thecompleteguidetofullstackethereumdevelopment3j13erc20token
  〔34〕代币标准:https:ethereum。orgendevelopersdocsstandardstokenserc20
  〔35〕OpenZepplin:https:github。comOpenZeppelinopenzeppelincontracts
  〔36〕wei:https:www。investopedia。comtermswwei。asp
  〔37〕Soliditybyexample:https:soliditybyexample。orgapperc20
  〔38〕Web3Modal:https:github。comWeb3Modalweb3modal
  〔39〕subgraphs:https:thegraph。comdocsdefineasubgraph

山路开车经常跑山路的车友注意这几点目前汽车基本上进入每个家庭。除了每天的通勤之外,许多人在旅行时选择自己开车,这就是现在所说的自驾游。相对而言,自驾游比团体游更有趣更自由,但危险系数也增加了。毕竟,自驾游通常需要独多个城市取消限跌令,降价序幕开启了?楼市也有春夏秋冬,不可能永远是春天。涨,势如破竹,跌,也会排山倒海。世间万物都有自身运行规律,房地产也不例外,涨得太高了,不跌?可能吗?现在许多地方已允许开发商在备案价的基础上,下国家严控省会城市无序扩张,福州撤县改区的希望或将破灭文城市情报社原创出品,欢迎关注!2022年,国家发改委明确严控省会规模扩张和撤县改区。这意味着,今后省会城市超大城市特大城市无序扩张都会受到严格的限制。作为近年发展最快的省会城市之AI医生秒速读片实时纠正,中山医院医企联合项目入围世界人工智能大会最高奖AI医生实现秒速读片吸气不足非医源性异物曝光不良针对技术员拍摄的X光片,AI实时督查,立即发现问题加以纠正。这是复旦大学附属中山医院携手上海联影联影智能上海联通等企业共同建设的融合伯利在不同国家拥有俱乐部有优势切尔西有很多障碍要打破直播吧9月14日讯在SALT的活动上,切尔西老板伯利表示,他正在和合作伙伴探索多俱乐部模式。伯利说道我想继续扩大足迹,我认为在不同的国家拥有俱乐部是有优势的。谈及图赫尔,伯利说道图左瑾言黄金,白银原油走势分析及策略建议没有必要让所有的人都认同你交易,更不用把所有的交易利润都给别人说个不停,支持爱你的人永远懂你。当你看清一个人而不揭穿,就懂格局的意义,当你厌恶一个人而不翻脸,就懂释然的重要性,活着文明旅游中秋佳节,文明旅游,不负美景!中秋佳节来临面对难得的长假很多人有了出游计划旅游观光能给人带来好心情文明旅游则反映出一个人的文明素质六种不文明行为须警惕1扰乱公共汽车电车火车船舶航空器或者其他公共交通工具秩序。2女王将于19日国葬!而英国王室的危机不过刚刚开始当地时间9月8日,英国女王伊丽莎白二世在苏格兰巴尔莫勒尔城堡去世,享年96岁。现年74岁的王储查尔斯正式继任,成为英国国王查尔斯三世。女王年岁已高,其实这些年来,英国民众对女王去世到张家界禾田居度假酒店寻一份闲静繁华盛世,忙忙碌碌。累了的你,是否想寻找一份闲静一份悠然。张家界禾田居度假酒店是由张家界禾田居投资有限公司,按国家五星级度假酒店标准投资兴建的一家豪华别墅式生态度假酒店。地处风景秀探访神潭大峡谷,亲近大自然,攻略详解相信大多数游客都有一个共性,就是远离都市的喧嚣,寻找有山有水的地方,探索原生态的美,追寻大自然中的参天古树,倾听叮咚作响的泉水,欣赏着飞瀑流泉,闻着沁人心脾的泥土和草香,呼吸着清晰时间反演对称性的实验检验取得进展记者近日从中国科学技术大学获悉,该校卢征天教授团队利用激光冷原子方法对镱171原子(Yb171)的固有电偶极矩进行了首次测量,获得上限结果,并对镱171原子核的席夫极矩设定了上限。
加大力度布局元宇宙全力助推产业经济新动能文申志华元宇宙产业的兴起是算力持续提升高速无线通信网络云计算区块链虚拟引擎VRAR数字孪生等技术创新逐渐聚合的结果,蕴含着巨大的经济价值。当前,我国元宇宙产业正迎来重要发展转型期,诺奖解读量子纠缠与贝尔不等式转载中国科学物理辑中国科学杂志社背景介绍今年,三位物理学家AlainAspect(阿斯佩),JohnF。Clauser(克劳瑟),AntonZeilinger(塞林格)因纠缠光子,西宁对年轻人的吸引力越来越弱,西宁房价四连跌,西宁楼市分析现在西宁房价还是跌个不停,西宁楼市的整体热度还是比较低的。西宁房价从去年下半年开始,就一直处于下跌阶段,哪怕是西宁楼市比较核心的城西板块,房价也顶不住,开始出现下跌了。西宁楼市主要恭喜,格林!火箭全新三巨头出炉,费尔蒂塔对2111巨星没兴趣北京时间12月28日,NBA常规赛已经开启第六十五天左右,其中比克斯塔夫表示,当凯文杜兰特凯里欧文西蒙斯专注于篮球时,布鲁克林篮网很难输球,泰伦卢透露,我们必须给予替补球员赞扬,他ACECOOL粒子重塑小鸟斗士这个巴掌大的按摩仪有点东西购买理由社畜一枚,基本办公室一坐就是一天,这个还没巴掌大的按摩仪也太可爱了吧,不仅小巧,颜值还高,果断种草入手。和大家来分享一下。外观展示首先拿到手,你就会被这款按摩仪的设计吸引,RedmiK50系列进化为K60宇宙,到底提升了多少?RedmiK50系列的表现相当不错,天玑8100三星2K屏5500毫安时大电池,创造了一代相当经典的传奇。RedmiK50在2000元价位几乎满足了大家对价格与配置的所有需求。最新养个中不溜的孩子最幸福太优秀的孩子是给社会培养的为人父母,总是希望孩子能青出于蓝而胜于蓝,往高了说就是功成名就光宗耀祖,往低了说至少丰衣足食一世无忧。为此,他们倾尽所有资源,铺好路,架好桥,搭好梯,要将亲子时刻枕头大战枕头大战辞旧迎新,更迭壹始!2023你好,又是一年元旦,又到了每周的亲自游戏时刻。儿子提议今天玩枕头大战的游戏,我老婆儿子每人一个枕头,可自由随意击打,八十一枕头,九十一枕头,五十爸爸不想带孩子,遛娃时一脚踢在婴儿车上,孩子和车一起摔倒在地没有危险时,爸爸就是最大的危险。爸爸带娃,要求不能太高,只要活着就好。同样是第一次当爸妈,为什么爸爸和妈妈差别如此之大?没有谁生来就会做什么事,只不过用心不用心的区别罢了。如果因为宝妈们要注意了!六种假营养早餐,别再给孩子准备了俗话说,早餐吃好,午餐吃饱,晚餐吃少,早餐作为一天中非常重要的一餐,其作用绝不仅仅是填饱肚子中国学龄儿童膳食指南中建议,早餐,应该提供全天百分之2530的能量,早餐的微量元素是决定家有姐妹是否预示情景喜剧再次崛起12月23日晚,电视剧家有姐妹在东方卫视两集播出。这部情景喜剧是根据东方卫视的综艺节目孵化的。从首播的两集内容来看,孵化的话剧质量远远高于开播!情景喜剧这档综艺节目的内容质量。家有
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网