on c9bf94f help sign in
bridge/src/lib/authToken.ts
128 lines 3.6 kB history raw
1import { crypto } from 'bitcoinjs-lib';
2import { ecdsaSign } from 'secp256k1';
3import Web3 from 'web3';
4import { hexToBytes } from 'web3-utils';
5import WalletConnect from '@walletconnect/client';
7import { WALLET_TYPES } from './constants';
8import { ledgerSignMessage } from './ledger';
9import { trezorSignMessage } from './trezor';
10import BridgeWallet from './types/BridgeWallet';
11import { Hash } from '@urbit/roller-api';
13const MESSAGE = 'Bridge Authentication Token';
15function signMessage(privateKey: Buffer) {
16 const msg = '\x19Ethereum Signed Message:\n' + MESSAGE.length + MESSAGE;
17 // #ecdsaSign requires a 32-byte buffer, hence sha256
18 const hashed = crypto.sha256(Buffer.from(msg));
19 const { signature } = ecdsaSign(Buffer.from(hashed), privateKey);
21 // add key recovery parameter
22 const ethSignature = new Uint8Array(65);
23 ethSignature.set(signature);
24 const v = (ethSignature[32] & 1) + 27;
25 ethSignature[64] = v;
27 return ethSignature;
30export function signTransactionHash(msg: Hash, prvKey: Buffer) {
31 // msg is a keccak-256 hash
32 //
33 const hashed = Buffer.from(hexToBytes(msg));
34 const { signature, recid } = ecdsaSign(hashed, prvKey);
35 // add key recovery parameter
36 const ethSignature = new Uint8Array(65);
37 ethSignature.set(signature);
38 ethSignature[64] = recid;
39 return `0x${Buffer.from(ethSignature).toString('hex')}`;
42type MetamaskAuthTokenArgs = {
43 address: string;
44 web3: Web3;
45 walletType: symbol;
46};
48type LedgerAuthTokenArgs = {
49 walletHdPath: string;
50 walletType: symbol;
51};
53type TrezorAuthTokenArgs = LedgerAuthTokenArgs;
55type WalletConnectAuthTokenArgs = {
56 address: string;
57 connector: WalletConnect;
58 walletType: symbol;
59};
61type DefaultAuthTokenArgs = {
62 wallet: BridgeWallet;
63 walletType?: symbol;
64};
66type GetAuthTokenArgs =
67 | MetamaskAuthTokenArgs
68 | LedgerAuthTokenArgs
69 | TrezorAuthTokenArgs
70 | WalletConnectAuthTokenArgs
71 | DefaultAuthTokenArgs;
73const getMetamaskAuthToken = ({ address, web3 }: MetamaskAuthTokenArgs) => {
74 if (window.ethereum) {
75 //NOTE this doesn't _seem_ to be affected by #596,
76 // but web3.eth.personal.sign hits it semi-reliably?
77 // no idea what's going on, we should figure it out,
78 // but we apply this bandaid to hopefully stop the bleeding.
79 return window.ethereum.request({
80 method: 'personal_sign',
81 params: [MESSAGE, address],
82 from: address,
83 });
84 } else {
85 return web3.eth.personal.sign(MESSAGE, address, '');
86 }
87};
89const getLedgerAuthToken = ({ walletHdPath }: LedgerAuthTokenArgs) => {
90 return ledgerSignMessage(MESSAGE, walletHdPath);
91};
93const getTrezorAuthToken = ({ walletHdPath }: TrezorAuthTokenArgs) => {
94 return trezorSignMessage(MESSAGE, walletHdPath);
95};
97const getWalletConnectAuthToken = ({
98 address,
99 connector,
100}: WalletConnectAuthTokenArgs) => {
101 return connector.signPersonalMessage([MESSAGE, address]);
102};
104const getDefaultAuthToken = ({ wallet }: DefaultAuthTokenArgs) => {
105 const signature = signMessage(wallet.privateKey);
107 const token = `0x${Buffer.from(signature).toString('hex')}`;
109 return token;
110};
112export const getAuthToken = async ({
113 walletType,
114 ...args
115}: GetAuthTokenArgs) => {
116 switch (walletType) {
117 case WALLET_TYPES.METAMASK:
118 return getMetamaskAuthToken(args);
119 case WALLET_TYPES.LEDGER:
120 return getLedgerAuthToken(args);
121 case WALLET_TYPES.TREZOR:
122 return getTrezorAuthToken(args);
123 case WALLET_TYPES.WALLET_CONNECT:
124 return getWalletConnectAuthToken(args);
125 default:
126 return getDefaultAuthToken(args);
127 }
128};