Skip to content

CP-13005: Basic Fusion SDK Integration#3574

Merged
atn4z7 merged 19 commits intomainfrom
fusion-sdk
Feb 16, 2026
Merged

CP-13005: Basic Fusion SDK Integration#3574
atn4z7 merged 19 commits intomainfrom
fusion-sdk

Conversation

@atn4z7
Copy link
Collaborator

@atn4z7 atn4z7 commented Feb 12, 2026

Description

Ticket: CP-13005

Fusion SDK Integration

  • Created FusionService to initialize TransferManager with environment-based configuration
  • Implemented feature flag-driven service enablement:
    • fusion-markr: Cross-chain swaps via Markr
    • fusion-avalanche-evm: EVM-based transfers
    • fusion-lombard-btc-to-btcb: BTC → BTC.b wrapping
    • fusion-lombard-btcb-to-btc: BTC.b → BTC unwrapping

Metro Config Update

  • Added package export resolution for @avalabs/unified-asset-transfer to fix module loading issues

Dynamic Chain Support

  • Fetch and display supported chains from SDK dynamically (removes hardcoded chain lists)

Zod v3 → v4 Upgrade

  • Fusion SDK requires Zod v4, which breaks Zodios (@zodios/core) as it depends on Zod v3.
  • Removed Zodios entirely and migrated to native nitro fetch with validation implementations for the following api clients: jupiter, markr, coingecko, defi, browser, meld, profile (openapi-zod-client → @hey-api/openapi-ts)

Testing

iOS: 0.0.0.7481
Android: 0.0.0.7482

Fusion Dynamic Chain Support

  • Only renders SDK-supported chains on "Select a token" screen
  • Chains should be filtered by current testnet mode and disabled chains should not show up

Portfolio & Track tabs:

  • Balance loads correctly for xp addresses
  • Token prices load correctly
  • Token logos display

Buy/Sell flow

  • Country list loads
  • Payment methods display
  • Quote generation works

Swap (v1)

  • Select Solana network
  • Choose SOL → USDC swap
  • Quote fetches successfully
  • Rate displays correctly

DeFi Protocol (DeFi tab)

  • DeFi protocols load
  • Chain list displays
  • Protocol balances show

Profile API

  • Balance loads correctly for xp addresses

Checklist

Please check all that apply (if applicable)

  • I have performed a self-review of my code
  • I have verified the code works
  • I have included screenshots / videos of android and ios
  • I have added testing steps
  • I have added/updated necessary unit tests
  • I have updated the documentation

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Integrates the Fusion (unified-asset-transfer) SDK into core-mobile and upgrades the API client layer to be compatible with Zod v4 by replacing Zodios with fetch-based clients and new OpenAPI codegen.

Changes:

  • Added Fusion feature flags, Redux listeners, SDK signers, and a FusionService wrapper around TransferManager.
  • Migrated multiple API clients from Zodios to fetchJson helpers with optional dev-only Zod validation, and switched OpenAPI codegen to @hey-api/openapi-ts.
  • Updated Metro resolution and various imports/paths for the new generated API client layout and dynamic supported-chain discovery.

Reviewed changes

Copilot reviewed 68 out of 70 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packages/core-mobile/scripts/codegen.js Switches generated output path and codegen tool to @hey-api/openapi-ts.
packages/core-mobile/profile-api.config.js Adds @hey-api/openapi-ts config for Profile API schema (env-based URL).
packages/core-mobile/package.json Adds Fusion SDK dep, removes Zodios, upgrades Zod to v4.
packages/core-mobile/metro.config.js Enables unstable_enablePackageExports for unified-asset-transfer (and Lombard).
packages/core-mobile/balance-api.config.js Makes Balance schema URL environment-based; updates output path.
packages/core-mobile/app/vmModule/ModuleManager.ts Updates constants import path for new API utils layout.
packages/core-mobile/app/utils/zodToCamelCase.ts Updates Zod import style for v4 and adjusts typing/transform.
packages/core-mobile/app/utils/getAddressesFromXpubXP/getAddressesFromXpubXP.ts Updates Profile API types import to new generated client output.
packages/core-mobile/app/utils/getAddressesFromXpubXP/getAddressesFromXpubXP.test.ts Updates Profile API types import to new generated client output.
packages/core-mobile/app/utils/apiClient/scripts/fixZodIntersections.js Removes openapi-zod-client patch script (no longer needed).
packages/core-mobile/app/utils/apiClient/profile/types.ts Removes old inferred types wrapper around openapi-zod-client schemas.
packages/core-mobile/app/utils/apiClient/profile/profileApi.ts Removes old axios/Zodios-style generated client setup and interceptors.
packages/core-mobile/app/utils/apiClient/balance/balanceApi.ts Removes old streaming balance implementation in legacy API client folder.
packages/core-mobile/app/utils/api/common/fetchWithValidation.ts Adds new fetch helpers (nitroFetch + expoFetch) with dev-only validation and query builder.
packages/core-mobile/app/utils/api/clients/profileApiClient.ts Adds @hey-api/client-fetch Profile API client configured with AppCheck + headers.
packages/core-mobile/app/utils/api/clients/glacierApiClient.ts Moves CORE_HEADERS import to the new API constants module.
packages/core-mobile/app/utils/api/clients/balanceApiClient.ts Adds streaming balance generator alongside non-streaming generated client.
packages/core-mobile/app/utils/api/clients/aggregatedTokensApiClient.ts Moves CORE_HEADERS import to the new API constants module.
packages/core-mobile/app/store/rpc/utils/assert.ts Adds a reusable RPC-flavored assertion helper.
packages/core-mobile/app/store/rpc/handlers/wc_sessionRequest/utils.ts Updates Zod usage for v4 and simplifies parse function typing.
packages/core-mobile/app/store/rpc/handlers/wallet_getNetworkState/utils.ts Simplifies parse function typing for v4.
packages/core-mobile/app/store/rpc/handlers/avalanche_setDeveloperMode/utils.ts Simplifies parse function typing for v4.
packages/core-mobile/app/store/rpc/handlers/account/avalanche_selectAccount/utils.ts Updates enum schema handling and simplifies parse typing.
packages/core-mobile/app/store/rpc/handlers/account/avalanche_renameAccount/utils.ts Simplifies parse function typing for v4.
packages/core-mobile/app/store/rpc/handlers/account/avalanche_addAccount/util.ts Simplifies parse function typing for v4.
packages/core-mobile/app/store/posthog/types.ts Adds Fusion sub-feature flags.
packages/core-mobile/app/store/posthog/slice.ts Adds selectors for Fusion sub-feature flags.
packages/core-mobile/app/store/middleware/listener.ts Registers Fusion listeners into app middleware.
packages/core-mobile/app/services/wallet/WalletService.tsx Switches Profile addresses call to @hey-api generated client + configured fetch client.
packages/core-mobile/app/services/token/types.ts Updates Zod record() usage for v4 key/value signatures.
packages/core-mobile/app/services/token/coingeckoProxyClient.ts Replaces Zodios client with fetch-based client + Zod validation.
packages/core-mobile/app/services/token/TokenService.ts Updates TokenService calls to the new coingecko proxy client API.
packages/core-mobile/app/services/posthog/types.ts Adds Fusion sub-feature flags.
packages/core-mobile/app/services/glacier/GlacierService.ts Moves CORE_HEADERS import to the new API constants module.
packages/core-mobile/app/services/defi/types.ts Updates Zod record() usage for v4 key/value signatures.
packages/core-mobile/app/services/defi/apiClient.ts Replaces Zodios with fetch-based DeFi + FX clients.
packages/core-mobile/app/services/defi/DeFiService.ts Updates DeFi service calls to new fetch-based client signatures.
packages/core-mobile/app/services/browser/apiClient.ts Replaces Zodios with fetch-based browser DeBank client.
packages/core-mobile/app/services/browser/BrowserService.ts Updates browser service to new api client signature.
packages/core-mobile/app/services/balance/utils/mapBalanceResponseToLegacy.ts Updates generated Balance API import path.
packages/core-mobile/app/services/balance/utils/buildRequestItemsForAccounts.ts Updates generated Balance API import path.
packages/core-mobile/app/services/balance/BalanceService.ts Switches streaming balances to streamingBalanceApiClient.
packages/core-mobile/app/services/balance/BalanceService.test.ts Updates mocks to match new streaming balance client interface.
packages/core-mobile/app/new/routes/(signedIn)/(modals)/swapV2/pricingDetails/index.tsx Updates zustand hook import location.
packages/core-mobile/app/new/routes/(signedIn)/(modals)/selectSwapV2ToToken/index.tsx Updates zustand hook import location.
packages/core-mobile/app/new/routes/(signedIn)/(modals)/selectSwapV2FromToken/index.tsx Updates zustand hook import location.
packages/core-mobile/app/new/features/swapV2/store/listeners.ts Adds Redux listeners to init/cleanup FusionService based on unlock/flags/dev mode.
packages/core-mobile/app/new/features/swapV2/services/types.ts Adds Fusion service/type interfaces for SDK integration.
packages/core-mobile/app/new/features/swapV2/services/signers/EvmSigner.ts Adds EVM signer adaptor for Fusion SDK using in-app RPC requests.
packages/core-mobile/app/new/features/swapV2/services/signers/BtcSigner.ts Adds BTC signer adaptor for Fusion SDK using in-app RPC requests.
packages/core-mobile/app/new/features/swapV2/services/FusionService.ts Adds singleton wrapper around unified-asset-transfer TransferManager and feature-flag enablement.
packages/core-mobile/app/new/features/swapV2/screens/SwapScreen.tsx Aligns “same-token selected” behavior to always clear the “to” token.
packages/core-mobile/app/new/features/swapV2/screens/SelectSwapV2TokenScreen.tsx Replaces hardcoded network list with Fusion SDK-supported chains.
packages/core-mobile/app/new/features/swapV2/hooks/useZustandStore.ts Fixes type import path.
packages/core-mobile/app/new/features/swapV2/hooks/useSwapV2Tokens.ts Uses useNetworks + new query keys and removes hardcoded C/Solana network logic.
packages/core-mobile/app/new/features/swapV2/hooks/useSupportedChains.ts Adds hook to fetch supported chains from FusionService and map to enabled networks.
packages/core-mobile/app/new/features/swapV2/contexts/SwapContext.tsx Updates zustand hook import location.
packages/core-mobile/app/new/features/swapV2/consts.ts Adds Fusion environment selection + Markr API URL constant.
packages/core-mobile/app/new/features/swap/utils/svm/jupiterApi.client.ts Replaces Zodios-based Jupiter client with fetch-based functions + validation.
packages/core-mobile/app/new/features/swap/services/MarkrService.ts Replaces Zodios client with fetch-based client + validation for Markr.
packages/core-mobile/app/new/features/swap/services/JupiterService.ts Updates JupiterService to new Jupiter API client signature.
packages/core-mobile/app/new/features/meld/services/apiClient.ts Replaces Zodios client with fetch-based Meld client factory.
packages/core-mobile/app/new/features/meld/services/MeldService.ts Updates MeldService calls to match new client signatures.
packages/core-mobile/app/hooks/networks/useNetworks.ts Decorates enabled networks with caip2ChainId and adds getEnabledNetworkByCaip2ChainId.
packages/core-mobile/app/hooks/balance/useSupportedChains.ts Updates generated Balance API import path.
packages/core-mobile/app/consts/reactQueryKeys.ts Adds React Query keys for Fusion supported chains & tokens.
packages/core-mobile/.gitignore Updates generated client ignore paths to new output structure.
packages/core-mobile/.eslintrc.js Removes legacy generated-client ignore glob and keeps new generated path.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +5 to +6
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export const parseRequestParams = (params: unknown) => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zod recommends we don't manually type the return type and just let it infer automatically

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious instead of manually typing it can we use z.infer here instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are letting it infer already here by not declaring a return type.

Copy link
Contributor

@B0Y3R-AVA B0Y3R-AVA left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left some super minor comments here, Great Work!

Comment on lines +5 to +6
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export const parseRequestParams = (params: unknown) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious instead of manually typing it can we use z.infer here instead?

Copilot AI review requested due to automatic review settings February 12, 2026 22:00
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 69 out of 72 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings February 12, 2026 22:11
B0Y3R-AVA
B0Y3R-AVA previously approved these changes Feb 12, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 71 out of 73 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (1)

packages/core-mobile/app/new/features/swapV2/screens/SwapScreen.tsx:594

  • The refs prevFromRef and prevToRef are declared and assigned but no longer used after the logic change to always clear the "to" field. These refs should be removed to clean up the code.
  const prevFromRef = useRef(fromToken)
  const prevToRef = useRef(toToken)

  useEffect(() => {
    if (fromToken && toToken && fromToken.localId === toToken.localId) {
      // Always clear the "to" field when same token is selected (matches swap v1 behavior)
      setToToken(undefined)
      setAmount(undefined)
      setToTokenValue(undefined)
      setFromTokenValue(undefined)
    }

    prevFromRef.current = fromToken
    prevToRef.current = toToken
  }, [fromToken, toToken, setToToken, setFromToken, setAmount])

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings February 16, 2026 13:29
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 71 out of 73 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +171 to +176
const getEnabledNetworkByCaip2ChainId = useCallback(
(caip2ChainId: string) => {
return enabledNetworks.find(n => n.caip2ChainId === caip2ChainId)
},
[enabledNetworks]
)
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The caip2ChainId property is defined as optional (caip2ChainId?: string) in the NetworkWithCaip2ChainId type, but this code assumes it will always be present by using strict equality comparison (n.caip2ChainId === caip2Id). If caip2ChainId is undefined, this comparison will never match, potentially returning undefined even when a matching network exists. Consider either:

  1. Making caip2ChainId required in the type definition
  2. Adding a guard to handle undefined caip2ChainId values
  3. Ensuring all networks always have caip2ChainId populated before being added to enabledNetworks

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 16, 2026 14:54
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 71 out of 73 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 78 to 93
// Create balance lookup map by localId
const balanceMap = new Map<string, LocalTokenWithBalance>()
balances?.forEach(balance => {
if (balance.localId) {
balanceMap.set(balance.localId.toLowerCase(), balance)
balanceMap.set(balance.localId, balance)
}
})

// Determine current network
const currentNetwork = isAvalancheCChainId(chainId)
? cChainNetwork
: isSolanaChainId(chainId)
? solanaNetwork
: null

// Create native token if network is available
let nativeToken: LocalTokenWithBalance | null = null

if (currentNetwork) {
const symbol = currentNetwork.networkToken.symbol
const decimals = currentNetwork.networkToken.decimals
const localId = `native-${symbol.toLowerCase()}`
const localId = `NATIVE-${symbol}`
const nativeBalanceData = balanceMap.get(localId)
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent localId casing in token identification. The code creates native token localIds with uppercase format (NATIVE-${symbol}) on line 92, but the balance lookup uses the localId directly without case normalization. Meanwhile, other parts of the codebase (e.g., useFilteredSwapTokens.ts:45, useSearchableTokenList.ts:98) consistently use .toLowerCase() for localId comparisons.

For ERC20 tokens, getLocalTokenIdFromApi returns address.toLowerCase() (getLocalTokenIdFromApi.ts:11), but the balance map lookup doesn't normalize the keys.

This inconsistency could cause balance data to not be matched correctly for native tokens or tokens with different casing. Consider:

  1. Normalizing all localIds to lowercase when creating the balance map
  2. Or ensuring consistent casing in localId generation across native and ERC20 tokens

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Copy link
Contributor

@alexnicolae-ava alexnicolae-ava left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dev tested. Great work! 🔥

@atn4z7 atn4z7 merged commit c63e93f into main Feb 16, 2026
4 checks passed
@atn4z7 atn4z7 deleted the fusion-sdk branch February 16, 2026 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants