Skip to content

Commit 050e649

Browse files
committed
new e2e tests
1 parent 71a7237 commit 050e649

File tree

3 files changed

+329
-20
lines changed

3 files changed

+329
-20
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import Keyring from '@polkadot/keyring';
2+
import { cryptoWaitReady } from '@polkadot/util-crypto';
3+
import { DedotClient, ISubstrateClient, LegacyClient, WsProvider } from 'dedot';
4+
import { SubstrateApi } from 'dedot/chaintypes';
5+
import { Contract, ContractDeployer, ContractMetadata, parseRawMetadata } from 'dedot/contracts';
6+
import { RpcVersion } from 'dedot/types';
7+
import { assert, isHex, isNumber, stringToHex } from 'dedot/utils';
8+
import * as flipperV4Raw from '../flipper_v4.json';
9+
import * as flipperV5Raw from '../flipper_v5.json';
10+
import { FlipperContractApi } from './contracts/flipper';
11+
12+
export const run = async (_nodeName: any, networkInfo: any) => {
13+
await cryptoWaitReady();
14+
15+
const alicePair = new Keyring({ type: 'sr25519' }).addFromUri('//Alice');
16+
const { wsUri } = networkInfo.nodesByName['collator-1'];
17+
18+
const caller = alicePair.address;
19+
const flipperV4 = parseRawMetadata(JSON.stringify(flipperV4Raw));
20+
const flipperV5 = parseRawMetadata(JSON.stringify(flipperV5Raw));
21+
22+
// Test with LegacyClient
23+
console.log('Testing contract chaining methods with LegacyClient');
24+
const apiLegacy = await LegacyClient.new(new WsProvider(wsUri));
25+
await testContractChainingMethods(apiLegacy, flipperV4, alicePair, caller);
26+
27+
// Test with DedotClient
28+
console.log('Testing contract chaining methods with DedotClient');
29+
const apiV2 = await DedotClient.new(new WsProvider(wsUri));
30+
await testContractChainingMethods(apiV2, flipperV5, alicePair, caller);
31+
};
32+
33+
async function testContractChainingMethods(
34+
api: ISubstrateClient<SubstrateApi[RpcVersion]>,
35+
flipper: ContractMetadata,
36+
alicePair: any,
37+
caller: string
38+
) {
39+
const wasm = flipper.source.wasm!;
40+
const deployer = new ContractDeployer<FlipperContractApi>(api, flipper, wasm, { defaultCaller: caller });
41+
42+
// Avoid using the same salt with previous tests
43+
const timestamp = await api.query.timestamp.now();
44+
const salt = stringToHex(`${api.rpcVersion}_${timestamp}_chaining_test`);
45+
46+
// Dry-run to estimate gas fee
47+
const {
48+
raw: { gasRequired },
49+
} = await deployer.query.new(true, {
50+
salt,
51+
});
52+
53+
console.log(`[${api.rpcVersion}] Testing untilBestChainBlockIncluded with contract deployment`);
54+
55+
// Test untilBestChainBlockIncluded with contract deployment
56+
const bestChainResult = await deployer.tx
57+
.new(true, { gasLimit: gasRequired, salt })
58+
.signAndSend(alicePair)
59+
.untilBestChainBlockIncluded();
60+
61+
// Verify the result contains the expected status
62+
assert(bestChainResult.status.type === 'BestChainBlockIncluded', 'Status should be BestChainBlockIncluded');
63+
assert(isHex(bestChainResult.status.value.blockHash), 'Block hash should be hex');
64+
assert(isNumber(bestChainResult.status.value.blockNumber), 'Block number should be number');
65+
assert(isNumber(bestChainResult.status.value.txIndex), 'Tx index should be number');
66+
67+
// Verify the contract was deployed successfully
68+
const instantiatedEvent = api.events.contracts.Instantiated.find(bestChainResult.events);
69+
assert(instantiatedEvent, 'Event Contracts.Instantiated should be available');
70+
71+
const contractAddress = instantiatedEvent.palletEvent.data.contract.address();
72+
console.log(`[${api.rpcVersion}] Deployed contract address`, contractAddress);
73+
74+
const contract = new Contract<FlipperContractApi>(api, flipper, contractAddress, { defaultCaller: caller });
75+
76+
// Get initial state
77+
const { data: initialState } = await contract.query.get();
78+
console.log(`[${api.rpcVersion}] Initial value:`, initialState);
79+
80+
// Dry-run to estimate gas fee for flip
81+
const { raw } = await contract.query.flip();
82+
83+
console.log(`[${api.rpcVersion}] Testing untilFinalized with contract method call`);
84+
85+
// Test untilFinalized with contract method call
86+
const finalizedResult = await contract.tx
87+
.flip({ gasLimit: raw.gasRequired })
88+
.signAndSend(alicePair)
89+
.untilFinalized();
90+
91+
// Verify the result contains the expected status
92+
assert(finalizedResult.status.type === 'Finalized', 'Status should be Finalized');
93+
assert(isHex(finalizedResult.status.value.blockHash), 'Block hash should be hex');
94+
assert(isNumber(finalizedResult.status.value.blockNumber), 'Block number should be number');
95+
assert(isNumber(finalizedResult.status.value.txIndex), 'Tx index should be number');
96+
97+
// Verify the flip was successful
98+
const flippedEvent = contract.events.Flipped.find(finalizedResult.events);
99+
assert(flippedEvent, 'Flipped event should be emitted');
100+
assert(flippedEvent.data.new === false, 'New value should be false');
101+
assert(flippedEvent.data.old === true, 'Old value should be true');
102+
103+
// Verify the state was changed
104+
const { data: newState } = await contract.query.get();
105+
console.log(`[${api.rpcVersion}] New value:`, newState);
106+
assert(initialState !== newState, 'State should be changed');
107+
108+
console.log(`[${api.rpcVersion}] Testing order of events with contract method call`);
109+
110+
// Test the order of events
111+
await testContractEventOrder(contract, alicePair, raw.gasRequired);
112+
113+
console.log(`[${api.rpcVersion}] Testing combined promises with contract method call`);
114+
115+
// Test using both promises together
116+
await testContractCombinedPromises(contract, alicePair, raw.gasRequired);
117+
}
118+
119+
async function testContractEventOrder(
120+
contract: Contract<FlipperContractApi>,
121+
alicePair: any,
122+
gasLimit: any
123+
) {
124+
// Track the order of events
125+
let bestChainBlockIncludedReceived = false;
126+
let finalizedReceived = false;
127+
let bestChainBlockIncludedTime = 0;
128+
let finalizedTime = 0;
129+
130+
// Send the transaction and track status updates
131+
await new Promise<void>((resolve) => {
132+
contract.tx
133+
.flip({ gasLimit })
134+
.signAndSend(alicePair, ({ status }: any) => {
135+
if (status.type === 'BestChainBlockIncluded') {
136+
bestChainBlockIncludedReceived = true;
137+
bestChainBlockIncludedTime = Date.now();
138+
console.log('Received BestChainBlockIncluded status at:', bestChainBlockIncludedTime);
139+
} else if (status.type === 'Finalized') {
140+
finalizedReceived = true;
141+
finalizedTime = Date.now();
142+
console.log('Received Finalized status at:', finalizedTime);
143+
resolve();
144+
}
145+
});
146+
});
147+
148+
// Verify both statuses were received and in the correct order
149+
assert(bestChainBlockIncludedReceived, 'BestChainBlockIncluded status should be received');
150+
assert(finalizedReceived, 'Finalized status should be received');
151+
assert(bestChainBlockIncludedTime < finalizedTime, 'BestChainBlockIncluded should be received before Finalized');
152+
}
153+
154+
async function testContractCombinedPromises(
155+
contract: Contract<FlipperContractApi>,
156+
alicePair: any,
157+
gasLimit: any
158+
) {
159+
// Create two promises using both chaining methods
160+
const signedTx = contract.tx
161+
.flip({ gasLimit })
162+
.signAndSend(alicePair);
163+
164+
const bestChainPromise = signedTx.untilBestChainBlockIncluded();
165+
const finalizedPromise = signedTx.untilFinalized();
166+
167+
// Wait for both promises to resolve
168+
const [bestChainResult, finalizedResult] = await Promise.all([bestChainPromise, finalizedPromise]);
169+
170+
// Verify the results
171+
assert(bestChainResult.status.type === 'BestChainBlockIncluded', 'First result status should be BestChainBlockIncluded');
172+
assert(finalizedResult.status.type === 'Finalized', 'Second result status should be Finalized');
173+
174+
// Verify both results refer to the same transaction
175+
assert(bestChainResult.txHash === finalizedResult.txHash, 'Both results should have the same txHash');
176+
177+
// Verify the flip was successful
178+
const flippedEvent = contract.events.Flipped.find(finalizedResult.events);
179+
assert(flippedEvent, 'Flipped event should be emitted');
180+
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import Keyring from '@polkadot/keyring';
2+
import { cryptoWaitReady } from '@polkadot/util-crypto';
3+
import { DedotClient, LegacyClient, WsProvider } from 'dedot';
4+
import { assert, isHex, isNumber } from 'dedot/utils';
5+
6+
const BOB = '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty';
7+
const TRANSFER_AMOUNT = BigInt(10 * 1e12); // 10 units
8+
9+
export const run = async (nodeName: any, networkInfo: any): Promise<void> => {
10+
await cryptoWaitReady();
11+
const keyring = new Keyring({ type: 'sr25519' });
12+
const alice = keyring.addFromUri('//Alice');
13+
14+
const { wsUri } = networkInfo.nodesByName[nodeName];
15+
16+
// Test with LegacyClient
17+
console.log('Testing chaining methods with LegacyClient');
18+
await testChainingMethods(LegacyClient, wsUri, alice);
19+
20+
// Test with DedotClient
21+
console.log('Testing chaining methods with DedotClient');
22+
await testChainingMethods(DedotClient, wsUri, alice);
23+
};
24+
25+
async function testChainingMethods(
26+
ClientClass: typeof LegacyClient | typeof DedotClient,
27+
wsUri: string,
28+
alice: any
29+
) {
30+
const api = await ClientClass.new(new WsProvider(wsUri));
31+
32+
// Test 1: untilBestChainBlockIncluded
33+
console.log('Testing untilBestChainBlockIncluded');
34+
await testUntilBestChainBlockIncluded(api, alice);
35+
36+
// Test 2: untilFinalized
37+
console.log('Testing untilFinalized');
38+
await testUntilFinalized(api, alice);
39+
40+
// Test 3: Compare both methods (should receive BestChainBlockIncluded before Finalized)
41+
console.log('Testing order of events');
42+
await testEventOrder(api, alice);
43+
44+
// Test 4: Test using both promises together
45+
console.log('Testing combined promises');
46+
await testCombinedPromises(api, alice);
47+
}
48+
49+
async function testUntilBestChainBlockIncluded(api: LegacyClient | DedotClient, alice: any) {
50+
const prevBobBalance = (await api.query.system.account(BOB)).data.free;
51+
console.log('BOB - initial balance:', prevBobBalance.toString());
52+
53+
const transferTx = api.tx.balances.transferKeepAlive(BOB, TRANSFER_AMOUNT);
54+
55+
// Use untilBestChainBlockIncluded to wait for the transaction to be included in a block
56+
const result = await transferTx.signAndSend(alice).untilBestChainBlockIncluded();
57+
58+
// Verify the result contains the expected status
59+
assert(result.status.type === 'BestChainBlockIncluded', 'Status should be BestChainBlockIncluded');
60+
assert(isHex(result.status.value.blockHash), 'Block hash should be hex');
61+
assert(isNumber(result.status.value.blockNumber), 'Block number should be number');
62+
assert(isNumber(result.status.value.txIndex), 'Tx index should be number');
63+
64+
// Verify the transaction was successful by checking Bob's balance
65+
const newBobBalance = (await api.query.system.account(BOB)).data.free;
66+
console.log('BOB - new balance after untilBestChainBlockIncluded:', newBobBalance.toString());
67+
assert(prevBobBalance + TRANSFER_AMOUNT === newBobBalance, 'Incorrect BOB balance after transfer');
68+
69+
console.log('untilBestChainBlockIncluded test passed');
70+
}
71+
72+
async function testUntilFinalized(api: LegacyClient | DedotClient, alice: any) {
73+
const prevBobBalance = (await api.query.system.account(BOB)).data.free;
74+
console.log('BOB - initial balance:', prevBobBalance.toString());
75+
76+
const transferTx = api.tx.balances.transferKeepAlive(BOB, TRANSFER_AMOUNT);
77+
78+
// Use untilFinalized to wait for the transaction to be finalized
79+
const result = await transferTx.signAndSend(alice).untilFinalized();
80+
81+
// Verify the result contains the expected status
82+
assert(result.status.type === 'Finalized', 'Status should be Finalized');
83+
assert(isHex(result.status.value.blockHash), 'Block hash should be hex');
84+
assert(isNumber(result.status.value.blockNumber), 'Block number should be number');
85+
assert(isNumber(result.status.value.txIndex), 'Tx index should be number');
86+
87+
// Verify the transaction was successful by checking Bob's balance
88+
const newBobBalance = (await api.query.system.account(BOB)).data.free;
89+
console.log('BOB - new balance after untilFinalized:', newBobBalance.toString());
90+
assert(prevBobBalance + TRANSFER_AMOUNT === newBobBalance, 'Incorrect BOB balance after transfer');
91+
92+
console.log('untilFinalized test passed');
93+
}
94+
95+
async function testEventOrder(api: LegacyClient | DedotClient, alice: any) {
96+
const transferTx = api.tx.balances.transferKeepAlive(BOB, TRANSFER_AMOUNT);
97+
98+
// Track the order of events
99+
let bestChainBlockIncludedReceived = false;
100+
let finalizedReceived = false;
101+
let bestChainBlockIncludedTime = 0;
102+
let finalizedTime = 0;
103+
104+
// Send the transaction and track status updates
105+
await new Promise<void>((resolve) => {
106+
transferTx.signAndSend(alice, ({ status }: any) => {
107+
if (status.type === 'BestChainBlockIncluded') {
108+
bestChainBlockIncludedReceived = true;
109+
bestChainBlockIncludedTime = Date.now();
110+
console.log('Received BestChainBlockIncluded status at:', bestChainBlockIncludedTime);
111+
} else if (status.type === 'Finalized') {
112+
finalizedReceived = true;
113+
finalizedTime = Date.now();
114+
console.log('Received Finalized status at:', finalizedTime);
115+
resolve();
116+
}
117+
});
118+
});
119+
120+
// Verify both statuses were received and in the correct order
121+
assert(bestChainBlockIncludedReceived, 'BestChainBlockIncluded status should be received');
122+
assert(finalizedReceived, 'Finalized status should be received');
123+
assert(bestChainBlockIncludedTime < finalizedTime, 'BestChainBlockIncluded should be received before Finalized');
124+
125+
console.log('Event order test passed');
126+
}
127+
128+
async function testCombinedPromises(api: LegacyClient | DedotClient, alice: any) {
129+
// Create two promises using both chaining methods
130+
const transferTx = api.tx.balances.transferKeepAlive(BOB, TRANSFER_AMOUNT);
131+
const signedTx = transferTx.signAndSend(alice);
132+
133+
const bestChainPromise = signedTx.untilBestChainBlockIncluded();
134+
const finalizedPromise = signedTx.untilFinalized();
135+
136+
// Wait for both promises to resolve
137+
const [bestChainResult, finalizedResult] = await Promise.all([bestChainPromise, finalizedPromise]);
138+
139+
// Verify the results
140+
assert(bestChainResult.status.type === 'BestChainBlockIncluded', 'First result status should be BestChainBlockIncluded');
141+
assert(finalizedResult.status.type === 'Finalized', 'Second result status should be Finalized');
142+
143+
// Verify both results refer to the same transaction
144+
assert(bestChainResult.txHash === finalizedResult.txHash, 'Both results should have the same txHash');
145+
146+
console.log('Combined promises test passed');
147+
}

zombienet-tests/src/0001-small-network.zndsl

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,5 @@ Creds: config
55
alice: is up
66
bob: is up
77
alice: reports node_roles is 4
8-
alice: ts-script ./0001-check-runtime-api.ts within 100 seconds
9-
alice: ts-script ./0001-check-storage-query.ts within 100 seconds
10-
alice: ts-script ./0001-check-storage-query-v2.ts within 100 seconds
11-
alice: ts-script ./0001-check-storage-map-pagination.ts within 200 seconds
12-
alice: ts-script ./0001-check-query-multi.ts within 100 seconds
13-
alice: ts-script ./0001-check-storage-subscription-reconnection.ts within 300 seconds
14-
alice: ts-script ./0001-check-tx-transfer-balance.ts within 100 seconds
15-
alice: ts-script ./0001-check-tx-transfer-balance-v2.ts within 100 seconds
16-
alice: ts-script ./0001-check-tx-batch.ts within 100 seconds
17-
alice: ts-script ./0001-check-tx-batch-v2.ts within 100 seconds
18-
alice: ts-script ./0001-check-ws-provider-connection.ts within 100 seconds
19-
alice: ts-script ./0001-tx-broadcaster.ts within 100 seconds
20-
alice: ts-script ./0001-verify-chain-head-logic.ts within 200 seconds
21-
alice: ts-script ./0001-check-payment-info.ts within 200 seconds
22-
alice: ts-script ./0001-tracking-tx-validity.ts within 200 seconds
23-
alice: ts-script ./0001-check-contract-api.ts within 500 seconds
24-
alice: ts-script ./0001-check-tx-alter-payload.ts within 200 seconds
25-
alice: ts-script ./0001-verify-contract-errors.ts within 500 seconds
26-
alice: ts-script ./0001-check-query-with-partial-keys.ts within 3000 seconds
27-
alice: ts-script ./0001-verify-dedot-client-events.ts within 100 seconds
8+
alice: ts-script ./0001-check-contract-tx-chaining-methods.ts within 200 seconds
9+
alice: ts-script ./0001-check-tx-chaining-methods.ts within 200 seconds

0 commit comments

Comments
 (0)