@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.
- package/demo/chain.browser.js +17 -13
- package/demo/peernet-swarm.browser.js +8 -9
- package/demo/workers/machine-worker.js +30 -11
- package/dist/browser/workers/machine-worker.js +18 -12
- package/dist/chain.js +149 -134
- package/dist/contracts/factory.js +1 -1
- package/dist/contracts/{nameService.js → name-service.js} +1 -1
- package/dist/contracts/native-token.js +1 -0
- package/dist/contracts/validators.js +1 -1
- package/dist/module/chain.js +146 -131
- package/dist/module/workers/machine-worker.js +18 -12
- package/dist/standards/token.js +1 -1
- package/dist/workers/machine-worker.js +1 -1
- package/package.json +20 -2
- package/rollup.config.js +4 -4
- package/src/chain.js +112 -102
- package/src/contracts/factory.js +58 -15
- package/src/contracts/{nameService.js → name-service.js} +3 -5
- package/src/contracts/{nativeToken.js → native-token.js} +2 -2
- package/src/contracts/{powerToken.js → power-token.js} +1 -1
- package/src/contracts/proxies/{factoryProxy.js → factory-proxy.js} +1 -1
- package/src/contracts/proxies/{nameServiceProxy.js → name-service-proxy.js} +1 -1
- package/src/contracts/proxies/{nativeTokenProxy.js → native-token-proxy.js} +1 -1
- package/src/contracts/proxies/{validatorsProxy.js → validators-proxy.js} +1 -1
- package/src/contracts/proxies/{votingProxy.js → voting-proxy.js} +1 -1
- package/src/contracts/{proxyManager.js → proxy-manager.js} +1 -1
- package/src/contracts/validators.js +35 -25
- package/src/fee/config.js +1 -1
- package/src/machine.js +34 -29
- package/src/standards/{proxyManager.js → proxy-manager.js} +0 -0
- package/src/standards/{Proxy.js → proxy.js} +4 -8
- package/src/standards/roles.js +7 -5
- package/src/standards/voting.js +1 -0
- package/src/transactions/transaction.js +1 -3
- package/src/transactions/validator.js +1 -1
- package/src/typer.js +1 -1
- package/dist/865.browser.js +0 -10
- package/dist/chain.browser.js +0 -59741
- package/dist/contracts/nativeToken.js +0 -1
- package/dist/generate-account.browser.js +0 -50
- package/dist/messages.browser.js +0 -328
- package/dist/multi-wallet.browser.js +0 -15
- package/dist/node.browser.js +0 -9858
- package/dist/pako.browser.js +0 -6900
- package/dist/peernet-swarm.browser.js +0 -840
- package/dist/storage.browser.js +0 -3724
- package/dist/wrtc.browser.js +0 -28
- 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 =
|
|
62
|
+
const start = Date.now()
|
|
61
63
|
try {
|
|
62
64
|
await this.#createBlock()
|
|
63
|
-
} catch (
|
|
64
|
-
console.error(
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error(error);
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
const end =
|
|
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
|
-
},
|
|
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
|
-
|
|
119
|
-
return this.#
|
|
120
|
+
getLatestBlock() {
|
|
121
|
+
return this.#getLatestBlock()
|
|
120
122
|
}
|
|
121
123
|
|
|
122
|
-
async #
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
|
156
|
-
this
|
|
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
|
-
|
|
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
|
|
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.#
|
|
180
|
+
const latestBlock = await this.#getLatestBlock()
|
|
181
|
+
await this.#syncChain(latestBlock)
|
|
178
182
|
}
|
|
179
|
-
} catch (
|
|
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 #
|
|
215
|
-
|
|
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
|
-
|
|
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 =
|
|
231
|
-
await this.#loadBlocks(this
|
|
232
|
-
this.#
|
|
233
|
-
|
|
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
|
|
247
|
-
} catch
|
|
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
|
|
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(`
|
|
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
|
-
|
|
280
|
-
} catch
|
|
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 (
|
|
295
|
-
console.log(
|
|
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
|
|
327
|
-
} catch (
|
|
328
|
-
pubsub.publish(`transaction.completed.${hash}`, {status: 'fail', hash, error:
|
|
329
|
-
throw
|
|
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
|
-
|
|
386
|
-
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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]
|
|
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
|
-
|
|
562
|
-
|
|
563
|
-
|
|
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,
|
|
633
|
-
return this.createTransactionFrom(peernet.selectedAccount, to, method,
|
|
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,
|
|
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
|
-
},
|
|
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 (
|
|
741
|
-
console.log(
|
|
742
|
-
throw
|
|
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,
|
|
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,
|
|
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 (
|
|
768
|
-
throw
|
|
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,
|
|
793
|
+
internalCall(sender, contract, method, parameters) {
|
|
784
794
|
globalThis.msg = this.#createMessage(sender)
|
|
785
795
|
|
|
786
|
-
return this.#machine.execute(contract, method,
|
|
796
|
+
return this.#machine.execute(contract, method, parameters)
|
|
787
797
|
}
|
|
788
798
|
|
|
789
|
-
call(contract, method,
|
|
799
|
+
call(contract, method, parameters) {
|
|
790
800
|
globalThis.msg = this.#createMessage()
|
|
791
801
|
|
|
792
|
-
return this.#machine.execute(contract, method,
|
|
802
|
+
return this.#machine.execute(contract, method, parameters)
|
|
793
803
|
}
|
|
794
804
|
|
|
795
|
-
staticCall(contract, method,
|
|
805
|
+
staticCall(contract, method, parameters) {
|
|
796
806
|
globalThis.msg = this.#createMessage()
|
|
797
|
-
return this.#machine.get(contract, method,
|
|
807
|
+
return this.#machine.get(contract, method, parameters)
|
|
798
808
|
}
|
|
799
809
|
|
|
800
|
-
delegate(contract, method,
|
|
810
|
+
delegate(contract, method, parameters) {
|
|
801
811
|
globalThis.msg = this.#createMessage()
|
|
802
812
|
|
|
803
|
-
return this.#machine.execute(contract, method,
|
|
813
|
+
return this.#machine.execute(contract, method, parameters)
|
|
804
814
|
}
|
|
805
815
|
|
|
806
|
-
staticDelegate(contract, method,
|
|
816
|
+
staticDelegate(contract, method, parameters) {
|
|
807
817
|
globalThis.msg = this.#createMessage()
|
|
808
818
|
|
|
809
|
-
return this.#machine.get(contract, method,
|
|
819
|
+
return this.#machine.get(contract, method, parameters)
|
|
810
820
|
}
|
|
811
821
|
|
|
812
822
|
mint(to, amount) {
|
package/src/contracts/factory.js
CHANGED
|
@@ -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
|
-
|
|
42
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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.#
|
|
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 (
|
|
86
|
-
throw
|
|
83
|
+
} catch (error) {
|
|
84
|
+
throw error
|
|
87
85
|
}
|
|
88
86
|
|
|
89
87
|
this.#registry[name] = {
|