Sign message using signDirect method with cosmos accounts (#51)

* Sign message using signDirect method with cosmos accounts

* Add explaination for signDirect method

* Use existing utility function to convert hex string to uint8array

* Handle review changes
This commit is contained in:
shreerang6921 2024-03-12 16:47:05 +05:30 committed by GitHub
parent 5b6f4e9f61
commit 7219162185
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 119 additions and 45 deletions

View File

@ -69,7 +69,6 @@ const App = (): React.JSX.Element => {
});
break;
// TODO: Debug signDirect
case 'cosmos_signDirect':
navigation.navigate('SignRequest', {
network: 'cosmos',

View File

@ -11,8 +11,9 @@
"postinstall": "patch-package"
},
"dependencies": {
"@cosmjs/amino": "^0.32.2",
"@cosmjs/crypto": "^0.32.2",
"@cosmjs/amino": "^0.32.3",
"@cosmjs/crypto": "^0.32.3",
"@cosmjs/proto-signing": "^0.32.3",
"@ethersproject/shims": "^5.7.0",
"@json-rpc-tools/utils": "^1.7.6",
"@react-native-async-storage/async-storage": "^1.22.3",
@ -21,6 +22,7 @@
"@react-navigation/native-stack": "^6.9.18",
"@walletconnect/react-native-compat": "^2.11.2",
"@walletconnect/web3wallet": "^1.10.2",
"cosmjs-types": "^0.9.0",
"ethers": "5.7.2",
"fast-text-encoding": "^1.0.6",
"metro-react-native-babel-preset": "^0.77.0",

View File

@ -5,9 +5,15 @@ import 'react-native-get-random-values';
import '@ethersproject/shims';
import { Wallet } from 'ethers';
import { SignDoc } from 'cosmjs-types/cosmos/tx/v1beta1/tx';
import { SignMessageParams } from '../types';
import { getCosmosAccounts, getMnemonic, getPathKey } from './utils';
import {
getCosmosAccounts,
getDirectWallet,
getMnemonic,
getPathKey,
} from './utils';
const signMessage = async ({
message,
@ -38,7 +44,7 @@ const signEthMessage = async (
return signature;
} catch (error) {
console.error('Error signing Ethereum message:', error);
return undefined;
throw error;
}
};
@ -76,8 +82,30 @@ const signCosmosMessage = async (
return cosmosSignature.signature.signature;
} catch (error) {
console.error('Error signing Cosmos message:', error);
return undefined;
throw error;
}
};
export { signMessage, signEthMessage, signCosmosMessage };
const signDirectMessage = async (
network: string,
accountId: number,
signDoc: SignDoc,
): Promise<string | undefined> => {
try {
const path = (await getPathKey(network, accountId)).path;
const mnemonic = await getMnemonic();
const { directWallet, data } = await getDirectWallet(mnemonic, path);
const directSignature = await directWallet.signDirect(
data.address,
signDoc,
);
return directSignature.signature.signature;
} catch (error) {
console.error('Error signing Cosmos message:', error);
throw error;
}
};
export { signMessage, signEthMessage, signCosmosMessage, signDirectMessage };

View File

@ -12,6 +12,7 @@ import {
} from 'react-native-keychain';
import { AccountData, Secp256k1HdWallet } from '@cosmjs/amino';
import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing';
import { stringToPath } from '@cosmjs/crypto';
const getMnemonic = async (): Promise<string> => {
@ -58,6 +59,19 @@ const getCosmosAccounts = async (
return { cosmosWallet, data };
};
export const getDirectWallet = async (
mnemonic: string,
path: string,
): Promise<{ directWallet: DirectSecp256k1HdWallet; data: AccountData }> => {
const directWallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
hdPaths: [stringToPath(`m/44'/118'/${path}`)],
});
const accountsData = await directWallet.getAccounts();
const data = accountsData[0];
return { directWallet, data };
};
const accountInfoFromHDPath = async (
hdPath: string,
): Promise<

View File

@ -5,7 +5,7 @@ import { SignClientTypes } from '@walletconnect/types';
import { getSdkError } from '@walletconnect/utils';
import { EIP155_SIGNING_METHODS } from './EIP155Lib';
import { signEthMessage } from '../sign-message';
import { signDirectMessage, signEthMessage } from '../sign-message';
import { Account } from '../../types';
import { getCosmosAccounts, getMnemonic, getPathKey } from '../utils';
@ -25,31 +25,45 @@ export async function approveWalletConnectRequest(
switch (request.method) {
case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
const signedEthMessage = await signEthMessage(message, account.counterId);
return formatJsonRpcResult(id, signedEthMessage);
// TODO: Debug signDirect
const ethSignature = await signEthMessage(message, account.counterId);
return formatJsonRpcResult(id, ethSignature);
case 'cosmos_signDirect':
const signedCosmosMessage = await cosmosAccount.cosmosWallet.signAmino(
address,
request.params.signDoc,
// Reference: https://github.com/confio/cosmjs-types/blob/66e52711914fccd2a9d1a03e392d3628fdf499e2/src/cosmos/tx/v1beta1/tx.ts#L51
// According above doc, in the signDoc interface 'bodyBytes' and 'authInfoBytes' have Uint8Array type
const bodyBytesArray = Uint8Array.from(
Buffer.from(request.params.signDoc.bodyBytes, 'hex'),
);
const authInfoBytesArray = Uint8Array.from(
Buffer.from(request.params.signDoc.authInfoBytes, 'hex'),
);
const cosmosDirectSignature = await signDirectMessage(
network,
account.counterId,
{
...request.params.signDoc,
bodyBytes: bodyBytesArray,
authInfoBytes: authInfoBytesArray,
},
);
return formatJsonRpcResult(id, {
signature: signedCosmosMessage.signature.signature,
signature: cosmosDirectSignature,
});
case 'cosmos_signAmino':
const signedAminoMessage = await cosmosAccount.cosmosWallet.signAmino(
const cosmosAminoSignature = await cosmosAccount.cosmosWallet.signAmino(
address,
request.params.signDoc,
);
if (!signedAminoMessage) {
if (!cosmosAminoSignature) {
throw new Error('Error signing message');
}
return formatJsonRpcResult(id, {
signature: signedAminoMessage.signature.signature,
signature: cosmosAminoSignature.signature.signature,
});
default:
throw new Error(getSdkError('INVALID_METHOD').message);

View File

@ -1167,49 +1167,61 @@
deepmerge "^3.2.0"
hoist-non-react-statics "^3.3.0"
"@cosmjs/amino@^0.32.2":
version "0.32.2"
resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.32.2.tgz#ba3cf255e4e6b1ba67461f1ef7b0b8ad3f895da7"
integrity sha512-lcK5RCVm4OfdAooxKcF2+NwaDVVpghOq6o/A40c2mHXDUzUoRZ33VAHjVJ9Me6vOFxshrw/XEFn1f4KObntjYA==
"@cosmjs/amino@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.32.3.tgz#b81d4a2b8d61568431a1afcd871e1344a19d97ff"
integrity sha512-G4zXl+dJbqrz1sSJ56H/25l5NJEk/pAPIr8piAHgbXYw88OdAOlpA26PQvk2IbSN/rRgVbvlLTNgX2tzz1dyUA==
dependencies:
"@cosmjs/crypto" "^0.32.2"
"@cosmjs/encoding" "^0.32.2"
"@cosmjs/math" "^0.32.2"
"@cosmjs/utils" "^0.32.2"
"@cosmjs/crypto" "^0.32.3"
"@cosmjs/encoding" "^0.32.3"
"@cosmjs/math" "^0.32.3"
"@cosmjs/utils" "^0.32.3"
"@cosmjs/crypto@^0.32.2":
version "0.32.2"
resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.32.2.tgz#8ed255d3d1c1c4d916a1586f8cbc33eaab82f511"
integrity sha512-RuxrYKzhrPF9g6NmU7VEq++Hn1vZJjqqJpZ9Tmw9lOYOV8BUsv+j/0BE86kmWi7xVJ7EwxiuxYsKuM8IR18CIA==
"@cosmjs/crypto@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.32.3.tgz#787f8e659709678722068ee1ddf379f65051a25e"
integrity sha512-niQOWJHUtlJm2GG4F00yGT7sGPKxfUwz+2qQ30uO/E3p58gOusTcH2qjiJNVxb8vScYJhFYFqpm/OA/mVqoUGQ==
dependencies:
"@cosmjs/encoding" "^0.32.2"
"@cosmjs/math" "^0.32.2"
"@cosmjs/utils" "^0.32.2"
"@cosmjs/encoding" "^0.32.3"
"@cosmjs/math" "^0.32.3"
"@cosmjs/utils" "^0.32.3"
"@noble/hashes" "^1"
bn.js "^5.2.0"
elliptic "^6.5.4"
libsodium-wrappers-sumo "^0.7.11"
"@cosmjs/encoding@^0.32.2":
version "0.32.2"
resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.32.2.tgz#8c5c64481a85cd570740c34dccce69d024a29805"
integrity sha512-WX7m1wLpA9V/zH0zRcz4EmgZdAv1F44g4dbXOgNj1eXZw1PIGR12p58OEkLN51Ha3S4DKRtCv5CkhK1KHEvQtg==
"@cosmjs/encoding@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.32.3.tgz#e245ff511fe4a0df7ba427b5187aab69e3468e5b"
integrity sha512-p4KF7hhv8jBQX3MkB3Defuhz/W0l3PwWVYU2vkVuBJ13bJcXyhU9nJjiMkaIv+XP+W2QgRceqNNgFUC5chNR7w==
dependencies:
base64-js "^1.3.0"
bech32 "^1.1.4"
readonly-date "^1.0.0"
"@cosmjs/math@^0.32.2":
version "0.32.2"
resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.32.2.tgz#4522312769197e132679e4960862bcec0eed4cb8"
integrity sha512-b8+ruAAY8aKtVKWSft2IvtCVCUH1LigIlf9ALIiY8n9jtM4kMASiaRbQ/27etnSAInV88IaezKK9rQZrtxTjcw==
"@cosmjs/math@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.32.3.tgz#16e4256f4da507b9352327da12ae64056a2ba6c9"
integrity sha512-amumUtZs8hCCnV+lSBaJIiZkGabQm22QGg/IotYrhcmoOEOjt82n7hMNlNXRs7V6WLMidGrGYcswB5zcmp0Meg==
dependencies:
bn.js "^5.2.0"
"@cosmjs/utils@^0.32.2":
version "0.32.2"
resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.32.2.tgz#324304aa85bfa6f10561cc17781d824d02130897"
integrity sha512-Gg5t+eR7vPJMAmhkFt6CZrzPd0EKpAslWwk5rFVYZpJsM8JG5KT9XQ99hgNM3Ov6ScNoIWbXkpX27F6A9cXR4Q==
"@cosmjs/proto-signing@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/proto-signing/-/proto-signing-0.32.3.tgz#91ae149b747d18666a6ccc924165b306431f7c0d"
integrity sha512-kSZ0ZUY0DwcRT0NcIn2HkadH4NKlwjfZgbLj1ABwh/4l0RgeT84QCscZCu63tJYq3K6auwqTiZSZERwlO4/nbg==
dependencies:
"@cosmjs/amino" "^0.32.3"
"@cosmjs/crypto" "^0.32.3"
"@cosmjs/encoding" "^0.32.3"
"@cosmjs/math" "^0.32.3"
"@cosmjs/utils" "^0.32.3"
cosmjs-types "^0.9.0"
"@cosmjs/utils@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.32.3.tgz#5dcaee6dd7cc846cdc073e9a7a7f63242f5f7e31"
integrity sha512-WCZK4yksj2hBDz4w7xFZQTRZQ/RJhBX26uFHmmQFIcNUUVAihrLO+RerqJgk0dZqC42wstM9pEUQGtPmLcIYvg==
"@craftzdog/react-native-buffer@^6.0.5":
version "6.0.5"
@ -3944,6 +3956,11 @@ cosmiconfig@^5.0.5, cosmiconfig@^5.1.0:
js-yaml "^3.13.1"
parse-json "^4.0.0"
cosmjs-types@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/cosmjs-types/-/cosmjs-types-0.9.0.tgz#c3bc482d28c7dfa25d1445093fdb2d9da1f6cfcc"
integrity sha512-MN/yUe6mkJwHnCFfsNPeCfXVhyxHYW6c/xDUzrSbBycYzw++XvWDMJArXp2pLdgD6FQ8DW79vkPjeNKVrXaHeQ==
create-ecdh@^4.0.0:
version "4.0.4"
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"