-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
337 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { isOfflineAminoSigner, isOfflineDirectSigner, OfflineSigner } from "@interchainjs/cosmos/types/wallet"; | ||
import { HttpEndpoint } from "@interchainjs/types"; | ||
import { SigningClient } from "interchainjs/signing-client" | ||
import { SignerOptions } from "interchainjs/types/signing-client"; | ||
import { RpcClient } from '@interchainjs/cosmos/query/rpc'; | ||
import { AminoSigner } from "./signers/amino"; | ||
import { DirectSigner } from "./signers/direct"; | ||
|
||
/** | ||
* signingClient for inj | ||
*/ | ||
export class InjSigningClient extends SigningClient { | ||
static async connectWithSigner( | ||
endpoint: string | HttpEndpoint, | ||
signer: OfflineSigner, | ||
options: SignerOptions = {} | ||
): Promise<InjSigningClient> { | ||
const signingClient = new InjSigningClient( | ||
new RpcClient(endpoint, options.prefix), | ||
signer, | ||
options | ||
); | ||
|
||
await signingClient.connect(); | ||
|
||
return signingClient; | ||
} | ||
|
||
override async connect() { | ||
if (isOfflineAminoSigner(this.offlineSigner)) { | ||
const aminoSigners = await AminoSigner.fromWalletToSigners( | ||
this.offlineSigner, | ||
this.encoders, | ||
this.converters, | ||
this.endpoint, | ||
{ | ||
prefix: this.options.prefix, | ||
} | ||
); | ||
|
||
for (const signer of aminoSigners) { | ||
this.aminoSigners[await signer.getAddress()] = signer; | ||
} | ||
} | ||
|
||
if (isOfflineDirectSigner(this.offlineSigner)) { | ||
const directSigners = await DirectSigner.fromWalletToSigners( | ||
this.offlineSigner, | ||
this.encoders, | ||
this.endpoint, | ||
{ | ||
prefix: this.options.prefix, | ||
} | ||
); | ||
|
||
for (const signer of directSigners) { | ||
this.directSigners[await signer.getAddress()] = signer; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
import { EthSecp256k1Auth } from '@interchainjs/auth/ethSecp256k1'; | ||
import { AccountData, AddrDerivation, Auth, SignerConfig } from '@interchainjs/types'; | ||
|
||
import { AminoDocSigner } from '../signers/amino'; | ||
import { defaultSignerOptions } from '../defaults'; | ||
import { DirectDocSigner } from '../signers/direct'; | ||
import { | ||
CosmosAccount, | ||
CosmosAminoDoc, | ||
CosmosDirectDoc, | ||
ICosmosAccount, | ||
ICosmosWallet, | ||
} from '@interchainjs/cosmos/types'; | ||
import { | ||
AminoSignResponse, | ||
DirectSignResponse, | ||
OfflineAminoSigner, | ||
OfflineDirectSigner, | ||
WalletOptions, | ||
} from '@interchainjs/cosmos/types/wallet'; | ||
import { InjAccount } from '../accounts/inj-account'; | ||
|
||
/** | ||
* Cosmos HD Wallet for secp256k1 | ||
*/ | ||
export class EthSecp256k1HDWallet | ||
implements ICosmosWallet, OfflineAminoSigner, OfflineDirectSigner | ||
{ | ||
constructor( | ||
public accounts: ICosmosAccount[], | ||
public options: SignerConfig | ||
) { | ||
this.options = { ...defaultSignerOptions.Cosmos, ...options }; | ||
} | ||
|
||
/** | ||
* Create a new HD wallet from mnemonic | ||
* @param mnemonic | ||
* @param derivations infos for derivate addresses | ||
* @param options wallet options | ||
* @returns HD wallet | ||
*/ | ||
static fromMnemonic( | ||
mnemonic: string, | ||
derivations: AddrDerivation[], | ||
options?: WalletOptions | ||
) { | ||
const hdPaths = derivations.map((derivation) => derivation.hdPath); | ||
|
||
const auths: Auth[] = EthSecp256k1Auth.fromMnemonic(mnemonic, hdPaths, { | ||
bip39Password: options?.bip39Password, | ||
}); | ||
|
||
const accounts = auths.map((auth, i) => { | ||
const derivation = derivations[i]; | ||
return new InjAccount(derivation.prefix, auth); | ||
}); | ||
|
||
return new EthSecp256k1HDWallet(accounts, options?.signerConfig); | ||
} | ||
|
||
/** | ||
* Get account data | ||
* @returns account data | ||
*/ | ||
async getAccounts(): Promise<AccountData[]> { | ||
return this.accounts.map((acct) => { | ||
return acct.toAccountData(); | ||
}); | ||
} | ||
|
||
/** | ||
* Get one of the accounts using the address. | ||
* @param address | ||
* @returns | ||
*/ | ||
private getAcctFromBech32Addr(address: string) { | ||
const id = this.accounts.findIndex((acct) => acct.address === address); | ||
if (id === -1) { | ||
throw new Error('No such signerAddress been authed.'); | ||
} | ||
return this.accounts[id]; | ||
} | ||
|
||
/** | ||
* Sign direct doc for signerAddress | ||
*/ | ||
async signDirect( | ||
signerAddress: string, | ||
signDoc: CosmosDirectDoc | ||
): Promise<DirectSignResponse> { | ||
const account = this.getAcctFromBech32Addr(signerAddress); | ||
|
||
const docSigner = new DirectDocSigner(account.auth, this.options); | ||
|
||
const resp = await docSigner.signDoc(signDoc); | ||
|
||
return { | ||
signed: resp.signDoc, | ||
signature: { | ||
pub_key: { | ||
type: 'tendermint/PubKeySecp256k1', | ||
value: { | ||
key: account.publicKey.toBase64(), | ||
}, | ||
}, | ||
signature: resp.signature.toBase64(), | ||
}, | ||
}; | ||
} | ||
|
||
/** | ||
* sign amino doc for signerAddress | ||
*/ | ||
async signAmino( | ||
signerAddress: string, | ||
signDoc: CosmosAminoDoc | ||
): Promise<AminoSignResponse> { | ||
const account = this.getAcctFromBech32Addr(signerAddress); | ||
|
||
const docSigner = new AminoDocSigner(account.auth, this.options); | ||
|
||
const resp = await docSigner.signDoc(signDoc); | ||
|
||
return { | ||
signed: resp.signDoc, | ||
signature: { | ||
pub_key: { | ||
type: 'tendermint/PubKeySecp256k1', | ||
value: { | ||
key: account.publicKey.toBase64(), | ||
}, | ||
}, | ||
signature: resp.signature.toBase64(), | ||
}, | ||
}; | ||
} | ||
|
||
/** | ||
* Convert this to offline direct signer for hiding the private key. | ||
*/ | ||
toOfflineDirectSigner(): OfflineDirectSigner { | ||
return { | ||
getAccounts: async () => this.getAccounts(), | ||
signDirect: async (signerAddress: string, signDoc: CosmosDirectDoc) => | ||
this.signDirect(signerAddress, signDoc), | ||
}; | ||
} | ||
|
||
/** | ||
* Convert this to offline amino signer for hiding the private key. | ||
*/ | ||
toOfflineAminoSigner(): OfflineAminoSigner { | ||
return { | ||
getAccounts: async () => this.getAccounts(), | ||
signAmino: async (signerAddress: string, signDoc: CosmosAminoDoc) => | ||
this.signAmino(signerAddress, signDoc), | ||
}; | ||
} | ||
} |
Oops, something went wrong.