Blockchain 如何订阅“日志事件”并在ThunderCore上获取通知?

Blockchain 如何订阅“日志事件”并在ThunderCore上获取通知?,blockchain,smartcontracts,web3js,thundercore,Blockchain,Smartcontracts,Web3js,Thundercore,当我想订阅log事件并在ThunderCore上获得通知时,我遇到了一些问题 据我所知,似乎我应该使用websocket和。有什么例子吗 或者,还有其他解决方案可以实现我的目标吗?通过以下方式获取ThunderCore上新合同事件的通知: 使用到RPC节点的Websocket连接,例如 在日志事件上调用eth\u subscribeRPC方法 自足的例子 SimpleRecord.sol pragma solidity ^0.4.25; contract SimpleRecord {

当我想订阅
log
事件并在ThunderCore上获得通知时,我遇到了一些问题

据我所知,似乎我应该使用websocket和。有什么例子吗


或者,还有其他解决方案可以实现我的目标吗?

通过以下方式获取ThunderCore上新合同事件的通知:

  • 使用到RPC节点的Websocket连接,例如
  • 日志
    事件上调用
    eth\u subscribe
    RPC方法
  • 自足的例子
    SimpleRecord.sol

    pragma solidity ^0.4.25;
    
    contract SimpleRecord {
        event Record(
            address indexed _from,
            uint _value
        );
    
        function write() payable public {
            emit Record(msg.sender, msg.value);
        }
    }
    
    要生成
    Record
    事件,请运行
    simple Record write
    查看运行的通知
    simple Record log subscribe

    
    const process = require('process')
    const path = require('path')
    const fs = require('fs')
    const Web3 = require('web3')
    const Accounts = require('web3-eth-accounts')
    const util = require('util')
    
    // truffle migrate --reset --network thunder-mainnet
    const thunderWsUrl = 'wss://mainnet-ws.thundercore.com'
    // truffle migrate --reset --network thunder-testnet
    //const thunderWsUrl = 'wss://testnet-ws.thundercore.com'
    
    const programName = () => {
        return path.basename(process.argv[1])
    }
    
    const web3Url = () => {
        let u = process.env['WEB3_PROVIDER_URI']
        if (u === undefined) {
            u = thunderWsUrl
        }
        return u
    }
    
    const signTx = async (fromAccount, tx) => {
        const signedTx = await fromAccount.signTransaction(tx)
        return signedTx.rawTransaction // hex string
    }
    
    const setup = async () => {
        const privateKeys = fs.readFileSync(path.join(__dirname, '..', '.private-keys'), {encoding: 'ascii'}).split('\n').filter(x => x.length > 0)
        const accounts = new Accounts()
        const account = accounts.privateKeyToAccount('0x' + privateKeys[0])
        const jsonBuf = fs.readFileSync(path.join(__dirname, '..', 'build', 'contracts', 'SimpleRecord.json'))
        const contractData = JSON.parse(jsonBuf)
        const contractAbi = contractData['abi']
        const web3ProviderUrl = web3Url()
        const web3 = new Web3(web3ProviderUrl)
        const networkId = await web3.eth.net.getId()
    
        let deployedNetwork, contractAddress
        try {
            deployedNetwork = contractData['networks'][networkId]
            contractAddress = deployedNetwork['address']
        } catch (err) {
            msg = `error getting deployedNetwork: ${err}`
            throw new Error(msg)
        }
        const contract = new web3.eth.Contract(contractAbi, contractAddress)
        return [ web3ProviderUrl, web3, networkId, contractAddress, contract, account ]
    }
    
    const prettyPrint = (o) => {
       return util.inspect(o, {showHidden: false, depth: null, colors: true})
    }
    
    const recordWrite = async () => {
        const [web3ProviderUrl, web3, chainId, contractAddress, contract, fromAccount] = await setup()
        console.log('web3ProviderUrl:', web3ProviderUrl)
        const txnData = contract.methods.write().encodeABI()
        console.log('account.address:', fromAccount.address)
        const promiseResults = await Promise.all([
            web3.eth.getTransactionCount(fromAccount.address),
            web3.eth.getGasPrice(),
        ])
        const nonce = promiseResults[0]
        const gasPrice = promiseResults[1]
        const tx = {
            'gasLimit': 0,
            'chainId': chainId,
            'gasPrice': gasPrice,
            'nonce': Web3.utils.toHex(nonce),
            'from': fromAccount.address,
            'to': contractAddress,
            'value': 0xbeef,
            'data': txnData,
        }
        const gasMultiple = 2.0
        tx.gasLimit = (await web3.eth.estimateGas(tx)) * gasMultiple
        console.log('tx:', prettyPrint(tx))
        const rawTxStr = await signTx(fromAccount, tx)
        const r = await web3.eth.sendSignedTransaction(rawTxStr)
        console.log('sendTransaction: receipt:', prettyPrint(r))
        return 0
    }
    
    const logSubscribe = () => {
        return new Promise((resolve, reject) => {
            setup().then(([web3ProviderUrl, web3, chainId, contractAddress, contract, account]) => {
                let eventCount = 0
                console.log('web3ProviderUrl:', web3ProviderUrl)
                console.log('contractAddress:', contractAddress)
                console.log('contract.options.jsonInterface:', prettyPrint(contract.options.jsonInterface))
                const eventAbis = contract.options.jsonInterface.filter((abiObj) => abiObj.type === 'event')
                web3.eth.subscribe('logs', { address: contractAddress }, (err, log) => {
                    console.log('eth.subscribe("logs") callback')
                    if (err) {
                        console.log('logs callback, err:', err)
                        reject(err)
                        return
                    }
                    eventCount++
                    console.log(`log[${eventCount}]:`, log)
                    const eventSig = log.topics[0]
                    for (let abi of eventAbis) {
                        if (eventSig === abi.signature) {
                            const decoded = web3.eth.abi.decodeLog(abi.inputs, log.data, log.topics.slice(1))
                            console.log('Decoded Event:', prettyPrint(abi), '\n', prettyPrint(decoded))
                            resolve(0)
                            return
                        }
                    }
                })
            })
        })
    }
    
    (async () => {
        if (programName().endsWith('-write')) {
            process.exit(await recordWrite())
        } else if (programName().endsWith('-log-subscribe')) {
            process.exit(await logSubscribe())
        } else {
            console.error(`unsupported program name: "${programName()}"`)
            process.exit(2)
        }
    })()
    

    查看
    现场支持
    repo的
    订阅日志
    分支中的完整项目。

    listen\u thundercore\u mainnet.js

    /**
    *连接到Thundercore mainnet并收听特定智能合约地址的提示。
    */
    const Web3=require('Web3');
    var提供者wss://mainnet-ws.thundercore.com';
    var web3=新的web3(提供者);
    let listence=()=>{
    //创建与Thundercore mainet的连接。
    常量smartContractAddress='0xB7D82E5B73E01BB4C1C1CCFB1448F1215BF165929A2'
    var subscription=web3.eth.subscripte('日志'{
    地址:smartContractAddress,
    },(错误、结果)=>{
    如果(错误){
    console.log(错误)
    console.log('重新连接到Thundercore mainnet')
    设置超时(()=>{
    //如果连接断开,则需要重新实例化web3。
    web3=新的web3(提供商);
    _听
    }, 5000);
    }
    })
    .on('connected',(subscriptionId)=>{
    console.log('已连接')
    })
    .on('数据',(日志)=>{
    console.log(log);
    })
    .on(“已更改”,(日志)=>{
    console.log('changed')
    })
    退订
    }
    const\u listen=async()=>{
    让tips=listence();
    console.log('连接到Thundercore mainnet')
    //web3订阅在60秒时超时。在50秒时关闭并重新打开。
    设置间隔(()=>{
    提示:取消订阅((错误,成功)=>{
    如果(错误){
    console.log('未能从Thundercore mainnet断开连接!');
    }
    如果(成功){
    console.log('disconnected');
    }
    });
    tips=listence();
    }, (50 * 1000));
    }
    _听
    
    与NodeJS一起运行

    节点侦听到\u thundercore\u mainnet.js
    
    Thundercore会在60秒后断开您的连接。因此,我们在这之前故意断开连接,并立即重新连接。 这种方法在跟踪流量巨大的合同时会错过一些交易