0xtrails 0.9.2 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ccip-g6lDdnrD.js → ccip-lAtzqne5.js} +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/{index-D-QngA_s.js → index-D5AG6huo.js} +22290 -21786
- package/dist/index.js +3 -3
- package/dist/intents.d.ts +1 -1
- package/dist/intents.d.ts.map +1 -1
- package/dist/mutations.d.ts +5 -2
- package/dist/mutations.d.ts.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/transactionIntent/constants.d.ts +1 -0
- package/dist/transactionIntent/constants.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +3 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/standardDeposit.d.ts +4 -1
- package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
- package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
- package/dist/transactionIntent/types.d.ts +2 -0
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/transactionIntent/utils/resilientDepositTracker.d.ts +25 -0
- package/dist/transactionIntent/utils/resilientDepositTracker.d.ts.map +1 -0
- package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/ConfigDisplay.d.ts.map +1 -1
- package/dist/widget/components/DynamicInputStyles.d.ts +2 -2
- package/dist/widget/components/Earn.d.ts.map +1 -1
- package/dist/widget/components/EarnPools.d.ts.map +1 -1
- package/dist/widget/components/Fund.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
- package/dist/widget/components/TransactionDetails.d.ts.map +1 -1
- package/dist/widget/components/UserPreferences.d.ts.map +1 -1
- package/dist/widget/components/WalletConnect.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/hooks/useQuote.d.ts +2 -0
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/providers/TrailsProvider.d.ts +2 -0
- package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
- package/dist/widget/widget.d.ts +1 -0
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/config.ts +1 -0
- package/src/constants.ts +1 -0
- package/src/error.ts +6 -1
- package/src/intents.ts +22 -1
- package/src/prices.ts +1 -1
- package/src/tokens.ts +4 -3
- package/src/transactionIntent/constants.ts +2 -0
- package/src/transactionIntent/deposits/depositOrchestrator.ts +7 -0
- package/src/transactionIntent/deposits/standardDeposit.ts +194 -37
- package/src/transactionIntent/handlers/crossChain.ts +152 -105
- package/src/transactionIntent/handlers/sameChainSameToken.ts +1 -0
- package/src/transactionIntent/quote/normalizeQuote.ts +7 -4
- package/src/transactionIntent/types.ts +2 -0
- package/src/transactionIntent/utils/resilientDepositTracker.ts +281 -0
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistory.tsx +170 -87
- package/src/widget/components/ClassicSwap.tsx +7 -1
- package/src/widget/components/ConfigDisplay.tsx +5 -0
- package/src/widget/components/Earn.tsx +14 -1
- package/src/widget/components/EarnPools.tsx +180 -59
- package/src/widget/components/Fund.tsx +3 -1
- package/src/widget/components/PoolWithdraw.tsx +1 -1
- package/src/widget/components/QuoteDetails.tsx +12 -35
- package/src/widget/components/Receipt.tsx +66 -40
- package/src/widget/components/SlippageToleranceSettings.tsx +86 -44
- package/src/widget/components/TransactionDetails.tsx +138 -218
- package/src/widget/components/UserPreferences.tsx +114 -41
- package/src/widget/components/WalletConnect.tsx +111 -48
- package/src/widget/hooks/useQuote.ts +389 -352
- package/src/widget/providers/TrailsProvider.tsx +5 -0
- package/src/widget/widget.tsx +2 -0
package/src/intents.ts
CHANGED
|
@@ -120,6 +120,7 @@ export async function quoteIntent(
|
|
|
120
120
|
trailsClient: TrailsApi,
|
|
121
121
|
args: QuoteIntentRequest,
|
|
122
122
|
additionalTrackingProps: Record<string, string> = {},
|
|
123
|
+
abortSignal?: AbortSignal,
|
|
123
124
|
): Promise<{
|
|
124
125
|
intent: Intent
|
|
125
126
|
gasFeeOptions?: GasFeeOptions
|
|
@@ -137,7 +138,27 @@ export async function quoteIntent(
|
|
|
137
138
|
|
|
138
139
|
try {
|
|
139
140
|
logger.console.log("[trails-sdk] quote intent args:", args)
|
|
140
|
-
|
|
141
|
+
|
|
142
|
+
// Create a promise that rejects when the abort signal fires
|
|
143
|
+
let response: any
|
|
144
|
+
if (abortSignal) {
|
|
145
|
+
const abortPromise = new Promise((_, reject) => {
|
|
146
|
+
if (abortSignal.aborted) {
|
|
147
|
+
reject(new Error("Request aborted"))
|
|
148
|
+
}
|
|
149
|
+
abortSignal.addEventListener("abort", () => {
|
|
150
|
+
reject(new Error("Request aborted"))
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
// Race between the API call and the abort signal
|
|
155
|
+
response = await Promise.race([
|
|
156
|
+
trailsClient.quoteIntent(args, {}, abortSignal),
|
|
157
|
+
abortPromise,
|
|
158
|
+
])
|
|
159
|
+
} else {
|
|
160
|
+
response = await trailsClient.quoteIntent(args)
|
|
161
|
+
}
|
|
141
162
|
|
|
142
163
|
if (!response || !response.intent) {
|
|
143
164
|
logger.console.error("[trails-sdk] No result from quoteIntent")
|
package/src/prices.ts
CHANGED
|
@@ -10,7 +10,7 @@ const CACHE_CONFIG = {
|
|
|
10
10
|
// Time configurations
|
|
11
11
|
staleTime: 5000, // 5 seconds - max cache time for token balance related prices
|
|
12
12
|
gcTime: 5000, // 5 seconds cache time
|
|
13
|
-
refetchInterval:
|
|
13
|
+
refetchInterval: 15000, // Background refetch every 15 seconds for prices
|
|
14
14
|
|
|
15
15
|
// Retry configurations
|
|
16
16
|
retry: 2,
|
package/src/tokens.ts
CHANGED
|
@@ -529,11 +529,12 @@ export function useSupportedTokens({ chainId }: { chainId?: number } = {}): {
|
|
|
529
529
|
trailsConfig.trailsApiUrl,
|
|
530
530
|
trailsConfig.trailsApiKey,
|
|
531
531
|
],
|
|
532
|
-
queryFn: () =>
|
|
533
|
-
getSupportedTokens({
|
|
532
|
+
queryFn: async () => {
|
|
533
|
+
return getSupportedTokens({
|
|
534
534
|
trailsApiKey: trailsConfig.trailsApiKey,
|
|
535
535
|
trailsApiUrl: trailsConfig.trailsApiUrl,
|
|
536
|
-
})
|
|
536
|
+
})
|
|
537
|
+
},
|
|
537
538
|
staleTime: 60 * 60 * 1000, // 1 hour - tokens rarely change
|
|
538
539
|
gcTime: 24 * 60 * 60 * 1000, // 24 hours - keep in cache for a full day
|
|
539
540
|
refetchOnWindowFocus: false, // Don't refetch when window regains focus
|
|
@@ -52,6 +52,8 @@ export async function attemptUserDepositTx({
|
|
|
52
52
|
depositRecipientOverride,
|
|
53
53
|
isSameChainSameToken,
|
|
54
54
|
destinationCalldata,
|
|
55
|
+
sequenceProjectAccessKey,
|
|
56
|
+
sequenceIndexerUrl,
|
|
55
57
|
}: {
|
|
56
58
|
originTokenAddress: string
|
|
57
59
|
paymasterUrl?: string
|
|
@@ -89,6 +91,8 @@ export async function attemptUserDepositTx({
|
|
|
89
91
|
depositRecipientOverride?: string
|
|
90
92
|
isSameChainSameToken?: boolean
|
|
91
93
|
destinationCalldata?: string
|
|
94
|
+
sequenceProjectAccessKey?: string
|
|
95
|
+
sequenceIndexerUrl?: string
|
|
92
96
|
}): Promise<TransactionReceipt | null> {
|
|
93
97
|
let depositUserTxnReceipt: TransactionReceipt | null = null
|
|
94
98
|
const originChainId = chain.id
|
|
@@ -207,6 +211,9 @@ export async function attemptUserDepositTx({
|
|
|
207
211
|
isSameChainSameToken,
|
|
208
212
|
recipient: effectiveDepositRecipient,
|
|
209
213
|
destinationCalldata,
|
|
214
|
+
sequenceProjectAccessKey,
|
|
215
|
+
sequenceIndexerUrl,
|
|
216
|
+
abortSignal,
|
|
210
217
|
})
|
|
211
218
|
}
|
|
212
219
|
|
|
@@ -22,6 +22,10 @@ import { updatePersistentToast } from "../../toast.js"
|
|
|
22
22
|
import { getChainInfo } from "../../chains.js"
|
|
23
23
|
import { trackTransactionConfirmed } from "../../analytics.js"
|
|
24
24
|
import { getIsUserRejectionError } from "../../error.js"
|
|
25
|
+
import {
|
|
26
|
+
trackDepositResilient,
|
|
27
|
+
isRecoverableDepositError,
|
|
28
|
+
} from "../utils/resilientDepositTracker.js"
|
|
25
29
|
|
|
26
30
|
export async function attemptStandardDeposit({
|
|
27
31
|
originTokenAddress,
|
|
@@ -42,6 +46,9 @@ export async function attemptStandardDeposit({
|
|
|
42
46
|
isSameChainSameToken,
|
|
43
47
|
recipient,
|
|
44
48
|
destinationCalldata,
|
|
49
|
+
sequenceProjectAccessKey,
|
|
50
|
+
sequenceIndexerUrl,
|
|
51
|
+
abortSignal,
|
|
45
52
|
}: {
|
|
46
53
|
originTokenAddress: string
|
|
47
54
|
depositAmount: string
|
|
@@ -66,6 +73,9 @@ export async function attemptStandardDeposit({
|
|
|
66
73
|
isSameChainSameToken?: boolean
|
|
67
74
|
recipient?: string
|
|
68
75
|
destinationCalldata?: string
|
|
76
|
+
sequenceProjectAccessKey?: string
|
|
77
|
+
sequenceIndexerUrl?: string
|
|
78
|
+
abortSignal?: AbortSignal
|
|
69
79
|
}): Promise<TransactionReceipt | null> {
|
|
70
80
|
logger.console.log("[trails-sdk] [STANDARD DEPOSIT] initiating deposit...")
|
|
71
81
|
let depositUserTxnReceipt: TransactionReceipt | null = null
|
|
@@ -444,7 +454,9 @@ export async function attemptStandardDeposit({
|
|
|
444
454
|
checkoutOnHandlers.triggerCheckoutSignatureRequest()
|
|
445
455
|
}
|
|
446
456
|
|
|
447
|
-
let txHash: `0x${string}`
|
|
457
|
+
let txHash: `0x${string}` | null = null
|
|
458
|
+
let sendError: unknown = null
|
|
459
|
+
|
|
448
460
|
try {
|
|
449
461
|
txHash = await sendOriginTransaction(
|
|
450
462
|
account,
|
|
@@ -456,63 +468,208 @@ export async function attemptStandardDeposit({
|
|
|
456
468
|
) // TODO: Add proper type
|
|
457
469
|
logger.console.log("[trails-sdk] origin tx", txHash)
|
|
458
470
|
|
|
471
|
+
// SIMULATE RPC ERROR: Throw error after successful transaction send
|
|
472
|
+
// This simulates the scenario where tx is broadcast but RPC fails immediately after
|
|
473
|
+
// if (true) { // Always enabled for testing
|
|
474
|
+
// logger.console.warn(
|
|
475
|
+
// "[trails-sdk] SIMULATING RPC ERROR after transaction send",
|
|
476
|
+
// { txHash }
|
|
477
|
+
// )
|
|
478
|
+
// throw new Error("SIMULATED: RPC connection lost after transaction broadcast")
|
|
479
|
+
// }
|
|
480
|
+
|
|
459
481
|
// Trigger signature confirmed callback after successful signing
|
|
460
482
|
if (checkoutOnHandlers?.triggerCheckoutSignatureConfirmed) {
|
|
461
|
-
checkoutOnHandlers
|
|
483
|
+
checkoutOnHandlers?.triggerCheckoutSignatureConfirmed?.()
|
|
462
484
|
}
|
|
463
485
|
} catch (error) {
|
|
486
|
+
sendError = error
|
|
487
|
+
logger.console.error(
|
|
488
|
+
"[trails-sdk] Error sending deposit transaction",
|
|
489
|
+
error,
|
|
490
|
+
)
|
|
491
|
+
|
|
464
492
|
// Check if this is a user rejection error
|
|
465
493
|
if (getIsUserRejectionError(error)) {
|
|
466
494
|
if (checkoutOnHandlers?.triggerCheckoutSignatureRejected) {
|
|
467
495
|
checkoutOnHandlers.triggerCheckoutSignatureRejected(error)
|
|
468
496
|
}
|
|
497
|
+
throw error // User rejections should fail immediately
|
|
469
498
|
}
|
|
470
|
-
throw error
|
|
471
|
-
}
|
|
472
499
|
|
|
473
|
-
|
|
474
|
-
|
|
500
|
+
// For recoverable errors, log but don't throw yet
|
|
501
|
+
if (!isRecoverableDepositError(error)) {
|
|
502
|
+
throw error // Non-recoverable errors should fail
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
logger.console.log(
|
|
506
|
+
"[trails-sdk] Deposit send failed with recoverable error, will attempt polling",
|
|
507
|
+
{ error: (error as Error)?.message },
|
|
508
|
+
)
|
|
475
509
|
}
|
|
476
510
|
|
|
477
|
-
|
|
478
|
-
|
|
511
|
+
// Handle successful transaction hash or fall back to resilient tracking
|
|
512
|
+
if (txHash) {
|
|
513
|
+
if (onOriginSend) {
|
|
514
|
+
onOriginSend()
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
if (transactionStates[0]) {
|
|
518
|
+
transactionStates[0].state = "pending"
|
|
519
|
+
transactionStates[0].transactionHash = txHash
|
|
520
|
+
|
|
521
|
+
try {
|
|
522
|
+
onTransactionStateChange(transactionStates)
|
|
523
|
+
} catch (error) {
|
|
524
|
+
logger.console.error(
|
|
525
|
+
"[trails-sdk] Error calling onTransactionStateChange:",
|
|
526
|
+
error,
|
|
527
|
+
)
|
|
528
|
+
}
|
|
529
|
+
}
|
|
479
530
|
|
|
531
|
+
// Try normal receipt retrieval first
|
|
480
532
|
try {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
533
|
+
// Wait for transaction receipt
|
|
534
|
+
const receipt = await publicClient.waitForTransactionReceipt({
|
|
535
|
+
hash: txHash,
|
|
536
|
+
retryCount: 10,
|
|
537
|
+
})
|
|
538
|
+
|
|
539
|
+
const chainInfo = getChainInfo(originChainId)
|
|
540
|
+
updatePersistentToast(
|
|
541
|
+
"Transfer Confirmed",
|
|
542
|
+
`Your transaction on ${chainInfo?.name || "chain"} has been confirmed`,
|
|
543
|
+
"info",
|
|
486
544
|
)
|
|
545
|
+
|
|
546
|
+
trackTransactionConfirmed({
|
|
547
|
+
transactionHash: txHash,
|
|
548
|
+
chainId: originChainId,
|
|
549
|
+
userAddress: account.address,
|
|
550
|
+
blockNumber: Number(receipt.blockNumber),
|
|
551
|
+
originIntentAddress,
|
|
552
|
+
originTokenSymbol,
|
|
553
|
+
destinationTokenSymbol,
|
|
554
|
+
depositTokenAmountUsd: depositAmountUsd?.toString(),
|
|
555
|
+
})
|
|
556
|
+
|
|
557
|
+
logger.console.log("[trails-sdk] receipt", receipt)
|
|
558
|
+
depositUserTxnReceipt = receipt
|
|
559
|
+
} catch (receiptError) {
|
|
560
|
+
logger.console.warn(
|
|
561
|
+
"[trails-sdk] Could not get receipt, using resilient tracking",
|
|
562
|
+
{ txHash, error: (receiptError as Error)?.message },
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
// Fall back to resilient tracking with known tx hash
|
|
566
|
+
depositUserTxnReceipt = await trackDepositResilient({
|
|
567
|
+
publicClient,
|
|
568
|
+
originChainId,
|
|
569
|
+
originIntentAddress,
|
|
570
|
+
originTokenAddress,
|
|
571
|
+
depositAmount,
|
|
572
|
+
txHash,
|
|
573
|
+
abortSignal,
|
|
574
|
+
sequenceProjectAccessKey,
|
|
575
|
+
sequenceIndexerUrl,
|
|
576
|
+
onDepositDetected: (hash, receipt) => {
|
|
577
|
+
const chainInfo = getChainInfo(originChainId)
|
|
578
|
+
updatePersistentToast(
|
|
579
|
+
"Transfer Confirmed",
|
|
580
|
+
`Your transaction on ${chainInfo?.name || "chain"} has been confirmed`,
|
|
581
|
+
"info",
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
if (receipt?.status === "success" && hash) {
|
|
585
|
+
trackTransactionConfirmed({
|
|
586
|
+
transactionHash: hash,
|
|
587
|
+
chainId: originChainId,
|
|
588
|
+
userAddress: account.address,
|
|
589
|
+
blockNumber: Number(receipt.blockNumber || 0),
|
|
590
|
+
originIntentAddress,
|
|
591
|
+
originTokenSymbol,
|
|
592
|
+
destinationTokenSymbol,
|
|
593
|
+
depositTokenAmountUsd: depositAmountUsd?.toString(),
|
|
594
|
+
})
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
})
|
|
487
598
|
}
|
|
488
|
-
}
|
|
599
|
+
} else if (sendError && isRecoverableDepositError(sendError)) {
|
|
600
|
+
// No transaction hash but error is recoverable - start polling
|
|
601
|
+
logger.console.log(
|
|
602
|
+
"[trails-sdk] Starting resilient deposit tracking after send failure",
|
|
603
|
+
)
|
|
489
604
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
605
|
+
updatePersistentToast(
|
|
606
|
+
"Checking Transaction",
|
|
607
|
+
"Verifying transaction status...",
|
|
608
|
+
"info",
|
|
609
|
+
)
|
|
495
610
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
611
|
+
depositUserTxnReceipt = await trackDepositResilient({
|
|
612
|
+
publicClient,
|
|
613
|
+
originChainId,
|
|
614
|
+
originIntentAddress,
|
|
615
|
+
originTokenAddress,
|
|
616
|
+
depositAmount,
|
|
617
|
+
txHash: null,
|
|
618
|
+
abortSignal,
|
|
619
|
+
sequenceProjectAccessKey,
|
|
620
|
+
sequenceIndexerUrl,
|
|
621
|
+
onDepositDetected: (detectedHash, receipt) => {
|
|
622
|
+
logger.console.log(
|
|
623
|
+
"[trails-sdk] Deposit detected via resilient tracking",
|
|
624
|
+
{ hash: detectedHash },
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
if (onOriginSend) {
|
|
628
|
+
onOriginSend()
|
|
629
|
+
}
|
|
502
630
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
631
|
+
if (transactionStates[0] && detectedHash) {
|
|
632
|
+
transactionStates[0].state = "pending"
|
|
633
|
+
transactionStates[0].transactionHash = detectedHash
|
|
634
|
+
|
|
635
|
+
try {
|
|
636
|
+
onTransactionStateChange(transactionStates)
|
|
637
|
+
} catch (error) {
|
|
638
|
+
logger.console.error(
|
|
639
|
+
"[trails-sdk] Error calling onTransactionStateChange:",
|
|
640
|
+
error,
|
|
641
|
+
)
|
|
642
|
+
}
|
|
643
|
+
}
|
|
513
644
|
|
|
514
|
-
|
|
515
|
-
|
|
645
|
+
const chainInfo = getChainInfo(originChainId)
|
|
646
|
+
updatePersistentToast(
|
|
647
|
+
"Transfer Confirmed",
|
|
648
|
+
`Your transaction on ${chainInfo?.name || "chain"} has been confirmed`,
|
|
649
|
+
"info",
|
|
650
|
+
)
|
|
651
|
+
|
|
652
|
+
if (receipt?.status === "success" && detectedHash) {
|
|
653
|
+
trackTransactionConfirmed({
|
|
654
|
+
transactionHash: detectedHash,
|
|
655
|
+
chainId: originChainId,
|
|
656
|
+
userAddress: account.address,
|
|
657
|
+
blockNumber: Number(receipt.blockNumber || 0),
|
|
658
|
+
originIntentAddress,
|
|
659
|
+
originTokenSymbol,
|
|
660
|
+
destinationTokenSymbol,
|
|
661
|
+
depositTokenAmountUsd: depositAmountUsd?.toString(),
|
|
662
|
+
})
|
|
663
|
+
}
|
|
664
|
+
},
|
|
665
|
+
})
|
|
666
|
+
|
|
667
|
+
if (!depositUserTxnReceipt) {
|
|
668
|
+
throw new Error(
|
|
669
|
+
"Deposit transaction could not be confirmed. Please check your wallet and try again.",
|
|
670
|
+
)
|
|
671
|
+
}
|
|
672
|
+
}
|
|
516
673
|
}
|
|
517
674
|
|
|
518
675
|
return depositUserTxnReceipt
|