Merge branch '71-wallethd-genesis-refactor-to-use-mnemonic-primitive' into 'development'
Resolve "WalletHD Genesis: Refactor to use Mnemonic Primitive" Closes #71 See merge request GeneralProtocols/xo/stack!115
This commit is contained in:
@@ -1,11 +1,7 @@
|
|||||||
import { BaseStore } from './base-store.js';
|
import { BaseStore } from './base-store.js';
|
||||||
import { StoreComposite } from './store-composite.js';
|
import { StoreComposite } from './store-composite.js';
|
||||||
|
|
||||||
import { EventEmitter, UUIDV7 } from '../utils/index.js';
|
import { type Optional, EventEmitter, UUIDV7 } from '../utils/index.js';
|
||||||
|
|
||||||
// Make the given property in a type optional.
|
|
||||||
// TODO: This is an extremely useful utility. If we use it elsewhere, move to own "type-utils.ts" file.
|
|
||||||
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
||||||
|
|
||||||
// Base Activity interface
|
// Base Activity interface
|
||||||
export interface Activity {
|
export interface Activity {
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ export * from './memoizer.js';
|
|||||||
export * from './misc.js';
|
export * from './misc.js';
|
||||||
export * from './sse-session.js';
|
export * from './sse-session.js';
|
||||||
export * from './sse-session-msgpackr.js';
|
export * from './sse-session-msgpackr.js';
|
||||||
|
export * from './type-utils.js';
|
||||||
export * from './uuid.js';
|
export * from './uuid.js';
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Utility for removing keys that works with distributive unions.
|
||||||
|
*/
|
||||||
|
export type DistributiveOmit<T, K extends keyof any> = T extends any
|
||||||
|
? Omit<T, K>
|
||||||
|
: never;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the given property in a type optional.
|
||||||
|
*/
|
||||||
|
export type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
||||||
@@ -5,6 +5,7 @@ import { type WalletBlockchain, type WalletDependencies } from './types.js';
|
|||||||
import { WalletP2PKH } from './wallet-p2pkh.js';
|
import { WalletP2PKH } from './wallet-p2pkh.js';
|
||||||
|
|
||||||
import { type BaseStore, Activities, StoreInMemory } from '../storage/index.js';
|
import { type BaseStore, Activities, StoreInMemory } from '../storage/index.js';
|
||||||
|
import { type DistributiveOmit } from '../utils/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type TokenBalances,
|
type TokenBalances,
|
||||||
@@ -23,15 +24,20 @@ export const ADDRESS_GAP = 20;
|
|||||||
export const CHAIN_EXTERNAL = 0;
|
export const CHAIN_EXTERNAL = 0;
|
||||||
export const CHAIN_INTERNAL = 1;
|
export const CHAIN_INTERNAL = 1;
|
||||||
|
|
||||||
export type WalletHDGenesisData = {
|
export type WalletHDEntropy =
|
||||||
type: 'WalletHD';
|
| { seed: string }
|
||||||
|
| { xpriv: string }
|
||||||
|
| { mnemonic: Mnemonic };
|
||||||
|
|
||||||
|
export type WalletHDDerivationData = {
|
||||||
derivationPath: string;
|
derivationPath: string;
|
||||||
addressGap?: number;
|
addressGap?: number;
|
||||||
} & (
|
};
|
||||||
| { seed: string }
|
|
||||||
| { mnemonic: string; passphrase?: string }
|
export type WalletHDGenesisData = {
|
||||||
| { xpriv: string }
|
type: 'WalletHD';
|
||||||
);
|
} & WalletHDEntropy &
|
||||||
|
WalletHDDerivationData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Hierarhical Determinstic (BIP44) Wallet.
|
* A Hierarhical Determinstic (BIP44) Wallet.
|
||||||
@@ -61,7 +67,7 @@ export class WalletHD extends BaseWallet {
|
|||||||
static async from<T extends typeof WalletHD>(
|
static async from<T extends typeof WalletHD>(
|
||||||
this: T,
|
this: T,
|
||||||
deps: WalletDependencies,
|
deps: WalletDependencies,
|
||||||
genesisData: WalletHDGenesisData,
|
genesisData: DistributiveOmit<WalletHDGenesisData, 'type'>,
|
||||||
) {
|
) {
|
||||||
// Assign defaults if not otherwise provideed.
|
// Assign defaults if not otherwise provideed.
|
||||||
const activities = deps.activities
|
const activities = deps.activities
|
||||||
@@ -99,7 +105,7 @@ export class WalletHD extends BaseWallet {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
dependencies: Required<WalletDependencies>,
|
dependencies: Required<WalletDependencies>,
|
||||||
genesisData: WalletHDGenesisData,
|
genesisData: DistributiveOmit<WalletHDGenesisData, 'type'>,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -109,22 +115,17 @@ export class WalletHD extends BaseWallet {
|
|||||||
this.cache = dependencies.cache;
|
this.cache = dependencies.cache;
|
||||||
|
|
||||||
// Assign our state.
|
// Assign our state.
|
||||||
this.genesisData = genesisData;
|
this.genesisData = {
|
||||||
|
type: 'WalletHD',
|
||||||
|
...genesisData,
|
||||||
|
};
|
||||||
|
|
||||||
// Instantiate the HDPrivateNode from the type specified in our genesis data.
|
// Instantiate the HDPrivateNode from the type specified in our genesis data.
|
||||||
if ('seed' in genesisData) {
|
if ('seed' in genesisData) {
|
||||||
this.hdPrivateNode = HDPrivateNode.fromSeed(genesisData.seed);
|
this.hdPrivateNode = HDPrivateNode.fromSeed(genesisData.seed);
|
||||||
} else if ('mnemonic' in genesisData) {
|
} else if ('mnemonic' in genesisData) {
|
||||||
// TODO: We really want to support multiple word-lists somehow.
|
|
||||||
// But this is not trivial because other word-lists are technically not standard.
|
|
||||||
// For now, we are allowing any phrase (BIP39 derives seed from literal phrase, not word indexes).
|
|
||||||
const mnemonic = Mnemonic.fromRaw({
|
|
||||||
words: genesisData.mnemonic.split(' '),
|
|
||||||
passphrase: genesisData.passphrase,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create the HD Node from our Mnemonic instance.
|
// Create the HD Node from our Mnemonic instance.
|
||||||
this.hdPrivateNode = HDPrivateNode.fromMnemonic(mnemonic);
|
this.hdPrivateNode = HDPrivateNode.fromMnemonic(genesisData.mnemonic);
|
||||||
} else {
|
} else {
|
||||||
this.hdPrivateNode = HDPrivateNode.fromXPriv(genesisData.xpriv);
|
this.hdPrivateNode = HDPrivateNode.fromXPriv(genesisData.xpriv);
|
||||||
}
|
}
|
||||||
@@ -364,7 +365,6 @@ export class WalletHD extends BaseWallet {
|
|||||||
cache: this.cache,
|
cache: this.cache,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'WalletP2PKH',
|
|
||||||
privateKey: privateKeyHex,
|
privateKey: privateKeyHex,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export class WalletP2PKH extends BaseWallet {
|
|||||||
static async from<T extends typeof WalletP2PKH>(
|
static async from<T extends typeof WalletP2PKH>(
|
||||||
this: T,
|
this: T,
|
||||||
deps: WalletDependencies,
|
deps: WalletDependencies,
|
||||||
genesisData: WalletP2PKHGenesisData,
|
genesisData: Omit<WalletP2PKHGenesisData, 'type'>,
|
||||||
) {
|
) {
|
||||||
// Assign defaults if not otherwise provideed.
|
// Assign defaults if not otherwise provideed.
|
||||||
const activities = deps.activities
|
const activities = deps.activities
|
||||||
@@ -77,7 +77,6 @@ export class WalletP2PKH extends BaseWallet {
|
|||||||
|
|
||||||
// Return a new instance of Wallet P2PKH.
|
// Return a new instance of Wallet P2PKH.
|
||||||
return this.from<T>(services, {
|
return this.from<T>(services, {
|
||||||
type: 'WalletP2PKH',
|
|
||||||
privateKey: privateKey.toHex(),
|
privateKey: privateKey.toHex(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -92,7 +91,6 @@ export class WalletP2PKH extends BaseWallet {
|
|||||||
|
|
||||||
// Return a new instance of Wallet P2PKH.
|
// Return a new instance of Wallet P2PKH.
|
||||||
return this.from<T>(services, {
|
return this.from<T>(services, {
|
||||||
type: 'WalletP2PKH',
|
|
||||||
privateKey: privateKey.toHex(),
|
privateKey: privateKey.toHex(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -107,7 +105,6 @@ export class WalletP2PKH extends BaseWallet {
|
|||||||
|
|
||||||
// Return a new instance of Wallet P2PKH.
|
// Return a new instance of Wallet P2PKH.
|
||||||
return this.from<T>(services, {
|
return this.from<T>(services, {
|
||||||
type: 'WalletP2PKH',
|
|
||||||
privateKey: privateKey.toHex(),
|
privateKey: privateKey.toHex(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -121,7 +118,6 @@ export class WalletP2PKH extends BaseWallet {
|
|||||||
|
|
||||||
// Return a new instance of Wallet P2PKH.
|
// Return a new instance of Wallet P2PKH.
|
||||||
return this.from<T>(services, {
|
return this.from<T>(services, {
|
||||||
type: 'WalletP2PKH',
|
|
||||||
privateKey: privateKey.toHex(),
|
privateKey: privateKey.toHex(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -143,7 +139,7 @@ export class WalletP2PKH extends BaseWallet {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
dependencies: Required<WalletDependencies>,
|
dependencies: Required<WalletDependencies>,
|
||||||
genesisData: WalletP2PKHGenesisData,
|
genesisData: Omit<WalletP2PKHGenesisData, 'type'>,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -153,7 +149,10 @@ export class WalletP2PKH extends BaseWallet {
|
|||||||
this.cache = dependencies.cache;
|
this.cache = dependencies.cache;
|
||||||
|
|
||||||
// Assign our Genesis Data.
|
// Assign our Genesis Data.
|
||||||
this.genesisData = genesisData;
|
this.genesisData = {
|
||||||
|
type: 'WalletP2PKH',
|
||||||
|
...genesisData,
|
||||||
|
};
|
||||||
|
|
||||||
// Optimizations/Simplifications.
|
// Optimizations/Simplifications.
|
||||||
this.privateKey = PrivateKey.fromHex(genesisData.privateKey);
|
this.privateKey = PrivateKey.fromHex(genesisData.privateKey);
|
||||||
|
|||||||
Reference in New Issue
Block a user