@cityofzion/bs-neo-legacy 0.7.3 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/.rush/temp/operation/build/all.log +1 -0
  2. package/.rush/temp/operation/build/state.json +3 -0
  3. package/.rush/temp/package-deps_build.json +6 -4
  4. package/.rush/temp/shrinkwrap-deps.json +350 -101
  5. package/CHANGELOG.json +22 -0
  6. package/CHANGELOG.md +11 -0
  7. package/bs-neo-legacy.build.log +1 -2
  8. package/dist/BSNeoLegacy.d.ts +24 -24
  9. package/dist/BSNeoLegacy.js +173 -173
  10. package/dist/CryptoCompareEDSNeoLegacy.d.ts +7 -7
  11. package/dist/CryptoCompareEDSNeoLegacy.js +51 -41
  12. package/dist/DoraBDSNeoLegacy.d.ts +16 -16
  13. package/dist/DoraBDSNeoLegacy.js +163 -163
  14. package/dist/DoraESNeoLegacy.d.ts +7 -7
  15. package/dist/DoraESNeoLegacy.js +17 -17
  16. package/dist/assets/tokens/common.json +18 -18
  17. package/dist/assets/tokens/mainnet.json +620 -620
  18. package/dist/constants.d.ts +13 -13
  19. package/dist/constants.js +23 -23
  20. package/dist/index.d.ts +4 -4
  21. package/dist/index.js +20 -20
  22. package/jest.config.ts +13 -13
  23. package/jest.setup.ts +1 -1
  24. package/package.json +26 -25
  25. package/src/BSNeoLegacy.ts +198 -198
  26. package/src/CryptoCompareEDSNeoLegacy.ts +50 -40
  27. package/src/DoraBDSNeoLegacy.ts +173 -173
  28. package/src/DoraESNeoLegacy.ts +18 -18
  29. package/src/__tests__/BDSNeoLegacy.spec.ts +120 -120
  30. package/src/__tests__/BSNeoLegacy.spec.ts +127 -127
  31. package/src/__tests__/CryptoCompareExchange.spec.ts +48 -46
  32. package/src/__tests__/DoraESNeoLegacy.spec.ts +15 -15
  33. package/src/assets/tokens/common.json +17 -17
  34. package/src/assets/tokens/mainnet.json +619 -619
  35. package/src/constants.ts +23 -23
  36. package/src/index.ts +4 -4
  37. package/tsconfig.build.json +4 -4
  38. package/tsconfig.json +14 -14
  39. package/dist/BDSNeoLegacy.d.ts +0 -15
  40. package/dist/BDSNeoLegacy.js +0 -199
  41. package/dist/asset/tokens.json +0 -480
  42. package/dist/explorer/dora/DoraResponsesNeoLegacy.d.ts +0 -95
  43. package/dist/explorer/dora/DoraResponsesNeoLegacy.js +0 -2
  44. package/dist/explorer/dora/DoraRoutesNeoLegacy.d.ts +0 -7
  45. package/dist/explorer/dora/DoraRoutesNeoLegacy.js +0 -10
  46. package/dist/explorer/index.d.ts +0 -6
  47. package/dist/explorer/index.js +0 -23
  48. package/docs/.nojekyll +0 -1
  49. package/docs/assets/highlight.css +0 -22
  50. package/docs/assets/main.js +0 -58
  51. package/docs/assets/search.js +0 -1
  52. package/docs/assets/style.css +0 -1280
  53. package/docs/classes/BDSNeoLegacy.html +0 -243
  54. package/docs/classes/BSNeoLegacy.html +0 -423
  55. package/docs/index.html +0 -70
  56. package/docs/interfaces/DoraNeoLegacyAsset.html +0 -103
  57. package/docs/interfaces/DoraNeoLegacyAssetResponse.html +0 -117
  58. package/docs/interfaces/DoraNeoLegacyBalance.html +0 -89
  59. package/docs/interfaces/DoraNeoLegacyConsensusNode.html +0 -75
  60. package/docs/interfaces/DoraNeoLegacyDetails.html +0 -138
  61. package/docs/interfaces/DoraNeoLegacyEntriesEntity.html +0 -110
  62. package/docs/interfaces/DoraNeoLegacyNameEntity.html +0 -75
  63. package/docs/interfaces/DoraNeoLegacyScriptsEntity.html +0 -75
  64. package/docs/interfaces/DoraNeoLegacyTransaction.html +0 -152
  65. package/docs/interfaces/DoraNeoLegacyTransactionsHistory.html +0 -96
  66. package/docs/interfaces/DoraNeoLegacyUnclaimed.html +0 -82
  67. package/docs/interfaces/DoraNeoLegacyVinEntity.html +0 -75
  68. package/docs/interfaces/DoraNeoLegacyVoutEntity.html +0 -89
  69. package/docs/modules.html +0 -98
  70. package/docs/variables/DORA_NEO_LEGACY_ASSET.html +0 -69
  71. package/docs/variables/DORA_NEO_LEGACY_BALANCE.html +0 -69
  72. package/docs/variables/DORA_NEO_LEGACY_CONTRACT.html +0 -69
  73. package/docs/variables/DORA_NEO_LEGACY_HISTORY_TRANSACTIONS.html +0 -69
  74. package/docs/variables/DORA_NEO_LEGACY_NODES.html +0 -69
  75. package/docs/variables/DORA_NEO_LEGACY_TRANSACTION.html +0 -69
  76. package/docs/variables/DORA_NEO_LEGACY_UNCLAIMED.html +0 -69
  77. package/docs/variables/explorerNeoLegacyOption.html +0 -74
@@ -1,13 +1,13 @@
1
- import { NetworkType, Token } from '@cityofzion/blockchain-service';
2
- export declare const TOKENS: Record<NetworkType, Token[]>;
3
- export declare const LEGACY_NETWORK_BY_NETWORK_TYPE: Record<Exclude<NetworkType, 'custom'>, string>;
4
- export declare const NATIVE_ASSETS: {
5
- symbol: string;
6
- type: string;
7
- name: string;
8
- hash: string;
9
- decimals: number;
10
- blockchain: string;
11
- }[];
12
- export declare const DEFAULT_URL_BY_NETWORK_TYPE: Record<Exclude<NetworkType, 'custom'>, string>;
13
- export declare const DERIVATION_PATH = "m/44'/888'/0'/0/?";
1
+ import { NetworkType, Token } from '@cityofzion/blockchain-service';
2
+ export declare const TOKENS: Record<NetworkType, Token[]>;
3
+ export declare const LEGACY_NETWORK_BY_NETWORK_TYPE: Record<Exclude<NetworkType, 'custom'>, string>;
4
+ export declare const NATIVE_ASSETS: {
5
+ symbol: string;
6
+ type: string;
7
+ name: string;
8
+ hash: string;
9
+ decimals: number;
10
+ blockchain: string;
11
+ }[];
12
+ export declare const DEFAULT_URL_BY_NETWORK_TYPE: Record<Exclude<NetworkType, 'custom'>, string>;
13
+ export declare const DERIVATION_PATH = "m/44'/888'/0'/0/?";
package/dist/constants.js CHANGED
@@ -1,23 +1,23 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DERIVATION_PATH = exports.DEFAULT_URL_BY_NETWORK_TYPE = exports.NATIVE_ASSETS = exports.LEGACY_NETWORK_BY_NETWORK_TYPE = exports.TOKENS = void 0;
7
- const common_json_1 = __importDefault(require("./assets/tokens/common.json"));
8
- const mainnet_json_1 = __importDefault(require("./assets/tokens/mainnet.json"));
9
- exports.TOKENS = {
10
- mainnet: [...common_json_1.default, ...mainnet_json_1.default],
11
- testnet: common_json_1.default,
12
- custom: common_json_1.default,
13
- };
14
- exports.LEGACY_NETWORK_BY_NETWORK_TYPE = {
15
- mainnet: 'MainNet',
16
- testnet: 'TestNet',
17
- };
18
- exports.NATIVE_ASSETS = common_json_1.default;
19
- exports.DEFAULT_URL_BY_NETWORK_TYPE = {
20
- mainnet: 'http://seed9.ngd.network:10332',
21
- testnet: 'http://seed5.ngd.network:20332',
22
- };
23
- exports.DERIVATION_PATH = "m/44'/888'/0'/0/?";
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DERIVATION_PATH = exports.DEFAULT_URL_BY_NETWORK_TYPE = exports.NATIVE_ASSETS = exports.LEGACY_NETWORK_BY_NETWORK_TYPE = exports.TOKENS = void 0;
7
+ const common_json_1 = __importDefault(require("./assets/tokens/common.json"));
8
+ const mainnet_json_1 = __importDefault(require("./assets/tokens/mainnet.json"));
9
+ exports.TOKENS = {
10
+ mainnet: [...common_json_1.default, ...mainnet_json_1.default],
11
+ testnet: common_json_1.default,
12
+ custom: common_json_1.default,
13
+ };
14
+ exports.LEGACY_NETWORK_BY_NETWORK_TYPE = {
15
+ mainnet: 'MainNet',
16
+ testnet: 'TestNet',
17
+ };
18
+ exports.NATIVE_ASSETS = common_json_1.default;
19
+ exports.DEFAULT_URL_BY_NETWORK_TYPE = {
20
+ mainnet: 'http://seed9.ngd.network:10332',
21
+ testnet: 'http://seed5.ngd.network:20332',
22
+ };
23
+ exports.DERIVATION_PATH = "m/44'/888'/0'/0/?";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export * from './BSNeoLegacy';
2
- export * from './DoraBDSNeoLegacy';
3
- export * from './constants';
4
- export * from './CryptoCompareEDSNeoLegacy';
1
+ export * from './BSNeoLegacy';
2
+ export * from './DoraBDSNeoLegacy';
3
+ export * from './constants';
4
+ export * from './CryptoCompareEDSNeoLegacy';
package/dist/index.js CHANGED
@@ -1,20 +1,20 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./BSNeoLegacy"), exports);
18
- __exportStar(require("./DoraBDSNeoLegacy"), exports);
19
- __exportStar(require("./constants"), exports);
20
- __exportStar(require("./CryptoCompareEDSNeoLegacy"), exports);
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./BSNeoLegacy"), exports);
18
+ __exportStar(require("./DoraBDSNeoLegacy"), exports);
19
+ __exportStar(require("./constants"), exports);
20
+ __exportStar(require("./CryptoCompareEDSNeoLegacy"), exports);
package/jest.config.ts CHANGED
@@ -1,13 +1,13 @@
1
- import { JestConfigWithTsJest } from 'ts-jest'
2
- const config: JestConfigWithTsJest = {
3
- preset: 'ts-jest',
4
- testEnvironment: 'node',
5
- clearMocks: true,
6
- verbose: true,
7
- bail: true,
8
- testMatch: ['<rootDir>/**/*.spec.ts'],
9
- setupFiles: ['<rootDir>/jest.setup.ts'],
10
- detectOpenHandles: true,
11
- }
12
-
13
- export default config
1
+ import { JestConfigWithTsJest } from 'ts-jest'
2
+ const config: JestConfigWithTsJest = {
3
+ preset: 'ts-jest',
4
+ testEnvironment: 'node',
5
+ clearMocks: true,
6
+ verbose: true,
7
+ bail: true,
8
+ testMatch: ['<rootDir>/**/*.spec.ts'],
9
+ setupFiles: ['<rootDir>/jest.setup.ts'],
10
+ detectOpenHandles: true,
11
+ }
12
+
13
+ export default config
package/jest.setup.ts CHANGED
@@ -1 +1 @@
1
- import 'dotenv/config'
1
+ import 'dotenv/config'
package/package.json CHANGED
@@ -1,26 +1,27 @@
1
- {
2
- "name": "@cityofzion/bs-neo-legacy",
3
- "version": "0.7.3",
4
- "main": "dist/index.js",
5
- "types": "dist/index.d.ts",
6
- "author": "Coz",
7
- "license": "MIT",
8
- "scripts": {
9
- "build": "tsc --project tsconfig.build.json",
10
- "test": "jest --config jest.config.ts"
11
- },
12
- "dependencies": {
13
- "@cityofzion/blockchain-service": "0.7.3",
14
- "@cityofzion/bs-asteroid-sdk": "0.7.3",
15
- "@cityofzion/dora-ts": "0.0.11",
16
- "@cityofzion/neon-js": "4.8.3"
17
- },
18
- "devDependencies": {
19
- "ts-node": "10.9.1",
20
- "typescript": "4.9.5",
21
- "jest": "29.6.2",
22
- "ts-jest": "29.1.1",
23
- "@types/jest": "29.5.3",
24
- "dotenv": "16.3.1"
25
- }
1
+ {
2
+ "name": "@cityofzion/bs-neo-legacy",
3
+ "version": "0.8.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "author": "Coz",
7
+ "license": "MIT",
8
+ "dependencies": {
9
+ "@cityofzion/dora-ts": "0.0.11",
10
+ "@cityofzion/neon-js": "4.8.3",
11
+ "axios": "1.5.1",
12
+ "@cityofzion/blockchain-service": "0.8.0",
13
+ "@cityofzion/bs-asteroid-sdk": "0.7.3"
14
+ },
15
+ "devDependencies": {
16
+ "ts-node": "10.9.1",
17
+ "typescript": "4.9.5",
18
+ "jest": "29.6.2",
19
+ "ts-jest": "29.1.1",
20
+ "@types/jest": "29.5.3",
21
+ "dotenv": "16.3.1"
22
+ },
23
+ "scripts": {
24
+ "build": "tsc --project tsconfig.build.json",
25
+ "test": "jest --config jest.config.ts"
26
+ }
26
27
  }
@@ -1,198 +1,198 @@
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
- } catch {
107
- const key = await wallet.decrypt(encryptedKey, password)
108
- return this.generateAccountFromKey(key)
109
- }
110
-
111
- if (!BsReactNativeDecrypt) {
112
- throw new Error('@CityOfZion/bs-react-native-decrypt is not installed')
113
- }
114
-
115
- const privateKey = await BsReactNativeDecrypt.decryptNeoLegacy(encryptedKey, password)
116
- return this.generateAccountFromKey(privateKey)
117
- }
118
-
119
- async transfer({ intent: transferIntent, senderAccount, tipIntent, ...params }: TransferParam): Promise<string> {
120
- const apiProvider = new api.neoCli.instance(this.network.url)
121
- const account = new wallet.Account(senderAccount.key)
122
- const priorityFee = Number(params.priorityFee ?? 0)
123
-
124
- const nativeIntents: ReturnType<typeof api.makeIntent> = []
125
- const nep5ScriptBuilder = new sc.ScriptBuilder()
126
-
127
- const intents = [transferIntent, ...(tipIntent ? [tipIntent] : [])]
128
-
129
- for (const intent of intents) {
130
- const tokenHashFixed = intent.tokenHash.replace('0x', '')
131
-
132
- const nativeAsset = NATIVE_ASSETS.find(asset => asset.hash === tokenHashFixed)
133
- if (nativeAsset) {
134
- nativeIntents.push(...api.makeIntent({ [nativeAsset.symbol]: Number(intent.amount) }, intent.receiverAddress))
135
- continue
136
- }
137
-
138
- nep5ScriptBuilder.emitAppCall(tokenHashFixed, 'transfer', [
139
- u.reverseHex(wallet.getScriptHashFromAddress(account.address)),
140
- u.reverseHex(wallet.getScriptHashFromAddress(intent.receiverAddress)),
141
- sc.ContractParam.integer(
142
- new u.Fixed8(intent.amount)
143
- .div(Math.pow(10, 8 - (intent.tokenDecimals ?? 8)))
144
- .toRawNumber()
145
- .toString()
146
- ),
147
- ])
148
- }
149
-
150
- let response
151
-
152
- if (nep5ScriptBuilder.isEmpty()) {
153
- response = await api.sendAsset({
154
- account,
155
- api: apiProvider,
156
- url: this.network.url,
157
- intents: nativeIntents,
158
- fees: priorityFee,
159
- })
160
- } else {
161
- response = await api.doInvoke({
162
- intents: nativeIntents.length > 0 ? nativeIntents : undefined,
163
- account,
164
- api: apiProvider,
165
- script: nep5ScriptBuilder.str,
166
- url: this.network.url,
167
- fees: priorityFee,
168
- })
169
- }
170
-
171
- if (!response.tx) throw new Error('Failed to send transaction')
172
- return response.tx.hash
173
- }
174
-
175
- async claim(account: Account): Promise<string> {
176
- const neoAccount = new wallet.Account(account.key)
177
-
178
- const balances = await this.blockchainDataService.getBalance(account.address)
179
- const neoBalance = balances.find(balance => balance.token.symbol === 'NEO')
180
- if (!neoBalance) throw new Error('It is necessary to have NEO to claim')
181
-
182
- const unclaimed = await this.blockchainDataService.getUnclaimed(account.address)
183
- if (Number(unclaimed) <= 0) throw new Error(`Doesn't have gas to claim`)
184
-
185
- const apiProvider = new api.neoCli.instance(this.legacyNetwork)
186
- const claims = await apiProvider.getClaims(account.address)
187
-
188
- const response = await api.claimGas({
189
- claims,
190
- api: apiProvider,
191
- account: neoAccount,
192
- url: this.network.url,
193
- })
194
-
195
- if (!response.tx) throw new Error('Failed to claim')
196
- return response.tx.hash
197
- }
198
- }
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
+ } catch {
107
+ const key = await wallet.decrypt(encryptedKey, password)
108
+ return this.generateAccountFromKey(key)
109
+ }
110
+
111
+ if (!BsReactNativeDecrypt) {
112
+ throw new Error('@CityOfZion/bs-react-native-decrypt is not installed')
113
+ }
114
+
115
+ const privateKey = await BsReactNativeDecrypt.decryptNeoLegacy(encryptedKey, password)
116
+ return this.generateAccountFromKey(privateKey)
117
+ }
118
+
119
+ async transfer({ intent: transferIntent, senderAccount, tipIntent, ...params }: TransferParam): Promise<string> {
120
+ const apiProvider = new api.neoCli.instance(this.network.url)
121
+ const account = new wallet.Account(senderAccount.key)
122
+ const priorityFee = Number(params.priorityFee ?? 0)
123
+
124
+ const nativeIntents: ReturnType<typeof api.makeIntent> = []
125
+ const nep5ScriptBuilder = new sc.ScriptBuilder()
126
+
127
+ const intents = [transferIntent, ...(tipIntent ? [tipIntent] : [])]
128
+
129
+ for (const intent of intents) {
130
+ const tokenHashFixed = intent.tokenHash.replace('0x', '')
131
+
132
+ const nativeAsset = NATIVE_ASSETS.find(asset => asset.hash === tokenHashFixed)
133
+ if (nativeAsset) {
134
+ nativeIntents.push(...api.makeIntent({ [nativeAsset.symbol]: Number(intent.amount) }, intent.receiverAddress))
135
+ continue
136
+ }
137
+
138
+ nep5ScriptBuilder.emitAppCall(tokenHashFixed, 'transfer', [
139
+ u.reverseHex(wallet.getScriptHashFromAddress(account.address)),
140
+ u.reverseHex(wallet.getScriptHashFromAddress(intent.receiverAddress)),
141
+ sc.ContractParam.integer(
142
+ new u.Fixed8(intent.amount)
143
+ .div(Math.pow(10, 8 - (intent.tokenDecimals ?? 8)))
144
+ .toRawNumber()
145
+ .toString()
146
+ ),
147
+ ])
148
+ }
149
+
150
+ let response
151
+
152
+ if (nep5ScriptBuilder.isEmpty()) {
153
+ response = await api.sendAsset({
154
+ account,
155
+ api: apiProvider,
156
+ url: this.network.url,
157
+ intents: nativeIntents,
158
+ fees: priorityFee,
159
+ })
160
+ } else {
161
+ response = await api.doInvoke({
162
+ intents: nativeIntents.length > 0 ? nativeIntents : undefined,
163
+ account,
164
+ api: apiProvider,
165
+ script: nep5ScriptBuilder.str,
166
+ url: this.network.url,
167
+ fees: priorityFee,
168
+ })
169
+ }
170
+
171
+ if (!response.tx) throw new Error('Failed to send transaction')
172
+ return response.tx.hash
173
+ }
174
+
175
+ async claim(account: Account): Promise<string> {
176
+ const neoAccount = new wallet.Account(account.key)
177
+
178
+ const balances = await this.blockchainDataService.getBalance(account.address)
179
+ const neoBalance = balances.find(balance => balance.token.symbol === 'NEO')
180
+ if (!neoBalance) throw new Error('It is necessary to have NEO to claim')
181
+
182
+ const unclaimed = await this.blockchainDataService.getUnclaimed(account.address)
183
+ if (Number(unclaimed) <= 0) throw new Error(`Doesn't have gas to claim`)
184
+
185
+ const apiProvider = new api.neoCli.instance(this.legacyNetwork)
186
+ const claims = await apiProvider.getClaims(account.address)
187
+
188
+ const response = await api.claimGas({
189
+ claims,
190
+ api: apiProvider,
191
+ account: neoAccount,
192
+ url: this.network.url,
193
+ })
194
+
195
+ if (!response.tx) throw new Error('Failed to claim')
196
+ return response.tx.hash
197
+ }
198
+ }