@cityofzion/bs-neo3 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.
- package/.rush/temp/operation/build/all.log +1 -0
- package/.rush/temp/operation/build/state.json +1 -1
- package/.rush/temp/package-deps_build.json +7 -5
- package/.rush/temp/shrinkwrap-deps.json +354 -130
- package/CHANGELOG.json +22 -0
- package/CHANGELOG.md +11 -0
- package/bs-neo3.build.log +1 -2
- package/dist/BSNeo3.d.ts +28 -28
- package/dist/BSNeo3.js +184 -184
- package/dist/DoraBDSNeo3.d.ts +12 -12
- package/dist/DoraBDSNeo3.js +169 -169
- package/dist/DoraESNeo3.d.ts +7 -7
- package/dist/DoraESNeo3.js +19 -19
- package/dist/FlamingoEDSNeo3.d.ts +8 -8
- package/dist/FlamingoEDSNeo3.js +45 -44
- package/dist/GhostMarketNDSNeo3.d.ts +10 -10
- package/dist/GhostMarketNDSNeo3.js +75 -75
- package/dist/RpcBDSNeo3.d.ts +16 -16
- package/dist/RpcBDSNeo3.js +153 -153
- package/dist/assets/tokens/common.json +14 -14
- package/dist/assets/tokens/mainnet.json +116 -116
- package/dist/constants.d.ts +7 -7
- package/dist/constants.js +28 -28
- package/dist/index.d.ts +6 -6
- package/dist/index.js +22 -22
- package/jest.config.ts +13 -13
- package/jest.setup.ts +1 -1
- package/package.json +33 -32
- package/src/BSNeo3.ts +228 -228
- package/src/DoraBDSNeo3.ts +180 -180
- package/src/DoraESNeo3.ts +19 -19
- package/src/FlamingoEDSNeo3.ts +47 -45
- package/src/GhostMarketNDSNeo3.ts +117 -117
- package/src/RpcBDSNeo3.ts +157 -157
- package/src/__tests__/BDSNeo3.spec.ts +126 -126
- package/src/__tests__/BSNeo3.spec.ts +142 -142
- package/src/__tests__/DoraESNeo3.spec.ts +23 -23
- package/src/__tests__/FlamingoEDSNeo3.spec.ts +48 -45
- package/src/__tests__/GhostMarketNDSNeo3.spec.ts +43 -43
- package/src/__tests__/utils/sleep.ts +1 -1
- package/src/assets/tokens/common.json +13 -13
- package/src/assets/tokens/mainnet.json +115 -115
- package/src/constants.ts +29 -29
- package/src/index.ts +6 -6
- package/tsconfig.build.json +4 -4
- package/tsconfig.json +14 -14
- package/dist/BDSNeo3.d.ts +0 -15
- package/dist/BDSNeo3.js +0 -211
- package/dist/assets/tokens.json +0 -128
- package/dist/exceptions.d.ts +0 -3
- package/dist/exceptions.js +0 -8
- package/dist/explorer/dora/DoraNeo3Responses.d.ts +0 -174
- package/dist/explorer/dora/DoraNeo3Responses.js +0 -3
- package/dist/explorer/dora/DoraNeo3Routes.d.ts +0 -6
- package/dist/explorer/dora/DoraNeo3Routes.js +0 -9
- package/dist/explorer/index.d.ts +0 -6
- package/dist/explorer/index.js +0 -23
- package/docs/.nojekyll +0 -1
- package/docs/assets/highlight.css +0 -22
- package/docs/assets/main.js +0 -58
- package/docs/assets/search.js +0 -1
- package/docs/assets/style.css +0 -1280
- package/docs/classes/BDSNeo3.html +0 -253
- package/docs/classes/BSNeo3.html +0 -442
- package/docs/index.html +0 -82
- package/docs/interfaces/DoraNeo3Abi.html +0 -78
- package/docs/interfaces/DoraNeo3Asset.html +0 -117
- package/docs/interfaces/DoraNeo3AssetState.html +0 -96
- package/docs/interfaces/DoraNeo3Balance.html +0 -89
- package/docs/interfaces/DoraNeo3ConsensusNode.html +0 -75
- package/docs/interfaces/DoraNeo3Contract.html +0 -110
- package/docs/interfaces/DoraNeo3Event.html +0 -75
- package/docs/interfaces/DoraNeo3Features.html +0 -84
- package/docs/interfaces/DoraNeo3HistoryState.html +0 -75
- package/docs/interfaces/DoraNeo3Invocation.html +0 -75
- package/docs/interfaces/DoraNeo3Item.html +0 -131
- package/docs/interfaces/DoraNeo3Manifest.html +0 -117
- package/docs/interfaces/DoraNeo3Metadata.html +0 -138
- package/docs/interfaces/DoraNeo3Method.html +0 -102
- package/docs/interfaces/DoraNeo3Nef.html +0 -103
- package/docs/interfaces/DoraNeo3Notification.html +0 -82
- package/docs/interfaces/DoraNeo3Parameter.html +0 -75
- package/docs/interfaces/DoraNeo3Permission.html +0 -75
- package/docs/interfaces/DoraNeo3Signer.html +0 -75
- package/docs/interfaces/DoraNeo3Token.html +0 -96
- package/docs/interfaces/DoraNeo3Transaction.html +0 -166
- package/docs/interfaces/DoraNeo3TransactionHistory.html +0 -75
- package/docs/interfaces/DoraNeo3Transfer.html +0 -117
- package/docs/interfaces/DoraNeo3Witness.html +0 -75
- package/docs/modules.html +0 -122
- package/docs/variables/DORA_ASSET.html +0 -81
- package/docs/variables/DORA_BALANCE.html +0 -81
- package/docs/variables/DORA_CONTRACT.html +0 -81
- package/docs/variables/DORA_NODES.html +0 -81
- package/docs/variables/DORA_TRANSACTION.html +0 -81
- package/docs/variables/DORA_TRANSACTIONS.html +0 -81
- package/docs/variables/explorerOptions.html +0 -86
- package/docs/variables/gasInfoNeo3.html +0 -90
- package/docs/variables/neoInfoNeo3.html +0 -90
package/src/BSNeo3.ts
CHANGED
|
@@ -1,228 +1,228 @@
|
|
|
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
|
-
} catch {
|
|
121
|
-
const key = await wallet.decrypt(encryptedKey, password)
|
|
122
|
-
return this.generateAccountFromKey(key)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (!BsReactNativeDecrypt) {
|
|
126
|
-
throw new Error('@CityOfZion/bs-react-native-decrypt is not installed')
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const privateKey = await BsReactNativeDecrypt.decryptNeo3(encryptedKey, password)
|
|
130
|
-
return this.generateAccountFromKey(privateKey)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
async calculateTransferFee(param: TransferParam): Promise<string> {
|
|
134
|
-
const account = new wallet.Account(param.senderAccount.key)
|
|
135
|
-
const invoker = await NeonInvoker.init({
|
|
136
|
-
rpcAddress: this.network.url,
|
|
137
|
-
account,
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
const invocations = this.buildTransferInvocation(param, account)
|
|
141
|
-
|
|
142
|
-
const { networkFee, systemFee } = await invoker.calculateFee({
|
|
143
|
-
invocations,
|
|
144
|
-
signers: [],
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
return networkFee.add(systemFee).toDecimal(this.feeToken.decimals)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async transfer(param: TransferParam): Promise<string> {
|
|
151
|
-
const account = new wallet.Account(param.senderAccount.key)
|
|
152
|
-
const invoker = await NeonInvoker.init({
|
|
153
|
-
rpcAddress: this.network.url,
|
|
154
|
-
account,
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
const invocations = this.buildTransferInvocation(param, account)
|
|
158
|
-
|
|
159
|
-
const transactionHash = await invoker.invokeFunction({
|
|
160
|
-
invocations,
|
|
161
|
-
signers: [],
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
return transactionHash
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async claim(account: Account): Promise<string> {
|
|
168
|
-
const neoAccount = new wallet.Account(account.key)
|
|
169
|
-
const facade = await api.NetworkFacade.fromConfig({ node: this.network.url })
|
|
170
|
-
|
|
171
|
-
const transactionHash = await facade.claimGas(neoAccount, {
|
|
172
|
-
signingCallback: api.signWithAccount(neoAccount),
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
return transactionHash
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
async resolveNameServiceDomain(domainName: string): Promise<any> {
|
|
179
|
-
const parser = NeonParser
|
|
180
|
-
const invoker = await NeonInvoker.init({ rpcAddress: this.network.url })
|
|
181
|
-
const response = await invoker.testInvoke({
|
|
182
|
-
invocations: [
|
|
183
|
-
{
|
|
184
|
-
scriptHash: NEO_NS_HASH,
|
|
185
|
-
operation: 'ownerOf',
|
|
186
|
-
args: [{ type: 'String', value: domainName }],
|
|
187
|
-
},
|
|
188
|
-
],
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
if (response.stack.length === 0) {
|
|
192
|
-
throw new Error(response.exception ?? 'unrecognized response')
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const parsed = parser.parseRpcResponse(response.stack[0] as any, {
|
|
196
|
-
type: ABI_TYPES.HASH160.name,
|
|
197
|
-
})
|
|
198
|
-
const address = parser.accountInputToAddress(parsed.replace('0x', ''))
|
|
199
|
-
return address
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
private buildTransferInvocation(
|
|
203
|
-
{ intent, tipIntent }: TransferParam,
|
|
204
|
-
account: Neon.wallet.Account
|
|
205
|
-
): ContractInvocation[] {
|
|
206
|
-
const intents = [intent, ...(tipIntent ? [tipIntent] : [])]
|
|
207
|
-
|
|
208
|
-
const invocations: ContractInvocation[] = intents.map(intent => {
|
|
209
|
-
return {
|
|
210
|
-
operation: 'transfer',
|
|
211
|
-
scriptHash: intent.tokenHash,
|
|
212
|
-
args: [
|
|
213
|
-
{ type: 'Hash160', value: account.address },
|
|
214
|
-
{ type: 'Hash160', value: intent.receiverAddress },
|
|
215
|
-
{
|
|
216
|
-
type: 'Integer',
|
|
217
|
-
value: intent.tokenDecimals
|
|
218
|
-
? u.BigInteger.fromDecimal(intent.amount, intent.tokenDecimals).toString()
|
|
219
|
-
: intent.amount,
|
|
220
|
-
},
|
|
221
|
-
{ type: 'Any', value: '' },
|
|
222
|
-
],
|
|
223
|
-
}
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
return invocations
|
|
227
|
-
}
|
|
228
|
-
}
|
|
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
|
+
} catch {
|
|
121
|
+
const key = await wallet.decrypt(encryptedKey, password)
|
|
122
|
+
return this.generateAccountFromKey(key)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (!BsReactNativeDecrypt) {
|
|
126
|
+
throw new Error('@CityOfZion/bs-react-native-decrypt is not installed')
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const privateKey = await BsReactNativeDecrypt.decryptNeo3(encryptedKey, password)
|
|
130
|
+
return this.generateAccountFromKey(privateKey)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async calculateTransferFee(param: TransferParam): Promise<string> {
|
|
134
|
+
const account = new wallet.Account(param.senderAccount.key)
|
|
135
|
+
const invoker = await NeonInvoker.init({
|
|
136
|
+
rpcAddress: this.network.url,
|
|
137
|
+
account,
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
const invocations = this.buildTransferInvocation(param, account)
|
|
141
|
+
|
|
142
|
+
const { networkFee, systemFee } = await invoker.calculateFee({
|
|
143
|
+
invocations,
|
|
144
|
+
signers: [],
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
return networkFee.add(systemFee).toDecimal(this.feeToken.decimals)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async transfer(param: TransferParam): Promise<string> {
|
|
151
|
+
const account = new wallet.Account(param.senderAccount.key)
|
|
152
|
+
const invoker = await NeonInvoker.init({
|
|
153
|
+
rpcAddress: this.network.url,
|
|
154
|
+
account,
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
const invocations = this.buildTransferInvocation(param, account)
|
|
158
|
+
|
|
159
|
+
const transactionHash = await invoker.invokeFunction({
|
|
160
|
+
invocations,
|
|
161
|
+
signers: [],
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
return transactionHash
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async claim(account: Account): Promise<string> {
|
|
168
|
+
const neoAccount = new wallet.Account(account.key)
|
|
169
|
+
const facade = await api.NetworkFacade.fromConfig({ node: this.network.url })
|
|
170
|
+
|
|
171
|
+
const transactionHash = await facade.claimGas(neoAccount, {
|
|
172
|
+
signingCallback: api.signWithAccount(neoAccount),
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
return transactionHash
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async resolveNameServiceDomain(domainName: string): Promise<any> {
|
|
179
|
+
const parser = NeonParser
|
|
180
|
+
const invoker = await NeonInvoker.init({ rpcAddress: this.network.url })
|
|
181
|
+
const response = await invoker.testInvoke({
|
|
182
|
+
invocations: [
|
|
183
|
+
{
|
|
184
|
+
scriptHash: NEO_NS_HASH,
|
|
185
|
+
operation: 'ownerOf',
|
|
186
|
+
args: [{ type: 'String', value: domainName }],
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
if (response.stack.length === 0) {
|
|
192
|
+
throw new Error(response.exception ?? 'unrecognized response')
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const parsed = parser.parseRpcResponse(response.stack[0] as any, {
|
|
196
|
+
type: ABI_TYPES.HASH160.name,
|
|
197
|
+
})
|
|
198
|
+
const address = parser.accountInputToAddress(parsed.replace('0x', ''))
|
|
199
|
+
return address
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private buildTransferInvocation(
|
|
203
|
+
{ intent, tipIntent }: TransferParam,
|
|
204
|
+
account: Neon.wallet.Account
|
|
205
|
+
): ContractInvocation[] {
|
|
206
|
+
const intents = [intent, ...(tipIntent ? [tipIntent] : [])]
|
|
207
|
+
|
|
208
|
+
const invocations: ContractInvocation[] = intents.map(intent => {
|
|
209
|
+
return {
|
|
210
|
+
operation: 'transfer',
|
|
211
|
+
scriptHash: intent.tokenHash,
|
|
212
|
+
args: [
|
|
213
|
+
{ type: 'Hash160', value: account.address },
|
|
214
|
+
{ type: 'Hash160', value: intent.receiverAddress },
|
|
215
|
+
{
|
|
216
|
+
type: 'Integer',
|
|
217
|
+
value: intent.tokenDecimals
|
|
218
|
+
? u.BigInteger.fromDecimal(intent.amount, intent.tokenDecimals).toString()
|
|
219
|
+
: intent.amount,
|
|
220
|
+
},
|
|
221
|
+
{ type: 'Any', value: '' },
|
|
222
|
+
],
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
return invocations
|
|
227
|
+
}
|
|
228
|
+
}
|