Files
Igor Sirotin f3e4363808 refactor: move protocol to internal/protocol
Part of the Go project layout migration, item 27.

Pure move plus import-path rewrite across 502 files. No API or behaviour
change. `internal/` keeps the messaging application logic unimportable
from outside the module, which is what the issue asks for -- status-go is
consumed through the C-bindings in mobile/, not as a Go library.

Things that had to follow the move, beyond the Go imports:

- tools/generate-handlers/template.txt. messenger_handlers.go is
  generated, and the template hard-codes the imports it emits, so the
  generated file kept importing protocol/common and failed typecheck.
- .gitignore. The ignore rule for that generated file was pinned to the
  old path; without moving it, a 1486-line generated file starts being
  tracked.
- Makefile: the logosstorage and torrent test targets (both the archive
  packages and ./protocol itself), the archive README, migration-protocol.
- scripts/run_unit_tests.sh, which names the protocol package explicitly
  to shard its tests.
- scripts/cleanup_generated_files.sh and .golangci.yml.

scripts/migration_check.sh also needed a fix that is not specific to this
move: it validated every file the branch touched under a migration dir
against the timestamp naming rule, and a directory rename makes every
migration in it look newly added. It now excludes renames, so moving a
migration is not mistaken for adding one.

refs #7067
2026-08-21 10:11:05 +02:00
..
2025-09-01 21:12:07 +01:00

📝Description

Welcome to status-backend. This is a tool for debugging and testing status-go. In contrast to existing statusd, 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.

📚 Building a bot? See API_REFERENCE.md for a practical API reference with request/response examples, community join sequences, error codes, and common gotchas.

📍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 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:

// 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)
}
  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 for real arguments and return values:
    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:
    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):
    if err != nil {
        return makeJSONResponse(err)
    }
    
    ... which wraps the error to 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

  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

🏃‍♂️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:

status-backend API

  • /health This is a basic health check endpoint. Response contains a single version property. Returns HTTP code 200 if alive.

👌 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

  1. Subscribe to /signals
  2. Call /statusgo/InitializeApplication
  3. Create an account
    1. Call /statusgo/CreateAccountAndLogin
    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

  1. Subscribe to /signals
  2. Call /statusgo/InitializeApplication
  3. Create an account
    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": [] }