Skip to content
Snippets Groups Projects
Verified Commit a5727227 authored by Mateusz Tyszczak's avatar Mateusz Tyszczak :scroll:
Browse files

Implement full manabar observer

parent 8988a7d9
No related branches found
No related tags found
No related merge requests found
......@@ -71,7 +71,7 @@ undefined
#### Defined in
src/interfaces.ts:63
src/interfaces.ts:72
<a name="interfacesioperationdatamd"></a>
......@@ -105,6 +105,31 @@ src/interfaces.ts:19
## Methods
### accountFullManabar
**accountFullManabar**(`name`): `Subscribable`\<`ApiAccount`\>
Observes given account and notifies when its manabar is 98 percent loaded
Note: This function will be called on every new block detected if manabar is full on every new block
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `name` | `string` | account name to observe |
#### Returns
`Subscribable`\<`ApiAccount`\>
subscribable object that will call `next` each time time its manabar is 98 percent loaded
#### Defined in
src/interfaces.ts:61
___
### accountOperations
**accountOperations**(`name`): `Subscribable`\<[`IOperationData`](#interfacesioperationdatamd)\>
......@@ -307,7 +332,7 @@ Remember that chain property will be initialized during [start](#start) call and
#### Defined in
src/interfaces.ts:76
src/interfaces.ts:85
___
......@@ -317,7 +342,7 @@ ___
#### Defined in
src/interfaces.ts:68
src/interfaces.ts:77
___
......@@ -327,7 +352,7 @@ ___
#### Defined in
src/interfaces.ts:93
src/interfaces.ts:102
___
......@@ -337,7 +362,7 @@ ___
#### Defined in
src/interfaces.ts:67
src/interfaces.ts:76
## Methods
......@@ -353,7 +378,7 @@ Allows you to iterate over blocks indefinitely
#### Defined in
src/interfaces.ts:113
src/interfaces.ts:122
___
......@@ -400,7 +425,7 @@ Deletes the current bot instance and underlying wax and beekepeer objects
#### Defined in
src/interfaces.ts:91
src/interfaces.ts:100
___
......@@ -660,7 +685,7 @@ EventEmitter.on
#### Defined in
src/interfaces.ts:121
src/interfaces.ts:130
**on**(`event`, `handler`): [`IWorkerBee`](#interfacesiworkerbeemd)
......@@ -683,7 +708,7 @@ EventEmitter.on
#### Defined in
src/interfaces.ts:128
src/interfaces.ts:137
**on**(`event`, `handler`): [`IWorkerBee`](#interfacesiworkerbeemd)
......@@ -706,7 +731,7 @@ EventEmitter.on
#### Defined in
src/interfaces.ts:135
src/interfaces.ts:144
**on**(`event`, `handler`): [`IWorkerBee`](#interfacesiworkerbeemd)
......@@ -729,7 +754,7 @@ EventEmitter.on
#### Defined in
src/interfaces.ts:142
src/interfaces.ts:151
**on**(`event`, `handler`): [`IWorkerBee`](#interfacesiworkerbeemd)
......@@ -752,7 +777,7 @@ EventEmitter.on
#### Defined in
src/interfaces.ts:149
src/interfaces.ts:158
___
......@@ -1154,7 +1179,7 @@ private key
#### Defined in
src/interfaces.ts:108
src/interfaces.ts:117
___
......@@ -1170,7 +1195,7 @@ Starts the automation with given configuration
#### Defined in
src/interfaces.ts:81
src/interfaces.ts:90
___
......@@ -1186,7 +1211,7 @@ Request automation stop
#### Defined in
src/interfaces.ts:86
src/interfaces.ts:95
<a name="interfacesiworkerbeeconstructormd"></a>
......@@ -1213,4 +1238,4 @@ Constructs new WorkerBee bot object
#### Defined in
src/interfaces.ts:158
src/interfaces.ts:167
......@@ -53,19 +53,22 @@
logger.prepend(node);
};
let bot, work, beneficiaryName;
const DAY_MS = 24 * 60 * 60 * 1000;
const posts = new Map(/* Map<`${Account}/${Permlink}`, { added: Date, fullBeneficiary?: Account }> */);
let bot, work, manaWork, beneficiaryName;
const voted = new Set(/* Set<`${Account}/${Permlink}`> */);
const posts = new Map(/* Map<`${Account}/${Permlink}`, { added: Date, beneficiaryMatched?: boolean }> */);
const getKey = (op) => `${op.account || op.author}/${op.permlink}`;
const vote = async(op, number) => {
const vote = async(op) => {
try {
// Build transaction
const builder = await bot.chain.getTransactionBuilder();
builder.push({
vote: {
voter: "voter",
author: "initminer",
author: op.author,
permlink: op.permlink,
weight: 1000
}
......@@ -74,15 +77,14 @@
// Broadcast our transaction with custom internal expiration time
const observer = await bot.signAndBroadcast(builder.build());
voted.add(getKey(op));
// Observe if our transaction has been applied
observer.subscribe({
next: ({ block: { number: appliedBlockNumber } }) => {
log(`Transasction from block #${number} ("${getKey(op)}") applied after ${appliedBlockNumber - number} blocks`);
log(`Vote on post ("${getKey(op)}") applied on block #${appliedBlockNumber}`);
},
error: (error) => {
console.error(error);
log(`Transaction observation time for post vote "${getKey(op)}" expired`, true);
}
});
......@@ -111,15 +113,16 @@
if(!post)
return;
post.fullBeneficiary = beneficiary.account;
post.beneficiaryMatched = true;
log(`Full beneficiary set on comment "${key}" in block #${this.number}: "${beneficiary.account}"`);
vote(op, this.number);
}
comment(op) {
log(`Got new comment in block #${this.number}: "${getKey(op)}"`);
if(voted.has(op))
return; // Already voted
posts.set(getKey(op), { added: new Date() });
}
}
......@@ -128,6 +131,32 @@
work = bot.observe.accountOperations(accountToObserve).subscribe({
next({ op, transaction: { block: { number } } }) {
new CommentVisitor(number).accept(op);
},
error(error) {
log(error, true);
}
});
manaWork = bot.observe.accountFullManabar(accountToObserve).subscribe({
next() {
const key = posts.keys().next().value;
if(!key)
return;
const post = posts.get(key);
log(`Full manabar - Trying to vote for "${key}"`);
const [ author, permlink ] = key.split('/');
if(post.beneficiaryMatched === true && Date.now() - post.added.getTime() <= DAY_MS) {
vote({ author, permlink });
posts.delete(key);
}
else
log(`Properties for post "${key}" not sufficient`);
},
error(error) {
log(error, true);
}
});
};
......@@ -144,6 +173,8 @@
if(work)
work.unsubscribe();
if(manaWork)
manaWork.unsubscribe();
running = false;
startBtn.innerText = 'Start';
......
......@@ -50,6 +50,7 @@
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"events": "^3.3.0",
"long": "^5.2.3",
"rxjs": "^7.8.1",
"tslib": "^2.6.2"
},
......
......@@ -20,6 +20,9 @@ dependencies:
events:
specifier: ^3.3.0
version: 3.3.0
long:
specifier: ^5.2.3
version: 5.2.3
rxjs:
specifier: ^7.8.1
version: 7.8.1
......
......@@ -194,6 +194,8 @@ export class WorkerBee extends EventEmitter implements IWorkerBee {
// This function actually allows you to actually reset the bot instance
await this.stop();
super.removeAllListeners();
this.chain?.delete();
this.wallet?.close();
await this.beekeeper?.delete();
......
import type EventEmitter from "events";
import type { ApiBlock, ApiTransaction, IHiveChainInterface, operation, transaction } from "@hive-staging/wax";
import type { ApiAccount, ApiBlock, ApiTransaction, IHiveChainInterface, operation, transaction } from "@hive-staging/wax";
import type { Subscribable } from "rxjs";
import type { IStartConfiguration } from "./bot";
......@@ -50,6 +50,15 @@ export interface IQueenBee {
* @returns subscribable object that will call `next` on every operation related to the given account
*/
accountOperations(name: string): Subscribable<IOperationData>;
/**
* Observes given account and notifies when its manabar is 98 percent loaded
* Note: This function will be called on every new block detected if manabar is full on every new block
*
* @param name account name to observe
* @returns subscribable object that will call `next` each time time its manabar is 98 percent loaded
*/
accountFullManabar(name: string): Subscribable<ApiAccount>;
}
export interface IBroadcastOptions {
......
import type { operation } from "@hive-staging/wax";
import type { ApiAccount, operation } from "@hive-staging/wax";
import Long from "long";
import type { Subscribable, Observer, Unsubscribable } from "rxjs";
import { AccountOperationVisitor } from "./account_observer";
......@@ -147,4 +148,50 @@ export class QueenBee {
}
};
}
public accountFullManabar(name: string): Subscribable<ApiAccount> {
return {
subscribe: (observer: Partial<Observer<ApiAccount>>): Unsubscribable => {
const listener = async(): Promise<void> => {
try {
const { accounts: [ account ] } = await this.worker.chain!.api.database_api.find_accounts({
accounts: [ name ]
});
const dgpo = await this.worker.chain!.api.database_api.get_dynamic_global_properties({});
const value = this.worker.chain!.calculateCurrentManabarValue(
Math.round(new Date(`${dgpo.time}Z`).getTime() / 1000), // Convert API time to seconds
account.post_voting_power.amount,
account.voting_manabar.current_mana,
account.voting_manabar.last_update_time
);
if(Long.fromString(value, true).multiply(100)
.divide(account.post_voting_power.amount)
.toNumber() >= 98)
observer.next?.(account);
} catch (error) {
observer.error?.(error);
}
};
this.worker.on("block", listener);
const complete = (): void => {
try {
observer.complete?.();
} catch (error) {
observer.error?.(error);
} finally {
this.worker.off("transaction", listener);
}
};
return {
unsubscribe: (): void => {
complete();
}
};
}
};
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment