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