-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: metamask support #194
Conversation
@kimurayu45z @jununifi |
@kimurayu45z @jununifi Screenshot of sending tx with MetaMask tx post response
chain's log (log level = debug)
frontend app's log
|
Memo: Need to change from signTypedData_v4 to personal_sign |
@jununifi @kimurayu45z |
a62fcef
to
60150f4
Compare
@jununifi cc: @kimurayu45z |
const txJson = JSON.parse(txJsonString); | ||
|
||
// fix JSONstringify issue | ||
delete txJson.auth_info.signer_infos[0].mode_info.multi; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
by using
cosmos-client/cosmos-client-ts#71
this PR, you can delete this line.
// fix JSONstringify issue | ||
delete txJson.auth_info.signer_infos[0].mode_info.multi; | ||
txJson.auth_info.signer_infos[0].mode_info.single.mode = 'SIGN_MODE_DIRECT'; | ||
txJson.auth_info.fee.gas_limit = txJson.auth_info.fee.gas_limit.toString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this line also seems to be able to be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI @jununifi
private messageToDigest(message: string): Uint8Array { | ||
const messageHash = ethers.utils.hashMessage(message); | ||
const digest = ethers.utils.arrayify(messageHash); | ||
return digest; | ||
} | ||
|
||
private async personalSign(message: string): Promise<string> { | ||
await detectEthereumProvider({ mustBeMetaMask: true }); | ||
if (!window.ethereum?.isMetaMask) { | ||
throw Error('MetaMask is not installed!'); | ||
} | ||
const provider = new ethers.providers.Web3Provider(window.ethereum); | ||
const accounts = await provider.send('eth_requestAccounts', []); | ||
if (!accounts?.length) { | ||
throw Error('Failed to get MetaMask account!'); | ||
} | ||
const address = accounts[0]; | ||
console.log(address); | ||
const signer = provider.getSigner(address); | ||
const signature = signer.signMessage(message); | ||
return signature; | ||
} | ||
|
||
private async getPublicKeyFromMetaMask(): Promise<string> { | ||
const message = 'Connecting to MetaMask from UnUniFi'; | ||
const signature = await this.personalSign(message); | ||
console.log('signature', signature); | ||
const recoveredAddress = ethers.utils.verifyMessage(message, signature); | ||
console.log('ethRecoveredAddress', recoveredAddress); | ||
|
||
const digest = this.messageToDigest(message); | ||
console.log('digest', digest); | ||
const recoveredUncompressedPublicKey = ethers.utils.recoverPublicKey(digest, signature); | ||
console.log('ethUncompressedPublicKey', recoveredUncompressedPublicKey); | ||
const recoverdAddress2 = ethers.utils.recoverAddress(digest, signature); | ||
console.log('ethRecoveredAddress2', recoverdAddress2); | ||
const recoveredCompressedPublicKey = ethers.utils.computePublicKey( | ||
recoveredUncompressedPublicKey, | ||
true, | ||
); | ||
console.log('ethCompressedPublicKey', recoveredCompressedPublicKey); | ||
const publicKeyWithout0x = recoveredCompressedPublicKey.slice(2); | ||
return publicKeyWithout0x; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jununifi
You can refer the procedure to get public key on front end side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI @jununifi
private async getCosmosStoredWalletFromMetaMask(): Promise<StoredWallet> { | ||
const ethAddress = await this.getEthAddress(); | ||
const publicKeyString = await this.getPublicKeyFromMetaMask(); | ||
const cosmosPublicKey = createCosmosPublicKeyFromString(KeyType.secp256k1, publicKeyString); | ||
if (!cosmosPublicKey) { | ||
throw Error('Invalid public key!'); | ||
} | ||
const accAddress = cosmosclient.AccAddress.fromPublicKey(cosmosPublicKey); | ||
const storedWallet: StoredWallet = { | ||
id: ethAddress, | ||
type: WalletType.metaMask, | ||
key_type: KeyType.ethsecp256k1, | ||
public_key: publicKeyString, | ||
address: accAddress.toString(), | ||
}; | ||
return storedWallet; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jununifi
You can refer the procedure to convert from public key to UnUniFi address.
signature verification failed
This should be reverted after fix
from SIGN_DIRECT to SIGN_MODE_DIRECT
- reference - ethers-io/ethers.js#447 (comment) - remove web3 - remove eth-sig-utils
c76bd11
to
169de99
Compare
@kimurayu45z |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for fixing config.js .
@jununifi
Because it seems your reference PR's branch ( #188 and https://github.com/UnUniFi/web-apps/tree/metamask_integration ) was checked out from main branch, I have created new branch and new PR with checking out from develop branch. I will implement this feature here.
Todos
Screenshots
Connect to MetaMask Image