Skip to content

Commit d5bf283

Browse files
feat: near intents NEP-245 support (#11043)
1 parent 7430bd4 commit d5bf283

File tree

3 files changed

+32
-15
lines changed

3 files changed

+32
-15
lines changed

packages/swapper/src/swappers/NearIntentsSwapper/types.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,13 @@ export const nearIntentsSupportedChainIds = [
1111
KnownChainIds.ArbitrumMainnet,
1212
KnownChainIds.BaseMainnet,
1313
KnownChainIds.GnosisMainnet,
14+
KnownChainIds.BnbSmartChainMainnet,
15+
KnownChainIds.PolygonMainnet,
16+
KnownChainIds.AvalancheMainnet,
17+
KnownChainIds.OptimismMainnet,
1418
KnownChainIds.BitcoinMainnet,
1519
KnownChainIds.DogecoinMainnet,
1620
KnownChainIds.SolanaMainnet,
17-
// TODO(gomes): NEP-245 support - https://github.com/shapeshift/web/issues/11020
18-
// KnownChainIds.BnbSmartChainMainnet,
19-
// KnownChainIds.PolygonMainnet,
20-
// KnownChainIds.AvalancheMainnet,
21-
// KnownChainIds.OptimismMainnet,
2221
] as const
2322

2423
export type NearIntentsSupportedChainId = (typeof nearIntentsSupportedChainIds)[number]
@@ -28,6 +27,10 @@ export const chainIdToNearIntentsChain: Record<NearIntentsSupportedChainId, stri
2827
[KnownChainIds.ArbitrumMainnet]: 'arb',
2928
[KnownChainIds.BaseMainnet]: 'base',
3029
[KnownChainIds.GnosisMainnet]: 'gnosis',
30+
[KnownChainIds.BnbSmartChainMainnet]: 'bsc',
31+
[KnownChainIds.PolygonMainnet]: 'pol',
32+
[KnownChainIds.AvalancheMainnet]: 'avax',
33+
[KnownChainIds.OptimismMainnet]: 'op',
3134
[KnownChainIds.BitcoinMainnet]: 'btc',
3235
[KnownChainIds.DogecoinMainnet]: 'doge',
3336
[KnownChainIds.SolanaMainnet]: 'sol',

packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { bnOrZero, isToken } from '@shapeshiftoss/utils'
66
import type { TransactionInstruction } from '@solana/web3.js'
77
import { zeroAddress } from 'viem'
88

9-
import type { GetExecutionStatusResponse } from '../../types'
9+
import type { GetExecutionStatusResponse, TokenResponse } from '../../types'
1010
import { chainIdToNearIntentsChain } from '../../types'
1111
import { OneClickService } from '../oneClickService'
1212

@@ -39,6 +39,8 @@ export const getNearIntentsAsset = ({
3939
return `nep141:${nearNetwork}-${contractAddress.toLowerCase()}.omft.near`
4040
}
4141

42+
const NEP245_CHAINS = ['bsc', 'pol', 'avax', 'op'] as const
43+
4244
export const assetToNearIntentsAsset = async (asset: Asset): Promise<string> => {
4345
const nearNetwork =
4446
chainIdToNearIntentsChain[asset.chainId as keyof typeof chainIdToNearIntentsChain]
@@ -47,22 +49,34 @@ export const assetToNearIntentsAsset = async (asset: Asset): Promise<string> =>
4749
throw new Error(`Unsupported chain for NEAR Intents: ${asset.chainId}`)
4850
}
4951

50-
// Solana tokens need lookup from /v0/tokens
51-
// Unlike other chains, Solana token IDs can't be generated from contract addresses
52-
// because NEAR Intents uses their own internal token registry for Solana SPL tokens
53-
if (asset.chainId === solanaChainId && isToken(asset.assetId)) {
52+
// NEP-245 chains (BSC, Polygon, Avalanche, Optimism) and Solana require token lookup
53+
// Asset IDs use hashed format that can't be generated from contract addresses
54+
const requiresLookup =
55+
NEP245_CHAINS.includes(nearNetwork as any) || asset.chainId === solanaChainId
56+
57+
if (requiresLookup) {
5458
const tokens = await OneClickService.getTokens()
55-
const solanaAddress = fromAssetId(asset.assetId).assetReference
56-
const match = tokens.find(t => t.blockchain === 'sol' && t.contractAddress === solanaAddress)
59+
const contractAddress = isToken(asset.assetId)
60+
? fromAssetId(asset.assetId).assetReference.toLowerCase()
61+
: null
62+
63+
const match = tokens.find((t: TokenResponse) => {
64+
if (t.blockchain !== nearNetwork) return false
65+
return contractAddress
66+
? t.contractAddress?.toLowerCase() === contractAddress
67+
: !t.contractAddress
68+
})
5769

5870
if (!match) {
59-
throw new Error(`Solana token not found in NEAR Intents: ${solanaAddress}`)
71+
throw new Error(
72+
`Token not found in NEAR Intents: ${asset.chainId} ${contractAddress || 'native'}`,
73+
)
6074
}
6175

6276
return match.assetId
6377
}
6478

65-
// For all other chains: use predictable NEP-141 format
79+
// NEP-141 chains (ETH, ARB, BASE, GNOSIS, BTC, DOGE): use predictable format
6680
const contractAddress = isToken(asset.assetId)
6781
? fromAssetId(asset.assetId).assetReference
6882
: zeroAddress

packages/unchained-client/openapitools.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@
149149
}
150150
},
151151
"arbitrum": {
152-
"inputSpec": "https://raw.githubusercontent.com/shapeshift/unchained/develop/node/coinstacks/arbitrum/api/src/swagger.json",
152+
"inputSpec": "https://raw.githubusercontent.com/shapeshift/unchained/2551305/node/coinstacks/arbitrum/api/src/swagger.json",
153153
"generatorName": "typescript-fetch",
154154
"output": "#{cwd}/src/generated/arbitrum",
155155
"enablePostProcessFile": true,

0 commit comments

Comments
 (0)