diff --git a/cookbook/cookbook.md b/cookbook/cookbook.md index 1d912627..1c8311c9 100644 --- a/cookbook/cookbook.md +++ b/cookbook/cookbook.md @@ -2402,18 +2402,16 @@ After the `10-epoch unbonding period` is complete, we can proceed with withdrawi ``` ### Relayed transactions -We are currently on the `third iteration (V3)` of relayed transactions. V1 and V2 will soon be deactivated, so we will focus on V3. +We are currently on the third iteration (V3) of relayed transactions. V1 and V2 will be deactivated soon, so we'll focus on V3. -For V3, two new fields have been added to transactions: -- relayer -- relayerSignature +For V3, two new fields have been added on transactions: `relayer` and `relayerSignature`. -Signing Process: -1. The relayer must be set before the sender signs the transaction. -2. Once the sender has signed, the relayer can also sign the transaction and broadcast it. +Note that: +1. the sender and the relayer can sign the transaction in any order. +2. before any of the sender or relayer can sign the transaction, the `relayer` field must be set. +3. relayed transactions require an additional `50,000` of gas. +4. the sender and the relayer must be in the same network shard. -**Important Consideration**: -Relayed V3 transactions require an additional `50,000` gas. Let’s see how to create a relayed transaction: ```js diff --git a/cookbook/relayed.ts b/cookbook/relayed.ts index d6166e78..8b60a4a9 100644 --- a/cookbook/relayed.ts +++ b/cookbook/relayed.ts @@ -3,18 +3,16 @@ import { Account, Address, DevnetEntrypoint, Transaction } from "../src"; // md- // md-start (async () => { // ### Relayed transactions - // We are currently on the `third iteration (V3)` of relayed transactions. V1 and V2 will soon be deactivated, so we will focus on V3. - - // For V3, two new fields have been added to transactions: - // - relayer - // - relayerSignature - - // Signing Process: - // 1. The relayer must be set before the sender signs the transaction. - // 2. Once the sender has signed, the relayer can also sign the transaction and broadcast it. - - // **Important Consideration**: - // Relayed V3 transactions require an additional `50,000` gas. + // We are currently on the third iteration (V3) of relayed transactions. V1 and V2 will be deactivated soon, so we'll focus on V3. + // + // For V3, two new fields have been added on transactions: `relayer` and `relayerSignature`. + // + // Note that: + // 1. the sender and the relayer can sign the transaction in any order. + // 2. before any of the sender or relayer can sign the transaction, the `relayer` field must be set. + // 3. relayed transactions require an additional `50,000` of gas. + // 4. the sender and the relayer must be in the same network shard. + // // Let’s see how to create a relayed transaction: // ```js diff --git a/package-lock.json b/package-lock.json index 2b5112cf..b9af603f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "15.0.0-beta.0", + "version": "15.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "15.0.0-beta.0", + "version": "15.1.1", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", @@ -1481,12 +1481,16 @@ } }, "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", + "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/cliui": { @@ -4668,15 +4672,23 @@ } }, "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "license": "(MIT AND BSD-3-Clause)", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/shasum-object": { @@ -4996,10 +5008,11 @@ } }, "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.14" } @@ -6542,12 +6555,12 @@ } }, "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" } }, "cliui": { @@ -8964,12 +8977,13 @@ } }, "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" } }, "shasum-object": { @@ -9222,9 +9236,9 @@ } }, "tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true }, "to-buffer": { diff --git a/package.json b/package.json index 8b365aa6..de492a4b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "15.0.0-beta.0", + "version": "15.1.1", "description": "MultiversX SDK for JavaScript and TypeScript", "author": "MultiversX", "homepage": "https://multiversx.com", diff --git a/src/core/errors.ts b/src/core/errors.ts index 076585f0..69954e87 100644 --- a/src/core/errors.ts +++ b/src/core/errors.ts @@ -445,6 +445,12 @@ export class ExpectedAccountConditionNotReachedError extends Err { */ export class ErrGasLimitCannotBeEstimated extends Err { public constructor(error: Error) { - super(`Failed to estimate gas limit: ${error}`, error); + super(`Failed to estimate gas limit: [${error}]`, error); + } +} + +export class ErrEstimateTransactionCost extends Err { + public constructor(message: string) { + super(message); } } diff --git a/src/core/index.ts b/src/core/index.ts index 3f70d7b5..de661b9e 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -12,6 +12,7 @@ export * from "./message"; export * from "./networkParams"; export * from "./smartContractQuery"; export * from "./tokens"; +export * from "./tokenTransfersDataBuilder"; export * from "./transaction"; export * from "./transactionComputer"; export * from "./transactionEvents"; @@ -20,4 +21,5 @@ export * from "./transactionOnNetwork"; export * from "./transactionsFactoryConfig"; export * from "./transactionStatus"; export * from "./transactionWatcher"; +export * from "./utils.codec"; export * from "./utils"; diff --git a/src/entrypoints/entrypoints.ts b/src/entrypoints/entrypoints.ts index 07db65d4..e230d168 100644 --- a/src/entrypoints/entrypoints.ts +++ b/src/entrypoints/entrypoints.ts @@ -16,7 +16,7 @@ import { GasLimitEstimator } from "../gasEstimator"; import { GovernanceController, GovernanceTransactionsFactory } from "../governance"; import { MultisigTransactionsFactory } from "../multisig"; import { MultisigController } from "../multisig/multisigController"; -import { ApiNetworkProvider, ProxyNetworkProvider } from "../networkProviders"; +import { ApiNetworkProvider, NetworkProviderConfig, ProxyNetworkProvider } from "../networkProviders"; import { INetworkProvider } from "../networkProviders/interface"; import { SmartContractTransactionsFactory } from "../smartContracts"; import { SmartContractController } from "../smartContracts/smartContractController"; @@ -34,19 +34,21 @@ export class NetworkEntrypoint { constructor(options: { networkProviderUrl: string; networkProviderKind: string; + networkProviderConfig?: NetworkProviderConfig; chainId: string; clientName?: string; withGasLimitEstimator?: boolean; gasLimitMultiplier?: number; }) { + const networkProviderConfig: NetworkProviderConfig = { + ...(options.networkProviderConfig ?? {}), + ...(options.clientName && { clientName: options.clientName }), + }; + if (options.networkProviderKind === "proxy") { - this.networkProvider = new ProxyNetworkProvider(options.networkProviderUrl, { - clientName: options.clientName, - }); + this.networkProvider = new ProxyNetworkProvider(options.networkProviderUrl, networkProviderConfig); } else if (options.networkProviderKind === "api") { - this.networkProvider = new ApiNetworkProvider(options.networkProviderUrl, { - clientName: options.clientName, - }); + this.networkProvider = new ApiNetworkProvider(options.networkProviderUrl, networkProviderConfig); } else { throw new ErrInvalidNetworkProviderKind(); } @@ -267,12 +269,14 @@ export class TestnetEntrypoint extends NetworkEntrypoint { clientName?: string; withGasLimitEstimator?: boolean; gasLimitMultiplier?: number; + networkProviderConfig?: NetworkProviderConfig; }) { const entrypointConfig = new TestnetEntrypointConfig(); options = options || {}; super({ networkProviderUrl: options.url || entrypointConfig.networkProviderUrl, networkProviderKind: options.kind || entrypointConfig.networkProviderKind, + networkProviderConfig: options.networkProviderConfig, chainId: entrypointConfig.chainId, clientName: options.clientName, withGasLimitEstimator: options.withGasLimitEstimator, @@ -288,12 +292,14 @@ export class DevnetEntrypoint extends NetworkEntrypoint { clientName?: string; withGasLimitEstimator?: boolean; gasLimitMultiplier?: number; + networkProviderConfig?: NetworkProviderConfig; }) { const entrypointConfig = new DevnetEntrypointConfig(); options = options || {}; super({ networkProviderUrl: options.url || entrypointConfig.networkProviderUrl, networkProviderKind: options.kind || entrypointConfig.networkProviderKind, + networkProviderConfig: options.networkProviderConfig, chainId: entrypointConfig.chainId, clientName: options.clientName, withGasLimitEstimator: options.withGasLimitEstimator, @@ -309,12 +315,14 @@ export class MainnetEntrypoint extends NetworkEntrypoint { clientName?: string; withGasLimitEstimator?: boolean; gasLimitMultiplier?: number; + networkProviderConfig?: NetworkProviderConfig; }) { const entrypointConfig = new MainnetEntrypointConfig(); options = options || {}; super({ networkProviderUrl: options.url || entrypointConfig.networkProviderUrl, networkProviderKind: options.kind || entrypointConfig.networkProviderKind, + networkProviderConfig: options.networkProviderConfig, chainId: entrypointConfig.chainId, clientName: options.clientName, withGasLimitEstimator: options.withGasLimitEstimator, diff --git a/src/networkProviders/proxyNetworkProvider.ts b/src/networkProviders/proxyNetworkProvider.ts index 09cdc97b..126efcb5 100644 --- a/src/networkProviders/proxyNetworkProvider.ts +++ b/src/networkProviders/proxyNetworkProvider.ts @@ -1,6 +1,7 @@ import { Address, ErrContractQuery, + ErrEstimateTransactionCost, ErrNetworkProvider, getAxios, prepareTransactionForBroadcasting, @@ -148,6 +149,10 @@ export class ProxyNetworkProvider implements INetworkProvider { const transaction = prepareTransactionForBroadcasting(copiedTx); const response = await this.doPostGeneric("transaction/cost", transaction); + const returnMessage: string = response.returnMessage; + if (returnMessage) { + throw new ErrEstimateTransactionCost(returnMessage); + } return TransactionCostResponse.fromHttpResponse(response); }