Implement SendPinAsync
MODIFY
WalletWasabi.Tests/HwiTests/DeviceConnectedTests/Katas.cs
WalletWasabi.Tests/HwiTests/DeviceConnectedTests/Katas.cs
@@ -56,7 +56,8 @@ namespace WalletWasabi.Tests.HwiTests.DeviceConnectedTests
// Trezor T doesn't support it.
await Assert.ThrowsAsync<HwiException>(async () => await client.PromptPinAsync(deviceType, devicePath, cts.Token));
- // ToDo: sendpin (Assert not working)
+ await Assert.ThrowsAsync<HwiException>(async () => await client.SendPinAsync(deviceType, devicePath, 1111, cts.Token));
+
// ToDo: getxpub
// ToDo: displayaddress
// ToDo: signmessage

MODIFY
WalletWasabi.Tests/HwiTests/NoDeviceConnectedTests/IMockHwiProcessBridge.cs
WalletWasabi.Tests/HwiTests/NoDeviceConnectedTests/IMockHwiProcessBridge.cs
@@ -91,6 +91,15 @@ namespace WalletWasabi.Tests.HwiTests.NoDeviceConnectedTests
return Task.FromResult((response, code));
}
}
+ else if (arguments.StartsWith("--device-path \"webusb: 001:4\" --device-type \"trezor\" sendpin", StringComparison.OrdinalIgnoreCase) || arguments.StartsWith("--testnet --device-path \"webusb: 001:4\" --device-type \"trezor\" sendpin", StringComparison.OrdinalIgnoreCase))
+ {
+ if (Model == HardwareWalletModels.TrezorT)
+ {
+ var response = "{\"error\": \"The PIN has already been sent to this device\", \"code\": -11}";
+ var code = 0;
+ return Task.FromResult((response, code));
+ }
+ }
throw new NotImplementedException($"Mocking is not implemented for '{arguments}'");
}

MODIFY
WalletWasabi.Tests/HwiTests/NoDeviceConnectedTests/MockedDeviceTests.cs
WalletWasabi.Tests/HwiTests/NoDeviceConnectedTests/MockedDeviceTests.cs
@@ -50,10 +50,12 @@ namespace WalletWasabi.Tests.HwiTests.NoDeviceConnectedTests
await client.RestoreAsync(deviceType, devicePath, cts.Token);
// Trezor T doesn't support it.
- await Assert.ThrowsAsync<HwiException>(async () => await client.BackupAsync(deviceType, devicePath, cts.Token));
+ var backup = await Assert.ThrowsAsync<HwiException>(async () => await client.BackupAsync(deviceType, devicePath, cts.Token));
// Trezor T doesn't support it.
- await Assert.ThrowsAsync<HwiException>(async () => await client.PromptPinAsync(deviceType, devicePath, cts.Token));
+ var promptpin = await Assert.ThrowsAsync<HwiException>(async () => await client.PromptPinAsync(deviceType, devicePath, cts.Token));
+
+ var sendpin = await Assert.ThrowsAsync<HwiException>(async () => await client.SendPinAsync(deviceType, devicePath, 1111, cts.Token));
}
}

MODIFY
WalletWasabi/Hwi2/HwiClient.cs
WalletWasabi/Hwi2/HwiClient.cs
@@ -40,9 +40,9 @@ namespace WalletWasabi.Hwi2
#region Commands
- private async Task<string> SendCommandAsync(IEnumerable<HwiOption> options, HwiCommands? command, CancellationToken cancel)
+ private async Task<string> SendCommandAsync(IEnumerable<HwiOption> options, HwiCommands? command, string commandArguments, CancellationToken cancel)
{
- string arguments = HwiParser.ToArgumentString(Network, options, command);
+ string arguments = HwiParser.ToArgumentString(Network, options, command, commandArguments);
try
{
@@ -76,6 +76,16 @@ namespace WalletWasabi.Hwi2
await SendCommandAsync(
options: new[] { HwiOption.DevicePath(devicePath), HwiOption.DeviceType(deviceType) },
command: HwiCommands.PromptPin,
+ commandArguments: null,
+ cancel).ConfigureAwait(false);
+ }
+
+ public async Task SendPinAsync(HardwareWalletVendors deviceType, string devicePath, int pin, CancellationToken cancel)
+ {
+ await SendCommandAsync(
+ options: new[] { HwiOption.DevicePath(devicePath), HwiOption.DeviceType(deviceType) },
+ command: HwiCommands.SendPin,
+ commandArguments: pin.ToString(),
cancel).ConfigureAwait(false);
}
@@ -84,6 +94,7 @@ namespace WalletWasabi.Hwi2
await SendCommandAsync(
options: new[] { HwiOption.DevicePath(devicePath), HwiOption.DeviceType(deviceType) },
command: HwiCommands.Wipe,
+ commandArguments: null,
cancel).ConfigureAwait(false);
}
@@ -92,6 +103,7 @@ namespace WalletWasabi.Hwi2
await SendCommandAsync(
options: new[] { HwiOption.DevicePath(devicePath), HwiOption.DeviceType(deviceType), HwiOption.Interactive },
command: HwiCommands.Setup,
+ commandArguments: null,
cancel).ConfigureAwait(false);
}
@@ -100,6 +112,7 @@ namespace WalletWasabi.Hwi2
await SendCommandAsync(
options: new[] { HwiOption.DevicePath(devicePath), HwiOption.DeviceType(deviceType), HwiOption.Interactive },
command: HwiCommands.Restore,
+ commandArguments: null,
cancel).ConfigureAwait(false);
}
@@ -114,12 +127,13 @@ namespace WalletWasabi.Hwi2
await SendCommandAsync(
options: new[] { HwiOption.DevicePath(devicePath), HwiOption.DeviceType(deviceType), HwiOption.Interactive },
command: HwiCommands.Backup,
+ commandArguments: null,
cancel).ConfigureAwait(false);
}
public async Task<Version> GetVersionAsync(CancellationToken cancel)
{
- string responseString = await SendCommandAsync(options: new[] { HwiOption.Version }, command: null, cancel).ConfigureAwait(false);
+ string responseString = await SendCommandAsync(options: new[] { HwiOption.Version }, command: null, commandArguments: null, cancel).ConfigureAwait(false);
var version = HwiParser.ParseVersion(responseString);
return version;
@@ -127,14 +141,14 @@ namespace WalletWasabi.Hwi2
public async Task<string> GetHelpAsync(CancellationToken cancel)
{
- string responseString = await SendCommandAsync(options: new[] { HwiOption.Help }, command: null, cancel).ConfigureAwait(false);
+ string responseString = await SendCommandAsync(options: new[] { HwiOption.Help }, command: null, commandArguments: null, cancel).ConfigureAwait(false);
return responseString;
}
public async Task<IEnumerable<HwiEnumerateEntry>> EnumerateAsync(CancellationToken cancel)
{
- string responseString = await SendCommandAsync(options: null, command: HwiCommands.Enumerate, cancel).ConfigureAwait(false);
+ string responseString = await SendCommandAsync(options: null, command: HwiCommands.Enumerate, commandArguments: null, cancel).ConfigureAwait(false);
IEnumerable<HwiEnumerateEntry> response = HwiParser.ParseHwiEnumerateResponse(responseString);
return response;
@@ -142,13 +156,13 @@ namespace WalletWasabi.Hwi2
public async Task<string> SetupAsync(CancellationToken cancel)
{
- string responseString = await SendCommandAsync(options: null, command: HwiCommands.Setup, cancel).ConfigureAwait(false);
+ string responseString = await SendCommandAsync(options: null, command: HwiCommands.Setup, commandArguments: null, cancel).ConfigureAwait(false);
return responseString;
}
public async Task<string> DisplayAddressAsync(CancellationToken cancel)
{
- string responseString = await SendCommandAsync(options: null, command: HwiCommands.DisplayAddress, cancel).ConfigureAwait(false);
+ string responseString = await SendCommandAsync(options: null, command: HwiCommands.DisplayAddress, commandArguments: null, cancel).ConfigureAwait(false);
return responseString;
}

MODIFY
WalletWasabi/Hwi2/Parsers/HwiParser.cs
WalletWasabi/Hwi2/Parsers/HwiParser.cs
@@ -250,7 +250,7 @@ namespace WalletWasabi.Hwi2.Parsers
throw new FormatException($"Cannot parse version from HWI's response. Response: {hwiResponse}.");
}
- public static string ToArgumentString(Network network, IEnumerable<HwiOption> options, HwiCommands? command)
+ public static string ToArgumentString(Network network, IEnumerable<HwiOption> options, HwiCommands? command, string commandArguments)
{
options = options ?? Enumerable.Empty<HwiOption>();
var fullOptions = new List<HwiOption>(options);
@@ -295,6 +295,13 @@ namespace WalletWasabi.Hwi2.Parsers
argumentBuilder.Append(command.ToString().ToLowerInvariant());
}
+ commandArguments = Guard.Correct(commandArguments);
+ if (commandArguments != "")
+ {
+ argumentBuilder.Append(' ');
+ argumentBuilder.Append(commandArguments);
+ }
+
var arguments = argumentBuilder.ToString().Trim();
return arguments;
}

Implement SendPinAsync