edge-currency-accountbased 0.7.72
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 +713 -0
- package/LICENSE +29 -0
- package/README.md +63 -0
- package/index.js +3 -0
- package/lib/binance/bnbEngine.js +591 -0
- package/lib/binance/bnbInfo.js +43 -0
- package/lib/binance/bnbPlugin.js +168 -0
- package/lib/binance/bnbSchema.js +83 -0
- package/lib/binance/bnbTypes.js +39 -0
- package/lib/common/engine.js +918 -0
- package/lib/common/plugin.js +152 -0
- package/lib/common/schema.js +108 -0
- package/lib/common/types.js +85 -0
- package/lib/common/utils.js +378 -0
- package/lib/eos/eosEngine.js +1216 -0
- package/lib/eos/eosInfo.js +98 -0
- package/lib/eos/eosPlugin.js +314 -0
- package/lib/eos/eosSchema.js +190 -0
- package/lib/eos/eosTypes.js +88 -0
- package/lib/eos/telosInfo.js +94 -0
- package/lib/eos/waxInfo.js +95 -0
- package/lib/ethereum/etcInfo.js +121 -0
- package/lib/ethereum/ethEngine.js +832 -0
- package/lib/ethereum/ethInfo.js +1300 -0
- package/lib/ethereum/ethMiningFees.js +157 -0
- package/lib/ethereum/ethNetwork.js +2195 -0
- package/lib/ethereum/ethPlugin.js +377 -0
- package/lib/ethereum/ethSchema.js +61 -0
- package/lib/ethereum/ethTypes.js +461 -0
- package/lib/ethereum/ftminfo.js +102 -0
- package/lib/ethereum/rskInfo.js +101 -0
- package/lib/fio/fioConst.js +38 -0
- package/lib/fio/fioEngine.js +1250 -0
- package/lib/fio/fioError.js +38 -0
- package/lib/fio/fioInfo.js +72 -0
- package/lib/fio/fioPlugin.js +486 -0
- package/lib/fio/fioSchema.js +56 -0
- package/lib/index.js +44 -0
- package/lib/pluginError.js +32 -0
- package/lib/react-native/edge-currency-accountbased.js +239635 -0
- package/lib/react-native/edge-currency-accountbased.js.map +1 -0
- package/lib/react-native-io.js +41 -0
- package/lib/stellar/stellarEngine.js +563 -0
- package/lib/stellar/stellarInfo.js +37 -0
- package/lib/stellar/stellarPlugin.js +215 -0
- package/lib/stellar/stellarSchema.js +54 -0
- package/lib/stellar/stellarTypes.js +66 -0
- package/lib/tezos/tezosEngine.js +497 -0
- package/lib/tezos/tezosInfo.js +60 -0
- package/lib/tezos/tezosPlugin.js +174 -0
- package/lib/tezos/tezosTypes.js +110 -0
- package/lib/xrp/xrpEngine.js +583 -0
- package/lib/xrp/xrpInfo.js +47 -0
- package/lib/xrp/xrpPlugin.js +229 -0
- package/lib/xrp/xrpSchema.js +74 -0
- package/lib/xrp/xrpTypes.js +38 -0
- package/package.json +139 -0
- package/postinstall.sh +7 -0
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }/**
|
|
2
|
+
* Created by paul on 8/8/17.
|
|
3
|
+
*/
|
|
4
|
+
//
|
|
5
|
+
|
|
6
|
+
import { bns } from 'biggystring'
|
|
7
|
+
import { generateMnemonic, mnemonicToSeedSync, validateMnemonic } from 'bip39'
|
|
8
|
+
import { Buffer } from 'buffer'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
import EthereumUtil from 'ethereumjs-util'
|
|
23
|
+
import hdKey from 'ethereumjs-wallet/hdkey'
|
|
24
|
+
|
|
25
|
+
import { CurrencyPlugin } from '../common/plugin.js'
|
|
26
|
+
import { biggyScience, getDenomInfo } from '../common/utils.js'
|
|
27
|
+
import { getFetchCors } from '../react-native-io.js'
|
|
28
|
+
import { EthereumEngine } from './ethEngine.js'
|
|
29
|
+
|
|
30
|
+
export { calcMiningFee } from './ethMiningFees.js' // may be tricky for RSK
|
|
31
|
+
|
|
32
|
+
export class EthereumPlugin extends CurrencyPlugin {
|
|
33
|
+
constructor(
|
|
34
|
+
io,
|
|
35
|
+
currencyInfo,
|
|
36
|
+
fetchCors
|
|
37
|
+
) {
|
|
38
|
+
super(io, currencyInfo.pluginId, currencyInfo)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async importPrivateKey(userInput) {
|
|
42
|
+
const { pluginId } = this.currencyInfo
|
|
43
|
+
const { pluginMnemonicKeyName, pluginRegularKeyName } =
|
|
44
|
+
this.currencyInfo.defaultSettings.otherSettings
|
|
45
|
+
if (/^(0x)?[0-9a-fA-F]{64}$/.test(userInput)) {
|
|
46
|
+
// It looks like a private key, so validate the hex:
|
|
47
|
+
const keyBuffer = Buffer.from(userInput.replace(/^0x/, ''), 'hex')
|
|
48
|
+
if (!EthereumUtil.isValidPrivate(keyBuffer)) {
|
|
49
|
+
throw new Error('Invalid private key')
|
|
50
|
+
}
|
|
51
|
+
const hexKey = keyBuffer.toString('hex')
|
|
52
|
+
|
|
53
|
+
// Validate the address derivation:
|
|
54
|
+
const keys = {
|
|
55
|
+
[pluginRegularKeyName]: hexKey
|
|
56
|
+
}
|
|
57
|
+
this.derivePublicKey({
|
|
58
|
+
type: `wallet:${pluginId}`,
|
|
59
|
+
id: 'fake',
|
|
60
|
+
keys
|
|
61
|
+
})
|
|
62
|
+
return keys
|
|
63
|
+
} else {
|
|
64
|
+
// it looks like a mnemonic, so validate that way:
|
|
65
|
+
if (!validateMnemonic(userInput)) {
|
|
66
|
+
// "input" instead of "mnemonic" in case private key
|
|
67
|
+
// was just the wrong length
|
|
68
|
+
throw new Error('Invalid input')
|
|
69
|
+
}
|
|
70
|
+
const hexKey = await this._mnemonicToHex(userInput)
|
|
71
|
+
return {
|
|
72
|
+
[pluginMnemonicKeyName]: userInput,
|
|
73
|
+
[pluginRegularKeyName]: hexKey
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async createPrivateKey(walletType) {
|
|
79
|
+
const { pluginMnemonicKeyName, pluginRegularKeyName } =
|
|
80
|
+
this.currencyInfo.defaultSettings.otherSettings
|
|
81
|
+
const type = walletType.replace('wallet:', '')
|
|
82
|
+
|
|
83
|
+
if (type !== this.currencyInfo.pluginId) {
|
|
84
|
+
throw new Error('InvalidWalletType')
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const mnemonicKey = generateMnemonic(128).split(',').join(' ')
|
|
88
|
+
|
|
89
|
+
const hexKey = await this._mnemonicToHex(mnemonicKey) // will not have 0x in it
|
|
90
|
+
return {
|
|
91
|
+
[pluginMnemonicKeyName]: mnemonicKey,
|
|
92
|
+
[pluginRegularKeyName]: hexKey
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async derivePublicKey(walletInfo) {
|
|
97
|
+
const { pluginId, defaultSettings } = this.currencyInfo
|
|
98
|
+
const { hdPathCoinType, pluginMnemonicKeyName, pluginRegularKeyName } =
|
|
99
|
+
defaultSettings.otherSettings
|
|
100
|
+
if (walletInfo.type !== `wallet:${pluginId}`) {
|
|
101
|
+
throw new Error('Invalid wallet type')
|
|
102
|
+
}
|
|
103
|
+
let address
|
|
104
|
+
if (walletInfo.keys[pluginMnemonicKeyName] != null) {
|
|
105
|
+
// If we have a mnemonic, use that:
|
|
106
|
+
const seedBuffer = mnemonicToSeedSync(
|
|
107
|
+
walletInfo.keys[pluginMnemonicKeyName]
|
|
108
|
+
)
|
|
109
|
+
const hdwallet = hdKey.fromMasterSeed(seedBuffer)
|
|
110
|
+
const walletHdpath = `m/44'/${hdPathCoinType}'/0'/0/`
|
|
111
|
+
const walletPathDerivation = hdwallet.derivePath(walletHdpath + 0)
|
|
112
|
+
const wallet = walletPathDerivation.getWallet()
|
|
113
|
+
const publicKey = wallet.getPublicKey()
|
|
114
|
+
address = `0x${EthereumUtil.pubToAddress(publicKey).toString('hex')}`
|
|
115
|
+
} else {
|
|
116
|
+
// Otherwise, use the private key:
|
|
117
|
+
const keyBuffer = Buffer.from(
|
|
118
|
+
walletInfo.keys[pluginRegularKeyName].replace(/^0x/, ''),
|
|
119
|
+
'hex'
|
|
120
|
+
)
|
|
121
|
+
if (!EthereumUtil.isValidPrivate(keyBuffer)) {
|
|
122
|
+
throw new Error('Invalid private key')
|
|
123
|
+
}
|
|
124
|
+
address = `0x${EthereumUtil.privateToAddress(keyBuffer).toString('hex')}`
|
|
125
|
+
}
|
|
126
|
+
if (!EthereumUtil.isValidAddress(address)) {
|
|
127
|
+
throw new Error('Invalid address')
|
|
128
|
+
}
|
|
129
|
+
return { publicKey: address }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async _mnemonicToHex(mnemonic) {
|
|
133
|
+
const { defaultSettings } = this.currencyInfo
|
|
134
|
+
const { hdPathCoinType } = defaultSettings.otherSettings
|
|
135
|
+
const hdwallet = hdKey.fromMasterSeed(mnemonicToSeedSync(mnemonic))
|
|
136
|
+
const walletHdpath = `m/44'/${hdPathCoinType}'/0'/0/`
|
|
137
|
+
const walletPathDerivation = hdwallet.derivePath(walletHdpath + 0)
|
|
138
|
+
const wallet = walletPathDerivation.getWallet()
|
|
139
|
+
const privKey = wallet.getPrivateKeyString().replace(/^0x/, '')
|
|
140
|
+
return privKey
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async parseUri(
|
|
144
|
+
uri,
|
|
145
|
+
currencyCode,
|
|
146
|
+
customTokens
|
|
147
|
+
) {
|
|
148
|
+
const networks = {}
|
|
149
|
+
this.currencyInfo.defaultSettings.otherSettings.uriNetworks.forEach(
|
|
150
|
+
network => {
|
|
151
|
+
networks[network] = true
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
const { parsedUri, edgeParsedUri } = this.parseUriCommon(
|
|
156
|
+
this.currencyInfo,
|
|
157
|
+
uri,
|
|
158
|
+
networks,
|
|
159
|
+
currencyCode || this.currencyInfo.currencyCode,
|
|
160
|
+
customTokens
|
|
161
|
+
)
|
|
162
|
+
let address = ''
|
|
163
|
+
if (edgeParsedUri.publicAddress) {
|
|
164
|
+
address = edgeParsedUri.publicAddress
|
|
165
|
+
edgeParsedUri.publicAddress = edgeParsedUri.publicAddress.toLowerCase()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let [prefix, contractAddress] = address.split('-') // Split the address to get the prefix according to EIP-681
|
|
169
|
+
// If contractAddress is null or undefined it means there is no prefix
|
|
170
|
+
if (!contractAddress) {
|
|
171
|
+
contractAddress = prefix // Set the contractAddress to be the prefix when the prefix is missing.
|
|
172
|
+
prefix = 'pay' // The default prefix according to EIP-681 is "pay"
|
|
173
|
+
}
|
|
174
|
+
address = contractAddress
|
|
175
|
+
|
|
176
|
+
// Verify checksum if it's present in the address
|
|
177
|
+
if (
|
|
178
|
+
/[A-F]/.test(address) &&
|
|
179
|
+
!EthereumUtil.isValidChecksumAddress(address)
|
|
180
|
+
) {
|
|
181
|
+
throw new Error('InvalidPublicAddressError')
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Verify address is valid
|
|
185
|
+
address = address.toLowerCase()
|
|
186
|
+
if (!EthereumUtil.isValidAddress(address || '')) {
|
|
187
|
+
throw new Error('InvalidPublicAddressError')
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Parse according to EIP-961
|
|
191
|
+
if (prefix === 'token' || prefix === 'token_info') {
|
|
192
|
+
if (!parsedUri.query) throw new Error('InvalidUriError')
|
|
193
|
+
|
|
194
|
+
const currencyCode = parsedUri.query.symbol || 'SYM'
|
|
195
|
+
if (currencyCode.length < 2 || currencyCode.length > 5) {
|
|
196
|
+
throw new Error('Wrong Token symbol')
|
|
197
|
+
}
|
|
198
|
+
const currencyName = parsedUri.query.name || currencyCode
|
|
199
|
+
const decimalsInput = parsedUri.query.decimals || '18'
|
|
200
|
+
let multiplier = '1000000000000000000'
|
|
201
|
+
const decimals = parseInt(decimalsInput)
|
|
202
|
+
if (decimals < 0 || decimals > 18) {
|
|
203
|
+
throw new Error('Wrong number of decimals')
|
|
204
|
+
}
|
|
205
|
+
multiplier = '1' + '0'.repeat(decimals)
|
|
206
|
+
|
|
207
|
+
const type =
|
|
208
|
+
parsedUri.query.type ||
|
|
209
|
+
this.currencyInfo.defaultSettings.otherSettings.ercTokenStandard
|
|
210
|
+
|
|
211
|
+
const edgeParsedUriToken = {
|
|
212
|
+
token: {
|
|
213
|
+
currencyCode,
|
|
214
|
+
contractAddress: contractAddress.toLowerCase(),
|
|
215
|
+
currencyName,
|
|
216
|
+
multiplier,
|
|
217
|
+
denominations: [{ name: currencyCode, multiplier }],
|
|
218
|
+
type: type.toUpperCase()
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return edgeParsedUriToken
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Parse according to EIP-681
|
|
225
|
+
if (prefix === 'pay') {
|
|
226
|
+
const targetAddress = address
|
|
227
|
+
const functionName = parsedUri.pathname.split('/')[1]
|
|
228
|
+
const parameters = parsedUri.query
|
|
229
|
+
|
|
230
|
+
// Handle contract function invocations
|
|
231
|
+
// This is a very important measure to prevent accidental payment to contract addresses
|
|
232
|
+
switch (functionName) {
|
|
233
|
+
// ERC-20 token transfer
|
|
234
|
+
case 'transfer': {
|
|
235
|
+
const publicAddress = _nullishCoalesce(parameters.address, () => ( ''))
|
|
236
|
+
const contractAddress = _nullishCoalesce(targetAddress, () => ( ''))
|
|
237
|
+
const nativeAmount =
|
|
238
|
+
parameters.uint256 != null
|
|
239
|
+
? biggyScience(parameters.uint256)
|
|
240
|
+
: edgeParsedUri.nativeAmount
|
|
241
|
+
|
|
242
|
+
// Get meta token from contract address
|
|
243
|
+
const metaToken = this.currencyInfo.metaTokens.find(
|
|
244
|
+
metaToken => metaToken.contractAddress === contractAddress
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
// If there is a currencyCode param, the metaToken must be found
|
|
248
|
+
// and it's currency code must matching the currencyCode param.
|
|
249
|
+
if (
|
|
250
|
+
currencyCode != null &&
|
|
251
|
+
(metaToken == null || metaToken.currencyCode !== currencyCode)
|
|
252
|
+
) {
|
|
253
|
+
throw new Error('InternalErrorInvalidCurrencyCode')
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Validate addresses
|
|
257
|
+
if (!EthereumUtil.isValidAddress(publicAddress)) {
|
|
258
|
+
throw new Error('InvalidPublicAddressError')
|
|
259
|
+
}
|
|
260
|
+
if (!EthereumUtil.isValidAddress(contractAddress)) {
|
|
261
|
+
throw new Error('InvalidContractAddressError')
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
...edgeParsedUri,
|
|
266
|
+
currencyCode: _optionalChain([metaToken, 'optionalAccess', _ => _.currencyCode]),
|
|
267
|
+
nativeAmount,
|
|
268
|
+
publicAddress
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// ETH payment
|
|
272
|
+
case undefined: {
|
|
273
|
+
const publicAddress = targetAddress
|
|
274
|
+
const nativeAmount =
|
|
275
|
+
parameters.value != null
|
|
276
|
+
? biggyScience(parameters.value)
|
|
277
|
+
: edgeParsedUri.nativeAmount
|
|
278
|
+
|
|
279
|
+
return { ...edgeParsedUri, publicAddress, nativeAmount }
|
|
280
|
+
}
|
|
281
|
+
default: {
|
|
282
|
+
throw new Error('UnsupportedContractFunction')
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
throw new Error('InvalidUriError')
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
async encodeUri(
|
|
291
|
+
obj,
|
|
292
|
+
customTokens
|
|
293
|
+
) {
|
|
294
|
+
const { publicAddress, nativeAmount, currencyCode } = obj
|
|
295
|
+
const valid = EthereumUtil.isValidAddress(publicAddress)
|
|
296
|
+
if (!valid) {
|
|
297
|
+
throw new Error('InvalidPublicAddressError')
|
|
298
|
+
}
|
|
299
|
+
let amount
|
|
300
|
+
if (typeof nativeAmount === 'string') {
|
|
301
|
+
const denom = getDenomInfo(
|
|
302
|
+
this.currencyInfo,
|
|
303
|
+
currencyCode || this.currencyInfo.currencyCode,
|
|
304
|
+
customTokens
|
|
305
|
+
)
|
|
306
|
+
if (!denom) {
|
|
307
|
+
throw new Error('InternalErrorInvalidCurrencyCode')
|
|
308
|
+
}
|
|
309
|
+
amount = bns.div(nativeAmount, denom.multiplier, 18)
|
|
310
|
+
}
|
|
311
|
+
const encodedUri = this.encodeUriCommon(
|
|
312
|
+
obj,
|
|
313
|
+
this.currencyInfo.pluginId,
|
|
314
|
+
amount
|
|
315
|
+
)
|
|
316
|
+
return encodedUri
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function makeEthereumBasedPluginInner(
|
|
321
|
+
opts,
|
|
322
|
+
currencyInfo
|
|
323
|
+
) {
|
|
324
|
+
const { io, initOptions } = opts
|
|
325
|
+
const fetchCors = getFetchCors(opts)
|
|
326
|
+
|
|
327
|
+
let toolsPromise
|
|
328
|
+
function makeCurrencyTools() {
|
|
329
|
+
if (toolsPromise != null) return toolsPromise
|
|
330
|
+
toolsPromise = Promise.resolve(
|
|
331
|
+
new EthereumPlugin(io, currencyInfo, fetchCors)
|
|
332
|
+
)
|
|
333
|
+
return toolsPromise
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
async function makeCurrencyEngine(
|
|
337
|
+
walletInfo,
|
|
338
|
+
opts
|
|
339
|
+
) {
|
|
340
|
+
const tools = await makeCurrencyTools()
|
|
341
|
+
const currencyEngine = new EthereumEngine(
|
|
342
|
+
tools,
|
|
343
|
+
walletInfo,
|
|
344
|
+
initOptions,
|
|
345
|
+
opts,
|
|
346
|
+
currencyInfo,
|
|
347
|
+
fetchCors
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
// Do any async initialization necessary for the engine
|
|
351
|
+
await currencyEngine.loadEngine(tools, walletInfo, opts)
|
|
352
|
+
|
|
353
|
+
// This is just to make sure otherData is Flow type checked
|
|
354
|
+
currencyEngine.otherData = currencyEngine.walletLocalData.otherData
|
|
355
|
+
|
|
356
|
+
// Initialize otherData defaults if they weren't on disk
|
|
357
|
+
if (!currencyEngine.otherData.nextNonce) {
|
|
358
|
+
currencyEngine.otherData.nextNonce = '0'
|
|
359
|
+
}
|
|
360
|
+
if (!currencyEngine.otherData.unconfirmedNextNonce) {
|
|
361
|
+
currencyEngine.otherData.unconfirmedNextNonce = '0'
|
|
362
|
+
}
|
|
363
|
+
if (!currencyEngine.otherData.networkFees) {
|
|
364
|
+
currencyEngine.otherData.networkFees =
|
|
365
|
+
currencyInfo.defaultSettings.otherSettings.defaultNetworkFees
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const out = currencyEngine
|
|
369
|
+
return out
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return {
|
|
373
|
+
currencyInfo,
|
|
374
|
+
makeCurrencyEngine,
|
|
375
|
+
makeCurrencyTools
|
|
376
|
+
}
|
|
377
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Created by paul on 8/27/17.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const EtherscanGetBlockHeight = {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
result: { type: 'string' }
|
|
9
|
+
},
|
|
10
|
+
required: ['result']
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const EtherscanGetAccountNonce = {
|
|
14
|
+
type: 'object',
|
|
15
|
+
properties: {
|
|
16
|
+
result: { type: 'string' }
|
|
17
|
+
},
|
|
18
|
+
required: ['result']
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const EthGasStationSchema = {
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
safeLow: { type: 'number' },
|
|
25
|
+
average: { type: 'number' },
|
|
26
|
+
fastest: { type: 'number' }
|
|
27
|
+
},
|
|
28
|
+
required: ['safeLow', 'average', 'fastest']
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const CustomTokenSchema = {
|
|
32
|
+
type: 'object',
|
|
33
|
+
properties: {
|
|
34
|
+
currencyCode: { type: 'string' },
|
|
35
|
+
currencyName: { type: 'string' },
|
|
36
|
+
multiplier: { type: 'string' },
|
|
37
|
+
contractAddress: { type: 'string' }
|
|
38
|
+
},
|
|
39
|
+
required: ['currencyCode', 'currencyName', 'multiplier', 'contractAddress']
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const BlockChairStatsSchema = {
|
|
43
|
+
type: 'object',
|
|
44
|
+
properties: {
|
|
45
|
+
data: {
|
|
46
|
+
type: 'object',
|
|
47
|
+
properties: {
|
|
48
|
+
blocks: { type: 'number' }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
required: ['data']
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const AmberdataRpcSchema = {
|
|
56
|
+
type: 'object',
|
|
57
|
+
properties: {
|
|
58
|
+
result: { type: 'string' }
|
|
59
|
+
},
|
|
60
|
+
required: ['result']
|
|
61
|
+
}
|