#near #block-height #lake #framework #s3 #stream #connect

near-lake-framework

用于连接NEAR Lake S3和流式传输数据的库

22个版本

0.8.0-beta.32023年11月22日
0.8.0-beta.22023年6月6日
0.7.9 2024年6月26日
0.7.7 2024年2月1日
0.5.0 2022年6月16日

#808 in 神奇豆子

Download history 272/week @ 2024-04-16 100/week @ 2024-04-23 34/week @ 2024-04-30 41/week @ 2024-05-07 36/week @ 2024-05-14 147/week @ 2024-05-21 11/week @ 2024-05-28 114/week @ 2024-06-04 158/week @ 2024-06-11 166/week @ 2024-06-18 186/week @ 2024-06-25 158/week @ 2024-07-02 84/week @ 2024-07-09 199/week @ 2024-07-16 91/week @ 2024-07-23 116/week @ 2024-07-30

494每月下载量
用于 3 crates

MIT/Apache

125KB
2K SLoC

NEAR Lake Framework

NEAR Lake Framework是NEAR Lake的一个小型库伴侣。它允许您构建自己的索引器,订阅来自NEAR Lake数据源的块流,并创建自己的逻辑来处理NEAR协议数据。

示例

fn main() -> anyhow::Result<()> {
    near_lake_framework::LakeBuilder::default()
        .testnet()
        .start_block_height(112205773)
        .build()?
        .run(handle_block)?;
    Ok(())
}

// The handler function to take the `Block`
// and print the block height
async fn handle_block(
    block: near_lake_primitives::block::Block,
) -> anyhow::Result<()> {
    eprintln!(
        "Block #{}",
        block.block_height(),
    );
#    Ok(())
}

将上下文传递给函数

#[derive(near_lake_framework::LakeContext)]
struct MyContext {
    my_field: String
}

fn main() -> anyhow::Result<()> {

    let context = MyContext {
        my_field: "My value".to_string(),
    };

    near_lake_framework::LakeBuilder::default()
        .testnet()
        .start_block_height(112205773)
        .build()?
        .run_with_context(handle_block, &context)?;

    Ok(())
}

// The handler function to take the `Block`
// and print the block height
async fn handle_block(
    block: near_lake_primitives::block::Block,
    context: &MyContext,
) -> anyhow::Result<()> {
    eprintln!(
        "Block #{} / {}",
        block.block_height(),
        context.my_field,
    );
#    Ok(())
}

收据上下文的父事务

这是一个老问题,NEAR协议在收据中不提供父事务哈希。这对于需要知道父事务哈希以构建事务树的索引器来说是一个问题。我们已经为你准备好了lake-parent-transaction-cache crate,它提供了父事务哈希的缓存。

use near_lake_framework::near_lake_primitives;
use near_lake_primitives::CryptoHash;
use near_lake_parent_transaction_cache::{ParentTransactionCache, ParentTransactionCacheBuilder};
use near_lake_primitives::actions::ActionMetaDataExt;

fn main() -> anyhow::Result<()> {
    let parent_transaction_cache_ctx = ParentTransactionCacheBuilder::default()
        .build()?;
    // Lake Framework start boilerplate
    near_lake_framework::LakeBuilder::default()
        .mainnet()
        .start_block_height(88444526)
        .build()?
        // developer-defined async function that handles each block
        .run_with_context(print_function_call_tx_hash, &parent_transaction_cache_ctx)?;
    Ok(())
}

async fn print_function_call_tx_hash(
    mut block: near_lake_primitives::block::Block,
    ctx: &ParentTransactionCache,
) -> anyhow::Result<()> {
    // Cache has been updated before this function is called.
    let block_height = block.block_height();
    let actions: Vec<(
        &near_lake_primitives::actions::FunctionCall,
        Option<CryptoHash>,
    )> = block
        .actions()
        .filter_map(|action| action.as_function_call())
        .map(|action| {
            (
                action,
                ctx.get_parent_transaction_hash(&action.receipt_id()),
            )
        })
        .collect();

    if !actions.is_empty() {
        // Here's the usage of the context.
        println!("Block #{:?}\n{:#?}", block_height, actions);
    }

    Ok(())
}

教程

更多示例

您可以在examples文件夹中查看始终更新的示例。

我们试图保持更新的其他示例,但有时可能会失败

使用方法

AWS S3凭据

为了能够从AWS S3存储桶中获取对象,您需要提供AWS凭据。

将凭据传递给配置构建器

use near_lake_framework::LakeBuilder;

# fn main() {
let credentials = aws_credential_types::Credentials::new(
    "AKIAIOSFODNN7EXAMPLE",
    "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
    None,
    None,
    "custom_credentials",
);
let s3_config = aws_sdk_s3::Config::builder()
    .credentials_provider(credentials)
    .build();

let lake = LakeBuilder::default()
    .s3_config(s3_config)
    .s3_bucket_name("near-lake-data-custom")
    .s3_region_name("eu-central-1")
    .start_block_height(1)
    .build()
    .expect("Failed to build LakeConfig");
# }

您绝对不应该将凭据硬编码,这是不安全的。使用描述的方法通过CLI参数传递您读取的凭据

基于文件的AWS凭据

使用aws configure设置的AWS默认配置文件看起来类似于以下内容

~/.aws/credentials

[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

AWS文档:配置和凭据文件设置

环境变量

或者,您可以通过具有常量名称的环境变量提供您的AWS凭据

$ export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
$ AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
$ AWS_DEFAULT_REGION=eu-central-1

依赖关系

将以下依赖关系添加到您的 Cargo.toml

...
[dependencies]
futures = "0.3.5"
itertools = "0.10.3"
tokio = { version = "1.1", features = ["sync", "time", "macros", "rt-multi-thread"] }
tokio-stream = { version = "0.1" }

# NEAR Lake Framework
near-lake-framework = "0.8.0"

自定义S3存储

如果您想运行自己的 near-lake 实例并在某些S3兼容存储中(例如MinioLocalstack)存储数据,您可以通过使用 s3_endpoint 选项覆盖默认S3 API端点

  • 运行minio
$ mkdir -p /data/near-lake-custom && minio server /data
  • 将自定义 aws_sdk_s3::config::Config 传递到 [LakeBuilder]
use near_lake_framework::LakeBuilder;

# #[tokio::main]
# async fn main() -> anyhow::Result<()> {
    let aws_config = aws_config::from_env().load().await;
    let s3_config = aws_sdk_s3::config::Builder::from(&aws_types::SdkConfig::from(aws_config))
        .endpoint_url("http://0.0.0.0:9000")
        .build();

    LakeBuilder::default()
        .s3_bucket_name("near-lake-custom")
        .s3_region_name("eu-central-1")
        .start_block_height(0)
        .s3_config(s3_config)
        .build()
        .expect("Failed to build Lake");

#    Ok(())
# }

配置

您应该通过 LakeConfigBuilder 结构在索引器应用程序启动之前配置所有内容。

可用参数

成本估算(2022年3月10日更新,计算更精确)

TL;DR 大约每月20美元(用于 AWS S3 访问,直接支付给 AWS)用于读取新鲜块

历史索引

GET LIST GET 小计 LIST 小计 总计 $
1000 5000 4 0.00215 0.0000216 $0.00
86,400 432000 345.6 0.18576 0.00186624 $0.19
2,592,000 12960000 10368 5.5728 0.0559872 $5.63
77,021,059 385105295 308084.236 165.5952769 1.663654874 $167.26

注意: ~77m 的块是在我计算时的块数。

每天约84,400个块(每秒1个块 * 60秒 * 60分钟 * 24小时)

每月约2,592,000个块(每天86,400个块 * 30天)

网络索引的顶端

GET LIST GET 小计 LIST 小计 总计 $
1000 5000 1000 0.00215 0.0054 $0.01
86,400 432000 86,400 0.18576 0.46656 $0.65
2,592,000 12960000 2,592,000 5.5728 13.9968 $19.57
77,021,059 385105295 77,021,059 165.5952769 415.9137186 $581.51

说明

假设 NEAR 协议每秒准确产生1个块(这实际上并不准确,平均块生产时间是1.3秒)。一天由86400秒组成,这是可以产生的最大块数。

根据Amazon S3 价格list 请求按每1000次请求0.0054美元计费,而get按每1000次请求0.00043美元计费。

计算(假设我们始终跟随网络顶端)

86400 blocks per day * 5 requests for each block / 1000 requests * $0.0004 per 1k requests = $0.19 * 30 days = $5.7

注意: 每个块的5个请求意味着我们有4个分片(1个用于公共块数据的文件和4个用于每个分片的单独文件)

我们需要在30天内执行的list请求数量

86400 blocks per day / 1000 requests * $0.005 per 1k list requests = $0.47 * 30 days = $14.1

$5.7 + $14.1 = $19.8

价格取决于分片的数量

未来计划

我们使用具有明确验收标准的里程碑

依赖关系

~45MB
~731K SLoC