Signers: Address post-merge review of #40 — bare compat for /signers, VoidSigner tx population, interface cleanup#95
Conversation
|
|
||
| export { ISigner } from '@tetherto/wdk-wallet' | ||
|
|
||
| export { ISignerEvm } from './src/signers/signer-evm.js' |
There was a problem hiding this comment.
We should export the 'ISignerEvm' interface only out of /src/signers/index.js.
| /** | ||
| * Signs a message. | ||
| * | ||
| * @param {string} message - The message to sign. | ||
| * @returns {Promise<string>} The message's signature. | ||
| */ | ||
| async sign (message) { | ||
| throw new NotImplementedError('sign(message)') | ||
| } |
There was a problem hiding this comment.
I think we might be able to move the 'sign' method directly to the 'ISigner' interface since all implementations should be able to sign a message. If this makes sense to you, let's add this change to wdk-wallet pr#52.
There was a problem hiding this comment.
Done in wdk-wallet#52 check there when you can
| /** | ||
| * Interface for EVM signers, extending the base `ISigner` from `@tetherto/wdk-wallet`. | ||
| * | ||
| * @extends {ISigner} |
There was a problem hiding this comment.
No need to use @extends if the class is already extending the type through the extends keyword.
| /** | ||
| * The account index. Always undefined for private key signers: a raw key has no | ||
| * BIP-44 position, so reporting an index would be misleading. | ||
| * | ||
| * @type {number|undefined} | ||
| */ | ||
| get index () { return undefined } | ||
|
|
||
| /** | ||
| * The derivation path. Always undefined for private key signers. | ||
| * | ||
| * @type {string|undefined} | ||
| */ | ||
| get path () { return this._path } |
There was a problem hiding this comment.
The path and index will always be null for a private key signer.
| /** | ||
| * The derivation path. Always undefined for private key signers. | ||
| * | ||
| * @type {string|undefined} | ||
| */ | ||
| get path () { return this._path } |
There was a problem hiding this comment.
Private key signers don't need a path property so you can get rid of it:
| /** | |
| * The derivation path. Always undefined for private key signers. | |
| * | |
| * @type {string|undefined} | |
| */ | |
| get path () { return this._path } | |
| /** | |
| * The BIP 0044 derivation path. | |
| * | |
| * @type {string | null} | |
| */ | |
| get path () { return null } |
| /** | ||
| * PrivateKeySignerEvm is not a hierarchical signer and cannot derive. | ||
| * @returns {Promise<never>} | ||
| * Derive a child signer using a relative path (e.g., "0'/0/0"). | ||
| * | ||
| * @param {string} relPath - The relative derivation path. | ||
| * @returns {Promise<never>} Never resolves; private-key signers cannot derive. | ||
| * @throws {SignerError} Always — private-key signers do not support derivation. | ||
| */ | ||
| async derive () { | ||
| async derive (relPath) { |
There was a problem hiding this comment.
#40 (comment)
The specification of the method should be equal to the superclass's except for the return value which should correctly be 'Promise'.
This should be:
| /** | |
| * PrivateKeySignerEvm is not a hierarchical signer and cannot derive. | |
| * @returns {Promise<never>} | |
| * Derive a child signer using a relative path (e.g., "0'/0/0"). | |
| * | |
| * @param {string} relPath - The relative derivation path. | |
| * @returns {Promise<never>} Never resolves; private-key signers cannot derive. | |
| * @throws {SignerError} Always — private-key signers do not support derivation. | |
| */ | |
| async derive () { | |
| async derive (relPath) { | |
| /** | |
| * Derive a child signer using a relative path (e.g., "0'/0/0"). | |
| * | |
| * @param {string} relPath - The relative derivation path. | |
| * @returns {Promise<never>} The derived signer. | |
| * @throws {SignerError} If the signer does not support derivation. | |
| */ | |
| async derive (relPath) { |
There was a problem hiding this comment.
Keep the order of the test cases consistent between the two test files.
- export ISignerEvm only from src/signers/index.js - drop redundant @extends tag on ISignerEvm - path/index return null on PrivateKeySignerEvm (null convention, aligned in ISignerEvm, WalletAccountEvm and wdk-wallet's IWalletAccount) - unify path/index descriptions across signer docs - reorder test cases so both signer suites follow the same order Deferred for the ongoing interface discussion: - moving sign() to ISigner: tetherto#95 (comment) - derive() doc spec alignment: tetherto#95 (comment)
faeb32c to
beb66fe
Compare
Description
This PR addresses the post-merge review comments from #40 (EVM: split signer from account). Changes grouped by area:
Bare compatibility (fix)
src/signers/bare.jsentry and abarecondition on the./signersexport. Importing@tetherto/wdk-wallet-evm/signersunder the bare runtime previously failed withMODULE_NOT_FOUND: Cannot find module 'http'(the subpath bypassed the bare-node-runtime import mapping applied by the rootbare.js); verified fixed against the actual bare runtime.Transaction population
WalletAccountEvm.sendTransactionnow populates transactions with ethers'VoidSigner#populateTransactioninstead of our own populator.src/utils/tx-populator-evm.jsis deleted entirely and theUnsignedEvmTransactiontype is replaced with ethers'TransactionLike. Verified equivalent output (byte-identical signed transactions for legacy, EIP-1559 and EIP-7702 type-4 transactions, including authorization-list gas estimation) and covered by the existing integration suite. One behavioral note: ethers does not auto-detect type-3 from blob fields, so blob transactions require an explicittype: 3— nothing in the package or tests relied on auto-detection.Signer interfaces
ISignerEvmmoved to its own filesrc/signers/signer-evm.jsand is now exported from the root entry, the/signersbarrel, and the types.ISigneris re-exported from the root entry as well.isDerivableandkeyPairmoved up to the baseISigner(see companion PR tetherto/wdk-wallet#);ISignerEvmkeeps only the EVM-specific members (index,path,address, sign methods) and no longer overrides methods it inherits (derive,getAddress,dispose).SeedSignerEvmandPrivateKeySignerEvmnow@implementsthe interface instead of extending it, matching the wdk-wallet convention.SeedSignerEvm#index(path/indexare always set for a seed signer); JSDoc cleaned up per review (concise descriptions, full specs on all public methods,deriveon the private-key signer documented asPromise<never>matching the superclass spec).Wallet manager
@throwstags, and the non-derivable-default-signer error is now aSignerError._accountscache keys simplified to the reviewed scheme:signerName/path/signerName:path.Tests
tests/signers.test.jssplit intotests/signers/seed-signer-evm.test.jsandtests/signers/private-key-signer-evm.test.jswith mirrored test cases for the shared interface surface (constructor, key pair bytes, derive, getAddress, sign, signTransaction, signTypedData, dispose — including double-dispose safety), plus signer-specific cases in each file.TRANSACTIONconstant removed.Types
.d.tsfiles hand-edited (nobuild:typesrun; generator issues tracked separately): stray generated comments removed, import statements moved to the bottom,SeedSignerEvmOpts.rootgiven a proper structuralMemorySafeHDNodeWallettype instead ofobject(the implementation is internal and ships no declarations).Verified: 122/122 unit + integration tests (hardhat),
standard,tscover the declaration files, bare-runtime import of both entrypoints, and the wdk-playground e2e suite on both node and bare runtimes against testnet (all checks pass; live sends and transfers go through the new VoidSigner path).Motivation and Context
Post-merge review of #40 raised valid points that couldn't be addressed before the merge/release: the
/signerssubpath was not usable under bare, transaction population re-implemented logic ethers already ships (and maintains) inVoidSigner, theISignerEvminterface lived in the wrong file with redundant overrides and fields that belong on the baseISigner, and the signer test suites and docs needed restructuring. This PR implements the agreed subset of that review; the remaining discussion points are being answered directly on the #40 threads.Depends on tetherto/wdk-wallet#52 (
ISigner.isDerivable/keyPair,IWalletAccountalignment). The@tetherto/wdk-walletdependency temporarily points at that branch and must be switched to the published version once it's released (as with previous release flows).Type of change