Skip to content

Commit 9ba9bdd

Browse files
authored
Fix/e2e test improvements (#2195)
# Goal The goal of this PR is to add a final set of e2e test improvements to allow e2e tests to run against testnet again post async-backing Closes #2154 # Discussion - Added a way to wait for finalization - Added errors instead of waiting forever for blocks - Reduced timeouts thanks to 6s blocktimes on testnet - Split up more tests for better parallelization # Testing - https://github.com/frequency-chain/frequency/actions/runs/11489493946/job/31978401849
1 parent 11225b1 commit 9ba9bdd

10 files changed

+277
-202
lines changed

e2e/.relay-chain.mocharc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
"require": ["scaffolding/globalHooks.ts", "scaffolding/rootHooks.ts", "scaffolding/extrinsicHelpers.ts"],
66
"import": "tsx/esm",
77
"spec": ["./{,!(node_modules|load-tests)/**}/*.test.ts"],
8-
"timeout": 600000
8+
"timeout": 180000
99
}

e2e/capacity/capacityFail.test.ts

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
import '@frequency-chain/api-augment';
2+
import { KeyringPair } from '@polkadot/keyring/types';
3+
import { Bytes, u64, u16 } from '@polkadot/types';
4+
import assert from 'assert';
5+
import { AddKeyData, ExtrinsicHelper } from '../scaffolding/extrinsicHelpers';
6+
import {
7+
createKeys,
8+
createAndFundKeypair,
9+
createMsaAndProvider,
10+
generateDelegationPayload,
11+
getBlockNumber,
12+
signPayloadSr25519,
13+
stakeToProvider,
14+
generateAddKeyPayload,
15+
CENTS,
16+
DOLLARS,
17+
getOrCreateGraphChangeSchema,
18+
getTestHandle,
19+
assertAddNewKey,
20+
} from '../scaffolding/helpers';
21+
import { getFundingSource } from '../scaffolding/funding';
22+
23+
const FUNDS_AMOUNT: bigint = 50n * DOLLARS;
24+
const fundingSource = getFundingSource('capacity-transactions-fail');
25+
26+
describe('Capacity Transaction Failures', function () {
27+
describe('pay_with_capacity', function () {
28+
describe('when caller does not have a Capacity account', function () {
29+
let delegatorKeys: KeyringPair;
30+
let delegatorProviderId: u64;
31+
let schemaId: u16;
32+
33+
beforeEach(async function () {
34+
// Create and fund a keypair with EXISTENTIAL_DEPOSIT
35+
// Use this keypair for delegator operations
36+
delegatorKeys = createKeys('OtherProviderKeys');
37+
delegatorProviderId = await createMsaAndProvider(fundingSource, delegatorKeys, 'Delegator', FUNDS_AMOUNT);
38+
schemaId = new u16(ExtrinsicHelper.api.registry, 0);
39+
});
40+
41+
describe('but has an MSA account that has not been registered as a Provider', function () {
42+
it('fails to pay for a transaction', async function () {
43+
// Create a keypair with msaId, but no provider
44+
const noProviderKeys = await createAndFundKeypair(fundingSource, FUNDS_AMOUNT, 'NoProviderKeys');
45+
46+
const createMsaOp = ExtrinsicHelper.createMsa(noProviderKeys);
47+
48+
const { target: msaCreatedEvent } = await createMsaOp.fundAndSend(fundingSource);
49+
assert.notEqual(msaCreatedEvent, undefined, 'should have returned MsaCreated event');
50+
51+
// When a user is not a registered provider and attempts to pay with Capacity,
52+
// it should error with InvalidTransaction::Payment, which is a 1010 error, Inability to pay some fees.
53+
const payload = await generateDelegationPayload({
54+
authorizedMsaId: delegatorProviderId,
55+
schemaIds: [schemaId],
56+
});
57+
const addProviderData = ExtrinsicHelper.api.registry.createType('PalletMsaAddProvider', payload);
58+
const grantDelegationOp = ExtrinsicHelper.grantDelegation(
59+
delegatorKeys,
60+
noProviderKeys,
61+
signPayloadSr25519(delegatorKeys, addProviderData),
62+
payload
63+
);
64+
65+
await assert.rejects(grantDelegationOp.payWithCapacity('current'), {
66+
name: 'RpcError',
67+
message: '1010: Invalid Transaction: Inability to pay some fees , e.g. account balance too low',
68+
});
69+
});
70+
});
71+
72+
describe('and does not have an MSA account associated to signing keys', function () {
73+
it('fails to pay for a transaction', async function () {
74+
const emptyKeys = await createAndFundKeypair(fundingSource, 50_000_000n);
75+
76+
const payload = await generateDelegationPayload({
77+
authorizedMsaId: delegatorProviderId,
78+
schemaIds: [schemaId],
79+
});
80+
const addProviderData = ExtrinsicHelper.api.registry.createType('PalletMsaAddProvider', payload);
81+
const grantDelegationOp = ExtrinsicHelper.grantDelegation(
82+
delegatorKeys,
83+
emptyKeys,
84+
signPayloadSr25519(delegatorKeys, addProviderData),
85+
payload
86+
);
87+
88+
await assert.rejects(grantDelegationOp.payWithCapacity('current'), {
89+
name: 'RpcError',
90+
message: '1010: Invalid Transaction: Custom error: 1',
91+
});
92+
});
93+
});
94+
});
95+
96+
describe('when caller has a Capacity account', function () {
97+
let schemaId: u16;
98+
const amountStaked = 3n * DOLLARS;
99+
100+
before(async function () {
101+
// Create schemas for testing with Grant Delegation to test pay_with_capacity
102+
schemaId = await getOrCreateGraphChangeSchema(fundingSource);
103+
assert.notEqual(schemaId, undefined, 'setup should populate schemaId');
104+
});
105+
106+
it('fails when a provider makes an eligible extrinsic call using non-funded control key', async function () {
107+
const capacityKeys = createKeys('CapacityKeysNSF');
108+
const capacityProvider = await createMsaAndProvider(fundingSource, capacityKeys, 'CapProvNSF', FUNDS_AMOUNT);
109+
// this will first fund 'capacityKeys' before staking
110+
await assert.doesNotReject(stakeToProvider(fundingSource, fundingSource, capacityProvider, amountStaked));
111+
112+
// As current owner, add a new set of control keys that do not have a balance.
113+
const newControlKeypair = createKeys('NewKeyNoBalance');
114+
const newPublicKey = newControlKeypair.publicKey;
115+
const addKeyPayload: AddKeyData = await generateAddKeyPayload({
116+
msaId: capacityProvider,
117+
newPublicKey: newPublicKey,
118+
});
119+
await assertAddNewKey(capacityKeys, addKeyPayload, newControlKeypair);
120+
121+
// attempt a capacity transaction using the new unfunded key: claimHandle
122+
const handle = getTestHandle();
123+
const expiration = (await getBlockNumber()) + 10;
124+
const handle_vec = new Bytes(ExtrinsicHelper.api.registry, handle);
125+
const handlePayload = {
126+
baseHandle: handle_vec,
127+
expiration: expiration,
128+
};
129+
const claimHandlePayload = ExtrinsicHelper.api.registry.createType(
130+
'CommonPrimitivesHandlesClaimHandlePayload',
131+
handlePayload
132+
);
133+
const claimHandle = ExtrinsicHelper.claimHandle(newControlKeypair, claimHandlePayload);
134+
await assert.rejects(claimHandle.payWithCapacity('current'), {
135+
name: 'RpcError',
136+
message: '1010: Invalid Transaction: Inability to pay some fees , e.g. account balance too low',
137+
});
138+
});
139+
140+
// When a user attempts to pay for a non-capacity transaction with Capacity,
141+
// it should error and drop the transaction from the transaction-pool.
142+
it('fails to pay with Capacity for a non-capacity transaction', async function () {
143+
const capacityKeys = createKeys('CapacityKeys');
144+
const capacityProvider = await createMsaAndProvider(
145+
fundingSource,
146+
capacityKeys,
147+
'CapacityProvider',
148+
FUNDS_AMOUNT
149+
);
150+
const nonCapacityTxn = ExtrinsicHelper.stake(capacityKeys, capacityProvider, 1n * CENTS);
151+
await assert.rejects(nonCapacityTxn.payWithCapacity('current'), {
152+
name: 'RpcError',
153+
message: '1010: Invalid Transaction: Custom error: 0',
154+
});
155+
});
156+
157+
// When a user does not have enough capacity to pay for the transaction fee
158+
// and is NOT eligible to replenish Capacity, it should error and be dropped
159+
// from the transaction pool.
160+
it('fails to pay for a transaction with empty capacity', async function () {
161+
const noCapacityKeys = createKeys('noCapacityKeys');
162+
const noCapacityProvider = await createMsaAndProvider(fundingSource, noCapacityKeys, 'NoCapProvider');
163+
164+
const delegatorKeys = createKeys('delegatorKeys');
165+
166+
const payload = await generateDelegationPayload({
167+
authorizedMsaId: noCapacityProvider,
168+
schemaIds: [schemaId],
169+
});
170+
const addProviderData = ExtrinsicHelper.api.registry.createType('PalletMsaAddProvider', payload);
171+
const grantDelegationOp = ExtrinsicHelper.createSponsoredAccountWithDelegation(
172+
delegatorKeys,
173+
noCapacityKeys,
174+
signPayloadSr25519(noCapacityKeys, addProviderData),
175+
payload
176+
);
177+
178+
await assert.rejects(grantDelegationOp.payWithCapacity('current'), {
179+
name: 'RpcError',
180+
message: '1010: Invalid Transaction: Inability to pay some fees , e.g. account balance too low',
181+
});
182+
});
183+
184+
// *All keys should have at least an EXISTENTIAL_DEPOSIT = 1M.
185+
it('fails to pay for transaction when key does has not met the min deposit', async function () {
186+
const capacityKeys = createKeys('CapKeysUnder');
187+
const capacityProvider = await createMsaAndProvider(fundingSource, capacityKeys, 'CapProvUnder', FUNDS_AMOUNT);
188+
const noTokensKeys = createKeys('noTokensKeys');
189+
const delegatorKeys = createKeys('delegatorKeys');
190+
191+
await assert.doesNotReject(stakeToProvider(fundingSource, fundingSource, capacityProvider, 1n * DOLLARS));
192+
193+
// Add new key
194+
const newKeyPayload: AddKeyData = await generateAddKeyPayload({
195+
msaId: new u64(ExtrinsicHelper.api.registry, capacityProvider),
196+
newPublicKey: noTokensKeys.publicKey,
197+
});
198+
const addKeyData = ExtrinsicHelper.api.registry.createType('PalletMsaAddKeyData', newKeyPayload);
199+
200+
const ownerSig = signPayloadSr25519(capacityKeys, addKeyData);
201+
const newSig = signPayloadSr25519(noTokensKeys, addKeyData);
202+
const addPublicKeyOp = ExtrinsicHelper.addPublicKeyToMsa(capacityKeys, ownerSig, newSig, newKeyPayload);
203+
204+
const { target: publicKeyEvent } = await addPublicKeyOp.fundAndSend(fundingSource);
205+
assert.notEqual(publicKeyEvent, undefined, 'should have added public key');
206+
207+
const payload = await generateDelegationPayload({
208+
authorizedMsaId: capacityProvider,
209+
schemaIds: [schemaId],
210+
});
211+
const addProviderData = ExtrinsicHelper.api.registry.createType('PalletMsaAddProvider', payload);
212+
const grantDelegationOp = ExtrinsicHelper.createSponsoredAccountWithDelegation(
213+
delegatorKeys,
214+
noTokensKeys,
215+
signPayloadSr25519(delegatorKeys, addProviderData),
216+
payload
217+
);
218+
219+
await assert.rejects(grantDelegationOp.payWithCapacity('current'), {
220+
name: 'RpcError',
221+
message: '1010: Invalid Transaction: Inability to pay some fees , e.g. account balance too low',
222+
});
223+
});
224+
});
225+
});
226+
});

0 commit comments

Comments
 (0)