Web3 開發人員通常選擇在前端顯示平台或協議的本機加密貨幣,而不是顯示轉換為法定貨幣。但是,雖然很容易關注本國貨幣,但顯示法定貨幣兌換可能是更好的選擇。加密貨幣的定價假設了解貨幣的當前價值,該價值往往會波動,並且還會為新用戶創造不那麼受歡迎的體驗,其中許多人更願意參考美元或他們的本國貨幣。
幸運的是,在ETH 和USD 等貨幣之間進行轉換很簡單 Chainlink 數據饋送,這意味著開發人員只需幾個簡單的步驟即可為用戶提供更好的體驗。本技術教程分解瞭如何使用ETH / USD Chainlink 價格饋送在前端顯示加密和法定價格。
什麼是Chainlink 數據源?
Chainlink 數據饋送是一組智能合約,可提供對安全可靠的現實世界數據源的訪問。它們由獨立、信譽良好且地理分佈的節點運營商提供支持,這有助於確保返回數據的可靠性。這 以太幣/美元 例如,feed 目前使用31 個獨立的預言機或信息源來確定當前以美元計價的ETH 價格的可信答案。
為什麼我們需要31 個來源來獲取相同的信息?使用多個源來聚合經過驗證的響應意味著不會出現單點故障並防止數據篡改。
關於提供者的說明
與智能合約交互時,需要有一個Web3 連接的提供者。通常,這將通過用戶的錢包連接獲得。如果這不可用,或者您不需要連接用戶的錢包,您可以通過以下方式完成相同的功能
const provider = new ethers.providers.JsonRpcProvider('RPC_URL_HERE');
RPC_URL_HERE
可以從節點提供商處獲得,例如 煉金術, 英富拉, 莫拉利斯, 或者 快速節點. 提供商是我們通往區塊鏈的“門戶”。
本教程的另一個要求是以太坊JavaScript 庫。在這個例子中,我使用 醚類. 您需要安裝它才能使示例正常工作。
npm install --save ethers
使用JavaScript 部署ETH / USD 轉換
現在,您需要在前端顯示ETH / USD 價格饋送的代碼。
如果您想跟隨,此示例的代碼可以在 示例回購. 按照README.md 中的說明在本地運行此示例。這個例子使用 苗條,但相同的概念應該適用於任何前端JavaScript 框架,例如React 或Vue。您還可以在SmartContract 中使用其他幾個入門工具包 GitHub 倉庫.
此代碼可以通過import 語句在前端使用
import { getETHPrice } from '../utils/getETHPrice';
然後,將結果存儲為ETH 的USD 價值
value = await getETHPrice();
假設使用此值從ETH 變為USD ethAmount
是要轉換的ETH 數量。
usdValue = Number(ethAmount * value).toFixed(2);
這是完整的文件:
~/utils/getEthPrice.js import { ethers } from 'ethers'; export async function getETHPrice() { const provider = new ethers.providers.JsonRpcProvider('RPC_URL_HERE'); // This constant describes the ABI interface of the contract, which will provide the price of ETH // It looks like a lot, and it is, but this information is generated when we compile the contract // We need to let ethers know how to interact with this contract. const aggregatorV3InterfaceABI = [ { inputs: [], name: 'decimals', outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], stateMutability: 'view', type: 'function' }, { inputs: [], name: 'description', outputs: [{ internalType: 'string', name: '', type: 'string' }], stateMutability: 'view', type: 'function' }, { inputs: [{ internalType: 'uint80', name: '_roundId', type: 'uint80' }], name: 'getRoundData', outputs: [ { internalType: 'uint80', name: 'roundId', type: 'uint80' }, { internalType: 'int256', name: 'answer', type: 'int256' }, { internalType: 'uint256', name: 'startedAt', type: 'uint256' }, { internalType: 'uint256', name: 'updatedAt', type: 'uint256' }, { internalType: 'uint80', name: 'answeredInRound', type: 'uint80' } ], stateMutability: 'view', type: 'function' }, { inputs: [], name: 'latestRoundData', outputs: [ { internalType: 'uint80', name: 'roundId', type: 'uint80' }, { internalType: 'int256', name: 'answer', type: 'int256' }, { internalType: 'uint256', name: 'startedAt', type: 'uint256' }, { internalType: 'uint256', name: 'updatedAt', type: 'uint256' }, { internalType: 'uint80', name: 'answeredInRound', type: 'uint80' } ], stateMutability: 'view', type: 'function' }, { inputs: [], name: 'version', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' } ]; // The address of the contract which will provide the price of ETH const addr = '0x8A753747A1Fa494EC906cE90E9f37563A8AF630e'; // We create an instance of the contract which we can interact with const priceFeed = new ethers.Contract(addr, aggregatorV3InterfaceABI, provider); // We get the data from the last round of the contract let roundData = await priceFeed.latestRoundData(); // Determine how many decimals the price feed has (10**decimals) let decimals = await priceFeed.decimals(); // We convert the price to a number and return it return Number((roundData.answer.toString() / Math.pow(10, decimals)).toFixed(2)); }
這 aggregatorV3InterfaceABI
或者ABI 構成了我們需要的大部分代碼。這是我們將與之交互的合約的數據結構,我們需要讓 醚類 知道關於。通常,您可以將這些存儲在前端項目中的單獨JSON 文件中。在這種情況下,它包含在util 文件中以將所有內容放在一起。
// The address of the contract which will provide the price of ETH const addr = '0x8A753747A1Fa494EC906cE90E9f37563A8AF630e';
該合約地址將根據網絡或價格對而變化; 你可以使用其中任何一個 數據饋送合同地址.
// We get the data from the last round of the contract let roundData = await priceFeed.latestRoundData(); // Determine how many decimals the price feed has (10**decimals) let decimals = await priceFeed.decimals(); // We convert the price to a number and return it return Number((roundData.answer.toString() / Math.pow(10, decimals)).toFixed(2));
與合同的交互很簡單。我們得到 latestRoundData
,它返回:
roundId
: 回合ID。answer
: 價格。startedAt
:回合開始時的時間戳。updatedAt
:更新回合的時間戳。answeredInRound
:計算答案的回合的回合ID。我們感興趣answer
. 這將是帶有一個小警告的ETH 價格。我們需要知道響應中包含的小數位數。那是哪裡
進來。它返回要包含的小數位數。decimals
我們使用 answer
和 decimal
返回一個ETH 的值:
return Number((roundData.answer.toString() / Math.pow(10, decimals)).toFixed(2));
使用價值
一旦我們有了一個ETH 的價值,我們就可以用它輕鬆地將ETH 轉換為美元。在以下示例中, rawETH
是從合約餘額返回的字符串。
<!-- Display the raw ETH --> {Number(rawETH).toFixed(8)} ETH <!-- Display the ETH converted to USD --> $ {(Number(rawETH) * value).toFixed(2)} USD
Chainlink 數據饋送 為使用安全方法將我們的價值從ETH 轉換為美元提供可靠的解決方案。
使用Solidity
到目前為止,在前端應用程序中創建實用函數似乎很簡單。但是,如果我們可以消除前端開發人員擔心定價的需要並為他們處理呢?
通過對您的合同進行一些更改,您可以向最終用戶提供當前價格數據——他們需要擔心的只是連接到您的合同。這簡化了所需的前端工作。讓我們看一個示例合同。
pragma solidity ^0.8.0; // Import the chainlink Aggregator Interface import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; // Create the contract contract YourAwesomeContract { // Declare the priceFeed as an Aggregator Interface AggregatorV3Interface internal priceFeed; constructor() { /** Define the priceFeed * Network: Rinkeby * Aggregator: ETH/USD * Address: 0x8A753747A1Fa494EC906cE90E9f37563A8AF630e */ priceFeed = AggregatorV3Interface( 0x8A753747A1Fa494EC906cE90E9f37563A8AF630e ); } // OTHER CONTRACT LOGIC HERE /** * Returns the latest price and # of decimals to use */ function getLatestPrice() public view returns (int256, uint8) { // Unused returned values are left out, hence lots of ","s (, int256 price, , , ) = priceFeed.latestRoundData(); uint8 decimals = priceFeed.decimals(); return (price, decimals); } }
首先,我們導入我們在上面的前端版本中使用的相同聚合器接口。
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
然後我們需要讓聚合器知道我們感興趣的價格饋送合約的地址。
priceFeed = AggregatorV3Interface( 0x8A753747A1Fa494EC906cE90E9f37563A8AF630e );
在我們的 getLatestPrice()
函數,我們稱 priceFeed.latestRoundData()
. priceFeed
引用的是我們在 getETHPrice
上面的實用程序。它返回:
roundId
: 回合ID。answer
: 價格。startedAt
:回合開始時的時間戳。updatedAt
:更新回合的時間戳。answeredInRound
:計算答案的回合的回合ID。
這裡的代碼可能看起來有點奇怪。我們感興趣的唯一值是 answer
. 因此,我們不會將其他值分配給變量。將它們關閉可防止存儲未使用的數據。
(, int256 price, , , ) = priceFeed.latestRoundData();
前端的變化
現在該值已包含在您的智能合約中,我們只需要在前端從合約中訪問該值即可。
async function getETHPrice() { let [ethPrice, decimals] = await yourAwesomeContract.getLatestPrice(); ethPrice = Number(ethPrice / Math.pow(10, decimals)).toFixed(2); return ethPrice; }
這將為我們合約的消費者創建一個更簡單的界面,因為他們不需要了解預言機或導入單獨的ABI。
概括
在本技術教程中,我們展示了將Chainlink 數據饋送集成到您的dApp 中是多麼容易,使用戶能夠輕鬆參考美元/ ETH 價格轉換。有大量適用於加密貨幣和法定貨幣的Chainlink 價格饋送,為開發人員提供了使用他們的選擇來調整這些步驟的機會。
通過訪問了解有關Chainlink 的更多信息 鏈環 或閱讀文檔 docs.chain.link. 要討論集成,請聯繫專家。