Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Transaction Watcher #386

Merged
merged 6 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 9 additions & 33 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"protobufjs": "7.2.4"
},
"devDependencies": {
"@multiversx/sdk-network-providers": "2.2.0",
"@multiversx/sdk-network-providers": "2.3.0",
"@multiversx/sdk-wallet": "4.2.0",
"@types/assert": "1.4.6",
"@types/chai": "4.2.11",
Expand Down
72 changes: 62 additions & 10 deletions src/smartcontracts/smartContract.local.net.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import { ResultsParser } from "./resultsParser";
import { SmartContract } from "./smartContract";
import { AddressValue, BigUIntValue, OptionalValue, OptionValue, TokenIdentifierValue, U32Value } from "./typesystem";
import { BytesValue } from "./typesystem/bytes";
import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig";
import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory";
import { TokenComputer } from "../tokens";
import { promises } from "fs";
import { TransactionComputer } from "../transaction";

describe("test on local testnet", function () {
let alice: TestWallet, bob: TestWallet, carol: TestWallet;
Expand Down Expand Up @@ -85,12 +90,12 @@ describe("test on local testnet", function () {
await provider.sendTransaction(transactionDeploy);
await provider.sendTransaction(transactionIncrement);

await watcher.awaitCompleted(transactionDeploy);
await watcher.awaitCompleted(transactionDeploy.getHash().hex());
let transactionOnNetwork = await provider.getTransaction(transactionDeploy.getHash().hex());
let bundle = resultsParser.parseUntypedOutcome(transactionOnNetwork);
assert.isTrue(bundle.returnCode.isSuccess());

await watcher.awaitCompleted(transactionIncrement);
await watcher.awaitCompleted(transactionIncrement.getHash().hex());
transactionOnNetwork = await provider.getTransaction(transactionIncrement.getHash().hex());
bundle = resultsParser.parseUntypedOutcome(transactionOnNetwork);
assert.isTrue(bundle.returnCode.isSuccess());
Expand Down Expand Up @@ -150,9 +155,9 @@ describe("test on local testnet", function () {
await provider.sendTransaction(transactionIncrementFirst);
await provider.sendTransaction(transactionIncrementSecond);

await watcher.awaitCompleted(transactionDeploy);
await watcher.awaitCompleted(transactionIncrementFirst);
await watcher.awaitCompleted(transactionIncrementSecond);
await watcher.awaitCompleted(transactionDeploy.getHash().hex());
await watcher.awaitCompleted(transactionIncrementFirst.getHash().hex());
await watcher.awaitCompleted(transactionIncrementSecond.getHash().hex());

// Check counter
let query = contract.createQuery({ func: new ContractFunction("get") });
Expand Down Expand Up @@ -212,9 +217,9 @@ describe("test on local testnet", function () {
await provider.sendTransaction(transactionMintBob);
await provider.sendTransaction(transactionMintCarol);

await watcher.awaitCompleted(transactionDeploy);
await watcher.awaitCompleted(transactionMintBob);
await watcher.awaitCompleted(transactionMintCarol);
await watcher.awaitCompleted(transactionDeploy.getHash().hex());
await watcher.awaitCompleted(transactionMintBob.getHash().hex());
await watcher.awaitCompleted(transactionMintCarol.getHash().hex());

// Query state, do some assertions
let query = contract.createQuery({ func: new ContractFunction("totalSupply") });
Expand Down Expand Up @@ -294,8 +299,8 @@ describe("test on local testnet", function () {
await provider.sendTransaction(transactionDeploy);
await provider.sendTransaction(transactionStart);

await watcher.awaitAllEvents(transactionDeploy, ["SCDeploy"]);
await watcher.awaitAnyEvent(transactionStart, ["completedTxEvent"]);
await watcher.awaitAllEvents(transactionDeploy.getHash().hex(), ["SCDeploy"]);
await watcher.awaitAnyEvent(transactionStart.getHash().hex(), ["completedTxEvent"]);

// Let's check the SCRs
let transactionOnNetwork = await provider.getTransaction(transactionDeploy.getHash().hex());
Expand Down Expand Up @@ -325,4 +330,51 @@ describe("test on local testnet", function () {
queryResponse = await provider.queryContract(query);
assert.equal(decodeUnsignedNumber(queryResponse.getReturnDataParts()[0]), 0);
});

it("counter: should deploy and call using the SmartContractFactory", async function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 👍 (in relation to the other comment about a next PR for integration tests, only now I see this test)

this.timeout(80000);

TransactionWatcher.DefaultPollingInterval = 5000;
TransactionWatcher.DefaultTimeout = 50000;

const network = await provider.getNetworkConfig();
await alice.sync(provider);

const transactionComputer = new TransactionComputer();
const config = new TransactionsFactoryConfig(network.ChainID);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I see - we should pass init parameters to TransactionsFactoryConfig as options (even if now there's only one, the chain ID) - similar to SmartContractTransactionsFactory etc. This, in order to avoid breaking changes in the future, if the config should be extended to receive an extra parameter in the constructor.

This would be for another, separate PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do in the next PR.

const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() });

let bytecode = await promises.readFile("src/testdata/counter.wasm");

const deployTransaction = factory.createTransactionForDeploy({
sender: alice.address,
bytecode: bytecode,
gasLimit: 3000000n,
});
deployTransaction.nonce = BigInt(alice.account.nonce.valueOf());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit verbose, but good at this moment. In the cookbook I think we will not mention AccountNonce class anymore - left for the client code to hold & handle the nonce.

deployTransaction.signature = await alice.signer.sign(
Buffer.from(transactionComputer.computeBytesForSigning(deployTransaction)),
);

const deployTxHash = await provider.sendTransaction(deployTransaction);
await watcher.awaitCompleted(deployTxHash);

const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce);

alice.account.incrementNonce();

const smartContractCallTransaction = factory.createTransactionForExecute({
sender: alice.address,
contract: contractAddress,
functionName: "increment",
gasLimit: 2000000n,
});
smartContractCallTransaction.nonce = BigInt(alice.account.nonce.valueOf());
smartContractCallTransaction.signature = await alice.signer.sign(
Buffer.from(transactionComputer.computeBytesForSigning(smartContractCallTransaction)),
);

const scCallTxHash = await provider.sendTransaction(smartContractCallTransaction);
await watcher.awaitCompleted(scCallTxHash);
});
});
8 changes: 4 additions & 4 deletions src/smartcontracts/smartContract.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe("test contract", () => {

await Promise.all([
provider.mockTransactionTimeline(deployTransaction, [new Wait(40), new TransactionStatus("pending"), new Wait(40), new TransactionStatus("executed"), new MarkCompleted()]),
watcher.awaitCompleted(deployTransaction)
watcher.awaitCompleted(deployTransaction.getHash().hex())
]);

assert.isTrue((await provider.getTransactionStatus(hash)).isExecuted());
Expand Down Expand Up @@ -118,8 +118,8 @@ describe("test contract", () => {
await Promise.all([
provider.mockTransactionTimeline(callTransactionOne, [new Wait(40), new TransactionStatus("pending"), new Wait(40), new TransactionStatus("executed"), new MarkCompleted()]),
provider.mockTransactionTimeline(callTransactionTwo, [new Wait(40), new TransactionStatus("pending"), new Wait(40), new TransactionStatus("executed"), new MarkCompleted()]),
watcher.awaitCompleted(callTransactionOne),
watcher.awaitCompleted(callTransactionTwo)
watcher.awaitCompleted(callTransactionOne.getHash().hex()),
watcher.awaitCompleted(callTransactionTwo.getHash().hex())
]);

assert.isTrue((await provider.getTransactionStatus(hashOne)).isExecuted());
Expand Down Expand Up @@ -159,7 +159,7 @@ describe("test contract", () => {

await Promise.all([
provider.mockTransactionTimeline(deployTransaction, [new Wait(40), new TransactionStatus("pending"), new Wait(40), new TransactionStatus("executed"), new MarkCompleted()]),
watcher.awaitCompleted(deployTransaction)
watcher.awaitCompleted(deployTransaction.getHash().hex())
]);

assert.isTrue((await provider.getTransactionStatus(hash)).isExecuted());
Expand Down
4 changes: 2 additions & 2 deletions src/smartcontracts/smartContractResults.local.net.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ describe("fetch transactions from local testnet", function () {
await provider.sendTransaction(transactionDeploy);
await provider.sendTransaction(transactionIncrement);

await watcher.awaitCompleted(transactionDeploy);
await watcher.awaitCompleted(transactionIncrement);
await watcher.awaitCompleted(transactionDeploy.getHash().hex());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a future PR, we should also adjust the integration tests to use the transaction factories for deploy, call etc.

await watcher.awaitCompleted(transactionIncrement.getHash().hex());

let transactionOnNetworkDeploy = await provider.getTransaction(transactionDeploy.getHash().hex());
let transactionOnNetworkIncrement = await provider.getTransaction(transactionIncrement.getHash().hex());
Expand Down
4 changes: 2 additions & 2 deletions src/testutils/contractController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class ContractController {
Logger.info(`ContractController.deploy [begin]: transaction = ${transaction.getHash()}`);

await this.provider.sendTransaction(transaction);
let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(transaction);
let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(transaction.getHash().hex());
let bundle = this.parser.parseUntypedOutcome(transactionOnNetwork);

Logger.info(`ContractController.deploy [end]: transaction = ${transaction.getHash()}, return code = ${bundle.returnCode}`);
Expand All @@ -37,7 +37,7 @@ export class ContractController {
interaction.check();

await this.provider.sendTransaction(transaction);
let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(transaction);
let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(transaction.getHash().hex());
let bundle = this.parser.parseOutcome(transactionOnNetwork, interaction.getEndpoint());

Logger.info(`ContractController.execute [end]: function = ${interaction.getFunction()}, transaction = ${transaction.getHash()}, return code = ${bundle.returnCode}`);
Expand Down
4 changes: 2 additions & 2 deletions src/testutils/networkProviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
ITransactionStatus,
} from "../interfaceOfNetwork";
import { Query } from "../smartcontracts/query";
import { Transaction } from "../transaction";
import { Transaction, TransactionNext } from "../transaction";

export function createLocalnetProvider(): INetworkProvider {
return new ProxyNetworkProvider("http://localhost:7950", { timeout: 5000 });
Expand All @@ -23,7 +23,7 @@ export interface INetworkProvider {
getAccount(address: IAddress): Promise<IAccountOnNetwork>;
getTransaction(txHash: string, withProcessStatus?: boolean): Promise<ITransactionOnNetwork>;
getTransactionStatus(txHash: string): Promise<ITransactionStatus>;
sendTransaction(tx: Transaction): Promise<string>;
sendTransaction(tx: Transaction | TransactionNext): Promise<string>;
simulateTransaction(tx: Transaction): Promise<any>;
queryContract(query: Query): Promise<IContractQueryResponse>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ describe("test factory on testnet", function () {
await provider.sendTransaction(transaction);
console.log(`Sent transaction [${tag}]: ${transaction.getHash().hex()}`);

const transactionOnNetwork = await watcher.awaitCompleted(transaction);
const transactionOnNetwork = await watcher.awaitCompleted(transaction.getHash().hex());
return transactionOnNetwork;
}
});
Loading
Loading