From c198dc73c5b7a6a2f092ad2719506a88a062da39 Mon Sep 17 00:00:00 2001 From: Jakub Sydor Date: Mon, 25 Jul 2022 11:38:01 +0200 Subject: [PATCH] fix: set check ethr signer for node clients (#618) * fix: set check ethr signer for node clients * test: add ethr signer tests --- e2e/signer.service.e2e.ts | 16 ++++++++++++++++ src/modules/signer/signer.service.ts | 28 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 e2e/signer.service.e2e.ts diff --git a/e2e/signer.service.e2e.ts b/e2e/signer.service.e2e.ts new file mode 100644 index 00000000..d955e506 --- /dev/null +++ b/e2e/signer.service.e2e.ts @@ -0,0 +1,16 @@ +import { providers, Wallet } from 'ethers'; +import { ProviderType, SignerService } from '../src'; + +describe('Signer tests', () => { + it('should set `isEthrSigner` for node environment during initialization', async () => { + const wallet = Wallet.createRandom(); + const provider = new providers.JsonRpcProvider('http://localhost:8544'); + const service = new SignerService( + wallet.connect(provider), + ProviderType.PrivateKey + ); + expect(service.isEthSigner).toBeUndefined(); + await service.init(); + expect(service.isEthSigner).toBe(true); + }); +}); diff --git a/src/modules/signer/signer.service.ts b/src/modules/signer/signer.service.ts index 2f030e04..47ef3e7f 100644 --- a/src/modules/signer/signer.service.ts +++ b/src/modules/signer/signer.service.ts @@ -85,7 +85,10 @@ export class SignerService { } else if (isEthSigner === 'false') { this._isEthSigner = false; } + } else { + this._setIsEthrSigner(); } + /** * @todo provide general way to initialize with previously saved key */ @@ -502,4 +505,29 @@ export class SignerService { sig )}`; } + + /** + * Set `_isEthSigner` value based on a signed message. + * Generates a test message and signs it. + */ + private async _setIsEthrSigner() { + // arrayification is necessary for WalletConnect signatures to work. eth_sign expects message in bytes: https://docs.walletconnect.org/json-rpc-api-methods/ethereum#eth_sign + // keccak256 hash is applied for Metamask to display a coherent hex value when signing + const message = arrayify(keccak256('0x')); + // Computation of the digest in order to recover the public key under the assumption + // that signature was performed as per the eth_sign spec (https://eth.wiki/json-rpc/API#eth_sign) + const digest = arrayify(hashMessage(message)); + const sig = await this._signer.signMessage(message); + const keyFromMessage = recoverPublicKey(message, sig); + const keyFromDigest = recoverPublicKey(digest, sig); + if (getAddress(this._address) === computeAddress(keyFromMessage)) { + this._publicKey = keyFromMessage; + this._isEthSigner = false; + } else if (getAddress(this._address) === computeAddress(keyFromDigest)) { + this._publicKey = keyFromDigest; + this._isEthSigner = true; + } else { + throw new Error(ERROR_MESSAGES.NON_ETH_SIGN_SIGNATURE); + } + } }