@cityofzion/bs-neo3 0.10.0 → 0.11.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.
Files changed (45) hide show
  1. package/dist/BSNeo3.d.ts +3 -2
  2. package/dist/BSNeo3.js +23 -6
  3. package/dist/DoraBDSNeo3.d.ts +0 -1
  4. package/dist/DoraBDSNeo3.js +11 -12
  5. package/dist/DoraESNeo3.d.ts +1 -1
  6. package/dist/DoraESNeo3.js +19 -5
  7. package/dist/FlamingoEDSNeo3.d.ts +1 -2
  8. package/dist/FlamingoEDSNeo3.js +20 -5
  9. package/dist/GhostMarketNDSNeo3.d.ts +1 -1
  10. package/dist/GhostMarketNDSNeo3.js +17 -3
  11. package/dist/LedgerServiceNeo3.d.ts +3 -1
  12. package/dist/LedgerServiceNeo3.js +3 -0
  13. package/dist/RpcBDSNeo3.d.ts +4 -4
  14. package/dist/RpcBDSNeo3.js +17 -17
  15. package/package.json +6 -3
  16. package/.eslintignore +0 -13
  17. package/.eslintrc.cjs +0 -22
  18. package/.rush/temp/operation/build/all.log +0 -1
  19. package/.rush/temp/operation/build/state.json +0 -3
  20. package/.rush/temp/package-deps_build.json +0 -32
  21. package/.rush/temp/shrinkwrap-deps.json +0 -520
  22. package/CHANGELOG.json +0 -83
  23. package/CHANGELOG.md +0 -40
  24. package/bs-neo3.build.log +0 -1
  25. package/jest.config.ts +0 -13
  26. package/jest.setup.ts +0 -1
  27. package/src/BSNeo3.ts +0 -254
  28. package/src/DoraBDSNeo3.ts +0 -188
  29. package/src/DoraESNeo3.ts +0 -19
  30. package/src/FlamingoEDSNeo3.ts +0 -41
  31. package/src/GhostMarketNDSNeo3.ts +0 -121
  32. package/src/LedgerServiceNeo3.ts +0 -107
  33. package/src/RpcBDSNeo3.ts +0 -161
  34. package/src/__tests__/BDSNeo3.spec.ts +0 -124
  35. package/src/__tests__/BSNeo3.spec.ts +0 -175
  36. package/src/__tests__/DoraESNeo3.spec.ts +0 -23
  37. package/src/__tests__/FlamingoEDSNeo3.spec.ts +0 -48
  38. package/src/__tests__/GhostMarketNDSNeo3.spec.ts +0 -48
  39. package/src/__tests__/utils/sleep.ts +0 -1
  40. package/src/assets/tokens/common.json +0 -14
  41. package/src/assets/tokens/mainnet.json +0 -116
  42. package/src/constants.ts +0 -29
  43. package/src/index.ts +0 -6
  44. package/tsconfig.build.json +0 -4
  45. package/tsconfig.json +0 -14
@@ -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
- }
@@ -1,107 +0,0 @@
1
- import { LedgerService } from '@cityofzion/blockchain-service'
2
- import Transport from '@ledgerhq/hw-transport'
3
- import { wallet, api, u } from '@cityofzion/neon-js'
4
- import { NeonParser } from '@cityofzion/neon-dappkit'
5
-
6
- export class LedgerServiceNeo3 implements LedgerService {
7
- async getAddress(transport: Transport): Promise<string> {
8
- const publicKey = await this.getPublicKey(transport)
9
- const { address } = new wallet.Account(publicKey)
10
-
11
- return address
12
- }
13
-
14
- getSigningCallback(transport: Transport): api.SigningFunction {
15
- return async (transaction, { witnessIndex, network }) => {
16
- const publicKey = await this.getPublicKey(transport)
17
- const account = new wallet.Account(publicKey)
18
-
19
- const witnessScriptHash = wallet.getScriptHashFromVerificationScript(
20
- transaction.witnesses[witnessIndex].verificationScript.toString()
21
- )
22
-
23
- if (account.scriptHash !== witnessScriptHash) {
24
- throw new Error('Invalid witness script hash')
25
- }
26
-
27
- const signature = await this.getSignature(transport, transaction.serialize(false), network, witnessIndex)
28
-
29
- return signature
30
- }
31
- }
32
-
33
- async getSignature(transport: Transport, serializedTransaction: string, networkMagic: number, addressIndex = 0) {
34
- const bip44Buffer = this.toBip44Buffer(addressIndex)
35
- await transport.send(0x80, 0x02, 0, 0x80, bip44Buffer, [0x9000])
36
- await transport.send(0x80, 0x02, 1, 0x80, Buffer.from(NeonParser.numToHex(networkMagic, 4, true), 'hex'), [0x9000])
37
-
38
- const chunks = serializedTransaction.match(/.{1,510}/g) || []
39
-
40
- for (let i = 0; i < chunks.length - 1; i++) {
41
- await transport.send(0x80, 0x02, 2 + i, 0x80, Buffer.from(chunks[i], 'hex'), [0x9000])
42
- }
43
-
44
- const response = await transport.send(
45
- 0x80,
46
- 0x02,
47
- 2 + chunks.length,
48
- 0x00,
49
- Buffer.from(chunks[chunks.length - 1], 'hex'),
50
- [0x9000]
51
- )
52
-
53
- if (response.length <= 2) {
54
- throw new Error(`No more data but Ledger did not return signature!`)
55
- }
56
-
57
- return this.derSignatureToHex(response.toString('hex'))
58
- }
59
-
60
- async getPublicKey(transport: Transport, addressIndex = 0): Promise<string> {
61
- const bip44Buffer = this.toBip44Buffer(addressIndex)
62
-
63
- const result = await transport.send(0x80, 0x04, 0x00, 0x00, bip44Buffer, [0x9000])
64
- const publicKey = result.toString('hex').substring(0, 130)
65
-
66
- return publicKey
67
- }
68
-
69
- private toBip44Buffer(addressIndex = 0, changeIndex = 0, accountIndex = 0) {
70
- const accountHex = this.to8BitHex(accountIndex + 0x80000000)
71
- const changeHex = this.to8BitHex(changeIndex)
72
- const addressHex = this.to8BitHex(addressIndex)
73
-
74
- return Buffer.from('8000002C' + '80000378' + accountHex + changeHex + addressHex, 'hex')
75
- }
76
-
77
- private to8BitHex(num: number): string {
78
- const hex = num.toString(16)
79
- return '0'.repeat(8 - hex.length) + hex
80
- }
81
-
82
- private derSignatureToHex(response: string): string {
83
- const ss = new u.StringStream(response)
84
- // The first byte is format. It is usually 0x30 (SEQ) or 0x31 (SET)
85
- // The second byte represents the total length of the DER module.
86
- ss.read(2)
87
- // Now we read each field off
88
- // Each field is encoded with a type byte, length byte followed by the data itself
89
- ss.read(1) // Read and drop the type
90
- const r = ss.readVarBytes()
91
- ss.read(1)
92
- const s = ss.readVarBytes()
93
-
94
- // We will need to ensure both integers are 32 bytes long
95
- const integers = [r, s].map(i => {
96
- if (i.length < 64) {
97
- i = '0'.repeat(i.length - 64) + i
98
- }
99
- if (i.length > 64) {
100
- i = i.substr(-64)
101
- }
102
- return i
103
- })
104
-
105
- return integers.join('')
106
- }
107
- }
package/src/RpcBDSNeo3.ts DELETED
@@ -1,161 +0,0 @@
1
- import {
2
- BDSClaimable,
3
- BalanceResponse,
4
- BlockchainDataService,
5
- ContractMethod,
6
- ContractParameter,
7
- ContractResponse,
8
- Network,
9
- Token,
10
- TransactionResponse,
11
- TransactionsByAddressParams,
12
- TransactionsByAddressResponse,
13
- } from '@cityofzion/blockchain-service'
14
- import { rpc, u } from '@cityofzion/neon-core'
15
- import { NeonInvoker, TypeChecker } from '@cityofzion/neon-dappkit'
16
- import { TOKENS } from './constants'
17
-
18
- export class RPCBDSNeo3 implements BlockchainDataService, BDSClaimable {
19
- protected readonly tokenCache: Map<string, Token> = new Map()
20
- protected readonly feeToken: Token
21
- protected readonly claimToken: Token
22
- readonly network: Network
23
-
24
- maxTimeToConfirmTransactionInMs: number = 1000 * 60 * 2
25
-
26
- constructor(network: Network, feeToken: Token, claimToken: Token) {
27
- this.network = network
28
- this.feeToken = feeToken
29
- this.claimToken = claimToken
30
- }
31
-
32
- async getTransaction(hash: string): Promise<TransactionResponse> {
33
- try {
34
- const rpcClient = new rpc.RPCClient(this.network.url)
35
- const response = await rpcClient.getRawTransaction(hash, true)
36
-
37
- return {
38
- hash: response.hash,
39
- block: response.validuntilblock,
40
- fee: u.BigInteger.fromNumber(response.netfee ?? 0)
41
- .add(u.BigInteger.fromNumber(response.sysfee ?? 0))
42
- .toDecimal(this.feeToken.decimals),
43
- notifications: [],
44
- transfers: [],
45
- time: response.blocktime,
46
- }
47
- } catch {
48
- throw new Error(`Transaction not found: ${hash}`)
49
- }
50
- }
51
-
52
- async getTransactionsByAddress(_params: TransactionsByAddressParams): Promise<TransactionsByAddressResponse> {
53
- throw new Error('Method not supported.')
54
- }
55
-
56
- async getContract(contractHash: string): Promise<ContractResponse> {
57
- try {
58
- const rpcClient = new rpc.RPCClient(this.network.url)
59
- const contractState = await rpcClient.getContractState(contractHash)
60
-
61
- const methods = contractState.manifest.abi.methods.map<ContractMethod>(method => ({
62
- name: method.name,
63
- parameters: method.parameters.map<ContractParameter>(parameter => ({
64
- name: parameter.name,
65
- type: parameter.type,
66
- })),
67
- }))
68
-
69
- return {
70
- hash: contractState.hash,
71
- name: contractState.manifest.name,
72
- methods,
73
- }
74
- } catch {
75
- throw new Error(`Contract not found: ${contractHash}`)
76
- }
77
- }
78
-
79
- async getTokenInfo(tokenHash: string): Promise<Token> {
80
- const localToken = TOKENS[this.network.type].find(token => token.hash === tokenHash)
81
- if (localToken) return localToken
82
-
83
- if (this.tokenCache.has(tokenHash)) {
84
- return this.tokenCache.get(tokenHash)!
85
- }
86
- try {
87
- const rpcClient = new rpc.RPCClient(this.network.url)
88
- const contractState = await rpcClient.getContractState(tokenHash)
89
-
90
- const invoker = await NeonInvoker.init({
91
- rpcAddress: this.network.url,
92
- })
93
-
94
- const response = await invoker.testInvoke({
95
- invocations: [
96
- {
97
- scriptHash: tokenHash,
98
- operation: 'decimals',
99
- args: [],
100
- },
101
- { scriptHash: tokenHash, operation: 'symbol', args: [] },
102
- ],
103
- })
104
-
105
- if (!TypeChecker.isStackTypeInteger(response.stack[0])) throw new Error('Invalid decimals')
106
- if (!TypeChecker.isStackTypeByteString(response.stack[1])) throw new Error('Invalid symbol')
107
- const decimals = Number(response.stack[0].value)
108
- const symbol = u.base642utf8(response.stack[1].value)
109
- const token = {
110
- name: contractState.manifest.name,
111
- symbol,
112
- hash: contractState.hash,
113
- decimals,
114
- }
115
-
116
- this.tokenCache.set(tokenHash, token)
117
-
118
- return token
119
- } catch {
120
- throw new Error(`Token not found: ${tokenHash}`)
121
- }
122
- }
123
-
124
- async getBalance(address: string): Promise<BalanceResponse[]> {
125
- const rpcClient = new rpc.RPCClient(this.network.url)
126
- const response = await rpcClient.getNep17Balances(address)
127
-
128
- const promises = response.balance.map<Promise<BalanceResponse>>(async balance => {
129
- let token: Token = {
130
- hash: balance.assethash,
131
- name: '-',
132
- symbol: '-',
133
- decimals: 8,
134
- }
135
- try {
136
- token = await this.getTokenInfo(balance.assethash)
137
- } catch {
138
- // Empty Block
139
- }
140
-
141
- return {
142
- amount: u.BigInteger.fromNumber(balance.amount).toDecimal(token?.decimals ?? 8),
143
- token,
144
- }
145
- })
146
- const balances = await Promise.all(promises)
147
-
148
- return balances
149
- }
150
-
151
- async getBlockHeight(): Promise<number> {
152
- const rpcClient = new rpc.RPCClient(this.network.url)
153
- return await rpcClient.getBlockCount()
154
- }
155
-
156
- async getUnclaimed(address: string): Promise<string> {
157
- const rpcClient = new rpc.RPCClient(this.network.url)
158
- const response = await rpcClient.getUnclaimedGas(address)
159
- return u.BigInteger.fromNumber(response).toDecimal(this.claimToken.decimals)
160
- }
161
- }
@@ -1,124 +0,0 @@
1
- import { BDSClaimable, BlockchainDataService } from '@cityofzion/blockchain-service'
2
- import { DoraBDSNeo3 } from '../DoraBDSNeo3'
3
- import { RPCBDSNeo3 } from '../RpcBDSNeo3'
4
- import { DEFAULT_URL_BY_NETWORK_TYPE, TOKENS } from '../constants'
5
-
6
- const gasToken = TOKENS.testnet.find(t => t.symbol === 'GAS')!
7
- const doraBDSNeo3 = new DoraBDSNeo3({ type: 'testnet', url: DEFAULT_URL_BY_NETWORK_TYPE.testnet }, gasToken, gasToken)
8
- const rpcBDSNeo3 = new RPCBDSNeo3({ type: 'testnet', url: DEFAULT_URL_BY_NETWORK_TYPE.testnet }, gasToken, gasToken)
9
-
10
- describe('BDSNeo3', () => {
11
- it.each([doraBDSNeo3, rpcBDSNeo3])(
12
- 'Should be able to get transaction - %s',
13
- async (bdsNeo3: BlockchainDataService) => {
14
- const hash = '0x70e7381c5dee6e81becd02844e4e0199f6b3df834213bc89418dc4da32cf3f21'
15
- const transaction = await bdsNeo3.getTransaction(hash)
16
-
17
- expect(transaction).toEqual(
18
- expect.objectContaining({
19
- block: expect.any(Number),
20
- hash,
21
- notifications: [],
22
- transfers: [],
23
- time: expect.any(Number),
24
- fee: expect.any(String),
25
- })
26
- )
27
- }
28
- )
29
-
30
- it.each([doraBDSNeo3])(
31
- 'Should be able to get transactions of address - %s',
32
- async (bdsNeo3: BlockchainDataService) => {
33
- const address = 'NNmTVFrSPhe7zjgN6iq9cLgXJwLZziUKV6'
34
- const response = await bdsNeo3.getTransactionsByAddress({ address, page: 1 })
35
-
36
- response.transactions.forEach(transaction => {
37
- expect(transaction).toEqual(
38
- expect.objectContaining({
39
- block: expect.any(Number),
40
- hash: expect.any(String),
41
- time: expect.any(Number),
42
- fee: expect.any(String),
43
- notifications: expect.arrayContaining([
44
- expect.objectContaining({
45
- eventName: expect.any(String),
46
- state: expect.arrayContaining([
47
- {
48
- type: expect.any(String),
49
- value: expect.any(String),
50
- },
51
- ]),
52
- }),
53
- ]),
54
- transfers: expect.arrayContaining([
55
- expect.objectContaining({
56
- amount: expect.any(String),
57
- from: expect.any(String),
58
- to: expect.any(String),
59
- type: 'token',
60
- }),
61
- ]),
62
- })
63
- )
64
- })
65
- }
66
- )
67
-
68
- it.each([doraBDSNeo3, rpcBDSNeo3])('Should be able to get contract - %s', async (bdsNeo3: BlockchainDataService) => {
69
- const hash = '0xd2a4cff31913016155e38e474a2c06d08be276cf'
70
- const contract = await bdsNeo3.getContract(hash)
71
- expect(contract).toEqual({
72
- hash: hash,
73
- name: 'GasToken',
74
- methods: expect.arrayContaining([
75
- expect.objectContaining({
76
- name: expect.any(String),
77
- parameters: expect.arrayContaining([
78
- expect.objectContaining({ name: expect.any(String), type: expect.any(String) }),
79
- ]),
80
- }),
81
- ]),
82
- })
83
- })
84
-
85
- it.each([doraBDSNeo3, rpcBDSNeo3])(
86
- 'Should be able to get token info - %s',
87
- async (bdsNeo3: BlockchainDataService) => {
88
- const hash = '0xd2a4cff31913016155e38e474a2c06d08be276cf'
89
- const token = await bdsNeo3.getTokenInfo(hash)
90
-
91
- expect(token).toEqual({
92
- decimals: 8,
93
- hash: hash,
94
- name: 'GasToken',
95
- symbol: 'GAS',
96
- })
97
- }
98
- )
99
-
100
- it.each([doraBDSNeo3, rpcBDSNeo3])('Should be able to get balance - %s', async (bdsNeo3: BlockchainDataService) => {
101
- const address = 'NNmTVFrSPhe7zjgN6iq9cLgXJwLZziUKV6'
102
- const balance = await bdsNeo3.getBalance(address)
103
- balance.forEach(balance => {
104
- expect(balance).toEqual({
105
- amount: expect.any(String),
106
- token: {
107
- hash: expect.any(String),
108
- name: expect.any(String),
109
- symbol: expect.any(String),
110
- decimals: expect.any(Number),
111
- },
112
- })
113
- })
114
- })
115
-
116
- it.each([doraBDSNeo3, rpcBDSNeo3])(
117
- 'Should be able to get unclaimed - %s',
118
- async (bdsNeo3: BlockchainDataService & BDSClaimable) => {
119
- const address = 'NNmTVFrSPhe7zjgN6iq9cLgXJwLZziUKV6'
120
- const unclaimed = await bdsNeo3.getUnclaimed(address)
121
- expect(unclaimed).toEqual(expect.any(String))
122
- }
123
- )
124
- })
@@ -1,175 +0,0 @@
1
- import { sleep } from './utils/sleep'
2
- import { BSNeo3 } from '../BSNeo3'
3
- import { generateMnemonic } from '@cityofzion/bs-asteroid-sdk'
4
- import TransportNodeHid from '@ledgerhq/hw-transport-node-hid'
5
-
6
- let bsNeo3: BSNeo3
7
-
8
- describe('BSNeo3', () => {
9
- beforeAll(() => {
10
- bsNeo3 = new BSNeo3('neo3', { type: 'testnet', url: 'https://testnet1.neo.coz.io:443' })
11
- })
12
-
13
- it('Should be able to validate an address', () => {
14
- const validAddress = 'NPRMF5bmYuW23DeDJqsDJenhXkAPSJyuYe'
15
- const invalidAddress = 'invalid address'
16
-
17
- expect(bsNeo3.validateAddress(validAddress)).toBeTruthy()
18
- expect(bsNeo3.validateAddress(invalidAddress)).toBeFalsy()
19
- })
20
-
21
- it('Should be able to validate an encrypted key', () => {
22
- const validEncryptedKey = '6PYVPVe1fQznphjbUxXP9KZJqPMVnVwCx5s5pr5axRJ8uHkMtZg97eT5kL'
23
- const invalidEncryptedKey = 'invalid encrypted key'
24
-
25
- expect(bsNeo3.validateEncrypted(validEncryptedKey)).toBeTruthy()
26
- expect(bsNeo3.validateEncrypted(invalidEncryptedKey)).toBeFalsy()
27
- })
28
-
29
- it('Should be able to validate a wif', () => {
30
- const validWif = 'L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP'
31
- const invalidWif = 'invalid wif'
32
-
33
- expect(bsNeo3.validateKey(validWif)).toBeTruthy()
34
- expect(bsNeo3.validateKey(invalidWif)).toBeFalsy()
35
- })
36
-
37
- it('Should be able to validate an domain', () => {
38
- const validDomain = 'test.neo'
39
- const invalidDomain = 'invalid domain'
40
-
41
- expect(bsNeo3.validateNameServiceDomainFormat(validDomain)).toBeTruthy()
42
- expect(bsNeo3.validateNameServiceDomainFormat(invalidDomain)).toBeFalsy()
43
- })
44
-
45
- it('Should be able to generate a mnemonic', () => {
46
- expect(() => {
47
- const mnemonic = generateMnemonic()
48
- expect(mnemonic).toHaveLength(12)
49
- }).not.toThrowError()
50
- })
51
-
52
- it('Should be able to gererate a account from mnemonic', () => {
53
- const mnemonic = generateMnemonic()
54
- const account = bsNeo3.generateAccountFromMnemonic(mnemonic, 0)
55
-
56
- expect(bsNeo3.validateAddress(account.address)).toBeTruthy()
57
- expect(bsNeo3.validateKey(account.key)).toBeTruthy()
58
- })
59
-
60
- it('Should be able to generate a account from wif', () => {
61
- const mnemonic = generateMnemonic()
62
- const account = bsNeo3.generateAccountFromMnemonic(mnemonic, 0)
63
-
64
- const accountFromWif = bsNeo3.generateAccountFromKey(account.key)
65
- expect(account).toEqual(expect.objectContaining(accountFromWif))
66
- })
67
-
68
- it('Should be able to decrypt a encrypted key', async () => {
69
- const mnemonic = generateMnemonic()
70
- const account = bsNeo3.generateAccountFromMnemonic(mnemonic, 0)
71
- const password = 'TestPassword'
72
- const encryptedKey = await bsNeo3.encrypt(account.key, password)
73
- const decryptedAccount = await bsNeo3.decrypt(encryptedKey, password)
74
- expect(account).toEqual(expect.objectContaining(decryptedAccount))
75
- }, 20000)
76
-
77
- it('Should be able to encrypt a key', async () => {
78
- const mnemonic = generateMnemonic()
79
- const account = bsNeo3.generateAccountFromMnemonic(mnemonic, 0)
80
- const password = 'TestPassword'
81
- const encryptedKey = await bsNeo3.encrypt(account.key, password)
82
- expect(encryptedKey).toEqual(expect.any(String))
83
- })
84
-
85
- it.skip('Should be able to calculate transfer fee', async () => {
86
- const account = bsNeo3.generateAccountFromKey(process.env.TESTNET_PRIVATE_KEY as string)
87
-
88
- const fee = await bsNeo3.calculateTransferFee({
89
- senderAccount: account,
90
- intent: {
91
- amount: '0.00000001',
92
- receiverAddress: 'NPRMF5bmYuW23DeDJqsDJenhXkAPSJyuYe',
93
- tokenHash: bsNeo3.feeToken.hash,
94
- tokenDecimals: bsNeo3.feeToken.decimals,
95
- },
96
- })
97
-
98
- expect(fee).toEqual({
99
- total: expect.any(Number),
100
- networkFee: expect.any(Number),
101
- systemFee: expect.any(Number),
102
- })
103
- })
104
-
105
- it.skip('Should be able to transfer', async () => {
106
- const account = bsNeo3.generateAccountFromKey(process.env.TESTNET_PRIVATE_KEY as string)
107
- const balance = await bsNeo3.blockchainDataService.getBalance(account.address)
108
- const gasBalance = balance.find(b => b.token.symbol === bsNeo3.feeToken.symbol)
109
- expect(Number(gasBalance?.amount)).toBeGreaterThan(0.00000001)
110
-
111
- const transactionHash = await bsNeo3.transfer({
112
- senderAccount: account,
113
- intent: {
114
- amount: '0.00000001',
115
- receiverAddress: 'NPRMF5bmYuW23DeDJqsDJenhXkAPSJyuYe',
116
- tokenHash: bsNeo3.feeToken.hash,
117
- tokenDecimals: bsNeo3.feeToken.decimals,
118
- },
119
- })
120
-
121
- expect(transactionHash).toEqual(expect.any(String))
122
- })
123
-
124
- it.skip('Should be able to transfer with ledger', async () => {
125
- const transport = await TransportNodeHid.create()
126
- const publicKey = await bsNeo3.ledgerService.getPublicKey(transport)
127
-
128
- const account = bsNeo3.generateAccountFromPublicKey(publicKey)
129
-
130
- const balance = await bsNeo3.blockchainDataService.getBalance(account.address)
131
- const gasBalance = balance.find(b => b.token.symbol === bsNeo3.feeToken.symbol)
132
- expect(Number(gasBalance?.amount)).toBeGreaterThan(0.00000001)
133
-
134
- const transactionHash = await bsNeo3.transfer({
135
- senderAccount: account,
136
- intent: {
137
- amount: '1',
138
- receiverAddress: 'NPRMF5bmYuW23DeDJqsDJenhXkAPSJyuYe',
139
- tokenHash: bsNeo3.feeToken.hash,
140
- tokenDecimals: bsNeo3.feeToken.decimals,
141
- },
142
- isLedger: true,
143
- ledgerTransport: transport,
144
- })
145
-
146
- expect(transactionHash).toEqual(expect.any(String))
147
- }, 60000)
148
-
149
- it.skip('Should be able to claim', async () => {
150
- const account = bsNeo3.generateAccountFromKey(process.env.TESTNET_PRIVATE_KEY as string)
151
-
152
- const maxTries = 10
153
- let tries = 0
154
-
155
- while (tries < maxTries) {
156
- try {
157
- const unclaimed = await bsNeo3.blockchainDataService.getUnclaimed(account.address)
158
- if (Number(unclaimed) <= 0) continue
159
-
160
- const transactionHash = await bsNeo3.claim(account)
161
- expect(transactionHash).toEqual(expect.any(String))
162
- break
163
- } catch (error) {
164
- await sleep(4000)
165
- } finally {
166
- tries++
167
- }
168
- }
169
- }, 60000)
170
-
171
- it('Should be able to resolve a name service domain', async () => {
172
- const owner = await bsNeo3.resolveNameServiceDomain('neo.neo')
173
- expect(owner).toEqual('Nj39M97Rk2e23JiULBBMQmvpcnKaRHqxFf')
174
- })
175
- })