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; break;
// TODO: Debug signDirect
case 'cosmos_signDirect': case 'cosmos_signDirect':
navigation.navigate('SignRequest', { navigation.navigate('SignRequest', {
network: 'cosmos', network: 'cosmos',

View File

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

View File

@ -5,9 +5,15 @@ import 'react-native-get-random-values';
import '@ethersproject/shims'; import '@ethersproject/shims';
import { Wallet } from 'ethers'; import { Wallet } from 'ethers';
import { SignDoc } from 'cosmjs-types/cosmos/tx/v1beta1/tx';
import { SignMessageParams } from '../types'; import { SignMessageParams } from '../types';
import { getCosmosAccounts, getMnemonic, getPathKey } from './utils'; import {
getCosmosAccounts,
getDirectWallet,
getMnemonic,
getPathKey,
} from './utils';
const signMessage = async ({ const signMessage = async ({
message, message,
@ -38,7 +44,7 @@ const signEthMessage = async (
return signature; return signature;
} catch (error) { } catch (error) {
console.error('Error signing Ethereum message:', error); console.error('Error signing Ethereum message:', error);
return undefined; throw error;
} }
}; };
@ -76,8 +82,30 @@ const signCosmosMessage = async (
return cosmosSignature.signature.signature; return cosmosSignature.signature.signature;
} catch (error) { } catch (error) {
console.error('Error signing Cosmos message:', 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'; } from 'react-native-keychain';
import { AccountData, Secp256k1HdWallet } from '@cosmjs/amino'; import { AccountData, Secp256k1HdWallet } from '@cosmjs/amino';
import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing';
import { stringToPath } from '@cosmjs/crypto'; import { stringToPath } from '@cosmjs/crypto';
const getMnemonic = async (): Promise<string> => { const getMnemonic = async (): Promise<string> => {
@ -58,6 +59,19 @@ const getCosmosAccounts = async (
return { cosmosWallet, data }; 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 ( const accountInfoFromHDPath = async (
hdPath: string, hdPath: string,
): Promise< ): Promise<

View File

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

View File

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