diff --git a/.changeset/funny-cherries-drive.md b/.changeset/funny-cherries-drive.md new file mode 100644 index 0000000000..922a306896 --- /dev/null +++ b/.changeset/funny-cherries-drive.md @@ -0,0 +1,5 @@ +--- +"@kadena/graph": patch +--- + +Fixed transaction subscription issue with mempool and completed transactions diff --git a/packages/apps/graph/src/graph/mappers/transaction-mapper.ts b/packages/apps/graph/src/graph/mappers/transaction-mapper.ts index 9babdb80c6..78452b3f9a 100644 --- a/packages/apps/graph/src/graph/mappers/transaction-mapper.ts +++ b/packages/apps/graph/src/graph/mappers/transaction-mapper.ts @@ -28,7 +28,7 @@ export function mempoolTransactionMapper(mempoolData: any): Transaction { // Convert creationTime to milliseconds (mempool has it in epoch format in seconds) mempoolTx.cmd.meta.creationTime = mempoolTx.cmd.meta.creationTime * 1000; - const transaction = { + const transaction: Transaction = { requestKey: mempoolTx.hash, badResult: null, continuation: null, @@ -51,7 +51,9 @@ export function mempoolTransactionMapper(mempoolData: any): Transaction { rollback: mempoolTx.cmd.payload.rollback, proof: mempoolTx.cmd.payload.proof, senderAccount: mempoolTx.cmd.meta.sender, - step: BigInt(mempoolTx.cmd.payload.step), + step: mempoolTx.cmd.payload.step + ? BigInt(mempoolTx.cmd.payload.step) + : mempoolTx.cmd.payload.step, ttl: BigInt(mempoolTx.cmd.meta.ttl), }; diff --git a/packages/apps/graph/src/graph/objects/transaction.ts b/packages/apps/graph/src/graph/objects/transaction.ts index 67fee6f83e..de006405d1 100644 --- a/packages/apps/graph/src/graph/objects/transaction.ts +++ b/packages/apps/graph/src/graph/objects/transaction.ts @@ -1,3 +1,4 @@ +import type { Signer } from '@prisma/client'; import { Prisma } from '@prisma/client'; import { getMempoolTransactionStatus } from '@services/chainweb-node/mempool'; import { normalizeError } from '@utils/errors'; @@ -22,27 +23,33 @@ export default builder.prismaNode(Prisma.ModelName.Transaction, { sigs: t.field({ type: [TransactionSigs], async resolve(parent) { - const signers = await signersLoader.load({ - blockHash: parent.blockHash, - requestKey: parent.requestKey, - chainId: parent.chainId.toString(), - }); + if (!nullishOrEmpty(parent.blockHash)) { + const signers = await signersLoader.load({ + blockHash: parent.blockHash, + requestKey: parent.requestKey, + chainId: parent.chainId.toString(), + }); - return signers.map((signer) => ({ - sig: signer.signature, - })); + return signers.map((signer) => ({ + sig: signer.signature, + })); + } + return []; }, }), cmd: t.field({ type: TransactionCommand, - async resolve(parent, __args, context) { + async resolve(parent, __args) { try { - const signers = await signersLoader.load({ - blockHash: parent.blockHash, - requestKey: parent.requestKey, - chainId: parent.chainId.toString(), - }); + let signers: Signer[] = []; + if (!nullishOrEmpty(parent.blockHash)) { + signers = await signersLoader.load({ + blockHash: parent.blockHash, + requestKey: parent.requestKey, + chainId: parent.chainId.toString(), + }); + } return { nonce: parent.nonce, @@ -74,15 +81,18 @@ export default builder.prismaNode(Prisma.ModelName.Transaction, { type: TransactonInfo, resolve: async (parent) => { try { - const status = await getMempoolTransactionStatus( - parent.requestKey, - parent.chainId.toString(), - ); + //This check is important because a transaction can be completed, yet we can still be able to fetch a status from the mempool + if (nullishOrEmpty(parent.blockHash)) { + const status = await getMempoolTransactionStatus( + parent.requestKey, + parent.chainId.toString(), + ); - if (!nullishOrEmpty(status) && status) { - return { - status, - }; + if (!nullishOrEmpty(status) && status) { + return { + status, + }; + } } return { diff --git a/packages/apps/graph/src/graph/subscription/transaction.ts b/packages/apps/graph/src/graph/subscription/transaction.ts index f06b0b5901..ba129935f1 100644 --- a/packages/apps/graph/src/graph/subscription/transaction.ts +++ b/packages/apps/graph/src/graph/subscription/transaction.ts @@ -59,6 +59,8 @@ async function* iteratorFn( if (mempoolResponse) { yield mempoolResponse; + } else { + yield undefined; } } diff --git a/packages/apps/graph/src/services/chainweb-node/mempool.ts b/packages/apps/graph/src/services/chainweb-node/mempool.ts index 648d344f7d..8c0d907b84 100644 --- a/packages/apps/graph/src/services/chainweb-node/mempool.ts +++ b/packages/apps/graph/src/services/chainweb-node/mempool.ts @@ -100,11 +100,19 @@ export async function mempoolLookup( }); res.on('end', () => { - resolve(JSON.parse(data)); + try { + resolve(JSON.parse(data)); + } catch (error) { + reject( + new MempoolError( + 'Error occurred while processing response data.', + error, + ), + ); + } }); }, ); - req.on('error', (error) => { reject( new MempoolError(