@cardano-sdk/e2e 0.45.4 → 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.45.4",
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",
@@ -23,7 +23,6 @@
23
23
  "load-test-custom:wallet-restoration": "ts-node test/load-test-custom/wallet-restoration/wallet-restoration.test.ts",
24
24
  "test": "echo 'test' command not implemented yet",
25
25
  "test:blockfrost": "jest -c jest.config.js --forceExit --selectProjects blockfrost --runInBand --verbose",
26
- "test:blockfrost:providers": "jest -c jest.config.js --forceExit --selectProjects blockfrost-providers --runInBand --verbose",
27
26
  "test:utils": "jest -c jest.config.js --forceExit --selectProjects utils --verbose",
28
27
  "test:long-running": "jest -c jest.config.js --forceExit --selectProjects long-running --runInBand --verbose",
29
28
  "test:local-network": "jest -c jest.config.js --forceExit --selectProjects local-network --runInBand --verbose",
@@ -76,20 +75,20 @@
76
75
  "dependencies": {
77
76
  "@cardano-foundation/ledgerjs-hw-app-cardano": "^7.1.4",
78
77
  "@cardano-ogmios/client": "6.9.0",
79
- "@cardano-sdk/cardano-services": "~0.32.3",
80
- "@cardano-sdk/cardano-services-client": "~0.22.3",
81
- "@cardano-sdk/core": "~0.41.4",
82
- "@cardano-sdk/crypto": "~0.1.31",
83
- "@cardano-sdk/hardware-ledger": "~0.12.13",
84
- "@cardano-sdk/hardware-trezor": "~0.6.12",
85
- "@cardano-sdk/input-selection": "~0.13.28",
86
- "@cardano-sdk/key-management": "~0.24.10",
87
- "@cardano-sdk/ogmios": "~0.18.13",
88
- "@cardano-sdk/tx-construction": "~0.21.13",
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
+ "@cardano-sdk/crypto": "~0.1.32",
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",
89
88
  "@cardano-sdk/util": "~0.15.5",
90
- "@cardano-sdk/util-dev": "~0.23.13",
91
- "@cardano-sdk/util-rxjs": "~0.7.41",
92
- "@cardano-sdk/wallet": "~0.44.22",
89
+ "@cardano-sdk/util-dev": "~0.24.0",
90
+ "@cardano-sdk/util-rxjs": "~0.7.43",
91
+ "@cardano-sdk/wallet": "~0.45.0",
93
92
  "@dcspark/cardano-multiplatform-lib-nodejs": "^3.1.1",
94
93
  "@shiroyasha9/axios-fetch-adapter": "1.0.3",
95
94
  "axios": "^1.7.4",
@@ -119,10 +118,10 @@
119
118
  "@babel/core": "^7.18.2",
120
119
  "@babel/preset-env": "^7.18.2",
121
120
  "@babel/preset-typescript": "^7.17.12",
122
- "@cardano-sdk/dapp-connector": "~0.12.44",
123
- "@cardano-sdk/projection": "~0.12.13",
124
- "@cardano-sdk/projection-typeorm": "~0.9.13",
125
- "@cardano-sdk/web-extension": "~0.34.21",
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",
126
125
  "@dcspark/cardano-multiplatform-lib-browser": "^3.1.1",
127
126
  "@emurgo/cardano-message-signing-asmjs": "^1.0.1",
128
127
  "@types/bunyan": "^1.8.8",
@@ -182,5 +181,5 @@
182
181
  "publishConfig": {
183
182
  "access": "public"
184
183
  },
185
- "gitHead": "f9d460a3fd97481bfb2fa5719a838b3521283907"
184
+ "gitHead": "cfb81dc2bf655e0a4d433b7c13a2aaa494510444"
186
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,
@@ -37,7 +38,13 @@ import {
37
38
  } from '@cardano-sdk/key-management';
38
39
  import {
39
40
  BlockfrostAssetProvider,
41
+ BlockfrostChainHistoryProvider,
40
42
  BlockfrostClient,
43
+ BlockfrostDRepProvider,
44
+ BlockfrostNetworkInfoProvider,
45
+ BlockfrostRewardsProvider,
46
+ BlockfrostTxSubmitProvider,
47
+ BlockfrostUtxoProvider,
41
48
  CardanoWsClient,
42
49
  assetInfoHttpProvider,
43
50
  chainHistoryHttpProvider,
@@ -76,6 +83,7 @@ export type CreateKeyAgent = (dependencies: KeyAgentDependencies) => Promise<Asy
76
83
  export const keyManagementFactory = new ProviderFactory<CreateKeyAgent>();
77
84
  export const assetProviderFactory = new ProviderFactory<AssetProvider>();
78
85
  export const chainHistoryProviderFactory = new ProviderFactory<ChainHistoryProvider>();
86
+ export const drepProviderFactory = new ProviderFactory<DRepProvider>();
79
87
  export const networkInfoProviderFactory = new ProviderFactory<NetworkInfoProvider>();
80
88
  export const rewardsProviderFactory = new ProviderFactory<RewardsProvider>();
81
89
  export const txSubmitProviderFactory = new ProviderFactory<TxSubmitProvider>();
@@ -162,6 +170,33 @@ chainHistoryProviderFactory.register(
162
170
  async (_params: any, logger: Logger) => (await getWsClient(logger)).chainHistoryProvider
163
171
  );
164
172
 
173
+ chainHistoryProviderFactory.register(BLOCKFROST_PROVIDER, async (params: any, logger) => {
174
+ if (params.baseUrl === undefined) throw new Error(`${BlockfrostChainHistoryProvider.name}: ${MISSING_URL_PARAM}`);
175
+
176
+ return new Promise(async (resolve) => {
177
+ resolve(
178
+ new BlockfrostChainHistoryProvider(
179
+ new BlockfrostClient({ baseUrl: params.baseUrl }, { rateLimiter: { schedule: (task) => task() } }),
180
+ await networkInfoProviderFactory.create('blockfrost', params, logger),
181
+ logger
182
+ )
183
+ );
184
+ });
185
+ });
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
+
165
200
  networkInfoProviderFactory.register(
166
201
  HTTP_PROVIDER,
167
202
  async (params: any, logger: Logger): Promise<NetworkInfoProvider> => {
@@ -178,6 +213,19 @@ networkInfoProviderFactory.register(
178
213
  async (_params: any, logger: Logger) => (await getWsClient(logger)).networkInfoProvider
179
214
  );
180
215
 
216
+ networkInfoProviderFactory.register(BLOCKFROST_PROVIDER, async (params: any, logger) => {
217
+ if (params.baseUrl === undefined) throw new Error(`${BlockfrostNetworkInfoProvider.name}: ${MISSING_URL_PARAM}`);
218
+
219
+ return new Promise(async (resolve) => {
220
+ resolve(
221
+ new BlockfrostNetworkInfoProvider(
222
+ new BlockfrostClient({ baseUrl: params.baseUrl }, { rateLimiter: { schedule: (task) => task() } }),
223
+ logger
224
+ )
225
+ );
226
+ });
227
+ });
228
+
181
229
  rewardsProviderFactory.register(HTTP_PROVIDER, async (params: any, logger: Logger): Promise<RewardsProvider> => {
182
230
  if (params.baseUrl === undefined) throw new Error(`${rewardsHttpProvider.name}: ${MISSING_URL_PARAM}`);
183
231
 
@@ -186,6 +234,19 @@ rewardsProviderFactory.register(HTTP_PROVIDER, async (params: any, logger: Logge
186
234
  });
187
235
  });
188
236
 
237
+ rewardsProviderFactory.register(BLOCKFROST_PROVIDER, async (params: any, logger) => {
238
+ if (params.baseUrl === undefined) throw new Error(`${BlockfrostRewardsProvider.name}: ${MISSING_URL_PARAM}`);
239
+
240
+ return new Promise(async (resolve) => {
241
+ resolve(
242
+ new BlockfrostRewardsProvider(
243
+ new BlockfrostClient({ baseUrl: params.baseUrl }, { rateLimiter: { schedule: (task) => task() } }),
244
+ logger
245
+ )
246
+ );
247
+ });
248
+ });
249
+
189
250
  txSubmitProviderFactory.register(OGMIOS_PROVIDER, async (params: any, logger: Logger): Promise<TxSubmitProvider> => {
190
251
  if (params.baseUrl === undefined) throw new Error(`${NodeTxSubmitProvider.name}: ${MISSING_URL_PARAM}`);
191
252
 
@@ -220,6 +281,19 @@ txSubmitProviderFactory.register(HTTP_PROVIDER, async (params: any, logger: Logg
220
281
  });
221
282
  });
222
283
 
284
+ txSubmitProviderFactory.register(BLOCKFROST_PROVIDER, async (params: any, logger) => {
285
+ if (params.baseUrl === undefined) throw new Error(`${BlockfrostTxSubmitProvider.name}: ${MISSING_URL_PARAM}`);
286
+
287
+ return new Promise(async (resolve) => {
288
+ resolve(
289
+ new BlockfrostTxSubmitProvider(
290
+ new BlockfrostClient({ baseUrl: params.baseUrl }, { rateLimiter: { schedule: (task) => task() } }),
291
+ logger
292
+ )
293
+ );
294
+ });
295
+ });
296
+
223
297
  utxoProviderFactory.register(HTTP_PROVIDER, async (params: any, logger: Logger): Promise<UtxoProvider> => {
224
298
  if (params.baseUrl === undefined) throw new Error(`${utxoHttpProvider.name}: ${MISSING_URL_PARAM}`);
225
299
 
@@ -233,6 +307,19 @@ utxoProviderFactory.register(
233
307
  async (_params: any, logger: Logger) => (await getWsClient(logger)).utxoProvider
234
308
  );
235
309
 
310
+ utxoProviderFactory.register(BLOCKFROST_PROVIDER, async (params: any, logger) => {
311
+ if (params.baseUrl === undefined) throw new Error(`${BlockfrostUtxoProvider.name}: ${MISSING_URL_PARAM}`);
312
+
313
+ return new Promise(async (resolve) => {
314
+ resolve(
315
+ new BlockfrostUtxoProvider(
316
+ new BlockfrostClient({ baseUrl: params.baseUrl }, { rateLimiter: { schedule: (task) => task() } }),
317
+ logger
318
+ )
319
+ );
320
+ });
321
+ });
322
+
236
323
  handleProviderFactory.register(HTTP_PROVIDER, async (params: any, logger: Logger): Promise<HandleProvider> => {
237
324
  if (params.baseUrl === undefined) throw new Error(`${handleHttpProvider.name}: ${MISSING_URL_PARAM}`);
238
325
 
@@ -412,6 +499,11 @@ export const getWallet = async (props: GetWalletProps) => {
412
499
  env.TEST_CLIENT_CHAIN_HISTORY_PROVIDER_PARAMS,
413
500
  logger
414
501
  ),
502
+ drepProvider: await drepProviderFactory.create(
503
+ env.TEST_CLIENT_DREP_PROVIDER,
504
+ env.TEST_CLIENT_DREP_PROVIDER_PARAMS,
505
+ logger
506
+ ),
415
507
  handleProvider: await handleProviderFactory.create(
416
508
  env.TEST_CLIENT_HANDLE_PROVIDER,
417
509
  env.TEST_CLIENT_HANDLE_PROVIDER_PARAMS,
@@ -500,6 +592,11 @@ export const getSharedWallet = async (props: GetSharedWalletProps) => {
500
592
  env.TEST_CLIENT_CHAIN_HISTORY_PROVIDER_PARAMS,
501
593
  logger
502
594
  ),
595
+ drepProvider: await drepProviderFactory.create(
596
+ env.TEST_CLIENT_DREP_PROVIDER,
597
+ env.TEST_CLIENT_DREP_PROVIDER_PARAMS,
598
+ logger
599
+ ),
503
600
  handleProvider: await handleProviderFactory.create(
504
601
  env.TEST_CLIENT_HANDLE_PROVIDER,
505
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
@@ -1,18 +1,13 @@
1
- import { BlockfrostChainHistoryProvider, BlockfrostNetworkInfoProvider, util } from '@cardano-sdk/cardano-services';
1
+ import { BlockfrostChainHistoryProvider, BlockfrostNetworkInfoProvider } from '@cardano-sdk/cardano-services-client';
2
2
  import { Cardano, ChainHistoryProvider } from '@cardano-sdk/core';
3
3
  import { logger } from '@cardano-sdk/util-dev';
4
+ import { util } from '@cardano-sdk/cardano-services';
4
5
 
5
6
  describe.only('BlockfrostChainHistoryProvider', () => {
6
7
  let chainHistoryProvider: ChainHistoryProvider;
7
- let blockfrost;
8
8
  beforeAll(async () => {
9
- blockfrost = util.getBlockfrostApi();
10
- const networkInfoProvider = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
11
- chainHistoryProvider = new BlockfrostChainHistoryProvider({
12
- blockfrost,
13
- logger,
14
- networkInfoProvider
15
- });
9
+ const networkInfoProvider = new BlockfrostNetworkInfoProvider(util.getBlockfrostClient(), logger);
10
+ chainHistoryProvider = new BlockfrostChainHistoryProvider(util.getBlockfrostClient(), networkInfoProvider, logger);
16
11
  });
17
12
 
18
13
  describe('transactionsByHashes', () => {
@@ -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,
@@ -139,6 +139,7 @@ describe('PersonalWallet/multiAddress', () => {
139
139
  expect(returnAdaTxFoundInHistory.id).toEqual(returnAdaSignedTx.id);
140
140
  expect(normalizeTxBody(returnAdaTxFoundInHistory.body)).toEqual(normalizeTxBody(returnAdaSignedTx.body));
141
141
 
142
+ await walletReady(newWallet.wallet);
142
143
  const endingBalance = await firstValueFromTimed(newWallet.wallet.balance.utxo.total$);
143
144
  const expectedEndingBalance = 1_500_000n - returnAdaTxFoundInHistory.body.fee;
144
145
 
@@ -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
+ });
@@ -1,26 +0,0 @@
1
- // cSpell:ignore cardano utxos
2
-
3
- import { NetworkInfoProvider } from '@cardano-sdk/core';
4
- import { logger } from '@cardano-sdk/util-dev';
5
- import { networkInfoHttpProvider } from '@cardano-sdk/cardano-services-client';
6
- import { toSerializableObject } from '@cardano-sdk/util';
7
-
8
- // LW-11858 to enable this
9
- describe.skip('Web Socket', () => {
10
- const legacyProvider = networkInfoHttpProvider({ baseUrl: 'http://localhost:4000/', logger });
11
- const provider = networkInfoHttpProvider({ baseUrl: 'http://localhost:4001/', logger });
12
-
13
- const methods: (keyof NetworkInfoProvider)[] = [
14
- 'eraSummaries',
15
- 'genesisParameters',
16
- 'lovelaceSupply',
17
- 'protocolParameters',
18
- 'stake'
19
- ];
20
-
21
- test.each(methods)('compare %s', async (method) => {
22
- const [legacyResponse, response] = await Promise.all([legacyProvider[method](), provider[method]()]);
23
-
24
- expect(toSerializableObject(response)).toEqual(toSerializableObject(legacyResponse));
25
- });
26
- });