Skip to content

Commit c8d4d94

Browse files
committed
test(integration): add electrum sync/apply/persist
1 parent 6102096 commit c8d4d94

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// @Tags(['integration'])
2+
3+
import 'dart:async';
4+
import 'dart:io';
5+
6+
import 'package:bdk_dart/bdk.dart';
7+
import 'package:test/test.dart';
8+
9+
import '../test_constants.dart';
10+
import 'integration_helpers.dart';
11+
12+
Future<void> _deleteDirectoryWithRetry(Directory dir) async {
13+
for (var attempt = 0; attempt < 10; attempt++) {
14+
try {
15+
if (dir.existsSync()) {
16+
await dir.delete(recursive: true);
17+
}
18+
return;
19+
} on PathAccessException {
20+
await Future<void>.delayed(const Duration(milliseconds: 100));
21+
}
22+
}
23+
if (dir.existsSync()) {
24+
await dir.delete(recursive: true);
25+
}
26+
}
27+
28+
String _createTempSqlitePath() {
29+
final tempDir = Directory.systemTemp.createTempSync(
30+
'bdk_dart_electrum_integration_',
31+
);
32+
addTearDown(() => _deleteDirectoryWithRetry(tempDir));
33+
return '${tempDir.path}/wallet.sqlite';
34+
}
35+
36+
void main() {
37+
group('Electrum integration', () {
38+
test(
39+
'sync, apply update, persist, and reload wallet state',
40+
() {
41+
final disposers = <Disposer>[];
42+
final sqlitePath = _createTempSqlitePath();
43+
final electrumUrl = envOrThrow(electrumUrlEnv);
44+
printOnFailure('Electrum URL: $electrumUrl');
45+
printOnFailure('SQLite path: $sqlitePath');
46+
47+
try {
48+
final descriptor = buildBip84Descriptor(Network.testnet);
49+
addDisposer(disposers, descriptor.dispose);
50+
51+
final changeDescriptor = buildBip84ChangeDescriptor(Network.testnet);
52+
addDisposer(disposers, changeDescriptor.dispose);
53+
54+
final persister = Persister.newSqlite(sqlitePath);
55+
addDisposer(disposers, persister.dispose);
56+
57+
final wallet = Wallet(
58+
descriptor,
59+
changeDescriptor,
60+
Network.testnet,
61+
persister,
62+
defaultLookahead,
63+
);
64+
addDisposer(disposers, wallet.dispose);
65+
66+
final revealed = wallet.revealNextAddress(KeychainKind.external_);
67+
addDisposer(disposers, revealed.address.dispose);
68+
69+
final persistedAddressReveal = wallet.persist(persister);
70+
printOnFailure(
71+
'Persisted after reveal address: $persistedAddressReveal',
72+
);
73+
74+
final checkpointBeforeSync = wallet.latestCheckpoint();
75+
final checkpointBeforeHeight = checkpointBeforeSync.height;
76+
addDisposer(disposers, checkpointBeforeSync.hash.dispose);
77+
printOnFailure(
78+
'Checkpoint before sync height: $checkpointBeforeHeight',
79+
);
80+
81+
final requestBuilder = wallet.startSyncWithRevealedSpks();
82+
addDisposer(disposers, requestBuilder.dispose);
83+
84+
final request = requestBuilder.build();
85+
addDisposer(disposers, request.dispose);
86+
87+
final client = buildElectrumClientFromEnv();
88+
addDisposer(disposers, client.dispose);
89+
90+
client.ping();
91+
final update = client.sync_(request, 100, true);
92+
addDisposer(disposers, update.dispose);
93+
94+
wallet.applyUpdate(update);
95+
final persistedAfterSync = wallet.persist(persister);
96+
printOnFailure('Persisted after sync: $persistedAfterSync');
97+
98+
final checkpointAfterSync = wallet.latestCheckpoint();
99+
final checkpointAfterHeight = checkpointAfterSync.height;
100+
addDisposer(disposers, checkpointAfterSync.hash.dispose);
101+
printOnFailure(
102+
'Checkpoint after sync height: $checkpointAfterHeight',
103+
);
104+
105+
expect(
106+
checkpointAfterHeight,
107+
greaterThanOrEqualTo(checkpointBeforeHeight),
108+
);
109+
expect(checkpointAfterHeight, greaterThan(0));
110+
111+
final persistedExternalIndex = wallet.nextDerivationIndex(
112+
KeychainKind.external_,
113+
);
114+
printOnFailure(
115+
'Persisted external derivation index: $persistedExternalIndex',
116+
);
117+
118+
final reloadedPersister = Persister.newSqlite(sqlitePath);
119+
addDisposer(disposers, reloadedPersister.dispose);
120+
121+
final reloadedWallet = Wallet.load(
122+
descriptor,
123+
changeDescriptor,
124+
reloadedPersister,
125+
defaultLookahead,
126+
);
127+
addDisposer(disposers, reloadedWallet.dispose);
128+
129+
final reloadedExternalIndex = reloadedWallet.nextDerivationIndex(
130+
KeychainKind.external_,
131+
);
132+
expect(reloadedExternalIndex, equals(persistedExternalIndex));
133+
134+
final reloadedCheckpoint = reloadedWallet.latestCheckpoint();
135+
final reloadedCheckpointHeight = reloadedCheckpoint.height;
136+
addDisposer(disposers, reloadedCheckpoint.hash.dispose);
137+
printOnFailure(
138+
'Reloaded checkpoint height: $reloadedCheckpointHeight',
139+
);
140+
expect(
141+
reloadedCheckpointHeight,
142+
greaterThanOrEqualTo(checkpointBeforeHeight),
143+
);
144+
} finally {
145+
disposeAll(disposers);
146+
}
147+
},
148+
skip: integrationSkipReason(requiredEnv: [electrumUrlEnv]),
149+
);
150+
});
151+
}

0 commit comments

Comments
 (0)