Nest/DHive Project
I consider myself someone functional with typescript, and I noticed there's a typescript library for HIVE. This is me trying it out and setting up a project to stream events and handle them.
Setup
I setup a unnamed-nest-dhive project
Then, I installed NestJS
node@e0d9a8ccb364 /w/t/unnamed-nest-dhive (master) [1]> npm i -g @nestjs/cli
added 249 packages, and audited 250 packages in 10s
39 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Next, create my nest project
node@e0d9a8ccb364 /w/t/unnamed-nest-dhive (master)> nest new unnamed-nest-dhive
⚡ We will scaffold your app in a few seconds..
CREATE unnamed-nest-dhive/.eslintrc.js (665 bytes)
CREATE unnamed-nest-dhive/.prettierrc (51 bytes)
CREATE unnamed-nest-dhive/README.md (3340 bytes)
CREATE unnamed-nest-dhive/nest-cli.json (118 bytes)
CREATE unnamed-nest-dhive/package.json (2003 bytes)
CREATE unnamed-nest-dhive/tsconfig.build.json (97 bytes)
CREATE unnamed-nest-dhive/tsconfig.json (546 bytes)
CREATE unnamed-nest-dhive/src/app.controller.spec.ts (617 bytes)
CREATE unnamed-nest-dhive/src/app.controller.ts (274 bytes)
CREATE unnamed-nest-dhive/src/app.module.ts (249 bytes)
CREATE unnamed-nest-dhive/src/app.service.ts (142 bytes)
CREATE unnamed-nest-dhive/src/main.ts (208 bytes)
CREATE unnamed-nest-dhive/test/app.e2e-spec.ts (630 bytes)
CREATE unnamed-nest-dhive/test/jest-e2e.json (183 bytes)
? Which package manager would you ❤️ to use? npm
✔ Installation in progress... ☕
🚀 Successfully created project unnamed-nest-dhive
👉 Get started with the following commands:
$ cd unnamed-nest-dhive
$ npm run start
Thanks for installing Nest 🙏
Please consider donating to our open collective
to help us maintain this package.
🍷 Donate: https://opencollective.com/nest
RANT Ok. I just want to say, this is silly. I always start with a VCS repo for my project first. I never start with nothing. It seems silly that these scaffoling projects want to assume or insist that you have nothing. No one is going to start a project that way. They always start with a VCS. Can we at least assume that much?
Thanks to nest insisting I start with an empty directory, I now have to copy everything into my VCS path.
node@e0d9a8ccb364 /w/t/unnamed-nest-dhive (master)> mv unnamed-nest-dhive/* .
node@e0d9a8ccb364 /w/t/unnamed-nest-dhive (master)> ls
nest-cli.json node_modules/ package.json package-lock.json README.md src/ test/ tsconfig.build.json tsconfig.json unnamed-nest-dhive/
node@e0d9a8ccb364 /w/t/unnamed-nest-dhive (master)> ls unnamed-nest-dhive/
node@e0d9a8ccb364 /w/t/unnamed-nest-dhive (master)> ls -a unnamed-nest-dhive/
./ ../ .eslintrc.js .git/ .gitignore .prettierrc
node@e0d9a8ccb364 /w/t/unnamed-nest-dhive (master)> mv unnamed-nest-dhive/.eslintrc.js unnamed-nest-dhive/.gitignore unnamed-nest-dhive/.prettierrc .
Install Bluebird
node@e0d9a8ccb364 /w/t/unnamed-nest-dhive (master)> npm install -S bluebird
up to date, audited 725 packages in 1s
89 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Then, I installed DHive
node@e0d9a8ccb364 /w/t/unnamed-nest-dhive (master)> npm install -S @hiveio/dhive
added 38 packages, and audited 724 packages in 15s
89 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Ok. Easy part done. LOL.
Nest allows us some scaffolding for creating services, so I'm going to create a hive service.
node@e0d9a8ccb364 /w/t/unnamed-nest-dhive (master)> nest
Usage: nest <command> [options]
Options:
-v, --version Output the current version.
-h, --help Output usage information.
Commands:
new|n [options] [name] Generate Nest application.
build [options] [app] Build Nest application.
start [options] [app] Run Nest application.
info|i Display Nest project details.
add [options] <library> Adds support for an external library to your project.
generate|g [options] <schematic> [name] [path] Generate a Nest element.
Schematics available on @nestjs/schematics collection:
┌───────────────┬─────────────┬──────────────────────────────────────────────┐
│ name │ alias │ description │
│ application │ application │ Generate a new application workspace │
│ class │ cl │ Generate a new class │
│ configuration │ config │ Generate a CLI configuration file │
│ controller │ co │ Generate a controller declaration │
│ decorator │ d │ Generate a custom decorator │
│ filter │ f │ Generate a filter declaration │
│ gateway │ ga │ Generate a gateway declaration │
│ guard │ gu │ Generate a guard declaration │
│ interceptor │ itc │ Generate an interceptor declaration │
│ interface │ itf │ Generate an interface │
│ middleware │ mi │ Generate a middleware declaration │
│ module │ mo │ Generate a module declaration │
│ pipe │ pi │ Generate a pipe declaration │
│ provider │ pr │ Generate a provider declaration │
│ resolver │ r │ Generate a GraphQL resolver declaration │
│ service │ s │ Generate a service declaration │
│ library │ lib │ Generate a new library within a monorepo │
│ sub-app │ app │ Generate a new application within a monorepo │
│ resource │ res │ Generate a new CRUD resource │
└───────────────┴─────────────┴──────────────────────────────────────────────┘
node@e0d9a8ccb364 /w/t/unnamed-nest-dhive (master) [1]> nest generate service hive
CREATE src/hive/hive.service.spec.ts (446 bytes)
CREATE src/hive/hive.service.ts (88 bytes)
UPDATE src/app.module.ts (313 bytes)
The scaffolding is great. It generates the stubbed source code and adds everything for me.
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { HiveService } from './hive/hive.service';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService, HiveService],
})
export class AppModule {}
Now I setup my DHive client in my hive.service.ts
import { Injectable, Logger } from '@nestjs/common';
import { BlockchainMode, Client, PrivateKey } from '@hiveio/dhive';
import * as Promise from 'bluebird';
@Injectable()
export class HiveService {
client: any;
constructor() {
this.client = new Client('https://api.hive.blog')
}
}
After that, I add a streamOperations
method to my hive.service.ts
. This will be important later for streaming events.
streamOperations(handler, errors): Promise {
const stream = this.client.blockchain.getOperationsStream();
stream.on("data", handler)
stream.on("error", errors)
}
At this point, my AppService
is pretty default and generic.
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
The first thing I do is inject HiveService
into the AppService
import { Injectable, Logger } from '@nestjs/common';
import { HiveService } from './hive/hive.service';
@Injectable()
export class AppService {
private hiveService: HiveService
constructor(
hiveService: HiveService,) {
this.hiveService = hiveService;
}
}
I change it to add a new run
method.
run() {
Logger.log("Streaming started")
const retval = this.hiveService.streamOperations(
(results) => {
return Promise.resolve(results.op).spread((operation_name, operation) => {
switch (operation_name) {
case 'comment':
break;
case 'vote':
Logger.log(`${operation.voter} voted on @${operation.author}/${operation.permlink}`)
break;
case 'unvote':
break;
case 'transfer':
break;
case 'comment_benefactor_reward':
break;
case 'account_update2':
break;
case 'transfer_to_vesting':
break;
case 'custom_json':
break;
case 'feed_publish':
break;
case 'producer_reward':
break;
case 'comment_options':
break;
case 'curation_reward':
break;
case 'author_reward':
break;
case 'claim_reward_balance':
break;
case 'limit_order_create':
break;
case 'limit_order_cancel':
break;
case 'claim_account':
break;
case 'fill_vesting_withdraw':
break;
case 'fill_order':
break;
case 'fill_convert_request':
break;
case 'convert':
break;
case 'create_claimed_account':
break;
case 'delegate_vesting_shares':
break;
case 'account_update':
break;
case 'witness_set_properties':
break;
case 'delete_comment':
break;
case 'account_witness_vote':
break;
case 'withdraw_vesting':
break;
case 'proposal_pay':
break;
case 'sps_fund':
break;
case 'return_vesting_delegation':
break;
case 'transfer_from_savings':
break;
case 'transfer_to_savings':
break;
case 'fill_transfer_from_savings':
break;
case 'fill_transfer_to_savings':
break;
case 'update_proposal_votes':
break;
case 'change_recovery_account':
break;
case 'account_create':
break;
case 'comment_payout_update':
break;
case 'effective_comment_vote':
break;
case 'transfer_to_vesting_completed':
break;
case 'comment_reward':
break;
case 'delayed_voting':
break;
case 'witness_update':
break;
case 'account_witness_proxy':
break;
case 'expired_account_notification':
break;
case 'fill_collateralized_convert_request':
break;
case 'fill_recurrent_transfer':
break;
case 'changed_recovery_account':
break;
case 'collateralized_convert':
break;
case 'clear_null_account_balance':
break;
case 'set_withdraw_vesting_route':
break;
case 'cancel_transfer_from_savings':
break;
case 'failed_recurrent_transfer':
break;
case 'interest':
break;
default:
Logger.log(`Unknown operation: ${operation_name}: ${JSON.stringify(operation)}`)
break;
}
})
.catch((err) => {
Logger.error("Bot died. Restarting ... ", err)
Logger.log(`Error Operation ${JSON.stringify(results.op)}`)
})
},
(error) => {
Logger.error(`Failed ${JSON.stringify(error)}`)
this.run()
})
}
I need to update main.ts
now. Originally, NestJS is setup as a web application. It starts a server which is not what I want to do. I just want to stream events, not provide a REST API. I modify main.ts
to just call run
from the AppService
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { AppService } from './app.service';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const appService = app.select(AppModule).get(AppService);
appService.run()
}
bootstrap();
Now, I can run npm start
node@e0d9a8ccb364 /w/t/unnamed-nest-dhive (master) [1]> npm start
> unnamed-nest-dhive@0.0.1 start
> nest start
[Nest] 10738 - 08/03/2022, 4:55:11 AM LOG [NestFactory] Starting Nest application...
[Nest] 10738 - 08/03/2022, 4:55:11 AM LOG [InstanceLoader] AppModule dependencies initialized +23ms
[Nest] 10738 - 08/03/2022, 4:55:11 AM LOG Streaming started
[Nest] 10738 - 08/03/2022, 4:55:15 AM LOG fatman voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:15 AM LOG investegg voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:15 AM LOG spaminator voted on @brittandjosie/rg0w90
[Nest] 10738 - 08/03/2022, 4:55:15 AM LOG sleepcult voted on @jovilia/re-life-20220803t044901z
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG thencsshifters voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG steempress voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG rawselectmusic voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG r00sj3 voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG martibis voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG lenasveganliving voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG leveluplifestyle voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG eonwarped voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG darkpylon voted on @creacioneslelys/apoawayj
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG cconn voted on @creacioneslelys/apoawayj
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG tomwafula voted on @creacioneslelys/apoawayj
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG joeyarnoldvn voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG sezermehmet voted on @acidyo/do-you-want-to-watch-an-ad-for-a-boost
[Nest] 10738 - 08/03/2022, 4:55:25 AM LOG schoolofminnows voted on @clavdio75/le-voyageur-de-la-nuit
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG mrainp voted on @jovilia/re-life-20220803t044901z
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG indigoocean voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG actioncats voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG spydo voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG chisdealhd voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG javyeslava.photo voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG marblely voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG devann voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG ocdb voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG howo voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG senorcoconut voted on @kevinnag58/warning-millions-already-drained-in-continuing-solana-based-wallet-hack
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG jlsplatts voted on @jayke-stringz/check-out-my-introductive-post-on-hive
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG beehivetrader voted on @kevinnag58/warning-millions-already-drained-in-continuing-solana-based-wallet-hack
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG brujita18 voted on @racn/how-i-made-strawberry-mojito
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG gabrielatravels voted on @jayke-stringz/check-out-my-introductive-post-on-hive
[Nest] 10738 - 08/03/2022, 4:55:32 AM LOG detlev voted on @jayke-stringz/check-out-my-introductive-post-on-hive
That's it. This is a good start for any application. Now you can build any application to respond to events in realtime. I plan to use this going forward to learn about how Hive works through the events.
I realize there are probably a lot of posts like this out there and that the community is inundated with this information. I think this adds value because I don't believe there are very many on streaming events in such an easy way. It looks like there's a lot involved here, but that's just because I'm being verbose. This really is only 5 min of work by anyone familiar with javascript.
Congratulations @timesheets! You have completed the following achievement on the Hive blockchain and have been rewarded with new badge(s):
Your next target is to reach 50 upvotes.
You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word
STOP
Check out the last post from @hivebuzz:
Support the HiveBuzz project. Vote for our proposal!