Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate the total volume transacted for a token on RSK?

I would like to be able to find out the total volume transacted for RDOC, from deployment until now.

Unable to get this information from the block explorer: 0x2d919f19d4892381d58edebeca66d5642cef1a1f

What's the best way to get this using RPC or web3.js?

like image 893
7alip Avatar asked Jun 16 '21 07:06

7alip


People also ask

How do you find the volume of a compound tank?

Calculate the area of the circle using πr² (if you have the diameter, divide it in half to get the radius). Then, just multiply the area of the circular base by the height of the tank to find its volume. Thanks! How do I calculate the volume of compound shapes?

What is tick volume in trading?

In the United Kingdom, the Financial Conduct Authority (FCA) performs the function. Investors can also track the tick volume of a security, which signifies the number of changes in the price of a contract. It is because as the volume of trade increases, price changes also tend to become more frequent.

What is trading volume in finance?

In other words, trading volume provides a measure of the number of shares that are transacted between a given time period. Trade volume is an indicator of the market activity and liquidity of a given security, e.g., stocks, bonds, futures contracts, options contracts, as well as all varieties of commodities.

What are the rules and regulations for volume of trade?

The rules and regulations regarding the usage of the volume of trade by financial markets traders are set in the US by the Securities and Exchange Commission (SEC). In the United Kingdom, the Financial Conduct Authority (FCA) performs the function.


2 Answers

You can get past logs

  • from the block when the contract was deployed

  • until the current block

  • emitted by the token contract address

  • where the topics[0] is keccak256 of the event signature

    In case of Transfer(address,address,uint256) event, the keccak256 hash is 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef

Since the first two params of the event are indexed, they are present in the topics[1] (sender) and topics[2] (receiver) fields of each event log. The third param (amount) is unindexed, so its value is in the data field (as a hex number) of each event log.

The total transacted volume is simply a sum of all transferred amounts (from the data field).

Mind that most RPC providers allow accessing only limited amount of historic blocks (e.g. max 100 blocks). So you might have to use a different provider or your own full node in order to access a deeper history (e.g. 200 blocks).

like image 88
Petr Hejda Avatar answered Sep 24 '22 19:09

Petr Hejda


tl;dr= (1) init a web3.eth.Contract instance for the RDOC deployed address; then (2) call .getPastEvents('Transfer'), then (3) aggregate the sum of Transfer.value values.

Detailed answer:

(1) Init the contract instance

There is a RPC data provider, GetBlock which you may think of as similar to an Infura that supports RSK.

For querying large amounts of data, such as historical data, Websockets can be faster/ more efficient than HTTP, so let's use their Websockets RPC endpoint for RSK Mainnet:

wss://rsk.getblock.io/mainnet/websocket

// init web3 instance
const GETBLOCK_API_KEY = /* copy the API key from GetBlock dashboard */;

const rpcWebsocketsUrl =
  `wss://rsk.getblock.io/mainnet/websocket`;
const rpcWebsocketsOptions = {
    timeout: 5000, // ms
    headers: {
      'x-api-key': GETBLOCK_API_KEY,
    },
};
const web3Provider = new Web3.providers.WebsocketProvider(
  rpcWebsocketsUrl,
  rpcWebsocketsOptions,
);
const web3 = new Web3(web3Provider);

Once we have a web3 instance ready, we need an ABI and the token smart contract's deployed address:

// init token contract instance
const tokenAbi = require('./abi.json'); // any standard ERC20 ABI will suffice for this purpose
const tokenAddress = '0x2d919f19d4892381d58edebeca66d5642cef1a1f'; // RDOC deployed address
const token = new web3.eth.Contract(tokenAbi, tokenAddress);

(2) Get past Transfer events

According to the ERC20 specification, each time an amount of the token is transferred between one account and another account, the ERC20 smart contract should emit a Transfer event. This event contains 3 parameters:

  • The sender address,
  • the receiver address,
  • and the amount.

(We only care about the amount for our objective here)

In web3.js, to get past events, you should specify the range of block numbers, and then query the past events using .getPastEvents(). Assuming we want to calculate the total transaction volume of RDOC in the past week, we can use the total number of seconds in a week divided by the number of seconds per block.

7 * (24 * 60 * 60) / 30 = 20160

Note that as with other blockchains, the time per block is approximate, therefore this gives us the number of blocks in approximately 1 week. The exact number of blocks can also be calculated by inspecting block timestamps

// get the range of blocks to query
const rangeNumberOfBlocks = 20160;
const latestBlockNumber = await web3.eth.getBlockNumber().toNumber();
const blockRange = {
  fromBlock: latestBlockNumber - rangeNumberOfBlocks,
  toBlock: latestBlockNumber,
};

Now we can query past events:

// get past `Transfer` events
const events = await token.getPastEvents(
  'Transfer',
  blockRange,
);

(3) calculate the aggregate

Each event in the events array contains the three event parameters, as per the ERC20 specification, however, we are only interested in event.returnValues.value.

Note that this is returned as a BN (BigNumber), and for good reason - it is a uint256, which is too large for Javascript's built in Number type. Also note that this number has a certain number of decimal places that it should be divided by, also specified in the ERC20 specification.

// prepare for division for decimal places
const decimals = await token.methods.decimals().call();
const decimalsExp = new web3.utils.BN(10).pow(new web3.utils.BN(decimals));

For most tokens, including RDOC, we expect decimalsExp to be 1e18 (1000000000000000000).

Finally, we can loop over the events, and calculate the aggregate value.

Below I'm using .iadd() instead of .add() so that the addition can occur in-place, so as to avoid reassignment/ memory allocation overhead (but this is optional).

  const sum = new web3.utils.BN(0);
  for (let eventIdx = 0; eventIdx < events.length; eventIdx += 1) {
    const event = events[eventIdx];
    sum.iadd(
      new web3.utils.BN(event.returnValues.value),
    );
  }
  const displaySum = sum.div(decimalsExp).toString();

displaySum should be the total amount of transacted RDOC for the selected time period.

like image 43
bguiz Avatar answered Sep 23 '22 19:09

bguiz