@leofcoin/workers 1.4.16 → 1.4.18

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @leofcoin/workers
2
2
 
3
+ ## 1.4.18
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix browser build
8
+
9
+ ## 1.4.17
10
+
11
+ ### Patch Changes
12
+
13
+ - Upgrade dependencies
14
+ - Updated dependencies
15
+ - @leofcoin/addresses@1.0.22
16
+ - @leofcoin/lib@1.2.42
17
+ - @leofcoin/messages@1.4.12
18
+ - @leofcoin/utils@1.1.17
19
+
3
20
  ## 1.4.16
4
21
 
5
22
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leofcoin/workers",
3
- "version": "1.4.16",
3
+ "version": "1.4.18",
4
4
  "description": "Workers used in @leofcoin/chain",
5
5
  "type": "module",
6
6
  "private": false,
@@ -13,17 +13,19 @@
13
13
  },
14
14
  "scripts": {
15
15
  "prettier": "prettier src --config ./../../.prettierrc --write",
16
- "test": "echo \"Error: no test specified\" && exit 1"
16
+ "test": "echo \"Error: no test specified\" && exit 1",
17
+ "npm-check-updates": "npx npm-check-updates -i",
18
+ "check-dependencies": "npx depcheck"
17
19
  },
18
20
  "keywords": [],
19
21
  "author": "",
20
22
  "license": "MIT",
21
23
  "dependencies": {
22
- "@leofcoin/addresses": "^1.0.21",
23
- "@leofcoin/lib": "^1.2.41",
24
- "@leofcoin/messages": "^1.4.11",
25
- "@leofcoin/storage": "^3.3.2",
26
- "@leofcoin/utils": "^1.1.16",
24
+ "@leofcoin/addresses": "^1.0.22",
25
+ "@leofcoin/lib": "^1.2.42",
26
+ "@leofcoin/messages": "^1.4.12",
27
+ "@leofcoin/storage": "^3.5.24",
28
+ "@leofcoin/utils": "^1.1.17",
27
29
  "@vandeurenglenn/easy-worker": "^1.0.2"
28
30
  }
29
31
  }
@@ -1,365 +1,364 @@
1
- import { BlockMessage, ContractMessage, TransactionMessage } from '@leofcoin/messages'
2
- import { formatBytes, BigNumber } from '@leofcoin/utils'
3
- import addresses from '@leofcoin/addresses'
4
- import bytecodes from '@leofcoin/lib/bytecodes' assert { type: 'json' }
5
- import EasyWorker from '@vandeurenglenn/easy-worker'
6
- import { nativeToken } from '@leofcoin/addresses'
7
- import { randomUUID } from 'crypto'
8
- import LittlePubSub from '@vandeurenglenn/little-pubsub'
9
- const pubsub = new LittlePubSub()
10
- const worker = new EasyWorker()
11
-
12
- const contractFactoryMessage = bytecodes.contractFactory
13
- const nativeTokenMessage = bytecodes.nativeToken
14
- const nameServiceMessage = bytecodes.nameService
15
- const validatorsMessage = bytecodes.validators
16
-
17
- const latestTransactions = []
18
- let nativeCalls = 0
19
- let nativeBurns = 0
20
- let nativeMints = 0
21
- let nativeTransfers = 0
22
- let totalTransactions = 0
23
-
24
- let totalBurnAmount = 0
25
- let totalMintAmount = 0
26
- let totalTransferAmount = 0
27
-
28
- let blocks = []
29
- let contracts = {}
30
- const _ = {}
31
-
32
- globalThis.BigNumber = BigNumber
33
-
34
- let lastBlock = { index: -1, hash: '0x0', previousHash: '0x0' }
35
-
36
- const debug = (message) => {
37
- worker.postMessage({
38
- type: 'debug',
39
- message
40
- })
41
- }
42
-
43
- const unique = (arr) =>
44
- arr.filter((el, pos, arr) => {
45
- return arr.indexOf(el) == pos
46
- })
47
-
48
- const has = (address) => {
49
- return contracts[address] ? true : false
50
- }
51
-
52
- const get = ({ contract, method, params }) => {
53
- let result
54
- if (params?.length > 0) {
55
- result = contracts[contract][method](...params)
56
- } else {
57
- result = contracts[contract][method]
58
- }
59
- return result
60
- }
61
-
62
- const resolveContract = (address) => askFor('contract', address)
63
-
64
- const respond = (id, value) => {
65
- worker.postMessage({
66
- type: 'response',
67
- value,
68
- id
69
- })
70
- }
71
-
72
- _.runContract = async ({ decoded, hash, encoded }, state) => {
73
- const params = decoded.constructorParameters
74
- try {
75
- const func = new Function(new TextDecoder().decode(decoded.contract))
76
- const Contract = func()
77
-
78
- if (state) params.push(state)
79
-
80
- globalThis.msg = createMessage(decoded.creator, hash)
81
- contracts[hash] = await new Contract(...params)
82
-
83
- debug(`loaded contract: ${hash} size: ${formatBytes(encoded.length)}`)
84
- } catch (e) {
85
- console.log(e)
86
- worker.postMessage({
87
- type: 'contractError',
88
- message: e.message,
89
- hash
90
- })
91
- }
92
- }
93
-
94
- _.execute = async ({ contract, method, params }) => {
95
- try {
96
- let result
97
-
98
- // don't execute the method on a proxy
99
- if (contracts[contract].fallback) {
100
- result = await contracts[contract].fallback(method, params)
101
- } else {
102
- result = await contracts[contract][method](...params)
103
- }
104
- // state.put(result)
105
- return result
106
- } catch (e) {
107
- console.log({ e })
108
- throw new Error(
109
- `error: ${e.message}
110
- contract: ${contract}
111
- method: ${method}
112
- params: ${JSON.stringify(params, null, '\t')}
113
- `
114
- )
115
- }
116
- }
117
-
118
- const createMessage = (sender = globalThis.peerid, contract) => {
119
- return {
120
- contract,
121
- sender,
122
- call: _.execute,
123
- staticCall: get
124
- }
125
- }
126
-
127
- const _executeTransaction = async (transaction) => {
128
- const hash = await new TransactionMessage(transaction).hash()
129
- if (latestTransactions.includes(hash)) {
130
- throw new Error(`double transaction found: ${hash} in block ${block.index}`)
131
- } else {
132
- latestTransactions.push(hash)
133
- const { from, to, method, params, nonce } = transaction
134
- globalThis.msg = createMessage(from)
135
-
136
- await _.execute({ contract: to, method, params })
137
- if (to === nativeToken) {
138
- nativeCalls += 1
139
- if (method === 'burn') nativeBurns += 1
140
- if (method === 'mint') nativeMints += 1
141
- if (method === 'transfer') nativeTransfers += 1
142
- }
143
- totalTransactions += 1
144
-
145
- worker.postMessage({
146
- type: 'transactionLoaded',
147
- result: {
148
- hash,
149
- from,
150
- nonce: String(nonce)
151
- }
152
- })
153
- }
154
- }
155
-
156
- _.init = async (message) => {
157
- let { peerid, fromState, state } = message
158
- globalThis.peerid = peerid
159
- console.log({ fromState })
160
- if (fromState) {
161
- lastBlock = message.lastBlock
162
- const setState = async (address, state) => {
163
- const contractBytes = await resolveContract(address)
164
- const contract = await new ContractMessage(contractBytes)
165
-
166
- await _.runContract({ hash: address, decoded: contract.decoded, encoded: contract.encoded }, state)
167
- }
168
-
169
- const entries = Object.entries(state)
170
- if (entries.length > 0) {
171
- const promises = []
172
- for (const [address, value] of entries) {
173
- promises.push(setState(address, value))
174
- }
175
- await Promise.all(promises)
176
- }
177
-
178
- const promises = []
179
- if (!contracts[addresses.contractFactory]) promises.push(setState(addresses.contractFactory))
180
- if (!contracts[addresses.nameService]) promises.push(setState(addresses.nameService))
181
- if (!contracts[addresses.validators]) promises.push(setState(addresses.validators))
182
- if (!contracts[addresses.nativeToken]) promises.push(setState(addresses.nativeToken))
183
- // contracts = await Promise.all(
184
- // contracts.map(async (contract) => {
185
- // contract = await new ContractMessage(new Uint8Array(contract.split(',')))
186
- // await _.runContract({ decoded: contract.decoded, encoded: contract.encoded, hash: await contract.hash() })
187
- // return contract
188
- // })
189
- // )
190
- await Promise.all(promises)
191
- } else {
192
- await Promise.all(
193
- [contractFactoryMessage, nativeTokenMessage, nameServiceMessage, validatorsMessage].map(async (contract) => {
194
- contract = await new ContractMessage(new Uint8Array(contract.split(',')))
195
- return _.runContract({ decoded: contract.decoded, encoded: contract.encoded, hash: await contract.hash() })
196
- })
197
- )
198
- console.log({ blocks: message.blocks })
199
- if (message.blocks?.length > 0) {
200
- let pre
201
-
202
- try {
203
- const importee = await import('url')
204
- const url = importee.default
205
- if (url) pre = url.fileURLToPath(new URL('.', import.meta.url))
206
- } catch {
207
- // browser env
208
- pre = './'
209
- }
210
-
211
- let _worker = await new EasyWorker(pre + '@leofcoin/workers/block-worker.js', {
212
- serialization: 'advanced',
213
- type: 'module'
214
- })
215
- blocks = await _worker.once(message.blocks)
216
- _worker = null
217
- // blocks = unique(globalThis.blocks ? globalThis : [], blocks)
218
- // for (let i = 0; i < blocks.length; i++) {
219
-
220
- // }
221
- for (const block of blocks) {
222
- // we only revalidate the latest 24 blocks
223
- // every 24 blocks a snapshot is taken and stored in state
224
- // this means contracts will be restored from this state
225
- // this also means devs NEED to make sure the state can be restored
226
- // on contract deploy an error will be thrown if state wasn't recoverable
227
- if (block.index > 24) {
228
- const transactionCount = blocks[block.index - 1].transactions.length
229
- latestTransactions.splice(-(transactionCount - 1), latestTransactions.length)
230
- }
231
-
232
- if (!block.loaded && !fromState) {
233
- const priority = block.transactions.filter((transaction) => transaction.priority)
234
- if (priority.length > 0)
235
- await Promise.all(
236
- priority.sort((a, b) => a.nonce - b.nonce).map((transaction) => _executeTransaction(transaction))
237
- )
238
-
239
- await Promise.all(
240
- block.transactions
241
- .filter((transaction) => !transaction.priority)
242
- .map(async (transaction) => _executeTransaction(transaction))
243
- )
244
- }
245
- block.loaded = true
246
- worker.postMessage({
247
- type: 'debug',
248
- message: `loaded transactions for block: ${block.blockInfo.hash} @${block.blockInfo.index} ${formatBytes(
249
- block.blockInfo.size
250
- )}`
251
- })
252
- }
253
-
254
- if (blocks.length > 0) {
255
- lastBlock = blocks[blocks.length - 1]
256
- }
257
- globalThis.blocks = blocks
258
- }
259
- }
260
-
261
- worker.postMessage({ type: 'machine-ready', lastBlock })
262
-
263
- // worker.postMessage({blocks});
264
- }
265
-
266
- _.addLoadedBlock = (block) => {
267
- blocks[block.index - 1] = block
268
- lastBlock = blocks[blocks.length - 1]
269
- return true
270
- }
271
-
272
- _.loadBlock = (block) => {
273
- // todo validate here and deprecate addLoadedBlock
274
- }
275
-
276
- const askFor = (question, input) =>
277
- new Promise((resolve) => {
278
- const id = randomUUID()
279
- pubsub.subscribe(id, resolve)
280
- worker.postMessage({
281
- type: 'ask',
282
- question,
283
- input,
284
- id
285
- })
286
- })
287
-
288
- const runTask = async (id, taskName, input) => {
289
- try {
290
- const result = await _[taskName](input)
291
- respond(id, result)
292
- } catch (e) {
293
- worker.postMessage({
294
- type: `${taskName}Error`,
295
- message: e.message,
296
- id
297
- })
298
- }
299
- }
300
-
301
- worker.onmessage(({ id, type, input }) => {
302
- if (pubsub.hasSubscribers(id)) {
303
- pubsub.publish(id, input)
304
- return
305
- }
306
- switch (type) {
307
- case 'init':
308
- runTask(id, 'init', input)
309
- break
310
- case 'run':
311
- runTask(id, 'runContract', input)
312
- break
313
- case 'execute':
314
- runTask(id, 'execute', input)
315
- break
316
- case 'addLoadedBlock':
317
- runTask(id, 'addLoadedBlock', input)
318
- break
319
- case 'nativeCalls':
320
- respond(id, nativeCalls)
321
- break
322
- case 'contracts':
323
- respond(id, contracts)
324
- break
325
- case 'nativeMints':
326
- respond(id, nativeMints)
327
- break
328
- case 'nativeBurns':
329
- respond(id, nativeBurns)
330
- break
331
- case 'nativeTransfers':
332
- respond(id, nativeTransfers)
333
- break
334
- case 'totalTransfers':
335
- respond(id, totalTransfers)
336
- break
337
- case 'totalBlocks':
338
- respond(id, blocks.length)
339
- break
340
- case 'blocks':
341
- respond(id, input ? blocks.slice(input.from, input.to) : blocks)
342
- break
343
- case 'block':
344
- respond(id, blocks[input - 1])
345
- break
346
- case 'lastBlock':
347
- respond(id, lastBlock)
348
- break
349
- case 'latestTransactions':
350
- respond(id, latestTransactions)
351
- break
352
- case 'totalTransactions':
353
- respond(id, totalTransactions)
354
- break
355
- case 'has':
356
- respond(id, has(input.address))
357
- break
358
- case 'get':
359
- respond(id, get(input))
360
- break
361
- default:
362
- console.log(`machine-worker: unsupported taskType: ${type}`)
363
- break
364
- }
365
- })
1
+ import { BlockMessage, ContractMessage, TransactionMessage } from '@leofcoin/messages'
2
+ import { formatBytes, BigNumber } from '@leofcoin/utils'
3
+ import addresses from '@leofcoin/addresses'
4
+ import bytecodes from '@leofcoin/lib/bytecodes' assert { type: 'json' }
5
+ import EasyWorker from '@vandeurenglenn/easy-worker'
6
+ import { nativeToken } from '@leofcoin/addresses'
7
+ import LittlePubSub from '@vandeurenglenn/little-pubsub'
8
+ const pubsub = new LittlePubSub()
9
+ const worker = new EasyWorker()
10
+
11
+ const contractFactoryMessage = bytecodes.contractFactory
12
+ const nativeTokenMessage = bytecodes.nativeToken
13
+ const nameServiceMessage = bytecodes.nameService
14
+ const validatorsMessage = bytecodes.validators
15
+
16
+ const latestTransactions = []
17
+ let nativeCalls = 0
18
+ let nativeBurns = 0
19
+ let nativeMints = 0
20
+ let nativeTransfers = 0
21
+ let totalTransactions = 0
22
+
23
+ let totalBurnAmount = 0
24
+ let totalMintAmount = 0
25
+ let totalTransferAmount = 0
26
+
27
+ let blocks = []
28
+ let contracts = {}
29
+ const _ = {}
30
+
31
+ globalThis.BigNumber = BigNumber
32
+
33
+ let lastBlock = { index: -1, hash: '0x0', previousHash: '0x0' }
34
+
35
+ const debug = (message) => {
36
+ worker.postMessage({
37
+ type: 'debug',
38
+ message
39
+ })
40
+ }
41
+
42
+ const unique = (arr) =>
43
+ arr.filter((el, pos, arr) => {
44
+ return arr.indexOf(el) == pos
45
+ })
46
+
47
+ const has = (address) => {
48
+ return contracts[address] ? true : false
49
+ }
50
+
51
+ const get = ({ contract, method, params }) => {
52
+ let result
53
+ if (params?.length > 0) {
54
+ result = contracts[contract][method](...params)
55
+ } else {
56
+ result = contracts[contract][method]
57
+ }
58
+ return result
59
+ }
60
+
61
+ const resolveContract = (address) => askFor('contract', address)
62
+
63
+ const respond = (id, value) => {
64
+ worker.postMessage({
65
+ type: 'response',
66
+ value,
67
+ id
68
+ })
69
+ }
70
+
71
+ _.runContract = async ({ decoded, hash, encoded }, state) => {
72
+ const params = decoded.constructorParameters
73
+ try {
74
+ const func = new Function(new TextDecoder().decode(decoded.contract))
75
+ const Contract = func()
76
+
77
+ if (state) params.push(state)
78
+
79
+ globalThis.msg = createMessage(decoded.creator, hash)
80
+ contracts[hash] = await new Contract(...params)
81
+
82
+ debug(`loaded contract: ${hash} size: ${formatBytes(encoded.length)}`)
83
+ } catch (e) {
84
+ console.log(e)
85
+ worker.postMessage({
86
+ type: 'contractError',
87
+ message: e.message,
88
+ hash
89
+ })
90
+ }
91
+ }
92
+
93
+ _.execute = async ({ contract, method, params }) => {
94
+ try {
95
+ let result
96
+
97
+ // don't execute the method on a proxy
98
+ if (contracts[contract].fallback) {
99
+ result = await contracts[contract].fallback(method, params)
100
+ } else {
101
+ result = await contracts[contract][method](...params)
102
+ }
103
+ // state.put(result)
104
+ return result
105
+ } catch (e) {
106
+ console.log({ e })
107
+ throw new Error(
108
+ `error: ${e.message}
109
+ contract: ${contract}
110
+ method: ${method}
111
+ params: ${JSON.stringify(params, null, '\t')}
112
+ `
113
+ )
114
+ }
115
+ }
116
+
117
+ const createMessage = (sender = globalThis.peerid, contract) => {
118
+ return {
119
+ contract,
120
+ sender,
121
+ call: _.execute,
122
+ staticCall: get
123
+ }
124
+ }
125
+
126
+ const _executeTransaction = async (transaction) => {
127
+ const hash = await new TransactionMessage(transaction).hash()
128
+ if (latestTransactions.includes(hash)) {
129
+ throw new Error(`double transaction found: ${hash} in block ${block.index}`)
130
+ } else {
131
+ latestTransactions.push(hash)
132
+ const { from, to, method, params, nonce } = transaction
133
+ globalThis.msg = createMessage(from)
134
+
135
+ await _.execute({ contract: to, method, params })
136
+ if (to === nativeToken) {
137
+ nativeCalls += 1
138
+ if (method === 'burn') nativeBurns += 1
139
+ if (method === 'mint') nativeMints += 1
140
+ if (method === 'transfer') nativeTransfers += 1
141
+ }
142
+ totalTransactions += 1
143
+
144
+ worker.postMessage({
145
+ type: 'transactionLoaded',
146
+ result: {
147
+ hash,
148
+ from,
149
+ nonce: String(nonce)
150
+ }
151
+ })
152
+ }
153
+ }
154
+
155
+ _.init = async (message) => {
156
+ let { peerid, fromState, state } = message
157
+ globalThis.peerid = peerid
158
+ console.log({ fromState })
159
+ if (fromState) {
160
+ lastBlock = message.lastBlock
161
+ const setState = async (address, state) => {
162
+ const contractBytes = await resolveContract(address)
163
+ const contract = await new ContractMessage(contractBytes)
164
+
165
+ await _.runContract({ hash: address, decoded: contract.decoded, encoded: contract.encoded }, state)
166
+ }
167
+
168
+ const entries = Object.entries(state)
169
+ if (entries.length > 0) {
170
+ const promises = []
171
+ for (const [address, value] of entries) {
172
+ promises.push(setState(address, value))
173
+ }
174
+ await Promise.all(promises)
175
+ }
176
+
177
+ const promises = []
178
+ if (!contracts[addresses.contractFactory]) promises.push(setState(addresses.contractFactory))
179
+ if (!contracts[addresses.nameService]) promises.push(setState(addresses.nameService))
180
+ if (!contracts[addresses.validators]) promises.push(setState(addresses.validators))
181
+ if (!contracts[addresses.nativeToken]) promises.push(setState(addresses.nativeToken))
182
+ // contracts = await Promise.all(
183
+ // contracts.map(async (contract) => {
184
+ // contract = await new ContractMessage(new Uint8Array(contract.split(',')))
185
+ // await _.runContract({ decoded: contract.decoded, encoded: contract.encoded, hash: await contract.hash() })
186
+ // return contract
187
+ // })
188
+ // )
189
+ await Promise.all(promises)
190
+ } else {
191
+ await Promise.all(
192
+ [contractFactoryMessage, nativeTokenMessage, nameServiceMessage, validatorsMessage].map(async (contract) => {
193
+ contract = await new ContractMessage(new Uint8Array(contract.split(',')))
194
+ return _.runContract({ decoded: contract.decoded, encoded: contract.encoded, hash: await contract.hash() })
195
+ })
196
+ )
197
+ console.log({ blocks: message.blocks })
198
+ if (message.blocks?.length > 0) {
199
+ let pre
200
+
201
+ try {
202
+ const importee = await import('url')
203
+ const url = importee.default
204
+ if (url) pre = url.fileURLToPath(new URL('.', import.meta.url))
205
+ } catch {
206
+ // browser env
207
+ pre = './'
208
+ }
209
+
210
+ let _worker = await new EasyWorker(pre + '@leofcoin/workers/block-worker.js', {
211
+ serialization: 'advanced',
212
+ type: 'module'
213
+ })
214
+ blocks = await _worker.once(message.blocks)
215
+ _worker = null
216
+ // blocks = unique(globalThis.blocks ? globalThis : [], blocks)
217
+ // for (let i = 0; i < blocks.length; i++) {
218
+
219
+ // }
220
+ for (const block of blocks) {
221
+ // we only revalidate the latest 24 blocks
222
+ // every 24 blocks a snapshot is taken and stored in state
223
+ // this means contracts will be restored from this state
224
+ // this also means devs NEED to make sure the state can be restored
225
+ // on contract deploy an error will be thrown if state wasn't recoverable
226
+ if (block.index > 24) {
227
+ const transactionCount = blocks[block.index - 1].transactions.length
228
+ latestTransactions.splice(-(transactionCount - 1), latestTransactions.length)
229
+ }
230
+
231
+ if (!block.loaded && !fromState) {
232
+ const priority = block.transactions.filter((transaction) => transaction.priority)
233
+ if (priority.length > 0)
234
+ await Promise.all(
235
+ priority.sort((a, b) => a.nonce - b.nonce).map((transaction) => _executeTransaction(transaction))
236
+ )
237
+
238
+ await Promise.all(
239
+ block.transactions
240
+ .filter((transaction) => !transaction.priority)
241
+ .map(async (transaction) => _executeTransaction(transaction))
242
+ )
243
+ }
244
+ block.loaded = true
245
+ worker.postMessage({
246
+ type: 'debug',
247
+ message: `loaded transactions for block: ${block.blockInfo.hash} @${block.blockInfo.index} ${formatBytes(
248
+ block.blockInfo.size
249
+ )}`
250
+ })
251
+ }
252
+
253
+ if (blocks.length > 0) {
254
+ lastBlock = blocks[blocks.length - 1]
255
+ }
256
+ globalThis.blocks = blocks
257
+ }
258
+ }
259
+
260
+ worker.postMessage({ type: 'machine-ready', lastBlock })
261
+
262
+ // worker.postMessage({blocks});
263
+ }
264
+
265
+ _.addLoadedBlock = (block) => {
266
+ blocks[block.index - 1] = block
267
+ lastBlock = blocks[blocks.length - 1]
268
+ return true
269
+ }
270
+
271
+ _.loadBlock = (block) => {
272
+ // todo validate here and deprecate addLoadedBlock
273
+ }
274
+
275
+ const askFor = (question, input) =>
276
+ new Promise((resolve) => {
277
+ const id = globalThis.crypto.randomUUID()
278
+ pubsub.subscribe(id, resolve)
279
+ worker.postMessage({
280
+ type: 'ask',
281
+ question,
282
+ input,
283
+ id
284
+ })
285
+ })
286
+
287
+ const runTask = async (id, taskName, input) => {
288
+ try {
289
+ const result = await _[taskName](input)
290
+ respond(id, result)
291
+ } catch (e) {
292
+ worker.postMessage({
293
+ type: `${taskName}Error`,
294
+ message: e.message,
295
+ id
296
+ })
297
+ }
298
+ }
299
+
300
+ worker.onmessage(({ id, type, input }) => {
301
+ if (pubsub.hasSubscribers(id)) {
302
+ pubsub.publish(id, input)
303
+ return
304
+ }
305
+ switch (type) {
306
+ case 'init':
307
+ runTask(id, 'init', input)
308
+ break
309
+ case 'run':
310
+ runTask(id, 'runContract', input)
311
+ break
312
+ case 'execute':
313
+ runTask(id, 'execute', input)
314
+ break
315
+ case 'addLoadedBlock':
316
+ runTask(id, 'addLoadedBlock', input)
317
+ break
318
+ case 'nativeCalls':
319
+ respond(id, nativeCalls)
320
+ break
321
+ case 'contracts':
322
+ respond(id, contracts)
323
+ break
324
+ case 'nativeMints':
325
+ respond(id, nativeMints)
326
+ break
327
+ case 'nativeBurns':
328
+ respond(id, nativeBurns)
329
+ break
330
+ case 'nativeTransfers':
331
+ respond(id, nativeTransfers)
332
+ break
333
+ case 'totalTransfers':
334
+ respond(id, totalTransfers)
335
+ break
336
+ case 'totalBlocks':
337
+ respond(id, blocks.length)
338
+ break
339
+ case 'blocks':
340
+ respond(id, input ? blocks.slice(input.from, input.to) : blocks)
341
+ break
342
+ case 'block':
343
+ respond(id, blocks[input - 1])
344
+ break
345
+ case 'lastBlock':
346
+ respond(id, lastBlock)
347
+ break
348
+ case 'latestTransactions':
349
+ respond(id, latestTransactions)
350
+ break
351
+ case 'totalTransactions':
352
+ respond(id, totalTransactions)
353
+ break
354
+ case 'has':
355
+ respond(id, has(input.address))
356
+ break
357
+ case 'get':
358
+ respond(id, get(input))
359
+ break
360
+ default:
361
+ console.log(`machine-worker: unsupported taskType: ${type}`)
362
+ break
363
+ }
364
+ })