EN
In the last post I showed how to use getAccountHistory to retrieve transactions of an account.
Today I want to show you a concrete example, one that I use for myself. I play Dcrops* and now i receive daily Hive rewards, because I have an Alpha Pack and Crops on my account. Since I have invested with others and we want to reinvest the hive, I wrote myself a script that tells me how much hive I have received in the meantime. Since I don't want to write this down every day and it's not always the same, I created the script.
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/@hiveio/hive-js/dist/hive.min.js"> </script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
(html comment removed: CSS only )
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
</head>
<body>
<div class="row">
<div class="col-xs-8 offset-sm-1">
<div class="row">
<div class="col-sm-6"><button id="show">Show Dcrops.Rewards</button></div>
</div>
<h2>Ausgabe/Output:</h2>
<div id="log2"></div>
<div id="log"></div>
</div>
</div>
<script>
var ChainTypes = {};
ChainTypes.reserved_spaces = {
relative_protocol_ids: 0,
protocol_ids: 1,
implementation_ids: 2
};
ChainTypes.operations= {
vote: 0,
comment: 1,
transfer: 2,
transfer_to_vesting: 3,
withdraw_vesting: 4,
limit_order_create: 5,
limit_order_cancel: 6,
feed_publish: 7,
convert: 8,
account_create: 9,
account_update: 10,
witness_update: 11,
account_witness_vote: 12,
account_witness_proxy: 13,
pow: 14,
custom: 15,
report_over_production: 16,
delete_comment: 17,
custom_json: 18,
comment_options: 19,
set_withdraw_vesting_route: 20,
limit_order_create2: 21,
claim_account: 22,
create_claimed_account: 23,
request_account_recovery: 24,
recover_account: 25,
change_recovery_account: 26,
escrow_transfer: 27,
escrow_dispute: 28,
escrow_release: 29,
pow2: 30,
escrow_approve: 31,
transfer_to_savings: 32,
transfer_from_savings: 33,
cancel_transfer_from_savings: 34,
custom_binary: 35,
decline_voting_rights: 36,
reset_account: 37,
set_reset_account: 38,
claim_reward_balance: 39,
delegate_vesting_shares: 40,
account_create_with_delegation: 41,
witness_set_properties: 42,
account_update2: 43,
create_proposal: 44,
update_proposal_votes: 45,
remove_proposal: 46,
update_proposal: 47,
collateralized_convert: 48,
recurrent_transfer: 49,
// virtual ops
fill_convert_request: 50,
author_reward: 51,
curation_reward: 52,
comment_reward: 53,
liquidity_reward: 54,
interest: 55,
fill_vesting_withdraw: 56,
fill_order: 57,
shutdown_witness: 58,
fill_transfer_from_savings: 59,
hardfork: 60,
comment_payout_update: 61,
return_vesting_delegation: 62,
comment_benefactor_reward: 63,
producer_reward: 64,
clear_null_account_balance: 65,
proposal_pay: 66,
sps_fund: 67,
hardfork_hive: 68,
hardfork_hive_restore: 69,
delayed_voting: 70,
consolidate_treasury_balance: 71,
effective_comment_vote: 72,
ineffective_delete_comment: 73,
sps_convert: 74,
expired_account_notification: 75,
changed_recovery_account: 76,
transfer_to_vesting_completed: 77,
pow_reward: 78,
vesting_shares_split: 79,
account_created: 80,
fill_collateralized_convert_request: 81,
system_warning: 82,
fill_recurrent_transfer: 83,
failed_recurrent_transfer: 84
};
//types.hpp
ChainTypes.object_type = {
"null": 0,
base: 1,
};
String.prototype.log = function () {
$("<div>"+this+"</div>").appendTo("#log");
};
String.prototype.log2 = function () {
$("#log2").html("<p>"+this+"</p>");
};
let makeBitMaskFilter = (allowedOperations) => {
return allowedOperations.reduce(([low, high], allowedOperation) => allowedOperation < 64 ?
[(low| (BigInt(1)<< BigInt(allowedOperation))), high]:
[low, (high| (BigInt(1)<< BigInt(allowedOperation-64)))],
[BigInt(0), BigInt(0)]).map(value => (value!== BigInt(0)) ? value.toString() : null);
};
const op = ChainTypes.operations;
const walletOperations = makeBitMaskFilter([
op.transfer
])
var rewards=0;
var last=0;
function getDcropsRewards(start){
let limit=1000;
hive.api.getAccountHistory('mein-senf-dazu', start, limit, walletOperations[0], walletOperations[0], function(err, result) {
if(err===null){
for(i=result.length-1;i>=0;i--){
let r=result[i];
if(r[1].op[1].from==="dcrops.rewards"){
(r[1].timestamp+": "+r[1].op[1].amount).log();
rewards+=parseFloat(r[1].op[1].amount.replace(" HIVE",""));
last=r[0]-1;
("Gesamtausschüttung/ Total rewards: "+rewards.toFixed(3)+" HIVE").log2();
}
}
console.log(last,start);
if(last<start || start==-1)
getDcropsRewards(last);
}
else
console.log(err);
});
}
$("#show").click(function() {
getDcropsRewards(-1);
});
</script>
</body>
</html>
I don't need to say anything about the first lines, you can read that in the previous post. Therefore I jump directly to lines 125-131. I have extended String by two functions to simplify the output for me. I have used this for myself many times before.
The lines 134-144 we already know from the previous post, where I made walletOperationslow and walletOperationsheigh now simply walletOperations, because I could not see any difference anyway and besides I only want to read "transfer".
I created the function getDcropsRewards which expects a parameter, this parameter is passed to getAccountHistory and specifies from where the data should be retrieved.
So I call my function by clicking on the button with the start value -1, where -1 stands for "start from last entry", you know that if you read the last post.
So getAccountHistory will be called after clicking on the button with the parameters 'mein-senf-dazu', -1, 1000 and transfer.
In lines 155-163, the response is run through and checked to see if the transfer came from the @dcrops.rewards account. If it did, the date and amount are printed (line 158) and the amount is summed (line 159). The id of the entry minus 1 is stored in the variable last (line 160). Since I can only retrieve 1000 entries at a time, I have to make this call with a new start id (line 166).
For this I check if last is less than start, because if not, I can stop, since I retrieved the last entry. Finally, for a few weeks I get this daily.
In another application you would rather have to move line 160 between 162 and 163 and change line 165 to "if(last>0)", then you would completely run through everything.
As I just noticed, I could still optimize the code, because I probably often retrieve data that I have already retrieved. I will change that and submit the optimized code later.
I hope it was understandable so far. If someone has questions, just leave a comment and let me know with @mein-senf-dazu.
As always you can find the code on jsfiddle and you can test it there and just copy it.
*My affiliate link, if you use this and buy packs I get a little something, you won't be harmed.
Translated with www.DeepL.com/Translator (free version)
DE
Im letzten Beitrag habe ich gezeigt, wie man mit getAccountHistory Transaktionen eines Accounts abrufen kann.
Heute möchte ich euch ein konkretes Beispiel zeigen, eins, dass ich für mich nutze. Ich spiele Dcrops* und erhalte inzwischen täglich Hive, da ich ein Alpha-Pack und Crops auf dem Account habe. Da ich mit anderen investiert habe und wir die Hive reinvestieren wollen, habe ich mir ein Script geschrieben, das mir ausgibt, wie viel Hive ich inzwischen bekommen habe. Da ich das nicht täglich notieren will und es nicht immer gleich ist, habe ich das Script erstellt.
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/@hiveio/hive-js/dist/hive.min.js"> </script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
(html comment removed: CSS only )
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
</head>
<body>
<div class="row">
<div class="col-xs-8 offset-sm-1">
<div class="row">
<div class="col-sm-6"><button id="show">Show Dcrops.Rewards</button></div>
</div>
<h2>Ausgabe/Output:</h2>
<div id="log2"></div>
<div id="log"></div>
</div>
</div>
<script>
var ChainTypes = {};
ChainTypes.reserved_spaces = {
relative_protocol_ids: 0,
protocol_ids: 1,
implementation_ids: 2
};
ChainTypes.operations= {
vote: 0,
comment: 1,
transfer: 2,
transfer_to_vesting: 3,
withdraw_vesting: 4,
limit_order_create: 5,
limit_order_cancel: 6,
feed_publish: 7,
convert: 8,
account_create: 9,
account_update: 10,
witness_update: 11,
account_witness_vote: 12,
account_witness_proxy: 13,
pow: 14,
custom: 15,
report_over_production: 16,
delete_comment: 17,
custom_json: 18,
comment_options: 19,
set_withdraw_vesting_route: 20,
limit_order_create2: 21,
claim_account: 22,
create_claimed_account: 23,
request_account_recovery: 24,
recover_account: 25,
change_recovery_account: 26,
escrow_transfer: 27,
escrow_dispute: 28,
escrow_release: 29,
pow2: 30,
escrow_approve: 31,
transfer_to_savings: 32,
transfer_from_savings: 33,
cancel_transfer_from_savings: 34,
custom_binary: 35,
decline_voting_rights: 36,
reset_account: 37,
set_reset_account: 38,
claim_reward_balance: 39,
delegate_vesting_shares: 40,
account_create_with_delegation: 41,
witness_set_properties: 42,
account_update2: 43,
create_proposal: 44,
update_proposal_votes: 45,
remove_proposal: 46,
update_proposal: 47,
collateralized_convert: 48,
recurrent_transfer: 49,
// virtual ops
fill_convert_request: 50,
author_reward: 51,
curation_reward: 52,
comment_reward: 53,
liquidity_reward: 54,
interest: 55,
fill_vesting_withdraw: 56,
fill_order: 57,
shutdown_witness: 58,
fill_transfer_from_savings: 59,
hardfork: 60,
comment_payout_update: 61,
return_vesting_delegation: 62,
comment_benefactor_reward: 63,
producer_reward: 64,
clear_null_account_balance: 65,
proposal_pay: 66,
sps_fund: 67,
hardfork_hive: 68,
hardfork_hive_restore: 69,
delayed_voting: 70,
consolidate_treasury_balance: 71,
effective_comment_vote: 72,
ineffective_delete_comment: 73,
sps_convert: 74,
expired_account_notification: 75,
changed_recovery_account: 76,
transfer_to_vesting_completed: 77,
pow_reward: 78,
vesting_shares_split: 79,
account_created: 80,
fill_collateralized_convert_request: 81,
system_warning: 82,
fill_recurrent_transfer: 83,
failed_recurrent_transfer: 84
};
//types.hpp
ChainTypes.object_type = {
"null": 0,
base: 1,
};
String.prototype.log = function () {
$("<div>"+this+"</div>").appendTo("#log");
};
String.prototype.log2 = function () {
$("#log2").html("<p>"+this+"</p>");
};
let makeBitMaskFilter = (allowedOperations) => {
return allowedOperations.reduce(([low, high], allowedOperation) => allowedOperation < 64 ?
[(low| (BigInt(1)<< BigInt(allowedOperation))), high]:
[low, (high| (BigInt(1)<< BigInt(allowedOperation-64)))],
[BigInt(0), BigInt(0)]).map(value => (value!== BigInt(0)) ? value.toString() : null);
};
const op = ChainTypes.operations;
const walletOperations = makeBitMaskFilter([
op.transfer
])
var rewards=0;
var last=0;
function getDcropsRewards(start){
let limit=1000;
hive.api.getAccountHistory('mein-senf-dazu', start, limit, walletOperations[0], walletOperations[0], function(err, result) {
if(err===null){
for(i=result.length-1;i>=0;i--){
let r=result[i];
if(r[1].op[1].from==="dcrops.rewards"){
(r[1].timestamp+": "+r[1].op[1].amount).log();
rewards+=parseFloat(r[1].op[1].amount.replace(" HIVE",""));
last=r[0]-1;
("Gesamtausschüttung/ Total rewards: "+rewards.toFixed(3)+" HIVE").log2();
}
}
console.log(last,start);
if(last<start || start==-1)
getDcropsRewards(last);
}
else
console.log(err);
});
}
$("#show").click(function() {
getDcropsRewards(-1);
});
</script>
</body>
</html>
Zu den ersten Zeilen brauche ich nichts sagen, das könnt ihr ja im vorherigen Beitrag lesen. Daher springe ich mal direkt zu Zeile 125-131. Ich habe hier String um zwei Funktionen erweitert, um für mich die Ausgabe etwas zu vereinfachen. Dies habe ich für mich schon öfters genutzt.
Die Zeilen 134-144 kennen wir bereits aus dem vorherigen Beitrag, wobei ich aus walletOperationslow und walletOperationsheigh nun einfach walletOperations gemacht habe, da ich eh keinen Unterschied erkennen konnte und zudem ich nur "transfer" auslesen möchte.
Ich habe mir die Funktion getDcropsRewards erstellt, die einen Parameter erwartet, dieser Parameter wird an getAccountHistory übergeben und gibt an, ab wo die Daten abgerufen werden sollen.
So rufe ich meine Funktion durch einen Klick auf den Button mit dem Startwert -1 auf, wobei -1 für "Start vom letzten Eintrag" steht, das wisst ihr, wenn ihr den letzten Beitrag gelesen habt.
Somit wird getAccountHistory nach dem Klick auf den Button mit den Parametern 'mein-senf-dazu', -1, 1000 und transfer.
In Zeile 155-163 wird die Antwort durchlaufen und geprüft, ob der Transfer vom Account @dcrops.rewards kam. Wenn das der Fall ist, wird das Datum und der Betrag ausgegeben (Zeile 158) und der Betrag aufsummiert (Zeile 159). Die Id des Eintrages minus 1 wird in der Variablen last gespeichert (Zeile 160). Da ich immer nur 1000 Einträge abrufen kann, muss ich diesen Aufruf mit einer neuen Startid durchführen (Zeile 166).
Dafür prüfe ich, ob last kleiner start ist, denn wenn nicht, dann kann ich aufhören, da habe ich den letzten Eintrag abgerufen. Schließlich bekomme ich seit paar Wochen dies täglich.
In einer anderen Anwendung müsste man eher Zeile 160 zwischen 162 und 163 verschieben und die Zeile 165 abändern in "if(last>0)", dann würde man komplett alles durchlaufen.
Wie mir gerade auffällt, könnte ich den Code noch optimieren, da ich wohl oft Daten abrufe, die ich bereits abgerufen habe. Das werde ich mal ändern und den optimierten Code noch nachreichen.
Ich hoffe, es war soweit verständlich. Wenn jemand Fragen hat, einfach ein Kommentar da lassen und am besten mich mit @mein-senf-dazu benachrichtigen.
Den Code findet ihr wie immer auf jsfiddle und könnt da etwas testen und es einfach kopieren.
*Mein Affiliate-Link, wenn ihr diesen nutzt und Packs kauft, erhalte ich eine Kleinigkeit, euch schadet es nicht.