From fd126a4403d48795c6e1076e7d656f3de8e3091c Mon Sep 17 00:00:00 2001 From: Fabrice Bascoulergue Date: Thu, 2 Dec 2021 14:29:59 +0100 Subject: [PATCH 1/2] Update auto generated doc --- docs/lib/classes/lumclient.md | 2 +- docs/lib/classes/lumpaperwallet.md | 8 +-- docs/lib/classes/lumwalletfactory.md | 38 +++++++-------- docs/lib/interfaces/lumtypes.account.md | 42 ++++++++++++++++ docs/lib/interfaces/lumtypes.log.md | 2 +- docs/lib/modules/lummessages.md | 30 +++++++++++- docs/lib/modules/lumutils.md | 65 ++++++++++++++++++++++--- 7 files changed, 153 insertions(+), 34 deletions(-) diff --git a/docs/lib/classes/lumclient.md b/docs/lib/classes/lumclient.md index ac9d458..a861593 100644 --- a/docs/lib/classes/lumclient.md +++ b/docs/lib/classes/lumclient.md @@ -56,7 +56,7 @@ ___ ### queryClient -• `Readonly` **queryClient**: `QueryClient` & `AuthExtension` & `AuthzExtension` & `BankExtension` & `BeamExtension` & `DistributionExtension` & `GovExtension` & `IbcExtension` & `MintExtension` & `StakingExtension` & `SlashingExtension` & `FeegrantExtension` +• `Readonly` **queryClient**: `QueryClient` & `AuthExtension` & `AuthzExtension` & `BankExtension` & `BeamExtension` & `DistributionExtension` & `GovExtension` & `IbcExtension` & `MintExtension` & `StakingExtension` & `SlashingExtension` & `FeegrantExtension` & `AirdropExtension` ___ diff --git a/docs/lib/classes/lumpaperwallet.md b/docs/lib/classes/lumpaperwallet.md index c4def32..87f8a80 100644 --- a/docs/lib/classes/lumpaperwallet.md +++ b/docs/lib/classes/lumpaperwallet.md @@ -233,10 +233,10 @@ Change the wallet to use #### Parameters -| Name | Type | -| :------ | :------ | -| `hdPath` | `string` | -| `addressPrefix` | `string` | +| Name | Type | Default value | +| :------ | :------ | :------ | +| `hdPath` | `string` | `undefined` | +| `addressPrefix` | `string` | `LumConstants.LumBech32PrefixAccAddr` | #### Returns diff --git a/docs/lib/classes/lumwalletfactory.md b/docs/lib/classes/lumwalletfactory.md index df257ee..1deb755 100644 --- a/docs/lib/classes/lumwalletfactory.md +++ b/docs/lib/classes/lumwalletfactory.md @@ -30,11 +30,11 @@ Create a LumWallet instance based on a keystore #### Parameters -| Name | Type | Description | -| :------ | :------ | :------ | -| `keystore` | `string` \| [`KeyStore`](../interfaces/LumUtils.KeyStore.md) | keystore used to decypher the private key | -| `password` | `string` | keystore password | -| `addressPrefix` | `string` | prefix to use to derive the address from the public key (ex: lum) | +| Name | Type | Default value | Description | +| :------ | :------ | :------ | :------ | +| `keystore` | `string` \| [`KeyStore`](../interfaces/LumUtils.KeyStore.md) | `undefined` | keystore used to decypher the private key | +| `password` | `string` | `undefined` | keystore password | +| `addressPrefix` | `string` | `LumConstants.LumBech32PrefixAccAddr` | prefix to use to derive the address from the public key (ex: lum) | #### Returns @@ -50,11 +50,11 @@ Create a LumWallet instance based on a ledger transport #### Parameters -| Name | Type | Description | -| :------ | :------ | :------ | -| `transport` | `default` | Ledger transport to use (https://github.com/LedgerHQ/ledgerjs) | -| `hdPath` | `string` | BIP44 derivation path | -| `addressPrefix` | `string` | prefix to use to derive the address from the public key (ex: lum) | +| Name | Type | Default value | Description | +| :------ | :------ | :------ | :------ | +| `transport` | `default` | `undefined` | Ledger transport to use (https://github.com/LedgerHQ/ledgerjs) | +| `hdPath` | `string` | `undefined` | BIP44 derivation path | +| `addressPrefix` | `string` | `LumConstants.LumBech32PrefixAccAddr` | prefix to use to derive the address from the public key (ex: lum) | #### Returns @@ -70,11 +70,11 @@ Create a LumWallet instance based on a mnemonic and a derivation path #### Parameters -| Name | Type | Description | -| :------ | :------ | :------ | -| `mnemonic` | `string` | mnemonic used to derive the private key | -| `hdPath` | `string` | BIP44 derivation path | -| `addressPrefix` | `string` | prefix to use to derive the address from the public key (ex: lum) | +| Name | Type | Default value | Description | +| :------ | :------ | :------ | :------ | +| `mnemonic` | `string` | `undefined` | mnemonic used to derive the private key | +| `hdPath` | `string` | `undefined` | BIP44 derivation path | +| `addressPrefix` | `string` | `LumConstants.LumBech32PrefixAccAddr` | prefix to use to derive the address from the public key (ex: lum) | #### Returns @@ -108,10 +108,10 @@ Create a LumWallet instance based on a private key (secp256k1) #### Parameters -| Name | Type | Description | -| :------ | :------ | :------ | -| `privateKey` | `Uint8Array` | wallet private key (secp256k1) | -| `addressPrefix` | `string` | prefix to use to derive the address from the public key (ex: lum) | +| Name | Type | Default value | Description | +| :------ | :------ | :------ | :------ | +| `privateKey` | `Uint8Array` | `undefined` | wallet private key (secp256k1) | +| `addressPrefix` | `string` | `LumConstants.LumBech32PrefixAccAddr` | prefix to use to derive the address from the public key (ex: lum) | #### Returns diff --git a/docs/lib/interfaces/lumtypes.account.md b/docs/lib/interfaces/lumtypes.account.md index ac8346e..52b997f 100644 --- a/docs/lib/interfaces/lumtypes.account.md +++ b/docs/lib/interfaces/lumtypes.account.md @@ -6,12 +6,48 @@ ### Properties +- [\_baseVestingAccount](LumTypes.Account.md#_basevestingaccount) +- [\_continuousVestingAccount](LumTypes.Account.md#_continuousvestingaccount) +- [\_delayedVestingAccount](LumTypes.Account.md#_delayedvestingaccount) +- [\_moduleAccount](LumTypes.Account.md#_moduleaccount) +- [\_periodicVestingAccount](LumTypes.Account.md#_periodicvestingaccount) - [accountNumber](LumTypes.Account.md#accountnumber) - [address](LumTypes.Account.md#address) +- [pubkey](LumTypes.Account.md#pubkey) - [sequence](LumTypes.Account.md#sequence) ## Properties +### \_baseVestingAccount + +• `Optional` `Readonly` **\_baseVestingAccount**: `BaseVestingAccount` + +___ + +### \_continuousVestingAccount + +• `Optional` `Readonly` **\_continuousVestingAccount**: `ContinuousVestingAccount` + +___ + +### \_delayedVestingAccount + +• `Optional` `Readonly` **\_delayedVestingAccount**: `DelayedVestingAccount` + +___ + +### \_moduleAccount + +• `Optional` `Readonly` **\_moduleAccount**: `ModuleAccount` + +___ + +### \_periodicVestingAccount + +• `Optional` `Readonly` **\_periodicVestingAccount**: `PeriodicVestingAccount` + +___ + ### accountNumber • `Readonly` **accountNumber**: `number` @@ -24,6 +60,12 @@ ___ ___ +### pubkey + +• `Readonly` **pubkey**: ``null`` \| `Pubkey` + +___ + ### sequence • `Readonly` **sequence**: `number` diff --git a/docs/lib/interfaces/lumtypes.log.md b/docs/lib/interfaces/lumtypes.log.md index 6fe0b95..6e8feb0 100644 --- a/docs/lib/interfaces/lumtypes.log.md +++ b/docs/lib/interfaces/lumtypes.log.md @@ -8,7 +8,7 @@ - [events](LumTypes.Log.md#events) - [log](LumTypes.Log.md#log) -- [msg_index](LumTypes.Log.md#msg_index) +- [msg\_index](LumTypes.Log.md#msg_index) ## Properties diff --git a/docs/lib/modules/lummessages.md b/docs/lib/modules/lummessages.md index f451948..a557fe3 100644 --- a/docs/lib/modules/lummessages.md +++ b/docs/lib/modules/lummessages.md @@ -11,6 +11,7 @@ - [MsgBeginRedelegateUrl](LumMessages.md#msgbeginredelegateurl) - [MsgClaimBeamUrl](LumMessages.md#msgclaimbeamurl) - [MsgCreateValidatorUrl](LumMessages.md#msgcreatevalidatorurl) +- [MsgCreateVestingAccountUrl](LumMessages.md#msgcreatevestingaccounturl) - [MsgDelegateUrl](LumMessages.md#msgdelegateurl) - [MsgDepositUrl](LumMessages.md#msgdepositurl) - [MsgEditValidatorUrl](LumMessages.md#msgeditvalidatorurl) @@ -37,6 +38,7 @@ - [BuildMsgBeginRedelegate](LumMessages.md#buildmsgbeginredelegate) - [BuildMsgClaimBeam](LumMessages.md#buildmsgclaimbeam) - [BuildMsgCreateValidator](LumMessages.md#buildmsgcreatevalidator) +- [BuildMsgCreateVestingAccount](LumMessages.md#buildmsgcreatevestingaccount) - [BuildMsgDelegate](LumMessages.md#buildmsgdelegate) - [BuildMsgDeposit](LumMessages.md#buildmsgdeposit) - [BuildMsgEditValidator](LumMessages.md#buildmsgeditvalidator) @@ -78,6 +80,12 @@ ___ ___ +### MsgCreateVestingAccountUrl + +• **MsgCreateVestingAccountUrl**: ``"/cosmos.vesting.v1beta1.MsgCreateVestingAccount"`` + +___ + ### MsgDelegateUrl • **MsgDelegateUrl**: ``"/cosmos.staking.v1beta1.MsgDelegate"`` @@ -194,7 +202,7 @@ ___ ### MsgWithdrawValidatorCommissionUrl -• **MsgWithdrawValidatorCommissionUrl**: ``"/cosmos.bank.v1beta1.MsgSend"`` +• **MsgWithdrawValidatorCommissionUrl**: ``"/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission"`` ## Functions @@ -257,6 +265,26 @@ ___ ___ +### BuildMsgCreateVestingAccount + +▸ `Const` **BuildMsgCreateVestingAccount**(`fromAddress`, `toAddress`, `amount`, `endTime`, `delayed`): [`Message`](../interfaces/LumMessages.Message.md) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `fromAddress` | `string` | +| `toAddress` | `string` | +| `amount` | [`Coin`](../interfaces/LumTypes.Coin.md)[] | +| `endTime` | `Long` | +| `delayed` | `boolean` | + +#### Returns + +[`Message`](../interfaces/LumMessages.Message.md) + +___ + ### BuildMsgDelegate ▸ `Const` **BuildMsgDelegate**(`delegatorAddress`, `validatorAddress`, `amount?`): [`Message`](../interfaces/LumMessages.Message.md) diff --git a/docs/lib/modules/lumutils.md b/docs/lib/modules/lumutils.md index b8c19bc..bf47b64 100644 --- a/docs/lib/modules/lumutils.md +++ b/docs/lib/modules/lumutils.md @@ -8,9 +8,11 @@ ### Functions +- [accountFromAny](LumUtils.md#accountfromany) - [broadcastTxCommitSuccess](LumUtils.md#broadcasttxcommitsuccess) - [broadcastTxSyncSuccess](LumUtils.md#broadcasttxsyncsuccess) - [convertUnit](LumUtils.md#convertunit) +- [estimatedVesting](LumUtils.md#estimatedvesting) - [generateAuthInfoBytes](LumUtils.md#generateauthinfobytes) - [generateKeyStore](LumUtils.md#generatekeystore) - [generateMnemonic](LumUtils.md#generatemnemonic) @@ -47,6 +49,22 @@ ## Functions +### accountFromAny + +▸ `Const` **accountFromAny**(`input`): [`Account`](../interfaces/LumTypes.Account.md) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `input` | `Any` | + +#### Returns + +[`Account`](../interfaces/LumTypes.Account.md) + +___ + ### broadcastTxCommitSuccess ▸ `Const` **broadcastTxCommitSuccess**(`response`): `boolean` @@ -108,6 +126,37 @@ the amount converted ___ +### estimatedVesting + +▸ `Const` **estimatedVesting**(`account`, `t?`, `denom?`): `Object` + +#### Parameters + +| Name | Type | Default value | +| :------ | :------ | :------ | +| `account` | [`Account`](../interfaces/LumTypes.Account.md) | `undefined` | +| `t?` | `Date` | `undefined` | +| `denom` | `string` | `LumConstants.MicroLumDenom` | + +#### Returns + +`Object` + +| Name | Type | +| :------ | :------ | +| `endsAt` | `Date` | +| `lockedBankCoins` | [`Coin`](../interfaces/LumTypes.Coin.md) | +| `lockedCoins` | [`Coin`](../interfaces/LumTypes.Coin.md) | +| `lockedDelegatedCoins` | [`Coin`](../interfaces/LumTypes.Coin.md) | +| `lockedPercentage` | `number` | +| `startsAt` | `Date` | +| `time` | `Date` | +| `totalCoins` | [`Coin`](../interfaces/LumTypes.Coin.md) | +| `unlockedCoins` | [`Coin`](../interfaces/LumTypes.Coin.md) | +| `unlockedPercentage` | `number` | + +___ + ### generateAuthInfoBytes ▸ `Const` **generateAuthInfoBytes**(`docSigners`, `fee`, `signMode`): `Uint8Array` @@ -263,10 +312,10 @@ Derives a bech32 wallet address from a public key (secp256k1) #### Parameters -| Name | Type | Description | -| :------ | :------ | :------ | -| `publicKey` | `Uint8Array` | public key to derive the address from | -| `prefix` | `string` | address prefix to use (ex: lum) | +| Name | Type | Default value | Description | +| :------ | :------ | :------ | :------ | +| `publicKey` | `Uint8Array` | `undefined` | public key to derive the address from | +| `prefix` | `string` | `LumBech32PrefixAccAddr` | address prefix to use (ex: lum) | #### Returns @@ -377,10 +426,10 @@ Verify that a wallet address is valid #### Parameters -| Name | Type | Description | -| :------ | :------ | :------ | -| `address` | `string` | address to check | -| `prefix` | `undefined` \| `string` | prefix to check (will not be checked if not provided) | +| Name | Type | Default value | Description | +| :------ | :------ | :------ | :------ | +| `address` | `string` | `undefined` | address to check | +| `prefix` | `undefined` \| `string` | `LumBech32PrefixAccAddr` | prefix to check (will not be checked if not provided) | #### Returns From f4380ace3ed17411356402294d5e9d63180b229c Mon Sep 17 00:00:00 2001 From: Fabrice Bascoulergue <3663159+lebascou@users.noreply.github.com> Date: Mon, 3 Jan 2022 19:00:17 +0100 Subject: [PATCH 2/2] Implement full offline signer capability (#37) * Improve abstraction to handle amino offline signer * Bump version to 0.7.2 * Remove useless double check which might cause reflection issues * Fix offline signing Co-authored-by: Fabrice Bascoulergue --- docs/lib/classes/lumwalletfactory.md | 2 +- package.json | 2 +- src/wallet/LumOfflineSignerWallet.ts | 67 ++++++++++++++++++-------- src/wallet/LumWalletFactory.ts | 4 +- tests/wallet.test.ts | 70 ++++++++++++++++++++++++---- 5 files changed, 114 insertions(+), 31 deletions(-) diff --git a/docs/lib/classes/lumwalletfactory.md b/docs/lib/classes/lumwalletfactory.md index 1deb755..ef19490 100644 --- a/docs/lib/classes/lumwalletfactory.md +++ b/docs/lib/classes/lumwalletfactory.md @@ -92,7 +92,7 @@ Create a LumWallet instance based on an OfflineDirectSigner instance compatible | Name | Type | Description | | :------ | :------ | :------ | -| `offlineSigner` | `OfflineDirectSigner` | OfflineDirectSigner instance compatible with Comsjs based implementations | +| `offlineSigner` | `OfflineSigner` | OfflineDirectSigner instance compatible with Comsjs based implementations | #### Returns diff --git a/package.json b/package.json index 2c32d8b..ccdf3e6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lum-network/sdk-javascript", - "version": "0.7.1", + "version": "0.7.2", "license": "Apache-2.0", "description": "Javascript SDK library for NodeJS and Web browsers to interact with the Lum Network.", "homepage": "https://github.com/lum-network/sdk-javascript#readme", diff --git a/src/wallet/LumOfflineSignerWallet.ts b/src/wallet/LumOfflineSignerWallet.ts index 74a9e0c..9127798 100644 --- a/src/wallet/LumOfflineSignerWallet.ts +++ b/src/wallet/LumOfflineSignerWallet.ts @@ -1,27 +1,33 @@ -import { OfflineDirectSigner } from '@cosmjs/proto-signing'; +import Long from 'long'; +import { OfflineAminoSigner } from '@cosmjs/amino'; +import { OfflineSigner, OfflineDirectSigner } from '@cosmjs/proto-signing'; import { SignMode } from '../codec/cosmos/tx/signing/v1beta1/signing'; -import { LumUtils, LumTypes, LumConstants } from '..'; +import { LumUtils, LumTypes, LumConstants, LumAminoRegistry } from '..'; import { LumWallet } from '.'; -import Long from 'long'; export class LumOfflineSignerWallet extends LumWallet { - private readonly offlineSigner: OfflineDirectSigner; + private readonly offlineSigner: OfflineSigner; /** - * Create a LumOfflineSignerWallet instance based on an OfflineDirectSigner instance compatible with Comsjs based + * Create a LumOfflineSignerWallet instance based on an OfflineSigner instance compatible with Comsjs based * implementations. * This constructor is not intended to be used directly as it does not initialize the underlying key pair * Better use the provided static LumPaperWallet builders * * @param mnemonicOrPrivateKey mnemonic (string) used to derive the private key or private key (Uint8Array) */ - constructor(offlineSigner: OfflineDirectSigner) { + constructor(offlineSigner: OfflineSigner) { super(); this.offlineSigner = offlineSigner; } signingMode = (): SignMode => { - return SignMode.SIGN_MODE_DIRECT; + if (typeof (this.offlineSigner as OfflineAminoSigner).signAmino === 'function') { + return SignMode.SIGN_MODE_LEGACY_AMINO_JSON; + } else if (typeof (this.offlineSigner as OfflineDirectSigner).signDirect === 'function') { + return SignMode.SIGN_MODE_DIRECT; + } + throw 'Unknown offline signer mode'; }; canChangeAccount = (): boolean => { @@ -53,9 +59,27 @@ export class LumOfflineSignerWallet extends LumWallet { if (signerIndex === -1) { throw new Error('Signer not found in document'); } - const signDoc = LumUtils.generateSignDoc(doc, signerIndex, this.signingMode()); - const response = await this.offlineSigner.signDirect(this.address, signDoc); - return [response.signed, LumUtils.fromBase64(response.signature.signature)]; + if (this.signingMode() === SignMode.SIGN_MODE_DIRECT) { + const signDoc = LumUtils.generateSignDoc(doc, signerIndex, this.signingMode()); + const response = await (this.offlineSigner as OfflineDirectSigner).signDirect(this.address, signDoc); + return [response.signed, LumUtils.fromBase64(response.signature.signature)]; + } else if (this.signingMode() === SignMode.SIGN_MODE_LEGACY_AMINO_JSON) { + const response = await (this.offlineSigner as OfflineAminoSigner).signAmino(this.address, { + 'account_number': doc.signers[signerIndex].accountNumber.toString(), + 'chain_id': doc.chainId, + 'fee': doc.fee, + 'memo': doc.memo || '', + 'msgs': doc.messages.map((msg) => LumAminoRegistry.toAmino(msg)), + 'sequence': doc.signers[signerIndex].sequence.toString(), + }); + if (response.signed) { + // Fees and memo could have been edited by the offline signer + doc.fee = response.signed.fee; + doc.memo = response.signed.memo; + } + return [LumUtils.generateSignDoc(doc, signerIndex, this.signingMode()), LumUtils.fromBase64(response.signature.signature)]; + } + throw 'Unknown offline signer mode'; }; signMessage = async (msg: string): Promise => { @@ -68,14 +92,19 @@ export class LumOfflineSignerWallet extends LumWallet { chainId: LumConstants.LumSignOnlyChainId, accountNumber: Long.fromNumber(0), }; - const response = await this.offlineSigner.signDirect(this.address, signDoc); - return { - address: this.getAddress(), - publicKey: this.getPublicKey(), - msg: msg, - sig: LumUtils.fromBase64(response.signature.signature), - version: LumConstants.LumWalletSigningVersion, - signer: LumConstants.LumMessageSigner.OFFLINE, - }; + if (this.signingMode() === SignMode.SIGN_MODE_DIRECT) { + const response = await (this.offlineSigner as OfflineDirectSigner).signDirect(this.address, signDoc); + return { + address: this.getAddress(), + publicKey: this.getPublicKey(), + msg: msg, + sig: LumUtils.fromBase64(response.signature.signature), + version: LumConstants.LumWalletSigningVersion, + signer: LumConstants.LumMessageSigner.OFFLINE, + }; + } else if (typeof (this.offlineSigner as OfflineAminoSigner).signAmino === 'function') { + throw 'Feature not available for amino signers'; + } + throw 'Unknown offline signer mode'; }; } diff --git a/src/wallet/LumWalletFactory.ts b/src/wallet/LumWalletFactory.ts index da2ae69..cd23da9 100644 --- a/src/wallet/LumWalletFactory.ts +++ b/src/wallet/LumWalletFactory.ts @@ -1,5 +1,5 @@ import Transport from '@ledgerhq/hw-transport'; -import { OfflineDirectSigner } from '@cosmjs/proto-signing'; +import { OfflineSigner } from '@cosmjs/proto-signing'; import { LumWallet } from './LumWallet'; import { LumLedgerWallet } from './LumLedgerWallet'; @@ -52,7 +52,7 @@ export class LumWalletFactory { * * @param offlineSigner OfflineDirectSigner instance compatible with Comsjs based implementations */ - static fromOfflineSigner = async (offlineSigner: OfflineDirectSigner): Promise => { + static fromOfflineSigner = async (offlineSigner: OfflineSigner): Promise => { const wallet = new LumOfflineSignerWallet(offlineSigner); await wallet.useAccount(); return wallet; diff --git a/tests/wallet.test.ts b/tests/wallet.test.ts index c88c8d1..a3a9753 100644 --- a/tests/wallet.test.ts +++ b/tests/wallet.test.ts @@ -1,10 +1,11 @@ import { AccountData, DirectSignResponse, OfflineDirectSigner } from '@cosmjs/proto-signing'; import { SignDoc } from '../src/codec/cosmos/tx/v1beta1/tx'; -import { LumWallet, LumWalletFactory, LumUtils, LumConstants, LumMessages } from '../src'; -import { encodeSecp256k1Signature } from '@cosmjs/amino'; +import { LumWallet, LumWalletFactory, LumUtils, LumConstants, LumMessages, LumRegistry, LumAminoRegistry } from '../src'; +import { AminoSignResponse, encodeSecp256k1Signature, OfflineAminoSigner, StdSignDoc } from '@cosmjs/amino'; +import { SignMode } from '../src/codec/cosmos/tx/signing/v1beta1/signing'; -class FakeOfflineSigner implements OfflineDirectSigner { +class FakeOfflineDirectSigner implements OfflineDirectSigner { private readonly privateKey: Uint8Array; constructor(privateKey: Uint8Array) { @@ -35,6 +36,48 @@ class FakeOfflineSigner implements OfflineDirectSigner { }; } +class FakeOfflineAminoSigner implements OfflineAminoSigner { + private readonly privateKey: Uint8Array; + + constructor(privateKey: Uint8Array) { + this.privateKey = privateKey; + } + + getAccounts = async (): Promise => { + const publicKey = await LumUtils.getPublicKeyFromPrivateKey(this.privateKey); + return [ + { + pubkey: publicKey, + address: LumUtils.getAddressFromPublicKey(publicKey), + algo: 'secp256k1', + }, + ]; + }; + + signAmino = async (signerAddress: string, stdSignDoc: StdSignDoc): Promise => { + const publicKey = await LumUtils.getPublicKeyFromPrivateKey(this.privateKey); + const signDoc = LumUtils.generateSignDoc( + { + chainId: stdSignDoc.chain_id, + fee: stdSignDoc.fee, + memo: stdSignDoc.memo, + messages: stdSignDoc.msgs.map((aminoMsg) => LumAminoRegistry.fromAmino(aminoMsg)), + signers: [{ accountNumber: parseInt(stdSignDoc.account_number), sequence: parseInt(stdSignDoc.sequence), publicKey: publicKey }], + }, + 0, + SignMode.SIGN_MODE_DIRECT, // Simulated to enable signature comparison during tests + ); + const signBytes = LumUtils.generateSignDocBytes(signDoc); + const hashedMessage = LumUtils.sha256(signBytes); + const signature = await LumUtils.generateSignature(hashedMessage, this.privateKey); + const stdSig = encodeSecp256k1Signature(publicKey, signature); + return { + signed: stdSignDoc, + signature: stdSig, + }; + }; +} + describe('LumWallet', () => { it('Should be identical from mnemonic, privatekey and keystore recovery', async () => { const mnemonic = 'surround miss nominee dream gap cross assault thank captain prosper drop duty group candy wealth weather scale put'; @@ -45,7 +88,8 @@ describe('LumWallet', () => { const w1 = await LumWalletFactory.fromMnemonic(mnemonic, `m/44'/837'/0'/0/0`); const w2 = await LumWalletFactory.fromPrivateKey(LumUtils.keyFromHex(privateKey)); const w3 = await LumWalletFactory.fromKeyStore(keystore, 'lumiere'); - const w4 = await LumWalletFactory.fromOfflineSigner(new FakeOfflineSigner(LumUtils.keyFromHex(privateKey))); + const w4 = await LumWalletFactory.fromOfflineSigner(new FakeOfflineDirectSigner(LumUtils.keyFromHex(privateKey))); + const w5 = await LumWalletFactory.fromOfflineSigner(new FakeOfflineAminoSigner(LumUtils.keyFromHex(privateKey))); expect(LumUtils.isAddressValid(w1.getAddress())).toBe(true); expect(LumUtils.isAddressValid(w1.getAddress(), LumConstants.LumBech32PrefixAccAddr)).toBe(true); @@ -71,17 +115,27 @@ describe('LumWallet', () => { ], }; + const w1Response = await w1.signTransaction(doc); + expect(LumUtils.verifySignature(w1Response[1], LumUtils.sha256(LumUtils.generateSignDocBytes(w1Response[0])), w5.getPublicKey())); + expect(w1.getAddress()).toEqual(w2.getAddress()); expect(w1.getPublicKey()).toEqual(w2.getPublicKey()); - expect(await w1.signTransaction(doc)).toEqual(await w2.signTransaction(doc)); + expect(w1Response).toEqual(await w2.signTransaction(doc)); expect(w1.getAddress()).toEqual(w3.getAddress()); expect(w1.getPublicKey()).toEqual(w3.getPublicKey()); - expect(await w1.signTransaction(doc)).toEqual(await w3.signTransaction(doc)); + expect(w1Response).toEqual(await w3.signTransaction(doc)); expect(w1.getAddress()).toEqual(w4.getAddress()); expect(w1.getPublicKey()).toEqual(w4.getPublicKey()); - expect(await w1.signTransaction(doc)).toEqual(await w4.signTransaction(doc)); + expect(w1Response).toEqual(await w4.signTransaction(doc)); + + expect(w1.getAddress()).toEqual(w5.getAddress()); + expect(w1.getPublicKey()).toEqual(w5.getPublicKey()); + // Signature will differ due to the SignMode use but should still be valid + const w5Response = await w5.signTransaction(doc); + expect(w1Response).not.toEqual(w5Response); + expect(LumUtils.verifySignature(w5Response[1], LumUtils.sha256(LumUtils.generateSignDocBytes(w5Response[0])), w5.getPublicKey())); const randomPrivateKey = LumUtils.generatePrivateKey(); expect(randomPrivateKey).toHaveLength(LumConstants.PrivateKeyLength); @@ -101,7 +155,7 @@ describe('LumWallet', () => { const w1 = await LumWalletFactory.fromMnemonic(mnemonic); const w2 = await LumWalletFactory.fromMnemonic(LumUtils.generateMnemonic()); - const w3 = await LumWalletFactory.fromOfflineSigner(new FakeOfflineSigner(LumUtils.keyFromHex(privateKey))); + const w3 = await LumWalletFactory.fromOfflineSigner(new FakeOfflineDirectSigner(LumUtils.keyFromHex(privateKey))); const signedW1 = await w1.signMessage(message); expect(signedW1.signer).toEqual(LumConstants.LumMessageSigner.PAPER);