geyser: support data_slice for accounts (#150)
This commit is contained in:
parent
b73848a37a
commit
ef9c079f07
|
@ -5,6 +5,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: arduino/setup-protoc@v2
|
||||
# Setup .npmrc file to publish to npm
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
|
|
|
@ -34,6 +34,16 @@ jobs:
|
|||
profile: minimal
|
||||
components: rustfmt
|
||||
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
yellowstone-grpc/target/
|
||||
key: cargo-${{ hashFiles('rust-toolchain.toml') }}-${{ hashFiles('**/Cargo.lock') }}-0001
|
||||
|
||||
- name: Check Solana version
|
||||
run: |
|
||||
echo "CI_TAG=$(ci/getTag.sh)" >> "$GITHUB_ENV"
|
||||
|
@ -50,6 +60,7 @@ jobs:
|
|||
run: ./ci/create-tarball.sh
|
||||
|
||||
- name: Release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: ${{ env.BUILD_NAME }}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
# Source:
|
||||
# https://github.com/solana-labs/solana-accountsdb-plugin-postgres/blob/master/.github/workflows/test.yml
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
|
@ -33,12 +30,15 @@ jobs:
|
|||
profile: minimal
|
||||
components: rustfmt, clippy
|
||||
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE}}
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
yellowstone-grpc/target/
|
||||
key: cargo-${{ hashFiles('rust-toolchain.toml') }}-${{ hashFiles('**/Cargo.lock') }}-0001
|
||||
|
||||
- name: cargo tree
|
||||
run: |
|
||||
|
|
77
CHANGELOG.md
77
CHANGELOG.md
|
@ -14,71 +14,48 @@ The minor version will be incremented upon a breaking change and the patch versi
|
|||
|
||||
### Fixes
|
||||
|
||||
### Breaking
|
||||
|
||||
## 2023-06-29
|
||||
|
||||
- @triton-one/yellowstone-grpc:0.1.2
|
||||
- yellowstone-grpc-client-1.4.0+solana.1.16.1
|
||||
- yellowstone-grpc-geyser-1.0.0+solana.1.16.1
|
||||
- yellowstone-grpc-proto-1.4.0+solana.1.16.1
|
||||
|
||||
### Features
|
||||
|
||||
- geyser: support data_slice for accounts ([#150](https://github.com/rpcpool/yellowstone-grpc/pull/150)).
|
||||
- client: add TypeScript client ([#142](https://github.com/rpcpool/yellowstone-grpc/pull/142)).
|
||||
|
||||
### Fixes
|
||||
|
||||
- client: set max message size for decode ([#151](https://github.com/rpcpool/yellowstone-grpc/pull/151)).
|
||||
- geyser: remove duplicated account updates for confirmed/finalized ([#152](https://github.com/rpcpool/yellowstone-grpc/pull/152)).
|
||||
|
||||
### Breaking
|
||||
## 2023-06-16
|
||||
|
||||
## [yellowstone-grpc-proto-1.3.0+solana.1.16.1] - 2023-06-16
|
||||
- yellowstone-grpc-client-1.3.0+solana.1.16.1
|
||||
- yellowstone-grpc-geyser-0.8.2+solana.1.16.1
|
||||
- yellowstone-grpc-proto-1.3.0+solana.1.16.1
|
||||
|
||||
### Features
|
||||
|
||||
- geyser: update solana =1.16.1 ([#146](https://github.com/rpcpool/yellowstone-grpc/pull/146)).
|
||||
|
||||
### Fixes
|
||||
## 2023-06-15
|
||||
|
||||
### Breaking
|
||||
|
||||
## [yellowstone-grpc-client-1.3.0+solana.1.16.1] - 2023-06-16
|
||||
|
||||
### Features
|
||||
|
||||
- geyser: update solana =1.16.1 ([#146](https://github.com/rpcpool/yellowstone-grpc/pull/146)).
|
||||
|
||||
### Fixes
|
||||
|
||||
### Breaking
|
||||
|
||||
## [yellowstone-grpc-geyser-0.8.2+solana.1.16.1] - 2023-06-16
|
||||
|
||||
### Features
|
||||
|
||||
- geyser: update solana =1.16.1 ([#146](https://github.com/rpcpool/yellowstone-grpc/pull/146)).
|
||||
|
||||
### Fixes
|
||||
|
||||
### Breaking
|
||||
|
||||
## [yellowstone-grpc-proto-1.3.0+solana.1.15.2] - 2023-06-15
|
||||
|
||||
### Features
|
||||
|
||||
- geyser: Update `tonic`, `0.8.2` => `0.9.2` ([#145](https://github.com/rpcpool/yellowstone-grpc/pull/145)).
|
||||
|
||||
### Fixes
|
||||
|
||||
### Breaking
|
||||
|
||||
## [yellowstone-grpc-client-1.3.0+solana.1.15.2] - 2023-06-15
|
||||
- yellowstone-grpc-client-1.3.0+solana.1.14.18
|
||||
- yellowstone-grpc-client-1.3.0+solana.1.15.2
|
||||
- yellowstone-grpc-geyser-0.8.2+solana.1.14.18
|
||||
- yellowstone-grpc-geyser-0.8.2+solana.1.15.2
|
||||
- yellowstone-grpc-proto-1.3.0+solana.1.14.18
|
||||
- yellowstone-grpc-proto-1.3.0+solana.1.15.2
|
||||
|
||||
### Features
|
||||
|
||||
- geyser: Update `tonic`, `0.8.2` => `0.9.2` ([#145](https://github.com/rpcpool/yellowstone-grpc/pull/145)).
|
||||
- geyser: Add methods `health_check` and `health_watch` ([#145](https://github.com/rpcpool/yellowstone-grpc/pull/145)).
|
||||
|
||||
### Fixes
|
||||
|
||||
### Breaking
|
||||
|
||||
## [yellowstone-grpc-geyser-0.8.2+solana.1.15.2] - 2023-06-15
|
||||
|
||||
### Features
|
||||
|
||||
- geyser: Add prometheus metric `message_queue_size` ([#145](https://github.com/rpcpool/yellowstone-grpc/pull/145)).
|
||||
- geyser: Update `tonic`, `0.8.2` => `0.9.2` ([#145](https://github.com/rpcpool/yellowstone-grpc/pull/145)).
|
||||
- geyser: Send task per connection ([#145](https://github.com/rpcpool/yellowstone-grpc/pull/145)).
|
||||
- geyser: Send processed immediately without `Slot` message ([#145](https://github.com/rpcpool/yellowstone-grpc/pull/145)).
|
||||
|
||||
### Fixes
|
||||
|
||||
### Breaking
|
||||
|
|
|
@ -4125,7 +4125,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yellowstone-grpc-client"
|
||||
version = "1.3.0+solana.1.16.1"
|
||||
version = "1.4.0+solana.1.16.1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
|
@ -4139,7 +4139,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yellowstone-grpc-client-simple"
|
||||
version = "1.3.0+solana.1.16.1"
|
||||
version = "1.4.0+solana.1.16.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"backoff",
|
||||
|
@ -4157,7 +4157,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yellowstone-grpc-geyser"
|
||||
version = "0.8.2+solana.1.16.1"
|
||||
version = "1.0.0+solana.1.16.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.21.2",
|
||||
|
@ -4187,7 +4187,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yellowstone-grpc-proto"
|
||||
version = "1.3.0+solana.1.16.1"
|
||||
version = "1.4.0+solana.1.16.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"prost",
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"examples/rust", # 1.3.0+solana.1.16.1
|
||||
"yellowstone-grpc-client", # 1.3.0+solana.1.16.1
|
||||
"yellowstone-grpc-geyser", # 0.8.2+solana.1.16.1
|
||||
"yellowstone-grpc-proto", # 1.3.0+solana.1.16.1
|
||||
"examples/rust", # 1.4.0+solana.1.16.1
|
||||
"yellowstone-grpc-client", # 1.4.0+solana.1.16.1
|
||||
"yellowstone-grpc-geyser", # 1.0.0+solana.1.16.1
|
||||
"yellowstone-grpc-proto", # 1.4.0+solana.1.16.1
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yellowstone-grpc-client-simple"
|
||||
version = "1.3.0+solana.1.16.1"
|
||||
version = "1.4.0+solana.1.16.1"
|
||||
authors = ["Triton One"]
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
|
|
@ -11,10 +11,11 @@ use {
|
|||
subscribe_request_filter_accounts_filter::Filter as AccountsFilterDataOneof,
|
||||
subscribe_request_filter_accounts_filter_memcmp::Data as AccountsFilterMemcmpOneof,
|
||||
subscribe_update::UpdateOneof, CommitmentLevel, SubscribeRequest,
|
||||
SubscribeRequestFilterAccounts, SubscribeRequestFilterAccountsFilter,
|
||||
SubscribeRequestFilterAccountsFilterMemcmp, SubscribeRequestFilterBlocks,
|
||||
SubscribeRequestFilterBlocksMeta, SubscribeRequestFilterSlots,
|
||||
SubscribeRequestFilterTransactions, SubscribeUpdateAccount,
|
||||
SubscribeRequestAccountsDataSlice, SubscribeRequestFilterAccounts,
|
||||
SubscribeRequestFilterAccountsFilter, SubscribeRequestFilterAccountsFilterMemcmp,
|
||||
SubscribeRequestFilterBlocks, SubscribeRequestFilterBlocksMeta,
|
||||
SubscribeRequestFilterSlots, SubscribeRequestFilterTransactions,
|
||||
SubscribeUpdateAccount,
|
||||
},
|
||||
tonic::service::Interceptor,
|
||||
},
|
||||
|
@ -109,6 +110,10 @@ struct ActionSubscribe {
|
|||
#[clap(long)]
|
||||
accounts_datasize: Option<u64>,
|
||||
|
||||
/// Receive only part of updated data account, format: `offset,size`
|
||||
#[clap(long)]
|
||||
accounts_data_slice: Vec<String>,
|
||||
|
||||
/// Subscribe on slots updates
|
||||
#[clap(long)]
|
||||
slots: bool,
|
||||
|
@ -229,6 +234,20 @@ impl Action {
|
|||
blocks_meta.insert("client".to_owned(), SubscribeRequestFilterBlocksMeta {});
|
||||
}
|
||||
|
||||
let mut accounts_data_slice = Vec::new();
|
||||
for data_slice in args.accounts_data_slice.iter() {
|
||||
match data_slice.split_once(',') {
|
||||
Some((offset, length)) => match (offset.parse(), length.parse()) {
|
||||
(Ok(offset), Ok(length)) => {
|
||||
accounts_data_slice
|
||||
.push(SubscribeRequestAccountsDataSlice { offset, length });
|
||||
}
|
||||
_ => anyhow::bail!("invalid data_slice"),
|
||||
},
|
||||
_ => anyhow::bail!("invalid data_slice"),
|
||||
}
|
||||
}
|
||||
|
||||
Some((
|
||||
SubscribeRequest {
|
||||
slots,
|
||||
|
@ -237,6 +256,7 @@ impl Action {
|
|||
blocks,
|
||||
blocks_meta,
|
||||
commitment: commitment.map(|x| x as i32),
|
||||
accounts_data_slice,
|
||||
},
|
||||
args.resub.unwrap_or(0),
|
||||
))
|
||||
|
@ -421,6 +441,7 @@ async fn geyser_subscribe(
|
|||
blocks: HashMap::default(),
|
||||
blocks_meta: HashMap::default(),
|
||||
commitment: None,
|
||||
accounts_data_slice: Vec::default(),
|
||||
})
|
||||
.await
|
||||
.map_err(GeyserGrpcClientError::SubscribeSendError)?;
|
||||
|
|
|
@ -90,6 +90,7 @@ async function subscribeCommand(client, args) {
|
|||
transactions: {},
|
||||
blocks: {},
|
||||
blocksMeta: {},
|
||||
accountsDataSlice: [],
|
||||
};
|
||||
if (args.accounts) {
|
||||
const filters: SubscribeRequestFilterAccountsFilter[] = [];
|
||||
|
@ -142,6 +143,21 @@ async function subscribeCommand(client, args) {
|
|||
request.blocksMeta.client = {};
|
||||
}
|
||||
|
||||
if (args.accounts.dataslice) {
|
||||
for (let filter in args.accounts.dataslice) {
|
||||
const filterSpec = filter.split(",", 1);
|
||||
if (filterSpec.length != 2) {
|
||||
throw new Error("invalid data slice");
|
||||
}
|
||||
|
||||
const [offset, length] = filterSpec;
|
||||
request.accountsDataSlice.push({
|
||||
offset: parseInt(offset, 10),
|
||||
length: parseInt(length, 10),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Send subscribe request
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
stream.write(request, (err) => {
|
||||
|
@ -222,6 +238,12 @@ function parseCommandLineArgs() {
|
|||
describe: "filter by data size",
|
||||
type: "number",
|
||||
},
|
||||
"accounts-dataslice": {
|
||||
default: [],
|
||||
describe:
|
||||
"receive only part of updated data account, format: `offset,size`",
|
||||
type: "string",
|
||||
},
|
||||
slots: {
|
||||
default: false,
|
||||
describe: "subscribe on slots updates",
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
node_modules
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@triton-one/yellowstone-grpc",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"license": "Apache-2.0",
|
||||
"author": "Triton One",
|
||||
"description": "Yellowstone gRPC Geyser Node.js Client",
|
||||
|
@ -31,5 +31,6 @@
|
|||
"prettier": "2.8.3",
|
||||
"ts-proto": "^1.139.0",
|
||||
"typescript": "^4.9.5"
|
||||
}
|
||||
},
|
||||
"files": ["dist"]
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
GetLatestBlockhashResponse,
|
||||
GeyserClient,
|
||||
IsBlockhashValidResponse,
|
||||
SubscribeRequestAccountsDataSlice,
|
||||
SubscribeRequestFilterAccounts,
|
||||
SubscribeRequestFilterBlocks,
|
||||
SubscribeRequestFilterBlocksMeta,
|
||||
|
@ -81,7 +82,8 @@ export default class Client {
|
|||
transactions: { [key: string]: SubscribeRequestFilterTransactions },
|
||||
blocks: { [key: string]: SubscribeRequestFilterBlocks },
|
||||
blocksMeta: { [key: string]: SubscribeRequestFilterBlocksMeta },
|
||||
commitment?: CommitmentLevel | undefined
|
||||
commitment: CommitmentLevel | undefined,
|
||||
accountsDataSlice: SubscribeRequestAccountsDataSlice[]
|
||||
) {
|
||||
const stream = await this._client.subscribe();
|
||||
|
||||
|
@ -94,6 +96,7 @@ export default class Client {
|
|||
blocks,
|
||||
blocksMeta,
|
||||
commitment,
|
||||
accountsDataSlice,
|
||||
},
|
||||
(err) => {
|
||||
if (err === null || err === undefined) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yellowstone-grpc-client"
|
||||
version = "1.3.0+solana.1.16.1"
|
||||
version = "1.4.0+solana.1.16.1"
|
||||
authors = ["Triton One"]
|
||||
edition = "2021"
|
||||
description = "Yellowstone gRPC Geyser Simple Client"
|
||||
|
@ -16,7 +16,7 @@ http = "0.2.8"
|
|||
thiserror = "1.0"
|
||||
tonic = { version = "0.9.2", features = ["gzip", "tls", "tls-roots"] }
|
||||
tonic-health = "0.9.2"
|
||||
yellowstone-grpc-proto = { path = "../yellowstone-grpc-proto", version = "1.3.0+solana.1.16.1" }
|
||||
yellowstone-grpc-proto = { path = "../yellowstone-grpc-proto", version = "1.4.0+solana.1.16.1" }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.21.2", features = ["macros"] }
|
||||
|
|
|
@ -20,9 +20,9 @@ use {
|
|||
GetBlockHeightResponse, GetLatestBlockhashRequest, GetLatestBlockhashResponse,
|
||||
GetSlotRequest, GetSlotResponse, GetVersionRequest, GetVersionResponse,
|
||||
IsBlockhashValidRequest, IsBlockhashValidResponse, PingRequest, PongResponse,
|
||||
SubscribeRequest, SubscribeRequestFilterAccounts, SubscribeRequestFilterBlocks,
|
||||
SubscribeRequestFilterBlocksMeta, SubscribeRequestFilterSlots,
|
||||
SubscribeRequestFilterTransactions, SubscribeUpdate,
|
||||
SubscribeRequest, SubscribeRequestAccountsDataSlice, SubscribeRequestFilterAccounts,
|
||||
SubscribeRequestFilterBlocks, SubscribeRequestFilterBlocksMeta,
|
||||
SubscribeRequestFilterSlots, SubscribeRequestFilterTransactions, SubscribeUpdate,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -133,6 +133,7 @@ impl<F: Interceptor> GeyserGrpcClient<F> {
|
|||
Ok((subscribe_tx, response.into_inner()))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn subscribe_once(
|
||||
&mut self,
|
||||
slots: HashMap<String, SubscribeRequestFilterSlots>,
|
||||
|
@ -141,6 +142,7 @@ impl<F: Interceptor> GeyserGrpcClient<F> {
|
|||
blocks: HashMap<String, SubscribeRequestFilterBlocks>,
|
||||
blocks_meta: HashMap<String, SubscribeRequestFilterBlocksMeta>,
|
||||
commitment: Option<CommitmentLevel>,
|
||||
accounts_data_slice: Vec<SubscribeRequestAccountsDataSlice>,
|
||||
) -> GeyserGrpcClientResult<impl Stream<Item = Result<SubscribeUpdate, Status>>> {
|
||||
let (mut subscribe_tx, response) = self.subscribe().await?;
|
||||
subscribe_tx
|
||||
|
@ -151,6 +153,7 @@ impl<F: Interceptor> GeyserGrpcClient<F> {
|
|||
blocks,
|
||||
blocks_meta,
|
||||
commitment: commitment.map(|value| value as i32),
|
||||
accounts_data_slice,
|
||||
})
|
||||
.await?;
|
||||
Ok(response)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yellowstone-grpc-geyser"
|
||||
version = "0.8.2+solana.1.16.1"
|
||||
version = "1.0.0+solana.1.16.1"
|
||||
authors = ["Triton One"]
|
||||
edition = "2021"
|
||||
description = "Yellowstone gRPC Geyser Plugin"
|
||||
|
|
|
@ -11,10 +11,10 @@ use {
|
|||
proto::{
|
||||
subscribe_request_filter_accounts_filter::Filter as AccountsFilterDataOneof,
|
||||
subscribe_request_filter_accounts_filter_memcmp::Data as AccountsFilterMemcmpOneof,
|
||||
CommitmentLevel, SubscribeRequest, SubscribeRequestFilterAccounts,
|
||||
SubscribeRequestFilterAccountsFilter, SubscribeRequestFilterBlocks,
|
||||
SubscribeRequestFilterBlocksMeta, SubscribeRequestFilterSlots,
|
||||
SubscribeRequestFilterTransactions, SubscribeUpdate,
|
||||
CommitmentLevel, SubscribeRequest, SubscribeRequestAccountsDataSlice,
|
||||
SubscribeRequestFilterAccounts, SubscribeRequestFilterAccountsFilter,
|
||||
SubscribeRequestFilterBlocks, SubscribeRequestFilterBlocksMeta,
|
||||
SubscribeRequestFilterSlots, SubscribeRequestFilterTransactions, SubscribeUpdate,
|
||||
},
|
||||
},
|
||||
base64::{engine::general_purpose::STANDARD as base64_engine, Engine},
|
||||
|
@ -34,6 +34,7 @@ pub struct Filter {
|
|||
blocks: FilterBlocks,
|
||||
blocks_meta: FilterBlocksMeta,
|
||||
commitment: CommitmentLevel,
|
||||
accounts_data_slice: Vec<FilterAccountsDataSlice>,
|
||||
}
|
||||
|
||||
impl Filter {
|
||||
|
@ -45,6 +46,7 @@ impl Filter {
|
|||
blocks: FilterBlocks::new(&config.blocks, &limit.blocks)?,
|
||||
blocks_meta: FilterBlocksMeta::new(&config.blocks_meta, &limit.blocks_meta)?,
|
||||
commitment: Self::decode_commitment(config.commitment)?,
|
||||
accounts_data_slice: FilterAccountsDataSlice::create(&config.accounts_data_slice)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -91,7 +93,7 @@ impl Filter {
|
|||
} else {
|
||||
Some(SubscribeUpdate {
|
||||
filters,
|
||||
update_oneof: Some(message.into()),
|
||||
update_oneof: Some(message.to_proto(&self.accounts_data_slice)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -538,6 +540,43 @@ impl FilterBlocksMeta {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FilterAccountsDataSlice {
|
||||
pub start: usize,
|
||||
pub end: usize,
|
||||
pub length: usize,
|
||||
}
|
||||
|
||||
impl From<&SubscribeRequestAccountsDataSlice> for FilterAccountsDataSlice {
|
||||
fn from(data_slice: &SubscribeRequestAccountsDataSlice) -> Self {
|
||||
Self {
|
||||
start: data_slice.offset as usize,
|
||||
end: (data_slice.offset + data_slice.length) as usize,
|
||||
length: data_slice.length as usize,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FilterAccountsDataSlice {
|
||||
pub fn create(slices: &[SubscribeRequestAccountsDataSlice]) -> anyhow::Result<Vec<Self>> {
|
||||
let slices = slices.iter().map(Into::into).collect::<Vec<Self>>();
|
||||
|
||||
for (i, slice_a) in slices.iter().enumerate() {
|
||||
// check order
|
||||
for slice_b in slices[i + 1..].iter() {
|
||||
anyhow::ensure!(slice_a.start <= slice_b.start, "data slices out of order");
|
||||
}
|
||||
|
||||
// check overlap
|
||||
for slice_b in slices[0..i].iter() {
|
||||
anyhow::ensure!(slice_a.start >= slice_b.end, "data slices overlap");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(slices)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use {
|
||||
|
@ -614,6 +653,7 @@ mod tests {
|
|||
blocks: HashMap::new(),
|
||||
blocks_meta: HashMap::new(),
|
||||
commitment: None,
|
||||
accounts_data_slice: Vec::new(),
|
||||
};
|
||||
let limit = ConfigGrpcFilters::default();
|
||||
let filter = Filter::new(&config, &limit);
|
||||
|
@ -640,6 +680,7 @@ mod tests {
|
|||
blocks: HashMap::new(),
|
||||
blocks_meta: HashMap::new(),
|
||||
commitment: None,
|
||||
accounts_data_slice: Vec::new(),
|
||||
};
|
||||
let mut limit = ConfigGrpcFilters::default();
|
||||
limit.accounts.any = false;
|
||||
|
@ -671,6 +712,7 @@ mod tests {
|
|||
blocks: HashMap::new(),
|
||||
blocks_meta: HashMap::new(),
|
||||
commitment: None,
|
||||
accounts_data_slice: Vec::new(),
|
||||
};
|
||||
let mut limit = ConfigGrpcFilters::default();
|
||||
limit.transactions.any = false;
|
||||
|
@ -701,6 +743,7 @@ mod tests {
|
|||
blocks: HashMap::new(),
|
||||
blocks_meta: HashMap::new(),
|
||||
commitment: None,
|
||||
accounts_data_slice: Vec::new(),
|
||||
};
|
||||
let mut limit = ConfigGrpcFilters::default();
|
||||
limit.transactions.any = false;
|
||||
|
@ -737,6 +780,7 @@ mod tests {
|
|||
blocks: HashMap::new(),
|
||||
blocks_meta: HashMap::new(),
|
||||
commitment: None,
|
||||
accounts_data_slice: Vec::new(),
|
||||
};
|
||||
let limit = ConfigGrpcFilters::default();
|
||||
let filter = Filter::new(&config, &limit).unwrap();
|
||||
|
@ -776,6 +820,7 @@ mod tests {
|
|||
blocks: HashMap::new(),
|
||||
blocks_meta: HashMap::new(),
|
||||
commitment: None,
|
||||
accounts_data_slice: Vec::new(),
|
||||
};
|
||||
let limit = ConfigGrpcFilters::default();
|
||||
let filter = Filter::new(&config, &limit).unwrap();
|
||||
|
@ -815,6 +860,7 @@ mod tests {
|
|||
blocks: HashMap::new(),
|
||||
blocks_meta: HashMap::new(),
|
||||
commitment: None,
|
||||
accounts_data_slice: Vec::new(),
|
||||
};
|
||||
let limit = ConfigGrpcFilters::default();
|
||||
let filter = Filter::new(&config, &limit).unwrap();
|
||||
|
@ -860,6 +906,7 @@ mod tests {
|
|||
blocks: HashMap::new(),
|
||||
blocks_meta: HashMap::new(),
|
||||
commitment: None,
|
||||
accounts_data_slice: Vec::new(),
|
||||
};
|
||||
let limit = ConfigGrpcFilters::default();
|
||||
let filter = Filter::new(&config, &limit).unwrap();
|
||||
|
@ -907,6 +954,7 @@ mod tests {
|
|||
blocks: HashMap::new(),
|
||||
blocks_meta: HashMap::new(),
|
||||
commitment: None,
|
||||
accounts_data_slice: Vec::new(),
|
||||
};
|
||||
let limit = ConfigGrpcFilters::default();
|
||||
let filter = Filter::new(&config, &limit).unwrap();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use {
|
||||
crate::{
|
||||
config::ConfigGrpc,
|
||||
filters::Filter,
|
||||
filters::{Filter, FilterAccountsDataSlice},
|
||||
prom::{CONNECTIONS_TOTAL, INVALID_FULL_BLOCKS, MESSAGE_QUEUE_SIZE},
|
||||
proto::{
|
||||
self,
|
||||
|
@ -213,33 +213,59 @@ pub enum Message {
|
|||
BlockMeta(MessageBlockMeta),
|
||||
}
|
||||
|
||||
impl From<&Message> for UpdateOneof {
|
||||
fn from(message: &Message) -> Self {
|
||||
match message {
|
||||
Message::Slot(message) => UpdateOneof::Slot(SubscribeUpdateSlot {
|
||||
impl Message {
|
||||
pub const fn get_slot(&self) -> u64 {
|
||||
match self {
|
||||
Self::Slot(msg) => msg.slot,
|
||||
Self::Account(msg) => msg.slot,
|
||||
Self::Transaction(msg) => msg.slot,
|
||||
Self::Block(msg) => msg.slot,
|
||||
Self::BlockMeta(msg) => msg.slot,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_proto(&self, accounts_data_slice: &[FilterAccountsDataSlice]) -> UpdateOneof {
|
||||
match self {
|
||||
Self::Slot(message) => UpdateOneof::Slot(SubscribeUpdateSlot {
|
||||
slot: message.slot,
|
||||
parent: message.parent,
|
||||
status: message.status as i32,
|
||||
}),
|
||||
Message::Account(message) => UpdateOneof::Account(SubscribeUpdateAccount {
|
||||
Self::Account(message) => {
|
||||
let data = if accounts_data_slice.is_empty() {
|
||||
message.account.data.clone()
|
||||
} else {
|
||||
let mut data =
|
||||
Vec::with_capacity(accounts_data_slice.iter().map(|ds| ds.length).sum());
|
||||
for data_slice in accounts_data_slice {
|
||||
if message.account.data.len() >= data_slice.end {
|
||||
data.extend_from_slice(
|
||||
&message.account.data[data_slice.start..data_slice.end],
|
||||
);
|
||||
}
|
||||
}
|
||||
data
|
||||
};
|
||||
UpdateOneof::Account(SubscribeUpdateAccount {
|
||||
account: Some(SubscribeUpdateAccountInfo {
|
||||
pubkey: message.account.pubkey.as_ref().into(),
|
||||
lamports: message.account.lamports,
|
||||
owner: message.account.owner.as_ref().into(),
|
||||
executable: message.account.executable,
|
||||
rent_epoch: message.account.rent_epoch,
|
||||
data: message.account.data.clone(),
|
||||
data,
|
||||
write_version: message.account.write_version,
|
||||
txn_signature: message.account.txn_signature.map(|s| s.as_ref().into()),
|
||||
}),
|
||||
slot: message.slot,
|
||||
is_startup: message.is_startup,
|
||||
}),
|
||||
Message::Transaction(message) => UpdateOneof::Transaction(SubscribeUpdateTransaction {
|
||||
})
|
||||
}
|
||||
Self::Transaction(message) => UpdateOneof::Transaction(SubscribeUpdateTransaction {
|
||||
transaction: Some((&message.transaction).into()),
|
||||
slot: message.slot,
|
||||
}),
|
||||
Message::Block(message) => UpdateOneof::Block(SubscribeUpdateBlock {
|
||||
Self::Block(message) => UpdateOneof::Block(SubscribeUpdateBlock {
|
||||
slot: message.slot,
|
||||
blockhash: message.blockhash.clone(),
|
||||
rewards: Some(proto::convert::create_rewards(message.rewards.as_slice())),
|
||||
|
@ -251,7 +277,7 @@ impl From<&Message> for UpdateOneof {
|
|||
parent_slot: message.parent_slot,
|
||||
parent_blockhash: message.parent_blockhash.clone(),
|
||||
}),
|
||||
Message::BlockMeta(message) => UpdateOneof::BlockMeta(SubscribeUpdateBlockMeta {
|
||||
Self::BlockMeta(message) => UpdateOneof::BlockMeta(SubscribeUpdateBlockMeta {
|
||||
slot: message.slot,
|
||||
blockhash: message.blockhash.clone(),
|
||||
rewards: Some(proto::convert::create_rewards(message.rewards.as_slice())),
|
||||
|
@ -267,18 +293,6 @@ impl From<&Message> for UpdateOneof {
|
|||
}
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub const fn get_slot(&self) -> u64 {
|
||||
match self {
|
||||
Self::Slot(msg) => msg.slot,
|
||||
Self::Account(msg) => msg.slot,
|
||||
Self::Transaction(msg) => msg.slot,
|
||||
Self::Block(msg) => msg.slot,
|
||||
Self::BlockMeta(msg) => msg.slot,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BlockhashStatus {
|
||||
slot: u64,
|
||||
|
@ -752,6 +766,7 @@ impl Geyser for GrpcService {
|
|||
blocks: HashMap::new(),
|
||||
blocks_meta: HashMap::new(),
|
||||
commitment: None,
|
||||
accounts_data_slice: Vec::new(),
|
||||
},
|
||||
&self.config.filters,
|
||||
)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yellowstone-grpc-proto"
|
||||
version = "1.3.0+solana.1.16.1"
|
||||
version = "1.4.0+solana.1.16.1"
|
||||
authors = ["Triton One"]
|
||||
edition = "2021"
|
||||
description = "Yellowstone gRPC Geyser Protobuf Definitions"
|
||||
|
|
|
@ -29,6 +29,7 @@ message SubscribeRequest {
|
|||
map<string, SubscribeRequestFilterBlocks> blocks = 4;
|
||||
map<string, SubscribeRequestFilterBlocksMeta> blocks_meta = 5;
|
||||
optional CommitmentLevel commitment = 6;
|
||||
repeated SubscribeRequestAccountsDataSlice accounts_data_slice = 7;
|
||||
}
|
||||
|
||||
message SubscribeRequestFilterAccounts {
|
||||
|
@ -68,6 +69,11 @@ message SubscribeRequestFilterBlocks {}
|
|||
|
||||
message SubscribeRequestFilterBlocksMeta {}
|
||||
|
||||
message SubscribeRequestAccountsDataSlice {
|
||||
uint64 offset = 1;
|
||||
uint64 length = 2;
|
||||
}
|
||||
|
||||
message SubscribeUpdate {
|
||||
repeated string filters = 1;
|
||||
oneof update_oneof {
|
||||
|
|
Loading…
Reference in New Issue