Skip to content

Commit

Permalink
Merge branch 'merge-master-into-staging-ln' into staging-ln
Browse files Browse the repository at this point in the history
  • Loading branch information
Beerosagos committed Feb 17, 2025
2 parents 9eb6d6e + c1eb6b8 commit e310e01
Show file tree
Hide file tree
Showing 262 changed files with 16,590 additions and 2,035 deletions.
1 change: 1 addition & 0 deletions .containerversion
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
27
64 changes: 42 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,44 @@ concurrency:
cancel-in-progress: true

env:
# Use alternative image when running on GitHub workflows CI to avoid potential
# rate limiting when executing jobs in parallel: they can't cache docker images
# and always pull.
#
# To update this image, generate a personal token with write:packages scope
# on https://github.com/settings/tokens and authenticate yourself locally with
# "docker login ghcr.io -u <github-username>" using the
# newly generated token as password.
# Once logged in, tag an new image:
# docker tag shiftcrypto/bitbox-wallet-app:VERSION \
# ghcr.io/bitboxswiss/bitbox-wallet-app-ci:VERSION
# and push as usual:
# docker push ghcr.io/bitboxswiss/bitbox-wallet-app-ci:VERSION
# Lastly, update the next line to use the newly pushed image version.
# See docs for more details:
# https://docs.github.com/en/packages/guides/pushing-and-pulling-docker-images
#
# Keep this in sync with default in scripts/github-ci.sh.
CI_IMAGE: ghcr.io/bitboxswiss/bitbox-wallet-app-ci:26
GITHUB_BUILD_DIR: ${{github.workspace}}

jobs:
setup-env:
runs-on: ubuntu-22.04
outputs:
ci_image: ${{ steps.set-ci-image.outputs.ci_image }}
steps:
- name: Clone the repo
uses: actions/checkout@v4

- name: Read CI Image Version
id: set-ci-image
run: |
# Use alternative image when running on GitHub workflows CI to avoid potential
# rate limiting when executing jobs in parallel: they can't cache docker images
# and always pull.
#
# To update this image, generate a personal token with write:packages scope
# on https://github.com/settings/tokens and authenticate yourself locally with
# "docker login ghcr.io -u <github-username>" using the
# newly generated token as password.
# Once logged in, tag an new image:
# docker tag shiftcrypto/bitbox-wallet-app:VERSION \
# ghcr.io/bitboxswiss/bitbox-wallet-app-ci:VERSION
# and push as usual:
# docker push ghcr.io/bitboxswiss/bitbox-wallet-app-ci:VERSION
# Lastly, update the next line to use the newly pushed image version.
# See docs for more details:
# https://docs.github.com/en/packages/guides/pushing-and-pulling-docker-images
#
# Keep this in sync with default in scripts/github-ci.sh.
CI_IMAGE_VERSION=$(cat .containerversion)
echo "ci_image=ghcr.io/bitboxswiss/bitbox-wallet-app-ci:$CI_IMAGE_VERSION" >> $GITHUB_OUTPUT
test-lint:
runs-on: ubuntu-22.04
needs: setup-env
steps:
- name: Clone the repo
with:
Expand All @@ -42,8 +56,11 @@ jobs:
run: ./scripts/github-ci.sh ci
env:
OS_NAME: linux
CI_IMAGE: ${{ needs.setup-env.outputs.ci_image }}

android:
runs-on: ubuntu-22.04
needs: setup-env
outputs:
artifact-url: ${{ steps.upload.outputs.artifact-url }}
steps:
Expand All @@ -60,6 +77,7 @@ jobs:
run: ./scripts/github-ci.sh android
env:
OS_NAME: linux
CI_IMAGE: ${{ needs.setup-env.outputs.ci_image }}
- name: Upload APK
id: upload
uses: actions/upload-artifact@v4
Expand All @@ -69,6 +87,7 @@ jobs:
if-no-files-found: error
qt-linux:
runs-on: ubuntu-22.04
needs: setup-env
outputs:
artifact-url-ai: ${{ steps.upload-ai.outputs.artifact-url }}
artifact-url-deb: ${{ steps.upload-deb.outputs.artifact-url }}
Expand All @@ -82,6 +101,7 @@ jobs:
run: ./scripts/github-ci.sh qt-linux
env:
OS_NAME: linux
CI_IMAGE: ${{ needs.setup-env.outputs.ci_image }}
- name: Upload AppImage
id: upload-ai
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -121,7 +141,7 @@ jobs:
with:
node-version: '20.x'
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install Qt
Expand Down Expand Up @@ -193,7 +213,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
with:
submodules: recursive
- name: Install Node.js
uses: actions/setup-node@v4
Expand All @@ -205,7 +225,7 @@ jobs:
# Take Go version to install from go.mod
go-version-file: 'go.mod'
- name: Install Qt
uses: jurplel/install-qt-action@v3
uses: jurplel/install-qt-action@v4
with:
version: '6.2'
host: 'windows'
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
- Use native scrollbars on macOS, iOS and Android
- Fix address signing fail on screen rotation for Pocket and Bitsurance
- Restrict selection to text files when importing notes
- Display the hide amount button by default and remove its settings
- Linux: add support for Wayland
- Fix the copy buttons in the Pocket order confirmation page
- Android: handle device disconnect while the app is in the background
- Improve send result view show relevant infos and options to make a new transaction or go back
- Added an option in advanced settings to allow the app to start in testnet at the next restart.

# 4.46.3
- Fix camera access on linux
Expand Down
4 changes: 2 additions & 2 deletions backend/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -1237,7 +1237,7 @@ outer:
// a user-facing setting. Now we simply use it for migration to decide which coins to add by
// default.
func (backend *Backend) persistDefaultAccountConfigs(keystore keystore.Keystore, accountsConfig *config.AccountsConfig) error {
if backend.arguments.Testing() {
if backend.Testing() {
if backend.arguments.Regtest() {
if backend.config.AppConfig().Backend.DeprecatedCoinActive(coinpkg.CodeRBTC) {
if _, err := backend.createAndPersistAccountConfig(
Expand Down Expand Up @@ -1499,7 +1499,7 @@ func (backend *Backend) maybeAddHiddenUnusedAccounts() {
switch {
case backend.arguments.Regtest():
coinCodes = []coinpkg.Code{coinpkg.CodeRBTC}
case backend.arguments.Testing():
case backend.Testing():
coinCodes = []coinpkg.Code{coinpkg.CodeTBTC, coinpkg.CodeTLTC}
default:
coinCodes = []coinpkg.Code{coinpkg.CodeBTC, coinpkg.CodeLTC}
Expand Down
8 changes: 8 additions & 0 deletions backend/accounts/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ type TransactionData struct {
Type TxType
// Amount is always >0 and is the amount received or sent (not including the fee).
Amount coin.Amount
// DeductedAmount is the amount sent, including the fee.
// This field is only used if Type is equal to either Send or SendToSelf.
// Whem the type is SendToSelf, DeductedAmount is equal to only the fee.
DeductedAmount coin.Amount
// Balance is balance of the account at the time of this transaction. It is the sum of all
// transactions up to this point.
// This value is only valid as part of `OrderedTransactions`.
Expand Down Expand Up @@ -163,6 +167,7 @@ func NewOrderedTransactions(txs []*TransactionData) OrderedTransactions {

balance := big.NewInt(0)
for i := len(txs) - 1; i >= 0; i-- {
deductedAmount := coin.NewAmountFromInt64(0)
tx := txs[i]
switch tx.Type {
case TxTypeReceive:
Expand All @@ -177,15 +182,18 @@ func NewOrderedTransactions(txs []*TransactionData) OrderedTransactions {
// mined.
if tx.Fee != nil && !tx.FeeIsDifferentUnit {
balance.Sub(balance, tx.Fee.BigInt())
deductedAmount = coin.SumAmounts(tx.Amount, *tx.Fee)
}
case TxTypeSendSelf:
// Subtract only fee. Ethereum: it is deducted even if the tx failed, as the tx was
// mined.
if tx.Fee != nil && !tx.FeeIsDifferentUnit {
balance.Sub(balance, tx.Fee.BigInt())
deductedAmount = *tx.Fee
}
}
tx.Balance = coin.NewAmount(balance)
tx.DeductedAmount = deductedAmount
}
return txs
}
Expand Down
55 changes: 55 additions & 0 deletions backend/accounts/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,58 @@ func TestOrderedTransactionsWithFailedTransactions(t *testing.T) {
require.Equal(t, coin.NewAmountFromInt64(expectedBalances[i]), ordered[i].Balance, i)
}
}

func requireAmountIsEqualTo(t *testing.T, amount coin.Amount, total int64) {
t.Helper()
value, err := amount.Int64()
require.NoError(t, err)
require.Equal(t, total, value)
}

func TestOrderedTransactionsDeductedAmount(t *testing.T) {
tt := func(t time.Time) *time.Time { return &t }
amount := coin.NewAmountFromInt64(100)
fee := coin.NewAmountFromInt64(10)
txs := []*TransactionData{
{
// Send tx, deductedAmount is amount+fee
Timestamp: tt(time.Date(2020, 9, 15, 12, 0, 0, 0, time.UTC)),
Height: 15,
Type: TxTypeSend,
Amount: amount,
Fee: &fee,
},
{
// SendToSelf tx, deductedAmount is equal to just the fee.
Timestamp: tt(time.Date(2020, 9, 16, 12, 0, 0, 0, time.UTC)),
Height: 15,
Type: TxTypeSendSelf,
Amount: amount,
Fee: &fee,
},
{
// Recv tx, deductedAmount is empty
Timestamp: tt(time.Date(2020, 9, 17, 12, 0, 0, 0, time.UTC)),
Height: 15,
Type: TxTypeReceive,
Amount: amount,
Fee: &fee,
},
{
// Fee is in different unit (e.g. erc20 tx), deductedAmount is empty.
Timestamp: tt(time.Date(2020, 9, 17, 12, 0, 0, 0, time.UTC)),
Height: 15,
Type: TxTypeSend,
FeeIsDifferentUnit: true,
Amount: amount,
Fee: &fee,
},
}

orderedTxs := NewOrderedTransactions(txs)

requireAmountIsEqualTo(t, orderedTxs[0].DeductedAmount, 110)
requireAmountIsEqualTo(t, orderedTxs[1].DeductedAmount, 10)
requireAmountIsEqualTo(t, orderedTxs[2].DeductedAmount, 0)
requireAmountIsEqualTo(t, orderedTxs[3].DeductedAmount, 0)
}
42 changes: 32 additions & 10 deletions backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ type Backend struct {

devices map[string]device.Interface

usbManager *usb.Manager

accountsAndKeystoreLock locker.Locker
accounts AccountsList
// keystore is nil if no keystore is connected.
Expand Down Expand Up @@ -232,20 +234,23 @@ type Backend struct {
tstCheckAccountUsed func(accounts.Interface) bool
// For unit tests, called when `backend.maybeAddHiddenUnusedAccounts()` has run.
tstMaybeAddHiddenUnusedAccounts func()

// testing tells us whether the app is in testing mode
testing bool
}

// NewBackend creates a new backend with the given arguments.
func NewBackend(arguments *arguments.Arguments, environment Environment) (*Backend, error) {
log := logging.Get().WithGroup("backend")
config, err := config.NewConfig(arguments.AppConfigFilename(), arguments.AccountsConfigFilename(), arguments.LightningConfigFilename())
backendConfig, err := config.NewConfig(arguments.AppConfigFilename(), arguments.AccountsConfigFilename(), arguments.LightningConfigFilename())
if err != nil {
return nil, errp.WithStack(err)
}
log.Infof("backend config: %+v", config.AppConfig().Backend)
log.Infof("frontend config: %+v", config.AppConfig().Frontend)
log.Infof("backend config: %+v", backendConfig.AppConfig().Backend)
log.Infof("frontend config: %+v", backendConfig.AppConfig().Frontend)
backendProxy := socksproxy.NewSocksProxy(
config.AppConfig().Backend.Proxy.UseProxy,
config.AppConfig().Backend.Proxy.ProxyAddress,
backendConfig.AppConfig().Backend.Proxy.UseProxy,
backendConfig.AppConfig().Backend.Proxy.ProxyAddress,
)
hclient, err := backendProxy.GetHTTPClient()
if err != nil {
Expand All @@ -255,7 +260,7 @@ func NewBackend(arguments *arguments.Arguments, environment Environment) (*Backe
backend := &Backend{
arguments: arguments,
environment: environment,
config: config,
config: backendConfig,
events: make(chan interface{}, 1000),

devices: map[string]device.Interface{},
Expand All @@ -271,7 +276,10 @@ func NewBackend(arguments *arguments.Arguments, environment Environment) (*Backe
},

log: log,

testing: backendConfig.AppConfig().Backend.StartInTestnet || arguments.Testing(),
}

notifier, err := NewNotifier(filepath.Join(arguments.MainDirectoryPath(), "notifier.db"))
if err != nil {
return nil, err
Expand Down Expand Up @@ -552,7 +560,7 @@ func (backend *Backend) Coin(code coinpkg.Code) (coinpkg.Coin, error) {
// Calling this is a no-op for coins that are already connected.
func (backend *Backend) ManualReconnect() {
var electrumCoinCodes []coinpkg.Code
if backend.arguments.Testing() {
if backend.Testing() {
electrumCoinCodes = []coinpkg.Code{
coinpkg.CodeTBTC,
coinpkg.CodeTLTC,
Expand Down Expand Up @@ -586,7 +594,7 @@ func (backend *Backend) ManualReconnect() {

// Testing returns whether this backend is for testing only.
func (backend *Backend) Testing() bool {
return backend.arguments.Testing()
return backend.testing
}

// Accounts returns the current accounts of the backend.
Expand Down Expand Up @@ -626,13 +634,14 @@ func (backend *Backend) OnDeviceUninit(f func(string)) {
// Start starts the background services. It returns a channel of events to handle by the library
// client.
func (backend *Backend) Start() <-chan interface{} {
usb.NewManager(
backend.usbManager = usb.NewManager(
backend.arguments.MainDirectoryPath(),
backend.arguments.BitBox02DirectoryPath(),
backend.socksProxy,
backend.environment.DeviceInfos,
backend.Register,
backend.Deregister).Start()
backend.Deregister)
backend.usbManager.Start()

httpClient, err := backend.socksProxy.GetHTTPClient()
if err != nil {
Expand All @@ -650,9 +659,22 @@ func (backend *Backend) Start() <-chan interface{} {

backend.environment.OnAuthSettingChanged(backend.config.AppConfig().Backend.Authentication)
go backend.lightning.Connect()

if backend.DefaultAppConfig().Backend.StartInTestnet {
if err := backend.config.ModifyAppConfig(func(c *config.AppConfig) error { c.Backend.StartInTestnet = false; return nil }); err != nil {
backend.log.WithError(err).Error("Can't set StartInTestnet to false")
}
}
return backend.events
}

// UsbUpdate triggers a scan of the USB devices to detect connects/disconnects.
func (backend *Backend) UsbUpdate() {
if backend.usbManager != nil {
backend.usbManager.Update()
}
}

// DevicesRegistered returns a map of device IDs to device of registered devices.
func (backend *Backend) DevicesRegistered() map[string]device.Interface {
return backend.devices
Expand Down
10 changes: 10 additions & 0 deletions backend/bridgecommon/bridgecommon.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,13 @@ func Shutdown() {
log.Info("Shutdown called, but backend not running")
}
}

// UsbUpdate wraps backend.UsbUpdate.
func UsbUpdate() {
mu.RLock()
defer mu.RUnlock()
if globalBackend == nil {
return
}
globalBackend.UsbUpdate()
}
Loading

0 comments on commit e310e01

Please sign in to comment.