Skip to content

Conversation

@Karrq
Copy link
Contributor

@Karrq Karrq commented Nov 13, 2025

This PR changes the backend to return the actual values for the /stats endpoint.
It does so by making a RPC call to the configured provider and reading the storage of the chain for the provider.

The PR also adds utilities to make runtime api calls (obsoleting and thus removing the RPC method for the payment stream's price per giga unit) and also for storage reads.

Another important change is that the backend now depends on the runtime, this was done to provide the appropriate type definitions and storage key encoding.
An alternative approach was using subxt, which allows for dynamic scale decoding, by fetching the runtime metadata "just in time" and processing it that way. Unfortunately, subxt still requires the backend to be "implicitly" dependant on the runtime (via the client's Config).
Nevertheless, the subxt approach is present in commit b66af47369f5660e6de19a099a188cf2a9f4bc7f if we decide to switch back to that instead.

@Karrq Karrq added B3-backendnoteworthy Changes should be mentioned in SH backend related release notes D3-trivial👶 PR contains trivial changes that do not require an audit not-breaking Does not need to be mentioned in breaking changes labels Nov 14, 2025
@santikaplan santikaplan requested review from HermanObst and removed request for ffarall November 27, 2025 13:04
Copy link
Contributor

@HermanObst HermanObst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome :).
Just some comments to discuss, mostly im curious to check that we have some integration test checking that the backend is getting correct info from the payment stream price runtime API

strictEqual(mspNodePeerId.toString(), userApi.shConsts.NODE_INFOS.msp1.expectedPeerId);
});

it("Should be able to retrieve current price per giga unit per tick", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is deleted because now the backend directly use runtime API?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont we still need to test that calling the runtime API from the backend is correctly working?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah the suite test/suites/backend/payment-streams.test.ts was the one supossed to test this but after your comments I checked it out and it wasn't testing much at all. Just refactored it to better test this functionality

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice! Thanks bro :)

Comment on lines +962 to +994
let total_bytes = stats
.capacity
.total_bytes
.parse::<BigDecimal>()
.expect("total_bytes to be a number");
let available_bytes = stats
.capacity
.available_bytes
.parse::<BigDecimal>()
.expect("available_bytes to be a number");
let used_bytes = stats
.capacity
.used_bytes
.parse::<BigDecimal>()
.expect("used_bytes to be a number");

assert!(
total_bytes.is_positive(),
"Total bytes should always be positive"
);
assert!(
available_bytes <= total_bytes,
"Available bytes should never be more than total bytes"
);
assert!(
used_bytes <= total_bytes,
"Used bytes should never be more than total bytes"
);
assert_eq!(
used_bytes + available_bytes,
total_bytes,
"Available + used bytes should always equal total bytes"
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also check the other stats fields?

  activeUsers: number;
  lastCapacityChange: string;
  valuePropsAmount: string;
  bucketsAmount: string;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't check much but I'll add some basic checks for them, sure. active_users the only thing that I would be able to test is that it's a number greater or equal to 0 but the type boundary already gives us that info so the compiler complains

Comment on lines 6 to 8
// if #[cfg(all(feature = "solochain", ...))] {
// compile_error!("Please select only 1 runtime");
// } else
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was commented on purpose?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm that is leftover work from Fran, I'll remove the comment

Comment on lines +30 to +44
pub last_capacity_change: String,
#[serde(rename = "valuePropsAmount")]
pub value_props_amount: u64,
pub value_props_amount: String,
#[serde(rename = "bucketsAmount")]
pub buckets_amount: u64,
pub buckets_amount: String,
}

#[derive(Debug, Serialize)]
pub struct Capacity {
#[serde(rename = "totalBytes")]
pub total_bytes: u64,
pub total_bytes: String,
#[serde(rename = "availableBytes")]
pub available_bytes: u64,
pub available_bytes: String,
#[serde(rename = "usedBytes")]
pub used_bytes: u64,
pub used_bytes: String,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why string and not unsigned?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We changed this as we were losing precision otherwise when sending these values through JSON, I believe

Comment on lines +154 to +160
pub async fn get_current_price_per_giga_unit_per_tick(&self) -> RpcResult<BigDecimal> {
debug!(target: "rpc::client::get_current_price_per_giga_unit_per_tick", "RPC call: get_current_price_per_giga_unit_per_tick");

self.call_no_params(methods::CURRENT_PRICE).await
self.call_runtime_api::<runtime_apis::GetCurrentPricePerGigaUnitPerTick>(())
.await
.map(|price| price.into())
}
Copy link
Contributor

@HermanObst HermanObst Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC this method is not being tested, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same answer as above

@TDemeco TDemeco requested a review from HermanObst November 28, 2025 14:03
Copy link
Contributor

@HermanObst HermanObst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B3-backendnoteworthy Changes should be mentioned in SH backend related release notes D3-trivial👶 PR contains trivial changes that do not require an audit not-breaking Does not need to be mentioned in breaking changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants