Library / SDK
status-im/status-go avatar
status-im/status-go

status-go: the Go backend behind the Status app

The "backend" library for Status Apps

759 stars271 forksGoMPL-2.0

At a glance

What is it?
status-go is the MPL 2.0 licensed Go library that carries most of the Status app business logic, and its most interesting part is the native token library, a pinned Nim and C dependency that has to be built per target and whose configuration flags have been removed rather than kept for compatibility. The judgement is that this is a project where the build system, not the application code, is where the engineering effort is visible.
Who is it for?
status-go fits a developer working on the Status app ecosystem who needs the wallet, the protocol and the token catalogue as a library rather than as a client, because the HTTP server mode in cmd/status-backend lets the same business logic run outside the mobile client. It is the wrong choice if you want a self-contained Go dependency, because the token catalogue is a native Nim and C library that has to be compiled, pinned and archived per target before anything will build.
Can I use it commercially?
Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The library that carries the app business logic

status-go is described as the backbone library of the Status App, acting as a backend for both applications and implementing most of the Status app business logic. That is an unusual shape for a project of this kind, because the app is the product and the library is where the logic lives, which means the mobile client, the desktop client and any service can all sit on the same code.

The readme points at a brief overview document for the full list of what the library covers, and it is marked as work in progress, which is a fair description of a piece of software that carries a wallet, a chat protocol and a token catalogue at once.

The documentation set is small and practical. There is a how-to-build page, a how-to-contribute guide, a how-to-release document, and a readme for running status-go as an HTTP server, which lives with the command in cmd/status-backend. That last one is the piece that matters for anyone outside the app, because it turns the library into a service that another program can call over HTTP.

The CI badges show two unit test jobs, one for the library and one for the RPC layer, plus a codecov report, and the last push to the repository was on 2026-10-20.

The Nim token library became the only token backend

The most detailed part of the readme concerns the token catalogue, and the change it describes is a simplification with a cost.

Status-go uses the public nim-token-lists Go wrapper and native library, pinned to the same revision. The make target build-libtkl prepares one checkout under build/deps/nim-token-lists including its pinned submodules, and it requires Git, Go, Nim 2.2.10 and the platform C toolchain. No separate library checkout and no local Go module replacement is needed, which removes two classic sources of build breakage.

The caching rules are explicit. An unchanged build reuses the checkout and the compiled archive, a changed compiler or build configuration rebuilds the archive, and if the source pin changes you run make clean to remove the managed checkout first. Cleanup does not remove the global Go module cache, and make test-libtkl checks the dependency and its ABI.

Then the breaking change. The C-backed Nim catalogue is now the sole token backend, the tkl build tag is no longer needed, and the configuration fields tokenListsUseNim and tokenListsShadow have been removed. Older JSON containing those names is decoded with them ignored. There is no runtime SDK rollback and no shadow comparison, and a rollback requires rebuilding an earlier version.

That last sentence is the one to sit with. A feature that could previously be turned off at runtime can now only be changed by shipping a different build.

Archives are per target, and a device archive is never a simulator archive

Because the token library is native, the build has to produce a different archive for every target, and the readme is unusually precise about how those archives are managed.

For controlled builds with prebuilt artefacts you supply both NIM_TKL_INC_DIR, holding tkl.h, and NIM_TKL_LIB_DIR, holding the isolated libtkl.a, and both must come from the recorded revision and the target. Nix and managed builds include a libtkl.target file beside the archive, recording GOOS and GOARCH, plus /iphoneos or /iphonesimulator for iOS. Prebuilt target metadata must match the requested build, and older archives without that metadata are accepted only for the host target.

The mobile Make targets discard inherited prebuilt paths and prepare their own target archive. The managed build covers Linux and macOS on amd64 and arm64, Windows on amd64 with MinGW, Android on arm64 and amd64, and iOS for the arm64 device and for the arm64 and amd64 simulators. Archives are kept separately under build/deps/nim-token-lists/build, with the target and the link step in the path, and the device and simulator archives are never reused for one another.

All targets share the same source checkout, so the revision is pinned once, and the archive is the part that varies. That design is the reason the metadata file exists at all: an archive on its own does not say which platform it was compiled for, and the file does.

Two make targets cover the mobile builds

The mobile builds are driven by two make targets, and the readme gives them as they are normally invoked:

sh
make statusgo-android-library ARCH=arm64 \
  ANDROID_NDK_ROOT="$ANDROID_NDK_ROOT" HOST_OS=darwin ANDROID_API=28
make statusgo-ios-library ARCH=arm64 \
  IPHONE_SDK=iphonesimulator IOS_TARGET=14.0

The Android side uses NDK 27.2.12479018 and API 28 or newer, and HOST_OS is set to linux when building on Linux, so the same target works from either host. The iOS side requires Xcode, with a minimum of iOS 13 for devices and for Intel simulators, and 14 for arm64 simulators. The token library is built with the same SDK and minimum as the Go consumer, which avoids the situation where the native half supports a platform the Go half does not.

For Linux cross builds you supply the target CC, TKL_LD, TKL_OBJCOPY and TKL_AR, while a native build uses the host tools. Windows builds run inside a MinGW64 shell with CC=gcc. The existing SDS build is unchanged by all of this.

For direct Go commands, the readme says to use bash scripts/tkl_env.sh go test with the arguments you want, or to source that script in the same shell first, which it notes enables strict shell mode. The script is what puts the compiled library and its include path in front of the Go toolchain.

Symbol visibility is decided at the final link

There is a layer of detail in the readme about export hiding that is unusual to find in a project readme, and it is the clearest statement of the trust boundary in the build.

For a shared library build, make statusgo-shared-library retains the existing libsds preparation and accepts the NIM_SDS_LIB_DIR and NIM_SDS_INC_DIR overrides for prebuilt inputs. TKL_NIM selects a compiler for the token lists only, while NIM shares the compiler with the other dependencies. Native changes invalidate Go's cgo cache, and source, build-option or output changes invalidate the backend cache.

The important rule is that shared library builds keep the tkl_* symbols private, and on Windows the managed archives have explicit DLL export directives removed. A supplied Windows prebuilt archive must likewise omit .drectve when exports are hidden. Static library builds bundle libtkl into libstatus.a, so the application does not need a separate token library linker input, and export hiding and verification still happen at the final application link.

So the token catalogue is an implementation detail of the library, and the guarantee is enforced at link time rather than by convention. That is a stronger property than simply not exporting something, and it is the sort of care that matters when the library is shipped inside a mobile application that other people build.

Verification scripts test the native boundary, not just the Go code

The test story extends past the Go unit tests, and it does so in a way that is easy to miss.

scripts/test_tkl_link.sh verifies a small Go shared library consumer on Linux, macOS, Android and Windows, and the Token library integration workflow checks native consumers and DLL exports. scripts/test_tkl_static.sh links a C application to the bundled Go archive on Linux, macOS, iOS and Windows, checks that the private exports really are private, and runs the result on the native host. make test-libtkl-coexistence checks both Nim runtimes in one process, using the existing SDS directory overrides or building SDS through its normal make prerequisite, and Jenkins runs that target in its Nix test environment, which already provides SDS.

The readme is explicit about what is not covered. Full application packaging and device runtime checks remain part of release validation, which is a sensible line to draw, because the scripts can run in CI while the final packaging depends on the release process.

Two build knobs exist for people who want to bring their own artefacts, NIM_TKL_INC_DIR and NIM_TKL_LIB_DIR, and both must come from the recorded revision and target. The Makefile itself has a generated help target with ANSI colours and categories, the release tag comes from a script at scripts/version.sh, and the lint binary is golangci-lint, with a configuration in .golangci.yml at the root.

Go 1.26, a forked dependency set and a version jump

The go.mod deserves a scan, because the set of replacements is unusual.

The module is github.com/status-im/status-go and it requires Go 1.26.0. The tool directives pull in go-bindata, a fast code generator, a goroutine defer guard, a coverage merger, mockgen and the protobuf compiler plugin, which is the toolchain a project of this size needs rather than an unusual dependency list.

The replace directives are the interesting part. notify is replaced with the status-im fork at version 1.0.2-status, the Docker engine is replaced, the resize library is replaced, gomoji is replaced, and go-sqlcipher is replaced with the status-im fork at v4.5.5. The libp2p pubsub library is replaced with the waku-org build tagged gowaku, which connects the project to the Waku network implementation.

The direct dependencies give the shape of the software: go-ethereum at v1.16.3 for the chain, libp2p and its pubsub for the peer to peer transport, go-multiaddr and go-cid for the addressing, anacrolix/torrent, kilic/bls12-381 for the cryptography, ipfs/go-cid, and the usual support libraries.

The container build shows the toolchain that goes with it, a Go 1.26.5 builder with Clang as the compiler, protoc 36.0 installed from prebuilt binaries with an architecture switch, and Nim 2.2.4 pulled from the nim-lang release index with the same kind of architecture handling.

The release history shows a version scheme change. The v0.179.x releases are from May 2024, v0.179.25 fixing the resend type for private group messages and v0.179.23 caching communities outside the chat loop, and the next listed release is v10.4.0 from 2025-02-18, which is a jump from a 0.x series to a 10.x one.

Editorial conclusion

status-go fits a developer working on the Status app ecosystem who needs the wallet, the protocol and the token catalogue as a library rather than as a client, because the HTTP server mode in cmd/status-backend lets the same business logic run outside the mobile client. It is the wrong choice if you want a self-contained Go dependency, because the token catalogue is a native Nim and C library that has to be compiled, pinned and archived per target before anything will build. It is also the wrong choice if you need a runtime switch between token backends, because the configuration fields for that were removed and older JSON is simply decoded with them ignored, so a rollback means rebuilding an earlier version. Before you build, read the token library section of the readme rather than the Go package list, and check which target you are producing, because device and simulator archives are never reused for one another.

Frequently asked questions

What is status-go?

It is the backbone library of the Status App, acting as a backend for both applications and implementing most of the Status app business logic. It can also be run as an HTTP server through the command in cmd/status-backend, and the licence is MPL 2.0.

What does the Nim token library dependency require?

The make target build-libtkl prepares a checkout under build/deps/nim-token-lists, and it requires Git, Go, Nim 2.2.10 and the platform C toolchain. No separate library checkout or local Go module replacement is needed, and make test-libtkl checks the dependency and its ABI.

Can I roll back the token catalogue at runtime?

No. The configuration fields tokenListsUseNim and tokenListsShadow have been removed, older JSON containing them is decoded with them ignored, and the readme states that a rollback requires rebuilding an earlier version.

How are prebuilt token library artefacts handled?

You supply NIM_TKL_INC_DIR with tkl.h and NIM_TKL_LIB_DIR with the isolated libtkl.a, both from the recorded revision and target. Managed builds also record GOOS and GOARCH in a libtkl.target file beside the archive, and device and simulator archives are never reused for one another.

Official sources

  1. License: MPL-2.0
  2. Project website
  3. README
  4. Releases
  5. status-im/status-go on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/status-im-status-go.svg)](https://hysenlabs.com/projects/status-im-status-go)

Was this useful?