3

教程:通过 Subspace 和 Infura 实现实时前端数据

 3 years ago
source link: https://learnblockchain.cn/article/1836
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

介绍如何跟踪已部署合约的交易,以及当它们在每个新确认的区块中进行更新时,如何在前端显示和更新这些数据。

在关于前端开发的上一篇文章中,我们最后提供了一个网站。用户可通过 MetaMask 连接该网站,它将显示用户的以太币账户余额。但是,有许多以太坊用例(例如 DeFi)涉及到 ERC20 令牌的发送和接收,其跟踪方式与原生以太币不同。在本指南中,我们将介绍如何跟踪已部署合约的交易,以及当它们在每个新确认的区块中进行更新时,如何在前端显示和更新这些数字。我们以跟踪 Uniswap 上的 Dai<>Eth 交易为例来进行说明。

nqemaqJ.png!mobile

Uniswap

为此,我们将使用来自 Status Embark 团队的一个库,名为 Subspace 。我们首选使用 React Hooks 跟踪实时数据。因此,我们将通过在 这里 找到的 Embark 示例代码,使用以太坊数据流设置前端。总的来说,该前端使用了 Infura、React(含助手库)和 Subspace。

  • 本教程是一个单独的网站,与上一个前端教程相互独立。我们将检查代码的重要部分,而非全部代码,因此建议 复制示例库 ,然后运行根目录(或者使用 yarn)中的 npm install 和 npm start,网站将进入 localhost:3000。从这里可以看到,使用 Hooks 和 useEffect() 添加更多数据跟踪非常轻松。

我们只需要检查 3 个重要文件。首先检查 src/index.js 的短文件,其中的 包装整个 App,从而为每个组件提供对 web3 对象的访问权限,该对象即我们通过 web3 提供商 Infura 与以太坊建立的连接。我们将稍后在 App.js 中设置为使用 Infura 进行 web3 连接。

const rootElement = document.getElementById('root')
ReactDOM.render(
  <SubspaceProvider web3={web3}>
    <App />
  </SubspaceProvider>,
  rootElement
);

在 contracts/exchange_abi.json 中有 Uniswap 的 ABI,它是我们要求 Subspace 跟踪的每个函数的已部署 Uniswap 合约的规范。ABI 在 JSON 中指定,我们将对 web3 的合约对象使用它来在去中心化应用中与 Uniswap 进行交互。每个在以太坊上部署的合约都有 ABI,因此您可以将任何现有合约添加到该前端,知道它的 ABI 和已部署合约的地址就能跟踪它的交易。

{
        "name": "TokenPurchase",
        "inputs": [
            {
                "type": "address",
                "name": "buyer",
                "indexed": true
            },
            {
                "type": "uint256",
                "name": "eth_sold",
                "indexed": true
            },
  ... and a lot more

在 App.js 中,我们首先使用 Infura 连接对 web3 对象进行初始化。如果您没有 API 密钥,可以 注册并免费获取 。然后,通过将 ABI 与该 ABI 的合约地址相组合来创建合约对象。该地址是 Uniswap 将 Dai 保存在流动性池所使用的合约。

  • 请注意,您现在可以返回 index.js,在那里将该相同 Infura URL 添加为 Web3 提供商。
const web3 = new Web3("wss://mainnet.infura.io/ws/v3/806ce35b64344f04a9a7e47379d9ca41");
const dai = new web3.eth.Contract(exchangeABI, '0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667');

在下一部分,我们将设置 Subspace 将会使用的 React 状态变量。Subspace 对象从 useSubspace() 进行创建,并且我们将它传递到我们刚刚创建的 Contract 对象中。然后进行一些定义,以帮助处理来自交易的 wei 值。

function App(props) {

    const subspace = useSubspace();
    const daiContract = subspace.contract(dai);

    const [txnObserver, setObservable] = useState();
    const [last5Observable, setlast5Observable] = useState();
    const [latestBlock, setBlock] = useState();
    const [last5, setLast5] = useState([]);

    //Trade details object for calculating exchange rate
    function TradeDetails(tokensSold, ethBought) {
        this.tokensSold = web3.utils.fromWei(tokensSold);
        this.ethBought = web3.utils.fromWei(ethBought);
        this.exchangeRate = this.tokensSold / this.ethBought;
    }

下面 3 个代码区块是去中心化应用中非常重要的 Hooks,为我们提供我们需要的实时流。我们将对它进行设置,使我们能够查看最新挖出的 50 个区块,并显示在这些区块中发生的最近 5 次 Eth->Dai 交易。随着不断有新的区块挖出和交易发生,这些信息将持续更新。

useEffect(() => {
        web3.eth.getBlockNumber().then((block) => setBlock(block));
        if (typeof(latestBlock) != "number") 
            return;

        const EthPurchased$ = daiContract.events.EthPurchase.track({
            fromBlock: latestBlock - 50
        });
        const last5$ = EthPurchased$.pipe($latest(5));
        setObservable(EthPurchased$);
        setlast5Observable(last5$)
    },[latestBlock])

上面的 useEffect() 会将 Hook 设置为从最新的 50 个以太坊区块获取最近的 5 个 EthPurchase 事件。重要的是,setObservable(EthPurchased$) 是我们跟踪的每个交易事件,我们通过使用管道操作符(从 RxJS 导入)并创建 5 个事件的 Observable 来限制前端仅显示 5 个事件。

接下来,我们还有一个 useEffect() Hook,它订阅符合我们在上面为 EthPurchase 定义的要求的所有交易,并将它们放到 console.log 中。

useEffect(() => {
        if ((txnObserver === undefined) || (typeof latestBlock != "number")) {
            return;
        }
        txnObserver.subscribe((trade) => {
            console.log(trade);
        });
    
        return () => { txnObserver.unsubscribe(); }
    }, [txnObserver, latestBlock]);

从我们在第一个 Hook 中创建的 last5Observable,我们获得了它们的交易详情,如下:

useEffect(() => {
        if (last5Observable === undefined) {
            return;
        }
        last5Observable.subscribe((fiveTrades) => {
            const prices = fiveTrades.map(trade => {
                const txnDetails = new TradeDetails(trade.tokens_sold, trade.eth_bought);
                return {'block': trade.blockNumber, 'rate': txnDetails.exchangeRate}
            });
            setLast5(prices);
        });
    
        return () => { last5Observable.unsubscribe(); }
    }, [last5Observable]);

最后,我们有一些 React UI 代码,然后就能看到前端!这是 gif 图。它刚开始不久,目前有 3 次交易。在开发者控制台中,我们可以看到每个交易的更多交易详情。随着新的交易涌入,较早的交易将被挤出堆栈。

希望这些内容清晰地解释了什么是 Subspace 库。它让去中心化应用前端开发变得非常简单轻松,尤其是使用 Infura 处理 web3 数据非常实用!复制 这里 的样板库并使用 Subspace。如果您对此有任何问题,请在这里与我们讨论。有关更多教程,请访问 我们的社区中的教程部分

在关于前端开发的上一篇文章中,我们最后提供了一个网站。用户可通过 MetaMask 连接该网站,它将显示用户的以太币账户余额。但是,有许多以太坊用例(例如 DeFi)涉及到 ERC20 令牌的发送和接收,其跟踪方式与原生以太币不同。在本指南中,我们将介绍如何跟踪已部署合约的交易,以及当它们在每个新确认的区块中进行更新时,如何在前端显示和更新这些数字。我们以跟踪 Uniswap 上的 Dai<>Eth 交易为例来进行说明。

nqemaqJ.png!mobile

Uniswap

为此,我们将使用来自 Status Embark 团队的一个库,名为 Subspace 。我们首选使用 React Hooks 跟踪实时数据。因此,我们将通过在 这里 找到的 Embark 示例代码,使用以太坊数据流设置前端。总的来说,该前端使用了 Infura、React(含助手库)和 Subspace。

  • 本教程是一个单独的网站,与上一个前端教程相互独立。我们将检查代码的重要部分,而非全部代码,因此建议 复制示例库 ,然后运行根目录(或者使用 yarn)中的 npm install 和 npm start,网站将进入 localhost:3000。从这里可以看到,使用 Hooks 和 useEffect() 添加更多数据跟踪非常轻松。

我们只需要检查 3 个重要文件。首先检查 src/index.js 的短文件,其中的 包装整个 App,从而为每个组件提供对 web3 对象的访问权限,该对象即我们通过 web3 提供商 Infura 与以太坊建立的连接。我们将稍后在 App.js 中设置为使用 Infura 进行 web3 连接。

const rootElement = document.getElementById('root')
ReactDOM.render(
  <SubspaceProvider web3={web3}>
    <App />
  </SubspaceProvider>,
  rootElement
);

在 contracts/exchange_abi.json 中有 Uniswap 的 ABI,它是我们要求 Subspace 跟踪的每个函数的已部署 Uniswap 合约的规范。ABI 在 JSON 中指定,我们将对 web3 的合约对象使用它来在去中心化应用中与 Uniswap 进行交互。每个在以太坊上部署的合约都有 ABI,因此您可以将任何现有合约添加到该前端,知道它的 ABI 和已部署合约的地址就能跟踪它的交易。

{
        "name": "TokenPurchase",
        "inputs": [
            {
                "type": "address",
                "name": "buyer",
                "indexed": true
            },
            {
                "type": "uint256",
                "name": "eth_sold",
                "indexed": true
            },
  ... and a lot more

在 App.js 中,我们首先使用 Infura 连接对 web3 对象进行初始化。如果您没有 API 密钥,可以 注册并免费获取 。然后,通过将 ABI 与该 ABI 的合约地址相组合来创建合约对象。该地址是 Uniswap 将 Dai 保存在流动性池所使用的合约。

  • 请注意,您现在可以返回 index.js,在那里将该相同 Infura URL 添加为 Web3 提供商。
const web3 = new Web3("wss://mainnet.infura.io/ws/v3/806ce35b64344f04a9a7e47379d9ca41");
const dai = new web3.eth.Contract(exchangeABI, '0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667');

在下一部分,我们将设置 Subspace 将会使用的 React 状态变量。Subspace 对象从 useSubspace() 进行创建,并且我们将它传递到我们刚刚创建的 Contract 对象中。然后进行一些定义,以帮助处理来自交易的 wei 值。

function App(props) {

    const subspace = useSubspace();
    const daiContract = subspace.contract(dai);

    const [txnObserver, setObservable] = useState();
    const [last5Observable, setlast5Observable] = useState();
    const [latestBlock, setBlock] = useState();
    const [last5, setLast5] = useState([]);

    //Trade details object for calculating exchange rate
    function TradeDetails(tokensSold, ethBought) {
        this.tokensSold = web3.utils.fromWei(tokensSold);
        this.ethBought = web3.utils.fromWei(ethBought);
        this.exchangeRate = this.tokensSold / this.ethBought;
    }

下面 3 个代码区块是去中心化应用中非常重要的 Hooks,为我们提供我们需要的实时流。我们将对它进行设置,使我们能够查看最新挖出的 50 个区块,并显示在这些区块中发生的最近 5 次 Eth->Dai 交易。随着不断有新的区块挖出和交易发生,这些信息将持续更新。

useEffect(() => {
        web3.eth.getBlockNumber().then((block) => setBlock(block));
        if (typeof(latestBlock) != "number") 
            return;

        const EthPurchased$ = daiContract.events.EthPurchase.track({
            fromBlock: latestBlock - 50
        });
        const last5$ = EthPurchased$.pipe($latest(5));
        setObservable(EthPurchased$);
        setlast5Observable(last5$)
    },[latestBlock])

上面的 useEffect() 会将 Hook 设置为从最新的 50 个以太坊区块获取最近的 5 个 EthPurchase 事件。重要的是,setObservable(EthPurchased$) 是我们跟踪的每个交易事件,我们通过使用管道操作符(从 RxJS 导入)并创建 5 个事件的 Observable 来限制前端仅显示 5 个事件。

接下来,我们还有一个 useEffect() Hook,它订阅符合我们在上面为 EthPurchase 定义的要求的所有交易,并将它们放到 console.log 中。

useEffect(() => {
        if ((txnObserver === undefined) || (typeof latestBlock != "number")) {
            return;
        }
        txnObserver.subscribe((trade) => {
            console.log(trade);
        });

        return () => { txnObserver.unsubscribe(); }
    }, [txnObserver, latestBlock]);

从我们在第一个 Hook 中创建的 last5Observable,我们获得了它们的交易详情,如下:

useEffect(() => {
        if (last5Observable === undefined) {
            return;
        }
        last5Observable.subscribe((fiveTrades) => {
            const prices = fiveTrades.map(trade => {
                const txnDetails = new TradeDetails(trade.tokens_sold, trade.eth_bought);
                return {'block': trade.blockNumber, 'rate': txnDetails.exchangeRate}
            });
            setLast5(prices);
        });

        return () => { last5Observable.unsubscribe(); }
    }, [last5Observable]);

最后,我们有一些 React UI 代码,然后就能看到前端!这是 gif 图。它刚开始不久,目前有 3 次交易。在开发者控制台中,我们可以看到每个交易的更多交易详情。随着新的交易涌入,较早的交易将被挤出堆栈。

希望这些内容清晰地解释了什么是 Subspace 库。它让去中心化应用前端开发变得非常简单轻松,尤其是使用 Infura 处理 web3 数据非常实用!复制 这里 的样板库并使用 Subspace。如果您对此有任何问题,请在这里与我们讨论。有关更多教程,请访问 我们的社区中的教程部分

本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 2分钟前
  • 阅读 ( 4 )
  • 学分 ( 0 )
  • 分类:DApp

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK