本文將詳細介紹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。
企業級區塊鏈平臺SettleMint推出AI助手,以輔助Web3開發人員編寫智能合約:金色財經報道,企業級區塊鏈平臺SettleMint最近在其平臺上推出AI助手,以幫助Web3開發人員編寫智能合約。SettleMint聯合創始人兼首席技術官Roderik van der Veer表示,SettleMint創造人工智能助手并不是為了取代人類,人工智能可以幫助起草智能合約,但其真正的價值在于解釋每一行代碼的作用。SettleMint主要在OpenAI的GPT-4上對人工智能助手進行培訓,并向其提供有關區塊鏈開發的最新信息。[2023/8/3 16:16:10]
朱嘉明:Web 3.0將創造全新的娛樂產業新生態:金色財經報道,7月29日由漢威信恒、新火科技與D11 Labs聯合主辦的“ChinaJoy Web3 2023”大會在上海順利召開。著名經濟學家、橫琴數鏈數字金融研究院學術與技術委員會主席朱嘉明教授遠程進行了視頻致辭,朱教授認為大數據、AIGC、虛擬現實技術,包括元宇宙、Web3都將為娛樂產業、娛樂產業群提供重要的技術基礎和技術支持,其中因為Web 3.0、AI的支持而形成的價值互聯網和智能互聯網,將創造全新的娛樂產業的新生態。[2023/7/29 16:05:59]
Web3 App開發平臺Sort宣布完成350萬美元種子輪融資:5月22日消息,Web3 App 開發平臺 Sort 宣布完成 350 萬美元種子輪融資,Lemniscap 和 The General Partnership 共同領投。Sort 允許開發人員將智能合約整合到應用程序中,本輪資金將用于擴大 Sort 團隊,推進平臺的產品套件。[2023/5/23 15:19:41]
Chainge Finance推出Chainge WEB 提升跨鏈聚合去中心化交易體驗:據官方消息,Chainge Finance宣布其Chainge WEB APP正式上線,該平臺為用戶提供最具流動性的跨鏈聚合去中心化交易場所,支持多條鏈的數字資產跨鏈互換。用戶可以通過Chainge WEB APP輕松進行跨鏈互換和套利,享受跨鏈流動性聚合帶來的最佳交易價格。此次上線有助于加強區塊鏈生態系統的互操作性,提升用戶交易體驗。作為區塊鏈行業的領先者之一,Chainge Finance將繼續推動區塊鏈技術的創新和發展,為用戶創造更多價值。[2023/4/11 13:56:09]
迪士尼CEO:過去一年一直在探索如何利用Web3技術:9月14日消息,在迪士尼兩年一度的 D23 Expo 大會上,該公司首席執行官鮑勃·查佩克稱迪士尼正在繼續探索和制定虛擬世界計劃,而且在過去一年時間里一直在悄悄探索如何利用 Web3 技術。鮑勃·查佩克表示,迪士尼希望使用來自物理世界和數字世界的數據來推動其元宇宙戰略,來自主題公園訪問數據和消費者流媒體習慣數據將使迪士尼元宇宙戰略中最關注的兩大領域。(nftevening)[2022/9/14 13:30:06]
盡管代幣的交易量在周末猛增,但Jasmy代幣價格回落。該代幣在周末躍升至0.0058美元的高位,然后跌至目前的0.0055美元。它已從今年3月的最低水平躍升了約30%.
1900/1/1 0:00:00GCV是廣大先鋒用智慧和信念打造起來的一致共識,是PiNetwork發展的重要支撐,其意義和價值深入人心,大勢所趨,一切阻擋GCV共識發展的行徑都不會得逞.
1900/1/1 0:00:00作者丨萊道君 來源丨萊道區塊鏈 2019年注定是不平凡的一年,區塊鏈世界終將由跨鏈技術將割裂的網絡連成一個整體,從而達到區塊鏈界的價值互聯.
1900/1/1 0:00:00雖然去中心化金融(DeFi)可能會帶來無窮無盡的機會,但一些問題可能會阻止它實現與當前中心化經濟體系競爭的目標,這就是WrappedBitcoin的用武之地.
1900/1/1 0:00:00moonriver想表達的意思很簡單:生活回歸本真,不要追求不切實際的東西。這首歌中文名非常唯美,叫作《月亮河》,是好萊塢經典硬盤BRETI中的插曲,該歌曲還獲得了第三十四屆奧斯卡最佳電影歌曲獎.
1900/1/1 0:00:00在比特幣系統上其實并不存在“賬戶”,而只有“地址”。只要你愿意,你就可以在比特幣區塊鏈上開設無限多個錢包地址,你擁有的比特幣數量是你所有的錢包地址中比特幣的總和.
1900/1/1 0:00:00