package org.bitcoinj.wallet;

import com.google.common.collect.ImmutableList;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.crypto.ChildNumber;

public class DerivationPathFactory {

    private NetworkParameters params;
    private final ChildNumber coinType;
    private static final ChildNumber FEATURE_PURPOSE = ChildNumber.NINE_HARDENED;
    private static final ChildNumber FEATURE_PURPOSE_IDENTITIES = ChildNumber.FIVE_HARDENED;
    public static final ChildNumber FEATURE_PURPOSE_DASHPAY = new ChildNumber(15, true);

    public DerivationPathFactory(NetworkParameters params) {
        this.params = params;
        this.coinType = new ChildNumber(params.getCoinType(), true);
    }

    /** blockchain identity registration funding derivation path
     * m/9'/5'/5'/1' (mainnet)
     * m/9'/1'/5'/1' (testnet, devnets)
     */
    public ImmutableList<ChildNumber> blockchainIdentityRegistrationFundingDerivationPath() {
        return ImmutableList.<ChildNumber>builder()
                .add(FEATURE_PURPOSE)
                .add(coinType)
                .add(FEATURE_PURPOSE_IDENTITIES)
                .add(ChildNumber.ONE_HARDENED)
                .build();
    }

    /** blockchain identity topup funding derivation path
     * m/9'/5'/5'/2' (mainnet)
     * m/9'/1'/5'/2' (testnet, devnets)
     */
    public ImmutableList<ChildNumber> blockchainIdentityTopupFundingDerivationPath() {
        return ImmutableList.<ChildNumber>builder()
                .add(FEATURE_PURPOSE)
                .add(coinType)
                .add(FEATURE_PURPOSE_IDENTITIES)
                .add(new ChildNumber(2, true))
                .build();
    }

    /** blockchain identity keys derivation path (EC Keys)
     * m/9'/5'/5'/0'/0'/(blockchain identity index)/ (mainnet)
     * m/9'/1'/5'/0'/0'/(blockchain identity index)/ (testnet, devnets)
     */
    public ImmutableList<ChildNumber> blockchainIdentityECDSADerivationPath() {
        return ImmutableList.<ChildNumber>builder()
                .add(FEATURE_PURPOSE)
                .add(coinType)
                .add(FEATURE_PURPOSE_IDENTITIES)
                .add(ChildNumber.ZERO_HARDENED)
                .add(ChildNumber.ZERO_HARDENED)
                .add(ChildNumber.ZERO) // default to 0 for now
                .build();
    }

    /** blockchain identity keys derivation path (BLS Keys)
     * m/9'/5'/5'/0'/1'/(blockchain identity index)/ (mainnet)
     * m/9'/1'/5'/0'/1'/(blockchain identity index)/ (testnet, devnets)
     */
    public ImmutableList<ChildNumber> blockchainIdentityBLSDerivationPath() {
        return ImmutableList.<ChildNumber>builder()
                .add(FEATURE_PURPOSE)
                .add(coinType)
                .add(FEATURE_PURPOSE_IDENTITIES)
                .add(ChildNumber.ZERO_HARDENED)
                .add(ChildNumber.ONE_HARDENED)
                .add(ChildNumber.ZERO) // default to 0 for now
                .build();
    }

    public ImmutableList<ChildNumber> masternodeHoldingsDerivationPath() {
        return ImmutableList.<ChildNumber>builder()
                .add(FEATURE_PURPOSE)
                .add(coinType)
                .add(new ChildNumber(3, true))
                .add(ChildNumber.ZERO_HARDENED)
                .build();
    }

    /** provider voting keys derivation path
     * m/9'/5'/3'/1' (mainnet)
     * m/9'/1'/3'/1' (testnet, devnets)
     */
    public ImmutableList<ChildNumber> masternodeVotingDerivationPath() {
        return ImmutableList.<ChildNumber>builder()
                .add(FEATURE_PURPOSE)
                .add(coinType)
                .add(new ChildNumber(3, true))
                .add(ChildNumber.ONE_HARDENED)
                .build();
    }

    /** provider owner keys derivation path
     * m/9'/5'/3'/2' (mainnet)
     * m/9'/1'/3'/2' (testnet, devnets)
     */
    public ImmutableList<ChildNumber> masternodeOwnerDerivationPath() {
        return ImmutableList.<ChildNumber>builder()
                .add(FEATURE_PURPOSE)
                .add(coinType)
                .add(new ChildNumber(3, true))
                .add(new ChildNumber(2, true))
                .build();
    }

    /** provider operator keys derivation path
     * m/9'/5'/3'/3' (mainnet)
     * m/9'/1'/3'/3' (testnet, devnets)
     */
    public ImmutableList<ChildNumber> masternodeOperatorDerivationPath() {
        return ImmutableList.<ChildNumber>builder()
                .add(FEATURE_PURPOSE)
                .add(coinType)
                .add(new ChildNumber(3, true))
                .add(new ChildNumber(3, true))
                .build();
    }

    /** Default wallet derivation path
     * m/44'/5'/@account' (mainnet)
     * m/44'/1'/@account' (testnet, devnets)
     */
    public ImmutableList<ChildNumber> bip44DerivationPath(int account) {
        return ImmutableList.<ChildNumber>builder()
                .add(new ChildNumber(44, true))
                .add(coinType)
                .add(new ChildNumber(account, true))
                .build();
    }

    /** Legacy wallet derivation path
     * m/@account' (mainnet, testnet, devnets)
     */
    public ImmutableList<ChildNumber> bip32DerivationPath(int account) {
        return ImmutableList.<ChildNumber>builder()
                .add(new ChildNumber(account, true))
                .build();
    }

    // Do we need this?
    private static DerivationPathFactory instance;
    public static DerivationPathFactory get(NetworkParameters params) {
        if(instance == null) {
            instance = new DerivationPathFactory(params);
        }
        return instance;
    }
}

@@ -2157,32 +2157,48 @@
 r.ZERO_HARDENED)
+ //sub feature 0
 %0A               
@@ -2221,32 +2221,60 @@
 r.ZERO_HARDENED)
+ //key type (0 is ECDSA key)
 %0A               
@@ -2299,33 +2299,141 @@
 ZERO
-) // default to 0 for now
+_HARDENED) //identity index (default to 0 for now)%0A                .add(ChildNumber.ZERO_HARDENED) //key index (default to 0 for now)
 %0A   
@@ -2952,32 +2952,48 @@
 r.ZERO_HARDENED)
+ //sub feature 0
 %0A               
@@ -3015,32 +3015,60 @@
 er.ONE_HARDENED)
+ //key type (0 is ECDSA key)
 %0A               
@@ -3093,33 +3093,142 @@
 ZERO
-) // default to 0 for now
+_HARDENED) // identity index (default to 0 for now)%0A                .add(ChildNumber.ZERO_HARDENED) //key index (default to 0 for now)
 %0A   

Align BlockchainIdentity Path with specs