Skip to content

feat(db): use deposit_address as PK instead of id (number) in nbtc_deposit_addresses#326

Closed
robert-zaremba wants to merge 4 commits intomasterfrom
robert/pk-nbtc-deposit-addresses
Closed

feat(db): use deposit_address as PK instead of id (number) in nbtc_deposit_addresses#326
robert-zaremba wants to merge 4 commits intomasterfrom
robert/pk-nbtc-deposit-addresses

Conversation

@robert-zaremba
Copy link
Contributor

@robert-zaremba robert-zaremba commented Jan 27, 2026

Summary by Sourcery

Switch nbtc_deposit_addresses to use deposit_address as the primary key instead of a numeric id and update related storage, queries, and schema accordingly.

Enhancements:

  • Refactor storage and indexer logic to reference deposit addresses directly rather than via numeric address IDs.
  • Simplify nbtc_minting and nbtc_utxos foreign key relationships to use deposit_address as the address identifier.
  • Adjust D1Storage and CFStorage models and queries to treat address_id as a string Bitcoin deposit address.

Tests:

  • Update unit tests and test helpers to work with deposit_address as the primary key for nbtc_deposit_addresses and remove an obsolete redeem input verification test path.

Chores:

  • Update initial database migration to reflect the new primary key and foreign key relationships for nbtc_deposit_addresses.

…t_addresses table

Signed-off-by: Robert Zaremba <robert@zaremba.ch>
@robert-zaremba robert-zaremba self-assigned this Jan 27, 2026
Copilot AI review requested due to automatic review settings January 27, 2026 23:11
@robert-zaremba robert-zaremba requested a review from a team as a code owner January 27, 2026 23:11
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Jan 27, 2026

Reviewer's Guide

Refactors the Bitcoin/nBTC indexing schema and logic so that deposit_address becomes the primary key and foreign key for nbtc_deposit_addresses, propagating this change through storage logic, queries, types, tests, and migrations to remove numeric address IDs in favor of using the deposit address string directly.

ER diagram for updated nbtc_deposit_addresses keying by deposit_address

erDiagram
  setups {
    INTEGER id PK
    TEXT btc_network
    TEXT sui_network
    TEXT nbtc_pkg
  }

  nbtc_deposit_addresses {
    TEXT deposit_address PK
    INTEGER setup_id FK
    INTEGER is_active
  }

  nbtc_minting {
    TEXT tx_id PK
    TEXT address_id FK
    TEXT sender
    INTEGER vout
    TEXT block_hash
    INTEGER block_height
    TEXT sui_recipient
    INTEGER amount
    TEXT status
    INTEGER created_at
    INTEGER updated_at
    TEXT sui_tx_id
    INTEGER retry_count
  }

  nbtc_utxos {
    INTEGER nbtc_utxo_id PK
    TEXT address_id FK
    TEXT dwallet_id
    TEXT txid
    INTEGER vout
    INTEGER amount
    BLOB script_pubkey
    TEXT status
    INTEGER locked_until
  }

  setups ||--o{ nbtc_deposit_addresses : has
  nbtc_deposit_addresses ||--o{ nbtc_minting : referenced_by
  nbtc_deposit_addresses ||--o{ nbtc_utxos : referenced_by
Loading

Class diagram for updated Utxo and UtxoRow address_id types

classDiagram
  class Utxo {
    +string nbtc_utxo_id
    +string dwallet_id
    +string txid
    +number vout
    +number amount
    +Uint8Array script_pubkey
    +string address_id
    +UtxoStatus status
    +number locked_until
  }

  class UtxoRow {
    +string nbtc_utxo_id
    +string dwallet_id
    +string txid
    +number vout
    +number amount
    +ArrayBuffer script_pubkey
    +string address_id
    +UtxoStatus status
    +number locked_until
  }

  Utxo <--> UtxoRow
Loading

File-Level Changes

Change Details Files
Use deposit_address as the primary and foreign key for nbtc_deposit_addresses instead of a numeric id, updating schema, FKs, and all associated joins.
  • Change nbtc_deposit_addresses schema so deposit_address is the TEXT PRIMARY KEY, remove the numeric id column and the unique constraint on deposit_address
  • Update nbtc_minting.address_id and nbtc_utxos.address_id columns from INTEGER to TEXT and change their FOREIGN KEY constraints to reference nbtc_deposit_addresses(deposit_address)
  • Adjust all SQL JOINs between nbtc_minting/nbtc_utxos and nbtc_deposit_addresses to join on address_id = deposit_address instead of id
packages/btcindexer/db/migrations/0001_initial_schema.sql
packages/btcindexer/src/cf-storage.ts
packages/sui-indexer/src/storage.ts
Remove address id lookups and derive address_id directly from the deposit address in application logic and test helpers.
  • In D1Storage.saveUtxos, stop querying nbtc_deposit_addresses for id by setup_id/deposit_address and instead store the deposit address itself in nbtc_utxos.address_id
  • Update all insert statements for nbtc_minting to bind the deposit address directly as address_id rather than subselecting an id from nbtc_deposit_addresses via setups and network/package filters
  • Simplify btcindexer test helper setupTestIndexerSuite to insert minting rows using the deposit address as address_id without first validating or resolving an internal numeric id
packages/sui-indexer/src/storage.ts
packages/btcindexer/src/cf-storage.ts
packages/btcindexer/src/btcindexer.helpers.test.ts
Align TypeScript models and tests with the new string-based address_id and adjusted insert APIs.
  • Change Utxo.address_id and UtxoRow.address_id types from number to string in the Sui indexer models and storage layer
  • Update test helpers and fixtures to stop passing numeric ids when inserting into nbtc_deposit_addresses and nbtc_minting, instead using deposit_address as the identifier
  • Comment out the redeem input verification test block that depends on numeric IDs, likely pending refactor to the new scheme
packages/sui-indexer/src/models.ts
packages/sui-indexer/src/storage.ts
packages/sui-indexer/src/storage.test.ts
packages/btcindexer/src/storage.test.ts

Possibly linked issues

  • #btcindexer: index deposit txs based on BTC and update API: PR migrates schema and storage to use BTC deposit_address as PK, matching issue’s BTC-based deposit indexing requirement.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In the initial schema, making deposit_address the primary key while keeping the comment -- make sure we don't share bitcoin deposit address between setups is slightly inconsistent with the new constraint (now it's globally unique, not per-setup); consider either changing the comment or using a composite key (e.g. (setup_id, deposit_address)) if per-setup uniqueness is actually desired.
  • In CFStorage the INSERT INTO nbtc_minting statements now bind address_id directly as deposit_address and no longer filter through setups metadata (btc_network, sui_network, nbtc_pkg); if multiple setups or networks can conceptually reuse addresses, you may want to keep an explicit join/validation to ensure the address maps to the expected setup before inserting.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the initial schema, making `deposit_address` the primary key while keeping the comment `-- make sure we don't share bitcoin deposit address between setups` is slightly inconsistent with the new constraint (now it's globally unique, not per-setup); consider either changing the comment or using a composite key (e.g. `(setup_id, deposit_address)`) if per-setup uniqueness is actually desired.
- In `CFStorage` the `INSERT INTO nbtc_minting` statements now bind `address_id` directly as `deposit_address` and no longer filter through `setups` metadata (btc_network, sui_network, nbtc_pkg); if multiple setups or networks can conceptually reuse addresses, you may want to keep an explicit join/validation to ensure the address maps to the expected setup before inserting.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Signed-off-by: Robert Zaremba <robert@zaremba.ch>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the D1 schema and related storage code to use the Bitcoin deposit_address (TEXT) as the primary key for nbtc_deposit_addresses, replacing the previous numeric id key.

Changes:

  • Updates the initial DB schema to make deposit_address the PK and changes dependent address_id columns/FKs to TEXT.
  • Updates Sui indexer storage/models to store and join on deposit_address instead of numeric IDs.
  • Updates btcindexer storage code and tests to insert/query using deposit_address directly.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/sui-indexer/src/storage.ts Writes/joins UTXOs using deposit_address as address_id
packages/sui-indexer/src/storage.test.ts Adjusts deposit address inserts for new schema
packages/sui-indexer/src/models.ts Updates Utxo.address_id type to string
packages/btcindexer/src/storage.test.ts Updates test inserts to omit numeric id
packages/btcindexer/src/cf-storage.ts Stores/joins minting rows using deposit_address
packages/btcindexer/src/btcindexer.helpers.test.ts Updates helper insert to use deposit_address directly
packages/btcindexer/db/migrations/0001_initial_schema.sql Changes PK/FKs to use deposit_address and TEXT address_id
Comments suppressed due to low confidence (1)

packages/sui-indexer/src/storage.test.ts:529

  • This test is currently effectively disabled: the calls/assertions are commented out, so markRedeemInputVerified is no longer exercised by the suite. Please re-enable the test (or replace it with an updated assertion) so regressions in verification logic are still caught.
		await storage.saveRedeemInputs([
			{
				redeem_id: 1,
				utxo_id: 1,
				input_index: 0,

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 164 to 168
await stmt
.bind(
u.nbtc_utxo_id,
addrRow.id,
depositAddress,
u.dwallet_id,
Copy link

Copilot AI Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

insertUtxo now writes depositAddress directly into nbtc_utxos.address_id without verifying that the derived address is registered for u.setup_id. With deposit_address being globally unique, a caller bug (wrong setup_id vs. script_pubkey) would still satisfy the FK and silently associate the UTXO with the other setup’s address. Consider restoring the invariant check by selecting setup_id from nbtc_deposit_addresses for depositAddress and throwing if it doesn’t match u.setup_id (or enforcing the relationship at the schema level).

Copilot uses AI. Check for mistakes.
Signed-off-by: Robert Zaremba <robert@zaremba.ch>
Signed-off-by: Robert Zaremba <robert@zaremba.ch>
@robert-zaremba robert-zaremba force-pushed the robert/pk-nbtc-deposit-addresses branch from 67260bc to 8dca98b Compare January 27, 2026 23:38
Copy link
Contributor

@sczembor sczembor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i am not sure about this change. I agree that the setup id is not needed, however it makes the whole thing more clear, now we have a field address_id that its not id, but the actual address

amount: number;
script_pubkey: Uint8Array;
address_id: number;
address_id: string; // deposit Bitcoin address
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it should be just address

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I will rename to deposit_address.

@robert-zaremba
Copy link
Contributor Author

Superseeded by: #328

@robert-zaremba robert-zaremba deleted the robert/pk-nbtc-deposit-addresses branch January 28, 2026 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants