formated by eslint
This commit is contained in:
parent
c32c82fdcc
commit
5aac799522
@ -1,118 +1,107 @@
|
|||||||
|
import {
|
||||||
|
AccountData, AminoSignResponse, OfflineAminoSigner, Pubkey, StdSignature, StdSignDoc,
|
||||||
|
} from '@cosmjs/amino'
|
||||||
|
import Transport from '@ledgerhq/hw-transport'
|
||||||
|
|
||||||
import { AccountData, AminoSignResponse, OfflineAminoSigner, Pubkey, StdSignature, StdSignDoc } from "@cosmjs/amino";
|
import Eth from '@ledgerhq/hw-app-eth'
|
||||||
import { AddressAndPubkey } from "@cosmjs/ledger-amino";
|
import { LoadConfig } from '@ledgerhq/hw-app-eth/lib/services/types'
|
||||||
import Transport from "@ledgerhq/hw-transport";
|
import {
|
||||||
|
fromBech32, fromHex, toBech32, toHex,
|
||||||
import Eth from "@ledgerhq/hw-app-eth";
|
} from '@cosmjs/encoding'
|
||||||
import { LedgerEthTransactionResolution, LoadConfig } from "@ledgerhq/hw-app-eth/lib/services/types";
|
|
||||||
import { fromBech32, fromHex, toBech32, toHex } from "@cosmjs/encoding";
|
|
||||||
import TransportWebBLE from '@ledgerhq/hw-transport-web-ble'
|
import TransportWebBLE from '@ledgerhq/hw-transport-web-ble'
|
||||||
import TransportWebUSB from '@ledgerhq/hw-transport-webusb'
|
import TransportWebUSB from '@ledgerhq/hw-transport-webusb'
|
||||||
import { HdPath, keccak256, pathToString } from "@cosmjs/crypto";
|
import {
|
||||||
|
HdPath, keccak256, pathToString,
|
||||||
|
} from '@cosmjs/crypto'
|
||||||
import { ethToEvmos } from '@tharsis/address-converter'
|
import { ethToEvmos } from '@tharsis/address-converter'
|
||||||
import eth from "@tharsis/proto/dist/proto/ethermint/crypto/v1/ethsecp256k1/keys";
|
import eth from '@tharsis/proto/dist/proto/ethermint/crypto/v1/ethsecp256k1/keys'
|
||||||
|
|
||||||
import { Secp256k1 } from "@cosmjs/crypto"
|
import EthCrypto from 'eth-crypto'
|
||||||
import EthCrypto from "eth-crypto"
|
import {
|
||||||
import { MessageTypeProperty, SignTypedDataVersion, TypedDataUtils, TypedMessage, MessageTypes } from "@metamask/eth-sig-util";
|
MessageTypeProperty, SignTypedDataVersion, TypedDataUtils,
|
||||||
import { EIPToSign } from "@tharsis/transactions";
|
} from '@metamask/eth-sig-util'
|
||||||
// import { recoverPublicKey } from "@metamask/eth-sig-util/dist/utils";
|
import { EIPToSign } from '@tharsis/transactions'
|
||||||
// export type Algo = "secp256k1" | "ed25519" | "sr25519" | "ethsecp256k1";
|
|
||||||
// export interface AccountData {
|
|
||||||
// /** A printable address (typically bech32 encoded) */
|
|
||||||
// readonly address: string;
|
|
||||||
// readonly algo: Algo;
|
|
||||||
// readonly pubkey: Uint8Array;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
function goEthAddress(address) {
|
||||||
|
return `0x${toHex(fromBech32(address).data)}`
|
||||||
|
}
|
||||||
|
|
||||||
export class EthereumLedgerSigner implements OfflineAminoSigner{
|
function toPubkey(keyBytes: Uint8Array): Pubkey {
|
||||||
|
return {
|
||||||
|
type: 'ethermint.crypto.v1.ethsecp256k1.PubKey',
|
||||||
|
value: new eth.ethermint.crypto.v1.ethsecp256k1.PubKey({
|
||||||
|
key: keyBytes,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class EthereumLedgerSigner implements OfflineAminoSigner {
|
||||||
app: Eth
|
app: Eth
|
||||||
hdpath: string = "44'/60'/0'/0/0"
|
|
||||||
prefix: string = "evmos"
|
|
||||||
|
|
||||||
static async create(protocol: string, hdpath: HdPath, scrambleKey = "w0w", loadConfig?: LoadConfig): Promise<EthereumLedgerSigner> {
|
hdpath = "44'/60'/0'/0/0"
|
||||||
let transport: Promise<Transport> = protocol === 'ledgerBle' ? TransportWebBLE.create() : TransportWebUSB.create()
|
|
||||||
|
prefix = 'evmos'
|
||||||
|
|
||||||
|
static async create(protocol: string, hdpath: HdPath, loadConfig?: LoadConfig, scrambleKey = 'w0w'): Promise<EthereumLedgerSigner> {
|
||||||
|
const transport: Promise<Transport> = protocol === 'ledgerBle' ? TransportWebBLE.create() : TransportWebUSB.create()
|
||||||
return transport.then(t => {
|
return transport.then(t => {
|
||||||
let instance = new EthereumLedgerSigner()
|
const instance = new EthereumLedgerSigner()
|
||||||
instance.hdpath = pathToString(hdpath).replace('m/', '').replace('/60/', "/60'/")
|
instance.hdpath = pathToString(hdpath).replace('m/', '').replace('/60/', "/60'/")
|
||||||
instance.app = new Eth(t, scrambleKey, loadConfig)
|
instance.app = new Eth(t, scrambleKey, loadConfig)
|
||||||
return instance
|
return instance
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getAccounts(): Promise<readonly AccountData[]> {
|
public async getAccounts(): Promise<readonly AccountData[]> {
|
||||||
return this.app.getAddress(this.hdpath).then(x => {
|
return this.app.getAddress(this.hdpath).then(x => {
|
||||||
const x1: AccountData = {
|
const x1: AccountData = {
|
||||||
pubkey: fromHex(EthCrypto.publicKey.compress(x.publicKey)),
|
pubkey: fromHex(EthCrypto.publicKey.compress(x.publicKey)),
|
||||||
address: x.address,
|
address: x.address,
|
||||||
algo: "secp256k1" // should be 'ethsecp256k1'
|
algo: 'secp256k1', // should be 'ethsecp256k1'
|
||||||
}
|
}
|
||||||
const x2: AccountData = {
|
const x2: AccountData = {
|
||||||
pubkey: fromHex(EthCrypto.publicKey.compress(x.publicKey)),
|
pubkey: fromHex(EthCrypto.publicKey.compress(x.publicKey)),
|
||||||
address: toBech32(this.prefix, fromBech32(ethToEvmos(x.address)).data),
|
address: toBech32(this.prefix, fromBech32(ethToEvmos(x.address)).data),
|
||||||
algo: "secp256k1" // should be 'ethsecp256k1'
|
algo: 'secp256k1', // should be 'ethsecp256k1'
|
||||||
}
|
}
|
||||||
return [x2, x1]
|
return [x2, x1]
|
||||||
}).catch(e=> {
|
}).catch(e => {
|
||||||
if(e.toString().indexOf('0x6b0c')> 0) {
|
if (e.toString().indexOf('0x6b0c') > 0) {
|
||||||
throw new Error('Please unlock your Ledger first')
|
throw new Error('Please unlock your Ledger first')
|
||||||
}
|
}
|
||||||
if(e.toString().indexOf('0x6e00')> 0) {
|
if (e.toString().indexOf('0x6e00') > 0) {
|
||||||
throw new Error('Please open Ethereum app on the Ledger!')
|
throw new Error('Please open Ethereum app on the Ledger!')
|
||||||
}
|
}
|
||||||
if(e.toString().indexOf('0x6511')> 0) {
|
if (e.toString().indexOf('0x6511') > 0) {
|
||||||
throw new Error('Please open Ethereum app on the Ledger!')
|
throw new Error('Please open Ethereum app on the Ledger!')
|
||||||
}
|
}
|
||||||
throw e
|
throw e
|
||||||
})
|
})
|
||||||
};
|
|
||||||
|
|
||||||
goEthAddress(address) {
|
|
||||||
return `0x${toHex(fromBech32(address).data)}`
|
|
||||||
}
|
|
||||||
|
|
||||||
toPubkey(keyBytes: Uint8Array): Pubkey {
|
|
||||||
return {
|
|
||||||
"type": "ethermint.crypto.v1.ethsecp256k1.PubKey",
|
|
||||||
value: new eth.ethermint.crypto.v1.ethsecp256k1.PubKey({
|
|
||||||
key: keyBytes,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async signAmino(signerAddress: string, signDoc: StdSignDoc): Promise<AminoSignResponse> {
|
public async signAmino(signerAddress: string, signDoc: StdSignDoc): Promise<AminoSignResponse> {
|
||||||
const ethAddr = this.goEthAddress(signerAddress)
|
const ethAddr = goEthAddress(signerAddress)
|
||||||
return this.getAccounts().then(list => {
|
return this.getAccounts().then(list => {
|
||||||
const acc = list.find(x => x.address === ethAddr)
|
const acc = list.find(x => x.address === ethAddr)
|
||||||
if (acc) {
|
if (acc) {
|
||||||
const messageHex: string = toHex(new TextEncoder().encode(JSON.stringify(signDoc)))
|
const messageHex: string = toHex(new TextEncoder().encode(JSON.stringify(signDoc)))
|
||||||
this.app.signPersonalMessage(this.hdpath, messageHex).then(result => {
|
this.app.signPersonalMessage(this.hdpath, messageHex).then(result => {
|
||||||
const signature: StdSignature = {
|
const signature: StdSignature = {
|
||||||
pub_key: this.toPubkey(acc.pubkey),
|
pub_key: toPubkey(acc.pubkey),
|
||||||
signature: result['s']
|
signature: result.s,
|
||||||
}
|
}
|
||||||
const output: AminoSignResponse = {
|
const output: AminoSignResponse = {
|
||||||
signed: signDoc,
|
signed: signDoc,
|
||||||
signature
|
signature,
|
||||||
}
|
}
|
||||||
return output
|
return output
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
throw new Error('Account Does not exists!')
|
throw new Error('Account Does not exists!')
|
||||||
})
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
// async showAddress(path?: HdPath): Promise<AddressAndPubkey> {
|
async sign712(eipToSign: EIPToSign) {
|
||||||
// return new Promise((r, j) => { })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async signTransaction(rawTxHex: string, resolution?: LedgerEthTransactionResolution) {
|
|
||||||
// return this.app.signPersonalMessage(this.hdpath, rawTxHex)
|
|
||||||
// }
|
|
||||||
|
|
||||||
async sign712( eipToSign: EIPToSign ) {
|
|
||||||
|
|
||||||
/// sign typed struct
|
/// sign typed struct
|
||||||
const types = eipToSign.types as Record<string, MessageTypeProperty[]>
|
const types = eipToSign.types as Record<string, MessageTypeProperty[]>
|
||||||
const domainSeparatorHex = TypedDataUtils.hashStruct('EIP712Domain', eipToSign.domain, types, SignTypedDataVersion.V4).toString('hex')
|
const domainSeparatorHex = TypedDataUtils.hashStruct('EIP712Domain', eipToSign.domain, types, SignTypedDataVersion.V4).toString('hex')
|
||||||
@ -120,11 +109,11 @@ export class EthereumLedgerSigner implements OfflineAminoSigner{
|
|||||||
const hashStructMessageHex = toHex(keccak256(TypedDataUtils.encodeData('Tx', eipToSign.message as Record<string, unknown>, types, SignTypedDataVersion.V4)))
|
const hashStructMessageHex = toHex(keccak256(TypedDataUtils.encodeData('Tx', eipToSign.message as Record<string, unknown>, types, SignTypedDataVersion.V4)))
|
||||||
// console.log('hex2:', hashStructMessageHex)
|
// console.log('hex2:', hashStructMessageHex)
|
||||||
const signature = await this.app.signEIP712HashedMessage(this.hdpath, domainSeparatorHex, hashStructMessageHex)
|
const signature = await this.app.signEIP712HashedMessage(this.hdpath, domainSeparatorHex, hashStructMessageHex)
|
||||||
let v: string = (signature.v - 27).toString(16);
|
let v: string = (signature.v - 27).toString(16)
|
||||||
if (v.length < 2) {
|
if (v.length < 2) {
|
||||||
v = "0" + v;
|
v = `0${v}`
|
||||||
}
|
}
|
||||||
const sig = "0x"+signature.r + signature.s + v
|
const sig = `0x${signature.r}${signature.s}${v}`
|
||||||
|
|
||||||
return sig
|
return sig
|
||||||
}
|
}
|
||||||
|
@ -1,260 +1,222 @@
|
|||||||
import {
|
import {
|
||||||
AminoTypes,
|
AminoTypes,
|
||||||
SignerData,
|
SignerData,
|
||||||
SigningStargateClient,
|
SigningStargateClient,
|
||||||
defaultRegistryTypes,
|
AminoConverters,
|
||||||
} from '@cosmjs/stargate';
|
createAuthzAminoConverters,
|
||||||
import { Registry, EncodeObject, TxBodyEncodeObject, makeAuthInfoBytes, GeneratedType } from '@cosmjs/proto-signing';
|
createBankAminoConverters,
|
||||||
import { LedgerSigner } from '@cosmjs/ledger-amino';
|
createDistributionAminoConverters,
|
||||||
import { EthereumLedgerSigner } from './EthereumLedgerSigner';
|
createFreegrantAminoConverters,
|
||||||
import TransportWebUSB from '@ledgerhq/hw-transport-webusb';
|
createGovAminoConverters,
|
||||||
|
createIbcAminoConverters,
|
||||||
|
createStakingAminoConverters,
|
||||||
|
} from '@cosmjs/stargate'
|
||||||
|
import {
|
||||||
|
EncodeObject, TxBodyEncodeObject, makeAuthInfoBytes,
|
||||||
|
} from '@cosmjs/proto-signing'
|
||||||
|
import { LedgerSigner } from '@cosmjs/ledger-amino'
|
||||||
|
import TransportWebUSB from '@ledgerhq/hw-transport-webusb'
|
||||||
import TransportWebBLE from '@ledgerhq/hw-transport-web-ble'
|
import TransportWebBLE from '@ledgerhq/hw-transport-web-ble'
|
||||||
import { makeSignDoc, OfflineAminoSigner, Pubkey, pubkeyType, StdFee } from "@cosmjs/amino";
|
|
||||||
import { TxBody, TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";
|
|
||||||
import {
|
import {
|
||||||
generateMessageWithMultipleTransactions,
|
StdFee,
|
||||||
MSG_WITHDRAW_DELEGATOR_REWARD_TYPES,
|
} from '@cosmjs/amino'
|
||||||
IBC_MSG_TRANSFER_TYPES,
|
import { TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx'
|
||||||
generateTypes,
|
|
||||||
generateFee,
|
|
||||||
createEIP712,
|
|
||||||
} from "@tharsis/eip712"
|
|
||||||
import {
|
import {
|
||||||
createTxRawEIP712, signatureToWeb3Extension, Chain,
|
generateMessageWithMultipleTransactions,
|
||||||
createMessageSend, createTxMsgWithdrawDelegatorReward, Fee, MsgWithdrawDelegatorRewardParams,
|
generateTypes,
|
||||||
createTxMsgMultipleWithdrawDelegatorReward,
|
generateFee,
|
||||||
MsgMultipleWithdrawDelegatorRewardParams,
|
createEIP712,
|
||||||
EIPToSign,
|
} from '@tharsis/eip712'
|
||||||
|
import {
|
||||||
|
createTxRawEIP712, signatureToWeb3Extension, Chain,
|
||||||
} from '@tharsis/transactions'
|
} from '@tharsis/transactions'
|
||||||
import {
|
|
||||||
createTransactionWithMultipleMessages,
|
|
||||||
createMsgWithdrawDelegatorReward,
|
|
||||||
createIBCMsgTransfer
|
|
||||||
} from '@tharsis/proto'
|
|
||||||
import { fromBase64, fromBech32, fromHex, toBase64, toHex } from '@cosmjs/encoding';
|
|
||||||
//import { generateEndpointBroadcast, generatePostBodyBroadcast } from '@tharsis/provider'
|
|
||||||
import { keccak256, Secp256k1 } from "@cosmjs/crypto"
|
|
||||||
import { SignMode } from 'cosmjs-types/cosmos/tx/signing/v1beta1/signing';
|
|
||||||
import { MessageTypeProperty, MessageTypes, SignTypedDataVersion, TypedDataUtils, TypedMessage, } from '@metamask/eth-sig-util'
|
|
||||||
import MetaMaskSigner from './MetaMaskSigner.js'
|
|
||||||
import * as eth from '@tharsis/proto/dist/proto/ethermint/crypto/v1/ethsecp256k1/keys' // /ethermint/crypto/v1/ethsecp256k1/keys'
|
|
||||||
import {
|
import {
|
||||||
AminoConverters,
|
createTransactionWithMultipleMessages,
|
||||||
createAuthzAminoConverters,
|
} from '@tharsis/proto'
|
||||||
createBankAminoConverters,
|
import {
|
||||||
createDistributionAminoConverters,
|
fromBase64, fromBech32, fromHex, toBase64,
|
||||||
createFreegrantAminoConverters,
|
} from '@cosmjs/encoding'
|
||||||
createGovAminoConverters,
|
// import { generateEndpointBroadcast, generatePostBodyBroadcast } from '@tharsis/provider'
|
||||||
createIbcAminoConverters,
|
import { SignMode } from 'cosmjs-types/cosmos/tx/signing/v1beta1/signing'
|
||||||
createStakingAminoConverters,
|
import * as eth from '@tharsis/proto/dist/proto/ethermint/crypto/v1/ethsecp256k1/keys' // /ethermint/crypto/v1/ethsecp256k1/keys'
|
||||||
} from "@cosmjs/stargate"
|
import { PubKey } from 'cosmjs-types/cosmos/crypto/secp256k1/keys'
|
||||||
import { Int53 } from '@cosmjs/math';
|
import { Int53 } from '@cosmjs/math'
|
||||||
import { Any } from 'cosmjs-types/google/protobuf/any';
|
import { Any } from 'cosmjs-types/google/protobuf/any'
|
||||||
import { legacyToBuffer, recoverPublicKey } from '@metamask/eth-sig-util/dist/utils';
|
import EthereumLedgerSigner from './EthereumLedgerSigner'
|
||||||
import { utils } from 'ethers'
|
import { defaultMessageAdapter } from './MessageAdapter'
|
||||||
import { signatureToPubkey } from '@hanchon/signature-to-pubkey'
|
|
||||||
import { defaultMessageAdapter } from './MessageAdapter';
|
|
||||||
|
|
||||||
export interface TypedDataField {
|
export interface TypedDataField {
|
||||||
name: string;
|
name: string;
|
||||||
type: string;
|
type: string;
|
||||||
};
|
|
||||||
|
|
||||||
export declare type SigningClient = SigningStargateClient | SigningEthermintClient;
|
|
||||||
|
|
||||||
export async function getSigningClient(device, hdpath): Promise<SigningClient> {
|
|
||||||
let ledgerAppName = 'Cosmos'
|
|
||||||
let coinType = Number(hdpath[1])
|
|
||||||
switch (coinType) {
|
|
||||||
case 60:
|
|
||||||
return new SigningEthermintClient(await EthereumLedgerSigner.create(device, hdpath)) // 'Ethereum'
|
|
||||||
case 529:
|
|
||||||
ledgerAppName = 'Secret' // 'Secret'
|
|
||||||
break
|
|
||||||
case 852:
|
|
||||||
ledgerAppName = 'Desmos' // 'Desmos'
|
|
||||||
break
|
|
||||||
case 118:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
const transport = await (device === 'ledgerBle' ? TransportWebBLE.create() : TransportWebUSB.create())
|
|
||||||
const signer = new LedgerSigner(transport, { hdPaths: [hdpath], ledgerAppName })
|
|
||||||
return SigningStargateClient.offline(signer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createDefaultTypes(prefix: string): AminoConverters {
|
function createDefaultTypes(prefix: string): AminoConverters {
|
||||||
return {
|
return {
|
||||||
...createAuthzAminoConverters(),
|
...createAuthzAminoConverters(),
|
||||||
...createBankAminoConverters(),
|
...createBankAminoConverters(),
|
||||||
...createDistributionAminoConverters(),
|
...createDistributionAminoConverters(),
|
||||||
...createGovAminoConverters(),
|
...createGovAminoConverters(),
|
||||||
...createStakingAminoConverters(prefix),
|
...createStakingAminoConverters(prefix),
|
||||||
...createIbcAminoConverters(),
|
...createIbcAminoConverters(),
|
||||||
...createFreegrantAminoConverters(),
|
...createFreegrantAminoConverters(),
|
||||||
// ...createVestingAminoConverters(),
|
// ...createVestingAminoConverters(),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractChainId(chainId: string) {
|
function extractChainId(chainId: string) {
|
||||||
const start = chainId.indexOf('_')
|
const start = chainId.indexOf('_')
|
||||||
const end = chainId.indexOf('-')
|
const end = chainId.indexOf('-')
|
||||||
if (end > start && start > 0) {
|
if (end > start && start > 0) {
|
||||||
return Number(chainId.substring(start + 1, end))
|
return Number(chainId.substring(start + 1, end))
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
|
||||||
export class SigningEthermintClient {
|
|
||||||
readonly signer: EthereumLedgerSigner
|
|
||||||
aminoTypes: AminoTypes
|
|
||||||
constructor(signer: EthereumLedgerSigner) {
|
|
||||||
this.signer = signer
|
|
||||||
this.aminoTypes = new AminoTypes(createDefaultTypes(""))
|
|
||||||
}
|
|
||||||
|
|
||||||
// async signEVM(signerAddress: string, messages: readonly EncodeObject[], stdfee: StdFee, memo: string, explicitSignerData?: SignerData): Promise<Uint8Array> {
|
|
||||||
// const chain: Chain = {
|
|
||||||
// chainId: extractChainId(explicitSignerData.chainId),
|
|
||||||
// cosmosChainId: explicitSignerData.chainId
|
|
||||||
// }
|
|
||||||
// this.signer.prefix = fromBech32(signerAddress).prefix
|
|
||||||
// const account = await this.signer.getAccounts()
|
|
||||||
|
|
||||||
// const sender = {
|
|
||||||
// accountAddress: signerAddress,
|
|
||||||
// sequence: explicitSignerData.sequence,
|
|
||||||
// accountNumber: explicitSignerData.accountNumber,
|
|
||||||
// pubkey: toBase64(account[0].pubkey),
|
|
||||||
// }
|
|
||||||
// const fee = {
|
|
||||||
// amount: stdfee.amount[0].amount,
|
|
||||||
// denom: stdfee.amount[0].denom,
|
|
||||||
// gas: stdfee.gas,
|
|
||||||
// }
|
|
||||||
// const validatorAddresses = messages.map(x => x.value.validatorAddress)
|
|
||||||
|
|
||||||
// let param: MsgMultipleWithdrawDelegatorRewardParams = {
|
|
||||||
// validatorAddresses
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const msgs = createTxMsgMultipleWithdrawDelegatorReward(chain, sender, fee, memo, param)
|
|
||||||
// const sig = await this.signer.sign712(msgs.eipToSign)
|
|
||||||
|
|
||||||
// let extension = signatureToWeb3Extension(chain, sender, sig)
|
|
||||||
|
|
||||||
// // Create the txRaw
|
|
||||||
// let prototx = createTxRawEIP712(msgs.legacyAmino.body, msgs.legacyAmino.authInfo, extension)
|
|
||||||
// return Promise.resolve(prototx.message.serializeBinary())
|
|
||||||
// }
|
|
||||||
|
|
||||||
async sign(signerAddress: string, messages: readonly EncodeObject[], fee: StdFee, memo: string, explicitSignerData?: SignerData): Promise<Uint8Array> {
|
|
||||||
|
|
||||||
const chain: Chain = {
|
|
||||||
chainId: extractChainId(explicitSignerData.chainId),
|
|
||||||
cosmosChainId: explicitSignerData.chainId
|
|
||||||
}
|
|
||||||
|
|
||||||
this.signer.prefix = fromBech32(signerAddress).prefix
|
|
||||||
const account = await this.signer.getAccounts()
|
|
||||||
|
|
||||||
const acc = account.find(x => x.address === signerAddress)
|
|
||||||
if(!acc) {
|
|
||||||
throw new Error('The signer address dose not exsits in Ledger!')
|
|
||||||
}
|
|
||||||
const sender = {
|
|
||||||
accountAddress: signerAddress,
|
|
||||||
sequence: explicitSignerData.sequence,
|
|
||||||
accountNumber: explicitSignerData.accountNumber,
|
|
||||||
pubkey: toBase64(account[0].pubkey),
|
|
||||||
}
|
|
||||||
|
|
||||||
let fees = generateFee(fee.amount[0].amount, fee.amount[0].denom, fee.gas, signerAddress)
|
|
||||||
|
|
||||||
const msgs = messages.map(x => this.aminoTypes.toAmino(x))
|
|
||||||
const tx = generateMessageWithMultipleTransactions(
|
|
||||||
sender.accountNumber.toString(),
|
|
||||||
sender.sequence.toString(),
|
|
||||||
explicitSignerData.chainId,
|
|
||||||
memo,
|
|
||||||
fees,
|
|
||||||
msgs,
|
|
||||||
)
|
|
||||||
|
|
||||||
const types = generateTypes(defaultMessageAdapter[messages[0].typeUrl].getTypes())
|
|
||||||
const eip = createEIP712(types, chain.chainId, tx )
|
|
||||||
const sig = await this.signer.sign712(eip)
|
|
||||||
|
|
||||||
const rawTx = makeRawTxEvmos(sender, messages, memo, fee, sig, chain)
|
|
||||||
|
|
||||||
return Promise.resolve(rawTx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeRawTxEvmos(sender, messages, memo, fee, signature, chain): Uint8Array {
|
function makeRawTxEvmos(sender, messages, memo, fee, signature, chain): Uint8Array {
|
||||||
/// evmos style
|
/// evmos style
|
||||||
///*
|
/// *
|
||||||
const protoMsgs = messages.map(x => {
|
const protoMsgs = messages.map(x => {
|
||||||
const adapter = defaultMessageAdapter[x.typeUrl]
|
const adapter = defaultMessageAdapter[x.typeUrl]
|
||||||
return adapter.toProto(x)
|
return adapter.toProto(x)
|
||||||
})
|
})
|
||||||
|
|
||||||
const evmos = createTransactionWithMultipleMessages(
|
const evmos = createTransactionWithMultipleMessages(
|
||||||
protoMsgs,
|
protoMsgs,
|
||||||
memo,
|
memo,
|
||||||
fee.amount[0].amount,
|
fee.amount[0].amount,
|
||||||
fee.amount[0].denom,
|
fee.amount[0].denom,
|
||||||
Number(fee.gas),
|
Number(fee.gas),
|
||||||
'ethsecp256',
|
'ethsecp256',
|
||||||
sender.pubkey,
|
sender.pubkey,
|
||||||
sender.sequence,
|
sender.sequence,
|
||||||
sender.accountNumber,
|
sender.accountNumber,
|
||||||
chain.cosmosChainId
|
chain.cosmosChainId,
|
||||||
|
)
|
||||||
|
|
||||||
|
const extension = signatureToWeb3Extension(chain, sender, signature)
|
||||||
|
|
||||||
|
// Create the txRaw
|
||||||
|
const prototx = createTxRawEIP712(evmos.legacyAmino.body, evmos.legacyAmino.authInfo, extension)
|
||||||
|
return prototx.message.serializeBinary()
|
||||||
|
/// end of EVMOS style */
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SigningEthermintClient {
|
||||||
|
readonly signer: EthereumLedgerSigner
|
||||||
|
|
||||||
|
aminoTypes: AminoTypes
|
||||||
|
|
||||||
|
constructor(signer: EthereumLedgerSigner) {
|
||||||
|
this.signer = signer
|
||||||
|
this.aminoTypes = new AminoTypes(createDefaultTypes(''))
|
||||||
|
}
|
||||||
|
|
||||||
|
async sign(signerAddress: string, messages: readonly EncodeObject[], fee: StdFee, memo: string, explicitSignerData?: SignerData): Promise<Uint8Array> {
|
||||||
|
const chain: Chain = {
|
||||||
|
chainId: extractChainId(explicitSignerData.chainId),
|
||||||
|
cosmosChainId: explicitSignerData.chainId,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.signer.prefix = fromBech32(signerAddress).prefix
|
||||||
|
const account = await this.signer.getAccounts()
|
||||||
|
|
||||||
|
const acc = account.find(x => x.address === signerAddress)
|
||||||
|
if (!acc) {
|
||||||
|
throw new Error('The signer address dose not exsits in Ledger!')
|
||||||
|
}
|
||||||
|
const sender = {
|
||||||
|
accountAddress: signerAddress,
|
||||||
|
sequence: explicitSignerData.sequence,
|
||||||
|
accountNumber: explicitSignerData.accountNumber,
|
||||||
|
pubkey: toBase64(account[0].pubkey),
|
||||||
|
}
|
||||||
|
|
||||||
|
const fees = generateFee(fee.amount[0].amount, fee.amount[0].denom, fee.gas, signerAddress)
|
||||||
|
|
||||||
|
const msgs = messages.map(x => this.aminoTypes.toAmino(x))
|
||||||
|
const tx = generateMessageWithMultipleTransactions(
|
||||||
|
sender.accountNumber.toString(),
|
||||||
|
sender.sequence.toString(),
|
||||||
|
explicitSignerData.chainId,
|
||||||
|
memo,
|
||||||
|
fees,
|
||||||
|
msgs,
|
||||||
)
|
)
|
||||||
|
|
||||||
let extension = signatureToWeb3Extension(chain, sender, signature)
|
const types = generateTypes(defaultMessageAdapter[messages[0].typeUrl].getTypes())
|
||||||
|
const eip = createEIP712(types, chain.chainId, tx)
|
||||||
|
const sig = await this.signer.sign712(eip)
|
||||||
|
|
||||||
// Create the txRaw
|
const rawTx = makeRawTxEvmos(sender, messages, memo, fee, sig, chain)
|
||||||
let prototx = createTxRawEIP712(evmos.legacyAmino.body, evmos.legacyAmino.authInfo, extension)
|
|
||||||
return prototx.message.serializeBinary()
|
return Promise.resolve(rawTx)
|
||||||
/// end of EVMOS style */
|
}
|
||||||
|
}
|
||||||
|
export function encodePubkey(pubkey: string): Any {
|
||||||
|
// const value = new eth.ethermint.crypto.v1.ethsecp256k1.PubKey({ key: fromBase64(pubkey) })
|
||||||
|
// return Any.fromPartial({
|
||||||
|
// typeUrl: '/ethermint.crypto.v1.ethsecp256k1.PubKey',
|
||||||
|
// value: value.serializeBinary(),
|
||||||
|
// })
|
||||||
|
return Any.fromPartial({
|
||||||
|
typeUrl: '/ethermint.crypto.v1.ethsecp256k1.PubKey',
|
||||||
|
value: PubKey.encode({
|
||||||
|
key: fromBase64(pubkey),
|
||||||
|
}).finish(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeRawTx(sender, messages, memo, fee, signature, registry): TxRaw {
|
function makeRawTx(sender, messages, memo, fee, signature, registry): TxRaw {
|
||||||
const pubkey = encodePubkey(sender.pubkey);
|
const pubkey = encodePubkey(sender.pubkey)
|
||||||
|
|
||||||
const signedTxBody = {
|
const signedTxBody = {
|
||||||
messages,
|
messages,
|
||||||
memo,
|
memo,
|
||||||
};
|
}
|
||||||
const signedTxBodyEncodeObject: TxBodyEncodeObject = {
|
const signedTxBodyEncodeObject: TxBodyEncodeObject = {
|
||||||
typeUrl: "/cosmos.tx.v1beta1.TxBody",
|
typeUrl: '/cosmos.tx.v1beta1.TxBody',
|
||||||
value: signedTxBody,
|
value: signedTxBody,
|
||||||
};
|
}
|
||||||
const signedTxBodyBytes = registry.encode(signedTxBodyEncodeObject);
|
const signedTxBodyBytes = registry.encode(signedTxBodyEncodeObject)
|
||||||
const signedGasLimit = Int53.fromString(fee.gas).toNumber();
|
const signedGasLimit = Int53.fromString(fee.gas).toNumber()
|
||||||
const signedSequence = sender.sequence;
|
// const signedSequence = sender.sequence
|
||||||
const signedAuthInfoBytes = makeAuthInfoBytes(
|
const signedAuthInfoBytes = makeAuthInfoBytes(
|
||||||
[{ pubkey, sequence: sender.sequence }],
|
[{ pubkey, sequence: sender.sequence }],
|
||||||
fee.amount,
|
fee.amount,
|
||||||
signedGasLimit,
|
signedGasLimit,
|
||||||
SignMode.SIGN_MODE_LEGACY_AMINO_JSON,
|
SignMode.SIGN_MODE_LEGACY_AMINO_JSON,
|
||||||
);
|
)
|
||||||
const rawTx = TxRaw.fromPartial({
|
const rawTx = TxRaw.fromPartial({
|
||||||
bodyBytes: signedTxBodyBytes,
|
bodyBytes: signedTxBodyBytes,
|
||||||
authInfoBytes: signedAuthInfoBytes,
|
authInfoBytes: signedAuthInfoBytes,
|
||||||
signatures: [fromHex(signature)],
|
signatures: [fromHex(signature)],
|
||||||
});
|
})
|
||||||
|
|
||||||
return rawTx
|
return rawTx
|
||||||
}
|
|
||||||
|
|
||||||
export function encodePubkey(pubkey: string): Any {
|
|
||||||
const value = new eth.ethermint.crypto.v1.ethsecp256k1.PubKey({ key: fromBase64(pubkey) })
|
|
||||||
return Any.fromPartial({
|
|
||||||
typeUrl: "/ethermint.crypto.v1.ethsecp256k1.PubKey",
|
|
||||||
value: value.serializeBinary(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// export function createAnyMessage(messages: readonly EncodeObject[]) {
|
// export function createAnyMessage(messages: readonly EncodeObject[]) {
|
||||||
// return messages.map(x => x.)
|
// return messages.map(x => x.)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
export declare type SigningClient = SigningStargateClient | SigningEthermintClient;
|
||||||
|
|
||||||
|
export async function getSigningClient(device, hdpath): Promise<SigningClient> {
|
||||||
|
let ledgerAppName = 'Cosmos'
|
||||||
|
const coinType = Number(hdpath[1])
|
||||||
|
switch (coinType) {
|
||||||
|
case 60:
|
||||||
|
return new SigningEthermintClient(await EthereumLedgerSigner.create(device, hdpath)) // 'Ethereum'
|
||||||
|
case 529:
|
||||||
|
ledgerAppName = 'Secret' // 'Secret'
|
||||||
|
break
|
||||||
|
case 852:
|
||||||
|
ledgerAppName = 'Desmos' // 'Desmos'
|
||||||
|
break
|
||||||
|
case 118:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
const transport = await (device === 'ledgerBle' ? TransportWebBLE.create() : TransportWebUSB.create())
|
||||||
|
const signer = new LedgerSigner(transport, { hdPaths: [hdpath], ledgerAppName })
|
||||||
|
return SigningStargateClient.offline(signer)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user