feat(swapper): add Panora swapper for Aptos swaps#12492
Conversation
- Add hdwallet-core/src/aptos.ts with AptosWallet interfaces - Add SLIP-44 637 for Aptos in utils.ts - Add supportsAptos/infoAptos in wallet.ts - Add hdwallet-native AptosAdapter (Ed25519 + SHA3-256) - Add MixinNativeAptosWallet/MixinNativeAptosWalletInfo - Wire into native.ts (initialize, wipe, describePath, mixins) Local only - no PR
Wires the Aptos chain adapter, HDWallet, and types (added in prior commits) into the full app: asset generation via Panora token list, CoinGecko adapter, plugin indexer URL, NEAR Intents Aptos support (web-xeq.3), RFOX bridge, send modal, trade execution dispatch, state migrations bump (v334), e2e fixtures, and ButterSwap test mock updates for the AptosSwapperDeps ripple. Also fixes audit findings: - getRpcUrl() on AptosChainAdapter to replace unsafe protected cast - VITE_APTOS_INDEXER_URL validation + type declaration - Record<AssetId, ...> typing on test fixture marketDataByAssetIdUsd Refs: web-xeq.1 (chain adapter), web-xeq.3 (NEAR Intents Aptos), web-xeq.4 (qabot fixtures). PanoraSwapper (web-xeq.2) intentionally deferred to a separate PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Aptos node, when called with estimate_max_gas_amount=true, overwrites max_gas_amount in the response with the sender's AFFORDABILITY ceiling (balance / gas_unit_price), NOT a tight recommendation. Reading that field as the gas estimate caused fees to be inflated by 100-300x. For a wallet holding 1.08 APT at gas_unit_price=100, the node returned max_gas_amount=1,084,352. Multiplied by the prioritized gas estimate (150 octas), the displayed network fee came out to 1.62 APT (~\$1.54) for what should be a ~0.01 APT transfer. Fix: prefer sim.gas_used (real simulated consumption) with the Aptos CLI's 1.5x safety factor (gas_used * 3 / 2). Cap at the affordability ceiling defensively. Bump MIN_MAX_GAS_AMOUNT from 12,000 to 20,000 to safely cover real transfer_coins consumption (historical on-chain: 5,500-10,500 units) when simulation fails (e.g., dummy pubkey rejected by INVALID_AUTH_KEY). Refs: - https://aptos.dev/build/guides/system-integrators-guide ("estimate uses min(max_gas_amount, gas_used * safety_factor)", CLI safety_factor = 1.5) - https://aptos.dev/network/blockchain/gas-txn-fee - Direct fullnode simulation confirmed max_gas_amount echoed as account_balance / gas_unit_price when the flag is set. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolves all 9 actionable comments from the CodeRabbit review on the Aptos chain integration PR. Chain adapter (packages/chain-adapters/src/aptos/AptosChainAdapter.ts): - validateAddress now uses AccountAddress.fromString() from the SDK, which correctly accepts both short-form (0x1) and full-form Aptos addresses, instead of a rigid regex that rejected 0x1. - parseTx status logic now handles all three cases explicitly: success === true → Confirmed, false → Failed, undefined (pending tx) → Pending. Previously undefined was incorrectly treated as Confirmed. - Sender/recipient equality now goes through AccountAddress.equals via a normalized eq() helper so casing/length variants of the same Aptos address compare correctly. - buildSendApiTransaction now honors chainSpecific.coinType so non-APT CoinStore coins on Aptos can be transferred via NEAR Intents (or any future swapper). Aptos types (packages/chain-adapters/src/aptos/types.ts): - BuildTxInput gains coinType?: string (Aptos CoinStore type, defaults to APT). NEAR Intents Aptos route (packages/swapper/src/swappers/NearIntentsSwapper/endpoints.ts): - getUnsignedAptosTransaction detects non-native Aptos coins via assetNamespace (slip44 = native APT, otherwise assetReference is the Move CoinStore type) and forwards coinType to the chain adapter. Aptos swap status check (packages/swapper/src/utils.ts): - checkAptosSwapStatus normalizes recipient addresses via AccountAddress before comparing, replacing the substring-style t.to.includes(address) check. Aptos util (src/lib/utils/aptos.ts): - isAptosChainAdapter type guard now checks that getChainId is a function and wraps the call in try/catch so plain objects can't throw. Native HDWallet (packages/hdwallet-native/src/aptos.ts): - aptosNextAccountPath now delegates to core.aptosNextAccountPath instead of throwing. Treasury (packages/utils/src/treasury.ts): - Drop KnownChainIds.AptosMainnet from treasuryChainIds and remove the placeholder DAO_TREASURY_APTOS constant. The Aptos treasury entry will be added when the real DAO multisig address is available. Treasury helpers (packages/swapper/src/swappers/utils/helpers/helpers.ts): - Drop the AptosMainnet entry from DAO_TREASURY_BY_CHAIN_ID. Ledger constants (src/context/WalletProvider/Ledger/constants.ts): - Remove conditional inclusion of aptosAssetId from availableLedgerAppAssetIds. LedgerHDWallet does not implement AptosWallet; Aptos Ledger support will land in a focused follow-up PR with physical-device testing. Tests (packages/chain-adapters/src/aptos/AptosChainAdapter.test.ts): - vi.mock now keeps the real exports of @aptos-labs/ts-sdk (AccountAddress, Ed25519PublicKey, etc.) and only mocks the network-using Aptos client, AptosConfig, and Network. Without this, the new AccountAddress.equals comparisons would throw silently. - validateAddress test cases updated to reflect the SDK's behavior: short-form (0x1) and unprefixed full-form are now accepted; only truly malformed inputs are rejected. Refs: CodeRabbit review on PR shapeshift#12349 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…first verifyLedgerAppOpen() previously called getCoin() and getLedgerAppName() unconditionally before checking the wallet type. Both switches throw "Unsupported chainId" for any chain not enumerated (e.g. Aptos in this PR, since the Aptos Ledger commit was intentionally deferred). Result: AptosChainAdapter.getAddress() threw for Native wallets too because the chain adapter calls verifyLedgerAppOpen() in its address path. Move the isLedger(wallet) early-return to the top of the function so the chain lookups only happen for actual Ledger wallets. Native and other non-Ledger wallets bypass the gate entirely. Side benefit: future chain additions to the app don't need a simultaneous ledgerAppGate.ts update unless they actually ship Ledger support. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the bespoke Panora-based fetcher with the same CoinGecko
tokenlist pattern used by every other non-EVM chain (Solana, Sui,
Near, Ton, Tron). Removes the VITE_PANORA_API_KEY requirement from
the asset generation pipeline.
CoinGecko exposes two different platform slugs for Aptos: their
/api/v3 endpoints (and our CoinGecko adapter) use 'aptos-network',
but the static tokenlist at tokens.coingecko.com only responds to
'aptos' ('aptos-network' returns 403 there). Hardcoded the right
slug in scripts/generateAssetData/coingecko.ts to keep the existing
'aptos-network' adapter value untouched for API consumers.
Verified `pnpm run generate:chain aptos` returns 70 assets from
CoinGecko without any API key.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds Aptos mainnet support across chain identifiers, wallets, native signing, chain adapters, assets, portfolio, sends, swaps, feature flags, and transaction status handling. Adds Panora as an Aptos swapper and extends NEAR Intents with Aptos transaction and fee flows. ChangesAptos foundation and wallet support
Panora and Aptos swap routing
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (6)
packages/swapper/src/swappers/PanoraSwapper/utils/helpers.ts (1)
6-26: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDeduplicate logic and apply verb prefix naming convention.
getTokenAddressandaptosAddressFromAssetIdcontain identical address resolution logic. Additionally, as per coding guidelines, functions should use verb prefixes for actions.Consider renaming
aptosAddressFromAssetIdtogetAptosAddressFromAssetIdand updatinggetTokenAddressto call it, eliminating the duplicate code.♻️ Proposed refactor
-export const getTokenAddress = (asset: Asset): string => { - const { assetNamespace, assetReference } = fromAssetId(asset.assetId) - - // For native APT (slip44 namespace), return the Panora native token address - if (assetNamespace === 'slip44') { - return PANORA_NATIVE_TOKEN_ADDRESS - } - - // For tokens, the assetReference is the Aptos token address - return assetReference -} - -export const aptosAddressFromAssetId = (assetId: string): string => { +export const getAptosAddressFromAssetId = (assetId: string): string => { const { assetReference, assetNamespace } = fromAssetId(assetId) if (assetNamespace === 'slip44') { return PANORA_NATIVE_TOKEN_ADDRESS } return assetReference } + +export const getTokenAddress = (asset: Asset): string => { + return getAptosAddressFromAssetId(asset.assetId) +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/swapper/src/swappers/PanoraSwapper/utils/helpers.ts` around lines 6 - 26, Rename aptosAddressFromAssetId to getAptosAddressFromAssetId and update all references to the new verb-prefixed name. Refactor getTokenAddress to delegate address resolution to getAptosAddressFromAssetId, removing its duplicated fromAssetId and slip44 handling while preserving the existing native and token address results.Source: Coding guidelines
packages/swapper/src/swappers/PanoraSwapper/utils/constants.ts (1)
13-13: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRemove unused constant.
PANORA_DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGEis never used. The actual default slippage used by the Panora swapper is defined centrally asDEFAULT_PANORA_SLIPPAGE_DECIMAL_PERCENTAGEinpackages/swapper/src/constants.ts.♻️ Proposed refactor
-export const PANORA_DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE = '0.005'🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/swapper/src/swappers/PanoraSwapper/utils/constants.ts` at line 13, Remove the unused PANORA_DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE export from the constants module, and retain DEFAULT_PANORA_SLIPPAGE_DECIMAL_PERCENTAGE in the central swapper constants as the sole default slippage definition.packages/chain-adapters/src/aptos/AptosChainAdapter.test.ts (1)
10-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMocked client omits
transaction.build/transaction.simulate/transaction.submit, so send/build/broadcast/fee paths are untested.
buildSendApiTransaction,buildEntryFunctionApiTransaction,estimateMaxGasAmount,broadcastTransaction, andgetFeeDatahave no test coverage here. That gap is directly why the FA-vs-Coin token-transfer branch mismatch flagged inAptosChainAdapter.ts(buildSendApiTransaction) wasn't caught. Consider extending the mock withtransaction.build.simple,transaction.simulate.simple,transaction.submit.simple, andgetSigningMessageto add coverage for these send-critical paths.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/chain-adapters/src/aptos/AptosChainAdapter.test.ts` around lines 10 - 25, The Aptos SDK mock in the test setup omits transaction send and fee APIs, leaving build, simulation, submission, and signing paths uncovered. Extend the mock returned by the Aptos constructor to provide transaction.build.simple, transaction.simulate.simple, transaction.submit.simple, and getSigningMessage, then add tests covering buildSendApiTransaction, buildEntryFunctionApiTransaction, estimateMaxGasAmount, broadcastTransaction, and getFeeData, including both FA and Coin transfer branches.src/plugins/aptos/index.tsx (1)
1-31: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRename this file to use the
.tsextension.Since this file does not contain any JSX, it should use the
.tsextension instead of.tsx.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/plugins/aptos/index.tsx` around lines 1 - 31, Rename the file from index.tsx to index.ts without changing the register function or its plugin configuration, since the implementation contains no JSX.src/config.ts (1)
310-312: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a default value for the Aptos node URL.
Without a default, developers will encounter configuration validation errors on startup if their
.envfile lacksVITE_APTOS_NODE_URL, even if the Aptos feature flag is disabled. Providing a public fallback avoids breaking the local development environment.♻️ Proposed refactor
VITE_FEATURE_APTOS: bool({ default: false }), - VITE_APTOS_NODE_URL: url(), + VITE_APTOS_NODE_URL: url({ default: 'https://api.mainnet.aptoslabs.com/v1' }), VITE_APTOS_INDEXER_URL: url({ default: 'https://api.mainnet.aptoslabs.com/v1/graphql' }),🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/config.ts` around lines 310 - 312, Update the VITE_APTOS_NODE_URL configuration entry in the config schema to include a suitable public default URL, matching the existing default behavior of VITE_APTOS_INDEXER_URL, so startup validation succeeds when the Aptos feature is disabled and the environment variable is absent.src/components/Modals/Send/utils.ts (1)
557-570: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winSupport
skipDeviceDerivationby passingpubKeyfor transaction building.To ensure proper functionality and future-proof hardware wallet support (preventing the wallet adapter from needing a physical device interaction just to fetch the sending address), consider passing
pubKeydown tobuildSendTransaction, aligning with the convention used for EVM, UTXO, NEAR, and Sui networks in this file.🛠️ Proposed fix
if (fromChainId(asset.chainId).chainNamespace === CHAIN_NAMESPACE.Aptos) { const { accountNumber } = bip44Params const adapter = assertGetAptosChainAdapter(chainId) + const pubKey = skipDeviceDerivation ? fromAccountId(sendInput.accountId).account : undefined return adapter.buildSendTransaction({ to, value, wallet, accountNumber, + pubKey, sendMax: sendInput.sendMax, chainSpecific: { memo }, } as BuildSendTxInput<KnownChainIds.AptosMainnet>) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/Modals/Send/utils.ts` around lines 557 - 570, Update the Aptos branch in the transaction-building flow to pass the available pubKey into adapter.buildSendTransaction, matching the existing EVM, UTXO, NEAR, and Sui call conventions. Preserve the current Aptos parameters and ensure the pubKey supports skipDeviceDerivation without requiring device address derivation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/caip/src/adapters/coingecko/index.ts`:
- Line 101: Update the Aptos CoinGecko platform identifier in the relevant
adapter enum or mapping from aptos-network to aptos, preserving the existing
lookup flow for other platforms.
In `@packages/chain-adapters/src/aptos/AptosChainAdapter.ts`:
- Around line 268-281: Update buildSendApiTransaction to distinguish FA-only
assets from CoinStore-backed coin types: retain the existing
aptos_account::transfer_coins payload for standard coins, but route bare FA
metadata addresses through the appropriate fungible-asset transfer entry
function with its expected arguments. Use the existing chainSpecific information
and established FA transaction-building symbols where available.
- Around line 207-209: Update AptosChainAdapter.getTxHistory() to return a
rejected Promise for the unimplemented operation instead of throwing
synchronously, preserving the existing error message and Promise<never> contract
so callers can handle failures with catch().
- Around line 211-235: In estimateMaxGasAmount, check sim.success immediately
after simulation and before reading gas_used or max_gas_amount; when false,
throw an error containing sim.vm_status. Preserve the existing gas calculation
only for successful simulations.
In `@packages/hdwallet-native/src/aptos.ts`:
- Around line 38-40: Update the aptosWipe method to declare an explicit void
return type while preserving its existing behavior of clearing aptosAdapter.
In `@packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeQuote.test.ts`:
- Line 46: Replace the any assertions used for mocked assertGetAptosChainAdapter
dependencies with unknown-based assertions typed as
ReturnType<SwapperDeps['assertGetAptosChainAdapter']> or ReturnType<typeof
vi.fn>. Apply this change at
packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeQuote.test.ts:46 and
both locations at
packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeRate.test.ts:35 and
80.
In `@packages/swapper/src/swappers/PanoraSwapper/utils/panoraService.ts`:
- Line 4: Replace the hardcoded value in PANORA_API_KEY with configuration
sourced from an environment variable or injected SwapperDeps config. Update
callers of the Panora service as needed to pass and reuse the configured key,
while preserving existing API request behavior and ensuring no secret remains in
source control.
In `@scripts/generateAssetData/generateTrustWalletUrl/generateTrustWalletUrl.ts`:
- Line 18: Update the Aptos entry in the Trust Wallet URL generation logic to
append the assetReference for both native and token assets, producing the
blockchains/aptos/assets/<asset_address>/info.json path instead of the base
assets/info.json path. Add focused tests covering Aptos native and token
AssetIds and verify other chain URL behavior remains unchanged.
In `@src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx`:
- Around line 215-220: Update the AptosMainnet branch in the transaction-status
handling to invoke the existing failAction callback when
getAptosTransactionStatus returns TxStatus.Failed, rather than treating the
failure as successful confirmation. Preserve isConfirmed for TxStatus.Confirmed
and keep the existing behavior for other statuses, matching the TON and Starknet
failure handling.
In `@src/lib/utils/aptos.ts`:
- Line 5: Update the TxStatus import in aptos.ts to use the standard
`@shapeshiftoss` package namespace instead of the direct
packages/unchained-client/src/types path, preserving the existing symbol usage.
---
Nitpick comments:
In `@packages/chain-adapters/src/aptos/AptosChainAdapter.test.ts`:
- Around line 10-25: The Aptos SDK mock in the test setup omits transaction send
and fee APIs, leaving build, simulation, submission, and signing paths
uncovered. Extend the mock returned by the Aptos constructor to provide
transaction.build.simple, transaction.simulate.simple,
transaction.submit.simple, and getSigningMessage, then add tests covering
buildSendApiTransaction, buildEntryFunctionApiTransaction, estimateMaxGasAmount,
broadcastTransaction, and getFeeData, including both FA and Coin transfer
branches.
In `@packages/swapper/src/swappers/PanoraSwapper/utils/constants.ts`:
- Line 13: Remove the unused PANORA_DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE export
from the constants module, and retain DEFAULT_PANORA_SLIPPAGE_DECIMAL_PERCENTAGE
in the central swapper constants as the sole default slippage definition.
In `@packages/swapper/src/swappers/PanoraSwapper/utils/helpers.ts`:
- Around line 6-26: Rename aptosAddressFromAssetId to getAptosAddressFromAssetId
and update all references to the new verb-prefixed name. Refactor
getTokenAddress to delegate address resolution to getAptosAddressFromAssetId,
removing its duplicated fromAssetId and slip44 handling while preserving the
existing native and token address results.
In `@src/components/Modals/Send/utils.ts`:
- Around line 557-570: Update the Aptos branch in the transaction-building flow
to pass the available pubKey into adapter.buildSendTransaction, matching the
existing EVM, UTXO, NEAR, and Sui call conventions. Preserve the current Aptos
parameters and ensure the pubKey supports skipDeviceDerivation without requiring
device address derivation.
In `@src/config.ts`:
- Around line 310-312: Update the VITE_APTOS_NODE_URL configuration entry in the
config schema to include a suitable public default URL, matching the existing
default behavior of VITE_APTOS_INDEXER_URL, so startup validation succeeds when
the Aptos feature is disabled and the environment variable is absent.
In `@src/plugins/aptos/index.tsx`:
- Around line 1-31: Rename the file from index.tsx to index.ts without changing
the register function or its plugin configuration, since the implementation
contains no JSX.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 86f6e5ba-4df3-45c3-8dad-4d8f05aa4bb1
⛔ Files ignored due to path filters (4)
packages/caip/src/adapters/coingecko/generated/aptos_861fb8e6/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coingecko/generated/index.tsis excluded by!**/generated/**pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlsrc/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/panora-icon.jpgis excluded by!**/*.jpg
📒 Files selected for processing (94)
.env.env.development.env.productione2e/fixtures/aptos-chain-integration.yamlheaders/csps/chains/aptos.tsheaders/csps/chains/panora.tsheaders/csps/index.tspackages/caip/src/adapters/coingecko/index.tspackages/caip/src/adapters/coingecko/utils.tspackages/caip/src/constants.tspackages/chain-adapters/package.jsonpackages/chain-adapters/src/aptos/AptosChainAdapter.test.tspackages/chain-adapters/src/aptos/AptosChainAdapter.tspackages/chain-adapters/src/aptos/index.tspackages/chain-adapters/src/aptos/types.tspackages/chain-adapters/src/index.tspackages/chain-adapters/src/types.tspackages/chain-adapters/src/utils/ledgerAppGate.tspackages/hdwallet-core/src/aptos.tspackages/hdwallet-core/src/index.tspackages/hdwallet-core/src/utils.tspackages/hdwallet-core/src/wallet.tspackages/hdwallet-native/src/aptos.tspackages/hdwallet-native/src/crypto/isolation/adapters/aptos.tspackages/hdwallet-native/src/native.tspackages/public-api/src/routes/chains/types.tspackages/public-api/src/routes/chains/utils.tspackages/public-api/src/swapperDeps.tspackages/swapper/package.jsonpackages/swapper/src/constants.tspackages/swapper/src/index.tspackages/swapper/src/swappers/ButterSwap/swapperApi/getTradeQuote.test.tspackages/swapper/src/swappers/ButterSwap/swapperApi/getTradeRate.test.tspackages/swapper/src/swappers/NearIntentsSwapper/NearIntentsSwapper.tspackages/swapper/src/swappers/NearIntentsSwapper/endpoints.tspackages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.tspackages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.tspackages/swapper/src/swappers/NearIntentsSwapper/types.tspackages/swapper/src/swappers/PanoraSwapper/PanoraSwapper.tspackages/swapper/src/swappers/PanoraSwapper/endpoints.tspackages/swapper/src/swappers/PanoraSwapper/index.tspackages/swapper/src/swappers/PanoraSwapper/swapperApi/getPanoraTradeData.tspackages/swapper/src/swappers/PanoraSwapper/swapperApi/getTradeQuote.tspackages/swapper/src/swappers/PanoraSwapper/swapperApi/getTradeRate.tspackages/swapper/src/swappers/PanoraSwapper/types.tspackages/swapper/src/swappers/PanoraSwapper/utils/constants.tspackages/swapper/src/swappers/PanoraSwapper/utils/helpers.tspackages/swapper/src/swappers/PanoraSwapper/utils/panoraService.tspackages/swapper/src/swappers/utils/test-data/cryptoMarketDataById.tspackages/swapper/src/thorchain-utils/getL1RateOrQuote.tspackages/swapper/src/types.tspackages/swapper/src/utils.tspackages/types/src/base.tspackages/utils/src/assetData/baseAssets.tspackages/utils/src/assetData/getBaseAsset.tspackages/utils/src/chainIdToFeeAssetId.tspackages/utils/src/getAssetNamespaceFromChainId.tspackages/utils/src/getChainShortName.tspackages/utils/src/getNativeFeeAssetReference.tsscripts/generateAssetData/aptos/index.tsscripts/generateAssetData/coingecko.tsscripts/generateAssetData/generateAssetData.tsscripts/generateAssetData/generateRelatedAssetIndex/generateChainRelatedAssetIndex.tsscripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.tsscripts/generateAssetData/generateTrustWalletUrl/generateTrustWalletUrl.tssrc/components/Modals/Send/utils.tssrc/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsxsrc/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeNetworkFeeCryptoBaseUnit.tsxsrc/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsxsrc/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteOrRateInput.tssrc/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsxsrc/config.tssrc/constants/chains.tssrc/context/PluginProvider/PluginProvider.tsxsrc/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsxsrc/hooks/useWalletSupportsChain/useWalletSupportsChain.tssrc/lib/account/account.tssrc/lib/account/aptos.tssrc/lib/asset-service/service/AssetService.tssrc/lib/coingecko/constants.tssrc/lib/coingecko/utils.tssrc/lib/tradeExecution.tssrc/lib/utils/aptos.tssrc/pages/Markets/components/MarketsRow.tsxsrc/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.tssrc/plugins/activePlugins.tssrc/plugins/aptos/index.tsxsrc/state/apis/swapper/helpers/swapperApiHelpers.tssrc/state/helpers.tssrc/state/slices/opportunitiesSlice/mappings.tssrc/state/slices/portfolioSlice/utils/index.tssrc/state/slices/preferencesSlice/preferencesSlice.tssrc/test/mocks/store.tssrc/vite-env.d.ts
| Starknet = 'starknet', | ||
| Tron = 'tron', | ||
| Sui = 'sui', | ||
| Aptos = 'aptos-network', |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Fetch and search CoinGecko asset platforms for Aptos identifiers.
curl -s https://api.coingecko.com/api/v3/asset_platforms | jq '.[] | select(.id | contains("aptos"))'Repository: shapeshift/web
Length of output: 614
Use CoinGecko’s Aptos platform id aptos. aptos-network does not match the asset platforms API response, so Aptos token lookups will fail.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/caip/src/adapters/coingecko/index.ts` at line 101, Update the Aptos
CoinGecko platform identifier in the relevant adapter enum or mapping from
aptos-network to aptos, preserving the existing lookup flow for other platforms.
| getTxHistory(): Promise<never> { | ||
| throw new Error('Aptos transaction history not yet implemented') | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the Aptos adapter and related interface/call sites
git ls-files 'packages/chain-adapters/src/aptos/*' \
'packages/chain-adapters/src/*' | sed -n '1,200p'
echo
echo '--- outline AptosChainAdapter.ts ---'
ast-grep outline packages/chain-adapters/src/aptos/AptosChainAdapter.ts --view expanded || true
echo
echo '--- relevant lines ---'
cat -n packages/chain-adapters/src/aptos/AptosChainAdapter.ts | sed -n '180,225p'
echo
echo '--- search for getTxHistory usage / declaration ---'
rg -n "getTxHistory\s*\(" packages/chain-adapters/src packages -g'!**/dist/**' -g'!**/build/**' || trueRepository: shapeshift/web
Length of output: 22358
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the base adapter/interface to see the expected contract
rg -n "interface .*getTxHistory|abstract .*getTxHistory|getTxHistory\(" packages/chain-adapters/src -g'!**/dist/**' -g'!**/build/**' || true
echo
echo '--- AptosChainAdapter surrounding implementation ---'
cat -n packages/chain-adapters/src/aptos/AptosChainAdapter.ts | sed -n '1,260p'Repository: shapeshift/web
Length of output: 13746
Return a rejected promise here
getTxHistory() throws before a promise is created, so adapter.getTxHistory().catch(...) will fail synchronously instead of returning a rejected promise. Return Promise.reject(...) or make the method async so callers can handle it uniformly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/chain-adapters/src/aptos/AptosChainAdapter.ts` around lines 207 -
209, Update AptosChainAdapter.getTxHistory() to return a rejected Promise for
the unimplemented operation instead of throwing synchronously, preserving the
existing error message and Promise<never> contract so callers can handle
failures with catch().
| private async estimateMaxGasAmount( | ||
| sender: string, | ||
| data: InputEntryFunctionData, | ||
| ): Promise<bigint> { | ||
| const tx = await this.client.transaction.build.simple({ | ||
| sender, | ||
| data, | ||
| options: { maxGasAmount: 2_000_000 }, | ||
| }) | ||
| const dummyPubKey = new Ed25519PublicKey('0x' + '00'.repeat(32)) | ||
| const [sim] = await this.client.transaction.simulate.simple({ | ||
| signerPublicKey: dummyPubKey, | ||
| transaction: tx, | ||
| options: { estimateGasUnitPrice: true, estimateMaxGasAmount: true }, | ||
| }) | ||
| // sim.max_gas_amount with estimateMaxGasAmount=true is the AFFORDABILITY ceiling | ||
| // (sender balance / gas_unit_price), NOT a recommendation. The real consumption is | ||
| // sim.gas_used. Apply the Aptos CLI 1.5x safety factor, capped by affordability. | ||
| const gasUsed = BigInt(sim?.gas_used ?? 0) | ||
| if (gasUsed === 0n) return MIN_MAX_GAS_AMOUNT | ||
| const ceiling = BigInt(sim?.max_gas_amount ?? 0) | ||
| const withBuffer = (gasUsed * 3n) / 2n | ||
| const recommended = ceiling > 0n && ceiling < withBuffer ? ceiling : withBuffer | ||
| return recommended > MIN_MAX_GAS_AMOUNT ? recommended : MIN_MAX_GAS_AMOUNT | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== File map =="
ast-grep outline packages/chain-adapters/src/aptos/AptosChainAdapter.ts --view expanded || true
echo
echo "== Relevant lines =="
sed -n '180,280p' packages/chain-adapters/src/aptos/AptosChainAdapter.ts
echo
echo "== Search for simulation handling =="
rg -n "simulate\.simple|success === false|vm_status|estimateMaxGasAmount|buildEntryFunctionApiTransaction" packages/chain-adapters/src/aptos -SRepository: shapeshift/web
Length of output: 6591
🌐 Web query:
Aptos TypeScript SDK transaction.simulate.simple return success false error handling gas_used vm_status
💡 Result:
When using the Aptos TypeScript SDK, the aptos.transaction.simulate.simple() function allows you to preview a transaction's outcome—including success, gas usage, and potential errors—without executing it on-chain [1][2]. Error Handling and Simulation Results The simulate.simple function returns an array containing a simulation response object [3][4]. To properly handle simulation outcomes, you should explicitly check the success property of the result [5][6]. If success is false, the transaction would fail if submitted; in such cases, you should inspect the vm_status property to understand the specific cause of the failure [5][7][6]. Example Pattern: const [simResult] = await aptos.transaction.simulate.simple({ signerPublicKey: account.publicKey, transaction }); if (!simResult.success) { // Use simResult.vm_status to identify the error (e.g., INSUFFICIENT_BALANCE_FOR_TRANSACTION_FEE) throw new Error(Simulation failed: ${simResult.vm_status}); } Key Simulation Properties - success (boolean): Indicates whether the transaction would have succeeded or failed [7][6]. - vm_status (string): Provides the Virtual Machine status code or message, which is essential for diagnosing why a transaction failed [7][6]. - gas_used (string): Represents the total gas consumed by the transaction during simulation [7][6]. Note that Aptos represents u64 values as strings to maintain precision in JavaScript/TypeScript environments [7]. Gas Estimation You can use the gas_used value alongside gas_unit_price to estimate the actual cost in Octas: const gasUsed = parseInt(simResult.gas_used); const gasUnitPrice = parseInt(simResult.gas_unit_price); const estimatedCost = gasUsed * gasUnitPrice; If you encounter a status like INSUFFICIENT_BALANCE_FOR_TRANSACTION_FEE, it often indicates that your account lacks sufficient funds to cover the max possible gas fee specified in the transaction [8]. Always ensure you are checking vm_status to determine if the failure is due to logic errors, insufficient balance, or other network constraints [7][8].
Citations:
- 1: https://aptos.dev/build/sdks/ts-sdk/building-transactions/simulating-transactions
- 2: https://aptos.dev/build/sdks/ts-sdk/building-transactions
- 3: https://github.com/aptos-labs/aptos-ts-sdk/blob/main/src/api/transactionSubmission/simulate.ts
- 4: https://github.com/aptos-labs/aptos-ts-sdk/blob/main/src/internal/transactionSubmission.ts
- 5: https://github.com/aptos-labs/aptos-agent-skills/blob/main/skills/sdk/typescript/ts-sdk-transactions/SKILL.md
- 6: https://aptos.dev/build/guides/first-transaction
- 7: https://aptos.dev/rest-api/operations/simulate_transaction
- 8: https://aptos.dev/build/sdks/ts-sdk/building-transactions/sponsoring-transactions
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== estimateMaxGasAmount and caller =="
sed -n '211,360p' packages/chain-adapters/src/aptos/AptosChainAdapter.ts
echo
echo "== success checks in aptos adapter =="
rg -n "success === false|vm_status|simulate\.simple|estimateMaxGasAmount" packages/chain-adapters/src/aptos/AptosChainAdapter.ts packages/chain-adapters/src/aptos -SRepository: shapeshift/web
Length of output: 7181
🌐 Web query:
site:aptos.dev transaction.simulate.simple success vm_status gas_used Aptos TypeScript SDK
💡 Result:
In the Aptos TypeScript SDK, the aptos.transaction.simulate.simple method returns an array of transaction responses, typically accessed as const [userTransactionResponse] = await aptos.transaction.simulate.simple(...) [1][2]. The userTransactionResponse object includes critical execution details, specifically: - gas_used: This field provides the actual amount of gas units consumed by the transaction during simulation [3][4]. It is essential for estimating the total gas fee when multiplied by the gas_unit_price [2][4]. - vm_status: This field indicates the result of the Virtual Machine (VM) execution [3]. It provides information on whether the transaction simulation succeeded or failed, and if it failed, it often contains the specific VM error code or status details [3][4]. By inspecting these fields in the simulation response, you can preview the transaction's resource consumption and verify its execution status without actually submitting the transaction to the ledger or incurring real fees [5][1][4]. This is particularly useful for debugging or fine-tuning transaction parameters like maxGasAmount and gasUnitPrice before formal submission [3][6].
Citations:
- 1: https://aptos.dev/build/sdks/ts-sdk/building-transactions
- 2: https://aptos.dev/build/sdks/ts-sdk/building-transactions/sponsoring-transactions
- 3: https://aptos.dev/rest-api/operations/simulate_transaction
- 4: https://aptos.dev/build/sdks/go-sdk/building-transactions/simulating-transactions
- 5: https://aptos.dev/build/sdks/ts-sdk/building-transactions/simulating-transactions
- 6: https://aptos.dev/build/sdks/ts-sdk/building-transactions/encrypted-pending-transactions
🌐 Web query:
Aptos TypeScript SDK simulate.simple return fields success gas_used vm_status docs
💡 Result:
In the Aptos TypeScript SDK, the aptos.transaction.simulate.simple method allows you to preview the results of a transaction without submitting it to the ledger or incurring actual fees [1][2]. When you call this method, it returns a simulation response that contains critical information regarding the transaction's potential execution [2][3]. The key fields available in the returned response include: success: A boolean value indicating whether the transaction would succeed (true) or fail (false) [3][4]. gas_used: A string representing the amount of gas that would be consumed by the transaction if it were executed [3][4]. vm_status: A string providing the Virtual Machine (VM) status, which is particularly useful for debugging or understanding the reason for a transaction failure [3][4]. You can typically access these fields directly from the result object returned by the simulation [3]. For example: const [simulationResult] = await aptos.transaction.simulate.simple({ signerPublicKey: signer.publicKey, transaction, }); console.log(Success: ${simulationResult.success}); console.log(Gas used: ${simulationResult.gas_used}); console.log(VM Status: ${simulationResult.vm_status}); Because gas_used is returned as a string, it is common practice to parse it into an integer (e.g., parseInt(simulationResult.gas_used)) if you need to perform calculations with the value, such as estimating total gas costs [3].
Citations:
- 1: https://aptos.dev/build/sdks/ts-sdk/building-transactions/simulating-transactions
- 2: https://aptos.dev/build/sdks/ts-sdk/building-transactions
- 3: https://aptos.dev/build/guides/first-transaction
- 4: https://github.com/aptos-labs/aptos-ts-sdk/blob/de936697bdc552eb9c88e676d85686449dba3467/src/types/index.ts
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '370,530p' packages/chain-adapters/src/aptos/AptosChainAdapter.tsRepository: shapeshift/web
Length of output: 5159
Check sim.success before using simulation gas. Failed Aptos simulations still expose gas_used/max_gas_amount, so estimateMaxGasAmount can return a signable tx for an operation the preflight already marks as failed. Throw with sim.vm_status instead.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/chain-adapters/src/aptos/AptosChainAdapter.ts` around lines 211 -
235, In estimateMaxGasAmount, check sim.success immediately after simulation and
before reading gas_used or max_gas_amount; when false, throw an error containing
sim.vm_status. Preserve the existing gas calculation only for successful
simulations.
| buildSendApiTransaction( | ||
| input: BuildSendApiTxInput<KnownChainIds.AptosMainnet>, | ||
| ): Promise<SignTx<KnownChainIds.AptosMainnet>> { | ||
| const { from, accountNumber, to, value, chainSpecific } = input | ||
| const coinType = chainSpecific?.coinType ?? APT_COIN_TYPE | ||
|
|
||
| const data: InputEntryFunctionData = { | ||
| function: '0x1::aptos_account::transfer_coins', | ||
| typeArguments: [coinType], | ||
| functionArguments: [to, BigInt(value)], | ||
| } | ||
|
|
||
| return this.buildEntryFunctionApiTransaction({ from, accountNumber, data }) | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
buildSendApiTransaction needs to branch for FA-only Aptos assets
chainSpecific.coinType can be a bare FA metadata address, but this method always passes it to 0x1::aptos_account::transfer_coins as a Move type argument. That works for CoinStore-backed assets only; pure FA assets will produce an invalid payload. Route FA-only transfers through the fungible-asset entry function instead.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/chain-adapters/src/aptos/AptosChainAdapter.ts` around lines 268 -
281, Update buildSendApiTransaction to distinguish FA-only assets from
CoinStore-backed coin types: retain the existing aptos_account::transfer_coins
payload for standard coins, but route bare FA metadata addresses through the
appropriate fungible-asset transfer entry function with its expected arguments.
Use the existing chainSpecific information and established FA
transaction-building symbols where available.
| aptosWipe() { | ||
| this.aptosAdapter = undefined | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add an explicit return type for aptosWipe.
As per coding guidelines, always use explicit types for function parameters and return values in TypeScript.
♻️ Proposed fix
- aptosWipe() {
+ aptosWipe(): void {
this.aptosAdapter = undefined
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| aptosWipe() { | |
| this.aptosAdapter = undefined | |
| } | |
| aptosWipe(): void { | |
| this.aptosAdapter = undefined | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/hdwallet-native/src/aptos.ts` around lines 38 - 40, Update the
aptosWipe method to declare an explicit void return type while preserving its
existing behavior of clearing aptosAdapter.
Source: Coding guidelines
| assertGetNearChainAdapter: () => vi.fn() as any, | ||
| assertGetStarknetChainAdapter: () => vi.fn() as any, | ||
| assertGetTonChainAdapter: () => vi.fn() as any, | ||
| assertGetAptosChainAdapter: () => vi.fn() as any, |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Avoid using any for type assertions.
All three files use as any when mocking the assertGetAptosChainAdapter dependency. As per coding guidelines, you should "NEVER use any type unless absolutely necessary" and "ALWAYS use unknown instead of any".
packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeQuote.test.ts#L46-L46: Replaceas anywithas unknown as ReturnType<SwapperDeps['assertGetAptosChainAdapter']>(oras unknown as ReturnType<typeof vi.fn>).packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeRate.test.ts#L35-L35: Apply the same type assertion fix.packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeRate.test.ts#L80-L80: Apply the same type assertion fix.
📍 Affects 2 files
packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeQuote.test.ts#L46-L46(this comment)packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeRate.test.ts#L35-L35packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeRate.test.ts#L80-L80
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeQuote.test.ts` at
line 46, Replace the any assertions used for mocked assertGetAptosChainAdapter
dependencies with unknown-based assertions typed as
ReturnType<SwapperDeps['assertGetAptosChainAdapter']> or ReturnType<typeof
vi.fn>. Apply this change at
packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeQuote.test.ts:46 and
both locations at
packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeRate.test.ts:35 and
80.
Source: Coding guidelines
| sui: 'sui', | ||
| near: 'near', | ||
| ton: 'ton', | ||
| aptos: 'aptos', |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
git ls-files 'scripts/generateAssetData/generateTrustWalletUrl/*' 'scripts/generateAssetData/**/*TrustWallet*' 'scripts/generateAssetData/**/*aptos*' | sed 's#^`#-` #'
echo
ast-grep outline scripts/generateAssetData/generateTrustWalletUrl/generateTrustWalletUrl.ts --view expanded || true
echo
cat -n scripts/generateAssetData/generateTrustWalletUrl/generateTrustWalletUrl.ts
echo
rg -n "aptos|chainReference|assetReference|blockchains/.*/assets|trust wallet" scripts/generateAssetData -SRepository: shapeshift/web
Length of output: 6614
🏁 Script executed:
#!/bin/bash
set -euo pipefail
cat -n scripts/generateAssetData/generateTrustWalletUrl/generateTrustWalletUrl.ts | sed -n '1,220p'Repository: shapeshift/web
Length of output: 1519
🏁 Script executed:
#!/bin/bash
set -euo pipefail
cat -n scripts/generateAssetData/generateTrustWalletUrl/generateTrustWalletUrl.ts | sed -n '1,220p'Repository: shapeshift/web
Length of output: 1519
🌐 Web query:
Trust Wallet assets Aptos blockchains/aptos assets info.json aptos assetReference path layout
💡 Result:
In the Trust Wallet assets repository (github.com/trustwallet/assets), assets are organized hierarchically under the blockchains directory. For the Aptos blockchain, the directory structure follows this path layout: blockchains/aptos/assets/<asset_address>/ Within the specific asset folder, two files are required [1][2]: 1. info.json: Contains metadata about the token [1][2]. 2. logo.png: The visual representation of the asset [1][2]. The info.json file serves as the template for token details [3]. To add a new asset, developers typically use the repository's Makefile commands (e.g., make add-token asset_id=...), which automate the creation of the necessary info.json template [3]. The repository configuration explicitly mandates that asset folders contain only logo.png and info.json files [2]. You can find additional technical documentation on the Trust Developers portal for listing new assets [4].
Citations:
- 1: https://developer.trustwallet.com/developer/new-asset/repository_details
- 2: https://github.com/trustwallet/assets/blob/master/.github/assets.config.yaml
- 3: https://github.com/trustwallet/assets?auto_subscribed=false
- 4: https://developer.trustwallet.com/developer/new-asset
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n "generateTrustWalletUrl\(" scripts src . -SRepository: shapeshift/web
Length of output: 1492
🌐 Web query:
Trust Wallet assets Aptos native coin blockchains/aptos/assets info.json AptosCoin 0x1
💡 Result:
In the context of the Trust Wallet assets repository, the Aptos native coin (APT) is identified by the type string 0x1::aptos_coin::AptosCoin [1][2]. The Trust Wallet assets repository organizes tokens within the blockchains folder [3][4]. For networks like Aptos, assets are structured using their specific identifiers rather than Ethereum-style contract addresses [3][4]. While Trust Wallet's official documentation notes that Ethereum-like assets use a checksummed address format for their folder names and info.json files [5][3], the Aptos native coin is defined at the protocol level by the module 0x1::aptos_coin and the resource type AptosCoin [6][7]. For integration purposes, Aptos coins utilize the type format
::<module_name>::<coin_name> [8][2]. The specific identifier for the native APT coin is: 0x1::aptos_coin::AptosCoin Technical documentation from Aptos Labs confirms this is the native token initialized during genesis [6]. Developers integrating with Trust Wallet should refer to the Trust Wallet Assets repository structure for how these assets are registered [9][3], noting that Aptos support has been expanded to include fungible assets [10].Citations:
- 1: https://explorer.aptoslabs.com/coin/0x1::aptos_coin::AptosCoin/info
- 2: https://explorer.aptoslabs.com/coins
- 3: https://developer.trustwallet.com/developer/new-asset/repository_details.md
- 4: https://github.com/trustwallet/developer/blob/master/assets/repository_details.md
- 5: https://developer.trustwallet.com/developer/new-asset/repository_details
- 6: https://aptos-labs.github.io/framework-book/aptos-framework/aptos_coin.html
- 7: https://github.com/aptos-labs/aptos-core/blob/21991ffa96acde5ec211ba73dea42528a29b1e01/aptos-move/framework/aptos-framework/sources/coin.move
- 8: https://aptos-labs.github.io/framework-book/aptos-framework/coin.html
- 9: https://github.com/trustwallet/assets
- 10: [Aptos]: Add support for fungible assets trustwallet/wallet-core#4206
Handle the Aptos asset reference here. Trust Wallet’s Aptos assets live under blockchains/aptos/assets/<asset_address>/info.json, but this branch never appends the Aptos assetReference, so all Aptos AssetIds fall back to the same .../blockchains/aptos/assets/info.json URL. Add Aptos-specific native/token handling and tests.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/generateAssetData/generateTrustWalletUrl/generateTrustWalletUrl.ts`
at line 18, Update the Aptos entry in the Trust Wallet URL generation logic to
append the assetReference for both native and token assets, producing the
blockchains/aptos/assets/<asset_address>/info.json path instead of the base
assets/info.json path. Add focused tests covering Aptos native and token
AssetIds and verify other chain URL behavior remains unchanged.
| case KnownChainIds.AptosMainnet: { | ||
| const aptosTxStatus = await getAptosTransactionStatus(txHash) | ||
| isConfirmed = | ||
| aptosTxStatus === TxStatus.Confirmed || aptosTxStatus === TxStatus.Failed | ||
| break | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Properly handle failed Aptos transactions.
Currently, if an Aptos transaction fails, isConfirmed is set to true, which mistakenly marks the action as completely successful in the UI. Instead, use the existing failAction callback to accurately report failures, similar to how it is handled for TON and Starknet.
🛠️ Proposed fix
case KnownChainIds.AptosMainnet: {
const aptosTxStatus = await getAptosTransactionStatus(txHash)
- isConfirmed =
- aptosTxStatus === TxStatus.Confirmed || aptosTxStatus === TxStatus.Failed
+
+ if (aptosTxStatus === TxStatus.Failed) {
+ failAction(action)
+
+ const intervalId = pollingIntervalsRef.current.get(pollingKey)
+ if (intervalId) {
+ clearInterval(intervalId)
+ pollingIntervalsRef.current.delete(pollingKey)
+ }
+ return
+ }
+
+ isConfirmed = aptosTxStatus === TxStatus.Confirmed
break
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| case KnownChainIds.AptosMainnet: { | |
| const aptosTxStatus = await getAptosTransactionStatus(txHash) | |
| isConfirmed = | |
| aptosTxStatus === TxStatus.Confirmed || aptosTxStatus === TxStatus.Failed | |
| break | |
| } | |
| case KnownChainIds.AptosMainnet: { | |
| const aptosTxStatus = await getAptosTransactionStatus(txHash) | |
| if (aptosTxStatus === TxStatus.Failed) { | |
| failAction(action) | |
| const intervalId = pollingIntervalsRef.current.get(pollingKey) | |
| if (intervalId) { | |
| clearInterval(intervalId) | |
| pollingIntervalsRef.current.delete(pollingKey) | |
| } | |
| return | |
| } | |
| isConfirmed = aptosTxStatus === TxStatus.Confirmed | |
| break | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx` around
lines 215 - 220, Update the AptosMainnet branch in the transaction-status
handling to invoke the existing failAction callback when
getAptosTransactionStatus returns TxStatus.Failed, rather than treating the
failure as successful confirmation. Preserve isConfirmed for TxStatus.Confirmed
and keep the existing behavior for other statuses, matching the TON and Starknet
failure handling.
| import { aptosChainId } from '@shapeshiftoss/caip' | ||
| import type { aptos } from '@shapeshiftoss/chain-adapters' | ||
| import type { KnownChainIds } from '@shapeshiftoss/types' | ||
| import { TxStatus } from 'packages/unchained-client/src/types' |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Fix import path for TxStatus.
Importing directly from packages/unchained-client/src/types circumvents package boundaries and workspaces configuration. Please use the standard @shapeshiftoss namespace import instead.
🛠️ Proposed fix
-import { TxStatus } from 'packages/unchained-client/src/types'
+import { TxStatus } from '`@shapeshiftoss/unchained-client`'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { TxStatus } from 'packages/unchained-client/src/types' | |
| import { TxStatus } from '`@shapeshiftoss/unchained-client`' |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/lib/utils/aptos.ts` at line 5, Update the TxStatus import in aptos.ts to
use the standard `@shapeshiftoss` package namespace instead of the direct
packages/unchained-client/src/types path, preserving the existing symbol usage.
468ec7f to
e013ce3
Compare
|
Pushed a conformity pass against the swapper integration contract:
Re-verified quotes end to end in the app after the change (APT to USDC via Panora, key threaded through deps.config). |
|
Swap execution verified end to end on Aptos mainnet with a dev wallet: 0.1 APT swapped to USDC through the Panora router from the trade UI. The BCS transaction built by the new |
Description
Adds Panora, the Aptos DEX aggregator, as a swapper for intra-Aptos swaps (APT and Aptos coins).
Stacked on #12349 (Aptos chain integration): this branch contains all of its commits plus two new ones. Only review the last two commits here; the rest is reviewed in #12349.
Implementation notes:
PanoraSwapperqueries the Panora/swapAPI for rates and quotes. The API deals in human readable token amounts, so amounts are converted from and to base units at the boundary (verified against the live API).AptosChainAdapter.buildEntryFunctionApiTransaction, which produces properly BCS serializedSimpleTransactionbytes via the Aptos SDK (gas simulation included).buildSendApiTransactionnow delegates to it.checkAptosSwapStatushelper, same pattern as the Cetus (Sui) swapper.PanoraSwapfeature flag (VITE_FEATURE_PANORA_SWAP, off in production), with a CSP entry forapi.panora.exchange.Affiliate fees: supported natively by Panora and verified against the live
/swapAPI (integratorFeePercentage+integratorFeeAddress, with the fee recipient embedded in the on-chain router call). Important caveat also verified live: if the percentage is sent without an address, the fee is still deducted from the user but kept by Panora. Fee sending is therefore gated behindPANORA_INTEGRATOR_FEE_ADDRESS, which stays unset until the DAO has an Aptos treasury address (the placeholderDAO_TREASURY_APTOSwas removed during #12349 review for the same reason). Until then quotes charge no affiliate fee rather than losing it.Issue (if applicable)
closes #
Risk
Low. New swapper entirely behind the
VITE_FEATURE_PANORA_SWAPfeature flag (off in production), and the Aptos chain itself is also feature flagged (#12349). No changes to existing swap flows.Panora router contract on Aptos only (
panora_swap::router_entry). Aptos entry function transactions are new, introduced by the #12349 stack. No existing swappers or chains are touched.Testing
Engineering
VITE_FEATURE_APTOSandVITE_FEATURE_PANORA_SWAPare already enabled in.env.development.pnpm run generate:asset-data, or wait for the regen.Operations
Screenshots (if applicable)
Screenshots taken on a local build with the flags enabled:
APT -> USDC

USDC -> APT

Execution: Confirm Details (0.1 APT -> USDC via Panora, mainnet)

Execution: swap complete (received exactly the quoted amount)

APT -> amAPT (liquid staking token route)

Summary by CodeRabbit