Skip to content

Commit 8d5411b

Browse files
committed
added BI44 protocol and direct derive without checking blockchain history
1 parent ee26d1e commit 8d5411b

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// BIP44.swift
3+
// Created by Alberto Penas Amor on 15/12/22.
4+
//
5+
6+
import Foundation
7+
8+
public protocol BIP44 {
9+
/**
10+
Derive an `HDNode` based on the provided `path`. The function will throws `BIP44Error.warning` if it was invoked with `warns` as true and the root key doesn't have a previous child with at least one transaction, using false the child node will be derived directly not throwing. This function needs to query the blockchain history when `warns`is true, so it can throw network errors.
11+
12+
- Parameter path: valid BIP32 path.
13+
- Parameter warns: true to be warned about following BIP44 standard, false otherwise.
14+
- Throws: `BIP44Error.warning` if the child key shouldn't be used according to BIP44 standard.
15+
- Returns: an HDNode child key for the provided `path` if it can be created, otherwise nil
16+
*/
17+
func derive(path: String, warns: Bool) async throws -> HDNode?
18+
}
19+
20+
public enum BIP44Error: Equatable {
21+
/// The selected path doesn't fulfill BIP44 standard, you can derive the root key anyway
22+
case warning
23+
}
24+
25+
extension HDNode: BIP44 {
26+
public func derive(path: String, warns: Bool = true) async throws -> HDNode? {
27+
if warns {
28+
// https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#account-discovery
29+
return nil
30+
} else {
31+
return derive(path: path, derivePrivateKey: true)
32+
}
33+
}
34+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// BIP44Tests.swift
3+
// Created by Alberto Penas Amor on 15/12/22.
4+
//
5+
6+
import XCTest
7+
import Web3Core
8+
@testable import web3swift
9+
10+
final class BIP44Tests: XCTestCase {
11+
12+
private let mnemonic = "fruit wave dwarf banana earth journey tattoo true farm silk olive fence"
13+
14+
func testBIP44DeriveWithoutWarningIfChildNodeHasPreviousChildsWithTransactions() async throws {
15+
let seed = try XCTUnwrap(BIP39.seedFromMmemonics(mnemonic, password: ""))
16+
let rootNode = try XCTUnwrap(HDNode(seed: seed))
17+
18+
let optChildNode = try await rootNode.derive(path: "m/44'/60'/1'/0/1", warns: false)
19+
let childNode = try XCTUnwrap(optChildNode)
20+
21+
XCTAssertEqual(childNode.publicKey.toHexString(), "03fe5fad1740a0c749c3c976c9b37f337204bf3df1d73d78da282dd365a7d47ad9")
22+
XCTAssertEqual(Utilities.publicToAddress(childNode.publicKey)?.address, "0x73C13e421eF367c4F55BBC02a8e2a2b12e82f717")
23+
}
24+
}

0 commit comments

Comments
 (0)