hive-stream 3.0.2 → 3.0.4

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 (202) hide show
  1. package/DOCUMENTATION.md +50 -2
  2. package/README.md +282 -4
  3. package/dist/adapters/base.adapter.d.ts +5 -0
  4. package/dist/adapters/base.adapter.js +9 -0
  5. package/dist/adapters/base.adapter.js.map +1 -1
  6. package/dist/adapters/mongodb.adapter.d.ts +6 -6
  7. package/dist/adapters/mongodb.adapter.js +36 -21
  8. package/dist/adapters/mongodb.adapter.js.map +1 -1
  9. package/dist/adapters/postgresql.adapter.d.ts +7 -0
  10. package/dist/adapters/postgresql.adapter.js +46 -19
  11. package/dist/adapters/postgresql.adapter.js.map +1 -1
  12. package/dist/adapters/sqlite.adapter.d.ts +4 -0
  13. package/dist/adapters/sqlite.adapter.js +10 -0
  14. package/dist/adapters/sqlite.adapter.js.map +1 -1
  15. package/dist/api.d.ts +13 -3
  16. package/dist/api.js +96 -62
  17. package/dist/api.js.map +1 -1
  18. package/dist/builders.d.ts +176 -0
  19. package/dist/builders.js +727 -0
  20. package/dist/builders.js.map +1 -0
  21. package/dist/config.d.ts +16 -1
  22. package/dist/config.js +95 -3
  23. package/dist/config.js.map +1 -1
  24. package/dist/contracts/auctionhouse.contract.d.ts +4 -0
  25. package/dist/contracts/auctionhouse.contract.js +234 -0
  26. package/dist/contracts/auctionhouse.contract.js.map +1 -0
  27. package/dist/contracts/booking.contract.d.ts +4 -0
  28. package/dist/contracts/booking.contract.js +225 -0
  29. package/dist/contracts/booking.contract.js.map +1 -0
  30. package/dist/contracts/bountyboard.contract.d.ts +4 -0
  31. package/dist/contracts/bountyboard.contract.js +233 -0
  32. package/dist/contracts/bountyboard.contract.js.map +1 -0
  33. package/dist/contracts/bundlemarketplace.contract.d.ts +4 -0
  34. package/dist/contracts/bundlemarketplace.contract.js +195 -0
  35. package/dist/contracts/bundlemarketplace.contract.js.map +1 -0
  36. package/dist/contracts/charitymatch.contract.d.ts +4 -0
  37. package/dist/contracts/charitymatch.contract.js +172 -0
  38. package/dist/contracts/charitymatch.contract.js.map +1 -0
  39. package/dist/contracts/coinflip.contract.js +25 -22
  40. package/dist/contracts/coinflip.contract.js.map +1 -1
  41. package/dist/contracts/crowdfund.contract.d.ts +4 -0
  42. package/dist/contracts/crowdfund.contract.js +290 -0
  43. package/dist/contracts/crowdfund.contract.js.map +1 -0
  44. package/dist/contracts/dcabot.contract.d.ts +4 -0
  45. package/dist/contracts/dcabot.contract.js +217 -0
  46. package/dist/contracts/dcabot.contract.js.map +1 -0
  47. package/dist/contracts/dice.contract.js +25 -22
  48. package/dist/contracts/dice.contract.js.map +1 -1
  49. package/dist/contracts/domainregistry.contract.d.ts +4 -0
  50. package/dist/contracts/domainregistry.contract.js +232 -0
  51. package/dist/contracts/domainregistry.contract.js.map +1 -0
  52. package/dist/contracts/exchange.contract.js +209 -168
  53. package/dist/contracts/exchange.contract.js.map +1 -1
  54. package/dist/contracts/fanclub.contract.d.ts +4 -0
  55. package/dist/contracts/fanclub.contract.js +193 -0
  56. package/dist/contracts/fanclub.contract.js.map +1 -0
  57. package/dist/contracts/giftcard.contract.d.ts +4 -0
  58. package/dist/contracts/giftcard.contract.js +158 -0
  59. package/dist/contracts/giftcard.contract.js.map +1 -0
  60. package/dist/contracts/grantrounds.contract.d.ts +4 -0
  61. package/dist/contracts/grantrounds.contract.js +265 -0
  62. package/dist/contracts/grantrounds.contract.js.map +1 -0
  63. package/dist/contracts/groupbuy.contract.d.ts +4 -0
  64. package/dist/contracts/groupbuy.contract.js +198 -0
  65. package/dist/contracts/groupbuy.contract.js.map +1 -0
  66. package/dist/contracts/helpers.d.ts +66 -0
  67. package/dist/contracts/helpers.js +166 -0
  68. package/dist/contracts/helpers.js.map +1 -0
  69. package/dist/contracts/insurancepool.contract.d.ts +4 -0
  70. package/dist/contracts/insurancepool.contract.js +281 -0
  71. package/dist/contracts/insurancepool.contract.js.map +1 -0
  72. package/dist/contracts/invoice.contract.d.ts +4 -0
  73. package/dist/contracts/invoice.contract.js +193 -0
  74. package/dist/contracts/invoice.contract.js.map +1 -0
  75. package/dist/contracts/launchpad.contract.d.ts +4 -0
  76. package/dist/contracts/launchpad.contract.js +225 -0
  77. package/dist/contracts/launchpad.contract.js.map +1 -0
  78. package/dist/contracts/lotto.contract.js +53 -37
  79. package/dist/contracts/lotto.contract.js.map +1 -1
  80. package/dist/contracts/multisigtreasury.contract.d.ts +4 -0
  81. package/dist/contracts/multisigtreasury.contract.js +245 -0
  82. package/dist/contracts/multisigtreasury.contract.js.map +1 -0
  83. package/dist/contracts/nft.contract.d.ts +1 -0
  84. package/dist/contracts/nft.contract.js +234 -195
  85. package/dist/contracts/nft.contract.js.map +1 -1
  86. package/dist/contracts/oraclebounty.contract.d.ts +4 -0
  87. package/dist/contracts/oraclebounty.contract.js +250 -0
  88. package/dist/contracts/oraclebounty.contract.js.map +1 -0
  89. package/dist/contracts/payroll.contract.d.ts +4 -0
  90. package/dist/contracts/payroll.contract.js +232 -0
  91. package/dist/contracts/payroll.contract.js.map +1 -0
  92. package/dist/contracts/paywall.contract.d.ts +4 -0
  93. package/dist/contracts/paywall.contract.js +185 -0
  94. package/dist/contracts/paywall.contract.js.map +1 -0
  95. package/dist/contracts/poll.contract.js +2 -0
  96. package/dist/contracts/poll.contract.js.map +1 -1
  97. package/dist/contracts/predictionmarket.contract.d.ts +4 -0
  98. package/dist/contracts/predictionmarket.contract.js +213 -0
  99. package/dist/contracts/predictionmarket.contract.js.map +1 -0
  100. package/dist/contracts/proposaltimelock.contract.d.ts +4 -0
  101. package/dist/contracts/proposaltimelock.contract.js +250 -0
  102. package/dist/contracts/proposaltimelock.contract.js.map +1 -0
  103. package/dist/contracts/questpass.contract.d.ts +4 -0
  104. package/dist/contracts/questpass.contract.js +214 -0
  105. package/dist/contracts/questpass.contract.js.map +1 -0
  106. package/dist/contracts/referral.contract.d.ts +4 -0
  107. package/dist/contracts/referral.contract.js +238 -0
  108. package/dist/contracts/referral.contract.js.map +1 -0
  109. package/dist/contracts/rental.contract.d.ts +4 -0
  110. package/dist/contracts/rental.contract.js +221 -0
  111. package/dist/contracts/rental.contract.js.map +1 -0
  112. package/dist/contracts/revenuesplit.contract.d.ts +4 -0
  113. package/dist/contracts/revenuesplit.contract.js +211 -0
  114. package/dist/contracts/revenuesplit.contract.js.map +1 -0
  115. package/dist/contracts/rps.contract.js +48 -20
  116. package/dist/contracts/rps.contract.js.map +1 -1
  117. package/dist/contracts/savings.contract.d.ts +4 -0
  118. package/dist/contracts/savings.contract.js +208 -0
  119. package/dist/contracts/savings.contract.js.map +1 -0
  120. package/dist/contracts/subscription.contract.d.ts +4 -0
  121. package/dist/contracts/subscription.contract.js +241 -0
  122. package/dist/contracts/subscription.contract.js.map +1 -0
  123. package/dist/contracts/sweepstakes.contract.d.ts +4 -0
  124. package/dist/contracts/sweepstakes.contract.js +209 -0
  125. package/dist/contracts/sweepstakes.contract.js.map +1 -0
  126. package/dist/contracts/ticketing.contract.d.ts +4 -0
  127. package/dist/contracts/ticketing.contract.js +185 -0
  128. package/dist/contracts/ticketing.contract.js.map +1 -0
  129. package/dist/contracts/tipjar.contract.js +2 -0
  130. package/dist/contracts/tipjar.contract.js.map +1 -1
  131. package/dist/contracts/token.contract.js +135 -125
  132. package/dist/contracts/token.contract.js.map +1 -1
  133. package/dist/index.d.ts +40 -0
  134. package/dist/index.js +72 -1
  135. package/dist/index.js.map +1 -1
  136. package/dist/metadata.d.ts +20 -0
  137. package/dist/metadata.js +320 -1
  138. package/dist/metadata.js.map +1 -1
  139. package/dist/providers/block-provider.d.ts +22 -0
  140. package/dist/providers/block-provider.js +3 -0
  141. package/dist/providers/block-provider.js.map +1 -0
  142. package/dist/providers/haf-client.d.ts +30 -0
  143. package/dist/providers/haf-client.js +119 -0
  144. package/dist/providers/haf-client.js.map +1 -0
  145. package/dist/providers/haf-provider.d.ts +49 -0
  146. package/dist/providers/haf-provider.js +256 -0
  147. package/dist/providers/haf-provider.js.map +1 -0
  148. package/dist/providers/hive-provider.d.ts +13 -0
  149. package/dist/providers/hive-provider.js +25 -0
  150. package/dist/providers/hive-provider.js.map +1 -0
  151. package/dist/providers/index.d.ts +4 -0
  152. package/dist/providers/index.js +21 -0
  153. package/dist/providers/index.js.map +1 -0
  154. package/dist/streamer.d.ts +65 -4
  155. package/dist/streamer.js +768 -72
  156. package/dist/streamer.js.map +1 -1
  157. package/dist/types/hive-stream.d.ts +317 -0
  158. package/dist/utils.d.ts +33 -0
  159. package/dist/utils.js +198 -2
  160. package/dist/utils.js.map +1 -1
  161. package/package.json +16 -1
  162. package/.claude/settings.local.json +0 -12
  163. package/.env.example +0 -3
  164. package/.travis.yml +0 -11
  165. package/AGENTS.md +0 -35
  166. package/CLAUDE.md +0 -75
  167. package/ecosystem.config.js +0 -17
  168. package/examples/contracts/README.md +0 -8
  169. package/examples/contracts/exchange.ts +0 -38
  170. package/examples/contracts/poll.ts +0 -21
  171. package/examples/contracts/rps.ts +0 -19
  172. package/examples/contracts/tipjar.ts +0 -19
  173. package/jest.config.js +0 -9
  174. package/test-contract-block.md +0 -19
  175. package/tests/actions.spec.ts +0 -252
  176. package/tests/adapters/actions-persistence.spec.ts +0 -144
  177. package/tests/adapters/postgresql.adapter.spec.ts +0 -127
  178. package/tests/adapters/sqlite.adapter.spec.ts +0 -181
  179. package/tests/config-input.spec.ts +0 -90
  180. package/tests/contracts/coinflip.contract.spec.ts +0 -94
  181. package/tests/contracts/dice.contract.spec.ts +0 -87
  182. package/tests/contracts/entrants.json +0 -729
  183. package/tests/contracts/exchange.contract.spec.ts +0 -84
  184. package/tests/contracts/lotto.contract.spec.ts +0 -59
  185. package/tests/contracts/nft.contract.spec.ts +0 -948
  186. package/tests/contracts/token.contract.spec.ts +0 -90
  187. package/tests/exchanges/coingecko.exchange.spec.ts +0 -169
  188. package/tests/exchanges/exchange.base.spec.ts +0 -246
  189. package/tests/helpers/mock-adapter.ts +0 -214
  190. package/tests/helpers/mock-fetch.ts +0 -165
  191. package/tests/hive-chain-features.spec.ts +0 -319
  192. package/tests/hive-rates.spec.ts +0 -443
  193. package/tests/integration/hive-rates.integration.spec.ts +0 -35
  194. package/tests/metadata.spec.ts +0 -63
  195. package/tests/setup.ts +0 -30
  196. package/tests/streamer-actions.spec.ts +0 -274
  197. package/tests/streamer.spec.ts +0 -342
  198. package/tests/types/rates.spec.ts +0 -216
  199. package/tests/utils.spec.ts +0 -113
  200. package/tsconfig.build.json +0 -4
  201. package/tslint.json +0 -21
  202. package/wallaby.js +0 -26
@@ -1,214 +0,0 @@
1
- import { AdapterBase } from '../../src/adapters/base.adapter';
2
-
3
- export class MockAdapter extends AdapterBase {
4
- public queries: string[] = [];
5
- public events: any[] = [];
6
- private queryResults: any[][] = [];
7
- private currentQueryIndex = 0;
8
- private testContext: any = {};
9
- public async create(): Promise<boolean> {
10
- return true;
11
- }
12
-
13
- public async destroy(): Promise<boolean> {
14
- return true;
15
- }
16
-
17
- public async loadActions() {
18
- return [];
19
- }
20
-
21
- public async loadState() {
22
- return { lastBlockNumber: 0, actions: [] };
23
- }
24
-
25
- public async saveState(data: any): Promise<boolean> {
26
- return true;
27
- }
28
-
29
- public async processBlock(block: any): Promise<any> {
30
- return true;
31
- }
32
-
33
- public async processOperation(op: any, blockNumber: number, blockId: string, prevBlockId: string, trxId: string, blockTime: Date): Promise<any> {
34
- return true;
35
- }
36
-
37
- public async processTransfer(operation: any, payload: any, metadata: any): Promise<boolean> {
38
- return true;
39
- }
40
-
41
- public async processCustomJson(operation: any, payload: any, metadata: any): Promise<boolean> {
42
- return true;
43
- }
44
-
45
- public async find(table: string, queryObject: Record<string, any>): Promise<any> {
46
- return [];
47
- }
48
-
49
- public async findOne(table: string, queryObject: Record<string, any>): Promise<any> {
50
- return null;
51
- }
52
-
53
- public async insert(table: string, data: any): Promise<any> {
54
- return true;
55
- }
56
-
57
- public async replace(table: string, queryObject: Record<string, any>, data: any): Promise<any> {
58
- return data;
59
- }
60
-
61
- public async addEvent(date: string | Date, contract: string, action: string, payload: any, data: any): Promise<boolean> {
62
- this.events.push({ date, contract, action, payload, data });
63
- return true;
64
- }
65
-
66
- public async query(sql: string, params?: any[]): Promise<any[]> {
67
- this.queries.push(sql);
68
-
69
- // Handle specific queries with predetermined responses
70
- if (sql.includes('CREATE TABLE')) {
71
- return [];
72
- }
73
-
74
- if (sql.includes('SELECT precision FROM tokens WHERE symbol = ?')) {
75
- const symbol = params?.[0];
76
- if (this.testContext.nonExistentToken === symbol) {
77
- return [];
78
- }
79
- return [{ precision: 3 }];
80
- }
81
-
82
- if (sql.includes('SELECT balance FROM token_balances WHERE account = ? AND symbol = ?')) {
83
- const account = params?.[0];
84
- const symbol = params?.[1];
85
-
86
- // Handle test scenarios
87
- if (this.testContext.insufficientBalance && account === 'alice') {
88
- return [{ balance: '50' }];
89
- }
90
- if (this.testContext.zeroBalance && account === 'alice') {
91
- return [];
92
- }
93
- if (this.testContext.noExistingBalance) {
94
- return [];
95
- }
96
-
97
- // Default balances
98
- if (account === 'alice') {
99
- return [{ balance: '1000' }];
100
- } else if (account === 'bob') {
101
- return [{ balance: '50' }];
102
- }
103
- return [];
104
- }
105
-
106
- if (sql.includes('SELECT * FROM tokens WHERE symbol = ?')) {
107
- const symbol = params?.[0];
108
- if (this.testContext.nonExistentToken === symbol) {
109
- return [];
110
- }
111
-
112
- // Handle max supply exceeded test
113
- if (this.testContext.maxSupplyExceeded) {
114
- return [{
115
- symbol: 'TEST',
116
- name: 'Test Token',
117
- creator: 'alice',
118
- precision: 3,
119
- max_supply: '1000000',
120
- current_supply: '999999'
121
- }];
122
- }
123
-
124
- // Return token info for existing tokens
125
- return [{
126
- symbol: 'TEST',
127
- name: 'Test Token',
128
- url: 'https://example.com/token',
129
- precision: 3,
130
- max_supply: '1000000',
131
- current_supply: '500000',
132
- creator: 'alice',
133
- created_at: new Date()
134
- }];
135
- }
136
-
137
- if (sql.includes('SELECT symbol FROM tokens WHERE symbol = ?')) {
138
- const symbol = params?.[0];
139
- if (this.testContext.existingToken === symbol) {
140
- return [{ symbol }];
141
- }
142
- return [];
143
- }
144
-
145
- // Use sequential results for other queries
146
- if (this.queryResults.length > this.currentQueryIndex) {
147
- return this.queryResults[this.currentQueryIndex++];
148
- }
149
- return [];
150
- }
151
-
152
- public setQueryResult(result: any[], index?: number): void {
153
- if (index !== undefined) {
154
- this.queryResults[index] = result;
155
- } else {
156
- this.queryResults.push(result);
157
- }
158
- }
159
-
160
- public setQueryResults(results: any[][]): void {
161
- this.queryResults = results;
162
- this.currentQueryIndex = 0;
163
- }
164
-
165
- public reset(): void {
166
- this.queries = [];
167
- this.events = [];
168
- this.queryResults = [];
169
- this.currentQueryIndex = 0;
170
- this.testContext = {};
171
- }
172
-
173
- public setTestContext(context: any): void {
174
- this.testContext = context;
175
- }
176
-
177
- public async getTransfers() {
178
- return [];
179
- }
180
-
181
- public async getEvents() {
182
- return [];
183
- }
184
-
185
- public async getJson() {
186
- return [];
187
- }
188
-
189
- public async getTransfersByContract(contract: string) {
190
- return [];
191
- }
192
-
193
- public async getTransfersByAccount(account: string) {
194
- return [];
195
- }
196
-
197
- public async getTransfersByBlockid(blockId: any) {
198
- return [];
199
- }
200
-
201
- public async getJsonByContract(contract: string) {
202
- return [];
203
- }
204
-
205
- public async getJsonByAccount(account: string) {
206
- return [];
207
- }
208
-
209
- public async getJsonByBlockid(blockId: any) {
210
- return [];
211
- }
212
- }
213
-
214
- export const createMockAdapter = () => new MockAdapter();
@@ -1,165 +0,0 @@
1
- /**
2
- * Test utilities for mocking fetch and external APIs
3
- */
4
-
5
- import { jest } from '@jest/globals';
6
-
7
- // Mock Response class that properly implements the Response interface
8
- export class MockResponse {
9
- public readonly status: number;
10
- public readonly statusText: string;
11
- public readonly ok: boolean;
12
- public readonly headers: Headers;
13
- public readonly redirected: boolean = false;
14
- public readonly type: ResponseType = 'default';
15
- public readonly url: string = '';
16
- public readonly body: ReadableStream<Uint8Array> | null = null;
17
- public readonly bodyUsed: boolean = false;
18
-
19
- private data: any;
20
-
21
- constructor(data: any, options: { status?: number; statusText?: string; headers?: HeadersInit } = {}) {
22
- this.data = data;
23
- this.status = options.status || 200;
24
- this.statusText = options.statusText || 'OK';
25
- this.ok = this.status >= 200 && this.status < 300;
26
- this.headers = new Headers(options.headers);
27
- }
28
-
29
- async json(): Promise<any> {
30
- return this.data;
31
- }
32
-
33
- async text(): Promise<string> {
34
- return typeof this.data === 'string' ? this.data : JSON.stringify(this.data);
35
- }
36
-
37
- async arrayBuffer(): Promise<ArrayBuffer> {
38
- throw new Error('arrayBuffer not implemented in mock');
39
- }
40
-
41
- async blob(): Promise<Blob> {
42
- throw new Error('blob not implemented in mock');
43
- }
44
-
45
- async formData(): Promise<FormData> {
46
- throw new Error('formData not implemented in mock');
47
- }
48
-
49
- async bytes(): Promise<Uint8Array> {
50
- throw new Error('bytes not implemented in mock');
51
- }
52
-
53
- clone(): MockResponse {
54
- return new MockResponse(this.data, {
55
- status: this.status,
56
- statusText: this.statusText,
57
- headers: this.headers
58
- });
59
- }
60
- }
61
-
62
- /**
63
- * Create a mock fetch function with predefined responses
64
- */
65
- export function createMockFetch(responses: { [url: string]: any } = {}) {
66
- return jest.fn().mockImplementation((...args: any[]) => {
67
- const url = args[0] as string;
68
-
69
- // Handle URL patterns
70
- if (url.includes('coingecko.com')) {
71
- return Promise.resolve(new MockResponse({
72
- hive: { usd: 0.25 },
73
- 'hive_dollar': { usd: 1.00 }
74
- }));
75
- }
76
-
77
- if (url.includes('fawazahmed0.github.io') && url.includes('/latest/currencies/usd.json')) {
78
- return Promise.resolve(new MockResponse({
79
- usd: {
80
- eur: 0.85,
81
- gbp: 0.73,
82
- jpy: 110.0,
83
- cad: 1.25,
84
- aud: 1.35
85
- }
86
- }));
87
- }
88
-
89
- // Handle specific URLs from responses object
90
- if (responses[url]) {
91
- return Promise.resolve(new MockResponse(responses[url]));
92
- }
93
-
94
- // Default error response
95
- return Promise.reject(new Error(`Unmocked URL: ${url}`));
96
- });
97
- }
98
-
99
- /**
100
- * Mock successful API responses for all endpoints
101
- */
102
- export function mockSuccessfulApis() {
103
- const mockFetch = createMockFetch();
104
- global.fetch = mockFetch as any;
105
- return mockFetch;
106
- }
107
-
108
- /**
109
- * Mock network errors for testing error handling
110
- */
111
- export function mockNetworkErrors() {
112
- const mockFetch = jest.fn().mockImplementation(() =>
113
- Promise.reject(new Error('Network error'))
114
- );
115
- global.fetch = mockFetch as any;
116
- return mockFetch;
117
- }
118
-
119
- /**
120
- * Mock timeout errors
121
- */
122
- export function mockTimeoutErrors() {
123
- const mockFetch = jest.fn().mockImplementation(() =>
124
- new Promise((_, reject) => {
125
- setTimeout(() => reject(new Error('Request timeout')), 100);
126
- })
127
- );
128
- global.fetch = mockFetch as any;
129
- return mockFetch;
130
- }
131
-
132
- /**
133
- * Mock invalid JSON responses
134
- */
135
- export function mockInvalidResponses() {
136
- const mockFetch = jest.fn().mockImplementation(() =>
137
- Promise.resolve(new MockResponse('invalid json', { status: 200 }))
138
- );
139
- global.fetch = mockFetch as any;
140
- return mockFetch;
141
- }
142
-
143
- /**
144
- * Mock HTTP error responses
145
- */
146
- export function mockHttpErrors(status: number = 500) {
147
- const mockFetch = jest.fn().mockImplementation(() =>
148
- Promise.resolve(
149
- new MockResponse({ error: 'Server error' }, { status, statusText: 'Internal Server Error' })
150
- )
151
- );
152
- global.fetch = mockFetch as any;
153
- return mockFetch;
154
- }
155
-
156
- /**
157
- * Clean up mocks after tests
158
- */
159
- export function cleanupMocks() {
160
- jest.clearAllMocks();
161
- // Reset fetch to original if needed
162
- if (global.fetch && 'mockRestore' in global.fetch) {
163
- (global.fetch as any).mockRestore();
164
- }
165
- }
@@ -1,319 +0,0 @@
1
- import { PrivateKey } from '@hiveio/dhive';
2
- import { Streamer } from '../src/streamer';
3
- import { Utils } from '../src/utils';
4
- import { action, defineContract } from '../src/contracts/contract';
5
- import { createMockAdapter } from './helpers/mock-adapter';
6
-
7
- describe('Hive chain features', () => {
8
- const activeKey = PrivateKey.fromSeed('hive-stream-active').toString();
9
-
10
- afterEach(() => {
11
- jest.restoreAllMocks();
12
- });
13
-
14
- describe('Utils multisig + escrow helpers', () => {
15
- test('broadcastMultiSigOperations signs with multiple keys', async () => {
16
- const keyOne = PrivateKey.fromSeed('key-one').toString();
17
- const keyTwo = PrivateKey.fromSeed('key-two').toString();
18
- const sendOperations = jest.fn().mockResolvedValue({ id: 'tx-id' });
19
- const client = {
20
- broadcast: {
21
- sendOperations
22
- },
23
- database: {
24
- getAccounts: jest.fn().mockResolvedValue([{
25
- memo_key: 'STMmemo',
26
- json_metadata: '{}',
27
- posting_json_metadata: '{}'
28
- }])
29
- }
30
- } as any;
31
-
32
- await Utils.broadcastMultiSigOperations(client, [['vote', { voter: 'alice' }]], [keyOne, keyTwo]);
33
-
34
- const passedKeys = sendOperations.mock.calls[0][1];
35
- expect(Array.isArray(passedKeys)).toBe(true);
36
- expect(passedKeys).toHaveLength(2);
37
- });
38
-
39
- test('updateAccountAuthorities uses account_update2 when posting JSON metadata is provided', async () => {
40
- const sendOperations = jest.fn().mockResolvedValue({ id: 'tx-id' });
41
- const client = {
42
- broadcast: {
43
- sendOperations
44
- },
45
- database: {
46
- getAccounts: jest.fn().mockResolvedValue([{
47
- memo_key: 'STMmemo',
48
- json_metadata: '{}',
49
- posting_json_metadata: '{}'
50
- }])
51
- }
52
- } as any;
53
-
54
- await Utils.updateAccountAuthorities(client, { ACTIVE_KEY: activeKey }, 'alice', {
55
- active: Utils.createAuthority([[`STM${'1'.repeat(50)}`, 1]], [], 1),
56
- posting_json_metadata: '{}'
57
- });
58
-
59
- const operation = sendOperations.mock.calls[0][0][0];
60
- expect(operation[0]).toBe('account_update2');
61
- });
62
-
63
- test('escrowTransfer builds and broadcasts escrow_transfer operation', async () => {
64
- const sendOperations = jest.fn().mockResolvedValue({ id: 'tx-id' });
65
- const client = {
66
- broadcast: {
67
- sendOperations
68
- }
69
- } as any;
70
-
71
- await Utils.escrowTransfer(client, { ACTIVE_KEY: activeKey }, {
72
- from: 'alice',
73
- to: 'bob',
74
- agent: 'escrow.agent',
75
- escrow_id: 42,
76
- hive_amount: '1.000 HIVE',
77
- hbd_amount: '0.000 HBD',
78
- fee: '0.001 HIVE',
79
- ratification_deadline: new Date('2025-01-01T00:00:00.000Z'),
80
- escrow_expiration: new Date('2025-01-02T00:00:00.000Z'),
81
- json_meta: { test: true }
82
- });
83
-
84
- const operation = sendOperations.mock.calls[0][0][0];
85
- expect(operation[0]).toBe('escrow_transfer');
86
- expect(operation[1].escrow_id).toBe(42);
87
- expect(operation[1].json_meta).toBe(JSON.stringify({ test: true }));
88
- expect(operation[1].ratification_deadline).toBe('2025-01-01T00:00:00');
89
- expect(operation[1].escrow_expiration).toBe('2025-01-02T00:00:00');
90
- });
91
- });
92
-
93
- describe('Streamer operation behavior', () => {
94
- let streamer: Streamer;
95
-
96
- beforeEach(async () => {
97
- streamer = new Streamer({
98
- ACTIVE_KEY: activeKey,
99
- JSON_ID: 'testing',
100
- PAYLOAD_IDENTIFIER: 'hive_stream',
101
- DEBUG_MODE: false
102
- });
103
-
104
- await streamer.registerAdapter(createMockAdapter());
105
- });
106
-
107
- afterEach(async () => {
108
- await streamer.stop();
109
- });
110
-
111
- test('transferHiveEngineTokens forwards quantity and symbol in correct order', () => {
112
- const spy = jest.spyOn(Utils, 'transferHiveEngineTokens').mockResolvedValue({} as any);
113
-
114
- streamer.transferHiveEngineTokens('alice', 'bob', 'TEST', '1.500', 'memo');
115
-
116
- expect(spy).toHaveBeenCalledWith(
117
- expect.anything(),
118
- expect.anything(),
119
- 'alice',
120
- 'bob',
121
- '1.500',
122
- 'TEST',
123
- 'memo'
124
- );
125
- });
126
-
127
- test('onCustomJsonId only fires callbacks for the matching id', async () => {
128
- const matching = jest.fn();
129
- const nonMatching = jest.fn();
130
-
131
- streamer.onCustomJsonId(matching, 'target-id');
132
- streamer.onCustomJsonId(nonMatching, 'other-id');
133
-
134
- await streamer.processOperation([
135
- 'custom_json',
136
- {
137
- id: 'target-id',
138
- json: '{}',
139
- required_auths: ['alice'],
140
- required_posting_auths: []
141
- }
142
- ], 10, 'block-id', 'prev-id', 'trx-id', new Date());
143
-
144
- expect(matching).toHaveBeenCalledTimes(1);
145
- expect(nonMatching).not.toHaveBeenCalled();
146
- });
147
-
148
- test('onHiveEngine still fires when tx verification lookup fails', async () => {
149
- const handler = jest.fn();
150
- const consoleError = jest.spyOn(console, 'error').mockImplementation(() => undefined);
151
- const getTransactionInfo = jest.spyOn(streamer['hive'], 'getTransactionInfo')
152
- .mockRejectedValue(new Error('temporary hive engine outage'));
153
-
154
- streamer.onHiveEngine(handler);
155
-
156
- await streamer.processOperation([
157
- 'custom_json',
158
- {
159
- id: 'ssc-mainnet-hive',
160
- json: JSON.stringify({
161
- contractName: 'tokens',
162
- contractAction: 'transfer',
163
- contractPayload: {
164
- symbol: 'TEST',
165
- to: 'target',
166
- quantity: '1.000',
167
- memo: 'memo'
168
- }
169
- }),
170
- required_auths: ['alice'],
171
- required_posting_auths: []
172
- }
173
- ], 20, 'block-20', 'block-19', 'trx-20', new Date('2025-01-01T00:00:00.000Z'));
174
-
175
- expect(getTransactionInfo).toHaveBeenCalledWith('trx-20');
176
- expect(handler).toHaveBeenCalledWith(
177
- 'tokens',
178
- 'transfer',
179
- {
180
- symbol: 'TEST',
181
- to: 'target',
182
- quantity: '1.000',
183
- memo: 'memo'
184
- },
185
- 'alice',
186
- expect.objectContaining({ id: 'ssc-mainnet-hive' }),
187
- 20,
188
- 'block-20',
189
- 'block-19',
190
- 'trx-20',
191
- expect.any(Date)
192
- );
193
-
194
- consoleError.mockRestore();
195
- });
196
-
197
- test('onHiveEngine does not fire when tx verification reports contract errors', async () => {
198
- const handler = jest.fn();
199
- jest.spyOn(streamer['hive'], 'getTransactionInfo').mockResolvedValue({
200
- logs: JSON.stringify({
201
- errors: ['boom']
202
- })
203
- } as any);
204
-
205
- streamer.onHiveEngine(handler);
206
-
207
- await streamer.processOperation([
208
- 'custom_json',
209
- {
210
- id: 'ssc-mainnet-hive',
211
- json: JSON.stringify({
212
- contractName: 'tokens',
213
- contractAction: 'transfer',
214
- contractPayload: {
215
- symbol: 'TEST',
216
- to: 'target',
217
- quantity: '1.000',
218
- memo: 'memo'
219
- }
220
- }),
221
- required_auths: ['alice'],
222
- required_posting_auths: []
223
- }
224
- ], 21, 'block-21', 'block-20', 'trx-21', new Date('2025-01-01T00:00:00.000Z'));
225
-
226
- expect(handler).not.toHaveBeenCalled();
227
- });
228
-
229
- test('processTransfer forwards block metadata into adapter', async () => {
230
- const adapter = createMockAdapter();
231
- const processTransferSpy = jest.spyOn(adapter, 'processTransfer');
232
- await streamer.registerAdapter(adapter);
233
- await streamer.registerContract(defineContract({
234
- name: 'sample',
235
- actions: {
236
- pay: action(jest.fn(), { trigger: 'transfer' })
237
- }
238
- }));
239
-
240
- await streamer.processOperation([
241
- 'transfer',
242
- {
243
- from: 'alice',
244
- to: 'bob',
245
- amount: '1.000 HIVE',
246
- memo: JSON.stringify({
247
- hive_stream: {
248
- contract: 'sample',
249
- action: 'pay',
250
- payload: { value: 1 }
251
- }
252
- })
253
- }
254
- ], 55, 'block-55', 'block-54', 'trx-55', new Date('2025-01-01T00:00:00.000Z'));
255
-
256
- expect(processTransferSpy).toHaveBeenCalledWith(
257
- expect.anything(),
258
- expect.anything(),
259
- expect.objectContaining({
260
- blockNumber: 55,
261
- blockId: 'block-55',
262
- previousBlockId: 'block-54',
263
- transactionId: 'trx-55'
264
- })
265
- );
266
- });
267
-
268
- test('escrow transfer can trigger a contract action via json_meta payload', async () => {
269
- const handler = jest.fn();
270
- const escrowSub = jest.fn();
271
-
272
- await streamer.registerContract(defineContract({
273
- name: 'escrowcontract',
274
- actions: {
275
- create: action(handler, { trigger: 'escrow_transfer' })
276
- }
277
- }));
278
-
279
- streamer.onEscrowTransfer(escrowSub);
280
-
281
- await streamer.processOperation([
282
- 'escrow_transfer',
283
- {
284
- from: 'alice',
285
- to: 'bob',
286
- agent: 'escrow.agent',
287
- escrow_id: 99,
288
- hive_amount: '1.000 HIVE',
289
- hbd_amount: '0.000 HBD',
290
- fee: '0.001 HIVE',
291
- ratification_deadline: '2025-01-01T00:00:00',
292
- escrow_expiration: '2025-01-02T00:00:00',
293
- json_meta: JSON.stringify({
294
- hive_stream: {
295
- contract: 'escrowcontract',
296
- action: 'create',
297
- payload: {
298
- orderId: 'A-1'
299
- }
300
- }
301
- })
302
- }
303
- ], 100, 'block-100', 'block-99', 'trx-100', new Date('2025-01-01T00:00:00.000Z'));
304
-
305
- expect(handler).toHaveBeenCalledWith(
306
- { orderId: 'A-1' },
307
- expect.objectContaining({
308
- trigger: 'escrow_transfer',
309
- sender: 'alice',
310
- escrow: expect.objectContaining({
311
- type: 'escrow_transfer',
312
- escrowId: 99
313
- })
314
- })
315
- );
316
- expect(escrowSub).toHaveBeenCalledTimes(1);
317
- });
318
- });
319
- });