September 23, 2023

Was sind Wahlzyklen in Shardeum?

Was sind Smart Contract Events?

Intelligente Vertragsereignisse übertragen neue

Daten aus einem Vertrag.

Warum sind Smart Contract-Ereignisse wichtig?

Smart Contract Event Listening benachrichtigt Anwendungen und Benutzer in Echtzeit darüber, dass in einem Smart Contract etwas Neues passiert ist.

Wo werden Ereignisse in Smart Contract-Anwendungen verwendet?

Frontend

Wenn Sie Token auf einer Website mithilfe eines AMM DEX-Smart-Vertrags austauschen, wissen die Token-Guthaben im Frontend mithilfe von Ereignissen fast sofort, wann sie aktualisiert werden müssen.

Backend

Trading-Bots können AMM DEX-SwapKontraktereignisse abhören und potenzielle Arbitrage-Möglichkeiten finden. IoT-Robotikanwendungen in der physischen Welt, die mit einem Smart Contract verbunden sind, können mit Ereignissen gesteuert werden.

Chainlink-Orakelknoten sind auch auf intelligente Vertragsereignisse angewiesen, um zu wissen, wann sie zwischen der realen Welt und Blockchains kommunizieren müssen.

Wie kann man Smart-Contract-Ereignisse auf Shardeum hören?

Websockets

Wir planen, in Zukunft Websocket-RPC-URL-Unterstützung hinzuzufügen, um Smart-Contract-Ereignisse zu abonnieren. Auf diese Weise können Benutzer API-Aufrufe sparen, anstatt bei jedem neuen Block/Bündel/Zyklus neue Daten abzufragen.

Umfrage

Das Lesen von Smart-Contract-Ereignissen kann auch mithilfe von Shardeum-Zyklen erfolgen (dazu hören wir Blöcke/Bündel ab).

Leseveranstaltungen mit Shardeum Cycles:

  1. Um den aktuellen Zyklus zu erhalten: Holen Sie sich den neuesten Block, dividieren Sie dann durch 10 und runden Sie ab.
  2. Erstellen Sie die JSON-URL mit:

Beispiel mit:

startCycle = endCycle = 49
address = 0x23FF65f07cAbAd1643440a0114d71260F2Bb6352

https://explorer-dapps.shardeum.org/api/transaction?startCycle=19020&endCycle=19045&address=0x245E2395712F888CeD1033C924115105dC32e388&_ga=2.129627980.1575414968.1695051107-1197877890.1692428116&_gl=1*1o3kvfu*_ga*MTE5Nzg3Nzg5MC4xNjkyNDI4MTE2*_ga_2VJLR99VYW*MTY5NTEyMDE5My4yMi4wLjE2OTUxMjAxOTMuNjAuMC4w

3. Filtern Sie nach Transaktionen pro Seite [Hinweis: 10 Transaktionen pro Seite]:

https://explorer-dapps.shardeum.org/api/transaction?startCycle=19020&endCycle=19045&address=0x245E2395712F888CeD1033C924115105dC32e388&page=1&_ga=2.166384510.1575414968.16950511075Nzg3Nzg5MC4xNjkyNDI4MTE2*_ga_2VJLR99VYW*MTY5NTEyMDE5My4yMi4wLjE2OTUxMjAxOTMuNjAuMC4w

JSON-URL-Filtervariablen

?startCycle=lastestCycle
&endCycle=lastestCycle
&address=addressToListenTo
&page=1

Beispiele für das Abhören von Ereignissen mit Umfragen:​

Transaktionsereignisse von der Nulladresse (Adresse(0)) von Zyklus 0 bis 1000 lesen:

JavaScript

const axios = require('axios');

let baseUrl = "https://explorer-dapps.shardeum.org/api/transaction?startCycle=19020&endCycle=19045&address=0x245E2395712F888CeD1033C924115105dC32e388"

getTransactionsToAddressCycleRange(baseUrl)

async function readJSONLoop(totalTransactions) {

    let total = totalTransactions;
    let pageIndex = 1

    while ( total > 0 ) {

        let filterUrl = baseUrl + "&page=" + pageIndex
        console.log(filterUrl)

        let responseRawJSON = await axios.get(filterUrl);
        responseRawJSON = responseRawJSON.data;
        console.log(responseRawJSON);

        total -= 10;
        pageIndex++;
    }

}

async function getTransactionsToAddressCycleRange(baseUrl) {

    let responseRawJSON = await axios.get(baseUrl);
    let responseDataJSON = responseRawJSON.data;
    let totalTransactions = responseDataJSON.totalTransactions
    console.log(totalTransactions);

    readJSONLoop(totalTransactions)
    
}


Python

from urllib.request import urlopen
import json

transactionsInCycleRangeUrlString = "https://explorer-dapps.shardeum.org/api/transaction?startCycle=19020&endCycle=19045&address=0x245E2395712F888CeD1033C924115105dC32e388"
transactionsInCycleRangeUrlOpened = urlopen(transactionsInCycleRangeUrlString)
transactionsInCycleRangeUrlJSON = json.loads(transactionsInCycleRangeUrlOpened.read())
totalTransactions = transactionsInCycleRangeUrlJSON["totalTransactions"]
print(totalTransactions)
pageIndex = 1

while totalTransactions > 0:
    print(pageIndex)
    print(totalTransactions)
    pageIndexIncrementUrlString = transactionsInCycleRangeUrlString + "&page=" + str(pageIndex)
    pageIndexIncrementUrlOpened = urlopen(pageIndexIncrementUrlString)
    rawTransactionDataPage = json.loads(pageIndexIncrementUrlOpened.read())
    print(rawTransactionDataPage)
    totalTransactions -= 10
    pageIndex += 1


Go

package main

import (
   "io/ioutil"
   "log"
   "net/http"
   "encoding/json"
   "strconv"
)

func main() {
   
   baseUrl := "https://explorer-dapps.shardeum.org/api/transaction?startCycle=";
   transactionCount := getTransactionCount(6928, baseUrl)
   log.Println(transactionCount)

   readJsonLoop(transactionCount, baseUrl)

}

type transactionCountJson struct {
    Success bool `json:"success"`
   TotalTransactions int `json:"totalTransactions"`
}

func getTransactionCount(cycleNumber int, baseUrl string) (x int) {

   getRequestUrl := 
      baseUrl +
      strconv.Itoa(cycleNumber)+
      "&endCycle="+
      strconv.Itoa(cycleNumber);
   log.Println(getRequestUrl)

   resp, err := http.Get(getRequestUrl)
   if err != nil {
      log.Fatalln(err)
   }

   rawBodyBytes, err := ioutil.ReadAll(resp.Body)
   if err != nil {
      log.Fatalln(err)
   }

   var transactionCountJsonInstance transactionCountJson

   err = json.Unmarshal(rawBodyBytes, &transactionCountJsonInstance)
   if err != nil {
      log.Fatalln(err)
   }

   return transactionCountJsonInstance.TotalTransactions;
}

func readJsonLoop(totalTransactions int, baseUrl string) {

   total := totalTransactions;
   pageIndex := 1;

   for total > 0 {

      getRequestUrl := 
         baseUrl+
         strconv.Itoa(6928)+
         "&endCycle="+
         strconv.Itoa(6928)+
         "&page=" + 
         strconv.Itoa(pageIndex)
      log.Println(getRequestUrl)

      resp, err := http.Get(getRequestUrl)
      if err != nil {
         log.Fatalln(err)
      }
   
      rawBodyBytes, err := ioutil.ReadAll(resp.Body)
      if err != nil {
         log.Fatalln(err)
      }
   
      log.Printf(string(rawBodyBytes))

      total -= 10;
      pageIndex++;
   }

}


Rust

use serde_json;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {

    let base_url = String::from("https://explorer-dapps.shardeum.org/api/transaction?startCycle=");
    let cycle_number = 6928;

    let transaction_count : u64 = get_transaction_count(cycle_number.clone(), base_url.clone()).await;    
    println!("transaction_count: {:#?}", transaction_count);
     
    read_json_loop(cycle_number.clone(), base_url.clone(), transaction_count).await;

    Ok(())
}

async fn get_transaction_count(cycle_number: u64, base_url: String) -> u64   {

    let get_request_url = 
        base_url +
        &cycle_number.to_string() +
        "&endCycle=" +
        &cycle_number.to_string();
    println!("getRequestUrl: {:#?}", get_request_url);

    let new_todo: serde_json::Value = reqwest::Client::new()
        .get(get_request_url)
        .send()
        .await.unwrap()
        .json()
        .await.unwrap();

    println!("JSON raw response: {:#?}", new_todo);
    println!("{:#?}", new_todo["success"]);
    println!("{:#?}", new_todo["totalTransactions"]);
    println!("{:#?}", new_todo["totalTransactions"].as_u64().unwrap());

    return new_todo["totalTransactions"].as_u64().unwrap();

}

async fn read_json_loop(cycle_number: u64, base_url: String, total_transactions: u64) {

   let mut total : i64 = total_transactions as i64; //Convert value to be signed so we do not have an underflow error when the value become negative.
   let mut page_index = 1;

   while total > 0 {

        let get_request_url = 
            base_url.clone() +
            &cycle_number.to_string() +
            "&endCycle=" +
            &cycle_number.to_string() +
            "&page=" + 
            &page_index.to_string();
        println!("getRequestUrl: {:#?}", get_request_url);

        let new_todo: serde_json::Value = reqwest::Client::new()
            .get(get_request_url)
            .send()
            .await.unwrap()
            .json()
            .await.unwrap();
    
        println!("JSON raw response: {:#?}", new_todo);

        total -= 10;
        page_index += 1;
    }   
    
}

Hören Sie auf den neuesten

Zyklus Lauschen auf den neuesten Zyklus, der möglicherweise Transaktionsereignisse von einer Adresse enthält:

JavaScript

const axios = require('axios');
const ethers = require('ethers')

const rpcURL = "https://dapps.shardeum.org/"

const provider = new ethers.providers.JsonRpcProvider(rpcURL)

const timeMilliSec = 1000;

listenForCycle()

function timeout(ms) {
    return new Promise(resolve => setTimeout(resolve,ms));
}

async function listenForCycle() {
  while (true){

    console.log("Current cycle (1 cycle = 10 blocks [bundles]) ")
    let cycle = await provider.getBlockNumber();
    console.log(Math.floor(cycle/10))

    let baseUrlCycleAddress = "https://explorer-dapps.shardeum.org/api/transaction?startCycle=" + cycle + "&endCycle=" + cycle + "&address=0x0000000000000000000000000000000000000000" 
    console.log(baseUrlCycleAddress)

    let responseRawJSON = await axios.get(baseUrlCycleAddress);
    let responseDataJSON = responseRawJSON.data;
    let totalTransactions = responseDataJSON.totalTransactions
    console.log(totalTransactions);

    readJSONLoopLatestCycle(totalTransactions,baseUrlCycleAddress)

    await timeout(60*timeMilliSec)

  }
}

async function readJSONLoopLatestCycle(totalTransactions,baseUrl) {

    let total = totalTransactions;
    let pageIndex = 1

    while ( total > 0 ) {

        let filterUrl = baseUrl + "&page=" + pageIndex
        console.log(filterUrl)

        let responseRawJSON = await axios.get(filterUrl);
        responseRawJSON = responseRawJSON.data;
        console.log(responseRawJSON);

    total -= 10;
        pageIndex++;
    }

}


Python

from web3 import Web3
import time
import math
from urllib.request import urlopen
import json

ShardeumConnectionHTTPS = "https://dapps.shardeum.org/";
web3 = Web3(Web3.HTTPProvider(ShardeumConnectionHTTPS))

print("Connected to Web3? ")
print(web3.isConnected())

print("Chain ID? ")
print(web3.eth.chain_id)

addressToSubscribeTo = "0x0000000000000000000000000000000000000000"

while True:
print("Current cycle (1 cycle = 10 blocks [bundles]) ")
cycle =  (math.floor(web3.eth.blockNumber/10))  #Divide current bundle [block] by 10, then round down to get cycle.
print(cycle)

transactionsInCycleRangeUrlString = "https://explorer-dapps.shardeum.org/api/transaction?startCycle=" + str(cycle) + "&endCycle=" + str(cycle) + "&address=" + addressToSubscribeTo
print(transactionsInCycleRangeUrlString)
transactionsInCycleRangeUrlOpened = urlopen(transactionsInCycleRangeUrlString)
transactionsInCycleRangeUrlJSON = json.loads(transactionsInCycleRangeUrlOpened.read())
totalTransactions = transactionsInCycleRangeUrlJSON["totalTransactions"]
print(totalTransactions)
pageIndex = 1

while totalTransactions > 0:
    print(pageIndex)
    print(totalTransactions)
    pageIndexIncrementUrlString = transactionsInCycleRangeUrlString + "&page=" + str(pageIndex)
    pageIndexIncrementUrlOpened = urlopen(pageIndexIncrementUrlString)
    rawTransactionDataPage = json.loads(pageIndexIncrementUrlOpened.read())
    print(rawTransactionDataPage)
    totalTransactions -= 10
    pageIndex += 1

time.sleep(60)  


Go

package main

import (
   "io/ioutil"
   "log"
   "net/http"
   "encoding/json"
   "context"
   "math/big"
   "strconv"
   "time"

   "github.com/ethereum/go-ethereum/ethclient"
)

func main() {

   client, chainID := clientSetup("https://dapps.shardeum.org/")

   log.Println("chainID: ", chainID)


   for {

      header, err := client.HeaderByNumber(context.Background(), nil)
      if err != nil {
         log.Fatal(err)
      }

      blockNumber := header.Number
      bigNumberTenBundlesPerCycle, _ := new(big.Int).SetString("10", 10)  //Value 10, decimal units also 10. 
      cycleNumber := new(big.Int).Div(blockNumber, bigNumberTenBundlesPerCycle)
      bigNumberOne, _ := new(big.Int).SetString("1", 10)  //Value 1, decimal units 10. 
      cycleNumberMinusOne := new(big.Int).Sub(cycleNumber, bigNumberOne)
      log.Println(cycleNumberMinusOne)
      
      baseUrl := "https://explorer-dapps.shardeum.org/api/transaction?startCycle=";
      transactionCount := getTransactionCount(cycleNumberMinusOne, baseUrl)
      log.Println(transactionCount)

      readJsonLoop(cycleNumberMinusOne,baseUrl,transactionCount)

      time.Sleep(60 * time.Second)

   }

}

type transactionCountJson struct {
    Success bool `json:"success"`
   TotalTransactions int `json:"totalTransactions"`
}

func getTransactionCount(cycleNumber *big.Int, baseUrl string) (x int) {

   getRequestUrl := 
      baseUrl +
      cycleNumber.String()+
      "&endCycle="+
      cycleNumber.String();
   log.Println(getRequestUrl)

   resp, err := http.Get(getRequestUrl)
   if err != nil {
      log.Fatalln(err)
   }

   rawBodyBytes, err := ioutil.ReadAll(resp.Body)
   if err != nil {
      log.Fatalln(err)
   }

   var transactionCountJsonInstance transactionCountJson

   err = json.Unmarshal(rawBodyBytes, &transactionCountJsonInstance)
   if err != nil {
      log.Fatalln(err)
   }

   return transactionCountJsonInstance.TotalTransactions;
}

func readJsonLoop(cycleNumber *big.Int, baseUrl string, totalTransactions int) {

   total := totalTransactions;
   pageIndex := 1;

   for total > 0 {

      getRequestUrl := 
         baseUrl+
         cycleNumber.String()+
         "&endCycle="+
         cycleNumber.String()+
         "&page=" + 
         strconv.Itoa(pageIndex)
      log.Println(getRequestUrl)

      resp, err := http.Get(getRequestUrl)
      if err != nil {
         log.Fatalln(err)
      }
   
      rawBodyBytes, err := ioutil.ReadAll(resp.Body)
      if err != nil {
         log.Fatalln(err)
      }
   
      log.Printf(string(rawBodyBytes))

      total -= 10;
      pageIndex++;
   }

}

func clientSetup(wssConnectionURL string) (client *ethclient.Client, chainID *big.Int) {

   client, err := ethclient.Dial(wssConnectionURL) //Also works with HTTPS connections. 
   if err != nil {
       log.Fatal(err)
   }
 
   chainID, err = client.NetworkID(context.Background())
   if err != nil {
      log.Fatal(err)
   }
   return
}



Rust

use serde_json;
use ethers_providers::{Middleware, Provider, Http};
use std::thread::{sleep};
use std::time::{Duration};

#[tokio::main]
async fn main() {

    let rpc_shardeum_https = "https://dapps.shardeum.org/";

    let provider = Provider::<Http>::try_from(rpc_shardeum_https).expect("could not instantiate HTTP Provider");

    let chainid = provider.get_chainid().await.unwrap();
    println!("Got chainid: {}", chainid);

    loop{

        let current_block_number = provider.get_block_number().await.unwrap();
        println!("current_block_number: {:?}", current_block_number);

        let current_cycle_number = current_block_number/10;
        println!("current_cycle_number: {:?}", current_cycle_number);

        let current_cycle_number_minus_one = current_cycle_number-1;
        println!("current_cycle_number: {:?}", current_cycle_number_minus_one);

        let base_url = String::from("https://explorer-dapps.shardeum.org/api/transaction?startCycle=");

        let transaction_count : u64 = get_transaction_count(current_cycle_number_minus_one.as_u64().clone(), base_url.clone()).await;    
        println!("transaction_count: {:#?}", transaction_count);
        
        read_json_loop(current_cycle_number_minus_one.as_u64().clone(), base_url.clone(), transaction_count).await;

        sleep(Duration::from_millis(60000)); // Sleep for 60 seconds.

    }

}

async fn get_transaction_count(cycle_number: u64, base_url: String) -> u64   {

    let get_request_url = 
        base_url +
        &cycle_number.to_string() +
        "&endCycle=" +
        &cycle_number.to_string();
    println!("getRequestUrl: {:#?}", get_request_url);

    let new_todo: serde_json::Value = reqwest::Client::new()
        .get(get_request_url)
        .send()
        .await.unwrap()
        .json()
        .await.unwrap();

    println!("JSON raw response: {:#?}", new_todo);
    println!("{:#?}", new_todo["success"]);
    println!("{:#?}", new_todo["totalTransactions"]);
    println!("{:#?}", new_todo["totalTransactions"].as_u64().unwrap());

    return new_todo["totalTransactions"].as_u64().unwrap();

}

async fn read_json_loop(cycle_number: u64, base_url: String, total_transactions: u64) {

   let mut total : i64 = total_transactions as i64; //Convert value to be signed so we do not have an underflow error when the value become negative.
   let mut page_index = 1;

   while total > 0 {

        let get_request_url = 
            base_url.clone() +
            &cycle_number.to_string() +
            "&endCycle=" +
            &cycle_number.to_string() +
            "&page=" + 
            &page_index.to_string();
        println!("getRequestUrl: {:#?}", get_request_url);

        let new_todo: serde_json::Value = reqwest::Client::new()
            .get(get_request_url)
            .send()
            .await.unwrap()
            .json()
            .await.unwrap();
    
        println!("JSON raw response: {:#?}", new_todo);

        total -= 10;
        page_index += 1;
    }   
    
}