@cardano-sdk/e2e 0.36.0 → 0.36.2
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/.env.example +5 -0
- package/CHANGELOG.md +10 -0
- package/dist/cjs/factories.d.ts.map +1 -1
- package/dist/cjs/factories.js +10 -5
- package/dist/cjs/factories.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/util/createMockKeyAgent.d.ts.map +1 -1
- package/dist/cjs/util/createMockKeyAgent.js +3 -1
- package/dist/cjs/util/createMockKeyAgent.js.map +1 -1
- package/dist/cjs/util/util.d.ts +2 -2
- package/dist/cjs/util/util.d.ts.map +1 -1
- package/dist/cjs/util/util.js +5 -4
- package/dist/cjs/util/util.js.map +1 -1
- package/dist/esm/factories.d.ts.map +1 -1
- package/dist/esm/factories.js +11 -6
- package/dist/esm/factories.js.map +1 -1
- package/dist/esm/index.d.ts +6 -6
- package/dist/esm/index.js +6 -6
- package/dist/esm/scripts/mnemonic.js +1 -1
- package/dist/esm/tools/multi-delegation-data-gen/index.js +2 -2
- package/dist/esm/tools/multi-delegation-data-gen/utils/index.d.ts +4 -4
- package/dist/esm/tools/multi-delegation-data-gen/utils/index.js +4 -4
- package/dist/esm/tools/multi-delegation-data-gen/utils/utils.d.ts +2 -2
- package/dist/esm/tools/multi-delegation-data-gen/utils/utils.js +4 -4
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/util/createMockKeyAgent.d.ts.map +1 -1
- package/dist/esm/util/createMockKeyAgent.js +4 -2
- package/dist/esm/util/createMockKeyAgent.js.map +1 -1
- package/dist/esm/util/handle-util.js +1 -1
- package/dist/esm/util/index.d.ts +4 -4
- package/dist/esm/util/index.js +4 -4
- package/dist/esm/util/util.d.ts +3 -3
- package/dist/esm/util/util.d.ts.map +1 -1
- package/dist/esm/util/util.js +7 -6
- package/dist/esm/util/util.js.map +1 -1
- package/docker-compose.yml +1 -0
- package/local-network/Dockerfile +7 -9
- package/local-network/scripts/clean.sh +1 -3
- package/local-network/scripts/install.sh +4 -4
- package/local-network/scripts/make-babbage.sh +36 -6
- package/local-network/scripts/mint-handles.sh +2 -4
- package/local-network/scripts/mint-tokens.sh +1 -2
- package/local-network/scripts/plutus-transaction.sh +5 -12
- package/local-network/scripts/pools/update-node-utils.sh +1 -2
- package/local-network/scripts/reference-input-transaction.sh +10 -23
- package/local-network/scripts/setup-new-delegator-keys.sh +184 -0
- package/local-network/scripts/setup-wallets.sh +2 -2
- package/local-network/scripts/start.sh +11 -0
- package/local-network/templates/babbage/alonzo-babbage-test-genesis.json +154 -154
- package/local-network/templates/babbage/byron-configuration.yaml +1 -0
- package/local-network/templates/babbage/conway-babbage-test-genesis.json +38 -0
- package/local-network/templates/babbage/node-config.json +12 -22
- package/local-network/templates/babbage/submit-api-config.json +9 -21
- package/package.json +25 -26
- package/src/factories.ts +16 -6
- package/src/util/createMockKeyAgent.ts +4 -2
- package/src/util/util.ts +7 -4
- package/test/local-network/register-pool.test.ts +3 -2
- package/test/projection/offline-fork.test.ts +2 -1
- package/test/wallet_epoch_0/PersonalWallet/conwayTransactions.test.ts +470 -0
- package/test/wallet_epoch_0/PersonalWallet/multisignature.test.ts +5 -3
- package/test/wallet_epoch_0/PersonalWallet/phase2validation.test.ts +4 -1
- package/test/wallet_epoch_0/PersonalWallet/plutusTest.test.ts +2 -1
- package/test/wallet_epoch_0/SharedWallet/utils.ts +7 -1
- package/test/wallet_epoch_3/PersonalWallet/delegationDistribution.test.ts +9 -8
- package/test/web-extension/webpack.config.base.js +2 -1
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
import * as Crypto from '@cardano-sdk/crypto';
|
|
2
|
+
import { BaseWallet } from '@cardano-sdk/wallet';
|
|
3
|
+
import { Cardano, Serialization } from '@cardano-sdk/core';
|
|
4
|
+
import { logger } from '@cardano-sdk/util-dev';
|
|
5
|
+
|
|
6
|
+
import { firstValueFrom, map } from 'rxjs';
|
|
7
|
+
import { getEnv, getWallet, submitAndConfirm, unDelegateWallet, walletReady, walletVariables } from '../../../src';
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
Use cases not covered by specific tests because covered by (before|after)(All|Each) hooks
|
|
11
|
+
- send RegisterDelegateRepresentative certificate
|
|
12
|
+
sent in beforeAll as a registered DRep is required to some other test cases
|
|
13
|
+
- send UnregisterDelegateRepresentative certificate
|
|
14
|
+
sent in afterAll as test suite tear down
|
|
15
|
+
- send Conway Registration certificate
|
|
16
|
+
sent in beforeEach in nested describe with tests requiring it
|
|
17
|
+
- send ProposalProcedure
|
|
18
|
+
sent in beforeAll in nested describe to check VotingProcedure
|
|
19
|
+
- send AuthorizeCommitteeHot
|
|
20
|
+
sent in beforeAll in nested describe to check UpdateDelegateRepresentative
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const {
|
|
24
|
+
CertificateType,
|
|
25
|
+
CredentialType,
|
|
26
|
+
GovernanceActionType,
|
|
27
|
+
RewardAccount,
|
|
28
|
+
StakeCredentialStatus,
|
|
29
|
+
StakePoolStatus,
|
|
30
|
+
Vote,
|
|
31
|
+
VoterType
|
|
32
|
+
} = Cardano;
|
|
33
|
+
|
|
34
|
+
const env = getEnv(walletVariables);
|
|
35
|
+
|
|
36
|
+
const anchor = {
|
|
37
|
+
dataHash: '3e33018e8293d319ef5b3ac72366dd28006bd315b715f7e7cfcbd3004129b80d' as Crypto.Hash32ByteBase16,
|
|
38
|
+
url: 'https://testing.this'
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const assertTxHasCertificate = (tx: Cardano.HydratedTx, certificate: Cardano.Certificate) =>
|
|
42
|
+
expect(tx.body.certificates![0]).toEqual(certificate);
|
|
43
|
+
|
|
44
|
+
const getTestWallet = async (idx: number, name: string, minCoinBalance?: bigint) => {
|
|
45
|
+
const { wallet } = await getWallet({ env, idx, logger, name, polling: { interval: 50 } });
|
|
46
|
+
|
|
47
|
+
await walletReady(wallet, minCoinBalance);
|
|
48
|
+
|
|
49
|
+
return wallet;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// TODO: remove once mainnet hardforks to conway-era, and this becomes "the norm"
|
|
53
|
+
describe.skip('PersonalWallet/conwayTransactions', () => {
|
|
54
|
+
let dRepWallet: BaseWallet;
|
|
55
|
+
let wallet: BaseWallet;
|
|
56
|
+
|
|
57
|
+
let dRepCredential: Cardano.Credential & { type: Cardano.CredentialType.KeyHash };
|
|
58
|
+
let poolId: Cardano.PoolId;
|
|
59
|
+
let rewardAccount: Cardano.RewardAccount;
|
|
60
|
+
let stakeCredential: Cardano.Credential;
|
|
61
|
+
|
|
62
|
+
let dRepDeposit: bigint;
|
|
63
|
+
let governanceActionDeposit: bigint;
|
|
64
|
+
let stakeKeyDeposit: bigint;
|
|
65
|
+
|
|
66
|
+
const assertWalletIsDelegating = async () =>
|
|
67
|
+
expect((await firstValueFrom(wallet.delegation.rewardAccounts$))[0].delegatee?.nextNextEpoch?.id).toEqual(poolId);
|
|
68
|
+
|
|
69
|
+
const getDRepCredential = async () => {
|
|
70
|
+
const drepPubKey = await dRepWallet.governance.getPubDRepKey();
|
|
71
|
+
const dRepKeyHash = Crypto.Hash28ByteBase16.fromEd25519KeyHashHex(
|
|
72
|
+
(await Crypto.Ed25519PublicKey.fromHex(drepPubKey!).hash()).hex()
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return { hash: dRepKeyHash, type: CredentialType.KeyHash } as typeof dRepCredential;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const getDeposits = async () => {
|
|
79
|
+
const protocolParameters = await wallet.networkInfoProvider.protocolParameters();
|
|
80
|
+
|
|
81
|
+
return [
|
|
82
|
+
BigInt(protocolParameters.dRepDeposit),
|
|
83
|
+
BigInt(protocolParameters.governanceActionDeposit),
|
|
84
|
+
BigInt(protocolParameters.stakeKeyDeposit)
|
|
85
|
+
];
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const getPoolId = async () => {
|
|
89
|
+
const activePools = await wallet.stakePoolProvider.queryStakePools({
|
|
90
|
+
filters: { status: [StakePoolStatus.Active] },
|
|
91
|
+
pagination: { limit: 1, startAt: 0 }
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return activePools.pageResults[0].id;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const getStakeCredential = async () => {
|
|
98
|
+
rewardAccount = await firstValueFrom(wallet.addresses$.pipe(map((addresses) => addresses[0].rewardAccount)));
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
hash: Crypto.Hash28ByteBase16.fromEd25519KeyHashHex(RewardAccount.toHash(rewardAccount)),
|
|
102
|
+
type: CredentialType.KeyHash
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// TODO LW-10555: Revert this to feed the dRep wallet, not the `wallet`, once the dbsync bug is fixed
|
|
107
|
+
// https://github.com/IntersectMBO/cardano-db-sync/issues/1702
|
|
108
|
+
const feedDRepWallet = async (amount: bigint) => {
|
|
109
|
+
const balance = await firstValueFrom(wallet.balance.utxo.total$);
|
|
110
|
+
|
|
111
|
+
if (balance.coins > amount) return;
|
|
112
|
+
|
|
113
|
+
const address = await firstValueFrom(wallet.addresses$.pipe(map((addresses) => addresses[0].address)));
|
|
114
|
+
|
|
115
|
+
const signedTx = await dRepWallet
|
|
116
|
+
.createTxBuilder()
|
|
117
|
+
.addOutput({ address, value: { coins: amount } })
|
|
118
|
+
.build()
|
|
119
|
+
.sign();
|
|
120
|
+
|
|
121
|
+
await submitAndConfirm(dRepWallet, signedTx.tx, 1);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const sendDRepRegCert = async (register: boolean) => {
|
|
125
|
+
const common = { dRepCredential, deposit: dRepDeposit };
|
|
126
|
+
const dRepUnRegCert: Cardano.UnRegisterDelegateRepresentativeCertificate = {
|
|
127
|
+
__typename: CertificateType.UnregisterDelegateRepresentative,
|
|
128
|
+
...common
|
|
129
|
+
};
|
|
130
|
+
const dRepRegCert: Cardano.RegisterDelegateRepresentativeCertificate = {
|
|
131
|
+
__typename: CertificateType.RegisterDelegateRepresentative,
|
|
132
|
+
anchor,
|
|
133
|
+
...common
|
|
134
|
+
};
|
|
135
|
+
const certificate = register ? dRepRegCert : dRepUnRegCert;
|
|
136
|
+
const signedTx = await dRepWallet
|
|
137
|
+
.createTxBuilder()
|
|
138
|
+
.customize(({ txBody }) => ({ ...txBody, certificates: [certificate] }))
|
|
139
|
+
.build()
|
|
140
|
+
.sign();
|
|
141
|
+
const [, confirmedTx] = await submitAndConfirm(dRepWallet, signedTx.tx, 1);
|
|
142
|
+
|
|
143
|
+
assertTxHasCertificate(confirmedTx, certificate);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const isRegisteredDRep = async () => {
|
|
147
|
+
const txs = [...(await firstValueFrom(dRepWallet.transactions.history$))].reverse();
|
|
148
|
+
|
|
149
|
+
for (const {
|
|
150
|
+
body: { certificates }
|
|
151
|
+
} of txs) {
|
|
152
|
+
if (certificates) {
|
|
153
|
+
for (const certificate of certificates) {
|
|
154
|
+
if (certificate.__typename === CertificateType.UnregisterDelegateRepresentative) return false;
|
|
155
|
+
if (certificate.__typename === CertificateType.RegisterDelegateRepresentative) return true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return false;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
beforeAll(async () => {
|
|
164
|
+
// TODO: remove once mainnet hardforks to conway-era, and this becomes "the norm"
|
|
165
|
+
Serialization.CborSet.useConwaySerialization = true;
|
|
166
|
+
Serialization.Redeemers.useConwaySerialization = true;
|
|
167
|
+
|
|
168
|
+
// TODO LW-10555: Revert this so that wallet is at account 0 and drepWallet at account 1, once the dbsync bug is fixed
|
|
169
|
+
// https://github.com/IntersectMBO/cardano-db-sync/issues/1702
|
|
170
|
+
[dRepWallet, wallet] = await Promise.all([
|
|
171
|
+
getTestWallet(0, 'Conway DRep Wallet', 100_000_000n),
|
|
172
|
+
getTestWallet(1, 'Conway Wallet', 0n)
|
|
173
|
+
]);
|
|
174
|
+
|
|
175
|
+
[dRepCredential, [dRepDeposit, governanceActionDeposit, stakeKeyDeposit], poolId, stakeCredential] =
|
|
176
|
+
await Promise.all([getDRepCredential(), getDeposits(), getPoolId(), getStakeCredential()]);
|
|
177
|
+
|
|
178
|
+
// TODO LW-10555: Revert this to use the 2*drepDeposit, once the dbsync bug is fixed
|
|
179
|
+
// https://github.com/IntersectMBO/cardano-db-sync/issues/1702
|
|
180
|
+
await feedDRepWallet(governanceActionDeposit * 6n + 100_000_000n);
|
|
181
|
+
|
|
182
|
+
if (!(await isRegisteredDRep())) await sendDRepRegCert(true);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
beforeEach(async () => await unDelegateWallet(wallet));
|
|
186
|
+
|
|
187
|
+
afterAll(async () => {
|
|
188
|
+
await sendDRepRegCert(false);
|
|
189
|
+
await unDelegateWallet(wallet);
|
|
190
|
+
|
|
191
|
+
wallet.shutdown();
|
|
192
|
+
dRepWallet.shutdown();
|
|
193
|
+
|
|
194
|
+
// TODO: remove once mainnet hardforks to conway-era, and this becomes "the norm"
|
|
195
|
+
Serialization.CborSet.useConwaySerialization = false;
|
|
196
|
+
Serialization.Redeemers.useConwaySerialization = false;
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('can register a stake key and delegate stake using a combo certificate', async () => {
|
|
200
|
+
const regAndDelegCert: Cardano.StakeRegistrationDelegationCertificate = {
|
|
201
|
+
__typename: CertificateType.StakeRegistrationDelegation,
|
|
202
|
+
deposit: stakeKeyDeposit,
|
|
203
|
+
poolId,
|
|
204
|
+
stakeCredential
|
|
205
|
+
};
|
|
206
|
+
const signedTx = await wallet
|
|
207
|
+
.createTxBuilder()
|
|
208
|
+
.customize(({ txBody }) => ({ ...txBody, certificates: [regAndDelegCert] }))
|
|
209
|
+
.build()
|
|
210
|
+
.sign();
|
|
211
|
+
const [, confirmedTx] = await submitAndConfirm(wallet, signedTx.tx, 1);
|
|
212
|
+
|
|
213
|
+
assertTxHasCertificate(confirmedTx, regAndDelegCert);
|
|
214
|
+
await assertWalletIsDelegating();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('can register a stake key and delegate vote using a combo certificate', async () => {
|
|
218
|
+
const regAndVoteDelegCert: Cardano.VoteRegistrationDelegationCertificate = {
|
|
219
|
+
__typename: CertificateType.VoteRegistrationDelegation,
|
|
220
|
+
dRep: dRepCredential,
|
|
221
|
+
deposit: stakeKeyDeposit,
|
|
222
|
+
stakeCredential
|
|
223
|
+
};
|
|
224
|
+
const signedTx = await wallet
|
|
225
|
+
.createTxBuilder()
|
|
226
|
+
.customize(({ txBody }) => ({ ...txBody, certificates: [regAndVoteDelegCert] }))
|
|
227
|
+
.build()
|
|
228
|
+
.sign();
|
|
229
|
+
const [, confirmedTx] = await submitAndConfirm(wallet, signedTx.tx, 1);
|
|
230
|
+
|
|
231
|
+
assertTxHasCertificate(confirmedTx, regAndVoteDelegCert);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('can register a stake key and delegate stake and vote using a combo certificate', async () => {
|
|
235
|
+
const regStakeVoteDelegCert: Cardano.StakeVoteRegistrationDelegationCertificate = {
|
|
236
|
+
__typename: CertificateType.StakeVoteRegistrationDelegation,
|
|
237
|
+
dRep: dRepCredential,
|
|
238
|
+
deposit: stakeKeyDeposit,
|
|
239
|
+
poolId,
|
|
240
|
+
stakeCredential
|
|
241
|
+
};
|
|
242
|
+
const signedTx = await wallet
|
|
243
|
+
.createTxBuilder()
|
|
244
|
+
.customize(({ txBody }) => ({ ...txBody, certificates: [regStakeVoteDelegCert] }))
|
|
245
|
+
.build()
|
|
246
|
+
.sign();
|
|
247
|
+
const [, confirmedTx] = await submitAndConfirm(wallet, signedTx.tx, 1);
|
|
248
|
+
|
|
249
|
+
assertTxHasCertificate(confirmedTx, regStakeVoteDelegCert);
|
|
250
|
+
await assertWalletIsDelegating();
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('can update delegation representatives', async () => {
|
|
254
|
+
const updateDRepCert: Cardano.UpdateDelegateRepresentativeCertificate = {
|
|
255
|
+
__typename: CertificateType.UpdateDelegateRepresentative,
|
|
256
|
+
anchor: null,
|
|
257
|
+
dRepCredential
|
|
258
|
+
};
|
|
259
|
+
const signedTx = await dRepWallet
|
|
260
|
+
.createTxBuilder()
|
|
261
|
+
.customize(({ txBody }) => ({ ...txBody, certificates: [updateDRepCert] }))
|
|
262
|
+
.build()
|
|
263
|
+
.sign();
|
|
264
|
+
const [, confirmedTx] = await submitAndConfirm(dRepWallet, signedTx.tx, 1);
|
|
265
|
+
|
|
266
|
+
assertTxHasCertificate(confirmedTx, updateDRepCert);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// TODO LW-9962
|
|
270
|
+
describe.skip('with constitutional committee', () => {
|
|
271
|
+
beforeAll(async () => {
|
|
272
|
+
const regCCCert: Cardano.AuthorizeCommitteeHotCertificate = {
|
|
273
|
+
__typename: CertificateType.AuthorizeCommitteeHot,
|
|
274
|
+
coldCredential: stakeCredential,
|
|
275
|
+
hotCredential: stakeCredential
|
|
276
|
+
};
|
|
277
|
+
const signedTx = await dRepWallet
|
|
278
|
+
.createTxBuilder()
|
|
279
|
+
.customize(({ txBody }) => ({ ...txBody, certificates: [regCCCert] }))
|
|
280
|
+
.build()
|
|
281
|
+
.sign();
|
|
282
|
+
const [, confirmedTx] = await submitAndConfirm(dRepWallet, signedTx.tx, 1);
|
|
283
|
+
|
|
284
|
+
assertTxHasCertificate(confirmedTx, regCCCert);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('can update delegation representatives', async () => {
|
|
288
|
+
const updateDRepCert: Cardano.UpdateDelegateRepresentativeCertificate = {
|
|
289
|
+
__typename: CertificateType.UpdateDelegateRepresentative,
|
|
290
|
+
anchor,
|
|
291
|
+
dRepCredential
|
|
292
|
+
};
|
|
293
|
+
const signedTx = await dRepWallet
|
|
294
|
+
.createTxBuilder()
|
|
295
|
+
.customize(({ txBody }) => ({ ...txBody, certificates: [updateDRepCert] }))
|
|
296
|
+
.build()
|
|
297
|
+
.sign();
|
|
298
|
+
const [, confirmedTx] = await submitAndConfirm(dRepWallet, signedTx.tx, 1);
|
|
299
|
+
|
|
300
|
+
assertTxHasCertificate(confirmedTx, updateDRepCert);
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
describe('with Conway Registration certificate', () => {
|
|
305
|
+
beforeEach(async () => {
|
|
306
|
+
const newRegCert: Cardano.NewStakeAddressCertificate = {
|
|
307
|
+
__typename: CertificateType.Registration,
|
|
308
|
+
deposit: stakeKeyDeposit,
|
|
309
|
+
stakeCredential
|
|
310
|
+
};
|
|
311
|
+
const signedTx = await wallet
|
|
312
|
+
.createTxBuilder()
|
|
313
|
+
.customize(({ txBody }) => ({ ...txBody, certificates: [newRegCert] }))
|
|
314
|
+
.build()
|
|
315
|
+
.sign();
|
|
316
|
+
const [, confirmedTx] = await submitAndConfirm(wallet, signedTx.tx, 1);
|
|
317
|
+
|
|
318
|
+
assertTxHasCertificate(confirmedTx, newRegCert);
|
|
319
|
+
expect((await firstValueFrom(wallet.delegation.rewardAccounts$))[0].credentialStatus).toBe(
|
|
320
|
+
StakeCredentialStatus.Registered
|
|
321
|
+
);
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
it('can un-register stake key through the new Conway certificates', async () => {
|
|
325
|
+
const newUnRegCert: Cardano.NewStakeAddressCertificate = {
|
|
326
|
+
__typename: CertificateType.Unregistration,
|
|
327
|
+
deposit: stakeKeyDeposit,
|
|
328
|
+
stakeCredential
|
|
329
|
+
};
|
|
330
|
+
const signedTx = await wallet
|
|
331
|
+
.createTxBuilder()
|
|
332
|
+
.customize(({ txBody }) => ({ ...txBody, certificates: [newUnRegCert] }))
|
|
333
|
+
.build()
|
|
334
|
+
.sign();
|
|
335
|
+
const [, confirmedTx] = await submitAndConfirm(wallet, signedTx.tx, 1);
|
|
336
|
+
|
|
337
|
+
assertTxHasCertificate(confirmedTx, newUnRegCert);
|
|
338
|
+
expect((await firstValueFrom(wallet.delegation.rewardAccounts$))[0].credentialStatus).toBe(
|
|
339
|
+
StakeCredentialStatus.Unregistered
|
|
340
|
+
);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('can delegate vote', async () => {
|
|
344
|
+
const voteDelegCert: Cardano.VoteDelegationCertificate = {
|
|
345
|
+
__typename: CertificateType.VoteDelegation,
|
|
346
|
+
dRep: dRepCredential,
|
|
347
|
+
stakeCredential
|
|
348
|
+
};
|
|
349
|
+
const signedTx = await wallet
|
|
350
|
+
.createTxBuilder()
|
|
351
|
+
.customize(({ txBody }) => ({ ...txBody, certificates: [voteDelegCert] }))
|
|
352
|
+
.build()
|
|
353
|
+
.sign();
|
|
354
|
+
const [, confirmedTx] = await submitAndConfirm(wallet, signedTx.tx, 1);
|
|
355
|
+
|
|
356
|
+
assertTxHasCertificate(confirmedTx, voteDelegCert);
|
|
357
|
+
await assertWalletIsDelegating();
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it('can delegate stake and vote using combo certificate', async () => {
|
|
361
|
+
const stakeVoteDelegCert: Cardano.StakeVoteDelegationCertificate = {
|
|
362
|
+
__typename: CertificateType.StakeVoteDelegation,
|
|
363
|
+
dRep: dRepCredential,
|
|
364
|
+
poolId,
|
|
365
|
+
stakeCredential
|
|
366
|
+
};
|
|
367
|
+
const signedTx = await wallet
|
|
368
|
+
.createTxBuilder()
|
|
369
|
+
.customize(({ txBody }) => ({ ...txBody, certificates: [stakeVoteDelegCert] }))
|
|
370
|
+
.build()
|
|
371
|
+
.sign();
|
|
372
|
+
const [, confirmedTx] = await submitAndConfirm(wallet, signedTx.tx, 1);
|
|
373
|
+
|
|
374
|
+
assertTxHasCertificate(confirmedTx, stakeVoteDelegCert);
|
|
375
|
+
await assertWalletIsDelegating();
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
describe('with proposal procedure', () => {
|
|
380
|
+
let actionId: Cardano.GovernanceActionId;
|
|
381
|
+
|
|
382
|
+
beforeAll(async () => {
|
|
383
|
+
const proposalProcedures: Cardano.ProposalProcedure[] = [
|
|
384
|
+
{
|
|
385
|
+
anchor,
|
|
386
|
+
deposit: governanceActionDeposit,
|
|
387
|
+
governanceAction: {
|
|
388
|
+
__typename: GovernanceActionType.parameter_change_action,
|
|
389
|
+
governanceActionId: null,
|
|
390
|
+
policyHash: null,
|
|
391
|
+
protocolParamUpdate: { maxTxSize: 2000 }
|
|
392
|
+
},
|
|
393
|
+
rewardAccount
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
anchor,
|
|
397
|
+
deposit: governanceActionDeposit,
|
|
398
|
+
governanceAction: {
|
|
399
|
+
__typename: GovernanceActionType.hard_fork_initiation_action,
|
|
400
|
+
governanceActionId: null,
|
|
401
|
+
protocolVersion: { major: 10, minor: 0 }
|
|
402
|
+
},
|
|
403
|
+
rewardAccount
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
anchor,
|
|
407
|
+
deposit: governanceActionDeposit,
|
|
408
|
+
governanceAction: {
|
|
409
|
+
__typename: GovernanceActionType.treasury_withdrawals_action,
|
|
410
|
+
policyHash: null,
|
|
411
|
+
withdrawals: new Set([{ coin: 10_000_000n, rewardAccount }])
|
|
412
|
+
},
|
|
413
|
+
rewardAccount
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
anchor,
|
|
417
|
+
deposit: governanceActionDeposit,
|
|
418
|
+
governanceAction: {
|
|
419
|
+
__typename: GovernanceActionType.no_confidence,
|
|
420
|
+
governanceActionId: null
|
|
421
|
+
},
|
|
422
|
+
rewardAccount
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
anchor,
|
|
426
|
+
deposit: governanceActionDeposit,
|
|
427
|
+
governanceAction: {
|
|
428
|
+
__typename: GovernanceActionType.new_constitution,
|
|
429
|
+
constitution: { anchor, scriptHash: null },
|
|
430
|
+
governanceActionId: null
|
|
431
|
+
},
|
|
432
|
+
rewardAccount
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
anchor,
|
|
436
|
+
deposit: governanceActionDeposit,
|
|
437
|
+
governanceAction: { __typename: GovernanceActionType.info_action },
|
|
438
|
+
rewardAccount
|
|
439
|
+
}
|
|
440
|
+
];
|
|
441
|
+
const signedTx = await wallet
|
|
442
|
+
.createTxBuilder()
|
|
443
|
+
.customize(({ txBody }) => ({ ...txBody, proposalProcedures }))
|
|
444
|
+
.build()
|
|
445
|
+
.sign();
|
|
446
|
+
const [id, confirmedTx] = await submitAndConfirm(wallet, signedTx.tx, 1);
|
|
447
|
+
|
|
448
|
+
expect(confirmedTx.body.proposalProcedures).toEqual(proposalProcedures);
|
|
449
|
+
|
|
450
|
+
actionId = { actionIndex: 0, id };
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
it('delegation representatives can vote proposal procedure', async () => {
|
|
454
|
+
const votingProcedures: Cardano.VotingProcedures = [
|
|
455
|
+
{
|
|
456
|
+
voter: { __typename: VoterType.dRepKeyHash, credential: dRepCredential },
|
|
457
|
+
votes: [{ actionId, votingProcedure: { anchor, vote: Vote.abstain } }]
|
|
458
|
+
}
|
|
459
|
+
];
|
|
460
|
+
const signedTx = await dRepWallet
|
|
461
|
+
.createTxBuilder()
|
|
462
|
+
.customize(({ txBody }) => ({ ...txBody, votingProcedures }))
|
|
463
|
+
.build()
|
|
464
|
+
.sign();
|
|
465
|
+
const [, confirmedTx] = await submitAndConfirm(dRepWallet, signedTx.tx, 1);
|
|
466
|
+
|
|
467
|
+
expect(confirmedTx.body.votingProcedures).toEqual(votingProcedures);
|
|
468
|
+
});
|
|
469
|
+
});
|
|
470
|
+
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { BaseWallet, FinalizeTxProps } from '@cardano-sdk/wallet';
|
|
3
3
|
import { Cardano, nativeScriptPolicyId } from '@cardano-sdk/core';
|
|
4
4
|
import { InitializeTxProps } from '@cardano-sdk/tx-construction';
|
|
5
|
-
import { KeyRole, util } from '@cardano-sdk/key-management';
|
|
5
|
+
import { KeyPurpose, KeyRole, util } from '@cardano-sdk/key-management';
|
|
6
6
|
import {
|
|
7
7
|
bip32Ed25519Factory,
|
|
8
8
|
burnTokens,
|
|
@@ -48,12 +48,14 @@ describe('PersonalWallet/multisignature', () => {
|
|
|
48
48
|
const aliceKeyAgent = await createStandaloneKeyAgent(
|
|
49
49
|
env.KEY_MANAGEMENT_PARAMS.mnemonic.split(' '),
|
|
50
50
|
genesis,
|
|
51
|
-
bip32Ed25519
|
|
51
|
+
bip32Ed25519,
|
|
52
|
+
KeyPurpose.MULTI_SIG
|
|
52
53
|
);
|
|
53
54
|
const bobKeyAgent = await createStandaloneKeyAgent(
|
|
54
55
|
env.KEY_MANAGEMENT_PARAMS.mnemonic.split(' '),
|
|
55
56
|
genesis,
|
|
56
|
-
bip32Ed25519
|
|
57
|
+
bip32Ed25519,
|
|
58
|
+
KeyPurpose.MULTI_SIG
|
|
57
59
|
);
|
|
58
60
|
|
|
59
61
|
const aliceDerivationPath = {
|
|
@@ -70,7 +70,10 @@ describe('PersonalWallet/phase2validation', () => {
|
|
|
70
70
|
wallet.shutdown();
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
// The submit fails instead of being able to send it.
|
|
74
|
+
// TODO: re-enable this after understanding how to force submit API to submit a transaction that
|
|
75
|
+
// will fain in phase2 validation
|
|
76
|
+
it.skip('can detect a phase2 validation failure and emit the transaction as failed', async () => {
|
|
74
77
|
wallet = (await getWallet({ env, logger, name: 'Minting Wallet', polling: { interval: 50 } })).wallet;
|
|
75
78
|
|
|
76
79
|
// Plutus script that always returns false.
|
|
@@ -184,7 +184,8 @@ const getScriptUtxoSet = (
|
|
|
184
184
|
)
|
|
185
185
|
);
|
|
186
186
|
|
|
187
|
-
|
|
187
|
+
// LW-10693: disable until costModels are fetched from protocolParams
|
|
188
|
+
describe.skip('PersonalWallet/plutus', () => {
|
|
188
189
|
let wallet: BaseWallet;
|
|
189
190
|
afterAll(() => {
|
|
190
191
|
wallet.shutdown();
|
|
@@ -2,6 +2,7 @@ import * as Crypto from '@cardano-sdk/crypto';
|
|
|
2
2
|
import {
|
|
3
3
|
AccountKeyDerivationPath,
|
|
4
4
|
KeyAgent,
|
|
5
|
+
KeyPurpose,
|
|
5
6
|
KeyRole,
|
|
6
7
|
SignBlobResult,
|
|
7
8
|
SignDataContext,
|
|
@@ -30,7 +31,12 @@ const getKeyAgent = async (
|
|
|
30
31
|
genesisParameters: Cardano.CompactGenesis,
|
|
31
32
|
bip32Ed25519: Crypto.Bip32Ed25519
|
|
32
33
|
) => {
|
|
33
|
-
const keyAgent = await createStandaloneKeyAgent(
|
|
34
|
+
const keyAgent = await createStandaloneKeyAgent(
|
|
35
|
+
mnemonics.split(' '),
|
|
36
|
+
genesisParameters,
|
|
37
|
+
bip32Ed25519,
|
|
38
|
+
KeyPurpose.MULTI_SIG
|
|
39
|
+
);
|
|
34
40
|
|
|
35
41
|
const pubKey = await keyAgent.derivePublicKey(DERIVATION_PATH);
|
|
36
42
|
|
|
@@ -105,19 +105,20 @@ const delegateToMultiplePools = async (
|
|
|
105
105
|
return { poolIds, portfolio };
|
|
106
106
|
};
|
|
107
107
|
|
|
108
|
-
const delegateAllToSinglePool = async (wallet: BaseWallet): Promise<
|
|
108
|
+
const delegateAllToSinglePool = async (wallet: BaseWallet): Promise<Cardano.StakePool> => {
|
|
109
109
|
// This is a negative testcase, simulating an HD wallet that has multiple stake keys delegated
|
|
110
110
|
// to the same stake pool. txBuilder.delegatePortfolio does not support this scenario.
|
|
111
|
-
const [
|
|
111
|
+
const [pool] = await getPoolIds(wallet);
|
|
112
112
|
const txBuilder = wallet.createTxBuilder();
|
|
113
113
|
const rewardAccounts = await firstValueFrom(wallet.delegation.rewardAccounts$);
|
|
114
114
|
txBuilder.partialTxBody.certificates = rewardAccounts.map(({ address }) =>
|
|
115
|
-
Cardano.createDelegationCert(address,
|
|
115
|
+
Cardano.createDelegationCert(address, pool.id)
|
|
116
116
|
);
|
|
117
117
|
|
|
118
|
-
logger.debug(`Delegating all stake keys to pool ${
|
|
118
|
+
logger.debug(`Delegating all stake keys to pool ${pool.id}`);
|
|
119
119
|
const { tx } = await txBuilder.build().sign();
|
|
120
120
|
await submitAndConfirm(wallet, tx);
|
|
121
|
+
return pool;
|
|
121
122
|
};
|
|
122
123
|
|
|
123
124
|
describe('PersonalWallet/delegationDistribution', () => {
|
|
@@ -216,11 +217,11 @@ describe('PersonalWallet/delegationDistribution', () => {
|
|
|
216
217
|
);
|
|
217
218
|
|
|
218
219
|
// Delegate all reward accounts to the same pool. delegationDistribution$ should have 1 entry with 100% distribution
|
|
219
|
-
await delegateAllToSinglePool(wallet);
|
|
220
|
+
const pool = await delegateAllToSinglePool(wallet);
|
|
220
221
|
simplifiedDelegationDistribution = await firstValueFrom(
|
|
221
222
|
wallet.delegation.distribution$.pipe(
|
|
222
223
|
tap((distribution) => {
|
|
223
|
-
logger.info('All stake keys are delegated to poolId:',
|
|
224
|
+
logger.info('All stake keys are delegated to poolId:', pool.id);
|
|
224
225
|
logger.info(distributionMessage, distribution);
|
|
225
226
|
}),
|
|
226
227
|
map((distribution) =>
|
|
@@ -236,8 +237,8 @@ describe('PersonalWallet/delegationDistribution', () => {
|
|
|
236
237
|
|
|
237
238
|
expect(simplifiedDelegationDistribution).toEqual([
|
|
238
239
|
{
|
|
239
|
-
id:
|
|
240
|
-
name:
|
|
240
|
+
id: pool.id,
|
|
241
|
+
name: pool.metadata?.name,
|
|
241
242
|
percentage: Percent(1),
|
|
242
243
|
rewardAccounts: rewardAccounts.map(({ address }) => address)
|
|
243
244
|
}
|
|
@@ -70,7 +70,9 @@ module.exports = {
|
|
|
70
70
|
resolve: {
|
|
71
71
|
extensions: ['.ts', '.js'],
|
|
72
72
|
fallback: {
|
|
73
|
+
'@cardano-sdk/cardano-services': false,
|
|
73
74
|
buffer: require.resolve('buffer/'),
|
|
75
|
+
crypto: require.resolve('crypto-browserify'),
|
|
74
76
|
events: require.resolve('events/'),
|
|
75
77
|
fs: false,
|
|
76
78
|
'get-port-please': false,
|
|
@@ -79,7 +81,6 @@ module.exports = {
|
|
|
79
81
|
os: false,
|
|
80
82
|
path: false,
|
|
81
83
|
perf_hooks: false,
|
|
82
|
-
crypto: require.resolve('crypto-browserify'),
|
|
83
84
|
stream: require.resolve('readable-stream'),
|
|
84
85
|
util: require.resolve('util/')
|
|
85
86
|
}
|