XO Wallet Integration Part IV

This commit is contained in:
Jim Hamill
2025-05-27 23:17:41 +00:00
parent 25b58853a3
commit 2bfeed8587
15 changed files with 249 additions and 123 deletions
+55 -10
View File
@@ -11,7 +11,15 @@ import { type BlockchainUTXOs } from '../blockchain/index.js';
import { type Activities, type BaseStore } from '../storage/index.js';
import { EventEmitter } from '../utils/index.js';
import { type TokenBalances, type Address } from '@xocash/primitives';
import {
type TokenBalances,
type Address,
Bytes,
Hasher,
encodeExtendedJson,
} from '@xocash/primitives';
export type WalletGenesisData = Record<string, unknown>;
export type WalletEvents = {
shouldMonitorUpdated: boolean;
@@ -33,32 +41,69 @@ export type WalletEvents = {
export abstract class BaseWallet<
WalletEventsType extends WalletEvents = WalletEvents,
> extends EventEmitter<WalletEventsType> {
static readonly deriveKey: (keyName: string) => Promise<Uint8Array>;
/**
* Derive a key to use based on the given Genesis Data.
*
* @remarks
*
* These keys can be used for Wallet Id's, Signing Keys, Encryption Keys and for Dapp Samdboxes.
*/
static deriveKey(genesisData: WalletGenesisData, keyName: string) {
// Hash the genesis data using Hash256 and the key ("WalletID") for this derivation using Hash256.
const genesisDataHashed = Hasher.fromUTF8(
encodeExtendedJson(genesisData),
).toHash256Bytes();
const keyHashed = Hasher.fromUTF8(keyName).toHash256Bytes();
// Combine the hashes and do one final hash for good measure.
return Hasher.fromBytes(
new Uint8Array([...genesisDataHashed, ...keyHashed]),
).toHash256Bytes();
}
static deriveId(genesisData: WalletGenesisData) {
return BaseWallet.deriveKey(genesisData, 'walletId');
}
// Dependencies.
abstract readonly activities: Activities;
abstract readonly blockchain: WalletBlockchain;
abstract readonly cache: BaseStore;
// Genesis Data.
abstract readonly genesisData: WalletGenesisData;
/**
* Get the ID for this wallet.
*/
abstract getId(): Promise<string>;
/**
* Derive a key using secret data from this wallet.
*/
abstract deriveKey(keyName: string): Promise<Uint8Array>;
async getId() {
// NOTE: Use the cache to optimize future calls.
return Bytes.from(
await this.cache.getOrSet('walletId', async () =>
BaseWallet.deriveKey(this.genesisData, 'walletId'),
),
).toHex();
}
/**
* Get the encryption key to use for this wallet.
*/
abstract getEncryptionKey(): Promise<Uint8Array>;
async getEncryptionKey() {
// NOTE: Use the cache to optimize future calls.
return await this.cache.getOrSet('encryptionKey', async () =>
BaseWallet.deriveKey(this.genesisData, 'encryptionKey'),
);
}
/**
* Get the signing key to use for this wallet.
*/
abstract getSigningKey(): Promise<Uint8Array>;
async getSigningKey() {
// NOTE: Use the cache to optimize future calls.
return this.cache.getOrSet('signingKey', async () =>
BaseWallet.deriveKey(this.genesisData, 'signingKey'),
);
}
/**
* Start monitoring this wallet for any transaction activity.