-
Notifications
You must be signed in to change notification settings - Fork 47
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
TransactionWorker
to fire events a dapp can listen to
#255
Conversation
91fcbb3
to
a506d33
Compare
a506d33
to
750c583
Compare
/** | ||
* Internal function to start listening to transaction worker events | ||
* | ||
* TODO - should we ask events to listen to as an input? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless it's really expense to emit events it might not be worth the complexity.
@@ -157,12 +165,21 @@ export class TransactionWorker { | |||
// transaction sent to chain | |||
this.sentTransactions.push([sentTransaction.value.hash, sequenceNumber, null]); | |||
// check sent transaction execution | |||
this.emit( | |||
TransactionWorkerEvents.TransactionSent, | |||
`transaction hash ${sentTransaction.value.hash} has been commited to chain`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the data being emitted? If so, shouldn't we emit something structured instead? That way the callback can actually do something with the data. So it emits some kind of TransactionSentEventData
that has a txnHash
field. The user can use that type in the callback too rather than data: any
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call! I have updated the worker/management to have a types returned data
3adb827
to
f4240f2
Compare
export interface TransactionWorkerEvents { | ||
transactionSent: (data: SuccessEventData) => void; | ||
transactionSendFailed: (data: FailureEventData) => void; | ||
transactionExecuted: (data: SuccessEventData) => void; | ||
transactionExecutionFailed: (data: FailureEventData) => void; | ||
executionFinish: (data: ExecutionFinishEventData) => void; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, just double checking I understand each event:
transactionSent
is fired after a transaction gets sent to the chaintransactionSendFailed
is fired if there is an error sending the transaction to the chaintransactionExecuted
is fired when a single transaction has run successfullytransactionExecutionFailed
is run if a single transaction fails in executionexecutionFinish
is run when the queue has been emptied
So if someone wanted to make an async function to batch requests, it would look like this:
// Pseudo code
type TxnHash = string;
function batchTransactionExample(sender: Account, payload: InputGenerateTransactionPayloadData[]): Promise<{
succeeded_txns: TxnHash[],
failed_txns: TxnHash[]
}> {
return new Promise(async (resolve, reject) => {
let succeeded_txns = [];
let failed_txns = [];
aptos.transaction.batch.forSingleAccount({sender, data: payload})
// Handle transaction successes, we don't care about sent, just executed
aptos.transaction.batch.on(TransactionWorkerEvents.TransactionExecuted, async (data: any) => {
succeeded_txns.push(data.txn_hash);
});
// Handle transaction failures (execution or send)
aptos.transaction.batch.on(TransactionWorkerEvents.TransactionExecutionFailed, async (data: any) => {
failed_txns.push(data.txn_hash);
});
aptos.transaction.batch.on(TransactionWorkerEvents.TransactionSendFailed, async (data: any) => {
failed_txns.push(data.txn_hash);
});
// Handle resolving the promise
aptos.transaction.batch.on(TransactionWorkerEvents.ExecutionFinish, async (data: any) => {
resolve({ succeeded_txns, failed_txns })
});
})
}
I'm guessing the caller will have to unsubscribe from the emitter? That is something we would want to highlight in the two examples potentially.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep! I'll add some doc comments - good catch!
34493ca
to
2f5b98e
Compare
); | ||
}); | ||
// worker finished execution, we can now unsubscribe from event listeners | ||
aptos.transaction.batch.removeAllListeners(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for getting this in!!!
Description
The transaction management is a send-and-forget process in a way that once transactions are sent to worker, the dapp is not aware of what is going on unless a potential error happens.
This PR adds logic for the
TransactionWorker
module to fire events during a worker task and dapp can listen to these events.Note:
Currently, dapp uses
aptos.batchTransactionsForSingleAccount()
to start the worker. We now introduce a dedicated namespace underaptos.transaction.batch
where one can useaptos.transaction.batch.forSingleAccount()
same as before. This is for potential future enhancement of the worker and to conform with the sdk design.Test Plan
pnpm test
batch_mint
andbatch_funds
for examplesRelated Links