public KeyManager(BitcoinEncryptedSecretNoEC encryptedSecret, byte[] chainCode, HDFingerprint?masterFingerprint, ExtPubKey extPubKey, bool?passwordVerified, int?minGapLimit, BlockchainState blockchainState, string filePath = null, KeyPath accountKeyPath = null) { HdPubKeys = new List <HdPubKey>(); HdPubKeyScriptBytes = new List <byte[]>(); ScriptHdPubKeyMap = new Dictionary <Script, HdPubKey>(); HdPubKeysLock = new object(); HdPubKeyScriptBytesLock = new object(); ScriptHdPubKeyMapLock = new object(); BlockchainStateLock = new object(); EncryptedSecret = encryptedSecret; ChainCode = chainCode; MasterFingerprint = masterFingerprint; ExtPubKey = Guard.NotNull(nameof(extPubKey), extPubKey); PasswordVerified = passwordVerified; SetMinGapLimit(minGapLimit); BlockchainState = blockchainState ?? new BlockchainState(); HardwareWalletInfo = null; AccountKeyPath = accountKeyPath ?? DefaultAccountKeyPath; SetFilePath(filePath); ToFileLock = new object(); ToFile(); }
public KeyManager(BitcoinEncryptedSecretNoEC encryptedSecret, byte[] chainCode, string password, int minGapLimit = AbsoluteMinGapLimit, string filePath = null, KeyPath accountKeyPath = null) { HdPubKeys = new List <HdPubKey>(); HdPubKeyScriptBytes = new List <byte[]>(); ScriptHdPubKeyMap = new Dictionary <Script, HdPubKey>(); HdPubKeysLock = new object(); HdPubKeyScriptBytesLock = new object(); ScriptHdPubKeyMapLock = new object(); BlockchainState = new BlockchainState(); BlockchainStateLock = new object(); HardwareWalletInfo = null; if (password is null) { password = ""; } SetMinGapLimit(minGapLimit); EncryptedSecret = Guard.NotNull(nameof(encryptedSecret), encryptedSecret); ChainCode = Guard.NotNull(nameof(chainCode), chainCode); var extKey = new ExtKey(encryptedSecret.GetKey(password), chainCode); MasterFingerprint = extKey.Neuter().PubKey.GetHDFingerPrint(); AccountKeyPath = accountKeyPath ?? DefaultAccountKeyPath; ExtPubKey = extKey.Derive(AccountKeyPath).Neuter(); SetFilePath(filePath); ToFileLock = new object(); ToFile(); }
public static async Task <PSBT> SignTxAsync(HardwareWalletInfo hardwareWalletInfo, PSBT psbt) { var psbtString = psbt.ToBase64(); var networkString = Network == Network.Main ? "" : "--testnet"; try { JToken jtok = null; using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMinutes(3))) { jtok = await SendCommandAsync($"{networkString} --device-type \"{hardwareWalletInfo.Type.ToString().ToLowerInvariant()}\" --device-path \"{hardwareWalletInfo.Path}\" signtx {psbtString}", cts.Token, isMutexPriority : true); } JObject json = jtok as JObject; var signedPsbtString = json.Value <string>("psbt"); var signedPsbt = PSBT.Parse(signedPsbtString, Network); if (!signedPsbt.IsAllFinalized()) { signedPsbt.Finalize(); } return(signedPsbt); } catch (IOException ex) when(hardwareWalletInfo.Type == HardwareWalletType.Ledger && (ex.Message.Contains("sign_tx cancelled", StringComparison.OrdinalIgnoreCase) || ex.Message.Contains("open failed", StringComparison.OrdinalIgnoreCase))) { throw new IOException("Log into your Bitcoin account on your Ledger. If you're already logged in, log out and log in again."); } catch (IOException ex) when(hardwareWalletInfo.Type == HardwareWalletType.Ledger && ex.Message.Contains("Bad argument", StringComparison.OrdinalIgnoreCase)) { throw new IOException("Ledger refused to sign the transaction."); } }
public static async Task <IEnumerable <HardwareWalletInfo> > EnumerateAsync() { JToken jtok = null; using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(60))) { jtok = await SendCommandAsync("enumerate", cts.Token); } JArray jarr = jtok as JArray; var hwis = new List <HardwareWalletInfo>(); foreach (JObject json in jarr) { var fingerprint = json.Value <string>("fingerprint"); var serialNumber = json.Value <string>("serial_number"); var typeString = json.Value <string>("type"); var path = json.Value <string>("path"); var error = json.Value <string>("error"); var type = (HardwareWalletType)Enum.Parse(typeof(HardwareWalletType), typeString, ignoreCase: true); var hwi = new HardwareWalletInfo(fingerprint, serialNumber, type, path, error); hwis.Add(hwi); } return(hwis); }
public LoadWalletEntry(HardwareWalletInfo hwi) { if (string.IsNullOrWhiteSpace(hwi.Error)) { WalletName = hwi.Type.ToString(); } else if (!hwi.Initialized) { WalletName = hwi.Type.ToString() + $" - Not Initialized"; } else if (!hwi.Ready) { WalletName = hwi.Type.ToString() + $" - Device Not Ready"; } else if (hwi.NeedPin) { WalletName = hwi.Type.ToString(); } else { WalletName = hwi.Type.ToString() + $" - Error: {hwi.Error}"; } HardwareWalletInfo = hwi; }
public KeyManager(BitcoinEncryptedSecretNoEC encryptedSecret, byte[] chainCode, string password, string filePath = null) { HdPubKeys = new List <HdPubKey>(); HdPubKeyScriptBytes = new List <byte[]>(); ScriptHdPubkeyMap = new Dictionary <Script, HdPubKey>(); HdPubKeysLock = new object(); HdPubKeyScriptBytesLock = new object(); ScriptHdPubkeyMapLock = new object(); BlockchainState = new BlockchainState(); BlockchainStateLock = new object(); HardwareWalletInfo = null; if (password is null) { password = ""; } EncryptedSecret = Guard.NotNull(nameof(encryptedSecret), encryptedSecret); IsWatchOnly = false; ChainCode = Guard.NotNull(nameof(chainCode), chainCode); var extKey = new ExtKey(encryptedSecret.GetKey(password), chainCode); ExtPubKey = extKey.Derive(AccountKeyPath).Neuter(); SetFilePath(filePath); ToFileLock = new object(); ToFile(); }
public static async Task <bool> SetupAsync(HardwareWalletInfo hardwareWalletInfo) { var networkString = Network == Network.Main ? "" : "--testnet"; JToken jtok = await SendCommandAsync($"{networkString} --device-type \"{hardwareWalletInfo.Type.ToString().ToLowerInvariant()}\" --device-path \"{hardwareWalletInfo.Path}\" --interactive setup"); JObject json = jtok as JObject; var success = json.Value <bool>("success"); return(success); }
/// <summary> /// Acquire bech32 xpub on path: m/84h/0h/0h /// https://github.com/bitcoin-core/HWI/blob/master/docs/examples.md /// </summary> public static async Task <ExtPubKey> GetXpubAsync(HardwareWalletInfo hardwareWalletInfo) { var networkString = Network == Network.Main ? "" : "--testnet "; JToken jtok = await SendCommandAsync($"{networkString}--device-type \"{hardwareWalletInfo.Type.ToString().ToLowerInvariant()}\" --device-path \"{hardwareWalletInfo.Path}\" getxpub m/84h/0h/0h"); JObject json = jtok as JObject; string xpub = json.Value <string>("xpub"); ExtPubKey extpub = NBitcoinHelpers.BetterParseExtPubKey(xpub); return(extpub); }
public static string GetNextHardwareWalletName(HardwareWalletInfo hwi) { for (int i = 0; i < int.MaxValue; i++) { var name = $"{hwi.Type}{i}"; if (!File.Exists(Path.Combine(Global.WalletsDir, $"{name}.json"))) { return(name); } } throw new NotSupportedException("This is impossible."); }
public static async Task <bool> SetupAsync(HardwareWalletInfo hardwareWalletInfo) { var networkString = Network == Network.Main ? "" : "--testnet"; JToken jtok = null; using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMinutes(3))) { jtok = await SendCommandAsync($"{networkString} --device-type \"{hardwareWalletInfo.Type.ToString().ToLowerInvariant()}\" --device-path \"{hardwareWalletInfo.Path}\" --interactive setup", cts.Token); } JObject json = jtok as JObject; var success = json.Value <bool>("success"); return(success); }
public static async Task <PSBT> SignTxAsync(HardwareWalletInfo hardwareWalletInfo, PSBT psbt) { var psbtString = psbt.ToBase64(); var networkString = Network == Network.Main ? "" : "--testnet"; JToken jtok = await SendCommandAsync($"{networkString} --device-type \"{hardwareWalletInfo.Type.ToString().ToLowerInvariant()}\" --device-path \"{hardwareWalletInfo.Path}\" signtx {psbtString}"); JObject json = jtok as JObject; var signedPsbtString = json.Value <string>("psbt"); var signedPsbt = PSBT.Parse(signedPsbtString, Network); signedPsbt.Finalize(); return(signedPsbt); }
/// <summary> /// Acquire bech32 xpub on path: m/84h/0h/0h /// https://github.com/bitcoin-core/HWI/blob/master/docs/examples.md /// </summary> public static async Task <ExtPubKey> GetXpubAsync(HardwareWalletInfo hardwareWalletInfo) { var networkString = Network == Network.Main ? "" : "--testnet "; JToken jtok = null; using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(60))) { jtok = await SendCommandAsync($"{networkString}--device-type \"{hardwareWalletInfo.Type.ToString().ToLowerInvariant()}\" --device-path \"{hardwareWalletInfo.Path}\" getxpub m/84h/0h/0h", cts.Token); } JObject json = jtok as JObject; string xpub = json.Value <string>("xpub"); ExtPubKey extpub = NBitcoinHelpers.BetterParseExtPubKey(xpub); return(extpub); }
public KeyManager(BitcoinEncryptedSecretNoEC encryptedSecret, byte[] chainCode, ExtPubKey extPubKey, bool?passwordVerified, BlockchainState blockchainState, string filePath = null) { HdPubKeys = new List <HdPubKey>(); HdPubKeyScriptBytes = new List <byte[]>(); ScriptHdPubkeyMap = new Dictionary <Script, HdPubKey>(); HdPubKeysLock = new object(); HdPubKeyScriptBytesLock = new object(); ScriptHdPubkeyMapLock = new object(); BlockchainStateLock = new object(); EncryptedSecret = encryptedSecret; IsWatchOnly = EncryptedSecret is null; ChainCode = chainCode; ExtPubKey = Guard.NotNull(nameof(extPubKey), extPubKey); PasswordVerified = passwordVerified; BlockchainState = blockchainState ?? new BlockchainState(); HardwareWalletInfo = null; SetFilePath(filePath); ToFileLock = new object(); ToFile(); }
public LoadWalletEntry(string walletName) { WalletName = walletName; HardwareWalletInfo = null; }
public LoadWalletEntry(HardwareWalletInfo hwi) { WalletName = hwi.Type.ToString(); HardwareWalletInfo = hwi; }