|
| 1 | +--- |
| 2 | +next: |
| 3 | + text: "Prompt Scavenger" |
| 4 | + link: "/developers/prompt-scavenger" |
| 5 | +--- |
| 6 | + |
| 7 | +# Rust client library tutorial {#rust-client-library} |
| 8 | + |
| 9 | +This section tutorial will guide you through using the most common RPC endpoints with [Lumina](https://github.com/eigerco/lumina/tree/main/rpc)'s rust client library. |
| 10 | + |
| 11 | +You will need to |
| 12 | +[setup dependencies, install, and run celestia-node](./node-tutorial.md#setting-up-dependencies) |
| 13 | +if you have not already. |
| 14 | + |
| 15 | +## Project setup |
| 16 | + |
| 17 | +To start, add `celestia_rpc` and `celestia_types` as a dependency to your project: |
| 18 | + |
| 19 | +```bash |
| 20 | +cargo add celestia_rpc celestia_types |
| 21 | +``` |
| 22 | + |
| 23 | +To use the following methods, you will need the node URL and your auth token. To get your auth token, see this [guide](./node-tutorial.md#auth-token). To run your node without an auth token, you can use the `--rpc.skip-auth` flag when starting your node. This allows you to pass an empty string as your auth token. |
| 24 | + |
| 25 | +The default URL is `http://localhost:26658`. If you would like to use subscription methods, such as `SubscribeHeaders` below, you must use the `ws` protocol in place of `http`: `ws://localhost:26658`. |
| 26 | + |
| 27 | +## Submitting and retrieving blobs |
| 28 | + |
| 29 | +The [blob.Submit](https://node-rpc-docs.celestia.org/?version=v0.11.0#blob.Submit) method takes an array of blobs and a gas price, returning the height the blob was successfully posted at. |
| 30 | + |
| 31 | +- The namespace can be generated with `Namespace::new_v0`. |
| 32 | +- The blobs can be generated with `Blob::new`. |
| 33 | +- You can set `GasPrice::default()` as the gas price to have celestia-node automatically determine an appropriate gas price. |
| 34 | + |
| 35 | +The [blob.GetAll](https://node-rpc-docs.celestia.org/?version=v0.11.0#blob.GetAll) method takes a height and array of namespaces, returning the array of blobs found in the given namespaces. |
| 36 | + |
| 37 | +```rust |
| 38 | +use celestia_rpc::{BlobClient, Client, HeaderClient, ShareClient}; |
| 39 | +use celestia_types::blob::GasPrice; |
| 40 | +use celestia_types::{nmt::Namespace, Blob, ExtendedDataSquare}; |
| 41 | + |
| 42 | +async fn submit_blob(url: &str, token: &str) { |
| 43 | + let client = Client::new(url, Some(token)) |
| 44 | + .await |
| 45 | + .expect("Failed creating rpc client"); |
| 46 | + |
| 47 | + // let's use the DEADBEEF namespace |
| 48 | + let namespace = Namespace::new_v0(&[0xDE, 0xAD, 0xBE, 0xEF]).expect("Invalid namespace"); |
| 49 | + |
| 50 | + // create a blob |
| 51 | + let blob = Blob::new(namespace, b"Hello, World!".to_vec()).expect("Blob creation failed"); |
| 52 | + |
| 53 | + // submit the blob to the network |
| 54 | + let height = client |
| 55 | + .blob_submit(&[blob.clone()], GasPrice::default()) |
| 56 | + .await |
| 57 | + .expect("Failed submitting blob"); |
| 58 | + |
| 59 | + println!("Blob was included at height {}", height); |
| 60 | + |
| 61 | + // fetch the blob back from the network |
| 62 | + let retrieved_blobs = client |
| 63 | + .blob_get_all(height, &[namespace]) |
| 64 | + .await |
| 65 | + .expect("Failed to retrieve blobs"); |
| 66 | + |
| 67 | + assert_eq!(retrieved_blobs.len(), 1); |
| 68 | + assert_eq!(retrieved_blobs[0].data, b"Hello, World!"); |
| 69 | + assert_eq!(retrieved_blobs[0].commitment, blob.commitment); |
| 70 | +} |
| 71 | +``` |
| 72 | + |
| 73 | +## Subscribing to new headers |
| 74 | + |
| 75 | +You can subscribe to new headers using the [header.Subscribe](https://node-rpc-docs.celestia.org/?version=v0.11.0#header.Subscribe) method. This method returns a `Subscription` that will receive new headers as they are produced. In this example, we will fetch all blobs at the height of the new header in the `0xDEADBEEF` namespace. |
| 76 | + |
| 77 | +```rust |
| 78 | +async fn subscribe_headers(url: &str, token: &str) { |
| 79 | + let client = Client::new(url, Some(token)) |
| 80 | + .await |
| 81 | + .expect("Failed creating rpc client"); |
| 82 | + |
| 83 | + let mut header_sub = client |
| 84 | + .header_subscribe() |
| 85 | + .await |
| 86 | + .expect("Failed subscribing to incoming headers"); |
| 87 | + |
| 88 | + // setup the namespace we will filter blobs by |
| 89 | + let namespace = Namespace::new_v0(&[0xDE, 0xAD, 0xBE, 0xEF]).expect("Invalid namespace"); |
| 90 | + |
| 91 | + while let Some(extended_header) = header_sub.next().await { |
| 92 | + match extended_header { |
| 93 | + Ok(header) => { |
| 94 | + let height = header.header.height.value(); |
| 95 | + // fetch all blobs at the height of the new header |
| 96 | + |
| 97 | + let blobs = match client.blob_get_all(height, &[namespace]).await { |
| 98 | + Ok(blobs) => blobs, |
| 99 | + Err(e) => { |
| 100 | + eprintln!("Error fetching blobs: {}", e); |
| 101 | + continue; |
| 102 | + } |
| 103 | + }; |
| 104 | + |
| 105 | + println!( |
| 106 | + "Found {} blobs at height {} in the 0xDEADBEEF namespace", |
| 107 | + blobs.len(), |
| 108 | + height |
| 109 | + ); |
| 110 | + } |
| 111 | + Err(e) => { |
| 112 | + eprintln!("Error receiving header: {}", e); |
| 113 | + } |
| 114 | + } |
| 115 | + } |
| 116 | +} |
| 117 | + |
| 118 | +``` |
| 119 | + |
| 120 | +## Fetching an Extended Data Square (EDS) |
| 121 | + |
| 122 | +You can fetch an [Extended Data Square (EDS)](https://celestiaorg.github.io/celestia-app/specs/data_structures.html#erasure-coding) using the [share.GetEDS](https://node-rpc-docs.celestia.org/?version=v0.11.0#share.GetEDS) method. This method takes a header and returns the EDS at the given height. |
| 123 | + |
| 124 | +```rust |
| 125 | +async fn get_eds(url: &str, token: &str) -> ExtendedDataSquare { |
| 126 | + let client = Client::new(url, Some(token)) |
| 127 | + .await |
| 128 | + .expect("Failed creating rpc client"); |
| 129 | + |
| 130 | + // first get the header of the block you want to fetch the EDS from |
| 131 | + let latest_header = client |
| 132 | + .header_local_head() |
| 133 | + .await |
| 134 | + .expect("Failed fetching header"); |
| 135 | + |
| 136 | + client |
| 137 | + .share_get_eds(&latest_header) |
| 138 | + .await |
| 139 | + .expect("Failed to get EDS from latest header") |
| 140 | +} |
| 141 | +``` |
| 142 | + |
| 143 | +## API documentation |
| 144 | + |
| 145 | +To see the full list of available methods, see the [API documentation](https://node-rpc-docs.celestia.org/?version=v0.11.0). |
0 commit comments