本文將詳細介紹Web3DApp開發的架構、技術,以及使用哪些工具,并給出完整示例。我們先介紹Web3用到的技術:區塊鏈,以以太坊為主流,也包括Solana、Aptos等其他非EVM鏈。區塊鏈本身是軟件,需要運行在一系列節點上,這些節點組成P2P網絡或者半中心化網絡。節點不僅負責接收新的輸入并生成新的區塊,還需要存儲區塊鏈運行時產生的所有數據,并負責同步、對外提供查詢等RPC服務。錢包:幫助用戶管理自己在區塊鏈上資產的軟件,加密存儲用戶的私鑰。當用戶需要和區塊鏈交互時,就需要用到私鑰簽名;智能合約:運行在區塊鏈上的一段托管程序,主要用來和外部賬戶交互;UI:這里特指前端頁面,因為直接通過RPC調用合約僅限個別高級用戶,普通用戶仍需要一個前端頁面,并通過JavaScript腳本配合錢包簽名與合約交互。因為區塊鏈上所有數據全透明,要查詢任意區塊的數據,可以通過EtherScan這個網站查。其他公鏈,無論是與Ethereum兼容的BSC、Polygon,還是不兼容的Solana、Aptos等,也提供類似XxxScan這樣的查詢網站。這些Scan能提供基本的讀寫合約的能力,有助于開發階段的測試。區塊鏈本身以及錢包、EtherScan等屬于基礎設施,如何基礎設施不在本文討論范圍之內。本文僅限定如何開發DApp。一個完整的DApp需要開發以下部分:智能合約:將邏輯寫入合約,并部署在鏈上;UI:為用戶提供一個交互式UI,配合錢包完成特定功能。此外,對后端開發有經驗的同學應該知道,通常來說,App數據會存儲在數據庫中,前端與后端交互,離不開后端對數據的查詢和修改。在DApp中,同樣需要一個查詢的“后端”,但這個后端通常不是數據庫。有的同學會認為,既然節點本身提供了查詢鏈上全部數據的PRC接口,那么,前端直接查詢節點是否可行?答案是不行。因為節點提供的數據,是用戶產生的原始日志。舉個例子,假設有個NFT合約,允許用戶創建NFT,那么,一段時間內,節點產生的日志如下:用戶A創建了NFT-1;用戶B創建了NFT-2;用戶B把NFT-2轉移給了用戶X;用戶C創建了NFT-3;...這些未經聚合處理的數據沒法生成一個不斷更新的數據庫表:OwnerNFTID用戶A1用戶X2用戶C3所以,一個DApp除了前端外,還需要一個后端服務,它主要功能是不斷聚合鏈上產生的數據,并根據DApp的業務需求設計表結構以方便查詢。一個直觀的想法是用Java或者Go語言等編寫一個后端服務,再配上一個數據庫,就可以為前端提供RESTAPI來實現查詢。只不過自己維護后端服務比較麻煩,還需要租用云端服務器、數據庫等資源,費時費力。我們推薦另一種后端服務:TheGraph。它本身也可看作是一個基礎設置。TheGraph可以讓我們部署一個Graph查詢服務,如何定義表結構以及如何更新則由我們提供一個預編譯的WASM。整個配置、WASM代碼以及查詢服務都托管在TheGraph中,無需自己搭建服務器,非常方便。因此,一個完整的DApp架構如下:┌───────┐┌───────────│DApp│───────────┐│└───────┘││read/writequery││contractdata│▼▼┌───────┐┌───────┐│Wallet││Graph│└───────┘└───────┘│▲│signindex││broadcastdata││││┌─────────────││┌────┐┌────┐┌────┐││└──┼?│Node││Node│...│Node│───┘└────┘└────┘└────┘││Ethereum─────────────┘我們看看開發各個組件所需的技能樹需求。由于本文僅討論ETH以及ETH兼容鏈的DApp開發,所以,以下技能樹僅適用于ETH系:合約開發:使用Solidity語言;合約部署工具:可以選擇Hardhat、Truffle或Foundry,建議使用Hardhat;數據聚合服務:選擇TheGraph提供的托管服務;數據聚合開發:TheGraph給出的模板代碼是TypeScript,因此這里使用TypeScript;前端頁面:HTML+JavaScript/TypeScript,也可配合任意前端框架如Vue、React等;合約交互框架:雖然理論上使用JSONRPC就可以讀寫合約,但使用Ethers.js可以大大簡化開發;錢包支持:如果僅支持MetaMask,則使用Ethers.js已足夠,如果要支持多種錢包,尤其是需要連接手機錢包,則需要使用Web3Modal。綜上所述,我們可以總結一個基本的Web3全棧開發技術需求:Solidity語言;JavaScript語言;TypeScript語言;HTML/CSS等前端技能。以及用到的服務:將所有源碼托管在GitHub;使用TheGraph提供的HostedService;使用GitHubPage實現靜態頁托管;可選:綁定一個域名。下面我們以一個具體的項目來演示Web3全棧開發的完整流程。該項目允許用戶在Polygon上創建屬于自己的NFT卡片,并可在頁面查看鏈上鑄造的所有NFT卡片:圖片Polygon是兼容以太坊的PoS鏈,特點是Gas便宜,速度快,領測試幣方便。編寫合約創建Web3DApp的第一步是編寫合約。我們使用Hardhat工具,它是Node.js開發的,確保本機安裝了Node.js和NPM,先安裝Solidity編譯器:$npminstall-gsolc$solc--versionsolc,thesoliditycompilercommandlineinterfaceVersion:0.8.17然后創建目錄web3stack并安裝Hardhat:$mkdirweb3stack$cdweb3stack$npminstall--save-devhardhat然后輸入命令npxhardhat開始創建一個新的合約項目:$npxhardhatHardhat提示選擇項目類型:?Whatdoyouwanttodo?…?CreateaJavaScriptprojectCreateaTypeScriptprojectCreateanemptyhardhat.config.jsQuit這里選擇JavaScript項目。后續接著提示項目根目錄、是否添加.gitignore、是否安裝相關依賴等:?Whatdoyouwanttodo?·CreateaJavaScriptproject?Hardhatprojectroot:·/path/to/web3stack?Doyouwanttoadda.gitignore?(Y/n)·y?Doyouwanttoinstallthissampleproject'sdependencieswithnpm(@nomicfoundation/hardhat-toolbox)?(Y/n)·y全部按默認值來。完成后查看package.json應該有兩個dev依賴:{"devDependencies":{"@nomicfoundation/hardhat-toolbox":"^2.0.1","hardhat":"^2.12.7"}}Hardhat默認創建了一個Lock合約,以及相關配置。我們可以自己再寫一個Card合約://SPDX-License-Identifier:GPL-v3pragmasolidity=0.8.17;import"@openzeppelin/contracts/token/ERC721/ERC721.sol";contractCardisERC721{...}直接編譯:$npxhardhatcompileErrorHH411:Thelibrary@openzeppelin/contracts,importedfromcontracts/Card.sol,isnotinstalled.Tryinstallingitusingnpm.編譯提示找不到library報錯,因為我們引用了OpenZeppelin的庫,所以要先用NPM安裝一下:npminstall--save@openzeppelin/contracts這條命令會在package.json中添加一個新的依賴:{..."dependencies":{"@openzeppelin/contracts":"^4.8.1"}}再次編譯:npxhardhatcompile生成的合約存放在artifacts/contracts/Card.sol/Card.json,它包括了ABI接口、字節碼等所有信息。部署合約就是把字節碼部署到鏈上。Hardhat提供了一個示例代碼script/deploy.js用于部署Lock合約,我們可以仿照這個腳本,復制一份script/deploy-card.js來部署Card合約:consthre=require("hardhat");asyncfunctionmain(){//合約工廠:constCard=awaithre.ethers.getContractFactory("Card");//部署:constcard=awaitCard.deploy();awaitcard.deployed();//打印部署的地址:console.log(`Carddeployedto${card.address}`);}main().catch((error)=>{console.error(error);process.exitCode=1;});部署時,直接運行腳本:$npxhardhatrunscripts/deploy-card.js但是,我們并沒有在本地配置任何關于鏈的信息,也沒有配置私鑰等賬戶信息,這個合約是不可能部署到鏈上的,那它部署到哪了?實際上合約默認部署到Hardhat提供的“虛擬JavaScript環境”,它可以在本地用Node執行合約代碼,主要用于測試。要部署到真實的鏈上,我們首先要在hardhat.config.js中加一點關于鏈的配置:module.exports={...//定義所有的鏈:networks:{//定義名為testnet的鏈:testnet:{//配置私鑰:accounts:,//配置為PolygonTestnet節點的PRC:url:"https://matic-mumbai.chainstacklabs.com"}},...}這里為了方便我們把私鑰直接寫進配置里,實際開發可從環境變量讀取。在部署前,確保私鑰對應的地址有一點MATIC測試幣。可以從這里領測試幣。然后用帶--network參數的命令部署:$npxhardhatrunscripts/deploy-card.js--networktestnet如果部署成功,則顯示Card合約被部署的地址:Carddeployedto0x8131aa1B766966f9F8ec3E1132D9d29D92311AB0在PolygonScan上就能查看該合約。順便可以將合約源碼在PolygonScan上驗證,驗證后即可在PolygonScan對合約進行基本的讀寫操作。開發DAppUIDAppUI就是前端頁面,既可以手寫HTML+JavaScript,也可以使用React、Vue等任何前端框架與Webpack等前端工具。為了簡化開發流程,這里我們直接手寫一個index.html頁,讓用戶能在頁面創建一個NFT。頁面引入的第三方庫包括jQuery、BootstrapCSS、Vue,以及用于合約交互的Ethers.js:<scriptsrc="https://cdn.jsdelivr.net/npm/ethers@5.0.32/dist/ethers.umd.min.js"></script>安裝了MetaMask插件后,頁面會獲得一個注入的window.ethereum全局變量,通過此變量與錢包進行交互,例如,連接錢包:awaitwindow.ethereum.request({method:'eth_requestAccounts',});調用合約方法則使用Ethers.js。下面的代碼創建了Card合約并調用mint()方法創建NFT:asyncfunction(){//創建合約:letcontract=newethers.Contract(//合約地址:'0x8131aa1b766966f9f8ec3e1132d9d29d92311ab0',//合約的ABI接口'',//錢包簽名對象:newethers.providers.Web3Provider(window.ethereum,"any").getSigner());//調用mint()方法:lettx=awaitcontract.mint();//等待1個確認:awaittx.wait(1);//TODO:解析tx的日志并拿到TokenID}異步調用mint()方法時,會拉起MetaMask,提示用戶對交易進行簽名。簽名后返回tx對象代表已發送的交易。等待1個確認后,如果要獲取交易信息,則需要解析tx的日志以便拿到TokenID等信息。最后注意到合約的ABI接口包含了合約完整的讀寫方法以及輸入輸出,它是一個JSON對象,這里以字符串形式傳入。Card合約的ABI可以在Card.json中找到并復制出來,不過我們可以使用Hardhat的一個插件直接輸出ABI文件。我們先用NPM安裝插件:$npminstall--save-devhardhat-abi-exporter然后在hardhat.config.js中添加插件配置://用require引入插件:require('hardhat-abi-exporter');...module.exports={...//使用ABIExporter插件:abiExporter:{//輸出到abi目錄:path:"./abi",clear:false,flat:true,pretty:false,//編譯時輸出:runOnCompile:true,}};再運行一次編譯,我們就可在abi目錄下看到若干.json文件。找到Card.json,整理下格式,變成一個字符串粘貼至HTML:...window.NFT_ABI=',"stateMutability":"nonpayable","type":"constructor"}...';...這樣,通過前端頁面,就可以調用合約方法。通過mint()方法寫入后,NFT已經生成,在PolygonScan查找對應的tx可查看詳細信息。通過PolygonScan的ReadContract頁面調用getImage()可獲得NFT圖片信息:圖片把返回的data:image/svg...復制到瀏覽器的地址欄,可查看圖片:圖片也可在OpenSea等第三方NFT市場看到該NFT的圖片。不過我們還有最后一個問題,就是如何在我們自己的頁面上展示用戶創建的NFT。有的同學會想到在頁面調用Card合約的讀方法,依次讀出每個NFT的信息,這種方式會非常慢,因為需要反復多次調用讀方法,且無法實現條件查詢,比如根據地址查詢該地址擁有的NFT,或者創建于一個月內的NFT。因此,我們還需要用到TheGraph提供的數據聚合服務。創建Graph查詢為了創建Graph查詢,我們需要使用TheGraph提供的托管服務。先注冊TheGraph,然后安裝全局命令行工具,只需運行一次:npminstall-g@graphprotocol/graph-cli安裝后可使用命令graph,例如查看版本:$graph--version0.38.0第二步是在TheGraph的HostedService-MyDashboard-AddSubgraph創建一個項目,創建成功后TheGraph顯示狀態為未部署。為了把Subgraph部署上去,我們在本地項目根目錄創建一個subgraph目錄,然后在此目錄下執行命令:$graphinit--producthosted-servicemichaelliao/web3stack注意將登錄名替換為你的GitHub用戶名,將項目名替換為TheGraph上創建的項目名。接下來依次輸入信息:選擇協議的類型:選ethereum;填寫subgraph名稱:用默認的名稱;填寫目錄名:用默認目錄名;選擇鏈:選mumbai;填寫合約地址:填入部署的地址0x8131...1ab0;嘗試自動獲取ABI,一般都能成功;填寫從指定的塊開始:查看合約部署的TX所在塊填入區塊高度;填寫合約名字:與合約代碼保持一致,此處必須為Card;是否索引事件:默認是。接下來會安裝一系列依賴。如果填寫的信息有問題,或者NPM運行出錯,刪掉subgraph目錄再來一遍即可。然后按照提示,先運行graphauth輸入TheGraph給的一個AccessToken,然后進入subgraph/web3stack目錄,運行:npmrundeploy幾秒鐘后,就可以在TheGraph提供的Playground輸入查詢并查看結果:圖片為什么我們可以直接查詢transfers?首先,我們查看schema.graphql,默認有3個Entity,把Entity看作是數據庫表,這3個Entity是TheGraph根據合約定義的Event自動生成的:typeApproval@entity(immutable:true){...}typeApprovalForAll@entity(immutable:true){...}typeTransfer@entity(immutable:true){...}但并不是我們的業務需要的。我們需要的是Card類型,包括owner、image等信息。因此,刪掉自動生成的代碼,換成我們自定義的Card:typeCard@entity(immutable:false){id:String!owner:Bytes!blockNumber:BigInt!blockTimestamp:BigInt!transactionHash:Bytes!image:String!}其中,id是唯一主鍵,這里用NFT的TokenID即可,但類型是String而不是BigInt。接下來,在subgraph.yaml中定義了如何處理事件,需要修改的有兩處,一是entities,刪除原有的3個Entity,換成我們定義的Card:dataSources:-kind:ethereum...mapping:...entities:-Card二是在eventHandlers中刪除我們不關心的Approval和ApprovalForAll事件,僅保留Transfer:dataSources:-kind:ethereum...mapping:...eventHandlers:-event:Transfer(indexedaddress,indexedaddress,indexeduint256)handler:handleTransfer當TheGraph的節點掃描到我們部署的合約產生了Transfer事件后,它將調用handleTransfer處理,這個函數定義在src/card.ts中,自動生成的代碼如下:exportfunctionhandleTransfer(event:TransferEvent):void{letentity=newTransfer(event.transaction.hash.concatI32(event.logIndex.toI32()))entity.from=event.params.fromentity.to=event.params.toentity.tokenId=event.params.tokenIdentity.blockNumber=event.block.numberentity.blockTimestamp=event.block.timestampentity.transactionHash=event.transaction.hashentity.save(。因此,每捕獲到一個Transfer事件,會保存一個Transfer的Entity,這就是我們前面在TheGraph的Playground中能查詢transfers的原因。現在我們不需要Transfer這個Entity,改成Card,先定義Card這個Entity:exportclassCardextendsEntity{...}再修改handleTransfer()的代碼:exportfunctionhandleTransfer(event:TransferEvent):void{lettokenId=event.params.tokenId;letcontract=CardContract.bind(event.address);if(event.params.from.equals(Address.zero())){//如果from=0,表示創建了新的NFT:letnft=newCard(tokenId.toString());nft.owner=event.params.to;nft.image=contract.getImage(tokenId);nft.blockNumber=event.block.number;nft.blockTimestamp=event.block.timestamp;nft.transactionHash=event.transaction.hash;nft.save();}else{//from!=0,表示NFT發生了轉移,需要更新owner和image:letnft=Card.load(tokenId.toString());if(nft===null){log.error('failedloadNFTbytoken:{}',);}else{nft.owner=event.params.to;nft.image=contract.getImage(tokenId);nft.save();}}}再次運行npmrundeploy,我們可以在TheGraph的Playground中查詢到cards:圖片這樣,支持頁面顯示的后端查詢服務就準備就緒。下一步,我們在頁面中添加一點查詢代碼:asyncfunctionquery(){letquery={"query"://輸入為Graph查詢字符串:`{cards(first:20,orderBy:blockTimestamp,orderDirection:desc){idownerimage}}`};//調用jQuery發送POST請求并獲得JSON結果:letopt={type:'POST',dataType:'json',contentType:'application/json',//與Graph服務接口保持一致:url:'https://api.thegraph.com/subgraphs/name/michaelliao/web3stack',data:JSON.stringify(query。;letresult=await$.ajax(opt);letcards=result.data.cards;}拿到查詢結果,我們就能直接在頁面展示:圖片最后一步就是把頁面發布到GitHubPages,然后綁一個域名,就可以讓用戶訪問了:https://web3stack.itranswarp.com至此,一個完整的DApp就開發完畢。FAQQ:可以不用TheGraph,自己寫后端服務嗎?A:可以,很多需求,例如用戶實名認證、發送Email是TheGraph服務無法支持的,必須自己編寫后端服務,配合數據庫實現。Q:可以同時支持多鏈嗎?A:可以,用戶在錢包切換鏈時,DApp可以通過chainChanged事件拿到鏈ID,提前配置好鏈ID與不同鏈的合約地址,就可以正常在不同鏈調用不同合約。Q:可以支持多種錢包嗎?A:可以,需要使用Web3Modal這個庫,能簡化連接多個錢包的代碼。小結從本文給出的完整示例來看,Web3全棧開發,最適合前端開發人員。當年國外有個前端開發叫Hayden,在17年失業了,他決定自學Solidity并花了幾個月的時間為以太坊開發了一個DeFi應用,后來這個應用火爆了,它叫Uniswap。
Arbitrum Nova與Web3數據提供商Covalent集成:金色財經報道,Arbitrum生態鏈Arbitrum Nova宣布與Web3數據提供商Covalent集成以提高開發人員的數據可用性,從而與區塊鏈技術一起構建更好的游戲生態系統。根據官方博客文章稱,本次Arbitrum Nova和Covalent集成將有助于擴展整個 Web3 開發并促進大規模采用,同時專注于提升 Gamefi 生態系統,這將使個人和企業能夠更好地控制他們的數據和資產。(crypto-economy)[2023/3/9 12:52:38]
Web3身份系統Gitcoin Passport推出Scorer API用于防御女巫攻擊:金色財經報道,Web3身份系統Gitcoin Passport宣布已推出Scorer API,開發人員通過該API只需要幾行代碼就可以獲得與Gitcoin Grants等級相同的女巫保護。此外,為了配合Scorer API的發布,官方徹底修改了其開發人員文檔。[2023/2/21 12:19:16]
SBF、a16z合伙人、螞蟻集團CEO等Web3領域人物將出席香港金融科技周并發表演講:10月28日消息,據香港金融科技周官網信息,SBF、a16z合伙人AlexRampell、AnimocaBrands聯創YatSiu、螞蟻集團CEO井賢棟等加密和Web3領域重磅人物將出席香港金融科技周并發表演講。該活動將于10月31日至11月4日舉行。
10月16日,香港財政司司長陳茂波表示,特區政府將在該活動上發布有關虛擬資產在港發展的政策宣言,內容涵蓋愿景和策略、監管制度、對于開放投資者接觸虛擬資產的取態,以及為把握虛擬資產帶來的技術優勢推出先導項目。陳茂波稱,政策宣言將向全球業界展示推動香港發展成國際虛擬資產中心的愿景,以及與全球資產業界一同探索金融創新的承擔和決心。[2022/10/28 11:52:45]
Web3游戲平臺Village Studio完成210萬歐元種子輪融資,Animoca Brands領投:5月30日消息,Web3 游戲平臺 Village Studio 宣布完成 210 萬歐元的種子輪融資,Animoca Brands 領投,Venrex、AngelHub、K3、WinZO 以及包括 Jas Purewal(Facepunch 董事長)和 Phil Mansell(Jagex 首席執行官)在內的一批天使投資人參投。
Village Studio 由游戲行業資深人士 Will Luton、Cyril Barrow 和 Tak Fung 創立,他們希望幫助 Web3 游戲提升互操作性并為玩家和開發者提供價值,并在本輪融資支持下擴大團隊規模、開發游戲平臺。(Pocketgamer)[2022/5/31 3:51:24]
Web3.0平臺Partisia Blockchain宣布推出去中心化社交平臺Instars:2月24日消息,Web3.0平臺Partisia Blockchain和市場研究公司Insights Network合作,宣布推出去中心化、注重隱私的社交媒體平臺Instars。(CoinDesk)[2021/2/24 17:49:33]
全球第三大穩定幣TerraUSD拋售潮已經持續兩周。周三,長期看漲加密貨幣的億萬富翁MikeNovogratz終于打破沉默,稱UST是一個“失敗的偉大想法”,并警告稱加密貨幣面臨的艱難環境將繼續.
1900/1/1 0:00:00加密貨幣市場各個板塊近期開始了持續輪動,今年二季度NFT大火并持續出圈,全球各大知名公司和名人紛紛加入開始競相追逐;Defi登上《財富》時代周刊封面,華爾街機構開始側目.
1900/1/1 0:00:007月5日,一代天后李玟突然離世,年僅44歲。這個消息震驚了全球華人,許多歌迷和明星都紛紛表達了對她的哀悼和敬仰.
1900/1/1 0:00:00撰文:白計劃團隊 區塊鏈是一個多方共同完成總帳本記錄過程的技術,參與的多個計算方將設備連接成網,形成了對外開放的區塊鏈網絡,諸如比特幣、以太坊、波卡等等,各個計算參與方共享資源.
1900/1/1 0:00:00MaskNetwork的原生代幣MASK繼續保持上漲趨勢,近期大幅上漲。在3月18日撰寫本文時,該代幣的易手價格為每份來自代幣追蹤器CoinMarketCap的數據6.19美元.
1900/1/1 0:00:00本文為Billions項目組漲幅榜20200624期。值此端午佳節來領之際,Billions項目組盤點近七日漲幅TOP的幣種,以饗讀者.
1900/1/1 0:00:00