@cardano-sdk/e2e 0.46.0 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardano-sdk/e2e",
3
- "version": "0.46.0",
3
+ "version": "0.47.0",
4
4
  "description": "End to end tests for the cardano-js-sdk packages.",
5
5
  "repository": "https://github.com/input-output-hk/cardano-js-sdk",
6
6
  "license": "Apache-2.0",
@@ -75,20 +75,20 @@
75
75
  "dependencies": {
76
76
  "@cardano-foundation/ledgerjs-hw-app-cardano": "^7.1.4",
77
77
  "@cardano-ogmios/client": "6.9.0",
78
- "@cardano-sdk/cardano-services": "~0.33.0",
79
- "@cardano-sdk/cardano-services-client": "~0.23.0",
80
- "@cardano-sdk/core": "~0.41.5",
78
+ "@cardano-sdk/cardano-services": "~0.33.1",
79
+ "@cardano-sdk/cardano-services-client": "~0.23.1",
80
+ "@cardano-sdk/core": "~0.42.0",
81
81
  "@cardano-sdk/crypto": "~0.1.32",
82
- "@cardano-sdk/hardware-ledger": "~0.12.14",
83
- "@cardano-sdk/hardware-trezor": "~0.6.13",
84
- "@cardano-sdk/input-selection": "~0.13.29",
85
- "@cardano-sdk/key-management": "~0.24.11",
86
- "@cardano-sdk/ogmios": "~0.18.14",
87
- "@cardano-sdk/tx-construction": "~0.21.14",
82
+ "@cardano-sdk/hardware-ledger": "~0.12.15",
83
+ "@cardano-sdk/hardware-trezor": "~0.6.14",
84
+ "@cardano-sdk/input-selection": "~0.13.30",
85
+ "@cardano-sdk/key-management": "~0.24.12",
86
+ "@cardano-sdk/ogmios": "~0.18.15",
87
+ "@cardano-sdk/tx-construction": "~0.22.0",
88
88
  "@cardano-sdk/util": "~0.15.5",
89
- "@cardano-sdk/util-dev": "~0.23.14",
90
- "@cardano-sdk/util-rxjs": "~0.7.42",
91
- "@cardano-sdk/wallet": "~0.44.23",
89
+ "@cardano-sdk/util-dev": "~0.24.0",
90
+ "@cardano-sdk/util-rxjs": "~0.7.43",
91
+ "@cardano-sdk/wallet": "~0.45.0",
92
92
  "@dcspark/cardano-multiplatform-lib-nodejs": "^3.1.1",
93
93
  "@shiroyasha9/axios-fetch-adapter": "1.0.3",
94
94
  "axios": "^1.7.4",
@@ -118,10 +118,10 @@
118
118
  "@babel/core": "^7.18.2",
119
119
  "@babel/preset-env": "^7.18.2",
120
120
  "@babel/preset-typescript": "^7.17.12",
121
- "@cardano-sdk/dapp-connector": "~0.12.45",
122
- "@cardano-sdk/projection": "~0.12.14",
123
- "@cardano-sdk/projection-typeorm": "~0.9.14",
124
- "@cardano-sdk/web-extension": "~0.34.22",
121
+ "@cardano-sdk/dapp-connector": "~0.12.46",
122
+ "@cardano-sdk/projection": "~0.12.15",
123
+ "@cardano-sdk/projection-typeorm": "~0.9.15",
124
+ "@cardano-sdk/web-extension": "~0.34.23",
125
125
  "@dcspark/cardano-multiplatform-lib-browser": "^3.1.1",
126
126
  "@emurgo/cardano-message-signing-asmjs": "^1.0.1",
127
127
  "@types/bunyan": "^1.8.8",
@@ -181,5 +181,5 @@
181
181
  "publishConfig": {
182
182
  "access": "public"
183
183
  },
184
- "gitHead": "379316d14c7774d2b7ef4ca726ed983f07568611"
184
+ "gitHead": "cfb81dc2bf655e0a4d433b7c13a2aaa494510444"
185
185
  }
@@ -92,6 +92,8 @@ const validators = {
92
92
  TEST_CLIENT_ASSET_PROVIDER_PARAMS: providerParams(),
93
93
  TEST_CLIENT_CHAIN_HISTORY_PROVIDER: str(),
94
94
  TEST_CLIENT_CHAIN_HISTORY_PROVIDER_PARAMS: providerParams(),
95
+ TEST_CLIENT_DREP_PROVIDER: str({ choices: ['blockfrost'] }),
96
+ TEST_CLIENT_DREP_PROVIDER_PARAMS: providerParams(),
95
97
  TEST_CLIENT_HANDLE_PROVIDER: str(),
96
98
  TEST_CLIENT_HANDLE_PROVIDER_PARAMS: providerParams(),
97
99
  TEST_CLIENT_NETWORK_INFO_PROVIDER: str(),
@@ -145,6 +147,8 @@ export const walletVariables = [
145
147
  'TEST_CLIENT_ASSET_PROVIDER_PARAMS',
146
148
  'TEST_CLIENT_CHAIN_HISTORY_PROVIDER',
147
149
  'TEST_CLIENT_CHAIN_HISTORY_PROVIDER_PARAMS',
150
+ 'TEST_CLIENT_DREP_PROVIDER',
151
+ 'TEST_CLIENT_DREP_PROVIDER_PARAMS',
148
152
  'TEST_CLIENT_HANDLE_PROVIDER',
149
153
  'TEST_CLIENT_HANDLE_PROVIDER_PARAMS',
150
154
  'KEY_MANAGEMENT_PARAMS',
package/src/factories.ts CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  AssetProvider,
19
19
  Cardano,
20
20
  ChainHistoryProvider,
21
+ DRepProvider,
21
22
  HandleProvider,
22
23
  NetworkInfoProvider,
23
24
  ProviderFactory,
@@ -39,6 +40,7 @@ import {
39
40
  BlockfrostAssetProvider,
40
41
  BlockfrostChainHistoryProvider,
41
42
  BlockfrostClient,
43
+ BlockfrostDRepProvider,
42
44
  BlockfrostNetworkInfoProvider,
43
45
  BlockfrostRewardsProvider,
44
46
  BlockfrostTxSubmitProvider,
@@ -81,6 +83,7 @@ export type CreateKeyAgent = (dependencies: KeyAgentDependencies) => Promise<Asy
81
83
  export const keyManagementFactory = new ProviderFactory<CreateKeyAgent>();
82
84
  export const assetProviderFactory = new ProviderFactory<AssetProvider>();
83
85
  export const chainHistoryProviderFactory = new ProviderFactory<ChainHistoryProvider>();
86
+ export const drepProviderFactory = new ProviderFactory<DRepProvider>();
84
87
  export const networkInfoProviderFactory = new ProviderFactory<NetworkInfoProvider>();
85
88
  export const rewardsProviderFactory = new ProviderFactory<RewardsProvider>();
86
89
  export const txSubmitProviderFactory = new ProviderFactory<TxSubmitProvider>();
@@ -181,6 +184,19 @@ chainHistoryProviderFactory.register(BLOCKFROST_PROVIDER, async (params: any, lo
181
184
  });
182
185
  });
183
186
 
187
+ drepProviderFactory.register(BLOCKFROST_PROVIDER, async (params: any, logger): Promise<DRepProvider> => {
188
+ if (params.baseUrl === undefined) throw new Error(`${BlockfrostDRepProvider.name}: ${MISSING_URL_PARAM}`);
189
+
190
+ return new Promise<DRepProvider>(async (resolve) => {
191
+ resolve(
192
+ new BlockfrostDRepProvider(
193
+ new BlockfrostClient({ baseUrl: params.baseUrl }, { rateLimiter: { schedule: (task) => task() } }),
194
+ logger
195
+ )
196
+ );
197
+ });
198
+ });
199
+
184
200
  networkInfoProviderFactory.register(
185
201
  HTTP_PROVIDER,
186
202
  async (params: any, logger: Logger): Promise<NetworkInfoProvider> => {
@@ -483,6 +499,11 @@ export const getWallet = async (props: GetWalletProps) => {
483
499
  env.TEST_CLIENT_CHAIN_HISTORY_PROVIDER_PARAMS,
484
500
  logger
485
501
  ),
502
+ drepProvider: await drepProviderFactory.create(
503
+ env.TEST_CLIENT_DREP_PROVIDER,
504
+ env.TEST_CLIENT_DREP_PROVIDER_PARAMS,
505
+ logger
506
+ ),
486
507
  handleProvider: await handleProviderFactory.create(
487
508
  env.TEST_CLIENT_HANDLE_PROVIDER,
488
509
  env.TEST_CLIENT_HANDLE_PROVIDER_PARAMS,
@@ -571,6 +592,11 @@ export const getSharedWallet = async (props: GetSharedWalletProps) => {
571
592
  env.TEST_CLIENT_CHAIN_HISTORY_PROVIDER_PARAMS,
572
593
  logger
573
594
  ),
595
+ drepProvider: await drepProviderFactory.create(
596
+ env.TEST_CLIENT_DREP_PROVIDER,
597
+ env.TEST_CLIENT_DREP_PROVIDER_PARAMS,
598
+ logger
599
+ ),
574
600
  handleProvider: await handleProviderFactory.create(
575
601
  env.TEST_CLIENT_HANDLE_PROVIDER,
576
602
  env.TEST_CLIENT_HANDLE_PROVIDER_PARAMS,
@@ -40,6 +40,9 @@ TEST_CLIENT_ASSET_PROVIDER=http
40
40
  TEST_CLIENT_ASSET_PROVIDER_PARAMS='{\"baseUrl\":\"${url}\"}'
41
41
  TEST_CLIENT_CHAIN_HISTORY_PROVIDER=ws
42
42
  TEST_CLIENT_CHAIN_HISTORY_PROVIDER_PARAMS='{\"baseUrl\":\"${url}\"}'
43
+ TEST_CLIENT_DREP_PROVIDER: 'blockfrost'
44
+ # TODO: use blockfrost URL
45
+ TEST_CLIENT_DREP_PROVIDER_PARAMS: '{"baseUrl":"http://localhost:3015"}'
43
46
  TEST_CLIENT_HANDLE_PROVIDER=http
44
47
  TEST_CLIENT_HANDLE_PROVIDER_PARAMS='{\"baseUrl\":\"${url}\"}'
45
48
  TEST_CLIENT_NETWORK_INFO_PROVIDER=ws
@@ -16,6 +16,7 @@ import {
16
16
  assetProviderFactory,
17
17
  bip32Ed25519Factory,
18
18
  chainHistoryProviderFactory,
19
+ drepProviderFactory,
19
20
  getEnv,
20
21
  getLoadTestScheduler,
21
22
  keyManagementFactory,
@@ -55,6 +56,11 @@ const getProviders = async () => ({
55
56
  env.TEST_CLIENT_CHAIN_HISTORY_PROVIDER_PARAMS,
56
57
  logger
57
58
  ),
59
+ drepProvider: await drepProviderFactory.create(
60
+ env.TEST_CLIENT_DREP_PROVIDER,
61
+ env.TEST_CLIENT_DREP_PROVIDER_PARAMS,
62
+ logger
63
+ ),
58
64
  networkInfoProvider: await networkInfoProviderFactory.create(
59
65
  env.TEST_CLIENT_NETWORK_INFO_PROVIDER,
60
66
  env.TEST_CLIENT_NETWORK_INFO_PROVIDER_PARAMS,
@@ -0,0 +1,296 @@
1
+ /* eslint-disable unicorn/consistent-destructuring */
2
+
3
+ import * as Crypto from '@cardano-sdk/crypto';
4
+ import { BaseWallet } from '@cardano-sdk/wallet';
5
+ import { Cardano, setInConwayEra } from '@cardano-sdk/core';
6
+ import { logger } from '@cardano-sdk/util-dev';
7
+
8
+ import { filter, firstValueFrom, map } from 'rxjs';
9
+ import {
10
+ firstValueFromTimed,
11
+ getEnv,
12
+ getWallet,
13
+ submitAndConfirm,
14
+ unDelegateWallet,
15
+ waitForWalletStateSettle,
16
+ walletReady,
17
+ walletVariables
18
+ } from '../../../src';
19
+
20
+ /*
21
+ Test that rewardAccounts$ drepDelegatees are updated when dreps retire, provided one of the following conditions are met:
22
+ - a transaction build is attempted
23
+ - drepDelegatees change, new ones are added, old ones removed
24
+ Both of these actions trigger a refetch for all dreps found in drepDelegatees.
25
+
26
+ Setup:
27
+ - create three accounts (wallet, drepWallet, drepWallet2)
28
+ - drep* wallets register as dreps
29
+ - wallet delegates to 2 stake pools, resulting in 2 registered stake keys
30
+ - wallet delegates voting power: stakeKey1 & stakeKey2 to drepWallet & drepWallet2 respectively
31
+ - Expect to see DRep1 & DRep2 in drepDelegatees
32
+ - DRep1 retires - no change in drepDelegatees because a refresh was not triggered
33
+ - Build a transaction with wallet, but do not submit
34
+ - Expect to see DRep1 removed from drepDelegatees
35
+ - DRep2 retires - no change in drepDelegatees because a refresh was not triggered
36
+ - Using another instance of the wallet, delegate stakeKey1 to AlwaysAbstain
37
+ - Original wallet detects the change of delegatees according to tx history, which triggers a refetch for all dreps
38
+ - Expect DRep2 to be removed from drepDelegatees
39
+ */
40
+
41
+ const { CertificateType, CredentialType, RewardAccount, StakePoolStatus } = Cardano;
42
+
43
+ const env = getEnv(walletVariables);
44
+
45
+ const anchor = {
46
+ dataHash: '3e33018e8293d319ef5b3ac72366dd28006bd315b715f7e7cfcbd3004129b80d' as Crypto.Hash32ByteBase16,
47
+ url: 'https://testing.this'
48
+ };
49
+
50
+ const getTestWallet = async (idx: number, name: string, minCoinBalance?: bigint) => {
51
+ const { wallet } = await getWallet({ env, idx, logger, name, polling: { interval: 50 } });
52
+
53
+ await walletReady(wallet, minCoinBalance);
54
+
55
+ return wallet;
56
+ };
57
+
58
+ describe('PersonalWallet/drepRetirement', () => {
59
+ let dRepWallet1: BaseWallet;
60
+ let dRepWallet2: BaseWallet;
61
+ let delegatingWallet: BaseWallet;
62
+
63
+ let dRepCredential1: Cardano.Credential & { type: Cardano.CredentialType.KeyHash };
64
+ let drepId1: Cardano.DRepID;
65
+ let dRepCredential2: Cardano.Credential & { type: Cardano.CredentialType.KeyHash };
66
+ let drepId2: Cardano.DRepID;
67
+ let poolId1: Cardano.PoolId;
68
+ let poolId2: Cardano.PoolId;
69
+ let stakeCredential1: Cardano.Credential;
70
+ let stakeCredential2: Cardano.Credential;
71
+
72
+ let dRepDeposit: bigint;
73
+
74
+ const getDRepCredential = async (wallet: BaseWallet) => {
75
+ const drepPubKey = await wallet.governance.getPubDRepKey();
76
+ const dRepKeyHash = Crypto.Hash28ByteBase16.fromEd25519KeyHashHex(
77
+ (await Crypto.Ed25519PublicKey.fromHex(drepPubKey!).hash()).hex()
78
+ );
79
+
80
+ return { hash: dRepKeyHash, type: CredentialType.KeyHash } as typeof dRepCredential1;
81
+ };
82
+
83
+ const getDeposits = async () => {
84
+ const protocolParameters = await delegatingWallet.networkInfoProvider.protocolParameters();
85
+
86
+ return [
87
+ BigInt(protocolParameters.dRepDeposit!),
88
+ BigInt(protocolParameters.governanceActionDeposit!),
89
+ BigInt(protocolParameters.stakeKeyDeposit)
90
+ ];
91
+ };
92
+
93
+ const getPoolIds = async () => {
94
+ const activePools = await delegatingWallet.stakePoolProvider.queryStakePools({
95
+ filters: { status: [StakePoolStatus.Active] },
96
+ pagination: { limit: 2, startAt: 0 }
97
+ });
98
+
99
+ return activePools.pageResults.map(({ id }) => id);
100
+ };
101
+
102
+ const getStakeCredential = async () => {
103
+ const rewardAccounts = await firstValueFrom(
104
+ delegatingWallet.addresses$.pipe(map((addresses) => addresses.map(({ rewardAccount }) => rewardAccount)))
105
+ );
106
+
107
+ return rewardAccounts.map((rewardAccount) => ({
108
+ hash: Crypto.Hash28ByteBase16.fromEd25519KeyHashHex(RewardAccount.toHash(rewardAccount)),
109
+ type: CredentialType.KeyHash
110
+ }));
111
+ };
112
+
113
+ const feedDRepWallet = async (dRepWallet: BaseWallet, amount: bigint) => {
114
+ const balance = await firstValueFrom(dRepWallet.balance.utxo.total$);
115
+
116
+ if (balance.coins > amount) return;
117
+
118
+ const address = await firstValueFrom(dRepWallet.addresses$.pipe(map((addresses) => addresses[0].address)));
119
+
120
+ const signedTx = await delegatingWallet
121
+ .createTxBuilder()
122
+ .addOutput({ address, value: { coins: amount } })
123
+ .build()
124
+ .sign();
125
+
126
+ await submitAndConfirm(delegatingWallet, signedTx.tx, 1);
127
+ };
128
+
129
+ const sendDRepRegCert = async (dRepWallet: BaseWallet, register: boolean) => {
130
+ const dRepCredential = await getDRepCredential(dRepWallet);
131
+ const common = { dRepCredential, deposit: dRepDeposit };
132
+ const dRepUnRegCert: Cardano.UnRegisterDelegateRepresentativeCertificate = {
133
+ __typename: CertificateType.UnregisterDelegateRepresentative,
134
+ ...common
135
+ };
136
+ const dRepRegCert: Cardano.RegisterDelegateRepresentativeCertificate = {
137
+ __typename: CertificateType.RegisterDelegateRepresentative,
138
+ anchor,
139
+ ...common
140
+ };
141
+ const certificate = register ? dRepRegCert : dRepUnRegCert;
142
+ const signedTx = await dRepWallet
143
+ .createTxBuilder()
144
+ .customize(({ txBody }) => ({ ...txBody, certificates: [certificate] }))
145
+ .build()
146
+ .sign();
147
+ await submitAndConfirm(dRepWallet, signedTx.tx, 1);
148
+ };
149
+
150
+ const isRegisteredDRep = async (wallet: BaseWallet) => {
151
+ await waitForWalletStateSettle(wallet);
152
+ return await firstValueFrom(wallet.governance.isRegisteredAsDRep$);
153
+ };
154
+
155
+ beforeAll(async () => {
156
+ // TODO: remove once mainnet hardforks to conway-era, and this becomes "the norm"
157
+ setInConwayEra(true);
158
+
159
+ [delegatingWallet, dRepWallet1, dRepWallet2] = await Promise.all([
160
+ getTestWallet(0, 'wallet-delegating', 100_000_000n),
161
+ getTestWallet(1, 'wallet-DRep1', 0n),
162
+ getTestWallet(2, 'wallet-DRep2', 0n)
163
+ ]);
164
+
165
+ [dRepCredential1, dRepCredential2, [dRepDeposit], [poolId1, poolId2]] = await Promise.all([
166
+ getDRepCredential(dRepWallet1),
167
+ getDRepCredential(dRepWallet2),
168
+ getDeposits(),
169
+ getPoolIds()
170
+ ]);
171
+
172
+ drepId1 = Cardano.DRepID.cip129FromCredential(dRepCredential1);
173
+ drepId2 = Cardano.DRepID.cip129FromCredential(dRepCredential2);
174
+
175
+ await feedDRepWallet(dRepWallet1, dRepDeposit * 2n);
176
+ await feedDRepWallet(dRepWallet2, dRepDeposit * 2n);
177
+
178
+ if (!(await isRegisteredDRep(dRepWallet1))) await sendDRepRegCert(dRepWallet1, true);
179
+ if (!(await isRegisteredDRep(dRepWallet2))) await sendDRepRegCert(dRepWallet2, true);
180
+
181
+ const txBuilder = delegatingWallet.createTxBuilder().delegatePortfolio({
182
+ name: 'Test Portfolio',
183
+ pools: [
184
+ { id: Cardano.PoolIdHex(Cardano.PoolId.toKeyHash(poolId1)), weight: 1 },
185
+ { id: Cardano.PoolIdHex(Cardano.PoolId.toKeyHash(poolId2)), weight: 1 }
186
+ ]
187
+ });
188
+ const poolDelegationTx = await txBuilder.build().sign();
189
+ await submitAndConfirm(delegatingWallet, poolDelegationTx.tx, 1);
190
+
191
+ [stakeCredential1, stakeCredential2] = await getStakeCredential();
192
+ });
193
+
194
+ afterAll(async () => {
195
+ if (await isRegisteredDRep(dRepWallet1)) await sendDRepRegCert(dRepWallet1, false);
196
+ if (await isRegisteredDRep(dRepWallet2)) await sendDRepRegCert(dRepWallet2, false);
197
+ await unDelegateWallet(delegatingWallet);
198
+
199
+ delegatingWallet.shutdown();
200
+ dRepWallet1.shutdown();
201
+ dRepWallet2.shutdown();
202
+
203
+ // TODO: remove once mainnet hardforks to conway-era, and this becomes "the norm"
204
+ setInConwayEra(false);
205
+ });
206
+
207
+ it('emits drepDelegatees after delegating voting power', async () => {
208
+ const voteDelegCert1: Cardano.VoteDelegationCertificate = {
209
+ __typename: CertificateType.VoteDelegation,
210
+ dRep: dRepCredential1,
211
+ stakeCredential: stakeCredential1
212
+ };
213
+ const voteDelegCert2: Cardano.VoteDelegationCertificate = {
214
+ __typename: CertificateType.VoteDelegation,
215
+ dRep: dRepCredential2,
216
+ stakeCredential: stakeCredential2
217
+ };
218
+
219
+ const signedTx = await delegatingWallet
220
+ .createTxBuilder()
221
+ .customize(({ txBody }) => ({ ...txBody, certificates: [voteDelegCert1, voteDelegCert2] }))
222
+ .build()
223
+ .sign();
224
+ await submitAndConfirm(delegatingWallet, signedTx.tx, 1);
225
+
226
+ const drepDelegatees = await firstValueFrom(
227
+ delegatingWallet.delegation.rewardAccounts$.pipe(
228
+ map((accounts) => accounts.map(({ dRepDelegatee }) => dRepDelegatee))
229
+ )
230
+ );
231
+
232
+ expect(drepDelegatees).toEqual([
233
+ { delegateRepresentative: expect.objectContaining({ active: true, id: drepId1 }) },
234
+ { delegateRepresentative: expect.objectContaining({ active: true, id: drepId2 }) }
235
+ ]);
236
+ });
237
+
238
+ it('transaction build triggers detection of retired DRep', async () => {
239
+ // Retire DRep1
240
+ await sendDRepRegCert(dRepWallet1, false);
241
+
242
+ // Only build and inspect to trigger the refetch of drep infos
243
+ await delegatingWallet.createTxBuilder().delegatePortfolio(null).build().inspect();
244
+
245
+ const drepDelegatees = await firstValueFrom(
246
+ delegatingWallet.delegation.rewardAccounts$.pipe(
247
+ map((accounts) => accounts.map(({ dRepDelegatee }) => dRepDelegatee))
248
+ )
249
+ );
250
+
251
+ expect(drepDelegatees).toEqual([
252
+ { delegateRepresentative: expect.objectContaining({ active: false, id: drepId1 }) },
253
+ { delegateRepresentative: expect.objectContaining({ active: true, amount: 0n, hasScript: false, id: drepId2 }) }
254
+ ]);
255
+ });
256
+
257
+ it('tx history vote delegation change triggers refresh of all delegations', async () => {
258
+ // Retire DRep2
259
+ await sendDRepRegCert(dRepWallet2, false);
260
+
261
+ // Create a clone of the delegatingWallet and change drep delegation.
262
+ // The delegatingWallet tx history will update, which will trigger a refetch of all dreps, including DRep2 which was retired.
263
+ const delegatingWalletClone = await getTestWallet(0, 'wallet-delegating-clone', 0n);
264
+ const signedTx = await delegatingWalletClone
265
+ .createTxBuilder()
266
+ .customize(({ txBody }) => ({
267
+ ...txBody,
268
+ certificates: [
269
+ {
270
+ __typename: CertificateType.VoteDelegation,
271
+ dRep: { __typename: 'AlwaysAbstain' },
272
+ stakeCredential: stakeCredential1
273
+ } as Cardano.VoteDelegationCertificate
274
+ ]
275
+ }))
276
+ .build()
277
+ .sign();
278
+ await submitAndConfirm(delegatingWalletClone, signedTx.tx, 1);
279
+
280
+ const drepDelegatees = await firstValueFromTimed(
281
+ delegatingWallet.delegation.rewardAccounts$.pipe(
282
+ map((accounts) => accounts.map(({ dRepDelegatee }) => dRepDelegatee)),
283
+ filter(
284
+ ([firstDelegatee]) =>
285
+ !!firstDelegatee?.delegateRepresentative &&
286
+ Cardano.isDRepAlwaysAbstain(firstDelegatee.delegateRepresentative)
287
+ )
288
+ )
289
+ );
290
+
291
+ expect(drepDelegatees).toEqual([
292
+ { delegateRepresentative: { __typename: 'AlwaysAbstain' } },
293
+ { delegateRepresentative: expect.objectContaining({ active: false, amount: 0n, hasScript: false, id: drepId2 }) }
294
+ ]);
295
+ });
296
+ });