@cityofzion/bs-neo3 0.9.3 → 0.11.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/BSNeo3.d.ts +8 -4
- package/dist/BSNeo3.js +38 -13
- package/dist/DoraBDSNeo3.d.ts +0 -1
- package/dist/DoraBDSNeo3.js +11 -12
- package/dist/DoraESNeo3.d.ts +1 -1
- package/dist/DoraESNeo3.js +19 -5
- package/dist/FlamingoEDSNeo3.d.ts +1 -2
- package/dist/FlamingoEDSNeo3.js +20 -5
- package/dist/GhostMarketNDSNeo3.d.ts +1 -1
- package/dist/GhostMarketNDSNeo3.js +17 -3
- package/dist/LedgerServiceNeo3.d.ts +14 -0
- package/dist/LedgerServiceNeo3.js +96 -0
- package/dist/RpcBDSNeo3.d.ts +4 -4
- package/dist/RpcBDSNeo3.js +23 -19
- package/package.json +12 -9
- 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 -31
- package/.rush/temp/shrinkwrap-deps.json +0 -439
- package/CHANGELOG.json +0 -66
- package/CHANGELOG.md +0 -33
- package/bs-neo3.build.log +0 -1
- package/jest.config.ts +0 -13
- package/jest.setup.ts +0 -1
- package/src/BSNeo3.ts +0 -232
- package/src/DoraBDSNeo3.ts +0 -188
- package/src/DoraESNeo3.ts +0 -19
- package/src/FlamingoEDSNeo3.ts +0 -41
- package/src/GhostMarketNDSNeo3.ts +0 -121
- package/src/RpcBDSNeo3.ts +0 -159
- package/src/__tests__/BDSNeo3.spec.ts +0 -124
- package/src/__tests__/BSNeo3.spec.ts +0 -149
- package/src/__tests__/DoraESNeo3.spec.ts +0 -23
- package/src/__tests__/FlamingoEDSNeo3.spec.ts +0 -48
- package/src/__tests__/GhostMarketNDSNeo3.spec.ts +0 -48
- package/src/__tests__/utils/sleep.ts +0 -1
- package/src/assets/tokens/common.json +0 -14
- package/src/assets/tokens/mainnet.json +0 -116
- package/src/constants.ts +0 -29
- package/src/index.ts +0 -6
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -14
package/src/BSNeo3.ts
DELETED
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BlockchainDataService,
|
|
3
|
-
BlockchainService,
|
|
4
|
-
BSClaimable,
|
|
5
|
-
Account,
|
|
6
|
-
ExchangeDataService,
|
|
7
|
-
BDSClaimable,
|
|
8
|
-
Token,
|
|
9
|
-
BSWithNameService,
|
|
10
|
-
Network,
|
|
11
|
-
PartialBy,
|
|
12
|
-
TransferParam,
|
|
13
|
-
BSCalculableFee,
|
|
14
|
-
NftDataService,
|
|
15
|
-
BSWithNft,
|
|
16
|
-
AccountWithDerivationPath,
|
|
17
|
-
BSWithExplorerService,
|
|
18
|
-
ExplorerService,
|
|
19
|
-
} from '@cityofzion/blockchain-service'
|
|
20
|
-
import { api, u, wallet } from '@cityofzion/neon-js'
|
|
21
|
-
import Neon from '@cityofzion/neon-core'
|
|
22
|
-
import { NeonInvoker } from '@cityofzion/neon-invoker'
|
|
23
|
-
import { NeonParser } from '@cityofzion/neon-parser'
|
|
24
|
-
import { ABI_TYPES } from '@cityofzion/neo3-parser'
|
|
25
|
-
import { ContractInvocation } from '@cityofzion/neo3-invoker'
|
|
26
|
-
|
|
27
|
-
import { RPCBDSNeo3 } from './RpcBDSNeo3'
|
|
28
|
-
import { DoraBDSNeo3 } from './DoraBDSNeo3'
|
|
29
|
-
import { DEFAULT_URL_BY_NETWORK_TYPE, DERIVATION_PATH, NEO_NS_HASH, TOKENS } from './constants'
|
|
30
|
-
import { FlamingoEDSNeo3 } from './FlamingoEDSNeo3'
|
|
31
|
-
import { GhostMarketNDSNeo3 } from './GhostMarketNDSNeo3'
|
|
32
|
-
import { keychain } from '@cityofzion/bs-asteroid-sdk'
|
|
33
|
-
import { DoraESNeo3 } from './DoraESNeo3'
|
|
34
|
-
|
|
35
|
-
export class BSNeo3<BSCustomName extends string = string>
|
|
36
|
-
implements BlockchainService, BSClaimable, BSWithNameService, BSCalculableFee, BSWithNft, BSWithExplorerService
|
|
37
|
-
{
|
|
38
|
-
readonly blockchainName: BSCustomName
|
|
39
|
-
readonly feeToken: Token
|
|
40
|
-
readonly claimToken: Token
|
|
41
|
-
readonly burnToken: Token
|
|
42
|
-
readonly derivationPath: string
|
|
43
|
-
|
|
44
|
-
blockchainDataService!: BlockchainDataService & BDSClaimable
|
|
45
|
-
nftDataService!: NftDataService
|
|
46
|
-
exchangeDataService!: ExchangeDataService
|
|
47
|
-
explorerService!: ExplorerService
|
|
48
|
-
tokens: Token[]
|
|
49
|
-
network!: Network
|
|
50
|
-
|
|
51
|
-
constructor(blockchainName: BSCustomName, network: PartialBy<Network, 'url'>) {
|
|
52
|
-
this.blockchainName = blockchainName
|
|
53
|
-
this.tokens = TOKENS[network.type]
|
|
54
|
-
|
|
55
|
-
this.derivationPath = DERIVATION_PATH
|
|
56
|
-
this.feeToken = this.tokens.find(token => token.symbol === 'GAS')!
|
|
57
|
-
this.burnToken = this.tokens.find(token => token.symbol === 'NEO')!
|
|
58
|
-
this.claimToken = this.tokens.find(token => token.symbol === 'GAS')!
|
|
59
|
-
this.setNetwork(network)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
setNetwork(param: PartialBy<Network, 'url'>) {
|
|
63
|
-
const network = {
|
|
64
|
-
type: param.type,
|
|
65
|
-
url: param.url ?? DEFAULT_URL_BY_NETWORK_TYPE[param.type],
|
|
66
|
-
}
|
|
67
|
-
this.network = network
|
|
68
|
-
|
|
69
|
-
if (network.type === 'custom') {
|
|
70
|
-
this.blockchainDataService = new RPCBDSNeo3(network, this.feeToken, this.claimToken)
|
|
71
|
-
} else {
|
|
72
|
-
this.blockchainDataService = new DoraBDSNeo3(network, this.feeToken, this.claimToken)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
this.exchangeDataService = new FlamingoEDSNeo3(network.type)
|
|
76
|
-
this.nftDataService = new GhostMarketNDSNeo3(network.type)
|
|
77
|
-
this.explorerService = new DoraESNeo3(network.type)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
validateAddress(address: string): boolean {
|
|
81
|
-
return wallet.isAddress(address, 53)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
validateEncrypted(encryptedKey: string): boolean {
|
|
85
|
-
return wallet.isNEP2(encryptedKey)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
validateKey(key: string): boolean {
|
|
89
|
-
return wallet.isWIF(key) || wallet.isPrivateKey(key)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
validateNameServiceDomainFormat(domainName: string): boolean {
|
|
93
|
-
if (!domainName.endsWith('.neo')) return false
|
|
94
|
-
return true
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
generateAccountFromMnemonic(mnemonic: string[] | string, index: number): AccountWithDerivationPath {
|
|
98
|
-
keychain.importMnemonic(Array.isArray(mnemonic) ? mnemonic.join(' ') : mnemonic)
|
|
99
|
-
const path = this.derivationPath.replace('?', index.toString())
|
|
100
|
-
const childKey = keychain.generateChildKey('neo', path)
|
|
101
|
-
const key = childKey.getWIF()
|
|
102
|
-
const { address } = new wallet.Account(key)
|
|
103
|
-
return { address, key, type: 'wif', derivationPath: path }
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
generateAccountFromKey(key: string): Account {
|
|
107
|
-
const type = wallet.isWIF(key) ? 'wif' : wallet.isPrivateKey(key) ? 'privateKey' : undefined
|
|
108
|
-
if (!type) throw new Error('Invalid key')
|
|
109
|
-
|
|
110
|
-
const { address } = new wallet.Account(key)
|
|
111
|
-
return { address, key, type }
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async decrypt(encryptedKey: string, password: string): Promise<Account> {
|
|
115
|
-
let BsReactNativeDecrypt: any
|
|
116
|
-
|
|
117
|
-
try {
|
|
118
|
-
const { NativeModules } = require('react-native')
|
|
119
|
-
BsReactNativeDecrypt = NativeModules.BsReactNativeDecrypt
|
|
120
|
-
|
|
121
|
-
if (!BsReactNativeDecrypt) {
|
|
122
|
-
throw new Error('@CityOfZion/bs-react-native-decrypt is not installed')
|
|
123
|
-
}
|
|
124
|
-
} catch {
|
|
125
|
-
const key = await wallet.decrypt(encryptedKey, password)
|
|
126
|
-
return this.generateAccountFromKey(key)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const privateKey = await BsReactNativeDecrypt.decryptNeo3(encryptedKey, password)
|
|
130
|
-
return this.generateAccountFromKey(privateKey)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
encrypt(key: string, password: string): Promise<string> {
|
|
134
|
-
return wallet.encrypt(key, password)
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async calculateTransferFee(param: TransferParam): Promise<string> {
|
|
138
|
-
const account = new wallet.Account(param.senderAccount.key)
|
|
139
|
-
const invoker = await NeonInvoker.init({
|
|
140
|
-
rpcAddress: this.network.url,
|
|
141
|
-
account,
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
const invocations = this.buildTransferInvocation(param, account)
|
|
145
|
-
|
|
146
|
-
const { networkFee, systemFee } = await invoker.calculateFee({
|
|
147
|
-
invocations,
|
|
148
|
-
signers: [],
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
return networkFee.add(systemFee).toDecimal(this.feeToken.decimals)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
async transfer(param: TransferParam): Promise<string> {
|
|
155
|
-
const account = new wallet.Account(param.senderAccount.key)
|
|
156
|
-
const invoker = await NeonInvoker.init({
|
|
157
|
-
rpcAddress: this.network.url,
|
|
158
|
-
account,
|
|
159
|
-
})
|
|
160
|
-
|
|
161
|
-
const invocations = this.buildTransferInvocation(param, account)
|
|
162
|
-
|
|
163
|
-
const transactionHash = await invoker.invokeFunction({
|
|
164
|
-
invocations,
|
|
165
|
-
signers: [],
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
return transactionHash
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async claim(account: Account): Promise<string> {
|
|
172
|
-
const neoAccount = new wallet.Account(account.key)
|
|
173
|
-
const facade = await api.NetworkFacade.fromConfig({ node: this.network.url })
|
|
174
|
-
|
|
175
|
-
const transactionHash = await facade.claimGas(neoAccount, {
|
|
176
|
-
signingCallback: api.signWithAccount(neoAccount),
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
return transactionHash
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
async resolveNameServiceDomain(domainName: string): Promise<any> {
|
|
183
|
-
const parser = NeonParser
|
|
184
|
-
const invoker = await NeonInvoker.init({ rpcAddress: this.network.url })
|
|
185
|
-
const response = await invoker.testInvoke({
|
|
186
|
-
invocations: [
|
|
187
|
-
{
|
|
188
|
-
scriptHash: NEO_NS_HASH,
|
|
189
|
-
operation: 'ownerOf',
|
|
190
|
-
args: [{ type: 'String', value: domainName }],
|
|
191
|
-
},
|
|
192
|
-
],
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
if (response.stack.length === 0) {
|
|
196
|
-
throw new Error(response.exception ?? 'unrecognized response')
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const parsed = parser.parseRpcResponse(response.stack[0] as any, {
|
|
200
|
-
type: ABI_TYPES.HASH160.name,
|
|
201
|
-
})
|
|
202
|
-
const address = parser.accountInputToAddress(parsed.replace('0x', ''))
|
|
203
|
-
return address
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
private buildTransferInvocation(
|
|
207
|
-
{ intent, tipIntent }: TransferParam,
|
|
208
|
-
account: Neon.wallet.Account
|
|
209
|
-
): ContractInvocation[] {
|
|
210
|
-
const intents = [intent, ...(tipIntent ? [tipIntent] : [])]
|
|
211
|
-
|
|
212
|
-
const invocations: ContractInvocation[] = intents.map(intent => {
|
|
213
|
-
return {
|
|
214
|
-
operation: 'transfer',
|
|
215
|
-
scriptHash: intent.tokenHash,
|
|
216
|
-
args: [
|
|
217
|
-
{ type: 'Hash160', value: account.address },
|
|
218
|
-
{ type: 'Hash160', value: intent.receiverAddress },
|
|
219
|
-
{
|
|
220
|
-
type: 'Integer',
|
|
221
|
-
value: intent.tokenDecimals
|
|
222
|
-
? u.BigInteger.fromDecimal(intent.amount, intent.tokenDecimals).toString()
|
|
223
|
-
: intent.amount,
|
|
224
|
-
},
|
|
225
|
-
{ type: 'Any', value: '' },
|
|
226
|
-
],
|
|
227
|
-
}
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
return invocations
|
|
231
|
-
}
|
|
232
|
-
}
|
package/src/DoraBDSNeo3.ts
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BalanceResponse,
|
|
3
|
-
ContractResponse,
|
|
4
|
-
TransactionsByAddressParams,
|
|
5
|
-
TransactionsByAddressResponse,
|
|
6
|
-
TransactionResponse,
|
|
7
|
-
TransactionNotifications,
|
|
8
|
-
Network,
|
|
9
|
-
Token,
|
|
10
|
-
TransactionTransferNft,
|
|
11
|
-
TransactionTransferAsset,
|
|
12
|
-
} from '@cityofzion/blockchain-service'
|
|
13
|
-
import { wallet, u } from '@cityofzion/neon-js'
|
|
14
|
-
import { NeoRESTApi } from '@cityofzion/dora-ts/dist/api'
|
|
15
|
-
import { RPCBDSNeo3 } from './RpcBDSNeo3'
|
|
16
|
-
import { TOKENS } from './constants'
|
|
17
|
-
|
|
18
|
-
const NeoRest = new NeoRESTApi({
|
|
19
|
-
doraUrl: 'https://dora.coz.io',
|
|
20
|
-
endpoint: '/api/v2/neo3',
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
export class DoraBDSNeo3 extends RPCBDSNeo3 {
|
|
24
|
-
readonly network: Network
|
|
25
|
-
|
|
26
|
-
constructor(network: Network, feeToken: Token, claimToken: Token) {
|
|
27
|
-
if (network.type === 'custom') {
|
|
28
|
-
throw new Error('DoraBDSNeo3 does not support custom networks')
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
super(network, feeToken, claimToken)
|
|
32
|
-
this.network = network
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async getTransaction(hash: string): Promise<TransactionResponse> {
|
|
36
|
-
try {
|
|
37
|
-
const data = await NeoRest.transaction(hash, this.network.type)
|
|
38
|
-
return {
|
|
39
|
-
block: data.block,
|
|
40
|
-
time: Number(data.time),
|
|
41
|
-
hash: data.hash,
|
|
42
|
-
fee: u.BigInteger.fromNumber(data.netfee ?? 0)
|
|
43
|
-
.add(u.BigInteger.fromNumber(data.sysfee ?? 0))
|
|
44
|
-
.toDecimal(this.feeToken.decimals),
|
|
45
|
-
notifications: [],
|
|
46
|
-
transfers: [],
|
|
47
|
-
}
|
|
48
|
-
} catch {
|
|
49
|
-
throw new Error(`Transaction not found: ${hash}`)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async getTransactionsByAddress({
|
|
54
|
-
address,
|
|
55
|
-
page = 1,
|
|
56
|
-
}: TransactionsByAddressParams): Promise<TransactionsByAddressResponse> {
|
|
57
|
-
const data = await NeoRest.addressTXFull(address, page, this.network.type)
|
|
58
|
-
|
|
59
|
-
const promises = data.items.map(async (item): Promise<TransactionResponse> => {
|
|
60
|
-
const transferPromises: Promise<TransactionTransferAsset | TransactionTransferNft>[] = []
|
|
61
|
-
|
|
62
|
-
item.notifications.forEach(({ contract: contractHash, state, event_name: eventName }) => {
|
|
63
|
-
const properties = Array.isArray(state) ? state : state.value
|
|
64
|
-
if (eventName !== 'Transfer' || (properties.length !== 3 && properties.length !== 4)) return
|
|
65
|
-
|
|
66
|
-
const promise = async (): Promise<TransactionTransferAsset | TransactionTransferNft> => {
|
|
67
|
-
const isAsset = properties.length === 3
|
|
68
|
-
|
|
69
|
-
const from = properties[0].value
|
|
70
|
-
const to = properties[1].value
|
|
71
|
-
const convertedFrom = from ? this.convertByteStringToAddress(from) : 'Mint'
|
|
72
|
-
const convertedTo = to ? this.convertByteStringToAddress(to) : 'Burn'
|
|
73
|
-
|
|
74
|
-
if (isAsset) {
|
|
75
|
-
const token = await this.getTokenInfo(contractHash)
|
|
76
|
-
const [, , { value: amount }] = properties
|
|
77
|
-
return {
|
|
78
|
-
amount: u.BigInteger.fromNumber(amount).toDecimal(token.decimals ?? 0),
|
|
79
|
-
from: convertedFrom,
|
|
80
|
-
to: convertedTo,
|
|
81
|
-
contractHash,
|
|
82
|
-
type: 'token',
|
|
83
|
-
token,
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
from: convertedFrom,
|
|
89
|
-
to: convertedTo,
|
|
90
|
-
tokenId: properties[3].value,
|
|
91
|
-
contractHash,
|
|
92
|
-
type: 'nft',
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
transferPromises.push(promise())
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
const transfers = await Promise.all(transferPromises)
|
|
100
|
-
|
|
101
|
-
const notifications = item.notifications.map<TransactionNotifications>(notification => ({
|
|
102
|
-
eventName: notification.event_name,
|
|
103
|
-
state: notification.state as any,
|
|
104
|
-
}))
|
|
105
|
-
|
|
106
|
-
return {
|
|
107
|
-
block: item.block,
|
|
108
|
-
time: Number(item.time),
|
|
109
|
-
hash: item.hash,
|
|
110
|
-
fee: u.BigInteger.fromNumber(item.netfee ?? 0)
|
|
111
|
-
.add(u.BigInteger.fromNumber(item.sysfee ?? 0))
|
|
112
|
-
.toDecimal(this.feeToken.decimals),
|
|
113
|
-
transfers,
|
|
114
|
-
notifications,
|
|
115
|
-
}
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
const transactions = await Promise.all(promises)
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
-
totalCount: data.totalCount,
|
|
122
|
-
transactions,
|
|
123
|
-
limit: 15,
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async getContract(contractHash: string): Promise<ContractResponse> {
|
|
128
|
-
try {
|
|
129
|
-
const data = await NeoRest.contract(contractHash, this.network.type)
|
|
130
|
-
return {
|
|
131
|
-
hash: data.hash,
|
|
132
|
-
methods: data.manifest.abi?.methods ?? [],
|
|
133
|
-
name: data.manifest.name,
|
|
134
|
-
}
|
|
135
|
-
} catch {
|
|
136
|
-
throw new Error(`Contract not found: ${contractHash}`)
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async getTokenInfo(tokenHash: string): Promise<Token> {
|
|
141
|
-
const localToken = TOKENS[this.network.type].find(token => token.hash === tokenHash)
|
|
142
|
-
if (localToken) return localToken
|
|
143
|
-
|
|
144
|
-
if (this.tokenCache.has(tokenHash)) {
|
|
145
|
-
return this.tokenCache.get(tokenHash)!
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
try {
|
|
149
|
-
const { decimals, symbol, name, scripthash } = await NeoRest.asset(tokenHash, this.network.type)
|
|
150
|
-
const token = {
|
|
151
|
-
decimals: Number(decimals),
|
|
152
|
-
symbol,
|
|
153
|
-
name,
|
|
154
|
-
hash: scripthash,
|
|
155
|
-
}
|
|
156
|
-
this.tokenCache.set(tokenHash, token)
|
|
157
|
-
|
|
158
|
-
return token
|
|
159
|
-
} catch {
|
|
160
|
-
throw new Error(`Token not found: ${tokenHash}`)
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
async getBalance(address: string): Promise<BalanceResponse[]> {
|
|
165
|
-
const response = await NeoRest.balance(address, this.network.type)
|
|
166
|
-
|
|
167
|
-
const promises = response.map<Promise<BalanceResponse | undefined>>(async balance => {
|
|
168
|
-
try {
|
|
169
|
-
const token = await this.getTokenInfo(balance.asset)
|
|
170
|
-
return {
|
|
171
|
-
amount: balance.balance.toString(),
|
|
172
|
-
token,
|
|
173
|
-
}
|
|
174
|
-
} catch {
|
|
175
|
-
// Empty block
|
|
176
|
-
}
|
|
177
|
-
})
|
|
178
|
-
const balances = await Promise.all(promises)
|
|
179
|
-
const filteredBalances = balances.filter(balance => balance !== undefined) as BalanceResponse[]
|
|
180
|
-
return filteredBalances
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
private convertByteStringToAddress(byteString: string): string {
|
|
184
|
-
const account = new wallet.Account(u.reverseHex(u.HexString.fromBase64(byteString).toString()))
|
|
185
|
-
|
|
186
|
-
return account.address
|
|
187
|
-
}
|
|
188
|
-
}
|
package/src/DoraESNeo3.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { ExplorerService, NetworkType, BuildNftUrlParams } from '@cityofzion/blockchain-service'
|
|
2
|
-
|
|
3
|
-
export class DoraESNeo3 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('DoraESNeo3 does not support custom network')
|
|
12
|
-
return `https://dora.coz.io/transaction/neo3/${this.networkType}/${hash}`
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
buildNftUrl({ contractHash, tokenId }: BuildNftUrlParams): string {
|
|
16
|
-
if (this.networkType === 'custom') throw new Error('DoraESNeo3 does not support custom network')
|
|
17
|
-
return `https://dora.coz.io/nft/neo3/${this.networkType}/${contractHash}/${tokenId}`
|
|
18
|
-
}
|
|
19
|
-
}
|
package/src/FlamingoEDSNeo3.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { Currency, ExchangeDataService, NetworkType, TokenPricesResponse } from '@cityofzion/blockchain-service'
|
|
2
|
-
import axios, { AxiosInstance } from 'axios'
|
|
3
|
-
|
|
4
|
-
type FlamingoTokenInfoPricesResponse = {
|
|
5
|
-
symbol: string
|
|
6
|
-
usd_price: number
|
|
7
|
-
hash: string
|
|
8
|
-
}[]
|
|
9
|
-
|
|
10
|
-
export class FlamingoEDSNeo3 implements ExchangeDataService {
|
|
11
|
-
readonly networkType: NetworkType
|
|
12
|
-
private axiosInstance: AxiosInstance
|
|
13
|
-
|
|
14
|
-
constructor(networkType: NetworkType) {
|
|
15
|
-
this.networkType = networkType
|
|
16
|
-
this.axiosInstance = axios.create({ baseURL: 'https://api.flamingo.finance' })
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async getTokenPrices(currency: Currency): Promise<TokenPricesResponse[]> {
|
|
20
|
-
if (this.networkType !== 'mainnet') throw new Error('Exchange is only available on mainnet')
|
|
21
|
-
|
|
22
|
-
const { data: prices } = await this.axiosInstance.get<FlamingoTokenInfoPricesResponse>('/token-info/prices')
|
|
23
|
-
|
|
24
|
-
let currencyRatio: number = 1
|
|
25
|
-
|
|
26
|
-
if (currency !== 'USD') {
|
|
27
|
-
currencyRatio = await this.getCurrencyRatio(currency)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return prices.map(price => ({
|
|
31
|
-
price: price.usd_price * currencyRatio,
|
|
32
|
-
symbol: price.symbol,
|
|
33
|
-
hash: price.hash,
|
|
34
|
-
}))
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
private async getCurrencyRatio(currency: Currency): Promise<number> {
|
|
38
|
-
const { data } = await this.axiosInstance.get<number>(`/fiat/exchange-rate?pair=USD_${currency}`)
|
|
39
|
-
return data
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
NftResponse,
|
|
3
|
-
NftsResponse,
|
|
4
|
-
NetworkType,
|
|
5
|
-
NftDataService,
|
|
6
|
-
GetNftParam,
|
|
7
|
-
GetNftsByAddressParams,
|
|
8
|
-
} from '@cityofzion/blockchain-service'
|
|
9
|
-
import qs from 'query-string'
|
|
10
|
-
import axios from 'axios'
|
|
11
|
-
|
|
12
|
-
import { GHOSTMARKET_CHAIN_BY_NETWORK_TYPE, GHOSTMARKET_URL_BY_NETWORK_TYPE } from './constants'
|
|
13
|
-
|
|
14
|
-
type GhostMarketNFT = {
|
|
15
|
-
tokenId: string
|
|
16
|
-
contract: {
|
|
17
|
-
chain?: string
|
|
18
|
-
hash: string
|
|
19
|
-
symbol: string
|
|
20
|
-
}
|
|
21
|
-
creator: {
|
|
22
|
-
address: string
|
|
23
|
-
offchainName?: string
|
|
24
|
-
}
|
|
25
|
-
apiUrl?: string
|
|
26
|
-
ownerships: {
|
|
27
|
-
owner: {
|
|
28
|
-
address?: string
|
|
29
|
-
}
|
|
30
|
-
}[]
|
|
31
|
-
collection: {
|
|
32
|
-
name?: string
|
|
33
|
-
logoUrl?: string
|
|
34
|
-
}
|
|
35
|
-
metadata: {
|
|
36
|
-
description: string
|
|
37
|
-
mediaType: string
|
|
38
|
-
mediaUri: string
|
|
39
|
-
mintDate: number
|
|
40
|
-
mintNumber: number
|
|
41
|
-
name: string
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
type GhostMarketAssets = {
|
|
46
|
-
assets: GhostMarketNFT[]
|
|
47
|
-
next: string
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export class GhostMarketNDSNeo3 implements NftDataService {
|
|
51
|
-
private networkType: NetworkType
|
|
52
|
-
|
|
53
|
-
constructor(networkType: NetworkType) {
|
|
54
|
-
this.networkType = networkType
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async getNftsByAddress({ address, size = 18, cursor }: GetNftsByAddressParams): Promise<NftsResponse> {
|
|
58
|
-
const url = this.getUrlWithParams({
|
|
59
|
-
size,
|
|
60
|
-
owners: [address],
|
|
61
|
-
cursor: cursor,
|
|
62
|
-
})
|
|
63
|
-
const { data } = await axios.get<GhostMarketAssets>(url)
|
|
64
|
-
const nfts = data.assets ?? []
|
|
65
|
-
|
|
66
|
-
return { nextCursor: data.next, items: nfts.map(this.parse.bind(this)) }
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async getNft({ contractHash, tokenId }: GetNftParam): Promise<NftResponse> {
|
|
70
|
-
const url = this.getUrlWithParams({
|
|
71
|
-
contract: contractHash,
|
|
72
|
-
tokenIds: [tokenId],
|
|
73
|
-
})
|
|
74
|
-
const { data } = await axios.get<GhostMarketAssets>(url)
|
|
75
|
-
return this.parse(data.assets[0])
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
private treatGhostMarketImage(srcImage?: string) {
|
|
79
|
-
if (!srcImage) {
|
|
80
|
-
return
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (srcImage.startsWith('ipfs://')) {
|
|
84
|
-
const [, imageId] = srcImage.split('://')
|
|
85
|
-
|
|
86
|
-
return `https://ghostmarket.mypinata.cloud/ipfs/${imageId}`
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return srcImage
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
private getUrlWithParams(params: Record<string, any>) {
|
|
93
|
-
const parameters = qs.stringify(
|
|
94
|
-
{
|
|
95
|
-
chain: GHOSTMARKET_CHAIN_BY_NETWORK_TYPE[this.networkType],
|
|
96
|
-
...params,
|
|
97
|
-
},
|
|
98
|
-
{ arrayFormat: 'bracket' }
|
|
99
|
-
)
|
|
100
|
-
return `${GHOSTMARKET_URL_BY_NETWORK_TYPE[this.networkType]}/assets?${parameters}`
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
private parse(data: GhostMarketNFT) {
|
|
104
|
-
const nftResponse: NftResponse = {
|
|
105
|
-
collectionImage: this.treatGhostMarketImage(data.collection?.logoUrl),
|
|
106
|
-
id: data.tokenId,
|
|
107
|
-
contractHash: data.contract.hash,
|
|
108
|
-
symbol: data.contract.symbol,
|
|
109
|
-
collectionName: data.collection?.name,
|
|
110
|
-
image: this.treatGhostMarketImage(data.metadata.mediaUri),
|
|
111
|
-
isSVG: String(data.metadata.mediaType).includes('svg+xml'),
|
|
112
|
-
name: data.metadata.name,
|
|
113
|
-
creator: {
|
|
114
|
-
address: data.creator.address,
|
|
115
|
-
name: data.creator.offchainName,
|
|
116
|
-
},
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return nftResponse
|
|
120
|
-
}
|
|
121
|
-
}
|