Skip to content

Commit

Permalink
Merge pull request #501 from multiversx/main
Browse files Browse the repository at this point in the history
Main into feat/inner
  • Loading branch information
andreibancioiu authored Oct 9, 2024
2 parents 9c76f79 + 6f76303 commit 7b5e01d
Show file tree
Hide file tree
Showing 16 changed files with 12,273 additions and 141 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ jobs:
- run: npm run lint
- run: npm run compile
- run: npm install esmify && npm run compile-browser
- run: npm test
- run: npm run tests-unit
- run: npm run tests-devnet
4 changes: 2 additions & 2 deletions package-lock.json

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

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@multiversx/sdk-core",
"version": "13.7.0",
"version": "13.8.0",
"description": "MultiversX SDK for JavaScript and TypeScript",
"author": "MultiversX",
"homepage": "https://multiversx.com",
Expand All @@ -22,10 +22,11 @@
],
"scripts": {
"test": "npm run tests-unit",
"tests-unit": "mocha $(find . -name '*.spec.ts' ! -name '*.local.net.spec.*' ! -name '*.devnet.spec.*' ! -name '*.testnet.spec.*')",
"tests-unit": "mocha $(find . -name '*.spec.ts' ! -name '*.local.net.spec.*' ! -name '*.test.net.spec.*' ! -name '*.dev.net.spec.*' ! -name '*.main.net.spec.*')",
"tests-localnet": "mocha $(find . -name '*.local.net.spec.ts')",
"tests-devnet": "mocha $(find . -name '*.devnet.spec.ts')",
"tests-testnet": "mocha $(find . -name '*.testnet.spec.ts')",
"tests-testnet": "mocha $(find . -name '*.test.net.spec.ts')",
"tests-devnet": "mocha $(find . -name '*.dev.net.spec.ts')",
"tests-mainnet": "mocha $(find . -name '*.main.net.spec.ts')",
"compile-browser": "tsc -p tsconfig.json && browserify out/index.js -o out-browser/sdk-core.js --standalone multiversxSdkCore -p esmify",
"compile": "tsc -p tsconfig.json",
"compile-proto": "npx pbjs -t static-module -w default -o src/proto/compiled.js src/proto/transaction.proto",
Expand Down
8 changes: 8 additions & 0 deletions src/converters/transactionsConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ export class TransactionsConverter {
return Buffer.from(value || "", "hex");
}

/**
* @deprecated Where {@link TransactionOutcome} was needed (throughout the SDK), pass the {@link ITransactionOnNetwork} object instead.
*
* Summarizes the outcome of a transaction on the network, and maps it to the "standard" resources (according to the sdk-specs).
*
* In the future, this converter function will become obsolete,
* as the impedance mismatch between the network components and the "core" components will be reduced.
*/
public transactionOnNetworkToOutcome(transactionOnNetwork: ITransactionOnNetwork): TransactionOutcome {
// In the future, this will not be needed because the transaction, as returned from the API,
// will hold the data corresponding to the direct smart contract call outcome (in case of smart contract calls).
Expand Down
1 change: 1 addition & 0 deletions src/interfaceOfNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export interface IContractResultItem {
data: string;
returnMessage: string;
logs: ITransactionLogs;
previousHash?: string;
}

export interface IContractQueryResponse {
Expand Down
62 changes: 6 additions & 56 deletions src/smartcontracts/resultsParser.spec.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import BigNumber from "bignumber.js";
import { assert } from "chai";
import { Address } from "../address";
import { IAddress } from "../interface";
import {
ContractQueryResponse,
ContractResultItem,
ContractResults,
TransactionEventData,
TransactionEventOnNetwork,
TransactionEventTopic,
TransactionLogsOnNetwork,
TransactionOnNetwork,
TransactionEventData,
} from "../networkProviders";
import BigNumber from "bignumber.js";
import { assert } from "chai";
import * as fs from "fs";
import path from "path";
import { Address } from "../address";
import { IAddress } from "../interface";
import { ITransactionOnNetwork } from "../interfaceOfNetwork";
import { LogLevel, Logger } from "../logger";
import { loadAbiRegistry } from "../testutils";
import { ArgSerializer } from "./argSerializer";
import { ResultsParser } from "./resultsParser";
Expand Down Expand Up @@ -258,10 +254,7 @@ describe("test smart contract results parser", () => {

let bundle = parser.parseUntypedOutcome(transaction);
assert.deepEqual(bundle.returnCode, ReturnCode.Ok);
assert.equal(
bundle.returnMessage,
"@too much gas provided for processing: gas provided = 596384500, gas used = 733010",
);
assert.equal(bundle.returnMessage, "ok");
assert.deepEqual(bundle.values, []);
});

Expand Down Expand Up @@ -383,47 +376,4 @@ describe("test smart contract results parser", () => {
assert.deepEqual(bundle.b, new BigNumber(43));
assert.deepEqual(bundle.c, new BigNumber(44));
});

// This test should be enabled manually and run against a set of sample transactions.
// 2022-04-03: test ran against ~1800 transactions sampled from devnet.
it.skip("should parse real-world contract outcomes", async () => {
let oldLogLevel = Logger.logLevel;
Logger.setLevel(LogLevel.Trace);

let folder = path.resolve(process.env["SAMPLES"] || "SAMPLES");
let samples = loadRealWorldSamples(folder);

for (const [transaction, _] of samples) {
console.log("Transaction:", transaction.hash.toString());

let bundle = parser.parseUntypedOutcome(transaction);

console.log("Return code:", bundle.returnCode.toString());
console.log("Return message:", bundle.returnMessage);
console.log("Num values:", bundle.values.length);
console.log("=".repeat(80));

assert.include(KnownReturnCodes, bundle.returnCode.valueOf());
}

Logger.setLevel(oldLogLevel);
});

function loadRealWorldSamples(folder: string): [ITransactionOnNetwork, string][] {
let transactionFiles = fs.readdirSync(folder);
let samples: [ITransactionOnNetwork, string][] = [];

for (const file of transactionFiles) {
let txHash = path.basename(file, ".json");
let filePath = path.resolve(folder, file);
let jsonContent: string = fs.readFileSync(filePath, { encoding: "utf8" });
let json = JSON.parse(jsonContent);
let payload = json["data"]["transaction"];
let transaction = TransactionOnNetwork.fromProxyHttpResponse(txHash, payload);

samples.push([transaction, jsonContent]);
}

return samples;
}
});
23 changes: 20 additions & 3 deletions src/smartcontracts/resultsParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,10 @@ export class ResultsParser {
}

let { returnCode, returnDataParts } = this.sliceDataFieldInParts(eventTooMuchGas.data);
let lastTopic = eventTooMuchGas.getLastTopic();
let returnMessage = lastTopic?.toString() || returnCode.toString();

return {
returnCode: returnCode,
returnMessage: returnMessage,
returnMessage: returnCode.toString(),
values: returnDataParts,
};
}
Expand Down Expand Up @@ -355,6 +353,25 @@ export class ResultsParser {
}
}

// Additional fallback heuristics (alter search constraints):
for (const resultItem of transaction.contractResults.items) {
let writeLogWithReturnData = resultItem.logs.findSingleOrNoneEvent(WellKnownEvents.OnWriteLog, (event) => {
const addressIsContract = event.address.bech32() == contractAddress.toBech32();
return addressIsContract;
});

if (writeLogWithReturnData) {
const { returnCode, returnDataParts } = this.sliceDataFieldInParts(writeLogWithReturnData.data);
const returnMessage = returnCode.toString();

return {
returnCode: returnCode,
returnMessage: returnMessage,
values: returnDataParts,
};
}
}

return null;
}

Expand Down
111 changes: 111 additions & 0 deletions src/testdata/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Testdata

## Files `transactions.mainnet.json`

Transactions were sampled from the mainnet BigQuery dataset:

```sql
DECLARE
TIMESTAMP_START DATE DEFAULT '2024-09-01';
DECLARE
TIMESTAMP_END DATE DEFAULT '2024-09-03';
-- Contract execute, with success
(
SELECT
`_id`,
'execute_success' `kind`
FROM
`multiversx-blockchain-etl.crypto_multiversx_mainnet_eu.transactions`
WHERE
DATE(`timestamp`) >= TIMESTAMP_START
AND DATE(`timestamp`) <= TIMESTAMP_END
AND `isScCall` = TRUE
AND ARRAY_LENGTH(`esdtValues`) = 0
AND `status` = 'success'
AND RAND() < 0.25
LIMIT
250 )
UNION ALL
-- Contract execute, with error
(
SELECT
`_id`,
'execute_error' `kind`
FROM
`multiversx-blockchain-etl.crypto_multiversx_mainnet_eu.transactions`
WHERE
DATE(`timestamp`) >= TIMESTAMP_START
AND DATE(`timestamp`) <= TIMESTAMP_END
AND `isScCall` = TRUE
AND ARRAY_LENGTH(`esdtValues`) = 0
AND `status` = 'fail'
AND RAND() < 0.25
LIMIT
250 )
UNION ALL
-- Contract transfer & execute, with success
(
SELECT
`_id`,
'transfer_execute_success' `kind`
FROM
`multiversx-blockchain-etl.crypto_multiversx_mainnet_eu.transactions`
WHERE
DATE(`timestamp`) >= TIMESTAMP_START
AND DATE(`timestamp`) <= TIMESTAMP_END
AND `isScCall` = TRUE
AND ARRAY_LENGTH(`esdtValues`) > 0
AND `status` = 'success'
AND RAND() < 0.25
LIMIT
250 )
UNION ALL
-- Contract transfer & execute, with error
(
SELECT
`_id`,
'transfer_execute_error' `kind`
FROM
`multiversx-blockchain-etl.crypto_multiversx_mainnet_eu.transactions`
WHERE
DATE(`timestamp`) >= TIMESTAMP_START
AND DATE(`timestamp`) <= TIMESTAMP_END
AND `isScCall` = TRUE
AND ARRAY_LENGTH(`esdtValues`) > 0
AND `status` = 'fail'
AND RAND() < 0.25
LIMIT
250)
UNION ALL
-- Relayed, with success
(
SELECT
`_id`,
'relayed_success' `kind`
FROM
`multiversx-blockchain-etl.crypto_multiversx_mainnet_eu.transactions`
WHERE
DATE(`timestamp`) >= TIMESTAMP_START
AND DATE(`timestamp`) <= TIMESTAMP_END
AND `isRelayed` = TRUE
AND `status` = 'success'
AND RAND() < 0.25
LIMIT
50)
UNION ALL
-- Relayed, with failure
(
SELECT
`_id`,
'relayed_error' `kind`
FROM
`multiversx-blockchain-etl.crypto_multiversx_mainnet_eu.transactions`
WHERE
DATE(`timestamp`) >= TIMESTAMP_START
AND DATE(`timestamp`) <= TIMESTAMP_END
AND `isRelayed` = TRUE
AND `status` = 'fail'
AND RAND() < 0.25
LIMIT
50)
```
Loading

0 comments on commit 7b5e01d

Please sign in to comment.