docs_: better usage docs for status-backend (#5955)

This commit is contained in:
Igor Sirotin 2024-10-18 21:59:09 +03:00 committed by GitHub
parent e611b1e513
commit 9fcb153f32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 156 additions and 31 deletions

View File

@ -11,7 +11,8 @@
- [How to run a Bootnode](BOOTNODE.md) - [How to run a Bootnode](BOOTNODE.md)
- [How to run a Mailserver](MAILSERVER.md) - [How to run a Mailserver](MAILSERVER.md)
- [How to run a Waku node](./_examples/README.md#run-waku-node) - [How to run a Waku node](./_examples/README.md#run-waku-node)
- [How to configure status-go](/config) - [How to configure status-go](/config/README.md)
- [How to run status-go as HTTP server](/cmd/status-backend/README.md)
## Policies ## Policies

View File

@ -1,4 +1,4 @@
# Description # 📝Description
Welcome to `status-backend`. This is a tool for debugging and testing `status-go`. Welcome to `status-backend`. This is a tool for debugging and testing `status-go`.
In contrast to existing `statusd` and `status-cli`, the `status-backend` exposes full status-go API through HTTP. In contrast to existing `statusd` and `status-cli`, the `status-backend` exposes full status-go API through HTTP.
@ -13,17 +13,87 @@ This allows to communicate with status-go through HTTP the same way as `status-d
- subscribe to status-go signals - subscribe to status-go signals
- etc. - etc.
# status-go API # 📍status-go API
## Public methods in `./mobile/status.go` > [!NOTE]
> Unfortunately, for now there is no convenient docs like OpenAPI
Only specific function signatures are currently supported: ## 1⃣ Public methods in `./mobile/status.go`
### Description
Any **public** functions in `./mobile/status.go` with the one of the following signatures:
- `func(string) string` - 1 argument, 1 return - `func(string) string` - 1 argument, 1 return
- `func() string` - 0 argument, 1 return - `func() string` - 0 argument, 1 return
### Address
Endpoints address: `http://<address>/statusgo/<function-name>`.
Here, `statusgo` is the name of the package in `/mobile/status.go`. We might create more APIs next to it in the future.
### Response
Responses have JSON body with a single `error` field.
If `error` is empty, no error occurred.
The structure of response is defined in [`APIResponse`](https://github.com/status-im/status-go/blob/91c6949cd25449d5459581a21f2c8b929290ced0/mobile/types.go#L9-L12):
```go
// APIResponse generic response from API.
type APIResponse struct {
Error string `json:"error"`
}
```
### Parameters
Parameters are passed as request JSON body.
Specific parameters for each endpoint should be checked in the source code.
### How to read the source code?
As example, let's look at [`CreateAccountAndLogin`](https://github.com/status-im/status-go/blob/fc36a7e980fc8f73dd36d7e3db29675ddff1d5dc/mobile/status.go#L415-L417).
```go
func CreateAccountAndLogin(requestJSON string) string {
return callWithResponse(createAccountAndLogin, requestJSON)
}
```
1. The function has 1 JSON string argument and 1 JSON string return value.
2. The function wraps a private `createAccountAndLogin` with `callWithResponse`.
`callWithResponse` does some internal magic like logging the request and response.
So we should check [the private function](https://github.com/status-im/status-go/blob/fc36a7e980fc8f73dd36d7e3db29675ddff1d5dc/mobile/status.go#L419) for real arguments and return values:
```go
func createAccountAndLogin(requestJSON string) string {
var request requests.CreateAccount
err := json.Unmarshal([]byte(requestJSON), &request)
// ...
}
```
3. We can see that the parameters are unmarshalled to [`requests.CreateAccount`](https://github.com/status-im/status-go/blob/f660be0daa7cc742a07f6a139ea5ac9966f3ebe0/protocol/requests/create_account.go#L35):
```go
type CreateAccount struct {
RootDataDir string `json:"rootDataDir"`
KdfIterations int `json:"kdfIterations"`
// ...
```
4. We can also see that each the response is formed as [`makeJSONResponse(err)`](https://github.com/status-im/status-go/blob/fc36a7e980fc8f73dd36d7e3db29675ddff1d5dc/mobile/status.go#L422-L424):
```go
if err != nil {
return makeJSONResponse(err)
}
```
... which wraps the error to [`APIResponse`](https://github.com/status-im/status-go/blob/91c6949cd25449d5459581a21f2c8b929290ced0/mobile/types.go#L9-L12):
```go
// APIResponse generic response from API.
type APIResponse struct {
Error string `json:"error"`
}
```
### Unsupported methods ### Unsupported methods
Attempt to call any other functions will return `501: Not Implemented` HTTP code. Attempt to call any functions with unsupported signatures will return `501: Not Implemented` HTTP code.
For example, [`VerifyAccountPassword`](https://github.com/status-im/status-go/blob/669256095e16d953ca1af4954b90ca2ae65caa2f/mobile/status.go#L275-L277) has 3 arguments: For example, [`VerifyAccountPassword`](https://github.com/status-im/status-go/blob/669256095e16d953ca1af4954b90ca2ae65caa2f/mobile/status.go#L275-L277) has 3 arguments:
```go ```go
func VerifyAccountPassword(keyStoreDir, address, password string) string { func VerifyAccountPassword(keyStoreDir, address, password string) string {
@ -38,7 +108,31 @@ For example, https://github.com/status-im/status-go/pull/5865 fixes some of thes
Deprecated methods will have `Deprecation: true` HTTP header. Deprecated methods will have `Deprecation: true` HTTP header.
## Signals in `./signal` ## 2⃣ Signals in `./signal`
> [!NOTE]
> Unfortunately, there is no description of when any expected signals will appear.
> For now, you have to check the source code.
### Address
Signals are available at `ws://<address>/signals`.
Connect to it as the first thing when running `status-backend`.
### Available signals
List of possible events can be found in `./signal/event_*.go` files.
For example, `node.login` event is defined [here](https://github.com/status-im/status-go/blob/6bcf5f1289f9160168574290cbd6f90dede3f8f6/signal/events_node.go#L27-L28):
```go
const (
// EventLoggedIn is once node was injected with user account and ready to be used.
EventLoggedIn = "node.login"
)
```
### Signals structure
Each signal has [this structure](https://github.com/status-im/status-go/blob/c9b777a2186364b8f394ad65bdb18b128ceffa70/signal/signals.go#L30-L33): Each signal has [this structure](https://github.com/status-im/status-go/blob/c9b777a2186364b8f394ad65bdb18b128ceffa70/signal/signals.go#L30-L33):
```go ```go
@ -49,16 +143,7 @@ type Envelope struct {
} }
``` ```
List of possible events can be found in `./signal/event_*.go` files. Here, `type` is the name of the event, e.g. `node.login`.
For example, `node.login` event is defined [here](https://github.com/status-im/status-go/blob/6bcf5f1289f9160168574290cbd6f90dede3f8f6/signal/events_node.go#L27-L28):
```go
const (
// EventLoggedIn is once node was injected with user account and ready to be used.
EventLoggedIn = "node.login"
)
```
And the structure of this event is [defined in the same file](https://github.com/status-im/status-go/blob/6bcf5f1289f9160168574290cbd6f90dede3f8f6/signal/events_node.go#L36-L42): And the structure of this event is [defined in the same file](https://github.com/status-im/status-go/blob/6bcf5f1289f9160168574290cbd6f90dede3f8f6/signal/events_node.go#L36-L42):
```go ```go
// NodeLoginEvent returns the result of the login event // NodeLoginEvent returns the result of the login event
@ -70,7 +155,6 @@ type NodeLoginEvent struct {
} }
``` ```
So the signal for `node.login` event will look like this (with corresponding data): So the signal for `node.login` event will look like this (with corresponding data):
```json ```json
{ {
@ -84,9 +168,33 @@ So the signal for `node.login` event will look like this (with corresponding dat
} }
``` ```
## Services in `./services/**/api.go` ## 3Services in `./services/**/api.go`
Services are registered in go-ethereum JSON-RPC server. To call such method, send request to `statusgo/CallRPC` endpoint. Services are registered in the [go-ethereum JSON-RPC](https://geth.ethereum.org/docs/interacting-with-geth/rpc) server.
All `./services/**/api.go` are registered as services in geth.
Each method name has form `<namespace>_<method>`. In most cases namespace is the directory name, but it can be ensured in the `APIs` method of each service. For example, for [wallet service](https://github.com/status-im/status-go/blob/1d173734a608de2d71480d6ad39f4559f11a75e2/services/wallet/service.go#L288-L298):
```go
// APIs returns list of available RPC APIs.
func (s *Service) APIs() []gethrpc.API {
return []gethrpc.API{
{
Namespace: "wallet",
Version: "0.1.0",
Service: NewAPI(s),
Public: true,
},
}
}
```
### Address
These methods are available through `/statusgo/CallRPC` endpoint defined [here](https://github.com/status-im/status-go/blob/fc36a7e980fc8f73dd36d7e3db29675ddff1d5dc/mobile/status.go#L249-L260).
This is the way desktop and mobile clients call these methods. You don't have to run a separate geth HTTP server for this.
### Arguments
For example: For example:
```http request ```http request
@ -105,12 +213,14 @@ POST http://localhost:12345/statusgo/CallRPC
} }
``` ```
Please reference to the source code for the list of methods and its arguments.
### Notes ### Notes
1. In this case, there's no limitation to the number of arguments, comparing to `mobile/status.go`, so ll method are supported. 1. In this case, there's no limitation to the number of arguments, comparing to `mobile/status.go`, so ll method are supported.
2. Deprecated methods won't have a corresponding `Deprecated: true` 2. Deprecated methods won't have a corresponding `Deprecated: true`
# Usage # 🏃‍♂️Usage
Start the app with the address to listen to: Start the app with the address to listen to:
```shell ```shell
@ -135,21 +245,35 @@ Access the exposed API with any HTTP client you prefer:
- [Python](https://pypi.org/project/requests/) - [Python](https://pypi.org/project/requests/)
- [Go](https://pkg.go.dev/net/http) - [Go](https://pkg.go.dev/net/http)
# Simple flows # 👌 Simple flows
In most cases to start testing you'll need some boilerplate. Below are the simple call flows for common cases. In most cases to start testing you'll need some boilerplate. Below are the simple call flows for common cases.
## Create account and login ## Create account and login
1. `InitializeApplication` 1. Subscribe to `/signals`
2. `CreateAccountAndLogin` 2. Call `/statusgo/InitializeApplication`
3. `wakuext_startMessenger` 3. Create an account
4. `wallet_startWallet` 1. Call `/statusgo/CreateAccountAndLogin`
5. `settings_getSettings` (temporary workaround, otherwise settings don't get saved into DB) 2. Wait for `node.login` signal
- If `error` is empty, no error occurred
- If `error` is not empty, stop the operation
4. Start required services
1. Call `/statusgo/CallRPC` with `{ "method": "wakuext_startMessenger", "params": [] }`
2. Call `/statusgo/CallRPC` with `{ "method": "wallet_startWallet", "params": [] }`
5. Apply temporary workarounds:
1. Call `/statusgo/CallRPC` with `{ "method": "settings_getSettings", "params": [] }`
_(otherwise settings don't get saved into DB)_
## Login into account ## Login into account
1. `InitializeApplication` 1. Subscribe to `/signals`
2. `LoginAccount` 2. Call `/statusgo/InitializeApplication`
3. `wakuext_startMessenger` 3. Create an account
4. `wallet_startWallet` 1. Call `/statusgo/LoginAccount`
2. Wait for `node.login` signal
- If `error` is empty, no error occurred
- If `error` is not empty, stop the operation
4. Start required services
1. Call `/statusgo/CallRPC` with `{ "method": "wakuext_startMessenger", "params": [] }`
2. Call `/statusgo/CallRPC` with `{ "method": "wallet_startWallet", "params": [] }`