Skip to content

Commit f231d82

Browse files
committed
Add working whitelist
1 parent 6e10e7e commit f231d82

File tree

2 files changed

+92
-24
lines changed

2 files changed

+92
-24
lines changed

packages/payments/src/providers/relay.ts

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -253,19 +253,29 @@ export function relayProvider(
253253

254254
if (isCadenceDestination) {
255255
// Fetch the user's COA (Cadence Owned Account) EVM address
256-
const coaAddress = await getCoaAddress({
257-
flowClient,
258-
cadenceAddress: destination.address,
259-
})
256+
try {
257+
const coaAddress = await getCoaAddress({
258+
flowClient,
259+
cadenceAddress: destination.address,
260+
})
261+
262+
if (!coaAddress) {
263+
throw new Error(
264+
`No COA (Cadence Owned Account) found for Cadence address ${destination.address}. ` +
265+
`Please ensure your Flow account has a COA set up. ` +
266+
`Alternatively, connect using your Flow EVM address directly.`
267+
)
268+
}
260269

261-
if (!coaAddress) {
270+
actualDestination = coaAddress
271+
} catch (error) {
262272
throw new Error(
263-
`No COA (Cadence Owned Account) found for ${destination.address}. ` +
264-
`Please ensure the account has a COA set up at /public/evm.`
273+
`Failed to get COA for Cadence address ${destination.address}: ${
274+
error instanceof Error ? error.message : String(error)
275+
}. ` +
276+
`Try connecting with your Flow EVM address instead, or ensure your account has a COA set up.`
265277
)
266278
}
267-
268-
actualDestination = coaAddress
269279
}
270280

271281
if (!isEvmAddress(actualDestination)) {
@@ -289,19 +299,24 @@ export function relayProvider(
289299
cryptoIntent.currency
290300
)
291301

292-
// Convert human-readable amount to base units if provided
293-
const amountInBaseUnits = cryptoIntent.amount
294-
? toBaseUnits(cryptoIntent.amount, originCurrency.decimals)
295-
: undefined
302+
// Convert human-readable amount to base units
303+
// For deposit address mode, if no amount is specified, use a default that covers fees
304+
// The actual amount sent by the user can be different for deposit addresses
305+
// Use 1.0 (~$1 for stablecoins) which is enough to cover fees but not hit liquidity limits
306+
const amountForQuote = cryptoIntent.amount || "1.0"
307+
const amountInBaseUnits = toBaseUnits(
308+
amountForQuote,
309+
originCurrency.decimals
310+
)
296311

297312
// Call Relay API with deposit address mode
298313
const quote = await callRelayQuote(apiUrl, {
299-
user: destination.address,
314+
user: actualDestination,
300315
originChainId: parseInt(originChainId),
301316
destinationChainId: parseInt(destinationChainId),
302317
originCurrency: originCurrency.address,
303318
destinationCurrency: destinationCurrency.address,
304-
recipient: destination.address,
319+
recipient: actualDestination,
305320
amount: amountInBaseUnits,
306321
tradeType: DEPOSIT_ADDRESS_TRADE_TYPE, // Deposit addresses only work with EXACT_INPUT
307322
useDepositAddress: true,

packages/react-sdk/src/components/FundContent.tsx

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ const getChainName = (caipId: string): string => {
3434
return chain?.name || caipId
3535
}
3636

37+
// Helper to convert Flow network name to Flow EVM chain ID
38+
const getFlowEvmChainId = (network: string): number => {
39+
switch (network) {
40+
case "mainnet":
41+
return 747 // Flow EVM Mainnet
42+
case "testnet":
43+
return 545 // Flow EVM Testnet
44+
default:
45+
return 747 // Default to mainnet
46+
}
47+
}
48+
3749
export const FundContent: React.FC = () => {
3850
const [amount, setAmount] = useState("")
3951
const [selectedTabIndex, setSelectedTabIndex] = useState(0)
@@ -53,10 +65,6 @@ export const FundContent: React.FC = () => {
5365
c => c.type === "crypto"
5466
) as CryptoProviderCapability
5567

56-
// Get destination currencies (what can be received on Flow)
57-
// These are typically FLOW, USDF, WFLOW, etc.
58-
const destinationCurrencies = cryptoCapability?.currencies || []
59-
6068
// Build SOURCE chains list (where user can send FROM)
6169
const sourceChains = (cryptoCapability?.sourceChains || []).map(
6270
(caipId, index) => ({
@@ -88,9 +96,26 @@ export const FundContent: React.FC = () => {
8896
if (!selectedSourceChain || !cryptoCapability?.getCurrenciesForChain) {
8997
return []
9098
}
91-
return await cryptoCapability.getCurrenciesForChain(
99+
const currencies = await cryptoCapability.getCurrenciesForChain(
92100
selectedSourceChain.caipId
93101
)
102+
103+
// Whitelist of tokens that reliably support Relay deposit addresses
104+
// These have been tested and confirmed to work with Flow EVM as destination
105+
const SUPPORTED_TOKENS = new Set([
106+
// USDC (works on all chains)
107+
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // Ethereum
108+
"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", // Base
109+
"0xaf88d065e77c8cc2239327c5edb3a432268e5831", // Arbitrum
110+
"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359", // Polygon
111+
// USDT (works on Base, Polygon)
112+
"0xfde4c96c8593536e31f229ea8f37b2ada2699bb2", // Base
113+
"0xc2132d05d31c914a87c6611c10748aeb04b58e8f", // Polygon
114+
])
115+
116+
return currencies.filter(c =>
117+
SUPPORTED_TOKENS.has(c.address.toLowerCase())
118+
)
94119
},
95120
enabled: !!selectedSourceChain && !!cryptoCapability,
96121
staleTime: 5 * 60 * 1000,
@@ -101,6 +126,30 @@ export const FundContent: React.FC = () => {
101126
// Use currency metadata directly
102127
const sourceTokens = chainCurrencies || []
103128

129+
// Fetch destination currencies for Flow EVM
130+
const {data: destinationCurrencies} = useQuery(
131+
{
132+
queryKey: ["destinationCurrencies", chainId],
133+
queryFn: async () => {
134+
if (!chainId || !cryptoCapability?.getCurrenciesForChain) {
135+
return []
136+
}
137+
// Fetch currencies available on Flow EVM (destination chain)
138+
const flowEvmChainId = getFlowEvmChainId(chainId)
139+
const currencies = await cryptoCapability.getCurrenciesForChain(
140+
`eip155:${flowEvmChainId}`
141+
)
142+
// Filter out native tokens (zero address) - Relay only supports ERC20 for deposit addresses
143+
return currencies.filter(
144+
c => c.address !== "0x0000000000000000000000000000000000000000"
145+
)
146+
},
147+
enabled: !!chainId && !!cryptoCapability,
148+
staleTime: 5 * 60 * 1000,
149+
},
150+
queryClient
151+
)
152+
104153
// Update token selection when currencies load or chain changes
105154
useEffect(() => {
106155
if (sourceTokens.length > 0) {
@@ -120,17 +169,20 @@ export const FundContent: React.FC = () => {
120169
user?.addr &&
121170
chainId &&
122171
selectedSourceToken &&
123-
selectedSourceChain
172+
selectedSourceChain &&
173+
destinationCurrencies &&
174+
destinationCurrencies.length > 0
124175
) {
125176
// User's Flow address as destination (in CAIP-10 format)
126-
const destination = `eip155:${chainId}:${user.addr}`
177+
const flowEvmChainId = getFlowEvmChainId(chainId)
178+
const destination = `eip155:${flowEvmChainId}:${user.addr}`
127179

128180
createSession({
129181
kind: "crypto",
130182
destination,
131-
// Use first available destination currency (e.g., FLOW, USDF)
183+
// Use first available destination currency (e.g., USDC on Flow EVM)
132184
// Relay will automatically bridge source token to this
133-
currency: destinationCurrencies[0] || selectedSourceToken.address,
185+
currency: destinationCurrencies[0].address,
134186
sourceChain: selectedSourceChain.caipId,
135187
sourceCurrency: selectedSourceToken.address,
136188
amount: amount || undefined,
@@ -140,6 +192,7 @@ export const FundContent: React.FC = () => {
140192
selectedTabIndex,
141193
selectedSourceToken,
142194
selectedSourceChain,
195+
destinationCurrencies,
143196
amount,
144197
user?.addr,
145198
chainId,

0 commit comments

Comments
 (0)