@b3dotfun/sdk 0.0.3 → 0.0.4-alpha.1
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/cjs/anyspend/index.js +1 -0
- package/dist/cjs/anyspend/react/components/index.d.ts +6 -5
- package/dist/cjs/anyspend/react/components/index.js +13 -11
- package/dist/cjs/anyspend/react/components/webview/WebviewOnrampPayment.d.ts +11 -0
- package/dist/cjs/anyspend/react/components/webview/WebviewOnrampPayment.js +93 -0
- package/dist/cjs/anyspend/react/hooks/useAnyspendOrderAndTransactions.d.ts +10 -0
- package/dist/cjs/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +10 -0
- package/dist/cjs/anyspend/services/anyspend.d.ts +5 -0
- package/dist/cjs/anyspend/types/order.d.ts +18 -0
- package/dist/cjs/anyspend/types/order.js +1 -0
- package/dist/cjs/anyspend/types/req-res/createOrder.d.ts +25 -0
- package/dist/cjs/anyspend/types/req-res/getOrderAndTransactions.d.ts +35 -0
- package/dist/cjs/anyspend/types/req-res/getOrderHistory.d.ts +25 -0
- package/dist/cjs/global-account/react/hooks/useTokenFromUrl.d.ts +1 -1
- package/dist/cjs/global-account/react/hooks/useTokenFromUrl.js +51 -13
- package/dist/cjs/shared/constants/chains/supported.d.ts +14 -4
- package/dist/cjs/shared/constants/chains/supported.js +11 -8
- package/dist/cjs/shared/generated/coingecko-chains.json +1072 -0
- package/dist/esm/anyspend/index.js +1 -0
- package/dist/esm/anyspend/react/components/index.d.ts +6 -5
- package/dist/esm/anyspend/react/components/index.js +6 -5
- package/dist/esm/anyspend/react/components/webview/WebviewOnrampPayment.d.ts +11 -0
- package/dist/esm/anyspend/react/components/webview/WebviewOnrampPayment.js +87 -0
- package/dist/esm/anyspend/react/hooks/useAnyspendOrderAndTransactions.d.ts +10 -0
- package/dist/esm/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +10 -0
- package/dist/esm/anyspend/services/anyspend.d.ts +5 -0
- package/dist/esm/anyspend/types/order.d.ts +18 -0
- package/dist/esm/anyspend/types/order.js +1 -0
- package/dist/esm/anyspend/types/req-res/createOrder.d.ts +25 -0
- package/dist/esm/anyspend/types/req-res/getOrderAndTransactions.d.ts +35 -0
- package/dist/esm/anyspend/types/req-res/getOrderHistory.d.ts +25 -0
- package/dist/esm/global-account/react/hooks/useTokenFromUrl.d.ts +1 -1
- package/dist/esm/global-account/react/hooks/useTokenFromUrl.js +51 -13
- package/dist/esm/shared/constants/chains/supported.d.ts +14 -4
- package/dist/esm/shared/constants/chains/supported.js +9 -7
- package/dist/esm/shared/generated/coingecko-chains.json +1072 -0
- package/dist/types/anyspend/react/components/index.d.ts +6 -5
- package/dist/types/anyspend/react/components/webview/WebviewOnrampPayment.d.ts +11 -0
- package/dist/types/anyspend/react/hooks/useAnyspendOrderAndTransactions.d.ts +10 -0
- package/dist/types/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +10 -0
- package/dist/types/anyspend/services/anyspend.d.ts +5 -0
- package/dist/types/anyspend/types/order.d.ts +18 -0
- package/dist/types/anyspend/types/req-res/createOrder.d.ts +25 -0
- package/dist/types/anyspend/types/req-res/getOrderAndTransactions.d.ts +35 -0
- package/dist/types/anyspend/types/req-res/getOrderHistory.d.ts +25 -0
- package/dist/types/global-account/react/hooks/useTokenFromUrl.d.ts +1 -1
- package/dist/types/shared/constants/chains/supported.d.ts +14 -4
- package/package.json +3 -3
- package/src/anyspend/index.ts +2 -0
- package/src/anyspend/react/components/index.ts +6 -5
- package/src/anyspend/react/components/webview/WebviewOnrampPayment.tsx +207 -0
- package/src/anyspend/types/order.ts +1 -0
- package/src/global-account/react/hooks/useTokenFromUrl.tsx +72 -14
- package/src/shared/constants/chains/supported.ts +23 -12
- package/src/shared/generated/coingecko-chains.json +1072 -0
- /package/dist/cjs/{generated → shared/generated}/chain-networks.json +0 -0
- /package/dist/esm/{generated → shared/generated}/chain-networks.json +0 -0
- /package/src/{generated → shared/generated}/chain-networks.json +0 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getChainName,
|
|
3
|
+
GetQuoteResponse,
|
|
4
|
+
OnrampVendor,
|
|
5
|
+
OrderType,
|
|
6
|
+
Token,
|
|
7
|
+
useAnyspendCreateOnrampOrder,
|
|
8
|
+
useGeoOnrampOptions
|
|
9
|
+
} from "@b3dotfun/sdk/anyspend";
|
|
10
|
+
import { Button } from "@b3dotfun/sdk/global-account/react";
|
|
11
|
+
import centerTruncate from "@b3dotfun/sdk/shared/utils/centerTruncate";
|
|
12
|
+
import { motion } from "framer-motion";
|
|
13
|
+
import { Loader2 } from "lucide-react";
|
|
14
|
+
import { useEffect, useRef, useState } from "react";
|
|
15
|
+
import { toast } from "sonner";
|
|
16
|
+
import { formatUnits } from "viem";
|
|
17
|
+
|
|
18
|
+
interface WebviewOnrampPaymentProps {
|
|
19
|
+
srcAmountOnRamp: string;
|
|
20
|
+
recipientAddress?: string;
|
|
21
|
+
destinationToken: Token;
|
|
22
|
+
anyspendQuote: GetQuoteResponse | undefined;
|
|
23
|
+
onOrderCreated: (orderId: string) => void;
|
|
24
|
+
userId?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function WebviewOnrampPayment({
|
|
28
|
+
srcAmountOnRamp,
|
|
29
|
+
recipientAddress,
|
|
30
|
+
destinationToken,
|
|
31
|
+
anyspendQuote,
|
|
32
|
+
onOrderCreated,
|
|
33
|
+
userId
|
|
34
|
+
}: WebviewOnrampPaymentProps) {
|
|
35
|
+
// Use a stable amount for geo onramp options to prevent unnecessary refetches
|
|
36
|
+
const [stableAmountForGeo, setStableAmountForGeo] = useState(srcAmountOnRamp);
|
|
37
|
+
const hasInitialized = useRef(false);
|
|
38
|
+
|
|
39
|
+
// Only update the stable amount on first render or when explicitly needed
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (!hasInitialized.current && srcAmountOnRamp) {
|
|
42
|
+
setStableAmountForGeo(srcAmountOnRamp);
|
|
43
|
+
hasInitialized.current = true;
|
|
44
|
+
}
|
|
45
|
+
}, [srcAmountOnRamp]);
|
|
46
|
+
|
|
47
|
+
const {
|
|
48
|
+
geoData,
|
|
49
|
+
isStripeWeb2Supported,
|
|
50
|
+
isLoading: isLoadingGeoOnramp
|
|
51
|
+
} = useGeoOnrampOptions(true, stableAmountForGeo);
|
|
52
|
+
|
|
53
|
+
console.log("isStripeWeb2Supported", isStripeWeb2Supported);
|
|
54
|
+
|
|
55
|
+
const { createOrder, isCreatingOrder } = useAnyspendCreateOnrampOrder({
|
|
56
|
+
onSuccess: data => {
|
|
57
|
+
const orderId = data.data.id;
|
|
58
|
+
window.location.href = `${window.location.origin}/?orderId=${orderId}`;
|
|
59
|
+
},
|
|
60
|
+
onError: error => {
|
|
61
|
+
console.error(error);
|
|
62
|
+
toast.error("Failed to create order: " + error.message);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const handleContinueToPayment = async () => {
|
|
67
|
+
try {
|
|
68
|
+
if (!recipientAddress) {
|
|
69
|
+
toast.error("Please select a recipient");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!srcAmountOnRamp || parseFloat(srcAmountOnRamp) <= 0) {
|
|
74
|
+
toast.error("Please enter a valid amount");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!isStripeWeb2Supported) {
|
|
79
|
+
toast.error("Stripe credit card not available");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!anyspendQuote) {
|
|
84
|
+
toast.error("Failed to get quote");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const getDstToken = (): Token => {
|
|
89
|
+
return {
|
|
90
|
+
...destinationToken,
|
|
91
|
+
chainId: destinationToken.chainId,
|
|
92
|
+
address: destinationToken.address
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
createOrder({
|
|
97
|
+
isMainnet: true,
|
|
98
|
+
recipientAddress,
|
|
99
|
+
orderType: OrderType.Swap,
|
|
100
|
+
dstChain: getDstToken().chainId,
|
|
101
|
+
dstToken: getDstToken(),
|
|
102
|
+
srcFiatAmount: srcAmountOnRamp,
|
|
103
|
+
onramp: {
|
|
104
|
+
vendor: OnrampVendor.StripeWeb2,
|
|
105
|
+
paymentMethod: "",
|
|
106
|
+
country: geoData?.country || "US",
|
|
107
|
+
ipAddress: geoData?.ip,
|
|
108
|
+
redirectUrl: `${window.location.origin}${userId ? `?userId=${userId}` : ""}`
|
|
109
|
+
},
|
|
110
|
+
expectedDstAmount: anyspendQuote?.data?.currencyOut?.amount?.toString() || "0"
|
|
111
|
+
});
|
|
112
|
+
} catch (err: any) {
|
|
113
|
+
console.error(err);
|
|
114
|
+
toast.error("Failed to create order: " + err.message);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<div className="mx-auto flex w-full max-w-[460px] flex-col gap-6">
|
|
120
|
+
{/* Order Summary Section */}
|
|
121
|
+
<>
|
|
122
|
+
<h2 className="-mb-3 text-lg font-semibold">Order summary</h2>
|
|
123
|
+
<div className="bg-b3-react-background border-b3-react-border flex flex-col gap-3 rounded-lg border p-4">
|
|
124
|
+
{/* Destination Token */}
|
|
125
|
+
<div className="flex items-center justify-between">
|
|
126
|
+
<p className="text-b3-react-foreground/60">Receiving</p>
|
|
127
|
+
<div className="flex items-center gap-2">
|
|
128
|
+
{destinationToken.metadata?.logoURI && (
|
|
129
|
+
<img
|
|
130
|
+
src={destinationToken.metadata.logoURI}
|
|
131
|
+
alt={destinationToken.symbol}
|
|
132
|
+
className="h-6 w-6 rounded-full"
|
|
133
|
+
/>
|
|
134
|
+
)}
|
|
135
|
+
<span className="text-b3-react-foreground/80">
|
|
136
|
+
{anyspendQuote?.data?.currencyOut?.amount
|
|
137
|
+
? Number(
|
|
138
|
+
formatUnits(BigInt(anyspendQuote.data.currencyOut.amount), destinationToken.decimals)
|
|
139
|
+
).toFixed(4)
|
|
140
|
+
: "0"}{" "}
|
|
141
|
+
{destinationToken.symbol}
|
|
142
|
+
</span>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
{/* Network */}
|
|
147
|
+
<div className="flex items-center justify-between">
|
|
148
|
+
<p className="text-b3-react-foreground/60">Network</p>
|
|
149
|
+
<span className="text-b3-react-foreground/80">{getChainName(destinationToken.chainId)}</span>
|
|
150
|
+
</div>
|
|
151
|
+
|
|
152
|
+
{/* Recipient Section */}
|
|
153
|
+
{recipientAddress && (
|
|
154
|
+
<motion.div
|
|
155
|
+
initial={false}
|
|
156
|
+
animate={{
|
|
157
|
+
opacity: 1,
|
|
158
|
+
y: 0,
|
|
159
|
+
filter: "blur(0px)"
|
|
160
|
+
}}
|
|
161
|
+
transition={{ duration: 0.3, delay: 0.2, ease: "easeInOut" }}
|
|
162
|
+
className="flex items-center justify-between"
|
|
163
|
+
>
|
|
164
|
+
<p className="text-b3-react-foreground/60">Recipient</p>
|
|
165
|
+
<div className="flex items-center gap-2">
|
|
166
|
+
<span className="text-b3-react-foreground/80">{centerTruncate(recipientAddress)}</span>
|
|
167
|
+
</div>
|
|
168
|
+
</motion.div>
|
|
169
|
+
)}
|
|
170
|
+
|
|
171
|
+
{/* Amount Section */}
|
|
172
|
+
<div className="border-b3-react-border border-t pt-3">
|
|
173
|
+
<div className="flex items-center justify-between">
|
|
174
|
+
<p className="text-b3-react-foreground font-semibold">You Pay</p>
|
|
175
|
+
<p className="text-b3-react-foreground text-xl font-semibold">
|
|
176
|
+
${parseFloat(srcAmountOnRamp).toFixed(2)}
|
|
177
|
+
</p>
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</>
|
|
182
|
+
|
|
183
|
+
{/* Payment Section */}
|
|
184
|
+
{isCreatingOrder ? (
|
|
185
|
+
<div className="bg-b3-react-background border-b3-react-border flex items-center justify-center gap-3 rounded-lg border p-6">
|
|
186
|
+
<Loader2 className="h-4 w-4 animate-spin" />
|
|
187
|
+
<span className="text-as-primary/70">Creating payment session...</span>
|
|
188
|
+
</div>
|
|
189
|
+
) : isLoadingGeoOnramp ? (
|
|
190
|
+
<div className="bg-b3-react-background border-b3-react-border flex items-center justify-center gap-3 rounded-lg border p-6">
|
|
191
|
+
<Loader2 className="h-4 w-4 animate-spin" />
|
|
192
|
+
<span className="text-as-primary/70">Loading payment options...</span>
|
|
193
|
+
</div>
|
|
194
|
+
) : (
|
|
195
|
+
<div className="flex flex-col gap-4">
|
|
196
|
+
<Button
|
|
197
|
+
onClick={handleContinueToPayment}
|
|
198
|
+
disabled={isCreatingOrder || !isStripeWeb2Supported}
|
|
199
|
+
className="bg-as-brand hover:bg-as-brand/90 text-as-primary h-14 w-full rounded-xl text-lg font-medium"
|
|
200
|
+
>
|
|
201
|
+
{isCreatingOrder ? "Creating Payment..." : "Continue to Payment"}
|
|
202
|
+
</Button>
|
|
203
|
+
</div>
|
|
204
|
+
)}
|
|
205
|
+
</div>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
@@ -57,6 +57,7 @@ export const zBaseOrder = z.object({
|
|
|
57
57
|
expiredAt: z.number(),
|
|
58
58
|
onrampMetadata: zOnrampMetadata.nullable(),
|
|
59
59
|
creatorAddress: z.string().nullable(),
|
|
60
|
+
partnerId: z.string().nullable(),
|
|
60
61
|
|
|
61
62
|
oneClickBuyUrl: z.string().nullable(),
|
|
62
63
|
stripePaymentIntentId: z.string().nullable(),
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { Token } from "@b3dotfun/sdk/anyspend";
|
|
4
|
+
import { getCoingeckoChainInfo } from "@b3dotfun/sdk/shared/constants/chains/supported";
|
|
5
|
+
import { useQuery } from "@tanstack/react-query";
|
|
4
6
|
import { useSearchParams } from "next/navigation";
|
|
5
7
|
|
|
6
8
|
interface UseTokenFromUrlOptions {
|
|
@@ -15,32 +17,88 @@ interface UseTokenFromUrlOptions {
|
|
|
15
17
|
prefix: string;
|
|
16
18
|
}
|
|
17
19
|
|
|
20
|
+
interface TokenInfo {
|
|
21
|
+
data: {
|
|
22
|
+
attributes: {
|
|
23
|
+
address: string;
|
|
24
|
+
name: string;
|
|
25
|
+
symbol: string;
|
|
26
|
+
decimals: number;
|
|
27
|
+
image_url: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function fetchTokenInfo(network: string, address: string): Promise<TokenInfo> {
|
|
33
|
+
const response = await fetch("https://api.b3.fun/tokens", {
|
|
34
|
+
method: "POST",
|
|
35
|
+
headers: {
|
|
36
|
+
"Content-Type": "application/json",
|
|
37
|
+
"X-Service-Method": "getCoinGeckoTokenInfo"
|
|
38
|
+
},
|
|
39
|
+
body: JSON.stringify({
|
|
40
|
+
network,
|
|
41
|
+
address
|
|
42
|
+
})
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
throw new Error("Failed to fetch token info");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return response.json();
|
|
50
|
+
}
|
|
51
|
+
|
|
18
52
|
/**
|
|
19
|
-
* Hook to parse token data from URL parameters.
|
|
53
|
+
* Hook to parse token data from URL parameters and fetch additional token info.
|
|
20
54
|
* Looks for parameters: [prefix]Currency
|
|
21
55
|
*/
|
|
22
56
|
export function useTokenFromUrl({ defaultToken, prefix }: UseTokenFromUrlOptions): Token {
|
|
23
57
|
const searchParams = useSearchParams();
|
|
24
58
|
|
|
25
|
-
if (!searchParams) {
|
|
26
|
-
return defaultToken;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
59
|
// Get parameters from URL
|
|
30
|
-
const currencyParam = searchParams
|
|
31
|
-
const chainIdParam = searchParams
|
|
32
|
-
|
|
60
|
+
const currencyParam = searchParams?.get(`${prefix}Currency`);
|
|
61
|
+
const chainIdParam = searchParams?.get(`${prefix}ChainId`);
|
|
62
|
+
|
|
63
|
+
// Determine if we should fetch token info
|
|
64
|
+
const shouldFetchToken = Boolean(
|
|
65
|
+
currencyParam && chainIdParam && currencyParam.toLowerCase() !== defaultToken.address.toLowerCase()
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
// Determine network based on chainId
|
|
69
|
+
const network = chainIdParam ? getCoingeckoChainInfo(Number(chainIdParam)).coingecko_id : "";
|
|
70
|
+
|
|
71
|
+
const { data: tokenInfo, isError } = useQuery({
|
|
72
|
+
queryKey: ["tokenInfo", network, currencyParam],
|
|
73
|
+
queryFn: () => fetchTokenInfo(network, currencyParam!),
|
|
74
|
+
enabled: shouldFetchToken,
|
|
75
|
+
staleTime: Infinity,
|
|
76
|
+
gcTime: Infinity
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Return default token if no params or same as default
|
|
80
|
+
if (!shouldFetchToken) {
|
|
33
81
|
return defaultToken;
|
|
34
82
|
}
|
|
35
83
|
|
|
36
|
-
//
|
|
37
|
-
if (
|
|
38
|
-
return
|
|
84
|
+
// Return basic token info if API call fails or while loading
|
|
85
|
+
if (isError || !tokenInfo) {
|
|
86
|
+
return {
|
|
87
|
+
...defaultToken,
|
|
88
|
+
address: currencyParam!,
|
|
89
|
+
chainId: Number(chainIdParam)
|
|
90
|
+
};
|
|
39
91
|
}
|
|
40
92
|
|
|
93
|
+
// Return enhanced token with API data
|
|
41
94
|
return {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
95
|
+
address: tokenInfo.data.attributes.address,
|
|
96
|
+
chainId: Number(chainIdParam),
|
|
97
|
+
name: tokenInfo.data.attributes.name,
|
|
98
|
+
symbol: tokenInfo.data.attributes.symbol,
|
|
99
|
+
decimals: tokenInfo.data.attributes.decimals,
|
|
100
|
+
metadata: {
|
|
101
|
+
logoURI: tokenInfo.data.attributes.image_url
|
|
102
|
+
}
|
|
45
103
|
};
|
|
46
104
|
}
|
|
@@ -3,8 +3,10 @@ import { toThirdwebChain, toViemChain } from "@b3dotfun/sdk/shared/utils/chain-t
|
|
|
3
3
|
import type { Chain as ThirdwebChain } from "thirdweb";
|
|
4
4
|
// Import the JSON directly
|
|
5
5
|
// @ts-ignore
|
|
6
|
-
import chainNetworksJSON from "
|
|
7
|
-
|
|
6
|
+
import chainNetworksJSON from "../../generated/chain-networks.json" with { type: "json" };
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
import coingeckoChainsJSON from "../../generated/coingecko-chains.json" with { type: "json" };
|
|
9
|
+
|
|
8
10
|
const chainNetworks = chainNetworksJSON as ChainNetworks[];
|
|
9
11
|
|
|
10
12
|
// Convert custom chains to Viem format
|
|
@@ -27,15 +29,24 @@ export const supportedChainsTW: ThirdwebChain[] = [
|
|
|
27
29
|
// Original format from chain-networks.json
|
|
28
30
|
export const supportedChainNetworks = chainNetworks;
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
// CoinGecko chain mapping
|
|
33
|
+
export const coingeckoChains = coingeckoChainsJSON as Record<
|
|
34
|
+
number,
|
|
35
|
+
{
|
|
36
|
+
coingecko_id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
native_coin_id: string;
|
|
39
|
+
}
|
|
40
|
+
>;
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
// Helper function to get CoinGecko chain info
|
|
43
|
+
export function getCoingeckoChainInfo(chainId: number) {
|
|
44
|
+
return coingeckoChains[chainId];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const b3Mainnet = supportedChains.find(chain => chain.id === 8333);
|
|
48
|
+
export const b3Testnet = supportedChains.find(chain => chain.id === 1993);
|
|
49
|
+
export const baseMainnet = supportedChains.find(chain => chain.id === 8453);
|
|
39
50
|
|
|
40
|
-
export const
|
|
41
|
-
|
|
51
|
+
export const b3MainnetThirdWeb = supportedChainsTW.find(chain => chain.id === 8333);
|
|
52
|
+
export const b3TestnetThirdWeb = supportedChainsTW.find(chain => chain.id === 1993);
|