status-go/cmd/statusd/library.go

392 lines
9.7 KiB
Go

package main
import "C"
import (
"encoding/json"
"fmt"
"os"
"gopkg.in/go-playground/validator.v9"
"github.com/status-im/status-go/geth/common"
"github.com/status-im/status-go/geth/log"
"github.com/status-im/status-go/geth/params"
"github.com/status-im/status-go/helpers/profiling"
)
//export GenerateConfig
func GenerateConfig(datadir *C.char, networkID C.int, devMode C.int) *C.char {
config, err := params.NewNodeConfig(C.GoString(datadir), uint64(networkID), devMode == 1)
if err != nil {
return makeJSONResponse(err)
}
outBytes, err := json.Marshal(&config)
if err != nil {
return makeJSONResponse(err)
}
return C.CString(string(outBytes))
}
//export StartNode
func StartNode(configJSON *C.char) *C.char {
config, err := params.LoadNodeConfig(C.GoString(configJSON))
if err != nil {
return makeJSONResponse(err)
}
_, err = statusAPI.StartNodeAsync(config)
return makeJSONResponse(err)
}
//export StopNode
func StopNode() *C.char {
_, err := statusAPI.StopNodeAsync()
return makeJSONResponse(err)
}
//export ValidateNodeConfig
func ValidateNodeConfig(configJSON *C.char) *C.char {
var resp common.APIDetailedResponse
_, err := params.LoadNodeConfig(C.GoString(configJSON))
// Convert errors to common.APIDetailedResponse
switch err := err.(type) {
case validator.ValidationErrors:
resp = common.APIDetailedResponse{
Message: "validation: validation failed",
FieldErrors: make([]common.APIFieldError, len(err)),
}
for i, ve := range err {
resp.FieldErrors[i] = common.APIFieldError{
Parameter: ve.Namespace(),
Errors: []common.APIError{
{
Message: fmt.Sprintf("field validation failed on the '%s' tag", ve.Tag()),
},
},
}
}
case error:
resp = common.APIDetailedResponse{
Message: fmt.Sprintf("validation: %s", err.Error()),
}
case nil:
resp = common.APIDetailedResponse{
Status: true,
}
}
respJSON, err := json.Marshal(resp)
if err != nil {
return makeJSONResponse(err)
}
return C.CString(string(respJSON))
}
//export ResetChainData
func ResetChainData() *C.char {
_, err := statusAPI.ResetChainDataAsync()
return makeJSONResponse(err)
}
//export CallRPC
func CallRPC(inputJSON *C.char) *C.char {
outputJSON := statusAPI.CallRPC(C.GoString(inputJSON))
return C.CString(outputJSON)
}
//export ResumeNode
func ResumeNode() *C.char {
err := fmt.Errorf("%v: %v", common.ErrDeprecatedMethod.Error(), "ResumeNode")
return makeJSONResponse(err)
}
//export StopNodeRPCServer
func StopNodeRPCServer() *C.char {
err := fmt.Errorf("%v: %v", common.ErrDeprecatedMethod.Error(), "StopNodeRPCServer")
return makeJSONResponse(err)
}
//export StartNodeRPCServer
func StartNodeRPCServer() *C.char {
err := fmt.Errorf("%v: %v", common.ErrDeprecatedMethod.Error(), "StartNodeRPCServer")
return makeJSONResponse(err)
}
//export PopulateStaticPeers
func PopulateStaticPeers() *C.char {
err := fmt.Errorf("%v: %v", common.ErrDeprecatedMethod.Error(), "PopulateStaticPeers")
return makeJSONResponse(err)
}
//export AddPeer
func AddPeer(url *C.char) *C.char {
err := fmt.Errorf("%v: %v", common.ErrDeprecatedMethod.Error(), "AddPeer")
return makeJSONResponse(err)
}
//export CreateAccount
func CreateAccount(password *C.char) *C.char {
// This is equivalent to creating an account from the command line,
// just modified to handle the function arg passing
address, pubKey, mnemonic, err := statusAPI.CreateAccount(C.GoString(password))
errString := ""
if err != nil {
fmt.Fprintln(os.Stderr, err)
errString = err.Error()
}
out := common.AccountInfo{
Address: address,
PubKey: pubKey,
Mnemonic: mnemonic,
Error: errString,
}
outBytes, _ := json.Marshal(&out)
return C.CString(string(outBytes))
}
//export CreateChildAccount
func CreateChildAccount(parentAddress, password *C.char) *C.char {
address, pubKey, err := statusAPI.CreateChildAccount(C.GoString(parentAddress), C.GoString(password))
errString := ""
if err != nil {
fmt.Fprintln(os.Stderr, err)
errString = err.Error()
}
out := common.AccountInfo{
Address: address,
PubKey: pubKey,
Error: errString,
}
outBytes, _ := json.Marshal(&out)
return C.CString(string(outBytes))
}
//export RecoverAccount
func RecoverAccount(password, mnemonic *C.char) *C.char {
address, pubKey, err := statusAPI.RecoverAccount(C.GoString(password), C.GoString(mnemonic))
errString := ""
if err != nil {
fmt.Fprintln(os.Stderr, err)
errString = err.Error()
}
out := common.AccountInfo{
Address: address,
PubKey: pubKey,
Mnemonic: C.GoString(mnemonic),
Error: errString,
}
outBytes, _ := json.Marshal(&out)
return C.CString(string(outBytes))
}
//export VerifyAccountPassword
func VerifyAccountPassword(keyStoreDir, address, password *C.char) *C.char {
_, err := statusAPI.VerifyAccountPassword(C.GoString(keyStoreDir), C.GoString(address), C.GoString(password))
return makeJSONResponse(err)
}
//export Login
func Login(address, password *C.char) *C.char {
// loads a key file (for a given address), tries to decrypt it using the password, to verify ownership
// if verified, purges all the previous identities from Whisper, and injects verified key as shh identity
err := statusAPI.SelectAccount(C.GoString(address), C.GoString(password))
return makeJSONResponse(err)
}
//export Logout
func Logout() *C.char {
// This is equivalent to clearing whisper identities
err := statusAPI.Logout()
return makeJSONResponse(err)
}
//export CompleteTransaction
func CompleteTransaction(id, password *C.char) *C.char {
txHash, err := statusAPI.CompleteTransaction(common.QueuedTxID(C.GoString(id)), C.GoString(password))
errString := ""
if err != nil {
fmt.Fprintln(os.Stderr, err)
errString = err.Error()
}
out := common.CompleteTransactionResult{
ID: C.GoString(id),
Hash: txHash.Hex(),
Error: errString,
}
outBytes, err := json.Marshal(&out)
if err != nil {
log.Error("failed to marshal CompleteTransaction output", "error", err.Error())
return makeJSONResponse(err)
}
return C.CString(string(outBytes))
}
//export CompleteTransactions
func CompleteTransactions(ids, password *C.char) *C.char {
out := common.CompleteTransactionsResult{}
out.Results = make(map[string]common.CompleteTransactionResult)
parsedIDs, err := common.ParseJSONArray(C.GoString(ids))
if err != nil {
out.Results["none"] = common.CompleteTransactionResult{
Error: err.Error(),
}
} else {
txIDs := make([]common.QueuedTxID, len(parsedIDs))
for i, id := range parsedIDs {
txIDs[i] = common.QueuedTxID(id)
}
results := statusAPI.CompleteTransactions(txIDs, C.GoString(password))
for txID, result := range results {
txResult := common.CompleteTransactionResult{
ID: string(txID),
Hash: result.Hash.Hex(),
}
if result.Error != nil {
txResult.Error = result.Error.Error()
}
out.Results[string(txID)] = txResult
}
}
outBytes, err := json.Marshal(&out)
if err != nil {
log.Error("failed to marshal CompleteTransactions output", "error", err.Error())
return makeJSONResponse(err)
}
return C.CString(string(outBytes))
}
//export DiscardTransaction
func DiscardTransaction(id *C.char) *C.char {
err := statusAPI.DiscardTransaction(common.QueuedTxID(C.GoString(id)))
errString := ""
if err != nil {
fmt.Fprintln(os.Stderr, err)
errString = err.Error()
}
out := common.DiscardTransactionResult{
ID: C.GoString(id),
Error: errString,
}
outBytes, err := json.Marshal(&out)
if err != nil {
log.Error("failed to marshal DiscardTransaction output", "error", err.Error())
return makeJSONResponse(err)
}
return C.CString(string(outBytes))
}
//export DiscardTransactions
func DiscardTransactions(ids *C.char) *C.char {
out := common.DiscardTransactionsResult{}
out.Results = make(map[string]common.DiscardTransactionResult)
parsedIDs, err := common.ParseJSONArray(C.GoString(ids))
if err != nil {
out.Results["none"] = common.DiscardTransactionResult{
Error: err.Error(),
}
} else {
txIDs := make([]common.QueuedTxID, len(parsedIDs))
for i, id := range parsedIDs {
txIDs[i] = common.QueuedTxID(id)
}
results := statusAPI.DiscardTransactions(txIDs)
for txID, result := range results {
txResult := common.DiscardTransactionResult{
ID: string(txID),
}
if result.Error != nil {
txResult.Error = result.Error.Error()
}
out.Results[string(txID)] = txResult
}
}
outBytes, err := json.Marshal(&out)
if err != nil {
log.Error("failed to marshal DiscardTransactions output", "error", err.Error())
return makeJSONResponse(err)
}
return C.CString(string(outBytes))
}
//export InitJail
func InitJail(js *C.char) {
statusAPI.JailBaseJS(C.GoString(js))
}
//export Parse
func Parse(chatID *C.char, js *C.char) *C.char {
res := statusAPI.JailParse(C.GoString(chatID), C.GoString(js))
return C.CString(res)
}
//export Call
func Call(chatID *C.char, path *C.char, params *C.char) *C.char {
res := statusAPI.JailCall(C.GoString(chatID), C.GoString(path), C.GoString(params))
return C.CString(res)
}
//export StartCPUProfile
func StartCPUProfile(dataDir *C.char) *C.char {
err := profiling.StartCPUProfile(C.GoString(dataDir))
return makeJSONResponse(err)
}
//export StopCPUProfiling
func StopCPUProfiling() *C.char {
err := profiling.StopCPUProfile()
return makeJSONResponse(err)
}
//export WriteHeapProfile
func WriteHeapProfile(dataDir *C.char) *C.char {
err := profiling.WriteHeapFile(C.GoString(dataDir))
return makeJSONResponse(err)
}
func makeJSONResponse(err error) *C.char {
errString := ""
if err != nil {
fmt.Fprintln(os.Stderr, err)
errString = err.Error()
}
out := common.APIResponse{
Error: errString,
}
outBytes, _ := json.Marshal(&out)
return C.CString(string(outBytes))
}
//export Notify
func Notify(token *C.char) *C.char {
res := statusAPI.Notify(C.GoString(token))
return C.CString(res)
}