@@ -2017,6 +2017,91 @@ fn print_current_holdings(
2017
2017
println ! ( ) ;
2018
2018
}
2019
2019
2020
+ fn merge_lots ( db : & mut Db , account_filter : Option < Pubkey > , verbose : bool ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
2021
+ let mut accounts = db. get_accounts ( ) ;
2022
+ accounts. sort_by ( |a, b| {
2023
+ let mut result = a. last_update_balance . cmp ( & b. last_update_balance ) ;
2024
+ if result == std:: cmp:: Ordering :: Equal {
2025
+ result = a. address . cmp ( & b. address ) ;
2026
+ }
2027
+ if result == std:: cmp:: Ordering :: Equal {
2028
+ result = a. description . cmp ( & b. description ) ;
2029
+ }
2030
+ result
2031
+ } ) ;
2032
+ for account in accounts. iter_mut ( ) {
2033
+ if let Some ( ref account_filter) = account_filter {
2034
+ if account. address != * account_filter {
2035
+ continue ;
2036
+ }
2037
+ }
2038
+ if account. lots . is_empty ( ) {
2039
+ continue ;
2040
+ }
2041
+ account
2042
+ . lots
2043
+ . sort_by ( |a, b| a. acquisition . when . cmp ( & b. acquisition . when ) ) ;
2044
+ let mut lot_num = 0 ;
2045
+ while lot_num < account. lots . len ( ) - 1 {
2046
+ let next_lot = account. lots . get ( lot_num + 1 ) . unwrap ( ) . clone ( ) ;
2047
+ let next_price = next_lot. acquisition . price ( ) ;
2048
+ let next_lot_number = next_lot. lot_number ;
2049
+ let this_lot = account. lots . get_mut ( lot_num) . unwrap ( ) ;
2050
+ let this_price = this_lot. acquisition . price ( ) ;
2051
+ let this_lot_number = this_lot. lot_number ;
2052
+ if this_lot. acquisition . when == next_lot. acquisition . when
2053
+ && this_price == next_price {
2054
+ this_lot. amount += next_lot. amount ;
2055
+ account. lots . remove ( lot_num + 1 ) ;
2056
+ if verbose {
2057
+ println ! (
2058
+ "merged lot {} into lot {}" ,
2059
+ next_lot_number,
2060
+ this_lot_number,
2061
+ ) ;
2062
+ }
2063
+ } else {
2064
+ lot_num += 1 ;
2065
+ }
2066
+ }
2067
+ db. update_account ( account. clone ( ) ) ?;
2068
+ }
2069
+ if account_filter. is_none ( ) {
2070
+ let mut disposed_lots = db. disposed_lots ( ) ;
2071
+ let mut lot_num = 0 ;
2072
+ while lot_num < disposed_lots. len ( ) - 1 {
2073
+ let next_lot = disposed_lots. get ( lot_num + 1 ) . unwrap ( ) . clone ( ) ;
2074
+ let next_price = next_lot. price ( ) ;
2075
+ let next_lot_number = next_lot. lot . lot_number ;
2076
+ let next_lot_acq_when = next_lot. lot . acquisition . when ;
2077
+ let next_lot_acq_price = next_lot. lot . acquisition . price ( ) ;
2078
+ let this_lot = disposed_lots. get_mut ( lot_num) . unwrap ( ) ;
2079
+ let this_price = this_lot. price ( ) ;
2080
+ let this_lot_number = this_lot. lot . lot_number ;
2081
+ let this_lot_acq_when = this_lot. lot . acquisition . when ;
2082
+ let this_lot_acq_price = this_lot. lot . acquisition . price ( ) ;
2083
+ if this_lot. when == next_lot. when
2084
+ && this_price == next_price
2085
+ && this_lot_acq_when == next_lot_acq_when
2086
+ && this_lot_acq_price == next_lot_acq_price {
2087
+ this_lot. lot . amount += next_lot. lot . amount ;
2088
+ disposed_lots. remove ( lot_num + 1 ) ;
2089
+ if verbose {
2090
+ println ! (
2091
+ "merged disposed lot {} into disposed lot {}" ,
2092
+ next_lot_number,
2093
+ this_lot_number,
2094
+ ) ;
2095
+ }
2096
+ } else {
2097
+ lot_num += 1 ;
2098
+ }
2099
+ }
2100
+ db. update_disposed_lots ( disposed_lots) ?;
2101
+ }
2102
+ Ok ( ( ) )
2103
+ }
2104
+
2020
2105
async fn process_account_list (
2021
2106
db : & Db ,
2022
2107
rpc_client : & RpcClient ,
@@ -5072,6 +5157,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
5072
5157
. validator ( is_valid_pubkey)
5073
5158
. help ( "Address to receive the lot" ) ,
5074
5159
)
5160
+ )
5161
+ . subcommand (
5162
+ SubCommand :: with_name ( "merge" )
5163
+ . about ( "Merge lots with same data and price into a single lot. \
5164
+ Useful to reduce the entropy")
5165
+ . arg (
5166
+ Arg :: with_name ( "account" )
5167
+ . value_name ( "ADDRESS" )
5168
+ . takes_value ( true )
5169
+ . validator ( is_valid_pubkey)
5170
+ . help ( "Do the merging for this account only" ) ,
5171
+ )
5075
5172
) ,
5076
5173
) ,
5077
5174
)
@@ -5916,6 +6013,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
5916
6013
db. delete_lot ( lot_number) ?;
5917
6014
}
5918
6015
}
6016
+ ( "merge" , Some ( arg_matches) ) => {
6017
+ let account_filter = pubkey_of ( arg_matches, "account" ) ;
6018
+ merge_lots ( & mut db, account_filter, verbose) ?;
6019
+ }
5919
6020
_ => unreachable ! ( ) ,
5920
6021
} ,
5921
6022
( "add" , Some ( arg_matches) ) => {
0 commit comments