-
Notifications
You must be signed in to change notification settings - Fork 55
/
DelegationTracker.ts
97 lines (92 loc) · 3.71 KB
/
DelegationTracker.ts
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { Cardano, StakePoolSearchProvider, WalletProvider } from '@cardano-sdk/core';
import { DelegationTracker, TransactionsTracker } from '../types';
import { Observable, map, share, switchMap } from 'rxjs';
import {
ObservableRewardsProvider,
ObservableStakePoolSearchProvider,
createQueryStakePoolsProvider,
createRewardAccountsTracker,
createRewardsProvider
} from './RewardAccounts';
import { RetryBackoffConfig } from 'backoff-rxjs';
import { RewardsHistoryProvider, createRewardsHistoryProvider, createRewardsHistoryTracker } from './RewardsHistory';
import { TrackerSubject, coldObservableProvider } from '../util';
import { TxWithEpoch } from './types';
import { transactionsWithCertificates } from './transactionCertificates';
export const createBlockEpochProvider =
(walletProvider: WalletProvider, retryBackoffConfig: RetryBackoffConfig) => (blockHashes: Cardano.BlockId[]) =>
coldObservableProvider(() => walletProvider.queryBlocksByHashes(blockHashes), retryBackoffConfig).pipe(
map((blocks) => blocks.map(({ epoch }) => epoch))
);
export type BlockEpochProvider = ReturnType<typeof createBlockEpochProvider>;
export interface DelegationTrackerProps {
walletProvider: WalletProvider;
rewardAccountAddresses$: Observable<Cardano.RewardAccount[]>;
stakePoolSearchProvider: StakePoolSearchProvider;
epoch$: Observable<Cardano.Epoch>;
transactionsTracker: TransactionsTracker;
retryBackoffConfig: RetryBackoffConfig;
internals?: {
queryStakePoolsProvider?: ObservableStakePoolSearchProvider;
rewardsProvider?: ObservableRewardsProvider;
rewardsHistoryProvider?: RewardsHistoryProvider;
blockEpochProvider?: BlockEpochProvider;
};
}
export const certificateTransactionsWithEpochs = (
transactionsTracker: TransactionsTracker,
blockEpochProvider: BlockEpochProvider,
certificateTypes: Cardano.CertificateType[]
): Observable<TxWithEpoch[]> =>
transactionsWithCertificates(transactionsTracker.history.outgoing$, certificateTypes).pipe(
switchMap((transactions) =>
blockEpochProvider(transactions.map((tx) => tx.blockHeader.blockHash)).pipe(
map((epochs) => transactions.map((tx, txIndex) => ({ epoch: epochs[txIndex], tx })))
)
),
share()
);
export const createDelegationTracker = ({
rewardAccountAddresses$,
epoch$,
walletProvider,
retryBackoffConfig,
transactionsTracker,
stakePoolSearchProvider,
internals: {
queryStakePoolsProvider = createQueryStakePoolsProvider(stakePoolSearchProvider, retryBackoffConfig),
rewardsHistoryProvider = createRewardsHistoryProvider(walletProvider, rewardAccountAddresses$, retryBackoffConfig),
rewardsProvider = createRewardsProvider(
epoch$,
transactionsTracker.outgoing.confirmed$,
walletProvider,
retryBackoffConfig
),
blockEpochProvider = createBlockEpochProvider(walletProvider, retryBackoffConfig)
} = {}
}: DelegationTrackerProps): DelegationTracker => {
const transactions$ = certificateTransactionsWithEpochs(transactionsTracker, blockEpochProvider, [
Cardano.CertificateType.StakeDelegation,
Cardano.CertificateType.StakeKeyRegistration,
Cardano.CertificateType.StakeKeyDeregistration
]);
const rewardsHistory$ = new TrackerSubject(createRewardsHistoryTracker(transactions$, rewardsHistoryProvider));
const rewardAccounts$ = new TrackerSubject(
createRewardAccountsTracker({
epoch$,
rewardAccountAddresses$,
rewardsProvider,
stakePoolSearchProvider: queryStakePoolsProvider,
transactions$,
transactionsInFlight$: transactionsTracker.outgoing.inFlight$
})
);
return {
rewardAccounts$,
rewardsHistory$,
shutdown: () => {
rewardAccounts$.complete();
rewardsHistory$.complete();
}
};
};