@leofcoin/chain 1.3.1 → 1.3.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 (48) hide show
  1. package/demo/chain.browser.js +17 -13
  2. package/demo/peernet-swarm.browser.js +8 -9
  3. package/demo/workers/machine-worker.js +30 -11
  4. package/dist/browser/workers/machine-worker.js +18 -12
  5. package/dist/chain.js +149 -134
  6. package/dist/contracts/factory.js +1 -1
  7. package/dist/contracts/{nameService.js → name-service.js} +1 -1
  8. package/dist/contracts/native-token.js +1 -0
  9. package/dist/contracts/validators.js +1 -1
  10. package/dist/module/chain.js +146 -131
  11. package/dist/module/workers/machine-worker.js +18 -12
  12. package/dist/standards/token.js +1 -1
  13. package/dist/workers/machine-worker.js +1 -1
  14. package/package.json +20 -2
  15. package/rollup.config.js +4 -4
  16. package/src/chain.js +112 -102
  17. package/src/contracts/factory.js +58 -15
  18. package/src/contracts/{nameService.js → name-service.js} +3 -5
  19. package/src/contracts/{nativeToken.js → native-token.js} +2 -2
  20. package/src/contracts/{powerToken.js → power-token.js} +1 -1
  21. package/src/contracts/proxies/{factoryProxy.js → factory-proxy.js} +1 -1
  22. package/src/contracts/proxies/{nameServiceProxy.js → name-service-proxy.js} +1 -1
  23. package/src/contracts/proxies/{nativeTokenProxy.js → native-token-proxy.js} +1 -1
  24. package/src/contracts/proxies/{validatorsProxy.js → validators-proxy.js} +1 -1
  25. package/src/contracts/proxies/{votingProxy.js → voting-proxy.js} +1 -1
  26. package/src/contracts/{proxyManager.js → proxy-manager.js} +1 -1
  27. package/src/contracts/validators.js +35 -25
  28. package/src/fee/config.js +1 -1
  29. package/src/machine.js +34 -29
  30. package/src/standards/{proxyManager.js → proxy-manager.js} +0 -0
  31. package/src/standards/{Proxy.js → proxy.js} +4 -8
  32. package/src/standards/roles.js +7 -5
  33. package/src/standards/voting.js +1 -0
  34. package/src/transactions/transaction.js +1 -3
  35. package/src/transactions/validator.js +1 -1
  36. package/src/typer.js +1 -1
  37. package/dist/865.browser.js +0 -10
  38. package/dist/chain.browser.js +0 -59741
  39. package/dist/contracts/nativeToken.js +0 -1
  40. package/dist/generate-account.browser.js +0 -50
  41. package/dist/messages.browser.js +0 -328
  42. package/dist/multi-wallet.browser.js +0 -15
  43. package/dist/node.browser.js +0 -9858
  44. package/dist/pako.browser.js +0 -6900
  45. package/dist/peernet-swarm.browser.js +0 -840
  46. package/dist/storage.browser.js +0 -3724
  47. package/dist/wrtc.browser.js +0 -28
  48. package/src/standards/Voting.js +0 -3
package/src/chain.js CHANGED
@@ -16,8 +16,10 @@ export default class Chain {
16
16
  #blocks = []
17
17
  #machine
18
18
  #runningEpoch = false
19
+ #chainSyncing = false
19
20
  #lastBlock = {index: 0, hash: '0x0', previousHash: '0x0'}
20
-
21
+ #participants = []
22
+ #participating = false
21
23
  #jail = []
22
24
 
23
25
  constructor() {
@@ -57,14 +59,14 @@ export default class Chain {
57
59
  console.log(validators);
58
60
  if (!validators[peernet.selectedAccount]?.active) return
59
61
 
60
- const start = new Date().getTime()
62
+ const start = Date.now()
61
63
  try {
62
64
  await this.#createBlock()
63
- } catch (e) {
64
- console.error(e);
65
+ } catch (error) {
66
+ console.error(error);
65
67
  }
66
68
 
67
- const end = new Date().getTime()
69
+ const end = Date.now()
68
70
  console.log(((end - start) / 1000) + ' s');
69
71
 
70
72
  if (await this.hasTransactionToHandle()) return this.#runEpoch()
@@ -101,7 +103,7 @@ export default class Chain {
101
103
  const timeout = setTimeout(() => {
102
104
  resolve([{index: 0, hash: '0x0'}])
103
105
  debug('sync timed out')
104
- }, 10000)
106
+ }, 10_000)
105
107
 
106
108
  promises = await Promise.allSettled(promises);
107
109
  promises = promises.filter(({status}) => status === 'fulfilled')
@@ -115,11 +117,11 @@ export default class Chain {
115
117
 
116
118
  }
117
119
 
118
- sync() {
119
- return this.#sync()
120
+ getLatestBlock() {
121
+ return this.#getLatestBlock()
120
122
  }
121
123
 
122
- async #sync() {
124
+ async #getLatestBlock() {
123
125
  let promises = [];
124
126
 
125
127
  let data = await new peernet.protos['peernet-request']({request: 'lastBlock'});
@@ -134,37 +136,38 @@ export default class Chain {
134
136
  }
135
137
  }
136
138
  promises = await this.promiseRequests(promises)
137
- promises = promises.reduce((set, value) => {
138
-
139
- if (value.index > set.index) {
140
- set.index = value.index;
141
- set.hash = value.hash;
142
- }
143
- return set
144
- }, {index: 0, hash: '0x0'});
145
- // get lastblock
146
- if (promises.hash && promises.hash !== '0x0') {
147
- let localBlock = await peernet.get(promises.hash)
139
+ let latest = {index: 0, hash: '0x0'}
140
+
141
+ for (const value of promises) {
142
+ if (value.index > latest.index) {
143
+ latest.index = value.index;
144
+ latest.hash = value.hash;
148
145
  }
149
-
150
-
146
+ }
147
+
148
+ if (latest.hash && latest.hash !== '0x0') {
149
+ let latestBlock = await peernet.get(latest.hash, block)
150
+ latestBlock = await new BlockMessage(latestBlock)
151
+ }
152
+
153
+ return latestBlock
151
154
  }
152
155
 
153
156
  async #init() {
154
157
  // this.node = await new Node()
155
- this.participants = []
156
- this.participating = false
158
+ this.#participants = []
159
+ this.#participating = false
157
160
  const initialized = await contractStore.has(addresses.contractFactory)
158
161
  if (!initialized) await this.#setup()
159
162
 
160
- this.#machine = await new Machine()
163
+
161
164
  this.utils = { BigNumber, formatUnits, parseUnits }
162
165
 
163
166
  try {
164
167
  let localBlock
165
168
  try {
166
169
  localBlock = await chainStore.get('lastBlock')
167
- } catch(e) {
170
+ } catch{
168
171
  await chainStore.put('lastBlock', '0x0')
169
172
  localBlock = await chainStore.get('lastBlock')
170
173
  }
@@ -174,13 +177,11 @@ export default class Chain {
174
177
  localBlock = await new BlockMessage(localBlock)
175
178
  this.#lastBlock = {...localBlock.decoded, hash: await localBlock.hash}
176
179
  } else {
177
- await this.#sync()
180
+ const latestBlock = await this.#getLatestBlock()
181
+ await this.#syncChain(latestBlock)
178
182
  }
179
- } catch (e) {
180
- console.log({e});
181
-
182
-
183
- // this.#setup()
183
+ } catch (error) {
184
+ console.log({e: error});
184
185
  }
185
186
 
186
187
  await peernet.addRequestHandler('bw-request-message', () => {
@@ -201,6 +202,8 @@ export default class Chain {
201
202
 
202
203
  // load local blocks
203
204
  await this.resolveBlocks()
205
+ this.#machine = await new Machine(this.#blocks)
206
+ await this.#loadBlocks(this.#blocks)
204
207
  return this
205
208
  }
206
209
 
@@ -211,29 +214,33 @@ export default class Chain {
211
214
  this.#jail.push(validatorInfo.address)
212
215
  }
213
216
 
214
- async #peerConnected(peer) {
215
- let node = await new peernet.protos['peernet-request']({request: 'lastBlock'})
216
- node = await peernet.prepareMessage(node)
217
- let response = await peer.request(node.encoded)
218
- response = await new globalThis.peernet.protos['peernet-response'](response)
219
- let lastBlock = response.decoded.response
217
+ async #syncChain(lastBlock) {
218
+ if (this.#chainSyncing) return
220
219
 
221
220
  if (!this.lastBlock || Number(this.lastBlock.index) < Number(lastBlock.index)) {
222
- // TODO: check if valid
221
+ this.#chainSyncing = true
222
+ // TODO: check if valid
223
223
  const localIndex = this.lastBlock ? this.lastBlock.index : 0
224
224
  const index = lastBlock.index
225
225
  await this.resolveBlock(lastBlock.hash)
226
- let blocksSynced = localIndex > 0 ? localIndex > index ? localIndex - index : index - localIndex : index
226
+ let blocksSynced = localIndex > 0 ? (localIndex > index ? localIndex - index : index - localIndex) : index
227
227
  debug(`synced ${blocksSynced} ${blocksSynced > 1 ? 'blocks' : 'block'}`)
228
228
 
229
229
  const end = this.#blocks.length
230
- const start = (this.#blocks.length) - blocksSynced
231
- await this.#loadBlocks(this.#blocks)
232
- this.#lastBlock = this.#blocks[this.#blocks.length - 1]
233
- const message = await new BlockMessage(this.lastBlock)
234
- await blockStore.put(await message.hash, message.encoded)
235
- await chainStore.put('lastBlock', this.lastBlock.hash)
230
+ const start = this.#blocks.length - blocksSynced
231
+ await this.#loadBlocks(this.blocks.slice(start))
232
+ await this.#updateState(this.#blocks[this.#blocks.length - 1])
233
+ this.#chainSyncing = false
236
234
  }
235
+ }
236
+
237
+ async #peerConnected(peer) {
238
+ let node = await new peernet.protos['peernet-request']({request: 'lastBlock'})
239
+ node = await peernet.prepareMessage(node)
240
+ let response = await peer.request(node.encoded)
241
+ response = await new globalThis.peernet.protos['peernet-response'](response)
242
+ let lastBlock = response.decoded.response
243
+ this.#syncChain(lastBlock)
237
244
  }
238
245
 
239
246
  #epochTimeout
@@ -243,9 +250,9 @@ export default class Chain {
243
250
  transaction = await new TransactionMessage(transaction)
244
251
  const has = await transactionPoolStore.has(await transaction.hash)
245
252
  if (!has) await transactionPoolStore.put(await transaction.hash, transaction.encoded)
246
- if (this.participating && !this.#runningEpoch) this.#runEpoch()
247
- } catch (e) {
248
- throw Error('invalid transaction')
253
+ if (this.#participating && !this.#runningEpoch) this.#runEpoch()
254
+ } catch {
255
+ throw new Error('invalid transaction')
249
256
  }
250
257
  }
251
258
 
@@ -258,11 +265,11 @@ async resolveBlock(hash) {
258
265
  let block = await peernet.get(hash, 'block')
259
266
  block = await new BlockMessage(block)
260
267
  if (!await peernet.has(hash, 'block')) await peernet.put(hash, block.encoded, 'block')
261
- const size = block.encoded.length || block.encoded.byteLength
268
+ const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength
262
269
  block = {...block.decoded, hash}
263
- if (this.#blocks[block.index]) throw `invalid block ${hash} @${block.index}`
270
+ if (this.#blocks[block.index] && this.#blocks[block.index].hash !== block.hash) throw `invalid block ${hash} @${block.index}`
264
271
  this.#blocks[block.index] = block
265
- console.log(`loaded block: ${hash} @${block.index} ${formatBytes(size)}`);
272
+ console.log(`resolved block: ${hash} @${block.index} ${formatBytes(size)}`);
266
273
  if (block.previousHash !== '0x0') {
267
274
  return this.resolveBlock(block.previousHash)
268
275
  }
@@ -276,8 +283,8 @@ async resolveBlock(hash) {
276
283
  if (hash && hash !== '0x0')
277
284
  await this.resolveBlock(hash)
278
285
  this.#lastBlock = this.#blocks[this.#blocks.length - 1]
279
- await this.#loadBlocks(this.#blocks)
280
- } catch (e) {
286
+
287
+ } catch {
281
288
  await chainStore.put('lastBlock', new TextEncoder().encode('0x0'))
282
289
  return this.resolveBlocks()
283
290
  // console.log(e);
@@ -291,11 +298,12 @@ async resolveBlock(hash) {
291
298
  try {
292
299
  await this.#machine.execute(transaction.to, transaction.method, transaction.params)
293
300
 
294
- } catch (e) {
295
- console.log(e);
301
+ } catch (error) {
302
+ console.log(error);
296
303
  }
297
304
  }
298
- block.loaded = true
305
+ this.#blocks[block.index].loaded = true
306
+ console.log(`loaded block: ${block.hash} @${block.index}`);
299
307
  // let message = await peernet.get(block.hash, 'block')
300
308
 
301
309
  // const compressed = pako.deflate(message);
@@ -323,10 +331,10 @@ async resolveBlock(hash) {
323
331
  let result = await this.#machine.execute(to, method, params, from, nonce)
324
332
  // if (!result) result = this.#machine.state
325
333
  pubsub.publish(`transaction.completed.${hash}`, {status: 'fulfilled', hash})
326
- return result ? result : 'no state change'
327
- } catch (e) {
328
- pubsub.publish(`transaction.completed.${hash}`, {status: 'fail', hash, error: e})
329
- throw e
334
+ return result || 'no state change'
335
+ } catch (error) {
336
+ pubsub.publish(`transaction.completed.${hash}`, {status: 'fail', hash, error: error})
337
+ throw error
330
338
  }
331
339
  }
332
340
 
@@ -347,8 +355,6 @@ async resolveBlock(hash) {
347
355
  // transaction = new TransactionMessage(transaction)
348
356
  // return transaction
349
357
  // }
350
-
351
- console.log(blockMessage);
352
358
  const deletions = await Promise.all(blockMessage.decoded.transactions
353
359
  .map(async transaction => transactionPoolStore.delete(await transaction.hash)))
354
360
  const hash = await blockMessage.hash
@@ -365,11 +371,15 @@ async resolveBlock(hash) {
365
371
  // await transactionStore.put(transaction.hash, transaction.encoded)
366
372
  const index = contracts.indexOf(transaction.to)
367
373
  if (index === -1) contracts.push(transaction.to)
374
+ // Todo: go trough all accounts
368
375
  promises.push(this.#executeTransaction(transaction))
376
+
369
377
  }
370
378
  try {
371
379
  promises = await Promise.allSettled(promises)
372
380
  for (let transaction of blockMessage.decoded.transactions) {
381
+ pubsub.publish('transaction-processed', transaction)
382
+ if (transaction.to === peernet.selectedAccount) pubsub.publish('account-transaction-processed', transaction)
373
383
  await accountsStore.put(transaction.from, String(transaction.nonce))
374
384
  }
375
385
 
@@ -382,8 +392,9 @@ async resolveBlock(hash) {
382
392
 
383
393
 
384
394
  pubsub.publish('block-processed', blockMessage.decoded)
385
- } catch (e) {
386
- console.log({e});
395
+
396
+ } catch (error) {
397
+ console.log({e: error});
387
398
  }
388
399
 
389
400
  }
@@ -403,7 +414,7 @@ async resolveBlock(hash) {
403
414
  // introduce peer-reputation
404
415
  // peerReputation(peerId)
405
416
  // {bandwith: {up, down}, uptime}
406
- this.participating = true
417
+ this.#participating = true
407
418
  if (!await this.staticCall(addresses.validators, 'has', [address])) await this.createTransactionFrom(address, addresses.validators, 'addValidator', [address])
408
419
  if (await this.hasTransactionToHandle() && !this.#runningEpoch) await this.#runEpoch()
409
420
 
@@ -465,7 +476,7 @@ async resolveBlock(hash) {
465
476
  block.transactions.push(transaction)
466
477
  block.fees += Number(calculateFee(transaction))
467
478
  await accountsStore.put(transaction.from, new TextEncoder().encode(String(transaction.nonce)))
468
- } catch (e) {
479
+ } catch {
469
480
  transaction = await new TransactionMessage(transaction)
470
481
  await transactionPoolStore.delete(await transaction.hash)
471
482
  }
@@ -498,9 +509,7 @@ async resolveBlock(hash) {
498
509
  address: validator,
499
510
  bw: bw.up + bw.down
500
511
  })
501
- } catch(e) {
502
-
503
- }
512
+ } catch{}
504
513
 
505
514
  } else if (peernet.selectedAccount === validator) {
506
515
  block.validators.push({
@@ -528,17 +537,17 @@ async resolveBlock(hash) {
528
537
  else block.index += 1
529
538
 
530
539
  block.previousHash = this.lastBlock?.hash || '0x0'
531
- block.timestamp = new Date().getTime()
540
+ block.timestamp = Date.now()
532
541
 
533
542
  const parts = String(block.fees).split('.')
534
543
  let decimals = 0
535
544
  if (parts[1]) {
536
545
  const potentional = parts[1].split('e')
537
- if (potentional[0] !== parts[1]) {
538
- parts[1] = potentional[0]
539
- decimals = Number(potentional[1]?.replace(/\-|\+/g, '')) + Number(potentional[0].length)
540
- } else {
546
+ if (potentional[0] === parts[1]) {
541
547
  decimals = parts[1].length
548
+ } else {
549
+ parts[1] = potentional[0]
550
+ decimals = Number(potentional[1]?.replace(/[+-]/g, '')) + Number(potentional[0].length)
542
551
  }
543
552
 
544
553
  }
@@ -558,9 +567,10 @@ async resolveBlock(hash) {
558
567
  debug(`created block: ${hash}`)
559
568
 
560
569
  peernet.publish('add-block', blockMessage.encoded)
561
- } catch (e) {
562
- console.log(e);
563
- throw Error(`invalid block ${block}`)
570
+ pubsub.publish('add-block', blockMessage.decoded)
571
+ } catch (error) {
572
+ console.log(error);
573
+ throw new Error(`invalid block ${block}`)
564
574
  }
565
575
  // data = await this.#machine.execute(to, method, params)
566
576
  // transactionStore.put(message.hash, message.encoded)
@@ -629,8 +639,8 @@ async resolveBlock(hash) {
629
639
  * @param {Array} params - array of paramters to apply to the contract method
630
640
  * @param {Number} nonce - total transaction count [optional]
631
641
  */
632
- async createTransaction(to, method, params, nonce, signature) {
633
- return this.createTransactionFrom(peernet.selectedAccount, to, method, params, nonce)
642
+ async createTransaction(to, method, parameters, nonce, signature) {
643
+ return this.createTransactionFrom(peernet.selectedAccount, to, method, parameters, nonce)
634
644
  }
635
645
 
636
646
 
@@ -690,8 +700,8 @@ async #signTransaction (transaction, wallet) {
690
700
  } else {
691
701
  let nonce = await accountsStore.get(transaction.from)
692
702
  nonce = new TextDecoder().decode(nonce)
693
- if (transaction.nonce < nonce) throw Error(`a transaction with a higher nonce already exists`)
694
- if (transaction.nonce === nonce) throw Error(`a transaction with the same nonce already exists`)
703
+ if (transaction.nonce < nonce) throw new Error(`a transaction with a higher nonce already exists`)
704
+ if (transaction.nonce === nonce) throw new Error(`a transaction with the same nonce already exists`)
695
705
  }
696
706
  return transaction
697
707
  }
@@ -706,10 +716,10 @@ async #signTransaction (transaction, wallet) {
706
716
  * @param {Array} params - array of paramters to apply to the contract method
707
717
  * @param {Number} nonce - total transaction count [optional]
708
718
  */
709
- async createTransactionFrom(from, to, method, params, nonce) {
719
+ async createTransactionFrom(from, to, method, parameters, nonce) {
710
720
  try {
711
721
 
712
- const rawTransaction = await this.createRawTransaction({from, to, nonce, method, params})
722
+ const rawTransaction = await this.createRawTransaction({from, to, nonce, method, params: parameters})
713
723
  const transaction = await this.signTransaction(rawTransaction, from)
714
724
  const message = await new TransactionMessage(transaction)
715
725
 
@@ -725,7 +735,7 @@ async #signTransaction (transaction, wallet) {
725
735
 
726
736
  setTimeout(async () => {
727
737
  pubsub.unsubscribe(`transaction.completed.${await message.hash}`, completed)
728
- }, 10000)
738
+ }, 10_000)
729
739
  }
730
740
  pubsub.subscribe(`transaction.completed.${await message.hash}`, completed)
731
741
  }
@@ -737,9 +747,9 @@ async #signTransaction (transaction, wallet) {
737
747
  peernet.publish('add-transaction', message.encoded)
738
748
  this.#addTransaction(message.encoded)
739
749
  return {hash: await message.hash, data, fee: await calculateFee(message.decoded), wait}
740
- } catch (e) {
741
- console.log(e)
742
- throw e
750
+ } catch (error) {
751
+ console.log(error)
752
+ throw error
743
753
  }
744
754
 
745
755
  }
@@ -757,15 +767,15 @@ async #signTransaction (transaction, wallet) {
757
767
  *
758
768
  * @param {String} contract - a contract string (see plugins/deployContract)
759
769
  */
760
- async deployContract(contract, params = []) {
770
+ async deployContract(contract, parameters = []) {
761
771
  globalThis.msg = {sender: peernet.selectedAccount, call: this.call}
762
772
 
763
- const hash = await this.createContractAddress(creator, contract, params)
773
+ const hash = await this.createContractAddress(creator, contract, parameters)
764
774
  console.log(hash);
765
775
  try {
766
776
  const tx = await this.createTransactionFrom(peernet.selectedAccount, addresses.contractFactory, 'deployContract', [hash, creator, contract, constructorParameters])
767
- } catch (e) {
768
- throw e
777
+ } catch (error) {
778
+ throw error
769
779
  }
770
780
  return this.#machine.addContract(message)
771
781
  }
@@ -780,33 +790,33 @@ console.log(hash);
780
790
  }
781
791
  }
782
792
 
783
- internalCall(sender, contract, method, params) {
793
+ internalCall(sender, contract, method, parameters) {
784
794
  globalThis.msg = this.#createMessage(sender)
785
795
 
786
- return this.#machine.execute(contract, method, params)
796
+ return this.#machine.execute(contract, method, parameters)
787
797
  }
788
798
 
789
- call(contract, method, params) {
799
+ call(contract, method, parameters) {
790
800
  globalThis.msg = this.#createMessage()
791
801
 
792
- return this.#machine.execute(contract, method, params)
802
+ return this.#machine.execute(contract, method, parameters)
793
803
  }
794
804
 
795
- staticCall(contract, method, params) {
805
+ staticCall(contract, method, parameters) {
796
806
  globalThis.msg = this.#createMessage()
797
- return this.#machine.get(contract, method, params)
807
+ return this.#machine.get(contract, method, parameters)
798
808
  }
799
809
 
800
- delegate(contract, method, params) {
810
+ delegate(contract, method, parameters) {
801
811
  globalThis.msg = this.#createMessage()
802
812
 
803
- return this.#machine.execute(contract, method, params)
813
+ return this.#machine.execute(contract, method, parameters)
804
814
  }
805
815
 
806
- staticDelegate(contract, method, params) {
816
+ staticDelegate(contract, method, parameters) {
807
817
  globalThis.msg = this.#createMessage()
808
818
 
809
- return this.#machine.get(contract, method, params)
819
+ return this.#machine.get(contract, method, parameters)
810
820
  }
811
821
 
812
822
  mint(to, amount) {
@@ -12,17 +12,24 @@ export default class Factory {
12
12
  */
13
13
  #contracts = []
14
14
 
15
+ /**
16
+ * Object => address => Array[addresses]
17
+ */
18
+ #implementations = {}
19
+
15
20
  constructor(state) {
16
21
  if (state) {
17
22
  this.#contracts = state.contracts
18
23
  this.#totalContracts = state.totalContracts
24
+ this.#implementations = state.implementations
19
25
  }
20
26
  }
21
27
 
22
28
  get state() {
23
29
  return {
24
30
  totalContracts: this.#totalContracts,
25
- contracts: this.#contracts
31
+ contracts: this.#contracts,
32
+ implementations: this.#implementations
26
33
  }
27
34
  }
28
35
 
@@ -37,23 +44,59 @@ export default class Factory {
37
44
  get totalContracts() {
38
45
  return this.#totalContracts
39
46
  }
40
-
41
- isvalid(hash, creator, contract, constructorParameters = []) {
42
- const message = new ContractMessage({
43
- creator,
44
- contract,
45
- constructorParameters
46
- })
47
- return Boolean(message.hash === hash)
47
+
48
+ get implementations() {
49
+ return {...this.#implementations}
48
50
  }
49
51
 
50
- async deployContract(contractHash, creator, contract, constructorParameters = []) {
51
- if (contract.creator !== msg.sender) throw new Error('only a contract creator can deploy a contract')
52
- if (await contractStore.has(hash)) throw new Error('duplicate contract')
53
- if (!this.isValid(contractHash, creator, contract, constructorParameters)) throw new Error('invalid contract')
52
+ /**
53
+ *
54
+ * @param {Address} address contract address to register
55
+ */
56
+ async registerContract(address) {
57
+ let isAllowed = false
58
+ isAllowed = await msg.staticCall(address, 'hasRole', [msg.sender, 'IMPLEMENTATION_MANAGER'])
59
+ if (!isAllowed) throw new Error('only the implementation manager can update')
60
+ if (this.#implementations[address]) throw new Error('already registered')
54
61
 
55
- await contractStore.put(hash, encoded)
56
62
  this.#totalContracts += 1
57
- this.#contracts.push(hash)
63
+ this.#implementations[address] = []
64
+ this.#implementations[address].push(address)
65
+ this.#contracts.push(address)
66
+ }
67
+
68
+ /**
69
+ * updates the current implementation to a new address
70
+ *
71
+ * @param {Address} address the current contract address
72
+ * @param {Address} newAddress the new contract address
73
+ */
74
+ async updateImplementation(address, newAddress) {
75
+ let isAllowed = false
76
+ isAllowed = await msg.staticCall(address, 'hasRole', [msg.sender, 'IMPLEMENTATION_MANAGER'])
77
+ if (!isAllowed) throw new Error('only the implementation manager can update')
78
+ if (!this.#implementations[address]) throw new Error(`register ${address} before updating to ${newAddress}`)
79
+
80
+ this.#implementations[address].push(newAddress)
81
+ }
82
+
83
+ /**
84
+ *
85
+ * @param {Address} address the original contract address
86
+ * @returns {Address} all implementations of the original contract
87
+ */
88
+ getImplementations(address) {
89
+ return this.#implementations[address]
90
+ }
91
+
92
+ /**
93
+ *
94
+ * @param {Address} address the original contract address
95
+ * @param {Number} index the index of the implmentation item or undefined (returns the latest implementation when undefined)
96
+ * @returns {Address} the latest/selected implementation of the original contract
97
+ */
98
+ getImplementation(address, index) {
99
+ index = index || this.#implementations[address].length - 1
100
+ return this.#implementations[address][index]
58
101
  }
59
102
  }
@@ -29,9 +29,7 @@ export default class NameService {
29
29
  return {...this.#registry}
30
30
  }
31
31
 
32
- get state() {
33
-
34
- }
32
+ get state() {}
35
33
 
36
34
  // TODO: control with contract
37
35
  constructor(factoryAddress, currency, validatorAddress, price, state) {
@@ -82,8 +80,8 @@ export default class NameService {
82
80
  if (balance < this.#price) throw new Error('price exceeds balance')
83
81
  try {
84
82
  await msg.call(this.#currency, 'transfer', [msg.sender, this.#owner, this.#price])
85
- } catch (e) {
86
- throw e
83
+ } catch (error) {
84
+ throw error
87
85
  }
88
86
 
89
87
  this.#registry[name] = {
@@ -1,7 +1,7 @@
1
- import Token from './../standards/token.js'
1
+ import Token from '../standards/token.js'
2
2
 
3
3
  export default class ArtOnline extends Token {
4
4
  constructor(state) {
5
5
  super('ArtOnline', 'ART', 18, state)
6
6
  }
7
- }
7
+ }
@@ -1,4 +1,4 @@
1
- import Token from './../standards/token.js'
1
+ import Token from '../standards/token.js'
2
2
 
3
3
  export default class Power extends Token {
4
4
  constructor(state) {
@@ -1,4 +1,4 @@
1
- import Proxy from './../../standards/Proxy.js'
1
+ import Proxy from '../../standards/proxy.js'
2
2
 
3
3
  export default class FactoryProxy extends Proxy {
4
4
  /**
@@ -1,4 +1,4 @@
1
- import Proxy from './../../standards/Proxy.js'
1
+ import Proxy from '../../standards/proxy.js'
2
2
 
3
3
  export default class NameServiceProxy extends Proxy {
4
4
  /**
@@ -1,4 +1,4 @@
1
- import Proxy from './../../standards/Proxy.js'
1
+ import Proxy from '../../standards/proxy.js'
2
2
 
3
3
  export default class NativeTokenProxy extends Proxy {
4
4
  /**
@@ -1,4 +1,4 @@
1
- import Proxy from './../../standards/Proxy.js'
1
+ import Proxy from '../../standards/proxy.js'
2
2
 
3
3
  export default class ValidatorsProxy extends Proxy {
4
4
  /**
@@ -1,4 +1,4 @@
1
- import Proxy from './../../standards/Proxy.js'
1
+ import Proxy from '../../standards/proxy.js'
2
2
 
3
3
  export default class VotingProxy extends Proxy {
4
4
  /**
@@ -1,4 +1,4 @@
1
- import ProxyManager from './../standards/proxyManager.js'
1
+ import ProxyManager from '../standards/proxy-manager.js'
2
2
 
3
3
  export default class ArtOnlineProxyManager extends ProxyManager {
4
4
  constructor(state) {