Skip to content

Commit c7e5907

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

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
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_esplora_integration_',
31+
);
32+
addTearDown(() => _deleteDirectoryWithRetry(tempDir));
33+
return '${tempDir.path}/wallet.sqlite';
34+
}
35+
36+
void main() {
37+
group('Esplora integration', () {
38+
test(
39+
'sync, apply update, persist, and reload wallet state',
40+
() {
41+
final disposers = <Disposer>[];
42+
final sqlitePath = _createTempSqlitePath();
43+
final esploraUrl = envOrThrow(esploraUrlEnv);
44+
printOnFailure('Esplora URL: $esploraUrl');
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 = buildEsploraClientFromEnv();
88+
addDisposer(disposers, client.dispose);
89+
90+
final chainHeight = client.getHeight();
91+
printOnFailure('Esplora chain height: $chainHeight');
92+
expect(chainHeight, greaterThan(0));
93+
94+
final update = client.sync_(request, 4);
95+
addDisposer(disposers, update.dispose);
96+
97+
wallet.applyUpdate(update);
98+
final persistedAfterSync = wallet.persist(persister);
99+
printOnFailure('Persisted after sync: $persistedAfterSync');
100+
101+
final checkpointAfterSync = wallet.latestCheckpoint();
102+
final checkpointAfterHeight = checkpointAfterSync.height;
103+
addDisposer(disposers, checkpointAfterSync.hash.dispose);
104+
printOnFailure(
105+
'Checkpoint after sync height: $checkpointAfterHeight',
106+
);
107+
108+
expect(
109+
checkpointAfterHeight,
110+
greaterThanOrEqualTo(checkpointBeforeHeight),
111+
);
112+
expect(checkpointAfterHeight, greaterThan(0));
113+
114+
final persistedExternalIndex = wallet.nextDerivationIndex(
115+
KeychainKind.external_,
116+
);
117+
printOnFailure(
118+
'Persisted external derivation index: $persistedExternalIndex',
119+
);
120+
121+
final reloadedPersister = Persister.newSqlite(sqlitePath);
122+
addDisposer(disposers, reloadedPersister.dispose);
123+
124+
final reloadedWallet = Wallet.load(
125+
descriptor,
126+
changeDescriptor,
127+
reloadedPersister,
128+
defaultLookahead,
129+
);
130+
addDisposer(disposers, reloadedWallet.dispose);
131+
132+
final reloadedExternalIndex = reloadedWallet.nextDerivationIndex(
133+
KeychainKind.external_,
134+
);
135+
expect(reloadedExternalIndex, equals(persistedExternalIndex));
136+
137+
final reloadedCheckpoint = reloadedWallet.latestCheckpoint();
138+
final reloadedCheckpointHeight = reloadedCheckpoint.height;
139+
addDisposer(disposers, reloadedCheckpoint.hash.dispose);
140+
printOnFailure(
141+
'Reloaded checkpoint height: $reloadedCheckpointHeight',
142+
);
143+
expect(
144+
reloadedCheckpointHeight,
145+
greaterThanOrEqualTo(checkpointBeforeHeight),
146+
);
147+
} finally {
148+
disposeAll(disposers);
149+
}
150+
},
151+
skip: integrationSkipReason(requiredEnv: [esploraUrlEnv]),
152+
);
153+
});
154+
}

0 commit comments

Comments
 (0)