Zip and binary map

Suppose the user wants to write an operator that takes a collection of current prices of arbitrary NFTs in ETH (using the high-precision 256-bit u256s type) as the input stream and converts them to USDC based on the current exchange rate of ETH/USDC obtained from a price oracle as a single-element collection. These two collections can be merged into a single collection of tuples using the built-in zip operator in the compiler.

By default, the zip operator can, for example, append the element of the single-element collection to the end of each tuple in the new collection. However, depending on the specific input streams, the zip operator's implementation may vary under the compiler's hood. After merging, the output stream of the zip operator can be passed as the input stream to the map operator and processed according to a user-defined closure named nft_price_to_eth:

let closure nft_price_to_eth = (
(meta, priceETH): (NFTMeta, u256s),
exchange_rate: u256s
) =>  {
    let converted_price = price * exchange_rate;
    (meta, converted_price)
}

The dataflow, where we export the output collection nfts_priced_in_eth to the end user, can be succinctly described with the following code:

export collection nfts_priced_in_eth = @input("PRICE_STREAM")
    .zip("EXCHANGE_RATE_STREAM")
    .map(nft_price_to_eth)

Here, we use the stream identifiers PRICE_STREAM and EXCHANGE_RATE_STREAM to specify the two input streams for the zip operator. It's important to note that the parameter of the zip operator is used as the identifier for the second stream since the @input directive only refers to one stream, which is always the first stream by default.

Last updated