0xtrails 0.6.0 → 0.6.2
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-Dw5AN7oU.js → ccip-CZfykYU7.js} +4 -4
- package/dist/chains.d.ts +9 -2
- package/dist/chains.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/contractUtils.d.ts +2 -1
- package/dist/contractUtils.d.ts.map +1 -1
- package/dist/{index-BtVUTbEZ.js → index-S9pphnT9.js} +29732 -36767
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +300 -242
- package/dist/prepareSend.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/types.d.ts +3 -1
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/widget/components/ChainImage.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/DepositTracker.d.ts +12 -0
- package/dist/widget/components/DepositTracker.d.ts.map +1 -0
- package/dist/widget/components/Disconnect.d.ts.map +1 -1
- package/dist/widget/components/FeeBreakdown.d.ts.map +1 -1
- package/dist/widget/components/QRCodeDeposit.d.ts.map +1 -1
- package/dist/widget/components/QRCodeOptions.d.ts +9 -0
- package/dist/widget/components/QRCodeOptions.d.ts.map +1 -0
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
- package/dist/widget/components/Toast.d.ts.map +1 -1
- package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
- package/dist/widget/components/WalletConnectionPending.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/css/index.css +103 -38
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -1
- package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFeeOption.d.ts.map +1 -1
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +6 -9
- package/src/chains.ts +37 -4
- package/src/constants.ts +1 -0
- package/src/contractUtils.ts +8 -7
- package/src/estimate.ts +2 -2
- package/src/index.ts +2 -0
- package/src/intents.ts +2 -2
- package/src/paymasterSend.ts +2 -2
- package/src/prepareSend.ts +34 -3
- package/src/sendUserOp.ts +2 -2
- package/src/tokens.ts +2 -2
- package/src/transactionIntent/deposits/gaslessDeposit.ts +2 -2
- package/src/transactionIntent/handlers/crossChain.ts +51 -2
- package/src/transactionIntent/handlers/sameChainSameToken.ts +52 -2
- package/src/transactionIntent/quote/normalizeQuote.ts +2 -2
- package/src/transactionIntent/types.ts +9 -1
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/ChainImage.tsx +10 -7
- package/src/widget/components/ChainList.tsx +1 -1
- package/src/widget/components/ClassicSwap.tsx +8 -4
- package/src/widget/components/ConnectedWallets.tsx +1 -1
- package/src/widget/components/DepositTracker.tsx +298 -0
- package/src/widget/components/Disconnect.tsx +24 -3
- package/src/widget/components/FeeBreakdown.tsx +3 -3
- package/src/widget/components/QRCodeDeposit.tsx +29 -19
- package/src/widget/components/QRCodeOptions.tsx +65 -0
- package/src/widget/components/QuoteDetails.tsx +694 -803
- package/src/widget/components/Receipt.tsx +76 -40
- package/src/widget/components/ThemeProvider.tsx +7 -12
- package/src/widget/components/Toast.tsx +3 -2
- package/src/widget/components/TokenSelector.tsx +1 -1
- package/src/widget/components/Tooltip.tsx +1 -1
- package/src/widget/components/TransferPendingVertical.tsx +11 -2
- package/src/widget/components/WalletConnectionPending.tsx +28 -5
- package/src/widget/hooks/useCheckout.ts +10 -2
- package/src/widget/hooks/useCurrentScreen.tsx +1 -0
- package/src/widget/hooks/useDebugScreens.ts +1 -0
- package/src/widget/hooks/useIntentTransactionHistory.ts +114 -143
- package/src/widget/hooks/useQuote.ts +92 -6
- package/src/widget/hooks/useSelectedFeeOption.tsx +86 -29
- package/src/widget/hooks/useSendForm.ts +43 -7
- package/src/widget/index.css +103 -38
- package/src/widget/widget.tsx +48 -5
- package/dist/0xtrails.css +0 -1
package/src/prepareSend.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import type { TransactionState } from "./transactions.js"
|
|
12
12
|
import { logger } from "./logger.js"
|
|
13
13
|
import { getIsCustomCalldata } from "./contractUtils.js"
|
|
14
|
-
import { getChainInfo,
|
|
14
|
+
import { getChainInfo, getChainRpcClient } from "./chains.js"
|
|
15
15
|
|
|
16
16
|
// Import from transactionIntent module
|
|
17
17
|
import {
|
|
@@ -88,6 +88,34 @@ export async function prepareSend(
|
|
|
88
88
|
} = options
|
|
89
89
|
let { sourceTokenPriceUsd, destinationTokenPriceUsd } = options
|
|
90
90
|
|
|
91
|
+
if (!originChainId) {
|
|
92
|
+
throw new Error("Origin chain ID is required")
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!destinationChainId) {
|
|
96
|
+
throw new Error("Destination chain ID is required")
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Sanity check: verify originPublicClient chain ID matches originChainId
|
|
100
|
+
if (options.originPublicClient) {
|
|
101
|
+
const clientChainId = options.originPublicClient?.chain?.id
|
|
102
|
+
if (clientChainId !== originChainId) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
`Origin public client chain ID mismatch: expected ${originChainId}, got ${clientChainId}`,
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Sanity check: verify destinationPublicClient chain ID matches destinationChainId
|
|
110
|
+
if (options.destinationPublicClient) {
|
|
111
|
+
const clientChainId = options.destinationPublicClient?.chain?.id
|
|
112
|
+
if (clientChainId !== destinationChainId) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`Destination public client chain ID mismatch: expected ${destinationChainId}, got ${clientChainId}`,
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
91
119
|
// Use slippage from options, or get from localStorage with config default fallback
|
|
92
120
|
// The config default (slippageToleranceFromOptions) comes from React component context
|
|
93
121
|
const slippageTolerance = getSlippageToleranceValue(
|
|
@@ -261,13 +289,16 @@ export async function prepareSend(
|
|
|
261
289
|
})
|
|
262
290
|
throw new Error(`Chain ${originChainId} not found`)
|
|
263
291
|
}
|
|
292
|
+
const isToSelf =
|
|
293
|
+
account.address.toLowerCase() === effectiveDestinationAddress.toLowerCase()
|
|
264
294
|
const isToSameChain = isSameChain(originChainId, destinationChainId)
|
|
265
295
|
const isToSameToken = isSameToken(originTokenAddress, destinationTokenAddress)
|
|
266
296
|
|
|
267
297
|
logger.console.log("[trails-sdk] isToSameChain", isToSameChain)
|
|
268
298
|
logger.console.log("[trails-sdk] isToSameToken", isToSameToken)
|
|
269
299
|
|
|
270
|
-
const publicClient =
|
|
300
|
+
const publicClient =
|
|
301
|
+
options.originPublicClient ?? getChainRpcClient(originChainId)
|
|
271
302
|
|
|
272
303
|
// origin tx
|
|
273
304
|
transactionStates.push({
|
|
@@ -311,7 +342,7 @@ export async function prepareSend(
|
|
|
311
342
|
explorerUrl: "",
|
|
312
343
|
chainId: destinationChainId,
|
|
313
344
|
state: "pending",
|
|
314
|
-
label: hasCustomCalldata ? "Execute" : "Receive",
|
|
345
|
+
label: hasCustomCalldata ? "Execute" : isToSelf ? "Receive" : "Send",
|
|
315
346
|
})
|
|
316
347
|
}
|
|
317
348
|
|
package/src/sendUserOp.ts
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
slice,
|
|
14
14
|
toHex,
|
|
15
15
|
} from "viem"
|
|
16
|
-
import { getHttpTransport,
|
|
16
|
+
import { getHttpTransport, getChainRpcClient } from "./chains.js"
|
|
17
17
|
import { privateKeyToAccount } from "viem/accounts"
|
|
18
18
|
import { logger } from "./logger.js"
|
|
19
19
|
|
|
@@ -190,7 +190,7 @@ export async function sendUserOperationDirectly({
|
|
|
190
190
|
account: relayerAccount,
|
|
191
191
|
})
|
|
192
192
|
|
|
193
|
-
const publicClient =
|
|
193
|
+
const publicClient = getChainRpcClient(chain.id)
|
|
194
194
|
|
|
195
195
|
const packedOp = toPackedUserOperation(userOp) // converts to PackedUserOperation
|
|
196
196
|
|
package/src/tokens.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { zeroAddress, erc20Abi } from "viem"
|
|
|
3
3
|
import {
|
|
4
4
|
getChainInfo,
|
|
5
5
|
getSupportedChains,
|
|
6
|
-
|
|
6
|
+
getChainRpcClient,
|
|
7
7
|
} from "./chains.js"
|
|
8
8
|
import {
|
|
9
9
|
arbitrum,
|
|
@@ -492,7 +492,7 @@ export async function getTokenInfo(
|
|
|
492
492
|
}
|
|
493
493
|
|
|
494
494
|
// Create a public client for the specific chain
|
|
495
|
-
const publicClient =
|
|
495
|
+
const publicClient = getChainRpcClient(chainId)
|
|
496
496
|
|
|
497
497
|
// Read token data on-chain
|
|
498
498
|
const [name, symbol, decimals] = await Promise.all([
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
validateGaslessSignature,
|
|
28
28
|
} from "../../gasless.js"
|
|
29
29
|
import { getIsUserRejectionError } from "../../error.js"
|
|
30
|
-
import {
|
|
30
|
+
import { getChainRpcClient } from "../../chains.js"
|
|
31
31
|
|
|
32
32
|
export async function attemptGaslessDeposit({
|
|
33
33
|
paymasterUrl,
|
|
@@ -86,7 +86,7 @@ export async function attemptGaslessDeposit({
|
|
|
86
86
|
},
|
|
87
87
|
)
|
|
88
88
|
|
|
89
|
-
const publicClient =
|
|
89
|
+
const publicClient = getChainRpcClient(chain.id)
|
|
90
90
|
|
|
91
91
|
logger.console.log("[trails-sdk] [GASLESS-FLOW] Intent entrypoint check:", {
|
|
92
92
|
chainId: chain.id,
|
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
TransactionReceipt,
|
|
7
7
|
} from "viem"
|
|
8
8
|
import { JsonEncode } from "@0xsequence/trails-api"
|
|
9
|
-
import {
|
|
9
|
+
import { getChainRpcClient } from "../../chains.js"
|
|
10
10
|
import type { FeeOption, TrailsApi } from "@0xsequence/trails-api"
|
|
11
11
|
import type { IntentTransaction } from "@0xsequence/trails-api"
|
|
12
12
|
import type { PrepareSendReturn, SendReturn } from "../types.js"
|
|
@@ -458,7 +458,9 @@ export async function handleCrossChain({
|
|
|
458
458
|
if (!destinationChainInfo) {
|
|
459
459
|
throw new Error(`Chain ${destinationChainId} not found`)
|
|
460
460
|
}
|
|
461
|
-
const destinationPublicClient =
|
|
461
|
+
const destinationPublicClient = getChainRpcClient(
|
|
462
|
+
destinationChainInfo.id,
|
|
463
|
+
)
|
|
462
464
|
|
|
463
465
|
const depositPromise = async () => {
|
|
464
466
|
logger.console.log(
|
|
@@ -695,6 +697,53 @@ export async function handleCrossChain({
|
|
|
695
697
|
hash: tx.txnHash as `0x${string}`,
|
|
696
698
|
})
|
|
697
699
|
|
|
700
|
+
// Validate that the deposit amount is sufficient before proceeding
|
|
701
|
+
logger.console.log(
|
|
702
|
+
"[trails-sdk] Checking if deposit amount is sufficient (cross-chain)",
|
|
703
|
+
{
|
|
704
|
+
depositAddress: originIntentAddress,
|
|
705
|
+
requiredAmount: quote.originAmount,
|
|
706
|
+
tokenAddress: originTokenAddress,
|
|
707
|
+
},
|
|
708
|
+
)
|
|
709
|
+
|
|
710
|
+
const balanceCheck = await checkAccountBalance({
|
|
711
|
+
account: {
|
|
712
|
+
address: originIntentAddress as `0x${string}`,
|
|
713
|
+
} as Account,
|
|
714
|
+
tokenAddress: originTokenAddress,
|
|
715
|
+
depositAmount: quote.originAmount,
|
|
716
|
+
publicClient: publicClient,
|
|
717
|
+
})
|
|
718
|
+
|
|
719
|
+
if (!balanceCheck.hasEnoughBalance) {
|
|
720
|
+
logger.console.warn(
|
|
721
|
+
"[trails-sdk] Deposit amount is insufficient, continuing to poll (cross-chain)",
|
|
722
|
+
{
|
|
723
|
+
balance: balanceCheck.balanceFormatted,
|
|
724
|
+
required: balanceCheck.requiredAmountFormatted,
|
|
725
|
+
percentComplete: (
|
|
726
|
+
(Number(balanceCheck.balance) /
|
|
727
|
+
Number(balanceCheck.requiredAmount)) *
|
|
728
|
+
100
|
|
729
|
+
).toFixed(2),
|
|
730
|
+
},
|
|
731
|
+
)
|
|
732
|
+
// Continue polling - don't break out of the loop yet
|
|
733
|
+
await new Promise((resolve) =>
|
|
734
|
+
setTimeout(resolve, POLLING_INTERVALS.TRANSACTION_HISTORY),
|
|
735
|
+
)
|
|
736
|
+
continue
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
logger.console.log(
|
|
740
|
+
"[trails-sdk] Deposit amount is sufficient, proceeding (cross-chain)",
|
|
741
|
+
{
|
|
742
|
+
balance: balanceCheck.balanceFormatted,
|
|
743
|
+
required: balanceCheck.requiredAmountFormatted,
|
|
744
|
+
},
|
|
745
|
+
)
|
|
746
|
+
|
|
698
747
|
depositUserTxnReceipt = originDepositTxReceipt
|
|
699
748
|
|
|
700
749
|
transactionStates[0] = getTransactionStateFromReceipt(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Account, Chain, WalletClient, TransactionReceipt } from "viem"
|
|
2
2
|
import { formatUnits } from "viem"
|
|
3
|
-
import {
|
|
3
|
+
import { getChainRpcClient } from "../../chains.js"
|
|
4
4
|
import type { FeeOption, TrailsApi } from "@0xsequence/trails-api"
|
|
5
5
|
import type { PrepareSendReturn, SendReturn } from "../types.js"
|
|
6
6
|
import type { IntentTransaction } from "@0xsequence/trails-api"
|
|
@@ -116,7 +116,7 @@ export async function handleSameChainSameToken({
|
|
|
116
116
|
const effectiveOriginTokenAddress = testnet
|
|
117
117
|
? getTestnetOriginTokenAddress(effectiveOriginChainId)
|
|
118
118
|
: originTokenAddress
|
|
119
|
-
const effectivePublicClient =
|
|
119
|
+
const effectivePublicClient = getChainRpcClient(effectiveOriginChain.id)
|
|
120
120
|
|
|
121
121
|
let noSufficientBalance = false
|
|
122
122
|
|
|
@@ -503,6 +503,56 @@ export async function handleSameChainSameToken({
|
|
|
503
503
|
hash: tx.txnHash as `0x${string}`,
|
|
504
504
|
})
|
|
505
505
|
|
|
506
|
+
// Validate that the deposit amount is sufficient before proceeding
|
|
507
|
+
logger.console.log(
|
|
508
|
+
"[trails-sdk] Checking if deposit amount is sufficient",
|
|
509
|
+
{
|
|
510
|
+
depositAddress: intent.originIntentAddress,
|
|
511
|
+
requiredAmount: quote.originAmount,
|
|
512
|
+
tokenAddress: effectiveOriginTokenAddress,
|
|
513
|
+
},
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
const balanceCheck = await checkAccountBalance({
|
|
517
|
+
account: {
|
|
518
|
+
address: intent.originIntentAddress as `0x${string}`,
|
|
519
|
+
} as Account,
|
|
520
|
+
tokenAddress: effectiveOriginTokenAddress,
|
|
521
|
+
depositAmount: quote.originAmount,
|
|
522
|
+
publicClient: effectivePublicClient,
|
|
523
|
+
})
|
|
524
|
+
|
|
525
|
+
if (!balanceCheck.hasEnoughBalance) {
|
|
526
|
+
logger.console.warn(
|
|
527
|
+
"[trails-sdk] Deposit amount is insufficient, continuing to poll",
|
|
528
|
+
{
|
|
529
|
+
balance: balanceCheck.balanceFormatted,
|
|
530
|
+
required: balanceCheck.requiredAmountFormatted,
|
|
531
|
+
percentComplete: (
|
|
532
|
+
(Number(balanceCheck.balance) /
|
|
533
|
+
Number(balanceCheck.requiredAmount)) *
|
|
534
|
+
100
|
|
535
|
+
).toFixed(2),
|
|
536
|
+
},
|
|
537
|
+
)
|
|
538
|
+
// Continue polling - don't break out of the loop yet
|
|
539
|
+
await new Promise((resolve) =>
|
|
540
|
+
setTimeout(
|
|
541
|
+
resolve,
|
|
542
|
+
POLLING_INTERVALS.TRANSACTION_HISTORY,
|
|
543
|
+
),
|
|
544
|
+
)
|
|
545
|
+
continue
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
logger.console.log(
|
|
549
|
+
"[trails-sdk] Deposit amount is sufficient, proceeding",
|
|
550
|
+
{
|
|
551
|
+
balance: balanceCheck.balanceFormatted,
|
|
552
|
+
required: balanceCheck.requiredAmountFormatted,
|
|
553
|
+
},
|
|
554
|
+
)
|
|
555
|
+
|
|
506
556
|
depositUserTxnReceipt = depositTxReceipt
|
|
507
557
|
|
|
508
558
|
localTransactionStates[0] = getTransactionStateFromReceipt(
|
|
@@ -5,7 +5,7 @@ import type { QuoteProviderInfo } from "../../widget/hooks/useQuote.js"
|
|
|
5
5
|
import { formatUnits } from "viem"
|
|
6
6
|
import { mainnet } from "viem/chains"
|
|
7
7
|
import { getTokenInfo } from "../../tokens.js"
|
|
8
|
-
import { getChainInfo,
|
|
8
|
+
import { getChainInfo, getChainRpcClient } from "../../chains.js"
|
|
9
9
|
import { logger } from "../../logger.js"
|
|
10
10
|
import {
|
|
11
11
|
formatRawAmount,
|
|
@@ -186,7 +186,7 @@ export async function getNormalizedQuoteObject({
|
|
|
186
186
|
|
|
187
187
|
const hasCustomCalldata = getIsCustomCalldata(destinationCalldata)
|
|
188
188
|
|
|
189
|
-
const publicClient =
|
|
189
|
+
const publicClient = getChainRpcClient(originChain.id)
|
|
190
190
|
|
|
191
191
|
let gasCostUsd: number = 0
|
|
192
192
|
let gasCostUsdDisplay: string = "0"
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
Account,
|
|
3
|
+
Chain,
|
|
4
|
+
PublicClient,
|
|
5
|
+
TransactionReceipt,
|
|
6
|
+
WalletClient,
|
|
7
|
+
} from "viem"
|
|
2
8
|
import type {
|
|
3
9
|
TrailsApi,
|
|
4
10
|
Intent,
|
|
@@ -51,6 +57,8 @@ export type PrepareSendOptions = {
|
|
|
51
57
|
quoteProvider?: string | null
|
|
52
58
|
fundMethod?: string
|
|
53
59
|
mode?: "pay" | "fund" | "earn" | "swap" | "receive"
|
|
60
|
+
originPublicClient?: PublicClient
|
|
61
|
+
destinationPublicClient?: PublicClient
|
|
54
62
|
checkoutOnHandlers?: Partial<CheckoutOnHandlers>
|
|
55
63
|
refundAddress?: string
|
|
56
64
|
selectedFeeOption?: FeeOption | null
|