Skip to content

Commit 44fec2a

Browse files
authored
Merge pull request #534 from AmbireTech/sentry-rest-api-docs
Sentry REST API docs
2 parents f4fb43b + 39a40a3 commit 44fec2a

14 files changed

+505
-69
lines changed

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ Sentry API will be accessible at `localhost:8006`
9292
IP_ADDR=127.0.0.1 REDIS_URL="redis://127.0.0.1:6379/2" \
9393
POSTGRES_DB="sentry_follower" PORT=8006 KEYSTORE_PWD=ganache1 cargo run -p sentry -- \
9494
--adapter ethereum \
95-
--keystoreFile ./adapter/test/resources/0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7_keystore.json
95+
--keystoreFile ./adapter/tests/resources/0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7_keystore.json \
9696
./docs/config/ganache.toml
9797
```
9898

@@ -174,7 +174,7 @@ Assuming you have [Sentry API running](#running-sentry-rest-api) for the **Leade
174174
```bash
175175
KEYSTORE_PWD=ganache0 cargo run -p validator_worker -- \
176176
--adapter ethereum \
177-
--keystoreFile ./adapter/test/resources/0x80690751969B234697e9059e04ed72195c3507fa_keystore.json \
177+
--keystoreFile ./adapter/tests/resources/0x80690751969B234697e9059e04ed72195c3507fa_keystore.json \
178178
--sentryUrl http://127.0.0.1:8005 \
179179
./docs/config/ganache.toml
180180
```
@@ -186,7 +186,7 @@ Assuming you have [Sentry API running](#running-sentry-rest-api) for the **Follo
186186
```bash
187187
KEYSTORE_PWD=ganache1 cargo run -p validator_worker -- \
188188
--adapter ethereum \
189-
--keystoreFile ./adapter/test/resources/0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7_keystore.json \
189+
--keystoreFile ./adapter/tests/resources/0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7_keystore.json \
190190
--sentryUrl http://127.0.0.1:8006 \
191191
./docs/config/ganache.toml
192192
```

primitives/Cargo.toml

+15
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,28 @@ required-features = ["test-util"]
3838
name = "channel_list_query"
3939
required-features = ["test-util"]
4040

41+
[[example]]
42+
name = "channel_last_approved_response"
43+
44+
[[example]]
45+
name = "channel_last_approved_query"
46+
4147
[[example]]
4248
name = "create_campaign"
4349
required-features = ["test-util"]
4450

4551
[[example]]
4652
name = "modify_campaign"
4753

54+
[[example]]
55+
name = "validator_messages_create_request"
56+
57+
[[example]]
58+
name = "validator_messages_list_query"
59+
60+
[[example]]
61+
name = "validator_messages_list_response"
62+
4863
[dependencies]
4964
# (De)Serialization
5065
serde = { version = "1.0", features = ["derive"] }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use primitives::sentry::LastApprovedQuery;
2+
3+
fn main() {
4+
// An empty query - no heartbeats will be included in the response (default).
5+
{
6+
// This is treated the same as `withHeartbeat=false` in the route.
7+
let empty = "";
8+
let empty_expected = LastApprovedQuery {
9+
with_heartbeat: None,
10+
};
11+
12+
assert_eq!(empty_expected, serde_qs::from_str(empty).unwrap());
13+
}
14+
15+
// Query with `with_heartbeat` parameter - latest 2 Heartbeats from
16+
// each Channel Validator will be returned in the response.
17+
{
18+
let with_heartbeat = "withHeartbeat=true";
19+
let with_heartbeat_expected = LastApprovedQuery {
20+
with_heartbeat: Some(true),
21+
};
22+
23+
assert_eq!(
24+
with_heartbeat_expected,
25+
serde_qs::from_str(with_heartbeat).unwrap()
26+
);
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
use primitives::{balances::UncheckedState, sentry::LastApprovedResponse};
2+
use serde_json::{from_value, json};
3+
4+
fn main() {
5+
// An empty response - Channel is brand new and neither an NewState nor a ApproveState
6+
// have been generated yet.
7+
// This is threated the same as `with_heartbeat=false` in the route.
8+
{
9+
let empty_json = json!({});
10+
11+
let empty_expected = LastApprovedResponse::<UncheckedState> {
12+
last_approved: None,
13+
heartbeats: None,
14+
};
15+
16+
assert_eq!(
17+
empty_expected,
18+
from_value(empty_json).expect("Should deserialize")
19+
);
20+
}
21+
22+
// Response without `with_heartbeat=true` query parameter
23+
// or with a `with_heartbeat=false` query parameter
24+
{
25+
let response_json = json!({
26+
"lastApproved": {
27+
"newState": {
28+
"from": "0x80690751969B234697e9059e04ed72195c3507fa",
29+
"received": "2022-08-09T14:45:38.090Z",
30+
"msg": {
31+
"type": "NewState",
32+
"stateRoot": "a1e2f6ee08185ae06e3212e56ad1e0fcbae95ac8939871eb96e1ee3016234321",
33+
"signature": "0x508bef21e91d5337ad71791503748fe0d7ee7592db90179be6f948570290d00b72e103b0d262452809ace183ebf83375072b4a359b6e441f2ad6f58b8552c8fa1b",
34+
"earners": {
35+
"0x80690751969B234697e9059e04ed72195c3507fa": "5",
36+
"0xE882ebF439207a70dDcCb39E13CA8506c9F45fD9": "100000",
37+
"0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7": "3"
38+
},
39+
"spenders": {
40+
"0xaCBaDA2d5830d1875ae3D2de207A1363B316Df2F": "100008"
41+
}
42+
}
43+
},
44+
"approveState": {
45+
"from": "0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7",
46+
"received": "2022-08-09T14:45:43.110Z",
47+
"msg": {
48+
"type": "ApproveState",
49+
"stateRoot": "a1e2f6ee08185ae06e3212e56ad1e0fcbae95ac8939871eb96e1ee3016234321",
50+
"signature": "0xb2ce0010ad5867a4fb4acbde6525c261d76b592d290cb22af120573565168a2e49381e84d4f409c0989fa171dd687bf68b7eeff5b595c845cec8e9b8b1738dbd1c",
51+
"isHealthy": true
52+
}
53+
}
54+
}
55+
});
56+
57+
let response: LastApprovedResponse<UncheckedState> =
58+
from_value(response_json).expect("Should deserialize");
59+
assert!(response.heartbeats.is_none());
60+
}
61+
62+
{
63+
let response_json = json!({
64+
"lastApproved": {
65+
"newState": {
66+
"from": "0x80690751969B234697e9059e04ed72195c3507fa",
67+
"received": "2022-08-09T14:45:38.090Z",
68+
"msg": {
69+
"type": "NewState",
70+
"stateRoot": "a1e2f6ee08185ae06e3212e56ad1e0fcbae95ac8939871eb96e1ee3016234321",
71+
"signature": "0x508bef21e91d5337ad71791503748fe0d7ee7592db90179be6f948570290d00b72e103b0d262452809ace183ebf83375072b4a359b6e441f2ad6f58b8552c8fa1b",
72+
"earners": {
73+
"0x80690751969B234697e9059e04ed72195c3507fa": "5",
74+
"0xE882ebF439207a70dDcCb39E13CA8506c9F45fD9": "100000",
75+
"0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7": "3"
76+
},
77+
"spenders": {
78+
"0xaCBaDA2d5830d1875ae3D2de207A1363B316Df2F": "100008"
79+
}
80+
}
81+
},
82+
"approveState": {
83+
"from": "0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7",
84+
"received": "2022-08-09T14:45:43.110Z",
85+
"msg": {
86+
"type": "ApproveState",
87+
"stateRoot": "a1e2f6ee08185ae06e3212e56ad1e0fcbae95ac8939871eb96e1ee3016234321",
88+
"signature": "0xb2ce0010ad5867a4fb4acbde6525c261d76b592d290cb22af120573565168a2e49381e84d4f409c0989fa171dd687bf68b7eeff5b595c845cec8e9b8b1738dbd1c",
89+
"isHealthy": true
90+
}
91+
}
92+
},
93+
"heartbeats": [
94+
{
95+
"from": "0x80690751969B234697e9059e04ed72195c3507fa",
96+
"received": "2022-08-09T14:45:58.110Z",
97+
"msg": {
98+
"type": "Heartbeat",
99+
"signature": "0xc96ed701fc53e27cb28b323c26060273a5bdbad07c4b5470d8090c6a8b03954422b5d0dcc791cc47b5e4186045f60971d7e8e4d69b380cf250fe416cf4aac6901b",
100+
"stateRoot": "888f915d6b84ccfa80d3cc6536021efab05f63293ddfb66f1bb1c191909d1372",
101+
"timestamp": "2022-08-09T14:45:58.097376454Z"
102+
}
103+
},
104+
{
105+
"from": "0x80690751969B234697e9059e04ed72195c3507fa",
106+
"received": "2022-08-09T14:45:28.090Z",
107+
"msg": {
108+
"type": "Heartbeat",
109+
"signature": "0x3f780e2abe0d704428a7921c2f18c070ad503953ef248f533b4ad13fa97c239c5e43a9f3db5077b24d4912cb13367337dc4a6c26976a15811a728e316e7275c41c",
110+
"stateRoot": "799c72322f9c35840c4bf41045df2623b33a97a5dfa3994022389ddf8930aac6",
111+
"timestamp": "2022-08-09T14:45:28.084928288Z"
112+
}
113+
},
114+
{
115+
"from": "0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7",
116+
"received": "2022-08-09T14:46:03.170Z",
117+
"msg": {
118+
"type": "Heartbeat",
119+
"signature": "0xd4ce3c8e1cc8ab690cddc2a6cd229311e91e13a53e59b1ec80d8f877afd241af2c86c5fade37be5057d36c8fc5e69d3222b49b98bf686ee00e73005cc280ebc41b",
120+
"stateRoot": "d0dc740d3352cdd7da9b823aa4051830f9757fae66c553a88176ce0001e378fb",
121+
"timestamp": "2022-08-09T14:46:03.127887835Z"
122+
}
123+
},
124+
{
125+
"from": "0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7",
126+
"received": "2022-08-09T14:45:28.160Z",
127+
"msg": {
128+
"type": "Heartbeat",
129+
"signature": "0x3afda200de4ac36d5c8f1a53da0ffdca5077b556a53fb56bb9a79def1c06f972547b0099731b1ac9b4a26c183e2ea66b8cd1759cdc1513e3436d182e9592ae0e1b",
130+
"stateRoot": "fa8f11b8aa6322905846f96219c855920b4449b18f0ceea97552e3880c5e4a9a",
131+
"timestamp": "2022-08-09T14:45:28.121225273Z"
132+
}
133+
}
134+
]
135+
});
136+
137+
let response: LastApprovedResponse<UncheckedState> =
138+
from_value(response_json).expect("Should deserialize");
139+
140+
assert!(response.heartbeats.is_some());
141+
}
142+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use primitives::sentry::ValidatorMessagesCreateRequest;
2+
use serde_json::{from_value, json};
3+
4+
fn main() {
5+
// This request is generated using the Ethereum Adapter
6+
let request_json = json!({
7+
"messages": [
8+
{
9+
"type": "ApproveState",
10+
"stateRoot": "a1e2f6ee08185ae06e3212e56ad1e0fcbae95ac8939871eb96e1ee3016234321",
11+
"signature": "0xb2ce0010ad5867a4fb4acbde6525c261d76b592d290cb22af120573565168a2e49381e84d4f409c0989fa171dd687bf68b7eeff5b595c845cec8e9b8b1738dbd1c",
12+
"isHealthy": true
13+
},
14+
{
15+
"type": "NewState",
16+
"stateRoot": "a1e2f6ee08185ae06e3212e56ad1e0fcbae95ac8939871eb96e1ee3016234321",
17+
"signature": "0x508bef21e91d5337ad71791503748fe0d7ee7592db90179be6f948570290d00b72e103b0d262452809ace183ebf83375072b4a359b6e441f2ad6f58b8552c8fa1b",
18+
"earners": {
19+
"0x80690751969B234697e9059e04ed72195c3507fa": "5",
20+
"0xE882ebF439207a70dDcCb39E13CA8506c9F45fD9": "100000",
21+
"0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7": "3"
22+
},
23+
"spenders": {
24+
"0xaCBaDA2d5830d1875ae3D2de207A1363B316Df2F": "100008"
25+
}
26+
},
27+
{
28+
"type": "Heartbeat",
29+
"signature": "0x3afda200de4ac36d5c8f1a53da0ffdca5077b556a53fb56bb9a79def1c06f972547b0099731b1ac9b4a26c183e2ea66b8cd1759cdc1513e3436d182e9592ae0e1b",
30+
"stateRoot": "fa8f11b8aa6322905846f96219c855920b4449b18f0ceea97552e3880c5e4a9a",
31+
"timestamp": "2022-08-09T14:45:28.121225273Z"
32+
}
33+
]
34+
});
35+
36+
let request: ValidatorMessagesCreateRequest =
37+
from_value(request_json).expect("Should deserialize");
38+
39+
println!("{request:#?}");
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use primitives::sentry::ValidatorMessagesListQuery;
2+
3+
fn main() {
4+
// Empty query - default values only
5+
{
6+
let empty_query = "";
7+
let query: ValidatorMessagesListQuery = serde_qs::from_str(empty_query).unwrap();
8+
9+
assert_eq!(None, query.limit);
10+
}
11+
// Query with set limit
12+
{
13+
let query_str = "limit=200";
14+
let query: ValidatorMessagesListQuery = serde_qs::from_str(query_str).unwrap();
15+
16+
assert_eq!(Some(200), query.limit);
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use primitives::sentry::ValidatorMessagesListResponse;
2+
use serde_json::{from_value, json};
3+
4+
fn main() {
5+
// This response is generated using the Ethereum Adapter
6+
let response_json = json!({
7+
"messages": [
8+
{
9+
"from": "0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7",
10+
"received": "2022-08-09T14:45:43.110Z",
11+
"msg": {
12+
"type": "ApproveState",
13+
"stateRoot": "a1e2f6ee08185ae06e3212e56ad1e0fcbae95ac8939871eb96e1ee3016234321",
14+
"signature": "0xb2ce0010ad5867a4fb4acbde6525c261d76b592d290cb22af120573565168a2e49381e84d4f409c0989fa171dd687bf68b7eeff5b595c845cec8e9b8b1738dbd1c",
15+
"isHealthy": true
16+
}
17+
},
18+
{
19+
"from": "0x80690751969B234697e9059e04ed72195c3507fa",
20+
"received": "2022-08-09T14:45:38.090Z",
21+
"msg": {
22+
"type": "NewState",
23+
"stateRoot": "a1e2f6ee08185ae06e3212e56ad1e0fcbae95ac8939871eb96e1ee3016234321",
24+
"signature": "0x508bef21e91d5337ad71791503748fe0d7ee7592db90179be6f948570290d00b72e103b0d262452809ace183ebf83375072b4a359b6e441f2ad6f58b8552c8fa1b",
25+
"earners": {
26+
"0x80690751969B234697e9059e04ed72195c3507fa": "5",
27+
"0xE882ebF439207a70dDcCb39E13CA8506c9F45fD9": "100000",
28+
"0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7": "3"
29+
},
30+
"spenders": {
31+
"0xaCBaDA2d5830d1875ae3D2de207A1363B316Df2F": "100008"
32+
}
33+
}
34+
},
35+
{
36+
"from": "0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7",
37+
"received": "2022-08-09T14:45:28.160Z",
38+
"msg": {
39+
"type": "Heartbeat",
40+
"signature": "0x3afda200de4ac36d5c8f1a53da0ffdca5077b556a53fb56bb9a79def1c06f972547b0099731b1ac9b4a26c183e2ea66b8cd1759cdc1513e3436d182e9592ae0e1b",
41+
"stateRoot": "fa8f11b8aa6322905846f96219c855920b4449b18f0ceea97552e3880c5e4a9a",
42+
"timestamp": "2022-08-09T14:45:28.121225273Z"
43+
}
44+
}
45+
]
46+
});
47+
48+
let response: ValidatorMessagesListResponse =
49+
from_value(response_json).expect("Should deserialize");
50+
51+
println!("{response:#?}");
52+
}

primitives/src/balances.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use thiserror::Error;
99
pub struct Balances<S: BalancesState = CheckedState> {
1010
pub earners: UnifiedMap,
1111
pub spenders: UnifiedMap,
12+
#[serde(skip)]
1213
state: PhantomData<S>,
1314
}
1415

0 commit comments

Comments
 (0)