Skip to content
This repository has been archived by the owner on Apr 25, 2024. It is now read-only.

Commit

Permalink
feat(wallet): allow signing method to be 'unknown', and client empty
Browse files Browse the repository at this point in the history
If a wallet config is uploaded that does not have a signing method included, caravan will set the
method to 'unknown' and during signing, the method selector dialog will be shown, but the BIP32 path
from the config will be used.

If a client isn't in a config, the ClientPicker will be shown.

BREAKING CHANGE:
none

Co-authored-by: Destry Saul <[email protected]>
  • Loading branch information
destrys and Destry Saul authored Jun 29, 2020
1 parent 5647499 commit bcada9d
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 32 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,4 @@ point caravan at 'http://localhost:1337/localhost:8332'.

## Contributing

Please see the [`CONTRIBUTING.md`](./CONTRIBUTING.md) and the open [GitHub Issues](https://github.com/caravan/issues).
Please see the [`CONTRIBUTING.md`](./CONTRIBUTING.md) and the open [GitHub Issues](https://github.com/caravan/issues)
5 changes: 3 additions & 2 deletions src/components/ClientPicker/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,16 @@ class ClientPicker extends React.Component {
checked={client.type === "private"}
/>
</RadioGroup>
{client.type === "public" ? (
{client.type === "public" && (
<FormHelperText>
{"'Public' uses the "}
<code>blockstream.info</code>
{" API. Switch to private to use a "}
<code>bitcoind</code>
{" node."}
</FormHelperText>
) : (
)}
{client.type === "private" && (
<PrivateClientSettings
handleUrlChange={(event) => this.handleUrlChange(event)}
handleUsernameChange={(event) =>
Expand Down
4 changes: 3 additions & 1 deletion src/components/ScriptExplorer/SignatureImporter.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
import "react-table/react-table.css";

const TEXT = "text";
const UNKNOWN = "unknown";

class SignatureImporter extends React.Component {
titleRef = React.createRef();
Expand Down Expand Up @@ -106,7 +107,8 @@ class SignatureImporter extends React.Component {
<form>
{(extendedPublicKeyImporter === null ||
typeof extendedPublicKeyImporter === "undefined" ||
extendedPublicKeyImporter.method === TEXT) && (
extendedPublicKeyImporter.method === TEXT ||
extendedPublicKeyImporter.method === UNKNOWN) && (
<FormControl fullWidth>
<InputLabel id={labelId}>Select Method</InputLabel>

Expand Down
30 changes: 27 additions & 3 deletions src/components/Wallet/WalletGenerator.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
} from "../../blockchain";

// Components
import ClientPicker from "../ClientPicker";
import ConfirmWallet from "./ConfirmWallet";
import WalletControl from "./WalletControl";
import WalletConfigInteractionButtons from "./WalletConfigInteractionButtons";
Expand Down Expand Up @@ -53,6 +54,7 @@ class WalletGenerator extends React.Component {
super(props);
this.state = {
connectSuccess: false,
unknownClient: false,
};
}

Expand All @@ -79,7 +81,17 @@ class WalletGenerator extends React.Component {
client,
common: { nodesLoaded },
setIsWallet,
configuring,
} = this.props;
const { unknownClient } = this.state;
if (client.type === "unknown" && prevProps.client.type === "public") {
this.setState({ unknownClient: true }); // eslint-disable-line react/no-did-update-set-state
} else if (configuring && client.type !== "unknown" && unknownClient) {
// re-initializes the state if we're in the configuring stage.
// catches situation where wallet is cleared and new one is added
// eslint-disable-next-line react/no-did-update-set-state
this.setState({ unknownClient: false });
}
// if the password was updated
if (prevPassword !== client.password && client.password.length) {
// test the connection using the set password
Expand Down Expand Up @@ -319,7 +331,7 @@ class WalletGenerator extends React.Component {
client,
generating,
} = this.props;
const { connectSuccess } = this.state;
const { connectSuccess, unknownClient } = this.state;
if (this.extendedPublicKeyCount() === totalSigners) {
if (generating && !configuring) {
return (
Expand All @@ -343,7 +355,16 @@ class WalletGenerator extends React.Component {
onClearFn={(e) => this.toggleImporters(e)}
onDownloadFn={downloadWalletDetails}
/>
{client.type === "private" && (
{unknownClient && (
<Box my={5}>
<Typography variant="subtitle1">
This config does not contain client information. Please choose
a client to connect to before importing your wallet.
</Typography>
<ClientPicker />
</Box>
)}
{client.type === "private" && !unknownClient && (
<Box my={5}>
<Grid container spacing={2} alignItems="center">
<Grid item xs={12}>
Expand Down Expand Up @@ -401,7 +422,10 @@ class WalletGenerator extends React.Component {
variant="contained"
color="primary"
onClick={this.generate}
disabled={client.type === "private" && !connectSuccess}
disabled={
(client.type === "private" && !connectSuccess) ||
client.type === "unknown"
}
>
Confirm
</Button>
Expand Down
82 changes: 57 additions & 25 deletions src/components/Wallet/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ class CreateWallet extends React.Component {
"name",
"addressType",
"network",
"client",
"quorum",
"extendedPublicKeys",
];
Expand All @@ -88,14 +87,18 @@ class CreateWallet extends React.Component {
);
if (validProperties !== "") return validProperties;

const clientProperties =
config.client.type === "public" ? ["type"] : ["type", "url", "username"];
const validClient = CreateWallet.validateProperties(
config,
clientProperties,
"client"
);
if (validClient !== "") return validClient;
if (config.client) {
const clientProperties =
config.client.type === "public"
? ["type"]
: ["type", "url", "username"];
const validClient = CreateWallet.validateProperties(
config,
clientProperties,
"client"
);
if (validClient !== "") return validClient;
}

const quorumProperties = ["requiredSigners", "totalSigners"];
const validQuorum = CreateWallet.validateProperties(
Expand All @@ -112,22 +115,29 @@ class CreateWallet extends React.Component {
}

static validateExtendedPublicKeys(xpubs, network) {
let tmpNetwork = network;
if (network === "regtest") {
tmpNetwork = "testnet";
}
const xpubFields = {
name: (name, index) =>
typeof name === "string"
? ""
: `Extended public key ${index} name must be a string`,
bip32Path: (bip32Path, index) => {
if (xpubs[index - 1].method === "text") return "";
if (typeof xpubs[index - 1].method === "undefined") return "";
const pathError = validateBIP32Path(bip32Path);
if (pathError !== "")
return `Extended public key ${index} error: ${pathError}`;
return "";
},
xpub: (xpub) => validateExtendedPublicKey(xpub, network),
xpub: (xpub) => validateExtendedPublicKey(xpub, tmpNetwork),
method: (method, index) =>
// eslint-disable-next-line no-bitwise
~["trezor", "ledger", "hermit", "xpub", "text"].indexOf(method) // FIXME
~["trezor", "ledger", "hermit", "xpub", "text", undefined].indexOf(
method
)
? ""
: `Invalid method for extended public key ${index}`,
};
Expand Down Expand Up @@ -167,7 +177,7 @@ class CreateWallet extends React.Component {
const config = JSON.parse(configJson);
configError = CreateWallet.validateConfig(config);
} catch (parseError) {
configError = "Invlaid JSON";
configError = "Invalid JSON";
}

if (sessionStorage) sessionStorage.setItem(CARAVAN_CONFIG, configJson);
Expand Down Expand Up @@ -223,18 +233,32 @@ class CreateWallet extends React.Component {
setTotalSigners(walletConfiguration.quorum.totalSigners);
setRequiredSigners(walletConfiguration.quorum.requiredSigners);
setAddressType(walletConfiguration.addressType);
setNetwork(walletConfiguration.network);
if (walletConfiguration.network === "regtest") {
setNetwork("testnet");
} else {
setNetwork(walletConfiguration.network);
}
updateWalletNameAction(0, walletConfiguration.name);
setClientType(walletConfiguration.client.type);
if (walletConfiguration.client.type === "private") {
setClientUrl(walletConfiguration.client.url);
setClientUsername(walletConfiguration.client.username);
// set client to unknown
if (walletConfiguration.client) {
setClientType(walletConfiguration.client.type);
if (walletConfiguration.client.type === "private") {
setClientUrl(walletConfiguration.client.url);
setClientUsername(walletConfiguration.client.username);
}
} else {
setClientType("unknown");
}
walletConfiguration.extendedPublicKeys.forEach(
(extendedPublicKey, index) => {
const number = index + 1;
setExtendedPublicKeyImporterName(number, extendedPublicKey.name);
setExtendedPublicKeyImporterMethod(number, extendedPublicKey.method);
if (extendedPublicKey.method) {
setExtendedPublicKeyImporterMethod(number, extendedPublicKey.method);
} else {
setExtendedPublicKeyImporterMethod(number, "unknown");
}

setExtendedPublicKeyImporterBIP32Path(
number,
extendedPublicKey.bip32Path
Expand All @@ -248,6 +272,7 @@ class CreateWallet extends React.Component {
);
};

// add client picker if client === 'unknown'
renderWalletImporter = () => {
const { configError } = this.state;
const { configuring } = this.props;
Expand Down Expand Up @@ -301,7 +326,6 @@ class CreateWallet extends React.Component {
</Box>
</Grid>
);

return settings;
};

Expand Down Expand Up @@ -399,12 +423,20 @@ ${this.extendedPublicKeyImporterBIP32Paths()}
extendedPublicKeyImporter.method === "text"
? "Unknown (make sure you have written this down previously!)"
: extendedPublicKeyImporter.bip32Path;
return ` {
"name": "${extendedPublicKeyImporter.name}",
"bip32Path": "${bip32Path}",
"xpub": "${extendedPublicKeyImporter.extendedPublicKey}",
"method": "${extendedPublicKeyImporter.method}"
}`;
const importer =
extendedPublicKeyImporter.method === "unknown"
? ` {
"name": "${extendedPublicKeyImporter.name}",
"bip32Path": "${bip32Path}",
"xpub": "${extendedPublicKeyImporter.extendedPublicKey}"
}`
: ` {
"name": "${extendedPublicKeyImporter.name}",
"bip32Path": "${bip32Path}",
"xpub": "${extendedPublicKeyImporter.extendedPublicKey}",
"method": "${extendedPublicKeyImporter.method}"
}`;
return importer;
};

walletDetailsFilename = () => {
Expand Down

0 comments on commit bcada9d

Please sign in to comment.