-
Notifications
You must be signed in to change notification settings - Fork 73
/
setup.ts
103 lines (91 loc) · 3.15 KB
/
setup.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import '@polkadot/types-codec'
import { HexString } from '@polkadot/util/types'
import { HttpProvider, WsProvider } from '@polkadot/rpc-provider'
import { ProviderInterface } from '@polkadot/rpc-provider/types'
import { RegisteredTypes } from '@polkadot/types/types'
import { Api } from './api.js'
import { Blockchain } from './blockchain/index.js'
import { BuildBlockMode } from './blockchain/txpool.js'
import { Database } from './database.js'
import { GenesisProvider } from './genesis-provider.js'
import { defaultLogger } from './logger.js'
import { inherentProviders } from './blockchain/inherent/index.js'
export type SetupOptions = {
endpoint?: string | string[]
block?: string | number | null
genesis?: GenesisProvider
buildBlockMode?: BuildBlockMode
db?: Database
mockSignatureHost?: boolean
allowUnresolvedImports?: boolean
runtimeLogLevel?: number
registeredTypes?: RegisteredTypes
offchainWorker?: boolean
maxMemoryBlockCount?: number
processQueuedMessages?: boolean
}
export const processOptions = async (options: SetupOptions) => {
defaultLogger.debug(options, 'Setup options')
let provider: ProviderInterface
if (options.genesis) {
provider = options.genesis
} else if (typeof options.endpoint === 'string' && /^(https|http):\/\//.test(options.endpoint || '')) {
provider = new HttpProvider(options.endpoint)
} else {
provider = new WsProvider(options.endpoint, 3_000)
}
const api = new Api(provider)
await api.isReady
let blockHash: string
if (options.block == null) {
blockHash = await api.getBlockHash().then((hash) => {
if (!hash) {
// should not happen, but just in case
throw new Error('Cannot find block hash')
}
return hash
})
} else if (typeof options.block === 'string' && options.block.startsWith('0x')) {
blockHash = options.block as string
} else if (Number.isInteger(+options.block)) {
blockHash = await api.getBlockHash(Number(options.block)).then((hash) => {
if (!hash) {
throw new Error(`Cannot find block hash for ${options.block}`)
}
return hash
})
} else {
throw new Error(`Invalid block number or hash: ${options.block}`)
}
defaultLogger.debug({ ...options, blockHash }, 'Args')
return { ...options, blockHash, api }
}
export const setup = async (options: SetupOptions) => {
const { api, blockHash, ...opts } = await processOptions(options)
const header = await api.getHeader(blockHash)
if (!header) {
throw new Error(`Cannot find header for ${blockHash}`)
}
const chain = new Blockchain({
api,
buildBlockMode: opts.buildBlockMode,
inherentProviders,
db: opts.db,
header: {
hash: blockHash as HexString,
number: Number(header.number),
},
mockSignatureHost: opts.mockSignatureHost,
allowUnresolvedImports: opts.allowUnresolvedImports,
runtimeLogLevel: opts.runtimeLogLevel,
registeredTypes: opts.registeredTypes || {},
offchainWorker: opts.offchainWorker,
maxMemoryBlockCount: opts.maxMemoryBlockCount,
processQueuedMessages: opts.processQueuedMessages,
})
if (opts.genesis) {
// build 1st block
await chain.newBlock()
}
return chain
}