add support for satschip nfc card

This commit is contained in:
Craig Raw
2024-02-07 09:19:55 +02:00
parent 4de6bd5e83
commit 74a551ed01
13 changed files with 61 additions and 18 deletions
@@ -62,7 +62,7 @@ public abstract class CardApi {
}
public static CardApi getCardApi(WalletModel walletModel, String pin) throws CardException {
if(walletModel == WalletModel.TAPSIGNER || walletModel == WalletModel.SATSCARD) {
if(walletModel == WalletModel.TAPSIGNER || walletModel == WalletModel.SATSCHIP || walletModel == WalletModel.SATSCARD) {
return new CkCardApi(walletModel, pin);
}
@@ -15,6 +15,7 @@ public class CardStatus extends CardResponse {
String ver;
BigInteger birth;
boolean tapsigner;
boolean satschip;
List<BigInteger> path;
BigInteger num_backups;
List<BigInteger> slots;
@@ -24,7 +25,7 @@ public class CardStatus extends CardResponse {
boolean testnet;
public boolean isInitialized() {
return (getCardType() == WalletModel.TAPSIGNER && path != null) || (getCardType() == WalletModel.SATSCARD && addr != null);
return ((getCardType() == WalletModel.TAPSIGNER || getCardType() == WalletModel.SATSCHIP) && path != null) || (getCardType() == WalletModel.SATSCARD && addr != null);
}
public String getIdentifier() {
@@ -42,11 +43,11 @@ public class CardStatus extends CardResponse {
}
public boolean requiresBackup() {
return num_backups == null || num_backups.intValue() == 0;
return !satschip && (num_backups == null || num_backups.intValue() == 0);
}
public WalletModel getCardType() {
return tapsigner ? WalletModel.TAPSIGNER : WalletModel.SATSCARD;
return satschip ? WalletModel.SATSCHIP : (tapsigner ? WalletModel.TAPSIGNER : WalletModel.SATSCARD);
}
public int getCurrentSlot() {
@@ -72,6 +73,7 @@ public class CardStatus extends CardResponse {
", ver='" + ver + '\'' +
", birth=" + birth +
", tapsigner=" + tapsigner +
", satschip=" + satschip +
", path=" + path +
", num_backups=" + num_backups +
", slots=" + slots +
@@ -32,10 +32,6 @@ public class CkCardApi extends CardApi {
private final CardProtocol cardProtocol;
private String cvc;
public CkCardApi(String cvc) throws CardException {
this(WalletModel.TAPSIGNER, cvc);
}
public CkCardApi(WalletModel cardType, String cvc) throws CardException {
this.cardType = cardType;
this.cardProtocol = new CardProtocol();
@@ -137,6 +133,8 @@ public class CkCardApi extends CardApi {
public Service<Void> getInitializationService(byte[] entropy, StringProperty messageProperty) {
if(cardType == WalletModel.TAPSIGNER) {
return new CardImportPane.CardInitializationService(new Tapsigner(), cvc, entropy, messageProperty);
} else if(cardType == WalletModel.SATSCHIP) {
return new CardImportPane.CardInitializationService(new Satschip(), cvc, entropy, messageProperty);
}
return new CardInitializationService(entropy, messageProperty);
@@ -144,6 +142,10 @@ public class CkCardApi extends CardApi {
@Override
public Service<Keystore> getImportService(List<ChildNumber> derivation, StringProperty messageProperty) {
if(cardType == WalletModel.SATSCHIP) {
return new CardImportPane.CardImportService(new Satschip(), cvc, derivation, messageProperty);
}
return new CardImportPane.CardImportService(new Tapsigner(), cvc, derivation, messageProperty);
}
@@ -155,11 +157,11 @@ public class CkCardApi extends CardApi {
ExtendedKey derivedXpubkey = ExtendedKey.fromDescriptor(Base58.encodeChecked(derivedXpub.xpub));
Keystore keystore = new Keystore();
keystore.setLabel(WalletModel.TAPSIGNER.toDisplayString());
keystore.setLabel(cardType.toDisplayString());
keystore.setKeyDerivation(keyDerivation);
keystore.setSource(KeystoreSource.HW_AIRGAPPED);
keystore.setExtendedPublicKey(derivedXpubkey);
keystore.setWalletModel(WalletModel.TAPSIGNER);
keystore.setWalletModel(cardType);
return keystore;
}
@@ -404,7 +406,7 @@ public class CkCardApi extends CardApi {
@Override
protected PSBT call() throws Exception {
CardStatus cardStatus = getStatus();
if(cardStatus.getCardType() != WalletModel.TAPSIGNER) {
if(cardStatus.getCardType() != WalletModel.TAPSIGNER && cardStatus.getCardType() != WalletModel.SATSCHIP) {
throw new IllegalStateException("Please use a " + WalletModel.TAPSIGNER.toDisplayString() + " to sign transactions.");
}
@@ -465,7 +467,7 @@ public class CkCardApi extends CardApi {
@Override
protected String call() throws Exception {
CardStatus cardStatus = getStatus();
if(cardStatus.getCardType() != WalletModel.TAPSIGNER) {
if(cardStatus.getCardType() != WalletModel.TAPSIGNER && cardStatus.getCardType() != WalletModel.SATSCHIP) {
throw new IllegalStateException("Please use a " + WalletModel.TAPSIGNER.toDisplayString() + " to sign messages.");
}
@@ -0,0 +1,20 @@
package com.sparrowwallet.sparrow.io.ckcard;
import com.sparrowwallet.drongo.wallet.WalletModel;
public class Satschip extends Tapsigner {
@Override
public String getKeystoreImportDescription(int account) {
return "Import the keystore from your Satschip by placing it on the card reader.";
}
@Override
public String getName() {
return "Satschip";
}
@Override
public WalletModel getWalletModel() {
return WalletModel.SATSCHIP;
}
}
@@ -16,7 +16,7 @@ public class Tapsigner implements KeystoreCardImport {
public boolean isInitialized() throws CardException {
CkCardApi cardApi = null;
try {
cardApi = new CkCardApi(null);
cardApi = new CkCardApi(getWalletModel(), null);
return cardApi.isInitialized();
} finally {
if(cardApi != null) {
@@ -37,7 +37,7 @@ public class Tapsigner implements KeystoreCardImport {
CkCardApi cardApi = null;
try {
cardApi = new CkCardApi(pin);
cardApi = new CkCardApi(getWalletModel(), pin);
CardStatus cardStatus = cardApi.getStatus();
if(cardStatus.isInitialized()) {
throw new IllegalStateException("Card is already initialized.");
@@ -63,7 +63,7 @@ public class Tapsigner implements KeystoreCardImport {
CkCardApi cardApi = null;
try {
cardApi = new CkCardApi(pin);
cardApi = new CkCardApi(getWalletModel(), pin);
CardStatus cardStatus = cardApi.getStatus();
if(!cardStatus.isInitialized()) {
throw new IllegalStateException("Card is not initialized.");
@@ -5,6 +5,7 @@ import com.sparrowwallet.sparrow.control.CardImportPane;
import com.sparrowwallet.sparrow.control.FileKeystoreImportPane;
import com.sparrowwallet.sparrow.control.TitledDescriptionPane;
import com.sparrowwallet.sparrow.io.*;
import com.sparrowwallet.sparrow.io.ckcard.Satschip;
import com.sparrowwallet.sparrow.io.ckcard.Tapsigner;
import com.sparrowwallet.sparrow.io.satochip.Satochip;
import javafx.fxml.FXML;
@@ -39,7 +40,7 @@ public class HwAirgappedController extends KeystoreImportDetailController {
}
}
List<KeystoreCardImport> cardImporters = List.of(new Tapsigner(), new Satochip());
List<KeystoreCardImport> cardImporters = List.of(new Tapsigner(), new Satochip(), new Satschip());
for(KeystoreCardImport importer : cardImporters) {
if(!importer.isDeprecated() || Config.get().isShowDeprecatedImportExport()) {
CardImportPane importPane = new CardImportPane(getMasterController().getWallet(), importer, getMasterController().getRequiredDerivation());
@@ -493,7 +493,7 @@ public class KeystoreController extends WalletFormController implements Initiali
log.error("Error communicating with card", e);
AppServices.showErrorDialog("Error communicating with card", e.getMessage());
});
ServiceProgressDialog serviceProgressDialog = new ServiceProgressDialog("Authentication Delay", "Waiting for authentication delay to clear...", "/image/tapsigner.png", authDelayService);
ServiceProgressDialog serviceProgressDialog = new ServiceProgressDialog("Authentication Delay", "Waiting for authentication delay to clear...", "/image/" + cardApi.getCardType().getType() + ".png", authDelayService);
serviceProgressDialog.initOwner(cardServiceButtons.getScene().getWindow());
AppServices.moveToActiveWindowScreen(serviceProgressDialog);
authDelayService.start();