Skip to content

Commit efb5871

Browse files
authored
Merge pull request #1734 from SatoshiPortal/develop
6.5.0
2 parents 79603e6 + d31c0a4 commit efb5871

651 files changed

Lines changed: 69633 additions & 33323 deletions

File tree

Some content is hidden

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

.fvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"flutter": "3.29.3"
2+
"flutter": "3.38.5"
33
}

.github/workflows/analyze_and_test.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ jobs:
1515

1616
- name: Install FVM
1717
run: |
18-
curl -fsSL https://fvm.app/install.sh | bash
19-
echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH
18+
curl -fsSL https://fvm.app/install.sh | bash -s -- 4.0.5
19+
echo "$HOME/fvm/bin" >> $GITHUB_PATH
2020
2121
- run: make fvm-check
2222
- run: make clean
2323
- run: make deps
2424
- run: make build-runner
25-
- run: make l10n
25+
- run: make translations
2626

2727
- name: Create .env file
2828
run: |

.github/workflows/claude.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Claude Code
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
pull_request_review_comment:
7+
types: [created]
8+
9+
permissions:
10+
id-token: write # needed for OIDC
11+
contents: write # so it can write the repo
12+
issues: write # so it can comment on issues
13+
pull-requests: write # so it can comment on PRs
14+
15+
jobs:
16+
claude:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v4
20+
with:
21+
token: ${{ secrets.GITHUB_TOKEN }}
22+
fetch-depth: 0 # Fetch full history for branch operations
23+
persist-credentials: true # Keep credentials for subsequent git commands
24+
25+
- uses: anthropics/claude-code-action@v1
26+
with:
27+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
28+
claude_args: "--model claude-opus-4-5-20251101"

ARCHITECTURE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ In this project, BLoCs/Cubits are used for state management, but other solutions
134134
- The **domain and presentation layer should use entities**, not models.
135135
- Only the **data layer should use models**, and transform them to entities.
136136

137+
### Rules for AI:
138+
- Always follow the architecture of the project when developing features.
139+
- Always use colors from the theme; never use raw colors. When the user explains something using raw color language; find the closest color in the theme and based on the application use a color from the theme that would make sense in dark mode too but do not try to change the color theme file by yourself ever.
140+
-
141+
137142
### Further reading
138143

139144
You can read more about Clean Architecture principles applied to Flutter in the following articles:

README.md

Lines changed: 12 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![Analyze](https://github.com/SatoshiPortal/bullbitcoin-mobile/actions/workflows/analyze.yml/badge.svg)](https://github.com/SatoshiPortal/bullbitcoin-mobile/actions/workflows/analyze.yml) [![Build](https://github.com/SatoshiPortal/bullbitcoin-mobile/actions/workflows/build.yml/badge.svg)](https://github.com/SatoshiPortal/bullbitcoin-mobile/actions/workflows/build.yml)
1+
[![Analyze and Test](https://github.com/SatoshiPortal/bullbitcoin-mobile/actions/workflows/analyze_and_test.yml/badge.svg?branch=develop)](https://github.com/SatoshiPortal/bullbitcoin-mobile/actions/workflows/analyze_and_test.yml)
22

33
# About BULL Wallet
44

@@ -16,22 +16,13 @@ At launch, two wallets are generated: the Secure Bitcoin Wallet and the Instant
1616

1717
Both these wallets are able to send and receive Lightning Network payments via the swap provider.
1818

19-
## Core dependencies
19+
### Translations
2020

21-
- [bdk](https://github.com/bitcoindevkit/bdk)
22-
- [bdk-flutter](https://github.com/LtbLightning/bdk-flutter)
23-
- [lwk](https://github.com/Blockstream/lwk)
24-
- [lwk-dart](https://github.com/SatoshiPortal/lwk-dart)
25-
- [boltz-rust](https://github.com/SatoshiPortal/boltz-rust)
26-
- [boltz-dart](https://github.com/SatoshiPortal/boltz-dart)
21+
[![Translation status](https://hosted.weblate.org/widget/bull/open-graph.png)](https://hosted.weblate.org/engage/bull/)
2722

28-
## Default external service providers
23+
### [Dependencies](https://github.com/SatoshiPortal/bullbitcoin-mobile/blob/develop/pubspec.yaml#L9)
2924

30-
- mempool.space API for fee estimates
31-
- mempool.bullbitcoin.com / mempool.space for transaction and address explorer
32-
- bullbitcoin.com API for fiat prices
33-
- bullbitcoin.com and blockstream.info electrum servers for blockchain data
34-
- boltz.exchange for swap services
25+
### [Default service providers](https://github.com/SatoshiPortal/bullbitcoin-mobile/blob/develop/lib/core/utils/constants.dart#L60)
3526

3627
### General features
3728

@@ -68,8 +59,7 @@ We try to always use a wallet that is the same network as the recipient: if reci
6859

6960
Automated selection of the wallet can be overridden by the user at any time. This will most likely trigger a warning that the user can choose to ignore.
7061

71-
### Wallet security
72-
62+
## Wallet security
7363
- An optional PIN from 4 to 8 digits can be set for access to the app.
7464
- The PIN is optional to prevent users from being accidentally locked out of a wallet without having first performed a backup.
7565
- Private keys are stored in secure storage and only accessed via the application when signing transactions, viewing the wallet’s private keys for back-up (mnemonic or xpriv). This prevents malicious applications from accessing the private keys.
@@ -106,42 +96,20 @@ When installing the BULL Wallet app, a self-custodial wallet will be created, re
10696

10797
When spending or selling Bitcoin, the exchange will create a payment invoice (BIP21) that will automatically be opened by the same application. All the user has to do is to confirm or reject that transaction. The experience will be functionally the same as that of a custodial exchange, with the exception that the user will have to do a backup of the Bitcoin wallet.
10898

109-
## Current roadmap
110-
111-
Suggestion to this roadmap can be proposed as Github issues.
112-
113-
- [x] Bumping replace-by-fee transactions
114-
- [ ] Re-implement smarter coin selection and labelling
115-
- [x] One mnemonic: new wallets are always created as a BIP39 passphrase
116-
- [x] Good UX/UI for creating PSBTs from watch-only wallets
117-
- [x] Good UX/UI for decoding and broadcasting PSBTs
118-
- [x] Better UX/UI for importing watch-only wallets
119-
- [x] Integration of Coinkite's BBQR library to export public keys, export PSBTs and import PSBTs
120-
- [x] Bitcoin <> Liquid network swaps (depends on Boltz backend update)
121-
- [ ] Integrate a client-side passphrase strength estimator
122-
- [x] Encrypted cloud backups connected to a key server: RecoverBull
123-
- [ ] Store persistent encrypted wallet backup on device
124-
- [ ] Biometric authentication
125-
- [ ] Show fiat value of transactions at the approximated time they were made
126-
- [ ] Spanish and French translations
127-
- [x] Payjoin integration
128-
- [ ] Integrate Bull Bitcoin Fee multiple
129-
- [x] Auto-consolidation mode for spend
130-
- [ ] Small UTXO warning and consolidation suggestions
131-
- [ ] Configurable mempool explorer URLs
132-
- [ ] Configurable swap provider (similar to Electrum server)
99+
## Roadmap
100+
101+
The roadmap is based on the Github issues. You can suggest your own ideas by creating a new issue. The issues are then prioritized by the maintainers according to their importance and feasibility.
133102

134103
## Acknowledgements
135104

136-
- The project is entirely financed by bullbitcoin.com
105+
- The project is entirely financed by [bullbitcoin.com](https://bullbitcoin.com)
137106
- Created by Francis Pouliot and Vishal Menon
138-
- Main developers: Vishal, Morteza and Sai
107+
- Maintainers: [i5hi](https://github.com/i5hi), [mocodesmo](https://github.com/mocodesmo), [ethicnology](https://github.com/ethicnology), [kumulynja](https://github.com/kumulynja), [basantagoswami](https://github.com/basantagoswami) and Q&A [kiranmetri](https://github.com/kiranmetri)
108+
- Thanks to all [contributors](https://github.com/SatoshiPortal/bullbitcoin-mobile/graphs/contributors)
139109
- Thanks to Raj for his work on Boltz-rust
140110
- Thanks to the BDK team: BitcoinZavior and ThunderBiscuit
141111
- Eternal gratitude to the Boltz team Michael and Killian
142112
- Thanks to Riccardo and the LWK team
143113
- Thanks to Blockstream for developing the Liquid Network
144114

145115
![image](https://github.com/BullishNode/bullbitcoin-mobile/assets/75800272/a61e4ccc-897d-410f-b97b-37a7c2b240cb)
146-
147-
This project is tested with BrowserStack

analysis_options.yaml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
include: package:lint/analysis_options.yaml
1+
include: package:lints/recommended.yaml
22

33
linter:
44
rules:
55
avoid_classes_with_only_static_members: false
6-
avoid_dynamic_calls: false
7-
no_wildcard_variable_uses: false
8-
unawaited_futures: true
96
avoid_redundant_argument_values: false
7+
avoid_dynamic_calls: false
108

119

1210
analyzer:
11+
errors:
12+
todo: ignore
1313
exclude:
1414
- lib/**/*.g.dart
1515
- lib/**/*.freezed.dart
16-
- maintainance/**
1716
- pubspec.yaml
1817

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def flutterVersionName = localProperties.getProperty('flutter.versionName') ?: '
2323

2424

2525
android {
26-
compileSdk = 35
26+
compileSdk = 36
2727

2828
ndkVersion = "29.0.13113456"
2929
compileOptions {
@@ -43,7 +43,7 @@ android {
4343
applicationId = 'com.bullbitcoin.mobile'
4444
minSdkVersion 26
4545
// TODO: targetSdkVersion flutter.targetSdkVersion
46-
targetSdkVersion 35
46+
targetSdkVersion 36
4747
versionCode flutterVersionCode.toInteger()
4848
versionName flutterVersionName
4949

android/app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
22
<uses-permission android:name="android.permission.INTERNET"/>
33
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
4+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
5+
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
6+
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
47
<!-- <uses-permission android:name="android.permission.NFC"/> -->
58
<uses-feature android:name="android.hardware.bluetooth" android:required="false" />
69
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false" />

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ subprojects {
88
if (project.plugins.hasPlugin("com.android.application") ||
99
project.plugins.hasPlugin("com.android.library")) {
1010
project.android {
11-
compileSdk = 35
11+
compileSdk = 36
1212
buildToolsVersion "35.0.0"
1313
}
1414
}

integration_test/sqlite_transactions_test.dart

Lines changed: 9 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
import 'dart:convert';
2-
31
import 'package:bb_mobile/core/electrum/domain/value_objects/electrum_server_network.dart';
42
import 'package:bb_mobile/core/electrum/frameworks/drift/datasources/electrum_remote_datasource.dart';
53
import 'package:bb_mobile/core/electrum/frameworks/drift/models/electrum_server_model.dart';
64
import 'package:bb_mobile/core/storage/sqlite_database.dart';
7-
import 'package:bb_mobile/core/transaction/data/transaction_repository.dart';
8-
import 'package:bb_mobile/core/transaction/domain/entities/tx.dart';
5+
import 'package:bb_mobile/core/transactions/bitcoin_transaction_repository.dart';
96
import 'package:bb_mobile/core/utils/constants.dart';
107
import 'package:bb_mobile/locator.dart';
118
import 'package:bb_mobile/main.dart';
@@ -21,8 +18,9 @@ Future<void> main({bool isInitialized = false}) async {
2118
url: ApiServiceConstants.bbElectrumUrl,
2219
network: ElectrumServerNetwork.bitcoinMainnet,
2320
),
21+
sqlite: sqlite,
2422
);
25-
final transactionRepository = TransactionRepository(
23+
final transactionRepository = BitcoinTransactionRepository(
2624
electrumRemoteDatasource: electrumDatasource,
2725
);
2826

@@ -33,58 +31,21 @@ Future<void> main({bool isInitialized = false}) async {
3331

3432
tearDownAll(() {});
3533
group('Sqlite Integration Tests', () {
36-
test('Fetch tx bytes from Electrum and store it into Sqlite', () async {
37-
// Ensure the tx does not exists in sqlite
38-
final sqliteTx =
39-
await sqlite.managers.transactions
40-
.filter((e) => e.txid(txid))
41-
.getSingleOrNull();
42-
expect(sqliteTx, isNull);
43-
44-
// Fetch the transaction from electrum
45-
final txBytes = await electrumDatasource.getTransaction(txid);
46-
// Converts the bytes into entity
47-
final txEntity = await RawBitcoinTxEntity.fromBytes(txBytes);
48-
49-
// Store the transaction into sqlite
50-
await sqlite.managers.transactions.create(
51-
(t) => t(
52-
txid: txEntity.txid,
53-
version: txEntity.version,
54-
size: txEntity.size.toString(),
55-
vsize: txEntity.vsize.toString(),
56-
locktime: txEntity.locktime,
57-
vin: json.encode(txEntity.vin.map((e) => e.toJson()).toList()),
58-
vout: json.encode(txEntity.vout.map((e) => e.toJson()).toList()),
59-
),
60-
);
61-
62-
// Fetch the transaction locally from sqlite
63-
final sqliteFetched =
64-
await sqlite.managers.transactions
65-
.filter((e) => e.txid(txid))
66-
.getSingleOrNull();
67-
expect(sqliteFetched, isNotNull);
68-
expect(sqliteFetched!.txid, txid);
69-
});
70-
7134
test('Ensure the repository works', () async {
7235
// Ensure the tx does not exists in sqlite
73-
var sqliteTx =
74-
await sqlite.managers.transactions
75-
.filter((e) => e.txid(txid))
76-
.getSingleOrNull();
36+
var sqliteTx = await sqlite.managers.transactions
37+
.filter((e) => e.txid(txid))
38+
.getSingleOrNull();
7739
expect(sqliteTx, isNull);
7840

7941
// Fetch a transaction and cache it in sqlite if not present
8042
final tx = await transactionRepository.fetch(txid: txid);
8143
expect(tx.txid, txid);
8244

8345
// Ensure the tx is now stored in sqlite
84-
sqliteTx =
85-
await sqlite.managers.transactions
86-
.filter((e) => e.txid(txid))
87-
.getSingleOrNull();
46+
sqliteTx = await sqlite.managers.transactions
47+
.filter((e) => e.txid(tx.txid))
48+
.getSingleOrNull();
8849
expect(sqliteTx, isNotNull);
8950
expect(tx.txid, sqliteTx!.txid);
9051
});

0 commit comments

Comments
 (0)