@@ -9,13 +9,34 @@ use axum_macros::debug_handler;
99use cached:: proc_macro:: once;
1010use rust_embed:: Embed ;
1111use std:: time:: Duration ;
12- use tracing:: { debug, error, info} ;
12+
13+ #[ derive( Debug , Clone , Default ) ]
14+ pub struct RepoUrl ( String ) ;
15+
16+ impl RepoUrl {
17+ pub fn new ( url : String ) -> Self {
18+ Self ( url)
19+ }
20+
21+ pub fn is_github ( & self ) -> bool {
22+ self . 0 . starts_with ( "https://github.com" )
23+ }
24+ }
25+
26+ impl std:: fmt:: Display for RepoUrl {
27+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
28+ write ! ( f, "{}" , self . 0 )
29+ }
30+ }
1331
1432#[ derive( Debug , Clone ) ]
1533pub struct PaidCommit {
1634 pub amount : String ,
1735 pub timestamp : u64 ,
1836 pub contributor_name : String ,
37+ pub commit_id : String ,
38+ pub commit_message : String ,
39+ pub currency : String ,
1940}
2041
2142#[ derive( Template , Debug , Clone , Default ) ]
@@ -26,7 +47,7 @@ pub struct IndexTemplate {
2647 pub monero_block_height : u64 ,
2748 pub monero_network : String ,
2849 pub monero_wallet_address : String ,
29- pub repository_url : String ,
50+ pub repository_url : RepoUrl ,
3051 pub commits : Vec < PaidCommit > ,
3152 pub monero_balance_usd : String ,
3253}
@@ -119,24 +140,35 @@ pub async fn refresh(State(state): State<AppState>) {
119140 crate :: currency:: Address :: BTC ( _) => todo ! ( ) ,
120141 #[ cfg( feature = "monero" ) ]
121142 crate :: currency:: Address :: XMR ( address) => {
122- let transfer_count = state. monero . count_transfers ( & address) . await . unwrap ( ) ;
123- debug ! ( count = transfer_count, address = ?address, "Transfers to XMR address" ) ;
124-
125- for commit_id in contributor. commits . iter ( ) . skip ( transfer_count) {
126- match state
127- . monero
128- . transfer (
129- & address,
130- monero_rpc:: monero:: Amount :: from_pico (
131- contributor. compute_payout ( commit_id. clone ( ) , state. base_payout , state. max_payout_cap ) ,
132- ) ,
133- commit_id,
134- )
135- . await
136- {
137- Ok ( _) => info ! ( "Transfer complete" ) ,
138- Err ( e) => error ! ( error=%e, "Transfer failed" ) ,
139- } ;
143+ debug ! ( address = ?address, total_commits = contributor. commits. len( ) , "Processing XMR contributor" ) ;
144+
145+ for commit_id in contributor. commits . iter ( ) {
146+ // Check if this commit was already paid using its dedicated subaddress
147+ match state. monero . is_commit_paid ( * commit_id) . await {
148+ Ok ( true ) => {
149+ debug ! ( commit = ?commit_id, "Commit already paid, skipping" ) ;
150+ continue ;
151+ }
152+ Ok ( false ) => {
153+ // Not paid yet, proceed with transfer
154+ let payout = contributor. compute_payout ( * commit_id, state. base_payout , state. max_payout_cap ) ;
155+ match state
156+ . monero
157+ . transfer (
158+ & address,
159+ monero_rpc:: monero:: Amount :: from_pico ( payout) ,
160+ commit_id,
161+ )
162+ . await
163+ {
164+ Ok ( _) => info ! ( commit = ?commit_id, amount = payout, "Transfer complete" ) ,
165+ Err ( e) => error ! ( commit = ?commit_id, error=%e, "Transfer failed" ) ,
166+ } ;
167+ }
168+ Err ( e) => {
169+ error ! ( commit = ?commit_id, error=%e, "Failed to check if commit was paid" ) ;
170+ }
171+ }
140172 }
141173 }
142174 } ;
0 commit comments