hive-stream 2.0.6 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/.env.example +2 -2
  3. package/.travis.yml +11 -11
  4. package/AGENTS.md +35 -0
  5. package/CHANGELOG.md +166 -0
  6. package/CLAUDE.md +75 -0
  7. package/DOCUMENTATION.md +380 -0
  8. package/LICENSE +21 -21
  9. package/README.md +429 -238
  10. package/dist/actions.d.ts +41 -10
  11. package/dist/actions.js +126 -23
  12. package/dist/actions.js.map +1 -1
  13. package/dist/adapters/base.adapter.d.ts +43 -25
  14. package/dist/adapters/base.adapter.js +79 -49
  15. package/dist/adapters/base.adapter.js.map +1 -1
  16. package/dist/adapters/mongodb.adapter.d.ts +44 -37
  17. package/dist/adapters/mongodb.adapter.js +363 -158
  18. package/dist/adapters/mongodb.adapter.js.map +1 -1
  19. package/dist/adapters/postgresql.adapter.d.ts +66 -0
  20. package/dist/adapters/postgresql.adapter.js +598 -0
  21. package/dist/adapters/postgresql.adapter.js.map +1 -0
  22. package/dist/adapters/sqlite.adapter.d.ts +57 -41
  23. package/dist/adapters/sqlite.adapter.js +561 -397
  24. package/dist/adapters/sqlite.adapter.js.map +1 -1
  25. package/dist/api.d.ts +6 -6
  26. package/dist/api.js +181 -55
  27. package/dist/api.js.map +1 -1
  28. package/dist/config.d.ts +19 -16
  29. package/dist/config.js +21 -18
  30. package/dist/config.js.map +1 -1
  31. package/dist/contracts/coinflip.contract.d.ts +9 -14
  32. package/dist/contracts/coinflip.contract.js +232 -94
  33. package/dist/contracts/coinflip.contract.js.map +1 -1
  34. package/dist/contracts/contract.d.ts +3 -0
  35. package/dist/contracts/contract.js +26 -0
  36. package/dist/contracts/contract.js.map +1 -0
  37. package/dist/contracts/dice.contract.d.ts +10 -29
  38. package/dist/contracts/dice.contract.js +217 -155
  39. package/dist/contracts/dice.contract.js.map +1 -1
  40. package/dist/contracts/exchange.contract.d.ts +11 -0
  41. package/dist/contracts/exchange.contract.js +492 -0
  42. package/dist/contracts/exchange.contract.js.map +1 -0
  43. package/dist/contracts/lotto.contract.d.ts +16 -20
  44. package/dist/contracts/lotto.contract.js +238 -246
  45. package/dist/contracts/lotto.contract.js.map +1 -1
  46. package/dist/contracts/nft.contract.d.ts +28 -0
  47. package/dist/contracts/nft.contract.js +598 -0
  48. package/dist/contracts/nft.contract.js.map +1 -0
  49. package/dist/contracts/poll.contract.d.ts +4 -0
  50. package/dist/contracts/poll.contract.js +105 -0
  51. package/dist/contracts/poll.contract.js.map +1 -0
  52. package/dist/contracts/rps.contract.d.ts +9 -0
  53. package/dist/contracts/rps.contract.js +217 -0
  54. package/dist/contracts/rps.contract.js.map +1 -0
  55. package/dist/contracts/tipjar.contract.d.ts +4 -0
  56. package/dist/contracts/tipjar.contract.js +60 -0
  57. package/dist/contracts/tipjar.contract.js.map +1 -0
  58. package/dist/contracts/token.contract.d.ts +4 -0
  59. package/dist/contracts/token.contract.js +311 -0
  60. package/dist/contracts/token.contract.js.map +1 -0
  61. package/dist/exchanges/bittrex.d.ts +6 -6
  62. package/dist/exchanges/bittrex.js +34 -34
  63. package/dist/exchanges/coingecko.d.ts +11 -0
  64. package/dist/exchanges/coingecko.js +57 -0
  65. package/dist/exchanges/coingecko.js.map +1 -0
  66. package/dist/exchanges/exchange.d.ts +16 -9
  67. package/dist/exchanges/exchange.js +80 -26
  68. package/dist/exchanges/exchange.js.map +1 -1
  69. package/dist/hive-rates.d.ts +34 -9
  70. package/dist/hive-rates.js +208 -75
  71. package/dist/hive-rates.js.map +1 -1
  72. package/dist/index.d.ts +19 -11
  73. package/dist/index.js +47 -32
  74. package/dist/index.js.map +1 -1
  75. package/dist/streamer.d.ts +233 -93
  76. package/dist/streamer.js +1063 -545
  77. package/dist/streamer.js.map +1 -1
  78. package/dist/test.d.ts +1 -1
  79. package/dist/test.js +24 -25
  80. package/dist/test.js.map +1 -1
  81. package/dist/types/hive-stream.d.ts +106 -6
  82. package/dist/types/hive-stream.js +2 -2
  83. package/dist/types/rates.d.ts +47 -0
  84. package/dist/types/rates.js +29 -0
  85. package/dist/types/rates.js.map +1 -0
  86. package/dist/utils.d.ts +334 -27
  87. package/dist/utils.js +960 -261
  88. package/dist/utils.js.map +1 -1
  89. package/ecosystem.config.js +17 -17
  90. package/examples/contracts/README.md +8 -0
  91. package/examples/contracts/exchange.ts +38 -0
  92. package/examples/contracts/poll.ts +21 -0
  93. package/examples/contracts/rps.ts +19 -0
  94. package/examples/contracts/tipjar.ts +19 -0
  95. package/jest.config.js +8 -8
  96. package/package.json +54 -48
  97. package/test-contract-block.md +18 -18
  98. package/tests/actions.spec.ts +252 -0
  99. package/tests/adapters/actions-persistence.spec.ts +144 -0
  100. package/tests/adapters/postgresql.adapter.spec.ts +127 -0
  101. package/tests/adapters/sqlite.adapter.spec.ts +180 -42
  102. package/tests/contracts/coinflip.contract.spec.ts +94 -132
  103. package/tests/contracts/dice.contract.spec.ts +87 -160
  104. package/tests/contracts/entrants.json +728 -728
  105. package/tests/contracts/exchange.contract.spec.ts +84 -0
  106. package/tests/contracts/lotto.contract.spec.ts +59 -324
  107. package/tests/contracts/nft.contract.spec.ts +948 -0
  108. package/tests/contracts/token.contract.spec.ts +90 -0
  109. package/tests/exchanges/coingecko.exchange.spec.ts +169 -0
  110. package/tests/exchanges/exchange.base.spec.ts +246 -0
  111. package/tests/helpers/mock-adapter.ts +214 -0
  112. package/tests/helpers/mock-fetch.ts +165 -0
  113. package/tests/hive-chain-features.spec.ts +238 -0
  114. package/tests/hive-rates.spec.ts +443 -0
  115. package/tests/integration/hive-rates.integration.spec.ts +35 -0
  116. package/tests/setup.ts +29 -18
  117. package/tests/streamer-actions.spec.ts +274 -0
  118. package/tests/streamer.spec.ts +342 -152
  119. package/tests/types/rates.spec.ts +216 -0
  120. package/tests/utils.spec.ts +113 -95
  121. package/tsconfig.build.json +3 -22
  122. package/tslint.json +20 -20
  123. package/wallaby.js +26 -26
package/README.md CHANGED
@@ -1,238 +1,429 @@
1
- # Hive Stream
2
-
3
- A Node.js layer for Hive that allows you to watch for specific actions on the Hive blockchain.
4
-
5
- ## Install
6
-
7
- ```shell
8
- npm install hive-stream
9
- ```
10
-
11
- ## Quick Usage
12
-
13
- ```javascript
14
- const { Streamer } = require('hive-stream');
15
-
16
- const ss = new Streamer();
17
-
18
- // Watch for all custom JSON operations
19
- ss.onCustomJson((op, { sender, isSignedWithActiveKey }, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
20
- // React to custom JSON operations
21
- });
22
- ```
23
-
24
- ## Configuration
25
-
26
- The `Streamer` object can accept an object of configuration values which are all optional. However, some operations like transferring Hive Engine tokens or other operations on the blockchain that are not READ ONLY, will require the active key and/or posting keys supplied as well as a username.
27
-
28
- The `BLOCK_CHECK_INTERVAL` value is how often to check for new blocks or in cases of error or falling behind, to poll for new blocks. You should keep this as the default 1000ms value which is one second. This allows you to account for situations where blocks fall behind the main block.
29
-
30
- The `BLOCKS_BEHIND_WARNING` value is a numeric value of the number of blocks your API will fall behind from the master before warning to the console.
31
-
32
- The `API_URL` is the Hive API. If you want to enable debug mode, set to `DEBUG_MODE` to `true`. The configuration values and their defaults can be found [here](https://github.com/Vheissu/hive-stream/blob/master/config.js).
33
-
34
- ```
35
- const options = {
36
- ACTIVE_KEY: '',
37
- POSTING_KEY: '',
38
- APP_NAME: 'hive-stream',
39
- USERNAME: '',
40
- LAST_BLOCK_NUMBER: 0,
41
- BLOCK_CHECK_INTERVAL: 1000,
42
- BLOCKS_BEHIND_WARNING: 25,
43
- API_URL: 'https://api.hiveit.com',
44
- DEBUG_MODE: false
45
- }
46
-
47
- const ss = new Streamer(options);
48
- ```
49
-
50
- The configuration itself can also be overloaded using the `setConfig` method which allows you to pass one or more of the above configuration options, useful in situations where multiple keys might be used for issuing.
51
-
52
- ```
53
- ss.setConfig({
54
- ACTIVE_KEY: 'newactivekey',
55
- USERNAME: 'newusername'
56
- });
57
- ```
58
-
59
- ## Streamer
60
-
61
- The following subscription methods are read only methods, they allow you to react to certain Hive and Hive Engine events on the blockchain. You do not need to pass in any keys to use these methods as they're purely read only.
62
-
63
- **The following actions DO require calling the `start` method first to watch the blockchain**
64
-
65
- #### Watch for transfers
66
-
67
- ```javascript
68
- ss.onTransfer((op, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
69
-
70
- })
71
- ```
72
-
73
- #### Watch for custom JSON operations
74
- ```javascript
75
- ss.onCustomJson((op, { sender, isSignedWithActiveKey }, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
76
-
77
- })
78
- ```
79
-
80
- #### Watch for custom JSON operations (with a specific ID)
81
- ```javascript
82
- ss.onCustomJsonId((op, { sender, isSignedWithActiveKey }, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
83
-
84
- })
85
- ```
86
-
87
- #### Watch for post operations
88
- ```javascript
89
- ss.onPost((op, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
90
-
91
- });
92
- ```
93
-
94
- #### Watch for comment operations
95
- ```javascript
96
- ss.onComment((op, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
97
-
98
- });
99
- ```
100
-
101
- ## Actions (active key)
102
-
103
- All of the below methods require an active key has been supplied in the constructor above called `ACTIVE_KEY`. The methods below are all promised based, so you can `await` them or use `then` to confirm a successful result.
104
-
105
- **The following actions do NOT require calling the `start` method first to watch the blockchain**
106
-
107
- ```javascript
108
- const ss = new Streamer({
109
- ACTIVE_KEY: 'youractivekey'
110
- });
111
- ```
112
-
113
- ### Transfer Hive (HIVE or HBD)
114
- ```javascript
115
- transferHiveTokens(from, to, amount, symbol, memo = '') {
116
-
117
- }
118
- ```
119
-
120
- ## Contracts
121
-
122
- Hive Stream allows you to write contracts which get executed when a custom JSON operation matches. The only requirement is sending a payload which contains `hiveContract` inside of it.
123
-
124
- The payload consists of:
125
-
126
- `name` the name of the smart contract you registered.
127
-
128
- `action` matches the name of a function defined inside of your contract
129
-
130
- `payload` an object of data which will be provided to the action
131
-
132
- ### Writing contracts
133
-
134
- Really, a contract is nothing more than a bunch of functions which get matched to values inside of JSON payloads.
135
-
136
- ### Register a contract
137
-
138
- Register a file containing contract code which will be executed.
139
-
140
- ```javascript
141
- import contract from './my-contract';
142
-
143
- registerContract('mycontract', Contract);
144
- ```
145
-
146
- ### Unregister a contract
147
-
148
- Unregister a contract that has been registered.
149
-
150
- ```javascript
151
- unregisterContract('mycontract');
152
- ```
153
-
154
- ### Example Payload
155
-
156
- ```javascript
157
- JSON.stringify({ hiveContract: { name: 'hivedice', action: 'roll', payload: { roll: 22, amount: '1'} } })
158
- ```
159
-
160
- This will match a registered contract called `hivedice` and inside of the contract code, a function called `roll` and finally, the payload is sent to the function as an argument, allowing you to access the values inside of it. See the example file `dice.contract.ts` in the `src/contracts` folder in the repository. there is also a coinflip and lotto contract showing you how to build a coinflip or lottery based contract.
161
-
162
- ## Time-based Actions
163
-
164
- It's like a cron job for your contracts. Time-based actions allow you to execute contract functions over a wide variety of different periods. Want to call a function every 3 seconds block time or want to call a function once per day? Time-based actions are an easy way to run time code.
165
-
166
- The following example will run a contract action every 30 seconds. All you do is register a new `TimeAction` instance.
167
-
168
- ```
169
- import { TimeAction, Streamer } from 'hive-stream';
170
-
171
- const streamer = new Streamer({
172
- ACTIVE_KEY: ''
173
- });
174
-
175
- const testAction = new TimeAction('30s', 'test30s', 'hivedice', 'testauto');
176
-
177
- streamer.registerAction(testAction);
178
-
179
- streamer.start();
180
- ```
181
-
182
- The `TimeAction` instance accepts the following values:
183
-
184
- - timeValue - When should this action be run?
185
- - uniqueId - A unique ID to describe your action
186
- - contractName - The name of the contract
187
- - contractMethod - The method we are calling inside of the contract
188
- - date - An optional final parameter that accepts a date of creation
189
-
190
- ```
191
- new TimeAction(timeValue, uniqueId, contractName, contractMethod, date)
192
- ```
193
-
194
- ### Valid time values
195
-
196
- At the moment, the `timeValue` passed in as the first argument to `TimeAction` cannot accept just any value. However, there are many available out-of-the-box with more flexibility to come in the future.
197
-
198
- - `3s` or `block` will run a task every block (3 seconds, approximately)
199
- - `30s` will run a task every 30 seconds
200
- - `1m` or `minute` will run a task every 60 seconds (1 minute)
201
- - `15m` or `quarter` will run a task every 15 minutes
202
- - `30m` or `halfhour` will run a task every 30 minutes
203
- - `1h` or `hourly` will run a task every 60 minutes (every hour)
204
- - `12h` or `halfday` will run a task every 12 hours (half a day)
205
- - `24h` or `day` will run a task every 24 hours (day)
206
-
207
- Values will be persisted if using one of the three adapters that ship with the library.
208
-
209
- ## Adapters
210
-
211
- The Hive Stream library supports custom adapters for various actions that take place in the library. When the library first loads, it makes a call to get the last block number or when a block is processed, storing the processed block number. This library ships with two adapters; File and SQLite, both of which are file based adapters. The SQLite database works more like a traditional database and shows how you might create an adapter for a database like MongoDB or MySQL.
212
-
213
- When creating an adapter, at a minimum your adapter requires two methods: `loadState` and `saveState`. It must also extend `AdapterBase` which is exported from the package.
214
-
215
- You can see a few adapters that ship with Hive Stream in the `src/adapters` directory.
216
-
217
- ## Permanently running with PM2
218
-
219
- Simply copy the `ecosystem.config.js` file from this repository into your application, globally install `pm2` via `npm install pm2 -g` and change the `script` value below to reflect the main file of your application.
220
-
221
- **ecosystem.config.js**
222
-
223
- ```
224
- module.exports = {
225
- apps: [
226
- {
227
- name: 'hive-stream',
228
- script: 'index.js',
229
- ignore_watch: ['node_modules'],
230
- env: {
231
- NODE_ENV: 'development'
232
- },
233
- env_production: {
234
- NODE_ENV: 'production'
235
- }
236
- }
237
- ]
238
- ```
1
+ # Hive Stream
2
+
3
+ A Node.js layer for Hive that allows you to watch for specific actions on the Hive blockchain.
4
+
5
+ ## Install
6
+
7
+ ```shell
8
+ npm install hive-stream
9
+ ```
10
+
11
+ ## Quick Usage
12
+
13
+ ```javascript
14
+ const { Streamer } = require('hive-stream');
15
+
16
+ const ss = new Streamer();
17
+
18
+ // Watch for all custom JSON operations
19
+ ss.onCustomJson((op, { sender, isSignedWithActiveKey }, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
20
+ // React to custom JSON operations
21
+ });
22
+ ```
23
+
24
+ ## Configuration
25
+
26
+ The `Streamer` object can accept an object of configuration values which are all optional. However, some operations like transferring Hive Engine tokens or other operations on the blockchain that are not READ ONLY, will require the active key and/or posting keys supplied as well as a username.
27
+
28
+ The `BLOCK_CHECK_INTERVAL` value is how often to check for new blocks or in cases of error or falling behind, to poll for new blocks. You should keep this as the default 1000ms value which is one second. This allows you to account for situations where blocks fall behind the main block.
29
+
30
+ The `BLOCKS_BEHIND_WARNING` value is a numeric value of the number of blocks your API will fall behind from the master before warning to the console.
31
+
32
+ To resume automatically from stored state, keep `RESUME_FROM_STATE` enabled (default). To force a specific start block, set `RESUME_FROM_STATE` to `false` and supply `LAST_BLOCK_NUMBER`.
33
+
34
+ For faster catch-up, `CATCH_UP_BATCH_SIZE` controls how many blocks are processed per polling cycle, and `CATCH_UP_DELAY_MS` controls the delay between catch-up batches (set to `0` for fastest catch-up).
35
+
36
+ The `API_NODES` are the Hive API endpoints used for failover. If you want to enable debug mode, set `DEBUG_MODE` to `true`. The configuration values and their defaults can be found in `src/config.ts`.
37
+
38
+ ```
39
+ const options = {
40
+ ACTIVE_KEY: '',
41
+ POSTING_KEY: '',
42
+ APP_NAME: 'hive-stream',
43
+ USERNAME: '',
44
+ LAST_BLOCK_NUMBER: 0,
45
+ BLOCK_CHECK_INTERVAL: 1000,
46
+ BLOCKS_BEHIND_WARNING: 25,
47
+ RESUME_FROM_STATE: true,
48
+ CATCH_UP_BATCH_SIZE: 50,
49
+ CATCH_UP_DELAY_MS: 0,
50
+ API_NODES: ['https://api.hive.blog', 'https://api.openhive.network', 'https://rpc.ausbit.dev'],
51
+ DEBUG_MODE: false
52
+ }
53
+
54
+ const ss = new Streamer(options);
55
+ ```
56
+
57
+ The configuration itself can also be overloaded using the `setConfig` method which allows you to pass one or more of the above configuration options, useful in situations where multiple keys might be used for issuing.
58
+
59
+ ```
60
+ ss.setConfig({
61
+ ACTIVE_KEY: 'newactivekey',
62
+ USERNAME: 'newusername'
63
+ });
64
+ ```
65
+
66
+ ## Streamer
67
+
68
+ The following subscription methods are read only methods, they allow you to react to certain Hive and Hive Engine events on the blockchain. You do not need to pass in any keys to use these methods as they're purely read only.
69
+
70
+ **The following actions DO require calling the `start` method first to watch the blockchain**
71
+
72
+ #### Watch for transfers
73
+
74
+ ```javascript
75
+ ss.onTransfer((op, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
76
+
77
+ })
78
+ ```
79
+
80
+ #### Watch for escrow operations
81
+ ```javascript
82
+ ss.onEscrowTransfer((op, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
83
+
84
+ });
85
+
86
+ ss.onEscrowApprove((op, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
87
+
88
+ });
89
+
90
+ ss.onEscrowDispute((op, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
91
+
92
+ });
93
+
94
+ ss.onEscrowRelease((op, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
95
+
96
+ });
97
+ ```
98
+
99
+ #### Watch for custom JSON operations
100
+ ```javascript
101
+ ss.onCustomJson((op, { sender, isSignedWithActiveKey }, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
102
+
103
+ })
104
+ ```
105
+
106
+ #### Watch for custom JSON operations (with a specific ID)
107
+ ```javascript
108
+ ss.onCustomJsonId((op, { sender, isSignedWithActiveKey }, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
109
+
110
+ })
111
+ ```
112
+
113
+ #### Watch for post operations
114
+ ```javascript
115
+ ss.onPost((op, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
116
+
117
+ });
118
+ ```
119
+
120
+ #### Watch for comment operations
121
+ ```javascript
122
+ ss.onComment((op, blockNumber, blockId, prevBlockId, trxId, blockTime) => {
123
+
124
+ });
125
+ ```
126
+
127
+ ## Actions (active key)
128
+
129
+ All of the below methods require an active key has been supplied in the constructor above called `ACTIVE_KEY`. The methods below are all promised based, so you can `await` them or use `then` to confirm a successful result.
130
+
131
+ **The following actions do NOT require calling the `start` method first to watch the blockchain**
132
+
133
+ ```javascript
134
+ const ss = new Streamer({
135
+ ACTIVE_KEY: 'youractivekey'
136
+ });
137
+ ```
138
+
139
+ ### Transfer Hive (HIVE or HBD)
140
+ ```javascript
141
+ transferHiveTokens(from, to, amount, symbol, memo = '') {
142
+
143
+ }
144
+ ```
145
+
146
+ ### Transfer Hive Engine Tokens
147
+ ```javascript
148
+ transferHiveEngineTokens(from, to, symbol, quantity, memo = '') {
149
+
150
+ }
151
+ ```
152
+
153
+ ### Transfer Hive Engine Tokens to Multiple Accounts
154
+ ```javascript
155
+ transferHiveEngineTokensMultiple(from, accounts = [], symbol, memo = '', amount = '0') {
156
+
157
+ }
158
+ ```
159
+
160
+ ### Issue Hive Engine Tokens
161
+ ```javascript
162
+ issueHiveEngineTokens(from, to, symbol, quantity, memo = '') {
163
+
164
+ }
165
+ ```
166
+
167
+ ### Issue Hive Engine Tokens to Multiple Accounts
168
+ ```javascript
169
+ issueHiveEngineTokensMultiple(from, accounts = [], symbol, memo = '', amount = '0') {
170
+
171
+ }
172
+ ```
173
+
174
+ ### Escrow Operations
175
+ ```javascript
176
+ escrowTransfer({
177
+ from,
178
+ to,
179
+ agent,
180
+ escrow_id,
181
+ hive_amount = '0.000 HIVE',
182
+ hbd_amount = '0.000 HBD',
183
+ fee,
184
+ ratification_deadline,
185
+ escrow_expiration,
186
+ json_meta
187
+ }, signingKeys?)
188
+
189
+ escrowApprove({ from, to, agent, who, escrow_id, approve }, signingKeys?)
190
+ escrowDispute({ from, to, agent, who, escrow_id }, signingKeys?)
191
+ escrowRelease({ from, to, agent, who, receiver, escrow_id, hive_amount, hbd_amount }, signingKeys?)
192
+ ```
193
+
194
+ ### Multisig + Authority Helpers
195
+ ```javascript
196
+ broadcastOperations(operations, signingKeys?)
197
+ broadcastMultiSigOperations(operations, signingKeys)
198
+ createAuthority(keyAuths, accountAuths, weightThreshold)
199
+ updateAccountAuthorities(account, authorityUpdate, signingKeys?)
200
+ ```
201
+
202
+ ### Recurrent Transfers + Governance
203
+ ```javascript
204
+ recurrentTransfer({ from, to, amount, memo, recurrence, executions }, signingKeys?)
205
+ createProposal({ creator, receiver, start_date, end_date, daily_pay, subject, permlink }, signingKeys?)
206
+ updateProposalVotes({ voter, proposal_ids, approve }, signingKeys?)
207
+ removeProposals({ proposal_owner, proposal_ids }, signingKeys?)
208
+ ```
209
+
210
+ ### Upvote/Downvote Posts
211
+ ```javascript
212
+ upvote(votePercentage = '100.0', username, permlink) {
213
+
214
+ }
215
+
216
+ downvote(votePercentage = '100.0', username, permlink) {
217
+
218
+ }
219
+ ```
220
+
221
+ ## Contracts
222
+
223
+ Hive Stream allows you to register contract definitions that execute when a transfer memo or custom JSON operation matches. The payload lives under the `PAYLOAD_IDENTIFIER` (default: `hive_stream`).
224
+
225
+ The payload shape is:
226
+
227
+ - `contract`: the name of the contract you registered
228
+ - `action`: the action name defined in your contract
229
+ - `payload`: data passed to the action
230
+ - `meta`: optional metadata
231
+
232
+ ### Writing contracts
233
+
234
+ Contracts are defined with `defineContract` + `action`. Each action can specify a trigger (`custom_json`, `transfer`, `time`, `escrow_transfer`, `escrow_approve`, `escrow_dispute`, `escrow_release`, or `recurrent_transfer`) and an optional Zod schema for payload validation.
235
+
236
+ For a full contract-building guide (payloads, context, triggers, validation, error handling, and exchange setup), see `DOCUMENTATION.md`.
237
+
238
+ ### Register a contract
239
+
240
+ Register a contract definition. Registration is async so hooks can initialize state.
241
+
242
+ ```javascript
243
+ import { defineContract, action } from 'hive-stream';
244
+
245
+ const MyContract = defineContract({
246
+ name: 'mycontract',
247
+ actions: {
248
+ hello: action(async (payload, ctx) => {
249
+ console.log('hello', payload, ctx.sender);
250
+ }, { trigger: 'custom_json' })
251
+ }
252
+ });
253
+
254
+ await streamer.registerContract(MyContract);
255
+ ```
256
+
257
+ ### Unregister a contract
258
+
259
+ Unregister a contract that has been registered.
260
+
261
+ ```javascript
262
+ await streamer.unregisterContract('mycontract');
263
+ ```
264
+
265
+ ### Example Payload
266
+
267
+ ```javascript
268
+ JSON.stringify({
269
+ hive_stream: {
270
+ contract: 'hivedice',
271
+ action: 'roll',
272
+ payload: { roll: 22 }
273
+ }
274
+ })
275
+ ```
276
+
277
+ This will match a registered contract called `hivedice`, run the `roll` action, and pass the payload into your handler.
278
+
279
+ ### Built-in Contract Examples
280
+
281
+ The library includes several built-in contract examples in the `src/contracts` folder:
282
+
283
+ - `createDiceContract` - A dice rolling game contract
284
+ - `createCoinflipContract` - A coin flip game contract
285
+ - `createLottoContract` - A lottery-style game contract
286
+ - `createTokenContract` - A contract for token operations
287
+ - `createNFTContract` - A contract for NFT operations
288
+ - `createRpsContract` - A rock-paper-scissors game contract
289
+ - `createPollContract` - A poll/voting contract
290
+ - `createTipJarContract` - A tip jar + message board contract
291
+ - `createExchangeContract` - A basic exchange with deposits, withdrawals, balances, and order matching (SQL adapter required)
292
+
293
+ These can be imported and used as examples for building your own contracts:
294
+
295
+ ```javascript
296
+ import { createDiceContract, createCoinflipContract, createLottoContract } from 'hive-stream';
297
+ ```
298
+
299
+ ### Example Snippets
300
+
301
+ Sample snippets for the newest contracts live in `examples/contracts/`:
302
+
303
+ - `examples/contracts/rps.ts`
304
+ - `examples/contracts/poll.ts`
305
+ - `examples/contracts/tipjar.ts`
306
+ - `examples/contracts/exchange.ts`
307
+
308
+ ## Time-based Actions
309
+
310
+ It's like a cron job for your contracts. Time-based actions allow you to execute contract functions over a wide variety of different periods. Want to call a function every 3 seconds block time or want to call a function once per day? Time-based actions are an easy way to run time code.
311
+
312
+ The following example will run a contract action every 30 seconds. All you do is register a new `TimeAction` instance.
313
+
314
+ ```
315
+ import { TimeAction, Streamer } from 'hive-stream';
316
+
317
+ const streamer = new Streamer({
318
+ ACTIVE_KEY: ''
319
+ });
320
+
321
+ const testAction = new TimeAction('30s', 'test30s', 'hivedice', 'testauto');
322
+
323
+ streamer.registerAction(testAction);
324
+
325
+ streamer.start();
326
+ ```
327
+
328
+ The `TimeAction` instance accepts the following values:
329
+
330
+ - timeValue - When should this action be run?
331
+ - uniqueId - A unique ID to describe your action
332
+ - contractName - The name of the contract
333
+ - contractAction - The action we are calling inside of the contract
334
+ - date - An optional final parameter that accepts a date of creation
335
+
336
+ ```
337
+ new TimeAction(timeValue, uniqueId, contractName, contractAction, date)
338
+ ```
339
+
340
+ ### Valid time values
341
+
342
+ At the moment, the `timeValue` passed in as the first argument to `TimeAction` cannot accept just any value. However, there are many available out-of-the-box with more flexibility to come in the future.
343
+
344
+ - `3s` or `block` will run a task every block (3 seconds, approximately)
345
+ - `10s` will run a task every 10 seconds
346
+ - `30s` will run a task every 30 seconds
347
+ - `1m` or `minute` will run a task every 60 seconds (1 minute)
348
+ - `5m` will run a task every 5 minutes
349
+ - `15m` or `quarter` will run a task every 15 minutes
350
+ - `30m` or `halfhour` will run a task every 30 minutes
351
+ - `1h` or `hourly` will run a task every 60 minutes (every hour)
352
+ - `12h` or `halfday` will run a task every 12 hours (half a day)
353
+ - `24h`, `day`, or `daily` will run a task every 24 hours (day)
354
+ - `week` or `weekly` will run a task every 7 days (week)
355
+
356
+ Values will be persisted if using one of the database adapters that ship with the library.
357
+
358
+ ## Adapters
359
+
360
+ The Hive Stream library supports custom adapters for various actions that take place in the library. When the library first loads, it makes a call to get the last block number or when a block is processed, storing the processed block number. This library ships with three adapters: SQLite, MongoDB, and PostgreSQL. These provide robust database storage for blockchain state and operations.
361
+
362
+ By default, Streamer uses SQLite adapter. To use a different adapter, use the `registerAdapter()` method:
363
+
364
+ ### SQLite Adapter (Default)
365
+ ```javascript
366
+ import { Streamer, SqliteAdapter } from 'hive-stream';
367
+
368
+ const streamer = new Streamer(config);
369
+ // SQLite is used by default, but you can explicitly register a custom SQLite database:
370
+ const adapter = new SqliteAdapter('./hive-stream.db');
371
+ await streamer.registerAdapter(adapter);
372
+ ```
373
+
374
+ ### MongoDB Adapter
375
+ ```javascript
376
+ import { Streamer, MongodbAdapter } from 'hive-stream';
377
+
378
+ const streamer = new Streamer(config);
379
+ const adapter = new MongodbAdapter('mongodb://localhost:27017', 'hive_stream');
380
+ await streamer.registerAdapter(adapter);
381
+ ```
382
+
383
+ ### PostgreSQL Adapter
384
+ ```javascript
385
+ import { Streamer, PostgreSQLAdapter } from 'hive-stream';
386
+
387
+ const streamer = new Streamer(config);
388
+ const adapter = new PostgreSQLAdapter({
389
+ host: 'localhost',
390
+ port: 5432,
391
+ user: 'postgres',
392
+ password: 'your_password',
393
+ database: 'hive_stream'
394
+ });
395
+
396
+ // Or with connection string
397
+ const adapter = new PostgreSQLAdapter({
398
+ connectionString: 'postgresql://user:pass@localhost:5432/hive_stream'
399
+ });
400
+
401
+ await streamer.registerAdapter(adapter);
402
+ ```
403
+
404
+ When creating an adapter, at a minimum your adapter requires two methods: `loadState` and `saveState`. It must also extend `AdapterBase` which is exported from the package.
405
+
406
+ You can see a few adapters that ship with Hive Stream in the `src/adapters` directory.
407
+
408
+ ## Permanently running with PM2
409
+
410
+ Simply copy the `ecosystem.config.js` file from this repository into your application, globally install `pm2` via `npm install pm2 -g` and change the `script` value below to reflect the main file of your application.
411
+
412
+ **ecosystem.config.js**
413
+
414
+ ```
415
+ module.exports = {
416
+ apps: [
417
+ {
418
+ name: 'hive-stream',
419
+ script: 'index.js',
420
+ ignore_watch: ['node_modules'],
421
+ env: {
422
+ NODE_ENV: 'development'
423
+ },
424
+ env_production: {
425
+ NODE_ENV: 'production'
426
+ }
427
+ }
428
+ ]
429
+ ```