@cityofzion/bs-neo-legacy 0.4.2 → 0.7.0

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 (52) hide show
  1. package/.rush/temp/shrinkwrap-deps.json +2 -2
  2. package/bs-neo-legacy.build.error.log +2 -82
  3. package/bs-neo-legacy.build.log +3 -84
  4. package/dist/BSNeoLegacy.d.ts +23 -13
  5. package/dist/BSNeoLegacy.js +98 -69
  6. package/dist/constants.d.ts +5 -2
  7. package/docs/assets/search.js +1 -1
  8. package/docs/classes/BDSNeoLegacy.html +13 -13
  9. package/docs/classes/BSNeoLegacy.html +81 -37
  10. package/docs/interfaces/DoraNeoLegacyAsset.html +7 -7
  11. package/docs/interfaces/DoraNeoLegacyAssetResponse.html +9 -9
  12. package/docs/interfaces/DoraNeoLegacyBalance.html +5 -5
  13. package/docs/interfaces/DoraNeoLegacyConsensusNode.html +3 -3
  14. package/docs/interfaces/DoraNeoLegacyDetails.html +12 -12
  15. package/docs/interfaces/DoraNeoLegacyEntriesEntity.html +8 -8
  16. package/docs/interfaces/DoraNeoLegacyNameEntity.html +3 -3
  17. package/docs/interfaces/DoraNeoLegacyScriptsEntity.html +3 -3
  18. package/docs/interfaces/DoraNeoLegacyTransaction.html +14 -14
  19. package/docs/interfaces/DoraNeoLegacyTransactionsHistory.html +6 -6
  20. package/docs/interfaces/DoraNeoLegacyUnclaimed.html +4 -4
  21. package/docs/interfaces/DoraNeoLegacyVinEntity.html +3 -3
  22. package/docs/interfaces/DoraNeoLegacyVoutEntity.html +5 -5
  23. package/docs/variables/DORA_NEO_LEGACY_ASSET.html +1 -1
  24. package/docs/variables/DORA_NEO_LEGACY_BALANCE.html +1 -1
  25. package/docs/variables/DORA_NEO_LEGACY_CONTRACT.html +1 -1
  26. package/docs/variables/DORA_NEO_LEGACY_HISTORY_TRANSACTIONS.html +1 -1
  27. package/docs/variables/DORA_NEO_LEGACY_NODES.html +1 -1
  28. package/docs/variables/DORA_NEO_LEGACY_TRANSACTION.html +1 -1
  29. package/docs/variables/DORA_NEO_LEGACY_UNCLAIMED.html +1 -1
  30. package/docs/variables/explorerNeoLegacyOption.html +1 -1
  31. package/jest.config.ts +13 -0
  32. package/jest.setup.ts +1 -0
  33. package/package.json +10 -6
  34. package/src/BSNeoLegacy.ts +184 -152
  35. package/src/CryptoCompareEDSNeoLegacy.ts +40 -0
  36. package/src/DoraBDSNeoLegacy.ts +171 -0
  37. package/src/__tests__/BDSNeoLegacy.spec.ts +120 -0
  38. package/src/__tests__/BSNeoLegacy.spec.ts +127 -0
  39. package/src/__tests__/CryptoCompareExchange.spec.ts +46 -0
  40. package/src/assets/tokens/common.json +18 -0
  41. package/src/assets/tokens/mainnet.json +620 -0
  42. package/src/constants.ts +20 -17
  43. package/src/index.ts +3 -2
  44. package/tsconfig.build.json +4 -0
  45. package/tsconfig.json +3 -7
  46. package/src/BDSNeoLegacy.ts +0 -163
  47. package/src/asset/blockchain_icon_neo_legacy.png +0 -0
  48. package/src/asset/blockchain_icon_neo_legacy_white.png +0 -0
  49. package/src/asset/tokens.json +0 -481
  50. package/src/explorer/dora/DoraResponsesNeoLegacy.ts +0 -107
  51. package/src/explorer/dora/DoraRoutesNeoLegacy.ts +0 -7
  52. package/src/explorer/index.ts +0 -8
@@ -0,0 +1,171 @@
1
+ import {
2
+ BalanceResponse,
3
+ BlockchainDataService,
4
+ ContractResponse,
5
+ TransactionsByAddressParams,
6
+ TransactionsByAddressResponse,
7
+ TransactionResponse,
8
+ BDSClaimable,
9
+ TransactionTransferAsset,
10
+ Token,
11
+ NetworkType,
12
+ Network,
13
+ } from '@cityofzion/blockchain-service'
14
+ import { api } from '@cityofzion/dora-ts'
15
+ import { TOKENS } from './constants'
16
+ import { rpc } from '@cityofzion/neon-js'
17
+
18
+ export class DoraBDSNeoLegacy implements BlockchainDataService, BDSClaimable {
19
+ readonly network: Network
20
+ private readonly claimToken: Token
21
+ private readonly feeToken: Token
22
+ private readonly tokenCache: Map<string, Token> = new Map()
23
+
24
+ constructor(network: Network, feeToken: Token, claimToken: Token) {
25
+ if (network.type === 'custom') throw new Error('Custom network is not supported for NEO Legacy')
26
+ this.network = network
27
+ this.claimToken = claimToken
28
+ this.feeToken = feeToken
29
+ }
30
+
31
+ async getTransaction(hash: string): Promise<TransactionResponse> {
32
+ const data = await api.NeoLegacyREST.transaction(hash, this.network.type)
33
+ if (!data || 'error' in data) throw new Error(`Transaction ${hash} not found`)
34
+
35
+ const vout: any[] = data.vout ?? []
36
+
37
+ const promises = vout.map<Promise<TransactionTransferAsset>>(async (transfer, _index, array) => {
38
+ const token = await this.getTokenInfo(transfer.asset)
39
+ return {
40
+ amount: String(transfer.value),
41
+ from: array[array.length - 1]?.address,
42
+ contractHash: transfer.asset,
43
+ to: transfer.address,
44
+ type: 'token',
45
+ token,
46
+ }
47
+ })
48
+ const transfers = await Promise.all(promises)
49
+
50
+ return {
51
+ hash: data.txid,
52
+ block: data.block,
53
+ fee: (Number(data.sys_fee ?? 0) + Number(data.net_fee ?? 0)).toFixed(this.feeToken.decimals),
54
+ time: Number(data.time),
55
+ notifications: [], //neoLegacy doesn't have notifications
56
+ transfers,
57
+ }
58
+ }
59
+
60
+ async getTransactionsByAddress({
61
+ address,
62
+ page = 1,
63
+ }: TransactionsByAddressParams): Promise<TransactionsByAddressResponse> {
64
+ const data = await api.NeoLegacyREST.getAddressAbstracts(address, page, this.network.type)
65
+ const transactions = new Map<string, TransactionResponse>()
66
+
67
+ const promises = data.entries.map(async entry => {
68
+ if (entry.address_from !== address && entry.address_to !== address) return
69
+
70
+ const token = await this.getTokenInfo(entry.asset)
71
+ const transfer: TransactionTransferAsset = {
72
+ amount: String(entry.amount),
73
+ from: entry.address_from ?? 'Mint',
74
+ to: entry.address_to ?? 'Burn',
75
+ type: 'token',
76
+ contractHash: entry.asset,
77
+ token,
78
+ }
79
+ const existingTransaction = transactions.get(entry.txid)
80
+ if (existingTransaction) {
81
+ existingTransaction.transfers.push(transfer)
82
+ return
83
+ }
84
+
85
+ transactions.set(entry.txid, {
86
+ block: entry.block_height,
87
+ hash: entry.txid,
88
+ time: entry.time,
89
+ transfers: [transfer],
90
+ notifications: [],
91
+ })
92
+ })
93
+ await Promise.all(promises)
94
+
95
+ return {
96
+ totalCount: data.total_entries,
97
+ limit: data.page_size,
98
+ transactions: Array.from(transactions.values()),
99
+ }
100
+ }
101
+
102
+ async getContract(contractHash: string): Promise<ContractResponse> {
103
+ const response = await api.NeoLegacyREST.contract(contractHash, this.network.type)
104
+ if (!response || 'error' in response) throw new Error(`Contract ${contractHash} not found`)
105
+
106
+ return {
107
+ hash: response.hash,
108
+ name: response.name,
109
+ methods: [],
110
+ }
111
+ }
112
+
113
+ async getTokenInfo(tokenHash: string): Promise<Token> {
114
+ const localToken = TOKENS[this.network.type].find(token => token.hash === tokenHash)
115
+ if (localToken) return localToken
116
+
117
+ if (this.tokenCache.has(tokenHash)) {
118
+ return this.tokenCache.get(tokenHash)!
119
+ }
120
+
121
+ const data = await api.NeoLegacyREST.asset(tokenHash, this.network.type)
122
+ if (!data || 'error' in data) throw new Error(`Token ${tokenHash} not found`)
123
+
124
+ const token = {
125
+ decimals: data.decimals,
126
+ symbol: data.symbol,
127
+ hash: data.scripthash,
128
+ name: data.name,
129
+ }
130
+
131
+ this.tokenCache.set(tokenHash, token)
132
+
133
+ return token
134
+ }
135
+
136
+ async getBalance(address: string): Promise<BalanceResponse[]> {
137
+ const data = await api.NeoLegacyREST.balance(address, this.network.type)
138
+
139
+ const promises = data.map<Promise<BalanceResponse>>(async balance => {
140
+ let token: Token = {
141
+ hash: balance.asset,
142
+ name: balance.asset_name,
143
+ symbol: balance.symbol,
144
+ decimals: 8,
145
+ }
146
+
147
+ try {
148
+ token = await this.getTokenInfo(balance.asset)
149
+ } catch {}
150
+
151
+ return {
152
+ amount: (Number(balance.balance) / 10 ** token.decimals).toFixed(token.decimals),
153
+ token,
154
+ }
155
+ })
156
+
157
+ const result = await Promise.all(promises)
158
+
159
+ return result
160
+ }
161
+
162
+ async getUnclaimed(address: string): Promise<string> {
163
+ const { unclaimed } = await api.NeoLegacyREST.getUnclaimed(address, this.network.type)
164
+ return (unclaimed / 10 ** this.claimToken.decimals).toFixed(this.claimToken.decimals)
165
+ }
166
+
167
+ async getBlockHeight(): Promise<number> {
168
+ const rpcClient = new rpc.RPCClient(this.network.url)
169
+ return await rpcClient.getBlockCount()
170
+ }
171
+ }
@@ -0,0 +1,120 @@
1
+ import { BDSClaimable, BlockchainDataService } from '@cityofzion/blockchain-service'
2
+ import { DoraBDSNeoLegacy } from '../DoraBDSNeoLegacy'
3
+ import { DEFAULT_URL_BY_NETWORK_TYPE, TOKENS } from '../constants'
4
+
5
+ const gasToken = TOKENS.testnet.find(t => t.symbol === 'GAS')!
6
+ let doraBDSNeoLegacy = new DoraBDSNeoLegacy(
7
+ { type: 'testnet', url: DEFAULT_URL_BY_NETWORK_TYPE.testnet },
8
+ gasToken,
9
+ gasToken
10
+ )
11
+
12
+ describe('BDSNeoLegacy', () => {
13
+ it.each([doraBDSNeoLegacy])('Should be able to get transaction - %s', async (bdsNeoLegacy: BlockchainDataService) => {
14
+ const hash = '0x6632e79b1e5182355bcc1f3ca0e91d11a426c893734cd266e7bf3d3f74618add'
15
+ const transaction = await bdsNeoLegacy.getTransaction(hash)
16
+ expect(transaction).toEqual(
17
+ expect.objectContaining({
18
+ block: expect.any(Number),
19
+ hash,
20
+ notifications: [],
21
+ transfers: expect.arrayContaining([
22
+ expect.objectContaining({
23
+ amount: expect.any(String),
24
+ from: expect.any(String),
25
+ to: expect.any(String),
26
+ type: 'token',
27
+ }),
28
+ ]),
29
+ time: expect.any(Number),
30
+ fee: expect.any(String),
31
+ })
32
+ )
33
+ })
34
+
35
+ it.each([doraBDSNeoLegacy])(
36
+ 'Should be able to get history transactions - %s',
37
+ async (bdsNeoLegacy: BlockchainDataService) => {
38
+ const address = 'AeGgZTTWPzyVtNiQRcpngkV75Xip1hznmi'
39
+ try {
40
+ const response = await bdsNeoLegacy.getTransactionsByAddress({ address, page: 1 })
41
+ response.transactions.forEach(transaction => {
42
+ expect(transaction).toEqual(
43
+ expect.objectContaining({
44
+ block: expect.any(Number),
45
+ hash: expect.any(String),
46
+ notifications: expect.arrayContaining([
47
+ expect.objectContaining({
48
+ eventName: expect.any(String),
49
+ state: expect.arrayContaining([
50
+ {
51
+ type: expect.any(String),
52
+ value: expect.any(String),
53
+ },
54
+ ]),
55
+ }),
56
+ ]),
57
+ transfers: expect.arrayContaining([
58
+ expect.objectContaining({
59
+ amount: expect.any(Number),
60
+ from: expect.any(String),
61
+ to: expect.any(String),
62
+ type: 'asset',
63
+ }),
64
+ ]),
65
+ time: expect.any(Number),
66
+ fee: expect.any(String),
67
+ })
68
+ )
69
+ })
70
+ } catch {}
71
+ }
72
+ )
73
+
74
+ it.each([doraBDSNeoLegacy])('Should be able to get contract - %s', async (bdsNeoLegacy: BlockchainDataService) => {
75
+ const hash = '0x998a0da7ec5f21c9a99ef5349f81af8af89f9644'
76
+ const contract = await bdsNeoLegacy.getContract(hash)
77
+ expect(contract).toEqual({
78
+ hash: hash,
79
+ name: 'Phantasma Stake',
80
+ methods: [],
81
+ })
82
+ })
83
+
84
+ it.each([doraBDSNeoLegacy])('Should be able to get token info - %s', async (bdsNeoLegacy: BlockchainDataService) => {
85
+ const hash = '0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7'
86
+ const token = await bdsNeoLegacy.getTokenInfo(hash)
87
+ expect(token).toEqual({
88
+ decimals: 8,
89
+ hash: hash,
90
+ name: 'GAS',
91
+ symbol: 'GAS',
92
+ })
93
+ })
94
+
95
+ it.each([doraBDSNeoLegacy])('Should be able to get balance - %s', async (bdsNeoLegacy: BlockchainDataService) => {
96
+ const address = 'AeGgZTTWPzyVtNiQRcpngkV75Xip1hznmi'
97
+ const balance = await bdsNeoLegacy.getBalance(address)
98
+
99
+ balance.forEach(balance => {
100
+ expect(balance).toEqual({
101
+ amount: expect.any(String),
102
+ token: {
103
+ hash: expect.any(String),
104
+ name: expect.any(String),
105
+ symbol: expect.any(String),
106
+ decimals: expect.any(Number),
107
+ },
108
+ })
109
+ })
110
+ })
111
+
112
+ it.each([doraBDSNeoLegacy])(
113
+ 'Should be able to get unclaimed - %s',
114
+ async (doraBDSNeoLegacy: BlockchainDataService & BDSClaimable) => {
115
+ const address = 'AeGgZTTWPzyVtNiQRcpngkV75Xip1hznmi'
116
+ const unclaimed = await doraBDSNeoLegacy.getUnclaimed(address)
117
+ expect(unclaimed).toEqual(expect.any(String))
118
+ }
119
+ )
120
+ })
@@ -0,0 +1,127 @@
1
+ import { BSNeoLegacy } from '../BSNeoLegacy'
2
+ import { wallet } from '@cityofzion/neon-js'
3
+ import { generateMnemonic } from '@cityofzion/bs-asteroid-sdk'
4
+
5
+ let bsNeoLegacy: BSNeoLegacy
6
+
7
+ describe('BSNeoLegacy', () => {
8
+ beforeEach(() => {
9
+ bsNeoLegacy = new BSNeoLegacy('neoLegacy', { type: 'testnet', url: 'http://seed5.ngd.network:20332' })
10
+ })
11
+
12
+ it('Should be able to validate an address', () => {
13
+ const validAddress = 'AJDZ8QP7ydjFicpcXCkG7wczeWEAKxpF69'
14
+ const invalidAddress = 'invalid address'
15
+
16
+ expect(bsNeoLegacy.validateAddress(validAddress)).toBeTruthy()
17
+ expect(bsNeoLegacy.validateAddress(invalidAddress)).toBeFalsy()
18
+ })
19
+
20
+ it('Should be able to validate an encrypted key', () => {
21
+ const validEncryptedKey = '6PYSsRjFn1v5uu79h5vXGZEYvvRkioHmd1Fd5bUyVp9Gt2wJcLKWHgD6Hy'
22
+ const invalidEncryptedKey = 'invalid encrypted key'
23
+
24
+ expect(bsNeoLegacy.validateEncrypted(validEncryptedKey)).toBeTruthy()
25
+ expect(bsNeoLegacy.validateEncrypted(invalidEncryptedKey)).toBeFalsy()
26
+ })
27
+
28
+ it('Should be able to validate a wif', () => {
29
+ const validWif = 'L4ZnhLegkFV9FTys1wBJDHUykn5hLnr15cPqvfuy4E1kzWTE6iRM'
30
+ const invalidWif = 'invalid wif'
31
+
32
+ expect(bsNeoLegacy.validateKey(validWif)).toBeTruthy()
33
+ expect(bsNeoLegacy.validateKey(invalidWif)).toBeFalsy()
34
+ })
35
+
36
+ it('Should be able to gererate a account from mnemonic', () => {
37
+ const mnemonic = generateMnemonic()
38
+ const account = bsNeoLegacy.generateAccountFromMnemonic(mnemonic, 0)
39
+
40
+ expect(bsNeoLegacy.validateAddress(account.address)).toBeTruthy()
41
+ expect(bsNeoLegacy.validateKey(account.key)).toBeTruthy()
42
+ })
43
+
44
+ it('Should be able to generate a account from wif', () => {
45
+ const mnemonic = generateMnemonic()
46
+ const account = bsNeoLegacy.generateAccountFromMnemonic(mnemonic, 0)
47
+
48
+ const accountFromWif = bsNeoLegacy.generateAccountFromKey(account.key)
49
+ expect(account).toEqual(expect.objectContaining(accountFromWif))
50
+ })
51
+
52
+ it('Should be able to decrypt a encrypted key', async () => {
53
+ const mnemonic = generateMnemonic()
54
+ const account = bsNeoLegacy.generateAccountFromMnemonic(mnemonic, 0)
55
+ const password = 'TestPassword'
56
+ const encryptedKey = await wallet.encrypt(account.key, password)
57
+ const decryptedAccount = await bsNeoLegacy.decrypt(encryptedKey, password)
58
+ expect(account).toEqual(expect.objectContaining(decryptedAccount))
59
+ }, 10000)
60
+
61
+ it.skip('Should be able to transfer a native asset', async () => {
62
+ const account = bsNeoLegacy.generateAccountFromKey(process.env.TESTNET_PRIVATE_KEY as string)
63
+ const balance = await bsNeoLegacy.blockchainDataService.getBalance(account.address)
64
+ const gasBalance = balance.find(b => b.token.symbol === 'GAS')!
65
+ expect(Number(gasBalance?.amount)).toBeGreaterThan(0.00000001)
66
+
67
+ const transactionHash = await bsNeoLegacy.transfer({
68
+ senderAccount: account,
69
+ intent: {
70
+ amount: '0.00000001',
71
+ receiverAddress: 'AQEQdmCcitFbE6oJU5Epa7dNxhTkCmTZST',
72
+ tokenHash: gasBalance.token.hash,
73
+ tokenDecimals: gasBalance.token.decimals,
74
+ },
75
+ })
76
+
77
+ expect(transactionHash).toEqual(expect.any(String))
78
+ })
79
+
80
+ it.skip('Should be able to transfer a nep5 asset', async () => {
81
+ bsNeoLegacy.setNetwork({ type: 'mainnet', url: 'http://seed9.ngd.network:10332' })
82
+ const account = bsNeoLegacy.generateAccountFromKey(process.env.TESTNET_PRIVATE_KEY as string)
83
+ const balance = await bsNeoLegacy.blockchainDataService.getBalance(account.address)
84
+ const LXBalance = balance.find(item => item.token.symbol === 'LX')!
85
+ expect(Number(LXBalance?.amount)).toBeGreaterThan(0.00000001)
86
+
87
+ const transactionHash = await bsNeoLegacy.transfer({
88
+ senderAccount: account,
89
+ intent: {
90
+ amount: '0.00000001',
91
+ receiverAddress: 'AQEQdmCcitFbE6oJU5Epa7dNxhTkCmTZST',
92
+ tokenHash: LXBalance.token.hash,
93
+ tokenDecimals: LXBalance.token.decimals,
94
+ },
95
+ })
96
+
97
+ expect(transactionHash).toEqual(expect.any(String))
98
+ })
99
+
100
+ it.skip('Should be able to transfer a asset with tip', async () => {
101
+ bsNeoLegacy.setNetwork({ type: 'mainnet', url: 'http://seed9.ngd.network:10332' })
102
+ const account = bsNeoLegacy.generateAccountFromKey(process.env.TESTNET_PRIVATE_KEY as string)
103
+ const balance = await bsNeoLegacy.blockchainDataService.getBalance(account.address)
104
+ const LXBalance = balance.find(item => item.token.symbol === 'LX')!
105
+ expect(Number(LXBalance?.amount)).toBeGreaterThan(0.00000001)
106
+ const gasBalance = balance.find(item => item.token.symbol === bsNeoLegacy.feeToken.symbol)!
107
+ expect(Number(gasBalance?.amount)).toBeGreaterThan(0.00000001)
108
+
109
+ const transactionHash = await bsNeoLegacy.transfer({
110
+ senderAccount: account,
111
+ intent: {
112
+ amount: '0.00000001',
113
+ receiverAddress: 'AQEQdmCcitFbE6oJU5Epa7dNxhTkCmTZST',
114
+ tokenHash: LXBalance.token.hash,
115
+ tokenDecimals: LXBalance.token.decimals,
116
+ },
117
+ tipIntent: {
118
+ amount: '0.00000001',
119
+ receiverAddress: 'AQEQdmCcitFbE6oJU5Epa7dNxhTkCmTZST',
120
+ tokenHash: gasBalance.token.hash,
121
+ tokenDecimals: gasBalance.token.decimals,
122
+ },
123
+ })
124
+
125
+ expect(transactionHash).toEqual(expect.any(String))
126
+ })
127
+ })
@@ -0,0 +1,46 @@
1
+ import { CryptoCompareEDSNeoLegacy } from '../CryptoCompareEDSNeoLegacy'
2
+
3
+ let cryptoCompareEDSNeoLegacy: CryptoCompareEDSNeoLegacy
4
+
5
+ describe('FlamingoEDSNeo3', () => {
6
+ beforeAll(() => {
7
+ cryptoCompareEDSNeoLegacy = new CryptoCompareEDSNeoLegacy('mainnet')
8
+ })
9
+
10
+ it('Should return a list with prices of tokens using USD', async () => {
11
+ const tokenPriceList = await cryptoCompareEDSNeoLegacy.getTokenPrices('USD')
12
+
13
+ tokenPriceList.forEach(tokenPrice => {
14
+ expect(tokenPrice).toEqual({
15
+ price: expect.any(Number),
16
+ symbol: expect.any(String),
17
+ })
18
+ })
19
+ })
20
+
21
+ it('Should return a list with prices of tokens using BRL', async () => {
22
+ const tokenPriceListInUSD = await cryptoCompareEDSNeoLegacy.getTokenPrices('USD')
23
+ const tokenPriceList = await cryptoCompareEDSNeoLegacy.getTokenPrices('BRL')
24
+
25
+ tokenPriceList.forEach((tokenPrice, index) => {
26
+ expect(tokenPrice.price).toBeGreaterThan(tokenPriceListInUSD[index].price)
27
+ expect(tokenPrice).toEqual({
28
+ price: expect.any(Number),
29
+ symbol: expect.any(String),
30
+ })
31
+ })
32
+ })
33
+
34
+ it('Should return a list with prices of tokens using EUR', async () => {
35
+ const tokenPriceListInUSD = await cryptoCompareEDSNeoLegacy.getTokenPrices('USD')
36
+ const tokenPriceList = await cryptoCompareEDSNeoLegacy.getTokenPrices('EUR')
37
+
38
+ tokenPriceList.forEach((tokenPrice, index) => {
39
+ expect(tokenPrice.price).toBeLessThan(tokenPriceListInUSD[index].price)
40
+ expect(tokenPrice).toEqual({
41
+ price: expect.any(Number),
42
+ symbol: expect.any(String),
43
+ })
44
+ })
45
+ })
46
+ })
@@ -0,0 +1,18 @@
1
+ [
2
+ {
3
+ "symbol": "GAS",
4
+ "type": "UtilityToken",
5
+ "name": "GAS",
6
+ "hash": "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7",
7
+ "decimals": 8,
8
+ "blockchain": "neoLegacy"
9
+ },
10
+ {
11
+ "symbol": "NEO",
12
+ "type": "GoverningToken",
13
+ "name": "NEO",
14
+ "hash": "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b",
15
+ "decimals": 0,
16
+ "blockchain": "neoLegacy"
17
+ }
18
+ ]