Skip to content

Commit 91cfc28

Browse files
author
slient-coder
committed
feat: implement Keystone Babylon integration with Cosmos signing support and Keplr compatibility
1 parent 9022301 commit 91cfc28

35 files changed

+1260
-530
lines changed

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
"@keystonehq/hw-app-base": "0.1.7",
4444
"@keystonehq/hw-transport-webusb": "0.4.0",
4545
"@metamask/obs-store": "^7.0.0",
46+
"@noble/curves": "^1.0.0",
47+
"@noble/hashes": "^1.7.1",
4648
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
4749
"@reduxjs/toolkit": "^1.9.2",
4850
"@sentry/browser": "^6.19.7",
@@ -59,7 +61,7 @@
5961
"@types/react": "^18.0.9",
6062
"@types/react-cache": "^2.0.1",
6163
"@types/react-dom": "^18.0.4",
62-
"@unisat/wallet-sdk": "1.8.0",
64+
"@unisat/wallet-sdk": "1.9.0",
6365
"antd": "^4.20.4",
6466
"antd-dayjs-webpack-plugin": "1.0.6",
6567
"assert": "^2.0.0",

src/background/controller/provider/controller.ts

+60-59
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
21
import { permissionService, sessionService } from '@/background/service';
32
import { CHAINS, CHAINS_MAP, NETWORK_TYPES, VERSION } from '@/shared/constant';
4-
53
import { NetworkType } from '@/shared/types';
6-
import { getChainInfo } from '@/shared/utils';
4+
import { getChainInfo, objToUint8Array } from '@/shared/utils';
75
import { amountToSatoshis } from '@/ui/utils';
6+
import * as encoding from '@cosmjs/encoding';
87
import { bitcoin } from '@unisat/wallet-sdk/lib/bitcoin-core';
98
import { verifyMessageOfBIP322Simple } from '@unisat/wallet-sdk/lib/message';
109
import { toPsbtNetwork } from '@unisat/wallet-sdk/lib/network';
1110
import { ethErrors } from 'eth-rpc-errors';
1211
import BaseController from '../base';
1312
import wallet from '../wallet';
1413

15-
import {
16-
SignDoc
17-
} from "@keplr-wallet/proto-types/cosmos/tx/v1beta1/tx";
14+
import { encodeSecp256k1Signature, makeADR36AminoSignDoc, serializeSignDoc } from '@/background/service/keyring/CosmosKeyring';
15+
import { makeSignBytes } from '@cosmjs/proto-signing';
1816

1917
function formatPsbtHex(psbtHex: string) {
2018
let formatData = '';
@@ -197,7 +195,7 @@ class ProviderController extends BaseController {
197195
return await wallet.pushTx(rawtx)
198196
}
199197

200-
@Reflect.metadata('APPROVAL', ['SignText', () => {
198+
@Reflect.metadata('APPROVAL', ['SignText', (req) => {
201199
// todo check text
202200
}])
203201
signMessage = async ({ data: { params: { text, type } }, approvalRes }) => {
@@ -303,6 +301,13 @@ class ProviderController extends BaseController {
303301
return utxos;
304302
};
305303

304+
305+
private _isKeystoneWallet = async () => {
306+
const currentKeyring = await wallet.getCurrentKeyring();
307+
return currentKeyring?.type === 'keystone';
308+
}
309+
310+
306311
@Reflect.metadata('APPROVAL', ['CosmosConnect', (req) => {
307312
// todo check
308313
}])
@@ -312,6 +317,7 @@ class ProviderController extends BaseController {
312317
}
313318
};
314319

320+
315321
@Reflect.metadata('SAFE', true)
316322
cosmosExperimentalSuggestChain = async ( {data:{params:{chainData}}} ) => {
317323
// const chainInfo:CosmosChainInfo = chainData;
@@ -322,76 +328,71 @@ class ProviderController extends BaseController {
322328
throw new Error('not implemented')
323329
}
324330

331+
325332
@Reflect.metadata('SAFE', true)
326333
cosmosGetKey = async ({ data: { params: { chainId} } }) => {
327334
const cosmosKeyring = await wallet.getCosmosKeyring(chainId);
328-
if(!cosmosKeyring){
329-
return null;
330-
}
331-
332-
const key = cosmosKeyring.getKey();
333-
const _key = Object.assign({},key,{
334-
address:key.address.toString(),
335-
pubKey:key.pubKey.toString()
336-
})
337-
return _key
335+
if(!cosmosKeyring){
336+
return null;
337+
}
338+
339+
const key = cosmosKeyring.getKey();
340+
const _key = Object.assign({},key,{
341+
address:key.address.toString(),
342+
pubKey:key.pubKey.toString()
343+
});
344+
return _key;
338345
}
339346

347+
340348
@Reflect.metadata('APPROVAL', ['CosmosSign', (req) => {
341-
// todo check
349+
const signDoc = req.data.params.signDoc;
350+
signDoc.bodyBytes = objToUint8Array(signDoc.bodyBytes);
351+
signDoc.authInfoBytes = objToUint8Array(signDoc.authInfoBytes);
352+
const signBytes = makeSignBytes(signDoc);
353+
req.data.params.signBytesHex = encoding.toHex(signBytes);
354+
342355
}])
343-
cosmosSignDirect = async ({ data: { params:msg } }) => {
344-
const signDoc = SignDoc.fromPartial({
345-
bodyBytes: msg.signDoc.bodyBytes,
346-
authInfoBytes: msg.signDoc.authInfoBytes,
347-
chainId: msg.signDoc.chainId,
348-
accountNumber: msg.signDoc.accountNumber,
349-
});
350-
351-
const cosmosKeyring = await wallet.getCosmosKeyring(msg.signDoc.chainId);
352-
if(!cosmosKeyring){
353-
throw new Error('no keyring')
356+
cosmosSignDirect = async ({ data: { params: msg } ,approvalRes}) => {
357+
if (!approvalRes) {
358+
throw new Error('approvalRes is required')
354359
}
355-
356-
const response = await cosmosKeyring.signDirect(
357-
msg.signDoc.chainId,
358-
msg.signerAddress,
359-
signDoc,
360-
);
361-
362-
return response
363-
364-
360+
const {bodyBytes,authInfoBytes,chainId,accountNumber} = msg.signDoc;
361+
const signature = encodeSecp256k1Signature(encoding.fromHex(approvalRes.publicKey), encoding.fromHex(approvalRes.signature));
362+
const respone = {
363+
signed: {
364+
bodyBytes:objToUint8Array(bodyBytes),
365+
authInfoBytes:objToUint8Array(authInfoBytes),
366+
chainId,
367+
accountNumber,
368+
},
369+
signature
370+
} ;
371+
return respone;
372+
365373
}
366374

367-
// signArbitrary
368375
@Reflect.metadata('APPROVAL', ['CosmosSign', (req) => {
369-
// todo check
376+
const signerAddress = req.data.params.signerAddress;
377+
const data = req.data.params.data;
378+
const signDoc = makeADR36AminoSignDoc(signerAddress, data);
379+
const signBytes = serializeSignDoc(signDoc);
380+
req.data.params.signBytesHex = encoding.toHex(signBytes);
370381
}])
371-
cosmosSignArbitrary = async ({ data: { params:msg } }) => {
372-
373-
const cosmosKeyring = await wallet.getCosmosKeyring(msg.chainId);
374-
if(!cosmosKeyring){
375-
throw new Error('no keyring')
382+
cosmosSignArbitrary = async ({ data: { params:msg } ,approvalRes}) => {
383+
if (!approvalRes) {
384+
throw new Error('approvalRes is required')
376385
}
377386

378-
const response = await cosmosKeyring.signAminoADR36(
379-
msg.chainId,
380-
msg.signer,
381-
typeof msg.data === "string" ? Buffer.from(msg.data) : msg.data,
382-
);
383-
384-
return response
387+
const signature = encodeSecp256k1Signature(encoding.fromHex(approvalRes.publicKey), encoding.fromHex(approvalRes.signature));
388+
const respone = signature
389+
return respone;
390+
391+
}
385392

386393

387-
}
388394

389395

390-
@Reflect.metadata('SAFE', true)
391-
cosmosSignAmino = async ({ data: { params: { signerAddress, signDoc } } }) => {
392-
throw new Error('not implemented')
393-
// return signerAddress
394-
}
395396
}
396397

397398
export default new ProviderController();

0 commit comments

Comments
 (0)