1 | const { sleep, loop } = require('../util');
|
2 | const LazyPromise = require('./LazyPromise');
|
3 |
|
4 | /**
|
5 | * Pending transaction subscriber
|
6 | */
|
7 | class PendingTransaction extends LazyPromise {
|
8 | constructor(func, params, conflux) {
|
9 | super(func, params);
|
10 | this.conflux = conflux;
|
11 | }
|
12 |
|
13 | /**
|
14 | * Get transaction by hash.
|
15 | *
|
16 | * @param [options] {object}
|
17 | * @param [options.delay=0] {number} - Defer execute after `delay` ms.
|
18 | * @return {Promise<Object|null>} See [Conflux.getTransactionByHash](#Conflux.js/getTransactionByHash)
|
19 | */
|
20 | async get({ delay = 0 } = {}) {
|
21 | await sleep(delay);
|
22 | const transactionHash = await this;
|
23 | return this.conflux.getTransactionByHash(transactionHash);
|
24 | }
|
25 |
|
26 | /**
|
27 | * Async wait till transaction been mined.
|
28 | *
|
29 | * - blockHash !== null
|
30 | *
|
31 | * @param [options] {object}
|
32 | * @param [options.delta=1000] {number} - Loop transaction interval in ms.
|
33 | * @param [options.timeout=60*1000] {number} - Loop timeout in ms.
|
34 | * @return {Promise<object>} See [Conflux.getTransactionByHash](#Conflux.js/getTransactionByHash)
|
35 | */
|
36 | async mined({ delta = 1000, timeout = 60 * 1000 } = {}) {
|
37 | return loop({ delta, timeout }, async () => {
|
38 | const transaction = await this.get();
|
39 | if (transaction && transaction.blockHash) {
|
40 | return transaction;
|
41 | }
|
42 |
|
43 | return undefined;
|
44 | });
|
45 | }
|
46 |
|
47 | /**
|
48 | * Async wait till transaction been executed.
|
49 | *
|
50 | * - mined
|
51 | * - receipt !== null
|
52 | * - receipt.outcomeStatus === 0
|
53 | *
|
54 | * @param [options] {object}
|
55 | * @param [options.delta=1000] {number} - Loop transaction interval in ms.
|
56 | * @param [options.timeout=5*60*1000] {number} - Loop timeout in ms.
|
57 | * @return {Promise<object>} See [Conflux.getTransactionReceipt](#Conflux.js/getTransactionReceipt)
|
58 | */
|
59 | async executed({ delta = 1000, timeout = 5 * 60 * 1000 } = {}) {
|
60 | const transactionHash = await this;
|
61 | return loop({ delta, timeout }, async () => {
|
62 | const receipt = await this.conflux.getTransactionReceipt(transactionHash);
|
63 | if (receipt) {
|
64 | if (receipt.outcomeStatus !== 0) {
|
65 | throw new Error(`transaction "${transactionHash}" executed failed, outcomeStatus ${receipt.outcomeStatus}`);
|
66 | }
|
67 |
|
68 | return receipt;
|
69 | }
|
70 |
|
71 | return undefined;
|
72 | });
|
73 | }
|
74 |
|
75 | /**
|
76 | * Async wait till transaction been confirmed.
|
77 | *
|
78 | * - executed
|
79 | * - transaction block risk coefficient < threshold
|
80 | *
|
81 | * @param [options] {object}
|
82 | * @param [options.delta=1000] {number} - Loop transaction interval in ms.
|
83 | * @param [options.timeout=30*60*1000] {number} - Loop timeout in ms.
|
84 | * @param [options.threshold=1e-8] {number} - Number in range (0,1)
|
85 | * @return {Promise<object>} See [Conflux.getTransactionReceipt](#Conflux.js/getTransactionReceipt)
|
86 | */
|
87 | async confirmed({ delta = 1000, timeout = 30 * 60 * 1000, threshold = 1e-8 } = {}) {
|
88 | return loop({ delta, timeout }, async () => {
|
89 | const receipt = await this.executed({ delta, timeout });
|
90 | const risk = await this.conflux.getConfirmationRiskByHash(receipt.blockHash);
|
91 | if (risk <= threshold) {
|
92 | return receipt;
|
93 | }
|
94 |
|
95 | return undefined;
|
96 | });
|
97 | }
|
98 | }
|
99 |
|
100 | module.exports = PendingTransaction;
|