Skip to content

Commit ba8f32f

Browse files
committed
Merge remote-tracking branch 'upstream/master' into staging-watchonly
There was a conflict in: backend/config/accounts.go
2 parents b8e9e30 + e92c10d commit ba8f32f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+2520
-1455
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ jobs:
8686
path: frontends/qt/build/linux/bitbox-*.rpm
8787
name: BitBoxApp-linux-${{github.sha}}.rpm
8888
macos:
89-
runs-on: macos-11
89+
runs-on: macos-12
9090
steps:
9191
- name: Clone the repo
9292
uses: actions/checkout@v2

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44
- Drop support for SAI token
5+
- Log Javascript console messages in the app log.txt
6+
- Add amounts hiding feature to enhance privacy when using the app in public
57

68
## 4.39.0
79
- Bundle BitBox02 firmware version v9.15.0

backend/config/accounts.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,19 @@ func (cfg *AccountsConfig) GetOrAddKeystore(rootFingerprint []byte) *Keystore {
126126
cfg.Keystores = append(cfg.Keystores, ks)
127127
return ks
128128
}
129+
130+
// migrateActiveTokens removes tokens from AccountsConfig.
131+
func migrateActiveTokens(accountsConf *AccountsConfig) error {
132+
for _, account := range accountsConf.Accounts {
133+
if account.CoinCode != coin.CodeETH {
134+
continue
135+
}
136+
137+
err := account.SetTokenActive("eth-erc20-sai0x89d", false)
138+
if err != nil {
139+
return err
140+
}
141+
142+
}
143+
return nil
144+
}

backend/config/config.go

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -269,12 +269,6 @@ func NewConfig(appConfigFilename string, accountsConfigFilename string) (*Config
269269
return config, nil
270270
}
271271

272-
// SetBtcOnly sets non-bitcoin accounts in the config to false.
273-
func (config *Config) SetBtcOnly() {
274-
config.appConfig.Backend.DeprecatedLitecoinActive = false
275-
config.appConfig.Backend.DeprecatedEthereumActive = false
276-
}
277-
278272
// SetBTCElectrumServers sets the BTC configuration to the provided electrumIP and electrumCert.
279273
func (config *Config) SetBTCElectrumServers(electrumAddress, electrumCert string) {
280274
config.appConfig.Backend.BTC = btcCoinConfig{
@@ -441,19 +435,3 @@ func migrateUserLanguage(appconf *AppConfig) {
441435
delete(frontconf, "userLanguage")
442436
}
443437
}
444-
445-
// migrateActiveTokens removes tokens from AccountsConfig.
446-
func migrateActiveTokens(accountsConf *AccountsConfig) error {
447-
for _, account := range accountsConf.Accounts {
448-
if account.CoinCode != coin.CodeETH {
449-
continue
450-
}
451-
452-
err := account.SetTokenActive("eth-erc20-sai0x89d", false)
453-
if err != nil {
454-
return err
455-
}
456-
457-
}
458-
return nil
459-
}

backend/config/config_test.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright 2023 Shift Crypto AG
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package config
16+
17+
import (
18+
"encoding/json"
19+
"errors"
20+
"os"
21+
"testing"
22+
23+
"github.com/digitalbitbox/bitbox-wallet-app/backend/coins/coin"
24+
"github.com/digitalbitbox/bitbox-wallet-app/util/test"
25+
"github.com/stretchr/testify/require"
26+
)
27+
28+
func TestNewConfig(t *testing.T) {
29+
appConfigFilename := test.TstTempFile("appConfig")
30+
accountsConfigFilename := test.TstTempFile("accountsConfig")
31+
32+
cfg, err := NewConfig(appConfigFilename, accountsConfigFilename)
33+
require.NoError(t, err)
34+
35+
appJsonBytes, err := os.ReadFile(appConfigFilename)
36+
require.NoError(t, err)
37+
expectedAppJsonBytes, err := json.Marshal(NewDefaultAppConfig())
38+
require.NoError(t, err)
39+
require.JSONEq(t, string(expectedAppJsonBytes), string(appJsonBytes))
40+
41+
accountsJsonBytes, err := os.ReadFile(accountsConfigFilename)
42+
require.NoError(t, err)
43+
expectedAccountsJsonBytes, err := json.Marshal(newDefaultAccountsonfig())
44+
require.NoError(t, err)
45+
require.JSONEq(t, string(expectedAccountsJsonBytes), string(accountsJsonBytes))
46+
47+
// Load existing config.
48+
cfg2, err := NewConfig(appConfigFilename, accountsConfigFilename)
49+
require.NoError(t, err)
50+
require.Equal(t, cfg, cfg2)
51+
}
52+
53+
func TestSetAppConfig(t *testing.T) {
54+
appConfigFilename := test.TstTempFile("appConfig")
55+
accountsConfigFilename := test.TstTempFile("accountsConfig")
56+
57+
cfg, err := NewConfig(appConfigFilename, accountsConfigFilename)
58+
require.NoError(t, err)
59+
60+
appCfg := cfg.AppConfig()
61+
require.Equal(t, coin.BtcUnitDefault, appCfg.Backend.BtcUnit)
62+
appCfg.Backend.BtcUnit = coin.BtcUnitSats
63+
appCfg.Frontend = map[string]interface{}{"foo": "bar"}
64+
require.NoError(t, cfg.SetAppConfig(appCfg))
65+
66+
cfg2, err := NewConfig(appConfigFilename, accountsConfigFilename)
67+
require.NoError(t, err)
68+
require.Equal(t, cfg, cfg2)
69+
require.Equal(t, coin.BtcUnitSats, cfg2.AppConfig().Backend.BtcUnit)
70+
require.Equal(t, map[string]interface{}{"foo": "bar"}, cfg2.AppConfig().Frontend)
71+
}
72+
73+
func TestModifyAccountsConfig(t *testing.T) {
74+
appConfigFilename := test.TstTempFile("appConfig")
75+
accountsConfigFilename := test.TstTempFile("accountsConfig")
76+
77+
cfg, err := NewConfig(appConfigFilename, accountsConfigFilename)
78+
require.NoError(t, err)
79+
80+
require.NoError(t, cfg.ModifyAccountsConfig(func(accountsCfg *AccountsConfig) error {
81+
accountsCfg.Accounts = append(accountsCfg.Accounts, &Account{Used: true})
82+
return nil
83+
}))
84+
85+
cfg2, err := NewConfig(appConfigFilename, accountsConfigFilename)
86+
require.NoError(t, err)
87+
require.Equal(t, cfg, cfg2)
88+
require.Equal(t, []*Account{{Used: true}}, cfg2.AccountsConfig().Accounts)
89+
90+
require.Error(t, cfg.ModifyAccountsConfig(func(accountsCfg *AccountsConfig) error {
91+
return errors.New("error")
92+
}))
93+
}
94+
95+
// TestMigrationSaved tests that migrations are applied when a config is loaded, and that the
96+
// migrations are persisted.
97+
func TestMigrationsAtLoad(t *testing.T) {
98+
appConfigFilename := test.TstTempFile("appConfig")
99+
accountsConfigFilename := test.TstTempFile("accountsConfig")
100+
101+
// Persist a config that includes data that will be migrated.
102+
cfg, err := NewConfig(appConfigFilename, accountsConfigFilename)
103+
require.NoError(t, err)
104+
appCfg := cfg.AppConfig()
105+
appCfg.Frontend = map[string]interface{}{
106+
"userLanguage": "de",
107+
}
108+
require.NoError(t, cfg.SetAppConfig(appCfg))
109+
require.NoError(t, cfg.ModifyAccountsConfig(func(accountsCfg *AccountsConfig) error {
110+
accountsCfg.Accounts = append(accountsCfg.Accounts,
111+
&Account{CoinCode: coin.CodeETH, ActiveTokens: []string{"eth-erc20-sai0x89d"}})
112+
return nil
113+
}))
114+
115+
// Loading the conf applies the migrations.
116+
cfg2, err := NewConfig(appConfigFilename, accountsConfigFilename)
117+
require.NoError(t, err)
118+
require.Equal(t, "de", cfg2.AppConfig().Backend.UserLanguage)
119+
require.Equal(t,
120+
[]*Account{{CoinCode: coin.CodeETH, ActiveTokens: nil}},
121+
cfg2.AccountsConfig().Accounts)
122+
123+
// The migrations were persisted.
124+
cfg3, err := NewConfig(appConfigFilename, accountsConfigFilename)
125+
require.NoError(t, err)
126+
require.Equal(t, cfg2, cfg3)
127+
}

frontends/qt/libserver.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <string.h>
44
#include <stdint.h>
55

6+
typedef const char cchar_t;
7+
68
typedef void (*pushNotificationsCallback) (const char*);
79
static void pushNotify(pushNotificationsCallback f, const char* msg) {
810
f(msg);
@@ -37,9 +39,9 @@ extern "C" {
3739
#endif
3840

3941

40-
extern void backendCall(int p0, char* p1);
42+
extern void backendCall(int queryID, cchar_t* s);
4143

42-
extern void handleURI(char* p0);
44+
extern void handleURI(cchar_t* uri);
4345

4446
extern void serve(
4547
cppHeapFree cppHeapFreeFn,
@@ -50,7 +52,9 @@ extern void serve(
5052
getSaveFilenameCallback getSaveFilenameFn
5153
);
5254

53-
extern void systemOpen(char* p0);
55+
extern void systemOpen(cchar_t* url);
56+
57+
extern void goLog(cchar_t* msg);
5458

5559
#ifdef __cplusplus
5660
}

frontends/qt/main.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class BitBoxApp : public SingleApplication
8282
// if the BitBoxApp is launched and also when it is already running, in which case
8383
// it is brought to the foreground automatically.
8484

85-
handleURI(const_cast<char*>(openEvent->url().toString().toStdString().c_str()));
85+
handleURI(openEvent->url().toString().toLocal8Bit().constData());
8686
}
8787
}
8888

@@ -98,6 +98,13 @@ class WebEnginePage : public QWebEnginePage {
9898
QWebEnginePage* createWindow(QWebEnginePage::WebWindowType type) {
9999
return externalPage;
100100
}
101+
102+
virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID)
103+
{
104+
// Log frontend console messages to the Go log.txt.
105+
QString formattedMsg = QString("msg: %1; line %2; source: %3").arg(message).arg(lineNumber).arg(sourceID);
106+
goLog(formattedMsg.toLocal8Bit().constData());
107+
}
101108
};
102109

103110
class RequestInterceptor : public QWebEngineUrlRequestInterceptor {
@@ -117,7 +124,7 @@ class RequestInterceptor : public QWebEngineUrlRequestInterceptor {
117124
if (onBuyPage) {
118125
if (info.firstPartyUrl().toString() == info.requestUrl().toString()) {
119126
// A link with target=_blank was clicked.
120-
systemOpen(const_cast<char*>(info.requestUrl().toString().toStdString().c_str()));
127+
systemOpen(info.requestUrl().toString().toLocal8Bit().constData());
121128
// No need to also load it in our page.
122129
info.block(true);
123130
}
@@ -380,11 +387,11 @@ int main(int argc, char *argv[])
380387
[&](int instanceId, QByteArray message) {
381388
QString arg = QString::fromUtf8(message);
382389
qDebug() << "Received arg from secondary instance:" << arg;
383-
handleURI(const_cast<char*>(arg.toStdString().c_str()));
390+
handleURI(arg.toLocal8Bit().constData());
384391
});
385392
// Handle URI which the app was launched with in the primary instance.
386393
if (a.arguments().size() == 2) {
387-
handleURI(const_cast<char*>(a.arguments()[1].toStdString().c_str()));
394+
handleURI(a.arguments()[1].toLocal8Bit().constData());
388395
}
389396

390397
return a.exec();

frontends/qt/server/server.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
LIBRARY LIBSERVER
2-
EXPORTS serve backendCall handleURI systemOpen
2+
EXPORTS serve backendCall handleURI systemOpen goLog

frontends/qt/server/server.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ package main
2121
#include <stdint.h>
2222
#include <stdlib.h>
2323
24+
// Workaround to be able to use `const char*` as a param type in the exported Go functions.
25+
typedef const char cchar_t;
26+
2427
typedef void (*pushNotificationsCallback) (const char*);
2528
static void pushNotify(pushNotificationsCallback f, const char* msg) {
2629
f(msg);
@@ -87,7 +90,7 @@ func backendCall(queryID C.int, s *C.char) {
8790
}
8891

8992
//export handleURI
90-
func handleURI(uri *C.char) {
93+
func handleURI(uri *C.cchar_t) {
9194
bridgecommon.HandleURI(C.GoString(uri))
9295
}
9396

@@ -179,13 +182,19 @@ func serve(
179182
}
180183

181184
//export systemOpen
182-
func systemOpen(url *C.char) {
185+
func systemOpen(url *C.cchar_t) {
183186
goURL := C.GoString(url)
184187
if err := system.Open(goURL); err != nil {
185188
logging.Get().WithGroup("server").WithError(err).Errorf("systemOpen: error opening %v", goURL)
186189
}
187190
}
188191

192+
//export goLog
193+
func goLog(msg *C.cchar_t) {
194+
goMsg := C.GoString(msg)
195+
logging.Get().WithGroup("qt-frontend").Info(goMsg)
196+
}
197+
189198
// Don't remove - needed for the C compilation.
190199
func main() {
191200
}

frontends/qt/webclass.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class WebClass : public QObject
2121
Q_OBJECT
2222
public slots:
2323
void call(int queryID, const QString& query) {
24-
backendCall(queryID, const_cast<char*>(query.toStdString().c_str()));
24+
backendCall(queryID, query.toLocal8Bit().constData());
2525
}
2626
signals:
2727
void gotResponse(int queryID, QString response);

0 commit comments

Comments
 (0)