Skip to content

lafbelmonte/token-ownership-worker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Authors

Abstract

The Ethereum JSON-RPC API will be used to retrieve all the events generated by all ERC20, ERC721, and ERC1155 smart contracts. These events will then be used to build a data model that represents the ownership of the users of tokens of all types. The worker service which will run this operation will be written entirely in the Rust programming language.

Models

contract_addresses

smart contract type

token_ownerships

smart contract token id owner quantity

Documentation

UML

Sequence Diagram

Task Concurrency

This worker utilizes two concurrent tasks/worker under the hood in order to process current and upcoming logs. The first one is the latest_block_worker, its only task is to keep track of the latest mined block to be used by the second worker as reference. The second one is the logs_worker, its task is to process/store all the logs in each block.

Pseudo code

let latest_block = Arc::new(Mutex::new(None));

let logs_worker_latest_block = latest_block.clone();

let latest_block_worker = task::spawn(async move {
    loop {
        *latest_block.lock().unwrap() = get_latest_block();
    }
});

let logs_worker = task::spawn(async move {

    let current_block = get_current_block();

    loop {
        let latest_block = *logs_worker_latest_block.lock().unwrap();

        if current_block <= latest_block {
            // process logs
        }
        
        current_block += 1;
    }
});

try_join!(latest_block_worker, logs_worker)

Processing Logs

Fetching Filtered Logs

let erc_20_and_721_transfer_signature = H256::from(keccak256("Transfer(address,address,uint256)".as_bytes()));
let erc_1155_transfer_single_signature = H256::from(keccak256("TransferSingle(address,address,address,uint256,uint256)".as_bytes()));
let erc_1155_transfer_batch_signature = H256::from(keccak256("TransferBatch(addressaddress,address,uint256[],uint256[])".as_bytes()));

let signatures_filter = vec![
    erc_20_and_721_transfer_signature,
    erc_1155_transfer_single_signature,
    erc_1155_transfer_batch_signature,
];

let filter = FilterBuilder::default()
    .from_block(BlockNumber::Number(current_block))
    .to_block(BlockNumber::Number(current_block))
    .topics(Some(signatures_filter), None, None, None)
    .build();

let logs: Vec<Log> = match logs_worker_web3.eth().logs(filter).await {
    Ok(logs) => logs,
    Err(error) => {
        // handle error
    }
};

Utilizing EIP-165

let contract = Contract::from_json(
    logs_worker_web3.eth(),
    log.address,
    include_bytes!("supports_interface_abi.json"),
)
.unwrap();

let erc_721_interface_id: [u8; 4] =
    hex::decode("80ac58cd").unwrap()[0..4].try_into().unwrap();

let supports_interface: bool = match contract
    .query(
        "supportsInterface",
        (erc_721_interface_id,),
        None,
        Options::default(),
        None,
    )
    .await
{
    Ok(value) => value,
    Err(_) => {
        continue;
    }
};

if supports_interface {
    // process
}

Decoding Quantity

let decoded_quantity = match decode(
    &vec![ParamType::Uint(256)],
    &log.data.0,
) {
    Ok(decoded) => match decoded[0] {
        Token::Uint(decoded_quantity) => decoded_quantity,
        _ => {
            // handle
        },
    },
    Err(_) => {
        // handle
    },
};

let quantity = decoded_quantity.as_u128().to_f64().unwrap();

Decoding Token ID

let decoded_token_id = match decode(
    &vec![ParamType::Uint(256)],
    &log.topics[3].as_bytes(),
) {
    Ok(decoded) => match decoded[0] {
        Token::Uint(token_id) => token_id,
        _ => {
            // handle
        },
    },
    Err(_) => {
        // handle
    },
};

let token_id = decoded_token_id.to_string();

Resources

Ethereum Logs

Rust Web3

Rust MongoDB

Tokio Concurrency

EIP-165

CLI

Rust Book

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages