@@ -149,71 +149,76 @@ public class BIP32Keystore: AbstractKeystore {
149149 } else {
150150 newIndex = UInt32 . zero
151151 }
152+
152153 guard let newNode = parentNode. derive ( index: newIndex, derivePrivateKey: true , hardened: false ) else {
153154 throw AbstractKeystoreError . keyDerivationError
154155 }
155156 guard let newAddress = Utilities . publicToAddress ( newNode. publicKey) else {
156157 throw AbstractKeystoreError . keyDerivationError
157158 }
158- let prefixPath = self . rootPrefix
159- var newPath : String
160- if newNode. isHardened {
161- newPath = prefixPath + " / " + String( newNode. index % HDNode. hardenedIndexPrefix) + " ' "
162- } else {
163- newPath = prefixPath + " / " + String( newNode. index)
164- }
159+ let newPath = rootPrefix + " / " + String( newNode. index)
165160 addressStorage. add ( address: newAddress, for: newPath)
166161 }
167162
168163 public func createNewCustomChildAccount( password: String , path: String ) throws {
169- guard let decryptedRootNode = try getPrefixNodeData ( password) else {
164+ guard let decryptedRootNode = try getPrefixNodeData ( password) ,
165+ let keystoreParams else {
170166 throw AbstractKeystoreError . encryptionError ( " Failed to decrypt a keystore " )
171167 }
172168 guard let rootNode = HDNode ( decryptedRootNode) else {
173169 throw AbstractKeystoreError . encryptionError ( " Failed to deserialize a root node " )
174170 }
175- let prefixPath = self . rootPrefix
176- var pathAppendix : String ?
171+
172+ let prefixPath = rootPrefix
173+ var pathAppendix = path
174+
177175 if path. hasPrefix ( prefixPath) {
178- let upperIndex = ( path. range ( of: prefixPath) ? . upperBound) !
179- if upperIndex < path. endIndex {
180- pathAppendix = String ( path [ path. index ( after: upperIndex) ] )
176+ if let upperIndex = ( path. range ( of: prefixPath) ? . upperBound) , upperIndex < path. endIndex {
177+ pathAppendix = String ( path [ path. index ( after: upperIndex) ..< path. endIndex] )
181178 } else {
182179 throw AbstractKeystoreError . encryptionError ( " out of bounds " )
183180 }
184-
185- guard pathAppendix != nil else {
186- throw AbstractKeystoreError . encryptionError ( " Derivation depth mismatch " )
187- }
188- if pathAppendix!. hasPrefix ( " / " ) {
189- pathAppendix = pathAppendix? . trimmingCharacters ( in: CharacterSet . init ( charactersIn: " / " ) )
190- }
191- } else {
192- if path. hasPrefix ( " / " ) {
193- pathAppendix = path. trimmingCharacters ( in: CharacterSet . init ( charactersIn: " / " ) )
194- }
195181 }
196- guard pathAppendix != nil else {
197- throw AbstractKeystoreError . encryptionError ( " Derivation depth mismatch " )
182+ if pathAppendix. hasPrefix ( " / " ) {
183+ pathAppendix = pathAppendix . trimmingCharacters ( in : . init ( charactersIn : " / " ) )
198184 }
199185 guard rootNode. depth == prefixPath. components ( separatedBy: " / " ) . count - 1 else {
200186 throw AbstractKeystoreError . encryptionError ( " Derivation depth mismatch " )
201187 }
202- guard let newNode = rootNode. derive ( path: pathAppendix! , derivePrivateKey: true ) else {
188+ guard let newNode = rootNode. derive ( path: pathAppendix, derivePrivateKey: true ) else {
203189 throw AbstractKeystoreError . keyDerivationError
204190 }
205191 guard let newAddress = Utilities . publicToAddress ( newNode. publicKey) else {
206192 throw AbstractKeystoreError . keyDerivationError
207193 }
208- var newPath : String
209- if newNode. isHardened {
210- newPath = prefixPath + " / " + pathAppendix!. trimmingCharacters ( in: CharacterSet . init ( charactersIn: " ' " ) ) + " ' "
211- } else {
212- newPath = prefixPath + " / " + pathAppendix!
213- }
194+
195+ let newPath = prefixPath + " / " + pathAppendix
196+
214197 addressStorage. add ( address: newAddress, for: newPath)
215- guard let serializedRootNode = rootNode. serialize ( serializePublic: false ) else { throw AbstractKeystoreError . keyDerivationError}
216- try encryptDataToStorage ( password, data: serializedRootNode, aesMode: self . keystoreParams!. crypto. cipher)
198+ guard let serializedRootNode = rootNode. serialize ( serializePublic: false ) else {
199+ throw AbstractKeystoreError . keyDerivationError
200+ }
201+ try encryptDataToStorage ( password, data: serializedRootNode, aesMode: keystoreParams. crypto. cipher)
202+ }
203+
204+ /// Fast generation addresses for current account
205+ /// used to show which addresses the user can get for indices from `0` to `number-1`
206+ /// - Parameters:
207+ /// - password: password of seed storage
208+ /// - number: number of wallets addresses needed to generate from `0` to `number-1`
209+ /// - Returns: Array of addresses generated from `0` to number bound
210+ public func getAddressForAccount( password: String , number: UInt ) throws -> [ EthereumAddress ] {
211+ guard let decryptedRootNode = try ? getPrefixNodeData ( password) ,
212+ let rootNode = HDNode ( decryptedRootNode) else {
213+ throw AbstractKeystoreError . encryptionError ( " Failed to decrypt a keystore " )
214+ }
215+ return try [ UInt] ( 0 ..< number) . compactMap { number in
216+ guard rootNode. depth == rootPrefix. components ( separatedBy: " / " ) . count - 1 ,
217+ let newNode = rootNode. derive ( path: " \( number) " , derivePrivateKey: true ) else {
218+ throw AbstractKeystoreError . keyDerivationError
219+ }
220+ return Utilities . publicToAddress ( newNode. publicKey)
221+ }
217222 }
218223
219224 fileprivate func encryptDataToStorage( _ password: String , data: Data , dkLen: Int = 32 , N: Int = 4096 , R: Int = 6 , P: Int = 1 , aesMode: String = " aes-128-cbc " ) throws {
0 commit comments