Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
message,
messageData,
}: Object = {}): Promise => {
/*
* Validate input values: derivationPath and message
*/
derivationPathValidator(derivationPath);
const toSign = messageOrDataValidator({ message, messageData });
try {
const ledger: LedgerInstanceType = await ledgerConnection();
/*
* Sign the message object via your Ledger Wallet
*
* We also warn the user here, since the device will need confirmation, but only in dev mode.
*/
warning(messages.userSignMessageInteractionWarning);
const {
r: rSignatureComponent,
s: sSignatureComponent,
v: recoveryParameter,
/*
* Flow bugs out here claiming the `r` property is not available on the return object.
*/
/* $FlowFixMe */
} = await ledger.signPersonalMessage(
derivationPathNormalizer(derivationPath),
/*
* The message needs to be sent in as an hex string
*
* Also, Flow don't know about Buffer
*/
/* $FlowFixMe */
* prototype `toString` method
*/
/* $FlowFixMe */
multipleOfTwoHexValueNormalizer(chainId.toString(16)),
),
},
to ? { to: addressNormalizer(to) } : {},
),
getChainDefinition(chainId),
);
/*
* Sign the transaction object via your Ledger Wallet
*
* We also warn the user here, since the device will need confirmation, but only in dev mode.
*/
warning(messages.userSignInteractionWarning);
const {
r: rSignatureComponent,
s: sSignatureComponent,
v: recoveryParameter,
} = await ledger.signTransaction(
derivationPathNormalizer(derivationPath),
unsignedTransaction.serialize().toString(HEX_HASH_TYPE),
);
/*
* Proving that we signed the above transaction.
*
* @NOTE We need to modify the original transaction
* Otherwise EthereumTx will complain because internally it checks for the valid instance
*/
unsignedTransaction.r = hexSequenceNormalizer(rSignatureComponent);
unsignedTransaction.s = hexSequenceNormalizer(sSignatureComponent);
*/
const normalizedPublicKey: string = hexSequenceNormalizer(
recoveredPublicKey,
);
/*
* Also set the internal public key
*/
internalPublicKey = normalizedPublicKey;
return resolve(normalizedPublicKey);
} catch (caughtError) {
/*
* Don't throw an Error if the user just cancels signing the message.
* This is normal UX, not an exception
*/
if (error.message.includes(STD_ERRORS.CANCEL_MSG_SIGN)) {
return warning(staticMethodsMessages.cancelMessageSign);
}
throw new Error(error.message);
}
},
);
/*
* We're usign Ethers's direct secret storage encrypt method to generate
* the keystore JSON string
*
* @TODO Validate the password
*
* The password won't work if it's not a string, so it will be best if
* we write a string validator for it
*/
encrypt(
privateKey,
internalEncryptionPassword.toString(),
)
);
}
warning(messages.noPassword);
return Promise.reject();
})();
}
value,
inputData,
} = transactionObjectValidator(transactionObject);
addressValidator(from);
/*
* Metamask auto-sets the nonce based on the next one available. You can manually
* override it, but it's best to omit it.
*
* So we only validate if there is one, otherwise we just pass undefined
* to the transaction object.
*
* We also notify (in dev mode) the user about not setting the nonce.
*/
if (manualNonce) {
safeIntegerValidator(manualNonce);
warning(messages.dontSetNonce);
}
/*
* We must check for the Metamask injected in-page proxy every time we
* try to access it. This is because something can change it from the time
* of last detection until now.
*/
return methodCaller(
/*
* @TODO Move into own (non-anonymous) method
* This way we could better test it
*/
() =>
new Promise((resolve, reject) =>
signTransactionMethodLink(
Object.assign(
{},
export const verifyMessage = async ({
address,
...signatureMessage
}: Object = {}): Promise => {
/*
* Validate the address locally
*/
addressValidator(address);
/*
* Validate the rest of the pros using the core helper
*/
const { message, signature } = messageVerificationObjectValidator(
signatureMessage,
);
warning(messages.messageSignatureOnlyTrezor);
try {
const { success: isMessageValid } = await payloadListener({
payload: Object.assign({}, PAYLOAD_VERIFYMSG, {
/*
* Trezor service requires the prefix from the address to be stripped
*/
address: addressNormalizer(address, false),
message,
/*
* Trezor service requires the prefix from the signature to be stripped
*/
signature: hexSequenceNormalizer(signature, false),
}),
});
return isMessageValid;
} catch (caughtError) {
/*
* Enable it
*/
[ addressAfterEnable ] = await global.ethereum.enable();
}
/*
* We're on the legacy version of Metamask
*/
if (!global.ethereum && global.web3) {
/*
* Warn the user about legacy mode
*
* @TODO Remove legacy metmask version messages
* After an adequate amount of time has passed
*/
warning(messages.legacyMode);
/*
* Enable it
*
* @NOTE There's an argument to be made here that it's dangerous to use
* the `getInpageProvider()` helper before using `detect()`
*/
const legacyProvider: MetamaskInpageProviderType = getInpageProvider();
legacyProvider.enable();
/*
* Inject the web3 provider (overwrite the current one)
*/
global.web3 = new Web3Instance(legacyProvider);
}
/*
* Everything functions the same since the Web3 instance is now in place
* (Granted, it's now using the 1.x.x version)
): Promise => {
/*
* Validate the trasaction's object input
*/
userInputValidator({
firstArgument: argumentObject,
});
const {
password,
entropy = getRandomValues(new Uint8Array(65536)),
chainId = CHAIN_IDS.HOMESTEAD,
} = argumentObject;
let basicWallet: WalletObjectType;
try {
if (!entropy || (entropy && !(entropy instanceof Uint8Array))) {
warning(messages.noEntrophy);
basicWallet = EthersWallet.createRandom();
} else {
basicWallet = EthersWallet.createRandom({
extraEntropy: entropy,
});
}
/*
* Set the password prop on the instance object.
*
* So that we can make use of them inside the SoftwareWallet
* constructor, as the Ethers Wallet instance object will
* be passed down.
*
* @TODO Better passing of values
*
* This needs to be refactored to pass values to the SoftwareWallet
payload: modifiedPayloadObject,
});
const walletInstance: TrezorWallet = new TrezorWallet({
publicKey,
chainCode,
rootDerivationPath,
addressCount,
chainId,
});
return walletInstance;
} catch (caughtError) {
/*
* Don't throw an error if the user cancelled
*/
if (caughtError.message === STD_ERRORS.CANCEL_ACC_EXPORT) {
return warning(messages.userExportCancel);
}
/*
* But throw otherwise, so we can see what's going on
*/
throw new Error(
/*
* @TODO Move message to general
*
* Right now this message string is added under the "static methods" category.
* Since this is used in multiple places, there's a case to be made about
* making it a "general" category message.
*/
`${messages.userExportGenericError}: ${objectToErrorString(
modifiedPayloadObject,
)} ${caughtError.message}`,
);
/*
* If we don't have a destination address, it means the user wants
* to deploy a contract.
*
* For this the Trezor service requires a `inputData` value set.
*
* Otherwise, a `to` address *must* be set.
*/
if (!to) {
requiredSignProps =
REQUIRED_TREZOR_PROPS.SIGN_TRANSACTION_CONTRACT;
/*
* Warn the user (in dev mode, at least) about Trezor's contract
* deployment requirements
*/
warning(messages.signContractDeployment);
}
/*
* Validate the trasaction's object input
*/
userInputValidator({
firstArgument: transactionObject,
requiredAll: requiredSignProps,
});
return signTransaction(
Object.assign({}, transactionObject, {
derivationPath: await this.derivationPath,
chainId,
}),
);
},
},