c5c28cc568
Set zap.Logger as the primary logger for status-go. All geth logs are now proxied through zap.Logger. closes: #6029 |
||
---|---|---|
.. | ||
requests | ||
server | ||
README.md | ||
main.go |
README.md
📝Description
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.
📍status-go API
[!NOTE]
Unfortunately, for now there is no convenient docs like OpenAPI
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 returnfunc() 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
:
// 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
.
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"` }
Unsupported methods
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, https://github.com/status-im/status-go/pull/5865 fixes some of these.
Deprecated methods
Deprecated methods will have Deprecation: true
HTTP header.
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:
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:
// 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": {}
}
}
3️⃣ Services in ./services/**/api.go
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,
},
}
}
Address
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.
Arguments
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.
Notes
- 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
🏃♂️Usage
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:
👌 Simple flows
In most cases to start testing you'll need some boilerplate. Below are the simple call flows for common cases.
Create account and login
- 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
Login into account
- 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