Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { DEFAULT_QUOTE_DEADLINE_MS, DEFAULT_SLIPPAGE_BPS } from '../constants'
import type { QuoteResponse } from '../types'
import { QuoteRequest } from '../types'
import { assetToNearIntentsAsset, calculateAccountCreationCosts } from '../utils/helpers/helpers'
import { initializeOneClickService, OneClickService } from '../utils/oneClickService'
import { ApiError, initializeOneClickService, OneClickService } from '../utils/oneClickService'

export const getTradeQuote = async (
input: CommonTradeQuoteInput,
Expand Down Expand Up @@ -72,6 +72,16 @@ export const getTradeQuote = async (
const originAsset = await assetToNearIntentsAsset(sellAsset)
const destinationAsset = await assetToNearIntentsAsset(buyAsset)

// This shouldn't be the case since we already got a rate and know these exist, but...
if (!(originAsset && destinationAsset)) {
return Err(
makeSwapErrorRight({
code: TradeQuoteError.UnsupportedTradePair,
message: 'Unsupported asset',
}),
)
}

const quoteRequest: QuoteRequest = {
dry: false,
swapType: QuoteRequest.swapType.EXACT_INPUT,
Expand Down Expand Up @@ -226,6 +236,20 @@ export const getTradeQuote = async (
return Ok([tradeQuote])
} catch (error) {
console.error('[NEAR Intents] getTradeQuote error:', error)

if (
error instanceof ApiError &&
(error.body?.message === 'tokenIn is not valid' ||
error.body?.message === 'tokenOut is not valid')
) {
return Err(
makeSwapErrorRight({
code: TradeQuoteError.UnsupportedTradePair,
message: 'Unsupported asset',
}),
)
}

return Err(
makeSwapErrorRight({
message:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { DEFAULT_QUOTE_DEADLINE_MS, DEFAULT_SLIPPAGE_BPS } from '../constants'
import type { QuoteResponse } from '../types'
import { QuoteRequest } from '../types'
import { assetToNearIntentsAsset, calculateAccountCreationCosts } from '../utils/helpers/helpers'
import { initializeOneClickService, OneClickService } from '../utils/oneClickService'
import { ApiError, initializeOneClickService, OneClickService } from '../utils/oneClickService'

export const getTradeRate = async (
input: GetTradeRateInput,
Expand All @@ -42,6 +42,15 @@ export const getTradeRate = async (
const originAsset = await assetToNearIntentsAsset(sellAsset)
const destinationAsset = await assetToNearIntentsAsset(buyAsset)

if (!(originAsset && destinationAsset)) {
return Err(
makeSwapErrorRight({
code: TradeQuoteError.UnsupportedTradePair,
message: 'Unsupported asset',
}),
)
}

// Wallet connected: use actual addresses
// No wallet: use "check-price" sentinel with INTENTS types
const hasWallet = sendAddress !== undefined
Expand Down Expand Up @@ -196,6 +205,19 @@ export const getTradeRate = async (

return Ok([tradeRate])
} catch (error) {
if (
error instanceof ApiError &&
(error.body?.message === 'tokenIn is not valid' ||
error.body?.message === 'tokenOut is not valid')
) {
return Err(
makeSwapErrorRight({
code: TradeQuoteError.UnsupportedTradePair,
message: 'Unsupported asset',
}),
)
}

return Err(
makeSwapErrorRight({
message: error instanceof Error ? error.message : 'Unknown error getting NEAR Intents rate',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,11 @@ export const getNearIntentsAsset = ({

const NEP245_CHAINS = ['bsc', 'pol', 'avax', 'op'] as const

export const assetToNearIntentsAsset = async (asset: Asset): Promise<string> => {
export const assetToNearIntentsAsset = async (asset: Asset): Promise<string | null> => {
const nearNetwork =
chainIdToNearIntentsChain[asset.chainId as keyof typeof chainIdToNearIntentsChain]

if (!nearNetwork) {
throw new Error(`Unsupported chain for NEAR Intents: ${asset.chainId}`)
}
if (!nearNetwork) return null

// NEP-245 chains (BSC, Polygon, Avalanche, Optimism) and Solana require token lookup
// Asset IDs use hashed format that can't be generated from contract addresses
Expand All @@ -67,11 +65,7 @@ export const assetToNearIntentsAsset = async (asset: Asset): Promise<string> =>
: !t.contractAddress
})

if (!match) {
throw new Error(
`Token not found in NEAR Intents: ${asset.chainId} ${contractAddress || 'native'}`,
)
}
if (!match) return null

return match.assetId
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { OneClickService, OpenAPI } from '@defuse-protocol/one-click-sdk-typescript'
import { ApiError, OneClickService, OpenAPI } from '@defuse-protocol/one-click-sdk-typescript'

import { ONE_CLICK_BASE_URL } from '../constants'

Expand All @@ -13,5 +13,5 @@ export const initializeOneClickService = (apiKey: string) => {
isInitialized = true
}

// Re-export the service for convenience
export { OneClickService }
// Re-export the service and types for convenience
export { ApiError, OneClickService }