Skip to content

Commit 47cb074

Browse files
authored
Fix/add option decode for all (#4)
* add decode_option for all classes * bump ver * ruff * add tests for new option<subnetinfo> decoding * fix readme * bump python req in test extra
1 parent 7c1aa79 commit 47cb074

13 files changed

+164
-73
lines changed

Cargo.lock

+11-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ name = "bt_decode"
1313
crate-type = ["cdylib"]
1414

1515
[dependencies.pyo3]
16-
version = "0.22.2"
16+
version = "0.22.3"
1717
features = ["extension-module"]
1818

1919
[dependencies.custom_derive]

README.md

+14-14
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ hex_bytes_result = sub.query_runtime_api(
1717
method="get_delegates",
1818
params=[ ]
1919
)
20-
# Decode scale-encoded DelegateInfo
20+
# Decode scale-encoded Vec<DelegateInfo>
2121
delegates_info: List[DelegateInfo] = DelegateInfo.decode_vec(
2222
bytes.fromhex(
2323
hex_bytes_result
@@ -38,7 +38,7 @@ hex_bytes_result = sub.query_runtime_api(
3838
method="get_delegated",
3939
params=[list( validator_key.public_key )]
4040
)
41-
# Decode scale-encoded (DelegateInfo, take)
41+
# Decode scale-encoded Vec<(DelegateInfo, take)>
4242
delegated_info: List[Tuple[DelegateInfo, int]] = DelegateInfo.decode_delegated(
4343
bytes.fromhex(
4444
hex_bytes_result
@@ -82,8 +82,8 @@ hex_bytes_result = sub.query_runtime_api(
8282
method="get_neurons",
8383
params=[NETUID]
8484
)
85-
# Decode scale-encoded NeuronInfo
86-
neurons: List[NeuronInfo] = NeuronInfo.decode(
85+
# Decode scale-encoded Vec<NeuronInfo>
86+
neurons: List[NeuronInfo] = NeuronInfo.decode_vec(
8787
bytes.fromhex(
8888
hex_bytes_result
8989
))
@@ -126,8 +126,8 @@ hex_bytes_result = sub.query_runtime_api(
126126
method="get_neurons_lite",
127127
params=[NETUID]
128128
)
129-
# Decode scale-encoded NeuronInfoLite
130-
neurons_lite: List[NeuronInfoLite] = NeuronInfoLite.decode(
129+
# Decode scale-encoded Vec<NeuronInfoLite>
130+
neurons_lite: List[NeuronInfoLite] = NeuronInfoLite.decode_vec(
131131
bytes.fromhex(
132132
hex_bytes_result
133133
))
@@ -178,7 +178,7 @@ hex_bytes_result = sub.query_runtime_api(
178178
method="get_stake_info_for_coldkeys",
179179
params=[encoded_coldkeys]
180180
)
181-
# Decode scale-encoded (AccountId, StakeInfo)
181+
# Decode scale-encoded Vec<(AccountId, StakeInfo)>
182182
stake_info: List[Tuple[bytes, List["StakeInfo"]]] = StakeInfo.decode_vec_tuple_vec(
183183
bytes.fromhex(
184184
hex_bytes_result
@@ -199,8 +199,8 @@ hex_bytes_result = sub.query_runtime_api(
199199
method="get_subnet_info",
200200
params=[NETUID]
201201
)
202-
# Decode scale-encoded SubnetInfo
203-
subnet_info: SubnetInfo = SubnetInfo.decode(
202+
# Decode scale-encoded Option<SubnetInfo>
203+
subnet_info: SubnetInfo = SubnetInfo.decode_option(
204204
bytes.fromhex(
205205
hex_bytes_result
206206
))
@@ -219,15 +219,15 @@ hex_bytes_result = sub.query_runtime_api(
219219
method="get_subnets_info",
220220
params=[ ]
221221
)
222-
# Decode scale-encoded Optional[SubnetInfo]
223-
subnets_info: List[Optional[SubnetInfo]] = SubnetInfo.decode_vec(
222+
# Decode scale-encoded Vec<Option<SubnetInfo>>
223+
subnets_info: List[Optional[SubnetInfo]] = SubnetInfo.decode_vec_option(
224224
bytes.fromhex(
225225
hex_bytes_result
226226
))
227227
```
228228

229229
### SubnetHyperparameters
230-
#### get_subnet_info
230+
#### get_subnet_hyperparams
231231
```python
232232
import bittensor
233233
from bt_decode import SubnetHyperparameters
@@ -241,8 +241,8 @@ hex_bytes_result = sub.query_runtime_api(
241241
method="get_subnet_hyperparams",
242242
params=[NETUID]
243243
)
244-
# Decode scale-encoded SubnetHyperparameters
245-
subnet_hyper_params: SubnetHyperparameters = SubnetHyperparameters.decode(
244+
# Decode scale-encoded Option<SubnetHyperparameters>
245+
subnet_hyper_params: Optional[SubnetHyperparameters] = SubnetHyperparameters.decode_option(
246246
bytes.fromhex(
247247
hex_bytes_result
248248
))

bt_decode.pyi

+68-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ class AxonInfo:
2222
def decode(encoded: bytes) -> "AxonInfo":
2323
pass
2424
@staticmethod
25+
def decode_option(encoded: bytes) -> Optional["AxonInfo"]:
26+
pass
27+
@staticmethod
2528
def decode_vec(encoded: bytes) -> List["AxonInfo"]:
2629
pass
2730

@@ -40,9 +43,50 @@ class PrometheusInfo:
4043
def decode(encoded: bytes) -> "PrometheusInfo":
4144
pass
4245
@staticmethod
46+
def decode_option(encoded: bytes) -> Optional["PrometheusInfo"]:
47+
pass
48+
@staticmethod
4349
def decode_vec(encoded: bytes) -> List["PrometheusInfo"]:
4450
pass
4551

52+
class NeuronInfo:
53+
hotkey: bytes
54+
coldkey: bytes
55+
uid: int
56+
netuid: int
57+
active: bool
58+
axon_info: AxonInfo
59+
prometheus_info: PrometheusInfo
60+
stake: List[
61+
Tuple[bytes, int]
62+
] # map of coldkey to stake on this neuron/hotkey (includes delegations)
63+
rank: int
64+
emission: int
65+
incentive: int
66+
consensus: int
67+
trust: int
68+
validator_trust: int
69+
dividends: int
70+
last_update: int
71+
validator_permit: bool
72+
weights: List[
73+
Tuple[int, int] # Vec of (uid, weight)
74+
]
75+
bonds: List[
76+
Tuple[int, int] # Vec of (uid, bond)
77+
]
78+
pruning_score: int
79+
80+
@staticmethod
81+
def decode(encoded: bytes) -> "NeuronInfo":
82+
pass
83+
@staticmethod
84+
def decode_option(encoded: bytes) -> Optional["NeuronInfo"]:
85+
pass
86+
@staticmethod
87+
def decode_vec(encoded: bytes) -> List["NeuronInfo"]:
88+
pass
89+
4690
class NeuronInfoLite:
4791
hotkey: bytes
4892
coldkey: bytes
@@ -70,6 +114,9 @@ class NeuronInfoLite:
70114
def decode(encoded: bytes) -> "NeuronInfoLite":
71115
pass
72116
@staticmethod
117+
def decode_option(encoded: bytes) -> Optional["NeuronInfoLite"]:
118+
pass
119+
@staticmethod
73120
def decode_vec(encoded: bytes) -> List["NeuronInfoLite"]:
74121
pass
75122

@@ -84,6 +131,9 @@ class SubnetIdentity:
84131
def decode(encoded: bytes) -> "SubnetIdentity":
85132
pass
86133
@staticmethod
134+
def decode_option(encoded: bytes) -> Optional["SubnetIdentity"]:
135+
pass
136+
@staticmethod
87137
def decode_vec(encoded: bytes) -> List["SubnetIdentity"]:
88138
pass
89139

@@ -111,6 +161,9 @@ class SubnetInfo:
111161
def decode(encoded: bytes) -> "SubnetInfo":
112162
pass
113163
@staticmethod
164+
def decode_option(encoded: bytes) -> Optional["SubnetInfo"]:
165+
pass
166+
@staticmethod
114167
def decode_vec(encoded: bytes) -> List["SubnetInfo"]:
115168
pass
116169
@staticmethod
@@ -142,6 +195,9 @@ class SubnetInfoV2:
142195
def decode(encoded: bytes) -> "SubnetInfoV2":
143196
pass
144197
@staticmethod
198+
def decode_option(encoded: bytes) -> Optional["SubnetInfoV2"]:
199+
pass
200+
@staticmethod
145201
def decode_vec(encoded: bytes) -> List["SubnetInfoV2"]:
146202
pass
147203
@staticmethod
@@ -181,6 +237,9 @@ class SubnetHyperparameters:
181237
def decode(encoded: bytes) -> "SubnetHyperparameters":
182238
pass
183239
@staticmethod
240+
def decode_option(encoded: bytes) -> Optional["SubnetHyperparameters"]:
241+
pass
242+
@staticmethod
184243
def decode_vec(encoded: bytes) -> List["SubnetHyperparameters"]:
185244
pass
186245

@@ -193,6 +252,9 @@ class StakeInfo:
193252
def decode(encoded: bytes) -> "StakeInfo":
194253
pass
195254
@staticmethod
255+
def decode_option(encoded: bytes) -> Optional["StakeInfo"]:
256+
pass
257+
@staticmethod
196258
def decode_vec(encoded: bytes) -> List["StakeInfo"]:
197259
pass
198260
@staticmethod
@@ -206,13 +268,18 @@ class DelegateInfo:
206268
owner_ss58: bytes
207269
registrations: List[int] # Vec of netuid this delegate is registered on
208270
validator_permits: List[int] # Vec of netuid this delegate has validator permit on
209-
return_per_1000: int # Delegators current daily return per 1000 TAO staked minus take fee
271+
return_per_1000: (
272+
int # Delegators current daily return per 1000 TAO staked minus take fee
273+
)
210274
total_daily_return: int
211275

212276
@staticmethod
213277
def decode(encoded: bytes) -> "DelegateInfo":
214278
pass
215279
@staticmethod
280+
def decode_option(encoded: bytes) -> Optional["DelegateInfo"]:
281+
pass
282+
@staticmethod
216283
def decode_vec(encoded: bytes) -> List["DelegateInfo"]:
217284
pass
218285
@staticmethod

libs/custom-derive/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "custom_derive"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
edition = "2021"
55

66
[lib]

libs/custom-derive/src/lib.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,8 @@ fn pydecode_impl(attr: TokenStream2, tokens: TokenStream2) -> Result<TokenStream
5252
#[pyo3(name = "decode")]
5353
#[staticmethod]
5454
fn py_decode(encoded: &[u8]) -> Self {
55-
let decoded = #struct_name::decode(&mut &encoded[..])
56-
.expect(&format!("Failed to decode {}", #struct_name_str));
57-
decoded
55+
#struct_name::decode(&mut &encoded[..])
56+
.expect(&format!("Failed to decode {}", #struct_name_str))
5857
}
5958
});
6059

@@ -68,6 +67,16 @@ fn pydecode_impl(attr: TokenStream2, tokens: TokenStream2) -> Result<TokenStream
6867
}
6968
});
7069

70+
// Add the py_decode_option method
71+
item_impl.items.push(parse_quote! {
72+
#[pyo3(name = "decode_option")]
73+
#[staticmethod]
74+
fn py_decode_option(encoded: &[u8]) -> Option<Self> {
75+
Option::<#struct_name>::decode(&mut &encoded[..])
76+
.expect(&format!("Failed to decode Option<{}>", #struct_name_str))
77+
}
78+
});
79+
7180
Ok(quote!(#item_impl))
7281
}
7382

pyproject.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "bt-decode"
3-
version = "0.2.0a"
3+
version = "0.2.1a"
44
description = "A wrapper around the scale-codec crate for fast scale-decoding of Bittensor data structures."
55
readme = "README.md"
66
license = {file = "LICENSE"}
@@ -41,7 +41,7 @@ build-backend = "maturin"
4141
[project.optional-dependencies]
4242
dev = ["black==23.7.0","maturin", "ruff==0.4.7"]
4343
test = [
44-
"bittensor==7.3.1",
44+
"bittensor==8.2.0",
4545
"pytest==7.2.0",
4646
"pytest-asyncio==0.23.7",
4747
"pytest-mock==3.12.0",

src/dyndecoder.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use scale_info::{form::PortableForm, PortableRegistry, Type, TypeDef};
22
use scale_info::{
3-
PortableType, TypeDefArray, TypeDefCompact, TypeDefPrimitive, TypeDefSequence,
4-
TypeDefTuple,
3+
PortableType, TypeDefArray, TypeDefCompact, TypeDefPrimitive, TypeDefSequence, TypeDefTuple,
54
};
65
use std::any::TypeId;
76
use std::collections::HashMap;

tests/test_decode_by_type_string.py

-2
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ class TestDecodeByPlainTypeString:
209209

210210
@classmethod
211211
def setup_class(cls) -> None:
212-
213212
with open(TEST_TYPES_JSON, "r") as f:
214213
types_json_str = f.read()
215214

@@ -233,7 +232,6 @@ class TestDecodeByScaleInfoTypeString:
233232

234233
@classmethod
235234
def setup_class(cls) -> None:
236-
237235
with open(TEST_TYPES_JSON, "r") as f:
238236
types_json_str = f.read()
239237

0 commit comments

Comments
 (0)