diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/plugin-ledger-connector-polkadot.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/plugin-ledger-connector-polkadot.ts index 4a81523370f..13cc32053fc 100644 --- a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/plugin-ledger-connector-polkadot.ts +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/plugin-ledger-connector-polkadot.ts @@ -433,49 +433,53 @@ export class PluginLedgerConnectorPolkadot const { mnemonic } = web3SigningCredential as Web3SigningCredentialMnemonicString; let success = false; - let transactionHash: string | undefined; - let blockHash: string | undefined; - try { - const keyring = new Keyring({ type: "sr25519" }); - const accountPair = keyring.createFromUri(mnemonic); - const accountAddress = transactionConfig.to; - const transferValue = transactionConfig.value; - const txResult = await new Promise<{ - success: boolean; - transactionHash: string; - blockhash: string; - }>((resolve, reject) => - this.api?.tx.balances - .transfer(accountAddress, transferValue) - .signAndSend(accountPair, ({ events = [], status, txHash }) => { - if (status.isInBlock) { - // Check if the system.ExtrinsicSuccess event is present - const successEvent = events.find( - ({ event: { section, method } }) => - section === "system" && method === "ExtrinsicSuccess", - ); - if (successEvent) { - resolve({ - success: true, - blockhash: status.asInBlock.toHex(), - transactionHash: txHash.toHex(), - }); - } else { - reject("transaction not successful"); - throw Error( - `Transaction Failed: The expected system.ExtrinsicSuccess event was not detected.` + - `events emitted are ${events}`, + const keyring = new Keyring({ type: "sr25519" }); + const accountPair = keyring.createFromUri(mnemonic); + const accountAddress = transactionConfig.to; + const transferValue = transactionConfig.value; + const txResult = await new Promise<{ + success: boolean; + transactionHash: string; + blockhash: string; + }>((resolve, reject) => { + if (!this.api) { + reject("transaction not successful"); + throw Error( + "The operation has failed because the API is not connected to Substrate Node", + ); + } + this.api.tx.balances + .transfer(accountAddress, transferValue) + .signAndSend(accountPair, ({ status, txHash, dispatchError }) => { + if (!this.api) { + throw Error( + "The operation has failed because the API is not connected to Substrate Node", + ); + } + if (status.isInBlock) { + if (dispatchError) { + reject("transaction not successful"); + if (dispatchError.isModule) { + const decoded = this.api.registry.findMetaError( + dispatchError.asModule, ); + const { docs, name, section } = decoded; + throw Error(`${section}.${name}: ${docs.join(" ")}`); + } else { + throw Error(dispatchError.toString()); } } - }), - ); - success = txResult.success; - transactionHash = txResult.transactionHash; - blockHash = txResult.blockhash; - } catch (e) { - throw Error(`${fnTag} The transaction failed. ` + `InnerException: ${e}`); - } + resolve({ + success: true, + blockhash: status.asInBlock.toHex(), + transactionHash: txHash.toHex(), + }); + } + }); + }); + success = txResult.success; + const transactionHash = txResult.transactionHash; + const blockHash = txResult.blockhash; return { success, txHash: transactionHash, @@ -496,9 +500,6 @@ export class PluginLedgerConnectorPolkadot "Starting api.rpc.author.submitAndWatchExtrinsic(transferSubmittable) ", ); let success = false; - let txHash: string | undefined; - let blockHash: string | undefined; - Checks.truthy(req, `${fnTag} req`); if (!this.api) { throw Error( @@ -515,39 +516,38 @@ export class PluginLedgerConnectorPolkadot throw Error(`${fnTag} Transaction signature is not valid. `); } - try { - const txResult = await new Promise<{ - success: boolean; - transactionHash: string; - blockhash: string; - }>((resolve, reject) => { - this.api?.rpc.author.submitAndWatchExtrinsic( - deserializedTransaction, - ({ isInBlock, hash, asInBlock, type }) => { - if (isInBlock) { - resolve({ - success: true, - blockhash: asInBlock.toHex(), - transactionHash: hash.toHex(), - }); - } else { - reject("transaction not successful"); - throw Error(`transaction not submitted with status: ${type}`); - } - }, + const txResult = await new Promise<{ + success: boolean; + transactionHash: string; + blockhash: string; + }>((resolve, reject) => { + if (!this.api) { + reject("transaction not successful"); + throw Error( + "The operation has failed because the API is not connected to Substrate Node", ); - }); - - success = txResult.success; - txHash = txResult.transactionHash; - blockHash = txResult.blockhash; - this.prometheusExporter.addCurrentTransaction(); - } catch (e) { - throw Error( - `${fnTag} The transaction submission failed. ` + `InnerException: ${e}`, + } + this.api.rpc.author.submitAndWatchExtrinsic( + deserializedTransaction, + ({ isInBlock, hash, asInBlock, type }) => { + if (isInBlock) { + resolve({ + success: true, + blockhash: asInBlock.toHex(), + transactionHash: hash.toHex(), + }); + } else { + reject("transaction not successful"); + throw Error(`transaction not submitted with status: ${type}`); + } + }, ); - } + }); + success = txResult.success; + const txHash = txResult.transactionHash; + const blockHash = txResult.blockhash; + this.prometheusExporter.addCurrentTransaction(); return { success, txHash, blockHash }; } @@ -593,7 +593,6 @@ export class PluginLedgerConnectorPolkadot ); } let success = false; - let contractAddress: string | undefined; const contractAbi = new Abi( req.metadata, this.api.registry.getChainProperties(), @@ -607,77 +606,67 @@ export class PluginLedgerConnectorPolkadot refTime: req.gasLimit.refTime, proofSize: req.gasLimit.proofSize, }); - try { - const keyring = new Keyring({ type: "sr25519" }); - const accountPair = keyring.createFromUri(mnemonic); - const tx = - req.params && req.params.length > 0 - ? contractCode.tx[contractAbi.constructors[0].method]( - { - gasLimit, - storageDepositLimit: req.storageDepositLimit, - salt: req.salt, - value: req.balance, - }, - ...req.params, - ) - : contractCode.tx[contractAbi.constructors[0].method]( - { - gasLimit, - storageDepositLimit: req.storageDepositLimit, - salt: req.salt, - value: req.balance, - }, - undefined, + const keyring = new Keyring({ type: "sr25519" }); + const accountPair = keyring.createFromUri(mnemonic); + const tx = + req.params && req.params.length > 0 + ? contractCode.tx[contractAbi.constructors[0].method]( + { + gasLimit, + storageDepositLimit: req.storageDepositLimit, + salt: req.salt, + value: req.balance, + }, + ...req.params, + ) + : contractCode.tx[contractAbi.constructors[0].method]( + { + gasLimit, + storageDepositLimit: req.storageDepositLimit, + salt: req.salt, + value: req.balance, + }, + undefined, + ); + const txResult = await new Promise<{ + success: boolean; + address: string | undefined; + }>((resolve, reject) => { + tx.signAndSend( + accountPair, + //https://github.com/polkadot-js/api/issues/5722 + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + ({ contract, status, dispatchError }) => { + if (!this.api) { + throw Error( + "The operation has failed because the API is not connected to Substrate Node", ); - if (tx) { - // Use Promise to ensure signAndSend completes before continuing - const txResult = await new Promise<{ - success: boolean; - address: string | undefined; - }>((resolve, reject) => { - tx.signAndSend( - accountPair, - //https://github.com/polkadot-js/api/issues/5722 - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - ({ contract, status, dispatchError }) => { - if (!this.api) { - throw Error( - "The operation has failed because the API is not connected to Substrate Node", + } + if (status.isInBlock || status.isFinalized) { + if (dispatchError) { + reject("deployment not successful"); + if (dispatchError.isModule) { + const decoded = this.api.registry.findMetaError( + dispatchError.asModule, ); + const { docs, name, section } = decoded; + throw Error(`${section}.${name}: ${docs.join(" ")}`); + } else { + throw Error(dispatchError.toString()); } - if (status.isInBlock || status.isFinalized) { - if (dispatchError) { - reject("deployment not successful"); - if (dispatchError.isModule) { - const decoded = this.api.registry.findMetaError( - dispatchError.asModule, - ); - const { docs, name, section } = decoded; - throw Error(`${section}.${name}: ${docs.join(" ")}`); - } else { - throw Error(dispatchError.toString()); - } - } - resolve({ - success: true, - address: contract.address.toString(), - }); - } - }, - ); - }); - success = txResult.success; - contractAddress = txResult.address; - } - } catch (e) { - throw Error( - `${fnTag} The contract upload and deployment failed. ` + - `InnerException: ${e}`, + } + resolve({ + success: true, + address: contract.address.toString(), + }); + } + }, ); - } - if (!contractAddress) { + }); + success = txResult.success; + const contractAddress = txResult.address; + if (contractAddress) { this.prometheusExporter.addCurrentTransaction(); } @@ -871,46 +860,42 @@ export class PluginLedgerConnectorPolkadot ): Promise { const fnTag = `${this.className}#obtainTxInformation()`; Checks.truthy(req, `${fnTag} req`); - this.log.info(`getTxFee`); + if (!this.api) { + throw Error( + "The operation has failed because the API is not connected to Substrate Node", + ); + } + const accountAddress = req.accountAddress; + const transactionExpiration = (req.transactionExpiration as number) || 50; try { - if (this.api) { - const accountAddress = req.accountAddress; - const transactionExpiration = - (req.transactionExpiration as number) || 50; - const signedBlock = await this.api.rpc.chain.getBlock(); - - const nonce = (await this.api.derive.balances.account(accountAddress)) - .accountNonce; - const blockHash = signedBlock.block.header.hash; - const era = this.api.createType("ExtrinsicEra", { - current: signedBlock.block.header.number, - period: transactionExpiration, - }); + const signedBlock = await this.api.rpc.chain.getBlock(); + const nonce = (await this.api.derive.balances.account(accountAddress)) + .accountNonce; + const blockHash = signedBlock.block.header.hash; + const era = this.api.createType("ExtrinsicEra", { + current: signedBlock.block.header.number, + period: transactionExpiration, + }); - const options = { - nonce: nonce, - blockHash: blockHash, - era: era, - }; + const options = { + nonce: nonce, + blockHash: blockHash, + era: era, + }; - const responseContainer = { - response_data: options, - succeeded: true, - message: "obtainTransactionInformation", - error: null, - }; + const responseContainer = { + response_data: options, + succeeded: true, + message: "obtainTransactionInformation", + error: null, + }; - const response: TransactionInfoResponse = { - responseContainer: responseContainer, - }; + const response: TransactionInfoResponse = { + responseContainer: responseContainer, + }; - return response; - } else { - throw Error( - "The operation has failed because the api is not connected to Substrate Node", - ); - } + return response; } catch (e) { throw Error( `${fnTag} Obtaining info for this transaction has failed. ` + diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/run-transaction.test.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/run-transaction.test.ts index fb16bb1ff45..fc44f6027c5 100644 --- a/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/run-transaction.test.ts +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/run-transaction.test.ts @@ -1,12 +1,6 @@ import { PrometheusExporter } from "../../../main/typescript/prometheus-exporter/prometheus-exporter"; import { AddressInfo } from "net"; import { v4 as uuidv4 } from "uuid"; -import type { SignerOptions } from "@polkadot/api/submittable/types"; -import type { - CodecHash, - ExtrinsicEra, - Index, -} from "@polkadot/types/interfaces"; import { Configuration } from "@hyperledger/cactus-core-api"; import { Keyring } from "@polkadot/api"; import http from "http"; @@ -115,15 +109,14 @@ test(testCase, async (t: Test) => { t2.equal(infoForSigningTransaction.status, 200); const response = infoForSigningTransaction.data; t2.ok(response); - const nonce = response.responseContainer.response_data.nonce as Index; + const nonce = response.responseContainer.response_data.nonce; t2.ok(nonce); - const blockHash = response.responseContainer.response_data - .blockHash as CodecHash; + const blockHash = response.responseContainer.response_data.blockHash; t2.ok(blockHash); - const era = response.responseContainer.response_data.era as ExtrinsicEra; + const era = response.responseContainer.response_data.era; t2.ok(era); - const signingOptions: SignerOptions = { + const signingOptions = { nonce: nonce, blockHash: blockHash, era: era, @@ -133,6 +126,8 @@ test(testCase, async (t: Test) => { to: bobPair.address, value: 20, }); + t2.ok(transaction); + t2.ok(transaction.data.responseContainer.response_data.rawTransaction); const rawTransaction = transaction.data.responseContainer.response_data.rawTransaction; @@ -144,8 +139,6 @@ test(testCase, async (t: Test) => { t2.ok(signedTransactionResponse.data.success); t2.ok(signedTransactionResponse.data.signedTransaction); t2.comment(`Signed transaction is: ${rawTransaction}`); - - t2.ok(rawTransaction); const signedTransaction = signedTransactionResponse.data.signedTransaction; const TransactionDetails = await apiClient.runTransaction({ web3SigningCredential: { type: "NONE" },