當您開始您的Web3 之旅時,您將採取的第一步將是安裝加密錢包。錢包是必不可少的軟件,使您能夠存儲加密貨幣並與之交互。在本技術教程中,我們將探索不同類型的加密錢包並學習如何構建我們自己的。
管理資金存在風險,本文的目的只是解釋加密錢包軟件背後的技術概念。強烈建議您使用已建立的錢包和開源且經過審計的代碼庫,例如MetaMask、Ledger 或Argent。
入門
出於本演示的目的,我們將創建一個簡單的Node.js 應用程序並使用 以太坊密碼學 和 ethers.js 圖書館。首先創建一個名為的新空文件夾 my-crypto-wallet
並導航到它。然後創建一個新項目並通過鍵入以下內容安裝必要的依賴項:
yard init -y yarn add ethereum-cryptography ethers
要繼續,請查看位於 Chainlink 智能合約示例存儲庫 在下面 My Crypto Wallet
文件夾。
git clone https://github.com/smartcontractkit/smart-contract-examples.git cd smart-contract-examples/my-crypto-wallet
都是密碼學
區塊鏈正在解決信任問題。使用加密貨幣,您一個人可以控制您的資金,而不是銀行或其他第三方。加密錢包只是一種管理資金的工具,您可以輕鬆地從一種錢包服務切換到另一種。由於密碼學,這一切都是可能的:我們不需要信任任何人,我們可以輕鬆地通過密碼驗證真相並保護我們自己的資金。
出於本演示的目的,我們將重點關注以太坊虛擬機(EVM) 帳戶,因為熟悉EVM 的開發人員數量很多。帳戶只是私鑰和公鑰的加密對。例如,假設您的帳戶是您的信用卡。公鑰將是您的信用卡號,而私鑰將是您的PIN。您可以輕鬆地與任何人共享您的公鑰,但私鑰必須只對您自己保密。如果您的私鑰被洩露,您將面臨永久失去所有資金的風險。和任何借記卡一樣,只要您的賬戶上有資金,您就可以花錢。
生成新錢包的第一步是寫下“種子短語”或助記詞。這會生成帳戶的其餘部分(私鑰/公鑰對),並且是恢復加密錢包的唯一方法。如果您刪除了移動錢包或丟失了手機,您的硬件錢包壞了,或者您使用了網絡瀏覽器擴展錢包並且您的計算機死了,您的助記詞將允許您在手機、瀏覽器或硬件設備上設置新錢包並重新獲得對您的加密貨幣的完全訪問權限。
在您的項目中創建一個新的JavaScript 文件並將其命名 01_newAccount.js
. 讓我們創建一個函數來生成助記符。比特幣改進提案39,或簡稱BIP-39,是生成助記詞或助記詞的規範。它以一個稱為熵的隨機數開始,它需要是32 位(強度% 32 == 0)的倍數,長度在128 位和256 位之間。一個128 位長的熵將產生一個由12 個字組成的助記符,而一個256 位長的熵將產生一個由24 個字組成的助記符。熵越大,生成的助記詞越多,錢包的安全性就越高。
const { generateMnemonic, mnemonicToEntropy } = require("ethereum-cryptography/bip39"); const { wordlist } = require("ethereum-cryptography/bip39/wordlists/english"); function _generateMnemonic() { const strength = 256; // 256 bits, 24 words; default is 128 bits, 12 words const mnemonic = generateMnemonic(wordlist, strength); const entropy = mnemonicToEntropy(mnemonic, wordlist); return { mnemonic, entropy }; }
如果您擁有一個帳戶的私鑰,您可以將其移動到另一個錢包應用程序並從那裡使用它,而您可以使用助記詞來恢復所有錢包的帳戶,只需從助記詞中一一生成即可。
BIP-32 是用於創建分層確定性(HD) 錢包的規範,其中單個密鑰可用於生成整個密鑰對樹。這個單一的密鑰作為樹的根,它總是由完全相同的單詞組合生成,也稱為助記詞或種子短語。根密鑰實際上為帳戶生成了所有其他私鑰,並且它們都可以通過這個單一的根密鑰來恢復。由於人類更容易記住一組12 或24 個單詞而不是複雜的隨機數和字符流,我們傾向於說助記詞可以恢復錢包,而實際上它用於生成根密鑰,然後可以導出私鑰樹。
const { HDKey } = require("ethereum-cryptography/hdkey"); function _getHdRootKey(_mnemonic) { return HDKey.fromMasterSeed(_mnemonic); }
帳戶的私鑰是256 位長的0 和1 流。如果您擲硬幣256 次並為正面/反面寫1/0,那麼您很可能會生成一個目前沒有其他人使用的私鑰。但是,當您可以使用助記詞創建錢包帳戶時,不建議生成隨機私鑰。
function _generatePrivateKey(_hdRootKey, _accountIndex) { return _hdRootKey.deriveChild(_accountIndex).privateKey; }
以太坊和比特幣使用secp256k1 橢圓曲線進行密碼計算。每個帳戶的公鑰都是使用橢圓曲線數字簽名算法或簡稱ECDSA 從對應的私鑰派生而來的。通過將ECDSA 應用於私鑰,我們得到一個64 字節的整數,它是兩個32 字節的整數,分別表示secp256k1 橢圓曲線上一個點的X 和Y,連接在一起。該算法背後的數學允許軟件輕鬆計算給定私鑰的公鑰,而反向過程是不可能的。無法在secp256k1 橢圓曲線上使用ECDSA 計算給定公鑰的私鑰。
const { getPublicKey } = require("ethereum-cryptography/secp256k1"); function _getPublicKey(_privateKey) { return getPublicKey(_privateKey); }
一旦我們有了公鑰,我們就可以計算出賬戶地址。以太坊在所有網絡中使用相同的地址,包括匯總、測試網絡和主網。用戶指定他們想要在錢包軟件中使用的網絡。
要根據公鑰計算地址,我們需要將Keccak-256 散列算法應用於公鑰並取最後(最不重要的)20 個字節的結果。
const { keccak256 } = require("ethereum-cryptography/keccak"); function _getEthAddress(_publicKey) { return keccak256(_publicKey).slice(-20); }
要生成一個新的錢包助記詞和第一個賬戶,我們需要調用所有之前定義的函數。
const { bytesToHex } = require("ethereum-cryptography/utils"); async function main() { const { mnemonic, entropy } = _generateMnemonic(); console.log(`WARNING! Never disclose your Seed Phrase:n ${mnemonic}`); const hdRootKey = _getHdRootKey(entropy); const accountOneIndex = 0; const accountOnePrivateKey = _generatePrivateKey(hdRootKey, accountOneIndex); const accountOnePublicKey = _getPublicKey(accountOnePrivateKey); const accountOneAddress = _getEthAddress(accountOnePublicKey); console.log(`Account One Wallet Address: 0x${bytesToHex(accountOneAddress)}`); } main() .then(() => process.exit(0)) .catch((error) => { console.error(error); process.exit(1); });
要運行此程序,請在終端中輸入以下命令:
node 01_newAccount.js
前面的程序創建了一個新錢包。如果你想用你的助記符恢復它,創建新文件,命名它 02_restoreWallet.js
,並粘貼以下代碼:
const { mnemonicToEntropy } = require("ethereum-cryptography/bip39"); const { wordlist } = require("ethereum-cryptography/bip39/wordlists/english"); const { HDKey } = require("ethereum-cryptography/hdkey"); const { getPublicKey } = require("ethereum-cryptography/secp256k1"); const { keccak256 } = require("ethereum-cryptography/keccak"); const { bytesToHex } = require("ethereum-cryptography/utils"); async function main(_mnemonic) { const entropy = mnemonicToEntropy(_mnemonic, wordlist); const hdRootKey = HDKey.fromMasterSeed(entropy); const privateKey = hdRootKey.deriveChild(0).privateKey; const publicKey = getPublicKey(privateKey); const address = keccak256(publicKey).slice(-20); console.log(`Account One Wallet Address: 0x${bytesToHex(address)}`); } main(process.argv[2]) .then(() => process.exit(0)) .catch((error) => { console.error(error); process.exit(1); });
要運行它,請鍵入 node 02_restoreWallet.js
和你的助記詞。
node 02_restoreWallet.js "here is where you should put your twelve-word mnemonic"
冷熱錢包的區別
當您想要發送您的一些數字資產(硬幣、代幣、NFT 等)時,您可以使用ECDSA 和您的私鑰對數據進行數字簽名,並在將其發送給接收方之前對其進行加密。接收方可以使用您的公鑰驗證簽名。
MetaMask 和Coinbase Wallet 等熱錢包或軟件錢包通常將帳戶私鑰存儲在其服務器和瀏覽器的本地存儲中。 Ledger 或Trezor 等冷錢包或硬件錢包是保存您的私鑰並使其離線的物理設備。要簽署交易,您必須連接您的硬件錢包,將其上線,然後點擊它進行確認。完成交易後,您將斷開錢包連接,您的密鑰將重新離線。重要的一點是,熱錢包或冷錢包都不會真正存儲你的資產。他們持有你的私鑰。您的資產始終在區塊鏈上。
出於本演示的目的,我們會將密鑰存儲在您機器上的文件系統中。將此功能添加到您的 01_newAccount.js
和 02_restoreWallet.js
文件:
const { writeFileSync } = require("fs"); function _store(_privateKey, _publicKey, _address) { const accountOne = { privateKey: _privateKey, publicKey: _publicKey, address: _address, }; const accountOneData = JSON.stringify(accountOne); writeFileSync("account 2.json", accountOneData); }
進行交易
最後,讓我們創建發送原生代幣的功能。為此,我們首先需要從文件系統中讀取我們帳戶的私鑰。然後我們需要創建一個ethers.js 錢包對象來傳遞私鑰和提供者作為參數。我們將網絡硬編碼為Goerli 測試網,但您顯然可以擴展該網絡並通過傳遞本地區塊鏈客戶端實例或節點即服務提供商(如Infura 或Alchemy)的URL 來創建您的提供商對象。接下來,我們需要傳遞接收者的地址和一個gETH 數量進行發送。最後,我們將創建一個交易對象並將其廣播到網絡。
創建一個名為的新文件 03_send.js
並粘貼以下代碼。
const { getDefaultProvider, Wallet, utils } = require("ethers"); const { readFileSync } = require("fs"); async function main(_receiverAddress, _ethAmount) { const network = "goerli"; const provider = getDefaultProvider(network); const accountRawData = readFileSync("account 1.json", "utf8"); const accountData = JSON.parse(accountRawData); const privateKey = Object.values(accountData.privateKey); const signer = new Wallet(privateKey, provider); const transaction = await signer.sendTransaction({ to: _receiverAddress, value: utils.parseEther(_ethAmount), }); console.log(transaction); } main(process.argv[2], process.argv[3]) .then(() => process.exit(0)) .catch((error) => { console.error(error); process.exit(1); });
要運行它,請鍵入:
node 03_send.js “receiverAddress” “amount”
概括
您的錢包可讓您讀取餘額、發送交易並連接到去中心化應用程序。許多錢包還允許您從一個應用程序管理多個帳戶。那是因為錢包沒有保管你的資金,你有。它們只是管理真正屬於您的東西的工具。
在本文中,您學習瞭如何使用Node.js 開發基本的加密錢包, 以太坊密碼學, 和 ethers.js. 儘管這是一個有趣的工程教程,但強烈建議您使用已經過測試和驗證的錢包解決方案,而不是從頭開始創建自己的解決方案。
要了解更多信息,請前往 Chainlink 智能合約示例存儲庫 並開始試驗這個和其他示例項目。
通過訪問了解有關Chainlink 的更多信息 鏈環 或閱讀文檔 docs.chain.link. 要討論集成,請聯繫專家。
帖子 如何構建加密錢包 首先出現在 Chainlink 博客.