@cityofzion/bs-ethereum 0.8.0 → 0.8.1
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/.rush/temp/operation/build/all.log +1 -1
- package/.rush/temp/operation/build/state.json +1 -1
- package/.rush/temp/package-deps_build.json +4 -6
- package/bs-ethereum.build.log +1 -1
- package/dist/BSEthereum.d.ts +23 -23
- package/dist/BSEthereum.js +178 -178
- package/dist/BitqueryBDSEthereum.d.ts +14 -14
- package/dist/BitqueryBDSEthereum.js +197 -186
- package/dist/BitqueryEDSEthereum.d.ts +8 -8
- package/dist/BitqueryEDSEthereum.js +73 -73
- package/dist/GhostMarketNDSEthereum.d.ts +10 -10
- package/dist/GhostMarketNDSEthereum.js +77 -77
- package/dist/RpcBDSEthereum.d.ts +12 -12
- package/dist/RpcBDSEthereum.js +89 -89
- package/dist/assets/tokens/common.json +8 -8
- package/dist/constants.d.ts +16 -16
- package/dist/constants.js +33 -33
- package/dist/graphql.d.ts +124 -123
- package/dist/graphql.js +163 -162
- package/dist/index.d.ts +6 -6
- package/dist/index.js +22 -22
- package/jest.config.ts +13 -13
- package/jest.setup.ts +1 -1
- package/package.json +34 -34
- package/src/BSEthereum.ts +184 -184
- package/src/BitqueryBDSEthereum.ts +230 -220
- package/src/BitqueryEDSEthereum.ts +67 -67
- package/src/GhostMarketNDSEthereum.ts +122 -122
- package/src/RpcBDSEthereum.ts +88 -88
- package/src/__tests__/BDSEthereum.spec.ts +123 -123
- package/src/__tests__/BSEthereum.spec.ts +123 -123
- package/src/__tests__/BitqueryEDSEthereum.spec.ts +49 -49
- package/src/__tests__/GhostMarketNDSEthereum.spec.ts +45 -45
- package/src/assets/tokens/common.json +7 -7
- package/src/constants.ts +37 -37
- package/src/graphql.ts +291 -289
- package/src/index.ts +6 -6
- package/tsconfig.build.json +4 -4
- package/tsconfig.json +15 -15
- package/CHANGELOG.json +0 -22
- package/CHANGELOG.md +0 -11
|
@@ -1,122 +1,122 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BlockchainService,
|
|
3
|
-
NftResponse,
|
|
4
|
-
NftsResponse,
|
|
5
|
-
NetworkType,
|
|
6
|
-
NftDataService,
|
|
7
|
-
GetNftParam,
|
|
8
|
-
GetNftsByAddressParams,
|
|
9
|
-
} from '@cityofzion/blockchain-service'
|
|
10
|
-
import qs from 'query-string'
|
|
11
|
-
|
|
12
|
-
import { GHOSTMARKET_CHAIN_BY_NETWORK_TYPE, GHOSTMARKET_URL_BY_NETWORK_TYPE } from './constants'
|
|
13
|
-
import fetch from 'node-fetch'
|
|
14
|
-
|
|
15
|
-
type GhostMarketNFT = {
|
|
16
|
-
tokenId: string
|
|
17
|
-
contract: {
|
|
18
|
-
chain?: string
|
|
19
|
-
hash: string
|
|
20
|
-
symbol: string
|
|
21
|
-
}
|
|
22
|
-
creator: {
|
|
23
|
-
address?: string
|
|
24
|
-
offchainName?: string
|
|
25
|
-
}
|
|
26
|
-
apiUrl?: string
|
|
27
|
-
ownerships: {
|
|
28
|
-
owner: {
|
|
29
|
-
address?: string
|
|
30
|
-
}
|
|
31
|
-
}[]
|
|
32
|
-
collection: {
|
|
33
|
-
name?: string
|
|
34
|
-
logoUrl?: string
|
|
35
|
-
}
|
|
36
|
-
metadata: {
|
|
37
|
-
description: string
|
|
38
|
-
mediaType: string
|
|
39
|
-
mediaUri: string
|
|
40
|
-
mintDate: number
|
|
41
|
-
mintNumber: number
|
|
42
|
-
name: string
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
type GhostMarketAssets = {
|
|
47
|
-
assets: GhostMarketNFT[]
|
|
48
|
-
next: string
|
|
49
|
-
}
|
|
50
|
-
export class GhostMarketNDSEthereum implements NftDataService {
|
|
51
|
-
private networkType: NetworkType
|
|
52
|
-
|
|
53
|
-
constructor(networkType: NetworkType) {
|
|
54
|
-
this.networkType = networkType
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async getNftsByAddress({ address, size = 18, cursor, page }: GetNftsByAddressParams): Promise<NftsResponse> {
|
|
58
|
-
const url = this.getUrlWithParams({
|
|
59
|
-
size,
|
|
60
|
-
owners: [address],
|
|
61
|
-
cursor: cursor,
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
const request = await fetch(url, { method: 'GET' })
|
|
65
|
-
const data = (await request.json()) as GhostMarketAssets
|
|
66
|
-
const nfts = data.assets ?? []
|
|
67
|
-
|
|
68
|
-
return { nextCursor: data.next, items: nfts.map(this.parse.bind(this)) }
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async getNft({ contractHash, tokenId }: GetNftParam): Promise<NftResponse> {
|
|
72
|
-
const url = this.getUrlWithParams({
|
|
73
|
-
contract: contractHash,
|
|
74
|
-
tokenIds: [tokenId],
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
const request = await fetch(url, { method: 'GET' })
|
|
78
|
-
const data = (await request.json()) as GhostMarketAssets
|
|
79
|
-
|
|
80
|
-
return this.parse(data.assets[0])
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private treatGhostMarketImage(srcImage?: string) {
|
|
84
|
-
if (!srcImage) {
|
|
85
|
-
return
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (srcImage.startsWith('ipfs://')) {
|
|
89
|
-
const [, imageId] = srcImage.split('://')
|
|
90
|
-
|
|
91
|
-
return `https://ghostmarket.mypinata.cloud/ipfs/${imageId}`
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return srcImage
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
private getUrlWithParams(params: any) {
|
|
98
|
-
const parameters = qs.stringify(
|
|
99
|
-
{
|
|
100
|
-
chain: GHOSTMARKET_CHAIN_BY_NETWORK_TYPE[this.networkType],
|
|
101
|
-
...params,
|
|
102
|
-
},
|
|
103
|
-
{ arrayFormat: 'bracket' }
|
|
104
|
-
)
|
|
105
|
-
return `${GHOSTMARKET_URL_BY_NETWORK_TYPE[this.networkType]}/assets?${parameters}`
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
private parse(data: GhostMarketNFT) {
|
|
109
|
-
const nftResponse: NftResponse = {
|
|
110
|
-
collectionImage: this.treatGhostMarketImage(data.collection?.logoUrl),
|
|
111
|
-
id: data.tokenId,
|
|
112
|
-
contractHash: data.contract.hash,
|
|
113
|
-
symbol: data.contract.symbol,
|
|
114
|
-
collectionName: data.collection?.name,
|
|
115
|
-
image: this.treatGhostMarketImage(data.metadata.mediaUri),
|
|
116
|
-
isSVG: String(data.metadata.mediaType).includes('svg+xml'),
|
|
117
|
-
name: data.metadata.name,
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return nftResponse
|
|
121
|
-
}
|
|
122
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
BlockchainService,
|
|
3
|
+
NftResponse,
|
|
4
|
+
NftsResponse,
|
|
5
|
+
NetworkType,
|
|
6
|
+
NftDataService,
|
|
7
|
+
GetNftParam,
|
|
8
|
+
GetNftsByAddressParams,
|
|
9
|
+
} from '@cityofzion/blockchain-service'
|
|
10
|
+
import qs from 'query-string'
|
|
11
|
+
|
|
12
|
+
import { GHOSTMARKET_CHAIN_BY_NETWORK_TYPE, GHOSTMARKET_URL_BY_NETWORK_TYPE } from './constants'
|
|
13
|
+
import fetch from 'node-fetch'
|
|
14
|
+
|
|
15
|
+
type GhostMarketNFT = {
|
|
16
|
+
tokenId: string
|
|
17
|
+
contract: {
|
|
18
|
+
chain?: string
|
|
19
|
+
hash: string
|
|
20
|
+
symbol: string
|
|
21
|
+
}
|
|
22
|
+
creator: {
|
|
23
|
+
address?: string
|
|
24
|
+
offchainName?: string
|
|
25
|
+
}
|
|
26
|
+
apiUrl?: string
|
|
27
|
+
ownerships: {
|
|
28
|
+
owner: {
|
|
29
|
+
address?: string
|
|
30
|
+
}
|
|
31
|
+
}[]
|
|
32
|
+
collection: {
|
|
33
|
+
name?: string
|
|
34
|
+
logoUrl?: string
|
|
35
|
+
}
|
|
36
|
+
metadata: {
|
|
37
|
+
description: string
|
|
38
|
+
mediaType: string
|
|
39
|
+
mediaUri: string
|
|
40
|
+
mintDate: number
|
|
41
|
+
mintNumber: number
|
|
42
|
+
name: string
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type GhostMarketAssets = {
|
|
47
|
+
assets: GhostMarketNFT[]
|
|
48
|
+
next: string
|
|
49
|
+
}
|
|
50
|
+
export class GhostMarketNDSEthereum implements NftDataService {
|
|
51
|
+
private networkType: NetworkType
|
|
52
|
+
|
|
53
|
+
constructor(networkType: NetworkType) {
|
|
54
|
+
this.networkType = networkType
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async getNftsByAddress({ address, size = 18, cursor, page }: GetNftsByAddressParams): Promise<NftsResponse> {
|
|
58
|
+
const url = this.getUrlWithParams({
|
|
59
|
+
size,
|
|
60
|
+
owners: [address],
|
|
61
|
+
cursor: cursor,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const request = await fetch(url, { method: 'GET' })
|
|
65
|
+
const data = (await request.json()) as GhostMarketAssets
|
|
66
|
+
const nfts = data.assets ?? []
|
|
67
|
+
|
|
68
|
+
return { nextCursor: data.next, items: nfts.map(this.parse.bind(this)) }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async getNft({ contractHash, tokenId }: GetNftParam): Promise<NftResponse> {
|
|
72
|
+
const url = this.getUrlWithParams({
|
|
73
|
+
contract: contractHash,
|
|
74
|
+
tokenIds: [tokenId],
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const request = await fetch(url, { method: 'GET' })
|
|
78
|
+
const data = (await request.json()) as GhostMarketAssets
|
|
79
|
+
|
|
80
|
+
return this.parse(data.assets[0])
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private treatGhostMarketImage(srcImage?: string) {
|
|
84
|
+
if (!srcImage) {
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (srcImage.startsWith('ipfs://')) {
|
|
89
|
+
const [, imageId] = srcImage.split('://')
|
|
90
|
+
|
|
91
|
+
return `https://ghostmarket.mypinata.cloud/ipfs/${imageId}`
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return srcImage
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private getUrlWithParams(params: any) {
|
|
98
|
+
const parameters = qs.stringify(
|
|
99
|
+
{
|
|
100
|
+
chain: GHOSTMARKET_CHAIN_BY_NETWORK_TYPE[this.networkType],
|
|
101
|
+
...params,
|
|
102
|
+
},
|
|
103
|
+
{ arrayFormat: 'bracket' }
|
|
104
|
+
)
|
|
105
|
+
return `${GHOSTMARKET_URL_BY_NETWORK_TYPE[this.networkType]}/assets?${parameters}`
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private parse(data: GhostMarketNFT) {
|
|
109
|
+
const nftResponse: NftResponse = {
|
|
110
|
+
collectionImage: this.treatGhostMarketImage(data.collection?.logoUrl),
|
|
111
|
+
id: data.tokenId,
|
|
112
|
+
contractHash: data.contract.hash,
|
|
113
|
+
symbol: data.contract.symbol,
|
|
114
|
+
collectionName: data.collection?.name,
|
|
115
|
+
image: this.treatGhostMarketImage(data.metadata.mediaUri),
|
|
116
|
+
isSVG: String(data.metadata.mediaType).includes('svg+xml'),
|
|
117
|
+
name: data.metadata.name,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return nftResponse
|
|
121
|
+
}
|
|
122
|
+
}
|
package/src/RpcBDSEthereum.ts
CHANGED
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BalanceResponse,
|
|
3
|
-
BlockchainDataService,
|
|
4
|
-
ContractResponse,
|
|
5
|
-
Network,
|
|
6
|
-
Token,
|
|
7
|
-
TransactionResponse,
|
|
8
|
-
TransactionsByAddressParams,
|
|
9
|
-
TransactionsByAddressResponse,
|
|
10
|
-
} from '@cityofzion/blockchain-service'
|
|
11
|
-
import { ethers } from 'ethers'
|
|
12
|
-
import { TOKENS } from './constants'
|
|
13
|
-
|
|
14
|
-
export class RpcBDSEthereum implements BlockchainDataService {
|
|
15
|
-
private readonly network: Network
|
|
16
|
-
|
|
17
|
-
maxTimeToConfirmTransactionInMs: number = 1000 * 60 * 5
|
|
18
|
-
|
|
19
|
-
constructor(network: Network) {
|
|
20
|
-
this.network = network
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async getTransaction(hash: string): Promise<TransactionResponse> {
|
|
24
|
-
const provider = new ethers.providers.JsonRpcProvider(this.network.url)
|
|
25
|
-
|
|
26
|
-
const transaction = await provider.getTransaction(hash)
|
|
27
|
-
if (!transaction || !transaction.blockHash || !transaction.to) throw new Error('Transaction not found')
|
|
28
|
-
|
|
29
|
-
const block = await provider.getBlock(transaction.blockHash)
|
|
30
|
-
if (!block) throw new Error('Block not found')
|
|
31
|
-
|
|
32
|
-
const tokens = TOKENS[this.network.type]
|
|
33
|
-
const token = tokens.find(token => token.symbol === 'ETH')!
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
block: block.number,
|
|
37
|
-
time: block.timestamp,
|
|
38
|
-
hash: transaction.hash,
|
|
39
|
-
transfers: [
|
|
40
|
-
{
|
|
41
|
-
type: 'token',
|
|
42
|
-
amount: ethers.utils.formatEther(transaction.value),
|
|
43
|
-
contractHash: '-',
|
|
44
|
-
from: transaction.from,
|
|
45
|
-
to: transaction.to,
|
|
46
|
-
token,
|
|
47
|
-
},
|
|
48
|
-
],
|
|
49
|
-
notifications: [],
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async getTransactionsByAddress(_params: TransactionsByAddressParams): Promise<TransactionsByAddressResponse> {
|
|
54
|
-
throw new Error("RPC doesn't support get transactions history of address")
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async getContract(): Promise<ContractResponse> {
|
|
58
|
-
throw new Error("RPC doesn't support contract info")
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async getTokenInfo(hash: string): Promise<Token> {
|
|
62
|
-
const tokens = TOKENS[this.network.type]
|
|
63
|
-
const token = tokens.find(token => token.hash === hash)
|
|
64
|
-
if (!token) throw new Error('Token not found')
|
|
65
|
-
|
|
66
|
-
return token
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async getBalance(address: string): Promise<BalanceResponse[]> {
|
|
70
|
-
const provider = new ethers.providers.JsonRpcProvider(this.network.url)
|
|
71
|
-
const balance = await provider.getBalance(address)
|
|
72
|
-
|
|
73
|
-
const tokens = TOKENS[this.network.type]
|
|
74
|
-
const token = tokens.find(token => token.symbol === 'ETH')!
|
|
75
|
-
|
|
76
|
-
return [
|
|
77
|
-
{
|
|
78
|
-
amount: ethers.utils.formatEther(balance),
|
|
79
|
-
token,
|
|
80
|
-
},
|
|
81
|
-
]
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async getBlockHeight(): Promise<number> {
|
|
85
|
-
const provider = new ethers.providers.JsonRpcProvider(this.network.url)
|
|
86
|
-
return await provider.getBlockNumber()
|
|
87
|
-
}
|
|
88
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
BalanceResponse,
|
|
3
|
+
BlockchainDataService,
|
|
4
|
+
ContractResponse,
|
|
5
|
+
Network,
|
|
6
|
+
Token,
|
|
7
|
+
TransactionResponse,
|
|
8
|
+
TransactionsByAddressParams,
|
|
9
|
+
TransactionsByAddressResponse,
|
|
10
|
+
} from '@cityofzion/blockchain-service'
|
|
11
|
+
import { ethers } from 'ethers'
|
|
12
|
+
import { TOKENS } from './constants'
|
|
13
|
+
|
|
14
|
+
export class RpcBDSEthereum implements BlockchainDataService {
|
|
15
|
+
private readonly network: Network
|
|
16
|
+
|
|
17
|
+
maxTimeToConfirmTransactionInMs: number = 1000 * 60 * 5
|
|
18
|
+
|
|
19
|
+
constructor(network: Network) {
|
|
20
|
+
this.network = network
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async getTransaction(hash: string): Promise<TransactionResponse> {
|
|
24
|
+
const provider = new ethers.providers.JsonRpcProvider(this.network.url)
|
|
25
|
+
|
|
26
|
+
const transaction = await provider.getTransaction(hash)
|
|
27
|
+
if (!transaction || !transaction.blockHash || !transaction.to) throw new Error('Transaction not found')
|
|
28
|
+
|
|
29
|
+
const block = await provider.getBlock(transaction.blockHash)
|
|
30
|
+
if (!block) throw new Error('Block not found')
|
|
31
|
+
|
|
32
|
+
const tokens = TOKENS[this.network.type]
|
|
33
|
+
const token = tokens.find(token => token.symbol === 'ETH')!
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
block: block.number,
|
|
37
|
+
time: block.timestamp,
|
|
38
|
+
hash: transaction.hash,
|
|
39
|
+
transfers: [
|
|
40
|
+
{
|
|
41
|
+
type: 'token',
|
|
42
|
+
amount: ethers.utils.formatEther(transaction.value),
|
|
43
|
+
contractHash: '-',
|
|
44
|
+
from: transaction.from,
|
|
45
|
+
to: transaction.to,
|
|
46
|
+
token,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
notifications: [],
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async getTransactionsByAddress(_params: TransactionsByAddressParams): Promise<TransactionsByAddressResponse> {
|
|
54
|
+
throw new Error("RPC doesn't support get transactions history of address")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async getContract(): Promise<ContractResponse> {
|
|
58
|
+
throw new Error("RPC doesn't support contract info")
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async getTokenInfo(hash: string): Promise<Token> {
|
|
62
|
+
const tokens = TOKENS[this.network.type]
|
|
63
|
+
const token = tokens.find(token => token.hash === hash)
|
|
64
|
+
if (!token) throw new Error('Token not found')
|
|
65
|
+
|
|
66
|
+
return token
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async getBalance(address: string): Promise<BalanceResponse[]> {
|
|
70
|
+
const provider = new ethers.providers.JsonRpcProvider(this.network.url)
|
|
71
|
+
const balance = await provider.getBalance(address)
|
|
72
|
+
|
|
73
|
+
const tokens = TOKENS[this.network.type]
|
|
74
|
+
const token = tokens.find(token => token.symbol === 'ETH')!
|
|
75
|
+
|
|
76
|
+
return [
|
|
77
|
+
{
|
|
78
|
+
amount: ethers.utils.formatEther(balance),
|
|
79
|
+
token,
|
|
80
|
+
},
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async getBlockHeight(): Promise<number> {
|
|
85
|
+
const provider = new ethers.providers.JsonRpcProvider(this.network.url)
|
|
86
|
+
return await provider.getBlockNumber()
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -1,123 +1,123 @@
|
|
|
1
|
-
import { BDSClaimable, BlockchainDataService } from '@cityofzion/blockchain-service'
|
|
2
|
-
import { BitqueryBDSEthereum } from '../BitqueryBDSEthereum'
|
|
3
|
-
import { RpcBDSEthereum } from '../RpcBDSEthereum'
|
|
4
|
-
import { DEFAULT_URL_BY_NETWORK_TYPE } from '../constants'
|
|
5
|
-
|
|
6
|
-
const bitqueryBDSEthereum = new BitqueryBDSEthereum({ type: 'testnet', url: DEFAULT_URL_BY_NETWORK_TYPE.testnet })
|
|
7
|
-
const rpcBDSEthereum = new RpcBDSEthereum({ type: 'testnet', url: DEFAULT_URL_BY_NETWORK_TYPE.testnet })
|
|
8
|
-
|
|
9
|
-
describe('BDSEthereum', () => {
|
|
10
|
-
it.each([rpcBDSEthereum, bitqueryBDSEthereum])(
|
|
11
|
-
'Should be able to get transaction - %s',
|
|
12
|
-
async (BDSEthereum: BlockchainDataService) => {
|
|
13
|
-
const hash = '0x43fa3015d077a13888409cfbd6228df8900abcd5314ff11ea6ce0c49e8b7c94d'
|
|
14
|
-
const transaction = await BDSEthereum.getTransaction(hash)
|
|
15
|
-
|
|
16
|
-
expect(transaction).toEqual(
|
|
17
|
-
expect.objectContaining({
|
|
18
|
-
block: expect.any(Number),
|
|
19
|
-
hash,
|
|
20
|
-
notifications: [],
|
|
21
|
-
time: expect.any(Number),
|
|
22
|
-
})
|
|
23
|
-
)
|
|
24
|
-
transaction.transfers.forEach(transfer => {
|
|
25
|
-
expect(transfer).toEqual(
|
|
26
|
-
expect.objectContaining({
|
|
27
|
-
from: expect.any(String),
|
|
28
|
-
to: expect.any(String),
|
|
29
|
-
contractHash: expect.any(String),
|
|
30
|
-
amount: expect.any(String),
|
|
31
|
-
type: expect.any(String),
|
|
32
|
-
})
|
|
33
|
-
)
|
|
34
|
-
})
|
|
35
|
-
},
|
|
36
|
-
10000
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
it.each([bitqueryBDSEthereum])(
|
|
40
|
-
'Should be able to get transactions of address - %s',
|
|
41
|
-
async (BDSEthereum: BlockchainDataService) => {
|
|
42
|
-
const address = '0x82B5Cd984880C8A821429cFFf89f36D35BaeBE89'
|
|
43
|
-
const response = await BDSEthereum.getTransactionsByAddress({ address: address, page: 1 })
|
|
44
|
-
expect(response.totalCount).toBeGreaterThan(0)
|
|
45
|
-
response.transactions.forEach(transaction => {
|
|
46
|
-
expect(transaction).toEqual(
|
|
47
|
-
expect.objectContaining({
|
|
48
|
-
block: expect.any(Number),
|
|
49
|
-
hash: expect.any(String),
|
|
50
|
-
notifications: [],
|
|
51
|
-
time: expect.any(Number),
|
|
52
|
-
fee: expect.any(String),
|
|
53
|
-
})
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
transaction.transfers.forEach(transfer => {
|
|
57
|
-
expect(transfer).toEqual(
|
|
58
|
-
expect.objectContaining({
|
|
59
|
-
from: expect.any(String),
|
|
60
|
-
to: expect.any(String),
|
|
61
|
-
contractHash: expect.any(String),
|
|
62
|
-
amount: expect.any(String),
|
|
63
|
-
type: expect.any(String),
|
|
64
|
-
})
|
|
65
|
-
)
|
|
66
|
-
})
|
|
67
|
-
})
|
|
68
|
-
},
|
|
69
|
-
10000
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
it.each([bitqueryBDSEthereum, rpcBDSEthereum])(
|
|
73
|
-
'Should be able to get eth info - %s',
|
|
74
|
-
async (BDSEthereum: BlockchainDataService) => {
|
|
75
|
-
const hash = '-'
|
|
76
|
-
const token = await BDSEthereum.getTokenInfo(hash)
|
|
77
|
-
|
|
78
|
-
expect(token).toEqual({
|
|
79
|
-
symbol: 'ETH',
|
|
80
|
-
name: 'Ethereum',
|
|
81
|
-
hash: '-',
|
|
82
|
-
decimals: 16,
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
it.each([bitqueryBDSEthereum])(
|
|
88
|
-
'Should be able to get token info - %s',
|
|
89
|
-
async (BDSEthereum: BlockchainDataService) => {
|
|
90
|
-
const hash = '0xBA62BCfcAaFc6622853cca2BE6Ac7d845BC0f2Dc'
|
|
91
|
-
const token = await BDSEthereum.getTokenInfo(hash)
|
|
92
|
-
|
|
93
|
-
expect(token).toEqual({
|
|
94
|
-
hash: '0xba62bcfcaafc6622853cca2be6ac7d845bc0f2dc',
|
|
95
|
-
name: 'FaucetToken',
|
|
96
|
-
symbol: 'FAU',
|
|
97
|
-
decimals: 18,
|
|
98
|
-
})
|
|
99
|
-
}
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
it.each([bitqueryBDSEthereum, rpcBDSEthereum])(
|
|
103
|
-
'Should be able to get balance - %s',
|
|
104
|
-
async (BDSEthereum: BlockchainDataService) => {
|
|
105
|
-
const address = '0x82B5Cd984880C8A821429cFFf89f36D35BaeBE89'
|
|
106
|
-
const balance = await BDSEthereum.getBalance(address)
|
|
107
|
-
|
|
108
|
-
balance.forEach(balance => {
|
|
109
|
-
expect(balance).toEqual(
|
|
110
|
-
expect.objectContaining({
|
|
111
|
-
amount: expect.any(String),
|
|
112
|
-
token: {
|
|
113
|
-
hash: expect.any(String),
|
|
114
|
-
name: expect.any(String),
|
|
115
|
-
symbol: expect.any(String),
|
|
116
|
-
decimals: expect.any(Number),
|
|
117
|
-
},
|
|
118
|
-
})
|
|
119
|
-
)
|
|
120
|
-
})
|
|
121
|
-
}
|
|
122
|
-
)
|
|
123
|
-
})
|
|
1
|
+
import { BDSClaimable, BlockchainDataService } from '@cityofzion/blockchain-service'
|
|
2
|
+
import { BitqueryBDSEthereum } from '../BitqueryBDSEthereum'
|
|
3
|
+
import { RpcBDSEthereum } from '../RpcBDSEthereum'
|
|
4
|
+
import { DEFAULT_URL_BY_NETWORK_TYPE } from '../constants'
|
|
5
|
+
|
|
6
|
+
const bitqueryBDSEthereum = new BitqueryBDSEthereum({ type: 'testnet', url: DEFAULT_URL_BY_NETWORK_TYPE.testnet })
|
|
7
|
+
const rpcBDSEthereum = new RpcBDSEthereum({ type: 'testnet', url: DEFAULT_URL_BY_NETWORK_TYPE.testnet })
|
|
8
|
+
|
|
9
|
+
describe('BDSEthereum', () => {
|
|
10
|
+
it.each([rpcBDSEthereum, bitqueryBDSEthereum])(
|
|
11
|
+
'Should be able to get transaction - %s',
|
|
12
|
+
async (BDSEthereum: BlockchainDataService) => {
|
|
13
|
+
const hash = '0x43fa3015d077a13888409cfbd6228df8900abcd5314ff11ea6ce0c49e8b7c94d'
|
|
14
|
+
const transaction = await BDSEthereum.getTransaction(hash)
|
|
15
|
+
|
|
16
|
+
expect(transaction).toEqual(
|
|
17
|
+
expect.objectContaining({
|
|
18
|
+
block: expect.any(Number),
|
|
19
|
+
hash,
|
|
20
|
+
notifications: [],
|
|
21
|
+
time: expect.any(Number),
|
|
22
|
+
})
|
|
23
|
+
)
|
|
24
|
+
transaction.transfers.forEach(transfer => {
|
|
25
|
+
expect(transfer).toEqual(
|
|
26
|
+
expect.objectContaining({
|
|
27
|
+
from: expect.any(String),
|
|
28
|
+
to: expect.any(String),
|
|
29
|
+
contractHash: expect.any(String),
|
|
30
|
+
amount: expect.any(String),
|
|
31
|
+
type: expect.any(String),
|
|
32
|
+
})
|
|
33
|
+
)
|
|
34
|
+
})
|
|
35
|
+
},
|
|
36
|
+
10000
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
it.each([bitqueryBDSEthereum])(
|
|
40
|
+
'Should be able to get transactions of address - %s',
|
|
41
|
+
async (BDSEthereum: BlockchainDataService) => {
|
|
42
|
+
const address = '0x82B5Cd984880C8A821429cFFf89f36D35BaeBE89'
|
|
43
|
+
const response = await BDSEthereum.getTransactionsByAddress({ address: address, page: 1 })
|
|
44
|
+
expect(response.totalCount).toBeGreaterThan(0)
|
|
45
|
+
response.transactions.forEach(transaction => {
|
|
46
|
+
expect(transaction).toEqual(
|
|
47
|
+
expect.objectContaining({
|
|
48
|
+
block: expect.any(Number),
|
|
49
|
+
hash: expect.any(String),
|
|
50
|
+
notifications: [],
|
|
51
|
+
time: expect.any(Number),
|
|
52
|
+
fee: expect.any(String),
|
|
53
|
+
})
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
transaction.transfers.forEach(transfer => {
|
|
57
|
+
expect(transfer).toEqual(
|
|
58
|
+
expect.objectContaining({
|
|
59
|
+
from: expect.any(String),
|
|
60
|
+
to: expect.any(String),
|
|
61
|
+
contractHash: expect.any(String),
|
|
62
|
+
amount: expect.any(String),
|
|
63
|
+
type: expect.any(String),
|
|
64
|
+
})
|
|
65
|
+
)
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
},
|
|
69
|
+
10000
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
it.each([bitqueryBDSEthereum, rpcBDSEthereum])(
|
|
73
|
+
'Should be able to get eth info - %s',
|
|
74
|
+
async (BDSEthereum: BlockchainDataService) => {
|
|
75
|
+
const hash = '-'
|
|
76
|
+
const token = await BDSEthereum.getTokenInfo(hash)
|
|
77
|
+
|
|
78
|
+
expect(token).toEqual({
|
|
79
|
+
symbol: 'ETH',
|
|
80
|
+
name: 'Ethereum',
|
|
81
|
+
hash: '-',
|
|
82
|
+
decimals: 16,
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
it.each([bitqueryBDSEthereum])(
|
|
88
|
+
'Should be able to get token info - %s',
|
|
89
|
+
async (BDSEthereum: BlockchainDataService) => {
|
|
90
|
+
const hash = '0xBA62BCfcAaFc6622853cca2BE6Ac7d845BC0f2Dc'
|
|
91
|
+
const token = await BDSEthereum.getTokenInfo(hash)
|
|
92
|
+
|
|
93
|
+
expect(token).toEqual({
|
|
94
|
+
hash: '0xba62bcfcaafc6622853cca2be6ac7d845bc0f2dc',
|
|
95
|
+
name: 'FaucetToken',
|
|
96
|
+
symbol: 'FAU',
|
|
97
|
+
decimals: 18,
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
it.each([bitqueryBDSEthereum, rpcBDSEthereum])(
|
|
103
|
+
'Should be able to get balance - %s',
|
|
104
|
+
async (BDSEthereum: BlockchainDataService) => {
|
|
105
|
+
const address = '0x82B5Cd984880C8A821429cFFf89f36D35BaeBE89'
|
|
106
|
+
const balance = await BDSEthereum.getBalance(address)
|
|
107
|
+
|
|
108
|
+
balance.forEach(balance => {
|
|
109
|
+
expect(balance).toEqual(
|
|
110
|
+
expect.objectContaining({
|
|
111
|
+
amount: expect.any(String),
|
|
112
|
+
token: {
|
|
113
|
+
hash: expect.any(String),
|
|
114
|
+
name: expect.any(String),
|
|
115
|
+
symbol: expect.any(String),
|
|
116
|
+
decimals: expect.any(Number),
|
|
117
|
+
},
|
|
118
|
+
})
|
|
119
|
+
)
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
)
|
|
123
|
+
})
|