1
1
import * as Cardano from '../Cardano' ;
2
2
import * as Crypto from '@cardano-sdk/crypto' ;
3
3
import { AssetId , TokenMap } from '../Cardano' ;
4
- import { AssetInfoWithAmount } from './tokenTransferInspector' ;
4
+ import { AssetInfoWithAmount , resolveWithTimeout } from './tokenTransferInspector' ;
5
5
import { AssetProvider } from '../Provider' ;
6
6
import {
7
7
AssetsMintedInspection ,
@@ -14,6 +14,8 @@ import {
14
14
totalAddressOutputsValueInspector
15
15
} from './txInspector' ;
16
16
import { BigIntMath } from '@cardano-sdk/util' ;
17
+ import { Logger } from 'ts-log' ;
18
+ import { Milliseconds } from './time' ;
17
19
import { coalesceTokenMaps , subtractTokenMaps } from '../Asset/util' ;
18
20
import { coalesceValueQuantities } from './coalesceValueQuantities' ;
19
21
import { computeImplicitCoin } from '../Cardano/util' ;
@@ -26,6 +28,8 @@ interface TransactionSummaryInspectorArgs {
26
28
protocolParameters : Cardano . ProtocolParameters ;
27
29
assetProvider : AssetProvider ;
28
30
dRepKeyHash ?: Crypto . Ed25519KeyHashHex ;
31
+ timeout : Milliseconds ;
32
+ logger ?: Logger ;
29
33
}
30
34
31
35
export type TransactionSummaryInspection = {
@@ -140,46 +144,106 @@ const toAssetInfoWithAmount = async (
140
144
return assetInfos ;
141
145
} ;
142
146
147
+ // todo: when timeout or provider error occurs during input resolution, return any unresolved inputs value in unresolved property;
148
+ // todo: when resolving AssetInfo fails due to provider error or timeout, resolve it without any metadata and set quantity/supply to -1. Document this behavior in doc comments.
149
+
143
150
/**
144
151
* Inspects a transaction and produces a summary.
145
152
*
146
153
* @param {TransactionSummaryInspectorArgs } args The arguments for the inspector.
147
154
*/
148
155
export const transactionSummaryInspector : TransactionSummaryInspector =
149
156
( args : TransactionSummaryInspectorArgs ) => async ( tx ) => {
150
- const { inputResolver, addresses, rewardAccounts, protocolParameters, assetProvider, dRepKeyHash } = args ;
151
- const resolvedInputs = await resolveInputs ( tx . body . inputs , inputResolver ) ;
152
- const fee = tx . body . fee ;
153
-
154
- const implicit = computeImplicitCoin (
157
+ const {
158
+ inputResolver,
159
+ addresses,
160
+ rewardAccounts,
155
161
protocolParameters,
156
- { certificates : tx . body . certificates , withdrawals : tx . body . withdrawals } ,
157
- rewardAccounts || [ ] ,
158
- dRepKeyHash
159
- ) ;
160
-
161
- const collateral = await getCollateral ( tx , inputResolver , addresses ) ;
162
-
163
- const totalOutputValue = await totalAddressOutputsValueInspector ( addresses ) ( tx ) ;
164
- const totalInputValue = await totalAddressInputsValueInspector ( addresses , inputResolver ) ( tx ) ;
165
- const implicitCoin = ( implicit . withdrawals || 0n ) + ( implicit . reclaimDeposit || 0n ) - ( implicit . deposit || 0n ) ;
166
- const implicitAssets = await getImplicitAssets ( tx ) ;
167
-
168
- const diff = {
169
- assets : subtractTokenMaps ( [ totalOutputValue . assets , totalInputValue . assets ] ) ,
170
- coins : totalOutputValue . coins - totalInputValue . coins
171
- } ;
172
-
173
- return {
174
- assets : await toAssetInfoWithAmount ( assetProvider , diff . assets ) ,
175
- coins : diff . coins ,
176
- collateral,
177
- deposit : implicit . deposit || 0n ,
178
- fee,
179
- returnedDeposit : implicit . reclaimDeposit || 0n ,
180
- unresolved : {
181
- inputs : resolvedInputs . unresolvedInputs ,
182
- value : await getUnaccountedFunds ( tx , resolvedInputs , implicitCoin , fee , implicitAssets )
162
+ assetProvider,
163
+ dRepKeyHash,
164
+ timeout,
165
+ logger
166
+ } = args ;
167
+
168
+ try {
169
+ // eslint-disable-next-line sonarjs/prefer-immediate-return
170
+ const resolvedInputs = await resolveWithTimeout ( resolveInputs ( tx . body . inputs , inputResolver ) , timeout ) ;
171
+ const fee = tx . body . fee ;
172
+
173
+ const implicit = computeImplicitCoin (
174
+ protocolParameters ,
175
+ { certificates : tx . body . certificates , withdrawals : tx . body . withdrawals } ,
176
+ rewardAccounts || [ ] ,
177
+ dRepKeyHash
178
+ ) ;
179
+
180
+ const collateral = await getCollateral ( tx , inputResolver , addresses ) ;
181
+
182
+ const totalOutputValue = await totalAddressOutputsValueInspector ( addresses ) ( tx ) ;
183
+ const totalInputValue = await totalAddressInputsValueInspector ( addresses , inputResolver ) ( tx ) ;
184
+ const implicitCoin = ( implicit . withdrawals || 0n ) + ( implicit . reclaimDeposit || 0n ) - ( implicit . deposit || 0n ) ;
185
+ const implicitAssets = await getImplicitAssets ( tx ) ;
186
+
187
+ const diff = {
188
+ assets : subtractTokenMaps ( [ totalOutputValue . assets , totalInputValue . assets ] ) ,
189
+ coins : totalOutputValue . coins - totalInputValue . coins
190
+ } ;
191
+
192
+ return {
193
+ assets : await toAssetInfoWithAmount ( assetProvider , diff . assets ) ,
194
+ coins : diff . coins ,
195
+ collateral,
196
+ deposit : implicit . deposit || 0n ,
197
+ fee,
198
+ returnedDeposit : implicit . reclaimDeposit || 0n ,
199
+ unresolved : {
200
+ inputs : resolvedInputs . unresolvedInputs ,
201
+ value : await getUnaccountedFunds ( tx , resolvedInputs , implicitCoin , fee , implicitAssets )
202
+ }
203
+ } ;
204
+ } catch ( error ) {
205
+ // also, resolve this null
206
+ // todo: when resolving AssetInfo fails due to provider error or timeout, resolve it without any metadata and set quantity/supply to -1. Document this behavior in doc comments.
207
+ if ( error === 'Timeout: failed to resolve inputs in time' ) {
208
+ // Handle timeout error specifically
209
+ logger . log ( 'Error: Inputs resolution timed out' ) ;
210
+ } else {
211
+ // Bubble up any other error
212
+ throw error ;
183
213
}
184
- } ;
214
+ }
215
+
216
+ // const fee = tx.body.fee;
217
+
218
+ // const implicit = computeImplicitCoin(
219
+ // protocolParameters,
220
+ // { certificates: tx.body.certificates, withdrawals: tx.body.withdrawals },
221
+ // rewardAccounts || [],
222
+ // dRepKeyHash
223
+ // );
224
+
225
+ // const collateral = await getCollateral(tx, inputResolver, addresses);
226
+
227
+ // const totalOutputValue = await totalAddressOutputsValueInspector(addresses)(tx);
228
+ // const totalInputValue = await totalAddressInputsValueInspector(addresses, inputResolver)(tx);
229
+ // const implicitCoin = (implicit.withdrawals || 0n) + (implicit.reclaimDeposit || 0n) - (implicit.deposit || 0n);
230
+ // const implicitAssets = await getImplicitAssets(tx);
231
+
232
+ // const diff = {
233
+ // assets: subtractTokenMaps([totalOutputValue.assets, totalInputValue.assets]),
234
+ // coins: totalOutputValue.coins - totalInputValue.coins
235
+ // };
236
+
237
+ // return {
238
+ // assets: await toAssetInfoWithAmount(assetProvider, diff.assets),
239
+ // coins: diff.coins,
240
+ // collateral,
241
+ // deposit: implicit.deposit || 0n,
242
+ // fee,
243
+ // returnedDeposit: implicit.reclaimDeposit || 0n,
244
+ // unresolved: {
245
+ // inputs: resolvedInputs.unresolvedInputs,
246
+ // value: await getUnaccountedFunds(tx, resolvedInputs, implicitCoin, fee, implicitAssets)
247
+ // }
248
+ // };
185
249
} ;
0 commit comments