Skip to content
This repository was archived by the owner on Jun 3, 2026. It is now read-only.

feat: add IdentityKeyManager for mnemonic-based key derivation - #87

Merged
thephez merged 7 commits into
evo-sdk-migrationfrom
evo-sdk-migration-key-mgr
Feb 12, 2026
Merged

thephez merged 7 commits into
evo-sdk-migrationfrom
evo-sdk-migration-key-mgr

Conversation

@thephez

@thephez thephez commented Feb 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add IdentityKeyManager class that derives all Platform signing keys (auth, master, transfer) from a single BIP-44/DIP-9 mnemonic, replacing the need to manually supply individual WIF keys
  • Migrate all write tutorials (registerContract, updateContract, registerName, submitDocument, updateDocument, deleteDocument, updateIdentity, transferCredits, withdrawCredits) to accept a keyManager instead of separate identityId/privateKeyWif/keyId params
  • Simplify env config from 5 variables (IDENTITY_ID, PRIVATE_KEY_WIF, IDENTITY_PUBLIC_KEY_ID, TRANSFER_KEY_WIF, MASTER_KEY_WIF) to a single PLATFORM_MNEMONIC
  • Add deriveKeysFromMnemonic and showIdentityKeys wallet tutorials
  • Add dedicated IdentityKeyManager test suite with key derivation, identity resolution, and signer validation tests

thephez and others added 7 commits February 11, 2026 17:36
Derives all 5 standard DIP-9 identity keys from a BIP39 mnemonic and provides named getters (getAuth, getAuthHigh, getTransfer, getEncryption, getMaster) that return ready-to-use { identity, identityKey, signer }.
…monic

Fix the DIP-9 derivation path to include the authentication subfeature level (m/9'/coin'/5'/0'/0'/identityIndex'/keyIndex'). Add auto-resolve for identityId in IdentityKeyManager.create() — when omitted, the master key's public key hash is looked up on-chain via sdk.identities.byPublicKeyHash(). Also corrects key ID mapping to match on-chain order (HIGH=1, CRITICAL=2).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace raw identityId/masterKeyWif params with keyManager in
updateIdentity tutorial. The keyManager.getMaster() method handles
identity fetch, master key signing, and additional WIFs for new keys.
Update test assertions to use keyManager.identityId.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…yManager

Replace raw identityId/privateKeyWif/keyId params with keyManager.getAuth()
pattern, consistent with submitDocument and updateIdentity migrations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d withdrawCredits to use IdentityKeyManager

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@thephez
thephez marked this pull request as ready for review February 12, 2026 18:20
@thephez
thephez merged commit cd4da52 into evo-sdk-migration Feb 12, 2026
@thephez
thephez deleted the evo-sdk-migration-key-mgr branch February 12, 2026 18:21
thephez added a commit that referenced this pull request Feb 18, 2026
* refactor: move deprecated js-dash-sdk files to dedicated subdirectories

* chore: update to evo-sdk 3.0.1

* feat: add evo-sdk tutorials and tests as ESM modules

Port tutorials and query tests to use @dashevo/evo-sdk with ES module
syntax. Update npm scripts and ESLint config for .mjs support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: make tutorials standalone and fix retrieveNameBySearch

Make all 8 evo-sdk tutorials documentation-ready with commented-out
setup/execution blocks matching the old tutorial pattern. Fix
retrieveNameBySearch to use documents.query with startsWith (prefix
search) instead of getUsernameByName (exact match only).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: improve tutorial correctness and consistency

Use SDK's homograph normalizer instead of incomplete custom
implementation, centralize DPNS contract ID, rename legacy
dapiClientMethods to getSystemInfo, fix getDocument filename
to match plural function, validate network param in createClient,
and skip known-failing startAt test (dashpay/platform#3078).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add robust assertions to tutorial tests

Replaces shallow undefined checks with structural and content validation
including JSON property checks, type verification, and known-value matching.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add write tutorials and tests

Contract create/update, document create/replace/delete, name registration, identity update, credit withdrawal/transfer

* feat: add deriveKeysFromMnemonic tutorial with DIP-9 key derivation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: split identity update into add and disable steps, reorder doc and contract ops

* refactor: centralize test constants and add dynamic info to test titles

Move hardcoded identity IDs, names, and addresses from test files into
tutorials/constants.mjs so both test.mjs and queryTest.mjs share a
single source of truth. Add this.test.title output for write operations
so created contract/document/key IDs appear inline in mocha results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: use instanceof assertions instead of constructor.name checks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add read tutorials for epochs, identity balance/keys, names, and tokens

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add contract history test with timestamp-keyed Map validation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: update workflows

- Move old tests to deprecated workflow
- Check evo sdk version now instead of dash
- Add new tests to main workflow

* docs: update readme

* chore: syntax fix

* test: add disabled token contract create

SDK doesn't support creating contract with tokens properly

* test: add missing query assertions and startAtComplex limit=2 tests

Port validation logic from deprecated js-dash-sdk query tests including
document ID equality/inequality checks, label verification, startsWith
prefix validation, and console.log output for debugging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add missing contract

* test: query test warm up query

* test: update timeouts and names

* test: update package.json test options

* chore: update dependencies

* feat: add IdentityKeyManager for mnemonic-based key derivation (#87)

* feat: add IdentityKeyManager for mnemonic-based key management

Derives all 5 standard DIP-9 identity keys from a BIP39 mnemonic and provides named getters (getAuth, getAuthHigh, getTransfer, getEncryption, getMaster) that return ready-to-use { identity, identityKey, signer }.

* fix: correct DIP-9 derivation path and auto-resolve identity from mnemonic

Fix the DIP-9 derivation path to include the authentication subfeature level (m/9'/coin'/5'/0'/0'/identityIndex'/keyIndex'). Add auto-resolve for identityId in IdentityKeyManager.create() — when omitted, the master key's public key hash is looked up on-chain via sdk.identities.byPublicKeyHash(). Also corrects key ID mapping to match on-chain order (HIGH=1, CRITICAL=2).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate updateIdentity to use IdentityKeyManager

Replace raw identityId/masterKeyWif params with keyManager in
updateIdentity tutorial. The keyManager.getMaster() method handles
identity fetch, master key signing, and additional WIFs for new keys.
Update test assertions to use keyManager.identityId.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate updateDocument and deleteDocument to use IdentityKeyManager

Replace raw identityId/privateKeyWif/keyId params with keyManager.getAuth()
pattern, consistent with submitDocument and updateIdentity migrations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate registerContract, registerName, transferCredits, and withdrawCredits to use IdentityKeyManager

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: replace individual key env vars with single PLATFORM_MNEMONIC

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: fmt and minor changes

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: add setupDashClient and simplify tutorial setup blocks

Replace verbose EvoSDK/IdentityKeyManager setup boilerplate in all
28 tutorial files with a single setupDashClient() call that reads
env vars internally. Mirrors the old js-dash-sdk setupDashClient
pattern where tutorials had zero setup code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update lock file after pinning deps

* feat: add retrieveIdentityIds tutorial for mnemonic identity enumeration

Derives DIP-9 master keys for successive identity indices and queries
byPublicKeyHash until no identity is found, mimicking the deprecated
account.identities.getIdentityIds() from js-dash-sdk.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: correct DIP-9 derivation path to include ECDSA key type component

The path was missing the 0' (ECDSA key type) component, producing
6-segment paths instead of the correct 7-segment
m/9'/{coin}'/5'/0'/0'/{identityIndex}'/{keyIndex}'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add platform address tutorials (#88)

* feat: add read-only platform address tutorials and passing tests

* feat: add platform address write tutorials with balance summary

Add transfer and top-up tutorials for platform addresses. Include before/after hooks that capture and display starting and ending balances for all addresses and the identity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add createIdentityFromAddresses tutorial and test

Implements identity creation funded from platform addresses using DIP-9
key derivation. Test is skipped pending SDK nonce off-by-one bug (#3083).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add addressWithdraw tutorial and enable test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: run fmt

* refactor: accept base58 address string in addressWithdraw instead of raw hash

Move base58check decode into the tutorial function so callers pass a
standard Dash address string rather than a pre-decoded hash160.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: use string enums in createIdentity and extract MIN_WITHDRAWAL_AMOUNT

- Use string enums for identity key purpose/securityLevel/keyType instead
  of numeric constants
- Extract MIN_WITHDRAWAL_AMOUNT (190000n) to constants.mjs
- Fix address balance lookup to match by bech32m instead of array index
- Re-enable createIdentityFromAddresses test with reduced amount

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: move identity key derivation into IdentityKeyManager

Add findNextIndex, createForNewIdentity, getKeysInCreation, and
getFullSigner to IdentityKeyManager. Simplify createIdentityFromAddresses
to delegate key derivation and index scanning to the manager.

Fix auth/authHigh keyId assertion swaps in existing tests and add new
tests for identityIndex, getFullSigner, and getKeysInCreation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: use SDK enums for KEY_SPECS purpose, securityLevel, and keyType

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: update constructors and methods for evo-sdk 3.1-dev breaking changes

Upgrade to @dashevo/evo-sdk 3.1.0-dev.1 which migrated WASM bindings
from wasm-dpp to wasm-dpp2, changing several constructors from positional
args to options objects and renaming methods.

- DataContract: positional args → { ownerId, identityNonce, schemas, ... }
- Document: positional args → { properties, documentTypeName, dataContractId, ownerId, ... }
- IdentityPublicKeyInCreation: positional args → { keyId, purpose, securityLevel, keyType, data }
- CoreScript.newP2PKH → CoreScript.fromP2PKH
- DataContract.getSchemas() → DataContract.schemas getter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: fmt

* fix: increase address funding and handle createIdentity proof mismatch

Increase transferToAddress amount from 100M to 500M credits to cover
the addressWithdraw minimum balance requirement of 400.5M. Also wrap
createIdentityFromAddresses test in try/catch to pass on the known
nonce off-by-one proof mismatch error (#3083), extracting the actual
identity ID from the error for test output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: remove outdated comment

* refactor: use this.skip() instead of expect() for dependent test preconditions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: reorder test sections for logical grouping

Split "Network connection and System info" into separate describe blocks
and move identity write tutorials before contract write tutorials.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: create fresh identity per test run instead of reusing index 0

Replace setupDashClient() with explicit bootstrap setup that funds a
platform address and creates a fresh identity as the first test case.
This makes write tests hermetic across runs. Adds keyManager skip
guards to dependent describe blocks and removes the duplicate
createIdentityFromAddresses test from the address block.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: use setupDashClient for bootstrap, check address balance before funding

- Re-add setupDashClient import so it's exercised by the test suite
- Rename bootstrapKeyManager → bootstrapIdentityKeyManager for clarity
- Extract FRESH_IDENTITY_AMOUNT const, only top up address if balance is insufficient
- Return unused identity credits to funding address in after() hook
- Use before() instead of beforeEach() for keyManager skip guards

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant