Message signing
This commit is contained in:
parent
b9bd734cd0
commit
b4d8f3617f
|
@ -76,6 +76,15 @@ export class LedgerWallet extends HardwareWallet implements IFullWallet {
|
||||||
// modeled after
|
// modeled after
|
||||||
// https://github.com/kvhnuke/etherwallet/blob/3f7ff809e5d02d7ea47db559adaca1c930025e24/app/scripts/controllers/signMsgCtrl.js#L53
|
// https://github.com/kvhnuke/etherwallet/blob/3f7ff809e5d02d7ea47db559adaca1c930025e24/app/scripts/controllers/signMsgCtrl.js#L53
|
||||||
public async signMessage(msg: string): Promise<string> {
|
public async signMessage(msg: string): Promise<string> {
|
||||||
|
if (process.env.BUILD_ELECTRON) {
|
||||||
|
const res = await EnclaveAPI.signMessage({
|
||||||
|
walletType: WalletTypes.LEDGER,
|
||||||
|
message: msg,
|
||||||
|
path: this.getPath()
|
||||||
|
});
|
||||||
|
return res.signedMessage;
|
||||||
|
}
|
||||||
|
|
||||||
const msgHex = Buffer.from(msg).toString('hex');
|
const msgHex = Buffer.from(msg).toString('hex');
|
||||||
try {
|
try {
|
||||||
const signed = await this.ethApp.signPersonalMessage_async(this.getPath(), msgHex);
|
const signed = await this.ethApp.signPersonalMessage_async(this.getPath(), msgHex);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import EthTx from 'ethereumjs-tx';
|
|
||||||
import { makeRequest } from './requests';
|
import { makeRequest } from './requests';
|
||||||
import {
|
import {
|
||||||
EnclaveMethods,
|
EnclaveMethods,
|
||||||
|
@ -7,7 +6,9 @@ import {
|
||||||
GetChainCodeParams,
|
GetChainCodeParams,
|
||||||
GetChainCodeResponse,
|
GetChainCodeResponse,
|
||||||
SignTransactionParams,
|
SignTransactionParams,
|
||||||
SignTransactionResponse
|
SignTransactionResponse,
|
||||||
|
SignMessageParams,
|
||||||
|
SignMessageResponse
|
||||||
} from 'shared/enclave/types';
|
} from 'shared/enclave/types';
|
||||||
|
|
||||||
const api = {
|
const api = {
|
||||||
|
@ -19,8 +20,12 @@ const api = {
|
||||||
return makeRequest<GetChainCodeResponse>(EnclaveMethods.GET_CHAIN_CODE, params);
|
return makeRequest<GetChainCodeResponse>(EnclaveMethods.GET_CHAIN_CODE, params);
|
||||||
},
|
},
|
||||||
|
|
||||||
async signTransaction(params: SignTransactionParams) {
|
signTransaction(params: SignTransactionParams) {
|
||||||
return makeRequest<SignTransactionResponse>(EnclaveMethods.SIGN_TRANSACTION, params);
|
return makeRequest<SignTransactionResponse>(EnclaveMethods.SIGN_TRANSACTION, params);
|
||||||
|
},
|
||||||
|
|
||||||
|
signMessage(params: SignMessageParams) {
|
||||||
|
return makeRequest<SignMessageResponse>(EnclaveMethods.SIGN_MESSAGE, params);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import getAddresses from './getAddresses';
|
import getAddresses from './getAddresses';
|
||||||
import getChainCode from './getChainCode';
|
import getChainCode from './getChainCode';
|
||||||
import signTransaction from './signTransaction';
|
import signTransaction from './signTransaction';
|
||||||
|
import signMessage from './signMessage';
|
||||||
import { EnclaveMethods, EnclaveMethodParams, EnclaveMethodResponse } from 'shared/enclave/types';
|
import { EnclaveMethods, EnclaveMethodParams, EnclaveMethodResponse } from 'shared/enclave/types';
|
||||||
|
|
||||||
const handlers: {
|
const handlers: {
|
||||||
|
@ -10,7 +11,8 @@ const handlers: {
|
||||||
} = {
|
} = {
|
||||||
[EnclaveMethods.GET_ADDRESSES]: getAddresses,
|
[EnclaveMethods.GET_ADDRESSES]: getAddresses,
|
||||||
[EnclaveMethods.GET_CHAIN_CODE]: getChainCode,
|
[EnclaveMethods.GET_CHAIN_CODE]: getChainCode,
|
||||||
[EnclaveMethods.SIGN_TRANSACTION]: signTransaction
|
[EnclaveMethods.SIGN_TRANSACTION]: signTransaction,
|
||||||
|
[EnclaveMethods.SIGN_MESSAGE]: signMessage
|
||||||
};
|
};
|
||||||
|
|
||||||
export default handlers;
|
export default handlers;
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { getWalletLib } from 'shared/enclave/server/wallets';
|
||||||
|
import { SignMessageParams, SignMessageResponse } from 'shared/enclave/types';
|
||||||
|
|
||||||
|
export default function(params: SignMessageParams): Promise<SignMessageResponse> {
|
||||||
|
const wallet = getWalletLib(params.walletType);
|
||||||
|
return wallet.signMessage(params.message, params.path);
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import { getWalletLib } from 'shared/enclave/server/wallets';
|
import { getWalletLib } from 'shared/enclave/server/wallets';
|
||||||
import { SignTransactionParams, SignTransactionResponse } from 'shared/enclave/types';
|
import { SignTransactionParams, SignTransactionResponse } from 'shared/enclave/types';
|
||||||
|
|
||||||
export default function(params: SignTransactionParams): SignTransactionResponse {
|
export default function(params: SignTransactionParams): Promise<SignTransactionResponse> {
|
||||||
const wallet = getWalletLib(params.walletType);
|
const wallet = getWalletLib(params.walletType);
|
||||||
return wallet.signTransaction(params.transaction, params.path);
|
return wallet.signTransaction(params.transaction, params.path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,15 @@ import { WalletLib } from 'shared/enclave/types';
|
||||||
|
|
||||||
const KeepKey: WalletLib = {
|
const KeepKey: WalletLib = {
|
||||||
async getChainCode() {
|
async getChainCode() {
|
||||||
throw new Error('Not yet supported');
|
throw new Error('Not yet implemented');
|
||||||
|
},
|
||||||
|
|
||||||
|
async signTransaction() {
|
||||||
|
throw new Error('Not yet implemented');
|
||||||
|
},
|
||||||
|
|
||||||
|
async signMessage() {
|
||||||
|
throw new Error('Not yet implemented');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import EthTx from 'ethereumjs-tx';
|
import EthTx from 'ethereumjs-tx';
|
||||||
import { addHexPrefix, toBuffer } from 'ethereumjs-util';
|
import { addHexPrefix, toBuffer } from 'ethereumjs-util';
|
||||||
import { WalletLib, RawTransaction } from 'shared/enclave/types';
|
import { WalletLib } from 'shared/enclave/types';
|
||||||
import TransportNodeHid from '@ledgerhq/hw-transport-node-hid';
|
import TransportNodeHid from '@ledgerhq/hw-transport-node-hid';
|
||||||
import LedgerEth from '@ledgerhq/hw-app-eth';
|
import LedgerEth from '@ledgerhq/hw-app-eth';
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ async function getEthApp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Ledger: WalletLib = {
|
const Ledger: WalletLib = {
|
||||||
async getChainCode(dpath: string) {
|
async getChainCode(dpath) {
|
||||||
const app = await getEthApp();
|
const app = await getEthApp();
|
||||||
try {
|
try {
|
||||||
const res = await app.getAddress(dpath, false, true);
|
const res = await app.getAddress(dpath, false, true);
|
||||||
|
@ -33,7 +33,7 @@ const Ledger: WalletLib = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async signTransaction(tx: RawTransaction, path: string) {
|
async signTransaction(tx, path) {
|
||||||
const app = await getEthApp();
|
const app = await getEthApp();
|
||||||
const ethTx = new EthTx({
|
const ethTx = new EthTx({
|
||||||
...tx,
|
...tx,
|
||||||
|
@ -52,6 +52,16 @@ const Ledger: WalletLib = {
|
||||||
return {
|
return {
|
||||||
signedTransaction: signedTx.serialize().toString('hex')
|
signedTransaction: signedTx.serialize().toString('hex')
|
||||||
};
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
async signMessage(msg: string, path: string) {
|
||||||
|
const app = await getEthApp();
|
||||||
|
const msgHex = Buffer.from(msg).toString('hex');
|
||||||
|
const signed = await app.signPersonalMessage(path, msgHex);
|
||||||
|
const combined = addHexPrefix(signed.r + signed.s + signed.v.toString(16));
|
||||||
|
return {
|
||||||
|
signedMessage: combined
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,10 @@ const Trezor: WalletLib = {
|
||||||
|
|
||||||
async signTransaction() {
|
async signTransaction() {
|
||||||
throw new Error('Not yet implemented');
|
throw new Error('Not yet implemented');
|
||||||
|
},
|
||||||
|
|
||||||
|
async signMessage() {
|
||||||
|
throw new Error('Not yet implemented');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
export enum EnclaveMethods {
|
export enum EnclaveMethods {
|
||||||
GET_ADDRESSES = 'get-addresses',
|
GET_ADDRESSES = 'get-addresses',
|
||||||
GET_CHAIN_CODE = 'get-chain-code',
|
GET_CHAIN_CODE = 'get-chain-code',
|
||||||
SIGN_TRANSACTION = 'sign-transaction'
|
SIGN_TRANSACTION = 'sign-transaction',
|
||||||
|
SIGN_MESSAGE = 'sign-message'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum WalletTypes {
|
export enum WalletTypes {
|
||||||
|
@ -52,12 +53,28 @@ export interface SignTransactionResponse {
|
||||||
signedTransaction: string;
|
signedTransaction: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sign Message Request
|
||||||
|
export interface SignMessageParams {
|
||||||
|
walletType: WalletTypes;
|
||||||
|
message: string;
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SignMessageResponse {
|
||||||
|
signedMessage: string;
|
||||||
|
}
|
||||||
|
|
||||||
// All Requests & Responses
|
// All Requests & Responses
|
||||||
export type EnclaveMethodParams = GetAddressesParams | GetChainCodeParams | SignTransactionParams;
|
export type EnclaveMethodParams =
|
||||||
|
| GetAddressesParams
|
||||||
|
| GetChainCodeParams
|
||||||
|
| SignTransactionParams
|
||||||
|
| SignMessageParams;
|
||||||
export type EnclaveMethodResponse =
|
export type EnclaveMethodResponse =
|
||||||
| GetAddressesResponse
|
| GetAddressesResponse
|
||||||
| GetChainCodeResponse
|
| GetChainCodeResponse
|
||||||
| SignTransactionResponse;
|
| SignTransactionResponse
|
||||||
|
| SignMessageResponse;
|
||||||
|
|
||||||
// RPC requests, responses & failures
|
// RPC requests, responses & failures
|
||||||
export interface EnclaveSuccessResponse<T = EnclaveMethodResponse> {
|
export interface EnclaveSuccessResponse<T = EnclaveMethodResponse> {
|
||||||
|
@ -82,4 +99,5 @@ export type EnclaveResponse<T = EnclaveMethodResponse> =
|
||||||
export interface WalletLib {
|
export interface WalletLib {
|
||||||
getChainCode(dpath: string): Promise<GetChainCodeResponse>;
|
getChainCode(dpath: string): Promise<GetChainCodeResponse>;
|
||||||
signTransaction(transaction: RawTransaction, path: string): Promise<SignTransactionResponse>;
|
signTransaction(transaction: RawTransaction, path: string): Promise<SignTransactionResponse>;
|
||||||
|
signMessage(msg: string, path: string): Promise<SignMessageResponse>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue