0xtrails 0.1.2 → 0.1.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/address.d.ts.map +1 -1
- package/dist/analytics.d.ts +86 -1
- package/dist/analytics.d.ts.map +1 -1
- package/dist/apiClient.d.ts +1 -1
- package/dist/apiClient.d.ts.map +1 -1
- package/dist/{ccip-BmFTEOaB.js → ccip-dLSEJjCf.js} +55 -55
- package/dist/cctpqueue.d.ts +1 -1
- package/dist/cctpqueue.d.ts.map +1 -1
- package/dist/chains.d.ts +9 -3
- 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/decoders.d.ts +58 -0
- package/dist/decoders.d.ts.map +1 -0
- package/dist/ens.d.ts +13 -0
- package/dist/ens.d.ts.map +1 -0
- package/dist/error.d.ts +9 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/{index-BPsVj7zK.js → index-BXbaLmtt.js} +28779 -25738
- package/dist/index.js +2 -2
- package/dist/intents.d.ts +4 -4
- package/dist/intents.d.ts.map +1 -1
- package/dist/lifi.d.ts +4 -0
- package/dist/lifi.d.ts.map +1 -0
- package/dist/metaTxns.d.ts +1 -1
- package/dist/metaTxns.d.ts.map +1 -1
- package/dist/mode.d.ts +1 -1
- package/dist/mode.d.ts.map +1 -1
- package/dist/preconditions.d.ts +1 -1
- package/dist/preconditions.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +32 -24
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/prices.d.ts +3 -1
- package/dist/prices.d.ts.map +1 -1
- package/dist/proxyCaller.d.ts +0 -1
- package/dist/proxyCaller.d.ts.map +1 -1
- package/dist/relaySdk.d.ts.map +1 -1
- package/dist/relayer.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts +1 -1
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts +2 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/trails.d.ts +4 -4
- package/dist/trails.d.ts.map +1 -1
- package/dist/transactions.d.ts +4 -0
- package/dist/transactions.d.ts.map +1 -1
- package/dist/utils.d.ts +6 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/wallets.d.ts +247 -5
- package/dist/wallets.d.ts.map +1 -1
- package/dist/widget/components/ChainFilterDropdown.d.ts +2 -0
- package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
- package/dist/widget/components/ConnectWallet.d.ts +1 -0
- package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
- package/dist/widget/components/DebugScreensDropdown.d.ts.map +1 -1
- package/dist/widget/components/ErrorDisplay.d.ts +9 -0
- package/dist/widget/components/ErrorDisplay.d.ts.map +1 -0
- package/dist/widget/components/FundSendForm.d.ts +2 -2
- package/dist/widget/components/FundSendForm.d.ts.map +1 -1
- package/dist/widget/components/OriginTransferInformation.d.ts +10 -0
- package/dist/widget/components/OriginTransferInformation.d.ts.map +1 -0
- package/dist/widget/components/PaySendForm.d.ts +2 -2
- package/dist/widget/components/PaySendForm.d.ts.map +1 -1
- package/dist/widget/components/QrCode.d.ts +1 -1
- package/dist/widget/components/QrCode.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/Receive.d.ts +12 -0
- package/dist/widget/components/Receive.d.ts.map +1 -0
- package/dist/widget/components/RefundAddressInput.d.ts +13 -0
- package/dist/widget/components/RefundAddressInput.d.ts.map +1 -0
- package/dist/widget/components/Swap.d.ts +47 -0
- package/dist/widget/components/Swap.d.ts.map +1 -0
- package/dist/widget/components/SwapDisplay.d.ts +9 -0
- package/dist/widget/components/SwapDisplay.d.ts.map +1 -0
- package/dist/widget/components/TokenList.d.ts +0 -2
- package/dist/widget/components/TokenList.d.ts.map +1 -1
- package/dist/widget/components/TokenSelector.d.ts +26 -0
- package/dist/widget/components/TokenSelector.d.ts.map +1 -0
- package/dist/widget/components/TransferPendingVertical.d.ts +2 -0
- package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
- package/dist/widget/components/WalletConnect.d.ts.map +1 -1
- package/dist/widget/components/WalletConnectionPending.d.ts +12 -0
- package/dist/widget/components/WalletConnectionPending.d.ts.map +1 -0
- package/dist/widget/components/WalletList.d.ts.map +1 -1
- package/dist/widget/components/YellowWarningAnimation.d.ts +2 -0
- package/dist/widget/components/YellowWarningAnimation.d.ts.map +1 -0
- package/dist/widget/hooks/useAmountUsd.d.ts +1 -3
- package/dist/widget/hooks/useAmountUsd.d.ts.map +1 -1
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts +22 -0
- package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -0
- package/dist/widget/hooks/useSendForm.d.ts +12 -6
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts +2 -3
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +19 -15
- package/src/aave.ts +13 -13
- package/src/address.ts +3 -0
- package/src/analytics.ts +192 -8
- package/src/apiClient.ts +1 -1
- package/src/cctpqueue.ts +1 -1
- package/src/chains.ts +45 -7
- package/src/constants.ts +7 -4
- package/src/decoders.ts +310 -0
- package/src/ens.ts +32 -0
- package/src/error.ts +101 -1
- package/src/intents.ts +10 -2
- package/src/lifi.ts +58 -0
- package/src/metaTxns.ts +1 -1
- package/src/mode.ts +1 -1
- package/src/morpho.ts +3 -3
- package/src/pools.ts +18 -18
- package/src/preconditions.ts +1 -1
- package/src/prepareSend.ts +463 -113
- package/src/prices.ts +26 -1
- package/src/proxyCaller.ts +2 -14
- package/src/relaySdk.ts +1 -0
- package/src/relayer.ts +8 -0
- package/src/tokenBalances.ts +24 -17
- package/src/tokens.ts +147 -22
- package/src/trails.ts +4 -4
- package/src/transactions.ts +35 -17
- package/src/utils.ts +28 -0
- package/src/wallets.ts +275 -35
- package/src/widget/compiled.css +2 -2
- package/src/widget/components/ChainFilterDropdown.tsx +42 -33
- package/src/widget/components/ChainImage.tsx +1 -1
- package/src/widget/components/ConnectWallet.tsx +92 -128
- package/src/widget/components/DebugScreensDropdown.tsx +6 -0
- package/src/widget/components/ErrorDisplay.tsx +150 -0
- package/src/widget/components/FundSendForm.tsx +78 -11
- package/src/widget/components/OriginTransferInformation.tsx +59 -0
- package/src/widget/components/PaySendForm.tsx +80 -13
- package/src/widget/components/QRCodeDeposit.tsx +6 -6
- package/src/widget/components/QrCode.tsx +278 -17
- package/src/widget/components/QuoteDetails.tsx +93 -25
- package/src/widget/components/Receipt.tsx +296 -103
- package/src/widget/components/Receive.tsx +146 -0
- package/src/widget/components/RecentTokens.tsx +1 -1
- package/src/widget/components/RefundAddressInput.tsx +149 -0
- package/src/widget/components/Swap.tsx +769 -0
- package/src/widget/components/SwapDisplay.tsx +68 -0
- package/src/widget/components/TokenList.tsx +27 -363
- package/src/widget/components/TokenSelector.tsx +405 -0
- package/src/widget/components/TransferPendingVertical.tsx +162 -112
- package/src/widget/components/WalletConnect.tsx +9 -7
- package/src/widget/components/WalletConnectionPending.tsx +157 -0
- package/src/widget/components/WalletList.tsx +6 -5
- package/src/widget/components/YellowWarningAnimation.tsx +146 -0
- package/src/widget/hooks/useAmountUsd.ts +3 -8
- package/src/widget/hooks/useCheckout.ts +3 -2
- package/src/widget/hooks/useDebugScreens.ts +583 -0
- package/src/widget/hooks/useSendForm.ts +111 -35
- package/src/widget/hooks/useTokenList.ts +155 -122
- package/src/widget/widget.tsx +503 -523
package/src/chains.ts
CHANGED
|
@@ -2,7 +2,9 @@ import { useQuery } from "@tanstack/react-query"
|
|
|
2
2
|
import type { Chain } from "viem"
|
|
3
3
|
import * as chains from "viem/chains"
|
|
4
4
|
import { getRelaySupportedChains } from "./relaySdk.js"
|
|
5
|
+
import { getLifiSupportedChains } from "./lifi.js"
|
|
5
6
|
import { getRpcSequenceProjectAccessKey } from "./config.js"
|
|
7
|
+
import type { QuoteProvider } from "./intents.js"
|
|
6
8
|
|
|
7
9
|
export const sequenceRpcUrls: Record<number, string> = {
|
|
8
10
|
[chains.arbitrum.id]: "https://nodes.sequence.app/arbitrum",
|
|
@@ -19,6 +21,8 @@ export const sequenceRpcUrls: Record<number, string> = {
|
|
|
19
21
|
[chains.b3.id]: "https://nodes.sequence.app/b3",
|
|
20
22
|
[chains.blast.id]: "https://nodes.sequence.app/blast",
|
|
21
23
|
[chains.bsc.id]: "https://nodes.sequence.app/bsc",
|
|
24
|
+
[chains.katana.id]: "https://nodes.sequence.app/katana",
|
|
25
|
+
[chains.etherlink.id]: "https://nodes.sequence.app/etherlink",
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
export const getRpcUrl = (
|
|
@@ -46,6 +50,8 @@ export const supportedSequenceChains: Record<number, Chain> = {
|
|
|
46
50
|
[chains.polygon.id]: getChainInfo(chains.polygon.id)!,
|
|
47
51
|
[chains.soneium.id]: getChainInfo(chains.soneium.id)!,
|
|
48
52
|
[chains.xai.id]: getChainInfo(chains.xai.id)!,
|
|
53
|
+
[chains.katana.id]: getChainInfo(chains.katana.id)!,
|
|
54
|
+
[chains.etherlink.id]: getChainInfo(chains.etherlink.id)!,
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
export const supportedSequenceTestnetChains: Record<number, Chain> = {
|
|
@@ -61,6 +67,7 @@ export const supportedSequenceTestnetChains: Record<number, Chain> = {
|
|
|
61
67
|
[chains.optimismSepolia.id]: getChainInfo(chains.optimismSepolia.id)!,
|
|
62
68
|
[chains.soneiumMinato.id]: getChainInfo(chains.soneiumMinato.id)!,
|
|
63
69
|
[chains.xaiTestnet.id]: getChainInfo(chains.xaiTestnet.id)!,
|
|
70
|
+
[chains.etherlinkTestnet.id]: getChainInfo(chains.etherlinkTestnet.id)!,
|
|
64
71
|
}
|
|
65
72
|
|
|
66
73
|
export const mainnetChainsToTestnetChains: Record<number, Chain> = {
|
|
@@ -78,13 +85,15 @@ export const mainnetChainsToTestnetChains: Record<number, Chain> = {
|
|
|
78
85
|
[chains.bsc.id]: chains.bscTestnet,
|
|
79
86
|
[chains.arbitrumNova.id]: chains.arbitrumSepolia,
|
|
80
87
|
[chains.apeChain.id]: chains.sepolia,
|
|
88
|
+
[chains.etherlink.id]: chains.etherlinkTestnet,
|
|
81
89
|
}
|
|
82
90
|
|
|
83
91
|
// Helper to get chain info
|
|
84
92
|
export function getChainInfo(
|
|
85
|
-
chainId
|
|
93
|
+
chainId?: number,
|
|
86
94
|
options?: { usePublicRpc?: boolean },
|
|
87
95
|
): Chain | null {
|
|
96
|
+
if (!chainId) return null
|
|
88
97
|
const chainInfo =
|
|
89
98
|
(Object.values(chains) as Array<Chain>).find(
|
|
90
99
|
(chain: Chain) => chain.id === chainId,
|
|
@@ -155,13 +164,36 @@ function sortChains(chainList: Chain[]): Chain[] {
|
|
|
155
164
|
})
|
|
156
165
|
}
|
|
157
166
|
|
|
158
|
-
export async function
|
|
159
|
-
const sequenceChains = await getSupportedSequenceChains()
|
|
167
|
+
export async function getAllQuoteProviderChains(): Promise<Chain[]> {
|
|
160
168
|
const relayChains = await getRelaySupportedChains()
|
|
169
|
+
const lifiChains = await getLifiSupportedChains()
|
|
170
|
+
const allChains = [...relayChains, ...lifiChains]
|
|
171
|
+
return allChains.filter(
|
|
172
|
+
(chain, index, self) => index === self.findIndex((c) => c.id === chain.id),
|
|
173
|
+
)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export async function getSupportedChains({
|
|
177
|
+
quoteProvider,
|
|
178
|
+
}: {
|
|
179
|
+
quoteProvider?: QuoteProvider | string
|
|
180
|
+
} = {}): Promise<Chain[]> {
|
|
181
|
+
let quoteProviderChains: Chain[] = []
|
|
182
|
+
if (quoteProvider === "relay") {
|
|
183
|
+
quoteProviderChains = await getRelaySupportedChains()
|
|
184
|
+
} else if (quoteProvider === "lifi") {
|
|
185
|
+
quoteProviderChains = await getLifiSupportedChains()
|
|
186
|
+
} else {
|
|
187
|
+
quoteProviderChains = await getAllQuoteProviderChains()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const sequenceChains = await getSupportedSequenceChains()
|
|
161
191
|
|
|
162
192
|
// Find intersection of sequence chains and relay chains
|
|
163
193
|
const supportedChains = sequenceChains.filter((sequenceChain) =>
|
|
164
|
-
|
|
194
|
+
quoteProviderChains.some(
|
|
195
|
+
(quoteProviderChain) => quoteProviderChain.id === sequenceChain.id,
|
|
196
|
+
),
|
|
165
197
|
)
|
|
166
198
|
|
|
167
199
|
// Ensure unique chain IDs by filtering duplicates
|
|
@@ -169,17 +201,23 @@ export async function getSupportedChains(): Promise<Chain[]> {
|
|
|
169
201
|
(chain, index, self) => index === self.findIndex((c) => c.id === chain.id),
|
|
170
202
|
)
|
|
171
203
|
|
|
204
|
+
const sortedChains = sortChains(uniqueChains)
|
|
205
|
+
|
|
172
206
|
// Sort chains by priority and then by name
|
|
173
|
-
return
|
|
207
|
+
return sortedChains
|
|
174
208
|
}
|
|
175
209
|
|
|
176
|
-
export function useSupportedChains(
|
|
210
|
+
export function useSupportedChains({
|
|
211
|
+
quoteProvider,
|
|
212
|
+
}: {
|
|
213
|
+
quoteProvider?: QuoteProvider | string
|
|
214
|
+
} = {}): {
|
|
177
215
|
supportedChains: Chain[]
|
|
178
216
|
isLoadingChains: boolean
|
|
179
217
|
} {
|
|
180
218
|
const { data: supportedChains = [], isLoading: isLoadingChains } = useQuery({
|
|
181
219
|
queryKey: ["supportedChains"],
|
|
182
|
-
queryFn: getSupportedChains,
|
|
220
|
+
queryFn: () => getSupportedChains({ quoteProvider }),
|
|
183
221
|
staleTime: 60 * 60 * 1000, // 1 hour - chains rarely change
|
|
184
222
|
gcTime: 24 * 60 * 60 * 1000, // 24 hours - keep in cache for a full day
|
|
185
223
|
refetchOnWindowFocus: false, // Don't refetch when window regains focus
|
package/src/constants.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import type { Context as ContextLike } from "@0xsequence/wallet-primitives"
|
|
2
2
|
|
|
3
3
|
export const SEQUENCE_V3_CONTRACT_ADDRESSES: ContextLike.Context = {
|
|
4
|
-
factory: "
|
|
5
|
-
stage1: "
|
|
6
|
-
stage2: "
|
|
4
|
+
factory: "0x7aaaD48b90Ea2c1DaE03cb68ea1Ed8E1DD26dB38" as `0x${string}`,
|
|
5
|
+
stage1: "0x4d7c112790F03caFc7287b1a29Aa03da1Bb00C10" as `0x${string}`,
|
|
6
|
+
stage2: "0x7C96ff440BCE51EEF0C9f748D69246B4b3F28173" as `0x${string}`,
|
|
7
7
|
creationCode:
|
|
8
|
-
"
|
|
8
|
+
"0x6041600e3d396021805130553df33d3d36153402601f57363d3d373d363d30545af43d82803e903d91601f57fd5bf3" as `0x${string}`,
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
export const TRAILS_BALANCE_INJECTOR_ADDRESS =
|
|
12
|
+
"0x9eCA6CEf73799402a1afe4779f588f03034c5D0f"
|
|
13
|
+
|
|
11
14
|
export const ATTESATION_SIGNER_ADDRESS =
|
|
12
15
|
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
|
|
13
16
|
|
package/src/decoders.ts
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import type { TransactionReceipt, Log } from "viem"
|
|
2
|
+
import { decodeEventLog, parseAbiItem } from "viem"
|
|
3
|
+
|
|
4
|
+
// Corrected ABI items
|
|
5
|
+
const CALL_SUCCEEDED_ABI = parseAbiItem(
|
|
6
|
+
"event CallSucceeded(bytes32 _opHash, uint256 _index)",
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
const CALL_FAILED_ABI = parseAbiItem(
|
|
10
|
+
"event CallFailed(bytes32 _opHash, uint256 _index, bytes _returnData)",
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
const CALL_ABORTED_ABI = parseAbiItem(
|
|
14
|
+
"event CallAborted(bytes32 _opHash, uint256 _index, bytes _returnData)",
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
// only `deploymentId` is indexed
|
|
18
|
+
const CALL_SKIPPED_ABI = parseAbiItem(
|
|
19
|
+
"event CallSkipped(bytes32 indexed deploymentId, uint256 actionIndex)",
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
// Refund / Sweep events come from the Trails Token Sweeper contract.
|
|
23
|
+
// Contract source and event definitions:
|
|
24
|
+
// - https://github.com/0xsequence/trails-contracts/pull/28
|
|
25
|
+
// - https://github.com/0xsequence/stack/pull/1249
|
|
26
|
+
const REFUND_ABI = parseAbiItem(
|
|
27
|
+
"event Refund(address indexed token, address indexed recipient, uint256 amount)",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
const SWEEP_ABI = parseAbiItem(
|
|
31
|
+
"event Sweep(address indexed token, address indexed recipient, uint256 amount)",
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
// Event types
|
|
35
|
+
export interface CallSucceededEvent {
|
|
36
|
+
type: "CallSucceeded"
|
|
37
|
+
opHash: string
|
|
38
|
+
index: bigint
|
|
39
|
+
log: Log
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface CallFailedEvent {
|
|
43
|
+
type: "CallFailed"
|
|
44
|
+
opHash: string
|
|
45
|
+
index: bigint
|
|
46
|
+
returnData: string
|
|
47
|
+
log: Log
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface CallAbortedEvent {
|
|
51
|
+
type: "CallAborted"
|
|
52
|
+
opHash: string
|
|
53
|
+
index: bigint
|
|
54
|
+
returnData: string
|
|
55
|
+
log: Log
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface CallSkippedEvent {
|
|
59
|
+
type: "CallSkipped"
|
|
60
|
+
deploymentId: string
|
|
61
|
+
actionIndex: bigint
|
|
62
|
+
log: Log
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface RefundEvent {
|
|
66
|
+
type: "Refund"
|
|
67
|
+
token: string
|
|
68
|
+
recipient: string
|
|
69
|
+
amount: bigint
|
|
70
|
+
log: Log
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface SweepEvent {
|
|
74
|
+
type: "Sweep"
|
|
75
|
+
token: string
|
|
76
|
+
recipient: string
|
|
77
|
+
amount: bigint
|
|
78
|
+
log: Log
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export type GuestModuleEvent =
|
|
82
|
+
| CallSucceededEvent
|
|
83
|
+
| CallFailedEvent
|
|
84
|
+
| CallAbortedEvent
|
|
85
|
+
| CallSkippedEvent
|
|
86
|
+
|
|
87
|
+
// Trails Token Sweeper events: see PR references above for canonical specs.
|
|
88
|
+
export type TrailsTokenSweeperEvent = RefundEvent | SweepEvent
|
|
89
|
+
|
|
90
|
+
// === Decoders ===
|
|
91
|
+
|
|
92
|
+
export function decodeCallSucceeded(log: Log): CallSucceededEvent | null {
|
|
93
|
+
try {
|
|
94
|
+
const decoded = decodeEventLog({
|
|
95
|
+
abi: [CALL_SUCCEEDED_ABI],
|
|
96
|
+
data: log.data,
|
|
97
|
+
topics: log.topics,
|
|
98
|
+
strict: false,
|
|
99
|
+
}) as {
|
|
100
|
+
eventName: "CallSucceeded"
|
|
101
|
+
args: { _opHash: string; _index: bigint }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
type: "CallSucceeded",
|
|
106
|
+
opHash: decoded.args._opHash,
|
|
107
|
+
index: decoded.args._index,
|
|
108
|
+
log,
|
|
109
|
+
}
|
|
110
|
+
} catch {
|
|
111
|
+
return null
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function decodeCallFailed(log: Log): CallFailedEvent | null {
|
|
116
|
+
try {
|
|
117
|
+
const decoded = decodeEventLog({
|
|
118
|
+
abi: [CALL_FAILED_ABI],
|
|
119
|
+
data: log.data,
|
|
120
|
+
topics: log.topics,
|
|
121
|
+
strict: false,
|
|
122
|
+
}) as {
|
|
123
|
+
eventName: "CallFailed"
|
|
124
|
+
args: { _opHash: string; _index: bigint; _returnData: string }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
type: "CallFailed",
|
|
129
|
+
opHash: decoded.args._opHash,
|
|
130
|
+
index: decoded.args._index,
|
|
131
|
+
returnData: decoded.args._returnData,
|
|
132
|
+
log,
|
|
133
|
+
}
|
|
134
|
+
} catch {
|
|
135
|
+
return null
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function decodeCallAborted(log: Log): CallAbortedEvent | null {
|
|
140
|
+
try {
|
|
141
|
+
const decoded = decodeEventLog({
|
|
142
|
+
abi: [CALL_ABORTED_ABI],
|
|
143
|
+
data: log.data,
|
|
144
|
+
topics: log.topics,
|
|
145
|
+
strict: false,
|
|
146
|
+
}) as {
|
|
147
|
+
eventName: "CallAborted"
|
|
148
|
+
args: { _opHash: string; _index: bigint; _returnData: string }
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
type: "CallAborted",
|
|
153
|
+
opHash: decoded.args._opHash,
|
|
154
|
+
index: decoded.args._index,
|
|
155
|
+
returnData: decoded.args._returnData,
|
|
156
|
+
log,
|
|
157
|
+
}
|
|
158
|
+
} catch {
|
|
159
|
+
return null
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function decodeCallSkipped(log: Log): CallSkippedEvent | null {
|
|
164
|
+
try {
|
|
165
|
+
const decoded = decodeEventLog({
|
|
166
|
+
abi: [CALL_SKIPPED_ABI],
|
|
167
|
+
data: log.data,
|
|
168
|
+
topics: log.topics,
|
|
169
|
+
strict: false,
|
|
170
|
+
}) as {
|
|
171
|
+
eventName: "CallSkipped"
|
|
172
|
+
args: { deploymentId: string; actionIndex: bigint }
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
type: "CallSkipped",
|
|
177
|
+
deploymentId: decoded.args.deploymentId,
|
|
178
|
+
actionIndex: decoded.args.actionIndex,
|
|
179
|
+
log,
|
|
180
|
+
}
|
|
181
|
+
} catch {
|
|
182
|
+
return null
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function decodeRefund(log: Log): RefundEvent | null {
|
|
187
|
+
try {
|
|
188
|
+
const decoded = decodeEventLog({
|
|
189
|
+
abi: [REFUND_ABI],
|
|
190
|
+
data: log.data,
|
|
191
|
+
topics: log.topics,
|
|
192
|
+
strict: false,
|
|
193
|
+
}) as {
|
|
194
|
+
eventName: "Refund"
|
|
195
|
+
args: { token: string; recipient: string; amount: bigint }
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
type: "Refund",
|
|
200
|
+
token: decoded.args.token,
|
|
201
|
+
recipient: decoded.args.recipient,
|
|
202
|
+
amount: decoded.args.amount,
|
|
203
|
+
log,
|
|
204
|
+
}
|
|
205
|
+
} catch {
|
|
206
|
+
return null
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function decodeSweep(log: Log): SweepEvent | null {
|
|
211
|
+
try {
|
|
212
|
+
const decoded = decodeEventLog({
|
|
213
|
+
abi: [SWEEP_ABI],
|
|
214
|
+
data: log.data,
|
|
215
|
+
topics: log.topics,
|
|
216
|
+
strict: false,
|
|
217
|
+
}) as {
|
|
218
|
+
eventName: "Sweep"
|
|
219
|
+
args: { token: string; recipient: string; amount: bigint }
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
type: "Sweep",
|
|
224
|
+
token: decoded.args.token,
|
|
225
|
+
recipient: decoded.args.recipient,
|
|
226
|
+
amount: decoded.args.amount,
|
|
227
|
+
log,
|
|
228
|
+
}
|
|
229
|
+
} catch {
|
|
230
|
+
return null
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// === Main decoder ===
|
|
235
|
+
|
|
236
|
+
export function decodeTrailsTokenSweeperEvents(
|
|
237
|
+
receipt: TransactionReceipt,
|
|
238
|
+
): TrailsTokenSweeperEvent[] {
|
|
239
|
+
const events: TrailsTokenSweeperEvent[] = []
|
|
240
|
+
|
|
241
|
+
for (const log of receipt.logs) {
|
|
242
|
+
const refund = decodeRefund(log)
|
|
243
|
+
if (refund) {
|
|
244
|
+
events.push(refund)
|
|
245
|
+
continue
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const sweep = decodeSweep(log)
|
|
249
|
+
if (sweep) {
|
|
250
|
+
events.push(sweep)
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return events
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export function decodeGuestModuleEvents(
|
|
258
|
+
receipt: TransactionReceipt,
|
|
259
|
+
): GuestModuleEvent[] {
|
|
260
|
+
const events: GuestModuleEvent[] = []
|
|
261
|
+
|
|
262
|
+
for (const log of receipt.logs) {
|
|
263
|
+
const succeeded = decodeCallSucceeded(log)
|
|
264
|
+
if (succeeded) {
|
|
265
|
+
events.push(succeeded)
|
|
266
|
+
continue
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const failed = decodeCallFailed(log)
|
|
270
|
+
if (failed) {
|
|
271
|
+
events.push(failed)
|
|
272
|
+
continue
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const aborted = decodeCallAborted(log)
|
|
276
|
+
if (aborted) {
|
|
277
|
+
events.push(aborted)
|
|
278
|
+
continue
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const skipped = decodeCallSkipped(log)
|
|
282
|
+
if (skipped) {
|
|
283
|
+
events.push(skipped)
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return events
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// === Utilities ===
|
|
291
|
+
|
|
292
|
+
export function getEventsByType<T extends GuestModuleEvent["type"]>(
|
|
293
|
+
events: GuestModuleEvent[],
|
|
294
|
+
type: T,
|
|
295
|
+
): Extract<GuestModuleEvent, { type: T }>[] {
|
|
296
|
+
return events.filter(
|
|
297
|
+
(event): event is Extract<GuestModuleEvent, { type: T }> =>
|
|
298
|
+
event.type === type,
|
|
299
|
+
)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export function getFirstEventByType<T extends GuestModuleEvent["type"]>(
|
|
303
|
+
events: GuestModuleEvent[],
|
|
304
|
+
type: T,
|
|
305
|
+
): Extract<GuestModuleEvent, { type: T }> | undefined {
|
|
306
|
+
return events.find(
|
|
307
|
+
(event): event is Extract<GuestModuleEvent, { type: T }> =>
|
|
308
|
+
event.type === type,
|
|
309
|
+
)
|
|
310
|
+
}
|
package/src/ens.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { mainnet } from "viem/chains"
|
|
2
|
+
import { useEnsAddress, useEnsName } from "wagmi"
|
|
3
|
+
|
|
4
|
+
export function useResolveEnsAddress({ textInput }: { textInput: string }) {
|
|
5
|
+
const { data: ensAddress, isLoading } = useEnsAddress({
|
|
6
|
+
name: textInput?.endsWith(".eth") ? textInput : undefined,
|
|
7
|
+
chainId: mainnet.id,
|
|
8
|
+
query: {
|
|
9
|
+
enabled: !!textInput && textInput.endsWith(".eth"),
|
|
10
|
+
},
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
ensAddress,
|
|
15
|
+
isLoading,
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function useResolveEnsName({ address }: { address: string }) {
|
|
20
|
+
const { data: ensName, isLoading } = useEnsName({
|
|
21
|
+
address: address?.startsWith("0x") ? (address as `0x${string}`) : undefined,
|
|
22
|
+
chainId: mainnet.id,
|
|
23
|
+
query: {
|
|
24
|
+
enabled: !!address && address.startsWith("0x"),
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
ensName,
|
|
30
|
+
isLoading,
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/error.ts
CHANGED
|
@@ -3,7 +3,10 @@ export function getFullErrorMessage(err: any) {
|
|
|
3
3
|
|
|
4
4
|
let current = err
|
|
5
5
|
while (current) {
|
|
6
|
-
if (current
|
|
6
|
+
if (typeof current === "string") {
|
|
7
|
+
messages.push(current)
|
|
8
|
+
}
|
|
9
|
+
if (typeof current.message === "string") {
|
|
7
10
|
messages.push(current.message)
|
|
8
11
|
}
|
|
9
12
|
|
|
@@ -37,3 +40,100 @@ export class InsufficientBalanceError extends Error {
|
|
|
37
40
|
this.name = "InsufficientBalanceError"
|
|
38
41
|
}
|
|
39
42
|
}
|
|
43
|
+
|
|
44
|
+
export function getIsApiError(err: unknown) {
|
|
45
|
+
const isApiError = /request aborted|not deployed/gi.test(
|
|
46
|
+
getErrorString(err).toLowerCase(),
|
|
47
|
+
)
|
|
48
|
+
return isApiError
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function getIsRateLimitedError(err: unknown) {
|
|
52
|
+
const isRateLimited = /slow down|request rate|rate limit/gi.test(
|
|
53
|
+
getErrorString(err).toLowerCase(),
|
|
54
|
+
)
|
|
55
|
+
return isRateLimited
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function getIsRequiredAmountNotMetError(err: unknown) {
|
|
59
|
+
// Example error:
|
|
60
|
+
// GetIntentsQuote failed: total required amount (196159816026182793237) exceeds user-specified maximum (21960919303474978846)
|
|
61
|
+
const isRequiredAmountNotMet = /exceeds user-specified maximum/gi.test(
|
|
62
|
+
getErrorString(err).toLowerCase(),
|
|
63
|
+
)
|
|
64
|
+
return isRequiredAmountNotMet
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function getIsNoAvailableQuoteError(err: unknown) {
|
|
68
|
+
const isNoAvailableQuote =
|
|
69
|
+
/no available quotes|failed to get quote from any provider/gi.test(
|
|
70
|
+
getErrorString(err).toLowerCase(),
|
|
71
|
+
)
|
|
72
|
+
return isNoAvailableQuote
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function getIsQuoteFailedError(err: unknown) {
|
|
76
|
+
const isQuoteFailed = /GetIntentsQuote failed/gi.test(
|
|
77
|
+
getErrorString(err).toLowerCase(),
|
|
78
|
+
)
|
|
79
|
+
return isQuoteFailed
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function getIsQuoteTokenError(err: unknown) {
|
|
83
|
+
const isQuoteTokenError =
|
|
84
|
+
/requires destination token to be USDC|Token or chain not found/gi.test(
|
|
85
|
+
getErrorString(err).toLowerCase(),
|
|
86
|
+
)
|
|
87
|
+
return isQuoteTokenError
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function getIsQuoteInputError(err: unknown) {
|
|
91
|
+
const isQuoteInputError =
|
|
92
|
+
/Invalid input or output currency|originTokenAmount must be greater than zero|trails fee is greater than the origin token amount/gi.test(
|
|
93
|
+
getErrorString(err).toLowerCase(),
|
|
94
|
+
)
|
|
95
|
+
return isQuoteInputError
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function getIsInsufficientLiquidityError(err: unknown) {
|
|
99
|
+
const isInsufficientLiquidity =
|
|
100
|
+
/insufficient liquidity|higher than the available liquidity/gi.test(
|
|
101
|
+
getErrorString(err).toLowerCase(),
|
|
102
|
+
)
|
|
103
|
+
return isInsufficientLiquidity
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function getPrettifiedErrorMessage(
|
|
107
|
+
err: unknown,
|
|
108
|
+
defaultMessage: string = "",
|
|
109
|
+
) {
|
|
110
|
+
const isRequiredAmountNotMet = getIsRequiredAmountNotMetError(err)
|
|
111
|
+
if (isRequiredAmountNotMet) {
|
|
112
|
+
return "The requested amount is too low to retrieve a quote or the account has insufficient funds to meet the required amount. Try again with a higher amount or make sure you have enough funds."
|
|
113
|
+
}
|
|
114
|
+
const isInsufficientLiquidity = getIsInsufficientLiquidityError(err)
|
|
115
|
+
if (isInsufficientLiquidity) {
|
|
116
|
+
return "The requested amount is too high to retrieve a quote. Try again with a lower amount."
|
|
117
|
+
}
|
|
118
|
+
const isNoAvailableQuote = getIsNoAvailableQuoteError(err)
|
|
119
|
+
if (isNoAvailableQuote) {
|
|
120
|
+
return "No quote found for the selected pair and/or amount. Try again with a different pair and/or amount."
|
|
121
|
+
}
|
|
122
|
+
const isQuoteTokenError = getIsQuoteTokenError(err)
|
|
123
|
+
if (isQuoteTokenError) {
|
|
124
|
+
return "The selected token is not supported. Please try again with a different token."
|
|
125
|
+
}
|
|
126
|
+
const isQuoteInputError = getIsQuoteInputError(err)
|
|
127
|
+
if (isQuoteInputError) {
|
|
128
|
+
return "No quote found for the input amount. Try again with a higher amount."
|
|
129
|
+
}
|
|
130
|
+
const isQuoteFailed = getIsQuoteFailedError(err)
|
|
131
|
+
if (isQuoteFailed) {
|
|
132
|
+
return "No quote found for the selected pair and amount."
|
|
133
|
+
}
|
|
134
|
+
const isApiError = getIsApiError(err)
|
|
135
|
+
if (isApiError) {
|
|
136
|
+
return "An API error occurred. Please try again later."
|
|
137
|
+
}
|
|
138
|
+
return defaultMessage
|
|
139
|
+
}
|
package/src/intents.ts
CHANGED
|
@@ -6,12 +6,12 @@ import type {
|
|
|
6
6
|
IntentCallsPayload,
|
|
7
7
|
IntentPrecondition,
|
|
8
8
|
SequenceAPIClient,
|
|
9
|
-
} from "@0xsequence/api"
|
|
9
|
+
} from "@0xsequence/trails-api"
|
|
10
10
|
|
|
11
11
|
export type {
|
|
12
12
|
IntentCallsPayload,
|
|
13
13
|
IntentPrecondition,
|
|
14
|
-
} from "@0xsequence/api"
|
|
14
|
+
} from "@0xsequence/trails-api"
|
|
15
15
|
|
|
16
16
|
import { Config, type Context, Payload } from "@0xsequence/wallet-primitives"
|
|
17
17
|
import {
|
|
@@ -116,6 +116,7 @@ export type SendOriginCallTxArgs = {
|
|
|
116
116
|
export async function getIntentCallsPayloads(
|
|
117
117
|
apiClient: SequenceAPIClient,
|
|
118
118
|
args: GetIntentCallsPayloadsArgs,
|
|
119
|
+
additionalTrackingProps: Record<string, string> = {},
|
|
119
120
|
): Promise<GetIntentCallsPayloadsReturn> {
|
|
120
121
|
const localApiIntent = getQueryParam("localapiintent") === "true"
|
|
121
122
|
if (localApiIntent) {
|
|
@@ -133,6 +134,7 @@ export async function getIntentCallsPayloads(
|
|
|
133
134
|
originTokenAddress: args.originTokenAddress,
|
|
134
135
|
destinationTokenAddress: args.destinationTokenAddress,
|
|
135
136
|
userAddress: args.userAddress,
|
|
137
|
+
...additionalTrackingProps,
|
|
136
138
|
})
|
|
137
139
|
|
|
138
140
|
try {
|
|
@@ -162,6 +164,7 @@ export async function getIntentCallsPayloads(
|
|
|
162
164
|
feeToken: result.trailsFee?.feeToken,
|
|
163
165
|
userAddress: args.userAddress,
|
|
164
166
|
intentAddress: result.originIntentAddress,
|
|
167
|
+
...additionalTrackingProps,
|
|
165
168
|
})
|
|
166
169
|
|
|
167
170
|
return result
|
|
@@ -174,6 +177,7 @@ export async function getIntentCallsPayloads(
|
|
|
174
177
|
destinationChainId: args.destinationChainId || 0,
|
|
175
178
|
originTokenAddress: args.originTokenAddress,
|
|
176
179
|
destinationTokenAddress: args.destinationTokenAddress,
|
|
180
|
+
...additionalTrackingProps,
|
|
177
181
|
})
|
|
178
182
|
throw error
|
|
179
183
|
}
|
|
@@ -259,6 +263,7 @@ export async function commitIntentConfig(
|
|
|
259
263
|
mainSignerAddress: string,
|
|
260
264
|
calls: Array<IntentCallsPayload>,
|
|
261
265
|
preconditions: Array<IntentPrecondition>,
|
|
266
|
+
additionalTrackingProps: Record<string, string> = {},
|
|
262
267
|
): Promise<CommitIntentConfigReturn> {
|
|
263
268
|
console.log("[trails-sdk] commitIntentConfig inputs:", {
|
|
264
269
|
mainSignerAddress,
|
|
@@ -323,6 +328,7 @@ export async function commitIntentConfig(
|
|
|
323
328
|
destinationChainId: destinationChainIdStr
|
|
324
329
|
? Number(destinationChainIdStr)
|
|
325
330
|
: undefined,
|
|
331
|
+
...additionalTrackingProps,
|
|
326
332
|
})
|
|
327
333
|
|
|
328
334
|
const result = await apiClient.commitIntentConfig({
|
|
@@ -338,6 +344,7 @@ export async function commitIntentConfig(
|
|
|
338
344
|
destinationChainId: destinationChainIdStr
|
|
339
345
|
? Number(destinationChainIdStr)
|
|
340
346
|
: undefined,
|
|
347
|
+
...additionalTrackingProps,
|
|
341
348
|
})
|
|
342
349
|
|
|
343
350
|
return result
|
|
@@ -351,6 +358,7 @@ export async function commitIntentConfig(
|
|
|
351
358
|
destinationChainId: destinationChainIdStr
|
|
352
359
|
? Number(destinationChainIdStr)
|
|
353
360
|
: undefined,
|
|
361
|
+
...additionalTrackingProps,
|
|
354
362
|
})
|
|
355
363
|
throw error
|
|
356
364
|
}
|