{"id":21531978,"url":"https://github.com/chainbound/fiber-rs","last_synced_at":"2025-10-29T18:03:02.733Z","repository":{"id":60263698,"uuid":"538133698","full_name":"chainbound/fiber-rs","owner":"chainbound","description":"Fiber client in Rust","archived":false,"fork":false,"pushed_at":"2025-05-06T07:25:03.000Z","size":448,"stargazers_count":49,"open_issues_count":2,"forks_count":7,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-06T07:48:02.340Z","etag":null,"topics":["blockchain","ethereum","evm","mev","p2p","rust"],"latest_commit_sha":null,"homepage":"https://fiber.chainbound.io","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chainbound.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-09-18T14:23:11.000Z","updated_at":"2025-05-06T06:53:28.000Z","dependencies_parsed_at":"2023-11-06T10:26:23.590Z","dependency_job_id":"f2ad3746-7ed3-4164-8ff7-41b50c61c7e3","html_url":"https://github.com/chainbound/fiber-rs","commit_stats":{"total_commits":104,"total_committers":5,"mean_commits":20.8,"dds":"0.42307692307692313","last_synced_commit":"445e95b2f1e2091c178977f2b0726f60f828c1b5"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/chainbound/fiber-rs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainbound%2Ffiber-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainbound%2Ffiber-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainbound%2Ffiber-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainbound%2Ffiber-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chainbound","download_url":"https://codeload.github.com/chainbound/fiber-rs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainbound%2Ffiber-rs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271444194,"owners_count":24760742,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-21T02:00:08.990Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blockchain","ethereum","evm","mev","p2p","rust"],"created_at":"2024-11-24T02:18:23.040Z","updated_at":"2025-10-29T18:02:57.682Z","avatar_url":"https://github.com/chainbound.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `fiber-rs`\n\nRust client package for interacting with a Fiber Network API over gRPC.\n\n## Installation\n\n```bash\ncargo add fiber --git https://github.com/chainbound/fiber-rs\n```\n\n## Usage\n\n`fiber-rs` prints traces to the `fiber` target. To see them, run your program with `RUST_LOG=fiber=info`.\n\n### Connecting\n\nUsing default options:\n\n```rs\nuse fiber::Client;\n\n#[tokio::main]\nasync fn main() {\n    let mut client = Client::connect(\"ENDPOINT_URL\", \"API_KEY\").await.unwrap();\n}\n```\n\nSpecifying options:\n\n```rs\nuse fiber::{Client, ClientOptions};\n\n#[tokio::main]\nasync fn main() {\n    let opts = ClientOptions::default().send_compressed(true);\n    let mut client = Client::connect_with_options(\"ENDPOINT_URL\", \"API_KEY\", opts).await.unwrap();\n}\n```\n\n### Performance \u0026 Compression\n\nWith `ClientOptions` you can negotiate incoming and outgoing stream compression. This activates gzip compression on the underlying gRPC connections. Compression is not always faster, and here are some general guidelines to follow:\n\n- If your client is close to the target Fiber node and you have enough bandwidth, it's best to disable `accept` compression.\n- If you client is far from the target Fiber node and you have limited bandwidth, it's best to enable `accept` compression.\n\n### Subscriptions\n\nAll subscriptions return a `Stream` (`UnboundedReceiverStream`) of the specified type.\nIf the underlying gRPC stream fails due to connection issues, it will automatically be retried.\n\n#### Transactions\n\nSubscribing to transactions will return a `Stream`, yielding [`Recovered\u003calloy::consensus::TxEnvelope\u003e`](https://docs.rs/alloy/latest/alloy/consensus/transaction/struct.Recovered.html) for every new transaction that's received.\n\n**Note on EIP-4844:** Blob-carrying type 3 transactions are returned by the stream WITHOUT their blobs. The blobs are returned in a separate stream, `subscribe_new_blob_transactions`.\n\n**Example:**\n\n```rs\nuse fiber::Client;\nuse tokio_stream::StreamExt;\n\n#[tokio::main]\nasync fn main() {\n    // Client needs to be mutable\n    let mut client = Client::connect(\"ENDPOINT_URL\", \"API_KEY\").await.unwrap();\n\n    // No filter in this example\n    let mut sub = client.subscribe_new_transactions(None).await;\n\n    // Use the stream as an async iterator\n    while let Some(tx) = sub.next().await {\n        handle_transaction(tx);\n    }\n}\n```\n\n#### Blob Transactions\n\nSubscribing to blob transactions will return a `Stream`, yielding [`Recovered\u003cSigned\u003cTxEip4844WithSidecar\u003e\u003e`](https://docs.rs/alloy/latest/alloy/consensus/struct.TxEip4844WithSidecar.html) for every new blob transaction that's received.\n\n**NOTE:** This stream will ONLY yield blob-carrying transactions with their blobs. To get all transactions, use `subscribe_new_transactions` instead.\n\n**Example:**\n\n```rs\nuse fiber::Client;\nuse tokio_stream::StreamExt;\n\n#[tokio::main]\nasync fn main() {\n    // Client needs to be mutable\n    let mut client = Client::connect(\"ENDPOINT_URL\", \"API_KEY\").await.unwrap();\n\n    // No filter in this example\n    let mut sub = client.subscribe_new_blob_transactions().await;\n\n    // Use the stream as an async iterator\n    while let Some(tx) = sub.next().await {\n        handle_blob_transaction(tx);\n    }\n}\n```\n\n#### Filtering\n\nYou can apply filters to the transaction stream using `fiber::filter::Filter`. The builder pattern is used\nfor constructing a filter, with a couple of examples below.\n\n```rs\nuse fiber::{Client, filter::FilterBuilder};\nuse tokio_stream::StreamExt;\n\n#[tokio::main]\nasync fn main() {\n    // Client needs to be mutable\n    let mut client = Client::connect(\"ENDPOINT_URL\", \"API_KEY\").await.unwrap();\n\n    // Construct filter\n    // example 1: simple receiver filter\n    let f = FilterBuilder::new()\n                .to(\"0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D\");\n\n    // example 2: all transactions with either of these addresses as the receiver\n    let f = FilterBuilder::new()\n                .or() // creates a new 'OR' level\n                  .to(\"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\")\n                  .to(\"0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D\");\n\n    // example 3: all ERC20 transfers on the 2 tokens below\n    let f = FilterBuilder::new()\n                .and()\n                  .method_id(\"0xa9059cbb\")\n                  .or()\n                    .to(\"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\")\n                    .to(\"0xdAC17F958D2ee523a2206206994597C13D831ec7\");\n\n    // Encode the filter\n    let mut sub = client.subscribe_new_transactions(f.encode().unwrap()).await;\n\n    // Use the stream as an async iterator\n    while let Some(tx) = sub.next().await {\n        handle_transaction(tx);\n    }\n}\n```\n\n#### Raw transactions\n\nSubscribing to raw transactions will return a `Stream`, yielding raw RLP encoded transactions.\n\n**Example:**\n\n```rs\nuse fiber::Client;\nuse tokio_stream::StreamExt;\n\n#[tokio::main]\nasync fn main() {\n    // Client needs to be mutable\n    let mut client = Client::connect(\"ENDPOINT_URL\", \"API_KEY\").await.unwrap();\n\n    // No filter in this example\n    let mut sub = client.subscribe_new_raw_transactions(None).await;\n\n    // Use the stream as an async iterator\n    while let Some(raw_tx) = sub.next().await {\n        handle_raw_transaction(tx);\n    }\n}\n```\n\n#### Execution Payloads (new block headers + transactions)\n\nReturns a stream of newly seen execution payloads. This is useful for getting the state updates of a\nnewly confirmed block. An `ExecutionPayload` contains both the block header and the transactions\nthat were executed in that block.\n\nThe type returned by this stream is an [`alloy-consensus::Block\u003cTxEnvelope\u003e`](https://docs.rs/alloy/latest/alloy/consensus/struct.Block.html). Since the blocks returned are parsed from consensus-layer payloads, they are missing the following fields, which are set to `None` or `zero` in all returned stream items:\n\n- `parent_beacon_block_root`\n- `transactions_root`\n- `withdrawals_root`\n- `requests_hash`\n\n**Example:**\n\n```rs\nuse fiber::Client;\nuse tokio_stream::StreamExt;\n\n#[tokio::main]\nasync fn main() {\n    // Client needs to be mutable\n    let mut client = Client::connect(\"ENDPOINT_URL\", \"API_KEY\").await.unwrap();\n\n    // No filter in this example\n    let mut sub = client.subscribe_new_execution_payloads().await;\n\n    // Use the stream as an async iterator\n    while let Some(block) = sub.next().await {\n        handle_block(block);\n    }\n}\n```\n\n#### Beacon Blocks\n\nReturns a stream of consensus-layer [`SignedBeaconBlock`](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#signedbeaconblock) objects.\n\n**Example:**\n\n```rs\nuse fiber::Client;\nuse tokio_stream::StreamExt;\n\n#[tokio::main]\nasync fn main() {\n    // Client needs to be mutable\n    let mut client = Client::connect(\"ENDPOINT_URL\", \"API_KEY\").await.unwrap();\n\n    // No filter in this example\n    let mut sub = client.subscribe_new_beacon_blocks().await;\n\n    // Use the stream as an async iterator\n    while let Some(block) = sub.next().await {\n        handle_beacon_block(block);\n    }\n}\n```\n\n#### Raw beacon blocks\n\nReturns a stream of raw SSZ-encoded beacon blocks. Decoding is left to the caller to handle.\n\n**Example:**\n\n```rs\nuse fiber::Client;\nuse tokio_stream::StreamExt;\n\n#[tokio::main]\nasync fn main() {\n    // Client needs to be mutable\n    let mut client = Client::connect(\"ENDPOINT_URL\", \"API_KEY\").await.unwrap();\n\n    // No filter in this example\n    let mut sub = client.subscribe_new_raw_beacon_blocks().await;\n\n    // Use the stream as an async iterator\n    while let Some(raw_block) = sub.next().await {\n        handle_raw_beacon_block(raw_block);\n    }\n}\n```\n\n### Sending Transactions\n\n#### `send_transaction`\n\nAllows to broadcast transactions quickly to the Fiber network. It expects a [`alloy::consensus::TxEnvelope`](https://docs.rs/alloy/latest/alloy/consensus/enum.TxEnvelope.html) object, and returns the transaction hash and the timestamp of when the first Fiber node received it.\n\n```rs\nuse alloy::{\n    consensus::{TxEip1559, TxEnvelope},\n    primitives::{b256, Address, PrimitiveSignature, TxKind, U256},\n    hex,\n};\nuse fiber::Client;\n\n#[tokio::main]\nasync fn main() {\n    let mut client = Client::connect(\"ENDPOINT_URL\", \"API_KEY\").await.unwrap();\n\n    // Create a transaction and a signature for it\n    let tx = TxEip1559 {\n        chain_id: 1,\n            nonce: 0x42,\n            gas_limit: 44386,\n            to: TxKind::Call( Address::from_str(\"0x6069a6c32cf691f5982febae4faf8a6f3ab2f0f6\").unwrap()),\n            value: U256::from(0),\n            input:  hex::decode(\"a22cb4650000000000000000000000005eee75727d804a2b13038928d36f8b188945a57a0000000000000000000000000000000000000000000000000000000000000000\").unwrap().into(),\n            max_fee_per_gas: 0x4a817c800,\n            max_priority_fee_per_gas: 0x3b9aca00,\n            access_list: AccessList::default(),\n    };\n\n    let sig = PrimitiveSignature::from_scalars_and_parity(\n        b256!(\"840cfc572845f5786e702984c2a582528cad4b49b2a10b9db1be7fca90058565\"),\n        b256!(\"25e7109ceb98168d95b09b18bbf6b685130e0562f233877d492b94eee0c5b6d1\"),\n        false,\n    );\n\n    let signed_tx = TxEnvelope::from(tx.into_signed(sig));\n\n    let res = client.send_transaction(signed_tx).await.unwrap();\n\n    println!(\"{:?}\", res);\n}\n```\n\n#### `send_transaction_sequence`\n\nSends a sequence of transactions to the Fiber network at once.\n\n```rs\nuse alloy::{\n    consensus::{TxEip1559, TxEnvelope},\n    eips::eip2718::Decodable2718,\n    primitives::{b256, Address, PrimitiveSignature, TxKind, U256},\n    hex,\n};\nuse std::str::FromStr;\nuse fiber::Client;\n\n#[tokio::main]\nasync fn main() {\n    let mut client = Client::connect(\"ENDPOINT_URL\", \"API_KEY\").await.unwrap();\n\n    // Provide a transaction with signature as the first transaction of the sequence\nlet tx = TxEip1559 {\n        chain_id: 1,\n            nonce: 0x42,\n            gas_limit: 44386,\n            to: TxKind::Call( Address::from_str(\"0x6069a6c32cf691f5982febae4faf8a6f3ab2f0f6\").unwrap()),\n            value: U256::from(0),\n            input:  hex::decode(\"a22cb4650000000000000000000000005eee75727d804a2b13038928d36f8b188945a57a0000000000000000000000000000000000000000000000000000000000000000\").unwrap().into(),\n            max_fee_per_gas: 0x4a817c800,\n            max_priority_fee_per_gas: 0x3b9aca00,\n            access_list: AccessList::default(),\n    };\n\n    let sig = PrimitiveSignature::from_scalars_and_parity(\n        b256!(\"840cfc572845f5786e702984c2a582528cad4b49b2a10b9db1be7fca90058565\"),\n        b256!(\"25e7109ceb98168d95b09b18bbf6b685130e0562f233877d492b94eee0c5b6d1\"),\n        false,\n    );\n\n\n    let signed_tx_1 = TxEnvelope::from(tx.into_signed(sig));\n\n    // Then, provide a second signed transaction from wherever you want\n    let tx_bytes = hex::decode(\"02f872018307910d808507204d2cb1827d0094388c818ca8b9251b393131c08a736a67ccb19297880320d04823e2701c80c001a0cf024f4815304df2867a1a74e9d2707b6abda0337d2d54a4438d453f4160f190a07ac0e6b3bc9395b5b9c8b9e6d77204a236577a5b18467b9175c01de4faa208d9\").unwrap();\n    let signed_tx_2 = TxEnvelope::decode_2718(tx_bytes).unwrap();\n\n    let res = client.send_transaction_sequence(vec![signed_tx_1, signed_tx_2]).await.unwrap();\n\n    println!(\"{:?}\", res);\n}\n```\n\n#### `send_raw_transaction`\n\nSends a raw RLP encoded transaction to the Fiber network.\n\n```rs\nuse fiber::Client;\n\n#[tokio::main]\nasync fn main() {\n    let mut client = Client::connect(\"ENDPOINT_URL\", \"API_KEY\").await.unwrap();\n\n    let raw_tx = hex::decode(\"02f872018307910d808507204d2cb1827d0094388c818ca8b9251b393131c08a736a67ccb19297880320d04823e2701c80c001a0cf024f4815304df2867a1a74e9d2707b6abda0337d2d54a4438d453f4160f190a07ac0e6b3bc9395b5b9c8b9e6d77204a236577a5b18467b9175c01de4faa208d9\").unwrap();\n\n    let res = client.send_raw_transaction(raw_tx).await.unwrap();\n\n    println!(\"{:?}\", res);\n}\n```\n\n#### `send_raw_transaction_sequence`\n\nSends a sequence of RLP encoded transactions, for things like backrunning and other strategies\nwhere the explicitly stated order is important.\n\n```rs\nuse fiber::Client;\n\n#[tokio::main]\nasyn fn main() {\n    let mut client = Client::connect(\"ENDPOINT_URL\", \"API_KEY\").await.unwrap();\n\n    // Our transaction, RLP-encoded\n    let raw_tx_1 = hex::decode(\"02f872018307910d808507204d2cb1827d0094388c818ca8b9251b393131c08a736a67ccb19297880320d04823e2701c80c001a0cf024f4815304df2867a1a74e9d2707b6abda0337d2d54a4438d453f4160f190a07ac0e6b3bc9395b5b9c8b9e6d77204a236577a5b18467b9175c01de4faa208d9\").unwrap();\n\n    // The target transaction should be an RLP encoded transaction as well\n    let target_tx_2: Vec\u003cu8\u003e = vec![...]\n\n    let res = client.send_raw_transaction_sequence(vec![raw_tx_1, target_tx_2]).await.unwrap();\n\n    println!(\"{:?}\", res);\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchainbound%2Ffiber-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchainbound%2Ffiber-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchainbound%2Ffiber-rs/lists"}