Closed HS-Joe closed 7 months ago
hey @HS-Joe you can use the below snippet to validate it.
const sortObject = (obj: any): any => {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(sortObject);
}
const sortedKeys = Object.keys(obj).sort();
const result: Record<string, any> = {};
for (const key of sortedKeys) {
result[key] = sortObject(obj[key]);
}
return result;
}
/**
*
* @param signDoc
*/
const serializeStdSignDoc = (signDoc: StdSignDoc) => {
const json = JSON.stringify(sortObject(signDoc));
return new TextEncoder().encode(json);
}
function base64ToArrayBuffer(base64: any) {
var binaryString = atob(base64);
var bytes = new Uint8Array(binaryString.length);
for (var i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes;
}
const getADR36SignDoc = (data: any, signer: string) => {
let isADR36WithString = false;
let b64Data = '';
if (typeof data === 'string') {
b64Data = Buffer.from(data).toString('base64');
isADR36WithString = true;
} else {
b64Data = Buffer.from(data).toString('base64');
}
const sortedSignDoc = {
chain_id: 'cosmoshub-4',
account_number: '0',
sequence: '0',
fee: {
gas: '0',
amount: [],
},
memo: '',
msgs: [
{
type: 'sign/MsgSignData',
value: {
signer: signer,
b64Data,
},
},
],
}
return sortedSignDoc;
}
const validate = async () => {
const data:any = { key: "value" };
const accountData = await window.ethereum.request({
method: 'wallet_invokeSnap',
params: {
snapId: "npm:@leapwallet/metamask-cosmos-snap",
request: {
method: 'getKey',
params: { chainId: 'cosmoshub-4' }
},
},
});
const base64Data:string = btoa(JSON.stringify(data));
const sign = await signArbitrary('cosmoshub-4', accountData.address, base64Data, { enableExtraEntropy: false });
const signDoc = getADR36SignDoc(base64Data, accountData.address);
const hashedSerializedSignDoc = sha256(serializeStdSignDoc(signDoc))
const pubKey = new Uint8Array(Object.values(accountData.pubkey));
const valid = secp.verify(
base64ToArrayBuffer(sign.signature),
hashedSerializedSignDoc,
pubKey);
console.log(valid);
}
I will expose appropriate methods from provider, so that you can avoid having them in your codebase
Thanks @leapsamvel I confirm it works!
When using signArbitrary with the snap, the generated sig cannot be verified, though using Leap wallet's browser extension signArbitrary it works.
How to reproduce
Could you guys have a look, and maybe write a unit test to help?