Merge pull request #10 from status-im/feat/build-system

feat: include nimbus-build-system and initial version of the Makefile to generate a static library
This commit is contained in:
Iuri Matias 2020-07-08 12:31:29 -04:00 committed by GitHub
commit f493853581
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1090 additions and 0 deletions

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
.idea
.vscode
bin/
build/
vendor/.nimble
tmp
nimcache
.DS_Store
TODO
nim_status
test/test
data/
keystore/
noBackup/

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "vendor/nimbus-build-system"]
path = vendor/nimbus-build-system
url = https://github.com/status-im/nimbus-build-system
[submodule "vendor/status-go"]
path = vendor/status-go
url = https://github.com/status-im/status-go

148
Makefile Normal file
View File

@ -0,0 +1,148 @@
# Copyright (c) 2020 Status Research & Development GmbH. Licensed under
# either of:
# - Apache License, version 2.0
# - MIT license
# at your option. This file may not be copied, modified, or distributed except
# according to those terms.
SHELL := bash # the shell used internally by Make
# used inside the included makefiles
BUILD_SYSTEM_DIR := vendor/nimbus-build-system
# we don't want an error here, so we can handle things later, in the ".DEFAULT" target
-include $(BUILD_SYSTEM_DIR)/makefiles/variables.mk
.PHONY: \
all \
bottles \
bottles-dummy \
bottles-macos \
clean \
deps \
nim_status \
update \
tests
ifeq ($(NIM_PARAMS),)
# "variables.mk" was not included, so we update the submodules.
GIT_SUBMODULE_UPDATE := git submodule update --init --recursive
.DEFAULT:
+@ echo -e "Git submodules not found. Running '$(GIT_SUBMODULE_UPDATE)'.\n"; \
$(GIT_SUBMODULE_UPDATE); \
echo
# Now that the included *.mk files appeared, and are newer than this file, Make will restart itself:
# https://www.gnu.org/software/make/manual/make.html#Remaking-Makefiles
#
# After restarting, it will execute its original goal, so we don't have to start a child Make here
# with "$(MAKE) $(MAKECMDGOALS)". Isn't hidden control flow great?
else # "variables.mk" was included. Business as usual until the end of this file.
all: nim_status
# must be included after the default target
-include $(BUILD_SYSTEM_DIR)/makefiles/targets.mk
ifeq ($(OS),Windows_NT) # is Windows_NT on XP, 2000, 7, Vista, 10...
detected_OS := Windows
else
detected_OS := $(strip $(shell uname))
endif
ifeq ($(detected_OS), Darwin)
BOTTLES_TARGET := bottles-macos
MACOSX_DEPLOYMENT_TARGET := 10.13
export MACOSX_DEPLOYMENT_TARGET
CGO_CFLAGS := -mmacosx-version-min=10.13
export CGO_CFLAGS
CFLAGS := -mmacosx-version-min=10.13
export CFLAGS
else
BOTTLES_TARGET := bottles-dummy
endif
bottles: $(BOTTLES_TARGET)
bottles-dummy: ;
BOTTLE_OPENSSL := bottles/openssl/INSTALL_RECEIPT.json
$(BOTTLE_OPENSSL):
rm -rf bottles/Downloads/openssl* bottles/openssl*
mkdir -p bottles/Downloads
cd bottles/Downloads && \
wget -O openssl.tar.gz "https://bintray.com/homebrew/bottles/download_file?file_path=openssl%401.1-1.1.1g.high_sierra.bottle.tar.gz" && \
tar xzf openssl* && \
mv openssl@1.1/1.1.1g ../openssl
BOTTLE_PCRE := bottles/pcre/INSTALL_RECEIPT.json
$(BOTTLE_PCRE):
rm -rf bottles/Downloads/pcre* bottles/pcre*
mkdir -p bottles/Downloads
cd bottles/Downloads && \
wget -O pcre.tar.gz "https://bintray.com/homebrew/bottles/download_file?file_path=pcre-8.44.high_sierra.bottle.tar.gz" && \
tar xzf pcre* && \
mv pcre/8.44 ../pcre
bottles-macos: | $(BOTTLE_OPENSSL) $(BOTTLE_PCRE)
rm -rf bottles/Downloads
ifeq ($(detected_OS), Darwin)
NIM_PARAMS := $(NIM_PARAMS) -L:"-framework Foundation -framework Security -framework IOKit -framework CoreServices"
endif
# TODO: control debug/release builds with a Make var
# We need `-d:debug` to get Nim's default stack traces.
NIM_PARAMS += -d:debug
deps: | deps-common
update: | update-common
STATUSGO := vendor/status-go/build/bin/libstatus.a
$(STATUSGO): | deps
echo -e $(BUILD_MSG) "status-go"
+ cd vendor/status-go && \
$(MAKE) statusgo-library $(HANDLE_OUTPUT)
clean: | clean-common clean-build-dir
rm -rf $(STATUSGO)
rm keystore
rm data
rm noBackup
clean-build-dir:
rm -rf build/*
NIMSTATUS := build/nim_status.a
$(NIMSTATUS): | build deps
echo -e $(BUILD_MSG) "$@" && \
$(ENV_SCRIPT) nim c $(NIM_PARAMS) --app:staticLib --header --noMain --nimcache:nimcache/nim_status -o:$@ src/nim_status.nim
cp nimcache/nim_status/nim_status.h build/.
mv nim_status.a build/.
nim_status: | clean-build-dir $(NIMSTATUS)
tests: | $(NIMSTATUS) $(STATUSGO)
rm -Rf keystore
rm -Rf data
rm -Rf noBackup
mkdir -p data
mkdir -p noBackup
mkdir -p keystore
echo "Compiling 'test/test'"
ifeq ($(detected_OS), Darwin)
$(CC) -I"$(CURDIR)/build" -I"$(CURDIR)/vendor/nimbus-build-system/vendor/Nim/lib" test/test.c $(NIMSTATUS) $(STATUSGO) -framework CoreFoundation -framework CoreServices -framework IOKit -framework Security -lm -pthread -o test/test
else
$(CC) -I"$(CURDIR)/build" -I"$(CURDIR)/vendor/nimbus-build-system/vendor/Nim/lib" test/test.c $(NIMSTATUS) $(STATUSGO) -lm -pthread -o test/test
endif
echo "Executing 'test/test'"
./test/test
endif # "variables.mk" was not included

View File

@ -3,3 +3,43 @@
Nim implementation of the Status protocol: https://github.com/status-im/specs
Corresponds roughly to status-go: https://github.com/status-im/status-go which is consumed by status-react: https://github.com/status-im/status-react/
### Requirements
* Go - (used to build status-go)
```
# Linux
<TODO>
# macOS
brew install go
```
### Installation
```
git clone https://github.com/status-im/nim-status
cd nim-status
make update
make
```
For more output use `make V=1 ...`.
Use 4 CPU cores with `make -j4 ...`.
### Usage
- Include `build/nim_status.a`, `build/nim_status.h` in your project
- Before any of the API calls are done, NimMain() needs to be run.
### Troubleshooting
If the `make` command fails due to already installed Homebrew packages, such as:
```
Error: protobuf 3.11.4 is already installed
To upgrade to 3.11.4_1, run `brew upgrade protobuf`.
make[1]: *** [install-os-dependencies] Error 1
make: *** [vendor/status-go/build/bin/libstatus.a] Error 2
```
This can be fixed by uninstalling the package e.g. `brew uninstall protobuf` followed by rerunning `make`.

41
config.nims Normal file
View File

@ -0,0 +1,41 @@
when defined(macosx):
import algorithm, strutils
if defined(release):
switch("nimcache", "nimcache/release/$projectName")
else:
switch("nimcache", "nimcache/debug/$projectName")
--threads:on
--opt:speed # -O3
--debugger:native # passes "-g" to the C compiler
--dynliboverrideall # don't use dlopen()
--define:ssl # needed by the stdlib to enable SSL procedures
if defined(macosx):
--tlsEmulation:off
switch("passL", "-lstdc++")
# statically linke these libs
switch("passL", "bottles/openssl/lib/libcrypto.a")
switch("passL", "bottles/openssl/lib/libssl.a")
switch("passL", "bottles/pcre/lib/libpcre.a")
# https://code.videolan.org/videolan/VLCKit/-/issues/232
switch("passL", "-Wl,-no_compact_unwind")
# set the minimum supported macOS version to 10.13
switch("passC", "-mmacosx-version-min=10.13")
else:
# dynamically link these libs, since we're opting out of dlopen()
switch("passL", "-lcrypto")
switch("passL", "-lssl")
# don't link libraries we're not actually using
switch("passL", "-Wl,-as-needed")
--define:chronicles_line_numbers # useful when debugging
# The compiler doth protest too much, methinks, about all these cases where it can't
# do its (N)RVO pass: https://github.com/nim-lang/RFCs/issues/230
switch("warning", "ObservableStores:off")
# Too many false positives for "Warning: method has lock level <unknown>, but another method has 0 [LockLevel]"
switch("warning", "LockLevel:off")

8
env.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash
# We use ${BASH_SOURCE[0]} instead of $0 to allow sourcing this file
# and we fall back to a Zsh-specific special var to also support Zsh.
REL_PATH="$(dirname ${BASH_SOURCE[0]:-${(%):-%x}})"
ABS_PATH="$(cd ${REL_PATH}; pwd)"
source ${ABS_PATH}/vendor/nimbus-build-system/scripts/env.sh

3
nim.cfg Normal file
View File

@ -0,0 +1,3 @@
# we need to link C++ libraries
gcc.linkerexe="g++"

13
nim_status.nimble Normal file
View File

@ -0,0 +1,13 @@
# Package
version = "0.1.0"
author = "Status Research & Development GmbH"
description = "Nim implementation of the Status protocol"
license = "MIT"
srcDir = "src"
bin = @[""]
skipDirs = @["test"]
# Deps
requires "nim >= 1.0.0"

161
src/nim_status.nim Normal file
View File

@ -0,0 +1,161 @@
import status_go
import types
# All procs start with lowercase because the compiler will also need to import status-go,
# and it will complain of duplication of function names
proc hashMessage*(message: cstring): cstring {.exportc.} =
result = status_go.HashMessage(message)
proc initKeystore*(keydir: cstring): cstring {.exportc.} =
result = status_go.InitKeystore(keydir)
proc openAccounts*(datadir: cstring): cstring {.exportc.} =
result = status_go.OpenAccounts(datadir)
proc multiAccountGenerateAndDeriveAddresses*(paramsJSON: cstring): cstring {.exportc.} =
result = status_go.MultiAccountGenerateAndDeriveAddresses(paramsJSON)
proc multiAccountStoreDerivedAccounts*(paramsJSON: cstring): cstring {.exportc.} =
result = status_go.MultiAccountStoreDerivedAccounts(paramsJSON)
proc multiAccountImportMnemonic*(paramsJSON: cstring): cstring {.exportc.} =
result = status_go.MultiAccountImportMnemonic(paramsJSON)
proc multiAccountImportPrivateKey*(paramsJSON: cstring): cstring {.exportc.} =
result = status_go.MultiAccountImportPrivateKey(paramsJSON)
proc multiAccountDeriveAddresses*(paramsJSON: cstring): cstring {.exportc.} =
result = status_go.MultiAccountDeriveAddresses(paramsJSON)
proc saveAccountAndLogin*(accountData: cstring, password: cstring, settingsJSON: cstring, configJSON: cstring, subaccountData: cstring): cstring {.exportc.} =
result = status_go.SaveAccountAndLogin(accountData, password, settingsJSON, configJSON, subaccountData)
proc callRPC*(inputJSON: cstring): cstring {.exportc.} =
result = status_go.CallRPC(inputJSON)
proc callPrivateRPC*(inputJSON: cstring): cstring {.exportc.} =
result = status_go.CallPrivateRPC(inputJSON)
proc addPeer*(peer: cstring): cstring {.exportc.} =
result = status_go.AddPeer(peer)
proc setSignalEventCallback*(callback: SignalCallback) {.exportc.} =
status_go.SetSignalEventCallback(callback)
proc sendTransaction*(jsonArgs: cstring, password: cstring): cstring {.exportc.} =
result = status_go.SendTransaction(jsonArgs, password)
proc generateAlias*(pk: GoString): cstring {.exportc.} =
result = status_go.GenerateAlias(pk)
proc identicon*(pk: GoString): cstring {.exportc.} =
result = status_go.Identicon(pk)
proc login*(accountData: cstring, password: cstring): cstring {.exportc.} =
result = status_go.Login(accountData, password)
proc logout*(): cstring {.exportc.} =
result = status_go.Logout()
proc verifyAccountPassword*(keyStoreDir: cstring, address: cstring, password: cstring): cstring {.exportc.} =
result = status_go.VerifyAccountPassword(keyStoreDir, address, password)
proc validateMnemonic*(mnemonic: cstring): cstring {.exportc.} =
result = status_go.ValidateMnemonic(mnemonic)
proc recoverAccount(password: cstring, mnemonic: cstring): cstring {.exportc.} =
result = status_go.RecoverAccount(password, mnemonic)
proc startOnboarding(n: cint, mnemonicPhraseLength: cint): cstring {.exportc.} =
result = status_go.StartOnboarding(n, mnemonicPhraseLength)
proc saveAccountAndLoginWithKeycard(accountData: cstring, password: cstring, settingsJSON: cstring, configJSON: cstring, subaccountData: cstring, keyHex: cstring): cstring {.exportc.} =
result = status_go.SaveAccountAndLoginWithKeycard(accountData, password, settingsJSON, configJSON, subaccountData, keyHex)
proc hashTransaction(txArgsJSON: cstring): cstring {.exportc.} =
result = status_go.HashTransaction(txArgsJSON)
proc extractGroupMembershipSignatures(signaturePairsStr: cstring): cstring {.exportc.} =
result = status_go.ExtractGroupMembershipSignatures(signaturePairsStr)
proc connectionChange(typ: cstring, expensive: cstring) {.exportc.} =
status_go.ConnectionChange(typ, expensive)
proc multiformatSerializePublicKey(key: cstring, outBase: cstring): cstring {.exportc.} =
result = status_go.MultiformatSerializePublicKey(key, outBase)
proc multiformatDeserializePublicKey(key: cstring, outBase: cstring): cstring {.exportc.} =
result = status_go.MultiformatDeserializePublicKey(key, outBase)
proc validateNodeConfig(configJSON: cstring): cstring {.exportc.} =
result = status_go.ValidateNodeConfig(configJSON)
proc loginWithKeycard(accountData: cstring, password: cstring, keyHex: cstring): cstring {.exportc.} =
result = status_go.LoginWithKeycard(accountData, password, keyHex)
proc recover(rpcParams: cstring): cstring {.exportc.} =
result = status_go.Recover(rpcParams)
proc writeHeapProfile(dataDir: cstring): cstring {.exportc.} =
result = status_go.WriteHeapProfile(dataDir)
proc importOnboardingAccount(id: cstring, password: cstring): cstring {.exportc.} =
result = status_go.ImportOnboardingAccount(id, password)
proc removeOnboarding() {.exportc.} =
status_go.RemoveOnboarding()
proc hashTypedData(data: cstring): cstring {.exportc.} =
result = status_go.HashTypedData(data)
proc resetChainData(): cstring {.exportc.} =
result = status_go.ResetChainData()
proc signMessage(rpcParams: cstring): cstring {.exportc.} =
result = status_go.SignMessage(rpcParams)
proc signTypedData(data: cstring, address: cstring, password: cstring): cstring {.exportc.} =
result = status_go.SignTypedData(data, address, password)
proc stopCPUProfiling(): cstring {.exportc.} =
result = status_go.StopCPUProfiling()
proc getNodesFromContract(rpcEndpoint: cstring, contractAddress: cstring): cstring {.exportc.} =
result = status_go.GetNodesFromContract(rpcEndpoint, contractAddress)
proc exportNodeLogs(): cstring {.exportc.} =
result = status_go.ExportNodeLogs()
proc chaosModeUpdate(on: cint): cstring {.exportc.} =
result = status_go.ChaosModeUpdate(on)
proc signHash(hexEncodedHash: cstring): cstring {.exportc.} =
result = status_go.SignHash(hexEncodedHash)
proc createAccount(password: cstring): cstring {.exportc.} =
result = status_go.CreateAccount(password)
proc sendTransactionWithSignature(txtArgsJSON: cstring, sigString: cstring): cstring {.exportc.} =
result = status_go.SendTransactionWithSignature(txtArgsJSON, sigString)
proc startCPUProfile(dataDir: cstring): cstring {.exportc.} =
result = status_go.StartCPUProfile(dataDir)
proc appStateChange(state: cstring) {.exportc.} =
status_go.AppStateChange(state)
proc signGroupMembership(content: cstring): cstring {.exportc.} =
result = status_go.SignGroupMembership(content)
proc multiAccountStoreAccount(paramsJSON: cstring): cstring {.exportc.} =
result = status_go.MultiAccountStoreAccount(paramsJSON)
proc multiAccountLoadAccount(paramsJSON: cstring): cstring {.exportc.} =
result = status_go.MultiAccountLoadAccount(paramsJSON)
proc multiAccountGenerate(paramsJSON: cstring): cstring {.exportc.} =
result = status_go.MultiAccountGenerate(paramsJSON)
proc multiAccountReset(): cstring {.exportc.} =
result = status_go.MultiAccountReset()

105
src/status_go.nim Normal file
View File

@ -0,0 +1,105 @@
import types
proc HashMessage*(message: cstring): cstring {.importc: "HashMessage".}
proc InitKeystore*(keydir: cstring): cstring {.importc: "InitKeystore".}
proc OpenAccounts*(datadir: cstring): cstring {.importc: "OpenAccounts".}
proc MultiAccountGenerateAndDeriveAddresses*(paramsJSON: cstring): cstring {.importc: "MultiAccountGenerateAndDeriveAddresses".}
proc MultiAccountStoreDerivedAccounts*(paramsJSON: cstring): cstring {.importc: "MultiAccountStoreDerivedAccounts".}
proc MultiAccountImportMnemonic*(paramsJSON: cstring): cstring {.importc: "MultiAccountImportMnemonic".}
proc MultiAccountImportPrivateKey*(paramsJSON: cstring): cstring {.importc: "MultiAccountImportPrivateKey".}
proc MultiAccountDeriveAddresses*(paramsJSON: cstring): cstring {.importc: "MultiAccountDeriveAddresses".}
proc SaveAccountAndLogin*(accountData: cstring, password: cstring, settingsJSON: cstring, configJSON: cstring, subaccountData: cstring): cstring {.importc: "SaveAccountAndLogin".}
proc CallRPC*(inputJSON: cstring): cstring {.importc: "CallRPC".}
proc CallPrivateRPC*(inputJSON: cstring): cstring {.importc: "CallPrivateRPC".}
proc AddPeer*(peer: cstring): cstring {.importc: "AddPeer".}
proc SetSignalEventCallback*(callback: SignalCallback) {.importc: "SetSignalEventCallback".}
proc SendTransaction*(jsonArgs: cstring, password: cstring): cstring {.importc: "SendTransaction".}
proc GenerateAlias*(pk: GoString): cstring {.importc: "GenerateAlias".}
proc Identicon*(pk: GoString): cstring {.importc: "Identicon".}
proc Login*(accountData: cstring, password: cstring): cstring {.importc: "Login".}
proc Logout*(): cstring {.importc: "Logout".}
proc VerifyAccountPassword*(keyStoreDir: cstring, address: cstring, password: cstring): cstring {.importc: "VerifyAccountPassword".}
proc ValidateMnemonic*(mnemonic: cstring): cstring {.importc: "ValidateMnemonic".}
proc RecoverAccount*(password: cstring, mnemonic: cstring): cstring {.importc: "RecoverAccount".}
proc StartOnboarding*(n: cint, mnemonicPhraseLength: cint): cstring {.importc: "StartOnboarding".}
proc SaveAccountAndLoginWithKeycard*(accountData: cstring, password: cstring, settingsJSON: cstring, configJSON: cstring, subaccountData: cstring, keyHex: cstring): cstring {.importc: "SaveAccountAndLoginWithKeycard".}
proc HashTransaction*(txArgsJSON: cstring): cstring {.importc: "HashTransaction".}
proc ExtractGroupMembershipSignatures*(signaturePairsStr: cstring): cstring {.importc: "ExtractGroupMembershipSignatures".}
proc ConnectionChange*(typ: cstring, expensive: cstring) {.importc: "ConnectionChange".}
proc MultiformatSerializePublicKey*(key: cstring, outBase: cstring): cstring {.importc: "MultiformatSerializePublicKey".}
proc MultiformatDeserializePublicKey*(key: cstring, outBase: cstring): cstring {.importc: "MultiformatDeserializePublicKey".}
proc ValidateNodeConfig*(configJSON: cstring): cstring {.importc: "ValidateNodeConfig".}
proc LoginWithKeycard*(accountData: cstring, password: cstring, keyHex: cstring): cstring {.importc: "LoginWithKeycard".}
proc Recover*(rpcParams: cstring): cstring {.importc: "Recover".}
proc WriteHeapProfile*(dataDir: cstring): cstring {.importc: "WriteHeapProfile".}
proc ImportOnboardingAccount*(id: cstring, password: cstring): cstring {.importc: "ImportOnboardingAccount".}
proc RemoveOnboarding*() {.importc: "RemoveOnboarding".}
proc HashTypedData*(data: cstring): cstring {.importc: "HashTypedData".}
proc ResetChainData*(): cstring {.importc: "ResetChainData".}
proc SignMessage*(rpcParams: cstring): cstring {.importc: "SignMessage".}
proc SignTypedData*(data: cstring, address: cstring, password: cstring): cstring {.importc: "SignTypedData".}
proc StopCPUProfiling*(): cstring {.importc: "StopCPUProfiling".}
proc GetNodesFromContract*(rpcEndpoint: cstring, contractAddress: cstring): cstring {.importc: "GetNodesFromContract".}
proc ExportNodeLogs*(): cstring {.importc: "ExportNodeLogs".}
proc ChaosModeUpdate*(on: cint): cstring {.importc: "ChaosModeUpdate".}
proc SignHash*(hexEncodedHash: cstring): cstring {.importc: "SignHash".}
proc CreateAccount*(password: cstring): cstring {.importc: "CreateAccount".}
proc SendTransactionWithSignature*(txtArgsJSON: cstring, sigString: cstring): cstring {.importc: "SendTransactionWithSignature".}
proc StartCPUProfile*(dataDir: cstring): cstring {.importc: "StartCPUProfile".}
proc AppStateChange*(state: cstring) {.importc: "AppStateChange".}
proc SignGroupMembership*(content: cstring): cstring {.importc: "SignGroupMembership".}
proc MultiAccountStoreAccount*(paramsJSON: cstring): cstring {.importc: "MultiAccountStoreAccount".}
proc MultiAccountLoadAccount*(paramsJSON: cstring): cstring {.importc: "MultiAccountLoadAccount".}
proc MultiAccountGenerate*(paramsJSON: cstring): cstring {.importc: "MultiAccountGenerate".}
proc MultiAccountReset*(): cstring {.importc: "MultiAccountReset".}

6
src/types.nim Normal file
View File

@ -0,0 +1,6 @@
type
GoString* {.exportc:"GoString".} = object
str*: cstring
length*: cint
type SignalCallback* {.exportc:"SignalCallback"} = proc(eventMessage: cstring): void {.cdecl.}

387
test/nxjson.c Normal file
View File

@ -0,0 +1,387 @@
/*
* Copyright (c) 2013 Yaroslav Stavnichiy <yarosla@gmail.com>
*
* This file is part of NXJSON.
*
* NXJSON is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* NXJSON is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with NXJSON. If not, see <http://www.gnu.org/licenses/>.
*/
// this file can be #included in your code
#ifndef NXJSON_C
#define NXJSON_C
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include "nxjson.h"
// redefine NX_JSON_CALLOC & NX_JSON_FREE to use custom allocator
#ifndef NX_JSON_CALLOC
#define NX_JSON_CALLOC() calloc(1, sizeof(nx_json))
#define NX_JSON_FREE(json) free((void*)(json))
#endif
// redefine NX_JSON_REPORT_ERROR to use custom error reporting
#ifndef NX_JSON_REPORT_ERROR
#define NX_JSON_REPORT_ERROR(msg, p) fprintf(stderr, "NXJSON PARSE ERROR (%d): " msg " at %s\n", __LINE__, p)
#endif
#define IS_WHITESPACE(c) ((unsigned char)(c)<=(unsigned char)' ')
static const nx_json dummy={ NX_JSON_NULL };
static nx_json* create_json(nx_json_type type, const char* key, nx_json* parent) {
nx_json* js=NX_JSON_CALLOC();
assert(js);
js->type=type;
js->key=key;
if (!parent->last_child) {
parent->child=parent->last_child=js;
}
else {
parent->last_child->next=js;
parent->last_child=js;
}
parent->length++;
return js;
}
void nx_json_free(const nx_json* js) {
nx_json* p=js->child;
nx_json* p1;
while (p) {
p1=p->next;
nx_json_free(p);
p=p1;
}
NX_JSON_FREE(js);
}
static int unicode_to_utf8(unsigned int codepoint, char* p, char** endp) {
// code from http://stackoverflow.com/a/4609989/697313
if (codepoint<0x80) *p++=codepoint;
else if (codepoint<0x800) *p++=192+codepoint/64, *p++=128+codepoint%64;
else if (codepoint-0xd800u<0x800) return 0; // surrogate must have been treated earlier
else if (codepoint<0x10000) *p++=224+codepoint/4096, *p++=128+codepoint/64%64, *p++=128+codepoint%64;
else if (codepoint<0x110000) *p++=240+codepoint/262144, *p++=128+codepoint/4096%64, *p++=128+codepoint/64%64, *p++=128+codepoint%64;
else return 0; // error
*endp=p;
return 1;
}
nx_json_unicode_encoder nx_json_unicode_to_utf8=unicode_to_utf8;
static inline int hex_val(char c) {
if (c>='0' && c<='9') return c-'0';
if (c>='a' && c<='f') return c-'a'+10;
if (c>='A' && c<='F') return c-'A'+10;
return -1;
}
static char* unescape_string(char* s, char** end, nx_json_unicode_encoder encoder) {
char* p=s;
char* d=s;
char c;
while ((c=*p++)) {
if (c=='"') {
*d='\0';
*end=p;
return s;
}
else if (c=='\\') {
switch (*p) {
case '\\':
case '/':
case '"':
*d++=*p++;
break;
case 'b':
*d++='\b'; p++;
break;
case 'f':
*d++='\f'; p++;
break;
case 'n':
*d++='\n'; p++;
break;
case 'r':
*d++='\r'; p++;
break;
case 't':
*d++='\t'; p++;
break;
case 'u': // unicode
if (!encoder) {
// leave untouched
*d++=c;
break;
}
char* ps=p-1;
int h1, h2, h3, h4;
if ((h1=hex_val(p[1]))<0 || (h2=hex_val(p[2]))<0 || (h3=hex_val(p[3]))<0 || (h4=hex_val(p[4]))<0) {
NX_JSON_REPORT_ERROR("invalid unicode escape", p-1);
return 0;
}
unsigned int codepoint=h1<<12|h2<<8|h3<<4|h4;
if ((codepoint & 0xfc00)==0xd800) { // high surrogate; need one more unicode to succeed
p+=6;
if (p[-1]!='\\' || *p!='u' || (h1=hex_val(p[1]))<0 || (h2=hex_val(p[2]))<0 || (h3=hex_val(p[3]))<0 || (h4=hex_val(p[4]))<0) {
NX_JSON_REPORT_ERROR("invalid unicode surrogate", ps);
return 0;
}
unsigned int codepoint2=h1<<12|h2<<8|h3<<4|h4;
if ((codepoint2 & 0xfc00)!=0xdc00) {
NX_JSON_REPORT_ERROR("invalid unicode surrogate", ps);
return 0;
}
codepoint=0x10000+((codepoint-0xd800)<<10)+(codepoint2-0xdc00);
}
if (!encoder(codepoint, d, &d)) {
NX_JSON_REPORT_ERROR("invalid codepoint", ps);
return 0;
}
p+=5;
break;
default:
// leave untouched
*d++=c;
break;
}
}
else {
*d++=c;
}
}
NX_JSON_REPORT_ERROR("no closing quote for string", s);
return 0;
}
static char* skip_block_comment(char* p) {
// assume p[-2]=='/' && p[-1]=='*'
char* ps=p-2;
if (!*p) {
NX_JSON_REPORT_ERROR("endless comment", ps);
return 0;
}
REPEAT:
p=strchr(p+1, '/');
if (!p) {
NX_JSON_REPORT_ERROR("endless comment", ps);
return 0;
}
if (p[-1]!='*') goto REPEAT;
return p+1;
}
static char* parse_key(const char** key, char* p, nx_json_unicode_encoder encoder) {
// on '}' return with *p=='}'
char c;
while ((c=*p++)) {
if (c=='"') {
*key=unescape_string(p, &p, encoder);
if (!*key) return 0; // propagate error
while (*p && IS_WHITESPACE(*p)) p++;
if (*p==':') return p+1;
NX_JSON_REPORT_ERROR("unexpected chars", p);
return 0;
}
else if (IS_WHITESPACE(c) || c==',') {
// continue
}
else if (c=='}') {
return p-1;
}
else if (c=='/') {
if (*p=='/') { // line comment
char* ps=p-1;
p=strchr(p+1, '\n');
if (!p) {
NX_JSON_REPORT_ERROR("endless comment", ps);
return 0; // error
}
p++;
}
else if (*p=='*') { // block comment
p=skip_block_comment(p+1);
if (!p) return 0;
}
else {
NX_JSON_REPORT_ERROR("unexpected chars", p-1);
return 0; // error
}
}
else {
NX_JSON_REPORT_ERROR("unexpected chars", p-1);
return 0; // error
}
}
NX_JSON_REPORT_ERROR("unexpected chars", p-1);
return 0; // error
}
static char* parse_value(nx_json* parent, const char* key, char* p, nx_json_unicode_encoder encoder) {
nx_json* js;
while (1) {
switch (*p) {
case '\0':
NX_JSON_REPORT_ERROR("unexpected end of text", p);
return 0; // error
case ' ': case '\t': case '\n': case '\r':
case ',':
// skip
p++;
break;
case '{':
js=create_json(NX_JSON_OBJECT, key, parent);
p++;
while (1) {
const char* new_key;
p=parse_key(&new_key, p, encoder);
if (!p) return 0; // error
if (*p=='}') return p+1; // end of object
p=parse_value(js, new_key, p, encoder);
if (!p) return 0; // error
}
case '[':
js=create_json(NX_JSON_ARRAY, key, parent);
p++;
while (1) {
p=parse_value(js, 0, p, encoder);
if (!p) return 0; // error
if (*p==']') return p+1; // end of array
}
case ']':
return p;
case '"':
p++;
js=create_json(NX_JSON_STRING, key, parent);
js->text_value=unescape_string(p, &p, encoder);
if (!js->text_value) return 0; // propagate error
return p;
case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
{
js=create_json(NX_JSON_INTEGER, key, parent);
char* pe;
js->int_value=strtoll(p, &pe, 0);
if (pe==p || errno==ERANGE) {
NX_JSON_REPORT_ERROR("invalid number", p);
return 0; // error
}
if (*pe=='.' || *pe=='e' || *pe=='E') { // double value
js->type=NX_JSON_DOUBLE;
js->dbl_value=strtod(p, &pe);
if (pe==p || errno==ERANGE) {
NX_JSON_REPORT_ERROR("invalid number", p);
return 0; // error
}
}
else {
js->dbl_value=js->int_value;
}
return pe;
}
case 't':
if (!strncmp(p, "true", 4)) {
js=create_json(NX_JSON_BOOL, key, parent);
js->int_value=1;
return p+4;
}
NX_JSON_REPORT_ERROR("unexpected chars", p);
return 0; // error
case 'f':
if (!strncmp(p, "false", 5)) {
js=create_json(NX_JSON_BOOL, key, parent);
js->int_value=0;
return p+5;
}
NX_JSON_REPORT_ERROR("unexpected chars", p);
return 0; // error
case 'n':
if (!strncmp(p, "null", 4)) {
create_json(NX_JSON_NULL, key, parent);
return p+4;
}
NX_JSON_REPORT_ERROR("unexpected chars", p);
return 0; // error
case '/': // comment
if (p[1]=='/') { // line comment
char* ps=p;
p=strchr(p+2, '\n');
if (!p) {
NX_JSON_REPORT_ERROR("endless comment", ps);
return 0; // error
}
p++;
}
else if (p[1]=='*') { // block comment
p=skip_block_comment(p+2);
if (!p) return 0;
}
else {
NX_JSON_REPORT_ERROR("unexpected chars", p);
return 0; // error
}
break;
default:
NX_JSON_REPORT_ERROR("unexpected chars", p);
return 0; // error
}
}
}
const nx_json* nx_json_parse_utf8(char* text) {
return nx_json_parse(text, unicode_to_utf8);
}
const nx_json* nx_json_parse(char* text, nx_json_unicode_encoder encoder) {
nx_json js={0};
if (!parse_value(&js, 0, text, encoder)) {
if (js.child) nx_json_free(js.child);
return 0;
}
return js.child;
}
const nx_json* nx_json_get(const nx_json* json, const char* key) {
if (!json || !key) return &dummy; // never return null
nx_json* js;
for (js=json->child; js; js=js->next) {
if (js->key && !strcmp(js->key, key)) return js;
}
return &dummy; // never return null
}
const nx_json* nx_json_item(const nx_json* json, int idx) {
if (!json) return &dummy; // never return null
nx_json* js;
for (js=json->child; js; js=js->next) {
if (!idx--) return js;
}
return &dummy; // never return null
}
#ifdef __cplusplus
}
#endif
#endif /* NXJSON_C */

65
test/nxjson.h Normal file
View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2013 Yaroslav Stavnichiy <yarosla@gmail.com>
*
* This file is part of NXJSON.
*
* NXJSON is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* NXJSON is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with NXJSON. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NXJSON_H
#define NXJSON_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum nx_json_type {
NX_JSON_NULL, // this is null value
NX_JSON_OBJECT, // this is an object; properties can be found in child nodes
NX_JSON_ARRAY, // this is an array; items can be found in child nodes
NX_JSON_STRING, // this is a string; value can be found in text_value field
NX_JSON_INTEGER, // this is an integer; value can be found in int_value field
NX_JSON_DOUBLE, // this is a double; value can be found in dbl_value field
NX_JSON_BOOL // this is a boolean; value can be found in int_value field
} nx_json_type;
typedef struct nx_json {
nx_json_type type; // type of json node, see above
const char* key; // key of the property; for object's children only
const char* text_value; // text value of STRING node
long long int_value; // the value of INTEGER or BOOL node
double dbl_value; // the value of DOUBLE node
int length; // number of children of OBJECT or ARRAY
struct nx_json* child; // points to first child
struct nx_json* next; // points to next child
struct nx_json* last_child;
} nx_json;
typedef int (*nx_json_unicode_encoder)(unsigned int codepoint, char* p, char** endp);
extern nx_json_unicode_encoder nx_json_unicode_to_utf8;
const nx_json* nx_json_parse(char* text, nx_json_unicode_encoder encoder);
const nx_json* nx_json_parse_utf8(char* text);
void nx_json_free(const nx_json* js);
const nx_json* nx_json_get(const nx_json* json, const char* key); // get object's property by key
const nx_json* nx_json_item(const nx_json* json, int idx); // get array element by index
#ifdef __cplusplus
}
#endif
#endif /* NXJSON_H */

91
test/test.c Normal file
View File

@ -0,0 +1,91 @@
#include <stdio.h>
#include <string.h>
#include "nim_status.h"
#include "nxjson.c"
#include <unistd.h>
void eventCallback(const char *event) {
printf("SIGNAL RECEIVED:\n%s\n", event);
}
int main(int argc, char* argv[]) {
NimMain();
const char* theMessage = hashMessage("Hello World!");
printf("HashMessage: %s\n\n", theMessage);
char* pubKey = "0x0441ccda1563d69ac6b2e53718973c4e7280b4a5d8b3a09bb8bce9ebc5f082778243f1a04ec1f7995660482ca4b966ab0044566141ca48d7cdef8b7375cd5b7af5";
struct GoString p1 = {pubKey, strlen(pubKey)};
const char* theIdenticon = identicon(p1);
printf("Identicon: %s\n\n", theIdenticon);
printf("Creating an account, login and receive signals:\n");
char* initKeystoreResult = initKeystore("./data");
printf("1. InitKeystore:\n%s\n\n", initKeystoreResult);
char* openAccountsResults = openAccounts("./noBackup");
printf("2. OpenAccounts:\n%s\n\n", openAccountsResults);
char* multiAccountGenerateAndDeriveAddressesResult = multiAccountGenerateAndDeriveAddresses("{\"n\":5,\"mnemonicPhraseLength\":12,\"bip39Passphrase\":\"\",\"paths\":[\"m/43'/60'/1581'/0'/0\",\"m/44'/60'/0'/0/0\"]}");
printf("3. MultiAccountGenerateAndDeriveAddresses:\n%s\n\n", multiAccountGenerateAndDeriveAddressesResult);
const nx_json* MultiAccountGenerateAndDeriveAddresses = nx_json_parse(multiAccountGenerateAndDeriveAddressesResult, 0);
char* accountID = nx_json_get(nx_json_item(MultiAccountGenerateAndDeriveAddresses, 0), "id")->text_value;
char p2[300];
char* password = "0x2cd9bf92c5e20b1b410f5ace94d963a96e89156fbe65b70365e8596b37f1f165"; // qwerty
sprintf(p2, "{\"accountID\": \"%s\", \"paths\": [\"m/44'/60'/0'/0\", \"m/43'/60'/1581'\", \"m/43'/60'/1581'/0'/0\", \"m/44'/60'/0'/0/0\"], \"password\": \"%s\"}", accountID, password);
char* multiAccountStoreDerivedAccountsResult = multiAccountStoreDerivedAccounts(p2);
printf("4. MultiAccountStoreDerivedAccounts:\n%s\n\n", multiAccountStoreDerivedAccountsResult);
const nx_json* MultiAccountStoreDerivedAccounts = nx_json_parse(multiAccountStoreDerivedAccountsResult, 0);
char* m4460publicKey = nx_json_get(nx_json_get(MultiAccountStoreDerivedAccounts, "m/44'/60'/0'/0/0"), "publicKey")->text_value;
char* m4460address = nx_json_get(nx_json_get(MultiAccountStoreDerivedAccounts, "m/44'/60'/0'/0/0"), "address")->text_value;
char* m4360publicKey = nx_json_get(nx_json_get(MultiAccountStoreDerivedAccounts, "m/43'/60'/1581'/0'/0"), "publicKey")->text_value;
char* m4360address = nx_json_get(nx_json_get(MultiAccountStoreDerivedAccounts, "m/43'/60'/1581'/0'/0"), "address")->text_value;
char accountsData[2000];
sprintf(accountsData, "[{\"public-key\":\"%s\",\"address\":\"%s\",\"color\":\"#4360df\",\"wallet\":true,\"path\":\"m/44'/60'/0'/0/0\",\"name\":\"Status account\"},{\"public-key\":\"%s\",\"address\":\"%s\",\"name\":\"Delectable Overjoyed Nauplius\",\"photo-path\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAmElEQVR4nOzX4QmAIBBA4Yp2aY52aox2ao6mqf+SoajwON73M0J4HBy6TEEYQmMIjSE0htCECVlbDziv+/n6fuzb3OP/UmEmYgiNITRNm+LPqO2UE2YihtAYQlN818ptoZzau1btOakwEzGExhCa5hdi7d2p1zZLhZmIITSG0PhCpDGExhANEmYihtAYQmMIjSE0bwAAAP//kHQdRIWYzToAAAAASUVORK5CYII=\",\"path\":\"m/43'/60'/1581'/0'/0\",\"chat\":true}]",
m4460publicKey, m4460address, m4360publicKey, m4360address);
char* finalConfig = "{\"BrowsersConfig\":{\"Enabled\":true},\"ClusterConfig\":{\"BootNodes\":[\"enode://23d0740b11919358625d79d4cac7d50a34d79e9c69e16831c5c70573757a1f5d7d884510bc595d7ee4da3c1508adf87bbc9e9260d804ef03f8c1e37f2fb2fc69@47.52.106.107:443\",\"enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@178.128.140.188:443\",\"enode://6e6554fb3034b211398fcd0f0082cbb6bd13619e1a7e76ba66e1809aaa0c5f1ac53c9ae79cf2fd4a7bacb10d12010899b370c75fed19b991d9c0cdd02891abad@47.75.99.169:443\",\"enode://5405c509df683c962e7c9470b251bb679dd6978f82d5b469f1f6c64d11d50fbd5dd9f7801c6ad51f3b20a5f6c7ffe248cc9ab223f8bcbaeaf14bb1c0ef295fd0@35.223.215.156:443\"],\"Enabled\":true,\"Fleet\":\"eth.prod\",\"RendezvousNodes\":[\"/ip4/34.70.75.208/tcp/30703/ethv4/16Uiu2HAm6ZsERLx2BwVD2UM9SVPnnMU6NBycG8XPtu8qKys5awsU\",\"/ip4/178.128.140.188/tcp/30703/ethv4/16Uiu2HAmLqTXuY4Sb6G28HNooaFUXUKzpzKXCcgyJxgaEE2i5vnf\",\"/ip4/47.52.106.107/tcp/30703/ethv4/16Uiu2HAmEHiptiDDd9gqNY8oQqo8hHUWMHJzfwt5aLRdD6W2zcXR\"],\"StaticNodes\":[\"enode://887cbd92d95afc2c5f1e227356314a53d3d18855880ac0509e0c0870362aee03939d4074e6ad31365915af41d34320b5094bfcc12a67c381788cd7298d06c875@178.128.141.0:443\",\"enode://fbeddac99d396b91d59f2c63a3cb5fc7e0f8a9f7ce6fe5f2eed5e787a0154161b7173a6a73124a4275ef338b8966dc70a611e9ae2192f0f2340395661fad81c0@34.67.230.193:443\"],\"TrustedMailServers\":[\"enode://2c8de3cbb27a3d30cbb5b3e003bc722b126f5aef82e2052aaef032ca94e0c7ad219e533ba88c70585ebd802de206693255335b100307645ab5170e88620d2a81@47.244.221.14:443\",\"enode://ee2b53b0ace9692167a410514bca3024695dbf0e1a68e1dff9716da620efb195f04a4b9e873fb9b74ac84de801106c465b8e2b6c4f0d93b8749d1578bfcaf03e@104.197.238.144:443\",\"enode://8a64b3c349a2e0ef4a32ea49609ed6eb3364be1110253c20adc17a3cebbc39a219e5d3e13b151c0eee5d8e0f9a8ba2cd026014e67b41a4ab7d1d5dd67ca27427@178.128.142.94:443\",\"enode://7aa648d6e855950b2e3d3bf220c496e0cae4adfddef3e1e6062e6b177aec93bc6cdcf1282cb40d1656932ebfdd565729da440368d7c4da7dbd4d004b1ac02bf8@178.128.142.26:443\",\"enode://c42f368a23fa98ee546fd247220759062323249ef657d26d357a777443aec04db1b29a3a22ef3e7c548e18493ddaf51a31b0aed6079bd6ebe5ae838fcfaf3a49@178.128.142.54:443\",\"enode://30211cbd81c25f07b03a0196d56e6ce4604bb13db773ff1c0ea2253547fafd6c06eae6ad3533e2ba39d59564cfbdbb5e2ce7c137a5ebb85e99dcfc7a75f99f55@23.236.58.92:443\"]},\"DataDir\":\"./data\",\"EnableNTPSync\":true,\"KeyStoreDir\":\"./keystore\",\"ListenAddr\":\":30304\",\"LogEnabled\":true,\"LogFile\":\"./geth.log\",\"LogLevel\":\"INFO\",\"MailserversConfig\":{\"Enabled\":true},\"Name\":\"StatusIM\",\"NetworkId\":1,\"NoDiscovery\":false,\"PermissionsConfig\":{\"Enabled\":true},\"Rendezvous\":true,\"RequireTopics\":{\"whisper\":{\"Max\":2,\"Min\":2}},\"ShhExtConfig\":{\"BackupDisabledDataDir\":\"./\",\"DataSyncEnabled\":true,\"InstallationID\":\"aef27732-8d86-5039-a32e-bdbe094d8791\",\"MailServerConfirmations\":true,\"MaxMessageDeliveryAttempts\":6,\"PFSEnabled\":true,\"VerifyENSContractAddress\":\"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e\",\"VerifyENSURL\":\"https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a\",\"VerifyTransactionChainID\":1,\"VerifyTransactionURL\":\"https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a\"},\"ShhextConfig\":{\"BackupDisabledDataDir\":null,\"DataSyncEnabled\":true,\"InstallationID\":\"aef27732-8d86-5039-a32e-bdbe094d8791\",\"MailServerConfirmations\":true,\"MaxMessageDeliveryAttempts\":6,\"PFSEnabled\":true,\"VerifyENSContractAddress\":\"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e\",\"VerifyENSURL\":\"https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a\",\"VerifyTransactionChainID\":1,\"VerifyTransactionURL\":\"https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a\"},\"StatusAccountsConfig\":{\"Enabled\":true},\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a\"},\"WakuConfig\":{\"BloomFilterMode\":null,\"Enabled\":true,\"LightClient\":true,\"MinimumPoW\":0.001},\"WalletConfig\":{\"Enabled\":true}}";
char* multiAccountGenerateAndDeriveAddresses0address = nx_json_get(nx_json_item(MultiAccountGenerateAndDeriveAddresses, 0), "address")->text_value;
char* multiAccountGenerateAndDeriveAddresses0keyUid = nx_json_get(nx_json_item(MultiAccountGenerateAndDeriveAddresses, 0), "keyUid")->text_value;
char multiAccountData[2000];
sprintf(multiAccountData, "{\"name\":\"Delectable Overjoyed Nauplius\",\"address\":\"%s\",\"photo-path\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAmElEQVR4nOzX4QmAIBBA4Yp2aY52aox2ao6mqf+SoajwON73M0J4HBy6TEEYQmMIjSE0htCECVlbDziv+/n6fuzb3OP/UmEmYgiNITRNm+LPqO2UE2YihtAYQlN818ptoZzau1btOakwEzGExhCa5hdi7d2p1zZLhZmIITSG0PhCpDGExhANEmYihtAYQmMIjSE0bwAAAP//kHQdRIWYzToAAAAASUVORK5CYII=\",\"key-uid\":\"%s\",\"keycard-pairing\":null}", multiAccountGenerateAndDeriveAddresses0address, multiAccountGenerateAndDeriveAddresses0keyUid);
// multiAccountGenerateAndDeriveAddresses0keyUid
char* multiAccountGenerateAndDeriveAddresses0mnemonic = nx_json_get(nx_json_item(MultiAccountGenerateAndDeriveAddresses, 0), "mnemonic")->text_value;
// m4360publicKey
// multiAccountGenerateAndDeriveAddresses0address
char* eip1581Address = nx_json_get(nx_json_get(MultiAccountStoreDerivedAccounts, "m/43'/60'/1581'"), "address")->text_value;
// m4460address
char* walletRootAddress = nx_json_get(nx_json_get(MultiAccountStoreDerivedAccounts, "m/44'/60'/0'/0"), "address")->text_value;
char settings[5000];
sprintf(settings, "{\"key-uid\":\"%s\",\"mnemonic\":\"%s\",\"public-key\":\"%s\",\"name\":\"Delectable Overjoyed Nauplius\",\"address\":\"%s\",\"eip1581-address\":\"%s\",\"dapps-address\":\"%s\",\"wallet-root-address\":\"%s\",\"preview-privacy?\":true,\"signing-phrase\":\"dust gear boss\",\"log-level\":\"INFO\",\"latest-derived-path\":0,\"networks/networks\":[{\"id\":\"testnet_rpc\",\"etherscan-link\":\"https://ropsten.etherscan.io/address/\",\"name\":\"Ropsten with upstream RPC\",\"config\":{\"NetworkId\":3,\"DataDir\":\"/ethereum/testnet_rpc\",\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://ropsten.infura.io/v3/f315575765b14720b32382a61a89341a\"}}},{\"id\":\"rinkeby_rpc\",\"etherscan-link\":\"https://rinkeby.etherscan.io/address/\",\"name\":\"Rinkeby with upstream RPC\",\"config\":{\"NetworkId\":4,\"DataDir\":\"/ethereum/rinkeby_rpc\",\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://rinkeby.infura.io/v3/f315575765b14720b32382a61a89341a\"}}},{\"id\":\"goerli_rpc\",\"etherscan-link\":\"https://goerli.etherscan.io/address/\",\"name\":\"Goerli with upstream RPC\",\"config\":{\"NetworkId\":5,\"DataDir\":\"/ethereum/goerli_rpc\",\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://goerli.blockscout.com/\"}}},{\"id\":\"mainnet_rpc\",\"etherscan-link\":\"https://etherscan.io/address/\",\"name\":\"Mainnet with upstream RPC\",\"config\":{\"NetworkId\":1,\"DataDir\":\"/ethereum/mainnet_rpc\",\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a\"}}},{\"id\":\"xdai_rpc\",\"name\":\"xDai Chain\",\"config\":{\"NetworkId\":100,\"DataDir\":\"/ethereum/xdai_rpc\",\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://dai.poa.network\"}}},{\"id\":\"poa_rpc\",\"name\":\"POA Network\",\"config\":{\"NetworkId\":99,\"DataDir\":\"/ethereum/poa_rpc\",\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://core.poa.network\"}}}],\"currency\":\"usd\",\"photo-path\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAmElEQVR4nOzX4QmAIBBA4Yp2aY52aox2ao6mqf+SoajwON73M0J4HBy6TEEYQmMIjSE0htCECVlbDziv+/n6fuzb3OP/UmEmYgiNITRNm+LPqO2UE2YihtAYQlN818ptoZzau1btOakwEzGExhCa5hdi7d2p1zZLhZmIITSG0PhCpDGExhANEmYihtAYQmMIjSE0bwAAAP//kHQdRIWYzToAAAAASUVORK5CYII=\",\"waku-enabled\":true,\"wallet/visible-tokens\":{\"mainnet\":[\"SNT\"]},\"appearance\":0,\"networks/current-network\":\"mainnet_rpc\",\"installation-id\":\"5d6bc316-a97e-5b89-9541-ad01f8eb7397\"}",
multiAccountGenerateAndDeriveAddresses0keyUid, multiAccountGenerateAndDeriveAddresses0mnemonic, m4360publicKey, multiAccountGenerateAndDeriveAddresses0address,
eip1581Address, m4460address, walletRootAddress);
char* loginResult = saveAccountAndLogin(multiAccountData, password, settings, finalConfig, accountsData);
printf("5. saveAccountAndLogin:\n%s\n\n", loginResult);
setSignalEventCallback(&eventCallback);
// TODO: tests GC strings
while(1) {
printf("...\n");
sleep(1);
}
return 0;
}

1
vendor/nimbus-build-system vendored Submodule

@ -0,0 +1 @@
Subproject commit 4fe12e1cfd7b4bce6d9802024342662f372bd5e5

1
vendor/status-go vendored Submodule

@ -0,0 +1 @@
Subproject commit 157f20a7c826598ddd8f9be936ffca20a4c3bacd