@cityofzion/bs-neo-legacy 0.9.3 → 0.10.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.
- package/dist/CryptoCompareEDSNeoLegacy.d.ts +1 -1
- package/dist/CryptoCompareEDSNeoLegacy.js +16 -2
- package/dist/DoraBDSNeoLegacy.d.ts +1 -4
- package/dist/DoraBDSNeoLegacy.js +33 -17
- package/dist/DoraESNeoLegacy.d.ts +1 -1
- package/dist/DoraESNeoLegacy.js +17 -3
- package/package.json +6 -3
- package/.eslintignore +0 -13
- package/.eslintrc.cjs +0 -22
- package/.rush/temp/operation/build/all.log +0 -1
- package/.rush/temp/operation/build/state.json +0 -3
- package/.rush/temp/package-deps_build.json +0 -27
- package/.rush/temp/shrinkwrap-deps.json +0 -435
- package/CHANGELOG.json +0 -64
- package/CHANGELOG.md +0 -30
- package/bs-neo-legacy.build.log +0 -1
- package/jest.config.ts +0 -13
- package/jest.setup.ts +0 -1
- package/src/BSNeoLegacy.ts +0 -202
- package/src/CryptoCompareEDSNeoLegacy.ts +0 -50
- package/src/DoraBDSNeoLegacy.ts +0 -176
- package/src/DoraESNeoLegacy.ts +0 -18
- package/src/__tests__/BDSNeoLegacy.spec.ts +0 -123
- package/src/__tests__/BSNeoLegacy.spec.ts +0 -134
- package/src/__tests__/CryptoCompareExchange.spec.ts +0 -48
- package/src/__tests__/DoraESNeoLegacy.spec.ts +0 -15
- package/src/assets/tokens/common.json +0 -14
- package/src/assets/tokens/mainnet.json +0 -466
- package/src/constants.ts +0 -23
- package/src/index.ts +0 -4
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -14
package/src/BSNeoLegacy.ts
DELETED
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Account,
|
|
3
|
-
BDSClaimable,
|
|
4
|
-
BlockchainDataService,
|
|
5
|
-
BlockchainService,
|
|
6
|
-
BSClaimable,
|
|
7
|
-
ExchangeDataService,
|
|
8
|
-
Token,
|
|
9
|
-
Network,
|
|
10
|
-
PartialBy,
|
|
11
|
-
TransferParam,
|
|
12
|
-
AccountWithDerivationPath,
|
|
13
|
-
BSWithExplorerService,
|
|
14
|
-
ExplorerService,
|
|
15
|
-
} from '@cityofzion/blockchain-service'
|
|
16
|
-
import { api, sc, u, wallet } from '@cityofzion/neon-js'
|
|
17
|
-
import {
|
|
18
|
-
DEFAULT_URL_BY_NETWORK_TYPE,
|
|
19
|
-
DERIVATION_PATH,
|
|
20
|
-
LEGACY_NETWORK_BY_NETWORK_TYPE,
|
|
21
|
-
NATIVE_ASSETS,
|
|
22
|
-
TOKENS,
|
|
23
|
-
} from './constants'
|
|
24
|
-
import { DoraBDSNeoLegacy } from './DoraBDSNeoLegacy'
|
|
25
|
-
import { CryptoCompareEDSNeoLegacy } from './CryptoCompareEDSNeoLegacy'
|
|
26
|
-
import { keychain } from '@cityofzion/bs-asteroid-sdk'
|
|
27
|
-
import { DoraESNeoLegacy } from './DoraESNeoLegacy'
|
|
28
|
-
|
|
29
|
-
export class BSNeoLegacy<BSCustomName extends string = string>
|
|
30
|
-
implements BlockchainService, BSClaimable, BSWithExplorerService
|
|
31
|
-
{
|
|
32
|
-
readonly blockchainName: BSCustomName
|
|
33
|
-
readonly feeToken: Token
|
|
34
|
-
readonly claimToken: Token
|
|
35
|
-
readonly burnToken: Token
|
|
36
|
-
readonly derivationPath: string
|
|
37
|
-
|
|
38
|
-
blockchainDataService!: BlockchainDataService & BDSClaimable
|
|
39
|
-
exchangeDataService!: ExchangeDataService
|
|
40
|
-
explorerService!: ExplorerService
|
|
41
|
-
tokens: Token[]
|
|
42
|
-
network!: Network
|
|
43
|
-
legacyNetwork: string
|
|
44
|
-
|
|
45
|
-
constructor(blockchainName: BSCustomName, network: PartialBy<Network, 'url'>) {
|
|
46
|
-
if (network.type === 'custom') throw new Error('Custom network is not supported for NEO Legacy')
|
|
47
|
-
|
|
48
|
-
this.blockchainName = blockchainName
|
|
49
|
-
this.legacyNetwork = LEGACY_NETWORK_BY_NETWORK_TYPE[network.type]
|
|
50
|
-
this.derivationPath = DERIVATION_PATH
|
|
51
|
-
this.tokens = TOKENS[network.type]
|
|
52
|
-
this.claimToken = this.tokens.find(token => token.symbol === 'GAS')!
|
|
53
|
-
this.burnToken = this.tokens.find(token => token.symbol === 'NEO')!
|
|
54
|
-
this.feeToken = this.tokens.find(token => token.symbol === 'GAS')!
|
|
55
|
-
this.setNetwork(network)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
setNetwork(param: PartialBy<Network, 'url'>) {
|
|
59
|
-
if (param.type === 'custom') throw new Error('Custom network is not supported for NEO Legacy')
|
|
60
|
-
|
|
61
|
-
const network = {
|
|
62
|
-
type: param.type,
|
|
63
|
-
url: param.url ?? DEFAULT_URL_BY_NETWORK_TYPE[param.type],
|
|
64
|
-
}
|
|
65
|
-
this.network = network
|
|
66
|
-
this.blockchainDataService = new DoraBDSNeoLegacy(network, this.feeToken, this.claimToken)
|
|
67
|
-
this.exchangeDataService = new CryptoCompareEDSNeoLegacy(network.type)
|
|
68
|
-
this.explorerService = new DoraESNeoLegacy(network.type)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
validateAddress(address: string): boolean {
|
|
72
|
-
return wallet.isAddress(address)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
validateEncrypted(key: string): boolean {
|
|
76
|
-
return wallet.isNEP2(key)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
validateKey(key: string): boolean {
|
|
80
|
-
return wallet.isWIF(key) || wallet.isPrivateKey(key)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
generateAccountFromMnemonic(mnemonic: string[] | string, index: number): AccountWithDerivationPath {
|
|
84
|
-
keychain.importMnemonic(Array.isArray(mnemonic) ? mnemonic.join(' ') : mnemonic)
|
|
85
|
-
const path = this.derivationPath.replace('?', index.toString())
|
|
86
|
-
const childKey = keychain.generateChildKey('neo', path)
|
|
87
|
-
const key = childKey.getWIF()
|
|
88
|
-
const { address } = new wallet.Account(key)
|
|
89
|
-
return { address, key, type: 'wif', derivationPath: path }
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
generateAccountFromKey(key: string): Account {
|
|
93
|
-
const type = wallet.isWIF(key) ? 'wif' : wallet.isPrivateKey(key) ? 'privateKey' : undefined
|
|
94
|
-
if (!type) throw new Error('Invalid key')
|
|
95
|
-
|
|
96
|
-
const { address } = new wallet.Account(key)
|
|
97
|
-
return { address, key, type }
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async decrypt(encryptedKey: string, password: string): Promise<Account> {
|
|
101
|
-
let BsReactNativeDecrypt: any
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
const { NativeModules } = require('react-native')
|
|
105
|
-
BsReactNativeDecrypt = NativeModules.BsReactNativeDecrypt
|
|
106
|
-
|
|
107
|
-
if (!BsReactNativeDecrypt) {
|
|
108
|
-
throw new Error('@CityOfZion/bs-react-native-decrypt is not installed')
|
|
109
|
-
}
|
|
110
|
-
} catch {
|
|
111
|
-
const key = await wallet.decrypt(encryptedKey, password)
|
|
112
|
-
return this.generateAccountFromKey(key)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const privateKey = await BsReactNativeDecrypt.decryptNeoLegacy(encryptedKey, password)
|
|
116
|
-
return this.generateAccountFromKey(privateKey)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
encrypt(key: string, password: string): Promise<string> {
|
|
120
|
-
return wallet.encrypt(key, password)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async transfer({ intent: transferIntent, senderAccount, tipIntent, ...params }: TransferParam): Promise<string> {
|
|
124
|
-
const apiProvider = new api.neoCli.instance(this.network.url)
|
|
125
|
-
const account = new wallet.Account(senderAccount.key)
|
|
126
|
-
const priorityFee = Number(params.priorityFee ?? 0)
|
|
127
|
-
|
|
128
|
-
const nativeIntents: ReturnType<typeof api.makeIntent> = []
|
|
129
|
-
const nep5ScriptBuilder = new sc.ScriptBuilder()
|
|
130
|
-
|
|
131
|
-
const intents = [transferIntent, ...(tipIntent ? [tipIntent] : [])]
|
|
132
|
-
|
|
133
|
-
for (const intent of intents) {
|
|
134
|
-
const tokenHashFixed = intent.tokenHash.replace('0x', '')
|
|
135
|
-
|
|
136
|
-
const nativeAsset = NATIVE_ASSETS.find(asset => asset.hash === tokenHashFixed)
|
|
137
|
-
if (nativeAsset) {
|
|
138
|
-
nativeIntents.push(...api.makeIntent({ [nativeAsset.symbol]: Number(intent.amount) }, intent.receiverAddress))
|
|
139
|
-
continue
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
nep5ScriptBuilder.emitAppCall(tokenHashFixed, 'transfer', [
|
|
143
|
-
u.reverseHex(wallet.getScriptHashFromAddress(account.address)),
|
|
144
|
-
u.reverseHex(wallet.getScriptHashFromAddress(intent.receiverAddress)),
|
|
145
|
-
sc.ContractParam.integer(
|
|
146
|
-
new u.Fixed8(intent.amount)
|
|
147
|
-
.div(Math.pow(10, 8 - (intent.tokenDecimals ?? 8)))
|
|
148
|
-
.toRawNumber()
|
|
149
|
-
.toString()
|
|
150
|
-
),
|
|
151
|
-
])
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
let response
|
|
155
|
-
|
|
156
|
-
if (nep5ScriptBuilder.isEmpty()) {
|
|
157
|
-
response = await api.sendAsset({
|
|
158
|
-
account,
|
|
159
|
-
api: apiProvider,
|
|
160
|
-
url: this.network.url,
|
|
161
|
-
intents: nativeIntents,
|
|
162
|
-
fees: priorityFee,
|
|
163
|
-
})
|
|
164
|
-
} else {
|
|
165
|
-
response = await api.doInvoke({
|
|
166
|
-
intents: nativeIntents.length > 0 ? nativeIntents : undefined,
|
|
167
|
-
account,
|
|
168
|
-
api: apiProvider,
|
|
169
|
-
script: nep5ScriptBuilder.str,
|
|
170
|
-
url: this.network.url,
|
|
171
|
-
fees: priorityFee,
|
|
172
|
-
})
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (!response.tx) throw new Error('Failed to send transaction')
|
|
176
|
-
return response.tx.hash
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
async claim(account: Account): Promise<string> {
|
|
180
|
-
const neoAccount = new wallet.Account(account.key)
|
|
181
|
-
|
|
182
|
-
const balances = await this.blockchainDataService.getBalance(account.address)
|
|
183
|
-
const neoBalance = balances.find(balance => balance.token.symbol === 'NEO')
|
|
184
|
-
if (!neoBalance) throw new Error('It is necessary to have NEO to claim')
|
|
185
|
-
|
|
186
|
-
const unclaimed = await this.blockchainDataService.getUnclaimed(account.address)
|
|
187
|
-
if (Number(unclaimed) <= 0) throw new Error(`Doesn't have gas to claim`)
|
|
188
|
-
|
|
189
|
-
const apiProvider = new api.neoCli.instance(this.legacyNetwork)
|
|
190
|
-
const claims = await apiProvider.getClaims(account.address)
|
|
191
|
-
|
|
192
|
-
const response = await api.claimGas({
|
|
193
|
-
claims,
|
|
194
|
-
api: apiProvider,
|
|
195
|
-
account: neoAccount,
|
|
196
|
-
url: this.network.url,
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
if (!response.tx) throw new Error('Failed to claim')
|
|
200
|
-
return response.tx.hash
|
|
201
|
-
}
|
|
202
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { Currency, ExchangeDataService, NetworkType, TokenPricesResponse } from '@cityofzion/blockchain-service'
|
|
2
|
-
import axios, { AxiosInstance } from 'axios'
|
|
3
|
-
import { TOKENS } from './constants'
|
|
4
|
-
|
|
5
|
-
type CryptoCompareDataResponse = {
|
|
6
|
-
RAW: {
|
|
7
|
-
[symbol: string]: {
|
|
8
|
-
[currency: string]: {
|
|
9
|
-
PRICE: number
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export class CryptoCompareEDSNeoLegacy implements ExchangeDataService {
|
|
16
|
-
networkType: NetworkType
|
|
17
|
-
private axiosInstance: AxiosInstance
|
|
18
|
-
|
|
19
|
-
constructor(network: NetworkType) {
|
|
20
|
-
this.networkType = network
|
|
21
|
-
this.axiosInstance = axios.create({ baseURL: 'https://min-api.cryptocompare.com' })
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async getTokenPrices(currency: Currency): Promise<TokenPricesResponse[]> {
|
|
25
|
-
if (this.networkType !== 'mainnet') throw new Error('Exchange is only available on mainnet')
|
|
26
|
-
|
|
27
|
-
const tokens = TOKENS[this.networkType]
|
|
28
|
-
const tokenSymbols = tokens.map(token => token.symbol)
|
|
29
|
-
const { data: prices } = await this.axiosInstance.get<CryptoCompareDataResponse>('/data/pricemultifull', {
|
|
30
|
-
params: {
|
|
31
|
-
fsyms: tokenSymbols.join(','),
|
|
32
|
-
tsyms: currency,
|
|
33
|
-
},
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
return Object.entries(prices.RAW)
|
|
37
|
-
.map(([symbol, priceObject]) => {
|
|
38
|
-
const price = priceObject[currency].PRICE
|
|
39
|
-
const token = tokens.find(token => token.symbol === symbol)
|
|
40
|
-
if (!token || !price) return
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
symbol,
|
|
44
|
-
price,
|
|
45
|
-
hash: token?.hash,
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
.filter((price): price is TokenPricesResponse => price !== undefined)
|
|
49
|
-
}
|
|
50
|
-
}
|
package/src/DoraBDSNeoLegacy.ts
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BalanceResponse,
|
|
3
|
-
BlockchainDataService,
|
|
4
|
-
ContractResponse,
|
|
5
|
-
TransactionsByAddressParams,
|
|
6
|
-
TransactionsByAddressResponse,
|
|
7
|
-
TransactionResponse,
|
|
8
|
-
BDSClaimable,
|
|
9
|
-
TransactionTransferAsset,
|
|
10
|
-
Token,
|
|
11
|
-
Network,
|
|
12
|
-
} from '@cityofzion/blockchain-service'
|
|
13
|
-
import { api } from '@cityofzion/dora-ts'
|
|
14
|
-
import { TOKENS } from './constants'
|
|
15
|
-
import { rpc } from '@cityofzion/neon-js'
|
|
16
|
-
|
|
17
|
-
export class DoraBDSNeoLegacy implements BlockchainDataService, BDSClaimable {
|
|
18
|
-
readonly network: Network
|
|
19
|
-
private readonly claimToken: Token
|
|
20
|
-
private readonly feeToken: Token
|
|
21
|
-
private readonly tokenCache: Map<string, Token> = new Map()
|
|
22
|
-
|
|
23
|
-
maxTimeToConfirmTransactionInMs: number = 1000 * 60 * 2
|
|
24
|
-
|
|
25
|
-
constructor(network: Network, feeToken: Token, claimToken: Token) {
|
|
26
|
-
if (network.type === 'custom') throw new Error('Custom network is not supported for NEO Legacy')
|
|
27
|
-
this.network = network
|
|
28
|
-
this.claimToken = claimToken
|
|
29
|
-
this.feeToken = feeToken
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async getTransaction(hash: string): Promise<TransactionResponse> {
|
|
33
|
-
const data = await api.NeoLegacyREST.transaction(hash, this.network.type)
|
|
34
|
-
if (!data || 'error' in data) throw new Error(`Transaction ${hash} not found`)
|
|
35
|
-
|
|
36
|
-
const vout: any[] = data.vout ?? []
|
|
37
|
-
|
|
38
|
-
const promises = vout.map<Promise<TransactionTransferAsset>>(async (transfer, _index, array) => {
|
|
39
|
-
const token = await this.getTokenInfo(transfer.asset)
|
|
40
|
-
return {
|
|
41
|
-
amount: String(transfer.value),
|
|
42
|
-
from: array[array.length - 1]?.address,
|
|
43
|
-
contractHash: transfer.asset,
|
|
44
|
-
to: transfer.address,
|
|
45
|
-
type: 'token',
|
|
46
|
-
token,
|
|
47
|
-
}
|
|
48
|
-
})
|
|
49
|
-
const transfers = await Promise.all(promises)
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
hash: data.txid,
|
|
53
|
-
block: data.block,
|
|
54
|
-
fee: (Number(data.sys_fee ?? 0) + Number(data.net_fee ?? 0)).toFixed(this.feeToken.decimals),
|
|
55
|
-
time: Number(data.time),
|
|
56
|
-
notifications: [], //neoLegacy doesn't have notifications
|
|
57
|
-
transfers,
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async getTransactionsByAddress({
|
|
62
|
-
address,
|
|
63
|
-
page = 1,
|
|
64
|
-
}: TransactionsByAddressParams): Promise<TransactionsByAddressResponse> {
|
|
65
|
-
const data = await api.NeoLegacyREST.getAddressAbstracts(address, page, this.network.type)
|
|
66
|
-
const transactions = new Map<string, TransactionResponse>()
|
|
67
|
-
|
|
68
|
-
const promises = data.entries.map(async entry => {
|
|
69
|
-
if (entry.address_from !== address && entry.address_to !== address) return
|
|
70
|
-
|
|
71
|
-
const token = await this.getTokenInfo(entry.asset)
|
|
72
|
-
const transfer: TransactionTransferAsset = {
|
|
73
|
-
amount: String(entry.amount),
|
|
74
|
-
from: entry.address_from ?? 'Mint',
|
|
75
|
-
to: entry.address_to ?? 'Burn',
|
|
76
|
-
type: 'token',
|
|
77
|
-
contractHash: entry.asset,
|
|
78
|
-
token,
|
|
79
|
-
}
|
|
80
|
-
const existingTransaction = transactions.get(entry.txid)
|
|
81
|
-
if (existingTransaction) {
|
|
82
|
-
existingTransaction.transfers.push(transfer)
|
|
83
|
-
return
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
transactions.set(entry.txid, {
|
|
87
|
-
block: entry.block_height,
|
|
88
|
-
hash: entry.txid,
|
|
89
|
-
time: entry.time,
|
|
90
|
-
transfers: [transfer],
|
|
91
|
-
notifications: [],
|
|
92
|
-
})
|
|
93
|
-
})
|
|
94
|
-
await Promise.all(promises)
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
totalCount: data.total_entries,
|
|
98
|
-
limit: data.page_size,
|
|
99
|
-
transactions: Array.from(transactions.values()),
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async getContract(contractHash: string): Promise<ContractResponse> {
|
|
104
|
-
const response = await api.NeoLegacyREST.contract(contractHash, this.network.type)
|
|
105
|
-
if (!response || 'error' in response) throw new Error(`Contract ${contractHash} not found`)
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
hash: response.hash,
|
|
109
|
-
name: response.name,
|
|
110
|
-
methods: [],
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async getTokenInfo(tokenHash: string): Promise<Token> {
|
|
115
|
-
const localToken = TOKENS[this.network.type].find(token => token.hash === tokenHash)
|
|
116
|
-
if (localToken) return localToken
|
|
117
|
-
|
|
118
|
-
if (this.tokenCache.has(tokenHash)) {
|
|
119
|
-
return this.tokenCache.get(tokenHash)!
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const data = await api.NeoLegacyREST.asset(tokenHash, this.network.type)
|
|
123
|
-
if (!data || 'error' in data) throw new Error(`Token ${tokenHash} not found`)
|
|
124
|
-
|
|
125
|
-
const token = {
|
|
126
|
-
decimals: Number(data.decimals),
|
|
127
|
-
symbol: data.symbol,
|
|
128
|
-
hash: data.scripthash,
|
|
129
|
-
name: data.name,
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
this.tokenCache.set(tokenHash, token)
|
|
133
|
-
|
|
134
|
-
return token
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async getBalance(address: string): Promise<BalanceResponse[]> {
|
|
138
|
-
const data = await api.NeoLegacyREST.balance(address, this.network.type)
|
|
139
|
-
|
|
140
|
-
const promises = data.map<Promise<BalanceResponse>>(async balance => {
|
|
141
|
-
const hash = balance.asset.replace('0x', '')
|
|
142
|
-
|
|
143
|
-
let token: Token = {
|
|
144
|
-
hash,
|
|
145
|
-
name: balance.asset_name,
|
|
146
|
-
symbol: balance.symbol,
|
|
147
|
-
decimals: 8,
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
try {
|
|
151
|
-
token = await this.getTokenInfo(hash)
|
|
152
|
-
} catch {
|
|
153
|
-
// Empty block
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return {
|
|
157
|
-
amount: Number(balance.balance).toFixed(token.decimals),
|
|
158
|
-
token,
|
|
159
|
-
}
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
const result = await Promise.all(promises)
|
|
163
|
-
|
|
164
|
-
return result
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async getUnclaimed(address: string): Promise<string> {
|
|
168
|
-
const { unclaimed } = await api.NeoLegacyREST.getUnclaimed(address, this.network.type)
|
|
169
|
-
return (unclaimed / 10 ** this.claimToken.decimals).toFixed(this.claimToken.decimals)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
async getBlockHeight(): Promise<number> {
|
|
173
|
-
const rpcClient = new rpc.RPCClient(this.network.url)
|
|
174
|
-
return await rpcClient.getBlockCount()
|
|
175
|
-
}
|
|
176
|
-
}
|
package/src/DoraESNeoLegacy.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { BuildNftUrlParams, ExplorerService, NetworkType } from '@cityofzion/blockchain-service'
|
|
2
|
-
|
|
3
|
-
export class DoraESNeoLegacy implements ExplorerService {
|
|
4
|
-
private networkType: NetworkType
|
|
5
|
-
|
|
6
|
-
constructor(networkType: NetworkType) {
|
|
7
|
-
this.networkType = networkType
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
buildTransactionUrl(hash: string): string {
|
|
11
|
-
if (this.networkType === 'custom') throw new Error('DoraESNeoLegacy does not support custom network')
|
|
12
|
-
return `https://dora.coz.io/transaction/neo2/${this.networkType}/${hash}`
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
buildNftUrl(_params: BuildNftUrlParams): string {
|
|
16
|
-
throw new Error('DoraESNeoLegacy does not support nft')
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
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
|
-
const 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
|
-
// Empty block
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
it.each([doraBDSNeoLegacy])('Should be able to get contract - %s', async (bdsNeoLegacy: BlockchainDataService) => {
|
|
77
|
-
const hash = '0x998a0da7ec5f21c9a99ef5349f81af8af89f9644'
|
|
78
|
-
const contract = await bdsNeoLegacy.getContract(hash)
|
|
79
|
-
expect(contract).toEqual({
|
|
80
|
-
hash: hash,
|
|
81
|
-
name: 'Phantasma Stake',
|
|
82
|
-
methods: [],
|
|
83
|
-
})
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
it.each([doraBDSNeoLegacy])('Should be able to get token info - %s', async (bdsNeoLegacy: BlockchainDataService) => {
|
|
87
|
-
const hash = '0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7'
|
|
88
|
-
const token = await bdsNeoLegacy.getTokenInfo(hash)
|
|
89
|
-
expect(token).toEqual({
|
|
90
|
-
decimals: 8,
|
|
91
|
-
hash: hash,
|
|
92
|
-
name: 'GAS',
|
|
93
|
-
symbol: 'GAS',
|
|
94
|
-
})
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
it.each([doraBDSNeoLegacy])('Should be able to get balance - %s', async (bdsNeoLegacy: BlockchainDataService) => {
|
|
98
|
-
const address = 'AeGgZTTWPzyVtNiQRcpngkV75Xip1hznmi'
|
|
99
|
-
const balance = await bdsNeoLegacy.getBalance(address)
|
|
100
|
-
|
|
101
|
-
balance.forEach(balance => {
|
|
102
|
-
expect(balance).toEqual({
|
|
103
|
-
amount: expect.any(String),
|
|
104
|
-
token: {
|
|
105
|
-
hash: expect.any(String),
|
|
106
|
-
name: expect.any(String),
|
|
107
|
-
symbol: expect.any(String),
|
|
108
|
-
decimals: expect.any(Number),
|
|
109
|
-
},
|
|
110
|
-
})
|
|
111
|
-
expect(balance.token.hash.startsWith('0x')).toBeFalsy()
|
|
112
|
-
})
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
it.each([doraBDSNeoLegacy])(
|
|
116
|
-
'Should be able to get unclaimed - %s',
|
|
117
|
-
async (doraBDSNeoLegacy: BlockchainDataService & BDSClaimable) => {
|
|
118
|
-
const address = 'AeGgZTTWPzyVtNiQRcpngkV75Xip1hznmi'
|
|
119
|
-
const unclaimed = await doraBDSNeoLegacy.getUnclaimed(address)
|
|
120
|
-
expect(unclaimed).toEqual(expect.any(String))
|
|
121
|
-
}
|
|
122
|
-
)
|
|
123
|
-
})
|