Skip to content

Conversation

@bertllll
Copy link
Contributor

No description provided.

a tx to the blockchain, and the tx is pending.
2. `pendingTxHashOpt` is not null and `failures` is greater than 0. This means that we've made more than one attempt.
There is an alive pending tx, plus we've experienced X failures before that.
3. `pendingTxHashOpt` is null and `failures` is greater than 0. This means that the payment mechanism is in a mid-state
Copy link
Collaborator

Choose a reason for hiding this comment

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

This case is bit confusing, we should always have a transaction hash, as it is generated locally.

"0x0290db1d56121112f4d45c1c3f36348644f6afd20b759b762f1dba9c4949066e"
.to_string(),
balance_gwei: 999888777,
tx_processing_info_opt: Some(TxProcessingInfo{pending_tx_hash_opt: Some("0x0290db1d56121112f4d45c1c3f36348644f6afd20b759b762f1dba9c4949066e".to_string()),failures: 0}
Copy link
Collaborator

Choose a reason for hiding this comment

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

According to me, the inner Some shouldn't exist, tx hash should be a compulsory value.

)
}
},
tx_processing_info_opt: account_with_tx_info.tx_opt,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Names could be consistent here.

if gwei > 0 {
gwei
} else {
panic!(
Copy link
Collaborator

Choose a reason for hiding this comment

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

This panic could be abstracted if you use a TryFrom conversion here, it'll look cleaner if you do that way.

gwei
} else {
panic!(
"Broken code: ReceivableAccount with balance between {} and 0 gwei \
Copy link
Collaborator

Choose a reason for hiding this comment

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

You may prefer to use the same code for conversion. If you decide to do so then prefer this piece of code over the other.

pending_payable_opt: None,
PayableAccountWithTxInfo {
account: PayableAccount {
wallet: make_wallet("ac3665c"),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Optional: Prefer Using Address over Wallet. (I know it's a time consuming change, that's why I kept it as optional)

account: PayableAccount {
wallet: make_wallet("abcd123"),
balance_wei: 58_568_686_005,
last_paid_timestamp: SystemTime::now().sub(Duration::from_secs(5000)),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Timestamp should be an u64, instead of SystemTime because precision here is useless.

Copy link
Collaborator

@utkarshg6 utkarshg6 left a comment

Choose a reason for hiding this comment

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

Continue at node/src/accountant/db_access_objects/payable_dao.rs

})
}
},
tx_opt: Self::maybe_construct_tx_info(tx_hash_opt, previous_failures),
Copy link
Collaborator

Choose a reason for hiding this comment

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

This function is not a good idea, there is a lot of uncertainty. In this whole PR, these Optional values are my biggest concern, prefer using absolute values so that guaranteed values are returned.

Copy link
Collaborator

@utkarshg6 utkarshg6 left a comment

Choose a reason for hiding this comment

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

Continue at node/src/accountant/db_access_objects/payable_dao.rs:367

{},
{}
{}",
"SELECT
Copy link
Collaborator

@utkarshg6 utkarshg6 Nov 22, 2025

Choose a reason for hiding this comment

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

Please add a comment at the top of this fn saying:

// A dynamic SQL query that joins payable, sent_payable, and failed_payable
// to provide comprehensive information about accounts that need to be paid, 
// including their current transaction processing status.

This comment only explains what this SQL does, but it's still a mystery Why it exists?

The Why is a more important question to answer here. So, please write an explanation why you wrote this code.

WHERE nonce = (SELECT MAX(nonce) FROM nonces_of_failures_by_wallet)
)
ELSE 0
END AS recent_failures_count
Copy link
Collaborator

@utkarshg6 utkarshg6 Nov 22, 2025

Choose a reason for hiding this comment

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

You can replace the entire EXISTS clause with this code:

(
    SELECT COUNT(*)
    FROM failed_payable
    WHERE receiver_address = p.wallet_address
        AND status NOT LIKE '%Concluded%'
        AND nonce = (
            SELECT MAX(nonce)
            FROM failed_payable
            WHERE receiver_address = p.wallet_address
                AND status NOT LIKE '%Concluded%'
        )
) AS recent_failures_count

It'll automatically return 0 if no cases match.

CASE WHEN s.status LIKE '%Pending%'
THEN s.tx_hash
ELSE NULL
END AS pending_tx_hash,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Always fetch the tx_hash and store the transaction status in a boolean called is_pending. Using NULL can cause confusion about whether the hash was ever present or removed conditionally. Since NULL values can lead to complications in SQL, it's best to avoid them.

You may use this code below:

s.tx_hash AS pending_tx_hash,
CASE WHEN s.status LIKE '%Pending%'
    THEN 1
    ELSE 0
END AS is_pending

Copy link
Collaborator

@utkarshg6 utkarshg6 left a comment

Choose a reason for hiding this comment

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

Continue at node/src/accountant/db_access_objects/payable_dao.rs:871

let mut sent_tx_2 = make_sent_tx(345);
sent_tx_2.receiver_address = Wallet::new(wallet_addr).address();
let sent_tx_hash_2 = sent_tx_2.hash;
let mut failed_tx_1 = make_failed_tx(123);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Optional: Call for a builder pattern here (everywhere in this test tbh, but it's up to you).

assert_eq!(
result,
vec![
PayableAccountWithTxInfo {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is general comment, you don't need to fix anything in specific here.

The thing is making assertions on everything can weaken test clarity, causing readers to overlook the specific fields or parameters we intended to highlight. This reduces code readability. I prefer to assert only on the items that we truly want to test.

2_500_647_000,
);
sent_payable_dao
.insert_new_records(&btreeset![SentTx {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Prefer creating SentTx using the builder method.

Copy link
Collaborator

@utkarshg6 utkarshg6 left a comment

Choose a reason for hiding this comment

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

Continue at node/src/accountant/db_access_objects/payable_dao.rs:1716

Copy link
Collaborator

@utkarshg6 utkarshg6 left a comment

Choose a reason for hiding this comment

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

Done!

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