@leofcoin/chain 1.4.21 → 1.4.23
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/LICENSE +88 -88
- package/README.md +4 -4
- package/exports/chain.js +1071 -0
- package/exports/node.js +23 -0
- package/exports/typings/chain.d.ts +83 -0
- package/exports/typings/config/config.d.ts +1 -0
- package/exports/typings/config/main.d.ts +5 -0
- package/exports/typings/config/protocol.d.ts +6 -0
- package/exports/typings/contract.d.ts +29 -0
- package/exports/typings/fee/config.d.ts +4 -0
- package/exports/typings/machine.d.ts +26 -0
- package/exports/typings/node.d.ts +9 -0
- package/exports/typings/protocol.d.ts +4 -0
- package/exports/typings/state.d.ts +5 -0
- package/exports/typings/transaction.d.ts +47 -0
- package/exports/typings/typer.d.ts +6 -0
- package/package.json +77 -75
- package/CHANGELOG.md +0 -14
- package/block-worker.js +0 -1
- package/demo/865.browser.js +0 -10
- package/demo/chain.browser.js +0 -66842
- package/demo/generate-account.browser.js +0 -50
- package/demo/index.html +0 -25
- package/demo/messages.browser.js +0 -328
- package/demo/multi-wallet.browser.js +0 -15
- package/demo/node.browser.js +0 -9858
- package/demo/pako.browser.js +0 -6900
- package/demo/peernet-swarm.browser.js +0 -839
- package/demo/storage.browser.js +0 -3724
- package/demo/workers/865.js +0 -10
- package/demo/workers/block-worker.js +0 -13175
- package/demo/workers/machine-worker.js +0 -13385
- package/demo/workers/pool-worker.js +0 -8503
- package/demo/workers/transaction-worker.js +0 -8495
- package/demo/wrtc.browser.js +0 -28
- package/dist/browser/workers/865.js +0 -10
- package/dist/browser/workers/block-worker.js +0 -9460
- package/dist/browser/workers/machine-worker.js +0 -9670
- package/dist/browser/workers/pool-worker.js +0 -4608
- package/dist/browser/workers/transaction-worker.js +0 -4600
- package/dist/chain.js +0 -10128
- package/dist/client-80bc8156.js +0 -491
- package/dist/commonjs-7fe3c381.js +0 -270
- package/dist/contracts/factory.js +0 -1
- package/dist/contracts/name-service.js +0 -1
- package/dist/contracts/native-token.js +0 -1
- package/dist/contracts/validators.js +0 -1
- package/dist/generate-account-445db122.js +0 -46
- package/dist/index-57f93805.js +0 -718
- package/dist/messages-bce1b91d-81af3b00.js +0 -315
- package/dist/module/chain.js +0 -10091
- package/dist/module/client-8031ec88.js +0 -489
- package/dist/module/commonjs-9005d5c0.js +0 -268
- package/dist/module/generate-account-489552b6.js +0 -44
- package/dist/module/index-ac2285c4.js +0 -688
- package/dist/module/messages-bce1b91d-eaf75d83.js +0 -302
- package/dist/module/node.js +0 -7049
- package/dist/module/workers/block-worker.js +0 -94
- package/dist/module/workers/machine-worker.js +0 -304
- package/dist/module/workers/pool-worker.js +0 -55
- package/dist/module/workers/transaction-worker.js +0 -47
- package/dist/node.js +0 -7061
- package/dist/standards/token.js +0 -1
- package/dist/workers/machine-worker.js +0 -1
- package/dist/workers/pool-worker.js +0 -1
- package/dist/workers/transaction-worker.js +0 -1
- package/examples/contracts/token.js +0 -7
- package/plugins/bundle.js +0 -18
- package/rollup.config.js +0 -15
- package/src/chain.ts +0 -710
- package/src/config/config.js +0 -14
- package/src/config/main.js +0 -4
- package/src/config/protocol.js +0 -5
- package/src/contract.js +0 -52
- package/src/fee/config.js +0 -3
- package/src/machine.js +0 -215
- package/src/node.ts +0 -24
- package/src/protocol.js +0 -4
- package/src/state.js +0 -31
- package/src/transaction.ts +0 -182
- package/src/type.index.d.ts +0 -21
- package/src/typer.js +0 -19
- package/test/chain.js +0 -150
- package/test/contracts/token.js +0 -40
- package/test/create-genesis.js +0 -66
- package/test/index.js +0 -1
- package/tsconfig.json +0 -17
- package/workers/block-worker.js +0 -40
- package/workers/machine-worker.js +0 -219
- package/workers/pool-worker.js +0 -28
- package/workers/transaction-worker.js +0 -20
- package/workers/workers.js +0 -9
package/src/config/config.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import main from './main'
|
|
2
|
-
import protocol from './protocol'
|
|
3
|
-
|
|
4
|
-
// export default async () => {
|
|
5
|
-
// let config = { ...main, protocol }
|
|
6
|
-
// try {
|
|
7
|
-
// let data = await read(main.configPath)
|
|
8
|
-
// data = JSON.parse(data.toString())
|
|
9
|
-
// config = { ...config, ...data }
|
|
10
|
-
// } catch (e) {
|
|
11
|
-
// await write(main.configPath, JSON.stringify(config, null, '\t'))
|
|
12
|
-
// }
|
|
13
|
-
// return config
|
|
14
|
-
// }
|
package/src/config/main.js
DELETED
package/src/config/protocol.js
DELETED
package/src/contract.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import Transaction from "./transaction.js";
|
|
2
|
-
import { createContractMessage } from '@leofcoin/lib'
|
|
3
|
-
import addresses from "@leofcoin/addresses"
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @extends {Transaction}
|
|
7
|
-
*/
|
|
8
|
-
export default class Contract extends Transaction {
|
|
9
|
-
constructor() {
|
|
10
|
-
super()
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
*
|
|
15
|
-
* @param {Address} creator
|
|
16
|
-
* @param {String} contract
|
|
17
|
-
* @param {Array} constructorParameters
|
|
18
|
-
* @returns lib.createContractMessage
|
|
19
|
-
*/
|
|
20
|
-
async createContractMessage(creator, contract, constructorParameters = []) {
|
|
21
|
-
return createContractMessage(creator, contract, constructorParameters)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
26
|
-
* @param {Address} creator
|
|
27
|
-
* @param {String} contract
|
|
28
|
-
* @param {Array} constructorParameters
|
|
29
|
-
* @returns {Address}
|
|
30
|
-
*/
|
|
31
|
-
async createContractAddress(creator, contract, constructorParameters = []) {
|
|
32
|
-
contract = await this.createContractMessage(creator, contract, constructorParameters)
|
|
33
|
-
return contract.hash()
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
*
|
|
38
|
-
* @param {String} contract
|
|
39
|
-
* @param {Array} parameters
|
|
40
|
-
* @returns
|
|
41
|
-
*/
|
|
42
|
-
async deployContract(contract, constructorParameters = []) {
|
|
43
|
-
const message = await createContractMessage(peernet.selectedAccount, contract, constructorParameters)
|
|
44
|
-
try {
|
|
45
|
-
await contractStore.put(await message.hash(), message.encoded)
|
|
46
|
-
} catch (error) {
|
|
47
|
-
throw error
|
|
48
|
-
}
|
|
49
|
-
return this.createTransactionFrom(peernet.selectedAccount, addresses.contractFactory, 'registerContract', [await message.hash()])
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
}
|
package/src/fee/config.js
DELETED
package/src/machine.js
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import { contractFactory, nativeToken, validators, nameService } from '@leofcoin/addresses'
|
|
2
|
-
import { randombytes } from '@leofcoin/crypto'
|
|
3
|
-
import EasyWorker from '@vandeurenglenn/easy-worker'
|
|
4
|
-
import { ContractMessage } from '@leofcoin/messages'
|
|
5
|
-
// import State from './state'
|
|
6
|
-
|
|
7
|
-
export default class Machine {
|
|
8
|
-
#contracts = {}
|
|
9
|
-
#nonces = {}
|
|
10
|
-
lastBlock = {index: 0, hash: '0x0', previousHash: '0x0'}
|
|
11
|
-
|
|
12
|
-
constructor(blocks) {
|
|
13
|
-
return this.#init(blocks)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
#createMessage(sender = peernet.selectedAccount) {
|
|
17
|
-
return {
|
|
18
|
-
sender,
|
|
19
|
-
call: this.execute,
|
|
20
|
-
staticCall: this.get.bind(this)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async #onmessage(data) {
|
|
25
|
-
switch (data.type) {
|
|
26
|
-
case 'contractError': {
|
|
27
|
-
console.warn(`removing contract ${await data.hash()}`);
|
|
28
|
-
await contractStore.delete(await data.hash())
|
|
29
|
-
break
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
case 'initError': {
|
|
33
|
-
console.error(`init error: ${data.message}`);
|
|
34
|
-
break
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
case 'executionError': {
|
|
38
|
-
// console.warn(`error executing transaction ${data.message}`);
|
|
39
|
-
pubsub.publish(data.id, {error: data.message})
|
|
40
|
-
break
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
case 'debug': {
|
|
44
|
-
for (const message of data.messages) debug(message)
|
|
45
|
-
break
|
|
46
|
-
}
|
|
47
|
-
case 'machine-ready': {
|
|
48
|
-
this.lastBlock = data.lastBlock
|
|
49
|
-
pubsub.publish('machine.ready', true)
|
|
50
|
-
break
|
|
51
|
-
}
|
|
52
|
-
case 'response': {
|
|
53
|
-
pubsub.publish(data.id, data.value || false)
|
|
54
|
-
break
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async #init(blocks) {
|
|
61
|
-
return new Promise(async (resolve) => {
|
|
62
|
-
const machineReady = () => {
|
|
63
|
-
pubsub.unsubscribe('machine.ready', machineReady)
|
|
64
|
-
resolve(this)
|
|
65
|
-
}
|
|
66
|
-
pubsub.subscribe('machine.ready', machineReady)
|
|
67
|
-
|
|
68
|
-
this.worker = await new EasyWorker('node_modules/@leofcoin/workers/src/machine-worker.js', {serialization: 'advanced', type:'module'})
|
|
69
|
-
this.worker.onmessage(this.#onmessage.bind(this))
|
|
70
|
-
|
|
71
|
-
// const blocks = await blockStore.values()
|
|
72
|
-
const contracts = await Promise.all([
|
|
73
|
-
contractStore.get(contractFactory),
|
|
74
|
-
contractStore.get(nativeToken),
|
|
75
|
-
contractStore.get(validators),
|
|
76
|
-
contractStore.get(nameService)
|
|
77
|
-
])
|
|
78
|
-
|
|
79
|
-
const message = {
|
|
80
|
-
type: 'init',
|
|
81
|
-
input: {
|
|
82
|
-
contracts,
|
|
83
|
-
blocks,
|
|
84
|
-
peerid: peernet.peerId
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
this.worker.postMessage(message)
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async #runContract(contractMessage) {
|
|
93
|
-
const hash = await contractMessage.hash()
|
|
94
|
-
return new Promise((resolve, reject) => {
|
|
95
|
-
const id = randombytes(20).toString('hex')
|
|
96
|
-
const onmessage = message => {
|
|
97
|
-
pubsub.unsubscribe(id, onmessage)
|
|
98
|
-
if (message?.error) reject(message.error)
|
|
99
|
-
else resolve(message)
|
|
100
|
-
}
|
|
101
|
-
pubsub.subscribe(id, onmessage)
|
|
102
|
-
this.worker.postMessage({
|
|
103
|
-
type: 'run',
|
|
104
|
-
id,
|
|
105
|
-
input: {
|
|
106
|
-
decoded: contractMessage.decoded,
|
|
107
|
-
encoded: contractMessage.encoded,
|
|
108
|
-
hash
|
|
109
|
-
}
|
|
110
|
-
})
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
*
|
|
117
|
-
* @param {Address} contract
|
|
118
|
-
* @param {String} method
|
|
119
|
-
* @param {Array} parameters
|
|
120
|
-
* @returns Promise<message>
|
|
121
|
-
*/
|
|
122
|
-
async execute(contract, method, parameters) {
|
|
123
|
-
try {
|
|
124
|
-
if (contract === contractFactory && method === 'registerContract') {
|
|
125
|
-
if (await this.has(parameters[0])) throw new Error(`duplicate contract @${parameters[0]}`)
|
|
126
|
-
let message;
|
|
127
|
-
if (!await contractStore.has(parameters[0])) {
|
|
128
|
-
message = await peernet.get(parameters[0], 'contract')
|
|
129
|
-
message = await new ContractMessage(message)
|
|
130
|
-
await contractStore.put(await message.hash(), message.encoded)
|
|
131
|
-
}
|
|
132
|
-
if (!message) {
|
|
133
|
-
message = await contractStore.get(parameters[0])
|
|
134
|
-
message = await new ContractMessage(message)
|
|
135
|
-
}
|
|
136
|
-
if (!await this.has(await message.hash())) await this.#runContract(message)
|
|
137
|
-
}
|
|
138
|
-
} catch (error) {
|
|
139
|
-
throw new Error(`contract deployment failed for ${parameters[0]}\n${error.message}`)
|
|
140
|
-
}
|
|
141
|
-
return new Promise((resolve, reject) => {
|
|
142
|
-
const id = randombytes(20).toString('hex')
|
|
143
|
-
const onmessage = message => {
|
|
144
|
-
pubsub.unsubscribe(id, onmessage)
|
|
145
|
-
if (message?.error) reject(message.error)
|
|
146
|
-
else resolve(message)
|
|
147
|
-
}
|
|
148
|
-
pubsub.subscribe(id, onmessage)
|
|
149
|
-
this.worker.postMessage({
|
|
150
|
-
type: 'execute',
|
|
151
|
-
id,
|
|
152
|
-
input: {
|
|
153
|
-
contract,
|
|
154
|
-
method,
|
|
155
|
-
params: parameters
|
|
156
|
-
}
|
|
157
|
-
})
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
get(contract, method, parameters) {
|
|
163
|
-
return new Promise((resolve, reject) => {
|
|
164
|
-
const id = randombytes(20).toString()
|
|
165
|
-
const onmessage = message => {
|
|
166
|
-
pubsub.unsubscribe(id, onmessage)
|
|
167
|
-
resolve(message)
|
|
168
|
-
}
|
|
169
|
-
pubsub.subscribe(id, onmessage)
|
|
170
|
-
this.worker.postMessage({
|
|
171
|
-
type: 'get',
|
|
172
|
-
id,
|
|
173
|
-
input: {
|
|
174
|
-
contract,
|
|
175
|
-
method,
|
|
176
|
-
params: parameters
|
|
177
|
-
}
|
|
178
|
-
})
|
|
179
|
-
})
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
async has(address) {
|
|
184
|
-
return new Promise((resolve, reject) => {
|
|
185
|
-
const id = randombytes(20).toString('hex')
|
|
186
|
-
const onmessage = message => {
|
|
187
|
-
pubsub.unsubscribe(id, onmessage)
|
|
188
|
-
if (message?.error) reject(message.error)
|
|
189
|
-
else resolve(message)
|
|
190
|
-
}
|
|
191
|
-
pubsub.subscribe(id, onmessage)
|
|
192
|
-
this.worker.postMessage({
|
|
193
|
-
type: 'has',
|
|
194
|
-
id,
|
|
195
|
-
input: {
|
|
196
|
-
address
|
|
197
|
-
}
|
|
198
|
-
})
|
|
199
|
-
})
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
async delete(hash) {
|
|
203
|
-
return contractStore.delete(hash)
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
*
|
|
208
|
-
* @returns Promise
|
|
209
|
-
*/
|
|
210
|
-
async deleteAll() {
|
|
211
|
-
let hashes = await contractStore.get()
|
|
212
|
-
hashes = Object.keys(hashes).map(hash => this.delete(hash))
|
|
213
|
-
return Promise.all(hashes)
|
|
214
|
-
}
|
|
215
|
-
}
|
package/src/node.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// import config from './config/config'
|
|
2
|
-
import Peernet from '@leofcoin/peernet'
|
|
3
|
-
import nodeConfig from '@leofcoin/lib/node-config';
|
|
4
|
-
import networks from '@leofcoin/networks';
|
|
5
|
-
|
|
6
|
-
export default class Node {
|
|
7
|
-
constructor() {
|
|
8
|
-
return this._init()
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async _init(config = {
|
|
12
|
-
network: 'leofcoin:peach',
|
|
13
|
-
networkName: 'leofcoin:peach',
|
|
14
|
-
networkVersion: 'peach',
|
|
15
|
-
stars: networks.leofcoin.peach.stars
|
|
16
|
-
}): Promise<this> {
|
|
17
|
-
globalThis.Peernet ? await new globalThis.Peernet(config) : await new Peernet(config)
|
|
18
|
-
await nodeConfig(config)
|
|
19
|
-
|
|
20
|
-
return this
|
|
21
|
-
// this.config = await config()
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
}
|
package/src/protocol.js
DELETED
package/src/state.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import pako from 'pako'
|
|
2
|
-
|
|
3
|
-
export default class State {
|
|
4
|
-
constructor() {
|
|
5
|
-
// return this.#init()
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
// async #init() {
|
|
9
|
-
// const state = await stateStore.get()
|
|
10
|
-
// for (const [key, value] of Object.entries(state)) {
|
|
11
|
-
//
|
|
12
|
-
// }
|
|
13
|
-
//
|
|
14
|
-
// return this
|
|
15
|
-
// }
|
|
16
|
-
|
|
17
|
-
async put(key, value, isCompressed = true) {
|
|
18
|
-
value = isCompressed ? value : await pako.deflate(value)
|
|
19
|
-
await stateStore.put(key, value)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async get(key, isCompressed = true) {
|
|
23
|
-
const value = await stateStore.get(key)
|
|
24
|
-
return isCompressed = true ? pako.inflate(value) : value
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
updateState(block) {
|
|
28
|
-
// block.decoded.index
|
|
29
|
-
// this.#isUpdateNeeded()
|
|
30
|
-
}
|
|
31
|
-
}
|
package/src/transaction.ts
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import Protocol from "./protocol.js"
|
|
2
|
-
import { TransactionMessage, BlockMessage } from "@leofcoin/messages"
|
|
3
|
-
import { calculateFee } from '@leofcoin/lib'
|
|
4
|
-
import { formatBytes } from '@leofcoin/utils'
|
|
5
|
-
|
|
6
|
-
export default class Transaction extends Protocol {
|
|
7
|
-
constructor() {
|
|
8
|
-
super()
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
* @param {Address[]} transactions
|
|
14
|
-
* @returns transactions to include
|
|
15
|
-
*/
|
|
16
|
-
async getTransactions (transactions) {
|
|
17
|
-
return new Promise(async (resolve, reject) => {
|
|
18
|
-
let size = 0
|
|
19
|
-
const _transactions = []
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const promises = await Promise.all(transactions
|
|
23
|
-
.map(async tx => {
|
|
24
|
-
tx = await new TransactionMessage(tx)
|
|
25
|
-
size += tx.encoded.length
|
|
26
|
-
if (!formatBytes(size).includes('MB') || formatBytes(size).includes('MB') && Number(formatBytes(size).split(' MB')[0]) <= 0.75) _transactions.push({...tx.decoded, hash: await tx.hash()})
|
|
27
|
-
else resolve(_transactions)
|
|
28
|
-
}))
|
|
29
|
-
|
|
30
|
-
return resolve(_transactions)
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
*
|
|
37
|
-
* @param {Transaction[]} transactions An array containing Transactions
|
|
38
|
-
* @returns {TransactionMessage}
|
|
39
|
-
*/
|
|
40
|
-
async promiseTransactions(transactions): Promise<TransactionMessage[]> {
|
|
41
|
-
transactions = await Promise.all(transactions.map(tx => new TransactionMessage(tx)))
|
|
42
|
-
return transactions
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
*
|
|
47
|
-
* @param {Transaction[]} transactions An array containing Transactions
|
|
48
|
-
* @returns {Object} {transaction.decoded, transaction.hash}
|
|
49
|
-
*/
|
|
50
|
-
async promiseTransactionsContent(transactions) {
|
|
51
|
-
transactions = await Promise.all(transactions.map(tx => new Promise(async (resolve, reject) => {
|
|
52
|
-
resolve({ ...tx.decoded, hash: await tx.hash() })
|
|
53
|
-
})))
|
|
54
|
-
|
|
55
|
-
return transactions
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* When a nonce isn't found for an address fallback to just checking the transactionnPoolStore
|
|
60
|
-
* @param {Address} address
|
|
61
|
-
* @returns {Number} nonce
|
|
62
|
-
*/
|
|
63
|
-
async #getNonceFallback(address) {
|
|
64
|
-
let transactions = await globalThis.transactionPoolStore.values()
|
|
65
|
-
transactions = await this.promiseTransactions(transactions)
|
|
66
|
-
transactions = transactions.filter(tx => tx.decoded.from === address)
|
|
67
|
-
transactions = await this.promiseTransactionsContent(transactions)
|
|
68
|
-
|
|
69
|
-
if (this.lastBlock?.hash && transactions.length === 0 && this.lastBlock.hash !== '0x0') {
|
|
70
|
-
|
|
71
|
-
let block = await peernet.get(this.lastBlock.hash)
|
|
72
|
-
block = await new BlockMessage(block)
|
|
73
|
-
|
|
74
|
-
// for (let tx of block.decoded?.transactions) {
|
|
75
|
-
// tx = await peernet.get(tx, 'transaction')
|
|
76
|
-
// transactions.push(new TransactionMessage(tx))
|
|
77
|
-
// }
|
|
78
|
-
transactions = transactions.filter(tx => tx.from === address)
|
|
79
|
-
while (transactions.length === 0 && block.decoded.index !== 0 && block.decoded.previousHash !== '0x0') {
|
|
80
|
-
block = await globalThis.blockStore.get(block.decoded.previousHash)
|
|
81
|
-
block = await new BlockMessage(block)
|
|
82
|
-
transactions = block.decoded.transactions.filter(tx => tx.from === address)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
if (transactions.length === 0) return 0
|
|
87
|
-
|
|
88
|
-
transactions = transactions.sort((a, b) => a.timestamp - b.timestamp)
|
|
89
|
-
return transactions[transactions.length - 1].nonce
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Get amount of transactions by address
|
|
94
|
-
* @param {Address} address The address to get the nonce for
|
|
95
|
-
* @returns {Number} nonce
|
|
96
|
-
*/
|
|
97
|
-
async getNonce(address) {
|
|
98
|
-
if (!await globalThis.accountsStore.has(address)) {
|
|
99
|
-
const nonce = await this.#getNonceFallback(address)
|
|
100
|
-
await globalThis.accountsStore.put(address, new TextEncoder().encode(String(nonce)))
|
|
101
|
-
}
|
|
102
|
-
// todo: are those in the pool in cluded also ? they need to be included!!!
|
|
103
|
-
let nonce = await globalThis.accountsStore.get(address)
|
|
104
|
-
nonce = new TextDecoder().decode(nonce)
|
|
105
|
-
|
|
106
|
-
let transactions = await globalThis.transactionPoolStore.values()
|
|
107
|
-
transactions = await this.promiseTransactions(transactions)
|
|
108
|
-
transactions = transactions.filter(tx => tx.decoded.from === address)
|
|
109
|
-
transactions = await this.promiseTransactionsContent(transactions)
|
|
110
|
-
for (const transaction of transactions) {
|
|
111
|
-
if (transaction.nonce > nonce) nonce = transaction.nonce
|
|
112
|
-
}
|
|
113
|
-
return Number(nonce)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
async validateNonce(address, nonce) {
|
|
117
|
-
let previousNonce = await globalThis.accountsStore.get(address)
|
|
118
|
-
previousNonce = Number(new TextDecoder().decode(previousNonce))
|
|
119
|
-
if (previousNonce > nonce) throw new Error(`a transaction with a higher nonce already exists`)
|
|
120
|
-
if (previousNonce === nonce) throw new Error(`a transaction with the same nonce already exists`)
|
|
121
|
-
|
|
122
|
-
let transactions = await globalThis.transactionPoolStore.values()
|
|
123
|
-
transactions = await this.promiseTransactions(transactions)
|
|
124
|
-
transactions = transactions.filter(tx => tx.decoded.from === address)
|
|
125
|
-
|
|
126
|
-
for (const transaction of transactions) {
|
|
127
|
-
if (transaction.decoded.nonce > nonce) throw new Error(`a transaction with a higher nonce already exists`)
|
|
128
|
-
if (transaction.decoded.nonce === nonce) throw new Error(`a transaction with the same nonce already exists`)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
isTransactionMessage(message) {
|
|
133
|
-
if (message instanceof TransactionMessage) return true
|
|
134
|
-
return false
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async createTransaction(transaction) {
|
|
138
|
-
return {
|
|
139
|
-
from: transaction.from,
|
|
140
|
-
to: transaction.to,
|
|
141
|
-
method: transaction.method,
|
|
142
|
-
params: transaction.params,
|
|
143
|
-
timestamp: transaction.timestamp || Date.now(),
|
|
144
|
-
nonce: transaction.nonce || (await this.getNonce(transaction.from)) + 1
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
async sendTransaction(message) {
|
|
149
|
-
if (!this.isTransactionMessage(message)) message = new TransactionMessage(message)
|
|
150
|
-
if (!message.decoded.signature) throw new Error(`transaction not signed`)
|
|
151
|
-
if (message.decoded.nonce === undefined) throw new Error(`nonce required`)
|
|
152
|
-
|
|
153
|
-
try {
|
|
154
|
-
await this.validateNonce(message.decoded.from, message.decoded.nonce)
|
|
155
|
-
// todo check if signature is valid
|
|
156
|
-
const hash = await message.hash()
|
|
157
|
-
let data
|
|
158
|
-
const wait = new Promise(async (resolve, reject) => {
|
|
159
|
-
if (pubsub.subscribers[`transaction.completed.${hash}`]) {
|
|
160
|
-
const result = pubsub.subscribers[`transaction.completed.${hash}`].value
|
|
161
|
-
result.status === 'fulfilled' ? resolve(result.hash) : reject({hash: result.hash, error: result.error})
|
|
162
|
-
} else {
|
|
163
|
-
const completed = async result => {
|
|
164
|
-
result.status === 'fulfilled' ? resolve(result.hash) : reject({hash: result.hash, error: result.error})
|
|
165
|
-
|
|
166
|
-
setTimeout(async () => {
|
|
167
|
-
pubsub.unsubscribe(`transaction.completed.${hash}`, completed)
|
|
168
|
-
}, 10_000)
|
|
169
|
-
}
|
|
170
|
-
pubsub.subscribe(`transaction.completed.${hash}`, completed)
|
|
171
|
-
}
|
|
172
|
-
})
|
|
173
|
-
await globalThis.transactionPoolStore.put(hash, message.encoded)
|
|
174
|
-
debug(`Added ${hash} to the transaction pool`)
|
|
175
|
-
peernet.publish('add-transaction', message.encoded)
|
|
176
|
-
return {hash: hash, data, fee: await calculateFee(message.decoded), wait, message}
|
|
177
|
-
} catch (error) {
|
|
178
|
-
throw error
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
}
|
package/src/type.index.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
type Address = string
|
|
2
|
-
|
|
3
|
-
interface Transaction {
|
|
4
|
-
to: Address,
|
|
5
|
-
from: Address,
|
|
6
|
-
method: String,
|
|
7
|
-
params: string[],
|
|
8
|
-
nonce: Number
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface RawTransaction extends Transaction {
|
|
12
|
-
timestamp: Number
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface globalMessage {
|
|
16
|
-
sender: Address,
|
|
17
|
-
call: Function,
|
|
18
|
-
staticCall: Function,
|
|
19
|
-
delegate: Function,
|
|
20
|
-
staticDelegate: Function
|
|
21
|
-
}
|
package/src/typer.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import {BigNumber} from '@leofcoin/utils'
|
|
2
|
-
|
|
3
|
-
const codec = '0x'
|
|
4
|
-
|
|
5
|
-
const isAddress = address => {
|
|
6
|
-
if (!address.startsWith(codec)) return false
|
|
7
|
-
if (address.length !== 64) return false
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default {
|
|
11
|
-
isType: (type, value) => {
|
|
12
|
-
type = type.toLowercase()
|
|
13
|
-
if (type === 'string') return typeof(value) === type
|
|
14
|
-
if (type === 'number') return !Number.isNaN(Number(value))
|
|
15
|
-
if (type === 'address') return isAddress(value)
|
|
16
|
-
if (type === 'BigNumber') return BigNumber.isBigNumber(value)
|
|
17
|
-
},
|
|
18
|
-
isAddress
|
|
19
|
-
}
|