ido: record EntryDistributed per distribution tx with the entry's txid

The EntryDistributed update was pushed in the POSTLAUNCH->DISTRIBUTED
branch using the collection tx's own txid. That branch fires once at
final collection rather than per distribution tx, and tx.compute_txid()
never equals an entry's creation txid, so the dist_expr join
(d.entry_txid = e.txid) never matched and entries were never marked
distributed.

Push it in the DISTRIBUTING handler instead, once per distribution tx,
using input#1.previous_output.txid (the entry NFT being spent), which is
the entry's creation txid recorded by IdoUpdate::Entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hossein Zoda 2026-06-23 12:57:31 +00:00
parent f9ee877392
commit b88475a75b

View file

@ -1908,7 +1908,7 @@ enum IdoUpdate {
OfferingTokenId(Vec<u8>), OfferingTokenId(Vec<u8>),
Entry(IdoUpdateEntry), Entry(IdoUpdateEntry),
EntryDistributed { EntryDistributed {
txid: Vec<u8>, entry_txid: Vec<u8>,
}, },
} }
@ -1989,8 +1989,8 @@ fn print_updates(updates: &[IdoUpdate]) {
let v = rev_blob(&value.txid); let v = rev_blob(&value.txid);
debug!("IDO IdoUpdate::Entry(value): {}", hex::encode(v)); debug!("IDO IdoUpdate::Entry(value): {}", hex::encode(v));
} }
IdoUpdate::EntryDistributed { txid } => { IdoUpdate::EntryDistributed { entry_txid } => {
let v = rev_blob(txid); let v = rev_blob(entry_txid);
debug!("IDO IdoUpdate::EntryDistributed: {}", hex::encode(v)); debug!("IDO IdoUpdate::EntryDistributed: {}", hex::encode(v));
} }
} }
@ -2282,6 +2282,11 @@ fn ido_add_tx(context: &IdoContext, tx: &Transaction) -> Result<IdoAddResult> {
} }
_ => return Err(anyhow::anyhow!("expecting active parameters")), _ => return Err(anyhow::anyhow!("expecting active parameters")),
} }
// input#1
let second_input = tx
.input
.get(1)
.ok_or_else(|| anyhow::anyhow!("Should have the second input!"))?;
// output#0 should contain a token with offering_token_id // output#0 should contain a token with offering_token_id
let first_output = tx let first_output = tx
.output .output
@ -2356,6 +2361,9 @@ fn ido_add_tx(context: &IdoContext, tx: &Transaction) -> Result<IdoAddResult> {
} else { } else {
return Err(anyhow::anyhow!("output#0 is not recognized!")); return Err(anyhow::anyhow!("output#0 is not recognized!"));
} }
updates.push(IdoUpdate::EntryDistributed {
entry_txid: second_input.previous_output.txid.to_blob(),
});
print_updates(&updates); print_updates(&updates);
Ok(IdoAddResult { Ok(IdoAddResult {
updates, updates,
@ -2406,9 +2414,6 @@ fn ido_add_tx(context: &IdoContext, tx: &Transaction) -> Result<IdoAddResult> {
platformEarnedAmount: prev_state.platformEarnedAmount.clone(), platformEarnedAmount: prev_state.platformEarnedAmount.clone(),
}, },
))); )));
updates.push(IdoUpdate::EntryDistributed {
txid: tx.compute_txid().to_blob(),
});
print_updates(&updates); print_updates(&updates);
Ok(IdoAddResult { Ok(IdoAddResult {
updates, updates,
@ -2540,14 +2545,14 @@ async fn upsert_updates_to_ido_entries(
.execute(&mut **dbtx) .execute(&mut **dbtx)
.await?; .await?;
} }
IdoUpdate::EntryDistributed { txid } => { IdoUpdate::EntryDistributed { entry_txid } => {
sqlx::query( sqlx::query(
"INSERT INTO ido_distribution (ido_id, entry_txid, txid, blockhash) "INSERT INTO ido_distribution (ido_id, entry_txid, txid, blockhash)
VALUES (?, ?, ?, ?) VALUES (?, ?, ?, ?)
ON CONFLICT(ido_id, entry_txid) DO NOTHING", ON CONFLICT(ido_id, entry_txid) DO NOTHING",
) )
.bind(internal_id) .bind(internal_id)
.bind(txid) .bind(entry_txid)
.bind(tx_txid) .bind(tx_txid)
.bind(&blockhash_blob) .bind(&blockhash_blob)
.execute(&mut **dbtx) .execute(&mut **dbtx)