Skip to content

Commit 69f59ca

Browse files
update still not working
1 parent e73d75b commit 69f59ca

4 files changed

Lines changed: 87 additions & 28 deletions

File tree

Cargo.toml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,28 @@ version = "0.0.1"
44
edition = "2021"
55

66
[dependencies]
7-
bdk_wallet = { version = "1.2.0", features = ["test-utils"] }
87
serde = { version = "1.0.208", features = ["derive"] }
98
serde_json = "1.0.125"
109
sqlx = { version = "0.8.1", default-features = false, features = ["runtime-tokio", "tls-rustls-ring","derive", "postgres", "sqlite", "json", "chrono", "uuid", "sqlx-macros", "migrate"] }
1110
thiserror = "1"
1211
tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] }
1312
tracing = "0.1.40"
1413
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "serde_json", "json"] }
15-
sqlx-postgres-tester = "0.1.1"
14+
15+
[dependencies.bdk_wallet]
16+
git = "https://github.com/bitcoindevkit/bdk_wallet.git"
17+
tag = "wallet-2.0.0"
18+
features = ["test-utils"]
1619

1720
[dev-dependencies]
1821
assert_matches = "1.5.0"
1922
anyhow = "1.0.89"
20-
bdk_electrum = { version = "0.20.1"}
2123
rustls = "0.23.14"
2224

25+
[dev-dependencies.bdk_electrum]
26+
git = "https://github.com/bitcoindevkit/bdk.git"
27+
tag = "chain-0.23.0"
28+
2329
[[example]]
2430
name = "bdk_sqlx_postgres"
2531
path = "examples/bdk_sqlx_postgres.rs"

examples/bdk_sqlx_postgres.rs

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
#![allow(unused)]
2-
use std::collections::HashSet;
3-
use std::io::Write;
4-
2+
use anyhow::Context;
53
use bdk_electrum::{electrum_client, BdkElectrumClient};
64
use bdk_sqlx::sqlx::Postgres;
75
use bdk_sqlx::{PgStoreBuilder, Store};
86
use bdk_wallet::bitcoin::secp256k1::Secp256k1;
97
use bdk_wallet::bitcoin::Network;
10-
use bdk_wallet::{KeychainKind, PersistedWallet, Wallet};
8+
use bdk_wallet::chain::spk_client::{FullScanRequest, SyncRequest};
9+
use bdk_wallet::{KeychainKind, PersistedWallet, Update, Wallet};
1110
use rustls::crypto::ring::default_provider;
11+
use std::collections::HashSet;
12+
use std::io::Write;
1213
use tracing_subscriber::layer::SubscriberExt;
1314
use tracing_subscriber::util::SubscriberInitExt;
1415
use tracing_subscriber::EnvFilter;
@@ -119,31 +120,45 @@ async fn main() -> anyhow::Result<()> {
119120

120121
Ok(())
121122
}
122-
123123
fn electrum(wallet: &mut PersistedWallet<Store<Postgres>>) -> anyhow::Result<()> {
124124
let client = BdkElectrumClient::new(electrum_client::Client::new(ELECTRUM_URL)?);
125125

126126
// Populate the electrum client's transaction cache so it doesn't re-download transaction we
127127
// already have.
128128
client.populate_tx_cache(wallet.tx_graph().full_txs().map(|tx_node| tx_node.tx));
129129

130-
let request = wallet.start_full_scan().inspect({
131-
let mut stdout = std::io::stdout();
132-
let mut once = HashSet::<KeychainKind>::new();
133-
move |k, spk_i, _| {
134-
if once.insert(k) {
135-
print!("\nScanning keychain [{:?}]", k);
136-
}
137-
print!(" {:<3}", spk_i);
138-
stdout.flush().expect("must flush");
139-
}
140-
});
141-
142-
let update = client.full_scan(request, STOP_GAP, BATCH_SIZE, true)?;
143-
144-
println!();
130+
131+
let graph = wallet.tx_graph();
132+
let chain = wallet.local_chain();
133+
let request = {
134+
FullScanRequest::builder()
135+
.chain_tip(chain.tip())
136+
.spks_for_keychain(
137+
KeychainKind::External,
138+
graph
139+
.index
140+
.unbounded_spk_iter(KeychainKind::External)
141+
.into_iter()
142+
.flatten(),
143+
)
144+
.spks_for_keychain(
145+
KeychainKind::Internal,
146+
graph
147+
.index
148+
.unbounded_spk_iter(KeychainKind::Internal)
149+
.into_iter()
150+
.flatten(),
151+
)
152+
};
145153

146-
wallet.apply_update(update)?;
154+
let res = client
155+
.full_scan::<_>(request, STOP_GAP, BATCH_SIZE, false)
156+
.context("scanning the blockchain")?;
157+
(
158+
res.chain_update,
159+
res.tx_update,
160+
Some(res.last_active_indices),
161+
);
147162

148163
Ok(())
149164
}

migrations/postgres/01_bdk_wallet.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ CREATE TABLE IF NOT EXISTS bdk_wallet.tx (
4343
txid TEXT NOT NULL,
4444
whole_tx BYTEA,
4545
last_seen BIGINT,
46+
last_evicted BIGINT,
47+
first_seen BIGINT,
4648
PRIMARY KEY (wallet_name, txid)
4749
);
4850

src/postgres.rs

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ impl Store<Postgres> {
250250
txid TEXT NOT NULL,
251251
whole_tx BYTEA,
252252
last_seen BIGINT,
253+
last_evicted BIGINT,
254+
first_seen BIGINT,
253255
PRIMARY KEY (wallet_name, txid)
254256
)"#,
255257
r#"CREATE TABLE IF NOT EXISTS "bdk_wallet"."txout" (
@@ -283,14 +285,42 @@ impl Store<Postgres> {
283285
})?;
284286
}
285287

286-
// At the end of migration, insert the current version
287-
// After all tables are created but before tx.commit()
288+
// Check current schema version and apply migrations if needed
289+
let current_version: Option<i32> = sqlx::query_scalar(
290+
r#"SELECT version FROM "bdk_wallet"."version" ORDER BY version DESC LIMIT 1"#,
291+
)
292+
.fetch_optional(&mut *tx)
293+
.await
294+
.map_err(|e| BdkSqlxError::QueryError {
295+
table: "select version".to_string(),
296+
source: e,
297+
})?;
298+
299+
match current_version {
300+
Some(1) => {
301+
// Migrate from v1 to v2: Add last_evicted and first_seen columns
302+
sqlx::query(
303+
r#"ALTER TABLE "bdk_wallet"."tx"
304+
ADD COLUMN IF NOT EXISTS last_evicted BIGINT,
305+
ADD COLUMN IF NOT EXISTS first_seen BIGINT"#,
306+
)
307+
.execute(&mut *tx)
308+
.await
309+
.map_err(|e| BdkSqlxError::QueryError {
310+
table: "alter tx table".to_string(),
311+
source: e,
312+
})?;
313+
}
314+
_ => {} // Fresh install or already at v2
315+
}
316+
317+
// Insert or update to current version
288318
sqlx::query(
289319
r#"INSERT INTO "bdk_wallet"."version" (version)
290320
VALUES ($1)
291321
ON CONFLICT (version) DO NOTHING"#,
292322
)
293-
.bind(1) // Current schema version
323+
.bind(2) // Current schema version is now 2
294324
.execute(&mut *tx)
295325
.await
296326
.map_err(|e| BdkSqlxError::QueryError {
@@ -512,7 +542,7 @@ pub async fn tx_graph_changeset_from_postgres(
512542

513543
// Fetch transactions
514544
let rows = sqlx::query(
515-
r#"SELECT txid, whole_tx, last_seen FROM "bdk_wallet"."tx" WHERE wallet_name = $1"#,
545+
r#"SELECT txid, whole_tx, last_seen, last_evicted, first_seen FROM "bdk_wallet"."tx" WHERE wallet_name = $1"#,
516546
)
517547
.bind(wallet_name)
518548
.fetch_all(&mut **db_tx)
@@ -527,6 +557,8 @@ pub async fn tx_graph_changeset_from_postgres(
527557
let txid = Txid::from_str(&txid)?;
528558
let whole_tx: Option<Vec<u8>> = row.get("whole_tx");
529559
let last_seen: Option<i64> = row.get("last_seen");
560+
let _last_evicted: Option<i64> = row.get("last_evicted");
561+
let _first_seen: Option<i64> = row.get("first_seen");
530562

531563
if let Some(tx_bytes) = whole_tx {
532564
if let Ok(tx) = bitcoin::Transaction::consensus_decode(&mut tx_bytes.as_slice()) {
@@ -536,6 +568,8 @@ pub async fn tx_graph_changeset_from_postgres(
536568
if let Some(last_seen) = last_seen {
537569
changeset.last_seen.insert(txid, last_seen as u64);
538570
}
571+
// Note: last_evicted and first_seen are fetched but not yet used in ChangeSet
572+
// These fields are stored for future use when bdk_chain supports them
539573
}
540574

541575
// Fetch txouts
@@ -602,6 +636,8 @@ pub async fn tx_graph_changeset_persist_to_postgres(
602636
) -> Result<()> {
603637
trace!("tx graph changeset from postgres");
604638
for tx in &changeset.txs {
639+
// Note: last_evicted and first_seen columns are reserved for future use
640+
// when bdk_chain adds support for these fields in ChangeSet
605641
sqlx::query(
606642
r#"INSERT INTO "bdk_wallet"."tx" (wallet_name, txid, whole_tx) VALUES ($1, $2, $3)
607643
ON CONFLICT (wallet_name, txid) DO UPDATE SET whole_tx = $3"#,

0 commit comments

Comments
 (0)