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.
This allows to communicate with status-go through HTTP the same way as status-desktop
and status-mobile
do, including:
- create account
- restore account
- login
- logout
- start messenger
- start wallet
- subscribe to status-go signals
- etc.
Note
Unfortunately, for now there is no convenient docs like OpenAPI
Any public functions in ./mobile/status.go
with the one of the following signatures:
func(string) string
- 1 argument, 1 returnfunc() string
- 0 argument, 1 return
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.
Responses have JSON body with a single error
field.
If error
is empty, no error occurred.
The structure of response is defined in APIResponse
:
// APIResponse generic response from API.
type APIResponse struct {
Error string `json:"error"`
}
Parameters are passed as request JSON body.
Specific parameters for each endpoint should be checked in the source code.
As example, let's look at CreateAccountAndLogin
.
func CreateAccountAndLogin(requestJSON string) string {
return callWithResponse(createAccountAndLogin, requestJSON)
}
- The function has 1 JSON string argument and 1 JSON string return value.
- The function wraps a private
createAccountAndLogin
withcallWithResponse
.
callWithResponse
does some internal magic like logging the request and response.
So we should check the private function for real arguments and return values:func createAccountAndLogin(requestJSON string) string { var request requests.CreateAccount err := json.Unmarshal([]byte(requestJSON), &request) // ... }
- We can see that the parameters are unmarshalled to
requests.CreateAccount
:type CreateAccount struct { RootDataDir string `json:"rootDataDir"` KdfIterations int `json:"kdfIterations"` // ...
- We can also see that each the response is formed as
makeJSONResponse(err)
:... which wraps the error toif err != nil { return makeJSONResponse(err) }
APIResponse
:// APIResponse generic response from API. type APIResponse struct { Error string `json:"error"` }
Attempt to call any functions with unsupported signatures will return 501: Not Implemented
HTTP code.
For example, VerifyAccountPassword
has 3 arguments:
func VerifyAccountPassword(keyStoreDir, address, password string) string {
return logAndCallString(verifyAccountPassword, keyStoreDir, address, password)
}
Later, as needed, a V2 of these functions will be introduced. V2 will have a single JSON argument composing all args in 1.
For example, #5865 fixes some of these.
Deprecated methods will have Deprecation: true
HTTP header.
Note
Unfortunately, there is no description of when any expected signals will appear.
For now, you have to check the source code.
Signals are available at ws://<address>/signals
.
Connect to it as the first thing when running status-backend
.
List of possible events can be found in ./signal/event_*.go
files.
For example, node.login
event is defined here:
const (
// EventLoggedIn is once node was injected with user account and ready to be used.
EventLoggedIn = "node.login"
)
Each signal has this structure:
// Envelope is a general signal sent upward from node to RN app
type Envelope struct {
Type string `json:"type"`
Event interface{} `json:"event"`
}
Here, type
is the name of the event, e.g. node.login
.
And the structure of this event is defined in the same file:
// NodeLoginEvent returns the result of the login event
type NodeLoginEvent struct {
Error string `json:"error,omitempty"`
Settings *settings.Settings `json:"settings,omitempty"`
Account *multiaccounts.Account `json:"account,omitempty"`
EnsUsernames json.RawMessage `json:"ensUsernames,omitempty"`
}
So the signal for node.login
event will look like this (with corresponding data):
{
"type": "node.login",
"event": {
"error": "",
"settings": {},
"account": {},
"endUsernames": {}
}
}
Services are registered in the go-ethereum JSON-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:
// 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,
},
}
}
These methods are available through /statusgo/CallRPC
endpoint defined here.
This is the way desktop and mobile clients call these methods. You don't have to run a separate geth HTTP server for this.
For example:
### Send Contact Request
POST http://localhost:12345/statusgo/CallRPC
{
"jsonrpc": "2.0",
"method": "wakuext_sendContactRequest",
"params": [
{
"id": "0x048f0b885010783429c2298b916e24b3c01f165e55fe8f98fce63df0a55ade80089f512943d4fde5f8c7211f1a87b267a85cbcb3932eb2e4f88aa4ca3918f97541",
"message": "Hi, Alice!"
}
]
}
Please reference to the source code for the list of methods and its arguments.
- In this case, there's no limitation to the number of arguments, comparing to
mobile/status.go
, so ll method are supported. - Deprecated methods won't have a corresponding
Deprecated: true
Start the app with the address to listen to:
status-backend --address localhost:12345
Or just use the root repo Makefile command:
make run-status-backend PORT=12345
Access the exposed API with any HTTP client you prefer:
- From your IDE:
- From UI client:
- From command line:
- From your script:
/health
This is a basic health check endpoint. Response contains a singleversion
property. Returns HTTP code 200 if alive.
In most cases to start testing you'll need some boilerplate. Below are the simple call flows for common cases.
- Subscribe to
/signals
- Call
/statusgo/InitializeApplication
- Create an account
- Call
/statusgo/CreateAccountAndLogin
- Wait for
node.login
signal- If
error
is empty, no error occurred - If
error
is not empty, stop the operation
- If
- Call
- Start required services
- Call
/statusgo/CallRPC
with{ "method": "wakuext_startMessenger", "params": [] }
- Call
/statusgo/CallRPC
with{ "method": "wallet_startWallet", "params": [] }
- Call
- Apply temporary workarounds:
- Call
/statusgo/CallRPC
with{ "method": "settings_getSettings", "params": [] }
(otherwise settings don't get saved into DB)
- Call
- Subscribe to
/signals
- Call
/statusgo/InitializeApplication
- Create an account
- Call
/statusgo/LoginAccount
- Wait for
node.login
signal- If
error
is empty, no error occurred - If
error
is not empty, stop the operation
- If
- Call
- Start required services
- Call
/statusgo/CallRPC
with{ "method": "wakuext_startMessenger", "params": [] }
- Call
/statusgo/CallRPC
with{ "method": "wallet_startWallet", "params": [] }
- Call