All files / src/services PublicStakeKeysTracker.ts

100% Statements 17/17
100% Branches 0/0
100% Functions 11/11
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63      37x 37x 37x                                     126x 126x   210x     217x 243x   288x     243x           37x         126x       217x   236x 236x                
import { AccountKeyDerivationPath, Bip32Account, GroupedAddress } from '@cardano-sdk/key-management';
import { Cardano } from '@cardano-sdk/core';
import { Ed25519PublicKeyHex } from '@cardano-sdk/crypto';
import { Observable, defaultIfEmpty, distinctUntilChanged, forkJoin, from, map, mergeMap, switchMap } from 'rxjs';
import { TrackerSubject } from '@cardano-sdk/util-rxjs';
import { deepEquals } from '@cardano-sdk/util';
 
export interface CreatePubStakeKeysTrackerProps {
  addresses$: Observable<GroupedAddress[]>;
  rewardAccounts$: Observable<Cardano.RewardAccountInfo[]>;
  bip32Account: Bip32Account;
}
 
export interface PubStakeKeyAndStatus {
  credentialStatus: Cardano.StakeCredentialStatus;
  publicStakeKey: Ed25519PublicKeyHex;
}
 
type StakeKeyDerivationPathAndStatus = {
  credentialStatus: Cardano.StakeCredentialStatus;
  stakeKeyDerivationPath: AccountKeyDerivationPath;
};
 
const withStakeKeyDerivationPaths =
  (addresses$: Observable<GroupedAddress[]>) => (source$: Observable<Cardano.RewardAccountInfo[]>) =>
    source$.pipe(
      switchMap((rewardAccounts) =>
        addresses$.pipe(
          // Get stakeKeyDerivationPath of each reward account
          map((groupedAddresses) =>
            rewardAccounts
              .map(({ credentialStatus, address }) => ({
                credentialStatus,
                stakeKeyDerivationPath: groupedAddresses.find((groupedAddr) => groupedAddr.rewardAccount === address)
                  ?.stakeKeyDerivationPath
              }))
              .filter((v): v is StakeKeyDerivationPathAndStatus => !!v.stakeKeyDerivationPath)
          )
        )
      )
    );
 
export const createPublicStakeKeysTracker = ({
  addresses$,
  rewardAccounts$,
  bip32Account: addressManager
}: CreatePubStakeKeysTrackerProps) =>
  new TrackerSubject(
    rewardAccounts$.pipe(
      withStakeKeyDerivationPaths(addresses$),
      mergeMap((derivationPathsAndStatus) =>
        forkJoin(
          derivationPathsAndStatus.map(({ stakeKeyDerivationPath, credentialStatus }) =>
            from(addressManager.derivePublicKey(stakeKeyDerivationPath)).pipe(
              map((publicStakeKey) => ({ credentialStatus, publicStakeKey: publicStakeKey.hex() }))
            )
          )
        ).pipe(defaultIfEmpty([]))
      ),
      distinctUntilChanged(deepEquals)
    )
  );